From: Paul Mackerras Date: Thu, 1 Jun 1995 07:01:42 +0000 (+0000) Subject: Update to state of pppd-new directory X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=41bd52fb6047d183d77b914449006deb59425463 Update to state of pppd-new directory --- diff --git a/pppd/Makefile.sun b/pppd/Makefile.sun index 98a335e..9c1513f 100644 --- a/pppd/Makefile.sun +++ b/pppd/Makefile.sun @@ -1,24 +1,22 @@ # # pppd makefile for Suns -# $Id: Makefile.sun,v 1.10 1995/04/28 06:15:48 paulus Exp $ +# $Id: Makefile.sun,v 1.10.2.1 1995/06/01 07:01:19 paulus Exp $ # BINDIR = /usr/local/etc MANDIR = /usr/local/man -INSTALL= install -o root -g daemon - PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \ auth.c options.c sys-bsd.c sys-str.c sys-ultrix.c sys-linux.c HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h MANPAGES = pppd.8 PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \ - auth.o options.o sys-str.o + auth.o options.o sys-str.o demand.o -# CC = gcc -DEBUG_FLAGS = -COMPILE_FLAGS = +CC = gcc +DEBUG_FLAGS = -g +COMPILE_FLAGS = -DSTREAMS COPTS = -O LIBS = -lkvm @@ -29,9 +27,9 @@ SOURCE= RELNOTES Makefile \ all: pppd -install: pppd - $(INSTALL) -c -m 4555 pppd $(BINDIR)/pppd - $(INSTALL) -c -m 444 pppd.8 $(MANDIR)/man8/pppd.8 +install: + install -c -m 4555 -o root -g daemon pppd $(BINDIR)/pppd + install -c -m 555 -o root pppd.8 $(MANDIR)/man8 pppd: $(PPPDOBJS) $(CC) $(CFLAGS) -o pppd $(PPPDOBJS) $(LIBS) @@ -42,4 +40,3 @@ clean: depend: cpp -M $(CFLAGS) $(PPPDSRCS) >.depend # makedepend $(CFLAGS) $(PPPDSRCS) - diff --git a/pppd/auth.c b/pppd/auth.c index f08fb31..7c6bbd3 100644 --- a/pppd/auth.c +++ b/pppd/auth.c @@ -33,7 +33,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: auth.c,v 1.15 1995/05/19 03:16:12 paulus Exp $"; +static char rcsid[] = "$Id: auth.c,v 1.15.2.1 1995/06/01 07:01:21 paulus Exp $"; #endif #include @@ -87,9 +87,19 @@ struct wordlist { /* Records which authentication operations haven't completed yet. */ static int auth_pending[NUM_PPP]; + +/* Set if we have successfully called login() */ static int logged_in; + +/* List of addresses which the peer may use. */ static struct wordlist *addresses[NUM_PPP]; +/* Number of network protocols which we have opened. */ +static int num_np_open; + +/* Number of network protocols which have come up. */ +static int num_np_up; + /* Bits in auth_pending[] */ #define UPAP_WITHPEER 1 #define UPAP_PEER 2 @@ -100,6 +110,7 @@ static struct wordlist *addresses[NUM_PPP]; void check_access __P((FILE *, char *)); static void network_phase __P((int)); +static void check_idle __P((caddr_t)); static int login __P((char *, char *, char **, int *)); static void logout __P((void)); static int null_login __P((int)); @@ -207,6 +218,7 @@ network_phase(unit) int unit; { phase = PHASE_NETWORK; + num_np_open = 1; ipcp_open(unit); ccp_open(unit); } @@ -303,6 +315,67 @@ auth_withpeer_success(unit, protocol) } +/* + * np_up - a network protocol has come up. + */ +void +np_up(unit, proto) + int unit, proto; +{ + if (num_np_up == 0 && idle_time_limit > 0) { + TIMEOUT(check_idle, NULL, idle_time_limit); + } + ++num_np_up; +} + +/* + * np_down - a network protocol has gone down. + */ +void +np_down(unit, proto) + int unit, proto; +{ + if (--num_np_up == 0 && idle_time_limit > 0) { + UNTIMEOUT(check_idle, NULL); + } +} + +/* + * np_finished - a network protocol has finished using the link. + */ +void +np_finished(unit, proto) + int unit, proto; +{ + if (--num_np_open <= 0) { + /* no further use for the link: shut up shop. */ + lcp_close(0); + } +} + +/* + * check_idle - check whether the link has been idle for long + * enough that we can shut it down. + */ +static void +check_idle(arg) + caddr_t arg; +{ + struct ppp_idle idle; + time_t itime; + + if (!get_idle_time(0, &idle)) + return; + itime = MIN(idle.xmit_idle, idle.recv_idle); + if (itime >= idle_time_limit) { + /* link is idle: shut it down. */ + syslog(LOG_INFO, "Terminating connection due to lack of activity."); + lcp_close(0); + } else { + TIMEOUT(check_idle, NULL, idle_time_limit - itime); + } +} + /* * check_auth_options - called to check authentication options. */ diff --git a/pppd/ccp.c b/pppd/ccp.c index 0ecfc97..aec1794 100644 --- a/pppd/ccp.c +++ b/pppd/ccp.c @@ -26,7 +26,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: ccp.c,v 1.9 1995/05/19 03:17:09 paulus Exp $"; +static char rcsid[] = "$Id: ccp.c,v 1.9.2.1 1995/06/01 07:01:22 paulus Exp $"; #endif #include @@ -109,6 +109,7 @@ ccp_init(unit) memset(&ccp_allowoptions[unit], 0, sizeof(ccp_options)); memset(&ccp_hisoptions[unit], 0, sizeof(ccp_options)); + ccp_wantoptions[0].bsd_compress = 1; ccp_wantoptions[0].bsd_bits = 12; /* default value */ ccp_allowoptions[0].bsd_compress = 1; diff --git a/pppd/ipcp.c b/pppd/ipcp.c index 112def9..260ab81 100644 --- a/pppd/ipcp.c +++ b/pppd/ipcp.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: ipcp.c,v 1.19 1995/06/01 01:30:38 paulus Exp $"; +static char rcsid[] = "$Id: ipcp.c,v 1.19.2.1 1995/06/01 07:01:26 paulus Exp $"; #endif /* @@ -44,7 +44,9 @@ ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ /* local vars */ -static int cis_received[NUM_PPP]; /* # Conf-Reqs received */ +static int cis_received[NUM_PPP]; /* # Conf-Reqs received */ +static int default_route_set[NUM_PPP]; /* Have set up a default route */ +static int proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */ /* * Callbacks for fsm code. (CI = Configuration Information) @@ -59,6 +61,7 @@ static int ipcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */ static void ipcp_up __P((fsm *)); /* We're UP */ static void ipcp_down __P((fsm *)); /* We're DOWN */ static void ipcp_script __P((fsm *, char *)); /* Run an up/down script */ +static void ipcp_finished __P((fsm *)); /* Don't need lower layer */ fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */ @@ -73,7 +76,7 @@ static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ ipcp_up, /* Called when fsm reaches OPENED state */ ipcp_down, /* Called when fsm leaves OPENED state */ NULL, /* Called when we want the lower layer up */ - NULL, /* Called when we want the lower layer down */ + ipcp_finished, /* Called when we want the lower layer down */ NULL, /* Called when Protocol-Reject received */ NULL, /* Retransmission is necessary */ NULL, /* Called to handle protocol-specific codes */ @@ -149,6 +152,8 @@ ipcp_init(unit) ao->neg_vj = 1; ao->maxslotindex = MAX_STATES - 1; ao->cflag = 1; + ao->default_route = 1; + ao->proxy_arp = 1; } @@ -962,6 +967,57 @@ endswitch: } +/* + * ipcp_demand_conf - configure the interface as though + * IPCP were up, for use with dial-on-demand. + */ +int +ipcp_demand_conf(u) + int u; +{ + ipcp_options *wo = &ipcp_wantoptions[u]; + + if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr))) + return 0; + if (!sifup(u)) + return 0; + if (wo->default_route) + if (sifdefaultroute(u, wo->hisaddr)) + default_route_set[u] = 1; + if (wo->proxy_arp) + if (sifproxyarp(u, wo->hisaddr)) + proxy_arp_set[u] = 1; + + syslog(LOG_NOTICE, "local IP address %s", ip_ntoa(wo->ouraddr)); + syslog(LOG_NOTICE, "remote IP address %s", ip_ntoa(wo->hisaddr)); + + return 1; +} + + +/* + * ipcp_demand_reset - reset the interface, which has been + * configured for dial-on-demand. + */ +void +ipcp_demand_reset(u) + int u; +{ + ipcp_options *wo = &ipcp_wantoptions[u]; + + if (proxy_arp_set[u]) { + cifproxyarp(u, wo->hisaddr); + proxy_arp_set[u] = 0; + } + if (default_route_set[u]) { + cifdefaultroute(u, wo->hisaddr); + default_route_set[u] = 0; + } + sifdown(u); + cifaddr(u, wo->ouraddr, wo->hisaddr); +} + + /* * ipcp_up - IPCP has come UP. * @@ -974,16 +1030,16 @@ ipcp_up(f) u_int32_t mask; ipcp_options *ho = &ipcp_hisoptions[f->unit]; ipcp_options *go = &ipcp_gotoptions[f->unit]; + ipcp_options *wo = &ipcp_wantoptions[f->unit]; + np_up(f->unit, PPP_IP); IPCPDEBUG((LOG_INFO, "ipcp: up")); - go->default_route = 0; - go->proxy_arp = 0; /* * We must have a non-zero IP address for both ends of the link. */ if (!ho->neg_addr) - ho->hisaddr = ipcp_wantoptions[f->unit].hisaddr; + ho->hisaddr = wo->hisaddr; if (ho->hisaddr == 0) { syslog(LOG_ERR, "Could not determine remote IP address"); @@ -1006,38 +1062,55 @@ ipcp_up(f) return; } - syslog(LOG_NOTICE, "local IP address %s", ip_ntoa(go->ouraddr)); - syslog(LOG_NOTICE, "remote IP address %s", ip_ntoa(ho->hisaddr)); + /* set tcp compression */ + sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex); /* - * Set IP addresses and (if specified) netmask. + * If we are doing dial-on-demand, the interface is already + * configured, so we put out any saved-up packets, then set the + * interface to pass IP packets. */ - mask = GetMask(go->ouraddr); - if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) { - IPCPDEBUG((LOG_WARNING, "sifaddr failed")); - ipcp_close(f->unit); - return; - } + if (demand) { + if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) { + syslog(LOG_ERR, "Failed to negotiate desired IP addresses"); + ipcp_close(f->unit); + return; + } + demand_rexmit(PPP_IP); + sifnpmode(f->unit, PPP_IP, NPMODE_PASS); + + } else { + + /* + * Set IP addresses and (if specified) netmask. + */ + mask = GetMask(go->ouraddr); + if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) { + IPCPDEBUG((LOG_WARNING, "sifaddr failed")); + ipcp_close(f->unit); + return; + } - /* set tcp compression */ - sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex); + /* bring the interface up for IP */ + if (!sifup(f->unit)) { + IPCPDEBUG((LOG_WARNING, "sifup failed")); + ipcp_close(f->unit); + return; + } - /* bring the interface up for IP */ - if (!sifup(f->unit)) { - IPCPDEBUG((LOG_WARNING, "sifup failed")); - ipcp_close(f->unit); - return; - } + /* assign a default route through the interface if required */ + if (ipcp_wantoptions[f->unit].default_route) + if (sifdefaultroute(f->unit, ho->hisaddr)) + default_route_set[f->unit] = 1; - /* assign a default route through the interface if required */ - if (ipcp_wantoptions[f->unit].default_route) - if (sifdefaultroute(f->unit, ho->hisaddr)) - go->default_route = 1; + /* Make a proxy ARP entry if requested. */ + if (ipcp_wantoptions[f->unit].proxy_arp) + if (sifproxyarp(f->unit, ho->hisaddr)) + proxy_arp_set[f->unit] = 1; - /* Make a proxy ARP entry if requested. */ - if (ipcp_wantoptions[f->unit].proxy_arp) - if (sifproxyarp(f->unit, ho->hisaddr)) - go->proxy_arp = 1; + syslog(LOG_NOTICE, "local IP address %s", ip_ntoa(go->ouraddr)); + syslog(LOG_NOTICE, "remote IP address %s", ip_ntoa(ho->hisaddr)); + } /* * Execute the ip-up script, like this: @@ -1060,22 +1133,47 @@ ipcp_down(f) { u_int32_t ouraddr, hisaddr; + np_down(f->unit, PPP_IP); IPCPDEBUG((LOG_INFO, "ipcp: down")); - ouraddr = ipcp_gotoptions[f->unit].ouraddr; - hisaddr = ipcp_hisoptions[f->unit].hisaddr; - if (ipcp_gotoptions[f->unit].proxy_arp) - cifproxyarp(f->unit, hisaddr); - if (ipcp_gotoptions[f->unit].default_route) - cifdefaultroute(f->unit, hisaddr); - sifdown(f->unit); - cifaddr(f->unit, ouraddr, hisaddr); + /* + * If we are doing dial-on-demand, set the interface + * to drop outgoing packets with an error (for now). + */ + if (demand) { + sifnpmode(f->unit, PPP_IP, NPMODE_ERROR); + + } else { + ouraddr = ipcp_gotoptions[f->unit].ouraddr; + hisaddr = ipcp_hisoptions[f->unit].hisaddr; + if (proxy_arp_set[f->unit]) { + cifproxyarp(f->unit, hisaddr); + proxy_arp_set[f->unit] = 0; + } + if (default_route_set[f->unit]) { + cifdefaultroute(f->unit, hisaddr); + default_route_set[f->unit] = 0; + } + sifdown(f->unit); + cifaddr(f->unit, ouraddr, hisaddr); + } /* Execute the ip-down script */ ipcp_script(f, _PATH_IPDOWN); } +/* + * ipcp_finished - possibly shut down the lower layers. + */ +static void +ipcp_finished(f) + fsm *f; +{ + np_finished(f->unit, PPP_IP); +} + + /* * ipcp_script - Execute a script with arguments * interface-name tty-name speed local-IP remote-IP. diff --git a/pppd/lcp.c b/pppd/lcp.c index af48e9c..fa90bd0 100644 --- a/pppd/lcp.c +++ b/pppd/lcp.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: lcp.c,v 1.19 1995/05/19 03:25:16 paulus Exp $"; +static char rcsid[] = "$Id: lcp.c,v 1.19.2.1 1995/06/01 07:01:27 paulus Exp $"; #endif /* @@ -43,11 +43,6 @@ static char rcsid[] = "$Id: lcp.c,v 1.19 1995/05/19 03:25:16 paulus Exp $"; #include "upap.h" #include "ipcp.h" -#ifdef _linux_ /* Needs ppp ioctls */ -#include -#include -#endif - /* global vars */ fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/ lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */ @@ -62,11 +57,6 @@ static u_int32_t lcp_echo_timer_running = 0; /* TRUE if a timer is running */ static u_char nak_buffer[PPP_MRU]; /* where we construct a nak packet */ -#ifdef _linux_ -u_int32_t idle_timer_running = 0; -extern int idle_time_limit; -#endif - /* * Callbacks for fsm code. (CI = Configuration Information) */ @@ -220,65 +210,6 @@ lcp_close(unit) fsm_close(&lcp_fsm[unit]); } -#ifdef _linux_ -static void IdleTimeCheck __P((caddr_t)); - -/* - * Timer expired for the LCP echo requests from this process. - */ - -static void -RestartIdleTimer (f) - fsm *f; -{ - u_long delta; - struct ppp_ddinfo ddinfo; - u_long latest; -/* - * Read the time since the last packet was received. - */ - if (ioctl (fd, PPPIOCGTIME, &ddinfo) < 0) { - syslog (LOG_ERR, "ioctl(PPPIOCGTIME): %m"); - die (1); - } -/* - * Choose the most recient IP activity. It may be a read or write frame - */ - latest = ddinfo.ip_sjiffies < ddinfo.ip_rjiffies ? ddinfo.ip_sjiffies - : ddinfo.ip_rjiffies; -/* - * Compute the time since the last packet was received. If the timer - * has expired then send the echo request and reset the timer to maximum. - */ - delta = (idle_time_limit * HZ) - latest; - if (((int) delta < HZ || (int) latest < 0L) && f->state == OPENED) { - syslog (LOG_NOTICE, "No IP frames exchanged within idle time limit"); - lcp_close(f->unit); /* Reset connection */ - phase = PHASE_TERMINATE; /* Mark it down */ - } else { - delta = (delta + HZ - 1) / HZ; - if (delta == 0) - delta = (u_long) idle_time_limit; - assert (idle_timer_running==0); - TIMEOUT (IdleTimeCheck, (caddr_t) f, delta); - idle_timer_running = 1; - } -} - -/* - * IdleTimeCheck - Timer expired on the IDLE detection for IP frames - */ - -static void -IdleTimeCheck (arg) - caddr_t arg; -{ - if (idle_timer_running != 0) { - idle_timer_running = 0; - RestartIdleTimer ((fsm *) arg); - } -} -#endif /* * lcp_lowerup - The lower layer is up. @@ -287,7 +218,6 @@ void lcp_lowerup(unit) int unit; { - sifdown(unit); ppp_set_xaccm(unit, xmit_accm[unit]); ppp_send_config(unit, PPP_MRU, 0xffffffff, 0, 0); ppp_recv_config(unit, PPP_MRU, 0x00000000, 0, 0); @@ -461,8 +391,8 @@ lcp_sprotrej(unit, p, len) * lcp_resetci - Reset our CI. */ static void - lcp_resetci(f) -fsm *f; +lcp_resetci(f) + fsm *f; { lcp_wantoptions[f->unit].magicnumber = magic(); lcp_wantoptions[f->unit].numloops = 0; @@ -861,6 +791,7 @@ lcp_nakci(f, p, len) * Check for a looped-back line. */ NAKCILONG(CI_MAGICNUMBER, neg_magicnumber, + magic_init(); try.magicnumber = magic(); looped_back = 1; ); @@ -1482,12 +1413,11 @@ lcp_down(f) ChapLowerDown(f->unit); upap_lowerdown(f->unit); - sifdown(f->unit); + link_down(f->unit); + ppp_send_config(f->unit, PPP_MRU, 0xffffffff, 0, 0); ppp_recv_config(f->unit, PPP_MRU, 0x00000000, 0, 0); peer_mru[f->unit] = PPP_MRU; - - link_down(f->unit); } @@ -1658,7 +1588,8 @@ void LcpLinkFailure (f) fsm *f; { if (f->state == OPENED) { - syslog (LOG_NOTICE, "Excessive lack of response to LCP echo frames."); + syslog(LOG_INFO, "No response to %d echo-requests", lcp_echos_pending); + syslog(LOG_NOTICE, "Serial link appears to be disconnected."); lcp_close(f->unit); /* Reset connection */ } } @@ -1671,43 +1602,13 @@ static void LcpEchoCheck (f) fsm *f; { - u_int32_t delta; -#ifdef __linux__ - struct ppp_ddinfo ddinfo; - u_int32_t latest; -/* - * Read the time since the last packet was received. - */ - if (ioctl (fd, PPPIOCGTIME, &ddinfo) < 0) { - syslog (LOG_ERR, "ioctl(PPPIOCGTIME): %m"); - die (1); - } -/* - * Choose the most recient frame received. It may be an IP or NON-IP frame. - */ - latest = ddinfo.nip_rjiffies < ddinfo.ip_rjiffies ? ddinfo.nip_rjiffies - : ddinfo.ip_rjiffies; -/* - * Compute the time since the last packet was received. If the timer - * has expired then send the echo request and reset the timer to maximum. - */ - delta = (lcp_echo_interval * HZ) - latest; - if (delta < HZ || latest < 0L) { - LcpSendEchoRequest (f); - delta = lcp_echo_interval * HZ; - } - delta /= HZ; - -#else /* Other implementations do not have ability to find delta */ LcpSendEchoRequest (f); - delta = lcp_echo_interval; -#endif -/* - * Start the timer for the next interval. - */ + /* + * Start the timer for the next interval. + */ assert (lcp_echo_timer_running==0); - TIMEOUT (LcpEchoTimeout, (caddr_t) f, delta); + TIMEOUT (LcpEchoTimeout, (caddr_t) f, lcp_echo_interval); lcp_echo_timer_running = 1; } @@ -1763,27 +1664,24 @@ LcpSendEchoRequest (f) u_int32_t lcp_magic; u_char pkt[4], *pktp; -/* - * Detect the failure of the peer at this point. - */ + /* + * Detect the failure of the peer at this point. + */ if (lcp_echo_fails != 0) { if (lcp_echos_pending++ >= lcp_echo_fails) { LcpLinkFailure(f); lcp_echos_pending = 0; } } -/* - * Make and send the echo request frame. - */ + + /* + * Make and send the echo request frame. + */ if (f->state == OPENED) { - lcp_magic = lcp_gotoptions[f->unit].neg_magicnumber - ? lcp_gotoptions[f->unit].magicnumber - : 0L; + lcp_magic = lcp_gotoptions[f->unit].magicnumber; pktp = pkt; PUTLONG(lcp_magic, pktp); - - fsm_sdata(f, ECHOREQ, - lcp_echo_number++ & 0xFF, pkt, pktp - pkt); + fsm_sdata(f, ECHOREQ, lcp_echo_number++ & 0xFF, pkt, pktp - pkt); } } @@ -1805,11 +1703,6 @@ lcp_echo_lowerup (unit) /* If a timeout interval is specified then start the timer */ if (lcp_echo_interval != 0) LcpEchoCheck (f); -#ifdef _linux_ - /* If a idle time limit is given then start it */ - if (idle_time_limit != 0) - RestartIdleTimer (f); -#endif } /* @@ -1826,11 +1719,4 @@ lcp_echo_lowerdown (unit) UNTIMEOUT (LcpEchoTimeout, (caddr_t) f); lcp_echo_timer_running = 0; } -#ifdef _linux_ - /* If a idle time limit is running then stop it */ - if (idle_timer_running != 0) { - UNTIMEOUT (IdleTimeCheck, (caddr_t) f); - idle_timer_running = 0; - } -#endif } diff --git a/pppd/magic.c b/pppd/magic.c index 7391b14..f219243 100644 --- a/pppd/magic.c +++ b/pppd/magic.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: magic.c,v 1.4 1995/04/24 05:57:01 paulus Exp $"; +static char rcsid[] = "$Id: magic.c,v 1.4.2.1 1995/06/01 07:01:29 paulus Exp $"; #endif #include @@ -39,14 +39,17 @@ extern void srand48 __P((long)); * magic_init - Initialize the magic number generator. * * Attempts to compute a random number seed which will not repeat. - * The current method uses the current hostid and current time, currently. + * The current method uses the current hostid, current process ID + * and current time, currently. */ void magic_init() { long seed; + struct timeval t; - seed = gethostid() ^ time(NULL); + gettimeofday(&t, NULL); + seed = gethostid() ^ t.tv_sec ^ t.tv_usec ^ getpid(); srand48(seed); } diff --git a/pppd/main.c b/pppd/main.c index 38af544..51b5535 100644 --- a/pppd/main.c +++ b/pppd/main.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: main.c,v 1.23 1995/05/19 03:26:25 paulus Exp $"; +static char rcsid[] = "$Id: main.c,v 1.23.2.1 1995/06/01 07:01:31 paulus Exp $"; #endif #include @@ -78,24 +78,28 @@ int kill_link; int open_ccp_flag; static int initfdflags = -1; /* Initial file descriptor flags */ +static int loop_fd = -1; /* fd for loopback device */ u_char outpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for outgoing packet */ -static u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */ +u_char inpacket_buf[PPP_MRU+PPP_HDRLEN]; /* buffer for incoming packet */ int hungup; /* terminal has been hung up */ static int n_children; /* # child processes still running */ int baud_rate; +static int locked; + /* prototypes */ static void hup __P((int)); static void term __P((int)); static void chld __P((int)); static void toggle_debug __P((int)); static void open_ccp __P((int)); +static void holdoff_end __P((void *)); static void get_input __P((void)); -void establish_ppp __P((void)); +void establish_ppp __P((int)); void calltimeout __P((void)); struct timeval *timeleft __P((struct timeval *)); void reap_kids __P((void)); @@ -206,6 +210,14 @@ main(argc, argv) sys_init(); magic_init(); + /* + * For dial-on-demand, we need to know the remote address. + */ + if (demand && ipcp_wantoptions[0].hisaddr == 0) { + fprintf(stderr, "Remote IP address must be specified for dial-on-demand\n"); + exit(1); + } + /* * Detach ourselves from the terminal, if required, * and identify who is running us. @@ -256,13 +268,72 @@ main(argc, argv) signal(SIGUSR2, open_ccp); /* Reopen CCP */ /* - * Lock the device if we've been asked to. + * If we're doing dial-on-demand, set up the interface now. */ - if (lockflag && !default_device) - if (lock(devnam) < 0) - die(1); + if (demand) { + /* + * Open the loopback channel and set it up to be the ppp interface. + */ + loop_fd = open_loopback(); + establish_ppp(loop_fd); + + syslog(LOG_INFO, "Using interface ppp%d", ifunit); + (void) sprintf(ifname, "ppp%d", ifunit); + + /* write pid to file */ + (void) sprintf(pidfilename, "%s%s.pid", _PATH_VARRUN, ifname); + if ((pidfile = fopen(pidfilename, "w")) != NULL) { + fprintf(pidfile, "%d\n", pid); + (void) fclose(pidfile); + } else { + syslog(LOG_ERR, "Failed to create pid file %s: %m", pidfilename); + pidfilename[0] = 0; + } + + /* + * Configure the interface and mark it up, etc. + */ + demand_conf(); + } + + for (;;) { + + if (demand) { + /* + * Don't do anything until we see some activity. + */ + phase = PHASE_DORMANT; + fd = loop_fd; + kill_link = 0; + demand_unblock(); + for (;;) { + wait_loop_output(timeleft(&timo)); + calltimeout(); + if (kill_link) { + if (!persist) + die(0); + kill_link = 0; + } + if (get_loop_output()) + break; + reap_kids(); + } + + /* + * Now we want to bring up the link. + */ + demand_block(); + syslog(LOG_INFO, "Starting link"); + } - do { + /* + * Lock the device if we've been asked to. + */ + if (lockflag && !default_device) { + if (lock(devnam) < 0) + goto fail; + locked = 1; + } /* * Open the serial device and set it up to be the ppp interface. @@ -273,7 +344,7 @@ main(argc, argv) nonblock = (connector || !modem)? O_NONBLOCK: 0; if ((fd = open(devnam, nonblock | O_RDWR, 0)) < 0) { syslog(LOG_ERR, "Failed to open %s: %m", devnam); - die(1); + goto fail; } if ((initfdflags = fcntl(fd, F_GETFL)) == -1) { syslog(LOG_ERR, "Couldn't get device fd flags: %m"); @@ -303,32 +374,16 @@ main(argc, argv) if (device_script(connector, fd, fd) < 0) { syslog(LOG_ERR, "Connect script failed"); setdtr(fd, FALSE); - die(1); + goto fail; } - syslog(LOG_INFO, "Connected..."); + syslog(LOG_INFO, "Serial connection established."); sleep(1); /* give it time to set up its terminal */ } /* set line speed, flow control, etc.; clear CLOCAL if modem option */ set_up_tty(fd, 0); - /* set up the serial device as a ppp interface */ - establish_ppp(); - - syslog(LOG_INFO, "Using interface ppp%d", ifunit); - (void) sprintf(ifname, "ppp%d", ifunit); - - /* write pid to file */ - (void) sprintf(pidfilename, "%s%s.pid", _PATH_VARRUN, ifname); - if ((pidfile = fopen(pidfilename, "w")) != NULL) { - fprintf(pidfile, "%d\n", pid); - (void) fclose(pidfile); - } else { - syslog(LOG_ERR, "Failed to create pid file %s: %m", pidfilename); - pidfilename[0] = 0; - } - /* * Set device for non-blocking reads. */ @@ -337,8 +392,33 @@ main(argc, argv) die(1); } + if (!demand) { + /* set up the serial device as a ppp interface */ + establish_ppp(fd); + + syslog(LOG_INFO, "Using interface ppp%d", ifunit); + (void) sprintf(ifname, "ppp%d", ifunit); + + /* write pid to file */ + (void) sprintf(pidfilename, "%s%s.pid", _PATH_VARRUN, ifname); + if ((pidfile = fopen(pidfilename, "w")) != NULL) { + fprintf(pidfile, "%d\n", pid); + (void) fclose(pidfile); + } else { + syslog(LOG_ERR, "Failed to create pid file %s: %m", + pidfilename); + pidfilename[0] = 0; + } + + } else { + /* + * Transfer the PPP unit over to the real serial device. + */ + transfer_ppp(fd); + } + /* - * Block all signals, start opening the connection, and wait for + * Start opening the connection and wait for * incoming events (reply, timeout, etc.). */ syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam); @@ -362,33 +442,80 @@ main(argc, argv) reap_kids(); /* Don't leave dead kids lying around */ } + /* + * If we may want to bring the link up again, transfer + * the ppp unit back to the loopback. Set the + * real serial device back to its normal mode of operation. + */ + clean_check(); + if (demand) { + transfer_ppp(loop_fd); + } else { + disestablish_ppp(fd); + } + /* * Run disconnector script, if requested. * First we need to reset non-blocking mode. + * XXX we may not be able to do this if the line has hung up! */ if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) >= 0) initfdflags = -1; - disestablish_ppp(); - if (disconnector) { + if (disconnector && !hungup) { set_up_tty(fd, 1); if (device_script(disconnector, fd, fd) < 0) { syslog(LOG_WARNING, "disconnect script failed"); - die(1); + } else { + syslog(LOG_INFO, "Serial link disconnected."); } - - syslog(LOG_INFO, "Disconnected..."); } + fail: close_fd(); - if (unlink(pidfilename) < 0 && errno != ENOENT) - syslog(LOG_WARNING, "unable to delete pid file: %m"); - pidfilename[0] = 0; + if (locked) { + unlock(); + locked = 0; + } + + if (!demand) { + if (unlink(pidfilename) < 0 && errno != ENOENT) + syslog(LOG_WARNING, "unable to delete pid file: %m"); + pidfilename[0] = 0; + } + + if (!persist) + break; - } while (persist); + demand_discard(); + if (holdoff > 0) { + phase = PHASE_HOLDOFF; + TIMEOUT(holdoff_end, NULL, holdoff); + do { + wait_time(timeleft(&timo)); + calltimeout(); + if (kill_link) { + if (!persist) + die(0); + kill_link = 0; + phase = PHASE_DORMANT; /* allow signal to end holdoff */ + } + reap_kids(); + } while (phase == PHASE_HOLDOFF); + } + } die(0); } +/* + * holdoff_end - called via a timeout when the holdoff period ends. + */ +static void +holdoff_end(arg) + void *arg; +{ + phase = PHASE_DORMANT; +} /* * get_input - called when incoming data is available. @@ -518,8 +645,11 @@ cleanup(status, arg) syslog(LOG_WARNING, "unable to delete pid file: %m"); pidfilename[0] = 0; - if (lockflag && !default_device) + if (locked) unlock(); + + if (demand) + demand_reset(); } /* @@ -536,7 +666,7 @@ close_fd() syslog(LOG_WARNING, "Couldn't restore device fd flags: %m"); initfdflags = -1; - disestablish_ppp(); + disestablish_ppp(fd); restore_tty(); @@ -760,6 +890,7 @@ device_script(program, in, out) { int pid; int status; + int errfd; pid = fork(); @@ -769,10 +900,14 @@ device_script(program, in, out) } if (pid == 0) { - setuid(getuid()); - setgid(getgid()); + sys_close(); dup2(in, 0); dup2(out, 1); + errfd = open(_PATH_CONNERRS, O_WRONLY | O_APPEND | O_CREAT, 0644); + if (errfd >= 0) + dup2(errfd, 2); + setuid(getuid()); + setgid(getgid()); execl("/bin/sh", "sh", "-c", program, (char *)0); syslog(LOG_ERR, "could not exec /bin/sh: %m"); _exit(99); @@ -821,11 +956,11 @@ run_program(prog, args, must_exist) setgid(getegid()); /* Ensure that nothing of our device environment is inherited. */ + sys_close(); close (0); close (1); close (2); close (fd); /* tty interface to the ppp device */ - /* XXX should call sysdep cleanup procedure here */ /* Don't pass handles to the PPP device, even by accident. */ new_fd = open (_PATH_DEVNULL, O_RDWR); diff --git a/pppd/options.c b/pppd/options.c index 3d5e020..d97f60a 100644 --- a/pppd/options.c +++ b/pppd/options.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: options.c,v 1.19 1995/04/27 00:20:16 paulus Exp $"; +static char rcsid[] = "$Id: options.c,v 1.19.2.1 1995/06/01 07:01:33 paulus Exp $"; #endif #include @@ -86,13 +86,11 @@ char our_name[MAXNAMELEN]; /* Our name for authentication purposes */ char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ int usehostname = 0; /* Use hostname for our_name */ int disable_defaultip = 0; /* Don't use hostname for default IP adrs */ +int demand = 0; /* do dial-on-demand */ char *ipparam = NULL; /* Extra parameter for ip up/down scripts */ int cryptpap; /* Passwords in pap-secrets are encrypted */ - -#ifdef _linux_ -int idle_time_limit = 0; -static int setidle __P((char **)); -#endif +int idle_time_limit = 0; /* Disconnect if idle for this many seconds */ +int holdoff = 30; /* # seconds to pause before reconnecting */ /* * Prototypes @@ -138,7 +136,9 @@ static int setremote __P((char **)); static int setauth __P((void)); static int readfile __P((char **)); static int setdefaultroute __P((void)); +static int setnodefaultroute __P((void)); static int setproxyarp __P((void)); +static int setnoproxyarp __P((void)); static int setpersist __P((void)); static int setdologin __P((void)); static int setusehostname __P((void)); @@ -162,8 +162,11 @@ static int setlcpechointv __P((char **)); static int setlcpechofails __P((char **)); static int setbsdcomp __P((char **)); static int setnobsdcomp __P((void)); +static int setdemand __P((void)); static int setipparam __P((char **)); static int setpapcrypt __P((void)); +static int setidle __P((char **)); +static int setholdoff __P((char **)); static int number_option __P((char *, long *, int)); static int readable __P((int fd)); @@ -222,8 +225,11 @@ static struct cmd { {"auth", 0, setauth}, /* Require authentication from peer */ {"file", 1, readfile}, /* Take options from a file */ {"defaultroute", 0, setdefaultroute}, /* Add default route */ + {"-defaultroute", 0, setnodefaultroute}, /* disable defaultroute option */ {"proxyarp", 0, setproxyarp}, /* Add proxy ARP entry */ + {"-proxyarp", 0, setnoproxyarp}, /* disable proxyarp option */ {"persist", 0, setpersist}, /* Keep on reopening connection after close */ + {"demand", 0, setdemand}, /* Dial on demand */ {"login", 0, setdologin}, /* Use system password database for UPAP */ {"noipdefault", 0, setnoipdflt}, /* Don't use name for default IP adrs */ {"lcp-echo-failure", 1, setlcpechofails}, /* consecutive echo failures */ @@ -247,9 +253,8 @@ static struct cmd { {"-bsdcomp", 0, setnobsdcomp}, /* don't allow BSD-Compress */ {"ipparam", 1, setipparam}, /* set ip script parameter */ {"papcrypt", 0, setpapcrypt}, /* PAP passwords encrypted */ -#ifdef _linux_ - {"idle-disconnect", 1, setidle}, /* seconds for disconnect of idle IP */ -#endif + {"idle", 1, setidle}, /* idle time limit (seconds) */ + {"holdoff", 1, setholdoff}, /* set holdoff time (seconds) */ {NULL, 0, NULL} }; @@ -1278,6 +1283,13 @@ setnodetach() return (1); } +static int +setdemand() +{ + demand = 1; + return 1; +} + static int setmodem() { @@ -1345,17 +1357,41 @@ setauth() static int setdefaultroute() { + if (!ipcp_allowoptions[0].default_route) { + fprintf(stderr, "%s: defaultroute option is disabled\n", progname); + return 0; + } ipcp_wantoptions[0].default_route = 1; return 1; } +static int +setnodefaultroute() +{ + ipcp_allowoptions[0].default_route = 0; + ipcp_wantoptions[0].default_route = 0; + return 1; +} + static int setproxyarp() { + if (!ipcp_allowoptions[0].proxy_arp) { + fprintf(stderr, "%s: proxyarp option is disabled\n", progname); + return 0; + } ipcp_wantoptions[0].proxy_arp = 1; return 1; } +static int +setnoproxyarp() +{ + ipcp_wantoptions[0].proxy_arp = 0; + ipcp_allowoptions[0].proxy_arp = 0; + return 1; +} + static int setpersist() { @@ -1545,10 +1581,16 @@ setpapcrypt() return 1; } -#ifdef _linux_ -static int setidle (argv) +static int +setidle(argv) char **argv; { return int_option(*argv, &idle_time_limit); } -#endif + +static int +setholdoff(argv) + char **argv; +{ + return int_option(*argv, &holdoff); +} diff --git a/pppd/patchlevel.h b/pppd/patchlevel.h index 629e48a..3dac0ce 100644 --- a/pppd/patchlevel.h +++ b/pppd/patchlevel.h @@ -1,6 +1,6 @@ -/* $Id: patchlevel.h,v 1.13 1994/10/24 04:53:17 paulus Exp $ */ +/* $Id: patchlevel.h,v 1.13.2.1 1995/06/01 07:01:35 paulus Exp $ */ #define PATCHLEVEL 0 -#define VERSION "2.2" -#define IMPLEMENTATION "alpha3" -#define DATE "24 Oct 94" +#define VERSION "2.3" +#define IMPLEMENTATION "alpha" +#define DATE "22 Dec 94" diff --git a/pppd/pathnames.h b/pppd/pathnames.h index 7baf95a..51ca73d 100644 --- a/pppd/pathnames.h +++ b/pppd/pathnames.h @@ -1,7 +1,7 @@ /* * define path names * - * $Id: pathnames.h,v 1.5 1994/09/01 00:32:56 paulus Exp $ + * $Id: pathnames.h,v 1.5.2.1 1995/06/01 07:01:36 paulus Exp $ */ #ifdef HAVE_PATHS_H @@ -18,4 +18,5 @@ #define _PATH_IPUP "/etc/ppp/ip-up" #define _PATH_IPDOWN "/etc/ppp/ip-down" #define _PATH_TTYOPT "/etc/ppp/options." +#define _PATH_CONNERRS "/etc/ppp/connect-errors" #define _PATH_USEROPT ".ppprc" diff --git a/pppd/pppd.h b/pppd/pppd.h index 66b0107..bbf04fd 100644 --- a/pppd/pppd.h +++ b/pppd/pppd.h @@ -16,7 +16,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: pppd.h,v 1.8 1995/04/26 06:46:31 paulus Exp $ + * $Id: pppd.h,v 1.8.2.1 1995/06/01 07:01:37 paulus Exp $ */ /* @@ -83,17 +83,22 @@ extern char our_name[]; /* Our name for authentication purposes */ extern char remote_name[]; /* Peer's name for authentication */ extern int usehostname; /* Use hostname for our_name */ extern int disable_defaultip; /* Don't use hostname for default IP adrs */ +extern int demand; /* Do dial-on-demand */ extern char *ipparam; /* Extra parameter for ip up/down scripts */ extern int cryptpap; /* Others' PAP passwords are encrypted */ +extern int idle_time_limit;/* Shut down link if idle for this long */ +extern int holdoff; /* Dead time before restarting */ /* * Values for phase. */ #define PHASE_DEAD 0 -#define PHASE_ESTABLISH 1 -#define PHASE_AUTHENTICATE 2 -#define PHASE_NETWORK 3 -#define PHASE_TERMINATE 4 +#define PHASE_DORMANT 1 +#define PHASE_ESTABLISH 2 +#define PHASE_AUTHENTICATE 3 +#define PHASE_NETWORK 4 +#define PHASE_TERMINATE 5 +#define PHASE_HOLDOFF 6 /* * Prototypes. @@ -113,6 +118,9 @@ int get_secret __P((int, char *, char *, char *, int *, int)); /* get "secret" for chap */ u_int32_t GetMask __P((u_int32_t)); /* get netmask for address */ void die __P((int)); +void np_up __P((int, int)); +void np_down __P((int, int)); +void np_finished __P((int, int)); /* * Inline versions of get/put char/short/long. @@ -192,9 +200,9 @@ void die __P((int)); #endif #ifndef LOG_PPP /* we use LOG_LOCAL2 for syslog by default */ -#if defined(DEBUGMAIN) || defined(DEBUGFSM) || defined(DEBUG) \ +#if defined(DEBUGMAIN) || defined(DEBUGFSM) || defined(DEBUGSYS) \ || defined(DEBUGLCP) || defined(DEBUGIPCP) || defined(DEBUGUPAP) \ - || defined(DEBUGCHAP) + || defined(DEBUGCHAP) || defined(DEBUG) #define LOG_PPP LOG_LOCAL2 #else #define LOG_PPP LOG_DAEMON @@ -207,6 +215,12 @@ void die __P((int)); #define MAINDEBUG(x) #endif +#ifdef DEBUGSYS +#define SYSDEBUG(x) if (debug) syslog x +#else +#define SYSDEBUG(x) +#endif + #ifdef DEBUGFSM #define FSMDEBUG(x) if (debug) syslog x #else diff --git a/pppd/sys-bsd.c b/pppd/sys-bsd.c index 1a7c83a..c6deb26 100644 --- a/pppd/sys-bsd.c +++ b/pppd/sys-bsd.c @@ -19,7 +19,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: sys-bsd.c,v 1.19 1995/05/19 03:27:03 paulus Exp $"; +static char rcsid[] = "$Id: sys-bsd.c,v 1.19.2.1 1995/06/01 07:01:39 paulus Exp $"; #endif /* @@ -53,13 +53,18 @@ static char rcsid[] = "$Id: sys-bsd.c,v 1.19 1995/05/19 03:27:03 paulus Exp $"; #include "pppd.h" static int initdisc = -1; /* Initial TTY discipline */ +static int ppp_fd = -1; /* fd which is set to PPP discipline */ static int rtm_seq; -static int restore_term; /* 1 => we've munged the terminal */ +static int restore_term; /* 1 => we've munged the terminal */ static struct termios inittermios; /* Initial TTY termios */ static char *lock_file; /* name of lock file created */ +static int loop_slave = -1; +static int loop_master; +static char loop_name[20]; + int sockfd; /* socket for doing interface ioctls */ /* @@ -80,6 +85,17 @@ sys_init() } } +/* + * sys_close - Clean up in a child process before execing. + */ +void +sys_close() +{ + close(sockfd); + closelog(); +} + + /* * note_debug_level - note a change in the debug level. */ @@ -105,7 +121,7 @@ ppp_available() struct ifreq ifr; if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - return 1; /* can't tell - maybe we're not root */ + return 1; /* can't tell */ strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name)); ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0; @@ -115,10 +131,11 @@ ppp_available() } /* - * establish_ppp - Turn the serial port into a ppp interface. + * establish_ppp - Turn the serial port (or loopback) into a ppp interface. */ void -establish_ppp() +establish_ppp(fd) + int fd; { int pppdisc = PPPDISC; int x; @@ -139,6 +156,7 @@ establish_ppp() syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m"); die(1); } + ppp_fd = fd; /* * Enable debug in the driver if requested. @@ -155,47 +173,111 @@ establish_ppp() } +/* + * transfer_ppp - make the device on fd `fd' take over the PPP interface + * unit that we are using. + */ +void +transfer_ppp(fd) + int fd; +{ + int x, prevdisc; + + if (fd == ppp_fd) + return; /* we can't get here */ + + /* + * Prime the old ppp device to relinquish the unit. + */ + if (ioctl(ppp_fd, PPPIOCXFERUNIT, 0) < 0) { + syslog(LOG_ERR, "ioctl(transfer ppp unit): %m"); + die(1); + } + + /* + * Save the old line discipline of fd, and set it to PPP. + */ + if (ioctl(fd, TIOCGETD, &prevdisc) < 0) { + syslog(LOG_ERR, "ioctl(TIOCGETD): %m"); + die(1); + } + x = PPPDISC; + if (ioctl(fd, TIOCSETD, &x) < 0) { + syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); + die(1); + } + + /* + * Set the old ppp device back to its previous discipline. + */ + ioctl(ppp_fd, TIOCSETD, &initdisc); + initdisc = prevdisc; + + /* + * Check that we got the same unit again. + */ + if (ioctl(fd, PPPIOCGUNIT, &x) < 0) { + syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m"); + die(1); + } + if (x != ifunit) { + syslog(LOG_ERR, "transfer_ppp failed: wanted unit %d, got %d", + ifunit, x); + die(1); + } + + ppp_fd = fd; +} + + /* * disestablish_ppp - Restore the serial port to normal operation. * This shouldn't call die() because it's called from die(). */ void -disestablish_ppp() +disestablish_ppp(fd) + int fd; +{ + if (fd == ppp_fd && fd >= 0 && initdisc >= 0) { + if (ioctl(fd, TIOCSETD, &initdisc) < 0) + syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); + initdisc = -1; + ppp_fd = -1; + } +} + +/* + * Check whether the link seems not to be 8-bit clean. + */ +void +clean_check() { int x; char *s; - if (initdisc >= 0) { - /* - * Check whether the link seems not to be 8-bit clean. - */ - if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) { - s = NULL; - switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) { - case SC_RCV_B7_0: - s = "bit 7 set to 1"; - break; - case SC_RCV_B7_1: - s = "bit 7 set to 0"; - break; - case SC_RCV_EVNP: - s = "odd parity"; - break; - case SC_RCV_ODDP: - s = "even parity"; - break; - } - if (s != NULL) { - syslog(LOG_WARNING, "Serial link is not 8-bit clean:"); - syslog(LOG_WARNING, "All received characters had %s", s); - } + if (ioctl(ppp_fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) { + s = NULL; + switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) { + case SC_RCV_B7_0: + s = "bit 7 set to 1"; + break; + case SC_RCV_B7_1: + s = "bit 7 set to 0"; + break; + case SC_RCV_EVNP: + s = "odd parity"; + break; + case SC_RCV_ODDP: + s = "even parity"; + break; + } + if (s != NULL) { + syslog(LOG_WARNING, "Serial link is not 8-bit clean:"); + syslog(LOG_WARNING, "All received characters had %s", s); } - if (ioctl(fd, TIOCSETD, &initdisc) < 0) - syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); } } - /* * set_up_tty: Set up the serial port on `fd' for 8 bits, no parity, * at the requested speed, etc. If `local' is true, set CLOCAL @@ -298,6 +380,40 @@ int fd, on; } +/* + * open_loopback - open the device we use for getting packets + * in demand mode. Here we use a pty. + */ +int +open_loopback() +{ + int flags; + struct termios tios; + + if (openpty(&loop_master, &loop_slave, loop_name, NULL, NULL) < 0) { + syslog(LOG_ERR, "No free pty for loopback"); + die(1); + } + SYSDEBUG((LOG_DEBUG, "using %s for loopback", loop_name)); + if (tcgetattr(loop_slave, &tios) == 0) { + tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB); + tios.c_cflag |= CS8 | CREAD; + tios.c_iflag = IGNPAR; + tios.c_oflag = 0; + tios.c_lflag = 0; + if (tcsetattr(loop_slave, TCSAFLUSH, &tios) < 0) + syslog(LOG_WARNING, "couldn't set attributes on loopback: %m"); + } + if ((flags = fcntl(loop_slave, F_GETFL)) != -1) + if (fcntl(loop_slave, F_SETFL, flags | O_NONBLOCK) == -1) + syslog(LOG_WARNING, "couldn't set loopback to nonblock: %m"); + if ((flags = fcntl(loop_master, F_GETFL)) != -1) + if (fcntl(loop_master, F_SETFL, flags | O_NONBLOCK) == -1) + syslog(LOG_WARNING, "couldn't set loopback(m) to nonblock: %m"); + return loop_slave; +} + + /* * output - Output PPP packet. */ @@ -308,7 +424,7 @@ output(unit, p, len) int len; { if (unit != 0) - MAINDEBUG((LOG_WARNING, "output: unit != 0!")); + SYSDEBUG((LOG_WARNING, "output: unit != 0!")); if (debug) log_packet(p, len, "sent "); @@ -340,6 +456,44 @@ wait_input(timo) } +/* + * wait_loop_output - wait until there is data available on the, + * loopback, for the length of time specified by *timo (indefinite + * if timo is NULL). + */ +wait_loop_output(timo) + struct timeval *timo; +{ + fd_set ready; + int n; + + FD_ZERO(&ready); + FD_SET(loop_master, &ready); + n = select(loop_master + 1, &ready, NULL, &ready, timo); + if (n < 0 && errno != EINTR) { + syslog(LOG_ERR, "select: %m"); + die(1); + } +} + + +/* + * wait_time - wait for a given length of time or until a + * signal is received. + */ +wait_time(timo) + struct timeval *timo; +{ + int n; + + n = select(0, NULL, NULL, NULL, timo); + if (n < 0 && errno != EINTR) { + syslog(LOG_ERR, "select: %m"); + die(1); + } +} + + /* * read_packet - get a PPP packet from the serial device. */ @@ -359,6 +513,29 @@ read_packet(buf) } +/* + * read_loop_output - get characters from the "bottom" of the loopback. + */ +int +read_loop_output(buf, maxlen) + u_char *buf; + int maxlen; +{ + int len; + + if ((len = read(loop_master, buf, maxlen)) < 0) { + if (errno == EWOULDBLOCK) + return 0; + syslog(LOG_ERR, "read from loopback: %m"); + die(1); + } else if (len == 0) { + syslog(LOG_ERR, "eof on loopback"); + die(1); + } + return len; +} + + /* * ppp_send_config - configure the transmit characteristics of * the ppp interface. @@ -376,23 +553,23 @@ ppp_send_config(unit, mtu, asyncmap, pcomp, accomp) ifr.ifr_mtu = mtu; if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) { syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m"); - quit(); + die(1); } if (ioctl(fd, PPPIOCSASYNCMAP, (caddr_t) &asyncmap) < 0) { syslog(LOG_ERR, "ioctl(PPPIOCSASYNCMAP): %m"); - quit(); + die(1); } if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m"); - quit(); + die(1); } x = pcomp? x | SC_COMP_PROT: x &~ SC_COMP_PROT; x = accomp? x | SC_COMP_AC: x &~ SC_COMP_AC; if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) { syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); - quit(); + die(1); } } @@ -424,20 +601,20 @@ ppp_recv_config(unit, mru, asyncmap, pcomp, accomp) if (ioctl(fd, PPPIOCSMRU, (caddr_t) &mru) < 0) { syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m"); - quit(); + die(1); } if (ioctl(fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) { syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m"); - quit(); + die(1); } if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m"); - quit(); + die(1); } x = !accomp? x | SC_REJ_COMP_AC: x &~ SC_REJ_COMP_AC; if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) { syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); - quit(); + die(1); } } @@ -494,6 +671,18 @@ ccp_fatal_error(unit) return x & SC_DC_FERROR; } +/* + * get_idle_time - return how long the link has been idle. + */ +int +get_idle_time(u, ip) + int u; + struct ppp_idle *ip; +{ + return ioctl(fd, PPPIOCGIDLE, ip) >= 0; +} + + /* * sifvjcomp - config tcp header compression */ @@ -523,16 +712,11 @@ sifvjcomp(u, vjcomp, cidcomp, maxcid) /* * sifup - Config the interface up and enable IP packets to pass. */ -#ifndef SC_ENABLE_IP -#define SC_ENABLE_IP 0x100 /* compat for old versions of kernel code */ -#endif - int sifup(u) int u; { struct ifreq ifr; - u_int x; struct npioctl npi; strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); @@ -548,20 +732,28 @@ sifup(u) npi.protocol = PPP_IP; npi.mode = NPMODE_PASS; if (ioctl(fd, PPPIOCSNPMODE, &npi) < 0) { - if (errno != ENOTTY) { - syslog(LOG_ERR, "ioctl(PPPIOCSNPMODE): %m"); - return 0; - } - /* for backwards compatibility */ - if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { - syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m"); - return 0; - } - x |= SC_ENABLE_IP; - if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) { - syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); - return 0; - } + syslog(LOG_ERR, "ioctl(set IP mode to PASS): %m"); + return 0; + } + return 1; +} + +/* + * sifnpmode - Set the mode for handling packets for a given NP. + */ +int +sifnpmode(u, proto, mode) + int u; + int proto; + enum NPmode mode; +{ + struct npioctl npi; + + npi.protocol = proto; + npi.mode = mode; + if (ioctl(fd, PPPIOCSNPMODE, &npi) < 0) { + syslog(LOG_ERR, "ioctl(set NP %d mode to %d): %m", proto, mode); + return 0; } return 1; } @@ -574,31 +766,14 @@ sifdown(u) int u; { struct ifreq ifr; - u_int x; int rv; struct npioctl npi; rv = 1; npi.protocol = PPP_IP; npi.mode = NPMODE_ERROR; - if (ioctl(fd, PPPIOCSNPMODE, (caddr_t) &npi) < 0) { - if (errno != ENOTTY) { - syslog(LOG_ERR, "ioctl(PPPIOCSNPMODE): %m"); - rv = 0; - } else { - /* backwards compatibility */ - if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { - syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m"); - rv = 0; - } else { - x &= ~SC_ENABLE_IP; - if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) { - syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); - rv = 0; - } - } - } - } + ioctl(ppp_fd, PPPIOCSNPMODE, (caddr_t) &npi); + /* ignore errors, because ppp_fd might have been closed by now. */ strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { diff --git a/pppd/sys-str.c b/pppd/sys-str.c index e583133..ae3c101 100644 --- a/pppd/sys-str.c +++ b/pppd/sys-str.c @@ -19,7 +19,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: sys-str.c,v 1.20 1995/05/01 00:26:22 paulus Exp $"; +static char rcsid[] = "$Id: sys-str.c,v 1.20.2.1 1995/06/01 07:01:42 paulus Exp $"; #endif /* @@ -65,9 +65,15 @@ static int str_module_count = 0; static int pushed_ppp; static int closed_stdio; +static int ppp_fd = -1; /* fd currently attached to ppp unit */ + static int restore_term; /* 1 => we've munged the terminal */ static struct termios inittermios; /* Initial TTY termios */ +static int loop_slave = -1; +static int loop_master; +static char loop_name[20]; + int sockfd; /* socket for doing interface ioctls */ static char *lock_file; /* lock file created for serial port */ @@ -146,19 +152,22 @@ ppp_available() /* - * establish_ppp - Turn the serial port into a ppp interface. + * establish_ppp - Turn the serial port (or loopback) into a ppp interface. */ void establish_ppp() { - /* go through and save the name of all the modules, then pop em */ - for (;;) { - if (ioctl(fd, I_LOOK, str_modules[str_module_count].modname) < 0 || - ioctl(fd, I_POP, 0) < 0) - break; - MAINDEBUG((LOG_DEBUG, "popped stream module : %s", - str_modules[str_module_count].modname)); - str_module_count++; + if (fd != loop_slave) { + str_module_count = 0; + /* go through and save the name of all the modules, then pop em */ + for (;;) { + if (ioctl(fd, I_LOOK, str_modules[str_module_count].modname) < 0 || + ioctl(fd, I_POP, 0) < 0) + break; + MAINDEBUG((LOG_DEBUG, "popped stream module : %s", + str_modules[str_module_count].modname)); + str_module_count++; + } } /* now push the async/fcs module */ @@ -167,7 +176,7 @@ establish_ppp() die(1); } /* push the compress module */ - if (ioctl(fd, I_PUSH, "pppcomp") < 0) { + if (fd != loop_slave && ioctl(fd, I_PUSH, "pppcomp") < 0) { syslog(LOG_WARNING, "ioctl(I_PUSH, ppp_comp): %m"); } /* finally, push the ppp_if module that actually handles the */ @@ -177,6 +186,7 @@ establish_ppp() die(1); } pushed_ppp = 1; + /* read mode, message non-discard mode */ if (ioctl(fd, I_SRDOPT, RMSGN) < 0) { syslog(LOG_ERR, "ioctl(I_SRDOPT, RMSGN): %m"); @@ -196,6 +206,8 @@ establish_ppp() syslog(LOG_ERR, "ioctl(SIOCSIFDEBUG): %m"); } + ppp_fd = fd; + /* close stdin, stdout, stderr if they might refer to the device */ if (default_device && !closed_stdio) { int i; @@ -207,17 +219,94 @@ establish_ppp() } } +/* + * transfer_ppp - make the device on fd `fd' take over the PPP interface + * unit that we are using. + */ +void +transfer_ppp(fd) + int fd; +{ + if (fd == ppp_fd) + return; /* we can't get here */ + + if (fd != loop_slave) { + /* go through and save the name of all the modules, then pop em */ + str_module_count = 0; + for (;;) { + if (ioctl(fd, I_LOOK, str_modules[str_module_count].modname) < 0 || + ioctl(fd, I_POP, 0) < 0) + break; + MAINDEBUG((LOG_DEBUG, "popped stream module : %s", + str_modules[str_module_count].modname)); + str_module_count++; + } + } + + /* now push the async/fcs module */ + if (ioctl(fd, I_PUSH, "pppasync") < 0) { + syslog(LOG_ERR, "ioctl(I_PUSH, ppp_async): %m"); + die(1); + } + /* push the compress module */ + if (ioctl(fd, I_PUSH, "pppcomp") < 0) { + syslog(LOG_WARNING, "ioctl(I_PUSH, ppp_comp): %m"); + } + /* finally, push the ppp_if module that actually handles the */ + /* network interface */ + if (ioctl(fd, I_PUSH, "pppif") < 0) { + syslog(LOG_ERR, "ioctl(I_PUSH, ppp_if): %m"); + die(1); + } + pushed_ppp = 1; + + /* read mode, message non-discard mode */ + if (ioctl(fd, I_SRDOPT, RMSGN) < 0) { + syslog(LOG_ERR, "ioctl(I_SRDOPT, RMSGN): %m"); + die(1); + } + /* + * Connect to the interface unit we want. + * (ppp_if handles this ioctl) + */ + if (ioctl(fd, SIOCSETU, &ifunit) < 0) { + syslog(LOG_ERR, "ioctl(SIOCSETU): %m"); + die(1); + } + + /* Set debug flags in driver */ + if (ioctl(fd, SIOCSIFDEBUG, &kdebugflag) < 0) { + syslog(LOG_ERR, "ioctl(SIOCSIFDEBUG): %m"); + } + + /* + * Pop the modules off the old ppp stream, and restore + * the modules that were there, if this is the real serial port. + */ + while (ioctl(ppp_fd, I_POP, 0) == 0) /* pop any we pushed */ + ; + if (fd == loop_slave) { + for (; str_module_count > 0; str_module_count--) { + if (ioctl(ppp_fd, I_PUSH, str_modules[str_module_count-1].modname)) { + if (errno != ENXIO) + syslog(LOG_WARNING, + "Couldn't restore STREAMS module %s: %m", + str_modules[str_module_count-1].modname); + } + } + } + ppp_fd = fd; +} + /* * disestablish_ppp - Restore the serial port to normal operation. * It attempts to reconstruct the stream with the previously popped * modules. This shouldn't call die() because it's called from die(). */ void -disestablish_ppp() +disestablish_ppp(fd) + int fd; { - int flags; - char *s; - if (hungup) { /* we can't push or pop modules after the stream has hung up */ str_module_count = 0; @@ -225,49 +314,55 @@ disestablish_ppp() return; } - if (pushed_ppp) { - /* - * Check whether the link seems not to be 8-bit clean. - */ - if (ioctl(fd, SIOCGIFDEBUG, (caddr_t) &flags) == 0) { - s = NULL; - switch (~flags & PAI_FLAGS_HIBITS) { - case PAI_FLAGS_B7_0: - s = "bit 7 set to 1"; - break; - case PAI_FLAGS_B7_1: - s = "bit 7 set to 0"; - break; - case PAI_FLAGS_PAR_EVEN: - s = "odd parity"; - break; - case PAI_FLAGS_PAR_ODD: - s = "even parity"; - break; - } - if (s != NULL) { - syslog(LOG_WARNING, "Serial link is not 8-bit clean:"); - syslog(LOG_WARNING, "All received characters had %s", s); - } - } - + if (fd == ppp_fd && fd >= 0 && pushed_ppp) { while (ioctl(fd, I_POP, 0) == 0) /* pop any we pushed */ ; + pushed_ppp = 0; for (; str_module_count > 0; str_module_count--) { if (ioctl(fd, I_PUSH, str_modules[str_module_count-1].modname)) { if (errno != ENXIO) - syslog(LOG_WARNING, "Couldn't restore module %s: %m", + syslog(LOG_WARNING, + "Couldn't restore STREAMS module %s: %m", str_modules[str_module_count-1].modname); - } else { - MAINDEBUG((LOG_INFO, "str_restore: pushed module %s", - str_modules[str_module_count-1].modname)); } } + ppp_fd = -1; pushed_ppp = 0; } } +/* + * Check whether the link seems not to be 8-bit clean. + */ +void +clean_check() +{ + int flags; + char *s; + + if (ioctl(ppp_fd, SIOCGIFDEBUG, (caddr_t) &flags) == 0) { + s = NULL; + switch (~flags & PAI_FLAGS_HIBITS) { + case PAI_FLAGS_B7_0: + s = "bit 7 set to 1"; + break; + case PAI_FLAGS_B7_1: + s = "bit 7 set to 0"; + break; + case PAI_FLAGS_PAR_EVEN: + s = "odd parity"; + break; + case PAI_FLAGS_PAR_ODD: + s = "even parity"; + break; + } + if (s != NULL) { + syslog(LOG_WARNING, "Serial link is not 8-bit clean:"); + syslog(LOG_WARNING, "All received characters had %s", s); + } + } +} /* * List of valid speeds. @@ -481,6 +576,65 @@ int fd, on; } +/* + * open_loopback - open the device we use for getting packets + * in demand mode. Here we use a pty. + */ +int +open_loopback() +{ + int flags; + struct termios tios; + static char c1[] = "pqrstuvwxyzPQRST"; + static char c2[] = "0123456789abcdef"; + char *p1, *p2; + + p1 = c1; + p2 = c2; + strcpy(loop_name, "/dev/ptyxx"); + loop_slave = -1; + for (;;) { + loop_name[8] = *p1; + loop_name[9] = *p2; + if ((loop_master = open(loop_name, O_RDWR, 0)) >= 0) { + loop_name[5] = 't'; + chown(loop_name, geteuid(), getegid()); + chmod(loop_name, S_IRUSR|S_IWUSR); + if ((loop_slave = open(loop_name, O_RDWR, 0)) >= 0) + break; + close(loop_master); + loop_name[5] = 'p'; + } else if (errno == ENOENT) + break; + if (*++p2 == 0) { + p2 = c2; + if (*++p1 == 0) + break; + } + } + if (loop_slave < 0) { + syslog(LOG_ERR, "No free pty for loopback"); + die(1); + } + SYSDEBUG((LOG_DEBUG, "using %s for loopback", loop_name)); + if (tcgetattr(loop_slave, &tios) == 0) { + tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB); + tios.c_cflag |= CS8 | CREAD; + tios.c_iflag = IGNPAR; + tios.c_oflag = 0; + tios.c_lflag = 0; + if (tcsetattr(loop_slave, TCSAFLUSH, &tios) < 0) + syslog(LOG_WARNING, "couldn't set attributes on loopback: %m"); + } + if ((flags = fcntl(loop_slave, F_GETFL)) != -1) + if (fcntl(loop_slave, F_SETFL, flags | O_NONBLOCK) == -1) + syslog(LOG_WARNING, "couldn't set loopback to nonblock: %m"); + if ((flags = fcntl(loop_master, F_GETFL)) != -1) + if (fcntl(loop_master, F_SETFL, flags | O_NONBLOCK) == -1) + syslog(LOG_WARNING, "couldn't set loopback(m) to nonblock: %m"); + return loop_slave; +} + /* * output - Output PPP packet. */ @@ -525,6 +679,26 @@ wait_input(timo) } } +/* + * wait_loop_output - wait until there is data available on the, + * loopback, for the length of time specified by *timo (indefinite + * if timo is NULL). + */ +wait_loop_output(timo) + struct timeval *timo; +{ + fd_set ready; + int n; + + FD_ZERO(&ready); + FD_SET(loop_master, &ready); + n = select(loop_master + 1, &ready, NULL, &ready, timo); + if (n < 0 && errno != EINTR) { + syslog(LOG_ERR, "select: %m"); + die(1); + } +} + /* * read_packet - get a PPP packet from the serial device. */ @@ -564,6 +738,29 @@ read_packet(buf) } +/* + * read_loop_output - get characters from the "bottom" of the loopback. + */ +int +read_loop_output(buf, maxlen) + u_char *buf; + int maxlen; +{ + int len; + + if ((len = read(loop_master, buf, maxlen)) < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) + return 0; + syslog(LOG_ERR, "read from loopback: %m"); + die(1); + } else if (len == 0) { + syslog(LOG_ERR, "eof on loopback"); + die(1); + } + return len; +} + + /* * ppp_send_config - configure the transmit characteristics of * the ppp interface. @@ -581,24 +778,24 @@ ppp_send_config(unit, mtu, asyncmap, pcomp, accomp) ifr.ifr_mtu = mtu; if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) { syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m"); - quit(); + die(1); } if(ioctl(fd, SIOCSIFASYNCMAP, (caddr_t) &asyncmap) < 0) { syslog(LOG_ERR, "ioctl(SIOCSIFASYNCMAP): %m"); - quit(); + die(1); } c = (pcomp? 1: 0); if(ioctl(fd, SIOCSIFCOMPPROT, &c) < 0) { syslog(LOG_ERR, "ioctl(SIOCSIFCOMPPROT): %m"); - quit(); + die(1); } c = (accomp? 1: 0); if(ioctl(fd, SIOCSIFCOMPAC, &c) < 0) { syslog(LOG_ERR, "ioctl(SIOCSIFCOMPAC): %m"); - quit(); + die(1); } } @@ -715,7 +912,7 @@ sifvjcomp(u, vjcomp, cidcomp, maxcid) } /* - * sifup - Config the interface up and enable IP packets to pass. + * sifup - Config the interface up. */ int sifup(u) @@ -737,10 +934,8 @@ sifup(u) npi.protocol = PPP_IP; npi.mode = NPMODE_PASS; if (ioctl(fd, SIOCSETNPMODE, &npi) < 0) { - if (errno != ENOTTY) { - syslog(LOG_ERR, "ioctl(SIOCSETNPMODE): %m"); - return 0; - } + syslog(LOG_ERR, "ioctl(SIOCSETNPMODE): %m"); + return 0; } return 1; } @@ -760,10 +955,8 @@ sifdown(u) npi.protocol = PPP_IP; npi.mode = NPMODE_ERROR; if (ioctl(fd, SIOCSETNPMODE, (caddr_t) &npi) < 0) { - if (errno != ENOTTY) { - syslog(LOG_ERR, "ioctl(SIOCSETNPMODE): %m"); - rv = 0; - } + syslog(LOG_ERR, "ioctl(SIOCSETNPMODE): %m"); + rv = 0; } strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); @@ -780,6 +973,26 @@ sifdown(u) return rv; } +/* + * sifnpmode - Set the mode for handling packets for a given NP. + */ +int +sifnpmode(u, proto, mode) + int u; + int proto; + enum NPmode mode; +{ + struct npioctl npi; + + npi.protocol = proto; + npi.mode = mode; + if (ioctl(fd, SIOCSETNPMODE, &npi) < 0) { + syslog(LOG_ERR, "ioctl(SIOCSETNPMODE): %m"); + return 0; + } + return 1; +} + /* * SET_SA_FAMILY - initialize a struct sockaddr, setting the sa_family field. */