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