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