]> git.ozlabs.org Git - ppp.git/blob - pppd/options.c
2661fa4d26d141204505e0fb7df3a22c1f423393
[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.1 1993/11/11 03:54:25 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)
301     char *filename;
302 {
303     FILE *f;
304     int i, newline;
305     struct cmd *cmdp;
306     char *argv[MAXARGS];
307     char args[MAXARGS][MAXWORDLEN];
308     char cmd[MAXWORDLEN];
309
310     if ((f = fopen(filename, "r")) == NULL) {
311         if (errno == ENOENT)
312             return 1;
313         perror(filename);
314         exit(1);
315     }
316     while (getword(f, cmd, &newline, filename)) {
317         /*
318          * First see if it's a command.
319          */
320         for (cmdp = cmds; cmdp->cmd_name; cmdp++)
321             if (!strcmp(cmd, cmdp->cmd_name))
322                 break;
323
324         if (cmdp->cmd_name != NULL) {
325             for (i = 0; i < cmdp->num_args; ++i) {
326                 if (!getword(f, args[i], &newline, filename)) {
327                     fprintf(stderr,
328                             "In file %s: too few parameters for command %s\n",
329                             filename, cmd);
330                     fclose(f);
331                     return 0;
332                 }
333                 argv[i] = args[i];
334             }
335             if (!(*cmdp->cmd_func)(argv)) {
336                 fclose(f);
337                 return 0;
338             }
339
340         } else {
341             /*
342              * Maybe a tty name, speed or IP address?
343              */
344             if (!setdevname(cmd) && !setspeed(cmd) && !setipaddr(cmd)) {
345                 fprintf(stderr, "In file %s: unrecognized command %s\n",
346                         filename, cmd);
347                 fclose(f);
348                 return 0;
349             }
350         }
351     }
352     return 1;
353 }
354
355 /*
356  * options_from_user - See if the use has a ~/.ppprc file,
357  * and if so, interpret options from it.
358  */
359 int
360 options_from_user()
361 {
362     char *user, *path, *file;
363     int ret;
364
365     if ((user = getenv("HOME")) == NULL)
366         return;
367     file = "/.ppprc";
368     path = malloc(strlen(user) + strlen(file) + 1);
369     if (path == NULL)
370         novm("init file name");
371     strcpy(path, user);
372     strcat(path, file);
373     ret = options_from_file(path);
374     free(path);
375     return ret;
376 }
377
378 /*
379  * Read a word from a file.
380  * Words are delimited by white-space or by quotes (").
381  * Quotes, white-space and \ may be escaped with \.
382  * \<newline> is ignored.
383  */
384 int
385 getword(f, word, newlinep, filename)
386     FILE *f;
387     char *word;
388     int *newlinep;
389     char *filename;
390 {
391     int c, len, escape;
392     int quoted;
393
394     *newlinep = 0;
395     len = 0;
396     escape = 0;
397     quoted = 0;
398
399     /*
400      * First skip white-space and comments
401      */
402     while ((c = getc(f)) != EOF) {
403         if (c == '\\') {
404             /*
405              * \<newline> is ignored; \ followed by anything else
406              * starts a word.
407              */
408             if ((c = getc(f)) == '\n')
409                 continue;
410             word[len++] = '\\';
411             escape = 1;
412             break;
413         }
414         if (c == '\n')
415             *newlinep = 1;      /* next word starts a line */
416         else if (c == '#') {
417             /* comment - ignore until EOF or \n */
418             while ((c = getc(f)) != EOF && c != '\n')
419                 ;
420             if (c == EOF)
421                 break;
422             *newlinep = 1;
423         } else if (!isspace(c))
424             break;
425     }
426
427     /*
428      * End of file or error - fail
429      */
430     if (c == EOF) {
431         if (ferror(f)) {
432             perror(filename);
433             die(1);
434         }
435         return 0;
436     }
437
438     for (;;) {
439         /*
440          * Is this character escaped by \ ?
441          */
442         if (escape) {
443             if (c == '\n')
444                 --len;                  /* ignore \<newline> */
445             else if (c == '"' || isspace(c) || c == '\\')
446                 word[len-1] = c;        /* put special char in word */
447             else {
448                 if (len < MAXWORDLEN-1)
449                     word[len] = c;
450                 ++len;
451             }
452             escape = 0;
453         } else if (c == '"') {
454             quoted = !quoted;
455         } else if (!quoted && (isspace(c) || c == '#')) {
456             ungetc(c, f);
457             break;
458         } else {
459             if (len < MAXWORDLEN-1)
460                 word[len] = c;
461             ++len;
462             if (c == '\\')
463                 quoted = 1;
464         }
465         if ((c = getc(f)) == EOF)
466             break;
467     }
468
469     if (ferror(f)) {
470         perror(filename);
471         die(1);
472     }
473
474     if (len >= MAXWORDLEN) {
475         word[MAXWORDLEN-1] = 0;
476         fprintf(stderr, "%s: warning: word in file %s too long (%.20s...)\n",
477                 progname, filename, word);
478     } else
479         word[len] = 0;
480
481     return 1;
482 }
483
484 /*
485  * number_option - parse a numeric parameter for an option
486  */
487 static int
488 number_option(str, valp, base)
489     char *str;
490     long *valp;
491     int base;
492 {
493     char *ptr;
494
495     *valp = strtol(str, &ptr, base);
496     if (ptr == str) {
497         fprintf(stderr, "%s: invalid number: %s\n", progname, str);
498         return 0;
499     }
500     return 1;
501 }
502
503
504 /*
505  * int_option - like number_option, but valp is int *,
506  * the base is assumed to be 0, and *valp is not changed
507  * if there is an error.
508  */
509 static int
510 int_option(str, valp)
511     char *str;
512     int *valp;
513 {
514     long v;
515
516     if (!number_option(str, &v, 0))
517         return 0;
518     *valp = (int) v;
519     return 1;
520 }
521
522
523 /*
524  * The following procedures execute commands.
525  */
526
527 /*
528  * readfile - take commands from a file.
529  */
530 static int
531 readfile(argv)
532     char **argv;
533 {
534     return options_from_file(*argv);
535 }
536
537 /*
538  * setdebug - Set debug (command line argument).
539  */
540 static int
541 setdebug()
542 {
543     debug++;
544     setlogmask(LOG_UPTO(LOG_DEBUG));
545     return (1);
546 }
547
548 /*
549  * noopt - Disable all options.
550  */
551 static int
552 noopt()
553 {
554     BZERO((char *) &lcp_wantoptions[0], sizeof (struct lcp_options));
555     BZERO((char *) &lcp_allowoptions[0], sizeof (struct lcp_options));
556     BZERO((char *) &ipcp_wantoptions[0], sizeof (struct ipcp_options));
557     BZERO((char *) &ipcp_allowoptions[0], sizeof (struct ipcp_options));
558     return (1);
559 }
560
561 /*
562  * noaccomp - Disable Address/Control field compression negotiation.
563  */
564 static int
565 noaccomp()
566 {
567     lcp_wantoptions[0].neg_accompression = 0;
568     lcp_allowoptions[0].neg_accompression = 0;
569     return (1);
570 }
571
572
573 /*
574  * noasyncmap - Disable async map negotiation.
575  */
576 static int
577 noasyncmap()
578 {
579     lcp_wantoptions[0].neg_asyncmap = 0;
580     lcp_allowoptions[0].neg_asyncmap = 0;
581     return (1);
582 }
583
584
585 /*
586  * noipaddr - Disable IP address negotiation.
587  */
588 static int
589 noipaddr()
590 {
591     ipcp_wantoptions[0].neg_addr = 0;
592     ipcp_allowoptions[0].neg_addr = 0;
593     return (1);
594 }
595
596
597 /*
598  * nomagicnumber - Disable magic number negotiation.
599  */
600 static int
601 nomagicnumber()
602 {
603     lcp_wantoptions[0].neg_magicnumber = 0;
604     lcp_allowoptions[0].neg_magicnumber = 0;
605     return (1);
606 }
607
608
609 /*
610  * nomru - Disable mru negotiation.
611  */
612 static int
613 nomru()
614 {
615     lcp_wantoptions[0].neg_mru = 0;
616     lcp_allowoptions[0].neg_mru = 0;
617     return (1);
618 }
619
620
621 /*
622  * setmru - Set MRU for negotiation.
623  */
624 static int
625 setmru(argv)
626     char **argv;
627 {
628     long mru;
629
630     if (!number_option(*argv, &mru, 0))
631         return 0;
632     lcp_wantoptions[0].mru = mru;
633     lcp_wantoptions[0].neg_mru = 1;
634     return (1);
635 }
636
637
638 /*
639  * nopcomp - Disable Protocol field compression negotiation.
640  */
641 static int
642 nopcomp()
643 {
644     lcp_wantoptions[0].neg_pcompression = 0;
645     lcp_allowoptions[0].neg_pcompression = 0;
646     return (1);
647 }
648
649
650 /*
651  * setpassive - Set passive mode (don't give up if we time out sending
652  * LCP configure-requests).
653  */
654 static int
655 setpassive()
656 {
657     lcp_wantoptions[0].passive = 1;
658     return (1);
659 }
660
661
662 /*
663  * setsilent - Set silent mode (don't start sending LCP configure-requests
664  * until we get one from the peer).
665  */
666 static int
667 setsilent()
668 {
669     lcp_wantoptions[0].silent = 1;
670     return 1;
671 }
672
673
674 /*
675  * nopap - Disable PAP authentication with peer.
676  */
677 static int
678 nopap()
679 {
680     lcp_allowoptions[0].neg_upap = 0;
681     return (1);
682 }
683
684
685 /*
686  * reqpap - Require PAP authentication from peer.
687  */
688 static int
689 reqpap()
690 {
691     lcp_wantoptions[0].neg_upap = 1;
692     auth_required = 1;
693 }
694
695
696 /*
697  * setupapfile - specifies UPAP info for authenticating with peer.
698  */
699 static int
700 setupapfile(argv)
701     char **argv;
702 {
703     FILE * ufile;
704     int l;
705
706     lcp_allowoptions[0].neg_upap = 1;
707
708     /* open user info file */
709     if ((ufile = fopen(*argv, "r")) == NULL) {
710         fprintf(stderr, "unable to open user login data file %s\n", *argv);
711         exit(1);
712     }
713     check_access(ufile, *argv);
714
715     /* get username */
716     if (fgets(user, MAXNAMELEN - 1, ufile) == NULL
717         || fgets(passwd, MAXSECRETLEN - 1, ufile) == NULL){
718         fprintf(stderr, "Unable to read user login data file %s.\n", *argv);
719         exit(2);
720     }
721     fclose(ufile);
722
723     /* get rid of newlines */
724     l = strlen(user);
725     if (l > 0 && user[l-1] == '\n')
726         user[l-1] = 0;
727     l = strlen(passwd);
728     if (l > 0 && passwd[l-1] == '\n')
729         passwd[l-1] = 0;
730
731     return (1);
732 }
733
734
735 /*
736  * nochap - Disable CHAP authentication with peer.
737  */
738 static int
739 nochap()
740 {
741     lcp_allowoptions[0].neg_chap = 0;
742     return (1);
743 }
744
745
746 /*
747  * reqchap - Require CHAP authentication from peer.
748  */
749 static int
750 reqchap()
751 {
752     lcp_wantoptions[0].neg_chap = 1;
753     auth_required = 1;
754     return (1);
755 }
756
757
758 /*
759  * setnovj - diable vj compression
760  */
761 static int
762 setnovj()
763 {
764     ipcp_wantoptions[0].neg_vj = 0;
765     ipcp_allowoptions[0].neg_vj = 0;
766     return (1);
767 }
768
769 /*
770  * setconnector - Set a program to connect to a serial line
771  */
772 static int
773 setconnector(argv)
774     char **argv;
775 {
776     connector = strdup(*argv);
777     if (connector == NULL)
778         novm("connector string");
779   
780     return (1);
781 }
782
783
784 /*
785  * setdomain - Set domain name to append to hostname 
786  */
787 static int
788 setdomain(argv)
789     char **argv;
790 {
791     strncat(hostname, *argv, MAXNAMELEN - strlen(hostname));
792     hostname[MAXNAMELEN-1] = 0;
793     return (1);
794 }
795
796 static int
797 setasyncmap(argv)
798     char **argv;
799 {
800     long asyncmap;
801
802     if (!number_option(*argv, &asyncmap, 16))
803         return 0;
804     lcp_wantoptions[0].asyncmap |= asyncmap;
805     lcp_wantoptions[0].neg_asyncmap = 1;
806     return(1);
807 }
808
809 /*
810  * setspeed - Set the speed.
811  */
812 static int
813 setspeed(arg)
814     char *arg;
815 {
816     char *ptr;
817     int spd;
818
819     spd = strtol(arg, &ptr, 0);
820     if (ptr == arg || *ptr != 0 || spd == 0)
821         return 0;
822     inspeed = spd;
823     return 1;
824 }
825
826
827 /*
828  * setdevname - Set the device name.
829  */
830 int
831 setdevname(cp)
832     char *cp;
833 {
834     struct stat statbuf;
835     char *tty, *ttyname();
836     char dev[MAXPATHLEN];
837   
838     if (strncmp("/dev/", cp, 5) != 0) {
839         strcpy(dev, "/dev/");
840         strncat(dev, cp, MAXPATHLEN - 5);
841         dev[MAXPATHLEN-1] = 0;
842         cp = dev;
843     }
844
845     /*
846      * Check if there is a device by this name.
847      */
848     if (stat(cp, &statbuf) < 0) {
849         if (errno == ENOENT)
850             return (0);
851         syslog(LOG_ERR, cp);
852         exit(1);
853     }
854   
855     (void) strncpy(devname, cp, MAXPATHLEN);
856     devname[MAXPATHLEN-1] = 0;
857     default_device = FALSE;
858   
859     return (1);
860 }
861
862
863 /*
864  * setipaddr - Set the IP address
865  */
866 int
867 setipaddr(arg)
868     char *arg;
869 {
870     struct hostent *hp;
871     char *colon, *index();
872     u_long local, remote;
873     ipcp_options *wo = &ipcp_wantoptions[0];
874   
875     /*
876      * IP address pair separated by ":".
877      */
878     if ((colon = index(arg, ':')) == NULL)
879         return (0);
880   
881     /*
882      * If colon first character, then no local addr.
883      */
884     if (colon != arg) {
885         *colon = '\0';
886         if ((local = inet_addr(arg)) == -1) {
887             if ((hp = gethostbyname(arg)) == NULL) {
888                 fprintf(stderr, "unknown host: %s", arg);
889                 local = 0;
890             } else {
891                 local = *(long *)hp->h_addr;
892                 if (our_name[0] == 0) {
893                     strncpy(our_name, arg, MAXNAMELEN);
894                     our_name[MAXNAMELEN-1] = 0;
895                 }
896             }
897         }
898         if (local != 0)
899             wo->ouraddr = local;
900         *colon = ':';
901     }
902   
903     /*
904      * If colon last character, then no remote addr.
905      */
906     if (*++colon != '\0') {
907         if ((remote = inet_addr(colon)) == -1) {
908             if ((hp = gethostbyname(colon)) == NULL) {
909                 fprintf(stderr, "unknown host: %s", colon);
910                 remote = 0;
911             } else {
912                 remote = *(long *)hp->h_addr;
913                 if (remote_name[0] == 0) {
914                     strncpy(remote_name, colon, MAXNAMELEN);
915                     remote_name[MAXNAMELEN-1] = 0;
916                 }
917             }
918         }
919         if (remote != 0)
920             wo->hisaddr = remote;
921     }
922
923     return (1);
924 }
925
926
927 /*
928  * setipdefault - default our local IP address based on our hostname.
929  */
930 void
931 setipdefault()
932 {
933     struct hostent *hp;
934     u_long local;
935     ipcp_options *wo = &ipcp_wantoptions[0];
936
937     /*
938      * If local IP address already given, don't bother.
939      */
940     if (wo->ouraddr != 0)
941         return;
942
943     /*
944      * Look up our hostname (possibly with domain name appended)
945      * and take the first IP address as our local IP address.
946      * If there isn't an IP address for our hostname, too bad.
947      */
948     if ((hp = gethostbyname(hostname)) == NULL)
949         return;
950     local = *(long *)hp->h_addr;
951     if (local != 0)
952         wo->ouraddr = local;
953 }
954
955
956 /*
957  * setnetmask - set the netmask to be used on the interface.
958  */
959 static int
960 setnetmask(argv)
961     char **argv;
962 {
963     u_long mask;
964         
965     if ((mask = inet_addr(*argv)) == -1) {
966         fprintf(stderr, "Invalid netmask %s\n", *argv);
967         exit(1);
968     }
969
970     netmask = mask;
971     return (1);
972 }
973
974 static int
975 setcrtscts()
976 {
977     crtscts = 1;
978     return (1);
979 }
980
981 static int
982 setnodetach()
983 {
984     nodetach = 1;
985     return (1);
986 }
987
988 static int
989 setmodem()
990 {
991     modem = 1;
992     return 1;
993 }
994
995 static int
996 setlocal()
997 {
998     modem = 0;
999     return 1;
1000 }
1001
1002 static int
1003 setusehostname()
1004 {
1005     usehostname = 1;
1006     return 1;
1007 }
1008
1009 static int
1010 setname(argv)
1011     char **argv;
1012 {
1013     if (our_name[0] == 0) {
1014         strncpy(our_name, argv[0], MAXNAMELEN);
1015         our_name[MAXNAMELEN-1] = 0;
1016     }
1017     return 1;
1018 }
1019
1020 static int
1021 setuser(argv)
1022     char **argv;
1023 {
1024     strncpy(user, argv[0], MAXNAMELEN);
1025     user[MAXNAMELEN-1] = 0;
1026     return 1;
1027 }
1028
1029 static int
1030 setremote(argv)
1031     char **argv;
1032 {
1033     strncpy(remote_name, argv[0], MAXNAMELEN);
1034     remote_name[MAXNAMELEN-1] = 0;
1035     return 1;
1036 }
1037
1038 static int
1039 setauth()
1040 {
1041     auth_required = 1;
1042     return 1;
1043 }
1044
1045 static int
1046 setdefaultroute()
1047 {
1048     ipcp_wantoptions[0].default_route = 1;
1049     return 1;
1050 }
1051
1052 static int
1053 setproxyarp()
1054 {
1055     ipcp_wantoptions[0].proxy_arp = 1;
1056     return 1;
1057 }
1058
1059 static int
1060 setpersist()
1061 {
1062     persist = 1;
1063     return 1;
1064 }
1065
1066 static int
1067 setdologin()
1068 {
1069     uselogin = 1;
1070     return 1;
1071 }
1072
1073 /*
1074  * Functions to set timeouts, max transmits, etc.
1075  */
1076 static int
1077 setlcptimeout(argv)
1078     char **argv;
1079 {
1080     return int_option(*argv, &lcp_fsm[0].timeouttime, 0);
1081 }
1082
1083 static int setlcpterm(argv)
1084     char **argv;
1085 {
1086     return int_option(*argv, &lcp_fsm[0].maxtermtransmits, 0);
1087 }
1088
1089 static int setlcpconf(argv)
1090     char **argv;
1091 {
1092     return int_option(*argv, &lcp_fsm[0].maxconfreqtransmits, 0);
1093 }
1094
1095 static int setlcpfails(argv)
1096     char **argv;
1097 {
1098     return int_option(*argv, &lcp_fsm[0].maxnakloops, 0);
1099 }
1100
1101 static int setipcptimeout(argv)
1102     char **argv;
1103 {
1104     return int_option(*argv, &ipcp_fsm[0].timeouttime, 0);
1105 }
1106
1107 static int setipcpterm(argv)
1108     char **argv;
1109 {
1110     return int_option(*argv, &ipcp_fsm[0].maxtermtransmits, 0);
1111 }
1112
1113 static int setipcpconf(argv)
1114     char **argv;
1115 {
1116     return int_option(*argv, &ipcp_fsm[0].maxconfreqtransmits, 0);
1117 }
1118
1119 static int setipcpfails(argv)
1120     char **argv;
1121 {
1122     return int_option(*argv, &lcp_fsm[0].maxnakloops, 0);
1123 }
1124
1125 static int setpaptimeout(argv)
1126     char **argv;
1127 {
1128     return int_option(*argv, &upap[0].us_timeouttime, 0);
1129 }
1130
1131 static int setpapreqs(argv)
1132     char **argv;
1133 {
1134     return int_option(*argv, &upap[0].us_maxtransmits, 0);
1135 }
1136
1137 static int setchaptimeout(argv)
1138     char **argv;
1139 {
1140     return int_option(*argv, &chap[0].timeouttime, 0);
1141 }
1142
1143 static int setchapchal(argv)
1144     char **argv;
1145 {
1146     return int_option(*argv, &chap[0].max_transmits, 0);
1147 }
1148
1149 static int setchapintv(argv)
1150     char **argv;
1151 {
1152     return int_option(*argv, &chap[0].chal_interval, 0);
1153 }