Home | History | Annotate | Line # | Download | only in pppd
      1 /*	$NetBSD: ipcp.c,v 1.6 2025/01/08 19:59:39 christos Exp $	*/
      2 
      3 /*
      4  * ipcp.c - PPP IP Control Protocol.
      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 (at) 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 #include <sys/cdefs.h>
     46 __RCSID("$NetBSD: ipcp.c,v 1.6 2025/01/08 19:59:39 christos Exp $");
     47 
     48 #ifdef HAVE_CONFIG_H
     49 #include "config.h"
     50 #endif
     51 
     52 #include <stdio.h>
     53 #include <string.h>
     54 #include <stdlib.h>
     55 #include <netdb.h>
     56 #include <sys/param.h>
     57 #include <sys/types.h>
     58 #include <sys/socket.h>
     59 #include <netinet/in.h>
     60 #include <arpa/inet.h>
     61 #include <net/if.h>
     62 
     63 #include "pppd-private.h"
     64 #include "options.h"
     65 #include "fsm.h"
     66 #include "ipcp.h"
     67 #include "pathnames.h"
     68 
     69 
     70 /* global vars */
     71 ipcp_options ipcp_wantoptions[NUM_PPP];	/* Options that we want to request */
     72 ipcp_options ipcp_gotoptions[NUM_PPP];	/* Options that peer ack'd */
     73 ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
     74 ipcp_options ipcp_hisoptions[NUM_PPP];	/* Options that we ack'd */
     75 
     76 char	*ipparam = NULL;	/* Extra parameter for ip up/down scripts */
     77 u_int32_t netmask = 0;		/* IP netmask to set on interface */
     78 
     79 bool	disable_defaultip = 0;	/* Don't use hostname for default IP adrs */
     80 bool	noremoteip = 0;		/* Let him have no IP address */
     81 
     82 ip_up_hook_fn *ip_up_hook = NULL;
     83 ip_down_hook_fn *ip_down_hook = NULL;
     84 ip_choose_hook_fn *ip_choose_hook = NULL;
     85 
     86 
     87 /* Notifiers for when IPCP goes up and down */
     88 struct notifier *ip_up_notifier = NULL;
     89 struct notifier *ip_down_notifier = NULL;
     90 
     91 /* local vars */
     92 static int default_route_set[NUM_PPP];	/* Have set up a default route */
     93 static int proxy_arp_set[NUM_PPP];	/* Have created proxy arp entry */
     94 static bool usepeerdns;			/* Ask peer for DNS addrs */
     95 static bool usepeerwins;		/* Ask peer for WINS addrs */
     96 static bool noresolvconf;		/* Do not create resolv.conf */
     97 static int ipcp_is_up;			/* have called np_up() */
     98 static int ipcp_is_open;		/* haven't called np_finished() */
     99 static bool ask_for_local;		/* request our address from peer */
    100 static char vj_value[8];		/* string form of vj option value */
    101 static char netmask_str[20];		/* string form of netmask value */
    102 
    103 /*
    104  * Callbacks for fsm code.  (CI = Configuration Information)
    105  */
    106 static void ipcp_resetci (fsm *);	/* Reset our CI */
    107 static int  ipcp_cilen (fsm *);	        /* Return length of our CI */
    108 static void ipcp_addci (fsm *, u_char *, int *); /* Add our CI */
    109 static int  ipcp_ackci (fsm *, u_char *, int);	/* Peer ack'd our CI */
    110 static int  ipcp_nakci (fsm *, u_char *, int, int);/* Peer nak'd our CI */
    111 static int  ipcp_rejci (fsm *, u_char *, int);	/* Peer rej'd our CI */
    112 static int  ipcp_reqci (fsm *, u_char *, int *, int); /* Rcv CI */
    113 static void ipcp_up (fsm *);		/* We're UP */
    114 static void ipcp_down (fsm *);		/* We're DOWN */
    115 static void ipcp_finished (fsm *);	/* Don't need lower layer */
    116 
    117 fsm ipcp_fsm[NUM_PPP];		/* IPCP fsm structure */
    118 
    119 static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
    120     ipcp_resetci,		/* Reset our Configuration Information */
    121     ipcp_cilen,			/* Length of our Configuration Information */
    122     ipcp_addci,			/* Add our Configuration Information */
    123     ipcp_ackci,			/* ACK our Configuration Information */
    124     ipcp_nakci,			/* NAK our Configuration Information */
    125     ipcp_rejci,			/* Reject our Configuration Information */
    126     ipcp_reqci,			/* Request peer's Configuration Information */
    127     ipcp_up,			/* Called when fsm reaches OPENED state */
    128     ipcp_down,			/* Called when fsm leaves OPENED state */
    129     NULL,			/* Called when we want the lower layer up */
    130     ipcp_finished,		/* Called when we want the lower layer down */
    131     NULL,			/* Called when Protocol-Reject received */
    132     NULL,			/* Retransmission is necessary */
    133     NULL,			/* Called to handle protocol-specific codes */
    134     "IPCP"			/* String name of protocol */
    135 };
    136 
    137 /*
    138  * Command-line options.
    139  */
    140 static int setvjslots (char **);
    141 static int setdnsaddr (char **);
    142 static int setwinsaddr (char **);
    143 static int setnetmask (char **);
    144 int setipaddr (char *, char **, int);
    145 static void printipaddr (struct option *, void (*)(void *, char *,...),void *);
    146 
    147 static struct option ipcp_option_list[] = {
    148     { "noip", o_bool, &ipcp_protent.enabled_flag,
    149       "Disable IP and IPCP" },
    150     { "-ip", o_bool, &ipcp_protent.enabled_flag,
    151       "Disable IP and IPCP", OPT_ALIAS },
    152 
    153     { "novj", o_bool, &ipcp_wantoptions[0].neg_vj,
    154       "Disable VJ compression", OPT_A2CLR, &ipcp_allowoptions[0].neg_vj },
    155     { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj,
    156       "Disable VJ compression", OPT_ALIAS | OPT_A2CLR,
    157       &ipcp_allowoptions[0].neg_vj },
    158 
    159     { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag,
    160       "Disable VJ connection-ID compression", OPT_A2CLR,
    161       &ipcp_allowoptions[0].cflag },
    162     { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag,
    163       "Disable VJ connection-ID compression", OPT_ALIAS | OPT_A2CLR,
    164       &ipcp_allowoptions[0].cflag },
    165 
    166     { "vj-max-slots", o_special, (void *)setvjslots,
    167       "Set maximum VJ header slots",
    168       OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, vj_value },
    169 
    170     { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local,
    171       "Accept peer's address for us", 1 },
    172     { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote,
    173       "Accept peer's address for it", 1 },
    174 
    175     { "ipparam", o_string, &ipparam,
    176       "Set ip script parameter", OPT_PRIO },
    177 
    178     { "noipdefault", o_bool, &disable_defaultip,
    179       "Don't use name for default IP adrs", 1 },
    180 
    181     { "ms-dns", o_special, (void *)setdnsaddr,
    182       "DNS address for the peer's use", OPT_A2LIST },
    183     { "ms-wins", o_special, (void *)setwinsaddr,
    184       "Nameserver for SMB over TCP/IP for peer", OPT_A2LIST },
    185 
    186     { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime,
    187       "Set timeout for IPCP", OPT_PRIO },
    188     { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits,
    189       "Set max #xmits for term-reqs", OPT_PRIO },
    190     { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits,
    191       "Set max #xmits for conf-reqs", OPT_PRIO },
    192     { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops,
    193       "Set max #conf-naks for IPCP", OPT_PRIO },
    194 
    195     { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route,
    196       "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route },
    197     { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route,
    198       "disable defaultroute option", OPT_A2CLR,
    199       &ipcp_wantoptions[0].default_route },
    200     { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route,
    201       "disable defaultroute option", OPT_ALIAS | OPT_A2CLR,
    202       &ipcp_wantoptions[0].default_route },
    203 
    204 #ifdef __linux__
    205     { "replacedefaultroute", o_bool,
    206 				&ipcp_wantoptions[0].replace_default_route,
    207       "Replace default route", OPT_PRIV | 1
    208     },
    209     { "noreplacedefaultroute", o_bool,
    210 				&ipcp_wantoptions[0].replace_default_route,
    211       "Do not replace default route", 0 },
    212 #endif
    213     { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp,
    214       "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp },
    215     { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
    216       "disable proxyarp option", OPT_A2CLR,
    217       &ipcp_wantoptions[0].proxy_arp },
    218     { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
    219       "disable proxyarp option", OPT_ALIAS | OPT_A2CLR,
    220       &ipcp_wantoptions[0].proxy_arp },
    221 
    222     { "usepeerdns", o_bool, &usepeerdns,
    223       "Ask peer for DNS address(es)", 1 },
    224 
    225     { "usepeerwins", o_bool, &usepeerwins,
    226       "Ask peer for WINS address(es)", 1 },
    227 
    228     { "noresolvconf", o_bool, &noresolvconf,
    229       "Do not create resolv.conf", 1 },
    230 
    231     { "netmask", o_special, (void *)setnetmask,
    232       "set netmask", OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, netmask_str },
    233 
    234     { "ipcp-no-addresses", o_bool, &ipcp_wantoptions[0].old_addrs,
    235       "Disable old-style IP-Addresses usage", OPT_A2CLR,
    236       &ipcp_allowoptions[0].old_addrs },
    237     { "ipcp-no-address", o_bool, &ipcp_wantoptions[0].neg_addr,
    238       "Disable IP-Address usage", OPT_A2CLR,
    239       &ipcp_allowoptions[0].neg_addr },
    240 #ifdef __linux__
    241     { "noremoteip", o_bool, &noremoteip,
    242       "Allow peer to have no IP address", 1 },
    243 #endif
    244     { "nosendip", o_bool, &ipcp_wantoptions[0].neg_addr,
    245       "Don't send our IP address to peer", OPT_A2CLR,
    246       &ipcp_wantoptions[0].old_addrs},
    247 
    248     { "IP addresses", o_wild, (void *) &setipaddr,
    249       "set local and remote IP addresses",
    250       OPT_NOARG | OPT_A2PRINTER, (void *) &printipaddr },
    251 
    252     { NULL }
    253 };
    254 
    255 /*
    256  * Protocol entry points from main code.
    257  */
    258 static void ipcp_init (int);
    259 static void ipcp_open (int);
    260 static void ipcp_close (int, char *);
    261 static void ipcp_lowerup (int);
    262 static void ipcp_lowerdown (int);
    263 static void ipcp_input (int, u_char *, int);
    264 static void ipcp_protrej (int);
    265 static int  ipcp_printpkt (u_char *, int,
    266 			   void (*) (void *, char *, ...), void *);
    267 static void ip_check_options (void);
    268 static int  ip_demand_conf (int);
    269 static int  ip_active_pkt (u_char *, int);
    270 static void create_resolv (u_int32_t, u_int32_t);
    271 
    272 struct protent ipcp_protent = {
    273     PPP_IPCP,
    274     ipcp_init,
    275     ipcp_input,
    276     ipcp_protrej,
    277     ipcp_lowerup,
    278     ipcp_lowerdown,
    279     ipcp_open,
    280     ipcp_close,
    281     ipcp_printpkt,
    282     NULL,
    283     1,
    284     "IPCP",
    285     "IP",
    286     ipcp_option_list,
    287     ip_check_options,
    288     ip_demand_conf,
    289     ip_active_pkt
    290 };
    291 
    292 static void ipcp_clear_addrs (int, u_int32_t, u_int32_t, bool);
    293 static void ipcp_script (char *, int);	/* Run an up/down script */
    294 static void ipcp_script_done (void *);
    295 
    296 /*
    297  * Lengths of configuration options.
    298  */
    299 #define CILEN_VOID	2
    300 #define CILEN_COMPRESS	4	/* min length for compression protocol opt. */
    301 #define CILEN_VJ	6	/* length for RFC1332 Van-Jacobson opt. */
    302 #define CILEN_ADDR	6	/* new-style single address option */
    303 #define CILEN_ADDRS	10	/* old-style dual address option */
    304 
    305 
    306 #define CODENAME(x)	((x) == CONFACK ? "ACK" : \
    307 			 (x) == CONFNAK ? "NAK" : "REJ")
    308 
    309 /*
    310  * This state variable is used to ensure that we don't
    311  * run an ipcp-up/down script while one is already running.
    312  */
    313 static enum script_state {
    314     s_down,
    315     s_up,
    316 } ipcp_script_state;
    317 static pid_t ipcp_script_pid;
    318 
    319 /*
    320  * Make a string representation of a network IP address.
    321  */
    322 char *
    323 ip_ntoa(u_int32_t ipaddr)
    324 {
    325     static char b[64];
    326 
    327     slprintf(b, sizeof(b), "%I", ipaddr);
    328     return b;
    329 }
    330 
    331 /*
    332  * Option parsing.
    333  */
    334 
    335 /*
    336  * setvjslots - set maximum number of connection slots for VJ compression
    337  */
    338 static int
    339 setvjslots(char **argv)
    340 {
    341     int value;
    342 
    343     if (!ppp_int_option(*argv, &value))
    344 	return 0;
    345     if (value < 2 || value > 16) {
    346 	ppp_option_error("vj-max-slots value must be between 2 and 16");
    347 	return 0;
    348     }
    349     ipcp_wantoptions [0].maxslotindex =
    350         ipcp_allowoptions[0].maxslotindex = value - 1;
    351     slprintf(vj_value, sizeof(vj_value), "%d", value);
    352     return 1;
    353 }
    354 
    355 /*
    356  * setdnsaddr - set the dns address(es)
    357  */
    358 static int
    359 setdnsaddr(char **argv)
    360 {
    361     u_int32_t dns;
    362     struct hostent *hp;
    363 
    364     dns = inet_addr(*argv);
    365     if (dns == (u_int32_t) -1) {
    366 	if ((hp = gethostbyname(*argv)) == NULL) {
    367 	    ppp_option_error("invalid address parameter '%s' for ms-dns option",
    368 			 *argv);
    369 	    return 0;
    370 	}
    371 	dns = *(u_int32_t *)hp->h_addr;
    372     }
    373 
    374     /* We take the last 2 values given, the 2nd-last as the primary
    375        and the last as the secondary.  If only one is given it
    376        becomes both primary and secondary. */
    377     if (ipcp_allowoptions[0].dnsaddr[1] == 0)
    378 	ipcp_allowoptions[0].dnsaddr[0] = dns;
    379     else
    380 	ipcp_allowoptions[0].dnsaddr[0] = ipcp_allowoptions[0].dnsaddr[1];
    381 
    382     /* always set the secondary address value. */
    383     ipcp_allowoptions[0].dnsaddr[1] = dns;
    384 
    385     return (1);
    386 }
    387 
    388 /*
    389  * setwinsaddr - set the wins address(es)
    390  * This is primrarly used with the Samba package under UNIX or for pointing
    391  * the caller to the existing WINS server on a Windows NT platform.
    392  */
    393 static int
    394 setwinsaddr(char **argv)
    395 {
    396     u_int32_t wins;
    397     struct hostent *hp;
    398 
    399     wins = inet_addr(*argv);
    400     if (wins == (u_int32_t) -1) {
    401 	if ((hp = gethostbyname(*argv)) == NULL) {
    402 	    ppp_option_error("invalid address parameter '%s' for ms-wins option",
    403 			 *argv);
    404 	    return 0;
    405 	}
    406 	wins = *(u_int32_t *)hp->h_addr;
    407     }
    408 
    409     /* We take the last 2 values given, the 2nd-last as the primary
    410        and the last as the secondary.  If only one is given it
    411        becomes both primary and secondary. */
    412     if (ipcp_allowoptions[0].winsaddr[1] == 0)
    413 	ipcp_allowoptions[0].winsaddr[0] = wins;
    414     else
    415 	ipcp_allowoptions[0].winsaddr[0] = ipcp_allowoptions[0].winsaddr[1];
    416 
    417     /* always set the secondary address value. */
    418     ipcp_allowoptions[0].winsaddr[1] = wins;
    419 
    420     return (1);
    421 }
    422 
    423 /*
    424  * setipaddr - Set the IP address
    425  * If doit is 0, the call is to check whether this option is
    426  * potentially an IP address specification.
    427  * Not static so that plugins can call it to set the addresses
    428  */
    429 int
    430 setipaddr(char *arg, char **argv, int doit)
    431 {
    432     struct hostent *hp;
    433     char *colon;
    434     u_int32_t local, remote;
    435     ipcp_options *wo = &ipcp_wantoptions[0];
    436     static int prio_local = 0, prio_remote = 0;
    437 
    438     /*
    439      * IP address pair separated by ":".
    440      */
    441     if ((colon = strchr(arg, ':')) == NULL)
    442 	return 0;
    443     if (!doit)
    444 	return 1;
    445 
    446     /*
    447      * If colon first character, then no local addr.
    448      */
    449     if (colon != arg && option_priority >= prio_local) {
    450 	*colon = '\0';
    451 	if ((local = inet_addr(arg)) == (u_int32_t) -1) {
    452 	    if ((hp = gethostbyname(arg)) == NULL) {
    453 		ppp_option_error("unknown host: %s", arg);
    454 		return 0;
    455 	    }
    456 	    local = *(u_int32_t *)hp->h_addr;
    457 	}
    458 	if (ppp_bad_ip_addr(local)) {
    459 	    ppp_option_error("bad local IP address %s", ip_ntoa(local));
    460 	    return 0;
    461 	}
    462 	if (local != 0)
    463 	    wo->ouraddr = local;
    464 	*colon = ':';
    465 	prio_local = option_priority;
    466     }
    467 
    468     /*
    469      * If colon last character, then no remote addr.
    470      */
    471     if (*++colon != '\0' && option_priority >= prio_remote) {
    472 	if ((remote = inet_addr(colon)) == (u_int32_t) -1) {
    473 	    if ((hp = gethostbyname(colon)) == NULL) {
    474 		ppp_option_error("unknown host: %s", colon);
    475 		return 0;
    476 	    }
    477 	    remote = *(u_int32_t *)hp->h_addr;
    478 	    if (remote_name[0] == 0)
    479 		strlcpy(remote_name, colon, sizeof(remote_name));
    480 	}
    481 	if (ppp_bad_ip_addr(remote)) {
    482 	    ppp_option_error("bad remote IP address %s", ip_ntoa(remote));
    483 	    return 0;
    484 	}
    485 	if (remote != 0)
    486 	    wo->hisaddr = remote;
    487 	prio_remote = option_priority;
    488     }
    489 
    490     return 1;
    491 }
    492 
    493 static void
    494 printipaddr(struct option *opt, void (*printer) (void *, char *, ...), void *arg)
    495 {
    496 	ipcp_options *wo = &ipcp_wantoptions[0];
    497 
    498 	if (wo->ouraddr != 0)
    499 		printer(arg, "%I", wo->ouraddr);
    500 	printer(arg, ":");
    501 	if (wo->hisaddr != 0)
    502 		printer(arg, "%I", wo->hisaddr);
    503 }
    504 
    505 /*
    506  * setnetmask - set the netmask to be used on the interface.
    507  */
    508 static int
    509 setnetmask(char **argv)
    510 {
    511     u_int32_t mask;
    512     int n;
    513     char *p;
    514 
    515     /*
    516      * Unfortunately, if we use inet_addr, we can't tell whether
    517      * a result of all 1s is an error or a valid 255.255.255.255.
    518      */
    519     p = *argv;
    520     n = parse_dotted_ip(p, &mask);
    521 
    522     mask = htonl(mask);
    523 
    524     if (n == 0 || p[n] != 0 || (netmask & ~mask) != 0) {
    525 	ppp_option_error("invalid netmask value '%s'", *argv);
    526 	return 0;
    527     }
    528 
    529     netmask = mask;
    530     slprintf(netmask_str, sizeof(netmask_str), "%I", mask);
    531 
    532     return (1);
    533 }
    534 
    535 int
    536 parse_dotted_ip(char *p, u_int32_t *vp)
    537 {
    538     int n;
    539     u_int32_t v, b;
    540     char *endp, *p0 = p;
    541 
    542     v = 0;
    543     for (n = 3;; --n) {
    544 	b = strtoul(p, &endp, 0);
    545 	if (endp == p)
    546 	    return 0;
    547 	if (b > 255) {
    548 	    if (n < 3)
    549 		return 0;
    550 	    /* accept e.g. 0xffffff00 */
    551 	    *vp = b;
    552 	    return endp - p0;
    553 	}
    554 	v |= b << (n * 8);
    555 	p = endp;
    556 	if (n == 0)
    557 	    break;
    558 	if (*p != '.')
    559 	    return 0;
    560 	++p;
    561     }
    562     *vp = v;
    563     return p - p0;
    564 }
    565 
    566 const char *ppp_ipparam()
    567 {
    568     return ipparam;
    569 }
    570 
    571 
    572 /*
    573  * ipcp_init - Initialize IPCP.
    574  */
    575 static void
    576 ipcp_init(int unit)
    577 {
    578     fsm *f = &ipcp_fsm[unit];
    579     ipcp_options *wo = &ipcp_wantoptions[unit];
    580     ipcp_options *ao = &ipcp_allowoptions[unit];
    581 
    582     f->unit = unit;
    583     f->protocol = PPP_IPCP;
    584     f->callbacks = &ipcp_callbacks;
    585     fsm_init(&ipcp_fsm[unit]);
    586 
    587     /*
    588      * Some 3G modems use repeated IPCP NAKs as a way of stalling
    589      * until they can contact a server on the network, so we increase
    590      * the default number of NAKs we accept before we start treating
    591      * them as rejects.
    592      */
    593     f->maxnakloops = 100;
    594 
    595     memset(wo, 0, sizeof(*wo));
    596     memset(ao, 0, sizeof(*ao));
    597 
    598     wo->neg_addr = wo->old_addrs = 1;
    599     wo->neg_vj = 1;
    600     wo->vj_protocol = IPCP_VJ_COMP;
    601     wo->maxslotindex = MAX_STATES - 1; /* really max index */
    602     wo->cflag = 1;
    603 
    604 
    605     /* max slots and slot-id compression are currently hardwired in */
    606     /* ppp_if.c to 16 and 1, this needs to be changed (among other */
    607     /* things) gmc */
    608 
    609     ao->neg_addr = ao->old_addrs = 1;
    610     ao->neg_vj = 1;
    611     ao->maxslotindex = MAX_STATES - 1;
    612     ao->cflag = 1;
    613 
    614     /*
    615      * XXX These control whether the user may use the proxyarp
    616      * and defaultroute options.
    617      */
    618     ao->proxy_arp = 1;
    619     ao->default_route = 1;
    620 }
    621 
    622 
    623 /*
    624  * ipcp_open - IPCP is allowed to come up.
    625  */
    626 static void
    627 ipcp_open(int unit)
    628 {
    629     fsm_open(&ipcp_fsm[unit]);
    630     ipcp_is_open = 1;
    631 }
    632 
    633 
    634 /*
    635  * ipcp_close - Take IPCP down.
    636  */
    637 static void
    638 ipcp_close(int unit, char *reason)
    639 {
    640     fsm_close(&ipcp_fsm[unit], reason);
    641 }
    642 
    643 
    644 /*
    645  * ipcp_lowerup - The lower layer is up.
    646  */
    647 static void
    648 ipcp_lowerup(int unit)
    649 {
    650     fsm_lowerup(&ipcp_fsm[unit]);
    651 }
    652 
    653 
    654 /*
    655  * ipcp_lowerdown - The lower layer is down.
    656  */
    657 static void
    658 ipcp_lowerdown(int unit)
    659 {
    660     fsm_lowerdown(&ipcp_fsm[unit]);
    661 }
    662 
    663 
    664 /*
    665  * ipcp_input - Input IPCP packet.
    666  */
    667 static void
    668 ipcp_input(int unit, u_char *p, int len)
    669 {
    670     fsm_input(&ipcp_fsm[unit], p, len);
    671 }
    672 
    673 
    674 /*
    675  * ipcp_protrej - A Protocol-Reject was received for IPCP.
    676  *
    677  * Pretend the lower layer went down, so we shut up.
    678  */
    679 static void
    680 ipcp_protrej(int unit)
    681 {
    682     fsm_lowerdown(&ipcp_fsm[unit]);
    683 }
    684 
    685 
    686 /*
    687  * ipcp_resetci - Reset our CI.
    688  * Called by fsm_sconfreq, Send Configure Request.
    689  */
    690 static void
    691 ipcp_resetci(fsm *f)
    692 {
    693     ipcp_options *wo = &ipcp_wantoptions[f->unit];
    694     ipcp_options *go = &ipcp_gotoptions[f->unit];
    695     ipcp_options *ao = &ipcp_allowoptions[f->unit];
    696 
    697     wo->req_addr = ((wo->neg_addr || wo->old_addrs) &&
    698 	(ao->neg_addr || ao->old_addrs)) ||
    699 	(wo->hisaddr && !wo->accept_remote);
    700     if (wo->ouraddr == 0)
    701 	wo->accept_local = 1;
    702     if (wo->hisaddr == 0)
    703 	wo->accept_remote = 1;
    704     wo->req_dns1 = usepeerdns;	/* Request DNS addresses from the peer */
    705     wo->req_dns2 = usepeerdns;
    706     wo->req_wins1 = usepeerwins; /* Request WINS addresses from the peer */
    707     wo->req_wins2 = usepeerwins;
    708     *go = *wo;
    709     if (!ask_for_local)
    710 	go->ouraddr = 0;
    711     if (ip_choose_hook) {
    712 	ip_choose_hook(&wo->hisaddr);
    713 	if (wo->hisaddr) {
    714 	    wo->accept_remote = 0;
    715 	}
    716     }
    717     BZERO(&ipcp_hisoptions[f->unit], sizeof(ipcp_options));
    718 }
    719 
    720 
    721 /*
    722  * ipcp_cilen - Return length of our CI.
    723  * Called by fsm_sconfreq, Send Configure Request.
    724  */
    725 static int
    726 ipcp_cilen(fsm *f)
    727 {
    728     ipcp_options *go = &ipcp_gotoptions[f->unit];
    729     ipcp_options *wo = &ipcp_wantoptions[f->unit];
    730     ipcp_options *ho = &ipcp_hisoptions[f->unit];
    731 
    732 #define LENCIADDRS(neg)		(neg ? CILEN_ADDRS : 0)
    733 #define LENCIVJ(neg, old)	(neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0)
    734 #define LENCIADDR(neg)		(neg ? CILEN_ADDR : 0)
    735 #define LENCIDNS(neg)		LENCIADDR(neg)
    736 #define LENCIWINS(neg)		LENCIADDR(neg)
    737 
    738     /*
    739      * First see if we want to change our options to the old
    740      * forms because we have received old forms from the peer.
    741      */
    742     if (go->neg_addr && go->old_addrs && !ho->neg_addr && ho->old_addrs)
    743 	go->neg_addr = 0;
    744     if (wo->neg_vj && !go->neg_vj && !go->old_vj) {
    745 	/* try an older style of VJ negotiation */
    746 	/* use the old style only if the peer did */
    747 	if (ho->neg_vj && ho->old_vj) {
    748 	    go->neg_vj = 1;
    749 	    go->old_vj = 1;
    750 	    go->vj_protocol = ho->vj_protocol;
    751 	}
    752     }
    753 
    754     return (LENCIADDRS(!go->neg_addr && go->old_addrs) +
    755 	    LENCIVJ(go->neg_vj, go->old_vj) +
    756 	    LENCIADDR(go->neg_addr) +
    757 	    LENCIDNS(go->req_dns1) +
    758 	    LENCIDNS(go->req_dns2) +
    759 	    LENCIWINS(go->req_wins1) +
    760 	    LENCIWINS(go->req_wins2)) ;
    761 }
    762 
    763 
    764 /*
    765  * ipcp_addci - Add our desired CIs to a packet.
    766  * Called by fsm_sconfreq, Send Configure Request.
    767  */
    768 static void
    769 ipcp_addci(fsm *f, u_char *ucp, int *lenp)
    770 {
    771     ipcp_options *go = &ipcp_gotoptions[f->unit];
    772     int len = *lenp;
    773 
    774 #define ADDCIADDRS(opt, neg, val1, val2) \
    775     if (neg) { \
    776 	if (len >= CILEN_ADDRS) { \
    777 	    u_int32_t l; \
    778 	    PUTCHAR(opt, ucp); \
    779 	    PUTCHAR(CILEN_ADDRS, ucp); \
    780 	    l = ntohl(val1); \
    781 	    PUTLONG(l, ucp); \
    782 	    l = ntohl(val2); \
    783 	    PUTLONG(l, ucp); \
    784 	    len -= CILEN_ADDRS; \
    785 	} else \
    786 	    go->old_addrs = 0; \
    787     }
    788 
    789 #define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \
    790     if (neg) { \
    791 	int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
    792 	if (len >= vjlen) { \
    793 	    PUTCHAR(opt, ucp); \
    794 	    PUTCHAR(vjlen, ucp); \
    795 	    PUTSHORT(val, ucp); \
    796 	    if (!old) { \
    797 		PUTCHAR(maxslotindex, ucp); \
    798 		PUTCHAR(cflag, ucp); \
    799 	    } \
    800 	    len -= vjlen; \
    801 	} else \
    802 	    neg = 0; \
    803     }
    804 
    805 #define ADDCIADDR(opt, neg, val) \
    806     if (neg) { \
    807 	if (len >= CILEN_ADDR) { \
    808 	    u_int32_t l; \
    809 	    PUTCHAR(opt, ucp); \
    810 	    PUTCHAR(CILEN_ADDR, ucp); \
    811 	    l = ntohl(val); \
    812 	    PUTLONG(l, ucp); \
    813 	    len -= CILEN_ADDR; \
    814 	} else \
    815 	    neg = 0; \
    816     }
    817 
    818 #define ADDCIDNS(opt, neg, addr) \
    819     if (neg) { \
    820 	if (len >= CILEN_ADDR) { \
    821 	    u_int32_t l; \
    822 	    PUTCHAR(opt, ucp); \
    823 	    PUTCHAR(CILEN_ADDR, ucp); \
    824 	    l = ntohl(addr); \
    825 	    PUTLONG(l, ucp); \
    826 	    len -= CILEN_ADDR; \
    827 	} else \
    828 	    neg = 0; \
    829     }
    830 
    831 #define ADDCIWINS(opt, neg, addr) \
    832     if (neg) { \
    833 	if (len >= CILEN_ADDR) { \
    834 	    u_int32_t l; \
    835 	    PUTCHAR(opt, ucp); \
    836 	    PUTCHAR(CILEN_ADDR, ucp); \
    837 	    l = ntohl(addr); \
    838 	    PUTLONG(l, ucp); \
    839 	    len -= CILEN_ADDR; \
    840 	} else \
    841 	    neg = 0; \
    842     }
    843 
    844     ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr,
    845 	       go->hisaddr);
    846 
    847     ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
    848 	    go->maxslotindex, go->cflag);
    849 
    850     ADDCIADDR(CI_ADDR, go->neg_addr, go->ouraddr);
    851 
    852     ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
    853 
    854     ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
    855 
    856     ADDCIWINS(CI_MS_WINS1, go->req_wins1, go->winsaddr[0]);
    857 
    858     ADDCIWINS(CI_MS_WINS2, go->req_wins2, go->winsaddr[1]);
    859 
    860     *lenp -= len;
    861 }
    862 
    863 
    864 /*
    865  * ipcp_ackci - Ack our CIs.
    866  * Called by fsm_rconfack, Receive Configure ACK.
    867  *
    868  * Returns:
    869  *	0 - Ack was bad.
    870  *	1 - Ack was good.
    871  */
    872 static int
    873 ipcp_ackci(fsm *f, u_char *p, int len)
    874 {
    875     ipcp_options *go = &ipcp_gotoptions[f->unit];
    876     u_short cilen, citype, cishort;
    877     u_int32_t cilong;
    878     u_char cimaxslotindex, cicflag;
    879 
    880     /*
    881      * CIs must be in exactly the same order that we sent...
    882      * Check packet length and CI length at each step.
    883      * If we find any deviations, then this packet is bad.
    884      */
    885 
    886 #define ACKCIADDRS(opt, neg, val1, val2) \
    887     if (neg) { \
    888 	u_int32_t l; \
    889 	if ((len -= CILEN_ADDRS) < 0) \
    890 	    goto bad; \
    891 	GETCHAR(citype, p); \
    892 	GETCHAR(cilen, p); \
    893 	if (cilen != CILEN_ADDRS || \
    894 	    citype != opt) \
    895 	    goto bad; \
    896 	GETLONG(l, p); \
    897 	cilong = htonl(l); \
    898 	if (val1 != cilong) \
    899 	    goto bad; \
    900 	GETLONG(l, p); \
    901 	cilong = htonl(l); \
    902 	if (val2 != cilong) \
    903 	    goto bad; \
    904     }
    905 
    906 #define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \
    907     if (neg) { \
    908 	int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
    909 	if ((len -= vjlen) < 0) \
    910 	    goto bad; \
    911 	GETCHAR(citype, p); \
    912 	GETCHAR(cilen, p); \
    913 	if (cilen != vjlen || \
    914 	    citype != opt)  \
    915 	    goto bad; \
    916 	GETSHORT(cishort, p); \
    917 	if (cishort != val) \
    918 	    goto bad; \
    919 	if (!old) { \
    920 	    GETCHAR(cimaxslotindex, p); \
    921 	    if (cimaxslotindex != maxslotindex) \
    922 		goto bad; \
    923 	    GETCHAR(cicflag, p); \
    924 	    if (cicflag != cflag) \
    925 		goto bad; \
    926 	} \
    927     }
    928 
    929 #define ACKCIADDR(opt, neg, val) \
    930     if (neg) { \
    931 	u_int32_t l; \
    932 	if ((len -= CILEN_ADDR) < 0) \
    933 	    goto bad; \
    934 	GETCHAR(citype, p); \
    935 	GETCHAR(cilen, p); \
    936 	if (cilen != CILEN_ADDR || \
    937 	    citype != opt) \
    938 	    goto bad; \
    939 	GETLONG(l, p); \
    940 	cilong = htonl(l); \
    941 	if (val != cilong) \
    942 	    goto bad; \
    943     }
    944 
    945 #define ACKCIDNS(opt, neg, addr) \
    946     if (neg) { \
    947 	u_int32_t l; \
    948 	if ((len -= CILEN_ADDR) < 0) \
    949 	    goto bad; \
    950 	GETCHAR(citype, p); \
    951 	GETCHAR(cilen, p); \
    952 	if (cilen != CILEN_ADDR || citype != opt) \
    953 	    goto bad; \
    954 	GETLONG(l, p); \
    955 	cilong = htonl(l); \
    956 	if (addr != cilong) \
    957 	    goto bad; \
    958     }
    959 
    960 #define ACKCIWINS(opt, neg, addr) \
    961     if (neg) { \
    962 	u_int32_t l; \
    963 	if ((len -= CILEN_ADDR) < 0) \
    964 	    goto bad; \
    965 	GETCHAR(citype, p); \
    966 	GETCHAR(cilen, p); \
    967 	if (cilen != CILEN_ADDR || citype != opt) \
    968 	    goto bad; \
    969 	GETLONG(l, p); \
    970 	cilong = htonl(l); \
    971 	if (addr != cilong) \
    972 	    goto bad; \
    973     }
    974 
    975     ACKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr,
    976 	       go->hisaddr);
    977 
    978     ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
    979 	    go->maxslotindex, go->cflag);
    980 
    981     ACKCIADDR(CI_ADDR, go->neg_addr, go->ouraddr);
    982 
    983     ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
    984 
    985     ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
    986 
    987     ACKCIWINS(CI_MS_WINS1, go->req_wins1, go->winsaddr[0]);
    988 
    989     ACKCIWINS(CI_MS_WINS2, go->req_wins2, go->winsaddr[1]);
    990 
    991     /*
    992      * If there are any remaining CIs, then this packet is bad.
    993      */
    994     if (len != 0)
    995 	goto bad;
    996     return (1);
    997 
    998 bad:
    999     IPCPDEBUG(("ipcp_ackci: received bad Ack!"));
   1000     return (0);
   1001 }
   1002 
   1003 /*
   1004  * ipcp_nakci - Peer has sent a NAK for some of our CIs.
   1005  * This should not modify any state if the Nak is bad
   1006  * or if IPCP is in the OPENED state.
   1007  * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
   1008  *
   1009  * Returns:
   1010  *	0 - Nak was bad.
   1011  *	1 - Nak was good.
   1012  */
   1013 static int
   1014 ipcp_nakci(fsm *f, u_char *p, int len, int treat_as_reject)
   1015 {
   1016     ipcp_options *wo = &ipcp_wantoptions[f->unit];
   1017     ipcp_options *go = &ipcp_gotoptions[f->unit];
   1018     u_char cimaxslotindex, cicflag;
   1019     u_char citype, cilen, *next;
   1020     u_short cishort;
   1021     u_int32_t ciaddr1, ciaddr2, l, cidnsaddr, ciwinsaddr;
   1022     ipcp_options no;		/* options we've seen Naks for */
   1023     ipcp_options try;		/* options to request next time */
   1024 
   1025     BZERO(&no, sizeof(no));
   1026     try = *go;
   1027 
   1028     /*
   1029      * Any Nak'd CIs must be in exactly the same order that we sent.
   1030      * Check packet length and CI length at each step.
   1031      * If we find any deviations, then this packet is bad.
   1032      */
   1033 #define NAKCIADDRS(opt, neg, code) \
   1034     if ((neg) && \
   1035 	(cilen = p[1]) == CILEN_ADDRS && \
   1036 	len >= cilen && \
   1037 	p[0] == opt) { \
   1038 	len -= cilen; \
   1039 	INCPTR(2, p); \
   1040 	GETLONG(l, p); \
   1041 	ciaddr1 = htonl(l); \
   1042 	GETLONG(l, p); \
   1043 	ciaddr2 = htonl(l); \
   1044 	no.old_addrs = 1; \
   1045 	code \
   1046     }
   1047 
   1048 #define NAKCIVJ(opt, neg, code) \
   1049     if (go->neg && \
   1050 	((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \
   1051 	len >= cilen && \
   1052 	p[0] == opt) { \
   1053 	len -= cilen; \
   1054 	INCPTR(2, p); \
   1055 	GETSHORT(cishort, p); \
   1056 	no.neg = 1; \
   1057         code \
   1058     }
   1059 
   1060 #define NAKCIADDR(opt, neg, code) \
   1061     if (go->neg && \
   1062 	(cilen = p[1]) == CILEN_ADDR && \
   1063 	len >= cilen && \
   1064 	p[0] == opt) { \
   1065 	len -= cilen; \
   1066 	INCPTR(2, p); \
   1067 	GETLONG(l, p); \
   1068 	ciaddr1 = htonl(l); \
   1069 	no.neg = 1; \
   1070 	code \
   1071     }
   1072 
   1073 #define NAKCIDNS(opt, neg, code) \
   1074     if (go->neg && \
   1075 	((cilen = p[1]) == CILEN_ADDR) && \
   1076 	len >= cilen && \
   1077 	p[0] == opt) { \
   1078 	len -= cilen; \
   1079 	INCPTR(2, p); \
   1080 	GETLONG(l, p); \
   1081 	cidnsaddr = htonl(l); \
   1082 	no.neg = 1; \
   1083 	code \
   1084     }
   1085 
   1086 #define NAKCIWINS(opt, neg, code) \
   1087     if (go->neg && \
   1088 	((cilen = p[1]) == CILEN_ADDR) && \
   1089 	len >= cilen && \
   1090 	p[0] == opt) { \
   1091 	len -= cilen; \
   1092 	INCPTR(2, p); \
   1093 	GETLONG(l, p); \
   1094 	ciwinsaddr = htonl(l); \
   1095 	no.neg = 1; \
   1096 	code \
   1097     }
   1098 
   1099     /*
   1100      * Accept the peer's idea of {our,his} address, if different
   1101      * from our idea, only if the accept_{local,remote} flag is set.
   1102      */
   1103     NAKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs,
   1104 	       if (treat_as_reject) {
   1105 		   try.old_addrs = 0;
   1106 	       } else {
   1107 		   if (go->accept_local && ciaddr1) {
   1108 		       /* take his idea of our address */
   1109 		       try.ouraddr = ciaddr1;
   1110 		   }
   1111 		   if (go->accept_remote && ciaddr2) {
   1112 		       /* take his idea of his address */
   1113 		       try.hisaddr = ciaddr2;
   1114 		   }
   1115 	       }
   1116 	);
   1117 
   1118     /*
   1119      * Accept the peer's value of maxslotindex provided that it
   1120      * is less than what we asked for.  Turn off slot-ID compression
   1121      * if the peer wants.  Send old-style compress-type option if
   1122      * the peer wants.
   1123      */
   1124     NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
   1125 	    if (treat_as_reject) {
   1126 		try.neg_vj = 0;
   1127 	    } else if (cilen == CILEN_VJ) {
   1128 		GETCHAR(cimaxslotindex, p);
   1129 		GETCHAR(cicflag, p);
   1130 		if (cishort == IPCP_VJ_COMP) {
   1131 		    try.old_vj = 0;
   1132 		    if (cimaxslotindex < go->maxslotindex)
   1133 			try.maxslotindex = cimaxslotindex;
   1134 		    if (!cicflag)
   1135 			try.cflag = 0;
   1136 		} else {
   1137 		    try.neg_vj = 0;
   1138 		}
   1139 	    } else {
   1140 		if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) {
   1141 		    try.old_vj = 1;
   1142 		    try.vj_protocol = cishort;
   1143 		} else {
   1144 		    try.neg_vj = 0;
   1145 		}
   1146 	    }
   1147 	    );
   1148 
   1149     NAKCIADDR(CI_ADDR, neg_addr,
   1150 	      if (treat_as_reject) {
   1151 		  try.neg_addr = 0;
   1152 		  try.old_addrs = 0;
   1153 	      } else if (go->accept_local && ciaddr1) {
   1154 		  /* take his idea of our address */
   1155 		  try.ouraddr = ciaddr1;
   1156 	      }
   1157 	      );
   1158 
   1159     NAKCIDNS(CI_MS_DNS1, req_dns1,
   1160 	     if (treat_as_reject) {
   1161 		 try.req_dns1 = 0;
   1162 	     } else {
   1163 		 try.dnsaddr[0] = cidnsaddr;
   1164 	     }
   1165 	     );
   1166 
   1167     NAKCIDNS(CI_MS_DNS2, req_dns2,
   1168 	     if (treat_as_reject) {
   1169 		 try.req_dns2 = 0;
   1170 	     } else {
   1171 		 try.dnsaddr[1] = cidnsaddr;
   1172 	     }
   1173 	     );
   1174 
   1175     NAKCIWINS(CI_MS_WINS1, req_wins1,
   1176 	     if (treat_as_reject) {
   1177 		 try.req_wins1 = 0;
   1178 	     } else {
   1179 		 try.winsaddr[0] = ciwinsaddr;
   1180 	     }
   1181 	     );
   1182 
   1183     NAKCIWINS(CI_MS_WINS2, req_wins2,
   1184 	     if (treat_as_reject) {
   1185 		 try.req_wins2 = 0;
   1186 	     } else {
   1187 		 try.winsaddr[1] = ciwinsaddr;
   1188 	     }
   1189 	     );
   1190 
   1191     /*
   1192      * There may be remaining CIs, if the peer is requesting negotiation
   1193      * on an option that we didn't include in our request packet.
   1194      * If they want to negotiate about IP addresses, we comply.
   1195      * If they want us to ask for compression, we refuse.
   1196      * If they want us to ask for ms-dns, we do that, since some
   1197      * peers get huffy if we don't.
   1198      */
   1199     while (len >= CILEN_VOID) {
   1200 	GETCHAR(citype, p);
   1201 	GETCHAR(cilen, p);
   1202 	if ( cilen < CILEN_VOID || (len -= cilen) < 0 )
   1203 	    goto bad;
   1204 	next = p + cilen - 2;
   1205 
   1206 	switch (citype) {
   1207 	case CI_COMPRESSTYPE:
   1208 	    if (go->neg_vj || no.neg_vj ||
   1209 		(cilen != CILEN_VJ && cilen != CILEN_COMPRESS))
   1210 		goto bad;
   1211 	    no.neg_vj = 1;
   1212 	    break;
   1213 	case CI_ADDRS:
   1214 	    if ((!go->neg_addr && go->old_addrs) || no.old_addrs
   1215 		|| cilen != CILEN_ADDRS)
   1216 		goto bad;
   1217 	    try.neg_addr = 0;
   1218 	    GETLONG(l, p);
   1219 	    ciaddr1 = htonl(l);
   1220 	    if (ciaddr1 && go->accept_local)
   1221 		try.ouraddr = wo->old_addrs ? ciaddr1 : 0;
   1222 	    GETLONG(l, p);
   1223 	    ciaddr2 = htonl(l);
   1224 	    if (ciaddr2 && go->accept_remote)
   1225 		try.hisaddr = ciaddr2;
   1226 	    no.old_addrs = 1;
   1227 	    break;
   1228 	case CI_ADDR:
   1229 	    if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR)
   1230 		goto bad;
   1231 	    try.old_addrs = 0;
   1232 	    GETLONG(l, p);
   1233 	    ciaddr1 = htonl(l);
   1234 	    if (ciaddr1 && go->accept_local)
   1235 		try.ouraddr = ciaddr1;
   1236 	    if (try.ouraddr != 0 && wo->neg_addr)
   1237 		try.neg_addr = 1;
   1238 	    no.neg_addr = 1;
   1239 	    break;
   1240 	case CI_MS_DNS1:
   1241 	    if (go->req_dns1 || no.req_dns1 || cilen != CILEN_ADDR)
   1242 		goto bad;
   1243 	    GETLONG(l, p);
   1244 	    try.dnsaddr[0] = htonl(l);
   1245 	    try.req_dns1 = 1;
   1246 	    no.req_dns1 = 1;
   1247 	    break;
   1248 	case CI_MS_DNS2:
   1249 	    if (go->req_dns2 || no.req_dns2 || cilen != CILEN_ADDR)
   1250 		goto bad;
   1251 	    GETLONG(l, p);
   1252 	    try.dnsaddr[1] = htonl(l);
   1253 	    try.req_dns2 = 1;
   1254 	    no.req_dns2 = 1;
   1255 	    break;
   1256 	case CI_MS_WINS1:
   1257 	    if (go->req_wins1 || no.req_wins1 || cilen != CILEN_ADDR)
   1258 		goto bad;
   1259 	    GETLONG(l, p);
   1260 	    try.winsaddr[0] = htonl(l);
   1261 	    try.req_wins1 = 1;
   1262 	    no.req_wins1 = 1;
   1263 	    break;
   1264 	case CI_MS_WINS2:
   1265 	    if (go->req_wins2 || no.req_wins2 || cilen != CILEN_ADDR)
   1266 		goto bad;
   1267 	    GETLONG(l, p);
   1268 	    try.winsaddr[1] = htonl(l);
   1269 	    try.req_wins2 = 1;
   1270 	    no.req_wins2 = 1;
   1271 	    break;
   1272 	}
   1273 	p = next;
   1274     }
   1275 
   1276     /*
   1277      * OK, the Nak is good.  Now we can update state.
   1278      * If there are any remaining options, we ignore them.
   1279      */
   1280     if (f->state != OPENED)
   1281 	*go = try;
   1282 
   1283     return 1;
   1284 
   1285 bad:
   1286     IPCPDEBUG(("ipcp_nakci: received bad Nak!"));
   1287     return 0;
   1288 }
   1289 
   1290 /*
   1291  * ipcp_rejci - Reject some of our CIs.
   1292  * Callback from fsm_rconfnakrej.
   1293  */
   1294 static int
   1295 ipcp_rejci(fsm *f, u_char *p, int len)
   1296 {
   1297     ipcp_options *go = &ipcp_gotoptions[f->unit];
   1298     u_char cimaxslotindex, ciflag, cilen;
   1299     u_short cishort;
   1300     u_int32_t cilong;
   1301     ipcp_options try;		/* options to request next time */
   1302 
   1303     try = *go;
   1304     /*
   1305      * Any Rejected CIs must be in exactly the same order that we sent.
   1306      * Check packet length and CI length at each step.
   1307      * If we find any deviations, then this packet is bad.
   1308      */
   1309 #define REJCIADDRS(opt, neg, val1, val2) \
   1310     if ((neg) && \
   1311 	(cilen = p[1]) == CILEN_ADDRS && \
   1312 	len >= cilen && \
   1313 	p[0] == opt) { \
   1314 	u_int32_t l; \
   1315 	len -= cilen; \
   1316 	INCPTR(2, p); \
   1317 	GETLONG(l, p); \
   1318 	cilong = htonl(l); \
   1319 	/* Check rejected value. */ \
   1320 	if (cilong != val1) \
   1321 	    goto bad; \
   1322 	GETLONG(l, p); \
   1323 	cilong = htonl(l); \
   1324 	/* Check rejected value. */ \
   1325 	if (cilong != val2) \
   1326 	    goto bad; \
   1327 	try.old_addrs = 0; \
   1328     }
   1329 
   1330 #define REJCIVJ(opt, neg, val, old, maxslot, cflag) \
   1331     if (go->neg && \
   1332 	p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \
   1333 	len >= p[1] && \
   1334 	p[0] == opt) { \
   1335 	len -= p[1]; \
   1336 	INCPTR(2, p); \
   1337 	GETSHORT(cishort, p); \
   1338 	/* Check rejected value. */  \
   1339 	if (cishort != val) \
   1340 	    goto bad; \
   1341 	if (!old) { \
   1342 	   GETCHAR(cimaxslotindex, p); \
   1343 	   if (cimaxslotindex != maxslot) \
   1344 	     goto bad; \
   1345 	   GETCHAR(ciflag, p); \
   1346 	   if (ciflag != cflag) \
   1347 	     goto bad; \
   1348         } \
   1349 	try.neg = 0; \
   1350      }
   1351 
   1352 #define REJCIADDR(opt, neg, val) \
   1353     if (go->neg && \
   1354 	(cilen = p[1]) == CILEN_ADDR && \
   1355 	len >= cilen && \
   1356 	p[0] == opt) { \
   1357 	u_int32_t l; \
   1358 	len -= cilen; \
   1359 	INCPTR(2, p); \
   1360 	GETLONG(l, p); \
   1361 	cilong = htonl(l); \
   1362 	/* Check rejected value. */ \
   1363 	if (cilong != val) \
   1364 	    goto bad; \
   1365 	try.neg = 0; \
   1366     }
   1367 
   1368 #define REJCIDNS(opt, neg, dnsaddr) \
   1369     if (go->neg && \
   1370 	((cilen = p[1]) == CILEN_ADDR) && \
   1371 	len >= cilen && \
   1372 	p[0] == opt) { \
   1373 	u_int32_t l; \
   1374 	len -= cilen; \
   1375 	INCPTR(2, p); \
   1376 	GETLONG(l, p); \
   1377 	cilong = htonl(l); \
   1378 	/* Check rejected value. */ \
   1379 	if (cilong != dnsaddr) \
   1380 	    goto bad; \
   1381 	try.neg = 0; \
   1382     }
   1383 
   1384 #define REJCIWINS(opt, neg, addr) \
   1385     if (go->neg && \
   1386 	((cilen = p[1]) == CILEN_ADDR) && \
   1387 	len >= cilen && \
   1388 	p[0] == opt) { \
   1389 	u_int32_t l; \
   1390 	len -= cilen; \
   1391 	INCPTR(2, p); \
   1392 	GETLONG(l, p); \
   1393 	cilong = htonl(l); \
   1394 	/* Check rejected value. */ \
   1395 	if (cilong != addr) \
   1396 	    goto bad; \
   1397 	try.neg = 0; \
   1398     }
   1399 
   1400     REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs,
   1401 	       go->ouraddr, go->hisaddr);
   1402 
   1403     REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj,
   1404 	    go->maxslotindex, go->cflag);
   1405 
   1406     REJCIADDR(CI_ADDR, neg_addr, go->ouraddr);
   1407 
   1408     REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]);
   1409 
   1410     REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]);
   1411 
   1412     REJCIWINS(CI_MS_WINS1, req_wins1, go->winsaddr[0]);
   1413 
   1414     REJCIWINS(CI_MS_WINS2, req_wins2, go->winsaddr[1]);
   1415 
   1416     /*
   1417      * If there are any remaining CIs, then this packet is bad.
   1418      */
   1419     if (len != 0)
   1420 	goto bad;
   1421     /*
   1422      * Now we can update state.
   1423      */
   1424     if (f->state != OPENED)
   1425 	*go = try;
   1426     return 1;
   1427 
   1428 bad:
   1429     IPCPDEBUG(("ipcp_rejci: received bad Reject!"));
   1430     return 0;
   1431 }
   1432 
   1433 
   1434 /*
   1435  * ipcp_reqci - Check the peer's requested CIs and send appropriate response.
   1436  * Callback from fsm_rconfreq, Receive Configure Request
   1437  *
   1438  * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
   1439  * appropriately.  If reject_if_disagree is non-zero, doesn't return
   1440  * CONFNAK; returns CONFREJ if it can't return CONFACK.
   1441  */
   1442 static int
   1443 ipcp_reqci(fsm *f, u_char *inp,	int *len, int reject_if_disagree)
   1444 {
   1445     ipcp_options *wo = &ipcp_wantoptions[f->unit];
   1446     ipcp_options *ho = &ipcp_hisoptions[f->unit];
   1447     ipcp_options *ao = &ipcp_allowoptions[f->unit];
   1448     u_char *cip, *next;		/* Pointer to current and next CIs */
   1449     u_int32_t cilen, citype;	/* Parsed len, type */
   1450     u_short cishort;		/* Parsed short value */
   1451     u_int32_t tl, ciaddr1, ciaddr2;/* Parsed address values */
   1452     int rc = CONFACK;		/* Final packet return code */
   1453     int orc;			/* Individual option return code */
   1454     u_char *p;			/* Pointer to next char to parse */
   1455     u_char *ucp = inp;		/* Pointer to current output char */
   1456     u_int32_t l = *len;		/* Length left */
   1457     u_char maxslotindex, cflag;
   1458     int d;
   1459 
   1460     /*
   1461      * Reset all his options.
   1462      */
   1463     BZERO(ho, sizeof(*ho));
   1464 
   1465     /*
   1466      * Process all his options.
   1467      */
   1468     next = inp;
   1469     while (l) {
   1470 	orc = CONFACK;			/* Assume success */
   1471 	cip = p = next;			/* Remember begining of CI */
   1472 	if (l < 2 ||			/* Not enough data for CI header or */
   1473 	    p[1] < 2 ||			/*  CI length too small or */
   1474 	    p[1] > l) {			/*  CI length too big? */
   1475 	    IPCPDEBUG(("ipcp_reqci: bad CI length!"));
   1476 	    orc = CONFREJ;		/* Reject bad CI */
   1477 	    cilen = l;			/* Reject till end of packet */
   1478 	    l = 0;			/* Don't loop again */
   1479 	    goto endswitch;
   1480 	}
   1481 	GETCHAR(citype, p);		/* Parse CI type */
   1482 	GETCHAR(cilen, p);		/* Parse CI length */
   1483 	l -= cilen;			/* Adjust remaining length */
   1484 	next += cilen;			/* Step to next CI */
   1485 
   1486 	switch (citype) {		/* Check CI type */
   1487 	case CI_ADDRS:
   1488 	    if (!ao->old_addrs || ho->neg_addr ||
   1489 		cilen != CILEN_ADDRS) {	/* Check CI length */
   1490 		orc = CONFREJ;		/* Reject CI */
   1491 		break;
   1492 	    }
   1493 
   1494 	    /*
   1495 	     * If he has no address, or if we both have his address but
   1496 	     * disagree about it, then NAK it with our idea.
   1497 	     * In particular, if we don't know his address, but he does,
   1498 	     * then accept it.
   1499 	     */
   1500 	    GETLONG(tl, p);		/* Parse source address (his) */
   1501 	    ciaddr1 = htonl(tl);
   1502 	    if (ciaddr1 != wo->hisaddr
   1503 		&& (ciaddr1 == 0 || !wo->accept_remote)) {
   1504 		orc = CONFNAK;
   1505 		if (!reject_if_disagree) {
   1506 		    DECPTR(sizeof(u_int32_t), p);
   1507 		    tl = ntohl(wo->hisaddr);
   1508 		    PUTLONG(tl, p);
   1509 		}
   1510 	    } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
   1511 		/*
   1512 		 * If neither we nor he knows his address, reject the option.
   1513 		 */
   1514 		orc = CONFREJ;
   1515 		wo->req_addr = 0;	/* don't NAK with 0.0.0.0 later */
   1516 		break;
   1517 	    }
   1518 
   1519 	    /*
   1520 	     * If he doesn't know our address, or if we both have our address
   1521 	     * but disagree about it, then NAK it with our idea.
   1522 	     */
   1523 	    GETLONG(tl, p);		/* Parse desination address (ours) */
   1524 	    ciaddr2 = htonl(tl);
   1525 	    if (ciaddr2 != wo->ouraddr) {
   1526 		if (ciaddr2 == 0 || !wo->accept_local) {
   1527 		    orc = CONFNAK;
   1528 		    if (!reject_if_disagree && wo->old_addrs) {
   1529 			DECPTR(sizeof(u_int32_t), p);
   1530 			tl = ntohl(wo->ouraddr);
   1531 			PUTLONG(tl, p);
   1532 		    }
   1533 		} else {
   1534 		    wo->ouraddr = ciaddr2;	/* accept peer's idea */
   1535 		}
   1536 	    }
   1537 
   1538 	    ho->old_addrs = 1;
   1539 	    ho->hisaddr = ciaddr1;
   1540 	    ho->ouraddr = ciaddr2;
   1541 	    break;
   1542 
   1543 	case CI_ADDR:
   1544 	    if (!ao->neg_addr || ho->old_addrs ||
   1545 		cilen != CILEN_ADDR) {	/* Check CI length */
   1546 		orc = CONFREJ;		/* Reject CI */
   1547 		break;
   1548 	    }
   1549 
   1550 	    /*
   1551 	     * If he has no address, or if we both have his address but
   1552 	     * disagree about it, then NAK it with our idea.
   1553 	     * In particular, if we don't know his address, but he does,
   1554 	     * then accept it.
   1555 	     */
   1556 	    GETLONG(tl, p);	/* Parse source address (his) */
   1557 	    ciaddr1 = htonl(tl);
   1558 	    if (ciaddr1 != wo->hisaddr
   1559 		&& (ciaddr1 == 0 || !wo->accept_remote)) {
   1560 		orc = CONFNAK;
   1561 		if (!reject_if_disagree) {
   1562 		    DECPTR(sizeof(u_int32_t), p);
   1563 		    tl = ntohl(wo->hisaddr);
   1564 		    PUTLONG(tl, p);
   1565 		}
   1566 	    } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
   1567 		/*
   1568 		 * Don't ACK an address of 0.0.0.0 - reject it instead.
   1569 		 */
   1570 		orc = CONFREJ;
   1571 		wo->req_addr = 0;	/* don't NAK with 0.0.0.0 later */
   1572 		break;
   1573 	    }
   1574 
   1575 	    ho->neg_addr = 1;
   1576 	    ho->hisaddr = ciaddr1;
   1577 	    break;
   1578 
   1579 	case CI_MS_DNS1:
   1580 	case CI_MS_DNS2:
   1581 	    /* Microsoft primary or secondary DNS request */
   1582 	    d = citype == CI_MS_DNS2;
   1583 
   1584 	    /* If we do not have a DNS address then we cannot send it */
   1585 	    if (ao->dnsaddr[d] == 0 ||
   1586 		cilen != CILEN_ADDR) {	/* Check CI length */
   1587 		orc = CONFREJ;		/* Reject CI */
   1588 		break;
   1589 	    }
   1590 	    GETLONG(tl, p);
   1591 	    if (htonl(tl) != ao->dnsaddr[d]) {
   1592                 DECPTR(sizeof(u_int32_t), p);
   1593 		tl = ntohl(ao->dnsaddr[d]);
   1594 		PUTLONG(tl, p);
   1595 		orc = CONFNAK;
   1596             }
   1597             break;
   1598 
   1599 	case CI_MS_WINS1:
   1600 	case CI_MS_WINS2:
   1601 	    /* Microsoft primary or secondary WINS request */
   1602 	    d = citype == CI_MS_WINS2;
   1603 
   1604 	    /* If we do not have a WINS address then we cannot send it */
   1605 	    if (ao->winsaddr[d] == 0 ||
   1606 		cilen != CILEN_ADDR) {	/* Check CI length */
   1607 		orc = CONFREJ;		/* Reject CI */
   1608 		break;
   1609 	    }
   1610 	    GETLONG(tl, p);
   1611 	    if (htonl(tl) != ao->winsaddr[d]) {
   1612                 DECPTR(sizeof(u_int32_t), p);
   1613 		tl = ntohl(ao->winsaddr[d]);
   1614 		PUTLONG(tl, p);
   1615 		orc = CONFNAK;
   1616             }
   1617             break;
   1618 
   1619 	case CI_COMPRESSTYPE:
   1620 	    if (!ao->neg_vj ||
   1621 		(cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) {
   1622 		orc = CONFREJ;
   1623 		break;
   1624 	    }
   1625 	    GETSHORT(cishort, p);
   1626 
   1627 	    if (!(cishort == IPCP_VJ_COMP ||
   1628 		  (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {
   1629 		orc = CONFREJ;
   1630 		break;
   1631 	    }
   1632 
   1633 	    ho->neg_vj = 1;
   1634 	    ho->vj_protocol = cishort;
   1635 	    if (cilen == CILEN_VJ) {
   1636 		GETCHAR(maxslotindex, p);
   1637 		if (maxslotindex > ao->maxslotindex) {
   1638 		    orc = CONFNAK;
   1639 		    if (!reject_if_disagree){
   1640 			DECPTR(1, p);
   1641 			PUTCHAR(ao->maxslotindex, p);
   1642 		    }
   1643 		}
   1644 		GETCHAR(cflag, p);
   1645 		if (cflag && !ao->cflag) {
   1646 		    orc = CONFNAK;
   1647 		    if (!reject_if_disagree){
   1648 			DECPTR(1, p);
   1649 			PUTCHAR(wo->cflag, p);
   1650 		    }
   1651 		}
   1652 		ho->maxslotindex = maxslotindex;
   1653 		ho->cflag = cflag;
   1654 	    } else {
   1655 		ho->old_vj = 1;
   1656 		ho->maxslotindex = MAX_STATES - 1;
   1657 		ho->cflag = 1;
   1658 	    }
   1659 	    break;
   1660 
   1661 	default:
   1662 	    orc = CONFREJ;
   1663 	    break;
   1664 	}
   1665 endswitch:
   1666 	if (orc == CONFACK &&		/* Good CI */
   1667 	    rc != CONFACK)		/*  but prior CI wasnt? */
   1668 	    continue;			/* Don't send this one */
   1669 
   1670 	if (orc == CONFNAK) {		/* Nak this CI? */
   1671 	    if (reject_if_disagree)	/* Getting fed up with sending NAKs? */
   1672 		orc = CONFREJ;		/* Get tough if so */
   1673 	    else {
   1674 		if (rc == CONFREJ)	/* Rejecting prior CI? */
   1675 		    continue;		/* Don't send this one */
   1676 		if (rc == CONFACK) {	/* Ack'd all prior CIs? */
   1677 		    rc = CONFNAK;	/* Not anymore... */
   1678 		    ucp = inp;		/* Backup */
   1679 		}
   1680 	    }
   1681 	}
   1682 
   1683 	if (orc == CONFREJ &&		/* Reject this CI */
   1684 	    rc != CONFREJ) {		/*  but no prior ones? */
   1685 	    rc = CONFREJ;
   1686 	    ucp = inp;			/* Backup */
   1687 	}
   1688 
   1689 	/* Need to move CI? */
   1690 	if (ucp != cip)
   1691 	    BCOPY(cip, ucp, cilen);	/* Move it */
   1692 
   1693 	/* Update output pointer */
   1694 	INCPTR(cilen, ucp);
   1695     }
   1696 
   1697     /*
   1698      * If we aren't rejecting this packet, and we want to negotiate
   1699      * their address, and they didn't send their address, then we
   1700      * send a NAK with a CI_ADDR option appended.  We assume the
   1701      * input buffer is long enough that we can append the extra
   1702      * option safely.
   1703      */
   1704     if (rc != CONFREJ && !ho->neg_addr && !ho->old_addrs &&
   1705 	wo->req_addr && !reject_if_disagree &&
   1706 	((wo->hisaddr && !wo->accept_remote) || !noremoteip)) {
   1707 	if (rc == CONFACK) {
   1708 	    rc = CONFNAK;
   1709 	    ucp = inp;			/* reset pointer */
   1710 	    wo->req_addr = 0;		/* don't ask again */
   1711 	}
   1712 	PUTCHAR(CI_ADDR, ucp);
   1713 	PUTCHAR(CILEN_ADDR, ucp);
   1714 	tl = ntohl(wo->hisaddr);
   1715 	PUTLONG(tl, ucp);
   1716     }
   1717 
   1718     *len = ucp - inp;			/* Compute output length */
   1719     IPCPDEBUG(("ipcp: returning Configure-%s", CODENAME(rc)));
   1720     return (rc);			/* Return final code */
   1721 }
   1722 
   1723 
   1724 /*
   1725  * ip_check_options - check that any IP-related options are OK,
   1726  * and assign appropriate defaults.
   1727  */
   1728 static void
   1729 ip_check_options(void)
   1730 {
   1731     struct hostent *hp;
   1732     u_int32_t local;
   1733     ipcp_options *wo = &ipcp_wantoptions[0];
   1734 
   1735     /*
   1736      * Default our local IP address based on our hostname.
   1737      * If local IP address already given, don't bother.
   1738      */
   1739     if (wo->ouraddr == 0 && !disable_defaultip) {
   1740 	/*
   1741 	 * Look up our hostname (possibly with domain name appended)
   1742 	 * and take the first IP address as our local IP address.
   1743 	 * If there isn't an IP address for our hostname, too bad.
   1744 	 */
   1745 	wo->accept_local = 1;	/* don't insist on this default value */
   1746 	if ((hp = gethostbyname(hostname)) != NULL) {
   1747 	    local = *(u_int32_t *)hp->h_addr;
   1748 	    if (local != 0 && !ppp_bad_ip_addr(local))
   1749 		wo->ouraddr = local;
   1750 	}
   1751     }
   1752     ask_for_local = wo->ouraddr != 0 || !disable_defaultip;
   1753 }
   1754 
   1755 
   1756 /*
   1757  * ip_demand_conf - configure the interface as though
   1758  * IPCP were up, for use with dial-on-demand.
   1759  */
   1760 static int
   1761 ip_demand_conf(int u)
   1762 {
   1763     ipcp_options *wo = &ipcp_wantoptions[u];
   1764 
   1765     if (wo->hisaddr == 0 && !noremoteip) {
   1766 	/* make up an arbitrary address for the peer */
   1767 	wo->hisaddr = htonl(0x0a707070 + ifunit);
   1768 	wo->accept_remote = 1;
   1769     }
   1770     if (wo->ouraddr == 0) {
   1771 	/* make up an arbitrary address for us */
   1772 	wo->ouraddr = htonl(0x0a404040 + ifunit);
   1773 	wo->accept_local = 1;
   1774 	ask_for_local = 0;	/* don't tell the peer this address */
   1775     }
   1776     if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr)))
   1777 	return 0;
   1778     ipcp_script(path_ippreup, 1);
   1779     if (!sifup(u))
   1780 	return 0;
   1781     if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
   1782 	return 0;
   1783     if (wo->default_route)
   1784 	if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr,
   1785 					    wo->replace_default_route))
   1786 	    default_route_set[u] = 1;
   1787     if (wo->proxy_arp)
   1788 	if (sifproxyarp(u, wo->hisaddr))
   1789 	    proxy_arp_set[u] = 1;
   1790 
   1791     notice("local  IP address %I", wo->ouraddr);
   1792     if (wo->hisaddr)
   1793 	notice("remote IP address %I", wo->hisaddr);
   1794 
   1795     return 1;
   1796 }
   1797 
   1798 
   1799 /*
   1800  * ipcp_up - IPCP has come UP.
   1801  *
   1802  * Configure the IP network interface appropriately and bring it up.
   1803  */
   1804 static void
   1805 ipcp_up(fsm *f)
   1806 {
   1807     u_int32_t mask;
   1808     ipcp_options *ho = &ipcp_hisoptions[f->unit];
   1809     ipcp_options *go = &ipcp_gotoptions[f->unit];
   1810     ipcp_options *wo = &ipcp_wantoptions[f->unit];
   1811     int ifindex;
   1812 
   1813     IPCPDEBUG(("ipcp: up"));
   1814 
   1815     /*
   1816      * We must have a non-zero IP address for both ends of the link.
   1817      */
   1818 
   1819     if (wo->hisaddr && !wo->accept_remote && (!(ho->neg_addr || ho->old_addrs) || ho->hisaddr != wo->hisaddr)) {
   1820 	error("Peer refused to agree to his IP address");
   1821 	ipcp_close(f->unit, "Refused his IP address");
   1822 	return;
   1823     }
   1824     if (!ho->neg_addr && !ho->old_addrs)
   1825 	ho->hisaddr = wo->hisaddr;
   1826 
   1827     if (!(go->neg_addr || go->old_addrs) && (wo->neg_addr || wo->old_addrs)
   1828 	&& wo->ouraddr != 0) {
   1829 	error("Peer refused to agree to our IP address");
   1830 	ipcp_close(f->unit, "Refused our IP address");
   1831 	return;
   1832     }
   1833     if (go->ouraddr == 0) {
   1834 	error("Could not determine local IP address");
   1835 	ipcp_close(f->unit, "Could not determine local IP address");
   1836 	return;
   1837     }
   1838     if (ho->hisaddr == 0 && !noremoteip) {
   1839 	ho->hisaddr = htonl(0x0a404040 + ifunit);
   1840 	warn("Could not determine remote IP address: defaulting to %I",
   1841 	     ho->hisaddr);
   1842     }
   1843     ppp_script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0);
   1844     if (ho->hisaddr != 0)
   1845 	ppp_script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1);
   1846 
   1847     if (!go->req_dns1)
   1848 	    go->dnsaddr[0] = 0;
   1849     if (!go->req_dns2)
   1850 	    go->dnsaddr[1] = 0;
   1851     if (go->dnsaddr[0])
   1852 	ppp_script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0);
   1853     if (go->dnsaddr[1])
   1854 	ppp_script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0);
   1855     if (usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) {
   1856 	ppp_script_setenv("USEPEERDNS", "1", 0);
   1857 	create_resolv(go->dnsaddr[0], go->dnsaddr[1]);
   1858     }
   1859 
   1860     if (go->winsaddr[0])
   1861         ppp_script_setenv("WINS1", ip_ntoa(go->winsaddr[0]), 0);
   1862     if (go->winsaddr[1])
   1863         ppp_script_setenv("WINS2", ip_ntoa(go->winsaddr[1]), 0);
   1864     if (usepeerwins && (go->winsaddr[0] || go->winsaddr[1]))
   1865         ppp_script_setenv("USEPEERWINS", "1", 0);
   1866 
   1867     /*
   1868      * Check that the peer is allowed to use the IP address it wants.
   1869      */
   1870     if (ho->hisaddr != 0 && !auth_ip_addr(f->unit, ho->hisaddr)) {
   1871 	error("Peer is not authorized to use remote address %I", ho->hisaddr);
   1872 	ipcp_close(f->unit, "Unauthorized remote IP address");
   1873 	return;
   1874     }
   1875 
   1876     /* set tcp compression */
   1877     sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex);
   1878 
   1879     /*
   1880      * If we are doing dial-on-demand, the interface is already
   1881      * configured, so we put out any saved-up packets, then set the
   1882      * interface to pass IP packets.
   1883      */
   1884     if (demand) {
   1885 	if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
   1886 	    ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr,
   1887 				      wo->replace_default_route);
   1888 	    if (go->ouraddr != wo->ouraddr) {
   1889 		warn("Local IP address changed to %I", go->ouraddr);
   1890 		ppp_script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0);
   1891 		wo->ouraddr = go->ouraddr;
   1892 	    } else
   1893 		ppp_script_unsetenv("OLDIPLOCAL");
   1894 	    if (ho->hisaddr != wo->hisaddr) {
   1895 		warn("Remote IP address changed to %I", ho->hisaddr);
   1896 		if (wo->hisaddr != 0)
   1897 		    ppp_script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0);
   1898 		wo->hisaddr = ho->hisaddr;
   1899 	    } else
   1900 		ppp_script_unsetenv("OLDIPREMOTE");
   1901 
   1902 	    /* Set the interface to the new addresses */
   1903 	    mask = GetMask(go->ouraddr);
   1904 	    if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
   1905 		if (debug)
   1906 		    warn("Interface configuration failed");
   1907 		ipcp_close(f->unit, "Interface configuration failed");
   1908 		return;
   1909 	    }
   1910 
   1911 	    /* assign a default route through the interface if required */
   1912 	    if (ipcp_wantoptions[f->unit].default_route)
   1913 		if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
   1914 					     wo->replace_default_route))
   1915 		    default_route_set[f->unit] = 1;
   1916 
   1917 	    /* Make a proxy ARP entry if requested. */
   1918 	    if (ho->hisaddr != 0 && ipcp_wantoptions[f->unit].proxy_arp)
   1919 		if (sifproxyarp(f->unit, ho->hisaddr))
   1920 		    proxy_arp_set[f->unit] = 1;
   1921 
   1922 	}
   1923 	demand_rexmit(PPP_IP);
   1924 	sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
   1925 
   1926     } else {
   1927 	/*
   1928 	 * Set IP addresses and (if specified) netmask.
   1929 	 */
   1930 	mask = GetMask(go->ouraddr);
   1931 
   1932 #if !(defined(SVR4) && (defined(SNI) || defined(__USLC__)))
   1933 	if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
   1934 	    if (debug)
   1935 		warn("Interface configuration failed");
   1936 	    ipcp_close(f->unit, "Interface configuration failed");
   1937 	    return;
   1938 	}
   1939 #endif
   1940 
   1941 	ifindex = if_nametoindex(ifname);
   1942 
   1943 	/* run the pre-up script, if any, and wait for it to finish */
   1944 	ipcp_script(path_ippreup, 1);
   1945 
   1946 	/* check if preup script renamed the interface */
   1947 	if (!if_indextoname(ifindex, ifname)) {
   1948             error("Interface index %d failed to get renamed by a pre-up script", ifindex);
   1949 	    ipcp_close(f->unit, "Interface configuration failed");
   1950 	    return;
   1951 	}
   1952 
   1953 	/* bring the interface up for IP */
   1954 	if (!sifup(f->unit)) {
   1955 	    if (debug)
   1956 		warn("Interface failed to come up");
   1957 	    ipcp_close(f->unit, "Interface configuration failed");
   1958 	    return;
   1959 	}
   1960 
   1961 #if (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
   1962 	if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
   1963 	    if (debug)
   1964 		warn("Interface configuration failed");
   1965 	    ipcp_close(f->unit, "Interface configuration failed");
   1966 	    return;
   1967 	}
   1968 #endif
   1969 	sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
   1970 
   1971 	/* assign a default route through the interface if required */
   1972 	if (ipcp_wantoptions[f->unit].default_route)
   1973 	    if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr,
   1974 					 wo->replace_default_route))
   1975 		default_route_set[f->unit] = 1;
   1976 
   1977 	/* Make a proxy ARP entry if requested. */
   1978 	if (ho->hisaddr != 0 && ipcp_wantoptions[f->unit].proxy_arp)
   1979 	    if (sifproxyarp(f->unit, ho->hisaddr))
   1980 		proxy_arp_set[f->unit] = 1;
   1981 
   1982 	ipcp_wantoptions[0].ouraddr = go->ouraddr;
   1983 
   1984 	notice("local  IP address %I", go->ouraddr);
   1985 	if (ho->hisaddr != 0)
   1986 	    notice("remote IP address %I", ho->hisaddr);
   1987 	if (go->dnsaddr[0])
   1988 	    notice("primary   DNS address %I", go->dnsaddr[0]);
   1989 	if (go->dnsaddr[1])
   1990 	    notice("secondary DNS address %I", go->dnsaddr[1]);
   1991     }
   1992 
   1993     reset_link_stats(f->unit);
   1994 
   1995     np_up(f->unit, PPP_IP);
   1996     ipcp_is_up = 1;
   1997 
   1998     notify(ip_up_notifier, 0);
   1999     if (ip_up_hook)
   2000 	ip_up_hook();
   2001 
   2002     /*
   2003      * Execute the ip-up script, like this:
   2004      *	/etc/ppp/ip-up interface tty speed local-IP remote-IP
   2005      */
   2006     if (ipcp_script_state == s_down && ipcp_script_pid == 0) {
   2007 	ipcp_script_state = s_up;
   2008 	ipcp_script(path_ipup, 0);
   2009     }
   2010 }
   2011 
   2012 
   2013 /*
   2014  * ipcp_down - IPCP has gone DOWN.
   2015  *
   2016  * Take the IP network interface down, clear its addresses
   2017  * and delete routes through it.
   2018  */
   2019 static void
   2020 ipcp_down(fsm *f)
   2021 {
   2022     IPCPDEBUG(("ipcp: down"));
   2023     /* XXX a bit IPv4-centric here, we only need to get the stats
   2024      * before the interface is marked down. */
   2025     /* XXX more correct: we must get the stats before running the notifiers,
   2026      * at least for the radius plugin */
   2027     ppp_get_link_stats(NULL);
   2028     notify(ip_down_notifier, 0);
   2029     if (ip_down_hook)
   2030 	ip_down_hook();
   2031     if (ipcp_is_up) {
   2032 	ipcp_is_up = 0;
   2033 	np_down(f->unit, PPP_IP);
   2034     }
   2035     sifvjcomp(f->unit, 0, 0, 0);
   2036 
   2037     print_link_stats(); /* _after_ running the notifiers and ip_down_hook(),
   2038 			 * because print_link_stats() sets link_stats_print
   2039 			 * to 0 (zero) */
   2040 
   2041     /*
   2042      * If we are doing dial-on-demand, set the interface
   2043      * to queue up outgoing packets (for now).
   2044      */
   2045     if (demand) {
   2046 	sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE);
   2047     } else {
   2048 	sifnpmode(f->unit, PPP_IP, NPMODE_DROP);
   2049 	sifdown(f->unit);
   2050 	ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr,
   2051 			 ipcp_hisoptions[f->unit].hisaddr, 0);
   2052     }
   2053 
   2054     /* Execute the ip-down script */
   2055     if (ipcp_script_state == s_up && ipcp_script_pid == 0) {
   2056 	ipcp_script_state = s_down;
   2057 	ipcp_script(path_ipdown, 0);
   2058     }
   2059 }
   2060 
   2061 
   2062 /*
   2063  * ipcp_clear_addrs() - clear the interface addresses, routes,
   2064  * proxy arp entries, etc.
   2065  */
   2066 static void
   2067 ipcp_clear_addrs(int unit, u_int32_t ouraddr, u_int32_t hisaddr, bool replacedefaultroute)
   2068 {
   2069     if (proxy_arp_set[unit]) {
   2070 	cifproxyarp(unit, hisaddr);
   2071 	proxy_arp_set[unit] = 0;
   2072     }
   2073     /* If replacedefaultroute, sifdefaultroute will be called soon
   2074      * with replacedefaultroute set and that will overwrite the current
   2075      * default route. This is the case only when doing demand, otherwise
   2076      * during demand, this cifdefaultroute would restore the old default
   2077      * route which is not what we want in this case. In the non-demand
   2078      * case, we'll delete the default route and restore the old if there
   2079      * is one saved by an sifdefaultroute with replacedefaultroute.
   2080      */
   2081     if (!replacedefaultroute && default_route_set[unit]) {
   2082 	cifdefaultroute(unit, ouraddr, hisaddr);
   2083 	default_route_set[unit] = 0;
   2084     }
   2085     cifaddr(unit, ouraddr, hisaddr);
   2086 }
   2087 
   2088 
   2089 /*
   2090  * ipcp_finished - possibly shut down the lower layers.
   2091  */
   2092 static void
   2093 ipcp_finished(fsm *f)
   2094 {
   2095 	if (ipcp_is_open) {
   2096 		ipcp_is_open = 0;
   2097 		np_finished(f->unit, PPP_IP);
   2098 	}
   2099 }
   2100 
   2101 
   2102 /*
   2103  * ipcp_script_done - called when the ip-up or ip-down script
   2104  * has finished.
   2105  */
   2106 static void
   2107 ipcp_script_done(void *arg)
   2108 {
   2109     ipcp_script_pid = 0;
   2110     switch (ipcp_script_state) {
   2111     case s_up:
   2112 	if (ipcp_fsm[0].state != OPENED) {
   2113 	    ipcp_script_state = s_down;
   2114 	    ipcp_script(path_ipdown, 0);
   2115 	}
   2116 	break;
   2117     case s_down:
   2118 	if (ipcp_fsm[0].state == OPENED) {
   2119 	    ipcp_script_state = s_up;
   2120 	    ipcp_script(path_ipup, 0);
   2121 	}
   2122 	break;
   2123     }
   2124 }
   2125 
   2126 
   2127 /*
   2128  * ipcp_script - Execute a script with arguments
   2129  * interface-name tty-name speed local-IP remote-IP.
   2130  */
   2131 static void
   2132 ipcp_script(char *script, int wait)
   2133 {
   2134     char strspeed[32], strlocal[32], strremote[32];
   2135     char *argv[8];
   2136 
   2137     slprintf(strspeed, sizeof(strspeed), "%d", baud_rate);
   2138     slprintf(strlocal, sizeof(strlocal), "%I", ipcp_gotoptions[0].ouraddr);
   2139     slprintf(strremote, sizeof(strremote), "%I", ipcp_hisoptions[0].hisaddr);
   2140 
   2141     argv[0] = script;
   2142     argv[1] = ifname;
   2143     argv[2] = devnam;
   2144     argv[3] = strspeed;
   2145     argv[4] = strlocal;
   2146     argv[5] = strremote;
   2147     argv[6] = ipparam;
   2148     argv[7] = NULL;
   2149     if (wait)
   2150 	run_program(script, argv, 0, NULL, NULL, 1);
   2151     else
   2152 	ipcp_script_pid = run_program(script, argv, 0, ipcp_script_done,
   2153 				      NULL, 0);
   2154 }
   2155 
   2156 /*
   2157  * create_resolv - create the replacement resolv.conf file
   2158  */
   2159 static void
   2160 create_resolv(u_int32_t peerdns1, u_int32_t peerdns2)
   2161 {
   2162     FILE *f;
   2163 
   2164     if (noresolvconf)
   2165 	return;
   2166 
   2167     f = fopen(PPP_PATH_RESOLV, "w");
   2168     if (f == NULL) {
   2169 	error("Failed to create %s: %m", PPP_PATH_RESOLV);
   2170 	return;
   2171     }
   2172 
   2173     if (peerdns1)
   2174 	fprintf(f, "nameserver %s\n", ip_ntoa(peerdns1));
   2175 
   2176     if (peerdns2 && peerdns2 != peerdns1)
   2177 	fprintf(f, "nameserver %s\n", ip_ntoa(peerdns2));
   2178 
   2179     if (ferror(f))
   2180 	error("Write failed to %s: %m", PPP_PATH_RESOLV);
   2181 
   2182     fclose(f);
   2183 }
   2184 
   2185 /*
   2186  * ipcp_printpkt - print the contents of an IPCP packet.
   2187  */
   2188 static char *ipcp_codenames[] = {
   2189     "ConfReq", "ConfAck", "ConfNak", "ConfRej",
   2190     "TermReq", "TermAck", "CodeRej"
   2191 };
   2192 
   2193 static int
   2194 ipcp_printpkt(u_char *p, int plen,
   2195 	      void (*printer) (void *, char *, ...), void *arg)
   2196 {
   2197     int code, id, len, olen;
   2198     u_char *pstart, *optend;
   2199     u_short cishort;
   2200     u_int32_t cilong;
   2201 
   2202     if (plen < HEADERLEN)
   2203 	return 0;
   2204     pstart = p;
   2205     GETCHAR(code, p);
   2206     GETCHAR(id, p);
   2207     GETSHORT(len, p);
   2208     if (len < HEADERLEN || len > plen)
   2209 	return 0;
   2210 
   2211     if (code >= 1 && code <= sizeof(ipcp_codenames) / sizeof(char *))
   2212 	printer(arg, " %s", ipcp_codenames[code-1]);
   2213     else
   2214 	printer(arg, " code=0x%x", code);
   2215     printer(arg, " id=0x%x", id);
   2216     len -= HEADERLEN;
   2217     switch (code) {
   2218     case CONFREQ:
   2219     case CONFACK:
   2220     case CONFNAK:
   2221     case CONFREJ:
   2222 	/* print option list */
   2223 	while (len >= 2) {
   2224 	    GETCHAR(code, p);
   2225 	    GETCHAR(olen, p);
   2226 	    p -= 2;
   2227 	    if (olen < 2 || olen > len) {
   2228 		break;
   2229 	    }
   2230 	    printer(arg, " <");
   2231 	    len -= olen;
   2232 	    optend = p + olen;
   2233 	    switch (code) {
   2234 	    case CI_ADDRS:
   2235 		if (olen == CILEN_ADDRS) {
   2236 		    p += 2;
   2237 		    GETLONG(cilong, p);
   2238 		    printer(arg, "addrs %I", htonl(cilong));
   2239 		    GETLONG(cilong, p);
   2240 		    printer(arg, " %I", htonl(cilong));
   2241 		}
   2242 		break;
   2243 	    case CI_COMPRESSTYPE:
   2244 		if (olen >= CILEN_COMPRESS) {
   2245 		    p += 2;
   2246 		    GETSHORT(cishort, p);
   2247 		    printer(arg, "compress ");
   2248 		    switch (cishort) {
   2249 		    case IPCP_VJ_COMP:
   2250 			printer(arg, "VJ");
   2251 			break;
   2252 		    case IPCP_VJ_COMP_OLD:
   2253 			printer(arg, "old-VJ");
   2254 			break;
   2255 		    default:
   2256 			printer(arg, "0x%x", cishort);
   2257 		    }
   2258 		}
   2259 		break;
   2260 	    case CI_ADDR:
   2261 		if (olen == CILEN_ADDR) {
   2262 		    p += 2;
   2263 		    GETLONG(cilong, p);
   2264 		    printer(arg, "addr %I", htonl(cilong));
   2265 		}
   2266 		break;
   2267 	    case CI_MS_DNS1:
   2268 	    case CI_MS_DNS2:
   2269 	        p += 2;
   2270 		GETLONG(cilong, p);
   2271 		printer(arg, "ms-dns%d %I", (code == CI_MS_DNS1? 1: 2),
   2272 			htonl(cilong));
   2273 		break;
   2274 	    case CI_MS_WINS1:
   2275 	    case CI_MS_WINS2:
   2276 	        p += 2;
   2277 		GETLONG(cilong, p);
   2278 		printer(arg, "ms-wins %I", htonl(cilong));
   2279 		break;
   2280 	    }
   2281 	    while (p < optend) {
   2282 		GETCHAR(code, p);
   2283 		printer(arg, " %.2x", code);
   2284 	    }
   2285 	    printer(arg, ">");
   2286 	}
   2287 	break;
   2288 
   2289     case TERMACK:
   2290     case TERMREQ:
   2291 	if (len > 0 && *p >= ' ' && *p < 0x7f) {
   2292 	    printer(arg, " ");
   2293 	    print_string((char *)p, len, printer, arg);
   2294 	    p += len;
   2295 	    len = 0;
   2296 	}
   2297 	break;
   2298     }
   2299 
   2300     /* print the rest of the bytes in the packet */
   2301     for (; len > 0; --len) {
   2302 	GETCHAR(code, p);
   2303 	printer(arg, " %.2x", code);
   2304     }
   2305 
   2306     return p - pstart;
   2307 }
   2308 
   2309 /*
   2310  * ip_active_pkt - see if this IP packet is worth bringing the link up for.
   2311  * We don't bring the link up for IP fragments or for TCP FIN packets
   2312  * with no data.
   2313  */
   2314 #define IP_HDRLEN	20	/* bytes */
   2315 #define IP_OFFMASK	0x1fff
   2316 #ifndef IPPROTO_TCP
   2317 #define IPPROTO_TCP	6
   2318 #endif
   2319 #define TCP_HDRLEN	20
   2320 #define TH_FIN		0x01
   2321 
   2322 /*
   2323  * We use these macros because the IP header may be at an odd address,
   2324  * and some compilers might use word loads to get th_off or ip_hl.
   2325  */
   2326 
   2327 #define net_short(x)	(((x)[0] << 8) + (x)[1])
   2328 #define get_iphl(x)	(((unsigned char *)(x))[0] & 0xF)
   2329 #define get_ipoff(x)	net_short((unsigned char *)(x) + 6)
   2330 #define get_ipproto(x)	(((unsigned char *)(x))[9])
   2331 #define get_tcpoff(x)	(((unsigned char *)(x))[12] >> 4)
   2332 #define get_tcpflags(x)	(((unsigned char *)(x))[13])
   2333 
   2334 static int
   2335 ip_active_pkt(u_char *pkt, int len)
   2336 {
   2337     u_char *tcp;
   2338     int hlen;
   2339 
   2340     len -= PPP_HDRLEN;
   2341     pkt += PPP_HDRLEN;
   2342     if (len < IP_HDRLEN)
   2343 	return 0;
   2344     if ((get_ipoff(pkt) & IP_OFFMASK) != 0)
   2345 	return 0;
   2346     if (get_ipproto(pkt) != IPPROTO_TCP)
   2347 	return 1;
   2348     hlen = get_iphl(pkt) * 4;
   2349     if (len < hlen + TCP_HDRLEN)
   2350 	return 0;
   2351     tcp = pkt + hlen;
   2352     if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4)
   2353 	return 0;
   2354     return 1;
   2355 }
   2356