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