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