*/
#ifndef lint
-static char rcsid[] = "$Id: options.c,v 1.17 1995/04/24 05:54:44 paulus Exp $";
+static char rcsid[] = "$Id: options.c,v 1.25 1995/10/27 03:39:14 paulus Exp $";
#endif
#include <stdio.h>
int usehostname = 0; /* Use hostname for our_name */
int disable_defaultip = 0; /* Don't use hostname for default IP adrs */
char *ipparam = NULL; /* Extra parameter for ip up/down scripts */
+int cryptpap; /* Passwords in pap-secrets are encrypted */
#ifdef _linux_
int idle_time_limit = 0;
static int setauth __P((void));
static int readfile __P((char **));
static int setdefaultroute __P((void));
+static int setnodefaultroute __P((void));
static int setproxyarp __P((void));
+static int setnoproxyarp __P((void));
static int setpersist __P((void));
static int setdologin __P((void));
static int setusehostname __P((void));
static int setipcpfails __P((char **));
static int setpaptimeout __P((char **));
static int setpapreqs __P((char **));
+static int setpapreqtime __P((char **));
static int setchaptimeout __P((char **));
static int setchapchal __P((char **));
static int setchapintv __P((char **));
static int setbsdcomp __P((char **));
static int setnobsdcomp __P((void));
static int setipparam __P((char **));
+static int setpapcrypt __P((void));
-static int number_option __P((char *, long *, int));
+static int number_option __P((char *, u_int32_t *, int));
static int readable __P((int fd));
void usage();
{"auth", 0, setauth}, /* Require authentication from peer */
{"file", 1, readfile}, /* Take options from a file */
{"defaultroute", 0, setdefaultroute}, /* Add default route */
+ {"-defaultroute", 0, setnodefaultroute}, /* disable defaultroute option */
{"proxyarp", 0, setproxyarp}, /* Add proxy ARP entry */
+ {"-proxyarp", 0, setnoproxyarp}, /* disable proxyarp option */
{"persist", 0, setpersist}, /* Keep on reopening connection after close */
{"login", 0, setdologin}, /* Use system password database for UPAP */
{"noipdefault", 0, setnoipdflt}, /* Don't use name for default IP adrs */
{"ipcp-max-terminate", 1, setipcpterm}, /* Set max #xmits for term-reqs */
{"ipcp-max-configure", 1, setipcpconf}, /* Set max #xmits for conf-reqs */
{"ipcp-max-failure", 1, setipcpfails}, /* Set max #conf-naks for IPCP */
- {"pap-restart", 1, setpaptimeout}, /* Set timeout for UPAP */
+ {"pap-restart", 1, setpaptimeout}, /* Set retransmit timeout for PAP */
{"pap-max-authreq", 1, setpapreqs}, /* Set max #xmits for auth-reqs */
+ {"pap-timeout", 1, setpapreqtime}, /* Set time limit for peer PAP auth. */
{"chap-restart", 1, setchaptimeout}, /* Set timeout for CHAP */
{"chap-max-challenge", 1, setchapchal}, /* Set max #xmits for challenge */
{"chap-interval", 1, setchapintv}, /* Set interval for rechallenge */
{"bsdcomp", 1, setbsdcomp}, /* request BSD-Compress */
{"-bsdcomp", 0, setnobsdcomp}, /* don't allow BSD-Compress */
{"ipparam", 1, setipparam}, /* set ip script parameter */
+ {"papcrypt", 0, setpapcrypt}, /* PAP passwords encrypted */
#ifdef _linux_
{"idle-disconnect", 1, setidle}, /* seconds for disconnect of idle IP */
#endif
/*
* Read a word from a file.
- * Words are delimited by white-space or by quotes (").
+ * Words are delimited by white-space or by quotes (" or ').
* Quotes, white-space and \ may be escaped with \.
* \<newline> is ignored.
*/
+
int
getword(f, word, newlinep, filename)
FILE *f;
char *filename;
{
int c, len, escape;
- int quoted;
+ int quoted, comment;
+ int value, digit, got, n;
+
+#define isoctal(c) ((c) >= '0' && (c) < '8')
*newlinep = 0;
len = 0;
escape = 0;
- quoted = 0;
+ comment = 0;
/*
- * First skip white-space and comments
+ * First skip white-space and comments.
*/
- while ((c = getc(f)) != EOF) {
+ for (;;) {
+ c = getc(f);
+ if (c == EOF)
+ break;
+
+ /*
+ * A newline means the end of a comment; backslash-newline
+ * is ignored. Note that we cannot have escape && comment.
+ */
+ if (c == '\n') {
+ if (!escape) {
+ *newlinep = 1;
+ comment = 0;
+ } else
+ escape = 0;
+ continue;
+ }
+
+ /*
+ * Ignore characters other than newline in a comment.
+ */
+ if (comment)
+ continue;
+
+ /*
+ * If this character is escaped, we have a word start.
+ */
+ if (escape)
+ break;
+
+ /*
+ * If this is the escape character, look at the next character.
+ */
if (c == '\\') {
+ escape = 1;
+ continue;
+ }
+
+ /*
+ * If this is the start of a comment, ignore the rest of the line.
+ */
+ if (c == '#') {
+ comment = 1;
+ continue;
+ }
+
+ /*
+ * A non-whitespace character is the start of a word.
+ */
+ if (!isspace(c))
+ break;
+ }
+
+ /*
+ * Save the delimiter for quoted strings.
+ */
+ if (!escape && (c == '"' || c == '\'')) {
+ quoted = c;
+ c = getc(f);
+ } else
+ quoted = 0;
+
+ /*
+ * Process characters until the end of the word.
+ */
+ while (c != EOF) {
+ if (escape) {
/*
- * \<newline> is ignored; \ followed by anything else
- * starts a word.
+ * This character is escaped: backslash-newline is ignored,
+ * various other characters indicate particular values
+ * as for C backslash-escapes.
*/
- if ((c = getc(f)) == '\n')
+ escape = 0;
+ if (c == '\n') {
+ c = getc(f);
continue;
- word[len++] = '\\';
- escape = 1;
- break;
+ }
+
+ got = 0;
+ switch (c) {
+ case 'a':
+ value = '\a';
+ break;
+ case 'b':
+ value = '\b';
+ break;
+ case 'f':
+ value = '\f';
+ break;
+ case 'n':
+ value = '\n';
+ break;
+ case 'r':
+ value = '\r';
+ break;
+ case 's':
+ value = ' ';
+ break;
+ case 't':
+ value = '\t';
+ break;
+
+ default:
+ if (isoctal(c)) {
+ /*
+ * \ddd octal sequence
+ */
+ value = 0;
+ for (n = 0; n < 3 && isoctal(c); ++n) {
+ value = (value << 3) + (c & 07);
+ c = getc(f);
+ }
+ got = 1;
+ break;
+ }
+
+ if (c == 'x') {
+ /*
+ * \x<hex_string> sequence
+ */
+ value = 0;
+ c = getc(f);
+ for (n = 0; n < 2 && isxdigit(c); ++n) {
+ digit = toupper(c) - '0';
+ if (digit > 10)
+ digit += '0' + 10 - 'A';
+ value = (value << 4) + digit;
+ c = getc (f);
+ }
+ got = 1;
+ break;
+ }
+
+ /*
+ * Otherwise the character stands for itself.
+ */
+ value = c;
+ break;
+ }
+
+ /*
+ * Store the resulting character for the escape sequence.
+ */
+ if (len < MAXWORDLEN-1)
+ word[len] = value;
+ ++len;
+
+ if (!got)
+ c = getc(f);
+ continue;
+
}
- if (c == '\n')
- *newlinep = 1; /* next word starts a line */
- else if (c == '#') {
- /* comment - ignore until EOF or \n */
- while ((c = getc(f)) != EOF && c != '\n')
- ;
- if (c == EOF)
+
+ /*
+ * Not escaped: see if we've reached the end of the word.
+ */
+ if (quoted) {
+ if (c == quoted)
break;
- *newlinep = 1;
- } else if (!isspace(c))
- break;
+ } else {
+ if (isspace(c) || c == '#') {
+ ungetc (c, f);
+ break;
+ }
+ }
+
+ /*
+ * Backslash starts an escape sequence.
+ */
+ if (c == '\\') {
+ escape = 1;
+ c = getc(f);
+ continue;
+ }
+
+ /*
+ * An ordinary character: store it in the word and get another.
+ */
+ if (len < MAXWORDLEN-1)
+ word[len] = c;
+ ++len;
+
+ c = getc(f);
}
/*
- * End of file or error - fail
+ * End of the word: check for errors.
*/
if (c == EOF) {
if (ferror(f)) {
+ if (errno == 0)
+ errno = EIO;
perror(filename);
die(1);
}
- return 0;
- }
-
- for (;;) {
/*
- * Is this character escaped by \ ?
+ * If len is zero, then we didn't find a word before the
+ * end of the file.
*/
- if (escape) {
- if (c == '\n')
- --len; /* ignore \<newline> */
- else if (c == '"' || isspace(c) || c == '\\')
- word[len-1] = c; /* put special char in word */
- else {
- if (len < MAXWORDLEN-1)
- word[len] = c;
- ++len;
- }
- escape = 0;
- } else if (c == '"') {
- quoted = !quoted;
- } else if (!quoted && (isspace(c) || c == '#')) {
- ungetc(c, f);
- break;
- } else {
- if (len < MAXWORDLEN-1)
- word[len] = c;
- ++len;
- if (c == '\\')
- escape = 1;
- }
- if ((c = getc(f)) == EOF)
- break;
- }
-
- if (ferror(f)) {
- perror(filename);
- die(1);
+ if (len == 0)
+ return 0;
}
+ /*
+ * Warn if the word was too long, and append a terminating null.
+ */
if (len >= MAXWORDLEN) {
- word[MAXWORDLEN-1] = 0;
fprintf(stderr, "%s: warning: word in file %s too long (%.20s...)\n",
progname, filename, word);
- } else
- word[len] = 0;
+ len = MAXWORDLEN - 1;
+ }
+ word[len] = 0;
return 1;
+
+#undef isoctal
+
}
/*
- * number_option - parse a numeric parameter for an option
+ * number_option - parse an unsigned numeric parameter for an option.
*/
static int
number_option(str, valp, base)
char *str;
- long *valp;
+ u_int32_t *valp;
int base;
{
char *ptr;
- *valp = strtol(str, &ptr, base);
+ *valp = strtoul(str, &ptr, base);
if (ptr == str) {
fprintf(stderr, "%s: invalid number: %s\n", progname, str);
return 0;
char *str;
int *valp;
{
- long v;
+ u_int32_t v;
if (!number_option(str, &v, 0))
return 0;
setmru(argv)
char **argv;
{
- long mru;
+ u_int32_t mru;
if (!number_option(*argv, &mru, 0))
return 0;
setmtu(argv)
char **argv;
{
- long mtu;
+ u_int32_t mtu;
if (!number_option(*argv, &mtu, 0))
return 0;
setdomain(argv)
char **argv;
{
- strncat(hostname, *argv, MAXNAMELEN - strlen(hostname));
+ gethostname(hostname, MAXNAMELEN);
+ if (**argv != 0) {
+ if (**argv != '.')
+ strncat(hostname, ".", MAXNAMELEN - strlen(hostname));
+ strncat(hostname, *argv, MAXNAMELEN - strlen(hostname));
+ }
hostname[MAXNAMELEN-1] = 0;
return (1);
}
setasyncmap(argv)
char **argv;
{
- long asyncmap;
+ u_int32_t asyncmap;
if (!number_option(*argv, &asyncmap, 16))
return 0;
return (1);
}
-/*
- * Return user specified netmask. A value of zero means no netmask has
- * been set.
- */
-/* ARGSUSED */
-u_int32_t
-GetMask(addr)
- u_int32_t addr;
-{
- return(netmask);
-}
-
-
static int
setcrtscts()
{
static int
setxonxoff()
{
- crtscts = 2;
+ lcp_wantoptions[0].asyncmap |= 0x000A0000; /* escape ^S and ^Q */
+ lcp_wantoptions[0].neg_asyncmap = 1;
+
+ crtscts = -2;
return (1);
}
static int
setdefaultroute()
{
+ if (!ipcp_allowoptions[0].default_route) {
+ fprintf(stderr, "%s: defaultroute option is disabled\n", progname);
+ return 0;
+ }
ipcp_wantoptions[0].default_route = 1;
return 1;
}
+static int
+setnodefaultroute()
+{
+ ipcp_allowoptions[0].default_route = 0;
+ ipcp_wantoptions[0].default_route = 0;
+ return 1;
+}
+
static int
setproxyarp()
{
+ if (!ipcp_allowoptions[0].proxy_arp) {
+ fprintf(stderr, "%s: proxyarp option is disabled\n", progname);
+ return 0;
+ }
ipcp_wantoptions[0].proxy_arp = 1;
return 1;
}
+static int
+setnoproxyarp()
+{
+ ipcp_wantoptions[0].proxy_arp = 0;
+ ipcp_allowoptions[0].proxy_arp = 0;
+ return 1;
+}
+
static int
setpersist()
{
return int_option(*argv, &upap[0].us_timeouttime);
}
+static int
+setpapreqtime(argv)
+ char **argv;
+{
+ return int_option(*argv, &upap[0].us_reqtimeout);
+}
+
static int
setpapreqs(argv)
char **argv;
progname);
return 0;
}
- if (rbits != 0 && (rbits < MIN_BSD_BITS || rbits > MAX_BSD_BITS)
- || abits != 0 && (abits < MIN_BSD_BITS || abits > MAX_BSD_BITS)) {
+ if (rbits != 0 && (rbits < BSD_MIN_BITS || rbits > BSD_MAX_BITS)
+ || abits != 0 && (abits < BSD_MIN_BITS || abits > BSD_MAX_BITS)) {
fprintf(stderr, "%s: bsdcomp option values must be 0 or %d .. %d\n",
- progname, MIN_BSD_BITS, MAX_BSD_BITS);
+ progname, BSD_MIN_BITS, BSD_MAX_BITS);
return 0;
}
if (rbits > 0) {
return 1;
}
+static int
+setpapcrypt()
+{
+ cryptpap = 1;
+ return 1;
+}
+
#ifdef _linux_
static int setidle (argv)
char **argv;