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