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