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