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