diff options
author | Peter Wemm <peter@FreeBSD.org> | 1995-10-31 21:21:51 +0000 |
---|---|---|
committer | Peter Wemm <peter@FreeBSD.org> | 1995-10-31 21:21:51 +0000 |
commit | 60f531a365ae3ea74e34b0c4f1f9482da86d03a0 (patch) | |
tree | 4d3d1e7e23ca53f41a20a9c41f78068854a5325f | |
parent | e046098fa9daa1381e7180ae5d3ad3cd36402368 (diff) | |
download | src-test2-60f531a365ae3ea74e34b0c4f1f9482da86d03a0.tar.gz src-test2-60f531a365ae3ea74e34b0c4f1f9482da86d03a0.zip |
Notes
-rw-r--r-- | usr.sbin/pppd/Makefile | 12 | ||||
-rw-r--r-- | usr.sbin/pppd/auth.c | 145 | ||||
-rw-r--r-- | usr.sbin/pppd/chap.c | 118 | ||||
-rw-r--r-- | usr.sbin/pppd/chap.h | 20 | ||||
-rw-r--r-- | usr.sbin/pppd/fsm.c | 67 | ||||
-rw-r--r-- | usr.sbin/pppd/fsm.h | 21 | ||||
-rw-r--r-- | usr.sbin/pppd/ipcp.c | 112 | ||||
-rw-r--r-- | usr.sbin/pppd/ipcp.h | 22 | ||||
-rw-r--r-- | usr.sbin/pppd/lcp.c | 488 | ||||
-rw-r--r-- | usr.sbin/pppd/lcp.h | 35 | ||||
-rw-r--r-- | usr.sbin/pppd/magic.c | 68 | ||||
-rw-r--r-- | usr.sbin/pppd/magic.h | 7 | ||||
-rw-r--r-- | usr.sbin/pppd/main.c | 1342 | ||||
-rw-r--r-- | usr.sbin/pppd/options.c | 722 | ||||
-rw-r--r-- | usr.sbin/pppd/patchlevel.h | 9 | ||||
-rw-r--r-- | usr.sbin/pppd/pathnames.h | 11 | ||||
-rw-r--r-- | usr.sbin/pppd/pppd.8 | 148 | ||||
-rw-r--r-- | usr.sbin/pppd/pppd.h | 86 | ||||
-rw-r--r-- | usr.sbin/pppd/sys-bsd.c | 528 | ||||
-rw-r--r-- | usr.sbin/pppd/upap.c | 79 | ||||
-rw-r--r-- | usr.sbin/pppd/upap.h | 26 |
21 files changed, 2384 insertions, 1682 deletions
diff --git a/usr.sbin/pppd/Makefile b/usr.sbin/pppd/Makefile index a0ca52e93e81..098cc4ac495d 100644 --- a/usr.sbin/pppd/Makefile +++ b/usr.sbin/pppd/Makefile @@ -1,10 +1,14 @@ -# From: Id: Makefile.bsd,v 1.4 1994/04/20 00:07:50 paulus Exp -# $Id$ +# $Id: Makefile.bsd,v 1.7 1995/04/27 00:19:50 paulus Exp $ + +BINDIR?= /usr/sbin +CFLAGS+= -I.. -DHAVE_PATHS_H PROG= pppd -SRCS= main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c \ - auth.c options.c lock.c sys-bsd.c +SRCS= 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 MAN8= pppd.8 +# The next line is for NetBSD-current systems. +MAN= pppd.cat8 BINMODE=4555 BINOWN= root diff --git a/usr.sbin/pppd/auth.c b/usr.sbin/pppd/auth.c index ec6ab986fec1..dd9735b89efd 100644 --- a/usr.sbin/pppd/auth.c +++ b/usr.sbin/pppd/auth.c @@ -33,11 +33,12 @@ */ #ifndef lint -static char rcsid[] = "$Id: auth.c,v 1.3 1995/05/30 03:51:04 rgrimes Exp $"; +static char rcsid[] = "$Id: auth.c,v 1.17 1995/08/16 01:37:22 paulus Exp $"; #endif #include <stdio.h> #include <stddef.h> +#include <stdlib.h> #include <syslog.h> #include <pwd.h> #include <string.h> @@ -48,16 +49,24 @@ static char rcsid[] = "$Id: auth.c,v 1.3 1995/05/30 03:51:04 rgrimes Exp $"; #include <netinet/in.h> #include <arpa/inet.h> -#include "ppp.h" +#ifdef HAS_SHADOW +#include <shadow.h> +#include <shadow/pwauth.h> +#ifndef PW_PPP +#define PW_PPP PW_LOGIN +#endif +#endif + #include "pppd.h" #include "fsm.h" #include "lcp.h" #include "upap.h" #include "chap.h" #include "ipcp.h" +#include "ccp.h" #include "pathnames.h" -#ifdef sparc +#if defined(sun) && defined(sparc) #include <alloca.h> #endif /*sparc*/ @@ -76,20 +85,10 @@ struct wordlist { #define FALSE 0 #define TRUE 1 -extern char user[]; -extern char passwd[]; -extern char devname[]; -extern char our_name[]; -extern char remote_name[]; -extern char hostname[]; -extern int uselogin; -extern int usehostname; -extern int auth_required; - /* Records which authentication operations haven't completed yet. */ -static int auth_pending[NPPP]; +static int auth_pending[NUM_PPP]; static int logged_in; -static struct wordlist *addresses[NPPP]; +static struct wordlist *addresses[NUM_PPP]; /* Bits in auth_pending[] */ #define UPAP_WITHPEER 1 @@ -98,19 +97,20 @@ static struct wordlist *addresses[NPPP]; #define CHAP_PEER 8 /* Prototypes */ -void check_access __ARGS((FILE *, char *)); - -static int login __ARGS((char *, char *, char **, int *)); -static void logout __ARGS((void)); -static int null_login __ARGS((int)); -static int get_upap_passwd __ARGS((void)); -static int have_upap_secret __ARGS((void)); -static int have_chap_secret __ARGS((char *, char *)); -static int scan_authfile __ARGS((FILE *, char *, char *, char *, +void check_access __P((FILE *, char *)); + +static void network_phase __P((int)); +static int login __P((char *, char *, char **, int *)); +static void logout __P((void)); +static int null_login __P((int)); +static int get_upap_passwd __P((void)); +static int have_upap_secret __P((void)); +static int have_chap_secret __P((char *, char *)); +static int scan_authfile __P((FILE *, char *, char *, char *, struct wordlist **, char *)); -static void free_wordlist __ARGS((struct wordlist *)); +static void free_wordlist __P((struct wordlist *)); -extern char *crypt __ARGS((char *, char *)); +extern char *crypt __P((char *, char *)); /* * An Open on LCP has requested a change from Dead to Establish phase. @@ -130,6 +130,8 @@ void link_terminated(unit) int unit; { + if (phase == PHASE_DEAD) + return; if (logged_in) logout(); phase = PHASE_DEAD; @@ -143,6 +145,8 @@ void link_down(unit) int unit; { + ipcp_close(0); + ccp_close(0); phase = PHASE_TERMINATE; } @@ -165,7 +169,7 @@ link_established(unit) * treat it as though it authenticated with PAP using a username * of "" and a password of "". If that's not OK, boot it out. */ - if (wo->neg_upap && !null_login(unit)) { + if (!wo->neg_upap || !null_login(unit)) { syslog(LOG_WARNING, "peer refused to authenticate"); lcp_close(unit); phase = PHASE_TERMINATE; @@ -191,10 +195,20 @@ link_established(unit) } auth_pending[unit] = auth; - if (!auth) { - phase = PHASE_NETWORK; - ipcp_open(unit); - } + if (!auth) + network_phase(unit); +} + +/* + * Proceed to the network phase. + */ +static void +network_phase(unit) + int unit; +{ + phase = PHASE_NETWORK; + ipcp_open(unit); + ccp_open(unit); } /* @@ -221,10 +235,10 @@ auth_peer_success(unit, protocol) int bit; switch (protocol) { - case CHAP: + case PPP_CHAP: bit = CHAP_PEER; break; - case UPAP: + case PPP_PAP: bit = UPAP_PEER; break; default: @@ -240,6 +254,7 @@ auth_peer_success(unit, protocol) if ((auth_pending[unit] &= ~bit) == 0) { phase = PHASE_NETWORK; ipcp_open(unit); + ccp_open(unit); } } @@ -267,10 +282,10 @@ auth_withpeer_success(unit, protocol) int bit; switch (protocol) { - case CHAP: + case PPP_CHAP: bit = CHAP_WITHPEER; break; - case UPAP: + case PPP_PAP: bit = UPAP_WITHPEER; break; default: @@ -283,10 +298,8 @@ auth_withpeer_success(unit, protocol) * If there is no more authentication still being done, * proceed to the network phase. */ - if ((auth_pending[unit] &= ~bit) == 0) { - phase = PHASE_NETWORK; - ipcp_open(unit); - } + if ((auth_pending[unit] &= ~bit) == 0) + network_phase(unit); } @@ -386,7 +399,7 @@ check_passwd(unit, auser, userlen, apasswd, passwdlen, msg, msglen) } else { check_access(f, filename); if (scan_authfile(f, user, our_name, secret, &addrs, filename) < 0 - || (secret[0] != 0 && strcmp(passwd, secret) != 0 + || (secret[0] != 0 && (cryptpap || strcmp(passwd, secret) != 0) && strcmp(crypt(passwd, secret), secret) != 0)) { syslog(LOG_WARNING, "upap authentication failure for %s", user); ret = UPAP_AUTHNAK; @@ -411,7 +424,7 @@ check_passwd(unit, auser, userlen, apasswd, passwdlen, msg, msglen) */ if (attempts++ >= 10) { syslog(LOG_WARNING, "%d LOGIN FAILURES ON %s, %s", - attempts, devname, user); + attempts, devnam, user); quit(); } if (attempts > 3) @@ -452,12 +465,22 @@ login(user, passwd, msg, msglen) char *epasswd; char *tty; +#ifdef HAS_SHADOW + struct spwd *spwd; + struct spwd *getspnam(); +#endif + if ((pw = getpwnam(user)) == NULL) { return (UPAP_AUTHNAK); } - if (pw->pw_expire && time(NULL) >= pw->pw_expire) - return (UPAP_AUTHNAK); +#ifdef HAS_SHADOW + if ((spwd = getspnam(user)) == NULL) { + pw->pw_passwd = ""; + } else { + pw->pw_passwd = spwd->sp_pwdp; + } +#endif /* * XXX If no passwd, let them login without one. @@ -466,21 +489,27 @@ login(user, passwd, msg, msglen) return (UPAP_AUTHACK); } +#ifdef HAS_SHADOW + if ((pw->pw_passwd && pw->pw_passwd[0] == '@' + && pw_auth (pw->pw_passwd+1, pw->pw_name, PW_PPP, NULL)) + || !valid (passwd, pw)) { + return (UPAP_AUTHNAK); + } +#else epasswd = crypt(passwd, pw->pw_passwd); if (strcmp(epasswd, pw->pw_passwd)) { return (UPAP_AUTHNAK); } +#endif syslog(LOG_INFO, "user %s logged in", user); /* * Write a wtmp entry for this user. */ - tty = strrchr(devname, '/'); - if (tty == NULL) - tty = devname; - else - tty++; + tty = devnam; + if (strncmp(tty, "/dev/", 5) == 0) + tty += 5; logwtmp(tty, user, ""); /* Add wtmp login entry */ logged_in = TRUE; @@ -495,11 +524,9 @@ logout() { char *tty; - tty = strrchr(devname, '/'); - if (tty == NULL) - tty = devname; - else - tty++; + tty = devnam; + if (strncmp(tty, "/dev/", 5) == 0) + tty += 5; logwtmp(tty, "", ""); /* Wipe out wtmp logout entry */ logged_in = FALSE; } @@ -691,9 +718,9 @@ get_secret(unit, client, server, secret, secret_len, save_addrs) int auth_ip_addr(unit, addr) int unit; - u_long addr; + u_int32_t addr; { - u_long a; + u_int32_t a; struct hostent *hp; struct wordlist *addrs; @@ -714,7 +741,7 @@ auth_ip_addr(unit, addr) addrs->word); continue; } else - a = *(u_long *)hp->h_addr; + a = *(u_int32_t *)hp->h_addr; } if (addr == a) return 1; @@ -729,7 +756,7 @@ auth_ip_addr(unit, addr) */ int bad_ip_adrs(addr) - u_long addr; + u_int32_t addr; { addr = ntohl(addr); return (addr >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET @@ -761,7 +788,7 @@ check_access(f, filename) * NONWILD_CLIENT set if the secret didn't have "*" for the client, and * NONWILD_SERVER set if the secret didn't have "*" for the server. * Any following words on the line (i.e. address authorization - * info) are placed in a wordlist and returned in *addrs. + * info) are placed in a wordlist and returned in *addrs. */ static int scan_authfile(f, client, server, secret, addrs, filename) @@ -854,7 +881,7 @@ scan_authfile(f, client, server, secret, addrs, filename) } if (secret != NULL) strcpy(secret, word); - + best_flag = got_flag; /* diff --git a/usr.sbin/pppd/chap.c b/usr.sbin/pppd/chap.c index 14b28b16b3d4..d72c36d4a989 100644 --- a/usr.sbin/pppd/chap.c +++ b/usr.sbin/pppd/chap.c @@ -19,7 +19,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: chap.c,v 1.2 1994/09/25 02:31:54 wollman Exp $"; +static char rcsid[] = "$Id: chap.c,v 1.8 1995/07/04 12:32:26 paulus Exp $"; #endif /* @@ -27,30 +27,30 @@ static char rcsid[] = "$Id: chap.c,v 1.2 1994/09/25 02:31:54 wollman Exp $"; */ #include <stdio.h> +#include <string.h> #include <sys/types.h> #include <sys/time.h> #include <syslog.h> -#include "ppp.h" #include "pppd.h" #include "chap.h" #include "md5.h" -chap_state chap[NPPP]; /* CHAP state; one for each unit */ +chap_state chap[NUM_PPP]; /* CHAP state; one for each unit */ -static void ChapChallengeTimeout __ARGS((caddr_t)); -static void ChapResponseTimeout __ARGS((caddr_t)); -static void ChapReceiveChallenge __ARGS((chap_state *, u_char *, int, int)); -static void ChapReceiveResponse __ARGS((chap_state *, u_char *, int, int)); -static void ChapReceiveSuccess __ARGS((chap_state *, u_char *, int, int)); -static void ChapReceiveFailure __ARGS((chap_state *, u_char *, int, int)); -static void ChapSendStatus __ARGS((chap_state *, int)); -static void ChapSendChallenge __ARGS((chap_state *)); -static void ChapSendResponse __ARGS((chap_state *)); -static void ChapGenChallenge __ARGS((chap_state *)); +static void ChapChallengeTimeout __P((caddr_t)); +static void ChapResponseTimeout __P((caddr_t)); +static void ChapReceiveChallenge __P((chap_state *, u_char *, int, int)); +static void ChapReceiveResponse __P((chap_state *, u_char *, int, int)); +static void ChapReceiveSuccess __P((chap_state *, u_char *, int, int)); +static void ChapReceiveFailure __P((chap_state *, u_char *, int, int)); +static void ChapSendStatus __P((chap_state *, int)); +static void ChapSendChallenge __P((chap_state *)); +static void ChapSendResponse __P((chap_state *)); +static void ChapGenChallenge __P((chap_state *)); -extern double drand48 __ARGS((void)); -extern void srand48 __ARGS((long)); +extern double drand48 __P((void)); +extern void srand48 __P((long)); /* * ChapInit - Initialize a CHAP unit. @@ -67,7 +67,7 @@ ChapInit(unit) cstate->serverstate = CHAPSS_INITIAL; cstate->timeouttime = CHAP_DEFTIMEOUT; cstate->max_transmits = CHAP_DEFTRANSMITS; - srand48((long) time(NULL)); /* joggle random number generator */ + /* random number generator is initialized in magic_init */ } @@ -95,7 +95,7 @@ ChapAuthWithPeer(unit, our_name, digest) /* * We get here as a result of LCP coming up. - * So even if CHAP was open before, we will + * So even if CHAP was open before, we will * have to re-authenticate ourselves. */ cstate->clientstate = CHAPCS_LISTEN; @@ -112,7 +112,7 @@ ChapAuthPeer(unit, our_name, digest) int digest; { chap_state *cstate = &chap[unit]; - + cstate->chal_name = our_name; cstate->chal_type = digest; @@ -137,7 +137,7 @@ ChapChallengeTimeout(arg) caddr_t arg; { chap_state *cstate = (chap_state *) arg; - + /* if we aren't sending challenges, don't worry. then again we */ /* probably shouldn't be here either */ if (cstate->serverstate != CHAPSS_INITIAL_CHAL && @@ -148,7 +148,7 @@ ChapChallengeTimeout(arg) /* give up on peer */ syslog(LOG_ERR, "Peer failed to respond to CHAP challenge"); cstate->serverstate = CHAPSS_BADAUTH; - auth_peer_fail(cstate->unit, CHAP); + auth_peer_fail(cstate->unit, PPP_CHAP); return; } @@ -189,9 +189,6 @@ ChapRechallenge(arg) ChapGenChallenge(cstate); ChapSendChallenge(cstate); cstate->serverstate = CHAPSS_RECHALLENGE; - - if (cstate->chal_interval != 0) - TIMEOUT(ChapRechallenge, (caddr_t) cstate, cstate->chal_interval); } @@ -205,7 +202,7 @@ ChapLowerUp(unit) int unit; { chap_state *cstate = &chap[unit]; - + if (cstate->clientstate == CHAPCS_INITIAL) cstate->clientstate = CHAPCS_CLOSED; else if (cstate->clientstate == CHAPCS_PENDING) @@ -231,7 +228,7 @@ ChapLowerDown(unit) int unit; { chap_state *cstate = &chap[unit]; - + /* Timeout(s) pending? Cancel if so. */ if (cstate->serverstate == CHAPSS_INITIAL_CHAL || cstate->serverstate == CHAPSS_RECHALLENGE) @@ -258,10 +255,10 @@ ChapProtocolReject(unit) if (cstate->serverstate != CHAPSS_INITIAL && cstate->serverstate != CHAPSS_CLOSED) - auth_peer_fail(unit, CHAP); + auth_peer_fail(unit, PPP_CHAP); if (cstate->clientstate != CHAPCS_INITIAL && cstate->clientstate != CHAPCS_CLOSED) - auth_withpeer_fail(unit, CHAP); + auth_withpeer_fail(unit, PPP_CHAP); ChapLowerDown(unit); /* shutdown chap */ } @@ -279,7 +276,7 @@ ChapInput(unit, inpacket, packet_len) u_char *inp; u_char code, id; int len; - + /* * Parse header (code, id and length). * If packet too short, drop it. @@ -301,7 +298,7 @@ ChapInput(unit, inpacket, packet_len) return; } len -= CHAP_HEADERLEN; - + /* * Action depends on code (as in fact it usually does :-). */ @@ -309,11 +306,11 @@ ChapInput(unit, inpacket, packet_len) case CHAP_CHALLENGE: ChapReceiveChallenge(cstate, inp, id, len); break; - + case CHAP_RESPONSE: ChapReceiveResponse(cstate, inp, id, len); break; - + case CHAP_FAILURE: ChapReceiveFailure(cstate, inp, id, len); break; @@ -345,7 +342,7 @@ ChapReceiveChallenge(cstate, inp, id, len) char secret[MAXSECRETLEN]; char rhostname[256]; MD5_CTX mdContext; - + CHAPDEBUG((LOG_INFO, "ChapReceiveChallenge: Rcvd id %d.", id)); if (cstate->clientstate == CHAPCS_CLOSED || cstate->clientstate == CHAPCS_PENDING) { @@ -392,7 +389,7 @@ ChapReceiveChallenge(cstate, inp, id, len) cstate->resp_transmits = 0; /* generate MD based on negotiated type */ - switch (cstate->resp_type) { + switch (cstate->resp_type) { case CHAP_DIGEST_MD5: /* only MD5 is defined for now */ MD5Init(&mdContext); @@ -494,7 +491,7 @@ ChapReceiveResponse(cstate, inp, id, len) } else { /* generate MD based on negotiated type */ - switch (cstate->chal_type) { + switch (cstate->chal_type) { case CHAP_DIGEST_MD5: /* only MD5 is defined for now */ if (remmd_len != MD5_SIGNATURE_SIZE) @@ -503,10 +500,10 @@ ChapReceiveResponse(cstate, inp, id, len) MD5Update(&mdContext, &cstate->chal_id, 1); MD5Update(&mdContext, secret, secret_len); MD5Update(&mdContext, cstate->challenge, cstate->chal_len); - MD5Final(&mdContext); + MD5Final(&mdContext); /* compare local and remote MDs and send the appropriate status */ - if (bcmp (mdContext.digest, remmd, MD5_SIGNATURE_SIZE) == 0) + if (memcmp (mdContext.digest, remmd, MD5_SIGNATURE_SIZE) == 0) code = CHAP_SUCCESS; /* they are the same! */ break; @@ -521,7 +518,7 @@ ChapReceiveResponse(cstate, inp, id, len) old_state = cstate->serverstate; cstate->serverstate = CHAPSS_OPEN; if (old_state == CHAPSS_INITIAL_CHAL) { - auth_peer_success(cstate->unit, CHAP); + auth_peer_success(cstate->unit, PPP_CHAP); } if (cstate->chal_interval != 0) TIMEOUT(ChapRechallenge, (caddr_t) cstate, cstate->chal_interval); @@ -529,7 +526,7 @@ ChapReceiveResponse(cstate, inp, id, len) } else { syslog(LOG_ERR, "CHAP peer authentication failed"); cstate->serverstate = CHAPSS_BADAUTH; - auth_peer_fail(cstate->unit, CHAP); + auth_peer_fail(cstate->unit, PPP_CHAP); } } @@ -567,7 +564,7 @@ ChapReceiveSuccess(cstate, inp, id, len) cstate->clientstate = CHAPCS_OPEN; - auth_withpeer_success(cstate->unit, CHAP); + auth_withpeer_success(cstate->unit, PPP_CHAP); } @@ -583,7 +580,7 @@ ChapReceiveFailure(cstate, inp, id, len) { u_char msglen; u_char *msg; - + CHAPDEBUG((LOG_INFO, "ChapReceiveFailure: Rcvd id %d.", id)); if (cstate->clientstate != CHAPCS_RESPONSE) { @@ -602,7 +599,7 @@ ChapReceiveFailure(cstate, inp, id, len) PRINTMSG(inp, len); syslog(LOG_ERR, "CHAP authentication failed"); - auth_withpeer_fail(cstate->unit, CHAP); + auth_withpeer_fail(cstate->unit, PPP_CHAP); } @@ -622,7 +619,7 @@ ChapSendChallenge(cstate) outlen = CHAP_HEADERLEN + sizeof (u_char) + chal_len + name_len; outp = outpacket_buf; - MAKEHEADER(outp, CHAP); /* paste in a CHAP header */ + MAKEHEADER(outp, PPP_CHAP); /* paste in a CHAP header */ PUTCHAR(CHAP_CHALLENGE, outp); PUTCHAR(cstate->chal_id, outp); @@ -634,8 +631,8 @@ ChapSendChallenge(cstate) BCOPY(cstate->chal_name, outp, name_len); /* append hostname */ - output(cstate->unit, outpacket_buf, outlen + DLLHEADERLEN); - + output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN); + CHAPDEBUG((LOG_INFO, "ChapSendChallenge: Sent id %d.", cstate->chal_id)); TIMEOUT(ChapChallengeTimeout, (caddr_t) cstate, cstate->timeouttime); @@ -664,14 +661,14 @@ ChapSendStatus(cstate, code) outlen = CHAP_HEADERLEN + msglen; outp = outpacket_buf; - MAKEHEADER(outp, CHAP); /* paste in a header */ - + MAKEHEADER(outp, PPP_CHAP); /* paste in a header */ + PUTCHAR(code, outp); PUTCHAR(cstate->chal_id, outp); PUTSHORT(outlen, outp); BCOPY(msg, outp, msglen); - output(cstate->unit, outpacket_buf, outlen + DLLHEADERLEN); - + output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN); + CHAPDEBUG((LOG_INFO, "ChapSendStatus: Sent code %d, id %d.", code, cstate->chal_id)); } @@ -691,8 +688,8 @@ ChapGenChallenge(cstate) u_char *ptr = cstate->challenge; unsigned int i; - /* pick a random challenge length between MIN_CHALLENGE_LENGTH and - MAX_CHALLENGE_LENGTH */ + /* pick a random challenge length between MIN_CHALLENGE_LENGTH and + MAX_CHALLENGE_LENGTH */ chal_len = (unsigned) ((drand48() * (MAX_CHALLENGE_LENGTH - MIN_CHALLENGE_LENGTH)) + MIN_CHALLENGE_LENGTH); @@ -722,7 +719,7 @@ ChapSendResponse(cstate) outlen = CHAP_HEADERLEN + sizeof (u_char) + md_len + name_len; outp = outpacket_buf; - MAKEHEADER(outp, CHAP); + MAKEHEADER(outp, PPP_CHAP); PUTCHAR(CHAP_RESPONSE, outp); /* we are a response */ PUTCHAR(cstate->resp_id, outp); /* copy id from challenge packet */ @@ -735,7 +732,7 @@ ChapSendResponse(cstate) BCOPY(cstate->resp_name, outp, name_len); /* append our name */ /* send the packet */ - output(cstate->unit, outpacket_buf, outlen + DLLHEADERLEN); + output(cstate->unit, outpacket_buf, outlen + PPP_HDRLEN); cstate->clientstate = CHAPCS_RESPONSE; TIMEOUT(ChapResponseTimeout, (caddr_t) cstate, cstate->timeouttime); @@ -753,7 +750,7 @@ int ChapPrintPkt(p, plen, printer, arg) u_char *p; int plen; - void (*printer) __ARGS((void *, char *, ...)); + void (*printer) __P((void *, char *, ...)); void *arg; { int code, id, len; @@ -806,18 +803,3 @@ ChapPrintPkt(p, plen, printer, arg) return len + CHAP_HEADERLEN; } - -#ifdef NO_DRAND48 - -double drand48() -{ - return (double)random() / (double)0x7fffffffL; /* 2**31-1 */ -} - -void srand48(seedval) -long seedval; -{ - srand((int)seedval); -} - -#endif diff --git a/usr.sbin/pppd/chap.h b/usr.sbin/pppd/chap.h index 682ecb864d17..44b08f2e205f 100644 --- a/usr.sbin/pppd/chap.h +++ b/usr.sbin/pppd/chap.h @@ -15,7 +15,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: chap.h,v 1.2 1994/04/11 07:13:44 paulus Exp $ + * $Id: chap.h,v 1.3 1994/09/21 06:47:37 paulus Exp $ */ #ifndef __CHAP_INCLUDE__ @@ -98,15 +98,15 @@ typedef struct chap_state { extern chap_state chap[]; -void ChapInit __ARGS((int)); -void ChapAuthWithPeer __ARGS((int, char *, int)); -void ChapAuthPeer __ARGS((int, char *, int)); -void ChapLowerUp __ARGS((int)); -void ChapLowerDown __ARGS((int)); -void ChapInput __ARGS((int, u_char *, int)); -void ChapProtocolReject __ARGS((int)); -int ChapPrintPkt __ARGS((u_char *, int, - void (*) __ARGS((void *, char *, ...)), void *)); +void ChapInit __P((int)); +void ChapAuthWithPeer __P((int, char *, int)); +void ChapAuthPeer __P((int, char *, int)); +void ChapLowerUp __P((int)); +void ChapLowerDown __P((int)); +void ChapInput __P((int, u_char *, int)); +void ChapProtocolReject __P((int)); +int ChapPrintPkt __P((u_char *, int, + void (*) __P((void *, char *, ...)), void *)); #define __CHAP_INCLUDE__ #endif /* __CHAP_INCLUDE__ */ diff --git a/usr.sbin/pppd/fsm.c b/usr.sbin/pppd/fsm.c index 4e05873a24d5..5d2eca6880ad 100644 --- a/usr.sbin/pppd/fsm.c +++ b/usr.sbin/pppd/fsm.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: fsm.c,v 1.2 1994/09/25 02:31:57 wollman Exp $"; +static char rcsid[] = "$Id: fsm.c,v 1.8 1994/11/10 01:52:05 paulus Exp $"; #endif /* @@ -28,27 +28,27 @@ static char rcsid[] = "$Id: fsm.c,v 1.2 1994/09/25 02:31:57 wollman Exp $"; */ #include <stdio.h> +#include <string.h> #include <sys/types.h> #include <syslog.h> -#include "ppp.h" #include "pppd.h" #include "fsm.h" extern char *proto_name(); -static void fsm_timeout __ARGS((caddr_t)); -static void fsm_rconfreq __ARGS((fsm *, int, u_char *, int)); -static void fsm_rconfack __ARGS((fsm *, int, u_char *, int)); -static void fsm_rconfnakrej __ARGS((fsm *, int, int, u_char *, int)); -static void fsm_rtermreq __ARGS((fsm *, int)); -static void fsm_rtermack __ARGS((fsm *)); -static void fsm_rcoderej __ARGS((fsm *, u_char *, int)); -static void fsm_sconfreq __ARGS((fsm *, int)); +static void fsm_timeout __P((caddr_t)); +static void fsm_rconfreq __P((fsm *, int, u_char *, int)); +static void fsm_rconfack __P((fsm *, int, u_char *, int)); +static void fsm_rconfnakrej __P((fsm *, int, int, u_char *, int)); +static void fsm_rtermreq __P((fsm *, int)); +static void fsm_rtermack __P((fsm *)); +static void fsm_rcoderej __P((fsm *, u_char *, int)); +static void fsm_sconfreq __P((fsm *, int)); #define PROTO_NAME(f) ((f)->callbacks->proto_name) -int peer_mru[NPPP]; +int peer_mru[NUM_PPP]; /* @@ -330,28 +330,28 @@ fsm_input(f, inpacket, l) case CONFREQ: fsm_rconfreq(f, id, inp, len); break; - + case CONFACK: fsm_rconfack(f, id, inp, len); break; - + case CONFNAK: case CONFREJ: fsm_rconfnakrej(f, code, id, inp, len); break; - + case TERMREQ: fsm_rtermreq(f, id); break; - + case TERMACK: fsm_rtermack(f); break; - + case CODEREJ: fsm_rcoderej(f, inp, len); break; - + default: if( !f->callbacks->extcode || !(*f->callbacks->extcode)(f, code, id, inp, len) ) @@ -446,15 +446,16 @@ fsm_rconfack(f, id, inp, len) FSMDEBUG((LOG_INFO, "fsm_rconfack(%s): Rcvd id %d.", PROTO_NAME(f), id)); - if (id != f->reqid) /* Expected id? */ - return; /* Nope, toss... */ - if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): (len == 0)) ){ + if (id != f->reqid || f->seen_ack) /* Expected id? */ + return; /* Nope, toss... */ + if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): + (len == 0)) ){ /* Ack is bad - ignore it */ FSMDEBUG((LOG_INFO, "%s: received bad Ack (length %d)", PROTO_NAME(f), len)); return; } - f->reqid = -1; + f->seen_ack = 1; switch (f->state) { case CLOSED: @@ -468,7 +469,8 @@ fsm_rconfack(f, id, inp, len) break; case ACKRCVD: - /* Huh? an extra Ack? oh well... */ + /* Huh? an extra valid Ack? oh well... */ + UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */ fsm_sconfreq(f, 0); f->state = REQSENT; break; @@ -507,16 +509,16 @@ fsm_rconfnakrej(f, code, id, inp, len) FSMDEBUG((LOG_INFO, "fsm_rconfnakrej(%s): Rcvd id %d.", PROTO_NAME(f), id)); - if (id != f->reqid) /* Expected id? */ - return; /* Nope, toss... */ + if (id != f->reqid || f->seen_ack) /* Expected id? */ + return; /* Nope, toss... */ proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci; - if( !proc || !proc(f, inp, len) ){ + if (!proc || !proc(f, inp, len)) { /* Nak/reject is bad - ignore it */ FSMDEBUG((LOG_INFO, "%s: received bad %s (length %d)", PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len)); return; } - f->reqid = -1; + f->seen_ack = 1; switch (f->state) { case CLOSED: @@ -533,6 +535,7 @@ fsm_rconfnakrej(f, code, id, inp, len) case ACKRCVD: /* Got a Nak/reject when we had already had an Ack?? oh well... */ + UNTIMEOUT(fsm_timeout, (caddr_t) f); /* Cancel timeout */ fsm_sconfreq(f, 0); f->state = REQSENT; break; @@ -590,11 +593,13 @@ fsm_rtermack(f) switch (f->state) { case CLOSING: + UNTIMEOUT(fsm_timeout, (caddr_t) f); f->state = CLOSED; if( f->callbacks->finished ) (*f->callbacks->finished)(f); break; case STOPPING: + UNTIMEOUT(fsm_timeout, (caddr_t) f); f->state = STOPPED; if( f->callbacks->finished ) (*f->callbacks->finished)(f); @@ -715,10 +720,12 @@ fsm_sconfreq(f, retransmit) f->reqid = ++f->id; } + f->seen_ack = 0; + /* * Make up the request packet */ - outp = outpacket_buf + DLLHEADERLEN + HEADERLEN; + outp = outpacket_buf + PPP_HDRLEN + HEADERLEN; if( f->callbacks->cilen && f->callbacks->addci ){ cilen = (*f->callbacks->cilen)(f); if( cilen > peer_mru[f->unit] - HEADERLEN ) @@ -759,14 +766,14 @@ fsm_sdata(f, code, id, data, datalen) outp = outpacket_buf; if (datalen > peer_mru[f->unit] - HEADERLEN) datalen = peer_mru[f->unit] - HEADERLEN; - if (datalen && data != outp + DLLHEADERLEN + HEADERLEN) - BCOPY(data, outp + DLLHEADERLEN + HEADERLEN, datalen); + if (datalen && data != outp + PPP_HDRLEN + HEADERLEN) + BCOPY(data, outp + PPP_HDRLEN + HEADERLEN, datalen); outlen = datalen + HEADERLEN; MAKEHEADER(outp, f->protocol); PUTCHAR(code, outp); PUTCHAR(id, outp); PUTSHORT(outlen, outp); - output(f->unit, outpacket_buf, outlen + DLLHEADERLEN); + output(f->unit, outpacket_buf, outlen + PPP_HDRLEN); FSMDEBUG((LOG_INFO, "fsm_sdata(%s): Sent code %d, id %d.", PROTO_NAME(f), code, id)); diff --git a/usr.sbin/pppd/fsm.h b/usr.sbin/pppd/fsm.h index a12966bef488..efe18bf92f00 100644 --- a/usr.sbin/pppd/fsm.h +++ b/usr.sbin/pppd/fsm.h @@ -16,7 +16,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: fsm.h,v 1.2 1994/04/11 07:18:35 paulus Exp $ + * $Id: fsm.h,v 1.5 1995/05/19 03:17:35 paulus Exp $ */ /* @@ -66,6 +66,7 @@ typedef struct fsm { int flags; /* Contains option bits */ u_char id; /* Current id */ u_char reqid; /* Current request id */ + u_char seen_ack; /* Have received valid Ack/Nak/Rej to Req */ int timeouttime; /* Timeout time in milliseconds */ int maxconfreqtransmits; /* Maximum Configure-Request transmissions */ int retransmits; /* Number of retransmissions left */ @@ -105,20 +106,20 @@ typedef struct fsm { #define DEFTIMEOUT 3 /* Timeout time in seconds */ #define DEFMAXTERMREQS 2 /* Maximum Terminate-Request transmissions */ #define DEFMAXCONFREQS 10 /* Maximum Configure-Request transmissions */ -#define DEFMAXNAKLOOPS 10 /* Maximum number of nak loops */ +#define DEFMAXNAKLOOPS 5 /* Maximum number of nak loops */ /* * Prototypes */ -void fsm_init __ARGS((fsm *)); -void fsm_lowerup __ARGS((fsm *)); -void fsm_lowerdown __ARGS((fsm *)); -void fsm_open __ARGS((fsm *)); -void fsm_close __ARGS((fsm *)); -void fsm_input __ARGS((fsm *, u_char *, int)); -void fsm_protreject __ARGS((fsm *)); -void fsm_sdata __ARGS((fsm *, int, int, u_char *, int)); +void fsm_init __P((fsm *)); +void fsm_lowerup __P((fsm *)); +void fsm_lowerdown __P((fsm *)); +void fsm_open __P((fsm *)); +void fsm_close __P((fsm *)); +void fsm_input __P((fsm *, u_char *, int)); +void fsm_protreject __P((fsm *)); +void fsm_sdata __P((fsm *, int, int, u_char *, int)); /* diff --git a/usr.sbin/pppd/ipcp.c b/usr.sbin/pppd/ipcp.c index 2508cdc73517..3d99235440b2 100644 --- a/usr.sbin/pppd/ipcp.c +++ b/usr.sbin/pppd/ipcp.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: ipcp.c,v 1.2 1994/09/25 02:31:59 wollman Exp $"; +static char rcsid[] = "$Id: ipcp.c,v 1.20 1995/08/10 06:51:04 paulus Exp $"; #endif /* @@ -30,41 +30,37 @@ static char rcsid[] = "$Id: ipcp.c,v 1.2 1994/09/25 02:31:59 wollman Exp $"; #include <syslog.h> #include <sys/types.h> #include <sys/socket.h> +#include <netinet/in.h> #include "pppd.h" -#include "ppp.h" #include "fsm.h" #include "ipcp.h" #include "pathnames.h" /* global vars */ -ipcp_options ipcp_wantoptions[NPPP]; /* Options that we want to request */ -ipcp_options ipcp_gotoptions[NPPP]; /* Options that peer ack'd */ -ipcp_options ipcp_allowoptions[NPPP]; /* Options we allow peer to request */ -ipcp_options ipcp_hisoptions[NPPP]; /* Options that we ack'd */ - -extern char ifname[]; -extern char devname[]; -extern int baud_rate; +ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */ +ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ +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[NPPP]; /* # Conf-Reqs received */ +static int cis_received[NUM_PPP]; /* # Conf-Reqs received */ /* * Callbacks for fsm code. (CI = Configuration Information) */ -static void ipcp_resetci __ARGS((fsm *)); /* Reset our CI */ -static int ipcp_cilen __ARGS((fsm *)); /* Return length of our CI */ -static void ipcp_addci __ARGS((fsm *, u_char *, int *)); /* Add our CI */ -static int ipcp_ackci __ARGS((fsm *, u_char *, int)); /* Peer ack'd our CI */ -static int ipcp_nakci __ARGS((fsm *, u_char *, int)); /* Peer nak'd our CI */ -static int ipcp_rejci __ARGS((fsm *, u_char *, int)); /* Peer rej'd our CI */ -static int ipcp_reqci __ARGS((fsm *, u_char *, int *, int)); /* Rcv CI */ -static void ipcp_up __ARGS((fsm *)); /* We're UP */ -static void ipcp_down __ARGS((fsm *)); /* We're DOWN */ -static void ipcp_script __ARGS((fsm *, char *)); /* Run an up/down script */ - -fsm ipcp_fsm[NPPP]; /* IPCP fsm structure */ +static void ipcp_resetci __P((fsm *)); /* Reset our CI */ +static int ipcp_cilen __P((fsm *)); /* Return length of our CI */ +static void ipcp_addci __P((fsm *, u_char *, int *)); /* Add our CI */ +static int ipcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */ +static int ipcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */ +static int ipcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */ +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 */ + +fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */ static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ ipcp_resetci, /* Reset our Configuration Information */ @@ -103,7 +99,7 @@ static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */ */ char * ip_ntoa(ipaddr) -u_long ipaddr; +u_int32_t ipaddr; { static char b[64]; @@ -130,7 +126,7 @@ ipcp_init(unit) ipcp_options *ao = &ipcp_allowoptions[unit]; f->unit = unit; - f->protocol = IPCP; + f->protocol = PPP_IPCP; f->callbacks = &ipcp_callbacks; fsm_init(&ipcp_fsm[unit]); @@ -296,7 +292,7 @@ ipcp_addci(f, ucp, lenp) if (neg) { \ int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ if (len >= addrlen) { \ - u_long l; \ + u_int32_t l; \ PUTCHAR(opt, ucp); \ PUTCHAR(addrlen, ucp); \ l = ntohl(val1); \ @@ -359,7 +355,7 @@ ipcp_ackci(f, p, len) { ipcp_options *go = &ipcp_gotoptions[f->unit]; u_short cilen, citype, cishort; - u_long cilong; + u_int32_t cilong; u_char cimaxslotindex, cicflag; /* @@ -394,7 +390,7 @@ ipcp_ackci(f, p, len) #define ACKCIADDR(opt, neg, old, val1, val2) \ if (neg) { \ int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \ - u_long l; \ + u_int32_t l; \ if ((len -= addrlen) < 0) \ goto bad; \ GETCHAR(citype, p); \ @@ -451,7 +447,7 @@ ipcp_nakci(f, p, len) u_char cimaxslotindex, cicflag; u_char citype, cilen, *next; u_short cishort; - u_long ciaddr1, ciaddr2, l; + u_int32_t ciaddr1, ciaddr2, l; ipcp_options no; /* options we've seen Naks for */ ipcp_options try; /* options to request next time */ @@ -498,7 +494,7 @@ ipcp_nakci(f, p, len) * Accept the peer's idea of {our,his} address, if different * from our idea, only if the accept_{local,remote} flag is set. */ - NAKCIADDR(CI_ADDR, neg_addr, go->old_addrs, + NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs, if (go->accept_local && ciaddr1) { /* Do we know our address? */ try.ouraddr = ciaddr1; IPCPDEBUG((LOG_INFO, "local IP address %s", @@ -579,16 +575,15 @@ ipcp_nakci(f, p, len) case CI_ADDR: if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) goto bad; - try.neg_addr = 1; try.old_addrs = 0; GETLONG(l, p); ciaddr1 = htonl(l); if (ciaddr1 && go->accept_local) try.ouraddr = ciaddr1; + if (try.ouraddr != 0) + try.neg_addr = 1; no.neg_addr = 1; break; - default: - goto bad; } p = next; } @@ -623,7 +618,7 @@ ipcp_rejci(f, p, len) ipcp_options *go = &ipcp_gotoptions[f->unit]; u_char cimaxslotindex, ciflag, cilen; u_short cishort; - u_long cilong; + u_int32_t cilong; ipcp_options try; /* options to request next time */ try = *go; @@ -637,7 +632,7 @@ ipcp_rejci(f, p, len) len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \ p[1] == cilen && \ p[0] == opt) { \ - u_long l; \ + u_int32_t l; \ len -= cilen; \ INCPTR(2, p); \ GETLONG(l, p); \ @@ -722,7 +717,7 @@ ipcp_reqci(f, inp, len, reject_if_disagree) u_char *cip, *next; /* Pointer to current and next CIs */ u_short cilen, citype; /* Parsed len, type */ u_short cishort; /* Parsed short value */ - u_long tl, ciaddr1, ciaddr2;/* Parsed address values */ + u_int32_t tl, ciaddr1, ciaddr2;/* Parsed address values */ int rc = CONFACK; /* Final packet return code */ int orc; /* Individual option return code */ u_char *p; /* Pointer to next char to parse */ @@ -734,7 +729,7 @@ ipcp_reqci(f, inp, len, reject_if_disagree) * Reset all his options. */ BZERO(ho, sizeof(*ho)); - + /* * Process all his options. */ @@ -778,10 +773,17 @@ ipcp_reqci(f, inp, len, reject_if_disagree) && (ciaddr1 == 0 || !wo->accept_remote)) { orc = CONFNAK; if (!reject_if_disagree) { - DECPTR(sizeof (long), p); + DECPTR(sizeof(u_int32_t), p); tl = ntohl(wo->hisaddr); PUTLONG(tl, p); } + } else if (ciaddr1 == 0 && wo->hisaddr == 0) { + /* + * If neither we nor he knows his address, reject the option. + */ + orc = CONFREJ; + wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ + break; } /* @@ -795,7 +797,7 @@ ipcp_reqci(f, inp, len, reject_if_disagree) if (ciaddr2 == 0 || !wo->accept_local) { orc = CONFNAK; if (!reject_if_disagree) { - DECPTR(sizeof (long), p); + DECPTR(sizeof(u_int32_t), p); tl = ntohl(wo->ouraddr); PUTLONG(tl, p); } @@ -832,16 +834,23 @@ ipcp_reqci(f, inp, len, reject_if_disagree) && (ciaddr1 == 0 || !wo->accept_remote)) { orc = CONFNAK; if (!reject_if_disagree) { - DECPTR(sizeof (long), p); + DECPTR(sizeof(u_int32_t), p); tl = ntohl(wo->hisaddr); PUTLONG(tl, p); } + } else if (ciaddr1 == 0 && wo->hisaddr == 0) { + /* + * Don't ACK an address of 0.0.0.0 - reject it instead. + */ + orc = CONFREJ; + wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */ + break; } - + ho->neg_addr = 1; ho->hisaddr = ciaddr1; break; - + case CI_COMPRESSTYPE: IPCPDEBUG((LOG_INFO, "ipcp: received COMPRESSTYPE ")); if (!ao->neg_vj || @@ -862,7 +871,7 @@ ipcp_reqci(f, inp, len, reject_if_disagree) ho->vj_protocol = cishort; if (cilen == CILEN_VJ) { GETCHAR(maxslotindex, p); - if (maxslotindex > ao->maxslotindex) { + if (maxslotindex > ao->maxslotindex) { orc = CONFNAK; if (!reject_if_disagree){ DECPTR(1, p); @@ -878,7 +887,7 @@ ipcp_reqci(f, inp, len, reject_if_disagree) } } ho->maxslotindex = maxslotindex; - ho->cflag = wo->cflag; + ho->cflag = cflag; } else { ho->old_vj = 1; ho->maxslotindex = MAX_STATES - 1; @@ -960,7 +969,7 @@ static void ipcp_up(f) fsm *f; { - u_long mask; + u_int32_t mask; ipcp_options *ho = &ipcp_hisoptions[f->unit]; ipcp_options *go = &ipcp_gotoptions[f->unit]; @@ -1019,7 +1028,7 @@ ipcp_up(f) } /* assign a default route through the interface if required */ - if (ipcp_wantoptions[f->unit].default_route) + if (ipcp_wantoptions[f->unit].default_route) if (sifdefaultroute(f->unit, ho->hisaddr)) go->default_route = 1; @@ -1047,7 +1056,7 @@ static void ipcp_down(f) fsm *f; { - u_long ouraddr, hisaddr; + u_int32_t ouraddr, hisaddr; IPCPDEBUG((LOG_INFO, "ipcp: down")); @@ -1055,7 +1064,7 @@ ipcp_down(f) hisaddr = ipcp_hisoptions[f->unit].hisaddr; if (ipcp_gotoptions[f->unit].proxy_arp) cifproxyarp(f->unit, hisaddr); - if (ipcp_gotoptions[f->unit].default_route) + if (ipcp_gotoptions[f->unit].default_route) cifdefaultroute(f->unit, hisaddr); sifdown(f->unit); cifaddr(f->unit, ouraddr, hisaddr); @@ -1083,11 +1092,12 @@ ipcp_script(f, script) argv[0] = script; argv[1] = ifname; - argv[2] = devname; + argv[2] = devnam; argv[3] = strspeed; argv[4] = strlocal; argv[5] = strremote; - argv[6] = NULL; + argv[6] = ipparam; + argv[7] = NULL; run_program(script, argv, 0); } @@ -1109,7 +1119,7 @@ ipcp_printpkt(p, plen, printer, arg) int code, id, len, olen; u_char *pstart, *optend; u_short cishort; - u_long cilong; + u_int32_t cilong; if (plen < HEADERLEN) return 0; diff --git a/usr.sbin/pppd/ipcp.h b/usr.sbin/pppd/ipcp.h index 393c9af90258..b1f9b4032fd9 100644 --- a/usr.sbin/pppd/ipcp.h +++ b/usr.sbin/pppd/ipcp.h @@ -16,7 +16,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: ipcp.h,v 1.2 1994/09/25 02:32:00 wollman Exp $ + * $Id: ipcp.h,v 1.5 1994/09/21 06:47:37 paulus Exp $ */ /* @@ -35,7 +35,7 @@ #define IPCP_VJ_COMP 0x002d /* current value for VJ compression option*/ #define IPCP_VJ_COMP_OLD 0x0037 /* "old" (i.e, broken) value for VJ */ - /* compression option*/ + /* compression option*/ typedef struct ipcp_options { int neg_addr : 1; /* Negotiate IP Address? */ @@ -49,7 +49,7 @@ typedef struct ipcp_options { int accept_remote : 1; /* accept peer's value for hisaddr */ u_short vj_protocol; /* protocol value to use in VJ option */ u_char maxslotindex, cflag; /* values for RFC1332 VJ compression neg. */ - u_long ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */ + u_int32_t ouraddr, hisaddr; /* Addresses in NETWORK BYTE ORDER */ } ipcp_options; extern fsm ipcp_fsm[]; @@ -58,11 +58,11 @@ extern ipcp_options ipcp_gotoptions[]; extern ipcp_options ipcp_allowoptions[]; extern ipcp_options ipcp_hisoptions[]; -void ipcp_init __ARGS((int)); -void ipcp_open __ARGS((int)); -void ipcp_close __ARGS((int)); -void ipcp_lowerup __ARGS((int)); -void ipcp_lowerdown __ARGS((int)); -void ipcp_input __ARGS((int, u_char *, int)); -void ipcp_protrej __ARGS((int)); -int ipcp_printpkt __ARGS((u_char *, int, void (*)(), void *)); +void ipcp_init __P((int)); +void ipcp_open __P((int)); +void ipcp_close __P((int)); +void ipcp_lowerup __P((int)); +void ipcp_lowerdown __P((int)); +void ipcp_input __P((int, u_char *, int)); +void ipcp_protrej __P((int)); +int ipcp_printpkt __P((u_char *, int, void (*)(), void *)); diff --git a/usr.sbin/pppd/lcp.c b/usr.sbin/pppd/lcp.c index c64296120d22..f9d6c1cc9b9c 100644 --- a/usr.sbin/pppd/lcp.c +++ b/usr.sbin/pppd/lcp.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: lcp.c,v 1.2 1994/09/25 02:32:01 wollman Exp $"; +static char rcsid[] = "$Id: lcp.c,v 1.21 1995/08/10 06:51:06 paulus Exp $"; #endif /* @@ -36,7 +36,6 @@ static char rcsid[] = "$Id: lcp.c,v 1.2 1994/09/25 02:32:01 wollman Exp $"; #include <netinet/in.h> #include "pppd.h" -#include "ppp.h" #include "fsm.h" #include "lcp.h" #include "magic.h" @@ -45,51 +44,56 @@ static char rcsid[] = "$Id: lcp.c,v 1.2 1994/09/25 02:32:01 wollman Exp $"; #include "ipcp.h" #ifdef _linux_ /* Needs ppp ioctls */ -#include <linux/ppp.h> +#include <net/if.h> +#include <linux/if_ppp.h> #endif /* global vars */ -fsm lcp_fsm[NPPP]; /* LCP fsm structure (global)*/ -lcp_options lcp_wantoptions[NPPP]; /* Options that we want to request */ -lcp_options lcp_gotoptions[NPPP]; /* Options that peer ack'd */ -lcp_options lcp_allowoptions[NPPP]; /* Options we allow peer to request */ -lcp_options lcp_hisoptions[NPPP]; /* Options that we ack'd */ -u_long xmit_accm[NPPP][8]; /* extended transmit ACCM */ - -static u_long lcp_echos_pending = 0; /* Number of outstanding echo msgs */ -static u_long lcp_echo_number = 0; /* ID number of next echo frame */ -static u_long lcp_echo_timer_running = 0; /* TRUE if a timer is running */ - -u_long lcp_echo_interval = 0; -u_long lcp_echo_fails = 0; +fsm lcp_fsm[NUM_PPP]; /* LCP fsm structure (global)*/ +lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */ +lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ +lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ +lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ +u_int32_t xmit_accm[NUM_PPP][8]; /* extended transmit ACCM */ + +static u_int32_t lcp_echos_pending = 0; /* Number of outstanding echo msgs */ +static u_int32_t lcp_echo_number = 0; /* ID number of next echo frame */ +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) */ -static void lcp_resetci __ARGS((fsm *)); /* Reset our CI */ -static int lcp_cilen __ARGS((fsm *)); /* Return length of our CI */ -static void lcp_addci __ARGS((fsm *, u_char *, int *)); /* Add our CI to pkt */ -static int lcp_ackci __ARGS((fsm *, u_char *, int)); /* Peer ack'd our CI */ -static int lcp_nakci __ARGS((fsm *, u_char *, int)); /* Peer nak'd our CI */ -static int lcp_rejci __ARGS((fsm *, u_char *, int)); /* Peer rej'd our CI */ -static int lcp_reqci __ARGS((fsm *, u_char *, int *, int)); /* Rcv peer CI */ -static void lcp_up __ARGS((fsm *)); /* We're UP */ -static void lcp_down __ARGS((fsm *)); /* We're DOWN */ -static void lcp_starting __ARGS((fsm *)); /* We need lower layer up */ -static void lcp_finished __ARGS((fsm *)); /* We need lower layer down */ -static int lcp_extcode __ARGS((fsm *, int, int, u_char *, int)); -static void lcp_rprotrej __ARGS((fsm *, u_char *, int)); +static void lcp_resetci __P((fsm *)); /* Reset our CI */ +static int lcp_cilen __P((fsm *)); /* Return length of our CI */ +static void lcp_addci __P((fsm *, u_char *, int *)); /* Add our CI to pkt */ +static int lcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */ +static int lcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */ +static int lcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */ +static int lcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv peer CI */ +static void lcp_up __P((fsm *)); /* We're UP */ +static void lcp_down __P((fsm *)); /* We're DOWN */ +static void lcp_starting __P((fsm *)); /* We need lower layer up */ +static void lcp_finished __P((fsm *)); /* We need lower layer down */ +static int lcp_extcode __P((fsm *, int, int, u_char *, int)); +static void lcp_rprotrej __P((fsm *, u_char *, int)); /* * routines to send LCP echos to peer */ -static void lcp_echo_lowerup __ARGS((int)); -static void lcp_echo_lowerdown __ARGS((int)); -static void LcpEchoTimeout __ARGS((caddr_t)); -static void lcp_received_echo_reply __ARGS((fsm *, int, u_char *, int)); -static void LcpSendEchoRequest __ARGS((fsm *)); -static void LcpLinkFailure __ARGS((fsm *)); +static void lcp_echo_lowerup __P((int)); +static void lcp_echo_lowerdown __P((int)); +static void LcpEchoTimeout __P((caddr_t)); +static void lcp_received_echo_reply __P((fsm *, int, u_char *, int)); +static void LcpSendEchoRequest __P((fsm *)); +static void LcpLinkFailure __P((fsm *)); static fsm_callbacks lcp_callbacks = { /* LCP callback routines */ lcp_resetci, /* Reset our Configuration Information */ @@ -109,7 +113,7 @@ static fsm_callbacks lcp_callbacks = { /* LCP callback routines */ "LCP" /* String name of protocol */ }; -int lcp_warnloops = DEFWARNLOOPS; /* Warn about a loopback this often */ +int lcp_loopbackfail = DEFLOOPBACKFAIL; /* * Length of each type of configuration option (in octets) @@ -136,7 +140,7 @@ lcp_init(unit) lcp_options *ao = &lcp_allowoptions[unit]; f->unit = unit; - f->protocol = LCP; + f->protocol = PPP_LCP; f->callbacks = &lcp_callbacks; fsm_init(f); @@ -216,6 +220,58 @@ 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_idle ddinfo; +/* + * Read the time since the last packet was received. + */ + if (ioctl (fd, PPPIOCGIDLE, &ddinfo) < 0) { + syslog (LOG_ERR, "ioctl(PPPIOCGIDLE): %m"); + die (1); + } +/* + * Compute the time since the last packet was received. If the timer + * has expired then disconnect the line. + */ + delta = idle_time_limit - (u_long) ddinfo.recv_idle; + if (((int) delta <= 0L) && (f->state == OPENED)) { + syslog (LOG_NOTICE, "No IP frames received within idle time limit"); + lcp_close(f->unit); /* Reset connection */ + phase = PHASE_TERMINATE; /* Mark it down */ + } else { + if ((int) delta <= 0L) + 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. @@ -226,9 +282,9 @@ lcp_lowerup(unit) { sifdown(unit); ppp_set_xaccm(unit, xmit_accm[unit]); - ppp_send_config(unit, MTU, 0xffffffff, 0, 0); - ppp_recv_config(unit, MTU, 0x00000000, 0, 0); - peer_mru[unit] = MTU; + ppp_send_config(unit, PPP_MRU, 0xffffffff, 0, 0); + ppp_recv_config(unit, PPP_MRU, 0x00000000, 0, 0); + peer_mru[unit] = PPP_MRU; lcp_allowoptions[unit].asyncmap = xmit_accm[unit][0]; fsm_lowerup(&lcp_fsm[unit]); @@ -255,7 +311,23 @@ lcp_input(unit, p, len) u_char *p; int len; { - fsm_input(&lcp_fsm[unit], p, len); + int oldstate; + fsm *f = &lcp_fsm[unit]; + lcp_options *go = &lcp_gotoptions[f->unit]; + + oldstate = f->state; + fsm_input(f, p, len); + if (oldstate == REQSENT && f->state == ACKSENT) { + /* + * The peer will probably send us an ack soon and then + * immediately start sending packets with the negotiated + * options. So as to be ready when that happens, we set + * our receive side to accept packets as negotiated now. + */ + ppp_recv_config(f->unit, PPP_MRU, + go->neg_asyncmap? go->asyncmap: 0x00000000, + go->neg_pcompression, go->neg_accompression); + } } @@ -275,18 +347,16 @@ lcp_extcode(f, code, id, inp, len) case PROTREJ: lcp_rprotrej(f, inp, len); break; - + case ECHOREQ: if (f->state != OPENED) break; LCPDEBUG((LOG_INFO, "lcp: Echo-Request, Rcvd id %d", id)); magp = inp; PUTLONG(lcp_gotoptions[f->unit].magicnumber, magp); - if (len < CILEN_LONG) - len = CILEN_LONG; fsm_sdata(f, ECHOREP, id, inp, len); break; - + case ECHOREP: lcp_received_echo_reply(f, id, inp, len); break; @@ -300,7 +370,7 @@ lcp_extcode(f, code, id, inp, len) return 1; } - + /* * lcp_rprotrej - Receive an Protocol-Reject. * @@ -390,7 +460,7 @@ fsm *f; lcp_wantoptions[f->unit].magicnumber = magic(); lcp_wantoptions[f->unit].numloops = 0; lcp_gotoptions[f->unit] = lcp_wantoptions[f->unit]; - peer_mru[f->unit] = MTU; + peer_mru[f->unit] = PPP_MRU; } @@ -463,14 +533,14 @@ lcp_addci(f, ucp, lenp) if (neg) { \ PUTCHAR(opt, ucp); \ PUTCHAR(CILEN_LQR, ucp); \ - PUTSHORT(LQR, ucp); \ + PUTSHORT(PPP_LQR, ucp); \ PUTLONG(val, ucp); \ } ADDCISHORT(CI_MRU, go->neg_mru, go->mru); ADDCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap); - ADDCICHAP(CI_AUTHTYPE, go->neg_chap, CHAP, go->chap_mdtype); - ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, UPAP); + ADDCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype); + ADDCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); ADDCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); ADDCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); ADDCIVOID(CI_PCOMPRESSION, go->neg_pcompression); @@ -500,7 +570,7 @@ lcp_ackci(f, p, len) lcp_options *go = &lcp_gotoptions[f->unit]; u_char cilen, citype, cichar; u_short cishort; - u_long cilong; + u_int32_t cilong; /* * CIs must be in exactly the same order that we sent. @@ -569,7 +639,7 @@ lcp_ackci(f, p, len) citype != opt) \ goto bad; \ GETSHORT(cishort, p); \ - if (cishort != LQR) \ + if (cishort != PPP_LQR) \ goto bad; \ GETLONG(cilong, p); \ if (cilong != val) \ @@ -578,8 +648,8 @@ lcp_ackci(f, p, len) ACKCISHORT(CI_MRU, go->neg_mru, go->mru); ACKCILONG(CI_ASYNCMAP, go->neg_asyncmap, go->asyncmap); - ACKCICHAP(CI_AUTHTYPE, go->neg_chap, CHAP, go->chap_mdtype); - ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, UPAP); + ACKCICHAP(CI_AUTHTYPE, go->neg_chap, PPP_CHAP, go->chap_mdtype); + ACKCISHORT(CI_AUTHTYPE, !go->neg_chap && go->neg_upap, PPP_PAP); ACKCILQR(CI_QUALITY, go->neg_lqr, go->lqr_period); ACKCILONG(CI_MAGICNUMBER, go->neg_magicnumber, go->magicnumber); ACKCIVOID(CI_PCOMPRESSION, go->neg_pcompression); @@ -614,12 +684,13 @@ lcp_nakci(f, p, len) { lcp_options *go = &lcp_gotoptions[f->unit]; lcp_options *wo = &lcp_wantoptions[f->unit]; - u_char cilen, citype, cichar, *next; + u_char citype, cichar, *next; u_short cishort; - u_long cilong; + u_int32_t cilong; lcp_options no; /* options we've seen Naks for */ lcp_options try; /* options to request next time */ int looped_back = 0; + int cilen; BZERO(&no, sizeof(no)); try = *go; @@ -697,21 +768,67 @@ lcp_nakci(f, p, len) if (cishort <= wo->mru || cishort < DEFMRU) try.mru = cishort; ); + /* * Add any characters they want to our (receive-side) asyncmap. */ NAKCILONG(CI_ASYNCMAP, neg_asyncmap, try.asyncmap = go->asyncmap | cilong; ); + /* - * If they can't cope with our CHAP hash algorithm, we'll have - * to stop asking for CHAP. We haven't got any other algorithm. + * If they've nak'd our authentication-protocol, check whether + * they are proposing a different protocol, or a different + * hash algorithm for CHAP. */ - NAKCICHAP(CI_AUTHTYPE, neg_chap, - try.neg_chap = 0; - ); + if ((go->neg_chap || go->neg_upap) + && len >= CILEN_SHORT + && p[0] == CI_AUTHTYPE && p[1] >= CILEN_SHORT) { + cilen = p[1]; + INCPTR(2, p); + GETSHORT(cishort, p); + if (cishort == PPP_PAP && cilen == CILEN_SHORT) { + /* + * If they are asking for PAP, then they don't want to do CHAP. + * If we weren't asking for CHAP, then we were asking for PAP, + * in which case this Nak is bad. + */ + if (!go->neg_chap) + goto bad; + go->neg_chap = 0; + + } else if (cishort == PPP_CHAP && cilen == CILEN_CHAP) { + GETCHAR(cichar, p); + if (go->neg_chap) { + /* + * We were asking for CHAP/MD5; they must want a different + * algorithm. If they can't do MD5, we'll have to stop + * asking for CHAP. + */ + if (cichar != go->chap_mdtype) + go->neg_chap = 0; + } else { + /* + * Stop asking for PAP if we were asking for it. + */ + go->neg_upap = 0; + } + + } else { + /* + * We don't recognize what they're suggesting. + * Stop asking for what we were asking for. + */ + if (go->neg_chap) + go->neg_chap = 0; + else + go->neg_upap = 0; + p += cilen - CILEN_SHORT; + } + } + /* - * Peer shouldn't send Nak for UPAP, protocol compression or + * Peer shouldn't send Nak for protocol compression or * address/control compression requests; they should send * a Reject instead. If they send a Nak, treat it as a Reject. */ @@ -720,23 +837,24 @@ lcp_nakci(f, p, len) try.neg_upap = 0; ); } + /* * If they can't cope with our link quality protocol, we'll have * to stop asking for LQR. We haven't got any other protocol. * If they Nak the reporting period, take their value XXX ? */ NAKCILQR(CI_QUALITY, neg_lqr, - if (cishort != LQR) + if (cishort != PPP_LQR) try.neg_lqr = 0; else try.lqr_period = cilong; ); + /* * Check for a looped-back line. */ NAKCILONG(CI_MAGICNUMBER, neg_magicnumber, try.magicnumber = magic(); - ++try.numloops; looped_back = 1; ); @@ -760,11 +878,13 @@ lcp_nakci(f, p, len) * `let me authenticate myself with you' which is a bit pointless. * For the quality protocol, the Nak means `ask me to send you quality * reports', but if we didn't ask for them, we don't want them. + * An option we don't recognize represents the peer asking to + * negotiate some option we don't support, so ignore it. */ while (len > CILEN_VOID) { GETCHAR(citype, p); GETCHAR(cilen, p); - if( (len -= cilen) < 0 ) + if ((len -= cilen) < 0) goto bad; next = p + cilen - 2; @@ -800,8 +920,6 @@ lcp_nakci(f, p, len) if (go->neg_lqr || no.neg_lqr || cilen != CILEN_LQR) goto bad; break; - default: - goto bad; } p = next; } @@ -814,9 +932,14 @@ lcp_nakci(f, p, len) * OK, the Nak is good. Now we can update state. */ if (f->state != OPENED) { + if (looped_back) { + if (++try.numloops >= lcp_loopbackfail) { + syslog(LOG_NOTICE, "Serial line is looped back."); + lcp_close(f->unit); + } + } else + try.numloops = 0; *go = try; - if (looped_back && try.numloops % lcp_warnloops == 0) - LCPDEBUG((LOG_INFO, "The line appears to be looped back.")); } return 1; @@ -845,7 +968,7 @@ lcp_rejci(f, p, len) lcp_options *go = &lcp_gotoptions[f->unit]; u_char cichar; u_short cishort; - u_long cilong; + u_int32_t cilong; u_char *start = p; int plen = len; lcp_options try; /* options to request next time */ @@ -894,6 +1017,7 @@ lcp_rejci(f, p, len) if (cishort != val || cichar != digest) \ goto bad; \ try.neg = 0; \ + try.neg_upap = 0; \ LCPDEBUG((LOG_INFO,"lcp_rejci rejected chap opt %d", opt)); \ } #define REJCILONG(opt, neg, val) \ @@ -920,7 +1044,7 @@ lcp_rejci(f, p, len) GETSHORT(cishort, p); \ GETLONG(cilong, p); \ /* Check rejected value. */ \ - if (cishort != LQR || cilong != val) \ + if (cishort != PPP_LQR || cilong != val) \ goto bad; \ try.neg = 0; \ LCPDEBUG((LOG_INFO,"lcp_rejci rejected LQR opt %d", opt)); \ @@ -928,9 +1052,9 @@ lcp_rejci(f, p, len) REJCISHORT(CI_MRU, neg_mru, go->mru); REJCILONG(CI_ASYNCMAP, neg_asyncmap, go->asyncmap); - REJCICHAP(CI_AUTHTYPE, neg_chap, CHAP, go->chap_mdtype); + REJCICHAP(CI_AUTHTYPE, neg_chap, PPP_CHAP, go->chap_mdtype); if (!go->neg_chap) { - REJCISHORT(CI_AUTHTYPE, neg_upap, UPAP); + REJCISHORT(CI_AUTHTYPE, neg_upap, PPP_PAP); } REJCILQR(CI_QUALITY, neg_lqr, go->lqr_period); REJCILONG(CI_MAGICNUMBER, neg_magicnumber, go->magicnumber); @@ -977,11 +1101,12 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) u_char *cip, *next; /* Pointer to current and next CIs */ u_char cilen, citype, cichar;/* Parsed len, type, char value */ u_short cishort; /* Parsed short value */ - u_long cilong; /* Parse long value */ + u_int32_t cilong; /* Parse long value */ int rc = CONFACK; /* Final packet return code */ int orc; /* Individual option return code */ u_char *p; /* Pointer to next char to parse */ - u_char *ucp = inp; /* Pointer to current output char */ + u_char *rejp; /* Pointer to next char in reject frame */ + u_char *nakp; /* Pointer to next char in Nak frame */ int l = *lenp; /* Length left */ /* @@ -993,6 +1118,8 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) * Process all his options. */ next = inp; + nakp = nak_buffer; + rejp = inp; while (l) { orc = CONFACK; /* Assume success */ cip = p = next; /* Remember begining of CI */ @@ -1028,10 +1155,9 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) */ if (cishort < MINMRU) { orc = CONFNAK; /* Nak CI */ - if( !reject_if_disagree ){ - DECPTR(sizeof (short), p); /* Backup */ - PUTSHORT(MINMRU, p); /* Give him a hint */ - } + PUTCHAR(CI_MRU, nakp); + PUTCHAR(CILEN_SHORT, nakp); + PUTSHORT(MINMRU, nakp); /* Give him a hint */ break; } ho->neg_mru = 1; /* Remember he sent MRU */ @@ -1046,7 +1172,7 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) break; } GETLONG(cilong, p); - LCPDEBUG((LOG_INFO, "(%lx)", cilong)); + LCPDEBUG((LOG_INFO, "(%x)", (unsigned int) cilong)); /* * Asyncmap must have set at least the bits @@ -1054,10 +1180,9 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) */ if ((ao->asyncmap & ~cilong) != 0) { orc = CONFNAK; - if( !reject_if_disagree ){ - DECPTR(sizeof (long), p); - PUTLONG(ao->asyncmap | cilong, p); - } + PUTCHAR(CI_ASYNCMAP, nakp); + PUTCHAR(CILEN_LONG, nakp); + PUTLONG(ao->asyncmap | cilong, nakp); break; } ho->neg_asyncmap = 1; @@ -1068,6 +1193,9 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd AUTHTYPE")); if (cilen < CILEN_SHORT || !(ao->neg_upap || ao->neg_chap)) { + /* + * Reject the option if we're not willing to authenticate. + */ orc = CONFREJ; break; } @@ -1085,34 +1213,47 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) * the ordering of the CIs in the peer's Configure-Request. */ - if (cishort == UPAP) { - if (!ao->neg_upap || /* we don't want to do PAP */ - ho->neg_chap || /* or we've already accepted CHAP */ + if (cishort == PPP_PAP) { + if (ho->neg_chap || /* we've already accepted CHAP */ cilen != CILEN_SHORT) { LCPDEBUG((LOG_WARNING, "lcp_reqci: rcvd AUTHTYPE PAP, rejecting...")); orc = CONFREJ; break; } + if (!ao->neg_upap) { /* we don't want to do PAP */ + orc = CONFNAK; /* NAK it and suggest CHAP */ + PUTCHAR(CI_AUTHTYPE, nakp); + PUTCHAR(CILEN_CHAP, nakp); + PUTSHORT(PPP_CHAP, nakp); + PUTCHAR(ao->chap_mdtype, nakp); + break; + } ho->neg_upap = 1; break; } - if (cishort == CHAP) { - if (!ao->neg_chap || /* we don't want to do CHAP */ - ho->neg_upap || /* or we've already accepted UPAP */ + if (cishort == PPP_CHAP) { + if (ho->neg_upap || /* we've already accepted PAP */ cilen != CILEN_CHAP) { LCPDEBUG((LOG_INFO, "lcp_reqci: rcvd AUTHTYPE CHAP, rejecting...")); orc = CONFREJ; break; } + if (!ao->neg_chap) { /* we don't want to do CHAP */ + orc = CONFNAK; /* NAK it and suggest PAP */ + PUTCHAR(CI_AUTHTYPE, nakp); + PUTCHAR(CILEN_SHORT, nakp); + PUTSHORT(PPP_PAP, nakp); + break; + } GETCHAR(cichar, p); /* get digest type*/ if (cichar != ao->chap_mdtype) { orc = CONFNAK; - if( !reject_if_disagree ){ - DECPTR(sizeof (u_char), p); - PUTCHAR(ao->chap_mdtype, p); - } + PUTCHAR(CI_AUTHTYPE, nakp); + PUTCHAR(CILEN_CHAP, nakp); + PUTSHORT(PPP_CHAP, nakp); + PUTCHAR(ao->chap_mdtype, nakp); break; } ho->chap_mdtype = cichar; /* save md type */ @@ -1122,9 +1263,19 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) /* * We don't recognize the protocol they're asking for. - * Reject it. + * Nak it with something we're willing to do. + * (At this point we know ao->neg_upap || ao->neg_chap.) */ - orc = CONFREJ; + orc = CONFNAK; + PUTCHAR(CI_AUTHTYPE, nakp); + if (ao->neg_chap) { + PUTCHAR(CILEN_CHAP, nakp); + PUTSHORT(PPP_CHAP, nakp); + PUTCHAR(ao->chap_mdtype, nakp); + } else { + PUTCHAR(CILEN_SHORT, nakp); + PUTSHORT(PPP_PAP, nakp); + } break; case CI_QUALITY: @@ -1137,16 +1288,20 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) GETSHORT(cishort, p); GETLONG(cilong, p); - LCPDEBUG((LOG_INFO, "(%x %lx)", cishort, cilong)); - if (cishort != LQR) { - orc = CONFREJ; - break; - } + LCPDEBUG((LOG_INFO, "(%x %x)", cishort, (unsigned int) cilong)); /* - * Check the reporting period. + * Check the protocol and the reporting period. * XXX When should we Nak this, and what with? */ + if (cishort != PPP_LQR) { + orc = CONFNAK; + PUTCHAR(CI_QUALITY, nakp); + PUTCHAR(CILEN_LQR, nakp); + PUTSHORT(PPP_LQR, nakp); + PUTLONG(ao->lqr_period, nakp); + break; + } break; case CI_MAGICNUMBER: @@ -1157,17 +1312,18 @@ lcp_reqci(f, inp, lenp, reject_if_disagree) break; } GETLONG(cilong, p); - LCPDEBUG((LOG_INFO, "(%lx)", cilong)); + LCPDEBUG((LOG_INFO, "(%x)", (unsigned int) cilong)); /* * He must have a different magic number. */ if (go->neg_magicnumber && cilong == go->magicnumber) { - orc = CONFNAK; - DECPTR(sizeof (long), p); cilong = magic(); /* Don't put magic() inside macro! */ - PUTLONG(cilong, p); + orc = CONFNAK; + PUTCHAR(CI_MAGICNUMBER, nakp); + PUTCHAR(CILEN_LONG, nakp); + PUTLONG(cilong, nakp); break; } ho->neg_magicnumber = 1; @@ -1209,35 +1365,46 @@ endswitch: continue; /* Don't send this one */ if (orc == CONFNAK) { /* Nak this CI? */ - if (reject_if_disagree) /* Getting fed up with sending NAKs? */ + if (reject_if_disagree /* Getting fed up with sending NAKs? */ + && citype != CI_MAGICNUMBER) { orc = CONFREJ; /* Get tough if so */ - else { + } else { if (rc == CONFREJ) /* Rejecting prior CI? */ continue; /* Don't send this one */ - if (rc == CONFACK) { /* Ack'd all prior CIs? */ - rc = CONFNAK; /* Not anymore... */ - ucp = inp; /* Backup */ - } + rc = CONFNAK; } } - if (orc == CONFREJ && /* Reject this CI */ - rc != CONFREJ) { /* but no prior ones? */ + if (orc == CONFREJ) { /* Reject this CI */ rc = CONFREJ; - ucp = inp; /* Backup */ + if (cip != rejp) /* Need to move rejected CI? */ + BCOPY(cip, rejp, cilen); /* Move it */ + INCPTR(cilen, rejp); /* Update output pointer */ } - if (ucp != cip) /* Need to move CI? */ - BCOPY(cip, ucp, cilen); /* Move it */ - INCPTR(cilen, ucp); /* Update output pointer */ } /* * If we wanted to send additional NAKs (for unsent CIs), the - * code would go here. This must be done with care since it might - * require a longer packet than we received. At present there - * are no cases where we want to ask the peer to negotiate an option. + * code would go here. The extra NAKs would go at *nakp. + * At present there are no cases where we want to ask the + * peer to negotiate an option. */ - *lenp = ucp - inp; /* Compute output length */ + switch (rc) { + case CONFACK: + *lenp = next - inp; + break; + case CONFNAK: + /* + * Copy the Nak'd options from the nak_buffer to the caller's buffer. + */ + *lenp = nakp - nak_buffer; + BCOPY(nak_buffer, inp, *lenp); + break; + case CONFREJ: + *lenp = rejp - inp; + break; + } + LCPDEBUG((LOG_INFO, "lcp_reqci: returning CONF%s.", CODENAME(rc))); return (rc); /* Return final code */ } @@ -1268,7 +1435,7 @@ lcp_up(f) * set our MRU to the larger of value we wanted and * the value we got in the negotiation. */ - ppp_send_config(f->unit, MIN(ao->mru, (ho->neg_mru? ho->mru: MTU)), + ppp_send_config(f->unit, MIN(ao->mru, (ho->neg_mru? ho->mru: PPP_MRU)), (ho->neg_asyncmap? ho->asyncmap: 0xffffffff), ho->neg_pcompression, ho->neg_accompression); /* @@ -1276,7 +1443,7 @@ lcp_up(f) * set the receive asyncmap to ffffffff, but we set it to 0 * for backwards contemptibility. */ - ppp_recv_config(f->unit, (go->neg_mru? MAX(wo->mru, go->mru): MTU), + ppp_recv_config(f->unit, (go->neg_mru? MAX(wo->mru, go->mru): PPP_MRU), (go->neg_asyncmap? go->asyncmap: 0x00000000), go->neg_pcompression, go->neg_accompression); @@ -1286,6 +1453,7 @@ lcp_up(f) ChapLowerUp(f->unit); /* Enable CHAP */ upap_lowerup(f->unit); /* Enable UPAP */ ipcp_lowerup(f->unit); /* Enable IPCP */ + ccp_lowerup(f->unit); /* Enable CCP */ lcp_echo_lowerup(f->unit); /* Enable echo messages */ link_established(f->unit); @@ -1302,14 +1470,15 @@ lcp_down(f) fsm *f; { lcp_echo_lowerdown(f->unit); + ccp_lowerdown(f->unit); ipcp_lowerdown(f->unit); ChapLowerDown(f->unit); upap_lowerdown(f->unit); sifdown(f->unit); - ppp_send_config(f->unit, MTU, 0xffffffff, 0, 0); - ppp_recv_config(f->unit, MTU, 0x00000000, 0, 0); - peer_mru[f->unit] = MTU; + 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); } @@ -1350,13 +1519,13 @@ int lcp_printpkt(p, plen, printer, arg) u_char *p; int plen; - void (*printer) __ARGS((void *, char *, ...)); + void (*printer) __P((void *, char *, ...)); void *arg; { int code, id, len, olen; u_char *pstart, *optend; u_short cishort; - u_long cilong; + u_int32_t cilong; if (plen < HEADERLEN) return 0; @@ -1410,10 +1579,10 @@ lcp_printpkt(p, plen, printer, arg) printer(arg, "auth "); GETSHORT(cishort, p); switch (cishort) { - case UPAP: + case PPP_PAP: printer(arg, "upap"); break; - case CHAP: + case PPP_CHAP: printer(arg, "chap"); break; default: @@ -1427,7 +1596,7 @@ lcp_printpkt(p, plen, printer, arg) printer(arg, "quality "); GETSHORT(cishort, p); switch (cishort) { - case LQR: + case PPP_LQR: printer(arg, "lqr"); break; default: @@ -1483,7 +1652,7 @@ void LcpLinkFailure (f) { if (f->state == OPENED) { syslog (LOG_NOTICE, "Excessive lack of response to LCP echo frames."); - lcp_lowerdown(f->unit); /* Reset connection */ + lcp_close(f->unit); /* Reset connection */ } } @@ -1495,43 +1664,36 @@ static void LcpEchoCheck (f) fsm *f; { - u_long delta; + long int delta; #ifdef __linux__ - struct ppp_ddinfo ddinfo; - u_long latest; + struct ppp_idle ddinfo; /* * Read the time since the last packet was received. */ - if (ioctl (fd, PPPIOCGTIME, &ddinfo) < 0) { - syslog (LOG_ERR, "ioctl(PPPIOCGTIME): %m"); + if (ioctl (fd, PPPIOCGIDLE, &ddinfo) < 0) { + syslog (LOG_ERR, "ioctl(PPPIOCGIDLE): %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) { + delta = (long int) lcp_echo_interval - (long int) ddinfo.recv_idle; + if (delta < 0L) { LcpSendEchoRequest (f); - delta = lcp_echo_interval * HZ; + delta = (int) lcp_echo_interval; } - delta /= HZ; #else /* Other implementations do not have ability to find delta */ LcpSendEchoRequest (f); - delta = lcp_echo_interval; + delta = (int) lcp_echo_interval; #endif /* * Start the timer for the next interval. */ assert (lcp_echo_timer_running==0); - TIMEOUT (LcpEchoTimeout, (caddr_t) f, delta); + TIMEOUT (LcpEchoTimeout, (caddr_t) f, (u_int32_t) delta); lcp_echo_timer_running = 1; } @@ -1558,15 +1720,19 @@ lcp_received_echo_reply (f, id, inp, len) fsm *f; int id; u_char *inp; int len; { - u_long magic; + u_int32_t magic; /* Check the magic number - don't count replies from ourselves. */ - if (len < CILEN_LONG) + if (len < 4) { + syslog(LOG_DEBUG, "lcp: received short Echo-Reply, length %d", len); return; + } GETLONG(magic, inp); if (lcp_gotoptions[f->unit].neg_magicnumber - && magic == lcp_gotoptions[f->unit].magicnumber) + && magic == lcp_gotoptions[f->unit].magicnumber) { + syslog(LOG_WARNING, "appear to have received our own echo-reply!"); return; + } /* Reset the number of outstanding echo frames */ lcp_echos_pending = 0; @@ -1580,7 +1746,7 @@ static void LcpSendEchoRequest (f) fsm *f; { - u_long lcp_magic; + u_int32_t lcp_magic; u_char pkt[4], *pktp; /* @@ -1601,7 +1767,7 @@ LcpSendEchoRequest (f) : 0L; pktp = pkt; PUTLONG(lcp_magic, pktp); - + fsm_sdata(f, ECHOREQ, lcp_echo_number++ & 0xFF, pkt, pktp - pkt); } @@ -1621,10 +1787,15 @@ lcp_echo_lowerup (unit) lcp_echos_pending = 0; lcp_echo_number = 0; lcp_echo_timer_running = 0; - + /* 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 } /* @@ -1641,4 +1812,11 @@ 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/usr.sbin/pppd/lcp.h b/usr.sbin/pppd/lcp.h index 0499a7cbd0d2..271ddc5ef3b6 100644 --- a/usr.sbin/pppd/lcp.h +++ b/usr.sbin/pppd/lcp.h @@ -16,7 +16,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: lcp.h,v 1.4 1994/05/24 11:22:28 paulus Exp $ + * $Id: lcp.h,v 1.8 1995/06/12 11:22:47 paulus Exp $ */ /* @@ -55,10 +55,10 @@ typedef struct lcp_options { int neg_lqr : 1; /* Negotiate use of Link Quality Reports */ u_short mru; /* Value of MRU */ u_char chap_mdtype; /* which MD type (hashing algorithm) */ - u_long asyncmap; /* Value of async map */ - u_long magicnumber; + u_int32_t asyncmap; /* Value of async map */ + u_int32_t magicnumber; int numloops; /* Number of loops during magic number neg. */ - u_long lqr_period; /* Reporting period for link quality */ + u_int32_t lqr_period; /* Reporting period for LQR 1/100ths second */ } lcp_options; extern fsm lcp_fsm[]; @@ -66,22 +66,23 @@ extern lcp_options lcp_wantoptions[]; extern lcp_options lcp_gotoptions[]; extern lcp_options lcp_allowoptions[]; extern lcp_options lcp_hisoptions[]; -extern u_long xmit_accm[][8]; +extern u_int32_t xmit_accm[][8]; #define DEFMRU 1500 /* Try for this */ #define MINMRU 128 /* No MRUs below this */ #define MAXMRU 16384 /* Normally limit MRU to this */ -void lcp_init __ARGS((int)); -void lcp_open __ARGS((int)); -void lcp_close __ARGS((int)); -void lcp_lowerup __ARGS((int)); -void lcp_lowerdown __ARGS((int)); -void lcp_input __ARGS((int, u_char *, int)); -void lcp_protrej __ARGS((int)); -void lcp_sprotrej __ARGS((int, u_char *, int)); -int lcp_printpkt __ARGS((u_char *, int, - void (*) __ARGS((void *, char *, ...)), void *)); +void lcp_init __P((int)); +void lcp_open __P((int)); +void lcp_close __P((int)); +void lcp_lowerup __P((int)); +void lcp_lowerdown __P((int)); +void lcp_input __P((int, u_char *, int)); +void lcp_protrej __P((int)); +void lcp_sprotrej __P((int, u_char *, int)); +int lcp_printpkt __P((u_char *, int, + void (*) __P((void *, char *, ...)), void *)); -extern int lcp_warnloops; /* Warn about a loopback this often */ -#define DEFWARNLOOPS 10 /* Default value for above */ +/* Default number of times we receive our magic number from the peer + before deciding the link is looped-back. */ +#define DEFLOOPBACKFAIL 5 diff --git a/usr.sbin/pppd/magic.c b/usr.sbin/pppd/magic.c index 20dfd6fe3a48..4797f0b19fd6 100644 --- a/usr.sbin/pppd/magic.c +++ b/usr.sbin/pppd/magic.c @@ -18,53 +18,73 @@ */ #ifndef lint -static char rcsid[] = "$Id: magic.c,v 1.1 1993/11/11 03:54:25 paulus Exp $"; +static char rcsid[] = "$Id: magic.c,v 1.5 1995/06/06 01:52:25 paulus Exp $"; #endif #include <stdio.h> #include <sys/types.h> #include <sys/time.h> +#include "pppd.h" #include "magic.h" +static u_int32_t next; /* Next value to return */ -static u_long next; /* Next value to return */ - -extern u_long gethostid __ARGS((void)); -extern long random __ARGS((void)); -extern void srandom __ARGS((int)); +extern int gethostid __P((void)); +extern long mrand48 __P((void)); +extern void srand48 __P((long)); /* * magic_init - Initialize the magic number generator. * - * Computes first magic number and seed for random number generator. * Attempts to compute a random number seed which will not repeat. - * The current method uses the current hostid and current time. + * The current method uses the current hostid, current process ID + * and current time, currently. */ -void magic_init() +void +magic_init() { - struct timeval tv; - - next = gethostid(); - if (gettimeofday(&tv, NULL)) { - perror("gettimeofday"); - exit(1); - } - next ^= (u_long) tv.tv_sec ^ (u_long) tv.tv_usec; + long seed; + struct timeval t; - srandom((int) next); + gettimeofday(&t, NULL); + seed = gethostid() ^ t.tv_sec ^ t.tv_usec ^ getpid(); + srand48(seed); } - /* * magic - Returns the next magic number. */ -u_long magic() +u_int32_t +magic() +{ + return (u_int32_t) mrand48(); +} + +#ifdef NO_DRAND48 +/* + * Substitute procedures for those systems which don't have + * drand48 et al. + */ + +double +drand48() +{ + return (double)random() / (double)0x7fffffffL; /* 2**31-1 */ +} + +long +mrand48() { - u_long m; + return random(); +} - m = next; - next = (u_long) random(); - return (m); +void +srand48(seedval) +long seedval; +{ + srandom((int)seedval); } + +#endif diff --git a/usr.sbin/pppd/magic.h b/usr.sbin/pppd/magic.h index d41aa39df7db..a118ca1afb9c 100644 --- a/usr.sbin/pppd/magic.h +++ b/usr.sbin/pppd/magic.h @@ -16,9 +16,8 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: magic.h,v 1.1 1993/11/11 03:54:25 paulus Exp $ + * $Id: magic.h,v 1.3 1994/09/21 06:47:37 paulus Exp $ */ -#include "args.h" -void magic_init __ARGS((void)); /* Initialize the magic number generator */ -u_long magic __ARGS((void)); /* Returns the next magic number */ +void magic_init __P((void)); /* Initialize the magic number generator */ +u_int32_t magic __P((void)); /* Returns the next magic number */ diff --git a/usr.sbin/pppd/main.c b/usr.sbin/pppd/main.c index 946e4d1d26b2..332195997bfa 100644 --- a/usr.sbin/pppd/main.c +++ b/usr.sbin/pppd/main.c @@ -18,158 +18,108 @@ */ #ifndef lint -static char rcsid[] = "$Id: main.c,v 1.3 1995/04/29 13:55:34 ache Exp $"; +static char rcsid[] = "$Id: main.c,v 1.27 1995/08/16 01:39:08 paulus Exp $"; #endif -#define SETSID - #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <signal.h> -#include <unistd.h> #include <errno.h> #include <fcntl.h> #include <syslog.h> #include <netdb.h> #include <utmp.h> #include <pwd.h> -#include <sys/wait.h> - -/* - * If REQ_SYSOPTIONS is defined to 1, pppd will not run unless - * /etc/ppp/options exists. - */ -#ifndef REQ_SYSOPTIONS -#define REQ_SYSOPTIONS 1 -#endif - -#ifdef SGTTY -#include <sgtty.h> -#else -#ifndef sun -#include <sys/ioctl.h> -#endif -#include <termios.h> -#endif - #include <sys/param.h> #include <sys/types.h> +#include <sys/wait.h> +#include <sys/time.h> +#include <sys/resource.h> #include <sys/stat.h> #include <sys/socket.h> -#include <sys/time.h> +#include <sys/ioctl.h> #include <net/if.h> -#include "callout.h" -#include "ppp.h" +#include "pppd.h" #include "magic.h" #include "fsm.h" #include "lcp.h" #include "ipcp.h" #include "upap.h" #include "chap.h" - -#include "pppd.h" +#include "ccp.h" #include "pathnames.h" #include "patchlevel.h" - -#ifndef TRUE -#define TRUE (1) -#endif /*TRUE*/ - -#ifndef FALSE -#define FALSE (0) -#endif /*FALSE*/ - -#ifdef PIDPATH -static char *pidpath = PIDPATH; /* filename in which pid will be stored */ -#else -static char *pidpath = _PATH_PIDFILE; -#endif /* PIDFILE */ +/* + * If REQ_SYSOPTIONS is defined to 1, pppd will not run unless + * /etc/ppp/options exists. + */ +#ifndef REQ_SYSOPTIONS +#define REQ_SYSOPTIONS 1 +#endif /* interface vars */ char ifname[IFNAMSIZ]; /* Interface name */ int ifunit; /* Interface unit number */ char *progname; /* Name of this program */ -char *username; char hostname[MAXNAMELEN]; /* Our hostname */ -char our_name[MAXNAMELEN]; -char remote_name[MAXNAMELEN]; -static char pidfilename[MAXPATHLEN]; - +static char pidfilename[MAXPATHLEN]; /* name of pid file */ +static char default_devnam[MAXPATHLEN]; /* name of default device */ static pid_t pid; /* Our pid */ static pid_t pgrpid; /* Process Group ID */ -uid_t uid; /* Our real user-id */ -gid_t gid; - -char devname[MAXPATHLEN] = "/dev/tty"; /* Device name */ -int default_device = TRUE; /* use default device (stdin/out) */ +static uid_t uid; /* Our real user-id */ int fd = -1; /* Device file descriptor */ -int s; /* Socket file descriptor */ int phase; /* where the link is at */ - -#ifdef SGTTY -static struct sgttyb initsgttyb; /* Initial TTY sgttyb */ -#else -static struct termios inittermios; /* Initial TTY termios */ -#endif +int kill_link; +int open_ccp_flag; static int initfdflags = -1; /* Initial file descriptor flags */ -static int restore_term; /* 1 => we've munged the terminal */ - -u_char outpacket_buf[MTU+DLLHEADERLEN]; /* buffer for outgoing packet */ -static u_char inpacket_buf[MTU+DLLHEADERLEN]; /* buffer for incoming packet */ +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 */ int hungup; /* terminal has been hung up */ static int n_children; /* # child processes still running */ -/* configured variables */ - -int debug = 0; /* Debug flag */ -int kdebugflag = 0; /* Kernel debugging flag */ -char user[MAXNAMELEN]; /* username for PAP */ -char passwd[MAXSECRETLEN]; /* password for PAP */ -char *connector = NULL; /* "connect" command */ -char *disconnector = NULL; /* "disconnect" command */ -int inspeed = 0; /* Input/Output speed requested */ -int baud_rate; /* bits/sec currently used */ -u_long netmask = 0; /* netmask to use on ppp interface */ -int crtscts = 0; /* use h/w flow control */ -int nodetach = 0; /* don't fork */ -int modem = 0; /* use modem control lines */ -int auth_required = 0; /* require peer to authenticate */ -int defaultroute = 0; /* assign default route through interface */ -int proxyarp = 0; /* set entry in arp table */ -int persist = 0; /* re-initiate on termination */ -int answer = 0; /* wait for incoming call */ -int uselogin = 0; /* check PAP info against /etc/passwd */ -int lockflag = 0; /* lock the serial device */ +int baud_rate; +char *no_ppp_msg = "Sorry - this system lacks PPP kernel support\n"; /* prototypes */ -static void hup __ARGS((int)); -static void intr __ARGS((int)); -static void term __ARGS((int)); -static void alrm __ARGS((int)); -static void io __ARGS((int)); -static void chld __ARGS((int)); -static void incdebug __ARGS((int)); -static void nodebug __ARGS((int)); -void establish_ppp __ARGS((void)); - -void reap_kids __ARGS((void)); -void cleanup __ARGS((int, caddr_t)); -void die __ARGS((int)); -void novm __ARGS((char *)); - -void log_packet __ARGS((u_char *, int, char *)); -void format_packet __ARGS((u_char *, int, +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 bad_signal __P((int)); + +static void get_input __P((void)); +void establish_ppp __P((void)); +void calltimeout __P((void)); +struct timeval *timeleft __P((struct timeval *)); +void reap_kids __P((void)); +void cleanup __P((int, caddr_t)); +void close_fd __P((void)); +void die __P((int)); +void novm __P((char *)); + +void log_packet __P((u_char *, int, char *)); +void format_packet __P((u_char *, int, void (*) (void *, char *, ...), void *)); -void pr_log __ARGS((void *, char *, ...)); +void pr_log __P((void *, char *, ...)); + +extern char *ttyname __P((int)); +extern char *getlogin __P((void)); + +#ifdef ultrix +#undef O_NONBLOCK +#define O_NONBLOCK O_NDELAY +#endif /* * PPP Data Link Layer "protocol" table. @@ -181,12 +131,19 @@ static struct protent { void (*input)(); void (*protrej)(); int (*printpkt)(); + void (*datainput)(); char *name; } prottbl[] = { - { LCP, lcp_init, lcp_input, lcp_protrej, lcp_printpkt, "LCP" }, - { IPCP, ipcp_init, ipcp_input, ipcp_protrej, ipcp_printpkt, "IPCP" }, - { UPAP, upap_init, upap_input, upap_protrej, upap_printpkt, "PAP" }, - { CHAP, ChapInit, ChapInput, ChapProtocolReject, ChapPrintPkt, "CHAP" }, + { PPP_LCP, lcp_init, lcp_input, lcp_protrej, + lcp_printpkt, NULL, "LCP" }, + { PPP_IPCP, ipcp_init, ipcp_input, ipcp_protrej, + ipcp_printpkt, NULL, "IPCP" }, + { PPP_PAP, upap_init, upap_input, upap_protrej, + upap_printpkt, NULL, "PAP" }, + { PPP_CHAP, ChapInit, ChapInput, ChapProtocolReject, + ChapPrintPkt, NULL, "CHAP" }, + { PPP_CCP, ccp_init, ccp_input, ccp_protrej, + ccp_printpkt, ccp_datainput, "CCP" }, }; #define N_PROTO (sizeof(prottbl) / sizeof(prottbl[0])) @@ -195,16 +152,19 @@ main(argc, argv) int argc; char *argv[]; { - int mask, i; + int i, nonblock; struct sigaction sa; struct cmd *cmdp; FILE *pidfile; char *p; struct passwd *pw; + struct timeval timo; + sigset_t mask; p = ttyname(0); if (p) - strcpy(devname, p); + strcpy(devnam, p); + strcpy(default_devnam, devnam); if (gethostname(hostname, MAXNAMELEN) < 0 ) { perror("couldn't get hostname"); @@ -212,12 +172,10 @@ main(argc, argv) } hostname[MAXNAMELEN-1] = 0; - pid = getpid(); uid = getuid(); - gid = getgid(); if (!ppp_available()) { - fprintf(stderr, "Sorry - PPP is not available on this system\n"); + fprintf(stderr, no_ppp_msg); exit(1); } @@ -228,7 +186,7 @@ main(argc, argv) */ for (i = 0; i < N_PROTO; i++) (*prottbl[i].init)(0); - + progname = *argv; if (!options_from_file(_PATH_SYSOPTIONS, REQ_SYSOPTIONS, 0) || @@ -240,89 +198,38 @@ main(argc, argv) setipdefault(); /* - * Initialize syslog system and magic number package. + * If the user has specified the default device name explicitly, + * pretend they hadn't. */ -#if !defined(ultrix) - openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP); - setlogmask(LOG_UPTO(LOG_INFO)); -#else - openlog("pppd", LOG_PID); -#define LOG_UPTO(x) (x) -#define setlogmask(x) (x) -#endif - if (debug) - setlogmask(LOG_UPTO(LOG_DEBUG)); + if (!default_device && strcmp(devnam, default_devnam) == 0) + default_device = 1; + /* + * Initialize system-dependent stuff and magic number package. + */ + sys_init(); magic_init(); - username = getlogin(); - if (username == NULL) { + /* + * Detach ourselves from the terminal, if required, + * and identify who is running us. + */ + if (!default_device && !nodetach && daemon(0, 0) < 0) { + perror("Couldn't detach from controlling terminal"); + exit(1); + } + pid = getpid(); + p = getlogin(); + if (p == NULL) { pw = getpwuid(uid); if (pw != NULL && pw->pw_name != NULL) - username = pw->pw_name; + p = pw->pw_name; else - username = "(unknown)"; + p = "(unknown)"; } syslog(LOG_NOTICE, "pppd %s.%d started by %s, uid %d", - VERSION, PATCHLEVEL, username, uid); - -#ifdef SETSID - /* - * Make sure we can set the serial device to be our controlling terminal. - */ - if (default_device) { - /* - * No device name was specified: - * we are in the device's session already. - */ - if ((pgrpid = getpgrp()) < 0) { - syslog(LOG_ERR, "getpgrp(): %m"); - die(1); - } - - } else { - /* - * Not default device: make sure we're not a process group leader, - * then become session leader of a new session (so we can make - * our device its controlling terminal and thus get SIGHUPs). - */ - if (!nodetach) { - /* fork so we're not a process group leader */ - if (pid = fork()) { - exit(0); /* parent is finished */ - } - if (pid < 0) { - syslog(LOG_ERR, "fork: %m"); - die(1); - } - pid = getpid(); /* otherwise pid is 0 in child */ - } else { - /* - * try to put ourself into our parent's process group, - * so we're not a process group leader - */ - if (setpgrp(pid, getppid()) < 0) - syslog(LOG_WARNING, "setpgrp: %m"); - } - - /* create new session */ - if ((pgrpid = setsid()) < 0) { - syslog(LOG_ERR, "setsid(): %m"); - die(1); - } - } -#endif - - if (lockflag && !default_device) - if (lock(devname) < 0) - die(1); - - /* Get an internet socket for doing socket ioctl's on. */ - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - syslog(LOG_ERR, "socket : %m"); - die(1); - } - + VERSION, PATCHLEVEL, p, uid); + /* * Compute mask of all interesting signals and install signal handlers * for each. Only one signal handler may be active at a time. Therefore, @@ -331,17 +238,13 @@ main(argc, argv) sigemptyset(&mask); sigaddset(&mask, SIGHUP); sigaddset(&mask, SIGINT); - sigaddset(&mask, SIGALRM); - sigaddset(&mask, SIGIO); + sigaddset(&mask, SIGTERM); sigaddset(&mask, SIGCHLD); -#ifdef STREAMS - sigaddset(&mask, SIGPOLL); -#endif #define SIGNAL(s, handler) { \ sa.sa_handler = handler; \ if (sigaction(s, &sa, NULL) < 0) { \ - syslog(LOG_ERR, "sigaction(%d): %m", s); \ + syslog(LOG_ERR, "Couldn't establish signal handler (%d): %m", s); \ die(1); \ } \ } @@ -349,393 +252,305 @@ main(argc, argv) sa.sa_mask = mask; sa.sa_flags = 0; SIGNAL(SIGHUP, hup); /* Hangup */ - SIGNAL(SIGINT, intr); /* Interrupt */ + SIGNAL(SIGINT, term); /* Interrupt */ SIGNAL(SIGTERM, term); /* Terminate */ - SIGNAL(SIGALRM, alrm); /* Timeout */ - SIGNAL(SIGIO, io); /* Input available */ - SIGNAL(SIGCHLD, chld); /* Death of child process */ -#ifdef STREAMS - SIGNAL(SIGPOLL, io); /* Input available */ -#endif + SIGNAL(SIGCHLD, chld); - signal(SIGUSR1, incdebug); /* Increment debug flag */ - signal(SIGUSR2, nodebug); /* Reset debug flag */ + SIGNAL(SIGUSR1, toggle_debug); /* Toggle debug flag */ + SIGNAL(SIGUSR2, open_ccp); /* Reopen CCP */ /* - * Block SIGIOs and SIGPOLLs for now + * Install a handler for other signals which would otherwise + * cause pppd to exit without cleaning up. */ - sigemptyset(&mask); - sigaddset(&mask, SIGIO); -#ifdef STREAMS - sigaddset(&mask, SIGPOLL); + SIGNAL(SIGABRT, bad_signal); + SIGNAL(SIGALRM, bad_signal); + SIGNAL(SIGFPE, bad_signal); + SIGNAL(SIGILL, bad_signal); + SIGNAL(SIGPIPE, bad_signal); + SIGNAL(SIGQUIT, bad_signal); + SIGNAL(SIGSEGV, bad_signal); +#ifdef SIGBUS + SIGNAL(SIGBUS, bad_signal); +#endif +#ifdef SIGEMT + SIGNAL(SIGEMT, bad_signal); +#endif +#ifdef SIGPOLL + SIGNAL(SIGPOLL, bad_signal); +#endif +#ifdef SIGPROF + SIGNAL(SIGPROF, bad_signal); +#endif +#ifdef SIGSYS + SIGNAL(SIGSYS, bad_signal); +#endif +#ifdef SIGTRAP + SIGNAL(SIGTRAP, bad_signal); +#endif +#ifdef SIGVTALRM + SIGNAL(SIGVTALRM, bad_signal); +#endif +#ifdef SIGXCPU + SIGNAL(SIGXCPU, bad_signal); +#endif +#ifdef SIGXFSZ + SIGNAL(SIGXFSZ, bad_signal); #endif - sigprocmask(SIG_BLOCK, &mask, NULL); /* - * Open the serial device and set it up to be the ppp interface. + * Lock the device if we've been asked to. */ - if ((fd = open(devname, O_RDWR /*| O_NDELAY*/)) < 0) { - syslog(LOG_ERR, "open(%s): %m", devname); - die(1); - } - hungup = 0; - -#ifdef TIOCSCTTY - /* set device to be controlling tty */ - if (!default_device && ioctl(fd, TIOCSCTTY) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSCTTY): %m"); - die(1); - } -#endif /* TIOCSCTTY */ - - /* run connection script */ - if (connector) { - MAINDEBUG((LOG_INFO, "Connecting with <%s>", connector)); + if (lockflag && !default_device) + if (lock(devnam) < 0) + die(1); - /* set line speed, flow control, etc.; set CLOCAL for now */ - set_up_tty(fd, 1); + do { - /* drop dtr to hang up in case modem is off hook */ - if (!default_device && modem) { - setdtr(fd, FALSE); - sleep(1); - setdtr(fd, TRUE); + /* + * Open the serial device and set it up to be the ppp interface. + * If we're dialling out, or we don't want to use the modem lines, + * we open it in non-blocking mode, but then we need to clear + * the non-blocking I/O bit. + */ + 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); } - - if (device_script(connector, fd, fd) < 0) { - syslog(LOG_ERR, "could not set up connection"); - setdtr(fd, FALSE); + if ((initfdflags = fcntl(fd, F_GETFL)) == -1) { + syslog(LOG_ERR, "Couldn't get device fd flags: %m"); die(1); } + if (nonblock) { + initfdflags &= ~O_NONBLOCK; + fcntl(fd, F_SETFL, initfdflags); + } + hungup = 0; + kill_link = 0; - syslog(LOG_INFO, "Connected..."); - sleep(1); /* give it time to set up its terminal */ - } + if (!default_device) + setsid(); - /* set line speed, flow control, etc.; clear CLOCAL if modem option */ - set_up_tty(fd, 0); + /* run connection script */ + if (connector && connector[0]) { + MAINDEBUG((LOG_INFO, "Connecting with <%s>", connector)); - /* set up the serial device as a ppp interface */ - establish_ppp(); + /* set line speed, flow control, etc.; set CLOCAL for now */ + set_up_tty(fd, 1); - syslog(LOG_INFO, "Using interface ppp%d", ifunit); - (void) sprintf(ifname, "ppp%d", ifunit); + /* drop dtr to hang up in case modem is off hook */ + if (!default_device && modem) { + setdtr(fd, FALSE); + sleep(1); + setdtr(fd, TRUE); + } - /* write pid to file */ - (void) sprintf(pidfilename, "%s/%s.pid", pidpath, ifname); - if ((pidfile = fopen(pidfilename, "w")) != NULL) { - fprintf(pidfile, "%d\n", pid); - (void) fclose(pidfile); - } else { - syslog(LOG_ERR, "unable to create pid file: %m"); - pidfilename[0] = 0; - } + if (device_script(connector, fd, fd) < 0) { + syslog(LOG_ERR, "Connect script failed"); + setdtr(fd, FALSE); + die(1); + } - /* - * Set process group of device to our process group so we can get - * SIGIOs and SIGHUPs. - */ -#ifdef SETSID - if (default_device) { - int id = tcgetpgrp(fd); - if (id != pgrpid) { - syslog(LOG_WARNING, "warning: not in tty's process group"); + syslog(LOG_INFO, "Serial connection established."); + sleep(1); /* give it time to set up its terminal */ } - } else { - if (tcsetpgrp(fd, pgrpid) < 0) { - syslog(LOG_ERR, "tcsetpgrp(): %m"); + + /* set line speed, flow control, etc.; clear CLOCAL if modem option */ + set_up_tty(fd, 0); + + /* attach to the controlling tty for signals */ + if (!default_device && ioctl(fd, TIOCSCTTY) < 0) { + syslog(LOG_ERR, "ioctl(TIOCSCTTY) : %m"); die(1); } - } -#else - /* set process group on tty so we get SIGIO's */ - if (ioctl(fd, TIOCSPGRP, &pgrpid) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSPGRP): %m"); - die(1); - } -#endif - /* - * Record initial device flags, then set device to cause SIGIO - * signals to be generated. - */ - if ((initfdflags = fcntl(fd, F_GETFL)) == -1) { - syslog(LOG_ERR, "fcntl(F_GETFL): %m"); - die(1); - } + /* set up the serial device as a ppp interface */ + establish_ppp(); -#ifdef _linux_ /* This is a kludge for Linux. FIXME !!! -- later. */ -#undef FASYNC -#define FASYNC 0 -#endif + syslog(LOG_INFO, "Using interface ppp%d", ifunit); + (void) sprintf(ifname, "ppp%d", ifunit); - if (fcntl(fd, F_SETFL, FNDELAY | FASYNC) == -1) { - syslog(LOG_ERR, "fcntl(F_SETFL, FNDELAY | FASYNC): %m"); - die(1); - } - - /* - * Block all signals, start opening the connection, and wait for - * incoming signals (reply, timeout, etc.). - */ - syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devname); - sigprocmask(SIG_BLOCK, &mask, NULL); /* Block signals now */ - lcp_lowerup(0); /* XXX Well, sort of... */ - lcp_open(0); /* Start protocol */ - for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) - sigpause(0); /* Wait for next signal */ + /* 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; + } - /* - * Run disconnector script, if requested - */ - if (disconnector) { - if (device_script(disconnector, fd, fd) < 0) { - syslog(LOG_WARNING, "disconnect script failed"); + /* + * Set device for non-blocking reads. + */ + if (fcntl(fd, F_SETFL, initfdflags | O_NONBLOCK) == -1) { + syslog(LOG_ERR, "Couldn't set device to non-blocking mode: %m"); die(1); } + + /* + * Block all signals, start opening the connection, and wait for + * incoming events (reply, timeout, etc.). + */ + syslog(LOG_NOTICE, "Connect: %s <--> %s", ifname, devnam); + lcp_lowerup(0); + lcp_open(0); /* Start protocol */ + for (phase = PHASE_ESTABLISH; phase != PHASE_DEAD; ) { + wait_input(timeleft(&timo)); + calltimeout(); + get_input(); + if (kill_link) { + lcp_close(0); + kill_link = 0; + } + if (open_ccp_flag) { + if (phase == PHASE_NETWORK) { + ccp_fsm[0].flags = OPT_RESTART; /* clears OPT_SILENT */ + ccp_open(0); + } + open_ccp_flag = 0; + } + reap_kids(); /* Don't leave dead kids lying around */ + } - syslog(LOG_INFO, "Disconnected..."); - } - - quit(); -} + /* + * 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) { + set_up_tty(fd, 1); + if (device_script(disconnector, fd, fd) < 0) { + syslog(LOG_WARNING, "disconnect script failed"); + } else { + syslog(LOG_INFO, "Serial link disconnected."); + } + } -#if B9600 == 9600 -/* - * XXX assume speed_t values numerically equal bits per second - * (so we can ask for any speed). - */ -#define translate_speed(bps) (bps) -#define baud_rate_of(speed) (speed) + close_fd(); + if (unlink(pidfilename) < 0 && errno != ENOENT) + syslog(LOG_WARNING, "unable to delete pid file: %m"); + pidfilename[0] = 0; -#else -/* - * List of valid speeds. - */ -struct speed { - int speed_int, speed_val; -} speeds[] = { -#ifdef B50 - { 50, B50 }, -#endif -#ifdef B75 - { 75, B75 }, -#endif -#ifdef B110 - { 110, B110 }, -#endif -#ifdef B134 - { 134, B134 }, -#endif -#ifdef B150 - { 150, B150 }, -#endif -#ifdef B200 - { 200, B200 }, -#endif -#ifdef B300 - { 300, B300 }, -#endif -#ifdef B600 - { 600, B600 }, -#endif -#ifdef B1200 - { 1200, B1200 }, -#endif -#ifdef B1800 - { 1800, B1800 }, -#endif -#ifdef B2000 - { 2000, B2000 }, -#endif -#ifdef B2400 - { 2400, B2400 }, -#endif -#ifdef B3600 - { 3600, B3600 }, -#endif -#ifdef B4800 - { 4800, B4800 }, -#endif -#ifdef B7200 - { 7200, B7200 }, -#endif -#ifdef B9600 - { 9600, B9600 }, -#endif -#ifdef B19200 - { 19200, B19200 }, -#endif -#ifdef B38400 - { 38400, B38400 }, -#endif -#ifdef EXTA - { 19200, EXTA }, -#endif -#ifdef EXTB - { 38400, EXTB }, -#endif -#ifdef B57600 - { 57600, B57600 }, -#endif -#ifdef B115200 - { 115200, B115200 }, -#endif - { 0, 0 } -}; + } while (persist); -/* - * Translate from bits/second to a speed_t. - */ -int -translate_speed(bps) - int bps; -{ - struct speed *speedp; - - if (bps == 0) - return 0; - for (speedp = speeds; speedp->speed_int; speedp++) - if (bps == speedp->speed_int) - return speedp->speed_val; - syslog(LOG_WARNING, "speed %d not supported", bps); - return 0; + die(0); } -/* - * Translate from a speed_t to bits/second. - */ -int -baud_rate_of(speed) - int speed; -{ - struct speed *speedp; - - if (speed == 0) - return 0; - for (speedp = speeds; speedp->speed_int; speedp++) - if (speed == speedp->speed_val) - return speedp->speed_int; - return 0; -} -#endif /* - * 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 - * regardless of whether the modem option was specified. + * get_input - called when incoming data is available. */ -set_up_tty(fd, local) - int fd, local; +static void +get_input() { -#ifndef SGTTY - int speed, x; - struct termios tios; + int len, i; + u_char *p; + u_short protocol; - if (tcgetattr(fd, &tios) < 0) { - syslog(LOG_ERR, "tcgetattr: %m"); - die(1); - } + p = inpacket_buf; /* point to beginning of packet buffer */ - if (!restore_term) - inittermios = tios; - -#ifdef CRTSCTS - tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL | CRTSCTS); - if (crtscts == 1) - tios.c_cflag |= CRTSCTS; -#else - tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL); -#endif /* CRTSCTS */ - - tios.c_cflag |= CS8 | CREAD | HUPCL; - if (local || !modem) - tios.c_cflag |= CLOCAL; - tios.c_iflag = IGNBRK | IGNPAR; - tios.c_oflag = 0; - tios.c_lflag = 0; - tios.c_cc[VMIN] = 1; - tios.c_cc[VTIME] = 0; - - if (crtscts == 2) { - tios.c_iflag |= IXOFF; - tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */ - tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */ - } + len = read_packet(inpacket_buf); + if (len < 0) + return; - speed = translate_speed(inspeed); - if (speed) { - cfsetospeed(&tios, speed); - cfsetispeed(&tios, speed); - } else { - speed = cfgetospeed(&tios); + if (len == 0) { + syslog(LOG_NOTICE, "Modem hangup"); + hungup = 1; + lcp_lowerdown(0); /* serial link is no longer available */ + phase = PHASE_DEAD; + return; } - if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { - syslog(LOG_ERR, "tcsetattr: %m"); - die(1); - } + if (debug /*&& (debugflags & DBG_INPACKET)*/) + log_packet(p, len, "rcvd "); -#ifdef ultrix - x = 0; - if (ioctl(fd, (crtscts || modem)? TIOCMODEM: TIOCNMODEM, &x) < 0) - syslog(LOG_WARNING, "TIOC(N)MODEM: %m"); - if (ioctl(fd, (local || !modem)? TIOCNCAR: TIOCCAR) < 0) - syslog(LOG_WARNING, "TIOC(N)CAR: %m"); -#endif + if (len < PPP_HDRLEN) { + MAINDEBUG((LOG_INFO, "io(): Received short packet.")); + return; + } -#else /* SGTTY */ - int speed; - struct sgttyb sgttyb; + p += 2; /* Skip address and control */ + GETSHORT(protocol, p); + len -= PPP_HDRLEN; /* - * Put the tty in raw mode. + * Toss all non-LCP packets unless LCP is OPEN. */ - if (ioctl(fd, TIOCGETP, &sgttyb) < 0) { - syslog(LOG_ERR, "ioctl(TIOCGETP): %m"); - die(1); + if (protocol != PPP_LCP && lcp_fsm[0].state != OPENED) { + MAINDEBUG((LOG_INFO, + "io(): Received non-LCP packet when LCP not open.")); + return; } - if (!restore_term) - initsgttyb = sgttyb; - - sgttyb.sg_flags = RAW | ANYP; - speed = translate_speed(inspeed); - if (speed) - sgttyb.sg_ispeed = speed; - else - speed = sgttyb.sg_ispeed; - - if (ioctl(fd, TIOCSETP, &sgttyb) < 0) { - syslog(LOG_ERR, "ioctl(TIOCSETP): %m"); - die(1); + /* + * Upcall the proper protocol input routine. + */ + for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++) { + if (prottbl[i].protocol == protocol) { + (*prottbl[i].input)(0, p, len); + return; + } + if (protocol == (prottbl[i].protocol & ~0x8000) + && prottbl[i].datainput != NULL) { + (*prottbl[i].datainput)(0, p, len); + return; + } } -#endif - baud_rate = baud_rate_of(speed); - restore_term = TRUE; + if (debug) + syslog(LOG_WARNING, "Unknown protocol (0x%x) received", protocol); + lcp_sprotrej(0, p - PPP_HDRLEN, len + PPP_HDRLEN); } + /* - * setdtr - control the DTR line on the serial port. - * This is called from die(), so it shouldn't call die(). + * demuxprotrej - Demultiplex a Protocol-Reject. */ -setdtr(fd, on) -int fd, on; +void +demuxprotrej(unit, protocol) + int unit; + u_short protocol; { - int modembits = TIOCM_DTR; + int i; - ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits); + /* + * Upcall the proper Protocol-Reject routine. + */ + for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++) + if (prottbl[i].protocol == protocol) { + (*prottbl[i].protrej)(unit); + return; + } + + syslog(LOG_WARNING, + "demuxprotrej: Unrecognized Protocol-Reject for protocol 0x%x", + protocol); } /* - * quit - Clean up state and exit. + * bad_signal - We've caught a fatal signal. Clean up state and exit. */ -void +static void +bad_signal(sig) + int sig; +{ + syslog(LOG_ERR, "Fatal signal %d", sig); + die(1); +} + +/* + * quit - Clean up state and exit (with an error indication). + */ +void quit() { - die(0); + die(1); } /* @@ -759,42 +574,49 @@ cleanup(status, arg) int status; caddr_t arg; { - if (fd >= 0) { - /* drop dtr to hang up */ - if (modem) - setdtr(fd, FALSE); + if (fd >= 0) + close_fd(); - if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0) - syslog(LOG_WARNING, "fcntl(F_SETFL, fdflags): %m"); - initfdflags = -1; + if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT) + syslog(LOG_WARNING, "unable to delete pid file: %m"); + pidfilename[0] = 0; - disestablish_ppp(); + if (lockflag && !default_device) + unlock(); +} - if (restore_term) { -#ifndef SGTTY - if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) - syslog(LOG_WARNING, "tcsetattr: %m"); -#else - if (ioctl(fd, TIOCSETP, &initsgttyb) < 0) - syslog(LOG_WARNING, "ioctl(TIOCSETP): %m"); -#endif - } +/* + * close_fd - restore the terminal device and close it. + */ +void +close_fd() +{ + disestablish_ppp(); - close(fd); - fd = -1; - } + /* drop dtr to hang up */ + if (modem) + setdtr(fd, FALSE); - if (pidfilename[0] != 0 && unlink(pidfilename) < 0) - syslog(LOG_WARNING, "unable to unlink pid file: %m"); - pidfilename[0] = 0; + if (initfdflags != -1 && fcntl(fd, F_SETFL, initfdflags) < 0) + syslog(LOG_WARNING, "Couldn't restore device fd flags: %m"); + initfdflags = -1; - if (lockflag && !default_device) - unlock(); + restore_tty(); + + close(fd); + fd = -1; } -static struct callout *callout = NULL; /* Callout list */ -static struct timeval schedtime; /* Time last timeout was set */ +struct callout { + struct timeval c_time; /* time at which to call routine */ + caddr_t c_arg; /* argument to routine */ + void (*c_func)(); /* routine */ + struct callout *c_next; +}; + +static struct callout *callout = NULL; /* Callout list */ +static struct timeval timenow; /* Current time */ /* * timeout - Schedule a timeout. @@ -808,12 +630,11 @@ timeout(func, arg, time) caddr_t arg; int time; { - struct itimerval itv; - struct callout *newp, **oldpp; - - MAINDEBUG((LOG_DEBUG, "Timeout %x:%x in %d seconds.", - (int) func, (int) arg, time)); - + struct callout *newp, *p, **pp; + + MAINDEBUG((LOG_DEBUG, "Timeout %lx:%lx in %d seconds.", + (long) func, (long) arg, time)); + /* * Allocate timeout. */ @@ -823,40 +644,20 @@ timeout(func, arg, time) } newp->c_arg = arg; newp->c_func = func; - - /* - * Find correct place to link it in and decrement its time by the - * amount of time used by preceding timeouts. - */ - for (oldpp = &callout; - *oldpp && (*oldpp)->c_time <= time; - oldpp = &(*oldpp)->c_next) - time -= (*oldpp)->c_time; - newp->c_time = time; - newp->c_next = *oldpp; - if (*oldpp) - (*oldpp)->c_time -= time; - *oldpp = newp; - + gettimeofday(&timenow, NULL); + newp->c_time.tv_sec = timenow.tv_sec + time; + newp->c_time.tv_usec = timenow.tv_usec; + /* - * If this is now the first callout then we have to set a new - * itimer. + * Find correct place and link it in. */ - if (callout == newp) { - itv.it_interval.tv_sec = itv.it_interval.tv_usec = - itv.it_value.tv_usec = 0; - itv.it_value.tv_sec = callout->c_time; - MAINDEBUG((LOG_DEBUG, "Setting itimer for %d seconds in timeout.", - itv.it_value.tv_sec)); - if (setitimer(ITIMER_REAL, &itv, NULL)) { - syslog(LOG_ERR, "setitimer(ITIMER_REAL): %m"); - die(1); - } - if (gettimeofday(&schedtime, NULL)) { - syslog(LOG_ERR, "gettimeofday: %m"); - die(1); - } - } + for (pp = &callout; (p = *pp); pp = &p->c_next) + if (newp->c_time.tv_sec < p->c_time.tv_sec + || (newp->c_time.tv_sec == p->c_time.tv_sec + && newp->c_time.tv_usec < p->c_time.tv_sec)) + break; + newp->c_next = p; + *pp = newp; } @@ -871,188 +672,102 @@ untimeout(func, arg) struct itimerval itv; struct callout **copp, *freep; int reschedule = 0; - - MAINDEBUG((LOG_DEBUG, "Untimeout %x:%x.", (int) func, (int) arg)); - + + MAINDEBUG((LOG_DEBUG, "Untimeout %lx:%lx.", (long) func, (long) arg)); + /* - * If the first callout is unscheduled then we have to set a new - * itimer. + * Find first matching timeout and remove it from the list. */ - if (callout && - callout->c_func == func && - callout->c_arg == arg) - reschedule = 1; - - /* - * Find first matching timeout. Add its time to the next timeouts - * time. - */ - for (copp = &callout; *copp; copp = &(*copp)->c_next) - if ((*copp)->c_func == func && - (*copp)->c_arg == arg) { - freep = *copp; + for (copp = &callout; (freep = *copp); copp = &freep->c_next) + if (freep->c_func == func && freep->c_arg == arg) { *copp = freep->c_next; - if (*copp) - (*copp)->c_time += freep->c_time; (void) free((char *) freep); break; } +} - if (reschedule) { - itv.it_interval.tv_sec = itv.it_interval.tv_usec = - itv.it_value.tv_usec = 0; - itv.it_value.tv_sec = callout ? callout->c_time : 0; - MAINDEBUG((LOG_DEBUG, "Setting itimer for %d seconds in untimeout.", - itv.it_value.tv_sec)); - if (setitimer(ITIMER_REAL, &itv, NULL)) { - syslog(LOG_ERR, "setitimer(ITIMER_REAL): %m"); - die(1); - } - if (gettimeofday(&schedtime, NULL)) { - syslog(LOG_ERR, "gettimeofday: %m"); + +/* + * calltimeout - Call any timeout routines which are now due. + */ +void +calltimeout() +{ + struct callout *p; + + while (callout != NULL) { + p = callout; + + if (gettimeofday(&timenow, NULL) < 0) { + syslog(LOG_ERR, "Failed to get time of day: %m"); die(1); } + if (!(p->c_time.tv_sec < timenow.tv_sec + || (p->c_time.tv_sec == timenow.tv_sec + && p->c_time.tv_usec <= timenow.tv_usec))) + break; /* no, it's not time yet */ + + callout = p->c_next; + (*p->c_func)(p->c_arg); + + free((char *) p); } } /* - * adjtimeout - Decrement the first timeout by the amount of time since - * it was scheduled. + * timeleft - return the length of time until the next timeout is due. */ -void -adjtimeout() +struct timeval * +timeleft(tvp) + struct timeval *tvp; { - struct timeval tv; - int timediff; - if (callout == NULL) - return; - /* - * Make sure that the clock hasn't been warped dramatically. - * Account for recently expired, but blocked timer by adding - * small fudge factor. - */ - if (gettimeofday(&tv, NULL)) { - syslog(LOG_ERR, "gettimeofday: %m"); - die(1); + return NULL; + + gettimeofday(&timenow, NULL); + tvp->tv_sec = callout->c_time.tv_sec - timenow.tv_sec; + tvp->tv_usec = callout->c_time.tv_usec - timenow.tv_usec; + if (tvp->tv_usec < 0) { + tvp->tv_usec += 1000000; + tvp->tv_sec -= 1; } - timediff = tv.tv_sec - schedtime.tv_sec; - if (timediff < 0 || - timediff > callout->c_time + 1) - return; + if (tvp->tv_sec < 0) + tvp->tv_sec = tvp->tv_usec = 0; - callout->c_time -= timediff; /* OK, Adjust time */ + return tvp; } - + /* * hup - Catch SIGHUP signal. * * Indicates that the physical layer has been disconnected. + * We don't rely on this indication; if the user has sent this + * signal, we just take the link down. */ static void hup(sig) int sig; { syslog(LOG_INFO, "Hangup (SIGHUP)"); - - hungup = 1; /* they hung up on us! */ - persist = 0; /* don't try to restart */ - adjtimeout(); /* Adjust timeouts */ - lcp_lowerdown(0); /* Reset connection */ - quit(); /* and die */ + kill_link = 1; } /* - * term - Catch SIGTERM signal. + * term - Catch SIGTERM signal and SIGINT signal (^C/del). * * Indicates that we should initiate a graceful disconnect and exit. */ +/*ARGSUSED*/ static void term(sig) int sig; { - syslog(LOG_INFO, "Terminating link."); - persist = 0; /* don't try to restart */ - adjtimeout(); /* Adjust timeouts */ - lcp_close(0); /* Close connection */ -} - - -/* - * intr - Catch SIGINT signal (DEL/^C). - * - * Indicates that we should initiate a graceful disconnect and exit. - */ -static void -intr(sig) - int sig; -{ - syslog(LOG_INFO, "Interrupt received: terminating link"); + syslog(LOG_INFO, "Terminating on signal %d.", sig); persist = 0; /* don't try to restart */ - adjtimeout(); /* Adjust timeouts */ - lcp_close(0); /* Close connection */ -} - - -/* - * alrm - Catch SIGALRM signal. - * - * Indicates a timeout. - */ -static void -alrm(sig) - int sig; -{ - struct itimerval itv; - struct callout *freep, *list, *last; - - MAINDEBUG((LOG_DEBUG, "Alarm")); - - if (callout == NULL) - return; - /* - * Get the first scheduled timeout and any that were scheduled - * for the same time as a list, and remove them all from callout - * list. - */ - list = last = callout; - while (last->c_next != NULL && last->c_next->c_time == 0) - last = last->c_next; - callout = last->c_next; - last->c_next = NULL; - - /* - * Set a new itimer if there are more timeouts scheduled. - */ - if (callout) { - itv.it_interval.tv_sec = itv.it_interval.tv_usec = 0; - itv.it_value.tv_usec = 0; - itv.it_value.tv_sec = callout->c_time; - MAINDEBUG((LOG_DEBUG, "Setting itimer for %d seconds in alrm.", - itv.it_value.tv_sec)); - if (setitimer(ITIMER_REAL, &itv, NULL)) { - syslog(LOG_ERR, "setitimer(ITIMER_REAL): %m"); - die(1); - } - if (gettimeofday(&schedtime, NULL)) { - syslog(LOG_ERR, "gettimeofday: %m"); - die(1); - } - } - - /* - * Now call all the timeout routines scheduled for this time. - */ - while (list) { - (*list->c_func)(list->c_arg); - freep = list; - list = list->c_next; - (void) free((char *) freep); - } - + kill_link = 1; } @@ -1069,129 +784,31 @@ chld(sig) /* - * io - Catch SIGIO signal. - * - * Indicates that incoming data is available. - */ -static void -io(sig) - int sig; -{ - int len, i; - u_char *p; - u_short protocol; - fd_set fdset; - struct timeval notime; - int ready; - - MAINDEBUG((LOG_DEBUG, "IO signal received")); - adjtimeout(); /* Adjust timeouts */ - - /* Yup, this is for real */ - for (;;) { /* Read all available packets */ - p = inpacket_buf; /* point to beginning of packet buffer */ - - len = read_packet(inpacket_buf); - if (len < 0) - return; - - if (len == 0) { - MAINDEBUG((LOG_DEBUG, "End of file on fd!")); - lcp_lowerdown(0); - return; - } - - if (debug /*&& (debugflags & DBG_INPACKET)*/) - log_packet(p, len, "rcvd "); - - if (len < DLLHEADERLEN) { - MAINDEBUG((LOG_INFO, "io(): Received short packet.")); - return; - } - - p += 2; /* Skip address and control */ - GETSHORT(protocol, p); - len -= DLLHEADERLEN; - - /* - * Toss all non-LCP packets unless LCP is OPEN. - */ - if (protocol != LCP && lcp_fsm[0].state != OPENED) { - MAINDEBUG((LOG_INFO, - "io(): Received non-LCP packet when LCP not open.")); - return; - } - - /* - * Upcall the proper protocol input routine. - */ - for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++) - if (prottbl[i].protocol == protocol) { - (*prottbl[i].input)(0, p, len); - break; - } - - if (i == sizeof (prottbl) / sizeof (struct protent)) { - syslog(LOG_WARNING, "input: Unknown protocol (%x) received!", - protocol); - lcp_sprotrej(0, p - DLLHEADERLEN, len + DLLHEADERLEN); - } - } -} - -/* - * demuxprotrej - Demultiplex a Protocol-Reject. - */ -void -demuxprotrej(unit, protocol) - int unit; - u_short protocol; -{ - int i; - - /* - * Upcall the proper Protocol-Reject routine. - */ - for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++) - if (prottbl[i].protocol == protocol) { - (*prottbl[i].protrej)(unit); - return; - } - - syslog(LOG_WARNING, - "demuxprotrej: Unrecognized Protocol-Reject for protocol %d!", - protocol); -} - - -/* - * incdebug - Catch SIGUSR1 signal. + * toggle_debug - Catch SIGUSR1 signal. * - * Increment debug flag. + * Toggle debug flag. */ /*ARGSUSED*/ static void -incdebug(sig) +toggle_debug(sig) int sig; { - syslog(LOG_INFO, "Debug turned ON, Level %d", debug); - setlogmask(LOG_UPTO(LOG_DEBUG)); - debug++; + debug = !debug; + note_debug_level(); } /* - * nodebug - Catch SIGUSR2 signal. + * open_ccp - Catch SIGUSR2 signal. * - * Turn off debugging. + * Try to (re)negotiate compression. */ /*ARGSUSED*/ static void -nodebug(sig) +open_ccp(sig) int sig; { - setlogmask(LOG_UPTO(LOG_WARNING)); - debug = 0; + open_ccp_flag = 1; } @@ -1206,27 +823,23 @@ device_script(program, in, out) { int pid; int status; - sigset_t mask; - - sigemptyset(&mask); - sigaddset(&mask, SIGINT); - sigaddset(&mask, SIGHUP); - sigprocmask(SIG_BLOCK, &mask, &mask); + int errfd; pid = fork(); if (pid < 0) { - syslog(LOG_ERR, "fork: %m"); + syslog(LOG_ERR, "Failed to create child process: %m"); die(1); } if (pid == 0) { - initgroups(username, gid); - setgid(gid); - setuid(uid); - sigprocmask(SIG_SETMASK, &mask, NULL); 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); @@ -1236,10 +849,9 @@ device_script(program, in, out) while (waitpid(pid, &status, 0) < 0) { if (errno == EINTR) continue; - syslog(LOG_ERR, "waiting for (dis)connection process: %m"); + syslog(LOG_ERR, "error waiting for (dis)connection process: %m"); die(1); } - sigprocmask(SIG_SETMASK, &mask, NULL); return (status == 0 ? 0 : -1); } @@ -1258,16 +870,54 @@ run_program(prog, args, must_exist) int must_exist; { int pid; + char *nullenv[1]; pid = fork(); if (pid == -1) { - syslog(LOG_ERR, "can't fork to run %s: %m", prog); + syslog(LOG_ERR, "Failed to create child process for %s: %m", prog); return -1; } if (pid == 0) { - execv(prog, args); + int new_fd; + + /* Leave the current location */ + (void) setsid(); /* No controlling tty. */ + (void) umask (S_IRWXG|S_IRWXO); + (void) chdir ("/"); /* no current directory. */ + setuid(geteuid()); + setgid(getegid()); + + /* Ensure that nothing of our device environment is inherited. */ + 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); + if (new_fd >= 0) { + if (new_fd != 0) { + dup2 (new_fd, 0); /* stdin <- /dev/null */ + close (new_fd); + } + dup2 (0, 1); /* stdout -> /dev/null */ + dup2 (0, 2); /* stderr -> /dev/null */ + } + +#ifdef BSD + /* Force the priority back to zero if pppd is running higher. */ + if (setpriority (PRIO_PROCESS, 0, 0) < 0) + syslog (LOG_WARNING, "can't reset priority to 0: %m"); +#endif + + /* SysV recommends a second fork at this point. */ + + /* run the program; give it a null environment */ + nullenv[0] = NULL; + execve(prog, args, nullenv); if (must_exist || errno != ENOENT) - syslog(LOG_WARNING, "can't execute %s: %m", prog); + syslog(LOG_WARNING, "Can't execute %s: %m", prog); _exit(-1); } MAINDEBUG((LOG_DEBUG, "Script %s started; pid = %d", prog, pid)); @@ -1289,13 +939,13 @@ reap_kids() return; if ((pid = waitpid(-1, &status, WNOHANG)) == -1) { if (errno != ECHILD) - syslog(LOG_ERR, "waitpid: %m"); + syslog(LOG_ERR, "Error waiting for child process: %m"); return; } if (pid > 0) { --n_children; if (WIFSIGNALED(status)) { - syslog(LOG_WARNING, "child process %d terminated with signal %d", + syslog(LOG_WARNING, "Child process %d terminated with signal %d", pid, WTERMSIG(status)); } } @@ -1330,17 +980,17 @@ void format_packet(p, len, printer, arg) u_char *p; int len; - void (*printer) __ARGS((void *, char *, ...)); + void (*printer) __P((void *, char *, ...)); void *arg; { int i, n; u_short proto; u_char x; - if (len >= DLLHEADERLEN && p[0] == ALLSTATIONS && p[1] == UI) { + if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) { p += 2; GETSHORT(proto, p); - len -= DLLHEADERLEN; + len -= PPP_HDRLEN; for (i = 0; i < N_PROTO; ++i) if (proto == prottbl[i].protocol) break; @@ -1419,7 +1069,7 @@ void print_string(p, len, printer, arg) char *p; int len; - void (*printer) __ARGS((void *, char *, ...)); + void (*printer) __P((void *, char *, ...)); void *arg; { int c; diff --git a/usr.sbin/pppd/options.c b/usr.sbin/pppd/options.c index ec0b7f56d263..d6f89e2ab097 100644 --- a/usr.sbin/pppd/options.c +++ b/usr.sbin/pppd/options.c @@ -18,16 +18,14 @@ */ #ifndef lint -static char rcsid[] = "$Id: options.c,v 1.4 1995/05/30 03:51:14 rgrimes Exp $"; +static char rcsid[] = "$Id: options.c,v 1.24 1995/08/16 01:39:35 paulus Exp $"; #endif #include <stdio.h> #include <errno.h> #include <unistd.h> #include <limits.h> -#define devname STDLIB_devname #include <stdlib.h> -#undef devname #include <termios.h> #include <syslog.h> #include <string.h> @@ -37,7 +35,6 @@ static char rcsid[] = "$Id: options.c,v 1.4 1995/05/30 03:51:14 rgrimes Exp $"; #include <sys/stat.h> #include <netinet/in.h> -#include "ppp.h" #include "pppd.h" #include "pathnames.h" #include "patchlevel.h" @@ -46,12 +43,15 @@ static char rcsid[] = "$Id: options.c,v 1.4 1995/05/30 03:51:14 rgrimes Exp $"; #include "ipcp.h" #include "upap.h" #include "chap.h" +#include "ccp.h" + +#include <net/ppp-comp.h> #define FALSE 0 #define TRUE 1 -#ifdef ultrix -char *strdup __ARGS((char *)); +#if defined(ultrix) || defined(NeXT) +char *strdup __P((char *)); #endif #ifndef GIDSET_TYPE @@ -59,103 +59,119 @@ char *strdup __ARGS((char *)); #endif /* - * Prototypes + * Option variables and default values. */ -static int setdebug __ARGS((void)); -static int setkdebug __ARGS((char **)); -static int setpassive __ARGS((void)); -static int setsilent __ARGS((void)); -static int noopt __ARGS((void)); -static int setnovj __ARGS((void)); -static int setnovjccomp __ARGS((void)); -static int setvjslots __ARGS((char **)); -static int reqpap __ARGS((void)); -static int nopap __ARGS((void)); -static int setupapfile __ARGS((char **)); -static int nochap __ARGS((void)); -static int reqchap __ARGS((void)); -static int setspeed __ARGS((char *)); -static int noaccomp __ARGS((void)); -static int noasyncmap __ARGS((void)); -static int noipaddr __ARGS((void)); -static int nomagicnumber __ARGS((void)); -static int setasyncmap __ARGS((char **)); -static int setescape __ARGS((char **)); -static int setmru __ARGS((char **)); -static int setmtu __ARGS((char **)); -static int nomru __ARGS((void)); -static int nopcomp __ARGS((void)); -static int setconnector __ARGS((char **)); -static int setdisconnector __ARGS((char **)); -static int setdomain __ARGS((char **)); -static int setnetmask __ARGS((char **)); -static int setcrtscts __ARGS((void)); -static int setxonxoff __ARGS((void)); -static int setnodetach __ARGS((void)); -static int setmodem __ARGS((void)); -static int setlocal __ARGS((void)); -static int setlock __ARGS((void)); -static int setname __ARGS((char **)); -static int setuser __ARGS((char **)); -static int setremote __ARGS((char **)); -static int setauth __ARGS((void)); -static int readfile __ARGS((char **)); -static int setdefaultroute __ARGS((void)); -static int setproxyarp __ARGS((void)); -static int setpersist __ARGS((void)); -static int setdologin __ARGS((void)); -static int setusehostname __ARGS((void)); -static int setnoipdflt __ARGS((void)); -static int setlcptimeout __ARGS((char **)); -static int setlcpterm __ARGS((char **)); -static int setlcpconf __ARGS((char **)); -static int setlcpfails __ARGS((char **)); -static int setipcptimeout __ARGS((char **)); -static int setipcpterm __ARGS((char **)); -static int setipcpconf __ARGS((char **)); -static int setipcpfails __ARGS((char **)); -static int setpaptimeout __ARGS((char **)); -static int setpapreqs __ARGS((char **)); -static int setchaptimeout __ARGS((char **)); -static int setchapchal __ARGS((char **)); -static int setchapintv __ARGS((char **)); -static int setipcpaccl __ARGS((void)); -static int setipcpaccr __ARGS((void)); -static int setlcpechointv __ARGS((char **)); -static int setlcpechofails __ARGS((char **)); - -static int number_option __ARGS((char *, long *, int)); -static int readable __ARGS((int fd)); +int debug = 0; /* Debug flag */ +int kdebugflag = 0; /* Tell kernel to print debug messages */ +int default_device = 1; /* Using /dev/tty or equivalent */ +char devnam[MAXPATHLEN] = "/dev/tty"; /* Device name */ +int crtscts = 0; /* Use hardware flow control */ +int modem = 1; /* Use modem control lines */ +int inspeed = 0; /* Input/Output speed requested */ +u_int32_t netmask = 0; /* IP netmask to set on interface */ +int lockflag = 0; /* Create lock file to lock the serial dev */ +int nodetach = 0; /* Don't detach from controlling tty */ +char *connector = NULL; /* Script to establish physical link */ +char *disconnector = NULL; /* Script to disestablish physical link */ +char user[MAXNAMELEN]; /* Username for PAP */ +char passwd[MAXSECRETLEN]; /* Password for PAP */ +int auth_required = 0; /* Peer is required to authenticate */ +int defaultroute = 0; /* assign default route through interface */ +int proxyarp = 0; /* Set up proxy ARP entry for peer */ +int persist = 0; /* Reopen link after it goes down */ +int uselogin = 0; /* Use /etc/passwd for checking PAP */ +int lcp_echo_interval = 0; /* Interval between LCP echo-requests */ +int lcp_echo_fails = 0; /* Tolerance to unanswered echo-requests */ +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 */ +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 /* - * Option variables + * Prototypes */ -extern char *progname; -extern int debug; -extern int kdebugflag; -extern int modem; -extern int lockflag; -extern int crtscts; -extern int nodetach; -extern char *connector; -extern char *disconnector; -extern int inspeed; -extern char devname[]; -extern int default_device; -extern u_long netmask; -extern int detach; -extern char user[]; -extern char passwd[]; -extern int auth_required; -extern int proxyarp; -extern int persist; -extern int uselogin; -extern u_long lcp_echo_interval; -extern u_long lcp_echo_fails; -extern char our_name[]; -extern char remote_name[]; -int usehostname; -int disable_defaultip; +static int setdebug __P((void)); +static int setkdebug __P((char **)); +static int setpassive __P((void)); +static int setsilent __P((void)); +static int noopt __P((void)); +static int setnovj __P((void)); +static int setnovjccomp __P((void)); +static int setvjslots __P((char **)); +static int reqpap __P((void)); +static int nopap __P((void)); +static int setupapfile __P((char **)); +static int nochap __P((void)); +static int reqchap __P((void)); +static int setspeed __P((char *)); +static int noaccomp __P((void)); +static int noasyncmap __P((void)); +static int noipaddr __P((void)); +static int nomagicnumber __P((void)); +static int setasyncmap __P((char **)); +static int setescape __P((char **)); +static int setmru __P((char **)); +static int setmtu __P((char **)); +static int nomru __P((void)); +static int nopcomp __P((void)); +static int setconnector __P((char **)); +static int setdisconnector __P((char **)); +static int setdomain __P((char **)); +static int setnetmask __P((char **)); +static int setcrtscts __P((void)); +static int setnocrtscts __P((void)); +static int setxonxoff __P((void)); +static int setnodetach __P((void)); +static int setmodem __P((void)); +static int setlocal __P((void)); +static int setlock __P((void)); +static int setname __P((char **)); +static int setuser __P((char **)); +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)); +static int setnoipdflt __P((void)); +static int setlcptimeout __P((char **)); +static int setlcpterm __P((char **)); +static int setlcpconf __P((char **)); +static int setlcpfails __P((char **)); +static int setipcptimeout __P((char **)); +static int setipcpterm __P((char **)); +static int setipcpconf __P((char **)); +static int setipcpfails __P((char **)); +static int setpaptimeout __P((char **)); +static int setpapreqs __P((char **)); +static int setpapreqtime __P((char **)); +static int setchaptimeout __P((char **)); +static int setchapchal __P((char **)); +static int setchapintv __P((char **)); +static int setipcpaccl __P((void)); +static int setipcpaccr __P((void)); +static int setlcpechointv __P((char **)); +static int setlcpechofails __P((char **)); +static int setbsdcomp __P((char **)); +static int setnobsdcomp __P((void)); +static int setipparam __P((char **)); +static int setpapcrypt __P((void)); + +static int number_option __P((char *, u_int32_t *, int)); +static int readable __P((int fd)); + +void usage(); /* * Valid arguments. @@ -189,8 +205,8 @@ static struct cmd { {"connect", 1, setconnector}, /* A program to set up a connection */ {"disconnect", 1, setdisconnector}, /* program to disconnect serial dev. */ {"crtscts", 0, setcrtscts}, /* set h/w flow control */ + {"-crtscts", 0, setnocrtscts}, /* clear h/w flow control */ {"xonxoff", 0, setxonxoff}, /* set s/w flow control */ - {"-crtscts", 0, setxonxoff}, /* another name for xonxoff */ {"debug", 0, setdebug}, /* Increase debugging level */ {"kdebug", 1, setkdebug}, /* Enable kernel-level debugging */ {"domain", 1, setdomain}, /* Add given domain name to hostname*/ @@ -209,7 +225,9 @@ 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 */ {"login", 0, setdologin}, /* Use system password database for UPAP */ {"noipdefault", 0, setnoipdflt}, /* Don't use name for default IP adrs */ @@ -223,13 +241,21 @@ static struct cmd { {"ipcp-max-terminate", 1, setipcpterm}, /* Set max #xmits for term-reqs */ {"ipcp-max-configure", 1, setipcpconf}, /* Set max #xmits for conf-reqs */ {"ipcp-max-failure", 1, setipcpfails}, /* Set max #conf-naks for IPCP */ - {"pap-restart", 1, setpaptimeout}, /* Set timeout for UPAP */ + {"pap-restart", 1, setpaptimeout}, /* Set retransmit timeout for PAP */ {"pap-max-authreq", 1, setpapreqs}, /* Set max #xmits for auth-reqs */ + {"pap-timeout", 1, setpapreqtime}, /* Set time limit for peer PAP auth. */ {"chap-restart", 1, setchaptimeout}, /* Set timeout for CHAP */ {"chap-max-challenge", 1, setchapchal}, /* Set max #xmits for challenge */ {"chap-interval", 1, setchapintv}, /* Set interval for rechallenge */ {"ipcp-accept-local", 0, setipcpaccl}, /* Accept peer's address for us */ {"ipcp-accept-remote", 0, setipcpaccr}, /* Accept peer's address for it */ + {"bsdcomp", 1, setbsdcomp}, /* request BSD-Compress */ + {"-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 {NULL, 0, NULL} }; @@ -313,6 +339,7 @@ parse_args(argc, argv) /* * usage - print out a message telling how to use the program. */ +void usage() { fprintf(stderr, usage_string, VERSION, PATCHLEVEL, IMPLEMENTATION, @@ -427,9 +454,9 @@ options_for_tty() char *dev, *path; int ret; - dev = strrchr(devname, '/'); + dev = strrchr(devnam, '/'); if (dev == NULL) - dev = devname; + dev = devnam; else ++dev; if (strcmp(dev, "tty") == 0) @@ -474,10 +501,11 @@ readable(fd) /* * Read a word from a file. - * Words are delimited by white-space or by quotes ("). + * Words are delimited by white-space or by quotes (" or '). * Quotes, white-space and \ may be escaped with \. * \<newline> is ignored. */ + int getword(f, word, newlinep, filename) FILE *f; @@ -486,110 +514,250 @@ getword(f, word, newlinep, filename) char *filename; { int c, len, escape; - int quoted; + int quoted, comment; + int value, digit, got, n; + +#define isoctal(c) ((c) >= '0' && (c) < '8') *newlinep = 0; len = 0; escape = 0; - quoted = 0; + comment = 0; /* - * First skip white-space and comments + * First skip white-space and comments. */ - while ((c = getc(f)) != EOF) { + for (;;) { + c = getc(f); + if (c == EOF) + break; + + /* + * A newline means the end of a comment; backslash-newline + * is ignored. Note that we cannot have escape && comment. + */ + if (c == '\n') { + if (!escape) { + *newlinep = 1; + comment = 0; + } else + escape = 0; + continue; + } + + /* + * Ignore characters other than newline in a comment. + */ + if (comment) + continue; + + /* + * If this character is escaped, we have a word start. + */ + if (escape) + break; + + /* + * If this is the escape character, look at the next character. + */ if (c == '\\') { + escape = 1; + continue; + } + + /* + * If this is the start of a comment, ignore the rest of the line. + */ + if (c == '#') { + comment = 1; + continue; + } + + /* + * A non-whitespace character is the start of a word. + */ + if (!isspace(c)) + break; + } + + /* + * Save the delimiter for quoted strings. + */ + if (!escape && (c == '"' || c == '\'')) { + quoted = c; + c = getc(f); + } else + quoted = 0; + + /* + * Process characters until the end of the word. + */ + while (c != EOF) { + if (escape) { /* - * \<newline> is ignored; \ followed by anything else - * starts a word. + * This character is escaped: backslash-newline is ignored, + * various other characters indicate particular values + * as for C backslash-escapes. */ - if ((c = getc(f)) == '\n') + escape = 0; + if (c == '\n') { + c = getc(f); continue; - word[len++] = '\\'; - escape = 1; - break; + } + + got = 0; + switch (c) { + case 'a': + value = '\a'; + break; + case 'b': + value = '\b'; + break; + case 'f': + value = '\f'; + break; + case 'n': + value = '\n'; + break; + case 'r': + value = '\r'; + break; + case 's': + value = ' '; + break; + case 't': + value = '\t'; + break; + + default: + if (isoctal(c)) { + /* + * \ddd octal sequence + */ + value = 0; + for (n = 0; n < 3 && isoctal(c); ++n) { + value = (value << 3) + (c & 07); + c = getc(f); + } + got = 1; + break; + } + + if (c == 'x') { + /* + * \x<hex_string> sequence + */ + value = 0; + c = getc(f); + for (n = 0; n < 2 && isxdigit(c); ++n) { + digit = toupper(c) - '0'; + if (digit > 10) + digit += '0' + 10 - 'A'; + value = (value << 4) + digit; + c = getc (f); + } + got = 1; + break; + } + + /* + * Otherwise the character stands for itself. + */ + value = c; + break; + } + + /* + * Store the resulting character for the escape sequence. + */ + if (len < MAXWORDLEN-1) + word[len] = value; + ++len; + + if (!got) + c = getc(f); + continue; + } - if (c == '\n') - *newlinep = 1; /* next word starts a line */ - else if (c == '#') { - /* comment - ignore until EOF or \n */ - while ((c = getc(f)) != EOF && c != '\n') - ; - if (c == EOF) + + /* + * Not escaped: see if we've reached the end of the word. + */ + if (quoted) { + if (c == quoted) break; - *newlinep = 1; - } else if (!isspace(c)) - break; + } else { + if (isspace(c) || c == '#') { + ungetc (c, f); + break; + } + } + + /* + * Backslash starts an escape sequence. + */ + if (c == '\\') { + escape = 1; + c = getc(f); + continue; + } + + /* + * An ordinary character: store it in the word and get another. + */ + if (len < MAXWORDLEN-1) + word[len] = c; + ++len; + + c = getc(f); } /* - * End of file or error - fail + * End of the word: check for errors. */ if (c == EOF) { if (ferror(f)) { + if (errno == 0) + errno = EIO; perror(filename); die(1); } - return 0; - } - - for (;;) { /* - * Is this character escaped by \ ? + * If len is zero, then we didn't find a word before the + * end of the file. */ - if (escape) { - if (c == '\n') - --len; /* ignore \<newline> */ - else if (c == '"' || isspace(c) || c == '\\') - word[len-1] = c; /* put special char in word */ - else { - if (len < MAXWORDLEN-1) - word[len] = c; - ++len; - } - escape = 0; - } else if (c == '"') { - quoted = !quoted; - } else if (!quoted && (isspace(c) || c == '#')) { - ungetc(c, f); - break; - } else { - if (len < MAXWORDLEN-1) - word[len] = c; - ++len; - if (c == '\\') - escape = 1; - } - if ((c = getc(f)) == EOF) - break; - } - - if (ferror(f)) { - perror(filename); - die(1); + if (len == 0) + return 0; } + /* + * Warn if the word was too long, and append a terminating null. + */ if (len >= MAXWORDLEN) { - word[MAXWORDLEN-1] = 0; fprintf(stderr, "%s: warning: word in file %s too long (%.20s...)\n", progname, filename, word); - } else - word[len] = 0; + len = MAXWORDLEN - 1; + } + word[len] = 0; return 1; + +#undef isoctal + } /* - * number_option - parse a numeric parameter for an option + * number_option - parse an unsigned numeric parameter for an option. */ static int number_option(str, valp, base) char *str; - long *valp; + u_int32_t *valp; int base; { char *ptr; - *valp = strtol(str, &ptr, base); + *valp = strtoul(str, &ptr, base); if (ptr == str) { fprintf(stderr, "%s: invalid number: %s\n", progname, str); return 0; @@ -608,7 +776,7 @@ int_option(str, valp) char *str; int *valp; { - long v; + u_int32_t v; if (!number_option(str, &v, 0)) return 0; @@ -731,7 +899,7 @@ static int setmru(argv) char **argv; { - long mru; + u_int32_t mru; if (!number_option(*argv, &mru, 0)) return 0; @@ -748,12 +916,12 @@ static int setmtu(argv) char **argv; { - long mtu; + u_int32_t mtu; if (!number_option(*argv, &mtu, 0)) return 0; if (mtu < MINMRU || mtu > MAXMRU) { - fprintf(stderr, "mtu option value of %d is too %s\n", mtu, + fprintf(stderr, "mtu option value of %ld is too %s\n", mtu, (mtu < MINMRU? "small": "large")); return 0; } @@ -817,6 +985,7 @@ reqpap() { lcp_wantoptions[0].neg_upap = 1; auth_required = 1; + return 1; } @@ -906,6 +1075,7 @@ setnovjccomp() { ipcp_wantoptions[0].cflag = 0; ipcp_allowoptions[0].cflag = 0; + return 1; } @@ -940,7 +1110,7 @@ setconnector(argv) connector = strdup(*argv); if (connector == NULL) novm("connector string"); - + return (1); } @@ -954,19 +1124,24 @@ setdisconnector(argv) disconnector = strdup(*argv); if (disconnector == NULL) novm("disconnector string"); - + return (1); } /* - * setdomain - Set domain name to append to hostname + * setdomain - Set domain name to append to hostname */ static int setdomain(argv) char **argv; { - strncat(hostname, *argv, MAXNAMELEN - strlen(hostname)); + gethostname(hostname, MAXNAMELEN); + if (**argv != 0) { + if (**argv != '.') + strncat(hostname, ".", MAXNAMELEN - strlen(hostname)); + strncat(hostname, *argv, MAXNAMELEN - strlen(hostname)); + } hostname[MAXNAMELEN-1] = 0; return (1); } @@ -979,7 +1154,7 @@ static int setasyncmap(argv) char **argv; { - long asyncmap; + u_int32_t asyncmap; if (!number_option(*argv, &asyncmap, 16)) return 0; @@ -1048,7 +1223,7 @@ setdevname(cp) struct stat statbuf; char *tty, *ttyname(); char dev[MAXPATHLEN]; - + if (strncmp("/dev/", cp, 5) != 0) { strcpy(dev, "/dev/"); strncat(dev, cp, MAXPATHLEN - 5); @@ -1065,11 +1240,11 @@ setdevname(cp) syslog(LOG_ERR, cp); return -1; } - - (void) strncpy(devname, cp, MAXPATHLEN); - devname[MAXPATHLEN-1] = 0; + + (void) strncpy(devnam, cp, MAXPATHLEN); + devnam[MAXPATHLEN-1] = 0; default_device = FALSE; - + return 1; } @@ -1082,16 +1257,16 @@ setipaddr(arg) char *arg; { struct hostent *hp; - char *colon, *index(); - u_long local, remote; + char *colon; + u_int32_t local, remote; ipcp_options *wo = &ipcp_wantoptions[0]; - + /* * IP address pair separated by ":". */ - if ((colon = index(arg, ':')) == NULL) + if ((colon = strchr(arg, ':')) == NULL) return 0; - + /* * If colon first character, then no local addr. */ @@ -1102,7 +1277,7 @@ setipaddr(arg) fprintf(stderr, "unknown host: %s\n", arg); return -1; } else { - local = *(long *)hp->h_addr; + local = *(u_int32_t *)hp->h_addr; if (our_name[0] == 0) { strncpy(our_name, arg, MAXNAMELEN); our_name[MAXNAMELEN-1] = 0; @@ -1117,7 +1292,7 @@ setipaddr(arg) wo->ouraddr = local; *colon = ':'; } - + /* * If colon last character, then no remote addr. */ @@ -1127,7 +1302,7 @@ setipaddr(arg) fprintf(stderr, "unknown host: %s\n", colon); return -1; } else { - remote = *(long *)hp->h_addr; + remote = *(u_int32_t *)hp->h_addr; if (remote_name[0] == 0) { strncpy(remote_name, colon, MAXNAMELEN); remote_name[MAXNAMELEN-1] = 0; @@ -1186,7 +1361,7 @@ void setipdefault() { struct hostent *hp; - u_long local; + u_int32_t local; ipcp_options *wo = &ipcp_wantoptions[0]; /* @@ -1203,7 +1378,7 @@ setipdefault() wo->accept_local = 1; /* don't insist on this default value */ if ((hp = gethostbyname(hostname)) == NULL) return; - local = *(long *)hp->h_addr; + local = *(u_int32_t *)hp->h_addr; if (local != 0 && !bad_ip_adrs(local)) wo->ouraddr = local; } @@ -1216,40 +1391,37 @@ static int setnetmask(argv) char **argv; { - struct in_addr mask; + u_int32_t mask; - if ((inet_aton(*argv, &mask) < 0) || (netmask & ~mask.s_addr)) { + if ((mask = inet_addr(*argv)) == -1 || (netmask & ~mask) != 0) { fprintf(stderr, "Invalid netmask %s\n", *argv); - return (0); + return 0; } - netmask = mask.s_addr; + netmask = mask; return (1); } -/* - * Return user specified netmask. A value of zero means no netmask has - * been set. - */ -/* ARGSUSED */ -u_long -GetMask(addr) - u_long addr; +static int +setcrtscts() { - return(netmask); + crtscts = 1; + return (1); } - static int -setcrtscts() +setnocrtscts() { - crtscts = 1; + crtscts = -1; return (1); } static int setxonxoff() { + lcp_wantoptions[0].asyncmap |= 0x000A0000; /* escape ^S and ^Q */ + lcp_wantoptions[0].neg_asyncmap = 1; + crtscts = 2; return (1); } @@ -1328,18 +1500,42 @@ 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() { persist = 1; @@ -1381,74 +1577,164 @@ setlcptimeout(argv) return int_option(*argv, &lcp_fsm[0].timeouttime); } -static int setlcpterm(argv) +static int +setlcpterm(argv) char **argv; { return int_option(*argv, &lcp_fsm[0].maxtermtransmits); } -static int setlcpconf(argv) +static int +setlcpconf(argv) char **argv; { return int_option(*argv, &lcp_fsm[0].maxconfreqtransmits); } -static int setlcpfails(argv) +static int +setlcpfails(argv) char **argv; { return int_option(*argv, &lcp_fsm[0].maxnakloops); } -static int setipcptimeout(argv) +static int +setipcptimeout(argv) char **argv; { return int_option(*argv, &ipcp_fsm[0].timeouttime); } -static int setipcpterm(argv) +static int +setipcpterm(argv) char **argv; { return int_option(*argv, &ipcp_fsm[0].maxtermtransmits); } -static int setipcpconf(argv) +static int +setipcpconf(argv) char **argv; { return int_option(*argv, &ipcp_fsm[0].maxconfreqtransmits); } -static int setipcpfails(argv) +static int +setipcpfails(argv) char **argv; { return int_option(*argv, &lcp_fsm[0].maxnakloops); } -static int setpaptimeout(argv) +static int +setpaptimeout(argv) char **argv; { return int_option(*argv, &upap[0].us_timeouttime); } -static int setpapreqs(argv) +static int +setpapreqtime(argv) + char **argv; +{ + return int_option(*argv, &upap[0].us_reqtimeout); +} + +static int +setpapreqs(argv) char **argv; { return int_option(*argv, &upap[0].us_maxtransmits); } -static int setchaptimeout(argv) +static int +setchaptimeout(argv) char **argv; { return int_option(*argv, &chap[0].timeouttime); } -static int setchapchal(argv) +static int +setchapchal(argv) char **argv; { return int_option(*argv, &chap[0].max_transmits); } -static int setchapintv(argv) +static int +setchapintv(argv) char **argv; { return int_option(*argv, &chap[0].chal_interval); } + +static int +setbsdcomp(argv) + char **argv; +{ + int rbits, abits; + char *str, *endp; + + str = *argv; + abits = rbits = strtol(str, &endp, 0); + if (endp != str && *endp == ',') { + str = endp + 1; + abits = strtol(str, &endp, 0); + } + if (*endp != 0 || endp == str) { + fprintf(stderr, "%s: invalid argument format for bsdcomp option\n", + progname); + return 0; + } + if (rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS) + || abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS)) { + fprintf(stderr, "%s: bsdcomp option values must be 0 or %d .. %d\n", + progname, BSD_MIN_BITS, BSD_MAX_BITS); + return 0; + } + if (rbits > 0) { + ccp_wantoptions[0].bsd_compress = 1; + ccp_wantoptions[0].bsd_bits = rbits; + } else + ccp_wantoptions[0].bsd_compress = 0; + if (abits > 0) { + ccp_allowoptions[0].bsd_compress = 1; + ccp_allowoptions[0].bsd_bits = abits; + } else + ccp_allowoptions[0].bsd_compress = 0; + return 1; +} + +static int +setnobsdcomp() +{ + ccp_wantoptions[0].bsd_compress = 0; + ccp_allowoptions[0].bsd_compress = 0; + return 1; +} + +static int +setipparam(argv) + char **argv; +{ + ipparam = strdup(*argv); + if (ipparam == NULL) + novm("ipparam string"); + + return 1; +} + +static int +setpapcrypt() +{ + cryptpap = 1; + return 1; +} + +#ifdef _linux_ +static int setidle (argv) + char **argv; +{ + return int_option(*argv, &idle_time_limit); +} +#endif diff --git a/usr.sbin/pppd/patchlevel.h b/usr.sbin/pppd/patchlevel.h index ad290b08f5fe..c722443f029d 100644 --- a/usr.sbin/pppd/patchlevel.h +++ b/usr.sbin/pppd/patchlevel.h @@ -1,5 +1,6 @@ -/* $Id: patchlevel.h,v 1.10 1994/06/09 01:51:10 paulus Exp $ */ -#define PATCHLEVEL 2 +/* $Id: patchlevel.h,v 1.16 1995/07/11 06:41:07 paulus Exp $ */ +#define PATCHLEVEL 0 -#define VERSION "2.1" -#define DATE "9 June 94" +#define VERSION "2.2" +#define IMPLEMENTATION "beta3" +#define DATE "11 July 95" diff --git a/usr.sbin/pppd/pathnames.h b/usr.sbin/pppd/pathnames.h index d8e91dcad676..4562a967017b 100644 --- a/usr.sbin/pppd/pathnames.h +++ b/usr.sbin/pppd/pathnames.h @@ -1,13 +1,15 @@ /* * define path names * - * $Id: pathnames.h,v 1.4 1994/05/18 06:34:46 paulus Exp $ + * $Id: pathnames.h,v 1.6 1995/06/12 11:22:53 paulus Exp $ */ -#if defined(STREAMS) || defined(ultrix) -#define _PATH_PIDFILE "/etc/ppp" +#ifdef HAVE_PATHS_H +#include <paths.h> + #else -#define _PATH_PIDFILE "/var/run" +#define _PATH_VARRUN "/etc/ppp/" +#define _PATH_DEVNULL "/dev/null" #endif #define _PATH_UPAPFILE "/etc/ppp/pap-secrets" @@ -16,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/usr.sbin/pppd/pppd.8 b/usr.sbin/pppd/pppd.8 index 3395631d8f64..e1c7bbdd9886 100644 --- a/usr.sbin/pppd/pppd.8 +++ b/usr.sbin/pppd/pppd.8 @@ -1,5 +1,5 @@ .\" manual page [] for pppd 2.0 -.\" $Id: pppd.8,v 1.7 1994/06/09 01:50:48 paulus Exp $ +.\" $Id: pppd.8,v 1.14 1995/08/16 01:39:53 paulus Exp $ .\" SH section heading .\" SS subsection heading .\" LP paragraph @@ -36,6 +36,7 @@ NCP for establishing and configuring the Internet Protocol (IP) .I <tty_name> Communicate over the named device. The string "/dev/" is prepended if necessary. If no device name is given, +or if the name of the controlling terminal is given, .I pppd will use the controlling terminal, and will not fork to put itself in the background. @@ -58,7 +59,7 @@ bit 31 (80000000) represents the character 0x1f or ^_. If multiple \fBasyncmap\fR options are given, the values are ORed together. If no \fBasyncmap\fR option is given, no async character map will be -negotiated for the receive direction; the peer will then escape +negotiated for the receive direction; the peer should then escape \fIall\fR control characters. .TP .B auth @@ -74,14 +75,17 @@ dial the modem and start the remote ppp session. Use hardware flow control (i.e. RTS/CTS) to control the flow of data on the serial port. .TP +.B -crtscts +Disable hardware flow control (i.e. RTS/CTS) on the serial port. If +neither the \fBcrtscts\fR nor the \fB\-crtscts\fR option is given, +the hardware flow control setting for the serial port is left +unchanged. +.TP .B xonxoff Use software flow control (i.e. XON/XOFF) to control the flow of data on -the serial port. This option is not implemented on BSD or Ultrix systems +the serial port. This option is only implemented on Linux systems at present. .TP -.B -crtscts -A synonym for \fBxonxoff\fR. -.TP .B defaultroute Add a default route to the system routing tables, using the peer as the gateway, when IPCP negotiation is successfully completed. @@ -135,7 +139,7 @@ will then just wait passively for a valid LCP packet from the peer With this option, .I pppd will not transmit LCP packets to initiate a connection until a valid -LCP packet is received from the peer (as for the "passive" option with +LCP packet is received from the peer (as for the `passive' option with old versions of \fIpppd\fR). .SH OPTIONS .TP @@ -228,6 +232,21 @@ Don't agree to authenticate using CHAP. Disable negotiation of Van Jacobson style IP header compression (use default, i.e. no compression). .TP +.B bsdcomp \fInr,nt +Request that the peer compress packets that it sends, using the +BSD-Compress scheme, with a maximum code size of \fInr\fR bits, and +agree to compress packets sent to the peer with a maximum code size of +\fInt\fR bits. If \fInt\fR is not specified, it defaults to the value +given for \fInr\fR. Values in the range 9 to 15 may be used for +\fInr\fR and \fInt\fR; larger values give better compression but +consume more kernel memory for compression dictionaries. +Alternatively, a value of 0 for \fInr\fR or \fInt\fR disables +compression in the corresponding direction. +.TP +.B \-bsdcomp +Disables compression; \fBpppd\fR will not request or agree to compress +packets using the BSD-Compress scheme. +.TP .B debug Increase debugging level (same as \fB\-d\fR). If this @@ -235,9 +254,12 @@ option is given, \fIpppd\fR will log the contents of all control packets sent or received in a readable form. The packets are logged through syslog with facility \fIdaemon\fR and level \fIdebug\fR. This information can be directed to a file by setting up /etc/syslog.conf -appropriately (see syslog.conf(5)). (If \fIpppd\fR is compiled with -extra debugging enabled, it will log messages using facility -\fIlocal2\fR instead of \fIdaemon\fR). +appropriately (see syslog.conf(5)). +.TP +.B \-defaultroute +Disable the \fBdefaultroute\fR option. The system administrator who +wishes to prevent users from creating default routes with \fIpppd\fR +can do so by placing this option in the /etc/ppp/options file. .TP .B domain \fI<d> Append the domain name <d> to the local host name for authentication @@ -245,10 +267,22 @@ purposes. For example, if gethostname() returns the name porsche, but the fully qualified domain name is porsche.Quotron.COM, you would use the domain option to set the domain name to Quotron.COM. .TP +.B ipparam \fIstring +Provides an extra parameter to the ip-up and ip-down scripts. If this +option is given, the \fIstring\fR supplied is given as the 6th +parameter to those scripts. +.TP .B modem -Use the modem control lines. On Ultrix, this option implies hardware -flow control, as for the \fBcrtscts\fR option. (This option is not fully -implemented.) +Use the modem control lines. This option is the default. With this +option, +.B pppd +will wait for the CD (Carrier Detect) signal from the modem to be asserted +when opening the serial device +(unless a connect script is specified), and it will drop the DTR (Data +Terminal Ready) signal briefly when the connection is terminated and before +executing the connect script. +On Ultrix, this option implies hardware +flow control, as for the \fBcrtscts\fR option. .TP .B kdebug \fIn Enable debugging code in the kernel-level PPP driver. The argument @@ -258,7 +292,10 @@ received packets be printed, and 4 to request that the contents of transmitted packets be printed. .TP .B local -Don't use the modem control lines. +Don't use the modem control lines. With this option, +.B pppd +will ignore the state of the CD (Carrier Detect) signal from the modem and +will not change the state of the DTR (Data Terminal Ready) signal. .TP .B mtu \fI<n> Set the MTU [Maximum Transmit Unit] value to \fI<n>\fR. Unless the @@ -283,11 +320,27 @@ option). Set the assumed name of the remote system for authentication purposes to <n>. .TP +.B papcrypt +Indicates that all secrets in the /etc/ppp/pap-secrets file which +are used for checking the identity of the peer are encrypted, and thus +pppd should not accept a password which (before encryption) is +identical to the secret from the /etc/ppp/pap-secrets file. +.TP .B proxyarp Add an entry to this system's ARP [Address Resolution Protocol] table with the IP address of the peer and the Ethernet address of this system. .TP +.B \-proxyarp +Disable the \fBproxyarp\fR option. The system administrator who +wishes to prevent users from creating proxy ARP entries with +\fIpppd\fR can do so by placing this option in the /etc/ppp/options +file. +.TP +.B persist +Do not exit after a connection is terminated; instead try to reopen +the connection. +.TP .B login Use the system password database for authenticating the peer using PAP. @@ -358,6 +411,12 @@ Set the PAP restart interval (retransmission timeout) to <n> seconds Set the maximum number of PAP authenticate-request transmissions to <n> (default 10). .TP +.B pap-timeout \fI<n> +Set the maximum time that +.I pppd +will wait for the peer to authenticate itself with PAP to +<n> seconds (0 means no limit). +.TP .B chap-restart \fI<n> Set the CHAP restart interval (retransmission timeout for challenges) to <n> seconds (default 3). @@ -424,7 +483,7 @@ directions if desired. .LP A secrets file is parsed into words as for a options file. A secret is specified by a line containing at least 3 words, in the order -client, server, secret. Any following words on the same line are +client name, server name, secret. Any following words on the same line are taken to be a list of acceptable IP addresses for that client. If there are only 3 words on the line, it is assumed that any IP address is OK; to disallow all IP addresses, use "-". If the secret starts @@ -480,11 +539,16 @@ When authenticating the peer with PAP, a secret of "" matches any password supplied by the peer. If the password doesn't match the secret, the password is encrypted using crypt() and checked against the secret again; thus secrets for authenticating the peer can be -stored in encrypted form. If the \fBlogin\fR option was specified, the +stored in encrypted form. If the \fBpapcrypt\fR option is given, the +first (unencrypted) comparison is omitted, for better security. +.LP +If the \fBlogin\fR option was specified, the username and password are also checked against the system password database. Thus, the system administrator can set up the pap-secrets file to allow PPP access only to certain users, and to restrict the -set of IP addresses that each user can use. +set of IP addresses that each user can use. Typically, when using the +\fBlogin\fR option, the secret in /etc/ppp/pap-secrets would be "", to +avoid the need to have the same secret in two places. .LP Secrets are selected from the CHAP secrets file as follows: .TP 2 @@ -590,27 +654,28 @@ to direct the messages to the desired output device or file. The \fBdebug\fR option causes the contents of all control packets sent or received to be logged, that is, all LCP, PAP, CHAP or IPCP packets. This can be useful if the PPP negotiation does not succeed. -If debugging is enabled at compile time, \fIpppd\fR uses facility -LOG_LOCAL2 instead of LOG_DAEMON, and the \fBdebug\fR option -causes additional debugging messages to be logged. +If debugging is enabled at compile time, the \fBdebug\fR option also +causes other debugging messages to be logged. .LP -Debugging can also be enabled by sending a +Debugging can also be enabled or disabled by sending a SIGUSR1 to the .I pppd -process. -Debugging may be disabled by sending a SIGUSR2 to the -.I pppd -process. +process. This signal acts as a toggle. .SH FILES .TP -.B /var/run/ppp\fIn\fB.pid \fR(BSD), \fB/etc/ppp/ppp\fIn\fB.pid \fR(SunOS) +.B /var/run/ppp\fIn\fB.pid \fR(BSD or Linux), \fB/etc/ppp/ppp\fIn\fB.pid \fR(others) Process-ID for \fIpppd\fR process on ppp interface unit \fIn\fR. .TP .B /etc/ppp/ip-up A program or script which is executed when the link is available for sending and receiving IP packets (that is, IPCP has come up). It is -executed with the parameters \fIinterface-name tty-device speed -local-IP-address remote-IP-address\fR. +executed with the parameters +.IP +\fIinterface-name tty-device speed local-IP-address +remote-IP-address\fR +.IP +and with its standard input, +output and error streams redirected to \fB/dev/null\fR. .IP This program or script is executed with the same real and effective user-ID as \fIpppd\fR, that is, at least the effective user-ID and @@ -682,20 +747,29 @@ The following signals have the specified effect when sent to the process. .TP .B SIGINT, SIGTERM -These signals cause \fIpppd\fR to terminate the link (by closing LCP), +These signals cause \fBpppd\fR to terminate the link (by closing LCP), restore the serial device settings, and exit. .TP .B SIGHUP -Indicates that the physical layer has been disconnected. \fIpppd\fR -will attempt to restore the serial device settings (this may produce -error messages on Suns), and then exit. -.SH BUGS -The use of the modem control lines and the effects of the \fBmodem\fR -and \fBlocal\fR options are not well defined. +This signal causes \fBpppd\fR to terminate the link, restore the +serial device settings, and close the serial device. If the +\fBpersist\fR option has been specified, \fBpppd\fR will try to reopen +the serial device and start another connection. Otherwise \fBpppd\fR +will exit. +.TP +.B SIGUSR2 +This signal causes +.B pppd +to renegotiate compression. This can be useful to re-enable +compression after it has been disabled as a result of a fatal +decompression error. With the BSD Compress scheme, fatal +decompression errors generally indicate a bug in one or other +implementation. + .SH AUTHORS Drew Perkins, Brad Clements, Karl Fox, Greg Christy, -Brad Parker (brad@fcr.com), -Paul Mackerras (paulus@cs.anu.edu.au) +Brad Parker, +Paul Mackerras (paulus@cs.anu.edu.au). diff --git a/usr.sbin/pppd/pppd.h b/usr.sbin/pppd/pppd.h index ddacee541347..66b0107efca7 100644 --- a/usr.sbin/pppd/pppd.h +++ b/usr.sbin/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.2 1994/09/25 02:32:13 wollman Exp $ + * $Id: pppd.h,v 1.8 1995/04/26 06:46:31 paulus Exp $ */ /* @@ -25,15 +25,17 @@ #ifndef __PPPD_H__ #define __PPPD_H__ -#include "args.h" #include <sys/param.h> /* for MAXPATHLEN and BSD4_4, if defined */ +#include <sys/types.h> /* for u_int32_t, if defined */ +#include <net/ppp_defs.h> -#define NPPP 1 /* One PPP interface supported (per process) */ +#define NUM_PPP 1 /* One PPP interface supported (per process) */ /* * Limits. */ + #define MAXWORDLEN 1024 /* max length of word in file (incl null) */ #define MAXARGS 1 /* max # args to a command */ #define MAXNAMELEN 256 /* max length of hostname or name for auth */ @@ -42,14 +44,47 @@ /* * Global variables. */ -extern int debug; /* Debug flag */ -extern int ifunit; /* Interface unit number */ -extern char ifname[]; /* Interface name */ -extern int fd; /* Device file descriptor */ -extern int s; /* socket descriptor */ -extern char hostname[]; /* hostname */ -extern u_char outpacket_buf[]; /* buffer for outgoing packets */ -extern int phase; /* See values below */ + +extern int hungup; /* Physical layer has disconnected */ +extern int ifunit; /* Interface unit number */ +extern char ifname[]; /* Interface name */ +extern int fd; /* Serial device file descriptor */ +extern char hostname[]; /* Our hostname */ +extern u_char outpacket_buf[]; /* Buffer for outgoing packets */ +extern int phase; /* Current state of link - see values below */ +extern int baud_rate; /* Current link speed in bits/sec */ +extern char *progname; /* Name of this program */ + +/* + * Variables set by command-line options. + */ + +extern int debug; /* Debug flag */ +extern int kdebugflag; /* Tell kernel to print debug messages */ +extern int default_device; /* Using /dev/tty or equivalent */ +extern char devnam[]; /* Device name */ +extern int crtscts; /* Use hardware flow control */ +extern int modem; /* Use modem control lines */ +extern int inspeed; /* Input/Output speed requested */ +extern u_int32_t netmask; /* IP netmask to set on interface */ +extern int lockflag; /* Create lock file to lock the serial dev */ +extern int nodetach; /* Don't detach from controlling tty */ +extern char *connector; /* Script to establish physical link */ +extern char *disconnector; /* Script to disestablish physical link */ +extern char user[]; /* Username for PAP */ +extern char passwd[]; /* Password for PAP */ +extern int auth_required; /* Peer is required to authenticate */ +extern int proxyarp; /* Set up proxy ARP entry for peer */ +extern int persist; /* Reopen link after it goes down */ +extern int uselogin; /* Use /etc/passwd for checking PAP */ +extern int lcp_echo_interval; /* Interval between LCP echo-requests */ +extern int lcp_echo_fails; /* Tolerance to unanswered echo-requests */ +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 char *ipparam; /* Extra parameter for ip up/down scripts */ +extern int cryptpap; /* Others' PAP passwords are encrypted */ /* * Values for phase. @@ -63,21 +98,21 @@ extern int phase; /* See values below */ /* * Prototypes. */ -void quit __ARGS((void)); /* Cleanup and exit */ -void timeout __ARGS((void (*)(), caddr_t, int)); +void quit __P((void)); /* Cleanup and exit */ +void timeout __P((void (*)(), caddr_t, int)); /* Look-alike of kernel's timeout() */ -void untimeout __ARGS((void (*)(), caddr_t)); +void untimeout __P((void (*)(), caddr_t)); /* Look-alike of kernel's untimeout() */ -void output __ARGS((int, u_char *, int)); +void output __P((int, u_char *, int)); /* Output a PPP packet */ -void demuxprotrej __ARGS((int, int)); +void demuxprotrej __P((int, int)); /* Demultiplex a Protocol-Reject */ -int check_passwd __ARGS((int, char *, int, char *, int, char **, int *)); +int check_passwd __P((int, char *, int, char *, int, char **, int *)); /* Check peer-supplied username/password */ -int get_secret __ARGS((int, char *, char *, char *, int *, int)); +int get_secret __P((int, char *, char *, char *, int *, int)); /* get "secret" for chap */ -u_long GetMask __ARGS((u_long)); /* get netmask for address */ - +u_int32_t GetMask __P((u_int32_t)); /* get netmask for address */ +void die __P((int)); /* * Inline versions of get/put char/short/long. @@ -118,6 +153,11 @@ u_long GetMask __ARGS((u_long)); /* get netmask for address */ #define INCPTR(n, cp) ((cp) += (n)) #define DECPTR(n, cp) ((cp) -= (n)) +#undef FALSE +#define FALSE 0 +#undef TRUE +#define TRUE 1 + /* * System dependent definitions for user-level 4.3BSD UNIX implementation. */ @@ -137,8 +177,8 @@ u_long GetMask __ARGS((u_long)); /* get netmask for address */ * MAKEHEADER - Add Header fields to a packet. */ #define MAKEHEADER(p, t) { \ - PUTCHAR(ALLSTATIONS, p); \ - PUTCHAR(UI, p); \ + PUTCHAR(PPP_ALLSTATIONS, p); \ + PUTCHAR(PPP_UI, p); \ PUTSHORT(t, p); } @@ -154,7 +194,7 @@ u_long GetMask __ARGS((u_long)); /* get netmask for address */ #ifndef LOG_PPP /* we use LOG_LOCAL2 for syslog by default */ #if defined(DEBUGMAIN) || defined(DEBUGFSM) || defined(DEBUG) \ || defined(DEBUGLCP) || defined(DEBUGIPCP) || defined(DEBUGUPAP) \ - || defined(DEBUGCHAP) + || defined(DEBUGCHAP) #define LOG_PPP LOG_LOCAL2 #else #define LOG_PPP LOG_DAEMON diff --git a/usr.sbin/pppd/sys-bsd.c b/usr.sbin/pppd/sys-bsd.c index 1539ee853ca3..eea6125b3352 100644 --- a/usr.sbin/pppd/sys-bsd.c +++ b/usr.sbin/pppd/sys-bsd.c @@ -19,21 +19,28 @@ */ #ifndef lint -static char rcsid[] = "$Id: sys-bsd.c,v 1.3 1995/05/30 03:51:16 rgrimes Exp $"; +static char rcsid[] = "$Id: sys-bsd.c,v 1.21 1995/08/16 01:40:23 paulus Exp $"; #endif /* * TODO: */ +#include <stdio.h> #include <syslog.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <fcntl.h> +#include <termios.h> #include <sys/ioctl.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/time.h> -#include <sys/errno.h> +#include <sys/stat.h> #include <net/if.h> +#include <net/ppp_defs.h> #include <net/if_ppp.h> #include <net/route.h> #include <net/if_dl.h> @@ -44,12 +51,75 @@ static char rcsid[] = "$Id: sys-bsd.c,v 1.3 1995/05/30 03:51:16 rgrimes Exp $"; #endif #include "pppd.h" -#include "ppp.h" -static int initdisc = -1; /* Initial TTY discipline */ -extern int kdebugflag; +static int initdisc = -1; /* Initial TTY discipline */ static int rtm_seq; +static int restore_term; /* 1 => we've munged the terminal */ +static struct termios inittermios; /* Initial TTY termios */ +static struct winsize wsinfo; /* Initial window size info */ + +static char *lock_file; /* name of lock file created */ + +int sockfd; /* socket for doing interface ioctls */ + +/* + * sys_init - System-dependent initialization. + */ +void +sys_init() +{ + openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP); + setlogmask(LOG_UPTO(LOG_INFO)); + if (debug) + setlogmask(LOG_UPTO(LOG_DEBUG)); + + /* Get an internet socket for doing socket ioctl's on. */ + if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + syslog(LOG_ERR, "Couldn't create IP socket: %m"); + die(1); + } +} + +/* + * note_debug_level - note a change in the debug level. + */ +void +note_debug_level() +{ + if (debug) { + syslog(LOG_INFO, "Debug turned ON, Level %d", debug); + setlogmask(LOG_UPTO(LOG_DEBUG)); + } else { + setlogmask(LOG_UPTO(LOG_WARNING)); + } +} + +/* + * ppp_available - check whether the system has any ppp interfaces + * (in fact we check whether we can do an ioctl on ppp0). + */ +int +ppp_available() +{ + int s, ok; + struct ifreq ifr; + extern char *no_ppp_msg; + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + return 1; /* can't tell */ + + strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name)); + ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0; + close(s); + + no_ppp_msg = "\ +This system lacks kernel support for PPP. To include PPP support\n\ +in the kernel, please follow the steps detailed in the README.bsd\n\ +file in the ppp-2.2 distribution.\n"; + return ok; +} + /* * establish_ppp - Turn the serial port into a ppp interface. */ @@ -71,7 +141,7 @@ establish_ppp() /* * Find out which interface we were given. */ - if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) { + if (ioctl(fd, PPPIOCGUNIT, &ifunit) < 0) { syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m"); die(1); } @@ -133,6 +203,111 @@ disestablish_ppp() /* + * 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 + * regardless of whether the modem option was specified. + * + * For *BSD, we assume that speed_t values numerically equal bits/second. + */ +set_up_tty(fd, local) + int fd, local; +{ + struct termios tios; + + if (tcgetattr(fd, &tios) < 0) { + syslog(LOG_ERR, "tcgetattr: %m"); + die(1); + } + + if (!restore_term) { + inittermios = tios; + ioctl(fd, TIOCGWINSZ, &wsinfo); + } + + tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL); + if (crtscts > 0) + tios.c_cflag |= CRTSCTS; + else if (crtscts < 0) + tios.c_cflag &= ~CRTSCTS; + + tios.c_cflag |= CS8 | CREAD | HUPCL; + if (local || !modem) + tios.c_cflag |= CLOCAL; + tios.c_iflag = IGNBRK | IGNPAR; + tios.c_oflag = 0; + tios.c_lflag = 0; + tios.c_cc[VMIN] = 1; + tios.c_cc[VTIME] = 0; + + if (crtscts == 2) { + tios.c_iflag |= IXOFF; + tios.c_cc[VSTOP] = 0x13; /* DC3 = XOFF = ^S */ + tios.c_cc[VSTART] = 0x11; /* DC1 = XON = ^Q */ + } + + if (inspeed) { + cfsetospeed(&tios, inspeed); + cfsetispeed(&tios, inspeed); + } else { + inspeed = cfgetospeed(&tios); + /* + * We can't proceed if the serial port speed is 0, + * since that implies that the serial port is disabled. + */ + if (inspeed == 0) { + syslog(LOG_ERR, "Baud rate for %s is 0; need explicit baud rate", + devnam); + die(1); + } + } + baud_rate = inspeed; + + if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { + syslog(LOG_ERR, "tcsetattr: %m"); + die(1); + } + + restore_term = 1; +} + +/* + * restore_tty - restore the terminal to the saved settings. + */ +void +restore_tty() +{ + if (restore_term) { + if (!default_device) { + /* + * Turn off echoing, because otherwise we can get into + * a loop with the tty and the modem echoing to each other. + * We presume we are the sole user of this tty device, so + * when we close it, it will revert to its defaults anyway. + */ + inittermios.c_lflag &= ~(ECHO | ECHONL); + } + if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) + if (errno != ENXIO) + syslog(LOG_WARNING, "tcsetattr: %m"); + ioctl(fd, TIOCSWINSZ, &wsinfo); + restore_term = 0; + } +} + +/* + * setdtr - control the DTR line on the serial port. + * This is called from die(), so it shouldn't call die(). + */ +setdtr(fd, on) +int fd, on; +{ + int modembits = TIOCM_DTR; + + ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits); +} + + +/* * output - Output PPP packet. */ void @@ -154,6 +329,27 @@ output(unit, p, len) /* + * wait_input - wait until there is data available on fd, + * for the length of time specified by *timo (indefinite + * if timo is NULL). + */ +wait_input(timo) + struct timeval *timo; +{ + fd_set ready; + int n; + + FD_ZERO(&ready); + FD_SET(fd, &ready); + n = select(fd+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. */ int @@ -162,11 +358,9 @@ read_packet(buf) { int len; - if ((len = read(fd, buf, MTU + DLLHEADERLEN)) < 0) { - if (errno == EWOULDBLOCK) { - MAINDEBUG((LOG_DEBUG, "read(fd): EWOULDBLOCK")); + if ((len = read(fd, buf, PPP_MTU + PPP_HDRLEN)) < 0) { + if (errno == EWOULDBLOCK || errno == EINTR) return -1; - } syslog(LOG_ERR, "read(fd): %m"); die(1); } @@ -181,7 +375,7 @@ read_packet(buf) void ppp_send_config(unit, mtu, asyncmap, pcomp, accomp) int unit, mtu; - u_long asyncmap; + u_int32_t asyncmap; int pcomp, accomp; { u_int x; @@ -189,7 +383,7 @@ ppp_send_config(unit, mtu, asyncmap, pcomp, accomp) strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); ifr.ifr_mtu = mtu; - if (ioctl(s, SIOCSIFMTU, (caddr_t) &ifr) < 0) { + if (ioctl(sockfd, SIOCSIFMTU, (caddr_t) &ifr) < 0) { syslog(LOG_ERR, "ioctl(SIOCSIFMTU): %m"); quit(); } @@ -232,7 +426,7 @@ ppp_set_xaccm(unit, accm) void ppp_recv_config(unit, mru, asyncmap, pcomp, accomp) int unit, mru; - u_long asyncmap; + u_int32_t asyncmap; int pcomp, accomp; { int x; @@ -257,6 +451,59 @@ ppp_recv_config(unit, mru, asyncmap, pcomp, accomp) } /* + * ccp_test - ask kernel whether a given compression method + * is acceptable for use. + */ +ccp_test(unit, opt_ptr, opt_len, for_transmit) + int unit, opt_len, for_transmit; + u_char *opt_ptr; +{ + struct ppp_option_data data; + + data.ptr = opt_ptr; + data.length = opt_len; + data.transmit = for_transmit; + return ioctl(fd, PPPIOCSCOMPRESS, (caddr_t) &data) >= 0; +} + +/* + * ccp_flags_set - inform kernel about the current state of CCP. + */ +void +ccp_flags_set(unit, isopen, isup) + int unit, isopen, isup; +{ + int x; + + if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { + syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m"); + return; + } + x = isopen? x | SC_CCP_OPEN: x &~ SC_CCP_OPEN; + x = isup? x | SC_CCP_UP: x &~ SC_CCP_UP; + if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) + syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); +} + +/* + * ccp_fatal_error - returns 1 if decompression was disabled as a + * result of an error detected after decompression of a packet, + * 0 otherwise. This is necessary because of patent nonsense. + */ +int +ccp_fatal_error(unit) + int unit; +{ + int x; + + if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { + syslog(LOG_ERR, "ioctl(PPPIOCGFLAGS): %m"); + return 0; + } + return x & SC_DC_FERROR; +} + +/* * sifvjcomp - config tcp header compression */ int @@ -285,31 +532,45 @@ 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)); - if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { + if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m"); return 0; } ifr.ifr_flags |= IFF_UP; - if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { + if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m"); return 0; } - 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; + 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; + } } return 1; } @@ -324,25 +585,37 @@ sifdown(u) struct ifreq ifr; u_int x; int rv; + struct npioctl npi; rv = 1; - 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"); + 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; + } + } } } + strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); - if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { + if (ioctl(sockfd, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m"); rv = 0; } else { ifr.ifr_flags &= ~IFF_UP; - if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { + if (ioctl(sockfd, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m"); rv = 0; } @@ -365,7 +638,7 @@ sifdown(u) int sifaddr(u, o, h, m) int u; - u_long o, h, m; + u_int32_t o, h, m; { struct ifaliasreq ifra; @@ -379,7 +652,7 @@ sifaddr(u, o, h, m) ((struct sockaddr_in *) &ifra.ifra_mask)->sin_addr.s_addr = m; } else BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask)); - if (ioctl(s, SIOCAIFADDR, (caddr_t) &ifra) < 0) { + if (ioctl(sockfd, SIOCAIFADDR, (caddr_t) &ifra) < 0) { if (errno != EEXIST) { syslog(LOG_ERR, "ioctl(SIOCAIFADDR): %m"); return 0; @@ -396,7 +669,7 @@ sifaddr(u, o, h, m) int cifaddr(u, o, h) int u; - u_long o, h; + u_int32_t o, h; { struct ifaliasreq ifra; @@ -406,21 +679,20 @@ cifaddr(u, o, h) SET_SA_FAMILY(ifra.ifra_broadaddr, AF_INET); ((struct sockaddr_in *) &ifra.ifra_broadaddr)->sin_addr.s_addr = h; BZERO(&ifra.ifra_mask, sizeof(ifra.ifra_mask)); - if (ioctl(s, SIOCDIFADDR, (caddr_t) &ifra) < 0) { + if (ioctl(sockfd, SIOCDIFADDR, (caddr_t) &ifra) < 0) { syslog(LOG_WARNING, "ioctl(SIOCDIFADDR): %m"); return 0; } return 1; } - /* * sifdefaultroute - assign a default route through the address given. */ int sifdefaultroute(u, g) int u; - u_long g; + u_int32_t g; { return dodefaultroute(g, 's'); } @@ -431,7 +703,7 @@ sifdefaultroute(u, g) int cifdefaultroute(u, g) int u; - u_long g; + u_int32_t g; { return dodefaultroute(g, 'c'); } @@ -441,7 +713,7 @@ cifdefaultroute(u, g) */ int dodefaultroute(g, cmd) - u_long g; + u_int32_t g; int cmd; { int routes; @@ -499,7 +771,7 @@ static int arpmsg_valid; int sifproxyarp(unit, hisaddr) int unit; - u_long hisaddr; + u_int32_t hisaddr; { int routes; int l; @@ -549,7 +821,7 @@ sifproxyarp(unit, hisaddr) int cifproxyarp(unit, hisaddr) int unit; - u_long hisaddr; + u_int32_t hisaddr; { int routes; @@ -583,7 +855,7 @@ cifproxyarp(unit, hisaddr) int sifproxyarp(unit, hisaddr) int unit; - u_long hisaddr; + u_int32_t hisaddr; { struct arpreq arpreq; struct { @@ -608,7 +880,7 @@ sifproxyarp(unit, hisaddr) SET_SA_FAMILY(arpreq.arp_pa, AF_INET); ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr; arpreq.arp_flags = ATF_PERM | ATF_PUBL; - if (ioctl(s, SIOCSARP, (caddr_t)&arpreq) < 0) { + if (ioctl(sockfd, SIOCSARP, (caddr_t)&arpreq) < 0) { syslog(LOG_ERR, "ioctl(SIOCSARP): %m"); return 0; } @@ -622,14 +894,14 @@ sifproxyarp(unit, hisaddr) int cifproxyarp(unit, hisaddr) int unit; - u_long hisaddr; + u_int32_t hisaddr; { struct arpreq arpreq; BZERO(&arpreq, sizeof(arpreq)); SET_SA_FAMILY(arpreq.arp_pa, AF_INET); ((struct sockaddr_in *) &arpreq.arp_pa)->sin_addr.s_addr = hisaddr; - if (ioctl(s, SIOCDARP, (caddr_t)&arpreq) < 0) { + if (ioctl(sockfd, SIOCDARP, (caddr_t)&arpreq) < 0) { syslog(LOG_WARNING, "ioctl(SIOCDARP): %m"); return 0; } @@ -639,12 +911,6 @@ cifproxyarp(unit, hisaddr) /* - * How to find the next ifreq structure in the stuff returned by SIOCGIFCONF. - */ -#define next_ifreq(ifr) \ - ((struct ifreq *) ((char *)&(ifr)->ifr_addr + (ifr)->ifr_addr.sa_len)) - -/* * get_ether_addr - get the hardware address of an interface on the * the same subnet as ipaddr. */ @@ -652,11 +918,11 @@ cifproxyarp(unit, hisaddr) int get_ether_addr(ipaddr, hwaddr) - u_long ipaddr; + u_int32_t ipaddr; struct sockaddr_dl *hwaddr; { struct ifreq *ifr, *ifend, *ifp; - u_long ina, mask; + u_int32_t ina, mask; struct sockaddr_dl *dla; struct ifreq ifreq; struct ifconf ifc; @@ -664,7 +930,7 @@ get_ether_addr(ipaddr, hwaddr) ifc.ifc_len = sizeof(ifs); ifc.ifc_req = ifs; - if (ioctl(s, SIOCGIFCONF, &ifc) < 0) { + if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { syslog(LOG_ERR, "ioctl(SIOCGIFCONF): %m"); return 0; } @@ -674,7 +940,8 @@ get_ether_addr(ipaddr, hwaddr) * address on the same subnet as `ipaddr'. */ ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); - for (ifr = ifc.ifc_req; ifr < ifend; ifr = next_ifreq(ifr)) { + for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *) + ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) { if (ifr->ifr_addr.sa_family == AF_INET) { ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr; strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); @@ -682,7 +949,7 @@ get_ether_addr(ipaddr, hwaddr) * Check that the interface is up, and not point-to-point * or loopback. */ - if (ioctl(s, SIOCGIFFLAGS, &ifreq) < 0) + if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0) continue; if ((ifreq.ifr_flags & (IFF_UP|IFF_BROADCAST|IFF_POINTOPOINT|IFF_LOOPBACK|IFF_NOARP)) @@ -691,7 +958,7 @@ get_ether_addr(ipaddr, hwaddr) /* * Get its netmask and check that it's on the right subnet. */ - if (ioctl(s, SIOCGIFNETMASK, &ifreq) < 0) + if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0) continue; mask = ((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr.s_addr; if ((ipaddr & mask) != (ina & mask)) @@ -710,7 +977,7 @@ get_ether_addr(ipaddr, hwaddr) * for this interface. */ ifp = ifr; - for (ifr = ifc.ifc_req; ifr < ifend; ifr = next_ifreq(ifr)) { + for (ifr = ifc.ifc_req; ifr < ifend; ) { if (strcmp(ifp->ifr_name, ifr->ifr_name) == 0 && ifr->ifr_addr.sa_family == AF_LINK) { /* @@ -720,28 +987,149 @@ get_ether_addr(ipaddr, hwaddr) BCOPY(dla, hwaddr, dla->sdl_len); return 1; } + ifr = (struct ifreq *) ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len); } return 0; } +/* + * Return user specified netmask, modified by any mask we might determine + * for address `addr' (in network byte order). + * Here we scan through the system's list of interfaces, looking for + * any non-point-to-point interfaces which might appear to be on the same + * network as `addr'. If we find any, we OR in their netmask to the + * user-specified netmask. + */ +u_int32_t +GetMask(addr) + u_int32_t addr; +{ + u_int32_t mask, nmask, ina; + struct ifreq *ifr, *ifend, ifreq; + struct ifconf ifc; + struct ifreq ifs[MAX_IFS]; + + addr = ntohl(addr); + if (IN_CLASSA(addr)) /* determine network mask for address class */ + nmask = IN_CLASSA_NET; + else if (IN_CLASSB(addr)) + nmask = IN_CLASSB_NET; + else + nmask = IN_CLASSC_NET; + /* class D nets are disallowed by bad_ip_adrs */ + mask = netmask | htonl(nmask); + + /* + * Scan through the system's network interfaces. + */ + ifc.ifc_len = sizeof(ifs); + ifc.ifc_req = ifs; + if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { + syslog(LOG_WARNING, "ioctl(SIOCGIFCONF): %m"); + return mask; + } + ifend = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); + for (ifr = ifc.ifc_req; ifr < ifend; ifr = (struct ifreq *) + ((char *)&ifr->ifr_addr + ifr->ifr_addr.sa_len)) { + /* + * Check the interface's internet address. + */ + if (ifr->ifr_addr.sa_family != AF_INET) + continue; + ina = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr.s_addr; + if ((ntohl(ina) & nmask) != (addr & nmask)) + continue; + /* + * Check that the interface is up, and not point-to-point or loopback. + */ + strncpy(ifreq.ifr_name, ifr->ifr_name, sizeof(ifreq.ifr_name)); + if (ioctl(sockfd, SIOCGIFFLAGS, &ifreq) < 0) + continue; + if ((ifreq.ifr_flags & (IFF_UP|IFF_POINTOPOINT|IFF_LOOPBACK)) + != IFF_UP) + continue; + /* + * Get its netmask and OR it into our mask. + */ + if (ioctl(sockfd, SIOCGIFNETMASK, &ifreq) < 0) + continue; + mask |= ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr.s_addr; + } + + return mask; +} /* - * ppp_available - check whether the system has any ppp interfaces - * (in fact we check whether we can do an ioctl on ppp0). + * lock - create a lock file for the named lock device */ +#define LOCK_PREFIX "/var/spool/lock/LCK.." + int -ppp_available() +lock(dev) + char *dev; { - int s, ok; - struct ifreq ifr; + char hdb_lock_buffer[12]; + int fd, pid, n; + char *p; + + if ((p = strrchr(dev, '/')) != NULL) + dev = p + 1; + lock_file = malloc(strlen(LOCK_PREFIX) + strlen(dev) + 1); + if (lock_file == NULL) + novm("lock file name"); + strcat(strcpy(lock_file, LOCK_PREFIX), dev); + + while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { + if (errno == EEXIST + && (fd = open(lock_file, O_RDONLY, 0)) >= 0) { + /* Read the lock file to find out who has the device locked */ + n = read(fd, hdb_lock_buffer, 11); + if (n > 0) { + hdb_lock_buffer[n] = 0; + pid = atoi(hdb_lock_buffer); + } + if (n <= 0) { + syslog(LOG_ERR, "Can't read pid from lock file %s", lock_file); + close(fd); + } else { + if (kill(pid, 0) == -1 && errno == ESRCH) { + /* pid no longer exists - remove the lock file */ + if (unlink(lock_file) == 0) { + close(fd); + syslog(LOG_NOTICE, "Removed stale lock on %s (pid %d)", + dev, pid); + continue; + } else + syslog(LOG_WARNING, "Couldn't remove stale lock on %s", + dev); + } else + syslog(LOG_NOTICE, "Device %s is locked by pid %d", + dev, pid); + } + close(fd); + } else + syslog(LOG_ERR, "Can't create lock file %s: %m", lock_file); + free(lock_file); + lock_file = NULL; + return -1; + } - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - return 1; /* can't tell - maybe we're not root */ + sprintf(hdb_lock_buffer, "%10d\n", getpid()); + write(fd, hdb_lock_buffer, 11); - strncpy(ifr.ifr_name, "ppp0", sizeof (ifr.ifr_name)); - ok = ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) >= 0; - close(s); + close(fd); + return 0; +} - return ok; +/* + * unlock - remove our lockfile + */ +unlock() +{ + if (lock_file) { + unlink(lock_file); + free(lock_file); + lock_file = NULL; + } } diff --git a/usr.sbin/pppd/upap.c b/usr.sbin/pppd/upap.c index 14b2e767b10e..aed4a7b0e1a5 100644 --- a/usr.sbin/pppd/upap.c +++ b/usr.sbin/pppd/upap.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: upap.c,v 1.2 1994/09/25 02:32:16 wollman Exp $"; +static char rcsid[] = "$Id: upap.c,v 1.6 1995/06/12 12:02:24 paulus Exp $"; #endif /* @@ -26,24 +26,25 @@ static char rcsid[] = "$Id: upap.c,v 1.2 1994/09/25 02:32:16 wollman Exp $"; */ #include <stdio.h> +#include <string.h> #include <sys/types.h> #include <sys/time.h> #include <syslog.h> -#include "ppp.h" #include "pppd.h" #include "upap.h" -upap_state upap[NPPP]; /* UPAP state; one for each unit */ +upap_state upap[NUM_PPP]; /* UPAP state; one for each unit */ -static void upap_timeout __ARGS((caddr_t)); -static void upap_rauthreq __ARGS((upap_state *, u_char *, int, int)); -static void upap_rauthack __ARGS((upap_state *, u_char *, int, int)); -static void upap_rauthnak __ARGS((upap_state *, u_char *, int, int)); -static void upap_sauthreq __ARGS((upap_state *)); -static void upap_sresp __ARGS((upap_state *, int, int, char *, int)); +static void upap_timeout __P((caddr_t)); +static void upap_reqtimeout __P((caddr_t)); +static void upap_rauthreq __P((upap_state *, u_char *, int, int)); +static void upap_rauthack __P((upap_state *, u_char *, int, int)); +static void upap_rauthnak __P((upap_state *, u_char *, int, int)); +static void upap_sauthreq __P((upap_state *)); +static void upap_sresp __P((upap_state *, int, int, char *, int)); /* @@ -65,6 +66,7 @@ upap_init(unit) u->us_id = 0; u->us_timeouttime = UPAP_DEFTIMEOUT; u->us_maxtransmits = 10; + u->us_reqtimeout = UPAP_DEFREQTIME; } @@ -117,11 +119,13 @@ upap_authpeer(unit) } u->us_serverstate = UPAPSS_LISTEN; + if (u->us_reqtimeout > 0) + TIMEOUT(upap_reqtimeout, (caddr_t) u, u->us_reqtimeout); } /* - * upap_timeout - Timeout expired. + * upap_timeout - Retransmission timer for sending auth-reqs expired. */ static void upap_timeout(arg) @@ -136,7 +140,7 @@ upap_timeout(arg) /* give up in disgust */ syslog(LOG_ERR, "No response to PAP authenticate-requests"); u->us_clientstate = UPAPCS_BADAUTH; - auth_withpeer_fail(u->us_unit, UPAP); + auth_withpeer_fail(u->us_unit, PPP_PAP); return; } @@ -145,6 +149,23 @@ upap_timeout(arg) /* + * upap_reqtimeout - Give up waiting for the peer to send an auth-req. + */ +static void +upap_reqtimeout(arg) + caddr_t arg; +{ + upap_state *u = (upap_state *) arg; + + if (u->us_serverstate != UPAPSS_LISTEN) + return; /* huh?? */ + + auth_peer_fail(u->us_unit, PPP_PAP); + u->us_serverstate = UPAPSS_BADAUTH; +} + + +/* * upap_lowerup - The lower layer is up. * * Start authenticating if pending. @@ -163,8 +184,11 @@ upap_lowerup(unit) if (u->us_serverstate == UPAPSS_INITIAL) u->us_serverstate = UPAPSS_CLOSED; - else if (u->us_serverstate == UPAPSS_PENDING) + else if (u->us_serverstate == UPAPSS_PENDING) { u->us_serverstate = UPAPSS_LISTEN; + if (u->us_reqtimeout > 0) + TIMEOUT(upap_reqtimeout, (caddr_t) u, u->us_reqtimeout); + } } @@ -179,8 +203,10 @@ upap_lowerdown(unit) { upap_state *u = &upap[unit]; - if (u->us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */ + if (u->us_clientstate == UPAPCS_AUTHREQ) /* Timeout pending? */ UNTIMEOUT(upap_timeout, (caddr_t) u); /* Cancel timeout */ + if (u->us_serverstate == UPAPSS_LISTEN && u->us_reqtimeout > 0) + UNTIMEOUT(upap_reqtimeout, (caddr_t) u); u->us_clientstate = UPAPCS_INITIAL; u->us_serverstate = UPAPSS_INITIAL; @@ -200,11 +226,11 @@ upap_protrej(unit) if (u->us_clientstate == UPAPCS_AUTHREQ) { syslog(LOG_ERR, "PAP authentication failed due to protocol-reject"); - auth_withpeer_fail(unit, UPAP); + auth_withpeer_fail(unit, PPP_PAP); } if (u->us_serverstate == UPAPSS_LISTEN) { syslog(LOG_ERR, "PAP authentication of peer failed (protocol-reject)"); - auth_peer_fail(unit, UPAP); + auth_peer_fail(unit, PPP_PAP); } upap_lowerdown(unit); } @@ -334,11 +360,14 @@ upap_rauthreq(u, inp, id, len) if (retcode == UPAP_AUTHACK) { u->us_serverstate = UPAPSS_OPEN; - auth_peer_success(u->us_unit, UPAP); + auth_peer_success(u->us_unit, PPP_PAP); } else { u->us_serverstate = UPAPSS_BADAUTH; - auth_peer_fail(u->us_unit, UPAP); + auth_peer_fail(u->us_unit, PPP_PAP); } + + if (u->us_reqtimeout > 0) + UNTIMEOUT(upap_reqtimeout, (caddr_t) u); } @@ -377,7 +406,7 @@ upap_rauthack(u, inp, id, len) u->us_clientstate = UPAPCS_OPEN; - auth_withpeer_success(u->us_unit, UPAP); + auth_withpeer_success(u->us_unit, PPP_PAP); } @@ -417,7 +446,7 @@ upap_rauthnak(u, inp, id, len) u->us_clientstate = UPAPCS_BADAUTH; syslog(LOG_ERR, "PAP authentication failed"); - auth_withpeer_fail(u->us_unit, UPAP); + auth_withpeer_fail(u->us_unit, PPP_PAP); } @@ -434,8 +463,8 @@ upap_sauthreq(u) outlen = UPAP_HEADERLEN + 2 * sizeof (u_char) + u->us_userlen + u->us_passwdlen; outp = outpacket_buf; - - MAKEHEADER(outp, UPAP); + + MAKEHEADER(outp, PPP_PAP); PUTCHAR(UPAP_AUTHREQ, outp); PUTCHAR(++u->us_id, outp); @@ -446,7 +475,7 @@ upap_sauthreq(u) PUTCHAR(u->us_passwdlen, outp); BCOPY(u->us_passwd, outp, u->us_passwdlen); - output(u->us_unit, outpacket_buf, outlen + DLLHEADERLEN); + output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN); UPAPDEBUG((LOG_INFO, "upap_sauth: Sent id %d.", u->us_id)); @@ -471,14 +500,14 @@ upap_sresp(u, code, id, msg, msglen) outlen = UPAP_HEADERLEN + sizeof (u_char) + msglen; outp = outpacket_buf; - MAKEHEADER(outp, UPAP); + MAKEHEADER(outp, PPP_PAP); PUTCHAR(code, outp); PUTCHAR(id, outp); PUTSHORT(outlen, outp); PUTCHAR(msglen, outp); BCOPY(msg, outp, msglen); - output(u->us_unit, outpacket_buf, outlen + DLLHEADERLEN); + output(u->us_unit, outpacket_buf, outlen + PPP_HDRLEN); UPAPDEBUG((LOG_INFO, "upap_sresp: Sent code %d, id %d.", code, id)); } @@ -494,7 +523,7 @@ int upap_printpkt(p, plen, printer, arg) u_char *p; int plen; - void (*printer) __ARGS((void *, char *, ...)); + void (*printer) __P((void *, char *, ...)); void *arg; { int code, id, len; diff --git a/usr.sbin/pppd/upap.h b/usr.sbin/pppd/upap.h index 10c3414a0afa..8b1501964ad2 100644 --- a/usr.sbin/pppd/upap.h +++ b/usr.sbin/pppd/upap.h @@ -16,7 +16,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: upap.h,v 1.2 1994/04/11 07:13:44 paulus Exp $ + * $Id: upap.h,v 1.4 1995/06/12 12:02:25 paulus Exp $ */ /* @@ -45,9 +45,10 @@ typedef struct upap_state { int us_clientstate; /* Client state */ int us_serverstate; /* Server state */ u_char us_id; /* Current id */ - int us_timeouttime; /* Timeout time in milliseconds */ + int us_timeouttime; /* Timeout (seconds) for auth-req retrans. */ int us_transmits; /* Number of auth-reqs sent */ int us_maxtransmits; /* Maximum number of auth-reqs to send */ + int us_reqtimeout; /* Time to wait for auth-req from peer */ } upap_state; @@ -75,17 +76,18 @@ typedef struct upap_state { /* * Timeouts. */ -#define UPAP_DEFTIMEOUT 3 /* Timeout time in seconds */ +#define UPAP_DEFTIMEOUT 3 /* Timeout (seconds) for retransmitting req */ +#define UPAP_DEFREQTIME 30 /* Time to wait for auth-req from peer */ extern upap_state upap[]; -void upap_init __ARGS((int)); -void upap_authwithpeer __ARGS((int, char *, char *)); -void upap_authpeer __ARGS((int)); -void upap_lowerup __ARGS((int)); -void upap_lowerdown __ARGS((int)); -void upap_input __ARGS((int, u_char *, int)); -void upap_protrej __ARGS((int)); -int upap_printpkt __ARGS((u_char *, int, - void (*) __ARGS((void *, char *, ...)), void *)); +void upap_init __P((int)); +void upap_authwithpeer __P((int, char *, char *)); +void upap_authpeer __P((int)); +void upap_lowerup __P((int)); +void upap_lowerdown __P((int)); +void upap_input __P((int, u_char *, int)); +void upap_protrej __P((int)); +int upap_printpkt __P((u_char *, int, + void (*) __P((void *, char *, ...)), void *)); |