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