ALT Linux repos
S: | 2.5.0-alt1 |
5.0: | 2.4.4-alt11 |
4.1: | 2.4.4-alt10.M41.1 |
4.0: | 2.4.4-alt10 |
+updates: | 2.4.4-alt10 |
3.0: | 2.4.2-alt6 |
+updates: | 2.4.2-alt6.M30.1 |
Group :: System/Servers
RPM: ppp
Main Changelog Spec Patches Sources Download Gear Bugs and FR Repocop
Patch: ppp-2.4.4-cbcp-alt.patch
Download
Download
diff -NurpP -x '*~' -x '*.o' -x pppd -x Makefile -x 'dhcp/*' -x '*.so' -x '*.a' pppd/auth.c /home/davinchi/src/ppp-2.4.4/pppd/auth.c
--- pppd/auth.c 2007-04-20 19:27:02 +0500
+++ /home/davinchi/src/ppp-2.4.4/pppd/auth.c 2007-04-22 00:09:52 +0500
@@ -245,7 +245,7 @@ extern char *crypt __P((const char *, co
/* Prototypes for procedures local to this file. */
-static void network_phase __P((int));
+void network_phase __P((int));
static void check_idle __P((void *));
static void connect_time_expired __P((void *));
static int plogin __P((char *, char *, char **));
@@ -587,8 +587,10 @@ void start_link(unit)
notice("Starting negotiation on %s", ppp_devnam);
add_fd(fd_ppp);
+#ifndef CBCP_SUPPORT
status = EXIT_NEGOTIATION_FAILED;
new_phase(PHASE_ESTABLISH);
+#endif
lcp_lowerup(0);
return;
@@ -802,7 +804,7 @@ link_established(unit)
/*
* Proceed to the network phase.
*/
-static void
+void
network_phase(unit)
int unit;
{
@@ -828,7 +830,8 @@ network_phase(unit)
/*
* If we negotiated callback, do it now.
*/
- if (go->neg_cbcp) {
+ if (((go->neg_cbcp) || (lcp_hisoptions[unit].neg_cbcp))
+ && (phase != PHASE_CALLBACK)) {
new_phase(PHASE_CALLBACK);
(*cbcp_protent.open)(unit);
return;
diff -NurpP -x '*~' -x '*.o' -x pppd -x Makefile -x 'dhcp/*' -x '*.so' -x '*.a' pppd/cbcp.c /home/davinchi/src/ppp-2.4.4/pppd/cbcp.c
--- pppd/cbcp.c 2007-04-09 00:41:41 +0500
+++ /home/davinchi/src/ppp-2.4.4/pppd/cbcp.c 2007-04-22 00:21:19 +0500
@@ -44,19 +44,24 @@
#include "cbcp.h"
#include "fsm.h"
#include "lcp.h"
+#include "ipcp.h"
+#include "pathnames.h"
+#include <sys/stat.h>
static const char rcsid[] = RCSID;
/*
* Options.
*/
-static int setcbcp __P((char **));
+/*
+int setcbcp __P((char **));
static option_t cbcp_option_list[] = {
{ "callback", o_special, (void *)setcbcp,
"Ask for callback", OPT_PRIO | OPT_A2STRVAL, &cbcp[0].us_number },
{ NULL }
};
+*/
/*
* Protocol entry points.
@@ -84,7 +89,7 @@ struct protent cbcp_protent = {
0,
"CBCP",
NULL,
- cbcp_option_list,
+ NULL,
NULL,
NULL,
NULL
@@ -94,26 +99,22 @@ cbcp_state cbcp[NUM_PPP];
/* internal prototypes */
+static void cbcp_sendreq __P((void *arg));
static void cbcp_recvreq __P((cbcp_state *us, u_char *pckt, int len));
-static void cbcp_resp __P((cbcp_state *us));
-static void cbcp_up __P((cbcp_state *us));
+static void cbcp_sendresp __P((cbcp_state *us));
+static void cbcp_recvresp __P((cbcp_state *us, char *pckt, int len));
+static void cbcp_sendack __P((void *));
static void cbcp_recvack __P((cbcp_state *us, u_char *pckt, int len));
static void cbcp_send __P((cbcp_state *us, int code, u_char *buf, int len));
+static void cbcp_make_options __P((int unit));
+static int cbcp_check_user __P((char *user, char *mask));
+static void cbcp_start_callback __P((cbcp_state *us));
+static void cbcp_up __P((cbcp_state *us));
-/* option processing */
-static int
-setcbcp(argv)
- char **argv;
-{
- lcp_wantoptions[0].neg_cbcp = 1;
- cbcp_protent.enabled_flag = 1;
- cbcp[0].us_number = strdup(*argv);
- if (cbcp[0].us_number == 0)
- novm("callback number");
- cbcp[0].us_type |= (1 << CB_CONF_USER);
- cbcp[0].us_type |= (1 << CB_CONF_ADMIN);
- return (1);
-}
+cbcp_state *stop_iface = NULL;
+
+void (*cbcp_init_hook) __P((cbcp_state *)) = NULL;
+
/* init state */
static void
@@ -125,7 +126,6 @@ cbcp_init(iface)
us = &cbcp[iface];
memset(us, 0, sizeof(cbcp_state));
us->us_unit = iface;
- us->us_type |= (1 << CB_CONF_NO);
}
/* lower layer is up */
@@ -137,9 +137,6 @@ cbcp_lowerup(iface)
dbglog("cbcp_lowerup");
dbglog("want: %d", us->us_type);
-
- if (us->us_type == CB_CONF_USER)
- dbglog("phone no: %s", us->us_number);
}
static void
@@ -147,6 +144,8 @@ cbcp_open(unit)
int unit;
{
dbglog("cbcp_open");
+ if (lcp_hisoptions[unit].neg_cbcp)
+ cbcp_make_options(unit);
}
/* process an incomming packet */
@@ -161,6 +160,8 @@ cbcp_input(unit, inpacket, pktlen)
u_short len;
cbcp_state *us = &cbcp[unit];
+ lcp_options *go = &lcp_gotoptions[unit];
+ lcp_options *his = &lcp_hisoptions[unit];
inp = inpacket;
@@ -184,16 +185,34 @@ cbcp_input(unit, inpacket, pktlen)
switch(code) {
case CBCP_REQ:
+ if ( !go->neg_cbcp )
+ {
+ dbglog("CBCP received CBCP_REQ, but CBCP running in server mode!");
+ return;
+ }
us->us_id = id;
cbcp_recvreq(us, inp, len);
break;
case CBCP_RESP:
- if (debug)
- dbglog("CBCP_RESP received");
+ if ( !his->neg_cbcp )
+ {
+ dbglog("CBCP received CBCP_RESP, but CBCP running in client mode!");
+ return;
+ }
+ if (id != us->us_id)
+ dbglog("id doesn't match: expected %d recv %d",
+ us->us_id, id);
+
+ cbcp_recvresp(us, inp, len);
break;
case CBCP_ACK:
+ if ( !go->neg_cbcp )
+ {
+ dbglog("CBCP received CBCP_ACK, but CBCP running in server mode!");
+ return;
+ }
if (debug && id != us->us_id)
dbglog("id doesn't match: expected %d recv %d",
us->us_id, id);
@@ -275,7 +294,7 @@ cbcp_printpkt(p, plen, printer, arg)
printer(arg, " delay = %d", delay);
}
- if (olen > 3) {
+ if (olen > 4) {
int addrt;
char str[256];
@@ -307,7 +326,7 @@ cbcp_recvreq(us, pckt, pcktlen)
u_char *pckt;
int pcktlen;
{
- u_char type, opt_len, delay, addr_type;
+ u_char type, opt_len, addr_type;
char address[256];
int len = pcktlen;
@@ -321,8 +340,9 @@ cbcp_recvreq(us, pckt, pcktlen)
if (opt_len < 2 || opt_len > len)
break;
+ us->us_delay = 0;
if (opt_len > 2)
- GETCHAR(delay, pckt);
+ GETCHAR(us->us_delay, pckt);
us->us_allowed |= (1 << type);
@@ -357,28 +377,29 @@ cbcp_recvreq(us, pckt, pcktlen)
return;
}
- cbcp_resp(us);
+ cbcp_sendresp(us);
}
static void
-cbcp_resp(us)
+cbcp_sendresp(us)
cbcp_state *us;
{
- u_char cb_type;
+ u_char cb_allowed;
u_char buf[256];
u_char *bufp = buf;
int len = 0;
int slen;
- cb_type = us->us_allowed & us->us_type;
- dbglog("cbcp_resp cb_type=%d", cb_type);
+ cb_allowed = us->us_allowed;
+ dbglog("cbcp_resp cb_type=%d", cb_allowed);
#if 0
if (!cb_type)
lcp_down(us->us_unit);
#endif
- if (cb_type & ( 1 << CB_CONF_USER ) ) {
+ if (cb_allowed & ( 1 << CB_CONF_USER ) ) {
+ us->us_type = 1 << CB_CONF_USER;
dbglog("cbcp_resp CONF_USER");
slen = strlen(us->us_number);
if (slen > 250) {
@@ -387,31 +408,33 @@ cbcp_resp(us)
}
PUTCHAR(CB_CONF_USER, bufp);
len = 3 + 1 + slen + 1;
- PUTCHAR(len , bufp);
- PUTCHAR(5, bufp); /* delay */
+ PUTCHAR(len, bufp);
+ PUTCHAR(us->us_delay, bufp); /* delay */
PUTCHAR(1, bufp);
BCOPY(us->us_number, bufp, slen + 1);
cbcp_send(us, CBCP_RESP, buf, len);
return;
}
- if (cb_type & ( 1 << CB_CONF_ADMIN ) ) {
+ if (cb_allowed & ( 1 << CB_CONF_ADMIN ) ) {
+ us->us_type = 1 << CB_CONF_ADMIN;
dbglog("cbcp_resp CONF_ADMIN");
PUTCHAR(CB_CONF_ADMIN, bufp);
len = 3;
PUTCHAR(len, bufp);
- PUTCHAR(5, bufp); /* delay */
+ PUTCHAR(us->us_delay, bufp); /* delay */
cbcp_send(us, CBCP_RESP, buf, len);
return;
}
- if (cb_type & ( 1 << CB_CONF_NO ) ) {
+ if (cb_allowed & ( 1 << CB_CONF_NO ) ) {
+ us->us_type = 1 << CB_CONF_NO;
dbglog("cbcp_resp CONF_NO");
PUTCHAR(CB_CONF_NO, bufp);
len = 2;
PUTCHAR(len , bufp);
cbcp_send(us, CBCP_RESP, buf, len);
- start_networks(us->us_unit);
+// start_networks(us->us_unit);
return;
}
}
@@ -448,17 +471,19 @@ cbcp_recvack(us, pckt, len)
u_char *pckt;
int len;
{
- u_char type, delay, addr_type;
+ u_char type, addr_type;
int opt_len;
char address[256];
+ stop_iface = us;
+
if (len >= 2) {
GETCHAR(type, pckt);
GETCHAR(opt_len, pckt);
if (opt_len >= 2 && opt_len <= len) {
if (opt_len > 2)
- GETCHAR(delay, pckt);
+ GETCHAR(us->us_delay, pckt);
if (opt_len > 4) {
GETCHAR(addr_type, pckt);
@@ -467,22 +492,404 @@ cbcp_recvack(us, pckt, len)
if (address[0])
dbglog("peer will call: %s", address);
}
- if (type == CB_CONF_NO)
- return;
-
- cbcp_up(us);
+ if (type != CB_CONF_NO)
+ {
+ callback_in_progress = us->us_unit + 1;
+ callback_in_progress |= CBCP_CLIENT;
+ cbcp_up(us);
+ }
+ else
+ network_phase(us->us_unit);
} else if (debug)
dbglog("cbcp_recvack: malformed packet");
}
}
-/* ok peer will do callback */
-static void
+/* Make options
+ if auth req, options from callback-users file, else use CBCP_CONF_USER */
+ static void
+cbcp_make_options (unit)
+ int unit;
+{
+ cbcp_state *us = &cbcp[unit];
+ FILE *userfile;
+ struct stat sbuf;
+ int best_fit, got_fit, newline;
+ char uname[ 256 ], option[ 256 ];
+
+ us->us_id = 1;
+ us->us_count = 0;
+ us->us_delay = 5; /* Default delay 5 seconds */
+ if ( *peer_authname ) { /* Username available */
+ userfile = fopen( _PATH_CBCP_USERS, "r" );
+ if ( userfile == NULL ){
+ dbglog( "Can't open callback user file: %s %m",
+ _PATH_CBCP_USERS );
+ dbglog( "Allow user definied callback." );
+ us->us_allowed = ( 1 << CB_CONF_USER );
+ }else
+ {
+ if ( fstat(fileno(userfile), &sbuf) < 0) {
+ dbglog("Cannot stat userfile file %s: %m",
+ _PATH_CBCP_USERS );
+ } else if ((sbuf.st_mode & (S_IRWXG | S_IRWXO)) != 0) {
+ dbglog("Warning - user file %s has world and/or group access",
+ _PATH_CBCP_USERS );
+ }
+
+ us->us_allowed = ( 1 << CB_CONF_NO ); /* Assume, no callback allowed */
+
+ if (getword(userfile, uname, &newline, _PATH_CBCP_USERS)){ /* file not empty */
+ newline = 1;
+ best_fit = 0;
+ *option = 0;
+ for (;;) {
+ /*
+ * Skip until we find a word at the start of a line.
+ */
+ while (!newline && getword(userfile, uname,
+ &newline, _PATH_CBCP_USERS))
+ ;
+ if (!newline)
+ break; /* got to end of file */
+
+ /*
+ * Got a user - check if it's a match or a wildcard.
+ */
+ got_fit = cbcp_check_user( peer_authname, uname );
+ if ( got_fit <= best_fit ){
+ newline = 0;
+ continue;
+ }
+
+ /* Read the options */
+ best_fit = got_fit;
+ if (getword(userfile, option, &newline, _PATH_CBCP_USERS))
+ break;
+
+ if ( newline )
+ *option = 0;
+
+ if ( best_fit == 100 )
+ break;
+ }
+ }
+
+ switch ( *option ){
+ case '-' : us->us_allowed = ( 1 << CB_CONF_NO ); break;
+ case '*' :
+ case 0 : us->us_allowed = ( 1 << CB_CONF_USER ); break;
+ default : us->us_allowed = ( 1 << CB_CONF_ADMIN );
+ us->us_number = strdup( option ); break;
+ }
+ fclose( userfile );
+ }
+ }
+ else
+ us->us_allowed = ( 1 << CB_CONF_USER );
+
+ if (cbcp_init_hook)
+ cbcp_init_hook( us );
+
+ cbcp_sendreq( us );
+}
+
+
+/* make cbcp request packet & send it */
+ static void
+cbcp_sendreq (arg)
+ void *arg;
+{
+ cbcp_state *us=(cbcp_state *)arg;
+ u_char cb_allow = us->us_allowed;
+ u_char buf[256];
+ u_char *bufp = buf;
+ int len = 0;
+
+ us->us_count++;
+ if (us->us_count<=CBCP_MAXRETRY)
+ TIMEOUT( cbcp_sendreq, arg, CBCP_DEFTIMEOUT );
+ else
+ {
+ lcp_close(0, "Sorry, CBCP not responding.");
+ return;
+ }
+ dbglog("cbcp_sendreq cb_allowed=%d", cb_allow);
+
+
+ if (cb_allow & ( 1 << CB_CONF_USER ) ) {
+ dbglog("cbcp_sendreq CONF_USER");
+ PUTCHAR(CB_CONF_USER, bufp);
+ len+=3;
+ PUTCHAR(3 , bufp);
+ PUTCHAR(us->us_delay, bufp);
+ }
+
+ if (cb_allow & ( 1 << CB_CONF_ADMIN ) ) {
+ dbglog("cbcp_sendreq CONF_ADMIN");
+ PUTCHAR(CB_CONF_ADMIN, bufp);
+ len += 3;
+ PUTCHAR(3 , bufp);
+ PUTCHAR(us->us_delay, bufp);
+ }
+
+ if (cb_allow & ( 1 << CB_CONF_NO ) ) {
+ dbglog("cbcp_sendreq CONF_NO");
+ PUTCHAR(CB_CONF_NO, bufp);
+ len += 3;
+ PUTCHAR(3 , bufp);
+ PUTCHAR(us->us_delay, bufp);
+ }
+
+ if (len)
+ cbcp_send(us, CBCP_REQ, buf, len);
+ else
+ {
+ dbglog("cbcp: no available options to client!");
+ }
+}
+
+/* Received CBCP response, make ACK */
+ static void
+cbcp_recvresp (us, pckt, len)
+ cbcp_state *us;
+ char *pckt;
+ int len;
+{
+ u_char type, addr_type;
+ int opt_len;
+ char address[256];
+
+ if (len) {
+ GETCHAR(type, pckt);
+ GETCHAR(opt_len, pckt);
+
+ if (!(( 1 << type )& us->us_allowed )) {
+ dbglog("CBCP received options not allowed on server!");
+ return;
+ }
+
+ if ((type!= CB_CONF_NO ) &&
+ (type!= CB_CONF_USER ) &&
+ (type!= CB_CONF_ADMIN )) {
+ dbglog("CBCP received BAD Response: too more or unknown options %d",type);
+ return;
+ }
+
+ UNTIMEOUT( cbcp_sendreq, us );
+ us->us_count = 0;
+
+
+ if (opt_len > 2)
+ GETCHAR(us->us_delay, pckt)
+ if ( us->us_delay < 5 )
+ us->us_delay = 5;
+
+ if (opt_len > 4) {
+ GETCHAR(addr_type, pckt); /* Address Type mezo elvesztve !!! */
+ memcpy(address, pckt, opt_len - 4);
+ address[opt_len - 4] = 0;
+ if (address[0])
+ dbglog("peer will callback the client on: %s", address);
+ us->us_number=strdup( address );
+ }
+
+ us->us_type = ( 1 << type );
+ cbcp_sendack( us );
+ }
+ else
+ {
+ dbglog("CBCP received BAD Response: size to small");
+ }
+}
+
+/* Send the CBCP_ACK packet */
+ static void
+cbcp_sendack (arg)
+ void *arg;
+{
+ cbcp_state *us= (cbcp_state *)arg;
+ u_char cb_type;
+ u_char buf[256];
+ u_char *bufp = buf;
+ int len = 0;
+
+ stop_iface = (cbcp_state *)arg;
+ cb_type = us->us_type;
+
+ dbglog("cbcp_sendack cb_type=%d", cb_type);
+
+ us->us_count++;
+ if (us->us_count<=CBCP_MAXRETRY)
+ TIMEOUT( cbcp_sendack, arg, CBCP_DEFTIMEOUT );
+ else
+ {
+ lcp_close(0, "Sorry, CBCP not responding.");
+ return;
+ }
+
+#if 0
+ if (!cb_type)
+ lcp_down(us->us_unit);
+#endif
+
+ if (cb_type == (1 << CB_CONF_USER )) {
+ dbglog("cbcp_sendack CONF_USER");
+ PUTCHAR(CB_CONF_USER, bufp);
+ len = 3 + 1 + strlen(us->us_number) + 1;
+ PUTCHAR(len , bufp);
+ PUTCHAR(us->us_delay, bufp); /* delay */
+ PUTCHAR(1, bufp); /* Elvesztett byte... */
+ BCOPY(us->us_number, bufp, strlen(us->us_number) + 1);
+ cbcp_send(us, CBCP_ACK, buf, len);
+ /* lcp_close( 2, "Illegal, but required to server..." ); */
+ callback_in_progress = us->us_unit + 1;
+ return;
+ }
+
+ if (cb_type == (1 << CB_CONF_ADMIN )) {
+ dbglog("cbcp_sendack CONF_ADMIN");
+ PUTCHAR(CB_CONF_ADMIN, bufp);
+ len = 3;
+ PUTCHAR(len , bufp);
+ PUTCHAR(us->us_delay, bufp); /* delay */
+ PUTCHAR(0, bufp);
+ cbcp_send(us, CBCP_ACK, buf, len);
+ /* lcp_close( 2, "Illegal, but required to server..." ); */
+ callback_in_progress = us->us_unit + 1;
+ return;
+ }
+
+ if (cb_type == (1 << CB_CONF_NO )) {
+ dbglog("cbcp_sendack CONF_NO");
+ PUTCHAR(CB_CONF_NO, bufp);
+ len = 3;
+ PUTCHAR(len , bufp);
+ PUTCHAR(0, bufp);
+ cbcp_send(us, CBCP_ACK, buf, len);
+ if (us->us_count<=1)
+ network_phase(us->us_unit);
+ return;
+ }
+
+ dbglog("CBCP - Bad options in Ack routine.");
+}
+
+/* CBCP coming succesful up */
+void cbcp_stop()
+{
+ if ( stop_iface && lcp_allowoptions[stop_iface->us_unit].neg_cbcp )
+ {
+ UNTIMEOUT( cbcp_sendack, stop_iface );
+ cbcp_start_callback( stop_iface );
+ }
+}
+
+/* The server side coming up & client 'ack-ed' */
+void cbcp_start_callback (us)
+ cbcp_state *us;
+{
+ lcp_allowoptions[us->us_unit].neg_cbcp=0;
+
+ dbglog("cbcp_start_callback running");
+}
+
+/* The client side coming up: server allowed the callback */
+ static void
cbcp_up(us)
cbcp_state *us;
{
persist = 0;
status = EXIT_CALLBACK;
lcp_close(0, "Call me back, please");
+ lcp_wantoptions[us->us_unit].neg_cbcp = 0;
+ dbglog("cbcp_up called");
+ lcp_close(us->us_unit, "Call me back, please");
}
+
+/* The main module gets the script with parameters to run */
+char *cbcp_get_script()
+{
+ cbcp_state *us = &cbcp[(callback_in_progress & CBCP_NCLIENT)-1];
+ char script[ 256 ];
+
+ if ( callback_in_progress & CBCP_CLIENT )
+ sprintf( script, "%s %d", _PATH_CBCP_CLIENT, us->us_delay );
+ else
+ sprintf( script, "%s %d %s", _PATH_CBCP_SERVER,
+ us->us_delay, us->us_number );
+
+ return strdup( script );
+}
+
+/* give me the hit rate. wild cars '*?' valids */
+int cbcp_check_user ( user, mask )
+ char *user;
+ char *mask;
+{
+ char *curr_user = user;
+ char *curr_mask = mask;
+ char *find, backp = 0;
+ int count, len = 0;
+
+ if ( !strcasecmp( user, mask ))
+ return 100;
+
+ if ( !strcmp( mask, "*" ))
+ return 1;
+
+ if ( !*user )
+ return 0;
+
+ count = 0;
+
+ while(( find = strpbrk( curr_mask, "*?" )) != 0 ) {
+ if ( find != curr_mask ){
+ len = find - curr_mask;
+ if ( strncmp( curr_user, curr_mask, len ))
+ break;
+ }
+
+ curr_mask += len + 1;
+ curr_user += len;
+ count += len;
+ if ( *curr_user == 0 )
+ break;
+
+ if ( *find == '?' ) {
+ curr_user++;
+ if ( *curr_user == 0 )
+ break;
+ } else {
+ if ( *curr_mask == 0 )
+ break;
+
+ if ( ( find = strpbrk( curr_mask, "*?" )) != 0 ){
+ backp = *find;
+ *find = 0;
+ }
+ curr_user = strstr( curr_user, curr_mask );
+ if ( find )
+ *find = backp;
+ if ( !curr_user )
+ break;
+
+ find = strpbrk( curr_mask, "*?" );
+ if ( find )
+ len = find - curr_mask;
+ else
+ len = strlen( curr_mask );
+
+ curr_mask += len;
+ curr_user += len;
+ count += len;
+ }
+ }
+
+ if ( *curr_user && *curr_mask && !strcmp( curr_user, curr_mask ))
+ count += strlen( curr_user );
+
+ return ( count * 100 / strlen( user ) );
+}
+
diff -NurpP -x '*~' -x '*.o' -x pppd -x Makefile -x 'dhcp/*' -x '*.so' -x '*.a' pppd/cbcp.h /home/davinchi/src/ppp-2.4.4/pppd/cbcp.h
--- pppd/cbcp.h 2007-04-09 00:41:41 +0500
+++ /home/davinchi/src/ppp-2.4.4/pppd/cbcp.h 2007-04-20 18:48:00 +0500
@@ -6,6 +6,8 @@ typedef struct cbcp_state {
u_char us_id; /* Current id */
u_char us_allowed;
int us_type;
+ u_char us_delay;
+ u_char us_count;
char *us_number; /* Telefone Number */
} cbcp_state;
@@ -19,8 +21,20 @@ extern struct protent cbcp_protent;
#define CBCP_RESP 2
#define CBCP_ACK 3
+
+#define CBCP_DEFTIMEOUT 5
+#define CBCP_MAXRETRY 50
+#define CBCP_CLIENT 0x8000
+#define CBCP_NCLIENT 0x7fff
+
+
#define CB_CONF_NO 1
#define CB_CONF_USER 2
#define CB_CONF_ADMIN 3
#define CB_CONF_LIST 4
+
+
+char *cbcp_get_script __P(());
+void cbcp_stop __P(());
+
#endif
diff -NurpP -x '*~' -x '*.o' -x pppd -x Makefile -x 'dhcp/*' -x '*.so' -x '*.a' pppd/ipcp.c /home/davinchi/src/ppp-2.4.4/pppd/ipcp.c
--- pppd/ipcp.c 2007-04-20 19:27:01 +0500
+++ /home/davinchi/src/ppp-2.4.4/pppd/ipcp.c 2007-04-20 18:48:38 +0500
@@ -61,6 +61,11 @@
#include "ipcp.h"
#include "pathnames.h"
+#ifdef CBCP_SUPPORT
+#include "cbcp.h"
+#endif
+
+
static const char rcsid[] = RCSID;
/* global vars */
@@ -1350,6 +1355,10 @@ ipcp_reqci(f, inp, len, reject_if_disagr
u_char maxslotindex, cflag;
int d;
+#ifdef CBCP_SUPPORT
+ cbcp_stop();
+#endif
+
/*
* Reset all his options.
*/
diff -NurpP -x '*~' -x '*.o' -x pppd -x Makefile -x 'dhcp/*' -x '*.so' -x '*.a' pppd/ipv6cp.c /home/davinchi/src/ppp-2.4.4/pppd/ipv6cp.c
--- pppd/ipv6cp.c 2007-04-20 19:27:02 +0500
+++ /home/davinchi/src/ppp-2.4.4/pppd/ipv6cp.c 2007-04-20 18:49:41 +0500
@@ -168,6 +168,11 @@
#include "magic.h"
#include "pathnames.h"
+#ifdef CBCP_SUPPORT
+#include "cbcp.h"
+#endif
+
+
static const char rcsid[] = RCSID;
/* global vars */
@@ -907,6 +912,11 @@ ipv6cp_reqci(f, inp, len, reject_if_disa
u_char *ucp = inp; /* Pointer to current output char */
int l = *len; /* Length left */
+#ifdef CBCP_SUPPORT
+ cbcp_stop();
+#endif
+
+
/*
* Reset all his options.
*/
diff -NurpP -x '*~' -x '*.o' -x pppd -x Makefile -x 'dhcp/*' -x '*.so' -x '*.a' pppd/ipxcp.c /home/davinchi/src/ppp-2.4.4/pppd/ipxcp.c
--- pppd/ipxcp.c 2007-04-09 00:41:41 +0500
+++ /home/davinchi/src/ppp-2.4.4/pppd/ipxcp.c 2007-04-20 18:50:37 +0500
@@ -62,6 +62,11 @@
#include "pathnames.h"
#include "magic.h"
+#ifdef CBCP_SUPPORT
+#include "cbcp.h"
+#endif
+
+
static const char rcsid[] = RCSID;
/* global vars */
@@ -1003,6 +1008,11 @@ ipxcp_reqci(f, inp, len, reject_if_disag
u_char *ucp = inp; /* Pointer to current output char */
int l = *len; /* Length left */
+#ifdef CBCP_SUPPORT
+ cbcp_stop();
+#endif
+
+
/*
* Reset all his options.
*/
diff -NurpP -x '*~' -x '*.o' -x pppd -x Makefile -x 'dhcp/*' -x '*.so' -x '*.a' pppd/lcp.c /home/davinchi/src/ppp-2.4.4/pppd/lcp.c
--- pppd/lcp.c 2007-04-09 00:41:41 +0500
+++ /home/davinchi/src/ppp-2.4.4/pppd/lcp.c 2007-04-20 19:02:45 +0500
@@ -1782,6 +1782,16 @@ lcp_reqci(f, inp, lenp, reject_if_disagr
ho->neg_accompression = 1;
break;
+ case CI_CALLBACK:
+ dbglog("lcp_reqci: rcvd CALLBACK");
+ if (!ao->neg_cbcp ||
+ cilen != CILEN_CHAR ) {
+ orc = CONFREJ;
+ break;
+ }
+ ho->neg_cbcp = 1;
+ break;
+
case CI_MRRU:
if (!ao->neg_mrru || !multilink ||
cilen != CILEN_SHORT) {
diff -NurpP -x '*~' -x '*.o' -x pppd -x Makefile -x 'dhcp/*' -x '*.so' -x '*.a' pppd/main.c /home/davinchi/src/ppp-2.4.4/pppd/main.c
--- pppd/main.c 2007-04-20 19:27:02 +0500
+++ /home/davinchi/src/ppp-2.4.4/pppd/main.c 2007-04-22 00:20:44 +0500
@@ -186,6 +186,11 @@ static sigjmp_buf sigjmp;
char **script_env; /* Env. variable values for scripts */
int s_env_nalloc; /* # words avail at script_env */
+#ifdef CBCP_SUPPORT
+int callback_in_progress; /* Callback running */
+#endif
+
+
u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */
u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */
@@ -307,6 +312,9 @@ main(argc, argv)
char *p;
struct passwd *pw;
struct protent *protp;
+#ifdef CBCP_SUPPORT
+ char *connector;
+#endif
char numbuf[16];
link_stats_valid = 0;
@@ -530,6 +538,13 @@ main(argc, argv)
lcp_open(0); /* Start protocol */
start_link(0);
+#ifdef CBCP_SUPPORT
+ for(callback_in_progress=1;callback_in_progress;){
+ callback_in_progress=0;
+
+ status = EXIT_NEGOTIATION_FAILED;
+ new_phase(PHASE_ESTABLISH);
+#endif
while (phase != PHASE_DEAD) {
handle_events();
get_input();
@@ -549,6 +564,82 @@ main(argc, argv)
}
/* restore FSMs to original state */
lcp_close(0, "");
+#ifdef CBCP_SUPPORT
+ if (callback_in_progress){
+ connector = NULL;
+ cbcp_stop();
+ remove_fd(fd_ppp);
+ clean_check();
+ the_channel->disestablish_ppp(devfd);
+ fd_ppp = -1;
+
+ if (!hungup){
+ lcp_lowerdown(0);
+ } else {
+ tty_close_fds();
+ setup_serial(connector);
+
+ }
+
+ devfd = callback();
+
+ /* set up the serial device as a ppp interface */
+#ifdef USE_TDB
+ tdb_lockall(pppdb);
+#endif
+ fd_ppp = the_channel->establish_ppp(devfd);
+ if (fd_ppp < 0) {
+#ifdef USE_TDB
+ tdb_unlockall(pppdb);
+#endif
+ status = EXIT_FATAL_ERROR;
+ asked_to_quit = 1;
+ break;
+ }
+
+ if (!demand && ifunit >= 0)
+ set_ifunit(1);
+#ifdef USE_TDB
+ tdb_unlockall(pppdb);
+#endif
+
+ /*
+ * Start opening the connection and wait for
+ * incoming events (reply, timeout, etc.).
+ */
+ notice("Connect: %s <--> %s", ifname, ppp_devnam);
+ gettimeofday(&start_time, NULL);
+ link_stats_valid = 0;
+ script_unsetenv("CONNECT_TIME");
+ script_unsetenv("BYTES_SENT");
+ script_unsetenv("BYTES_RCVD");
+ lcp_lowerup(0);
+
+ /*
+ * If we are initiating this connection, wait for a short
+ * time for something from the peer. This can avoid bouncing
+ * our packets off his tty before he has it set up.
+ */
+ add_fd(fd_ppp);
+ if (listen_time != 0) {
+ struct timeval t;
+ t.tv_sec = listen_time / 1000;
+ t.tv_usec = listen_time % 1000;
+ wait_input(&t);
+ }
+
+ /*if (connector != NULL || ptycommand != NULL) {
+ struct timeval t;
+ t.tv_sec = 1;
+ t.tv_usec = 0;
+ wait_input(&t);
+ }*/
+
+ lcp_open(0); /* Start protocol */
+ }
+ }
+#endif
+
if (!persist || asked_to_quit || (maxfail > 0 && unsuccess >= maxfail))
break;
@@ -2144,3 +2235,5 @@ cleanup_db()
delete_db_key(p);
}
#endif /* USE_TDB */
+
+
diff -NurpP -x '*~' -x '*.o' -x pppd -x Makefile -x 'dhcp/*' -x '*.so' -x '*.a' pppd/options.c /home/davinchi/src/ppp-2.4.4/pppd/options.c
--- pppd/options.c 2007-04-20 19:27:02 +0500
+++ /home/davinchi/src/ppp-2.4.4/pppd/options.c 2007-04-22 00:20:02 +0500
@@ -75,6 +75,12 @@
#include "pppd.h"
#include "pathnames.h"
+#ifdef CBCP_SUPPORT
+#include "fsm.h"
+#include "lcp.h"
+#include "cbcp.h"
+#endif
+
#if defined(ultrix) || defined(NeXT)
char *strdup __P((char *));
#endif
@@ -181,6 +187,11 @@ struct option_list {
struct option_list *next;
};
+#ifdef CBCP_SUPPORT
+static int setcbcp __P((char **));
+#endif
+
+
static struct option_list *extra_options = NULL;
/*
@@ -326,6 +337,11 @@ option_t general_options[] = {
"Check for traffic limit every N seconds", OPT_PRIO | OPT_LLIMIT | 1 },
#endif
+#ifdef CBCP_SUPPORT
+ { "callback", o_special, setcbcp,
+ "Callback request to server - OR - calling back the client" },
+#endif
+
{ NULL }
};
@@ -1633,3 +1649,23 @@ loadplugin(argv)
return 0;
}
#endif /* PLUGIN */
+
+#ifdef CBCP_SUPPORT
+int
+setcbcp(argv)
+ char **argv;
+{
+ cbcp[0].us_number = strdup(*argv);
+ if (cbcp_protent.enabled_flag)
+ novm("Only one callback parameter supported!");
+ if (cbcp[0].us_number == 0)
+ novm("callback number");
+ if (!strcmp(cbcp[0].us_number,"server")){
+ lcp_allowoptions[0].neg_cbcp = 1;
+ } else {
+ lcp_wantoptions[0].neg_cbcp = 1;
+ }
+ cbcp_protent.enabled_flag = 1;
+ return 1;
+}
+#endif
diff -NurpP -x '*~' -x '*.o' -x pppd -x Makefile -x 'dhcp/*' -x '*.so' -x '*.a' pppd/pathnames.h /home/davinchi/src/ppp-2.4.4/pppd/pathnames.h
--- pppd/pathnames.h 2007-04-20 19:27:01 +0500
+++ /home/davinchi/src/ppp-2.4.4/pppd/pathnames.h 2007-04-20 19:13:37 +0500
@@ -45,6 +45,13 @@
#define _PATH_IPXDOWN _ROOT_PATH "/etc/ppp/ipx-down"
#endif /* IPX_CHANGE */
+#ifdef CBCP_SUPPORT
+#define _PATH_CBCP_SERVER _ROOT_PATH "/etc/ppp/callback-server"
+#define _PATH_CBCP_CLIENT _ROOT_PATH "/etc/ppp/callback-client"
+#define _PATH_CBCP_USERS _ROOT_PATH "/etc/ppp/callback-users"
+#define _PATH_CBCP _ROOT_PATH "/etc/ppp/callback"
+#endif /* CBCP_SUPPORT */
+
#ifdef __STDC__
#define _PATH_PPPDB _ROOT_PATH _PATH_VARRUN "pppd2.tdb"
#else /* __STDC__ */
Файлы pppd/plugins/rp-pppoe/pppoe-discovery и /home/davinchi/src/ppp-2.4.4/pppd/plugins/rp-pppoe/pppoe-discovery различаются
diff -NurpP -x '*~' -x '*.o' -x pppd -x Makefile -x 'dhcp/*' -x '*.so' -x '*.a' pppd/pppd.8 /home/davinchi/src/ppp-2.4.4/pppd/pppd.8
--- pppd/pppd.8 2007-04-20 19:27:01 +0500
+++ /home/davinchi/src/ppp-2.4.4/pppd/pppd.8 2007-04-20 19:14:08 +0500
@@ -88,6 +88,14 @@ is not being run by root. The \fIname\f
or include .. as a pathname component. The format of the options file
is described below.
.TP
+.B callback \fIserver/number
+When compiled with the CBCP extensions (-DCBCP_SUPPORT) the ppp daemon
+can act as a client to servers which provide CBCP-protocol callback
+negotiation or act as a \fIserver. It reads its options from
+/etc/ppp/callback-users and invokes /etc/ppp/callback-server
+when dialing out. Otherwise it will invoke /etc/ppp/callback-client
+to wait for a call.
+.TP
.B connect \fIscript
Usually there is something which needs to be done to prepare the link
before the PPP protocol can be started; for instance, with a dial-up
diff -NurpP -x '*~' -x '*.o' -x pppd -x Makefile -x 'dhcp/*' -x '*.so' -x '*.a' pppd/pppd.h /home/davinchi/src/ppp-2.4.4/pppd/pppd.h
--- pppd/pppd.h 2007-04-20 19:27:02 +0500
+++ /home/davinchi/src/ppp-2.4.4/pppd/pppd.h 2007-04-20 19:16:05 +0500
@@ -74,6 +74,10 @@
#include "eui64.h"
#endif
+/* for cbcp_init_hook */
+#include "cbcp.h"
+
+
/*
* Limits.
*/
@@ -358,6 +362,10 @@ extern struct bpf_program pass_filter;
extern struct bpf_program active_filter; /* Filter for link-active pkts */
#endif
+#ifdef CBCP_SUPPORT
+extern int callback_in_progress; /*Callback running*/
+#endif
+
#ifdef MSLANMAN
extern bool ms_lanman; /* Use LanMan password instead of NT */
/* Has meaning only with MS-CHAP challenges */
@@ -518,6 +526,8 @@ void unlock_db __P((void));
/* Procedures exported from tty.c. */
void tty_init __P((void));
+void setup_serial __P((char *));
+int callback __P ((void));
/* Procedures exported from utils.c. */
void log_packet __P((u_char *, int, char *, int));
@@ -543,6 +553,7 @@ ssize_t complete_read __P((int, void *,
/* read a complete buffer */
/* Procedures exported from auth.c */
+void network_phase __P((int)); /* the dataexchanger CP-s goung up */
void link_required __P((int)); /* we are starting to use the link */
void start_link __P((int)); /* bring the link up now */
void link_terminated __P((int)); /* we are finished with the link */
@@ -728,6 +739,7 @@ extern int (*allowed_address_hook) __P((
extern void (*ip_up_hook) __P((void));
extern void (*ip_down_hook) __P((void));
extern void (*ip_choose_hook) __P((u_int32_t *));
+extern void (*cbcp_init_hook) __P((cbcp_state *));
extern int (*chap_check_hook) __P((void));
extern int (*chap_passwd_hook) __P((char *user, char *passwd));
diff -NurpP -x '*~' -x '*.o' -x pppd -x Makefile -x 'dhcp/*' -x '*.so' -x '*.a' pppd/tty.c /home/davinchi/src/ppp-2.4.4/pppd/tty.c
--- pppd/tty.c 2007-04-20 19:27:01 +0500
+++ /home/davinchi/src/ppp-2.4.4/pppd/tty.c 2007-04-20 19:21:37 +0500
@@ -96,6 +96,10 @@
#include "pppd.h"
#include "fsm.h"
#include "lcp.h"
+#ifdef CBCP_SUPPORT
+#include "cbcp.h"
+#endif /* CBCP_SUPPORT */
+
void tty_process_extra_options __P((void));
void tty_check_options __P((void));
@@ -513,12 +517,10 @@ tty_check_options()
int connect_tty()
{
char *connector;
- int fdflags;
-#ifndef __linux__
- struct stat statbuf;
-#endif
char numbuf[16];
+ connector = doing_callback? callback_script: connect_script;
+
/*
* Get a pty master/slave pair if the pty, notty, socket,
* or record options were specified.
@@ -547,77 +549,6 @@ int connect_tty()
}
/*
- * Open the serial device and set it up to be the ppp interface.
- * First we open it in non-blocking mode so we can set the
- * various termios flags appropriately. If we aren't dialling
- * out and we want to use the modem lines, we reopen it later
- * in order to wait for the carrier detect signal from the modem.
- */
- hungup = 0;
- got_sigterm = 0;
- connector = doing_callback? callback_script: connect_script;
- if (devnam[0] != 0) {
- for (;;) {
- /* If the user specified the device name, become the
- user before opening it. */
- int err, prio;
-
- prio = privopen? OPRIO_ROOT: tty_options[0].priority;
- if (prio < OPRIO_ROOT && seteuid(uid) == -1) {
- error("Unable to drop privileges before opening %s: %m\n",
- devnam);
- status = EXIT_OPEN_FAILED;
- goto errret;
- }
- real_ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0);
- err = errno;
- if (prio < OPRIO_ROOT && seteuid(0) == -1)
- fatal("Unable to regain privileges");
- if (real_ttyfd >= 0)
- break;
- errno = err;
- if (err != EINTR) {
- error("Failed to open %s: %m", devnam);
- status = EXIT_OPEN_FAILED;
- }
- if (!persist || err != EINTR)
- goto errret;
- }
- ttyfd = real_ttyfd;
- if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1
- || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
- warn("Couldn't reset non-blocking mode on device: %m");
-
-#ifndef __linux__
- /*
- * Linux 2.4 and above blocks normal writes to the tty
- * when it is in PPP line discipline, so this isn't needed.
- */
- /*
- * Do the equivalent of `mesg n' to stop broadcast messages.
- */
- if (fstat(ttyfd, &statbuf) < 0
- || fchmod(ttyfd, statbuf.st_mode & ~S_IWOTH) < 0) {
- warn("Couldn't restrict write permissions to %s: %m", devnam);
- } else
- tty_mode = statbuf.st_mode;
-#endif /* __linux__ */
-
- /*
- * Set line speed, flow control, etc.
- * If we have a non-null connection or initializer script,
- * on most systems we set CLOCAL for now so that we can talk
- * to the modem before carrier comes up. But this has the
- * side effect that we might miss it if CD drops before we
- * get to clear CLOCAL below. On systems where we can talk
- * successfully to the modem with CLOCAL clear and CD down,
- * we could clear CLOCAL at this point.
- */
- set_up_tty(ttyfd, ((connector != NULL && connector[0] != 0)
- || initializer != NULL));
- }
-
- /*
* If the pty, socket, notty and/or record option was specified,
* start up the character shunt now.
*/
@@ -1261,3 +1192,111 @@ record_write(f, code, buf, nb, tp)
}
return 1;
}
+
+void setup_serial(char *connector)
+{
+ int fdflags;
+ struct stat statbuf;
+
+ /*
+ * Open the serial device and set it up to be the ppp interface.
+ * First we open it in non-blocking mode so we can set the
+ * various termios flags appropriately. If we aren't dialling
+ * out and we want to use the modem lines, we reopen it later
+ * in order to wait for the carrier detect signal from the modem.
+ */
+ hungup = 0;
+ kill_link = 0;
+ connector = doing_callback? callback_script: connect_script;
+ if (devnam[0] != 0) {
+ for (;;) {
+ /* If the user specified the device name, become the
+ user before opening it. */
+ int err, prio;
+
+ prio = privopen? OPRIO_ROOT: tty_options[0].priority;
+ if (prio < OPRIO_ROOT)
+ seteuid(uid);
+ ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0);
+ err = errno;
+ if (prio < OPRIO_ROOT)
+ seteuid(0);
+ if (ttyfd >= 0)
+ break;
+ errno = err;
+ if (err != EINTR) {
+ error("Failed to open %s: %m", devnam);
+ status = EXIT_OPEN_FAILED;
+ }
+ if (!persist || err != EINTR)
+ return -1;
+ }
+ real_ttyfd = ttyfd;
+ if ((fdflags = fcntl(ttyfd, F_GETFL)) == -1
+ || fcntl(ttyfd, F_SETFL, fdflags & ~O_NONBLOCK) < 0)
+ warn("Couldn't reset non-blocking mode on device: %m");
+
+ /*
+ * Do the equivalent of `mesg n' to stop broadcast messages.
+ */
+ if (fstat(ttyfd, &statbuf) < 0
+ || fchmod(ttyfd, statbuf.st_mode & ~(S_IWGRP | S_IWOTH)) < 0) {
+ warn("Couldn't restrict write permissions to %s: %m", devnam);
+ } else
+ tty_mode = statbuf.st_mode;
+
+ /*
+ * Set line speed, flow control, etc.
+ * If we have a non-null connection or initializer script,
+ * on most systems we set CLOCAL for now so that we can talk
+ * to the modem before carrier comes up. But this has the
+ * side effect that we might miss it if CD drops before we
+ * get to clear CLOCAL below. On systems where we can talk
+ * successfully to the modem with CLOCAL clear and CD down,
+ * we could clear CLOCAL at this point.
+ */
+ set_up_tty(ttyfd, ((connector != NULL && connector[0] != 0)
+ || initializer != NULL));
+ }
+}
+
+#ifdef CBCP_SUPPORT
+int callback()
+{
+ char *s;
+ char numbuf[16];
+
+ cbcp_protent.enabled_flag = 0; /* Already not need */
+ s = cbcp_get_script();
+ syslog(LOG_INFO, "Callback with <%s>",s );
+
+ set_up_tty( ttyfd, 1 );
+
+ if (real_ttyfd != -1) {
+ if (!default_device && modem) {
+ setdtr(real_ttyfd, 0); /* in case modem is off hook */
+ sleep(1);
+ setdtr(real_ttyfd, 1);
+ }
+ }
+
+ /* syslog(LOG_INFO, "ttyfd is %d and hungup is %d",ttyfd,hungup ); */
+ if (device_script(s, ttyfd, ttyfd, 0) < 0) {
+ error("Callback script failed");
+ status = EXIT_INIT_FAILED;
+ setdtr(ttyfd, 0 );
+ return -1;
+ }
+
+ info("Serial connection established." );
+
+ if (real_ttyfd != -1)
+ set_up_tty( real_ttyfd, 0 );
+
+ slprintf(numbuf, sizeof(numbuf), "%d", baud_rate);
+ script_setenv("SPEED", numbuf, 1);
+
+ return ttyfd;
+
+}
+#endif /* CBCP Support */