add `must_exist' parameter to options_from_file
[ppp.git] / pppd / options.c
1 /*
2  * options.c - handles option processing for PPP.
3  *
4  * Copyright (c) 1989 Carnegie Mellon University.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms are permitted
8  * provided that the above copyright notice and this paragraph are
9  * duplicated in all such forms and that any documentation,
10  * advertising materials, and other materials related to such
11  * distribution and use acknowledge that the software was developed
12  * by Carnegie Mellon University.  The name of the
13  * University may not be used to endorse or promote products derived
14  * from this software without specific prior written permission.
15  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18  */
19
20 #ifndef lint
21 static char rcsid[] = "$Id: options.c,v 1.2 1993/11/23 23:40:53 paulus Exp $";
22 #endif
23
24 #include <stdio.h>
25 #include <errno.h>
26 #include <unistd.h>
27 #include <stdlib.h>
28 #include <termios.h>
29 #include <syslog.h>
30 #include <string.h>
31 #include <netdb.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34
35 #include "ppp.h"
36 #include "pppd.h"
37 #include "pathnames.h"
38 #include "patchlevel.h"
39 #include "fsm.h"
40 #include "lcp.h"
41 #include "ipcp.h"
42 #include "upap.h"
43 #include "chap.h"
44
45 #define FALSE   0
46 #define TRUE    1
47
48
49 /*
50  * Prototypes
51  */
52 static int setdebug __ARGS((void));
53 static int setpassive __ARGS((void));
54 static int setsilent __ARGS((void));
55 static int noopt __ARGS((void));
56 static int setnovj __ARGS((void));
57 static int reqpap __ARGS((void));
58 static int nopap __ARGS((void));
59 static int setupapfile __ARGS((char **));
60 static int nochap __ARGS((void));
61 static int reqchap __ARGS((void));
62 static int setspeed __ARGS((char *));
63 static int noaccomp __ARGS((void));
64 static int noasyncmap __ARGS((void));
65 static int noipaddr __ARGS((void));
66 static int nomagicnumber __ARGS((void));
67 static int setasyncmap __ARGS((char **));
68 static int setmru __ARGS((char **));
69 static int nomru __ARGS((void));
70 static int nopcomp __ARGS((void));
71 static int setconnector __ARGS((char **));
72 static int setdomain __ARGS((char **));
73 static int setnetmask __ARGS((char **));
74 static int setcrtscts __ARGS((void));
75 static int setnodetach __ARGS((void));
76 static int setmodem __ARGS((void));
77 static int setlocal __ARGS((void));
78 static int setname __ARGS((char **));
79 static int setuser __ARGS((char **));
80 static int setremote __ARGS((char **));
81 static int setauth __ARGS((void));
82 static int readfile __ARGS((char **));
83 static int setdefaultroute __ARGS((void));
84 static int setproxyarp __ARGS((void));
85 static int setpersist __ARGS((void));
86 static int setdologin __ARGS((void));
87 static int setusehostname __ARGS((void));
88 static int setlcptimeout __ARGS((char **));
89 static int setlcpterm __ARGS((char **));
90 static int setlcpconf __ARGS((char **));
91 static int setlcpfails __ARGS((char **));
92 static int setipcptimeout __ARGS((char **));
93 static int setipcpterm __ARGS((char **));
94 static int setipcpconf __ARGS((char **));
95 static int setipcpfails __ARGS((char **));
96 static int setpaptimeout __ARGS((char **));
97 static int setpapreqs __ARGS((char **));
98 static int setchaptimeout __ARGS((char **));
99 static int setchapchal __ARGS((char **));
100 static int setchapintv __ARGS((char **));
101
102 static int number_option __ARGS((char *, long *, int));
103
104
105 /*
106  * Option variables
107  */
108 extern char *progname;
109 extern int debug;
110 extern int modem;
111 extern int crtscts;
112 extern int nodetach;
113 extern char *connector;
114 extern int inspeed;
115 extern char devname[];
116 extern int default_device;
117 extern u_long netmask;
118 extern int detach;
119 extern char user[];
120 extern char passwd[];
121 extern int auth_required;
122 extern int proxyarp;
123 extern int persist;
124 extern int uselogin;
125 extern char our_name[];
126 extern char remote_name[];
127 int usehostname;
128
129 /*
130  * Valid arguments.
131  */
132 static struct cmd {
133     char *cmd_name;
134     int num_args;
135     int (*cmd_func)();
136 } cmds[] = {
137     "-all", 0, noopt,           /* Don't request/allow any options */
138     "-ac", 0, noaccomp,         /* Disable Address/Control compress */
139     "-am", 0, noasyncmap,       /* Disable asyncmap negotiation */
140     "-as", 1, setasyncmap,      /* set the desired async map */
141     "-d", 0, setdebug,          /* Increase debugging level */
142     "-detach", 0, setnodetach,  /* don't fork */
143     "-ip", 0, noipaddr,         /* Disable IP address negotiation */
144     "-mn", 0, nomagicnumber,    /* Disable magic number negotiation */
145     "-mru", 0, nomru,           /* Disable mru negotiation */
146     "-p", 0, setpassive,        /* Set passive mode */
147     "-pc", 0, nopcomp,          /* Disable protocol field compress */
148     "+ua", 1, setupapfile,      /* Get PAP user and password from file */
149     "+pap", 0, reqpap,          /* Require PAP auth from peer */
150     "-pap", 0, nopap,           /* Don't allow UPAP authentication with peer */
151     "+chap", 0, reqchap,        /* Require CHAP authentication from peer */
152     "-chap", 0, nochap,         /* Don't allow CHAP authentication with peer */
153     "-vj", 0, setnovj,          /* disable VJ compression */
154     "asyncmap", 1, setasyncmap, /* set the desired async map */
155     "connect", 1, setconnector, /* A program to set up a connection */
156     "crtscts", 0, setcrtscts,   /* set h/w flow control */
157     "debug", 0, setdebug,       /* Increase debugging level */
158     "domain", 1, setdomain,     /* Add given domain name to hostname*/
159     "mru", 1, setmru,           /* Set MRU value for negotiation */
160     "netmask", 1, setnetmask,   /* set netmask */
161     "passive", 0, setpassive,   /* Set passive mode */
162     "silent", 0, setsilent,     /* Set silent mode */
163     "modem", 0, setmodem,       /* Use modem control lines */
164     "local", 0, setlocal,       /* Don't use modem control lines */
165     "name", 1, setname,         /* Set local name for authentication */
166     "user", 1, setuser,         /* Set username for PAP auth with peer */
167     "usehostname", 0, setusehostname,   /* Must use hostname for auth. */
168     "remotename", 1, setremote, /* Set remote name for authentication */
169     "auth", 0, setauth,         /* Require authentication from peer */
170     "file", 1, readfile,        /* Take options from a file */
171     "defaultroute", 0, setdefaultroute, /* Add default route */
172     "proxyarp", 0, setproxyarp, /* Add proxy ARP entry */
173     "persist", 0, setpersist,   /* Keep on reopening connection after close */
174     "login", 0, setdologin,     /* Use system password database for UPAP */
175     "lcp-restart", 1, setlcptimeout,    /* Set timeout for LCP */
176     "lcp-max-terminate", 1, setlcpterm, /* Set max #xmits for term-reqs */
177     "lcp-max-configure", 1, setlcpconf, /* Set max #xmits for conf-reqs */
178     "lcp-max-failure", 1, setlcpfails,  /* Set max #conf-naks for LCP */
179     "ipcp-restart", 1, setipcptimeout,  /* Set timeout for IPCP */
180     "ipcp-max-terminate", 1, setipcpterm, /* Set max #xmits for term-reqs */
181     "ipcp-max-configure", 1, setipcpconf, /* Set max #xmits for conf-reqs */
182     "ipcp-max-failure", 1, setipcpfails,  /* Set max #conf-naks for IPCP */
183     "pap-restart", 1, setpaptimeout,    /* Set timeout for UPAP */
184     "pap-max-authreq", 1, setpapreqs,   /* Set max #xmits for auth-reqs */
185     "chap-restart", 1, setchaptimeout,  /* Set timeout for CHAP */
186     "chap-max-challenge", 1, setchapchal, /* Set max #xmits for challenge */
187     "chap-interval", 1, setchapintv,    /* Set interval for rechallenge */
188     NULL
189 };
190
191
192 static char *usage_string = "\
193 pppd version %s patch level %d\n\
194 Usage: %s [ arguments ], where arguments are:\n\
195         <device>        Communicate over the named device\n\
196         <speed>         Set the baud rate to <speed>\n\
197         <loc>:<rem>     Set the local and/or remote interface IP\n\
198                         addresses.  Either one may be omitted.\n\
199         asyncmap <n>    Set the desired async map to hex <n>\n\
200         auth            Require authentication from peer\n\
201         connect <p>     Invoke shell command <p> to set up the serial line\n\
202         crtscts         Use hardware RTS/CTS flow control\n\
203         defaultroute    Add default route through interface\n\
204         file <f>        Take options from file <f>\n\
205         modem           Use modem control lines\n\
206         mru <n>         Set MRU value to <n> for negotiation\n\
207         netmask <n>     Set interface netmask to <n>\n\
208 See pppd(8) for more options.\n\
209 ";
210
211 /*
212 Options omitted:
213         -all            Don't request/allow any options\n\
214         -ac             Disable Address/Control compression\n\
215         -am             Disable asyncmap negotiation\n\
216         -as <n>         Set the desired async map to hex <n>\n\
217         -d              Increase debugging level\n\
218         -detach         Don't fork to background\n\
219         -ip             Disable IP address negotiation\n\
220         -mn             Disable magic number negotiation\n\
221         -mru            Disable mru negotiation\n\
222         -p              Set passive mode\n\
223         -pc             Disable protocol field compression\n\
224         +ua <f>         Get username and password for authenticating\n\
225                         with peer using PAP from file <f>\n\
226         +pap            Require PAP authentication from peer\n\
227         -pap            Don't agree to authenticating with peer using PAP\n\
228         +chap           Require CHAP authentication from peer\n\
229         -chap           Don't agree to authenticating with peer using CHAP\n\
230         -vj             disable VJ compression\n\
231         -auth           Don't agree to authenticate with peer\n\
232         debug           Increase debugging level\n\
233         domain <d>      Append domain name <d> to hostname for authentication\n\
234         passive         Set passive mode\n\
235         local           Don't use modem control lines\n\
236         proxyarp        Add proxy ARP entry\n\
237 */
238
239
240 /*
241  * parse_args - parse a string of arguments, from the command
242  * line or from a file.
243  */
244 int
245 parse_args(argc, argv)
246     int argc;
247     char **argv;
248 {
249     char *arg, *val;
250     struct cmd *cmdp;
251
252     while (argc > 0) {
253         arg = *argv++;
254         --argc;
255
256         /*
257          * First see if it's a command.
258          */
259         for (cmdp = cmds; cmdp->cmd_name; cmdp++)
260             if (!strcmp(arg, cmdp->cmd_name))
261                 break;
262
263         if (cmdp->cmd_name != NULL) {
264             if (argc < cmdp->num_args) {
265                 fprintf(stderr, "Too few parameters for command %s\n", arg);
266                 return 0;
267             }
268             if (!(*cmdp->cmd_func)(argv))
269                 return 0;
270             argc -= cmdp->num_args;
271             argv += cmdp->num_args;
272
273         } else {
274             /*
275              * Maybe a tty name, speed or IP address?
276              */
277             if (!setdevname(arg) && !setspeed(arg) && !setipaddr(arg)) {
278                 fprintf(stderr, "%s: unrecognized command\n", arg);
279                 usage();
280                 return 0;
281             }
282         }
283     }
284     return 1;
285 }
286
287 /*
288  * usage - print out a message telling how to use the program.
289  */
290 usage()
291 {
292     fprintf(stderr, usage_string, VERSION, PATCHLEVEL, progname);
293 }
294
295 /*
296  * options_from_file - Read a string of options from a file,
297  * and interpret them.
298  */
299 int
300 options_from_file(filename, must_exist)
301     char *filename;
302     int must_exist;
303 {
304     FILE *f;
305     int i, newline;
306     struct cmd *cmdp;
307     char *argv[MAXARGS];
308     char args[MAXARGS][MAXWORDLEN];
309     char cmd[MAXWORDLEN];
310
311     if ((f = fopen(filename, "r")) == NULL) {
312         if (!must_exist && errno == ENOENT)
313             return 1;
314         perror(filename);
315         exit(1);
316     }
317     while (getword(f, cmd, &newline, filename)) {
318         /*
319          * First see if it's a command.
320          */
321         for (cmdp = cmds; cmdp->cmd_name; cmdp++)
322             if (!strcmp(cmd, cmdp->cmd_name))
323                 break;
324
325         if (cmdp->cmd_name != NULL) {
326             for (i = 0; i < cmdp->num_args; ++i) {
327                 if (!getword(f, args[i], &newline, filename)) {
328                     fprintf(stderr,
329                             "In file %s: too few parameters for command %s\n",
330                             filename, cmd);
331                     fclose(f);
332                     return 0;
333                 }
334                 argv[i] = args[i];
335             }
336             if (!(*cmdp->cmd_func)(argv)) {
337                 fclose(f);
338                 return 0;
339             }
340
341         } else {
342             /*
343              * Maybe a tty name, speed or IP address?
344              */
345             if (!setdevname(cmd) && !setspeed(cmd) && !setipaddr(cmd)) {
346                 fprintf(stderr, "In file %s: unrecognized command %s\n",
347                         filename, cmd);
348                 fclose(f);
349                 return 0;
350             }
351         }
352     }
353     return 1;
354 }
355
356 /*
357  * options_from_user - See if the use has a ~/.ppprc file,
358  * and if so, interpret options from it.
359  */
360 int
361 options_from_user()
362 {
363     char *user, *path, *file;
364     int ret;
365
366     if ((user = getenv("HOME")) == NULL)
367         return;
368     file = "/.ppprc";
369     path = malloc(strlen(user) + strlen(file) + 1);
370     if (path == NULL)
371         novm("init file name");
372     strcpy(path, user);
373     strcat(path, file);
374     ret = options_from_file(path, 0);
375     free(path);
376     return ret;
377 }
378
379 /*
380  * Read a word from a file.
381  * Words are delimited by white-space or by quotes (").
382  * Quotes, white-space and \ may be escaped with \.
383  * \<newline> is ignored.
384  */
385 int
386 getword(f, word, newlinep, filename)
387     FILE *f;
388     char *word;
389     int *newlinep;
390     char *filename;
391 {
392     int c, len, escape;
393     int quoted;
394
395     *newlinep = 0;
396     len = 0;
397     escape = 0;
398     quoted = 0;
399
400     /*
401      * First skip white-space and comments
402      */
403     while ((c = getc(f)) != EOF) {
404         if (c == '\\') {
405             /*
406              * \<newline> is ignored; \ followed by anything else
407              * starts a word.
408              */
409             if ((c = getc(f)) == '\n')
410                 continue;
411             word[len++] = '\\';
412             escape = 1;
413             break;
414         }
415         if (c == '\n')
416             *newlinep = 1;      /* next word starts a line */
417         else if (c == '#') {
418             /* comment - ignore until EOF or \n */
419             while ((c = getc(f)) != EOF && c != '\n')
420                 ;
421             if (c == EOF)
422                 break;
423             *newlinep = 1;
424         } else if (!isspace(c))
425             break;
426     }
427
428     /*
429      * End of file or error - fail
430      */
431     if (c == EOF) {
432         if (ferror(f)) {
433             perror(filename);
434             die(1);
435         }
436         return 0;
437     }
438
439     for (;;) {
440         /*
441          * Is this character escaped by \ ?
442          */
443         if (escape) {
444             if (c == '\n')
445                 --len;                  /* ignore \<newline> */
446             else if (c == '"' || isspace(c) || c == '\\')
447                 word[len-1] = c;        /* put special char in word */
448             else {
449                 if (len < MAXWORDLEN-1)
450                     word[len] = c;
451                 ++len;
452             }
453             escape = 0;
454         } else if (c == '"') {
455             quoted = !quoted;
456         } else if (!quoted && (isspace(c) || c == '#')) {
457             ungetc(c, f);
458             break;
459         } else {
460             if (len < MAXWORDLEN-1)
461                 word[len] = c;
462             ++len;
463             if (c == '\\')
464                 quoted = 1;
465         }
466         if ((c = getc(f)) == EOF)
467             break;
468     }
469
470     if (ferror(f)) {
471         perror(filename);
472         die(1);
473     }
474
475     if (len >= MAXWORDLEN) {
476         word[MAXWORDLEN-1] = 0;
477         fprintf(stderr, "%s: warning: word in file %s too long (%.20s...)\n",
478                 progname, filename, word);
479     } else
480         word[len] = 0;
481
482     return 1;
483 }
484
485 /*
486  * number_option - parse a numeric parameter for an option
487  */
488 static int
489 number_option(str, valp, base)
490     char *str;
491     long *valp;
492     int base;
493 {
494     char *ptr;
495
496     *valp = strtol(str, &ptr, base);
497     if (ptr == str) {
498         fprintf(stderr, "%s: invalid number: %s\n", progname, str);
499         return 0;
500     }
501     return 1;
502 }
503
504
505 /*
506  * int_option - like number_option, but valp is int *,
507  * the base is assumed to be 0, and *valp is not changed
508  * if there is an error.
509  */
510 static int
511 int_option(str, valp)
512     char *str;
513     int *valp;
514 {
515     long v;
516
517     if (!number_option(str, &v, 0))
518         return 0;
519     *valp = (int) v;
520     return 1;
521 }
522
523
524 /*
525  * The following procedures execute commands.
526  */
527
528 /*
529  * readfile - take commands from a file.
530  */
531 static int
532 readfile(argv)
533     char **argv;
534 {
535     return options_from_file(*argv, 1);
536 }
537
538 /*
539  * setdebug - Set debug (command line argument).
540  */
541 static int
542 setdebug()
543 {
544     debug++;
545     setlogmask(LOG_UPTO(LOG_DEBUG));
546     return (1);
547 }
548
549 /*
550  * noopt - Disable all options.
551  */
552 static int
553 noopt()
554 {
555     BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options));
556     BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options));
557     BZERO((char *) &ipcp_wantoptions[0], sizeof (struct ipcp_options));
558     BZERO((char *) &ipcp_allowoptions[0], sizeof (struct ipcp_options));
559     return (1);
560 }
561
562 /*
563  * noaccomp - Disable Address/Control field compression negotiation.
564  */
565 static int
566 noaccomp()
567 {
568     lcp_wantoptions[0].neg_accompression = 0;
569     lcp_allowoptions[0].neg_accompression = 0;
570     return (1);
571 }
572
573
574 /*
575  * noasyncmap - Disable async map negotiation.
576  */
577 static int
578 noasyncmap()
579 {
580     lcp_wantoptions[0].neg_asyncmap = 0;
581     lcp_allowoptions[0].neg_asyncmap = 0;
582     return (1);
583 }
584
585
586 /*
587  * noipaddr - Disable IP address negotiation.
588  */
589 static int
590 noipaddr()
591 {
592     ipcp_wantoptions[0].neg_addr = 0;
593     ipcp_allowoptions[0].neg_addr = 0;
594     return (1);
595 }
596
597
598 /*
599  * nomagicnumber - Disable magic number negotiation.
600  */
601 static int
602 nomagicnumber()
603 {
604     lcp_wantoptions[0].neg_magicnumber = 0;
605     lcp_allowoptions[0].neg_magicnumber = 0;
606     return (1);
607 }
608
609
610 /*
611  * nomru - Disable mru negotiation.
612  */
613 static int
614 nomru()
615 {
616     lcp_wantoptions[0].neg_mru = 0;
617     lcp_allowoptions[0].neg_mru = 0;
618     return (1);
619 }
620
621
622 /*
623  * setmru - Set MRU for negotiation.
624  */
625 static int
626 setmru(argv)
627     char **argv;
628 {
629     long mru;
630
631     if (!number_option(*argv, &mru, 0))
632         return 0;
633     lcp_wantoptions[0].mru = mru;
634     lcp_wantoptions[0].neg_mru = 1;
635     return (1);
636 }
637
638
639 /*
640  * nopcomp - Disable Protocol field compression negotiation.
641  */
642 static int
643 nopcomp()
644 {
645     lcp_wantoptions[0].neg_pcompression = 0;
646     lcp_allowoptions[0].neg_pcompression = 0;
647     return (1);
648 }
649
650
651 /*
652  * setpassive - Set passive mode (don't give up if we time out sending
653  * LCP configure-requests).
654  */
655 static int
656 setpassive()
657 {
658     lcp_wantoptions[0].passive = 1;
659     return (1);
660 }
661
662
663 /*
664  * setsilent - Set silent mode (don't start sending LCP configure-requests
665  * until we get one from the peer).
666  */
667 static int
668 setsilent()
669 {
670     lcp_wantoptions[0].silent = 1;
671     return 1;
672 }
673
674
675 /*
676  * nopap - Disable PAP authentication with peer.
677  */
678 static int
679 nopap()
680 {
681     lcp_allowoptions[0].neg_upap = 0;
682     return (1);
683 }
684
685
686 /*
687  * reqpap - Require PAP authentication from peer.
688  */
689 static int
690 reqpap()
691 {
692     lcp_wantoptions[0].neg_upap = 1;
693     auth_required = 1;
694 }
695
696
697 /*
698  * setupapfile - specifies UPAP info for authenticating with peer.
699  */
700 static int
701 setupapfile(argv)
702     char **argv;
703 {
704     FILE * ufile;
705     int l;
706
707     lcp_allowoptions[0].neg_upap = 1;
708
709     /* open user info file */
710     if ((ufile = fopen(*argv, "r")) == NULL) {
711         fprintf(stderr, "unable to open user login data file %s\n", *argv);
712         exit(1);
713     }
714     check_access(ufile, *argv);
715
716     /* get username */
717     if (fgets(user, MAXNAMELEN - 1, ufile) == NULL
718         || fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){
719         fprintf(stderr, "Unable to read user login data file %s.\n", *argv);
720         exit(2);
721     }
722     fclose(ufile);
723
724     /* get rid of newlines */
725     l = strlen(user);
726     if (l > 0 && user[l-1] == '\n')
727         user[l-1] = 0;
728     l = strlen(passwd);
729     if (l > 0 && passwd[l-1] == '\n')
730         passwd[l-1] = 0;
731
732     return (1);
733 }
734
735
736 /*
737  * nochap - Disable CHAP authentication with peer.
738  */
739 static int
740 nochap()
741 {
742     lcp_allowoptions[0].neg_chap = 0;
743     return (1);
744 }
745
746
747 /*
748  * reqchap - Require CHAP authentication from peer.
749  */
750 static int
751 reqchap()
752 {
753     lcp_wantoptions[0].neg_chap = 1;
754     auth_required = 1;
755     return (1);
756 }
757
758
759 /*
760  * setnovj - diable vj compression
761  */
762 static int
763 setnovj()
764 {
765     ipcp_wantoptions[0].neg_vj = 0;
766     ipcp_allowoptions[0].neg_vj = 0;
767     return (1);
768 }
769
770 /*
771  * setconnector - Set a program to connect to a serial line
772  */
773 static int
774 setconnector(argv)
775     char **argv;
776 {
777     connector = strdup(*argv);
778     if (connector == NULL)
779         novm("connector string");
780   
781     return (1);
782 }
783
784
785 /*
786  * setdomain - Set domain name to append to hostname 
787  */
788 static int
789 setdomain(argv)
790     char **argv;
791 {
792     strncat(hostname, *argv, MAXNAMELEN - strlen(hostname));
793     hostname[MAXNAMELEN-1] = 0;
794     return (1);
795 }
796
797 static int
798 setasyncmap(argv)
799     char **argv;
800 {
801     long asyncmap;
802
803     if (!number_option(*argv, &asyncmap, 16))
804         return 0;
805     lcp_wantoptions[0].asyncmap |= asyncmap;
806     lcp_wantoptions[0].neg_asyncmap = 1;
807     return(1);
808 }
809
810 /*
811  * setspeed - Set the speed.
812  */
813 static int
814 setspeed(arg)
815     char *arg;
816 {
817     char *ptr;
818     int spd;
819
820     spd = strtol(arg, &ptr, 0);
821     if (ptr == arg || *ptr != 0 || spd == 0)
822         return 0;
823     inspeed = spd;
824     return 1;
825 }
826
827
828 /*
829  * setdevname - Set the device name.
830  */
831 int
832 setdevname(cp)
833     char *cp;
834 {
835     struct stat statbuf;
836     char *tty, *ttyname();
837     char dev[MAXPATHLEN];
838   
839     if (strncmp("/dev/", cp, 5) != 0) {
840         strcpy(dev, "/dev/");
841         strncat(dev, cp, MAXPATHLEN - 5);
842         dev[MAXPATHLEN-1] = 0;
843         cp = dev;
844     }
845
846     /*
847      * Check if there is a device by this name.
848      */
849     if (stat(cp, &statbuf) < 0) {
850         if (errno == ENOENT)
851             return (0);
852         syslog(LOG_ERR, cp);
853         exit(1);
854     }
855   
856     (void) strncpy(devname, cp, MAXPATHLEN);
857     devname[MAXPATHLEN-1] = 0;
858     default_device = FALSE;
859   
860     return (1);
861 }
862
863
864 /*
865  * setipaddr - Set the IP address
866  */
867 int
868 setipaddr(arg)
869     char *arg;
870 {
871     struct hostent *hp;
872     char *colon, *index();
873     u_long local, remote;
874     ipcp_options *wo = &ipcp_wantoptions[0];
875   
876     /*
877      * IP address pair separated by ":".
878      */
879     if ((colon = index(arg, ':')) == NULL)
880         return (0);
881   
882     /*
883      * If colon first character, then no local addr.
884      */
885     if (colon != arg) {
886         *colon = '\0';
887         if ((local = inet_addr(arg)) == -1) {
888             if ((hp = gethostbyname(arg)) == NULL) {
889                 fprintf(stderr, "unknown host: %s", arg);
890                 local = 0;
891             } else {
892                 local = *(long *)hp->h_addr;
893                 if (our_name[0] == 0) {
894                     strncpy(our_name, arg, MAXNAMELEN);
895                     our_name[MAXNAMELEN-1] = 0;
896                 }
897             }
898         }
899         if (local != 0)
900             wo->ouraddr = local;
901         *colon = ':';
902     }
903   
904     /*
905      * If colon last character, then no remote addr.
906      */
907     if (*++colon != '\0') {
908         if ((remote = inet_addr(colon)) == -1) {
909             if ((hp = gethostbyname(colon)) == NULL) {
910                 fprintf(stderr, "unknown host: %s", colon);
911                 remote = 0;
912             } else {
913                 remote = *(long *)hp->h_addr;
914                 if (remote_name[0] == 0) {
915                     strncpy(remote_name, colon, MAXNAMELEN);
916                     remote_name[MAXNAMELEN-1] = 0;
917                 }
918             }
919         }
920         if (remote != 0)
921             wo->hisaddr = remote;
922     }
923
924     return (1);
925 }
926
927
928 /*
929  * setipdefault - default our local IP address based on our hostname.
930  */
931 void
932 setipdefault()
933 {
934     struct hostent *hp;
935     u_long local;
936     ipcp_options *wo = &ipcp_wantoptions[0];
937
938     /*
939      * If local IP address already given, don't bother.
940      */
941     if (wo->ouraddr != 0)
942         return;
943
944     /*
945      * Look up our hostname (possibly with domain name appended)
946      * and take the first IP address as our local IP address.
947      * If there isn't an IP address for our hostname, too bad.
948      */
949     if ((hp = gethostbyname(hostname)) == NULL)
950         return;
951     local = *(long *)hp->h_addr;
952     if (local != 0)
953         wo->ouraddr = local;
954 }
955
956
957 /*
958  * setnetmask - set the netmask to be used on the interface.
959  */
960 static int
961 setnetmask(argv)
962     char **argv;
963 {
964     u_long mask;
965         
966     if ((mask = inet_addr(*argv)) == -1) {
967         fprintf(stderr, "Invalid netmask %s\n", *argv);
968         exit(1);
969     }
970
971     netmask = mask;
972     return (1);
973 }
974
975 static int
976 setcrtscts()
977 {
978     crtscts = 1;
979     return (1);
980 }
981
982 static int
983 setnodetach()
984 {
985     nodetach = 1;
986     return (1);
987 }
988
989 static int
990 setmodem()
991 {
992     modem = 1;
993     return 1;
994 }
995
996 static int
997 setlocal()
998 {
999     modem = 0;
1000     return 1;
1001 }
1002
1003 static int
1004 setusehostname()
1005 {
1006     usehostname = 1;
1007     return 1;
1008 }
1009
1010 static int
1011 setname(argv)
1012     char **argv;
1013 {
1014     if (our_name[0] == 0) {
1015         strncpy(our_name, argv[0], MAXNAMELEN);
1016         our_name[MAXNAMELEN-1] = 0;
1017     }
1018     return 1;
1019 }
1020
1021 static int
1022 setuser(argv)
1023     char **argv;
1024 {
1025     strncpy(user, argv[0], MAXNAMELEN);
1026     user[MAXNAMELEN-1] = 0;
1027     return 1;
1028 }
1029
1030 static int
1031 setremote(argv)
1032     char **argv;
1033 {
1034     strncpy(remote_name, argv[0], MAXNAMELEN);
1035     remote_name[MAXNAMELEN-1] = 0;
1036     return 1;
1037 }
1038
1039 static int
1040 setauth()
1041 {
1042     auth_required = 1;
1043     return 1;
1044 }
1045
1046 static int
1047 setdefaultroute()
1048 {
1049     ipcp_wantoptions[0].default_route = 1;
1050     return 1;
1051 }
1052
1053 static int
1054 setproxyarp()
1055 {
1056     ipcp_wantoptions[0].proxy_arp = 1;
1057     return 1;
1058 }
1059
1060 static int
1061 setpersist()
1062 {
1063     persist = 1;
1064     return 1;
1065 }
1066
1067 static int
1068 setdologin()
1069 {
1070     uselogin = 1;
1071     return 1;
1072 }
1073
1074 /*
1075  * Functions to set timeouts, max transmits, etc.
1076  */
1077 static int
1078 setlcptimeout(argv)
1079     char **argv;
1080 {
1081     return int_option(*argv, &lcp_fsm[0].timeouttime, 0);
1082 }
1083
1084 static int setlcpterm(argv)
1085     char **argv;
1086 {
1087     return int_option(*argv, &lcp_fsm[0].maxtermtransmits, 0);
1088 }
1089
1090 static int setlcpconf(argv)
1091     char **argv;
1092 {
1093     return int_option(*argv, &lcp_fsm[0].maxconfreqtransmits, 0);
1094 }
1095
1096 static int setlcpfails(argv)
1097     char **argv;
1098 {
1099     return int_option(*argv, &lcp_fsm[0].maxnakloops, 0);
1100 }
1101
1102 static int setipcptimeout(argv)
1103     char **argv;
1104 {
1105     return int_option(*argv, &ipcp_fsm[0].timeouttime, 0);
1106 }
1107
1108 static int setipcpterm(argv)
1109     char **argv;
1110 {
1111     return int_option(*argv, &ipcp_fsm[0].maxtermtransmits, 0);
1112 }
1113
1114 static int setipcpconf(argv)
1115     char **argv;
1116 {
1117     return int_option(*argv, &ipcp_fsm[0].maxconfreqtransmits, 0);
1118 }
1119
1120 static int setipcpfails(argv)
1121     char **argv;
1122 {
1123     return int_option(*argv, &lcp_fsm[0].maxnakloops, 0);
1124 }
1125
1126 static int setpaptimeout(argv)
1127     char **argv;
1128 {
1129     return int_option(*argv, &upap[0].us_timeouttime, 0);
1130 }
1131
1132 static int setpapreqs(argv)
1133     char **argv;
1134 {
1135     return int_option(*argv, &upap[0].us_maxtransmits, 0);
1136 }
1137
1138 static int setchaptimeout(argv)
1139     char **argv;
1140 {
1141     return int_option(*argv, &chap[0].timeouttime, 0);
1142 }
1143
1144 static int setchapchal(argv)
1145     char **argv;
1146 {
1147     return int_option(*argv, &chap[0].max_transmits, 0);
1148 }
1149
1150 static int setchapintv(argv)
1151     char **argv;
1152 {
1153     return int_option(*argv, &chap[0].chal_interval, 0);
1154 }