X-Git-Url: https://git.ozlabs.org/?a=blobdiff_plain;f=pppd%2Foptions.c;h=e92fb20c5b0d966ab6a3c13c64bd03eddfc6c1cd;hb=13e277c831dfdd5cecab41e534e78fcbf5393d6e;hp=4520f2df4fc07a16e6067b570416d6f924d0c11b;hpb=9be4164a6a772660090d2cca1a4501fa9c175735;p=ppp.git diff --git a/pppd/options.c b/pppd/options.c index 4520f2d..e92fb20 100644 --- a/pppd/options.c +++ b/pppd/options.c @@ -18,7 +18,7 @@ */ #ifndef lint -static char rcsid[] = "$Id: options.c,v 1.4 1994/02/08 23:48:50 paulus Exp $"; +static char rcsid[] = "$Id: options.c,v 1.8 1994/05/24 11:24:32 paulus Exp $"; #endif #include @@ -29,8 +29,10 @@ static char rcsid[] = "$Id: options.c,v 1.4 1994/02/08 23:48:50 paulus Exp $"; #include #include #include +#include #include #include +#include #include "ppp.h" #include "pppd.h" @@ -45,11 +47,19 @@ static char rcsid[] = "$Id: options.c,v 1.4 1994/02/08 23:48:50 paulus Exp $"; #define FALSE 0 #define TRUE 1 +#ifdef ultrix +char *strdup __ARGS((char *)); +#endif + +#ifndef GIDSET_TYPE +#define GIDSET_TYPE int +#endif /* * 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 +75,21 @@ static int noasyncmap __ARGS((void)); static int noipaddr __ARGS((void)); static int nomagicnumber __ARGS((void)); static int setasyncmap __ARGS((char **)); +static int setescape __ARGS((char **)); static int setmru __ARGS((char **)); +static int setmtu __ARGS((char **)); static int nomru __ARGS((void)); static int nopcomp __ARGS((void)); static int setconnector __ARGS((char **)); +static int setdisconnector __ARGS((char **)); static int setdomain __ARGS((char **)); static int setnetmask __ARGS((char **)); static int setcrtscts __ARGS((void)); +static int setxonxoff __ARGS((void)); static int setnodetach __ARGS((void)); static int setmodem __ARGS((void)); static int setlocal __ARGS((void)); +static int setlock __ARGS((void)); static int setname __ARGS((char **)); static int setuser __ARGS((char **)); static int setremote __ARGS((char **)); @@ -101,19 +116,25 @@ static int setchapchal __ARGS((char **)); static int setchapintv __ARGS((char **)); static int setipcpaccl __ARGS((void)); static int setipcpaccr __ARGS((void)); +static int setlcpechointerval __ARGS((char **)); +static int setlcpechofails __ARGS((char **)); +static int setslots __ARGS((char **)); static int number_option __ARGS((char *, long *, int)); - +static int readable __ARGS((int fd)); /* * Option variables */ 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; @@ -125,6 +146,9 @@ extern int auth_required; extern int proxyarp; extern int persist; extern int uselogin; +extern int nslots; +extern u_long lcp_echo_interval; +extern u_long lcp_echo_fails; extern char our_name[]; extern char remote_name[]; int usehostname; @@ -156,16 +180,23 @@ 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 */ + "xonxoff", 0, setxonxoff, /* set s/w flow control */ + "-crtscts", 0, setxonxoff, /* another name for xonxoff */ "debug", 0, setdebug, /* Increase debugging level */ + "kdebug", 1, setkdebug, /* Enable kernel-level debugging */ "domain", 1, setdomain, /* Add given domain name to hostname*/ "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. */ @@ -177,6 +208,8 @@ static struct cmd { "persist", 0, setpersist, /* Keep on reopening connection after close */ "login", 0, setdologin, /* Use system password database for UPAP */ "noipdefault", 0, setnoipdflt, /* Don't use name for default IP adrs */ + "lcp-echo-failure", 1, setlcpechofails, /* consecutive echo failures */ + "lcp-echo-interval", 1, setlcpechointerval, /* time for lcp echo events */ "lcp-restart", 1, setlcptimeout, /* Set timeout for LCP */ "lcp-max-terminate", 1, setlcpterm, /* Set max #xmits for term-reqs */ "lcp-max-configure", 1, setlcpconf, /* Set max #xmits for conf-reqs */ @@ -185,6 +218,7 @@ static struct cmd { "ipcp-max-terminate", 1, setipcpterm, /* Set max #xmits for term-reqs */ "ipcp-max-configure", 1, setipcpconf, /* Set max #xmits for conf-reqs */ "ipcp-max-failure", 1, setipcpfails, /* Set max #conf-naks for IPCP */ + "ipcp-max-slots", 1, setslots, /* Set maximum vj header slots */ "pap-restart", 1, setpaptimeout, /* Set timeout for UPAP */ "pap-max-authreq", 1, setpapreqs, /* Set max #xmits for auth-reqs */ "chap-restart", 1, setchaptimeout, /* Set timeout for CHAP */ @@ -196,8 +230,12 @@ static struct cmd { }; +#ifndef IMPLEMENTATION +#define IMPLEMENTATION "" +#endif + static char *usage_string = "\ -pppd version %s patch level %d\n\ +pppd version %s patch level %d%s\n\ Usage: %s [ arguments ], where arguments are:\n\ Communicate over the named device\n\ Set the baud rate to \n\ @@ -215,34 +253,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 @@ -255,6 +265,7 @@ parse_args(argc, argv) { char *arg, *val; struct cmd *cmdp; + int ret; while (argc > 0) { arg = *argv++; @@ -281,11 +292,15 @@ parse_args(argc, argv) /* * Maybe a tty name, speed or IP address? */ - if (!setdevname(arg) && !setspeed(arg) && !setipaddr(arg)) { + if ((ret = setdevname(arg)) == 0 + && (ret = setspeed(arg)) == 0 + && (ret = setipaddr(arg)) == 0) { fprintf(stderr, "%s: unrecognized command\n", arg); usage(); return 0; } + if (ret < 0) /* error */ + return 0; } } return 1; @@ -296,7 +311,8 @@ parse_args(argc, argv) */ usage() { - fprintf(stderr, usage_string, VERSION, PATCHLEVEL, progname); + fprintf(stderr, usage_string, VERSION, PATCHLEVEL, IMPLEMENTATION, + progname); } /* @@ -304,12 +320,13 @@ usage() * and interpret them. */ int -options_from_file(filename, must_exist) +options_from_file(filename, must_exist, check_prot) char *filename; int must_exist; + int check_prot; { FILE *f; - int i, newline; + int i, newline, ret; struct cmd *cmdp; char *argv[MAXARGS]; char args[MAXARGS][MAXWORDLEN]; @@ -319,8 +336,14 @@ options_from_file(filename, must_exist) if (!must_exist && errno == ENOENT) return 1; perror(filename); - exit(1); + return 0; + } + if (check_prot && !readable(fileno(f))) { + fprintf(stderr, "%s: access denied\n", filename); + fclose(f); + return 0; } + while (getword(f, cmd, &newline, filename)) { /* * First see if it's a command. @@ -349,12 +372,16 @@ options_from_file(filename, must_exist) /* * Maybe a tty name, speed or IP address? */ - if (!setdevname(cmd) && !setspeed(cmd) && !setipaddr(cmd)) { + if ((ret = setdevname(cmd)) == 0 + && (ret = setspeed(cmd)) == 0 + && (ret = setipaddr(cmd)) == 0) { fprintf(stderr, "In file %s: unrecognized command %s\n", filename, cmd); fclose(f); return 0; } + if (ret < 0) /* error */ + return 0; } } return 1; @@ -369,20 +396,78 @@ options_from_user() { char *user, *path, *file; int ret; + struct passwd *pw; - if ((user = getenv("HOME")) == NULL) - return; - file = "/.ppprc"; - path = malloc(strlen(user) + strlen(file) + 1); + pw = getpwuid(getuid()); + if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0) + return 1; + file = _PATH_USEROPT; + path = malloc(strlen(user) + strlen(file) + 2); if (path == NULL) novm("init file name"); strcpy(path, user); + strcat(path, "/"); strcat(path, file); - ret = options_from_file(path, 0); + ret = options_from_file(path, 0, 1); free(path); return ret; } +/* + * options_for_tty - See if an options file exists for the serial + * device, and if so, interpret options from it. + */ +int +options_for_tty() +{ + char *dev, *path; + int ret; + + dev = strrchr(devname, '/'); + if (dev == NULL) + dev = devname; + else + ++dev; + if (strcmp(dev, "tty") == 0) + return 1; /* don't look for /etc/ppp/options.tty */ + path = malloc(strlen(_PATH_TTYOPT) + strlen(dev) + 1); + if (path == NULL) + novm("tty init file name"); + strcpy(path, _PATH_TTYOPT); + strcat(path, dev); + ret = options_from_file(path, 0, 0); + free(path); + return ret; +} + +/* + * readable - check if a file is readable by the real user. + */ +static int +readable(fd) + int fd; +{ + uid_t uid; + int ngroups, i; + struct stat sbuf; + GIDSET_TYPE groups[NGROUPS_MAX]; + + uid = getuid(); + if (uid == 0) + return 1; + if (fstat(fd, &sbuf) != 0) + return 0; + if (sbuf.st_uid == uid) + return sbuf.st_mode & S_IRUSR; + if (sbuf.st_gid == getgid()) + return sbuf.st_mode & S_IRGRP; + ngroups = getgroups(NGROUPS_MAX, groups); + for (i = 0; i < ngroups; ++i) + if (sbuf.st_gid == groups[i]) + return sbuf.st_mode & S_IRGRP; + return sbuf.st_mode & S_IROTH; +} + /* * Read a word from a file. * Words are delimited by white-space or by quotes ("). @@ -539,7 +624,7 @@ static int readfile(argv) char **argv; { - return options_from_file(*argv, 1); + return options_from_file(*argv, 1, 1); } /* @@ -549,10 +634,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 +737,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 +831,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 +839,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 +903,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 +930,10 @@ setdomain(argv) return (1); } + +/* + * setasyncmap - add bits to asyncmap (what we request peer to escape). + */ static int setasyncmap(argv) char **argv; @@ -814,6 +947,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. */ @@ -855,16 +1020,16 @@ setdevname(cp) */ if (stat(cp, &statbuf) < 0) { if (errno == ENOENT) - return (0); + return 0; syslog(LOG_ERR, cp); - exit(1); + return -1; } (void) strncpy(devname, cp, MAXPATHLEN); devname[MAXPATHLEN-1] = 0; default_device = FALSE; - return (1); + return 1; } @@ -884,7 +1049,7 @@ setipaddr(arg) * IP address pair separated by ":". */ if ((colon = index(arg, ':')) == NULL) - return (0); + return 0; /* * If colon first character, then no local addr. @@ -893,8 +1058,8 @@ setipaddr(arg) *colon = '\0'; if ((local = inet_addr(arg)) == -1) { if ((hp = gethostbyname(arg)) == NULL) { - fprintf(stderr, "unknown host: %s", arg); - local = 0; + fprintf(stderr, "unknown host: %s\n", arg); + return -1; } else { local = *(long *)hp->h_addr; if (our_name[0] == 0) { @@ -903,6 +1068,10 @@ setipaddr(arg) } } } + if (bad_ip_adrs(local)) { + fprintf(stderr, "bad local IP address %s\n", ip_ntoa(local)); + return -1; + } if (local != 0) wo->ouraddr = local; *colon = ':'; @@ -914,8 +1083,8 @@ setipaddr(arg) if (*++colon != '\0') { if ((remote = inet_addr(colon)) == -1) { if ((hp = gethostbyname(colon)) == NULL) { - fprintf(stderr, "unknown host: %s", colon); - remote = 0; + fprintf(stderr, "unknown host: %s\n", colon); + return -1; } else { remote = *(long *)hp->h_addr; if (remote_name[0] == 0) { @@ -924,11 +1093,15 @@ setipaddr(arg) } } } + if (bad_ip_adrs(remote)) { + fprintf(stderr, "bad remote IP address %s\n", ip_ntoa(remote)); + return -1; + } if (remote != 0) wo->hisaddr = remote; } - return (1); + return 1; } @@ -990,7 +1163,7 @@ setipdefault() if ((hp = gethostbyname(hostname)) == NULL) return; local = *(long *)hp->h_addr; - if (local != 0) + if (local != 0 && !bad_ip_adrs(local)) wo->ouraddr = local; } @@ -1003,16 +1176,29 @@ setnetmask(argv) char **argv; { u_long mask; - - if ((mask = inet_addr(*argv)) == -1) { + + if ((mask = inet_addr(*argv)) == -1 || (netmask & ~mask) != 0) { 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() { @@ -1020,6 +1206,13 @@ setcrtscts() return (1); } +static int +setxonxoff() +{ + crtscts = 2; + return (1); +} + static int setnodetach() { @@ -1041,6 +1234,13 @@ setlocal() return 1; } +static int +setlock() +{ + lockflag = 1; + return 1; +} + static int setusehostname() { @@ -1112,6 +1312,22 @@ setdologin() return 1; } +/* + * Functions to set the echo interval for modem-less monitors + */ + +static int setlcpechointerval(argv) + char **argv; +{ + return int_option(*argv, &lcp_echo_interval, 0); +} + +static int setlcpechofails(argv) + char **argv; +{ + return int_option(*argv, &lcp_echo_fails, 0); +} + /* * Functions to set timeouts, max transmits, etc. */ @@ -1193,3 +1409,16 @@ static int setchapintv(argv) { return int_option(*argv, &chap[0].chal_interval, 0); } + +static int setslots(argv) + char **argv; +{ + int value; + int answer = int_option(*argv, &value, 0); + + if (answer == 1 && value > 1 && value < 17) { + ipcp_wantoptions [0].maxslotindex = + ipcp_allowoptions[0].maxslotindex = value - 1; + } + return answer; +}