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