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