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