From 1a4adaf687bc5c11dc28ddc7c40d257460a188b5 Mon Sep 17 00:00:00 2001 From: paulus Date: Sun, 8 May 1994 12:16:10 +0000 Subject: [PATCH] Latest version of pppd from ppp-2.1 release --- usr.sbin/pppd/Makefile | 4 +- usr.sbin/pppd/auth.c | 88 +++++- usr.sbin/pppd/chap.c | 71 ++++- usr.sbin/pppd/chap.h | 7 +- usr.sbin/pppd/fsm.c | 8 +- usr.sbin/pppd/fsm.h | 7 +- usr.sbin/pppd/ipcp.c | 159 ++++++++++- usr.sbin/pppd/ipcp.h | 3 +- usr.sbin/pppd/lcp.c | 150 +++++++++- usr.sbin/pppd/lcp.h | 13 +- usr.sbin/pppd/main.c | 466 ++++++++++++++++++++++---------- usr.sbin/pppd/options.c | 156 ++++++++--- usr.sbin/pppd/patchlevel.h | 8 +- usr.sbin/pppd/pathnames.h | 6 +- usr.sbin/pppd/pppd.8 | 122 ++++++--- usr.sbin/pppd/pppd.h | 18 +- usr.sbin/pppd/pppd/Makefile | 4 +- usr.sbin/pppd/pppd/auth.c | 88 +++++- usr.sbin/pppd/pppd/chap.c | 71 ++++- usr.sbin/pppd/pppd/chap.h | 7 +- usr.sbin/pppd/pppd/fsm.c | 8 +- usr.sbin/pppd/pppd/fsm.h | 7 +- usr.sbin/pppd/pppd/ipcp.c | 159 ++++++++++- usr.sbin/pppd/pppd/ipcp.h | 3 +- usr.sbin/pppd/pppd/lcp.c | 150 +++++++++- usr.sbin/pppd/pppd/lcp.h | 13 +- usr.sbin/pppd/pppd/main.c | 466 ++++++++++++++++++++++---------- usr.sbin/pppd/pppd/options.c | 156 ++++++++--- usr.sbin/pppd/pppd/patchlevel.h | 8 +- usr.sbin/pppd/pppd/pathnames.h | 6 +- usr.sbin/pppd/pppd/pppd.8 | 122 ++++++--- usr.sbin/pppd/pppd/pppd.h | 18 +- usr.sbin/pppd/pppd/sys-bsd.c | 135 +++++++-- usr.sbin/pppd/pppd/upap.c | 81 +++++- usr.sbin/pppd/pppd/upap.h | 4 +- usr.sbin/pppd/sys-bsd.c | 135 +++++++-- usr.sbin/pppd/upap.c | 81 +++++- usr.sbin/pppd/upap.h | 4 +- 38 files changed, 2442 insertions(+), 570 deletions(-) diff --git a/usr.sbin/pppd/Makefile b/usr.sbin/pppd/Makefile index d7fbfa149c97..294a34e1c4d6 100644 --- a/usr.sbin/pppd/Makefile +++ b/usr.sbin/pppd/Makefile @@ -1,8 +1,8 @@ -# $Id: Makefile,v 1.5 1993/11/10 01:33:51 paulus Exp $ +# $Id: Makefile,v 1.6 1994/05/08 12:16:10 paulus Exp $ PROG= pppd SRCS= main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c \ - auth.c options.c sys-bsd.c + auth.c options.c lock.c sys-bsd.c MAN8= pppd.0 SUBDIR= pppstats chat BINMODE=4555 diff --git a/usr.sbin/pppd/auth.c b/usr.sbin/pppd/auth.c index cdcd1f3abee8..d2faf5222c30 100644 --- a/usr.sbin/pppd/auth.c +++ b/usr.sbin/pppd/auth.c @@ -33,7 +33,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: auth.c,v 1.4 1994/01/25 05:58:02 paulus Exp $"; +static char rcsid[] = "$Id: auth.c,v 1.5 1994/05/08 12:16:13 paulus Exp $"; #endif #include @@ -106,6 +106,7 @@ 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 *)); @@ -135,11 +136,18 @@ link_terminated(unit) { if (logged_in) logout(); - if (lcp_wantoptions[unit].restart) { - lcp_lowerdown(unit); - lcp_lowerup(unit); - } else - EXIT(unit); + phase = PHASE_DEAD; + syslog(LOG_NOTICE, "Connection terminated."); +} + +/* + * LCP has gone down; it will either die or try to re-establish. + */ +void +link_down(unit) + int unit; +{ + phase = PHASE_TERMINATE; } /* @@ -157,14 +165,19 @@ link_established(unit) if (auth_required && !(go->neg_chap || go->neg_upap)) { /* - * We wanted the peer to authenticate himself, and he refused: - * tell him to go away. + * We wanted the peer to authenticate itself, and it refused: + * treat it as though it authenticated with PAP using a username + * of "" and a password of "". If that's not OK, boot it out. */ - syslog(LOG_WARNING, "peer refused to authenticate"); - lcp_close(unit); - return; + if (wo->neg_upap && !null_login(unit)) { + syslog(LOG_WARNING, "peer refused to authenticate"); + lcp_close(unit); + phase = PHASE_TERMINATE; + return; + } } + phase = PHASE_AUTHENTICATE; auth = 0; if (go->neg_chap) { ChapAuthPeer(unit, our_name, go->chap_mdtype); @@ -182,8 +195,10 @@ link_established(unit) } auth_pending[unit] = auth; - if (!auth) + if (!auth) { + phase = PHASE_NETWORK; ipcp_open(unit); + } } /* @@ -197,6 +212,7 @@ auth_peer_fail(unit, protocol) * Authentication failure: take the link down */ lcp_close(unit); + phase = PHASE_TERMINATE; } /* @@ -225,8 +241,10 @@ auth_peer_success(unit, protocol) * If there is no more authentication still to be done, * proceed to the network phase. */ - if ((auth_pending[unit] &= ~bit) == 0) + if ((auth_pending[unit] &= ~bit) == 0) { + phase = PHASE_NETWORK; ipcp_open(unit); + } } /* @@ -268,8 +286,10 @@ 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) + if ((auth_pending[unit] &= ~bit) == 0) { + phase = PHASE_NETWORK; ipcp_open(unit); + } } @@ -485,6 +505,46 @@ logout() } +/* + * null_login - Check if a username of "" and a password of "" are + * acceptable, and iff so, set the list of acceptable IP addresses + * and return 1. + */ +static int +null_login(unit) + int unit; +{ + char *filename; + FILE *f; + int i, ret; + struct wordlist *addrs; + char secret[MAXWORDLEN]; + + /* + * Open the file of upap secrets and scan for a suitable secret. + * We don't accept a wildcard client. + */ + filename = _PATH_UPAPFILE; + addrs = NULL; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + check_access(f, filename); + + i = scan_authfile(f, "", our_name, secret, &addrs, filename); + ret = i >= 0 && (i & NONWILD_CLIENT) != 0 && secret[0] == 0; + + if (ret) { + if (addresses[unit] != NULL) + free_wordlist(addresses[unit]); + addresses[unit] = addrs; + } + + fclose(f); + return ret; +} + + /* * get_upap_passwd - get a password for authenticating ourselves with * our peer using PAP. Returns 1 on success, 0 if no suitable password diff --git a/usr.sbin/pppd/chap.c b/usr.sbin/pppd/chap.c index 815ece43e994..f33464450beb 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.3 1993/11/10 01:33:59 paulus Exp $"; +static char rcsid[] = "$Id: chap.c,v 1.4 1994/05/08 12:16:15 paulus Exp $"; #endif /* @@ -557,6 +557,8 @@ ChapReceiveSuccess(cstate, inp, id, len) return; } + UNTIMEOUT(ChapResponseTimeout, (caddr_t) cstate); + /* * Print message. */ @@ -591,6 +593,8 @@ ChapReceiveFailure(cstate, inp, id, len) return; } + UNTIMEOUT(ChapResponseTimeout, (caddr_t) cstate); + /* * Print message. */ @@ -738,6 +742,71 @@ ChapSendResponse(cstate) ++cstate->resp_transmits; } +/* + * ChapPrintPkt - print the contents of a CHAP packet. + */ +char *ChapCodenames[] = { + "Challenge", "Response", "Success", "Failure" +}; + +int +ChapPrintPkt(p, plen, printer, arg) + u_char *p; + int plen; + void (*printer) __ARGS((void *, char *, ...)); + void *arg; +{ + int code, id, len; + int clen, nlen; + u_char x; + + if (plen < CHAP_HEADERLEN) + return 0; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < CHAP_HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *)) + printer(arg, " %s", ChapCodenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= CHAP_HEADERLEN; + switch (code) { + case CHAP_CHALLENGE: + case CHAP_RESPONSE: + if (len < 1) + break; + clen = p[0]; + if (len < clen + 1) + break; + ++p; + nlen = len - clen - 1; + printer(arg, " <"); + for (; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, "%.2x", x); + } + printer(arg, ">, name = "); + print_string((char *)p, nlen, printer, arg); + break; + case CHAP_FAILURE: + case CHAP_SUCCESS: + printer(arg, " "); + print_string((char *)p, len, printer, arg); + break; + default: + for (clen = len; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, " %.2x", x); + } + } + + return len + CHAP_HEADERLEN; +} + #ifdef NO_DRAND48 double drand48() diff --git a/usr.sbin/pppd/chap.h b/usr.sbin/pppd/chap.h index 5ac40bfc4295..218580de0ec7 100644 --- a/usr.sbin/pppd/chap.h +++ b/usr.sbin/pppd/chap.h @@ -1,6 +1,5 @@ /* * chap.h - Cryptographic Handshake Authentication Protocol definitions. - * based on November 1991 draft of PPP Authentication RFC * * Copyright (c) 1991 Gregory M. Christy * All rights reserved. @@ -16,13 +15,13 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: chap.h,v 1.3 1993/11/10 01:34:02 paulus Exp $ + * $Id: chap.h,v 1.4 1994/05/08 12:16:16 paulus Exp $ */ #ifndef __CHAP_INCLUDE__ /* Code + ID + length */ -#define CHAP_HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short)) +#define CHAP_HEADERLEN 4 /* * CHAP codes. @@ -106,6 +105,8 @@ 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 *)); #define __CHAP_INCLUDE__ #endif /* __CHAP_INCLUDE__ */ diff --git a/usr.sbin/pppd/fsm.c b/usr.sbin/pppd/fsm.c index c6d1b705374d..832332c5dfde 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.3 1993/11/10 01:34:04 paulus Exp $"; +static char rcsid[] = "$Id: fsm.c,v 1.4 1994/05/08 12:16:17 paulus Exp $"; #endif /* @@ -29,7 +29,6 @@ static char rcsid[] = "$Id: fsm.c,v 1.3 1993/11/10 01:34:04 paulus Exp $"; #include #include -/*#include */ #include #include "ppp.h" @@ -453,6 +452,7 @@ fsm_rconfack(f, id, inp, len) PROTO_NAME(f), len)); return; } + f->reqid = -1; switch (f->state) { case CLOSED: @@ -514,6 +514,7 @@ fsm_rconfnakrej(f, code, id, inp, len) PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len)); return; } + f->reqid = -1; switch (f->state) { case CLOSED: @@ -556,7 +557,6 @@ fsm_rtermreq(f, id) FSMDEBUG((LOG_INFO, "fsm_rtermreq(%s): Rcvd id %d.", PROTO_NAME(f), id)); - fsm_sdata(f, TERMACK, id, NULL, 0); switch (f->state) { case ACKRCVD: case ACKSENT: @@ -572,6 +572,8 @@ fsm_rtermreq(f, id) TIMEOUT(fsm_timeout, (caddr_t) f, f->timeouttime); break; } + + fsm_sdata(f, TERMACK, id, NULL, 0); } diff --git a/usr.sbin/pppd/fsm.h b/usr.sbin/pppd/fsm.h index 0b90190409a0..d6383906f9ca 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.3 1993/11/10 01:34:07 paulus Exp $ + * $Id: fsm.h,v 1.4 1994/05/08 12:16:18 paulus Exp $ */ /* @@ -35,11 +35,6 @@ #define TERMREQ 5 /* Termination Request */ #define TERMACK 6 /* Termination Ack */ #define CODEREJ 7 /* Code Reject */ -#define PROTREJ 8 /* Protocol Reject */ -#define ECHOREQ 9 /* Echo Request */ -#define ECHOREP 10 /* Echo Reply */ -#define DISCREQ 11 /* Discard Request */ -#define KEEPALIVE 12 /* Keepalive */ /* diff --git a/usr.sbin/pppd/ipcp.c b/usr.sbin/pppd/ipcp.c index 3906c47371e0..b95563a84faa 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.4 1994/02/22 00:11:57 paulus Exp $"; +static char rcsid[] = "$Id: ipcp.c,v 1.5 1994/05/08 12:16:19 paulus Exp $"; #endif /* @@ -43,7 +43,7 @@ static char rcsid[] = "$Id: ipcp.c,v 1.4 1994/02/22 00:11:57 paulus Exp $"; #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 */ @@ -51,6 +51,10 @@ 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; + /* local vars */ static int cis_received[NPPP]; /* # Conf-Reqs received */ @@ -66,7 +70,7 @@ 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 */ @@ -885,6 +889,10 @@ ipcp_reqci(f, inp, len, reject_if_disagree) } ho->maxslotindex = maxslotindex; ho->cflag = wo->cflag; + } else { + ho->old_vj = 1; + ho->maxslotindex = MAX_STATES - 1; + ho->cflag = 1; } break; @@ -988,7 +996,7 @@ ipcp_up(f) } /* - * Check that the peer is allowed to use the IP address he wants. + * Check that the peer is allowed to use the IP address it wants. */ if (!auth_ip_addr(f->unit, ho->hisaddr)) { syslog(LOG_ERR, "Peer is not authorized to use remote address %s", @@ -1011,7 +1019,7 @@ ipcp_up(f) } /* set tcp compression */ - sifvjcomp(f->unit, ho->neg_vj, ho->cflag); + sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex); /* bring the interface up for IP */ if (!sifup(f->unit)) { @@ -1029,6 +1037,13 @@ ipcp_up(f) if (ipcp_wantoptions[f->unit].proxy_arp) if (sifproxyarp(f->unit, ho->hisaddr)) go->proxy_arp = 1; + + /* + * Execute the ip-up script, like this: + * /etc/ppp/ip-up interface tty speed local-IP remote-IP + */ + ipcp_script(f, _PATH_IPUP); + } @@ -1054,4 +1069,138 @@ ipcp_down(f) cifdefaultroute(f->unit, hisaddr); sifdown(f->unit); cifaddr(f->unit, ouraddr, hisaddr); + + /* Execute the ip-down script */ + ipcp_script(f, _PATH_IPDOWN); +} + + +/* + * ipcp_script - Execute a script with arguments + * interface-name tty-name speed local-IP remote-IP. + */ +static void +ipcp_script(f, script) + fsm *f; + char *script; +{ + char strspeed[32], strlocal[32], strremote[32]; + char *argv[8]; + + sprintf(strspeed, "%d", baud_rate); + strcpy(strlocal, ip_ntoa(ipcp_gotoptions[f->unit].ouraddr)); + strcpy(strremote, ip_ntoa(ipcp_hisoptions[f->unit].hisaddr)); + + argv[0] = script; + argv[1] = ifname; + argv[2] = devname; + argv[3] = strspeed; + argv[4] = strlocal; + argv[5] = strremote; + argv[6] = NULL; + run_program(script, argv, 0); +} + +/* + * ipcp_printpkt - print the contents of an IPCP packet. + */ +char *ipcp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej" +}; + +int +ipcp_printpkt(p, plen, printer, arg) + u_char *p; + int plen; + void (*printer)(); + void *arg; +{ + int code, id, len, olen; + u_char *pstart, *optend; + u_short cishort; + u_long cilong; + + if (plen < HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= sizeof(ipcp_codenames) / sizeof(char *)) + printer(arg, " %s", ipcp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < 2 || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { + case CI_ADDRS: + if (olen == CILEN_ADDRS) { + p += 2; + GETLONG(cilong, p); + printer(arg, "addrs %s", ip_ntoa(htonl(cilong))); + GETLONG(cilong, p); + printer(arg, " %s", ip_ntoa(htonl(cilong))); + } + break; + case CI_COMPRESSTYPE: + if (olen >= CILEN_COMPRESS) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "compress "); + switch (cishort) { + case IPCP_VJ_COMP: + printer(arg, "VJ"); + break; + case IPCP_VJ_COMP_OLD: + printer(arg, "old-VJ"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_ADDR: + if (olen == CILEN_ADDR) { + p += 2; + GETLONG(cilong, p); + printer(arg, "addr %s", ip_ntoa(htonl(cilong))); + } + break; + } + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; } diff --git a/usr.sbin/pppd/ipcp.h b/usr.sbin/pppd/ipcp.h index a42ebd99bd4f..4d1381f725f7 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.4 1994/02/22 00:11:59 paulus Exp $ + * $Id: ipcp.h,v 1.5 1994/05/08 12:16:20 paulus Exp $ */ /* @@ -65,3 +65,4 @@ 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 *)); diff --git a/usr.sbin/pppd/lcp.c b/usr.sbin/pppd/lcp.c index 9d8d8363077f..24a01ebf7db4 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.3 1993/11/10 01:34:15 paulus Exp $"; +static char rcsid[] = "$Id: lcp.c,v 1.4 1994/05/08 12:16:22 paulus Exp $"; #endif /* @@ -55,6 +55,7 @@ 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 */ /* * Callbacks for fsm code. (CI = Configuration Information) @@ -129,7 +130,7 @@ lcp_init(unit) implementations */ wo->neg_mru = 1; wo->mru = DEFMRU; - wo->neg_asyncmap = 1; + wo->neg_asyncmap = 0; wo->asyncmap = 0; wo->neg_chap = 0; /* Set to 1 on server */ wo->neg_upap = 0; /* Set to 1 on server */ @@ -151,6 +152,8 @@ lcp_init(unit) ao->neg_accompression = 1; ao->neg_lqr = 0; /* no LQR implementation yet */ + memset(xmit_accm[unit], 0, sizeof(xmit_accm[0])); + xmit_accm[unit][3] = 0x60000000; } @@ -192,9 +195,11 @@ lcp_lowerup(unit) int unit; { sifdown(unit); + ppp_set_xaccm(unit, xmit_accm[unit]); ppp_send_config(unit, MTU, 0xffffffff, 0, 0); ppp_recv_config(unit, MTU, 0, 0, 0); peer_mru[unit] = MTU; + lcp_allowoptions[unit].asyncmap = xmit_accm[unit][0]; fsm_lowerup(&lcp_fsm[unit]); } @@ -1219,7 +1224,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, (ho->neg_mru? MIN(ao->mru, ho->mru): MTU), + ppp_send_config(f->unit, MIN(ao->mru, (ho->neg_mru? ho->mru: MTU)), (ho->neg_asyncmap? ho->asyncmap: 0xffffffff), ho->neg_pcompression, ho->neg_accompression); ppp_recv_config(f->unit, (go->neg_mru? MAX(wo->mru, go->mru): MTU), @@ -1254,7 +1259,8 @@ lcp_down(f) ppp_send_config(f->unit, MTU, 0xffffffff, 0, 0); ppp_recv_config(f->unit, MTU, 0, 0, 0); peer_mru[f->unit] = MTU; - syslog(LOG_NOTICE, "Connection terminated."); + + link_down(f->unit); } @@ -1279,3 +1285,139 @@ lcp_finished(f) link_terminated(f->unit); } + +/* + * lcp_printpkt - print the contents of an LCP packet. + */ +char *lcp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej", "ProtRej", + "EchoReq", "EchoRep", "DiscReq" +}; + +int +lcp_printpkt(p, plen, printer, arg) + u_char *p; + int plen; + void (*printer) __ARGS((void *, char *, ...)); + void *arg; +{ + int code, id, len, olen; + u_char *pstart, *optend; + u_short cishort; + u_long cilong; + + if (plen < HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *)) + printer(arg, " %s", lcp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < 2 || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { + case CI_MRU: + if (olen == CILEN_SHORT) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "mru %d", cishort); + } + break; + case CI_ASYNCMAP: + if (olen == CILEN_LONG) { + p += 2; + GETLONG(cilong, p); + printer(arg, "asyncmap 0x%x", cilong); + } + break; + case CI_AUTHTYPE: + if (olen >= CILEN_SHORT) { + p += 2; + printer(arg, "auth "); + GETSHORT(cishort, p); + switch (cishort) { + case UPAP: + printer(arg, "upap"); + break; + case CHAP: + printer(arg, "chap"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_QUALITY: + if (olen >= CILEN_SHORT) { + p += 2; + printer(arg, "quality "); + GETSHORT(cishort, p); + switch (cishort) { + case LQR: + printer(arg, "lqr"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_MAGICNUMBER: + if (olen == CILEN_LONG) { + p += 2; + GETLONG(cilong, p); + printer(arg, "magic 0x%x", cilong); + } + break; + case CI_PCOMPRESSION: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "pcomp"); + } + break; + case CI_ACCOMPRESSION: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "accomp"); + } + break; + } + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; +} diff --git a/usr.sbin/pppd/lcp.h b/usr.sbin/pppd/lcp.h index ffbb0ae8b78b..e1195632257d 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.3 1993/11/10 01:34:17 paulus Exp $ + * $Id: lcp.h,v 1.4 1994/05/08 12:16:23 paulus Exp $ */ /* @@ -27,10 +27,16 @@ #define CI_AUTHTYPE 3 /* Authentication Type */ #define CI_QUALITY 4 /* Quality Protocol */ #define CI_MAGICNUMBER 5 /* Magic Number */ -#define CI_KEEPALIVE 6 /* Keep Alive Parameters - OBSOLETE */ #define CI_PCOMPRESSION 7 /* Protocol Field Compression */ #define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */ +/* + * LCP-specific packet types. + */ +#define PROTREJ 8 /* Protocol Reject */ +#define ECHOREQ 9 /* Echo Request */ +#define ECHOREP 10 /* Echo Reply */ +#define DISCREQ 11 /* Discard Request */ /* * The state of options is described by an lcp_options structure. @@ -60,6 +66,7 @@ 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]; #define DEFMRU 1500 /* Try for this */ #define MINMRU 128 /* No MRUs below this */ @@ -73,6 +80,8 @@ 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 *)); extern int lcp_warnloops; /* Warn about a loopback this often */ #define DEFWARNLOOPS 10 /* Default value for above */ diff --git a/usr.sbin/pppd/main.c b/usr.sbin/pppd/main.c index ee378e9f793a..daf21342c5a7 100644 --- a/usr.sbin/pppd/main.c +++ b/usr.sbin/pppd/main.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: main.c,v 1.8 1994/01/25 05:58:05 paulus Exp $"; +static char rcsid[] = "$Id: main.c,v 1.9 1994/05/08 12:16:24 paulus Exp $"; #endif #define SETSID @@ -30,6 +30,7 @@ static char rcsid[] = "$Id: main.c,v 1.8 1994/01/25 05:58:05 paulus Exp $"; #include #include #include +#include /* * If REQ_SYSOPTIONS is defined to 1, pppd will not run unless @@ -39,10 +40,6 @@ static char rcsid[] = "$Id: main.c,v 1.8 1994/01/25 05:58:05 paulus Exp $"; #define REQ_SYSOPTIONS 0 #endif -#ifdef STREAMS -#undef SGTTY -#endif - #ifdef SGTTY #include #else @@ -115,6 +112,8 @@ int default_device = TRUE; /* use default device (stdin/out) */ int fd; /* 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 @@ -129,14 +128,18 @@ u_char outpacket_buf[MTU+DLLHEADERLEN]; /* buffer for outgoing packet */ static u_char inpacket_buf[MTU+DLLHEADERLEN]; /* 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 */ -int inspeed = 0; /* Input/Output speed */ +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 */ @@ -147,6 +150,7 @@ 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 */ /* prototypes */ @@ -159,13 +163,16 @@ 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 dumpbuffer __ARGS((unsigned char *, int, int)); +void novm __ARGS((char *)); + +void log_packet __ARGS((u_char *, int, char *)); +void format_packet __ARGS((u_char *, int, + void (*) (void *, char *, ...), void *)); +void pr_log __ARGS((void *, char *, ...)); -#ifdef STREAMS -extern char *ttyname __ARGS((int)); -#endif extern char *getlogin __ARGS((void)); /* @@ -177,13 +184,16 @@ static struct protent { void (*init)(); void (*input)(); void (*protrej)(); + int (*printpkt)(); + char *name; } prottbl[] = { - { LCP, lcp_init, lcp_input, lcp_protrej }, - { IPCP, ipcp_init, ipcp_input, ipcp_protrej }, - { UPAP, upap_init, upap_input, upap_protrej }, - { CHAP, ChapInit, ChapInput, ChapProtocolReject }, + { 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" }, }; +#define N_PROTO (sizeof(prottbl) / sizeof(prottbl[0])) main(argc, argv) int argc; @@ -195,28 +205,8 @@ main(argc, argv) FILE *pidfile; char *p; - /* - * Initialize syslog system and magic number package. - */ -#if BSD >= 43 || defined(sun) - 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 - -#ifdef STREAMS - p = ttyname(fileno(stdin)); - if (p) - strcpy(devname, p); -#endif - - magic_init(); - if (gethostname(hostname, MAXNAMELEN) < 0 ) { - syslog(LOG_ERR, "couldn't get hostname: %m"); + perror("couldn't get hostname"); die(1); } hostname[MAXNAMELEN-1] = 0; @@ -233,7 +223,7 @@ main(argc, argv) * the system options file, the user's options file, and the command * line arguments. */ - for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++) + for (i = 0; i < N_PROTO; i++) (*prottbl[i].init)(0); progname = *argv; @@ -245,6 +235,20 @@ main(argc, argv) check_auth_options(); setipdefault(); + if (lockflag && !default_device) + if (lock(devname) < 0) + die(1); + + /* + * Initialize syslog system and magic number package. + */ + openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP); + setlogmask(LOG_UPTO(LOG_INFO)); + if (debug) + setlogmask(LOG_UPTO(LOG_DEBUG)); + + magic_init(); + p = getlogin(); if (p == NULL) p = "(unknown)"; @@ -314,9 +318,6 @@ main(argc, argv) sigaddset(&mask, SIGINT); sigaddset(&mask, SIGALRM); sigaddset(&mask, SIGIO); -#ifdef STREAMS - sigaddset(&mask, SIGPOLL); -#endif #define SIGNAL(s, handler) { \ sv.sv_handler = handler; \ @@ -333,9 +334,6 @@ main(argc, argv) SIGNAL(SIGTERM, term); /* Terminate */ SIGNAL(SIGALRM, alrm); /* Timeout */ SIGNAL(SIGIO, io); /* Input available */ -#ifdef STREAMS - SIGNAL(SIGPOLL, io); /* Input available */ -#endif signal(SIGUSR1, incdebug); /* Increment debug flag */ signal(SIGUSR2, nodebug); /* Reset debug flag */ @@ -345,9 +343,6 @@ main(argc, argv) */ sigemptyset(&mask); sigaddset(&mask, SIGIO); -#ifdef STREAMS - sigaddset(&mask, SIGPOLL); -#endif sigprocmask(SIG_BLOCK, &mask, NULL); /* @@ -359,18 +354,20 @@ main(argc, argv) } 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); } - - /* set line speed, flow control, etc. */ - set_up_tty(fd); +#endif /* TIOCSCTTY */ /* run connection script */ if (connector) { - syslog(LOG_INFO, "Connecting with <%s>", connector); + MAINDEBUG((LOG_INFO, "Connecting with <%s>", connector)); + + /* set line speed, flow control, etc.; set CLOCAL for now */ + set_up_tty(fd, 1); /* drop dtr to hang up in case modem is off hook */ if (!default_device && modem) { @@ -379,7 +376,7 @@ main(argc, argv) setdtr(fd, TRUE); } - if (set_up_connection(connector, fd, fd) < 0) { + if (device_script(connector, fd, fd) < 0) { syslog(LOG_ERR, "could not set up connection"); setdtr(fd, FALSE); die(1); @@ -389,6 +386,9 @@ main(argc, argv) sleep(1); /* give it time to set up its terminal */ } + /* set line speed, flow control, etc.; clear CLOCAL if modem option */ + set_up_tty(fd, 0); + /* set up the serial device as a ppp interface */ establish_ppp(); @@ -448,11 +448,26 @@ main(argc, argv) */ 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 (;;) { - sigpause(0); /* Wait for next signal */ + 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 */ + reap_kids(); /* Don't leave dead kids lying around */ } + + /* + * Run disconnector script, if requested + */ + if (disconnector) { + if (device_script(disconnector, fd, fd) < 0) { + syslog(LOG_WARNING, "disconnect script failed"); + die(1); + } + + syslog(LOG_INFO, "Disconnected..."); + } + + quit(); } #if B9600 == 9600 @@ -461,6 +476,7 @@ main(argc, argv) * (so we can ask for any speed). */ #define translate_speed(bps) (bps) +#define baud_rate_of(speed) (speed) #else /* @@ -555,14 +571,32 @@ translate_speed(bps) syslog(LOG_WARNING, "speed %d not supported", bps); return 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. + * at the requested speed, etc. If `local' is true, set CLOCAL + * regardless of whether the modem option was specified. */ -set_up_tty(fd) - int fd; +set_up_tty(fd, local) + int fd, local; { #ifndef SGTTY int speed; @@ -576,11 +610,16 @@ set_up_tty(fd) if (!restore_term) inittermios = tios; +#ifdef CRTSCTS tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL | CRTSCTS); - tios.c_cflag |= CS8 | CREAD | HUPCL; if (crtscts) tios.c_cflag |= CRTSCTS; - if (!modem) +#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; @@ -591,12 +630,15 @@ set_up_tty(fd) if (speed) { cfsetospeed(&tios, speed); cfsetispeed(&tios, speed); + } else { + speed = cfgetospeed(&tios); } if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { syslog(LOG_ERR, "tcsetattr: %m"); die(1); } + #else /* SGTTY */ int speed; struct sgttyb sgttyb; @@ -616,15 +658,31 @@ set_up_tty(fd) 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); } #endif + + baud_rate = baud_rate_of(speed); restore_term = TRUE; } +/* + * 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); +} + /* * quit - Clean up state and exit. @@ -656,23 +714,23 @@ cleanup(status, arg) int status; caddr_t arg; { - if (fd != 0) { + if (fd >= 0) { /* drop dtr to hang up */ if (modem) setdtr(fd, FALSE); if (fcntl(fd, F_SETFL, initfdflags) < 0) - syslog(LOG_ERR, "fcntl(F_SETFL, fdflags): %m"); + syslog(LOG_WARNING, "fcntl(F_SETFL, fdflags): %m"); disestablish_ppp(); if (restore_term) { #ifndef SGTTY if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) - syslog(LOG_ERR, "tcsetattr: %m"); + syslog(LOG_WARNING, "tcsetattr: %m"); #else if (ioctl(fd, TIOCSETP, &initsgttyb) < 0) - syslog(LOG_ERR, "ioctl(TIOCSETP): %m"); + syslog(LOG_WARNING, "ioctl(TIOCSETP): %m"); #endif } @@ -683,6 +741,9 @@ cleanup(status, arg) if (pidfilename[0] != 0 && unlink(pidfilename) < 0) syslog(LOG_WARNING, "unable to unlink pid file: %m"); pidfilename[0] = 0; + + if (lockflag && !default_device) + unlock(); } @@ -739,7 +800,7 @@ timeout(func, arg, time) 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.", + 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"); @@ -795,7 +856,7 @@ untimeout(func, arg) 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.", + 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"); @@ -912,23 +973,23 @@ alrm(sig, code, scp, addr) char *addr; { struct itimerval itv; - struct callout *freep; + struct callout *freep, *list, *last; MAINDEBUG((LOG_DEBUG, "Alarm")); + if (callout == NULL) + return; /* - * Call and free first scheduled timeout and any that were scheduled - * for the same time. + * Get the first scheduled timeout and any that were scheduled + * for the same time as a list, and remove them all from callout + * list. */ - while (callout) { - freep = callout; /* Remove entry before calling */ - callout = freep->c_next; - (*freep->c_func)(freep->c_arg); - (void) free((char *) freep); - if (callout && callout->c_time) - break; - } - + 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. */ @@ -936,7 +997,7 @@ alrm(sig, code, scp, addr) 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.", + 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"); @@ -947,6 +1008,17 @@ alrm(sig, code, scp, addr) 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); + } + } @@ -1000,10 +1072,13 @@ io(sig, code, scp, addr) return; if (len == 0) { - syslog(LOG_ERR, "End of file on fd!"); + syslog(LOG_WARNING, "End of file on fd!"); die(1); } + if (debug /*&& (debugflags & DBG_INPACKET)*/) + log_packet(p, len, "rcvd "); + if (len < DLLHEADERLEN) { MAINDEBUG((LOG_INFO, "io(): Received short packet.")); return; @@ -1019,8 +1094,6 @@ io(sig, code, scp, addr) if (protocol != LCP && lcp_fsm[0].state != OPENED) { MAINDEBUG((LOG_INFO, "io(): Received non-LCP packet when LCP not open.")); - if (debug) - dumpbuffer(inpacket_buf, len + DLLHEADERLEN, LOG_INFO); return; } @@ -1098,10 +1171,11 @@ nodebug(sig) /* - * set_up_connection - run a program to initialize the serial connector + * device_script - run a program to connect or disconnect the + * serial device. */ int -set_up_connection(program, in, out) +device_script(program, in, out) char *program; int in, out; { @@ -1115,12 +1189,12 @@ set_up_connection(program, in, out) sigprocmask(SIG_BLOCK, &mask, &mask); pid = fork(); - + if (pid < 0) { syslog(LOG_ERR, "fork: %m"); die(1); } - + if (pid == 0) { setreuid(getuid(), getuid()); setregid(getgid(), getgid()); @@ -1133,10 +1207,10 @@ set_up_connection(program, in, out) /* NOTREACHED */ } - while (waitpid(pid, &status, 0) != pid) { + while (waitpid(pid, &status, 0) < 0) { if (errno == EINTR) continue; - syslog(LOG_ERR, "waiting for connection process: %m"); + syslog(LOG_ERR, "waiting for (dis)connection process: %m"); die(1); } sigprocmask(SIG_SETMASK, &mask, NULL); @@ -1146,82 +1220,154 @@ set_up_connection(program, in, out) /* - * Return user specified netmask. A value of zero means no netmask has - * been set. + * run-program - execute a program with given arguments, + * but don't wait for it. + * If the program can't be executed, logs an error unless + * must_exist is 0 and the program file doesn't exist. */ -/* ARGSUSED */ -u_long -GetMask(addr) - u_long addr; +int +run_program(prog, args, must_exist) + char *prog; + char **args; + int must_exist; { - return(netmask); + int pid; + + pid = fork(); + if (pid == -1) { + syslog(LOG_ERR, "can't fork to run %s: %m", prog); + return -1; + } + if (pid == 0) { + execv(prog, args); + if (must_exist || errno != ENOENT) + syslog(LOG_WARNING, "can't execute %s: %m", prog); + _exit(-1); + } + MAINDEBUG((LOG_DEBUG, "Script %s started; pid = %d", prog, pid)); + ++n_children; + return 0; } + /* - * dumpbuffer - print contents of a buffer in hex to standard output. + * reap_kids - get status from any dead child processes, + * and log a message for abnormal terminations. */ void -dumpbuffer(buffer, size, level) - unsigned char *buffer; - int size; - int level; +reap_kids() { - register int i; - char line[256], *p; + int pid, status; - printf("%d bytes:\n", size); - while (size > 0) - { - p = line; - sprintf(p, "%08lx: ", buffer); - p += 10; - - for (i = 0; i < 8; i++, p += 3) - if (size - i <= 0) - sprintf(p, "xx "); - else - sprintf(p, "%02x ", buffer[i]); - - for (i = 0; i < 8; i++) - if (size - i <= 0) - *p++ = 'x'; - else - *p++ = (' ' <= buffer[i] && buffer[i] <= '~') ? - buffer[i] : '.'; - - *p++ = 0; - buffer += 8; - size -= 8; - -/* syslog(level, "%s\n", line); */ - printf("%s\n", line); - fflush(stdout); + if (n_children == 0) + return; + if ((pid = waitpid(-1, &status, WNOHANG)) == -1) { + if (errno != ECHILD) + syslog(LOG_ERR, "waitpid: %m"); + return; + } + if (pid > 0) { + --n_children; + if (WIFSIGNALED(status)) { + syslog(LOG_WARNING, "child process %d terminated with signal %d", + pid, WTERMSIG(status)); + } } } /* - * setdtr - control the DTR line on the serial port. - * This is called from die(), so it shouldn't call die(). + * log_packet - format a packet and log it. */ -setdtr(fd, on) -int fd, on; -{ - int modembits = TIOCM_DTR; - ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits); +char line[256]; /* line to be logged accumulated here */ +char *linep; + +void +log_packet(p, len, prefix) + u_char *p; + int len; + char *prefix; +{ + strcpy(line, prefix); + linep = line + strlen(line); + format_packet(p, len, pr_log, NULL); + if (linep != line) + syslog(LOG_DEBUG, "%s", line); } +/* + * format_packet - make a readable representation of a packet, + * calling `printer(arg, format, ...)' to output it. + */ +void +format_packet(p, len, printer, arg) + u_char *p; + int len; + void (*printer) __ARGS((void *, char *, ...)); + void *arg; +{ + int i, n; + u_short proto; + u_char x; + + if (len >= DLLHEADERLEN && p[0] == ALLSTATIONS && p[1] == UI) { + p += 2; + GETSHORT(proto, p); + len -= DLLHEADERLEN; + for (i = 0; i < N_PROTO; ++i) + if (proto == prottbl[i].protocol) + break; + if (i < N_PROTO) { + printer(arg, "[%s", prottbl[i].name); + n = (*prottbl[i].printpkt)(p, len, printer, arg); + printer(arg, "]"); + p += n; + len -= n; + } else { + printer(arg, "[proto=0x%x]", proto); + } + } + + for (; len > 0; --len) { + GETCHAR(x, p); + printer(arg, " %.2x", x); + } +} + +#ifdef __STDC__ +#include + +void +pr_log(void *arg, char *fmt, ...) +{ + int n; + va_list pvar; + char buf[256]; + + va_start(pvar, fmt); + vsprintf(buf, fmt, pvar); + va_end(pvar); + + n = strlen(buf); + if (linep + n + 1 > line + sizeof(line)) { + syslog(LOG_DEBUG, "%s", line); + linep = line; + } + strcpy(linep, buf); + linep += n; +} + +#else /* __STDC__ */ #include -char line[256]; -char *p; - -logf(level, fmt, va_alist) -int level; +void +pr_log(arg, fmt, va_alist) +void *arg; char *fmt; va_dcl { + int n; va_list pvar; char buf[256]; @@ -1229,15 +1375,43 @@ va_dcl vsprintf(buf, fmt, pvar); va_end(pvar); - p = line + strlen(line); - strcat(p, buf); - - if (buf[strlen(buf)-1] == '\n') { - syslog(level, "%s", line); - line[0] = 0; + n = strlen(buf); + if (linep + n + 1 > line + sizeof(line)) { + syslog(LOG_DEBUG, "%s", line); + linep = line; } + strcpy(linep, buf); + linep += n; +} +#endif + +/* + * print_string - print a readable representation of a string using + * printer. + */ +void +print_string(p, len, printer, arg) + char *p; + int len; + void (*printer) __ARGS((void *, char *, ...)); + void *arg; +{ + int c; + + printer(arg, "\""); + for (; len > 0; --len) { + c = *p++; + if (' ' <= c && c <= '~') + printer(arg, "%c", c); + else + printer(arg, "\\%.3o", c); + } + printer(arg, "\""); } +/* + * novm - log an error message saying we ran out of memory, and die. + */ void novm(msg) char *msg; diff --git a/usr.sbin/pppd/options.c b/usr.sbin/pppd/options.c index cf6dff425eb5..7b28559fad8d 100644 --- a/usr.sbin/pppd/options.c +++ b/usr.sbin/pppd/options.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: options.c,v 1.5 1994/02/22 00:12:01 paulus Exp $"; +static char rcsid[] = "$Id: options.c,v 1.6 1994/05/08 12:16:26 paulus Exp $"; #endif #include @@ -45,11 +45,11 @@ static char rcsid[] = "$Id: options.c,v 1.5 1994/02/22 00:12:01 paulus Exp $"; #define FALSE 0 #define TRUE 1 - /* * Prototypes */ 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)); @@ -65,16 +65,20 @@ 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 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 **)); @@ -110,10 +114,13 @@ static int number_option __ARGS((char *, long *, int)); */ 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; @@ -156,16 +163,21 @@ static struct cmd { "-chap", 0, nochap, /* Don't allow CHAP authentication with peer */ "-vj", 0, setnovj, /* disable VJ compression */ "asyncmap", 1, setasyncmap, /* set the desired async map */ + "escape", 1, setescape, /* set chars to escape on transmission */ "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 */ "debug", 0, setdebug, /* Increase debugging level */ + "kdebug", 1, setkdebug, /* Enable kernel-level debugging */ "domain", 1, setdomain, /* Add given domain name to hostname*/ "mru", 1, setmru, /* Set MRU value for negotiation */ + "mtu", 1, setmtu, /* Set our MTU */ "netmask", 1, setnetmask, /* set netmask */ "passive", 0, setpassive, /* Set passive mode */ "silent", 0, setsilent, /* Set silent mode */ "modem", 0, setmodem, /* Use modem control lines */ "local", 0, setlocal, /* Don't use modem control lines */ + "lock", 0, setlock, /* Lock serial device (with lock file) */ "name", 1, setname, /* Set local name for authentication */ "user", 1, setuser, /* Set username for PAP auth with peer */ "usehostname", 0, setusehostname, /* Must use hostname for auth. */ @@ -215,34 +227,6 @@ Usage: %s [ arguments ], where arguments are:\n\ See pppd(8) for more options.\n\ "; -/* -Options omitted: - -all Don't request/allow any options\n\ - -ac Disable Address/Control compression\n\ - -am Disable asyncmap negotiation\n\ - -as Set the desired async map to hex \n\ - -d Increase debugging level\n\ - -detach Don't fork to background\n\ - -ip Disable IP address negotiation\n\ - -mn Disable magic number negotiation\n\ - -mru Disable mru negotiation\n\ - -p Set passive mode\n\ - -pc Disable protocol field compression\n\ - +ua Get username and password for authenticating\n\ - with peer using PAP from file \n\ - +pap Require PAP authentication from peer\n\ - -pap Don't agree to authenticating with peer using PAP\n\ - +chap Require CHAP authentication from peer\n\ - -chap Don't agree to authenticating with peer using CHAP\n\ - -vj disable VJ compression\n\ - -auth Don't agree to authenticate with peer\n\ - debug Increase debugging level\n\ - domain Append domain name to hostname for authentication\n\ - passive Set passive mode\n\ - local Don't use modem control lines\n\ - proxyarp Add proxy ARP entry\n\ -*/ - /* * parse_args - parse a string of arguments, from the command @@ -319,7 +303,7 @@ options_from_file(filename, must_exist) if (!must_exist && errno == ENOENT) return 1; perror(filename); - exit(1); + return 0; } while (getword(f, cmd, &newline, filename)) { /* @@ -549,10 +533,19 @@ static int setdebug() { debug++; - setlogmask(LOG_UPTO(LOG_DEBUG)); return (1); } +/* + * setkdebug - Set kernel debugging level. + */ +static int +setkdebug(argv) + char **argv; +{ + return int_option(*argv, &kdebugflag); +} + /* * noopt - Disable all options. */ @@ -643,6 +636,27 @@ setmru(argv) } +/* + * setmru - Set the largest MTU we'll use. + */ +static int +setmtu(argv) + char **argv; +{ + long 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, + (mtu < MINMRU? "small": "large")); + return 0; + } + lcp_allowoptions[0].mru = mtu; + return (1); +} + + /* * nopcomp - Disable Protocol field compression negotiation. */ @@ -716,7 +730,7 @@ setupapfile(argv) /* open user info file */ if ((ufile = fopen(*argv, "r")) == NULL) { fprintf(stderr, "unable to open user login data file %s\n", *argv); - exit(1); + return 0; } check_access(ufile, *argv); @@ -724,7 +738,7 @@ setupapfile(argv) if (fgets(user, MAXNAMELEN - 1, ufile) == NULL || fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){ fprintf(stderr, "Unable to read user login data file %s.\n", *argv); - exit(2); + return 0; } fclose(ufile); @@ -788,6 +802,20 @@ setconnector(argv) return (1); } +/* + * setdisconnector - Set a program to disconnect from the serial line + */ +static int +setdisconnector(argv) + char **argv; +{ + disconnector = strdup(*argv); + if (disconnector == NULL) + novm("disconnector string"); + + return (1); +} + /* * setdomain - Set domain name to append to hostname @@ -801,6 +829,10 @@ setdomain(argv) return (1); } + +/* + * setasyncmap - add bits to asyncmap (what we request peer to escape). + */ static int setasyncmap(argv) char **argv; @@ -814,6 +846,38 @@ setasyncmap(argv) return(1); } + +/* + * setescape - add chars to the set we escape on transmission. + */ +static int +setescape(argv) + char **argv; +{ + int n, ret; + char *p, *endp; + + p = *argv; + ret = 1; + while (*p) { + n = strtol(p, &endp, 16); + if (p == endp) { + fprintf(stderr, "%s: invalid hex number: %s\n", progname, p); + return 0; + } + p = endp; + if (n < 0 || 0x20 <= n && n <= 0x3F || n == 0x5E || n > 0xFF) { + fprintf(stderr, "%s: can't escape character 0x%x\n", n); + ret = 0; + } else + xmit_accm[0][n >> 5] |= 1 << (n & 0x1F); + while (*p == ',' || *p == ' ') + ++p; + } + return ret; +} + + /* * setspeed - Set the speed. */ @@ -857,7 +921,7 @@ setdevname(cp) if (errno == ENOENT) return (0); syslog(LOG_ERR, cp); - exit(1); + return 0; } (void) strncpy(devname, cp, MAXPATHLEN); @@ -1006,13 +1070,26 @@ setnetmask(argv) if ((mask = inet_addr(*argv)) == -1) { fprintf(stderr, "Invalid netmask %s\n", *argv); - exit(1); + return 0; } 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; +{ + return(netmask); +} + + static int setcrtscts() { @@ -1041,6 +1118,13 @@ setlocal() return 1; } +static int +setlock() +{ + lockflag = 1; + return 1; +} + static int setusehostname() { diff --git a/usr.sbin/pppd/patchlevel.h b/usr.sbin/pppd/patchlevel.h index 6a50eae22344..c5880b7a7b58 100644 --- a/usr.sbin/pppd/patchlevel.h +++ b/usr.sbin/pppd/patchlevel.h @@ -1,5 +1,5 @@ -/* $Id: patchlevel.h,v 1.6 1994/02/22 00:12:03 paulus Exp $ */ -#define PATCHLEVEL 4 +/* $Id: patchlevel.h,v 1.7 1994/05/08 12:16:27 paulus Exp $ */ +#define PATCHLEVEL 0 -#define VERSION "2.0" -#define DATE "9 Feb 94" +#define VERSION "2.1" +#define DATE "1 May 94" diff --git a/usr.sbin/pppd/pathnames.h b/usr.sbin/pppd/pathnames.h index 818b85f0eb6a..d8634448c67f 100644 --- a/usr.sbin/pppd/pathnames.h +++ b/usr.sbin/pppd/pathnames.h @@ -1,10 +1,10 @@ /* * define path names * - * $Id: pathnames.h,v 1.4 1993/11/10 01:34:26 paulus Exp $ + * $Id: pathnames.h,v 1.5 1994/05/08 12:16:28 paulus Exp $ */ -#ifdef STREAMS +#if defined(STREAMS) || defined(ultrix) #define _PATH_PIDFILE "/etc/ppp" #else #define _PATH_PIDFILE "/var/run" @@ -13,3 +13,5 @@ #define _PATH_UPAPFILE "/etc/ppp/pap-secrets" #define _PATH_CHAPFILE "/etc/ppp/chap-secrets" #define _PATH_SYSOPTIONS "/etc/ppp/options" +#define _PATH_IPUP "/etc/ppp/ip-up" +#define _PATH_IPDOWN "/etc/ppp/ip-down" diff --git a/usr.sbin/pppd/pppd.8 b/usr.sbin/pppd/pppd.8 index d1553fd3535b..498c7f8da8db 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.5 1994/02/22 00:12:04 paulus Exp $ +.\" $Id: pppd.8,v 1.6 1994/05/08 12:16:29 paulus Exp $ .\" SH section heading .\" SS subsection heading .\" LP paragraph @@ -50,20 +50,23 @@ Set the async character map to . This map describes which control characters cannot be successfully received over the serial line. .I pppd -will ask the peer to send these characters as a 2-byte "escape" sequence. +will ask the peer to send these characters as a 2-byte escape sequence. The argument is a 32 bit hex number with each bit representing a character to escape. Bit 0 (00000001) represents the character 0x00; bit 31 (80000000) represents the character 0x1f or ^_. -The default asyncmap is 0. If multiple \fBasyncmap\fR options are +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 +\fIall\fR control characters. .TP .B auth Require the peer to authenticate itself before allowing network packets to be sent or received. .TP .B connect \fI

-Use the executable or shell command specified by

to set up the +Use the executable or shell command specified by \fI

\fR to set up the serial line. This script would typically use the "chat" program to dial the modem and start the remote ppp session. .TP @@ -76,14 +79,33 @@ Add a default route to the system routing tables, using the peer as the gateway, when IPCP negotiation is successfully completed. This entry is removed when the PPP connection is broken. .TP +.B disconnect \fI

+Run the executable or shell command specified by \fI

\fR after +\fIpppd\fR has terminated the link. This script could, for example, +issue commands to the modem to cause it to hang up. +.TP +.B escape \fIxx,yy,... +Specifies that certain characters should be escaped on transmission +(regardless of whether the peer requests them to be escaped with its +async control character map). The characters to be escaped are +specified as a list of hex numbers separated by commas. Note that +almost any character can be specified for the \fBescape\fR option, +unlike the \fBasyncmap\fR option which only allows control characters +to be specified. The characters which may not be escaped are those +with hex values 0x20 - 0x3f or 0x5e. +.TP .B file \fI Read options from file (the format is described below). .TP +.B lock +Specifies that \fIpppd\fR should use a UUCP-style lock on the serial +device to ensure exclusive access to the device. +.TP .B mru \fI Set the MRU [Maximum Receive Unit] value to for negotiation. .I pppd will ask the peer to send packets of no more than bytes. - The minimum MRU value is 128. +The minimum MRU value is 128. The default MRU value is 1500. A value of 296 is recommended for slow links (40 bytes for TCP/IP header + 256 bytes of data). .TP @@ -132,17 +154,18 @@ default values). .TP .B -ac Disable Address/Control compression negotiation (use default, i.e. -disabled). +address/control field disabled). .TP .B -am -Disable asyncmap negotiation (use default, i.e. 0xffffffff). +Disable asyncmap negotiation (use the default asyncmap, i.e. escape +all control characters). .TP .B -as \fI Same as .B asyncmap \fI .TP .B -d -Increase debugging level. +Increase debugging level (same as the \fBdebug\fR option). .TP .B -detach Don't fork to become a background process (otherwise @@ -168,7 +191,8 @@ Same as the option. .TP .B -pc -Disable protocol field compression negotiation (use default, i.e. disabled). +Disable protocol field compression negotiation (use default, i.e. +protocol field compression disabled). .TP .B +ua \fI

Agree to authenticate using PAP [Password Authentication Protocol] if @@ -196,9 +220,13 @@ Disable negotiation of Van Jacobson style IP header compression (use default, i.e. no compression). .TP .B debug -Increase debugging level (same as -.B -d -). +Increase debugging level (same as \fB\-d\fR). +If this +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)). .TP .B domain \fI Append the domain name to the local host name for authentication @@ -209,9 +237,22 @@ domain option to set the domain name to Quotron.COM. .B modem Use the modem control lines. (This option is not fully implemented.) .TP +.B kdebug \fIn +Enable debugging code in the kernel-level PPP driver. The argument +\fIn\fR is a number which is the sum of the following values: 1 to +enable general debug messages, 2 to request that the contents of +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. .TP +.B mtu \fI +Set the MTU [Maximum Transmit Unit] value to \fI\fR. Unless the +peer requests a smaller value via MRU negotiation, \fIpppd\fR will +request that the kernel networking code send data packets of no more +than \fIn\fR bytes through the PPP network interface. +.TP .B name \fI Set the name of the local system for authentication purposes to . .TP @@ -429,6 +470,16 @@ other Network Control Protocol) can be started. If authentication fails, \fIpppd\fR will terminated the link (by closing LCP). If IPCP negotiates an unacceptable IP address for the remote host, IPCP will be closed. IP packets can only be sent or received when IPCP is open. +.LP +In some cases it is desirable to allow some hosts which can't +authenticate themselves to connect and use one of a restricted set of +IP addresses, even when the local host generally requires +authentication. If the peer refuses to authenticate itself when +requested, \fIpppd\fR takes that as equivalent to authenticating with +PAP using the empty string for the username and password. Thus, by +adding a line to the pap-secrets file which specifies the empty string +for the client and password, it is possible to allow restricted access +to hosts which refuse to authenticate themselves. .SH ROUTING .LP When IPCP negotiation is completed successfully, @@ -483,29 +534,34 @@ for example: pppd /dev/ttya 38400 connect 'chat "" "" "login:" "username" "Password:" "password" "% " "exec pppd passive"' .LP +(Note however that running chat like this will leave the password +visible in the parameter list of pppd and chat.) +.LP If your serial connection is any more complicated than a piece of wire, you may need to arrange for some control characters to be escaped. In particular, it is often useful to escape XON (^Q) and XOFF (^S), using \fBasyncmap a0000\fR. If the path includes a telnet, you probably should escape ^] as well (\fBasyncmap 200a0000\fR). -Don't use an rlogin in the path - many implementations are not +If the path includes an rlogin, you will need to use the \fBescape +ff\fR option on the end which is running the rlogin client, since many +rlogin implementations are not transparent; they will remove the sequence [0xff, 0xff, 0x73, 0x73, followed by any 8 bytes] from the stream. .SH DIAGNOSTICS .LP -Messages are sent to the syslog daemon using facility -LOG_DAEMON unless -.I pppd -has been compiled with debugging code. In this case the logging -facility used will be LOG_LOCAL2 in order to allow separation of the debug -output from the other daemons using the LOG_DAEMON facility. You can -override this by defining the macro LOG_PPP to the desired facility -and recompiling. In order to see the error and debug messages, you -will need to edit your /etc/syslog.conf file to direct the messages to -the desired output device or file. +Messages are sent to the syslog daemon using facility LOG_DAEMON. +(This can be overriden by recompiling \fIpppd\fR with the macro +LOG_PPP defined as the desired facility.) In order to see the error +and debug messages, you will need to edit your /etc/syslog.conf file +to direct the messages to the desired output device or file. .LP -If enabled at compile time, debugging printout can be enabled by -setting the -d or debug flag on the command line, or by sending a +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, the \fBdebug\fR option also +causes other debugging messages to be logged. +.LP +Debugging can also be enabled by sending a SIGUSR1 to the .I pppd process. @@ -542,12 +598,6 @@ Rivest, R. .I The MD5 Message-Digest Algorithm. 1992 April. .TP -.B RFC1331 -Simpson, W.A. -.I Point\-to\-Point Protocol (PPP) for the transmission of multi\-protocol -.I datagrams over point\-to\-point links. -1992 May. -.TP .B RFC1332 McGregor, G. .I PPP Internet Protocol Control Protocol (IPCP). @@ -557,6 +607,16 @@ McGregor, G. Lloyd, B.; Simpson, W.A. .I PPP authentication protocols. 1992 October. +.TP +.B RFC1548 +Simpson, W.A. +.I The Point\-to\-Point Protocol (PPP). +1993 December. +.TP +.B RFC1549 +Simpson, W.A. +.I PPP in HDLC Framing. +1993 December .SH NOTES The following signals have the specified effect when sent to the .I pppd diff --git a/usr.sbin/pppd/pppd.h b/usr.sbin/pppd/pppd.h index dc6ff25e2fd2..c75cc4c1e89a 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.4 1993/11/10 01:34:32 paulus Exp $ + * $Id: pppd.h,v 1.5 1994/05/08 12:16:30 paulus Exp $ */ /* @@ -39,6 +39,9 @@ #define MAXNAMELEN 256 /* max length of hostname or name for auth */ #define MAXSECRETLEN 256 /* max length of password or secret */ +/* + * Global variables. + */ extern int debug; /* Debug flag */ extern int ifunit; /* Interface unit number */ extern char ifname[]; /* Interface name */ @@ -46,7 +49,20 @@ 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 */ +/* + * Values for phase. + */ +#define PHASE_DEAD 0 +#define PHASE_ESTABLISH 1 +#define PHASE_AUTHENTICATE 2 +#define PHASE_NETWORK 3 +#define PHASE_TERMINATE 4 + +/* + * Prototypes. + */ void quit __ARGS((void)); /* Cleanup and exit */ void timeout __ARGS((void (*)(), caddr_t, int)); /* Look-alike of kernel's timeout() */ diff --git a/usr.sbin/pppd/pppd/Makefile b/usr.sbin/pppd/pppd/Makefile index d7fbfa149c97..294a34e1c4d6 100644 --- a/usr.sbin/pppd/pppd/Makefile +++ b/usr.sbin/pppd/pppd/Makefile @@ -1,8 +1,8 @@ -# $Id: Makefile,v 1.5 1993/11/10 01:33:51 paulus Exp $ +# $Id: Makefile,v 1.6 1994/05/08 12:16:10 paulus Exp $ PROG= pppd SRCS= main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c \ - auth.c options.c sys-bsd.c + auth.c options.c lock.c sys-bsd.c MAN8= pppd.0 SUBDIR= pppstats chat BINMODE=4555 diff --git a/usr.sbin/pppd/pppd/auth.c b/usr.sbin/pppd/pppd/auth.c index cdcd1f3abee8..d2faf5222c30 100644 --- a/usr.sbin/pppd/pppd/auth.c +++ b/usr.sbin/pppd/pppd/auth.c @@ -33,7 +33,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: auth.c,v 1.4 1994/01/25 05:58:02 paulus Exp $"; +static char rcsid[] = "$Id: auth.c,v 1.5 1994/05/08 12:16:13 paulus Exp $"; #endif #include @@ -106,6 +106,7 @@ 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 *)); @@ -135,11 +136,18 @@ link_terminated(unit) { if (logged_in) logout(); - if (lcp_wantoptions[unit].restart) { - lcp_lowerdown(unit); - lcp_lowerup(unit); - } else - EXIT(unit); + phase = PHASE_DEAD; + syslog(LOG_NOTICE, "Connection terminated."); +} + +/* + * LCP has gone down; it will either die or try to re-establish. + */ +void +link_down(unit) + int unit; +{ + phase = PHASE_TERMINATE; } /* @@ -157,14 +165,19 @@ link_established(unit) if (auth_required && !(go->neg_chap || go->neg_upap)) { /* - * We wanted the peer to authenticate himself, and he refused: - * tell him to go away. + * We wanted the peer to authenticate itself, and it refused: + * treat it as though it authenticated with PAP using a username + * of "" and a password of "". If that's not OK, boot it out. */ - syslog(LOG_WARNING, "peer refused to authenticate"); - lcp_close(unit); - return; + if (wo->neg_upap && !null_login(unit)) { + syslog(LOG_WARNING, "peer refused to authenticate"); + lcp_close(unit); + phase = PHASE_TERMINATE; + return; + } } + phase = PHASE_AUTHENTICATE; auth = 0; if (go->neg_chap) { ChapAuthPeer(unit, our_name, go->chap_mdtype); @@ -182,8 +195,10 @@ link_established(unit) } auth_pending[unit] = auth; - if (!auth) + if (!auth) { + phase = PHASE_NETWORK; ipcp_open(unit); + } } /* @@ -197,6 +212,7 @@ auth_peer_fail(unit, protocol) * Authentication failure: take the link down */ lcp_close(unit); + phase = PHASE_TERMINATE; } /* @@ -225,8 +241,10 @@ auth_peer_success(unit, protocol) * If there is no more authentication still to be done, * proceed to the network phase. */ - if ((auth_pending[unit] &= ~bit) == 0) + if ((auth_pending[unit] &= ~bit) == 0) { + phase = PHASE_NETWORK; ipcp_open(unit); + } } /* @@ -268,8 +286,10 @@ 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) + if ((auth_pending[unit] &= ~bit) == 0) { + phase = PHASE_NETWORK; ipcp_open(unit); + } } @@ -485,6 +505,46 @@ logout() } +/* + * null_login - Check if a username of "" and a password of "" are + * acceptable, and iff so, set the list of acceptable IP addresses + * and return 1. + */ +static int +null_login(unit) + int unit; +{ + char *filename; + FILE *f; + int i, ret; + struct wordlist *addrs; + char secret[MAXWORDLEN]; + + /* + * Open the file of upap secrets and scan for a suitable secret. + * We don't accept a wildcard client. + */ + filename = _PATH_UPAPFILE; + addrs = NULL; + f = fopen(filename, "r"); + if (f == NULL) + return 0; + check_access(f, filename); + + i = scan_authfile(f, "", our_name, secret, &addrs, filename); + ret = i >= 0 && (i & NONWILD_CLIENT) != 0 && secret[0] == 0; + + if (ret) { + if (addresses[unit] != NULL) + free_wordlist(addresses[unit]); + addresses[unit] = addrs; + } + + fclose(f); + return ret; +} + + /* * get_upap_passwd - get a password for authenticating ourselves with * our peer using PAP. Returns 1 on success, 0 if no suitable password diff --git a/usr.sbin/pppd/pppd/chap.c b/usr.sbin/pppd/pppd/chap.c index 815ece43e994..f33464450beb 100644 --- a/usr.sbin/pppd/pppd/chap.c +++ b/usr.sbin/pppd/pppd/chap.c @@ -19,7 +19,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: chap.c,v 1.3 1993/11/10 01:33:59 paulus Exp $"; +static char rcsid[] = "$Id: chap.c,v 1.4 1994/05/08 12:16:15 paulus Exp $"; #endif /* @@ -557,6 +557,8 @@ ChapReceiveSuccess(cstate, inp, id, len) return; } + UNTIMEOUT(ChapResponseTimeout, (caddr_t) cstate); + /* * Print message. */ @@ -591,6 +593,8 @@ ChapReceiveFailure(cstate, inp, id, len) return; } + UNTIMEOUT(ChapResponseTimeout, (caddr_t) cstate); + /* * Print message. */ @@ -738,6 +742,71 @@ ChapSendResponse(cstate) ++cstate->resp_transmits; } +/* + * ChapPrintPkt - print the contents of a CHAP packet. + */ +char *ChapCodenames[] = { + "Challenge", "Response", "Success", "Failure" +}; + +int +ChapPrintPkt(p, plen, printer, arg) + u_char *p; + int plen; + void (*printer) __ARGS((void *, char *, ...)); + void *arg; +{ + int code, id, len; + int clen, nlen; + u_char x; + + if (plen < CHAP_HEADERLEN) + return 0; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < CHAP_HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= sizeof(ChapCodenames) / sizeof(char *)) + printer(arg, " %s", ChapCodenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= CHAP_HEADERLEN; + switch (code) { + case CHAP_CHALLENGE: + case CHAP_RESPONSE: + if (len < 1) + break; + clen = p[0]; + if (len < clen + 1) + break; + ++p; + nlen = len - clen - 1; + printer(arg, " <"); + for (; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, "%.2x", x); + } + printer(arg, ">, name = "); + print_string((char *)p, nlen, printer, arg); + break; + case CHAP_FAILURE: + case CHAP_SUCCESS: + printer(arg, " "); + print_string((char *)p, len, printer, arg); + break; + default: + for (clen = len; clen > 0; --clen) { + GETCHAR(x, p); + printer(arg, " %.2x", x); + } + } + + return len + CHAP_HEADERLEN; +} + #ifdef NO_DRAND48 double drand48() diff --git a/usr.sbin/pppd/pppd/chap.h b/usr.sbin/pppd/pppd/chap.h index 5ac40bfc4295..218580de0ec7 100644 --- a/usr.sbin/pppd/pppd/chap.h +++ b/usr.sbin/pppd/pppd/chap.h @@ -1,6 +1,5 @@ /* * chap.h - Cryptographic Handshake Authentication Protocol definitions. - * based on November 1991 draft of PPP Authentication RFC * * Copyright (c) 1991 Gregory M. Christy * All rights reserved. @@ -16,13 +15,13 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: chap.h,v 1.3 1993/11/10 01:34:02 paulus Exp $ + * $Id: chap.h,v 1.4 1994/05/08 12:16:16 paulus Exp $ */ #ifndef __CHAP_INCLUDE__ /* Code + ID + length */ -#define CHAP_HEADERLEN (sizeof (u_char) + sizeof (u_char) + sizeof (u_short)) +#define CHAP_HEADERLEN 4 /* * CHAP codes. @@ -106,6 +105,8 @@ 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 *)); #define __CHAP_INCLUDE__ #endif /* __CHAP_INCLUDE__ */ diff --git a/usr.sbin/pppd/pppd/fsm.c b/usr.sbin/pppd/pppd/fsm.c index c6d1b705374d..832332c5dfde 100644 --- a/usr.sbin/pppd/pppd/fsm.c +++ b/usr.sbin/pppd/pppd/fsm.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: fsm.c,v 1.3 1993/11/10 01:34:04 paulus Exp $"; +static char rcsid[] = "$Id: fsm.c,v 1.4 1994/05/08 12:16:17 paulus Exp $"; #endif /* @@ -29,7 +29,6 @@ static char rcsid[] = "$Id: fsm.c,v 1.3 1993/11/10 01:34:04 paulus Exp $"; #include #include -/*#include */ #include #include "ppp.h" @@ -453,6 +452,7 @@ fsm_rconfack(f, id, inp, len) PROTO_NAME(f), len)); return; } + f->reqid = -1; switch (f->state) { case CLOSED: @@ -514,6 +514,7 @@ fsm_rconfnakrej(f, code, id, inp, len) PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len)); return; } + f->reqid = -1; switch (f->state) { case CLOSED: @@ -556,7 +557,6 @@ fsm_rtermreq(f, id) FSMDEBUG((LOG_INFO, "fsm_rtermreq(%s): Rcvd id %d.", PROTO_NAME(f), id)); - fsm_sdata(f, TERMACK, id, NULL, 0); switch (f->state) { case ACKRCVD: case ACKSENT: @@ -572,6 +572,8 @@ fsm_rtermreq(f, id) TIMEOUT(fsm_timeout, (caddr_t) f, f->timeouttime); break; } + + fsm_sdata(f, TERMACK, id, NULL, 0); } diff --git a/usr.sbin/pppd/pppd/fsm.h b/usr.sbin/pppd/pppd/fsm.h index 0b90190409a0..d6383906f9ca 100644 --- a/usr.sbin/pppd/pppd/fsm.h +++ b/usr.sbin/pppd/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.3 1993/11/10 01:34:07 paulus Exp $ + * $Id: fsm.h,v 1.4 1994/05/08 12:16:18 paulus Exp $ */ /* @@ -35,11 +35,6 @@ #define TERMREQ 5 /* Termination Request */ #define TERMACK 6 /* Termination Ack */ #define CODEREJ 7 /* Code Reject */ -#define PROTREJ 8 /* Protocol Reject */ -#define ECHOREQ 9 /* Echo Request */ -#define ECHOREP 10 /* Echo Reply */ -#define DISCREQ 11 /* Discard Request */ -#define KEEPALIVE 12 /* Keepalive */ /* diff --git a/usr.sbin/pppd/pppd/ipcp.c b/usr.sbin/pppd/pppd/ipcp.c index 3906c47371e0..b95563a84faa 100644 --- a/usr.sbin/pppd/pppd/ipcp.c +++ b/usr.sbin/pppd/pppd/ipcp.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: ipcp.c,v 1.4 1994/02/22 00:11:57 paulus Exp $"; +static char rcsid[] = "$Id: ipcp.c,v 1.5 1994/05/08 12:16:19 paulus Exp $"; #endif /* @@ -43,7 +43,7 @@ static char rcsid[] = "$Id: ipcp.c,v 1.4 1994/02/22 00:11:57 paulus Exp $"; #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 */ @@ -51,6 +51,10 @@ 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; + /* local vars */ static int cis_received[NPPP]; /* # Conf-Reqs received */ @@ -66,7 +70,7 @@ 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 */ @@ -885,6 +889,10 @@ ipcp_reqci(f, inp, len, reject_if_disagree) } ho->maxslotindex = maxslotindex; ho->cflag = wo->cflag; + } else { + ho->old_vj = 1; + ho->maxslotindex = MAX_STATES - 1; + ho->cflag = 1; } break; @@ -988,7 +996,7 @@ ipcp_up(f) } /* - * Check that the peer is allowed to use the IP address he wants. + * Check that the peer is allowed to use the IP address it wants. */ if (!auth_ip_addr(f->unit, ho->hisaddr)) { syslog(LOG_ERR, "Peer is not authorized to use remote address %s", @@ -1011,7 +1019,7 @@ ipcp_up(f) } /* set tcp compression */ - sifvjcomp(f->unit, ho->neg_vj, ho->cflag); + sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex); /* bring the interface up for IP */ if (!sifup(f->unit)) { @@ -1029,6 +1037,13 @@ ipcp_up(f) if (ipcp_wantoptions[f->unit].proxy_arp) if (sifproxyarp(f->unit, ho->hisaddr)) go->proxy_arp = 1; + + /* + * Execute the ip-up script, like this: + * /etc/ppp/ip-up interface tty speed local-IP remote-IP + */ + ipcp_script(f, _PATH_IPUP); + } @@ -1054,4 +1069,138 @@ ipcp_down(f) cifdefaultroute(f->unit, hisaddr); sifdown(f->unit); cifaddr(f->unit, ouraddr, hisaddr); + + /* Execute the ip-down script */ + ipcp_script(f, _PATH_IPDOWN); +} + + +/* + * ipcp_script - Execute a script with arguments + * interface-name tty-name speed local-IP remote-IP. + */ +static void +ipcp_script(f, script) + fsm *f; + char *script; +{ + char strspeed[32], strlocal[32], strremote[32]; + char *argv[8]; + + sprintf(strspeed, "%d", baud_rate); + strcpy(strlocal, ip_ntoa(ipcp_gotoptions[f->unit].ouraddr)); + strcpy(strremote, ip_ntoa(ipcp_hisoptions[f->unit].hisaddr)); + + argv[0] = script; + argv[1] = ifname; + argv[2] = devname; + argv[3] = strspeed; + argv[4] = strlocal; + argv[5] = strremote; + argv[6] = NULL; + run_program(script, argv, 0); +} + +/* + * ipcp_printpkt - print the contents of an IPCP packet. + */ +char *ipcp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej" +}; + +int +ipcp_printpkt(p, plen, printer, arg) + u_char *p; + int plen; + void (*printer)(); + void *arg; +{ + int code, id, len, olen; + u_char *pstart, *optend; + u_short cishort; + u_long cilong; + + if (plen < HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= sizeof(ipcp_codenames) / sizeof(char *)) + printer(arg, " %s", ipcp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < 2 || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { + case CI_ADDRS: + if (olen == CILEN_ADDRS) { + p += 2; + GETLONG(cilong, p); + printer(arg, "addrs %s", ip_ntoa(htonl(cilong))); + GETLONG(cilong, p); + printer(arg, " %s", ip_ntoa(htonl(cilong))); + } + break; + case CI_COMPRESSTYPE: + if (olen >= CILEN_COMPRESS) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "compress "); + switch (cishort) { + case IPCP_VJ_COMP: + printer(arg, "VJ"); + break; + case IPCP_VJ_COMP_OLD: + printer(arg, "old-VJ"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_ADDR: + if (olen == CILEN_ADDR) { + p += 2; + GETLONG(cilong, p); + printer(arg, "addr %s", ip_ntoa(htonl(cilong))); + } + break; + } + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; } diff --git a/usr.sbin/pppd/pppd/ipcp.h b/usr.sbin/pppd/pppd/ipcp.h index a42ebd99bd4f..4d1381f725f7 100644 --- a/usr.sbin/pppd/pppd/ipcp.h +++ b/usr.sbin/pppd/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.4 1994/02/22 00:11:59 paulus Exp $ + * $Id: ipcp.h,v 1.5 1994/05/08 12:16:20 paulus Exp $ */ /* @@ -65,3 +65,4 @@ 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 *)); diff --git a/usr.sbin/pppd/pppd/lcp.c b/usr.sbin/pppd/pppd/lcp.c index 9d8d8363077f..24a01ebf7db4 100644 --- a/usr.sbin/pppd/pppd/lcp.c +++ b/usr.sbin/pppd/pppd/lcp.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: lcp.c,v 1.3 1993/11/10 01:34:15 paulus Exp $"; +static char rcsid[] = "$Id: lcp.c,v 1.4 1994/05/08 12:16:22 paulus Exp $"; #endif /* @@ -55,6 +55,7 @@ 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 */ /* * Callbacks for fsm code. (CI = Configuration Information) @@ -129,7 +130,7 @@ lcp_init(unit) implementations */ wo->neg_mru = 1; wo->mru = DEFMRU; - wo->neg_asyncmap = 1; + wo->neg_asyncmap = 0; wo->asyncmap = 0; wo->neg_chap = 0; /* Set to 1 on server */ wo->neg_upap = 0; /* Set to 1 on server */ @@ -151,6 +152,8 @@ lcp_init(unit) ao->neg_accompression = 1; ao->neg_lqr = 0; /* no LQR implementation yet */ + memset(xmit_accm[unit], 0, sizeof(xmit_accm[0])); + xmit_accm[unit][3] = 0x60000000; } @@ -192,9 +195,11 @@ lcp_lowerup(unit) int unit; { sifdown(unit); + ppp_set_xaccm(unit, xmit_accm[unit]); ppp_send_config(unit, MTU, 0xffffffff, 0, 0); ppp_recv_config(unit, MTU, 0, 0, 0); peer_mru[unit] = MTU; + lcp_allowoptions[unit].asyncmap = xmit_accm[unit][0]; fsm_lowerup(&lcp_fsm[unit]); } @@ -1219,7 +1224,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, (ho->neg_mru? MIN(ao->mru, ho->mru): MTU), + ppp_send_config(f->unit, MIN(ao->mru, (ho->neg_mru? ho->mru: MTU)), (ho->neg_asyncmap? ho->asyncmap: 0xffffffff), ho->neg_pcompression, ho->neg_accompression); ppp_recv_config(f->unit, (go->neg_mru? MAX(wo->mru, go->mru): MTU), @@ -1254,7 +1259,8 @@ lcp_down(f) ppp_send_config(f->unit, MTU, 0xffffffff, 0, 0); ppp_recv_config(f->unit, MTU, 0, 0, 0); peer_mru[f->unit] = MTU; - syslog(LOG_NOTICE, "Connection terminated."); + + link_down(f->unit); } @@ -1279,3 +1285,139 @@ lcp_finished(f) link_terminated(f->unit); } + +/* + * lcp_printpkt - print the contents of an LCP packet. + */ +char *lcp_codenames[] = { + "ConfReq", "ConfAck", "ConfNak", "ConfRej", + "TermReq", "TermAck", "CodeRej", "ProtRej", + "EchoReq", "EchoRep", "DiscReq" +}; + +int +lcp_printpkt(p, plen, printer, arg) + u_char *p; + int plen; + void (*printer) __ARGS((void *, char *, ...)); + void *arg; +{ + int code, id, len, olen; + u_char *pstart, *optend; + u_short cishort; + u_long cilong; + + if (plen < HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= sizeof(lcp_codenames) / sizeof(char *)) + printer(arg, " %s", lcp_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= HEADERLEN; + switch (code) { + case CONFREQ: + case CONFACK: + case CONFNAK: + case CONFREJ: + /* print option list */ + while (len >= 2) { + GETCHAR(code, p); + GETCHAR(olen, p); + p -= 2; + if (olen < 2 || olen > len) { + break; + } + printer(arg, " <"); + len -= olen; + optend = p + olen; + switch (code) { + case CI_MRU: + if (olen == CILEN_SHORT) { + p += 2; + GETSHORT(cishort, p); + printer(arg, "mru %d", cishort); + } + break; + case CI_ASYNCMAP: + if (olen == CILEN_LONG) { + p += 2; + GETLONG(cilong, p); + printer(arg, "asyncmap 0x%x", cilong); + } + break; + case CI_AUTHTYPE: + if (olen >= CILEN_SHORT) { + p += 2; + printer(arg, "auth "); + GETSHORT(cishort, p); + switch (cishort) { + case UPAP: + printer(arg, "upap"); + break; + case CHAP: + printer(arg, "chap"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_QUALITY: + if (olen >= CILEN_SHORT) { + p += 2; + printer(arg, "quality "); + GETSHORT(cishort, p); + switch (cishort) { + case LQR: + printer(arg, "lqr"); + break; + default: + printer(arg, "0x%x", cishort); + } + } + break; + case CI_MAGICNUMBER: + if (olen == CILEN_LONG) { + p += 2; + GETLONG(cilong, p); + printer(arg, "magic 0x%x", cilong); + } + break; + case CI_PCOMPRESSION: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "pcomp"); + } + break; + case CI_ACCOMPRESSION: + if (olen == CILEN_VOID) { + p += 2; + printer(arg, "accomp"); + } + break; + } + while (p < optend) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + printer(arg, ">"); + } + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; +} diff --git a/usr.sbin/pppd/pppd/lcp.h b/usr.sbin/pppd/pppd/lcp.h index ffbb0ae8b78b..e1195632257d 100644 --- a/usr.sbin/pppd/pppd/lcp.h +++ b/usr.sbin/pppd/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.3 1993/11/10 01:34:17 paulus Exp $ + * $Id: lcp.h,v 1.4 1994/05/08 12:16:23 paulus Exp $ */ /* @@ -27,10 +27,16 @@ #define CI_AUTHTYPE 3 /* Authentication Type */ #define CI_QUALITY 4 /* Quality Protocol */ #define CI_MAGICNUMBER 5 /* Magic Number */ -#define CI_KEEPALIVE 6 /* Keep Alive Parameters - OBSOLETE */ #define CI_PCOMPRESSION 7 /* Protocol Field Compression */ #define CI_ACCOMPRESSION 8 /* Address/Control Field Compression */ +/* + * LCP-specific packet types. + */ +#define PROTREJ 8 /* Protocol Reject */ +#define ECHOREQ 9 /* Echo Request */ +#define ECHOREP 10 /* Echo Reply */ +#define DISCREQ 11 /* Discard Request */ /* * The state of options is described by an lcp_options structure. @@ -60,6 +66,7 @@ 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]; #define DEFMRU 1500 /* Try for this */ #define MINMRU 128 /* No MRUs below this */ @@ -73,6 +80,8 @@ 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 *)); extern int lcp_warnloops; /* Warn about a loopback this often */ #define DEFWARNLOOPS 10 /* Default value for above */ diff --git a/usr.sbin/pppd/pppd/main.c b/usr.sbin/pppd/pppd/main.c index ee378e9f793a..daf21342c5a7 100644 --- a/usr.sbin/pppd/pppd/main.c +++ b/usr.sbin/pppd/pppd/main.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: main.c,v 1.8 1994/01/25 05:58:05 paulus Exp $"; +static char rcsid[] = "$Id: main.c,v 1.9 1994/05/08 12:16:24 paulus Exp $"; #endif #define SETSID @@ -30,6 +30,7 @@ static char rcsid[] = "$Id: main.c,v 1.8 1994/01/25 05:58:05 paulus Exp $"; #include #include #include +#include /* * If REQ_SYSOPTIONS is defined to 1, pppd will not run unless @@ -39,10 +40,6 @@ static char rcsid[] = "$Id: main.c,v 1.8 1994/01/25 05:58:05 paulus Exp $"; #define REQ_SYSOPTIONS 0 #endif -#ifdef STREAMS -#undef SGTTY -#endif - #ifdef SGTTY #include #else @@ -115,6 +112,8 @@ int default_device = TRUE; /* use default device (stdin/out) */ int fd; /* 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 @@ -129,14 +128,18 @@ u_char outpacket_buf[MTU+DLLHEADERLEN]; /* buffer for outgoing packet */ static u_char inpacket_buf[MTU+DLLHEADERLEN]; /* 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 */ -int inspeed = 0; /* Input/Output speed */ +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 */ @@ -147,6 +150,7 @@ 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 */ /* prototypes */ @@ -159,13 +163,16 @@ 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 dumpbuffer __ARGS((unsigned char *, int, int)); +void novm __ARGS((char *)); + +void log_packet __ARGS((u_char *, int, char *)); +void format_packet __ARGS((u_char *, int, + void (*) (void *, char *, ...), void *)); +void pr_log __ARGS((void *, char *, ...)); -#ifdef STREAMS -extern char *ttyname __ARGS((int)); -#endif extern char *getlogin __ARGS((void)); /* @@ -177,13 +184,16 @@ static struct protent { void (*init)(); void (*input)(); void (*protrej)(); + int (*printpkt)(); + char *name; } prottbl[] = { - { LCP, lcp_init, lcp_input, lcp_protrej }, - { IPCP, ipcp_init, ipcp_input, ipcp_protrej }, - { UPAP, upap_init, upap_input, upap_protrej }, - { CHAP, ChapInit, ChapInput, ChapProtocolReject }, + { 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" }, }; +#define N_PROTO (sizeof(prottbl) / sizeof(prottbl[0])) main(argc, argv) int argc; @@ -195,28 +205,8 @@ main(argc, argv) FILE *pidfile; char *p; - /* - * Initialize syslog system and magic number package. - */ -#if BSD >= 43 || defined(sun) - 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 - -#ifdef STREAMS - p = ttyname(fileno(stdin)); - if (p) - strcpy(devname, p); -#endif - - magic_init(); - if (gethostname(hostname, MAXNAMELEN) < 0 ) { - syslog(LOG_ERR, "couldn't get hostname: %m"); + perror("couldn't get hostname"); die(1); } hostname[MAXNAMELEN-1] = 0; @@ -233,7 +223,7 @@ main(argc, argv) * the system options file, the user's options file, and the command * line arguments. */ - for (i = 0; i < sizeof (prottbl) / sizeof (struct protent); i++) + for (i = 0; i < N_PROTO; i++) (*prottbl[i].init)(0); progname = *argv; @@ -245,6 +235,20 @@ main(argc, argv) check_auth_options(); setipdefault(); + if (lockflag && !default_device) + if (lock(devname) < 0) + die(1); + + /* + * Initialize syslog system and magic number package. + */ + openlog("pppd", LOG_PID | LOG_NDELAY, LOG_PPP); + setlogmask(LOG_UPTO(LOG_INFO)); + if (debug) + setlogmask(LOG_UPTO(LOG_DEBUG)); + + magic_init(); + p = getlogin(); if (p == NULL) p = "(unknown)"; @@ -314,9 +318,6 @@ main(argc, argv) sigaddset(&mask, SIGINT); sigaddset(&mask, SIGALRM); sigaddset(&mask, SIGIO); -#ifdef STREAMS - sigaddset(&mask, SIGPOLL); -#endif #define SIGNAL(s, handler) { \ sv.sv_handler = handler; \ @@ -333,9 +334,6 @@ main(argc, argv) SIGNAL(SIGTERM, term); /* Terminate */ SIGNAL(SIGALRM, alrm); /* Timeout */ SIGNAL(SIGIO, io); /* Input available */ -#ifdef STREAMS - SIGNAL(SIGPOLL, io); /* Input available */ -#endif signal(SIGUSR1, incdebug); /* Increment debug flag */ signal(SIGUSR2, nodebug); /* Reset debug flag */ @@ -345,9 +343,6 @@ main(argc, argv) */ sigemptyset(&mask); sigaddset(&mask, SIGIO); -#ifdef STREAMS - sigaddset(&mask, SIGPOLL); -#endif sigprocmask(SIG_BLOCK, &mask, NULL); /* @@ -359,18 +354,20 @@ main(argc, argv) } 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); } - - /* set line speed, flow control, etc. */ - set_up_tty(fd); +#endif /* TIOCSCTTY */ /* run connection script */ if (connector) { - syslog(LOG_INFO, "Connecting with <%s>", connector); + MAINDEBUG((LOG_INFO, "Connecting with <%s>", connector)); + + /* set line speed, flow control, etc.; set CLOCAL for now */ + set_up_tty(fd, 1); /* drop dtr to hang up in case modem is off hook */ if (!default_device && modem) { @@ -379,7 +376,7 @@ main(argc, argv) setdtr(fd, TRUE); } - if (set_up_connection(connector, fd, fd) < 0) { + if (device_script(connector, fd, fd) < 0) { syslog(LOG_ERR, "could not set up connection"); setdtr(fd, FALSE); die(1); @@ -389,6 +386,9 @@ main(argc, argv) sleep(1); /* give it time to set up its terminal */ } + /* set line speed, flow control, etc.; clear CLOCAL if modem option */ + set_up_tty(fd, 0); + /* set up the serial device as a ppp interface */ establish_ppp(); @@ -448,11 +448,26 @@ main(argc, argv) */ 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 (;;) { - sigpause(0); /* Wait for next signal */ + 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 */ + reap_kids(); /* Don't leave dead kids lying around */ } + + /* + * Run disconnector script, if requested + */ + if (disconnector) { + if (device_script(disconnector, fd, fd) < 0) { + syslog(LOG_WARNING, "disconnect script failed"); + die(1); + } + + syslog(LOG_INFO, "Disconnected..."); + } + + quit(); } #if B9600 == 9600 @@ -461,6 +476,7 @@ main(argc, argv) * (so we can ask for any speed). */ #define translate_speed(bps) (bps) +#define baud_rate_of(speed) (speed) #else /* @@ -555,14 +571,32 @@ translate_speed(bps) syslog(LOG_WARNING, "speed %d not supported", bps); return 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. + * at the requested speed, etc. If `local' is true, set CLOCAL + * regardless of whether the modem option was specified. */ -set_up_tty(fd) - int fd; +set_up_tty(fd, local) + int fd, local; { #ifndef SGTTY int speed; @@ -576,11 +610,16 @@ set_up_tty(fd) if (!restore_term) inittermios = tios; +#ifdef CRTSCTS tios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CLOCAL | CRTSCTS); - tios.c_cflag |= CS8 | CREAD | HUPCL; if (crtscts) tios.c_cflag |= CRTSCTS; - if (!modem) +#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; @@ -591,12 +630,15 @@ set_up_tty(fd) if (speed) { cfsetospeed(&tios, speed); cfsetispeed(&tios, speed); + } else { + speed = cfgetospeed(&tios); } if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { syslog(LOG_ERR, "tcsetattr: %m"); die(1); } + #else /* SGTTY */ int speed; struct sgttyb sgttyb; @@ -616,15 +658,31 @@ set_up_tty(fd) 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); } #endif + + baud_rate = baud_rate_of(speed); restore_term = TRUE; } +/* + * 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); +} + /* * quit - Clean up state and exit. @@ -656,23 +714,23 @@ cleanup(status, arg) int status; caddr_t arg; { - if (fd != 0) { + if (fd >= 0) { /* drop dtr to hang up */ if (modem) setdtr(fd, FALSE); if (fcntl(fd, F_SETFL, initfdflags) < 0) - syslog(LOG_ERR, "fcntl(F_SETFL, fdflags): %m"); + syslog(LOG_WARNING, "fcntl(F_SETFL, fdflags): %m"); disestablish_ppp(); if (restore_term) { #ifndef SGTTY if (tcsetattr(fd, TCSAFLUSH, &inittermios) < 0) - syslog(LOG_ERR, "tcsetattr: %m"); + syslog(LOG_WARNING, "tcsetattr: %m"); #else if (ioctl(fd, TIOCSETP, &initsgttyb) < 0) - syslog(LOG_ERR, "ioctl(TIOCSETP): %m"); + syslog(LOG_WARNING, "ioctl(TIOCSETP): %m"); #endif } @@ -683,6 +741,9 @@ cleanup(status, arg) if (pidfilename[0] != 0 && unlink(pidfilename) < 0) syslog(LOG_WARNING, "unable to unlink pid file: %m"); pidfilename[0] = 0; + + if (lockflag && !default_device) + unlock(); } @@ -739,7 +800,7 @@ timeout(func, arg, time) 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.", + 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"); @@ -795,7 +856,7 @@ untimeout(func, arg) 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.", + 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"); @@ -912,23 +973,23 @@ alrm(sig, code, scp, addr) char *addr; { struct itimerval itv; - struct callout *freep; + struct callout *freep, *list, *last; MAINDEBUG((LOG_DEBUG, "Alarm")); + if (callout == NULL) + return; /* - * Call and free first scheduled timeout and any that were scheduled - * for the same time. + * Get the first scheduled timeout and any that were scheduled + * for the same time as a list, and remove them all from callout + * list. */ - while (callout) { - freep = callout; /* Remove entry before calling */ - callout = freep->c_next; - (*freep->c_func)(freep->c_arg); - (void) free((char *) freep); - if (callout && callout->c_time) - break; - } - + 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. */ @@ -936,7 +997,7 @@ alrm(sig, code, scp, addr) 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.", + 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"); @@ -947,6 +1008,17 @@ alrm(sig, code, scp, addr) 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); + } + } @@ -1000,10 +1072,13 @@ io(sig, code, scp, addr) return; if (len == 0) { - syslog(LOG_ERR, "End of file on fd!"); + syslog(LOG_WARNING, "End of file on fd!"); die(1); } + if (debug /*&& (debugflags & DBG_INPACKET)*/) + log_packet(p, len, "rcvd "); + if (len < DLLHEADERLEN) { MAINDEBUG((LOG_INFO, "io(): Received short packet.")); return; @@ -1019,8 +1094,6 @@ io(sig, code, scp, addr) if (protocol != LCP && lcp_fsm[0].state != OPENED) { MAINDEBUG((LOG_INFO, "io(): Received non-LCP packet when LCP not open.")); - if (debug) - dumpbuffer(inpacket_buf, len + DLLHEADERLEN, LOG_INFO); return; } @@ -1098,10 +1171,11 @@ nodebug(sig) /* - * set_up_connection - run a program to initialize the serial connector + * device_script - run a program to connect or disconnect the + * serial device. */ int -set_up_connection(program, in, out) +device_script(program, in, out) char *program; int in, out; { @@ -1115,12 +1189,12 @@ set_up_connection(program, in, out) sigprocmask(SIG_BLOCK, &mask, &mask); pid = fork(); - + if (pid < 0) { syslog(LOG_ERR, "fork: %m"); die(1); } - + if (pid == 0) { setreuid(getuid(), getuid()); setregid(getgid(), getgid()); @@ -1133,10 +1207,10 @@ set_up_connection(program, in, out) /* NOTREACHED */ } - while (waitpid(pid, &status, 0) != pid) { + while (waitpid(pid, &status, 0) < 0) { if (errno == EINTR) continue; - syslog(LOG_ERR, "waiting for connection process: %m"); + syslog(LOG_ERR, "waiting for (dis)connection process: %m"); die(1); } sigprocmask(SIG_SETMASK, &mask, NULL); @@ -1146,82 +1220,154 @@ set_up_connection(program, in, out) /* - * Return user specified netmask. A value of zero means no netmask has - * been set. + * run-program - execute a program with given arguments, + * but don't wait for it. + * If the program can't be executed, logs an error unless + * must_exist is 0 and the program file doesn't exist. */ -/* ARGSUSED */ -u_long -GetMask(addr) - u_long addr; +int +run_program(prog, args, must_exist) + char *prog; + char **args; + int must_exist; { - return(netmask); + int pid; + + pid = fork(); + if (pid == -1) { + syslog(LOG_ERR, "can't fork to run %s: %m", prog); + return -1; + } + if (pid == 0) { + execv(prog, args); + if (must_exist || errno != ENOENT) + syslog(LOG_WARNING, "can't execute %s: %m", prog); + _exit(-1); + } + MAINDEBUG((LOG_DEBUG, "Script %s started; pid = %d", prog, pid)); + ++n_children; + return 0; } + /* - * dumpbuffer - print contents of a buffer in hex to standard output. + * reap_kids - get status from any dead child processes, + * and log a message for abnormal terminations. */ void -dumpbuffer(buffer, size, level) - unsigned char *buffer; - int size; - int level; +reap_kids() { - register int i; - char line[256], *p; + int pid, status; - printf("%d bytes:\n", size); - while (size > 0) - { - p = line; - sprintf(p, "%08lx: ", buffer); - p += 10; - - for (i = 0; i < 8; i++, p += 3) - if (size - i <= 0) - sprintf(p, "xx "); - else - sprintf(p, "%02x ", buffer[i]); - - for (i = 0; i < 8; i++) - if (size - i <= 0) - *p++ = 'x'; - else - *p++ = (' ' <= buffer[i] && buffer[i] <= '~') ? - buffer[i] : '.'; - - *p++ = 0; - buffer += 8; - size -= 8; - -/* syslog(level, "%s\n", line); */ - printf("%s\n", line); - fflush(stdout); + if (n_children == 0) + return; + if ((pid = waitpid(-1, &status, WNOHANG)) == -1) { + if (errno != ECHILD) + syslog(LOG_ERR, "waitpid: %m"); + return; + } + if (pid > 0) { + --n_children; + if (WIFSIGNALED(status)) { + syslog(LOG_WARNING, "child process %d terminated with signal %d", + pid, WTERMSIG(status)); + } } } /* - * setdtr - control the DTR line on the serial port. - * This is called from die(), so it shouldn't call die(). + * log_packet - format a packet and log it. */ -setdtr(fd, on) -int fd, on; -{ - int modembits = TIOCM_DTR; - ioctl(fd, (on? TIOCMBIS: TIOCMBIC), &modembits); +char line[256]; /* line to be logged accumulated here */ +char *linep; + +void +log_packet(p, len, prefix) + u_char *p; + int len; + char *prefix; +{ + strcpy(line, prefix); + linep = line + strlen(line); + format_packet(p, len, pr_log, NULL); + if (linep != line) + syslog(LOG_DEBUG, "%s", line); } +/* + * format_packet - make a readable representation of a packet, + * calling `printer(arg, format, ...)' to output it. + */ +void +format_packet(p, len, printer, arg) + u_char *p; + int len; + void (*printer) __ARGS((void *, char *, ...)); + void *arg; +{ + int i, n; + u_short proto; + u_char x; + + if (len >= DLLHEADERLEN && p[0] == ALLSTATIONS && p[1] == UI) { + p += 2; + GETSHORT(proto, p); + len -= DLLHEADERLEN; + for (i = 0; i < N_PROTO; ++i) + if (proto == prottbl[i].protocol) + break; + if (i < N_PROTO) { + printer(arg, "[%s", prottbl[i].name); + n = (*prottbl[i].printpkt)(p, len, printer, arg); + printer(arg, "]"); + p += n; + len -= n; + } else { + printer(arg, "[proto=0x%x]", proto); + } + } + + for (; len > 0; --len) { + GETCHAR(x, p); + printer(arg, " %.2x", x); + } +} + +#ifdef __STDC__ +#include + +void +pr_log(void *arg, char *fmt, ...) +{ + int n; + va_list pvar; + char buf[256]; + + va_start(pvar, fmt); + vsprintf(buf, fmt, pvar); + va_end(pvar); + + n = strlen(buf); + if (linep + n + 1 > line + sizeof(line)) { + syslog(LOG_DEBUG, "%s", line); + linep = line; + } + strcpy(linep, buf); + linep += n; +} + +#else /* __STDC__ */ #include -char line[256]; -char *p; - -logf(level, fmt, va_alist) -int level; +void +pr_log(arg, fmt, va_alist) +void *arg; char *fmt; va_dcl { + int n; va_list pvar; char buf[256]; @@ -1229,15 +1375,43 @@ va_dcl vsprintf(buf, fmt, pvar); va_end(pvar); - p = line + strlen(line); - strcat(p, buf); - - if (buf[strlen(buf)-1] == '\n') { - syslog(level, "%s", line); - line[0] = 0; + n = strlen(buf); + if (linep + n + 1 > line + sizeof(line)) { + syslog(LOG_DEBUG, "%s", line); + linep = line; } + strcpy(linep, buf); + linep += n; +} +#endif + +/* + * print_string - print a readable representation of a string using + * printer. + */ +void +print_string(p, len, printer, arg) + char *p; + int len; + void (*printer) __ARGS((void *, char *, ...)); + void *arg; +{ + int c; + + printer(arg, "\""); + for (; len > 0; --len) { + c = *p++; + if (' ' <= c && c <= '~') + printer(arg, "%c", c); + else + printer(arg, "\\%.3o", c); + } + printer(arg, "\""); } +/* + * novm - log an error message saying we ran out of memory, and die. + */ void novm(msg) char *msg; diff --git a/usr.sbin/pppd/pppd/options.c b/usr.sbin/pppd/pppd/options.c index cf6dff425eb5..7b28559fad8d 100644 --- a/usr.sbin/pppd/pppd/options.c +++ b/usr.sbin/pppd/pppd/options.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: options.c,v 1.5 1994/02/22 00:12:01 paulus Exp $"; +static char rcsid[] = "$Id: options.c,v 1.6 1994/05/08 12:16:26 paulus Exp $"; #endif #include @@ -45,11 +45,11 @@ static char rcsid[] = "$Id: options.c,v 1.5 1994/02/22 00:12:01 paulus Exp $"; #define FALSE 0 #define TRUE 1 - /* * Prototypes */ 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)); @@ -65,16 +65,20 @@ 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 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 **)); @@ -110,10 +114,13 @@ static int number_option __ARGS((char *, long *, int)); */ 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; @@ -156,16 +163,21 @@ static struct cmd { "-chap", 0, nochap, /* Don't allow CHAP authentication with peer */ "-vj", 0, setnovj, /* disable VJ compression */ "asyncmap", 1, setasyncmap, /* set the desired async map */ + "escape", 1, setescape, /* set chars to escape on transmission */ "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 */ "debug", 0, setdebug, /* Increase debugging level */ + "kdebug", 1, setkdebug, /* Enable kernel-level debugging */ "domain", 1, setdomain, /* Add given domain name to hostname*/ "mru", 1, setmru, /* Set MRU value for negotiation */ + "mtu", 1, setmtu, /* Set our MTU */ "netmask", 1, setnetmask, /* set netmask */ "passive", 0, setpassive, /* Set passive mode */ "silent", 0, setsilent, /* Set silent mode */ "modem", 0, setmodem, /* Use modem control lines */ "local", 0, setlocal, /* Don't use modem control lines */ + "lock", 0, setlock, /* Lock serial device (with lock file) */ "name", 1, setname, /* Set local name for authentication */ "user", 1, setuser, /* Set username for PAP auth with peer */ "usehostname", 0, setusehostname, /* Must use hostname for auth. */ @@ -215,34 +227,6 @@ Usage: %s [ arguments ], where arguments are:\n\ See pppd(8) for more options.\n\ "; -/* -Options omitted: - -all Don't request/allow any options\n\ - -ac Disable Address/Control compression\n\ - -am Disable asyncmap negotiation\n\ - -as Set the desired async map to hex \n\ - -d Increase debugging level\n\ - -detach Don't fork to background\n\ - -ip Disable IP address negotiation\n\ - -mn Disable magic number negotiation\n\ - -mru Disable mru negotiation\n\ - -p Set passive mode\n\ - -pc Disable protocol field compression\n\ - +ua Get username and password for authenticating\n\ - with peer using PAP from file \n\ - +pap Require PAP authentication from peer\n\ - -pap Don't agree to authenticating with peer using PAP\n\ - +chap Require CHAP authentication from peer\n\ - -chap Don't agree to authenticating with peer using CHAP\n\ - -vj disable VJ compression\n\ - -auth Don't agree to authenticate with peer\n\ - debug Increase debugging level\n\ - domain Append domain name to hostname for authentication\n\ - passive Set passive mode\n\ - local Don't use modem control lines\n\ - proxyarp Add proxy ARP entry\n\ -*/ - /* * parse_args - parse a string of arguments, from the command @@ -319,7 +303,7 @@ options_from_file(filename, must_exist) if (!must_exist && errno == ENOENT) return 1; perror(filename); - exit(1); + return 0; } while (getword(f, cmd, &newline, filename)) { /* @@ -549,10 +533,19 @@ static int setdebug() { debug++; - setlogmask(LOG_UPTO(LOG_DEBUG)); return (1); } +/* + * setkdebug - Set kernel debugging level. + */ +static int +setkdebug(argv) + char **argv; +{ + return int_option(*argv, &kdebugflag); +} + /* * noopt - Disable all options. */ @@ -643,6 +636,27 @@ setmru(argv) } +/* + * setmru - Set the largest MTU we'll use. + */ +static int +setmtu(argv) + char **argv; +{ + long 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, + (mtu < MINMRU? "small": "large")); + return 0; + } + lcp_allowoptions[0].mru = mtu; + return (1); +} + + /* * nopcomp - Disable Protocol field compression negotiation. */ @@ -716,7 +730,7 @@ setupapfile(argv) /* open user info file */ if ((ufile = fopen(*argv, "r")) == NULL) { fprintf(stderr, "unable to open user login data file %s\n", *argv); - exit(1); + return 0; } check_access(ufile, *argv); @@ -724,7 +738,7 @@ setupapfile(argv) if (fgets(user, MAXNAMELEN - 1, ufile) == NULL || fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){ fprintf(stderr, "Unable to read user login data file %s.\n", *argv); - exit(2); + return 0; } fclose(ufile); @@ -788,6 +802,20 @@ setconnector(argv) return (1); } +/* + * setdisconnector - Set a program to disconnect from the serial line + */ +static int +setdisconnector(argv) + char **argv; +{ + disconnector = strdup(*argv); + if (disconnector == NULL) + novm("disconnector string"); + + return (1); +} + /* * setdomain - Set domain name to append to hostname @@ -801,6 +829,10 @@ setdomain(argv) return (1); } + +/* + * setasyncmap - add bits to asyncmap (what we request peer to escape). + */ static int setasyncmap(argv) char **argv; @@ -814,6 +846,38 @@ setasyncmap(argv) return(1); } + +/* + * setescape - add chars to the set we escape on transmission. + */ +static int +setescape(argv) + char **argv; +{ + int n, ret; + char *p, *endp; + + p = *argv; + ret = 1; + while (*p) { + n = strtol(p, &endp, 16); + if (p == endp) { + fprintf(stderr, "%s: invalid hex number: %s\n", progname, p); + return 0; + } + p = endp; + if (n < 0 || 0x20 <= n && n <= 0x3F || n == 0x5E || n > 0xFF) { + fprintf(stderr, "%s: can't escape character 0x%x\n", n); + ret = 0; + } else + xmit_accm[0][n >> 5] |= 1 << (n & 0x1F); + while (*p == ',' || *p == ' ') + ++p; + } + return ret; +} + + /* * setspeed - Set the speed. */ @@ -857,7 +921,7 @@ setdevname(cp) if (errno == ENOENT) return (0); syslog(LOG_ERR, cp); - exit(1); + return 0; } (void) strncpy(devname, cp, MAXPATHLEN); @@ -1006,13 +1070,26 @@ setnetmask(argv) if ((mask = inet_addr(*argv)) == -1) { fprintf(stderr, "Invalid netmask %s\n", *argv); - exit(1); + return 0; } 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; +{ + return(netmask); +} + + static int setcrtscts() { @@ -1041,6 +1118,13 @@ setlocal() return 1; } +static int +setlock() +{ + lockflag = 1; + return 1; +} + static int setusehostname() { diff --git a/usr.sbin/pppd/pppd/patchlevel.h b/usr.sbin/pppd/pppd/patchlevel.h index 6a50eae22344..c5880b7a7b58 100644 --- a/usr.sbin/pppd/pppd/patchlevel.h +++ b/usr.sbin/pppd/pppd/patchlevel.h @@ -1,5 +1,5 @@ -/* $Id: patchlevel.h,v 1.6 1994/02/22 00:12:03 paulus Exp $ */ -#define PATCHLEVEL 4 +/* $Id: patchlevel.h,v 1.7 1994/05/08 12:16:27 paulus Exp $ */ +#define PATCHLEVEL 0 -#define VERSION "2.0" -#define DATE "9 Feb 94" +#define VERSION "2.1" +#define DATE "1 May 94" diff --git a/usr.sbin/pppd/pppd/pathnames.h b/usr.sbin/pppd/pppd/pathnames.h index 818b85f0eb6a..d8634448c67f 100644 --- a/usr.sbin/pppd/pppd/pathnames.h +++ b/usr.sbin/pppd/pppd/pathnames.h @@ -1,10 +1,10 @@ /* * define path names * - * $Id: pathnames.h,v 1.4 1993/11/10 01:34:26 paulus Exp $ + * $Id: pathnames.h,v 1.5 1994/05/08 12:16:28 paulus Exp $ */ -#ifdef STREAMS +#if defined(STREAMS) || defined(ultrix) #define _PATH_PIDFILE "/etc/ppp" #else #define _PATH_PIDFILE "/var/run" @@ -13,3 +13,5 @@ #define _PATH_UPAPFILE "/etc/ppp/pap-secrets" #define _PATH_CHAPFILE "/etc/ppp/chap-secrets" #define _PATH_SYSOPTIONS "/etc/ppp/options" +#define _PATH_IPUP "/etc/ppp/ip-up" +#define _PATH_IPDOWN "/etc/ppp/ip-down" diff --git a/usr.sbin/pppd/pppd/pppd.8 b/usr.sbin/pppd/pppd/pppd.8 index d1553fd3535b..498c7f8da8db 100644 --- a/usr.sbin/pppd/pppd/pppd.8 +++ b/usr.sbin/pppd/pppd/pppd.8 @@ -1,5 +1,5 @@ .\" manual page [] for pppd 2.0 -.\" $Id: pppd.8,v 1.5 1994/02/22 00:12:04 paulus Exp $ +.\" $Id: pppd.8,v 1.6 1994/05/08 12:16:29 paulus Exp $ .\" SH section heading .\" SS subsection heading .\" LP paragraph @@ -50,20 +50,23 @@ Set the async character map to . This map describes which control characters cannot be successfully received over the serial line. .I pppd -will ask the peer to send these characters as a 2-byte "escape" sequence. +will ask the peer to send these characters as a 2-byte escape sequence. The argument is a 32 bit hex number with each bit representing a character to escape. Bit 0 (00000001) represents the character 0x00; bit 31 (80000000) represents the character 0x1f or ^_. -The default asyncmap is 0. If multiple \fBasyncmap\fR options are +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 +\fIall\fR control characters. .TP .B auth Require the peer to authenticate itself before allowing network packets to be sent or received. .TP .B connect \fI

-Use the executable or shell command specified by

to set up the +Use the executable or shell command specified by \fI

\fR to set up the serial line. This script would typically use the "chat" program to dial the modem and start the remote ppp session. .TP @@ -76,14 +79,33 @@ Add a default route to the system routing tables, using the peer as the gateway, when IPCP negotiation is successfully completed. This entry is removed when the PPP connection is broken. .TP +.B disconnect \fI

+Run the executable or shell command specified by \fI

\fR after +\fIpppd\fR has terminated the link. This script could, for example, +issue commands to the modem to cause it to hang up. +.TP +.B escape \fIxx,yy,... +Specifies that certain characters should be escaped on transmission +(regardless of whether the peer requests them to be escaped with its +async control character map). The characters to be escaped are +specified as a list of hex numbers separated by commas. Note that +almost any character can be specified for the \fBescape\fR option, +unlike the \fBasyncmap\fR option which only allows control characters +to be specified. The characters which may not be escaped are those +with hex values 0x20 - 0x3f or 0x5e. +.TP .B file \fI Read options from file (the format is described below). .TP +.B lock +Specifies that \fIpppd\fR should use a UUCP-style lock on the serial +device to ensure exclusive access to the device. +.TP .B mru \fI Set the MRU [Maximum Receive Unit] value to for negotiation. .I pppd will ask the peer to send packets of no more than bytes. - The minimum MRU value is 128. +The minimum MRU value is 128. The default MRU value is 1500. A value of 296 is recommended for slow links (40 bytes for TCP/IP header + 256 bytes of data). .TP @@ -132,17 +154,18 @@ default values). .TP .B -ac Disable Address/Control compression negotiation (use default, i.e. -disabled). +address/control field disabled). .TP .B -am -Disable asyncmap negotiation (use default, i.e. 0xffffffff). +Disable asyncmap negotiation (use the default asyncmap, i.e. escape +all control characters). .TP .B -as \fI Same as .B asyncmap \fI .TP .B -d -Increase debugging level. +Increase debugging level (same as the \fBdebug\fR option). .TP .B -detach Don't fork to become a background process (otherwise @@ -168,7 +191,8 @@ Same as the option. .TP .B -pc -Disable protocol field compression negotiation (use default, i.e. disabled). +Disable protocol field compression negotiation (use default, i.e. +protocol field compression disabled). .TP .B +ua \fI

Agree to authenticate using PAP [Password Authentication Protocol] if @@ -196,9 +220,13 @@ Disable negotiation of Van Jacobson style IP header compression (use default, i.e. no compression). .TP .B debug -Increase debugging level (same as -.B -d -). +Increase debugging level (same as \fB\-d\fR). +If this +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)). .TP .B domain \fI Append the domain name to the local host name for authentication @@ -209,9 +237,22 @@ domain option to set the domain name to Quotron.COM. .B modem Use the modem control lines. (This option is not fully implemented.) .TP +.B kdebug \fIn +Enable debugging code in the kernel-level PPP driver. The argument +\fIn\fR is a number which is the sum of the following values: 1 to +enable general debug messages, 2 to request that the contents of +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. .TP +.B mtu \fI +Set the MTU [Maximum Transmit Unit] value to \fI\fR. Unless the +peer requests a smaller value via MRU negotiation, \fIpppd\fR will +request that the kernel networking code send data packets of no more +than \fIn\fR bytes through the PPP network interface. +.TP .B name \fI Set the name of the local system for authentication purposes to . .TP @@ -429,6 +470,16 @@ other Network Control Protocol) can be started. If authentication fails, \fIpppd\fR will terminated the link (by closing LCP). If IPCP negotiates an unacceptable IP address for the remote host, IPCP will be closed. IP packets can only be sent or received when IPCP is open. +.LP +In some cases it is desirable to allow some hosts which can't +authenticate themselves to connect and use one of a restricted set of +IP addresses, even when the local host generally requires +authentication. If the peer refuses to authenticate itself when +requested, \fIpppd\fR takes that as equivalent to authenticating with +PAP using the empty string for the username and password. Thus, by +adding a line to the pap-secrets file which specifies the empty string +for the client and password, it is possible to allow restricted access +to hosts which refuse to authenticate themselves. .SH ROUTING .LP When IPCP negotiation is completed successfully, @@ -483,29 +534,34 @@ for example: pppd /dev/ttya 38400 connect 'chat "" "" "login:" "username" "Password:" "password" "% " "exec pppd passive"' .LP +(Note however that running chat like this will leave the password +visible in the parameter list of pppd and chat.) +.LP If your serial connection is any more complicated than a piece of wire, you may need to arrange for some control characters to be escaped. In particular, it is often useful to escape XON (^Q) and XOFF (^S), using \fBasyncmap a0000\fR. If the path includes a telnet, you probably should escape ^] as well (\fBasyncmap 200a0000\fR). -Don't use an rlogin in the path - many implementations are not +If the path includes an rlogin, you will need to use the \fBescape +ff\fR option on the end which is running the rlogin client, since many +rlogin implementations are not transparent; they will remove the sequence [0xff, 0xff, 0x73, 0x73, followed by any 8 bytes] from the stream. .SH DIAGNOSTICS .LP -Messages are sent to the syslog daemon using facility -LOG_DAEMON unless -.I pppd -has been compiled with debugging code. In this case the logging -facility used will be LOG_LOCAL2 in order to allow separation of the debug -output from the other daemons using the LOG_DAEMON facility. You can -override this by defining the macro LOG_PPP to the desired facility -and recompiling. In order to see the error and debug messages, you -will need to edit your /etc/syslog.conf file to direct the messages to -the desired output device or file. +Messages are sent to the syslog daemon using facility LOG_DAEMON. +(This can be overriden by recompiling \fIpppd\fR with the macro +LOG_PPP defined as the desired facility.) In order to see the error +and debug messages, you will need to edit your /etc/syslog.conf file +to direct the messages to the desired output device or file. .LP -If enabled at compile time, debugging printout can be enabled by -setting the -d or debug flag on the command line, or by sending a +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, the \fBdebug\fR option also +causes other debugging messages to be logged. +.LP +Debugging can also be enabled by sending a SIGUSR1 to the .I pppd process. @@ -542,12 +598,6 @@ Rivest, R. .I The MD5 Message-Digest Algorithm. 1992 April. .TP -.B RFC1331 -Simpson, W.A. -.I Point\-to\-Point Protocol (PPP) for the transmission of multi\-protocol -.I datagrams over point\-to\-point links. -1992 May. -.TP .B RFC1332 McGregor, G. .I PPP Internet Protocol Control Protocol (IPCP). @@ -557,6 +607,16 @@ McGregor, G. Lloyd, B.; Simpson, W.A. .I PPP authentication protocols. 1992 October. +.TP +.B RFC1548 +Simpson, W.A. +.I The Point\-to\-Point Protocol (PPP). +1993 December. +.TP +.B RFC1549 +Simpson, W.A. +.I PPP in HDLC Framing. +1993 December .SH NOTES The following signals have the specified effect when sent to the .I pppd diff --git a/usr.sbin/pppd/pppd/pppd.h b/usr.sbin/pppd/pppd/pppd.h index dc6ff25e2fd2..c75cc4c1e89a 100644 --- a/usr.sbin/pppd/pppd/pppd.h +++ b/usr.sbin/pppd/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.4 1993/11/10 01:34:32 paulus Exp $ + * $Id: pppd.h,v 1.5 1994/05/08 12:16:30 paulus Exp $ */ /* @@ -39,6 +39,9 @@ #define MAXNAMELEN 256 /* max length of hostname or name for auth */ #define MAXSECRETLEN 256 /* max length of password or secret */ +/* + * Global variables. + */ extern int debug; /* Debug flag */ extern int ifunit; /* Interface unit number */ extern char ifname[]; /* Interface name */ @@ -46,7 +49,20 @@ 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 */ +/* + * Values for phase. + */ +#define PHASE_DEAD 0 +#define PHASE_ESTABLISH 1 +#define PHASE_AUTHENTICATE 2 +#define PHASE_NETWORK 3 +#define PHASE_TERMINATE 4 + +/* + * Prototypes. + */ void quit __ARGS((void)); /* Cleanup and exit */ void timeout __ARGS((void (*)(), caddr_t, int)); /* Look-alike of kernel's timeout() */ diff --git a/usr.sbin/pppd/pppd/sys-bsd.c b/usr.sbin/pppd/pppd/sys-bsd.c index 034dcc03bce6..a99e333cb62c 100644 --- a/usr.sbin/pppd/pppd/sys-bsd.c +++ b/usr.sbin/pppd/pppd/sys-bsd.c @@ -19,7 +19,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: sys-bsd.c,v 1.3 1994/01/25 05:58:14 paulus Exp $"; +static char rcsid[] = "$Id: sys-bsd.c,v 1.4 1994/05/08 12:16:31 paulus Exp $"; #endif /* @@ -42,8 +42,8 @@ static char rcsid[] = "$Id: sys-bsd.c,v 1.3 1994/01/25 05:58:14 paulus Exp $"; #include "pppd.h" #include "ppp.h" -static int initdisc; /* Initial TTY discipline */ - +static int initdisc = -1; /* Initial TTY discipline */ +extern int kdebugflag; /* * establish_ppp - Turn the serial port into a ppp interface. @@ -52,6 +52,7 @@ void establish_ppp() { int pppdisc = PPPDISC; + int x; if (ioctl(fd, TIOCGETD, &initdisc) < 0) { syslog(LOG_ERR, "ioctl(TIOCGETD): %m"); @@ -69,6 +70,19 @@ establish_ppp() syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m"); die(1); } + + /* + * Enable debug in the driver if requested. + */ + if (kdebugflag) { + if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { + syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m"); + } else { + x |= (kdebugflag & 0xFF) * SC_DEBUG; + if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) + syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m"); + } + } } @@ -79,8 +93,37 @@ establish_ppp() void disestablish_ppp() { - if (ioctl(fd, TIOCSETD, &initdisc) < 0) - syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); + int x; + char *s; + + if (initdisc >= 0) { + /* + * Check whether the link seems not to be 8-bit clean. + */ + if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) { + s = NULL; + switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) { + case SC_RCV_B7_0: + s = "bit 7 set to 1"; + break; + case SC_RCV_B7_1: + s = "bit 7 set to 0"; + break; + case SC_RCV_EVNP: + s = "odd parity"; + break; + case SC_RCV_ODDP: + s = "even parity"; + break; + } + if (s != NULL) { + syslog(LOG_WARNING, "Serial link is not 8-bit clean:"); + syslog(LOG_WARNING, "All received characters had %s", s); + } + } + if (ioctl(fd, TIOCSETD, &initdisc) < 0) + syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); + } } @@ -95,6 +138,8 @@ output(unit, p, len) { if (unit != 0) MAINDEBUG((LOG_WARNING, "output: unit != 0!")); + if (debug) + log_packet(p, len, "sent "); if (write(fd, p, len) < 0) { syslog(LOG_ERR, "write: %m"); @@ -161,9 +206,23 @@ ppp_send_config(unit, mtu, asyncmap, pcomp, accomp) } } + +/* + * ppp_set_xaccm - set the extended transmit ACCM for the interface. + */ +void +ppp_set_xaccm(unit, accm) + int unit; + ext_accm accm; +{ + if (ioctl(fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY) + syslog(LOG_WARNING, "ioctl(set extended ACCM): %m"); +} + + /* * ppp_recv_config - configure the receive-side characteristics of - * the ppp interface. At present this does nothing. + * the ppp interface. */ void ppp_recv_config(unit, mru, asyncmap, pcomp, accomp) @@ -171,12 +230,16 @@ ppp_recv_config(unit, mru, asyncmap, pcomp, accomp) u_long asyncmap; int pcomp, accomp; { -#ifdef notyet + int x; + + if (ioctl(fd, PPPIOCSMRU, (caddr_t) &mru) < 0) { + syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m"); + quit(); + } if (ioctl(fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) { syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m"); quit(); } - if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m"); quit(); @@ -186,14 +249,14 @@ ppp_recv_config(unit, mru, asyncmap, pcomp, accomp) syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); quit(); } -#endif /* notyet */ } /* * sifvjcomp - config tcp header compression */ int -sifvjcomp(u, vjcomp, cidcomp) +sifvjcomp(u, vjcomp, cidcomp, maxcid) + int u, vjcomp, cidcomp, maxcid; { u_int x; @@ -203,7 +266,11 @@ sifvjcomp(u, vjcomp, cidcomp) } x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP; x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID; - if(ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) { + if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) { + syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); + return 0; + } + if (ioctl(fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) { syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); return 0; } @@ -211,12 +278,14 @@ sifvjcomp(u, vjcomp, cidcomp) } /* - * sifup - Config the interface up. + * sifup - Config the interface up and enable IP packets to pass. */ int sifup(u) { struct ifreq ifr; + u_int x; + strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m"); @@ -227,27 +296,51 @@ sifup(u) 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; + } return 1; } /* - * sifdown - Config the interface down. + * sifdown - Config the interface down and disable IP. */ int sifdown(u) { struct ifreq ifr; + u_int x; + int rv; + + 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"); + rv = 0; + } + } strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m"); - return 0; + rv = 0; + } else { + ifr.ifr_flags &= ~IFF_UP; + if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { + syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m"); + rv = 0; + } } - ifr.ifr_flags &= ~IFF_UP; - if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { - syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m"); - return 0; - } - return 1; + return rv; } /* @@ -481,11 +574,11 @@ get_ether_addr(ipaddr, hwaddr) return 0; } + /* * 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() { diff --git a/usr.sbin/pppd/pppd/upap.c b/usr.sbin/pppd/pppd/upap.c index 85c6f1521296..41485fef5e27 100644 --- a/usr.sbin/pppd/pppd/upap.c +++ b/usr.sbin/pppd/pppd/upap.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: upap.c,v 1.3 1993/11/10 01:34:35 paulus Exp $"; +static char rcsid[] = "$Id: upap.c,v 1.4 1994/05/08 12:16:32 paulus Exp $"; #endif /* @@ -310,7 +310,7 @@ upap_rauthreq(u, inp, id, len) return; } GETCHAR(ruserlen, inp); - len -= sizeof (u_char) + ruserlen + sizeof (u_char);; + len -= sizeof (u_char) + ruserlen + sizeof (u_char); if (len < 0) { UPAPDEBUG((LOG_INFO, "upap_rauth: rcvd short packet.")); return; @@ -482,3 +482,80 @@ upap_sresp(u, code, id, msg, msglen) UPAPDEBUG((LOG_INFO, "upap_sresp: Sent code %d, id %d.", code, id)); } + +/* + * upap_printpkt - print the contents of a PAP packet. + */ +char *upap_codenames[] = { + "AuthReq", "AuthAck", "AuthNak" +}; + +int +upap_printpkt(p, plen, printer, arg) + u_char *p; + int plen; + void (*printer) __ARGS((void *, char *, ...)); + void *arg; +{ + int code, id, len; + int mlen, ulen, wlen; + char *user, *pwd, *msg; + u_char *pstart; + + if (plen < UPAP_HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < UPAP_HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= sizeof(upap_codenames) / sizeof(char *)) + printer(arg, " %s", upap_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= UPAP_HEADERLEN; + switch (code) { + case UPAP_AUTHREQ: + if (len < 1) + break; + ulen = p[0]; + if (len < ulen + 2) + break; + wlen = p[ulen + 1]; + if (len < ulen + wlen + 2) + break; + user = (char *) (p + 1); + pwd = (char *) (p + ulen + 2); + p += ulen + wlen + 2; + len -= ulen + wlen + 2; + printer(arg, " user="); + print_string(user, ulen, printer, arg); + printer(arg, " password="); + print_string(pwd, wlen, printer, arg); + break; + case UPAP_AUTHACK: + case UPAP_AUTHNAK: + if (len < 1) + break; + mlen = p[0]; + if (len < mlen + 1) + break; + msg = (char *) (p + 1); + p += mlen + 1; + len -= mlen + 1; + printer(arg, "msg="); + print_string(msg, mlen, printer, arg); + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; +} diff --git a/usr.sbin/pppd/pppd/upap.h b/usr.sbin/pppd/pppd/upap.h index b8fa2ab78477..6c771798b609 100644 --- a/usr.sbin/pppd/pppd/upap.h +++ b/usr.sbin/pppd/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.3 1993/11/10 01:34:38 paulus Exp $ + * $Id: upap.h,v 1.4 1994/05/08 12:16:34 paulus Exp $ */ /* @@ -87,3 +87,5 @@ 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 *)); diff --git a/usr.sbin/pppd/sys-bsd.c b/usr.sbin/pppd/sys-bsd.c index 034dcc03bce6..a99e333cb62c 100644 --- a/usr.sbin/pppd/sys-bsd.c +++ b/usr.sbin/pppd/sys-bsd.c @@ -19,7 +19,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: sys-bsd.c,v 1.3 1994/01/25 05:58:14 paulus Exp $"; +static char rcsid[] = "$Id: sys-bsd.c,v 1.4 1994/05/08 12:16:31 paulus Exp $"; #endif /* @@ -42,8 +42,8 @@ static char rcsid[] = "$Id: sys-bsd.c,v 1.3 1994/01/25 05:58:14 paulus Exp $"; #include "pppd.h" #include "ppp.h" -static int initdisc; /* Initial TTY discipline */ - +static int initdisc = -1; /* Initial TTY discipline */ +extern int kdebugflag; /* * establish_ppp - Turn the serial port into a ppp interface. @@ -52,6 +52,7 @@ void establish_ppp() { int pppdisc = PPPDISC; + int x; if (ioctl(fd, TIOCGETD, &initdisc) < 0) { syslog(LOG_ERR, "ioctl(TIOCGETD): %m"); @@ -69,6 +70,19 @@ establish_ppp() syslog(LOG_ERR, "ioctl(PPPIOCGUNIT): %m"); die(1); } + + /* + * Enable debug in the driver if requested. + */ + if (kdebugflag) { + if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { + syslog(LOG_WARNING, "ioctl (PPPIOCGFLAGS): %m"); + } else { + x |= (kdebugflag & 0xFF) * SC_DEBUG; + if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) + syslog(LOG_WARNING, "ioctl(PPPIOCSFLAGS): %m"); + } + } } @@ -79,8 +93,37 @@ establish_ppp() void disestablish_ppp() { - if (ioctl(fd, TIOCSETD, &initdisc) < 0) - syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); + int x; + char *s; + + if (initdisc >= 0) { + /* + * Check whether the link seems not to be 8-bit clean. + */ + if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) == 0) { + s = NULL; + switch (~x & (SC_RCV_B7_0|SC_RCV_B7_1|SC_RCV_EVNP|SC_RCV_ODDP)) { + case SC_RCV_B7_0: + s = "bit 7 set to 1"; + break; + case SC_RCV_B7_1: + s = "bit 7 set to 0"; + break; + case SC_RCV_EVNP: + s = "odd parity"; + break; + case SC_RCV_ODDP: + s = "even parity"; + break; + } + if (s != NULL) { + syslog(LOG_WARNING, "Serial link is not 8-bit clean:"); + syslog(LOG_WARNING, "All received characters had %s", s); + } + } + if (ioctl(fd, TIOCSETD, &initdisc) < 0) + syslog(LOG_ERR, "ioctl(TIOCSETD): %m"); + } } @@ -95,6 +138,8 @@ output(unit, p, len) { if (unit != 0) MAINDEBUG((LOG_WARNING, "output: unit != 0!")); + if (debug) + log_packet(p, len, "sent "); if (write(fd, p, len) < 0) { syslog(LOG_ERR, "write: %m"); @@ -161,9 +206,23 @@ ppp_send_config(unit, mtu, asyncmap, pcomp, accomp) } } + +/* + * ppp_set_xaccm - set the extended transmit ACCM for the interface. + */ +void +ppp_set_xaccm(unit, accm) + int unit; + ext_accm accm; +{ + if (ioctl(fd, PPPIOCSXASYNCMAP, accm) < 0 && errno != ENOTTY) + syslog(LOG_WARNING, "ioctl(set extended ACCM): %m"); +} + + /* * ppp_recv_config - configure the receive-side characteristics of - * the ppp interface. At present this does nothing. + * the ppp interface. */ void ppp_recv_config(unit, mru, asyncmap, pcomp, accomp) @@ -171,12 +230,16 @@ ppp_recv_config(unit, mru, asyncmap, pcomp, accomp) u_long asyncmap; int pcomp, accomp; { -#ifdef notyet + int x; + + if (ioctl(fd, PPPIOCSMRU, (caddr_t) &mru) < 0) { + syslog(LOG_ERR, "ioctl(PPPIOCSMRU): %m"); + quit(); + } if (ioctl(fd, PPPIOCSRASYNCMAP, (caddr_t) &asyncmap) < 0) { syslog(LOG_ERR, "ioctl(PPPIOCSRASYNCMAP): %m"); quit(); } - if (ioctl(fd, PPPIOCGFLAGS, (caddr_t) &x) < 0) { syslog(LOG_ERR, "ioctl (PPPIOCGFLAGS): %m"); quit(); @@ -186,14 +249,14 @@ ppp_recv_config(unit, mru, asyncmap, pcomp, accomp) syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); quit(); } -#endif /* notyet */ } /* * sifvjcomp - config tcp header compression */ int -sifvjcomp(u, vjcomp, cidcomp) +sifvjcomp(u, vjcomp, cidcomp, maxcid) + int u, vjcomp, cidcomp, maxcid; { u_int x; @@ -203,7 +266,11 @@ sifvjcomp(u, vjcomp, cidcomp) } x = vjcomp ? x | SC_COMP_TCP: x &~ SC_COMP_TCP; x = cidcomp? x & ~SC_NO_TCP_CCID: x | SC_NO_TCP_CCID; - if(ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) { + if (ioctl(fd, PPPIOCSFLAGS, (caddr_t) &x) < 0) { + syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); + return 0; + } + if (ioctl(fd, PPPIOCSMAXCID, (caddr_t) &maxcid) < 0) { syslog(LOG_ERR, "ioctl(PPPIOCSFLAGS): %m"); return 0; } @@ -211,12 +278,14 @@ sifvjcomp(u, vjcomp, cidcomp) } /* - * sifup - Config the interface up. + * sifup - Config the interface up and enable IP packets to pass. */ int sifup(u) { struct ifreq ifr; + u_int x; + strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m"); @@ -227,27 +296,51 @@ sifup(u) 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; + } return 1; } /* - * sifdown - Config the interface down. + * sifdown - Config the interface down and disable IP. */ int sifdown(u) { struct ifreq ifr; + u_int x; + int rv; + + 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"); + rv = 0; + } + } strncpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) { syslog(LOG_ERR, "ioctl (SIOCGIFFLAGS): %m"); - return 0; + rv = 0; + } else { + ifr.ifr_flags &= ~IFF_UP; + if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { + syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m"); + rv = 0; + } } - ifr.ifr_flags &= ~IFF_UP; - if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) { - syslog(LOG_ERR, "ioctl(SIOCSIFFLAGS): %m"); - return 0; - } - return 1; + return rv; } /* @@ -481,11 +574,11 @@ get_ether_addr(ipaddr, hwaddr) return 0; } + /* * 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() { diff --git a/usr.sbin/pppd/upap.c b/usr.sbin/pppd/upap.c index 85c6f1521296..41485fef5e27 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.3 1993/11/10 01:34:35 paulus Exp $"; +static char rcsid[] = "$Id: upap.c,v 1.4 1994/05/08 12:16:32 paulus Exp $"; #endif /* @@ -310,7 +310,7 @@ upap_rauthreq(u, inp, id, len) return; } GETCHAR(ruserlen, inp); - len -= sizeof (u_char) + ruserlen + sizeof (u_char);; + len -= sizeof (u_char) + ruserlen + sizeof (u_char); if (len < 0) { UPAPDEBUG((LOG_INFO, "upap_rauth: rcvd short packet.")); return; @@ -482,3 +482,80 @@ upap_sresp(u, code, id, msg, msglen) UPAPDEBUG((LOG_INFO, "upap_sresp: Sent code %d, id %d.", code, id)); } + +/* + * upap_printpkt - print the contents of a PAP packet. + */ +char *upap_codenames[] = { + "AuthReq", "AuthAck", "AuthNak" +}; + +int +upap_printpkt(p, plen, printer, arg) + u_char *p; + int plen; + void (*printer) __ARGS((void *, char *, ...)); + void *arg; +{ + int code, id, len; + int mlen, ulen, wlen; + char *user, *pwd, *msg; + u_char *pstart; + + if (plen < UPAP_HEADERLEN) + return 0; + pstart = p; + GETCHAR(code, p); + GETCHAR(id, p); + GETSHORT(len, p); + if (len < UPAP_HEADERLEN || len > plen) + return 0; + + if (code >= 1 && code <= sizeof(upap_codenames) / sizeof(char *)) + printer(arg, " %s", upap_codenames[code-1]); + else + printer(arg, " code=0x%x", code); + printer(arg, " id=0x%x", id); + len -= UPAP_HEADERLEN; + switch (code) { + case UPAP_AUTHREQ: + if (len < 1) + break; + ulen = p[0]; + if (len < ulen + 2) + break; + wlen = p[ulen + 1]; + if (len < ulen + wlen + 2) + break; + user = (char *) (p + 1); + pwd = (char *) (p + ulen + 2); + p += ulen + wlen + 2; + len -= ulen + wlen + 2; + printer(arg, " user="); + print_string(user, ulen, printer, arg); + printer(arg, " password="); + print_string(pwd, wlen, printer, arg); + break; + case UPAP_AUTHACK: + case UPAP_AUTHNAK: + if (len < 1) + break; + mlen = p[0]; + if (len < mlen + 1) + break; + msg = (char *) (p + 1); + p += mlen + 1; + len -= mlen + 1; + printer(arg, "msg="); + print_string(msg, mlen, printer, arg); + break; + } + + /* print the rest of the bytes in the packet */ + for (; len > 0; --len) { + GETCHAR(code, p); + printer(arg, " %.2x", code); + } + + return p - pstart; +} diff --git a/usr.sbin/pppd/upap.h b/usr.sbin/pppd/upap.h index b8fa2ab78477..6c771798b609 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.3 1993/11/10 01:34:38 paulus Exp $ + * $Id: upap.h,v 1.4 1994/05/08 12:16:34 paulus Exp $ */ /* @@ -87,3 +87,5 @@ 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 *));