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