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