]> git.ozlabs.org Git - ppp.git/blob - pppd/options.c
Update to state of pppd-new directory
[ppp.git] / pppd / options.c
1 /*
2  * options.c - handles option processing for PPP.
3  *
4  * Copyright (c) 1989 Carnegie Mellon University.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms are permitted
8  * provided that the above copyright notice and this paragraph are
9  * duplicated in all such forms and that any documentation,
10  * advertising materials, and other materials related to such
11  * distribution and use acknowledge that the software was developed
12  * by Carnegie Mellon University.  The name of the
13  * University may not be used to endorse or promote products derived
14  * from this software without specific prior written permission.
15  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18  */
19
20 #ifndef lint
21 static char rcsid[] = "$Id: options.c,v 1.19.2.1 1995/06/01 07:01:33 paulus Exp $";
22 #endif
23
24 #include <stdio.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include <limits.h>
28 #include <stdlib.h>
29 #include <termios.h>
30 #include <syslog.h>
31 #include <string.h>
32 #include <netdb.h>
33 #include <pwd.h>
34 #include <sys/types.h>
35 #include <sys/stat.h>
36 #include <netinet/in.h>
37
38 #include "pppd.h"
39 #include "pathnames.h"
40 #include "patchlevel.h"
41 #include "fsm.h"
42 #include "lcp.h"
43 #include "ipcp.h"
44 #include "upap.h"
45 #include "chap.h"
46 #include "ccp.h"
47
48 #include <net/ppp-comp.h>
49
50 #define FALSE   0
51 #define TRUE    1
52
53 #if defined(ultrix) || defined(NeXT)
54 char *strdup __P((char *));
55 #endif
56
57 #ifndef GIDSET_TYPE
58 #define GIDSET_TYPE     gid_t
59 #endif
60
61 /*
62  * Option variables and default values.
63  */
64 int     debug = 0;              /* Debug flag */
65 int     kdebugflag = 0;         /* Tell kernel to print debug messages */
66 int     default_device = 1;     /* Using /dev/tty or equivalent */
67 char    devnam[MAXPATHLEN] = "/dev/tty";        /* Device name */
68 int     crtscts = 0;            /* Use hardware flow control */
69 int     modem = 1;              /* Use modem control lines */
70 int     inspeed = 0;            /* Input/Output speed requested */
71 u_int32_t netmask = 0;          /* IP netmask to set on interface */
72 int     lockflag = 0;           /* Create lock file to lock the serial dev */
73 int     nodetach = 0;           /* Don't detach from controlling tty */
74 char    *connector = NULL;      /* Script to establish physical link */
75 char    *disconnector = NULL;   /* Script to disestablish physical link */
76 char    user[MAXNAMELEN];       /* Username for PAP */
77 char    passwd[MAXSECRETLEN];   /* Password for PAP */
78 int     auth_required = 0;      /* Peer is required to authenticate */
79 int     defaultroute = 0;       /* assign default route through interface */
80 int     proxyarp = 0;           /* Set up proxy ARP entry for peer */
81 int     persist = 0;            /* Reopen link after it goes down */
82 int     uselogin = 0;           /* Use /etc/passwd for checking PAP */
83 int     lcp_echo_interval = 0;  /* Interval between LCP echo-requests */
84 int     lcp_echo_fails = 0;     /* Tolerance to unanswered echo-requests */
85 char    our_name[MAXNAMELEN];   /* Our name for authentication purposes */
86 char    remote_name[MAXNAMELEN]; /* Peer's name for authentication */
87 int     usehostname = 0;        /* Use hostname for our_name */
88 int     disable_defaultip = 0;  /* Don't use hostname for default IP adrs */
89 int     demand = 0;             /* do dial-on-demand */
90 char    *ipparam = NULL;        /* Extra parameter for ip up/down scripts */
91 int     cryptpap;               /* Passwords in pap-secrets are encrypted */
92 int     idle_time_limit = 0;    /* Disconnect if idle for this many seconds */
93 int     holdoff = 30;           /* # seconds to pause before reconnecting */
94
95 /*
96  * Prototypes
97  */
98 static int setdebug __P((void));
99 static int setkdebug __P((char **));
100 static int setpassive __P((void));
101 static int setsilent __P((void));
102 static int noopt __P((void));
103 static int setnovj __P((void));
104 static int setnovjccomp __P((void));
105 static int setvjslots __P((char **));
106 static int reqpap __P((void));
107 static int nopap __P((void));
108 static int setupapfile __P((char **));
109 static int nochap __P((void));
110 static int reqchap __P((void));
111 static int setspeed __P((char *));
112 static int noaccomp __P((void));
113 static int noasyncmap __P((void));
114 static int noipaddr __P((void));
115 static int nomagicnumber __P((void));
116 static int setasyncmap __P((char **));
117 static int setescape __P((char **));
118 static int setmru __P((char **));
119 static int setmtu __P((char **));
120 static int nomru __P((void));
121 static int nopcomp __P((void));
122 static int setconnector __P((char **));
123 static int setdisconnector __P((char **));
124 static int setdomain __P((char **));
125 static int setnetmask __P((char **));
126 static int setcrtscts __P((void));
127 static int setnocrtscts __P((void));
128 static int setxonxoff __P((void));
129 static int setnodetach __P((void));
130 static int setmodem __P((void));
131 static int setlocal __P((void));
132 static int setlock __P((void));
133 static int setname __P((char **));
134 static int setuser __P((char **));
135 static int setremote __P((char **));
136 static int setauth __P((void));
137 static int readfile __P((char **));
138 static int setdefaultroute __P((void));
139 static int setnodefaultroute __P((void));
140 static int setproxyarp __P((void));
141 static int setnoproxyarp __P((void));
142 static int setpersist __P((void));
143 static int setdologin __P((void));
144 static int setusehostname __P((void));
145 static int setnoipdflt __P((void));
146 static int setlcptimeout __P((char **));
147 static int setlcpterm __P((char **));
148 static int setlcpconf __P((char **));
149 static int setlcpfails __P((char **));
150 static int setipcptimeout __P((char **));
151 static int setipcpterm __P((char **));
152 static int setipcpconf __P((char **));
153 static int setipcpfails __P((char **));
154 static int setpaptimeout __P((char **));
155 static int setpapreqs __P((char **));
156 static int setchaptimeout __P((char **));
157 static int setchapchal __P((char **));
158 static int setchapintv __P((char **));
159 static int setipcpaccl __P((void));
160 static int setipcpaccr __P((void));
161 static int setlcpechointv __P((char **));
162 static int setlcpechofails __P((char **));
163 static int setbsdcomp __P((char **));
164 static int setnobsdcomp __P((void));
165 static int setdemand __P((void));
166 static int setipparam __P((char **));
167 static int setpapcrypt __P((void));
168 static int setidle __P((char **));
169 static int setholdoff __P((char **));
170
171 static int number_option __P((char *, long *, int));
172 static int readable __P((int fd));
173
174 void usage();
175
176 /*
177  * Valid arguments.
178  */
179 static struct cmd {
180     char *cmd_name;
181     int num_args;
182     int (*cmd_func)();
183 } cmds[] = {
184     {"-all", 0, noopt},         /* Don't request/allow any options */
185     {"-ac", 0, noaccomp},       /* Disable Address/Control compress */
186     {"-am", 0, noasyncmap},     /* Disable asyncmap negotiation */
187     {"-as", 1, setasyncmap},    /* set the desired async map */
188     {"-d", 0, setdebug},        /* Increase debugging level */
189     {"-detach", 0, setnodetach}, /* don't fork */
190     {"-ip", 0, noipaddr},       /* Disable IP address negotiation */
191     {"-mn", 0, nomagicnumber},  /* Disable magic number negotiation */
192     {"-mru", 0, nomru},         /* Disable mru negotiation */
193     {"-p", 0, setpassive},      /* Set passive mode */
194     {"-pc", 0, nopcomp},        /* Disable protocol field compress */
195     {"+ua", 1, setupapfile},    /* Get PAP user and password from file */
196     {"+pap", 0, reqpap},        /* Require PAP auth from peer */
197     {"-pap", 0, nopap},         /* Don't allow UPAP authentication with peer */
198     {"+chap", 0, reqchap},      /* Require CHAP authentication from peer */
199     {"-chap", 0, nochap},       /* Don't allow CHAP authentication with peer */
200     {"-vj", 0, setnovj},        /* disable VJ compression */
201     {"-vjccomp", 0, setnovjccomp}, /* disable VJ connection-ID compression */
202     {"vj-max-slots", 1, setvjslots}, /* Set maximum VJ header slots */
203     {"asyncmap", 1, setasyncmap}, /* set the desired async map */
204     {"escape", 1, setescape},   /* set chars to escape on transmission */
205     {"connect", 1, setconnector}, /* A program to set up a connection */
206     {"disconnect", 1, setdisconnector}, /* program to disconnect serial dev. */
207     {"crtscts", 0, setcrtscts}, /* set h/w flow control */
208     {"-crtscts", 0, setnocrtscts}, /* clear h/w flow control */
209     {"xonxoff", 0, setxonxoff}, /* set s/w flow control */
210     {"debug", 0, setdebug},     /* Increase debugging level */
211     {"kdebug", 1, setkdebug},   /* Enable kernel-level debugging */
212     {"domain", 1, setdomain},   /* Add given domain name to hostname*/
213     {"mru", 1, setmru},         /* Set MRU value for negotiation */
214     {"mtu", 1, setmtu},         /* Set our MTU */
215     {"netmask", 1, setnetmask}, /* set netmask */
216     {"passive", 0, setpassive}, /* Set passive mode */
217     {"silent", 0, setsilent},   /* Set silent mode */
218     {"modem", 0, setmodem},     /* Use modem control lines */
219     {"local", 0, setlocal},     /* Don't use modem control lines */
220     {"lock", 0, setlock},       /* Lock serial device (with lock file) */
221     {"name", 1, setname},       /* Set local name for authentication */
222     {"user", 1, setuser},       /* Set username for PAP auth with peer */
223     {"usehostname", 0, setusehostname}, /* Must use hostname for auth. */
224     {"remotename", 1, setremote}, /* Set remote name for authentication */
225     {"auth", 0, setauth},       /* Require authentication from peer */
226     {"file", 1, readfile},      /* Take options from a file */
227     {"defaultroute", 0, setdefaultroute}, /* Add default route */
228     {"-defaultroute", 0, setnodefaultroute}, /* disable defaultroute option */
229     {"proxyarp", 0, setproxyarp}, /* Add proxy ARP entry */
230     {"-proxyarp", 0, setnoproxyarp}, /* disable proxyarp option */
231     {"persist", 0, setpersist}, /* Keep on reopening connection after close */
232     {"demand", 0, setdemand},   /* Dial on demand */
233     {"login", 0, setdologin},   /* Use system password database for UPAP */
234     {"noipdefault", 0, setnoipdflt}, /* Don't use name for default IP adrs */
235     {"lcp-echo-failure", 1, setlcpechofails}, /* consecutive echo failures */
236     {"lcp-echo-interval", 1, setlcpechointv}, /* time for lcp echo events */
237     {"lcp-restart", 1, setlcptimeout}, /* Set timeout for LCP */
238     {"lcp-max-terminate", 1, setlcpterm}, /* Set max #xmits for term-reqs */
239     {"lcp-max-configure", 1, setlcpconf}, /* Set max #xmits for conf-reqs */
240     {"lcp-max-failure", 1, setlcpfails}, /* Set max #conf-naks for LCP */
241     {"ipcp-restart", 1, setipcptimeout}, /* Set timeout for IPCP */
242     {"ipcp-max-terminate", 1, setipcpterm}, /* Set max #xmits for term-reqs */
243     {"ipcp-max-configure", 1, setipcpconf}, /* Set max #xmits for conf-reqs */
244     {"ipcp-max-failure", 1, setipcpfails}, /* Set max #conf-naks for IPCP */
245     {"pap-restart", 1, setpaptimeout}, /* Set timeout for UPAP */
246     {"pap-max-authreq", 1, setpapreqs}, /* Set max #xmits for auth-reqs */
247     {"chap-restart", 1, setchaptimeout}, /* Set timeout for CHAP */
248     {"chap-max-challenge", 1, setchapchal}, /* Set max #xmits for challenge */
249     {"chap-interval", 1, setchapintv}, /* Set interval for rechallenge */
250     {"ipcp-accept-local", 0, setipcpaccl}, /* Accept peer's address for us */
251     {"ipcp-accept-remote", 0, setipcpaccr}, /* Accept peer's address for it */
252     {"bsdcomp", 1, setbsdcomp},         /* request BSD-Compress */
253     {"-bsdcomp", 0, setnobsdcomp},      /* don't allow BSD-Compress */
254     {"ipparam", 1, setipparam},         /* set ip script parameter */
255     {"papcrypt", 0, setpapcrypt},       /* PAP passwords encrypted */
256     {"idle", 1, setidle},               /* idle time limit (seconds) */
257     {"holdoff", 1, setholdoff},         /* set holdoff time (seconds) */
258     {NULL, 0, NULL}
259 };
260
261
262 #ifndef IMPLEMENTATION
263 #define IMPLEMENTATION ""
264 #endif
265
266 static char *usage_string = "\
267 pppd version %s patch level %d%s\n\
268 Usage: %s [ arguments ], where arguments are:\n\
269         <device>        Communicate over the named device\n\
270         <speed>         Set the baud rate to <speed>\n\
271         <loc>:<rem>     Set the local and/or remote interface IP\n\
272                         addresses.  Either one may be omitted.\n\
273         asyncmap <n>    Set the desired async map to hex <n>\n\
274         auth            Require authentication from peer\n\
275         connect <p>     Invoke shell command <p> to set up the serial line\n\
276         crtscts         Use hardware RTS/CTS flow control\n\
277         defaultroute    Add default route through interface\n\
278         file <f>        Take options from file <f>\n\
279         modem           Use modem control lines\n\
280         mru <n>         Set MRU value to <n> for negotiation\n\
281         netmask <n>     Set interface netmask to <n>\n\
282 See pppd(8) for more options.\n\
283 ";
284
285
286 /*
287  * parse_args - parse a string of arguments, from the command
288  * line or from a file.
289  */
290 int
291 parse_args(argc, argv)
292     int argc;
293     char **argv;
294 {
295     char *arg, *val;
296     struct cmd *cmdp;
297     int ret;
298
299     while (argc > 0) {
300         arg = *argv++;
301         --argc;
302
303         /*
304          * First see if it's a command.
305          */
306         for (cmdp = cmds; cmdp->cmd_name; cmdp++)
307             if (!strcmp(arg, cmdp->cmd_name))
308                 break;
309
310         if (cmdp->cmd_name != NULL) {
311             if (argc < cmdp->num_args) {
312                 fprintf(stderr, "Too few parameters for command %s\n", arg);
313                 return 0;
314             }
315             if (!(*cmdp->cmd_func)(argv))
316                 return 0;
317             argc -= cmdp->num_args;
318             argv += cmdp->num_args;
319
320         } else {
321             /*
322              * Maybe a tty name, speed or IP address?
323              */
324             if ((ret = setdevname(arg)) == 0
325                 && (ret = setspeed(arg)) == 0
326                 && (ret = setipaddr(arg)) == 0) {
327                 fprintf(stderr, "%s: unrecognized command\n", arg);
328                 usage();
329                 return 0;
330             }
331             if (ret < 0)        /* error */
332                 return 0;
333         }
334     }
335     return 1;
336 }
337
338 /*
339  * usage - print out a message telling how to use the program.
340  */
341 void
342 usage()
343 {
344     fprintf(stderr, usage_string, VERSION, PATCHLEVEL, IMPLEMENTATION,
345             progname);
346 }
347
348 /*
349  * options_from_file - Read a string of options from a file,
350  * and interpret them.
351  */
352 int
353 options_from_file(filename, must_exist, check_prot)
354     char *filename;
355     int must_exist;
356     int check_prot;
357 {
358     FILE *f;
359     int i, newline, ret;
360     struct cmd *cmdp;
361     char *argv[MAXARGS];
362     char args[MAXARGS][MAXWORDLEN];
363     char cmd[MAXWORDLEN];
364
365     if ((f = fopen(filename, "r")) == NULL) {
366         if (!must_exist && errno == ENOENT)
367             return 1;
368         perror(filename);
369         return 0;
370     }
371     if (check_prot && !readable(fileno(f))) {
372         fprintf(stderr, "%s: access denied\n", filename);
373         fclose(f);
374         return 0;
375     }
376
377     while (getword(f, cmd, &newline, filename)) {
378         /*
379          * First see if it's a command.
380          */
381         for (cmdp = cmds; cmdp->cmd_name; cmdp++)
382             if (!strcmp(cmd, cmdp->cmd_name))
383                 break;
384
385         if (cmdp->cmd_name != NULL) {
386             for (i = 0; i < cmdp->num_args; ++i) {
387                 if (!getword(f, args[i], &newline, filename)) {
388                     fprintf(stderr,
389                             "In file %s: too few parameters for command %s\n",
390                             filename, cmd);
391                     fclose(f);
392                     return 0;
393                 }
394                 argv[i] = args[i];
395             }
396             if (!(*cmdp->cmd_func)(argv)) {
397                 fclose(f);
398                 return 0;
399             }
400
401         } else {
402             /*
403              * Maybe a tty name, speed or IP address?
404              */
405             if ((ret = setdevname(cmd)) == 0
406                 && (ret = setspeed(cmd)) == 0
407                 && (ret = setipaddr(cmd)) == 0) {
408                 fprintf(stderr, "In file %s: unrecognized command %s\n",
409                         filename, cmd);
410                 fclose(f);
411                 return 0;
412             }
413             if (ret < 0)        /* error */
414                 return 0;
415         }
416     }
417     return 1;
418 }
419
420 /*
421  * options_from_user - See if the use has a ~/.ppprc file,
422  * and if so, interpret options from it.
423  */
424 int
425 options_from_user()
426 {
427     char *user, *path, *file;
428     int ret;
429     struct passwd *pw;
430
431     pw = getpwuid(getuid());
432     if (pw == NULL || (user = pw->pw_dir) == NULL || user[0] == 0)
433         return 1;
434     file = _PATH_USEROPT;
435     path = malloc(strlen(user) + strlen(file) + 2);
436     if (path == NULL)
437         novm("init file name");
438     strcpy(path, user);
439     strcat(path, "/");
440     strcat(path, file);
441     ret = options_from_file(path, 0, 1);
442     free(path);
443     return ret;
444 }
445
446 /*
447  * options_for_tty - See if an options file exists for the serial
448  * device, and if so, interpret options from it.
449  */
450 int
451 options_for_tty()
452 {
453     char *dev, *path;
454     int ret;
455
456     dev = strrchr(devnam, '/');
457     if (dev == NULL)
458         dev = devnam;
459     else
460         ++dev;
461     if (strcmp(dev, "tty") == 0)
462         return 1;               /* don't look for /etc/ppp/options.tty */
463     path = malloc(strlen(_PATH_TTYOPT) + strlen(dev) + 1);
464     if (path == NULL)
465         novm("tty init file name");
466     strcpy(path, _PATH_TTYOPT);
467     strcat(path, dev);
468     ret = options_from_file(path, 0, 0);
469     free(path);
470     return ret;
471 }
472
473 /*
474  * readable - check if a file is readable by the real user.
475  */
476 static int
477 readable(fd)
478     int fd;
479 {
480     uid_t uid;
481     int ngroups, i;
482     struct stat sbuf;
483     GIDSET_TYPE groups[NGROUPS_MAX];
484
485     uid = getuid();
486     if (uid == 0)
487         return 1;
488     if (fstat(fd, &sbuf) != 0)
489         return 0;
490     if (sbuf.st_uid == uid)
491         return sbuf.st_mode & S_IRUSR;
492     if (sbuf.st_gid == getgid())
493         return sbuf.st_mode & S_IRGRP;
494     ngroups = getgroups(NGROUPS_MAX, groups);
495     for (i = 0; i < ngroups; ++i)
496         if (sbuf.st_gid == groups[i])
497             return sbuf.st_mode & S_IRGRP;
498     return sbuf.st_mode & S_IROTH;
499 }
500
501 /*
502  * Read a word from a file.
503  * Words are delimited by white-space or by quotes (").
504  * Quotes, white-space and \ may be escaped with \.
505  * \<newline> is ignored.
506  */
507 int
508 getword(f, word, newlinep, filename)
509     FILE *f;
510     char *word;
511     int *newlinep;
512     char *filename;
513 {
514     int c, len, escape;
515     int quoted;
516
517     *newlinep = 0;
518     len = 0;
519     escape = 0;
520     quoted = 0;
521
522     /*
523      * First skip white-space and comments
524      */
525     while ((c = getc(f)) != EOF) {
526         if (c == '\\') {
527             /*
528              * \<newline> is ignored; \ followed by anything else
529              * starts a word.
530              */
531             if ((c = getc(f)) == '\n')
532                 continue;
533             word[len++] = '\\';
534             escape = 1;
535             break;
536         }
537         if (c == '\n')
538             *newlinep = 1;      /* next word starts a line */
539         else if (c == '#') {
540             /* comment - ignore until EOF or \n */
541             while ((c = getc(f)) != EOF && c != '\n')
542                 ;
543             if (c == EOF)
544                 break;
545             *newlinep = 1;
546         } else if (!isspace(c))
547             break;
548     }
549
550     /*
551      * End of file or error - fail
552      */
553     if (c == EOF) {
554         if (ferror(f)) {
555             perror(filename);
556             die(1);
557         }
558         return 0;
559     }
560
561     for (;;) {
562         /*
563          * Is this character escaped by \ ?
564          */
565         if (escape) {
566             if (c == '\n')
567                 --len;                  /* ignore \<newline> */
568             else if (c == '"' || isspace(c) || c == '\\')
569                 word[len-1] = c;        /* put special char in word */
570             else {
571                 if (len < MAXWORDLEN-1)
572                     word[len] = c;
573                 ++len;
574             }
575             escape = 0;
576         } else if (c == '"') {
577             quoted = !quoted;
578         } else if (!quoted && (isspace(c) || c == '#')) {
579             ungetc(c, f);
580             break;
581         } else {
582             if (len < MAXWORDLEN-1)
583                 word[len] = c;
584             ++len;
585             if (c == '\\')
586                 escape = 1;
587         }
588         if ((c = getc(f)) == EOF)
589             break;
590     }
591
592     if (ferror(f)) {
593         perror(filename);
594         die(1);
595     }
596
597     if (len >= MAXWORDLEN) {
598         word[MAXWORDLEN-1] = 0;
599         fprintf(stderr, "%s: warning: word in file %s too long (%.20s...)\n",
600                 progname, filename, word);
601     } else
602         word[len] = 0;
603
604     return 1;
605 }
606
607 /*
608  * number_option - parse a numeric parameter for an option
609  */
610 static int
611 number_option(str, valp, base)
612     char *str;
613     long *valp;
614     int base;
615 {
616     char *ptr;
617
618     *valp = strtol(str, &ptr, base);
619     if (ptr == str) {
620         fprintf(stderr, "%s: invalid number: %s\n", progname, str);
621         return 0;
622     }
623     return 1;
624 }
625
626
627 /*
628  * int_option - like number_option, but valp is int *,
629  * the base is assumed to be 0, and *valp is not changed
630  * if there is an error.
631  */
632 static int
633 int_option(str, valp)
634     char *str;
635     int *valp;
636 {
637     long v;
638
639     if (!number_option(str, &v, 0))
640         return 0;
641     *valp = (int) v;
642     return 1;
643 }
644
645
646 /*
647  * The following procedures execute commands.
648  */
649
650 /*
651  * readfile - take commands from a file.
652  */
653 static int
654 readfile(argv)
655     char **argv;
656 {
657     return options_from_file(*argv, 1, 1);
658 }
659
660 /*
661  * setdebug - Set debug (command line argument).
662  */
663 static int
664 setdebug()
665 {
666     debug++;
667     return (1);
668 }
669
670 /*
671  * setkdebug - Set kernel debugging level.
672  */
673 static int
674 setkdebug(argv)
675     char **argv;
676 {
677     return int_option(*argv, &kdebugflag);
678 }
679
680 /*
681  * noopt - Disable all options.
682  */
683 static int
684 noopt()
685 {
686     BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options));
687     BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options));
688     BZERO((char *) &ipcp_wantoptions[0], sizeof (struct ipcp_options));
689     BZERO((char *) &ipcp_allowoptions[0], sizeof (struct ipcp_options));
690     return (1);
691 }
692
693 /*
694  * noaccomp - Disable Address/Control field compression negotiation.
695  */
696 static int
697 noaccomp()
698 {
699     lcp_wantoptions[0].neg_accompression = 0;
700     lcp_allowoptions[0].neg_accompression = 0;
701     return (1);
702 }
703
704
705 /*
706  * noasyncmap - Disable async map negotiation.
707  */
708 static int
709 noasyncmap()
710 {
711     lcp_wantoptions[0].neg_asyncmap = 0;
712     lcp_allowoptions[0].neg_asyncmap = 0;
713     return (1);
714 }
715
716
717 /*
718  * noipaddr - Disable IP address negotiation.
719  */
720 static int
721 noipaddr()
722 {
723     ipcp_wantoptions[0].neg_addr = 0;
724     ipcp_allowoptions[0].neg_addr = 0;
725     return (1);
726 }
727
728
729 /*
730  * nomagicnumber - Disable magic number negotiation.
731  */
732 static int
733 nomagicnumber()
734 {
735     lcp_wantoptions[0].neg_magicnumber = 0;
736     lcp_allowoptions[0].neg_magicnumber = 0;
737     return (1);
738 }
739
740
741 /*
742  * nomru - Disable mru negotiation.
743  */
744 static int
745 nomru()
746 {
747     lcp_wantoptions[0].neg_mru = 0;
748     lcp_allowoptions[0].neg_mru = 0;
749     return (1);
750 }
751
752
753 /*
754  * setmru - Set MRU for negotiation.
755  */
756 static int
757 setmru(argv)
758     char **argv;
759 {
760     long mru;
761
762     if (!number_option(*argv, &mru, 0))
763         return 0;
764     lcp_wantoptions[0].mru = mru;
765     lcp_wantoptions[0].neg_mru = 1;
766     return (1);
767 }
768
769
770 /*
771  * setmru - Set the largest MTU we'll use.
772  */
773 static int
774 setmtu(argv)
775     char **argv;
776 {
777     long mtu;
778
779     if (!number_option(*argv, &mtu, 0))
780         return 0;
781     if (mtu < MINMRU || mtu > MAXMRU) {
782         fprintf(stderr, "mtu option value of %ld is too %s\n", mtu,
783                 (mtu < MINMRU? "small": "large"));
784         return 0;
785     }
786     lcp_allowoptions[0].mru = mtu;
787     return (1);
788 }
789
790
791 /*
792  * nopcomp - Disable Protocol field compression negotiation.
793  */
794 static int
795 nopcomp()
796 {
797     lcp_wantoptions[0].neg_pcompression = 0;
798     lcp_allowoptions[0].neg_pcompression = 0;
799     return (1);
800 }
801
802
803 /*
804  * setpassive - Set passive mode (don't give up if we time out sending
805  * LCP configure-requests).
806  */
807 static int
808 setpassive()
809 {
810     lcp_wantoptions[0].passive = 1;
811     return (1);
812 }
813
814
815 /*
816  * setsilent - Set silent mode (don't start sending LCP configure-requests
817  * until we get one from the peer).
818  */
819 static int
820 setsilent()
821 {
822     lcp_wantoptions[0].silent = 1;
823     return 1;
824 }
825
826
827 /*
828  * nopap - Disable PAP authentication with peer.
829  */
830 static int
831 nopap()
832 {
833     lcp_allowoptions[0].neg_upap = 0;
834     return (1);
835 }
836
837
838 /*
839  * reqpap - Require PAP authentication from peer.
840  */
841 static int
842 reqpap()
843 {
844     lcp_wantoptions[0].neg_upap = 1;
845     auth_required = 1;
846     return 1;
847 }
848
849
850 /*
851  * setupapfile - specifies UPAP info for authenticating with peer.
852  */
853 static int
854 setupapfile(argv)
855     char **argv;
856 {
857     FILE * ufile;
858     int l;
859
860     lcp_allowoptions[0].neg_upap = 1;
861
862     /* open user info file */
863     if ((ufile = fopen(*argv, "r")) == NULL) {
864         fprintf(stderr, "unable to open user login data file %s\n", *argv);
865         return 0;
866     }
867     if (!readable(fileno(ufile))) {
868         fprintf(stderr, "%s: access denied\n", *argv);
869         return 0;
870     }
871     check_access(ufile, *argv);
872
873     /* get username */
874     if (fgets(user, MAXNAMELEN - 1, ufile) == NULL
875         || fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){
876         fprintf(stderr, "Unable to read user login data file %s.\n", *argv);
877         return 0;
878     }
879     fclose(ufile);
880
881     /* get rid of newlines */
882     l = strlen(user);
883     if (l > 0 && user[l-1] == '\n')
884         user[l-1] = 0;
885     l = strlen(passwd);
886     if (l > 0 && passwd[l-1] == '\n')
887         passwd[l-1] = 0;
888
889     return (1);
890 }
891
892
893 /*
894  * nochap - Disable CHAP authentication with peer.
895  */
896 static int
897 nochap()
898 {
899     lcp_allowoptions[0].neg_chap = 0;
900     return (1);
901 }
902
903
904 /*
905  * reqchap - Require CHAP authentication from peer.
906  */
907 static int
908 reqchap()
909 {
910     lcp_wantoptions[0].neg_chap = 1;
911     auth_required = 1;
912     return (1);
913 }
914
915
916 /*
917  * setnovj - disable vj compression
918  */
919 static int
920 setnovj()
921 {
922     ipcp_wantoptions[0].neg_vj = 0;
923     ipcp_allowoptions[0].neg_vj = 0;
924     return (1);
925 }
926
927
928 /*
929  * setnovjccomp - disable VJ connection-ID compression
930  */
931 static int
932 setnovjccomp()
933 {
934     ipcp_wantoptions[0].cflag = 0;
935     ipcp_allowoptions[0].cflag = 0;
936     return 1;
937 }
938
939
940 /*
941  * setvjslots - set maximum number of connection slots for VJ compression
942  */
943 static int
944 setvjslots(argv)
945     char **argv;
946 {
947     int value;
948
949     if (!int_option(*argv, &value))
950         return 0;
951     if (value < 2 || value > 16) {
952         fprintf(stderr, "pppd: vj-max-slots value must be between 2 and 16\n");
953         return 0;
954     }
955     ipcp_wantoptions [0].maxslotindex =
956         ipcp_allowoptions[0].maxslotindex = value - 1;
957     return 1;
958 }
959
960
961 /*
962  * setconnector - Set a program to connect to a serial line
963  */
964 static int
965 setconnector(argv)
966     char **argv;
967 {
968     connector = strdup(*argv);
969     if (connector == NULL)
970         novm("connector string");
971   
972     return (1);
973 }
974
975 /*
976  * setdisconnector - Set a program to disconnect from the serial line
977  */
978 static int
979 setdisconnector(argv)
980     char **argv;
981 {
982     disconnector = strdup(*argv);
983     if (disconnector == NULL)
984         novm("disconnector string");
985   
986     return (1);
987 }
988
989
990 /*
991  * setdomain - Set domain name to append to hostname 
992  */
993 static int
994 setdomain(argv)
995     char **argv;
996 {
997     strncat(hostname, *argv, MAXNAMELEN - strlen(hostname));
998     hostname[MAXNAMELEN-1] = 0;
999     return (1);
1000 }
1001
1002
1003 /*
1004  * setasyncmap - add bits to asyncmap (what we request peer to escape).
1005  */
1006 static int
1007 setasyncmap(argv)
1008     char **argv;
1009 {
1010     long asyncmap;
1011
1012     if (!number_option(*argv, &asyncmap, 16))
1013         return 0;
1014     lcp_wantoptions[0].asyncmap |= asyncmap;
1015     lcp_wantoptions[0].neg_asyncmap = 1;
1016     return(1);
1017 }
1018
1019
1020 /*
1021  * setescape - add chars to the set we escape on transmission.
1022  */
1023 static int
1024 setescape(argv)
1025     char **argv;
1026 {
1027     int n, ret;
1028     char *p, *endp;
1029
1030     p = *argv;
1031     ret = 1;
1032     while (*p) {
1033         n = strtol(p, &endp, 16);
1034         if (p == endp) {
1035             fprintf(stderr, "%s: invalid hex number: %s\n", progname, p);
1036             return 0;
1037         }
1038         p = endp;
1039         if (n < 0 || 0x20 <= n && n <= 0x3F || n == 0x5E || n > 0xFF) {
1040             fprintf(stderr, "%s: can't escape character 0x%x\n", progname, n);
1041             ret = 0;
1042         } else
1043             xmit_accm[0][n >> 5] |= 1 << (n & 0x1F);
1044         while (*p == ',' || *p == ' ')
1045             ++p;
1046     }
1047     return ret;
1048 }
1049
1050
1051 /*
1052  * setspeed - Set the speed.
1053  */
1054 static int
1055 setspeed(arg)
1056     char *arg;
1057 {
1058     char *ptr;
1059     int spd;
1060
1061     spd = strtol(arg, &ptr, 0);
1062     if (ptr == arg || *ptr != 0 || spd == 0)
1063         return 0;
1064     inspeed = spd;
1065     return 1;
1066 }
1067
1068
1069 /*
1070  * setdevname - Set the device name.
1071  */
1072 int
1073 setdevname(cp)
1074     char *cp;
1075 {
1076     struct stat statbuf;
1077     char *tty, *ttyname();
1078     char dev[MAXPATHLEN];
1079   
1080     if (strncmp("/dev/", cp, 5) != 0) {
1081         strcpy(dev, "/dev/");
1082         strncat(dev, cp, MAXPATHLEN - 5);
1083         dev[MAXPATHLEN-1] = 0;
1084         cp = dev;
1085     }
1086
1087     /*
1088      * Check if there is a device by this name.
1089      */
1090     if (stat(cp, &statbuf) < 0) {
1091         if (errno == ENOENT)
1092             return 0;
1093         syslog(LOG_ERR, cp);
1094         return -1;
1095     }
1096   
1097     (void) strncpy(devnam, cp, MAXPATHLEN);
1098     devnam[MAXPATHLEN-1] = 0;
1099     default_device = FALSE;
1100   
1101     return 1;
1102 }
1103
1104
1105 /*
1106  * setipaddr - Set the IP address
1107  */
1108 int
1109 setipaddr(arg)
1110     char *arg;
1111 {
1112     struct hostent *hp;
1113     char *colon;
1114     u_int32_t local, remote;
1115     ipcp_options *wo = &ipcp_wantoptions[0];
1116   
1117     /*
1118      * IP address pair separated by ":".
1119      */
1120     if ((colon = strchr(arg, ':')) == NULL)
1121         return 0;
1122   
1123     /*
1124      * If colon first character, then no local addr.
1125      */
1126     if (colon != arg) {
1127         *colon = '\0';
1128         if ((local = inet_addr(arg)) == -1) {
1129             if ((hp = gethostbyname(arg)) == NULL) {
1130                 fprintf(stderr, "unknown host: %s\n", arg);
1131                 return -1;
1132             } else {
1133                 local = *(u_int32_t *)hp->h_addr;
1134                 if (our_name[0] == 0) {
1135                     strncpy(our_name, arg, MAXNAMELEN);
1136                     our_name[MAXNAMELEN-1] = 0;
1137                 }
1138             }
1139         }
1140         if (bad_ip_adrs(local)) {
1141             fprintf(stderr, "bad local IP address %s\n", ip_ntoa(local));
1142             return -1;
1143         }
1144         if (local != 0)
1145             wo->ouraddr = local;
1146         *colon = ':';
1147     }
1148   
1149     /*
1150      * If colon last character, then no remote addr.
1151      */
1152     if (*++colon != '\0') {
1153         if ((remote = inet_addr(colon)) == -1) {
1154             if ((hp = gethostbyname(colon)) == NULL) {
1155                 fprintf(stderr, "unknown host: %s\n", colon);
1156                 return -1;
1157             } else {
1158                 remote = *(u_int32_t *)hp->h_addr;
1159                 if (remote_name[0] == 0) {
1160                     strncpy(remote_name, colon, MAXNAMELEN);
1161                     remote_name[MAXNAMELEN-1] = 0;
1162                 }
1163             }
1164         }
1165         if (bad_ip_adrs(remote)) {
1166             fprintf(stderr, "bad remote IP address %s\n", ip_ntoa(remote));
1167             return -1;
1168         }
1169         if (remote != 0)
1170             wo->hisaddr = remote;
1171     }
1172
1173     return 1;
1174 }
1175
1176
1177 /*
1178  * setnoipdflt - disable setipdefault()
1179  */
1180 static int
1181 setnoipdflt()
1182 {
1183     disable_defaultip = 1;
1184     return 1;
1185 }
1186
1187
1188 /*
1189  * setipcpaccl - accept peer's idea of our address
1190  */
1191 static int
1192 setipcpaccl()
1193 {
1194     ipcp_wantoptions[0].accept_local = 1;
1195     return 1;
1196 }
1197
1198
1199 /*
1200  * setipcpaccr - accept peer's idea of its address
1201  */
1202 static int
1203 setipcpaccr()
1204 {
1205     ipcp_wantoptions[0].accept_remote = 1;
1206     return 1;
1207 }
1208
1209
1210 /*
1211  * setipdefault - default our local IP address based on our hostname.
1212  */
1213 void
1214 setipdefault()
1215 {
1216     struct hostent *hp;
1217     u_int32_t local;
1218     ipcp_options *wo = &ipcp_wantoptions[0];
1219
1220     /*
1221      * If local IP address already given, don't bother.
1222      */
1223     if (wo->ouraddr != 0 || disable_defaultip)
1224         return;
1225
1226     /*
1227      * Look up our hostname (possibly with domain name appended)
1228      * and take the first IP address as our local IP address.
1229      * If there isn't an IP address for our hostname, too bad.
1230      */
1231     wo->accept_local = 1;       /* don't insist on this default value */
1232     if ((hp = gethostbyname(hostname)) == NULL)
1233         return;
1234     local = *(u_int32_t *)hp->h_addr;
1235     if (local != 0 && !bad_ip_adrs(local))
1236         wo->ouraddr = local;
1237 }
1238
1239
1240 /*
1241  * setnetmask - set the netmask to be used on the interface.
1242  */
1243 static int
1244 setnetmask(argv)
1245     char **argv;
1246 {
1247     u_int32_t mask;
1248
1249     if ((mask = inet_addr(*argv)) == -1 || (netmask & ~mask) != 0) {
1250         fprintf(stderr, "Invalid netmask %s\n", *argv);
1251         return 0;
1252     }
1253
1254     netmask = mask;
1255     return (1);
1256 }
1257
1258 static int
1259 setcrtscts()
1260 {
1261     crtscts = 1;
1262     return (1);
1263 }
1264
1265 static int
1266 setnocrtscts()
1267 {
1268     crtscts = -1;
1269     return (1);
1270 }
1271
1272 static int
1273 setxonxoff()
1274 {
1275     crtscts = 2;
1276     return (1);
1277 }
1278
1279 static int
1280 setnodetach()
1281 {
1282     nodetach = 1;
1283     return (1);
1284 }
1285
1286 static int
1287 setdemand()
1288 {
1289     demand = 1;
1290     return 1;
1291 }
1292
1293 static int
1294 setmodem()
1295 {
1296     modem = 1;
1297     return 1;
1298 }
1299
1300 static int
1301 setlocal()
1302 {
1303     modem = 0;
1304     return 1;
1305 }
1306
1307 static int
1308 setlock()
1309 {
1310     lockflag = 1;
1311     return 1;
1312 }
1313
1314 static int
1315 setusehostname()
1316 {
1317     usehostname = 1;
1318     return 1;
1319 }
1320
1321 static int
1322 setname(argv)
1323     char **argv;
1324 {
1325     if (our_name[0] == 0) {
1326         strncpy(our_name, argv[0], MAXNAMELEN);
1327         our_name[MAXNAMELEN-1] = 0;
1328     }
1329     return 1;
1330 }
1331
1332 static int
1333 setuser(argv)
1334     char **argv;
1335 {
1336     strncpy(user, argv[0], MAXNAMELEN);
1337     user[MAXNAMELEN-1] = 0;
1338     return 1;
1339 }
1340
1341 static int
1342 setremote(argv)
1343     char **argv;
1344 {
1345     strncpy(remote_name, argv[0], MAXNAMELEN);
1346     remote_name[MAXNAMELEN-1] = 0;
1347     return 1;
1348 }
1349
1350 static int
1351 setauth()
1352 {
1353     auth_required = 1;
1354     return 1;
1355 }
1356
1357 static int
1358 setdefaultroute()
1359 {
1360     if (!ipcp_allowoptions[0].default_route) {
1361         fprintf(stderr, "%s: defaultroute option is disabled\n", progname);
1362         return 0;
1363     }
1364     ipcp_wantoptions[0].default_route = 1;
1365     return 1;
1366 }
1367
1368 static int
1369 setnodefaultroute()
1370 {
1371     ipcp_allowoptions[0].default_route = 0;
1372     ipcp_wantoptions[0].default_route = 0;
1373     return 1;
1374 }
1375
1376 static int
1377 setproxyarp()
1378 {
1379     if (!ipcp_allowoptions[0].proxy_arp) {
1380         fprintf(stderr, "%s: proxyarp option is disabled\n", progname);
1381         return 0;
1382     }
1383     ipcp_wantoptions[0].proxy_arp = 1;
1384     return 1;
1385 }
1386
1387 static int
1388 setnoproxyarp()
1389 {
1390     ipcp_wantoptions[0].proxy_arp = 0;
1391     ipcp_allowoptions[0].proxy_arp = 0;
1392     return 1;
1393 }
1394
1395 static int
1396 setpersist()
1397 {
1398     persist = 1;
1399     return 1;
1400 }
1401
1402 static int
1403 setdologin()
1404 {
1405     uselogin = 1;
1406     return 1;
1407 }
1408
1409 /*
1410  * Functions to set the echo interval for modem-less monitors
1411  */
1412
1413 static int
1414 setlcpechointv(argv)
1415     char **argv;
1416 {
1417     return int_option(*argv, &lcp_echo_interval);
1418 }
1419
1420 static int
1421 setlcpechofails(argv)
1422     char **argv;
1423 {
1424     return int_option(*argv, &lcp_echo_fails);
1425 }
1426
1427 /*
1428  * Functions to set timeouts, max transmits, etc.
1429  */
1430 static int
1431 setlcptimeout(argv)
1432     char **argv;
1433 {
1434     return int_option(*argv, &lcp_fsm[0].timeouttime);
1435 }
1436
1437 static int
1438 setlcpterm(argv)
1439     char **argv;
1440 {
1441     return int_option(*argv, &lcp_fsm[0].maxtermtransmits);
1442 }
1443
1444 static int
1445 setlcpconf(argv)
1446     char **argv;
1447 {
1448     return int_option(*argv, &lcp_fsm[0].maxconfreqtransmits);
1449 }
1450
1451 static int
1452 setlcpfails(argv)
1453     char **argv;
1454 {
1455     return int_option(*argv, &lcp_fsm[0].maxnakloops);
1456 }
1457
1458 static int
1459 setipcptimeout(argv)
1460     char **argv;
1461 {
1462     return int_option(*argv, &ipcp_fsm[0].timeouttime);
1463 }
1464
1465 static int
1466 setipcpterm(argv)
1467     char **argv;
1468 {
1469     return int_option(*argv, &ipcp_fsm[0].maxtermtransmits);
1470 }
1471
1472 static int
1473 setipcpconf(argv)
1474     char **argv;
1475 {
1476     return int_option(*argv, &ipcp_fsm[0].maxconfreqtransmits);
1477 }
1478
1479 static int
1480 setipcpfails(argv)
1481     char **argv;
1482 {
1483     return int_option(*argv, &lcp_fsm[0].maxnakloops);
1484 }
1485
1486 static int
1487 setpaptimeout(argv)
1488     char **argv;
1489 {
1490     return int_option(*argv, &upap[0].us_timeouttime);
1491 }
1492
1493 static int
1494 setpapreqs(argv)
1495     char **argv;
1496 {
1497     return int_option(*argv, &upap[0].us_maxtransmits);
1498 }
1499
1500 static int
1501 setchaptimeout(argv)
1502     char **argv;
1503 {
1504     return int_option(*argv, &chap[0].timeouttime);
1505 }
1506
1507 static int
1508 setchapchal(argv)
1509     char **argv;
1510 {
1511     return int_option(*argv, &chap[0].max_transmits);
1512 }
1513
1514 static int
1515 setchapintv(argv)
1516     char **argv;
1517 {
1518     return int_option(*argv, &chap[0].chal_interval);
1519 }
1520
1521 static int
1522 setbsdcomp(argv)
1523     char **argv;
1524 {
1525     int rbits, abits;
1526     char *str, *endp;
1527
1528     str = *argv;
1529     abits = rbits = strtol(str, &endp, 0);
1530     if (endp != str && *endp == ',') {
1531         str = endp + 1;
1532         abits = strtol(str, &endp, 0);
1533     }
1534     if (*endp != 0 || endp == str) {
1535         fprintf(stderr, "%s: invalid argument format for bsdcomp option\n",
1536                 progname);
1537         return 0;
1538     }
1539     if (rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS)
1540         || abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS)) {
1541         fprintf(stderr, "%s: bsdcomp option values must be 0 or %d .. %d\n",
1542                 progname, BSD_MIN_BITS, BSD_MAX_BITS);
1543         return 0;
1544     }
1545     if (rbits > 0) {
1546         ccp_wantoptions[0].bsd_compress = 1;
1547         ccp_wantoptions[0].bsd_bits = rbits;
1548     } else
1549         ccp_wantoptions[0].bsd_compress = 0;
1550     if (abits > 0) {
1551         ccp_allowoptions[0].bsd_compress = 1;
1552         ccp_allowoptions[0].bsd_bits = abits;
1553     } else
1554         ccp_allowoptions[0].bsd_compress = 0;
1555     return 1;
1556 }
1557
1558 static int
1559 setnobsdcomp()
1560 {
1561     ccp_wantoptions[0].bsd_compress = 0;
1562     ccp_allowoptions[0].bsd_compress = 0;
1563     return 1;
1564 }
1565
1566 static int
1567 setipparam(argv)
1568     char **argv;
1569 {
1570     ipparam = strdup(*argv);
1571     if (ipparam == NULL)
1572         novm("ipparam string");
1573
1574     return 1;
1575 }
1576
1577 static int
1578 setpapcrypt()
1579 {
1580     cryptpap = 1;
1581     return 1;
1582 }
1583
1584 static int
1585 setidle(argv)
1586     char **argv;
1587 {
1588     return int_option(*argv, &idle_time_limit);
1589 }
1590
1591 static int
1592 setholdoff(argv)
1593     char **argv;
1594 {
1595     return int_option(*argv, &holdoff);
1596 }