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