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