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