From: Paul Mackerras Date: Thu, 8 Mar 2001 05:11:16 +0000 (+0000) Subject: New options system with priorities for option values, with options X-Git-Tag: ppp-2.4.7~506 X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=commitdiff_plain;h=37a8acc7ee2527693d0c8ba82b2eaea249abde34 New options system with priorities for option values, with options grouped into groups where necessary, so the command line overrides the per-tty options file, plus the ability to print out the set of options currently in effect. Some options moved from lcp.c to tty.c. --- diff --git a/pppd/auth.c b/pppd/auth.c index f24b98b..9a6bfb1 100644 --- a/pppd/auth.c +++ b/pppd/auth.c @@ -32,7 +32,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: auth.c,v 1.67 2000/08/01 01:38:29 paulus Exp $" +#define RCSID "$Id: auth.c,v 1.68 2001/03/08 05:11:10 paulus Exp $" #include #include @@ -160,6 +160,8 @@ bool allow_any_ip = 0; /* Allow peer to use any IP address */ bool explicit_remote = 0; /* User specified explicit remote name */ char remote_name[MAXNAMELEN]; /* Peer's name for authentication */ +static char *uafname; /* name of most recent +ua file */ + /* Bits in auth_pending[] */ #define PAP_WITHPEER 1 #define PAP_PEER 2 @@ -198,50 +200,69 @@ static int wordlist_count __P((struct wordlist *)); * Authentication-related options. */ option_t auth_options[] = { + { "auth", o_bool, &auth_required, + "Require authentication from peer", OPT_PRIO | 1 }, + { "noauth", o_bool, &auth_required, + "Don't require peer to authenticate", OPT_PRIOSUB | OPT_PRIV, + &allow_any_ip }, { "require-pap", o_bool, &lcp_wantoptions[0].neg_upap, - "Require PAP authentication from peer", 1, &auth_required }, + "Require PAP authentication from peer", + OPT_PRIOSUB | 1, &auth_required }, { "+pap", o_bool, &lcp_wantoptions[0].neg_upap, - "Require PAP authentication from peer", 1, &auth_required }, + "Require PAP authentication from peer", + OPT_ALIAS | OPT_PRIOSUB | 1, &auth_required }, + { "require-chap", o_bool, &lcp_wantoptions[0].neg_chap, + "Require CHAP authentication from peer", + OPT_PRIOSUB | 1, &auth_required }, + { "+chap", o_bool, &lcp_wantoptions[0].neg_chap, + "Require CHAP authentication from peer", + OPT_ALIAS | OPT_PRIOSUB | 1, &auth_required }, + { "refuse-pap", o_bool, &refuse_pap, "Don't agree to auth to peer with PAP", 1 }, { "-pap", o_bool, &refuse_pap, - "Don't allow PAP authentication with peer", 1 }, - { "require-chap", o_bool, &lcp_wantoptions[0].neg_chap, - "Require CHAP authentication from peer", 1, &auth_required }, - { "+chap", o_bool, &lcp_wantoptions[0].neg_chap, - "Require CHAP authentication from peer", 1, &auth_required }, + "Don't allow PAP authentication with peer", OPT_ALIAS | 1 }, + { "refuse-chap", o_bool, &refuse_chap, "Don't agree to auth to peer with CHAP", 1 }, { "-chap", o_bool, &refuse_chap, - "Don't allow CHAP authentication with peer", 1 }, + "Don't allow CHAP authentication with peer", OPT_ALIAS | 1 }, + { "name", o_string, our_name, "Set local name for authentication", - OPT_PRIV|OPT_STATIC, NULL, MAXNAMELEN }, + OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXNAMELEN }, + + { "+ua", o_special, (void *)setupapfile, + "Get PAP user and password from file", + OPT_PRIO | OPT_A2STRVAL, &uafname }, + { "user", o_string, user, - "Set name for auth with peer", OPT_STATIC, NULL, MAXNAMELEN }, + "Set name for auth with peer", OPT_PRIO | OPT_STATIC, NULL, MAXNAMELEN }, + + { "password", o_string, passwd, + "Password for authenticating us to the peer", + OPT_PRIO | OPT_STATIC | OPT_HIDE, NULL, MAXSECRETLEN }, + { "usehostname", o_bool, &usehostname, "Must use hostname for authentication", 1 }, + { "remotename", o_string, remote_name, - "Set remote name for authentication", OPT_STATIC, + "Set remote name for authentication", OPT_PRIO | OPT_STATIC, &explicit_remote, MAXNAMELEN }, - { "auth", o_bool, &auth_required, - "Require authentication from peer", 1 }, - { "noauth", o_bool, &auth_required, - "Don't require peer to authenticate", OPT_PRIV, &allow_any_ip }, - { "login", o_bool, &uselogin, + + { "login", o_bool, &uselogin, "Use system password database for PAP", 1 }, + { "papcrypt", o_bool, &cryptpap, "PAP passwords are encrypted", 1 }, - { "+ua", o_special, (void *)setupapfile, - "Get PAP user and password from file" }, - { "password", o_string, passwd, - "Password for authenticating us to the peer", OPT_STATIC, - NULL, MAXSECRETLEN }, + { "privgroup", o_special, (void *)privgroup, - "Allow group members to use privileged options", OPT_PRIV }, + "Allow group members to use privileged options", OPT_PRIV | OPT_A2LIST }, + { "allow-ip", o_special, (void *)set_noauth_addr, "Set IP address(es) which can be used without authentication", - OPT_PRIV }, + OPT_PRIV | OPT_A2LIST }, + { NULL } }; @@ -252,36 +273,47 @@ static int setupapfile(argv) char **argv; { - FILE * ufile; + FILE *ufile; int l; + char u[MAXNAMELEN], p[MAXSECRETLEN]; + char *fname; lcp_allowoptions[0].neg_upap = 1; /* open user info file */ + fname = strdup(*argv); + if (fname == NULL) + novm("+ua file name"); seteuid(getuid()); - ufile = fopen(*argv, "r"); + ufile = fopen(fname, "r"); seteuid(0); if (ufile == NULL) { - option_error("unable to open user login data file %s", *argv); + option_error("unable to open user login data file %s", fname); return 0; } - check_access(ufile, *argv); + check_access(ufile, fname); + uafname = fname; /* get username */ - if (fgets(user, MAXNAMELEN - 1, ufile) == NULL - || fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){ - option_error("unable to read user login data file %s", *argv); + if (fgets(u, MAXNAMELEN - 1, ufile) == NULL + || fgets(p, MAXSECRETLEN - 1, ufile) == NULL){ + option_error("unable to read user login data file %s", fname); return 0; } fclose(ufile); /* get rid of newlines */ - l = strlen(user); - if (l > 0 && user[l-1] == '\n') - user[l-1] = 0; - l = strlen(passwd); - if (l > 0 && passwd[l-1] == '\n') - passwd[l-1] = 0; + l = strlen(u); + if (l > 0 && u[l-1] == '\n') + u[l-1] = 0; + l = strlen(p); + if (l > 0 && p[l-1] == '\n') + p[l-1] = 0; + + if (override_value("user", option_priority, fname)) + strlcpy(user, u, sizeof(user)); + if (override_value("passwd", option_priority, fname)) + strlcpy(passwd, p, sizeof(passwd)); return (1); } @@ -782,6 +814,7 @@ auth_check_options() /* If authentication is required, ask peer for CHAP or PAP. */ if (auth_required) { + allow_any_ip = 0; if (!wo->neg_chap && !wo->neg_upap) { wo->neg_chap = 1; wo->neg_upap = 1; @@ -1776,12 +1809,12 @@ scan_authfile(f, client, server, secret, addrs, opts, filename) for (;;) { if (!getword(f, word, &newline, filename) || newline) break; - ap = (struct wordlist *) malloc(sizeof(struct wordlist)); + ap = (struct wordlist *) + malloc(sizeof(struct wordlist) + strlen(word) + 1); if (ap == NULL) novm("authorized addresses"); - ap->word = strdup(word); - if (ap->word == NULL) - novm("authorized addresses"); + ap->word = (char *) (ap + 1); + strcpy(ap->word, word); *app = ap; app = &ap->next; } diff --git a/pppd/cbcp.c b/pppd/cbcp.c index 6b68228..e48aa46 100644 --- a/pppd/cbcp.c +++ b/pppd/cbcp.c @@ -18,7 +18,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: cbcp.c,v 1.10 1999/08/13 06:46:10 paulus Exp $" +#define RCSID "$Id: cbcp.c,v 1.11 2001/03/08 05:11:10 paulus Exp $" #include #include @@ -39,7 +39,7 @@ static int setcbcp __P((char **)); static option_t cbcp_option_list[] = { { "callback", o_special, setcbcp, - "Ask for callback" }, + "Ask for callback", OPT_PRIO | OPT_A2STRVAL, &cbcp[0].us_number }, { NULL } }; diff --git a/pppd/ccp.c b/pppd/ccp.c index 3a5fc97..ab1c5bd 100644 --- a/pppd/ccp.c +++ b/pppd/ccp.c @@ -25,7 +25,7 @@ * OR MODIFICATIONS. */ -#define RCSID "$Id: ccp.c,v 1.31 2001/02/22 03:10:06 paulus Exp $" +#define RCSID "$Id: ccp.c,v 1.32 2001/03/08 05:11:11 paulus Exp $" #include #include @@ -51,38 +51,46 @@ static const char rcsid[] = RCSID; */ static int setbsdcomp __P((char **)); static int setdeflate __P((char **)); +static char bsd_value[8]; +static char deflate_value[8]; static option_t ccp_option_list[] = { { "noccp", o_bool, &ccp_protent.enabled_flag, "Disable CCP negotiation" }, { "-ccp", o_bool, &ccp_protent.enabled_flag, - "Disable CCP negotiation" }, + "Disable CCP negotiation", OPT_ALIAS }, + { "bsdcomp", o_special, (void *)setbsdcomp, - "Request BSD-Compress packet compression" }, + "Request BSD-Compress packet compression", + OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, bsd_value }, { "nobsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, - "don't allow BSD-Compress", OPT_A2COPY, + "don't allow BSD-Compress", OPT_PRIOSUB | OPT_A2CLR, &ccp_allowoptions[0].bsd_compress }, { "-bsdcomp", o_bool, &ccp_wantoptions[0].bsd_compress, - "don't allow BSD-Compress", OPT_A2COPY, + "don't allow BSD-Compress", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, &ccp_allowoptions[0].bsd_compress }, + { "deflate", o_special, (void *)setdeflate, - "request Deflate compression" }, + "request Deflate compression", + OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, deflate_value }, { "nodeflate", o_bool, &ccp_wantoptions[0].deflate, - "don't allow Deflate compression", OPT_A2COPY, + "don't allow Deflate compression", OPT_PRIOSUB | OPT_A2CLR, &ccp_allowoptions[0].deflate }, { "-deflate", o_bool, &ccp_wantoptions[0].deflate, - "don't allow Deflate compression", OPT_A2COPY, + "don't allow Deflate compression", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, &ccp_allowoptions[0].deflate }, + { "nodeflatedraft", o_bool, &ccp_wantoptions[0].deflate_draft, "don't use draft deflate #", OPT_A2COPY, &ccp_allowoptions[0].deflate_draft }, + { "predictor1", o_bool, &ccp_wantoptions[0].predictor_1, - "request Predictor-1", 1, &ccp_allowoptions[0].predictor_1 }, + "request Predictor-1", 1, &ccp_allowoptions[0].predictor_1, OPT_PRIO }, { "nopredictor1", o_bool, &ccp_wantoptions[0].predictor_1, - "don't allow Predictor-1", OPT_A2COPY, + "don't allow Predictor-1", OPT_PRIOSUB | OPT_A2CLR, &ccp_allowoptions[0].predictor_1 }, { "-predictor1", o_bool, &ccp_wantoptions[0].predictor_1, - "don't allow Predictor-1", OPT_A2COPY, + "don't allow Predictor-1", OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, &ccp_allowoptions[0].predictor_1 }, { NULL } @@ -216,6 +224,9 @@ setbsdcomp(argv) ccp_allowoptions[0].bsd_bits = abits; } else ccp_allowoptions[0].bsd_compress = 0; + slprintf(bsd_value, sizeof(bsd_value), + rbits == abits? "%d": "%d,%d", rbits, abits); + return 1; } @@ -261,10 +272,12 @@ setdeflate(argv) ccp_allowoptions[0].deflate_size = abits; } else ccp_allowoptions[0].deflate = 0; + slprintf(deflate_value, sizeof(deflate_value), + rbits == abits? "%d": "%d,%d", rbits, abits); + return 1; } - /* * ccp_init - initialize CCP. */ diff --git a/pppd/chap.c b/pppd/chap.c index 2a43c05..3d7a660 100644 --- a/pppd/chap.c +++ b/pppd/chap.c @@ -33,7 +33,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: chap.c,v 1.24 1999/11/15 01:51:50 paulus Exp $" +#define RCSID "$Id: chap.c,v 1.25 2001/03/08 05:11:11 paulus Exp $" /* * TODO: @@ -58,11 +58,11 @@ static const char rcsid[] = RCSID; */ static option_t chap_option_list[] = { { "chap-restart", o_int, &chap[0].timeouttime, - "Set timeout for CHAP" }, + "Set timeout for CHAP", OPT_PRIO }, { "chap-max-challenge", o_int, &chap[0].max_transmits, - "Set max #xmits for challenge" }, + "Set max #xmits for challenge", OPT_PRIO }, { "chap-interval", o_int, &chap[0].chal_interval, - "Set interval for rechallenge" }, + "Set interval for rechallenge", OPT_PRIO }, #ifdef MSLANMAN { "ms-lanman", o_bool, &ms_lanman, "Use LanMan passwd when using MS-CHAP", 1 }, diff --git a/pppd/ipcp.c b/pppd/ipcp.c index 71db5dd..5236244 100644 --- a/pppd/ipcp.c +++ b/pppd/ipcp.c @@ -17,7 +17,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: ipcp.c,v 1.56 2001/02/22 03:15:16 paulus Exp $" +#define RCSID "$Id: ipcp.c,v 1.57 2001/03/08 05:11:12 paulus Exp $" /* * TODO: @@ -43,7 +43,7 @@ static const char rcsid[] = RCSID; /* global vars */ ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */ ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ -ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ +ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ u_int32_t netmask = 0; /* IP netmask to set on interface */ @@ -65,6 +65,8 @@ static int proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */ static bool usepeerdns; /* Ask peer for DNS addrs */ static int ipcp_is_up; /* have called np_up() */ static bool ask_for_local; /* request our address from peer */ +static char vj_value[8]; /* string form of vj option value */ +static char netmask_str[20]; /* string form of netmask value */ /* * Callbacks for fsm code. (CI = Configuration Information) @@ -108,66 +110,84 @@ static int setdnsaddr __P((char **)); static int setwinsaddr __P((char **)); static int setnetmask __P((char **)); static int setipaddr __P((char *, char **, int)); +static void printipaddr __P((option_t *, void (*)(void *, char *,...),void *)); static option_t ipcp_option_list[] = { { "noip", o_bool, &ipcp_protent.enabled_flag, "Disable IP and IPCP" }, { "-ip", o_bool, &ipcp_protent.enabled_flag, - "Disable IP and IPCP" }, + "Disable IP and IPCP", OPT_ALIAS }, + { "novj", o_bool, &ipcp_wantoptions[0].neg_vj, - "Disable VJ compression", OPT_A2COPY, &ipcp_allowoptions[0].neg_vj }, + "Disable VJ compression", OPT_A2CLR, &ipcp_allowoptions[0].neg_vj }, { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj, - "Disable VJ compression", OPT_A2COPY, &ipcp_allowoptions[0].neg_vj }, + "Disable VJ compression", OPT_ALIAS | OPT_A2CLR, + &ipcp_allowoptions[0].neg_vj }, + { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag, - "Disable VJ connection-ID compression", OPT_A2COPY, + "Disable VJ connection-ID compression", OPT_A2CLR, &ipcp_allowoptions[0].cflag }, { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag, - "Disable VJ connection-ID compression", OPT_A2COPY, + "Disable VJ connection-ID compression", OPT_ALIAS | OPT_A2CLR, &ipcp_allowoptions[0].cflag }, + { "vj-max-slots", o_special, (void *)setvjslots, - "Set maximum VJ header slots" }, + "Set maximum VJ header slots", + OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, vj_value }, + { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local, "Accept peer's address for us", 1 }, { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote, "Accept peer's address for it", 1 }, + { "ipparam", o_string, &ipparam, - "Set ip script parameter" }, + "Set ip script parameter", OPT_PRIO }, + { "noipdefault", o_bool, &disable_defaultip, "Don't use name for default IP adrs", 1 }, + { "ms-dns", 1, (void *)setdnsaddr, "DNS address for the peer's use" }, { "ms-wins", 1, (void *)setwinsaddr, "Nameserver for SMB over TCP/IP for peer" }, + { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime, - "Set timeout for IPCP" }, + "Set timeout for IPCP", OPT_PRIO }, { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits, - "Set max #xmits for term-reqs" }, + "Set max #xmits for term-reqs", OPT_PRIO }, { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits, - "Set max #xmits for conf-reqs" }, + "Set max #xmits for conf-reqs", OPT_PRIO }, { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops, - "Set max #conf-naks for IPCP" }, + "Set max #conf-naks for IPCP", OPT_PRIO }, + { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route, "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route }, { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route, - "disable defaultroute option", OPT_A2COPY, + "disable defaultroute option", OPT_A2CLR, &ipcp_wantoptions[0].default_route }, { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route, - "disable defaultroute option", OPT_A2COPY, + "disable defaultroute option", OPT_ALIAS | OPT_A2CLR, &ipcp_wantoptions[0].default_route }, + { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp, "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp }, { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, - "disable proxyarp option", OPT_A2COPY, + "disable proxyarp option", OPT_A2CLR, &ipcp_wantoptions[0].proxy_arp }, { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp, - "disable proxyarp option", OPT_A2COPY, + "disable proxyarp option", OPT_ALIAS | OPT_A2CLR, &ipcp_wantoptions[0].proxy_arp }, + { "usepeerdns", o_bool, &usepeerdns, "Ask peer for DNS address(es)", 1 }, + { "netmask", o_special, (void *)setnetmask, - "set netmask" }, + "set netmask", OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, netmask_str }, + { "IP addresses", o_wild, (void *) &setipaddr, - "set local and remote IP addresses", OPT_NOARG | OPT_MULTIPART }, + "set local and remote IP addresses", + OPT_NOARG | OPT_A2PRINTER, (void *) &printipaddr }, + { NULL } }; @@ -269,6 +289,7 @@ setvjslots(argv) } ipcp_wantoptions [0].maxslotindex = ipcp_allowoptions[0].maxslotindex = value - 1; + slprintf(vj_value, sizeof(vj_value), "%d", value); return 1; } @@ -292,11 +313,15 @@ setdnsaddr(argv) dns = *(u_int32_t *)hp->h_addr; } - /* if there is no primary then update it. */ - if (ipcp_allowoptions[0].dnsaddr[0] == 0) + /* We take the last 2 values given, the 2nd-last as the primary + and the last as the secondary. If only one is given it + becomes both primary and secondary. */ + if (ipcp_allowoptions[0].dnsaddr[1] == 0) ipcp_allowoptions[0].dnsaddr[0] = dns; + else + ipcp_allowoptions[0].dnsaddr[0] = ipcp_allowoptions[0].dnsaddr[1]; - /* always set the secondary address value to the same value. */ + /* always set the secondary address value. */ ipcp_allowoptions[0].dnsaddr[1] = dns; return (1); @@ -324,11 +349,15 @@ setwinsaddr(argv) wins = *(u_int32_t *)hp->h_addr; } - /* if there is no primary then update it. */ - if (ipcp_allowoptions[0].winsaddr[0] == 0) + /* We take the last 2 values given, the 2nd-last as the primary + and the last as the secondary. If only one is given it + becomes both primary and secondary. */ + if (ipcp_allowoptions[0].winsaddr[1] == 0) ipcp_allowoptions[0].winsaddr[0] = wins; + else + ipcp_allowoptions[0].winsaddr[0] = ipcp_allowoptions[0].winsaddr[1]; - /* always set the secondary address value to the same value. */ + /* always set the secondary address value. */ ipcp_allowoptions[0].winsaddr[1] = wins; return (1); @@ -406,6 +435,21 @@ setipaddr(arg, argv, doit) return 1; } +static void +printipaddr(opt, printer, arg) + option_t *opt; + void (*printer) __P((void *, char *, ...)); + void *arg; +{ + ipcp_options *wo = &ipcp_wantoptions[0]; + + if (wo->ouraddr != 0) + printer(arg, "%I", wo->ouraddr); + printer(arg, ":"); + if (wo->hisaddr != 0) + printer(arg, "%I", wo->hisaddr); +} + /* * setnetmask - set the netmask to be used on the interface. */ @@ -432,6 +476,8 @@ setnetmask(argv) } netmask = mask; + slprintf(netmask_str, sizeof(netmask_str), "%I", mask); + return (1); } diff --git a/pppd/ipv6cp.c b/pppd/ipv6cp.c index de3076f..b877625 100644 --- a/pppd/ipv6cp.c +++ b/pppd/ipv6cp.c @@ -90,10 +90,10 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: ipv6cp.c,v 1.12 2001/02/22 03:15:16 paulus Exp $ + * $Id: ipv6cp.c,v 1.13 2001/03/08 05:11:12 paulus Exp $ */ -#define RCSID "$Id: ipv6cp.c,v 1.12 2001/02/22 03:15:16 paulus Exp $" +#define RCSID "$Id: ipv6cp.c,v 1.13 2001/03/08 05:11:12 paulus Exp $" /* * TODO: @@ -172,33 +172,40 @@ static fsm_callbacks ipv6cp_callbacks = { /* IPV6CP callback routines */ * Command-line options. */ static int setifaceid __P((char **arg)); +static void printifaceid __P((option_t *, + void (*)(void *, char *, ...), void *)); static option_t ipv6cp_option_list[] = { { "ipv6", o_special, (void *)setifaceid, - "Set interface identifiers for IPV6", OPT_MULTIPART }, + "Set interface identifiers for IPV6", + OPT_A2PRINTER, (void *)printifaceid }, + + { "+ipv6", o_bool, &ipv6cp_protent.enabled_flag, + "Enable IPv6 and IPv6CP", OPT_PRIO | 1 }, { "noipv6", o_bool, &ipv6cp_protent.enabled_flag, - "Disable IPv6 and IPv6CP" }, + "Disable IPv6 and IPv6CP", OPT_PRIOSUB }, { "-ipv6", o_bool, &ipv6cp_protent.enabled_flag, - "Disable IPv6 and IPv6CP" }, - { "+ipv6", o_bool, &ipv6cp_protent.enabled_flag, - "Enable IPv6 and IPv6CP", 1 }, + "Disable IPv6 and IPv6CP", OPT_PRIOSUB | OPT_ALIAS }, { "ipv6cp-accept-local", o_bool, &ipv6cp_allowoptions[0].accept_local, "Accept peer's interface identifier for us", 1 }, + { "ipv6cp-use-ipaddr", o_bool, &ipv6cp_allowoptions[0].use_ip, - "Use (default) IPv4 address as interface identifier", 0 }, + "Use (default) IPv4 address as interface identifier", 1 }, + #if defined(SOL2) { "ipv6cp-use-persistent", o_bool, &ipv6cp_wantoptions[0].use_persistent, "Use uniquely-available persistent value for link local address", 1 }, #endif /* defined(SOL2) */ + { "ipv6cp-restart", o_int, &ipv6cp_fsm[0].timeouttime, - "Set timeout for IPv6CP" }, + "Set timeout for IPv6CP", OPT_PRIO }, { "ipv6cp-max-terminate", o_int, &ipv6cp_fsm[0].maxtermtransmits, - "Set max #xmits for term-reqs" }, + "Set max #xmits for term-reqs", OPT_PRIO }, { "ipv6cp-max-configure", o_int, &ipv6cp_fsm[0].maxconfreqtransmits, - "Set max #xmits for conf-reqs" }, + "Set max #xmits for conf-reqs", OPT_PRIO }, { "ipv6cp-max-failure", o_int, &ipv6cp_fsm[0].maxnakloops, - "Set max #conf-naks for IPv6CP" }, + "Set max #conf-naks for IPv6CP", OPT_PRIO }, { NULL } }; @@ -318,10 +325,26 @@ setifaceid(argv) } } - ipv6cp_protent.enabled_flag = 1; + if (override_value("+ipv6", option_priority, option_source)) + ipv6cp_protent.enabled_flag = 1; return 1; } +static void +printipaddr(opt, printer, arg) + option_t *opt; + void (*printer) __P((void *, char *, ...)); + void *arg; +{ + ipv6cp_options *wo = &ipv6cp_wantoptions[0]; + + if (wo->opt_local) + printer(arg, "%s", llv6_ntoa(wo->ourid)); + printer(arg, ","); + if (wo->opt_remote) + printer(arg, "%s", llv6_ntoa(wo->hisid)); +} + /* * Make a string representation of a network address. */ diff --git a/pppd/ipxcp.c b/pppd/ipxcp.c index f7b1a51..8612451 100644 --- a/pppd/ipxcp.c +++ b/pppd/ipxcp.c @@ -19,7 +19,7 @@ #ifdef IPX_CHANGE -#define RCSID "$Id: ipxcp.c,v 1.19 2001/02/22 03:15:20 paulus Exp $" +#define RCSID "$Id: ipxcp.c,v 1.20 2001/03/08 05:11:13 paulus Exp $" /* * TODO: @@ -91,43 +91,55 @@ static fsm_callbacks ipxcp_callbacks = { /* IPXCP callback routines */ * Command-line options. */ static int setipxnode __P((char **)); +static void printipxnode __P((option_t *, + void (*)(void *, char *, ...), void *)); static int setipxname __P((char **)); static option_t ipxcp_option_list[] = { { "ipx", o_bool, &ipxcp_protent.enabled_flag, - "Enable IPXCP (and IPX)", 1 }, + "Enable IPXCP (and IPX)", OPT_PRIO | 1 }, { "+ipx", o_bool, &ipxcp_protent.enabled_flag, - "Enable IPXCP (and IPX)", 1 }, + "Enable IPXCP (and IPX)", OPT_PRIOSUB | OPT_ALIAS | 1 }, { "noipx", o_bool, &ipxcp_protent.enabled_flag, - "Disable IPXCP (and IPX)" }, + "Disable IPXCP (and IPX)", OPT_PRIOSUB }, { "-ipx", o_bool, &ipxcp_protent.enabled_flag, - "Disable IPXCP (and IPX)" } , + "Disable IPXCP (and IPX)", OPT_PRIOSUB | OPT_ALIAS }, + { "ipx-network", o_uint32, &ipxcp_wantoptions[0].our_network, - "Set our IPX network number", 0, &ipxcp_wantoptions[0].neg_nn }, + "Set our IPX network number", OPT_PRIO, &ipxcp_wantoptions[0].neg_nn }, + { "ipxcp-accept-network", o_bool, &ipxcp_wantoptions[0].accept_network, "Accept peer IPX network number", 1, &ipxcp_allowoptions[0].accept_network }, - { "ipx-node", o_special, setipxnode, - "Set IPX node number", OPT_MULTIPART }, + + { "ipx-node", o_special, (void *)setipxnode, + "Set IPX node number", OPT_A2PRINTER, (void *)printipxnode }, + { "ipxcp-accept-local", o_bool, &ipxcp_wantoptions[0].accept_local, "Accept our IPX address", 1, &ipxcp_allowoptions[0].accept_local }, + { "ipxcp-accept-remote", o_bool, &ipxcp_wantoptions[0].accept_remote, "Accept peer's IPX address", 1, &ipxcp_allowoptions[0].accept_remote }, + { "ipx-routing", o_int, &ipxcp_wantoptions[0].router, - "Set IPX routing proto number", 0, + "Set IPX routing proto number", OPT_PRIO, &ipxcp_wantoptions[0].neg_router }, + { "ipx-router-name", o_special, setipxname, - "Set IPX router name" }, + "Set IPX router name", OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, + &ipxcp_wantoptions[0].name }, + { "ipxcp-restart", o_int, &ipxcp_fsm[0].timeouttime, - "Set timeout for IPXCP" }, + "Set timeout for IPXCP", OPT_PRIO }, { "ipxcp-max-terminate", o_int, &ipxcp_fsm[0].maxtermtransmits, - "Set max #xmits for IPXCP term-reqs" }, + "Set max #xmits for IPXCP term-reqs", OPT_PRIO }, { "ipxcp-max-configure", o_int, &ipxcp_fsm[0].maxconfreqtransmits, - "Set max #xmits for IPXCP conf-reqs" }, + "Set max #xmits for IPXCP conf-reqs", OPT_PRIO }, { "ipxcp-max-failure", o_int, &ipxcp_fsm[0].maxnakloops, - "Set max #conf-naks for IPXCP" }, + "Set max #conf-naks for IPXCP", OPT_PRIO }, + { NULL } }; @@ -248,6 +260,8 @@ u_char *src, *dst; return src; } +static int ipx_prio_our, ipx_prio_his; + static int setipxnode(argv) char **argv; @@ -256,7 +270,6 @@ setipxnode(argv) int have_his = 0; u_char our_node[6]; u_char his_node[6]; - static int prio_our, prio_his; memset (our_node, 0, 6); memset (his_node, 0, 6); @@ -269,13 +282,13 @@ setipxnode(argv) if (*end == '\0') { ipxcp_wantoptions[0].neg_node = 1; - if (option_priority >= prio_our) { + if (option_priority >= ipx_prio_our) { memcpy(&ipxcp_wantoptions[0].our_node[0], our_node, 6); - prio_our = option_priority; + ipx_prio_our = option_priority; } - if (have_his && option_priority >= prio_his) { + if (have_his && option_priority >= ipx_prio_his) { memcpy(&ipxcp_wantoptions[0].his_node[0], his_node, 6); - prio_his = option_priority; + ipx_prio_his = option_priority; } return 1; } @@ -284,6 +297,25 @@ setipxnode(argv) return 0; } +static void +printipxnode(opt, printer, arg) + option_t *opt; + void (*printer) __P((void *, char *, ...)); + void *arg; +{ + unsigned char *p; + + p = ipxcp_wantoptions[0].our_node; + if (ipx_prio_our) + printer(arg, "%.2x%.2x%.2x%.2x%.2x%.2x", + p[0], p[1], p[2], p[3], p[4], p[5]); + printer(arg, ":"); + p = ipxcp_wantoptions[0].his_node; + if (ipx_prio_his) + printer(arg, "%.2x%.2x%.2x%.2x%.2x%.2x", + p[0], p[1], p[2], p[3], p[4], p[5]); +} + static int setipxname (argv) char **argv; @@ -305,7 +337,7 @@ setipxname (argv) return 0; } - if (count >= sizeof (ipxcp_wantoptions[0].name)) { + if (count >= sizeof (ipxcp_wantoptions[0].name) - 1) { option_error("IPX router name is limited to %d characters", sizeof (ipxcp_wantoptions[0].name) - 1); return 0; @@ -313,6 +345,7 @@ setipxname (argv) dest[count++] = toupper (ch); } + dest[count] = 0; return 1; } diff --git a/pppd/lcp.c b/pppd/lcp.c index 4542164..d708c27 100644 --- a/pppd/lcp.c +++ b/pppd/lcp.c @@ -17,7 +17,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: lcp.c,v 1.56 2001/02/22 03:16:26 paulus Exp $" +#define RCSID "$Id: lcp.c,v 1.57 2001/03/08 05:11:14 paulus Exp $" /* * TODO: @@ -54,94 +54,112 @@ bool lax_recv = 0; /* accept control chars in asyncmap */ bool noendpoint = 0; /* don't send/accept endpoint discriminator */ static int noopt __P((char **)); -static int setescape __P((char **)); #ifdef HAVE_MULTILINK static int setendpoint __P((char **)); +static void printendpoint __P((option_t *, void (*)(void *, char *, ...), + void *)); #endif /* HAVE_MULTILINK */ static option_t lcp_option_list[] = { /* LCP options */ { "-all", o_special_noarg, (void *)noopt, "Don't request/allow any LCP options" }, + { "noaccomp", o_bool, &lcp_wantoptions[0].neg_accompression, "Disable address/control compression", - OPT_A2COPY, &lcp_allowoptions[0].neg_accompression }, + OPT_A2CLR, &lcp_allowoptions[0].neg_accompression }, { "-ac", o_bool, &lcp_wantoptions[0].neg_accompression, "Disable address/control compression", - OPT_A2COPY, &lcp_allowoptions[0].neg_accompression }, - { "default-asyncmap", o_bool, &lcp_wantoptions[0].neg_asyncmap, - "Disable asyncmap negotiation", - OPT_A2COPY, &lcp_allowoptions[0].neg_asyncmap }, - { "-am", o_bool, &lcp_wantoptions[0].neg_asyncmap, - "Disable asyncmap negotiation", - OPT_A2COPY, &lcp_allowoptions[0].neg_asyncmap }, + OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_accompression }, + { "asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap, "Set asyncmap (for received packets)", OPT_OR, &lcp_wantoptions[0].neg_asyncmap }, { "-as", o_uint32, &lcp_wantoptions[0].asyncmap, "Set asyncmap (for received packets)", - OPT_OR, &lcp_wantoptions[0].neg_asyncmap }, + OPT_ALIAS | OPT_OR, &lcp_wantoptions[0].neg_asyncmap }, + { "default-asyncmap", o_uint32, &lcp_wantoptions[0].asyncmap, + "Disable asyncmap negotiation", + OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR, + &lcp_allowoptions[0].neg_asyncmap }, + { "-am", o_uint32, &lcp_wantoptions[0].asyncmap, + "Disable asyncmap negotiation", + OPT_ALIAS | OPT_OR | OPT_NOARG | OPT_VAL(~0U) | OPT_A2CLR, + &lcp_allowoptions[0].neg_asyncmap }, + { "nomagic", o_bool, &lcp_wantoptions[0].neg_magicnumber, "Disable magic number negotiation (looped-back line detection)", - OPT_A2COPY, &lcp_allowoptions[0].neg_magicnumber }, + OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber }, { "-mn", o_bool, &lcp_wantoptions[0].neg_magicnumber, "Disable magic number negotiation (looped-back line detection)", - OPT_A2COPY, &lcp_allowoptions[0].neg_magicnumber }, + OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_magicnumber }, + + { "mru", o_int, &lcp_wantoptions[0].mru, + "Set MRU (maximum received packet size) for negotiation", + OPT_PRIO, &lcp_wantoptions[0].neg_mru }, { "default-mru", o_bool, &lcp_wantoptions[0].neg_mru, "Disable MRU negotiation (use default 1500)", - OPT_A2COPY, &lcp_allowoptions[0].neg_mru }, + OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru }, { "-mru", o_bool, &lcp_wantoptions[0].neg_mru, "Disable MRU negotiation (use default 1500)", - OPT_A2COPY, &lcp_allowoptions[0].neg_mru }, - { "mru", o_int, &lcp_wantoptions[0].mru, - "Set MRU (maximum received packet size) for negotiation", - 0, &lcp_wantoptions[0].neg_mru }, + OPT_ALIAS | OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_mru }, + { "mtu", o_int, &lcp_allowoptions[0].mru, "Set our MTU", OPT_LIMITS, NULL, MAXMRU, MINMRU }, + { "nopcomp", o_bool, &lcp_wantoptions[0].neg_pcompression, "Disable protocol field compression", - OPT_A2COPY, &lcp_allowoptions[0].neg_pcompression }, + OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression }, { "-pc", o_bool, &lcp_wantoptions[0].neg_pcompression, "Disable protocol field compression", - OPT_A2COPY, &lcp_allowoptions[0].neg_pcompression }, - { "-p", o_bool, &lcp_wantoptions[0].passive, - "Set passive mode", 1 }, + OPT_ALIAS | OPT_A2CLR, &lcp_allowoptions[0].neg_pcompression }, + { "passive", o_bool, &lcp_wantoptions[0].passive, "Set passive mode", 1 }, + { "-p", o_bool, &lcp_wantoptions[0].passive, + "Set passive mode", OPT_ALIAS | 1 }, + { "silent", o_bool, &lcp_wantoptions[0].silent, "Set silent mode", 1 }, - { "escape", o_special, (void *)setescape, - "List of character codes to escape on transmission" }, + { "lcp-echo-failure", o_int, &lcp_echo_fails, - "Set number of consecutive echo failures to indicate link failure" }, + "Set number of consecutive echo failures to indicate link failure", + OPT_PRIO }, { "lcp-echo-interval", o_int, &lcp_echo_interval, - "Set time in seconds between LCP echo requests" }, + "Set time in seconds between LCP echo requests", OPT_PRIO }, { "lcp-restart", o_int, &lcp_fsm[0].timeouttime, - "Set time in seconds between LCP retransmissions" }, + "Set time in seconds between LCP retransmissions", OPT_PRIO }, { "lcp-max-terminate", o_int, &lcp_fsm[0].maxtermtransmits, - "Set maximum number of LCP terminate-request transmissions" }, + "Set maximum number of LCP terminate-request transmissions", OPT_PRIO }, { "lcp-max-configure", o_int, &lcp_fsm[0].maxconfreqtransmits, - "Set maximum number of LCP configure-request transmissions" }, + "Set maximum number of LCP configure-request transmissions", OPT_PRIO }, { "lcp-max-failure", o_int, &lcp_fsm[0].maxnakloops, - "Set limit on number of LCP configure-naks" }, + "Set limit on number of LCP configure-naks", OPT_PRIO }, + { "receive-all", o_bool, &lax_recv, "Accept all received control characters", 1 }, + #ifdef HAVE_MULTILINK { "mrru", o_int, &lcp_wantoptions[0].mrru, "Maximum received packet size for multilink bundle", - 0, &lcp_wantoptions[0].neg_mrru }, + OPT_PRIO, &lcp_wantoptions[0].neg_mrru }, + { "mpshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf, "Use short sequence numbers in multilink headers", - OPT_A2COPY | 1, &lcp_allowoptions[0].neg_ssnhf }, + OPT_PRIO | 1, &lcp_allowoptions[0].neg_ssnhf }, { "nompshortseq", o_bool, &lcp_wantoptions[0].neg_ssnhf, "Don't use short sequence numbers in multilink headers", - OPT_A2COPY, &lcp_allowoptions[0].neg_ssnhf }, - { "endpoint", o_special, setendpoint, - "Endpoint discriminator for multilink" }, + OPT_PRIOSUB | OPT_A2CLR, &lcp_allowoptions[0].neg_ssnhf }, + + { "endpoint", o_special, (void *) setendpoint, + "Endpoint discriminator for multilink", + OPT_PRIO | OPT_A2PRINTER, (void *) printendpoint }, #endif /* HAVE_MULTILINK */ + { "noendpoint", o_bool, &noendpoint, "Don't send or accept multilink endpoint discriminator", 1 }, + {NULL} }; @@ -151,7 +169,6 @@ lcp_options lcp_wantoptions[NUM_PPP]; /* Options that we want to request */ lcp_options lcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */ lcp_options lcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */ lcp_options lcp_hisoptions[NUM_PPP]; /* Options that we ack'd */ -u_int32_t xmit_accm[NUM_PPP][8]; /* extended transmit ACCM */ static int lcp_echos_pending = 0; /* Number of outstanding echo msgs */ static int lcp_echo_number = 0; /* ID number of next echo frame */ @@ -266,37 +283,6 @@ noopt(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) { - option_error("escape parameter contains invalid hex number '%s'", - p); - return 0; - } - p = endp; - if (n < 0 || n == 0x5E || n > 0xFF) { - option_error("can't escape character 0x%x", n); - ret = 0; - } else - xmit_accm[0][n >> 5] |= 1 << (n & 0x1F); - while (*p == ',' || *p == ' ') - ++p; - } - return ret; -} - #ifdef HAVE_MULTILINK static int setendpoint(argv) @@ -309,6 +295,15 @@ setendpoint(argv) option_error("Can't parse '%s' as an endpoint discriminator", *argv); return 0; } + +static void +printendpoint(opt, printer, arg) + option_t *opt; + void (*printer) __P((void *, char *, ...)); + void *arg; +{ + printer(arg, "%s", epdisc_to_str(&lcp_wantoptions[0].endpoint)); +} #endif /* HAVE_MULTILINK */ /* @@ -351,9 +346,6 @@ lcp_init(unit) ao->neg_cbcp = 1; #endif ao->neg_endpoint = 1; - - BZERO(xmit_accm[unit], sizeof(xmit_accm[0])); - xmit_accm[unit][3] = 0x60000000; } @@ -418,12 +410,10 @@ lcp_lowerup(unit) * but accept A/C and protocol compressed packets * if we are going to ask for A/C and protocol compression. */ - ppp_set_xaccm(unit, xmit_accm[unit]); ppp_send_config(unit, PPP_MRU, 0xffffffff, 0, 0); ppp_recv_config(unit, PPP_MRU, (lax_recv? 0: 0xffffffff), wo->neg_pcompression, wo->neg_accompression); peer_mru[unit] = PPP_MRU; - lcp_allowoptions[unit].asyncmap = xmit_accm[unit][0]; if (listen_time != 0) { f->flags |= DELAYED_UP; @@ -1781,6 +1771,7 @@ lcp_up(f) lcp_options *ho = &lcp_hisoptions[f->unit]; lcp_options *go = &lcp_gotoptions[f->unit]; lcp_options *ao = &lcp_allowoptions[f->unit]; + int mtu; if (!go->neg_magicnumber) go->magicnumber = 0; @@ -1792,8 +1783,16 @@ lcp_up(f) * the MRU our peer wanted. If we negotiated an MRU, * set our MRU to the larger of value we wanted and * the value we got in the negotiation. + * Note on the MTU: the link MTU can be the MRU the peer wanted, + * the interface MTU is set to the lower of that and the + * MTU we want to use. */ - ppp_send_config(f->unit, MIN(ao->mru, (ho->neg_mru? ho->mru: PPP_MRU)), + mtu = ho->neg_mru? ho->mru: PPP_MRU; +#ifdef HAVE_MULTILINK + if (!(multilink && go->neg_mrru && ho->neg_mrru)) +#endif /* HAVE_MULTILINK */ + netif_set_mtu(f->unit, MIN(mtu, ao->mru)); + ppp_send_config(f->unit, 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): PPP_MRU), diff --git a/pppd/lcp.h b/pppd/lcp.h index e52bdf5..5122b7b 100644 --- a/pppd/lcp.h +++ b/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.15 2000/04/04 07:06:51 paulus Exp $ + * $Id: lcp.h,v 1.16 2001/03/08 05:11:14 paulus Exp $ */ /* @@ -77,7 +77,6 @@ extern lcp_options lcp_wantoptions[]; extern lcp_options lcp_gotoptions[]; extern lcp_options lcp_allowoptions[]; extern lcp_options lcp_hisoptions[]; -extern u_int32_t xmit_accm[][8]; #define DEFMRU 1500 /* Try for this */ #define MINMRU 128 /* No MRUs below this */ diff --git a/pppd/main.c b/pppd/main.c index e03b362..24f88ec 100644 --- a/pppd/main.c +++ b/pppd/main.c @@ -17,7 +17,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: main.c,v 1.102 2001/02/22 03:10:57 paulus Exp $" +#define RCSID "$Id: main.c,v 1.103 2001/03/08 05:11:14 paulus Exp $" #include #include @@ -54,7 +54,6 @@ #include "chap.h" #include "ccp.h" #include "pathnames.h" -#include "patchlevel.h" #include "tdb.h" #ifdef CBCP_SUPPORT @@ -74,6 +73,8 @@ static const char rcsid[] = RCSID; char ifname[32]; /* Interface name */ int ifunit; /* Interface unit number */ +struct channel *the_channel; + char *progname; /* Name of this program */ char hostname[MAXNAMELEN]; /* Our hostname */ static char pidfilename[MAXPATHLEN]; /* name of pid file */ @@ -278,6 +279,10 @@ main(argc, argv) */ for (i = 0; (protp = protocols[i]) != NULL; ++i) (*protp->init)(0); + + /* + * Initialize the default channel. + */ tty_init(); progname = *argv; @@ -296,7 +301,14 @@ main(argc, argv) * Work out the device name, if it hasn't already been specified, * and parse the tty's options file. */ - tty_device_check(); + if (the_channel->process_extra_options) + (*the_channel->process_extra_options)(); + + if (dump_options || dryrun) { + init_pr_log(NULL, LOG_INFO); + print_options(pr_log, NULL); + end_pr_log(); + } /* * Check that we are running as root. @@ -315,6 +327,7 @@ main(argc, argv) /* * Check that the options given are valid and consistent. */ + check_options(); if (!sys_check_options()) exit(EXIT_OPTION_ERROR); auth_check_options(); @@ -324,7 +337,8 @@ main(argc, argv) for (i = 0; (protp = protocols[i]) != NULL; ++i) if (protp->check_options != NULL) (*protp->check_options)(); - tty_check_options(); + if (the_channel->check_options) + (*the_channel->check_options)(); /* * Initialize system-dependent stuff. @@ -333,6 +347,9 @@ main(argc, argv) if (debug) setlogmask(LOG_UPTO(LOG_DEBUG)); + if (dryrun) + die(0); + pppdb = tdb_open(_PATH_PPPDB, 0, 0, O_RDWR|O_CREAT, 0644); if (pppdb != NULL) { slprintf(db_key, sizeof(db_key), "pppd%d", getpid()); @@ -359,8 +376,7 @@ main(argc, argv) else p = "(unknown)"; } - syslog(LOG_NOTICE, "pppd %s.%d%s started by %s, uid %d", - VERSION, PATCHLEVEL, IMPLEMENTATION, p, uid); + syslog(LOG_NOTICE, "pppd %s started by %s, uid %d", VERSION, p, uid); script_setenv("PPPLOGNAME", p, 0); if (devnam[0]) @@ -430,7 +446,7 @@ main(argc, argv) new_phase(PHASE_SERIALCONN); - devfd = connect_tty(); + devfd = the_channel->connect(); if (devfd < 0) goto fail; @@ -507,7 +523,7 @@ main(argc, argv) clean_check(); if (demand) restore_loop(); - disestablish_ppp(devfd); + disestablish_ppp(devfd); /* XXX */ fd_ppp = -1; if (!hungup) lcp_lowerdown(0); @@ -520,10 +536,11 @@ main(argc, argv) */ disconnect: new_phase(PHASE_DISCONNECT); - disconnect_tty(); + the_channel->disconnect(); fail: - cleanup_tty(); + if (the_channel->cleanup) + (*the_channel->cleanup)(); if (!demand) { if (pidfilename[0] != 0 @@ -741,7 +758,7 @@ detach() close(1); close(2); detached = 1; - if (!log_to_file && !log_to_specific_fd) + if (log_default) log_to_fd = -1; /* update pid files if they have been written already */ if (pidfilename[0]) @@ -1020,7 +1037,8 @@ cleanup() if (fd_ppp >= 0) disestablish_ppp(devfd); - cleanup_tty(); + if (the_channel->cleanup) + (*the_channel->cleanup)(); if (pidfilename[0] != 0 && unlink(pidfilename) < 0 && errno != ENOENT) warn("unable to delete pid file %s: %m", pidfilename); @@ -1378,7 +1396,8 @@ device_script(program, in, out, dont_wait) close(1); close(2); sys_close(); - tty_close_fds(); + if (the_channel->close) + (*the_channel->close)(); closelog(); /* dup the in, out, err fds to 0, 1, 2 */ @@ -1460,7 +1479,8 @@ run_program(prog, args, must_exist, done, arg) close (0); close (1); close (2); - tty_close_fds(); + if (the_channel->close) + (*the_channel->close)(); /* Don't pass handles to the PPP device, even by accident. */ new_fd = open (_PATH_DEVNULL, O_RDWR); diff --git a/pppd/options.c b/pppd/options.c index ec52cbb..689bde6 100644 --- a/pppd/options.c +++ b/pppd/options.c @@ -17,7 +17,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: options.c,v 1.78 2001/02/22 03:15:20 paulus Exp $" +#define RCSID "$Id: options.c,v 1.79 2001/03/08 05:11:15 paulus Exp $" #include #include @@ -38,7 +38,6 @@ #include "pppd.h" #include "pathnames.h" -#include "patchlevel.h" #if defined(ultrix) || defined(NeXT) char *strdup __P((char *)); @@ -46,6 +45,12 @@ char *strdup __P((char *)); static const char rcsid[] = RCSID; +struct option_value { + struct option_value *next; + const char *source; + char value[1]; +}; + /* * Option variables and default values. */ @@ -69,6 +74,7 @@ int idle_time_limit = 0; /* Disconnect if idle for this many seconds */ int holdoff = 30; /* # seconds to pause before reconnecting */ bool holdoff_specified; /* true if a holdoff value has been given */ int log_to_fd = 1; /* send log messages to this fd too */ +bool log_default = 1; /* log_to_fd is default (stdout) */ int maxfail = 10; /* max # of unsuccessful connection attempts */ char linkname[MAXPATHLEN]; /* logical name for link */ bool tune_kernel; /* may alter kernel settings */ @@ -76,6 +82,9 @@ int connect_delay = 1000; /* wait this many ms after connect script */ int req_unit = -1; /* requested interface unit */ bool multilink = 0; /* Enable multilink operation */ char *bundle_name = NULL; /* bundle name for multilink */ +bool dump_options; /* print out option values */ +bool dryrun; /* print out option values and exit */ +char *domain; /* domain name set by domain option */ extern option_t auth_options[]; extern struct stat devstat; @@ -92,8 +101,8 @@ char *option_source; /* string saying where the option came from */ int option_priority = OPRIO_CFGFILE; /* priority of the current options */ bool devnam_fixed; /* can no longer change device name */ -bool log_to_file; /* log_to_fd is a file opened by us */ -bool log_to_specific_fd; /* log_to_fd was specified by user option */ +static int logfile_fd = -1; /* fd opened for log file */ +static char logfile_name[MAXPATHLEN]; /* name of log file */ /* * Prototypes @@ -114,7 +123,7 @@ static int setpassfilter __P((char **)); static int setactivefilter __P((char **)); #endif -static option_t *find_option __P((char *name)); +static option_t *find_option __P((const char *name)); static int process_option __P((option_t *, char *, char **)); static int n_arguments __P((option_t *)); static int number_option __P((char *, u_int32_t *, int)); @@ -134,89 +143,123 @@ static struct option_list *extra_options = NULL; */ option_t general_options[] = { { "debug", o_int, &debug, - "Increase debugging level", OPT_INC|OPT_NOARG|1 }, + "Increase debugging level", OPT_INC | OPT_NOARG | 1 }, { "-d", o_int, &debug, - "Increase debugging level", OPT_INC|OPT_NOARG|1 }, + "Increase debugging level", + OPT_ALIAS | OPT_INC | OPT_NOARG | 1 }, + { "kdebug", o_int, &kdebugflag, - "Set kernel driver debug level" }, + "Set kernel driver debug level", OPT_PRIO }, + { "nodetach", o_bool, &nodetach, - "Don't detach from controlling tty", 1 }, + "Don't detach from controlling tty", OPT_PRIO | 1 }, { "-detach", o_bool, &nodetach, - "Don't detach from controlling tty", 1 }, + "Don't detach from controlling tty", OPT_ALIAS | OPT_PRIOSUB | 1 }, { "updetach", o_bool, &updetach, - "Detach from controlling tty once link is up", 1 }, + "Detach from controlling tty once link is up", + OPT_PRIOSUB | OPT_A2CLR | 1, &nodetach }, + { "holdoff", o_int, &holdoff, - "Set time in seconds before retrying connection" }, + "Set time in seconds before retrying connection", OPT_PRIO }, + { "idle", o_int, &idle_time_limit, - "Set time in seconds before disconnecting idle link" }, + "Set time in seconds before disconnecting idle link", OPT_PRIO }, + { "maxconnect", o_int, &maxconnect, - "Set connection time limit", OPT_LLIMIT|OPT_NOINCR|OPT_ZEROINF }, + "Set connection time limit", + OPT_PRIO | OPT_LLIMIT | OPT_NOINCR | OPT_ZEROINF }, + { "domain", o_special, (void *)setdomain, - "Add given domain name to hostname", OPT_PRIV }, + "Add given domain name to hostname", + OPT_PRIO | OPT_PRIV | OPT_A2STRVAL, &domain }, + { "file", o_special, (void *)readfile, - "Take options from a file" }, + "Take options from a file", OPT_NOPRINT }, { "call", o_special, (void *)callfile, - "Take options from a privileged file" }, + "Take options from a privileged file", OPT_NOPRINT }, + { "persist", o_bool, &persist, - "Keep on reopening connection after close", 1 }, + "Keep on reopening connection after close", OPT_PRIO | 1 }, { "nopersist", o_bool, &persist, - "Turn off persist option" }, + "Turn off persist option", OPT_PRIOSUB }, + { "demand", o_bool, &demand, "Dial on demand", OPT_INITONLY | 1, &persist }, + { "--version", o_special_noarg, (void *)showversion, "Show version number" }, { "--help", o_special_noarg, (void *)showhelp, "Show brief listing of options" }, { "-h", o_special_noarg, (void *)showhelp, - "Show brief listing of options" }, + "Show brief listing of options", OPT_ALIAS }, + + { "logfile", o_special, (void *)setlogfile, + "Append log messages to this file", + OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, &logfile_name }, { "logfd", o_int, &log_to_fd, "Send log messages to this file descriptor", - 0, &log_to_specific_fd }, - { "logfile", o_special, (void *)setlogfile, - "Append log messages to this file" }, + OPT_PRIOSUB | OPT_A2CLR, &log_default }, { "nolog", o_int, &log_to_fd, "Don't send log messages to any file", - OPT_NOARG | OPT_VAL(-1) }, + OPT_PRIOSUB | OPT_NOARG | OPT_VAL(-1) }, { "nologfd", o_int, &log_to_fd, "Don't send log messages to any file descriptor", - OPT_NOARG | OPT_VAL(-1) }, + OPT_PRIOSUB | OPT_ALIAS | OPT_NOARG | OPT_VAL(-1) }, + { "linkname", o_string, linkname, "Set logical name for link", - OPT_PRIV|OPT_STATIC, NULL, MAXPATHLEN }, + OPT_PRIO | OPT_PRIV | OPT_STATIC, NULL, MAXPATHLEN }, + { "maxfail", o_int, &maxfail, - "Maximum number of unsuccessful connection attempts to allow" }, + "Maximum number of unsuccessful connection attempts to allow", + OPT_PRIO }, + { "ktune", o_bool, &tune_kernel, - "Alter kernel settings as necessary", 1 }, + "Alter kernel settings as necessary", OPT_PRIO | 1 }, { "noktune", o_bool, &tune_kernel, - "Don't alter kernel settings", 0 }, + "Don't alter kernel settings", OPT_PRIOSUB }, + { "connect-delay", o_int, &connect_delay, - "Maximum time (in ms) to wait after connect script finishes" }, + "Maximum time (in ms) to wait after connect script finishes", + OPT_PRIO }, + { "unit", o_int, &req_unit, - "PPP interface unit number to use if possible", OPT_LLIMIT, 0, 0 }, + "PPP interface unit number to use if possible", + OPT_PRIO | OPT_LLIMIT, 0, 0 }, + + { "dump", o_bool, &dump_options, + "Print out option values after parsing all options", 1 }, + { "dryrun", o_bool, &dryrun, + "Stop after parsing, printing, and checking options", 1 }, + #ifdef HAVE_MULTILINK { "multilink", o_bool, &multilink, - "Enable multilink operation", 1 }, - { "nomultilink", o_bool, &multilink, - "Disable multilink operation", 0 }, + "Enable multilink operation", OPT_PRIO | 1 }, { "mp", o_bool, &multilink, - "Enable multilink operation", 1 }, + "Enable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 1 }, + { "nomultilink", o_bool, &multilink, + "Disable multilink operation", OPT_PRIOSUB | 0 }, { "nomp", o_bool, &multilink, - "Disable multilink operation", 0 }, + "Disable multilink operation", OPT_PRIOSUB | OPT_ALIAS | 0 }, + { "bundle", o_string, &bundle_name, - "Bundle name for multilink" }, + "Bundle name for multilink", OPT_PRIO }, #endif /* HAVE_MULTILINK */ + #ifdef PLUGIN { "plugin", o_special, (void *)loadplugin, - "Load a plug-in module into pppd", OPT_PRIV }, + "Load a plug-in module into pppd", OPT_PRIV | OPT_A2LIST }, #endif #ifdef PPP_FILTER { "pdebug", o_int, &dflag, - "libpcap debugging" }, + "libpcap debugging", OPT_PRIO }, + { "pass-filter", 1, setpassfilter, - "set filter for packets to pass" }, + "set filter for packets to pass", OPT_PRIO }, + { "active-filter", 1, setactivefilter, - "set filter for active pkts" }, + "set filter for active pkts", OPT_PRIO }, #endif { NULL } @@ -227,7 +270,7 @@ option_t general_options[] = { #endif static char *usage_string = "\ -pppd version %s.%d%s\n\ +pppd version %s\n\ Usage: %s [ options ], where options are:\n\ Communicate over the named device\n\ Set the baud rate to \n\ @@ -487,7 +530,7 @@ match_option(name, opt, dowild) */ static option_t * find_option(name) - char *name; + const char *name; { option_t *opt; struct option_list *list; @@ -504,6 +547,9 @@ find_option(name) for (opt = list->options; opt->name != NULL; ++opt) if (match_option(name, opt, dowild)) return opt; + for (opt = the_channel->options; opt->name != NULL; ++opt) + if (match_option(name, opt, dowild)) + return opt; for (i = 0; protocols[i] != NULL; ++i) if ((opt = protocols[i]->options) != NULL) for (; opt->name != NULL; ++opt) @@ -529,23 +575,23 @@ process_option(opt, cmd, argv) int (*wildp) __P((char *, char **, int)); char *optopt = (opt->type == o_wild)? "": " option"; int prio = option_priority; + option_t *mainopt = opt; if ((opt->flags & OPT_PRIVFIX) && privileged_option) prio += OPRIO_ROOT; - /* Multipart options (like the local:remote IP address option) - need to keep a separate priority value for each part, - so we let the parser function handle that. */ - if ((opt->flags & OPT_MULTIPART) == 0) { - if (prio < opt->priority) { + while (mainopt->flags & OPT_PRIOSUB) + --mainopt; + if (mainopt->flags & OPT_PRIO) { + if (prio < mainopt->priority) { /* new value doesn't override old */ - if (prio == OPRIO_CMDLINE && opt->priority > OPRIO_ROOT) { + if (prio == OPRIO_CMDLINE && mainopt->priority > OPRIO_ROOT) { option_error("%s%s set in %s cannot be overridden\n", - opt->name, optopt, opt->source); + opt->name, optopt, mainopt->source); return 0; } return 1; } - if (prio > OPRIO_ROOT && opt->priority == OPRIO_CMDLINE) + if (prio > OPRIO_ROOT && mainopt->priority == OPRIO_CMDLINE) warn("%s%s from %s overrides command line", opt->name, optopt, option_source); } @@ -626,6 +672,8 @@ process_option(opt, cmd, argv) case o_uint32: if (opt->flags & OPT_NOARG) { v = opt->flags & OPT_VALUE; + if (v & 0x80) + v |= 0xffffff00U; } else if (!number_option(*argv, &v, 16)) return 0; if (opt->flags & OPT_OR) @@ -651,6 +699,20 @@ process_option(opt, cmd, argv) parser = (int (*) __P((char **))) opt->addr; if (!(*parser)(argv)) return 0; + if (opt->flags & OPT_A2LIST) { + struct option_value *ovp, **pp; + + ovp = malloc(sizeof(*ovp) + strlen(*argv)); + if (ovp != 0) { + strcpy(ovp->value, *argv); + ovp->source = option_source; + ovp->next = NULL; + pp = (struct option_value **) &opt->addr2; + while (*pp != 0) + pp = &(*pp)->next; + *pp = ovp; + } + } break; case o_wild: @@ -660,15 +722,43 @@ process_option(opt, cmd, argv) break; } - if (opt->addr2 && (opt->flags & (OPT_A2COPY|OPT_ENABLE)) == 0) - *(bool *)(opt->addr2) = 1; + if (opt->addr2 && (opt->flags & (OPT_A2COPY|OPT_ENABLE + |OPT_A2PRINTER|OPT_A2STRVAL|OPT_A2LIST)) == 0) + *(bool *)(opt->addr2) = !(opt->flags & OPT_A2CLR); - opt->source = option_source; - opt->priority = prio; + mainopt->source = option_source; + mainopt->priority = prio; + mainopt->winner = opt - mainopt; return 1; } +/* + * override_value - if the option priorities would permit us to + * override the value of option, return 1 and update the priority + * and source of the option value. Otherwise returns 0. + */ +int +override_value(option, priority, source) + const char *option; + int priority; + const char *source; +{ + option_t *opt; + + opt = find_option(option); + if (opt == NULL) + return 0; + while (opt->flags & OPT_PRIOSUB) + --opt; + if ((opt->flags & OPT_PRIO) && priority < opt->priority) + return 0; + opt->priority = priority; + opt->source = source; + opt->winner = -1; + return 1; +} + /* * n_arguments - tell how many arguments an option takes */ @@ -697,6 +787,157 @@ add_options(opt) extra_options = list; } +/* + * check_options - check that options are valid and consistent. + */ +void +check_options() +{ + if (logfile_fd >= 0 && logfile_fd != log_to_fd) + close(logfile_fd); +} + +/* + * print_option - print out an option and its value + */ +static void +print_option(opt, mainopt, printer, arg) + option_t *opt, *mainopt; + void (*printer) __P((void *, char *, ...)); + void *arg; +{ + int i, v; + char *p; + + if (opt->flags & OPT_NOPRINT) + return; + switch (opt->type) { + case o_bool: + v = opt->flags & OPT_VALUE; + if (*(bool *)opt->addr != v) + printer(arg, "oops, %s value is %d not %d?\n", + opt->name, *(bool *)opt->addr, v); + printer(arg, "%s", opt->name); + break; + case o_int: + v = opt->flags & OPT_VALUE; + if (v >= 128) + v -= 256; + i = *(int *)opt->addr; + if (opt->flags & OPT_NOARG) { + printer(arg, "%s", opt->name); + if (i != v) { + if (opt->flags & OPT_INC) { + for (; i > v; i -= v) + printer(arg, " %s", opt->name); + } else + printer(arg, " # oops: %d not %d\n", + i, v); + } + } else { + printer(arg, "%s %d", opt->name, i); + } + break; + case o_uint32: + printer(arg, "%s", opt->name); + if ((opt->flags & OPT_NOARG) == 0) + printer(arg, " %x", *(u_int32_t *)opt->addr); + break; + + case o_string: + if (opt->flags & OPT_HIDE) { + p = "??????"; + } else { + p = (char *) opt->addr; + if ((opt->flags & OPT_STATIC) == 0) + p = *(char **)p; + } + printer(arg, "%s %q", opt->name, p); + break; + + case o_special: + case o_special_noarg: + case o_wild: + if (opt->type != o_wild) { + printer(arg, "%s", opt->name); + if (n_arguments(opt) == 0) + break; + printer(arg, " "); + } + if (opt->flags & OPT_A2PRINTER) { + void (*oprt) __P((option_t *, + void ((*)__P((void *, char *, ...))), + void *)); + oprt = opt->addr2; + (*oprt)(opt, printer, arg); + } else if (opt->flags & OPT_A2STRVAL) { + p = (char *) opt->addr2; + if ((opt->flags & OPT_STATIC) == 0) + p = *(char **)p; + printer("%q", p); + } else if (opt->flags & OPT_A2LIST) { + struct option_value *ovp; + + ovp = (struct option_value *) opt->addr2; + for (;;) { + printer(arg, "%q", ovp->value); + if ((ovp = ovp->next) == NULL) + break; + printer(arg, "\t\t# (from %s)\n%s ", + ovp->source, opt->name); + } + } else { + printer(arg, "xxx # [don't know how to print value]"); + } + break; + + default: + printer(arg, "# %s value (type %d??)", opt->name, opt->type); + break; + } + printer(arg, "\t\t# (from %s)\n", mainopt->source); +} + +/* + * print_option_list - print out options in effect from an + * array of options. + */ +static void +print_option_list(opt, printer, arg) + option_t *opt; + void (*printer) __P((void *, char *, ...)); + void *arg; +{ + while (opt->name != NULL) { + if (opt->priority != OPRIO_DEFAULT + && opt->winner != (short int) -1) + print_option(opt + opt->winner, opt, printer, arg); + do { + ++opt; + } while (opt->flags & OPT_PRIOSUB); + } +} + +/* + * print_options - print out what options are in effect. + */ +void +print_options(printer, arg) + void (*printer) __P((void *, char *, ...)); + void *arg; +{ + struct option_list *list; + int i; + + print_option_list(general_options, printer, arg); + print_option_list(auth_options, printer, arg); + for (list = extra_options; list != NULL; list = list->next) + print_option_list(list->options, printer, arg); + print_option_list(the_channel->options, printer, arg); + for (i = 0; protocols[i] != NULL; ++i) + print_option_list(protocols[i]->options, printer, arg); +} + /* * usage - print out a message telling how to use the program. */ @@ -704,8 +945,7 @@ static void usage() { if (phase == PHASE_INITIALIZE) - fprintf(stderr, usage_string, VERSION, PATCHLEVEL, IMPLEMENTATION, - progname); + fprintf(stderr, usage_string, VERSION, progname); } /* @@ -730,8 +970,7 @@ showversion(argv) char **argv; { if (phase == PHASE_INITIALIZE) { - fprintf(stderr, "pppd version %s.%d%s\n", - VERSION, PATCHLEVEL, IMPLEMENTATION); + fprintf(stderr, "pppd version %s\n", VERSION); exit(0); } return 0; @@ -1178,6 +1417,7 @@ setdomain(argv) if (**argv != 0) { if (**argv != '.') strncat(hostname, ".", MAXNAMELEN - strlen(hostname)); + domain = hostname + strlen(hostname); strncat(hostname, *argv, MAXNAMELEN - strlen(hostname)); } hostname[MAXNAMELEN-1] = 0; @@ -1204,10 +1444,12 @@ setlogfile(argv) option_error("Can't open log file %s: %m", *argv); return 0; } - if (log_to_file && log_to_fd >= 0) - close(log_to_fd); + strlcpy(logfile_name, *argv, sizeof(logfile_name)); + if (logfile_fd >= 0) + close(logfile_fd); + logfile_fd = fd; log_to_fd = fd; - log_to_file = 1; + log_default = 0; return 1; } @@ -1220,23 +1462,49 @@ loadplugin(argv) void *handle; const char *err; void (*init) __P((void)); - - handle = dlopen(arg, RTLD_GLOBAL | RTLD_NOW); + char *path = arg; + const char *vers; + + if (strchr(arg, '/') == 0) { + const char *base = _PATH_PLUGIN; + int l = strlen(base) + strlen(arg) + 2; + path = malloc(l); + if (path == 0) + novm("plugin file path"); + strlcpy(path, base, l); + strlcat(path, "/", l); + strlcat(path, arg, l); + } + handle = dlopen(path, RTLD_GLOBAL | RTLD_NOW); if (handle == 0) { err = dlerror(); if (err != 0) option_error("%s", err); option_error("Couldn't load plugin %s", arg); - return 0; + goto err; } init = (void (*)(void))dlsym(handle, "plugin_init"); if (init == 0) { option_error("%s has no initialization entry point", arg); - dlclose(handle); - return 0; + goto errclose; + } + vers = (const char *) dlsym(handle, "pppd_version"); + if (vers == 0) { + warn("Warning: plugin %s has no version information", arg); + } else if (strcmp(vers, VERSION) != 0) { + option_error("Plugin %s is for pppd version %s, this is %s", + vers, VERSION); + goto errclose; } info("Plugin %s loaded.", arg); (*init)(); return 1; + + errclose: + dlclose(handle); + err: + if (path != arg) + free(path); + return 0; } #endif /* PLUGIN */ diff --git a/pppd/pppd.h b/pppd/pppd.h index f33c0fb..03dd28a 100644 --- a/pppd/pppd.h +++ b/pppd/pppd.h @@ -16,7 +16,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * $Id: pppd.h,v 1.57 2001/02/22 03:15:21 paulus Exp $ + * $Id: pppd.h,v 1.58 2001/03/08 05:11:16 paulus Exp $ */ /* @@ -32,6 +32,7 @@ #include /* for u_int32_t, if defined */ #include /* for struct timeval */ #include +#include "patchlevel.h" #if defined(__STDC__) #include @@ -83,7 +84,8 @@ typedef struct { int upper_limit; int lower_limit; const char *source; - int priority; + short int priority; + short int winner; } option_t; /* Values for flags */ @@ -98,15 +100,23 @@ typedef struct { #define OPT_ULIMIT 0x8000 /* check value against upper limit */ #define OPT_LIMITS (OPT_LLIMIT|OPT_ULIMIT) #define OPT_ZEROOK 0x10000 /* 0 value is OK even if not within limits */ +#define OPT_HIDE 0x10000 /* for o_string, print value as ?????? */ +#define OPT_A2LIST 0x10000 /* for o_special, keep list of values */ #define OPT_NOINCR 0x20000 /* value mustn't be increased */ #define OPT_ZEROINF 0x40000 /* with OPT_NOINCR, 0 == infinity */ -#define OPT_MULTIPART 0x80000 /* optionally sets multiple variables */ -#define OPT_A2COPY 0x200000 /* addr2 -> second location to rcv value */ -#define OPT_ENABLE 0x400000 /* use *addr2 as enable for option */ -#define OPT_PRIVFIX 0x800000 /* user can't override if set by root */ -#define OPT_INITONLY 0x2000000 /* option can only be set in init phase */ -#define OPT_DEVEQUIV 0x4000000 /* equiv to device name */ +#define OPT_PRIO 0x80000 /* process option priorities for this option */ +#define OPT_PRIOSUB 0x100000 /* subsidiary member of priority group */ +#define OPT_ALIAS 0x200000 /* option is alias for previous option */ +#define OPT_A2COPY 0x400000 /* addr2 -> second location to rcv value */ +#define OPT_ENABLE 0x800000 /* use *addr2 as enable for option */ +#define OPT_A2CLR 0x1000000 /* clear *(bool *)addr2 */ +#define OPT_PRIVFIX 0x2000000 /* user can't override if set by root */ +#define OPT_INITONLY 0x4000000 /* option can only be set in init phase */ +#define OPT_DEVEQUIV 0x8000000 /* equiv to device name */ #define OPT_DEVNAM (OPT_INITONLY | OPT_DEVEQUIV) +#define OPT_A2PRINTER 0x10000000 /* *addr2 is a fn for printing option */ +#define OPT_A2STRVAL 0x20000000 /* *addr2 points to current string value */ +#define OPT_NOPRINT 0x40000000 /* don't print this option at all */ #define OPT_VAL(x) ((x) & OPT_VALUE) @@ -194,8 +204,7 @@ extern int link_stats_valid; /* set if link_stats is valid */ extern int link_connect_time; /* time the link was up for */ extern int using_pty; /* using pty as device (notty or pty opt.) */ extern int log_to_fd; /* logging to this fd as well as syslog */ -extern bool log_to_file; /* log_to_fd is a file */ -extern bool log_to_specific_fd; /* log_to_fd was specified by user */ +extern bool log_default; /* log_to_fd is default (stdout) */ extern char *no_ppp_msg; /* message to print if ppp not in kernel */ extern volatile int status; /* exit status for pppd */ extern bool devnam_fixed; /* can no longer change devnam */ @@ -208,8 +217,6 @@ extern struct notifier *phasechange; /* for notifications of phase changes */ extern struct notifier *exitnotify; /* for notification that we're exiting */ extern struct notifier *sigreceived; /* notification of received signal */ extern int listen_time; /* time to listen first (ms) */ -extern char *current_option; /* option we're processing now */ -extern int option_priority; /* priority of current options */ /* Values for do_callback and doing_callback */ #define CALLBACK_DIALIN 1 /* we are expecting the call back */ @@ -263,6 +270,8 @@ extern int req_unit; /* interface unit number to use */ extern bool multilink; /* enable multilink operation */ extern bool noendpoint; /* don't send or accept endpt. discrim. */ extern char *bundle_name; /* bundle name for multilink */ +extern bool dump_options; /* print out option values */ +extern bool dryrun; /* check everything, print options, exit */ #ifdef PPP_FILTER extern struct bpf_program pass_filter; /* Filter for pkts to pass */ @@ -277,6 +286,7 @@ extern bool ms_lanman; /* Use LanMan password instead of NT */ extern char *current_option; /* the name of the option being parsed */ extern int privileged_option; /* set iff the current option came from root */ extern char *option_source; /* string saying where the option came from */ +extern int option_priority; /* priority of current options */ /* * Values for phase. @@ -335,6 +345,48 @@ struct protent { /* Table of pointers to supported protocols */ extern struct protent *protocols[]; +/* + * This struct contains pointers to a set of procedures for + * doing operations on a "channel". A channel provides a way + * to send and receive PPP packets - the canonical example is + * a serial port device in PPP line discipline (or equivalently + * with PPP STREAMS modules pushed onto it). + */ +struct channel { + /* set of options for this channel */ + option_t *options; + /* find and process a per-channel options file */ + void (*process_extra_options) __P((void)); + /* check all the options that have been given */ + void (*check_options) __P((void)); + /* get the channel ready to do PPP, return a file descriptor */ + int (*connect) __P((void)); + /* we're finished doing PPP on the channel */ + void (*disconnect) __P((void)); + /* set the transmit-side PPP parameters of the channel */ + void (*send_config) __P((int, u_int32_t, int, int)); + /* set the receive-side PPP parameters of the channel */ + void (*recv_config) __P((int, u_int32_t, int, int)); + /* cleanup on error or normal exit */ + void (*cleanup) __P((void)); + /* close the device, called in children after fork */ + void (*close) __P((void)); +}; + +extern struct channel *the_channel; + +#define ppp_send_config(unit, mtu, accm, pc, acc) \ +do { \ + if (the_channel->send_config) \ + (*the_channel->send_config)((mtu), (accm), (pc), (acc)); \ +} while (0) + +#define ppp_recv_config(unit, mtu, accm, pc, acc) \ +do { \ + if (the_channel->send_config) \ + (*the_channel->recv_config)((mtu), (accm), (pc), (acc)); \ +} while (0) + /* * Prototypes. */ @@ -366,12 +418,6 @@ void notify __P((struct notifier *, int)); /* Procedures exported from tty.c. */ void tty_init __P((void)); -void tty_device_check __P((void)); -void tty_check_options __P((void)); -int connect_tty __P((void)); -void disconnect_tty __P((void)); -void tty_close_fds __P((void)); -void cleanup_tty __P((void)); /* Procedures exported from utils.c. */ void log_packet __P((u_char *, int, char *, int)); @@ -388,6 +434,9 @@ void notice __P((char *, ...)); /* log a notice-level message */ void warn __P((char *, ...)); /* log a warning message */ void error __P((char *, ...)); /* log an error message */ void fatal __P((char *, ...)); /* log an error message and die(1) */ +void init_pr_log __P((char *, int)); /* initialize for using pr_log */ +void pr_log __P((void *, char *, ...)); /* printer fn, output to syslog */ +void end_pr_log __P((void)); /* finish up after using pr_log */ /* Procedures exported from auth.c */ void link_required __P((int)); /* we are starting to use the link */ @@ -458,11 +507,11 @@ void add_fd __P((int)); /* Add fd to set to wait for */ void remove_fd __P((int)); /* Remove fd from set to wait for */ int read_packet __P((u_char *)); /* Read PPP packet */ int get_loop_output __P((void)); /* Read pkts from loopback */ -void ppp_send_config __P((int, int, u_int32_t, int, int)); +void tty_send_config __P((int, u_int32_t, int, int)); /* Configure i/f transmit parameters */ -void ppp_set_xaccm __P((int, ext_accm)); +void tty_set_xaccm __P((ext_accm)); /* Set extended transmit ACCM */ -void ppp_recv_config __P((int, int, u_int32_t, int, int)); +void tty_recv_config __P((int, u_int32_t, int, int)); /* Configure i/f receive parameters */ int ccp_test __P((int, u_char *, int, int)); /* Test support for compression scheme */ @@ -473,6 +522,7 @@ int get_idle_time __P((int, struct ppp_idle *)); /* Find out how long link has been idle */ int get_ppp_stats __P((int, struct pppd_stats *)); /* Return link statistics */ +void netif_set_mtu __P((int, int)); /* Set PPP interface MTU */ int sifvjcomp __P((int, int, int, int)); /* Configure VJ TCP header compression */ int sifup __P((int)); /* Configure i/f up for one protocol */ @@ -533,6 +583,11 @@ void option_error __P((char *fmt, ...)); int int_option __P((char *, int *)); /* Simplified number_option for decimal ints */ void add_options __P((option_t *)); /* Add extra options */ +void check_options __P((void)); /* check values after all options parsed */ +int override_value __P((const char *, int, const char *)); + /* override value if permitted by priority */ +void print_options __P((void (*) __P((void *, char *, ...)), void *)); + /* print out values of all options */ int parse_dotted_ip __P((char *, u_int32_t *)); diff --git a/pppd/tty.c b/pppd/tty.c index b7e6165..f245427 100644 --- a/pppd/tty.c +++ b/pppd/tty.c @@ -20,7 +20,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: tty.c,v 1.4 2001/02/22 03:15:21 paulus Exp $" +#define RCSID "$Id: tty.c,v 1.5 2001/03/08 05:11:16 paulus Exp $" #include #include @@ -49,9 +49,19 @@ #include "fsm.h" #include "lcp.h" +void tty_process_extra_options __P((void)); +void tty_check_options __P((void)); +int connect_tty __P((void)); +void disconnect_tty __P((void)); +void tty_close_fds __P((void)); +void cleanup_tty __P((void)); +void tty_do_send_config __P((int, u_int32_t, int, int)); + static int setdevname __P((char *, char **, int)); static int setspeed __P((char *, char **, int)); static int setxonxoff __P((char **)); +static int setescape __P((char **)); +static void printescape __P((option_t *, void (*)(void *, char *,...),void *)); static void finish_tty __P((void)); static int start_charshunt __P((int, int)); static void stop_charshunt __P((void *, int)); @@ -66,6 +76,7 @@ static int pty_master; /* fd for master side of pty */ static int pty_slave; /* fd for slave side of pty */ static int real_ttyfd; /* fd for actual serial port (not pty) */ static int ttyfd; /* Serial port file descriptor */ +static char speed_str[16]; /* Serial port speed as string */ mode_t tty_mode = (mode_t)-1; /* Original access permissions to tty */ int baud_rate; /* Actual bits/second for serial device */ @@ -97,57 +108,101 @@ extern int kill_link; /* XXX */ extern int privopen; /* don't lock, open device as root */ +u_int32_t xmit_accm[8]; /* extended transmit ACCM */ + /* option descriptors */ option_t tty_options[] = { /* device name must be first, or change connect_tty() below! */ { "device name", o_wild, (void *) &setdevname, - "Serial port device name", OPT_DEVNAM | OPT_PRIVFIX | OPT_NOARG }, + "Serial port device name", + OPT_DEVNAM | OPT_PRIVFIX | OPT_NOARG | OPT_A2STRVAL | OPT_STATIC, + devnam}, + { "tty speed", o_wild, (void *) &setspeed, - "Baud rate for serial port", OPT_NOARG }, + "Baud rate for serial port", + OPT_PRIO | OPT_NOARG | OPT_A2STRVAL | OPT_STATIC, speed_str }, + { "lock", o_bool, &lockflag, - "Lock serial device with UUCP-style lock file", 1 }, + "Lock serial device with UUCP-style lock file", OPT_PRIO | 1 }, { "nolock", o_bool, &lockflag, - "Don't lock serial device", OPT_PRIV }, + "Don't lock serial device", OPT_PRIOSUB | OPT_PRIV }, + { "init", o_string, &initializer, - "A program to initialize the device", OPT_PRIVFIX }, + "A program to initialize the device", OPT_PRIO | OPT_PRIVFIX }, + { "connect", o_string, &connect_script, - "A program to set up a connection", OPT_PRIVFIX }, + "A program to set up a connection", OPT_PRIO | OPT_PRIVFIX }, + { "disconnect", o_string, &disconnect_script, - "Program to disconnect serial device", OPT_PRIVFIX }, + "Program to disconnect serial device", OPT_PRIO | OPT_PRIVFIX }, + { "welcome", o_string, &welcomer, - "Script to welcome client", OPT_PRIVFIX }, + "Script to welcome client", OPT_PRIO | OPT_PRIVFIX }, + { "pty", o_string, &ptycommand, - "Script to run on pseudo-tty master side", OPT_PRIVFIX | OPT_DEVNAM }, + "Script to run on pseudo-tty master side", + OPT_PRIO | OPT_PRIVFIX | OPT_DEVNAM }, + { "notty", o_bool, ¬ty, "Input/output is not a tty", OPT_DEVNAM | 1 }, + { "socket", o_string, &pty_socket, - "Send and receive over socket, arg is host:port", OPT_DEVNAM }, + "Send and receive over socket, arg is host:port", + OPT_PRIO | OPT_DEVNAM }, + { "record", o_string, &record_file, - "Record characters sent/received to file" }, + "Record characters sent/received to file", OPT_PRIO }, + { "crtscts", o_int, &crtscts, - "Set hardware (RTS/CTS) flow control", OPT_NOARG|OPT_VAL(1) }, + "Set hardware (RTS/CTS) flow control", + OPT_PRIO | OPT_NOARG | OPT_VAL(1) }, + { "cdtrcts", o_int, &crtscts, + "Set alternate hardware (DTR/CTS) flow control", + OPT_PRIOSUB | OPT_NOARG | OPT_VAL(2) }, { "nocrtscts", o_int, &crtscts, - "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) }, + "Disable hardware flow control", + OPT_PRIOSUB | OPT_NOARG | OPT_VAL(-1) }, { "-crtscts", o_int, &crtscts, - "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) }, - { "cdtrcts", o_int, &crtscts, - "Set alternate hardware (DTR/CTS) flow control", OPT_NOARG|OPT_VAL(2) }, + "Disable hardware flow control", + OPT_PRIOSUB | OPT_ALIAS | OPT_NOARG | OPT_VAL(-1) }, { "nocdtrcts", o_int, &crtscts, - "Disable hardware flow control", OPT_NOARG|OPT_VAL(-1) }, + "Disable hardware flow control", + OPT_PRIOSUB | OPT_ALIAS | OPT_NOARG | OPT_VAL(-1) }, { "xonxoff", o_special_noarg, (void *)setxonxoff, - "Set software (XON/XOFF) flow control" }, + "Set software (XON/XOFF) flow control", OPT_PRIOSUB }, + { "modem", o_bool, &modem, - "Use modem control lines", 1 }, + "Use modem control lines", OPT_PRIO | 1 }, { "local", o_bool, &modem, - "Don't use modem control lines" }, + "Don't use modem control lines", OPT_PRIOSUB | 0 }, + { "sync", o_bool, &sync_serial, "Use synchronous HDLC serial encoding", 1 }, + { "datarate", o_int, &max_data_rate, - "Maximum data rate in bytes/sec (with pty, notty or record option)" }, + "Maximum data rate in bytes/sec (with pty, notty or record option)", + OPT_PRIO }, + + { "escape", o_special, (void *)setescape, + "List of character codes to escape on transmission", + OPT_A2PRINTER, (void *)printescape }, + { NULL } }; +struct channel tty_channel = { + tty_options, + &tty_process_extra_options, + &tty_check_options, + &connect_tty, + &disconnect_tty, + &tty_do_send_config, + &tty_recv_config, + &cleanup_tty, + &tty_close_fds +}; + /* * setspeed - Set the serial port baud rate. * If doit is 0, the call is to check whether this option is @@ -165,8 +220,10 @@ setspeed(arg, argv, doit) spd = strtol(arg, &ptr, 0); if (ptr == arg || *ptr != 0 || spd == 0) return 0; - if (doit) + if (doit) { inspeed = spd; + slprintf(speed_str, sizeof(speed_str), "%d", spd); + } return 1; } @@ -229,20 +286,77 @@ setxonxoff(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) { + option_error("escape parameter contains invalid hex number '%s'", + p); + return 0; + } + p = endp; + if (n < 0 || n == 0x5E || n > 0xFF) { + option_error("can't escape character 0x%x", n); + ret = 0; + } else + xmit_accm[n >> 5] |= 1 << (n & 0x1F); + while (*p == ',' || *p == ' ') + ++p; + } + lcp_allowoptions[0].asyncmap = xmit_accm[0]; + return ret; +} + +static void +printescape(opt, printer, arg) + option_t *opt; + void (*printer) __P((void *, char *, ...)); + void *arg; +{ + int n; + int first = 1; + + for (n = 0; n < 256; ++n) { + if (n == 0x7d) + n += 2; /* skip 7d, 7e */ + if (xmit_accm[n >> 5] & (1 << (n & 0x1f))) { + if (!first) + printer(arg, ","); + else + first = 0; + printer(arg, "%x", n); + } + } + if (first) + printer(arg, "oops # nothing escaped"); +} + /* * tty_init - do various tty-related initializations. */ void tty_init() { add_notifier(&pidchange, maybe_relock, 0); - add_options(tty_options); + the_channel = &tty_channel; + xmit_accm[3] = 0x60000000; } /* - * tty_device_check - work out which tty device we are using + * tty_process_extra_options - work out which tty device we are using * and read its options file. */ -void tty_device_check() +void tty_process_extra_options() { using_pty = notty || ptycommand != NULL || pty_socket != NULL; if (using_pty) @@ -594,6 +708,20 @@ void cleanup_tty() } } +/* + * tty_do_send_config - set transmit-side PPP configuration. + * We set the extended transmit ACCM here as well. + */ +void +tty_do_send_config(mtu, accm, pcomp, accomp) + int mtu; + u_int32_t accm; + int pcomp, accomp; +{ + tty_set_xaccm(xmit_accm); + tty_send_config(mtu, accm, pcomp, accomp); +} + /* * finish_tty - restore the terminal device to its original settings */ diff --git a/pppd/upap.c b/pppd/upap.c index 7e5f0d5..ad13e39 100644 --- a/pppd/upap.c +++ b/pppd/upap.c @@ -17,7 +17,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: upap.c,v 1.23 1999/11/20 05:11:47 paulus Exp $" +#define RCSID "$Id: upap.c,v 1.24 2001/03/08 05:11:16 paulus Exp $" /* * TODO: @@ -38,15 +38,17 @@ static bool hide_password = 1; */ static option_t pap_option_list[] = { { "hide-password", o_bool, &hide_password, - "Don't output passwords to log", 1 }, + "Don't output passwords to log", OPT_PRIO | 1 }, { "show-password", o_bool, &hide_password, - "Show password string in debug log messages", 0 }, + "Show password string in debug log messages", OPT_PRIOSUB | 0 }, + { "pap-restart", o_int, &upap[0].us_timeouttime, - "Set retransmit timeout for PAP" }, + "Set retransmit timeout for PAP", OPT_PRIO }, { "pap-max-authreq", o_int, &upap[0].us_maxtransmits, - "Set max number of transmissions for auth-reqs" }, + "Set max number of transmissions for auth-reqs", OPT_PRIO }, { "pap-timeout", o_int, &upap[0].us_reqtimeout, - "Set time limit for peer PAP authentication" }, + "Set time limit for peer PAP authentication", OPT_PRIO }, + { NULL } }; diff --git a/pppd/utils.c b/pppd/utils.c index f6aa287..b176fbb 100644 --- a/pppd/utils.c +++ b/pppd/utils.c @@ -17,7 +17,7 @@ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ -#define RCSID "$Id: utils.c,v 1.10 2000/03/27 01:36:48 paulus Exp $" +#define RCSID "$Id: utils.c,v 1.11 2001/03/08 05:11:16 paulus Exp $" #include #include @@ -51,8 +51,8 @@ static const char rcsid[] = RCSID; extern char *strerror(); #endif -static void pr_log __P((void *, char *, ...)); static void logit __P((int, char *, va_list)); +static void log_write __P((int, char *)); static void vslp_printer __P((void *, char *, ...)); static void format_packet __P((u_char *, int, void (*) (void *, char *, ...), void *)); @@ -407,13 +407,11 @@ vslp_printer __V((void *arg, char *fmt, ...)) bi->len -= n; } +#ifdef unused /* * log_packet - format a packet and log it. */ -char line[256]; /* line to be logged accumulated here */ -char *linep; - void log_packet(p, len, prefix, level) u_char *p; @@ -421,12 +419,11 @@ log_packet(p, len, prefix, level) char *prefix; int level; { - strlcpy(line, prefix, sizeof(line)); - linep = line + strlen(line); - format_packet(p, len, pr_log, NULL); - if (linep != line) - syslog(level, "%s", line); + init_pr_log(prefix, level); + format_packet(p, len, pr_log, &level); + end_pr_log(); } +#endif /* unused */ /* * format_packet - make a readable representation of a packet, @@ -478,32 +475,91 @@ format_packet(p, len, printer, arg) printer(arg, "%.*B", len, p); } -static void +/* + * init_pr_log, end_pr_log - initialize and finish use of pr_log. + */ + +static char line[256]; /* line to be logged accumulated here */ +static char *linep; /* current pointer within line */ +static int llevel; /* level for logging */ + +void +init_pr_log(prefix, level) + char *prefix; + int level; +{ + linep = line; + if (prefix != NULL) { + strlcpy(line, prefix, sizeof(line)); + linep = line + strlen(line); + } + llevel = level; +} + +void +end_pr_log() +{ + if (linep != line) { + *linep = 0; + log_write(llevel, line); + } +} + +/* + * pr_log - printer routine for outputting to syslog + */ +void pr_log __V((void *arg, char *fmt, ...)) { - int n; - va_list pvar; - char buf[256]; + int l, n; + va_list pvar; + char *p, *eol; + char buf[256]; #if defined(__STDC__) - va_start(pvar, fmt); + va_start(pvar, fmt); #else - void *arg; - char *fmt; - va_start(pvar); - arg = va_arg(pvar, void *); - fmt = va_arg(pvar, char *); + void *arg; + char *fmt; + va_start(pvar); + arg = va_arg(pvar, void *); + fmt = va_arg(pvar, char *); #endif - n = vslprintf(buf, sizeof(buf), fmt, pvar); - va_end(pvar); + n = vslprintf(buf, sizeof(buf), fmt, pvar); + va_end(pvar); + + p = buf; + eol = strchr(buf, '\n'); + if (linep != line) { + l = (eol == NULL)? n: eol - buf; + if (linep + l < line + sizeof(line)) { + if (l > 0) { + memcpy(linep, buf, l); + linep += l; + } + if (eol == NULL) + return; + p = eol + 1; + eol = strchr(p, '\n'); + } + *linep = 0; + log_write(llevel, line); + linep = line; + } - if (linep + n + 1 > line + sizeof(line)) { - syslog(LOG_DEBUG, "%s", line); - linep = line; - } - strlcpy(linep, buf, line + sizeof(line) - linep); - linep += n; + while (eol != NULL) { + *eol = 0; + log_write(llevel, p); + p = eol + 1; + } + + /* assumes sizeof(buf) <= sizeof(line) */ + l = buf + n - p; + if (l > 0) { + memcpy(line, p, n); + linep = line + l; + } } /* @@ -558,11 +614,22 @@ logit(level, fmt, args) char buf[1024]; n = vslprintf(buf, sizeof(buf), fmt, args); + log_write(level, buf); +} + +static void +log_write(level, buf) + int level; + char *buf; +{ syslog(level, "%s", buf); if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) { - if (buf[n-1] != '\n') - buf[n++] = '\n'; - if (write(log_to_fd, buf, n) != n) + int n = strlen(buf); + + if (n > 0 && buf[n-1] == '\n') + --n; + if (write(log_to_fd, buf, n) != n + || write(log_to_fd, "\n", 1) != 1) log_to_fd = -1; } }