xref: /netbsd-src/external/bsd/ppp/dist/pppd/ipcp.c (revision 80d9064ac03cbb6a4174695f0d5b237c8766d3d0)
1 /*	$NetBSD: ipcp.c,v 1.2 2013/11/28 22:33:42 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.2 2013/11/28 22:33:42 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     ACKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr,
973 	       go->hisaddr);
974 
975     ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
976 	    go->maxslotindex, go->cflag);
977 
978     ACKCIADDR(CI_ADDR, go->neg_addr, go->ouraddr);
979 
980     ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
981 
982     ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
983 
984     /*
985      * If there are any remaining CIs, then this packet is bad.
986      */
987     if (len != 0)
988 	goto bad;
989     return (1);
990 
991 bad:
992     IPCPDEBUG(("ipcp_ackci: received bad Ack!"));
993     return (0);
994 }
995 
996 /*
997  * ipcp_nakci - Peer has sent a NAK for some of our CIs.
998  * This should not modify any state if the Nak is bad
999  * or if IPCP is in the OPENED state.
1000  * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
1001  *
1002  * Returns:
1003  *	0 - Nak was bad.
1004  *	1 - Nak was good.
1005  */
1006 static int
1007 ipcp_nakci(f, p, len, treat_as_reject)
1008     fsm *f;
1009     u_char *p;
1010     int len;
1011     int treat_as_reject;
1012 {
1013     ipcp_options *go = &ipcp_gotoptions[f->unit];
1014     u_char cimaxslotindex, cicflag;
1015     u_char citype, cilen, *next;
1016     u_short cishort;
1017     u_int32_t ciaddr1, ciaddr2, l, cidnsaddr;
1018     ipcp_options no;		/* options we've seen Naks for */
1019     ipcp_options try;		/* options to request next time */
1020 
1021     BZERO(&no, sizeof(no));
1022     try = *go;
1023 
1024     /*
1025      * Any Nak'd CIs must be in exactly the same order that we sent.
1026      * Check packet length and CI length at each step.
1027      * If we find any deviations, then this packet is bad.
1028      */
1029 #define NAKCIADDRS(opt, neg, code) \
1030     if ((neg) && \
1031 	(cilen = p[1]) == CILEN_ADDRS && \
1032 	len >= cilen && \
1033 	p[0] == opt) { \
1034 	len -= cilen; \
1035 	INCPTR(2, p); \
1036 	GETLONG(l, p); \
1037 	ciaddr1 = htonl(l); \
1038 	GETLONG(l, p); \
1039 	ciaddr2 = htonl(l); \
1040 	no.old_addrs = 1; \
1041 	code \
1042     }
1043 
1044 #define NAKCIVJ(opt, neg, code) \
1045     if (go->neg && \
1046 	((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \
1047 	len >= cilen && \
1048 	p[0] == opt) { \
1049 	len -= cilen; \
1050 	INCPTR(2, p); \
1051 	GETSHORT(cishort, p); \
1052 	no.neg = 1; \
1053         code \
1054     }
1055 
1056 #define NAKCIADDR(opt, neg, code) \
1057     if (go->neg && \
1058 	(cilen = p[1]) == CILEN_ADDR && \
1059 	len >= cilen && \
1060 	p[0] == opt) { \
1061 	len -= cilen; \
1062 	INCPTR(2, p); \
1063 	GETLONG(l, p); \
1064 	ciaddr1 = htonl(l); \
1065 	no.neg = 1; \
1066 	code \
1067     }
1068 
1069 #define NAKCIDNS(opt, neg, code) \
1070     if (go->neg && \
1071 	((cilen = p[1]) == CILEN_ADDR) && \
1072 	len >= cilen && \
1073 	p[0] == opt) { \
1074 	len -= cilen; \
1075 	INCPTR(2, p); \
1076 	GETLONG(l, p); \
1077 	cidnsaddr = htonl(l); \
1078 	no.neg = 1; \
1079 	code \
1080     }
1081 
1082     /*
1083      * Accept the peer's idea of {our,his} address, if different
1084      * from our idea, only if the accept_{local,remote} flag is set.
1085      */
1086     NAKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs,
1087 	       if (treat_as_reject) {
1088 		   try.old_addrs = 0;
1089 	       } else {
1090 		   if (go->accept_local && ciaddr1) {
1091 		       /* take his idea of our address */
1092 		       try.ouraddr = ciaddr1;
1093 		   }
1094 		   if (go->accept_remote && ciaddr2) {
1095 		       /* take his idea of his address */
1096 		       try.hisaddr = ciaddr2;
1097 		   }
1098 	       }
1099 	);
1100 
1101     /*
1102      * Accept the peer's value of maxslotindex provided that it
1103      * is less than what we asked for.  Turn off slot-ID compression
1104      * if the peer wants.  Send old-style compress-type option if
1105      * the peer wants.
1106      */
1107     NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
1108 	    if (treat_as_reject) {
1109 		try.neg_vj = 0;
1110 	    } else if (cilen == CILEN_VJ) {
1111 		GETCHAR(cimaxslotindex, p);
1112 		GETCHAR(cicflag, p);
1113 		if (cishort == IPCP_VJ_COMP) {
1114 		    try.old_vj = 0;
1115 		    if (cimaxslotindex < go->maxslotindex)
1116 			try.maxslotindex = cimaxslotindex;
1117 		    if (!cicflag)
1118 			try.cflag = 0;
1119 		} else {
1120 		    try.neg_vj = 0;
1121 		}
1122 	    } else {
1123 		if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) {
1124 		    try.old_vj = 1;
1125 		    try.vj_protocol = cishort;
1126 		} else {
1127 		    try.neg_vj = 0;
1128 		}
1129 	    }
1130 	    );
1131 
1132     NAKCIADDR(CI_ADDR, neg_addr,
1133 	      if (treat_as_reject) {
1134 		  try.neg_addr = 0;
1135 		  try.old_addrs = 0;
1136 	      } else if (go->accept_local && ciaddr1) {
1137 		  /* take his idea of our address */
1138 		  try.ouraddr = ciaddr1;
1139 	      }
1140 	      );
1141 
1142     NAKCIDNS(CI_MS_DNS1, req_dns1,
1143 	     if (treat_as_reject) {
1144 		 try.req_dns1 = 0;
1145 	     } else {
1146 		 try.dnsaddr[0] = cidnsaddr;
1147 	     }
1148 	     );
1149 
1150     NAKCIDNS(CI_MS_DNS2, req_dns2,
1151 	     if (treat_as_reject) {
1152 		 try.req_dns2 = 0;
1153 	     } else {
1154 		 try.dnsaddr[1] = cidnsaddr;
1155 	     }
1156 	     );
1157 
1158     /*
1159      * There may be remaining CIs, if the peer is requesting negotiation
1160      * on an option that we didn't include in our request packet.
1161      * If they want to negotiate about IP addresses, we comply.
1162      * If they want us to ask for compression, we refuse.
1163      * If they want us to ask for ms-dns, we do that, since some
1164      * peers get huffy if we don't.
1165      */
1166     while (len >= CILEN_VOID) {
1167 	GETCHAR(citype, p);
1168 	GETCHAR(cilen, p);
1169 	if ( cilen < CILEN_VOID || (len -= cilen) < 0 )
1170 	    goto bad;
1171 	next = p + cilen - 2;
1172 
1173 	switch (citype) {
1174 	case CI_COMPRESSTYPE:
1175 	    if (go->neg_vj || no.neg_vj ||
1176 		(cilen != CILEN_VJ && cilen != CILEN_COMPRESS))
1177 		goto bad;
1178 	    no.neg_vj = 1;
1179 	    break;
1180 	case CI_ADDRS:
1181 	    if ((!go->neg_addr && go->old_addrs) || no.old_addrs
1182 		|| cilen != CILEN_ADDRS)
1183 		goto bad;
1184 	    try.neg_addr = 0;
1185 	    GETLONG(l, p);
1186 	    ciaddr1 = htonl(l);
1187 	    if (ciaddr1 && go->accept_local)
1188 		try.ouraddr = ciaddr1;
1189 	    GETLONG(l, p);
1190 	    ciaddr2 = htonl(l);
1191 	    if (ciaddr2 && go->accept_remote)
1192 		try.hisaddr = ciaddr2;
1193 	    no.old_addrs = 1;
1194 	    break;
1195 	case CI_ADDR:
1196 	    if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR)
1197 		goto bad;
1198 	    try.old_addrs = 0;
1199 	    GETLONG(l, p);
1200 	    ciaddr1 = htonl(l);
1201 	    if (ciaddr1 && go->accept_local)
1202 		try.ouraddr = ciaddr1;
1203 	    if (try.ouraddr != 0)
1204 		try.neg_addr = 1;
1205 	    no.neg_addr = 1;
1206 	    break;
1207 	case CI_MS_DNS1:
1208 	    if (go->req_dns1 || no.req_dns1 || cilen != CILEN_ADDR)
1209 		goto bad;
1210 	    GETLONG(l, p);
1211 	    try.dnsaddr[0] = htonl(l);
1212 	    try.req_dns1 = 1;
1213 	    no.req_dns1 = 1;
1214 	    break;
1215 	case CI_MS_DNS2:
1216 	    if (go->req_dns2 || no.req_dns2 || cilen != CILEN_ADDR)
1217 		goto bad;
1218 	    GETLONG(l, p);
1219 	    try.dnsaddr[1] = htonl(l);
1220 	    try.req_dns2 = 1;
1221 	    no.req_dns2 = 1;
1222 	    break;
1223 	case CI_MS_WINS1:
1224 	case CI_MS_WINS2:
1225 	    if (cilen != CILEN_ADDR)
1226 		goto bad;
1227 	    GETLONG(l, p);
1228 	    ciaddr1 = htonl(l);
1229 	    if (ciaddr1)
1230 		try.winsaddr[citype == CI_MS_WINS2] = ciaddr1;
1231 	    break;
1232 	}
1233 	p = next;
1234     }
1235 
1236     /*
1237      * OK, the Nak is good.  Now we can update state.
1238      * If there are any remaining options, we ignore them.
1239      */
1240     if (f->state != OPENED)
1241 	*go = try;
1242 
1243     return 1;
1244 
1245 bad:
1246     IPCPDEBUG(("ipcp_nakci: received bad Nak!"));
1247     return 0;
1248 }
1249 
1250 
1251 /*
1252  * ipcp_rejci - Reject some of our CIs.
1253  * Callback from fsm_rconfnakrej.
1254  */
1255 static int
1256 ipcp_rejci(f, p, len)
1257     fsm *f;
1258     u_char *p;
1259     int len;
1260 {
1261     ipcp_options *go = &ipcp_gotoptions[f->unit];
1262     u_char cimaxslotindex, ciflag, cilen;
1263     u_short cishort;
1264     u_int32_t cilong;
1265     ipcp_options try;		/* options to request next time */
1266 
1267     try = *go;
1268     /*
1269      * Any Rejected CIs must be in exactly the same order that we sent.
1270      * Check packet length and CI length at each step.
1271      * If we find any deviations, then this packet is bad.
1272      */
1273 #define REJCIADDRS(opt, neg, val1, val2) \
1274     if ((neg) && \
1275 	(cilen = p[1]) == CILEN_ADDRS && \
1276 	len >= cilen && \
1277 	p[0] == opt) { \
1278 	u_int32_t l; \
1279 	len -= cilen; \
1280 	INCPTR(2, p); \
1281 	GETLONG(l, p); \
1282 	cilong = htonl(l); \
1283 	/* Check rejected value. */ \
1284 	if (cilong != val1) \
1285 	    goto bad; \
1286 	GETLONG(l, p); \
1287 	cilong = htonl(l); \
1288 	/* Check rejected value. */ \
1289 	if (cilong != val2) \
1290 	    goto bad; \
1291 	try.old_addrs = 0; \
1292     }
1293 
1294 #define REJCIVJ(opt, neg, val, old, maxslot, cflag) \
1295     if (go->neg && \
1296 	p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \
1297 	len >= p[1] && \
1298 	p[0] == opt) { \
1299 	len -= p[1]; \
1300 	INCPTR(2, p); \
1301 	GETSHORT(cishort, p); \
1302 	/* Check rejected value. */  \
1303 	if (cishort != val) \
1304 	    goto bad; \
1305 	if (!old) { \
1306 	   GETCHAR(cimaxslotindex, p); \
1307 	   if (cimaxslotindex != maxslot) \
1308 	     goto bad; \
1309 	   GETCHAR(ciflag, p); \
1310 	   if (ciflag != cflag) \
1311 	     goto bad; \
1312         } \
1313 	try.neg = 0; \
1314      }
1315 
1316 #define REJCIADDR(opt, neg, val) \
1317     if (go->neg && \
1318 	(cilen = p[1]) == CILEN_ADDR && \
1319 	len >= cilen && \
1320 	p[0] == opt) { \
1321 	u_int32_t l; \
1322 	len -= cilen; \
1323 	INCPTR(2, p); \
1324 	GETLONG(l, p); \
1325 	cilong = htonl(l); \
1326 	/* Check rejected value. */ \
1327 	if (cilong != val) \
1328 	    goto bad; \
1329 	try.neg = 0; \
1330     }
1331 
1332 #define REJCIDNS(opt, neg, dnsaddr) \
1333     if (go->neg && \
1334 	((cilen = p[1]) == CILEN_ADDR) && \
1335 	len >= cilen && \
1336 	p[0] == opt) { \
1337 	u_int32_t l; \
1338 	len -= cilen; \
1339 	INCPTR(2, p); \
1340 	GETLONG(l, p); \
1341 	cilong = htonl(l); \
1342 	/* Check rejected value. */ \
1343 	if (cilong != dnsaddr) \
1344 	    goto bad; \
1345 	try.neg = 0; \
1346     }
1347 
1348 #define REJCIWINS(opt, addr) \
1349     if (addr && \
1350 	((cilen = p[1]) == CILEN_ADDR) && \
1351 	len >= cilen && \
1352 	p[0] == opt) { \
1353 	u_int32_t l; \
1354 	len -= cilen; \
1355 	INCPTR(2, p); \
1356 	GETLONG(l, p); \
1357 	cilong = htonl(l); \
1358 	/* Check rejected value. */ \
1359 	if (cilong != addr) \
1360 	    goto bad; \
1361 	try.winsaddr[opt == CI_MS_WINS2] = 0; \
1362     }
1363 
1364     REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs,
1365 	       go->ouraddr, go->hisaddr);
1366 
1367     REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj,
1368 	    go->maxslotindex, go->cflag);
1369 
1370     REJCIADDR(CI_ADDR, neg_addr, go->ouraddr);
1371 
1372     REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]);
1373 
1374     REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]);
1375 
1376     REJCIWINS(CI_MS_WINS1, go->winsaddr[0]);
1377 
1378     REJCIWINS(CI_MS_WINS2, go->winsaddr[1]);
1379 
1380     /*
1381      * If there are any remaining CIs, then this packet is bad.
1382      */
1383     if (len != 0)
1384 	goto bad;
1385     /*
1386      * Now we can update state.
1387      */
1388     if (f->state != OPENED)
1389 	*go = try;
1390     return 1;
1391 
1392 bad:
1393     IPCPDEBUG(("ipcp_rejci: received bad Reject!"));
1394     return 0;
1395 }
1396 
1397 
1398 /*
1399  * ipcp_reqci - Check the peer's requested CIs and send appropriate response.
1400  * Callback from fsm_rconfreq, Receive Configure Request
1401  *
1402  * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
1403  * appropriately.  If reject_if_disagree is non-zero, doesn't return
1404  * CONFNAK; returns CONFREJ if it can't return CONFACK.
1405  */
1406 static int
1407 ipcp_reqci(f, inp, len, reject_if_disagree)
1408     fsm *f;
1409     u_char *inp;		/* Requested CIs */
1410     int *len;			/* Length of requested CIs */
1411     int reject_if_disagree;
1412 {
1413     ipcp_options *wo = &ipcp_wantoptions[f->unit];
1414     ipcp_options *ho = &ipcp_hisoptions[f->unit];
1415     ipcp_options *ao = &ipcp_allowoptions[f->unit];
1416     u_char *cip, *next;		/* Pointer to current and next CIs */
1417     u_short cilen, citype;	/* Parsed len, type */
1418     u_short cishort;		/* Parsed short value */
1419     u_int32_t tl, ciaddr1, ciaddr2;/* Parsed address values */
1420     int rc = CONFACK;		/* Final packet return code */
1421     int orc;			/* Individual option return code */
1422     u_char *p;			/* Pointer to next char to parse */
1423     u_char *ucp = inp;		/* Pointer to current output char */
1424     int l = *len;		/* Length left */
1425     u_char maxslotindex, cflag;
1426     int d;
1427 
1428     /*
1429      * Reset all his options.
1430      */
1431     BZERO(ho, sizeof(*ho));
1432 
1433     /*
1434      * Process all his options.
1435      */
1436     next = inp;
1437     while (l) {
1438 	orc = CONFACK;			/* Assume success */
1439 	cip = p = next;			/* Remember begining of CI */
1440 	if (l < 2 ||			/* Not enough data for CI header or */
1441 	    p[1] < 2 ||			/*  CI length too small or */
1442 	    p[1] > l) {			/*  CI length too big? */
1443 	    IPCPDEBUG(("ipcp_reqci: bad CI length!"));
1444 	    orc = CONFREJ;		/* Reject bad CI */
1445 	    cilen = l;			/* Reject till end of packet */
1446 	    l = 0;			/* Don't loop again */
1447 	    goto endswitch;
1448 	}
1449 	GETCHAR(citype, p);		/* Parse CI type */
1450 	GETCHAR(cilen, p);		/* Parse CI length */
1451 	l -= cilen;			/* Adjust remaining length */
1452 	next += cilen;			/* Step to next CI */
1453 
1454 	switch (citype) {		/* Check CI type */
1455 	case CI_ADDRS:
1456 	    if (!ao->old_addrs || ho->neg_addr ||
1457 		cilen != CILEN_ADDRS) {	/* Check CI length */
1458 		orc = CONFREJ;		/* Reject CI */
1459 		break;
1460 	    }
1461 
1462 	    /*
1463 	     * If he has no address, or if we both have his address but
1464 	     * disagree about it, then NAK it with our idea.
1465 	     * In particular, if we don't know his address, but he does,
1466 	     * then accept it.
1467 	     */
1468 	    GETLONG(tl, p);		/* Parse source address (his) */
1469 	    ciaddr1 = htonl(tl);
1470 	    if (ciaddr1 != wo->hisaddr
1471 		&& (ciaddr1 == 0 || !wo->accept_remote)) {
1472 		orc = CONFNAK;
1473 		if (!reject_if_disagree) {
1474 		    DECPTR(sizeof(u_int32_t), p);
1475 		    tl = ntohl(wo->hisaddr);
1476 		    PUTLONG(tl, p);
1477 		}
1478 	    } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
1479 		/*
1480 		 * If neither we nor he knows his address, reject the option.
1481 		 */
1482 		orc = CONFREJ;
1483 		wo->req_addr = 0;	/* don't NAK with 0.0.0.0 later */
1484 		break;
1485 	    }
1486 
1487 	    /*
1488 	     * If he doesn't know our address, or if we both have our address
1489 	     * but disagree about it, then NAK it with our idea.
1490 	     */
1491 	    GETLONG(tl, p);		/* Parse desination address (ours) */
1492 	    ciaddr2 = htonl(tl);
1493 	    if (ciaddr2 != wo->ouraddr) {
1494 		if (ciaddr2 == 0 || !wo->accept_local) {
1495 		    orc = CONFNAK;
1496 		    if (!reject_if_disagree) {
1497 			DECPTR(sizeof(u_int32_t), p);
1498 			tl = ntohl(wo->ouraddr);
1499 			PUTLONG(tl, p);
1500 		    }
1501 		} else {
1502 		    wo->ouraddr = ciaddr2;	/* accept peer's idea */
1503 		}
1504 	    }
1505 
1506 	    ho->old_addrs = 1;
1507 	    ho->hisaddr = ciaddr1;
1508 	    ho->ouraddr = ciaddr2;
1509 	    break;
1510 
1511 	case CI_ADDR:
1512 	    if (!ao->neg_addr || ho->old_addrs ||
1513 		cilen != CILEN_ADDR) {	/* Check CI length */
1514 		orc = CONFREJ;		/* Reject CI */
1515 		break;
1516 	    }
1517 
1518 	    /*
1519 	     * If he has no address, or if we both have his address but
1520 	     * disagree about it, then NAK it with our idea.
1521 	     * In particular, if we don't know his address, but he does,
1522 	     * then accept it.
1523 	     */
1524 	    GETLONG(tl, p);	/* Parse source address (his) */
1525 	    ciaddr1 = htonl(tl);
1526 	    if (ciaddr1 != wo->hisaddr
1527 		&& (ciaddr1 == 0 || !wo->accept_remote)) {
1528 		orc = CONFNAK;
1529 		if (!reject_if_disagree) {
1530 		    DECPTR(sizeof(u_int32_t), p);
1531 		    tl = ntohl(wo->hisaddr);
1532 		    PUTLONG(tl, p);
1533 		}
1534 	    } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
1535 		/*
1536 		 * Don't ACK an address of 0.0.0.0 - reject it instead.
1537 		 */
1538 		orc = CONFREJ;
1539 		wo->req_addr = 0;	/* don't NAK with 0.0.0.0 later */
1540 		break;
1541 	    }
1542 
1543 	    ho->neg_addr = 1;
1544 	    ho->hisaddr = ciaddr1;
1545 	    break;
1546 
1547 	case CI_MS_DNS1:
1548 	case CI_MS_DNS2:
1549 	    /* Microsoft primary or secondary DNS request */
1550 	    d = citype == CI_MS_DNS2;
1551 
1552 	    /* If we do not have a DNS address then we cannot send it */
1553 	    if (ao->dnsaddr[d] == 0 ||
1554 		cilen != CILEN_ADDR) {	/* Check CI length */
1555 		orc = CONFREJ;		/* Reject CI */
1556 		break;
1557 	    }
1558 	    GETLONG(tl, p);
1559 	    if (htonl(tl) != ao->dnsaddr[d]) {
1560                 DECPTR(sizeof(u_int32_t), p);
1561 		tl = ntohl(ao->dnsaddr[d]);
1562 		PUTLONG(tl, p);
1563 		orc = CONFNAK;
1564             }
1565             break;
1566 
1567 	case CI_MS_WINS1:
1568 	case CI_MS_WINS2:
1569 	    /* Microsoft primary or secondary WINS request */
1570 	    d = citype == CI_MS_WINS2;
1571 
1572 	    /* If we do not have a DNS address then we cannot send it */
1573 	    if (ao->winsaddr[d] == 0 ||
1574 		cilen != CILEN_ADDR) {	/* Check CI length */
1575 		orc = CONFREJ;		/* Reject CI */
1576 		break;
1577 	    }
1578 	    GETLONG(tl, p);
1579 	    if (htonl(tl) != ao->winsaddr[d]) {
1580                 DECPTR(sizeof(u_int32_t), p);
1581 		tl = ntohl(ao->winsaddr[d]);
1582 		PUTLONG(tl, p);
1583 		orc = CONFNAK;
1584             }
1585             break;
1586 
1587 	case CI_COMPRESSTYPE:
1588 	    if (!ao->neg_vj ||
1589 		(cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) {
1590 		orc = CONFREJ;
1591 		break;
1592 	    }
1593 	    GETSHORT(cishort, p);
1594 
1595 	    if (!(cishort == IPCP_VJ_COMP ||
1596 		  (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {
1597 		orc = CONFREJ;
1598 		break;
1599 	    }
1600 
1601 	    ho->neg_vj = 1;
1602 	    ho->vj_protocol = cishort;
1603 	    if (cilen == CILEN_VJ) {
1604 		GETCHAR(maxslotindex, p);
1605 		if (maxslotindex > ao->maxslotindex) {
1606 		    orc = CONFNAK;
1607 		    if (!reject_if_disagree){
1608 			DECPTR(1, p);
1609 			PUTCHAR(ao->maxslotindex, p);
1610 		    }
1611 		}
1612 		GETCHAR(cflag, p);
1613 		if (cflag && !ao->cflag) {
1614 		    orc = CONFNAK;
1615 		    if (!reject_if_disagree){
1616 			DECPTR(1, p);
1617 			PUTCHAR(wo->cflag, p);
1618 		    }
1619 		}
1620 		ho->maxslotindex = maxslotindex;
1621 		ho->cflag = cflag;
1622 	    } else {
1623 		ho->old_vj = 1;
1624 		ho->maxslotindex = MAX_STATES - 1;
1625 		ho->cflag = 1;
1626 	    }
1627 	    break;
1628 
1629 	default:
1630 	    orc = CONFREJ;
1631 	    break;
1632 	}
1633 endswitch:
1634 	if (orc == CONFACK &&		/* Good CI */
1635 	    rc != CONFACK)		/*  but prior CI wasnt? */
1636 	    continue;			/* Don't send this one */
1637 
1638 	if (orc == CONFNAK) {		/* Nak this CI? */
1639 	    if (reject_if_disagree)	/* Getting fed up with sending NAKs? */
1640 		orc = CONFREJ;		/* Get tough if so */
1641 	    else {
1642 		if (rc == CONFREJ)	/* Rejecting prior CI? */
1643 		    continue;		/* Don't send this one */
1644 		if (rc == CONFACK) {	/* Ack'd all prior CIs? */
1645 		    rc = CONFNAK;	/* Not anymore... */
1646 		    ucp = inp;		/* Backup */
1647 		}
1648 	    }
1649 	}
1650 
1651 	if (orc == CONFREJ &&		/* Reject this CI */
1652 	    rc != CONFREJ) {		/*  but no prior ones? */
1653 	    rc = CONFREJ;
1654 	    ucp = inp;			/* Backup */
1655 	}
1656 
1657 	/* Need to move CI? */
1658 	if (ucp != cip)
1659 	    BCOPY(cip, ucp, cilen);	/* Move it */
1660 
1661 	/* Update output pointer */
1662 	INCPTR(cilen, ucp);
1663     }
1664 
1665     /*
1666      * If we aren't rejecting this packet, and we want to negotiate
1667      * their address, and they didn't send their address, then we
1668      * send a NAK with a CI_ADDR option appended.  We assume the
1669      * input buffer is long enough that we can append the extra
1670      * option safely.
1671      */
1672     if (rc != CONFREJ && !ho->neg_addr && !ho->old_addrs &&
1673 	wo->req_addr && !reject_if_disagree && !noremoteip) {
1674 	if (rc == CONFACK) {
1675 	    rc = CONFNAK;
1676 	    ucp = inp;			/* reset pointer */
1677 	    wo->req_addr = 0;		/* don't ask again */
1678 	}
1679 	PUTCHAR(CI_ADDR, ucp);
1680 	PUTCHAR(CILEN_ADDR, ucp);
1681 	tl = ntohl(wo->hisaddr);
1682 	PUTLONG(tl, ucp);
1683     }
1684 
1685     *len = ucp - inp;			/* Compute output length */
1686     IPCPDEBUG(("ipcp: returning Configure-%s", CODENAME(rc)));
1687     return (rc);			/* Return final code */
1688 }
1689 
1690 
1691 /*
1692  * ip_check_options - check that any IP-related options are OK,
1693  * and assign appropriate defaults.
1694  */
1695 static void
1696 ip_check_options()
1697 {
1698     struct hostent *hp;
1699     u_int32_t local;
1700     ipcp_options *wo = &ipcp_wantoptions[0];
1701 
1702     /*
1703      * Default our local IP address based on our hostname.
1704      * If local IP address already given, don't bother.
1705      */
1706     if (wo->ouraddr == 0 && !disable_defaultip) {
1707 	/*
1708 	 * Look up our hostname (possibly with domain name appended)
1709 	 * and take the first IP address as our local IP address.
1710 	 * If there isn't an IP address for our hostname, too bad.
1711 	 */
1712 	wo->accept_local = 1;	/* don't insist on this default value */
1713 	if ((hp = gethostbyname(hostname)) != NULL) {
1714 	    local = *(u_int32_t *)hp->h_addr;
1715 	    if (local != 0 && !bad_ip_adrs(local))
1716 		wo->ouraddr = local;
1717 	}
1718     }
1719     ask_for_local = wo->ouraddr != 0 || !disable_defaultip;
1720 }
1721 
1722 
1723 /*
1724  * ip_demand_conf - configure the interface as though
1725  * IPCP were up, for use with dial-on-demand.
1726  */
1727 static int
1728 ip_demand_conf(u)
1729     int u;
1730 {
1731     ipcp_options *wo = &ipcp_wantoptions[u];
1732 
1733     if (wo->hisaddr == 0 && !noremoteip) {
1734 	/* make up an arbitrary address for the peer */
1735 	wo->hisaddr = htonl(0x0a707070 + ifunit);
1736 	wo->accept_remote = 1;
1737     }
1738     if (wo->ouraddr == 0) {
1739 	/* make up an arbitrary address for us */
1740 	wo->ouraddr = htonl(0x0a404040 + ifunit);
1741 	wo->accept_local = 1;
1742 	ask_for_local = 0;	/* don't tell the peer this address */
1743     }
1744     if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr)))
1745 	return 0;
1746     ipcp_script(_PATH_IPPREUP, 1);
1747     if (!sifup(u))
1748 	return 0;
1749     if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
1750 	return 0;
1751     if (wo->default_route)
1752 	if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
1753 	    default_route_set[u] = 1;
1754     if (wo->proxy_arp)
1755 	if (sifproxyarp(u, wo->hisaddr))
1756 	    proxy_arp_set[u] = 1;
1757 
1758     notice("local  IP address %I", wo->ouraddr);
1759     if (wo->hisaddr)
1760 	notice("remote IP address %I", wo->hisaddr);
1761 
1762     return 1;
1763 }
1764 
1765 
1766 /*
1767  * ipcp_up - IPCP has come UP.
1768  *
1769  * Configure the IP network interface appropriately and bring it up.
1770  */
1771 static void
1772 ipcp_up(f)
1773     fsm *f;
1774 {
1775     u_int32_t mask;
1776     ipcp_options *ho = &ipcp_hisoptions[f->unit];
1777     ipcp_options *go = &ipcp_gotoptions[f->unit];
1778     ipcp_options *wo = &ipcp_wantoptions[f->unit];
1779 
1780     IPCPDEBUG(("ipcp: up"));
1781 
1782     /*
1783      * We must have a non-zero IP address for both ends of the link.
1784      */
1785     if (!ho->neg_addr && !ho->old_addrs)
1786 	ho->hisaddr = wo->hisaddr;
1787 
1788     if (!(go->neg_addr || go->old_addrs) && (wo->neg_addr || wo->old_addrs)
1789 	&& wo->ouraddr != 0) {
1790 	error("Peer refused to agree to our IP address");
1791 	ipcp_close(f->unit, "Refused our IP address");
1792 	return;
1793     }
1794     if (go->ouraddr == 0) {
1795 	error("Could not determine local IP address");
1796 	ipcp_close(f->unit, "Could not determine local IP address");
1797 	return;
1798     }
1799     if (ho->hisaddr == 0 && !noremoteip) {
1800 	ho->hisaddr = htonl(0x0a404040 + ifunit);
1801 	warn("Could not determine remote IP address: defaulting to %I",
1802 	     ho->hisaddr);
1803     }
1804     script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0);
1805     if (ho->hisaddr != 0)
1806 	script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1);
1807 
1808     if (!go->req_dns1)
1809 	    go->dnsaddr[0] = 0;
1810     if (!go->req_dns2)
1811 	    go->dnsaddr[1] = 0;
1812     if (go->dnsaddr[0])
1813 	script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0);
1814     if (go->dnsaddr[1])
1815 	script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0);
1816     if (usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) {
1817 	script_setenv("USEPEERDNS", "1", 0);
1818 	create_resolv(go->dnsaddr[0], go->dnsaddr[1]);
1819     }
1820 
1821     /*
1822      * Check that the peer is allowed to use the IP address it wants.
1823      */
1824     if (ho->hisaddr != 0 && !auth_ip_addr(f->unit, ho->hisaddr)) {
1825 	error("Peer is not authorized to use remote address %I", ho->hisaddr);
1826 	ipcp_close(f->unit, "Unauthorized remote IP address");
1827 	return;
1828     }
1829 
1830     /* set tcp compression */
1831     sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex);
1832 
1833     /*
1834      * If we are doing dial-on-demand, the interface is already
1835      * configured, so we put out any saved-up packets, then set the
1836      * interface to pass IP packets.
1837      */
1838     if (demand) {
1839 	if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
1840 	    ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr);
1841 	    if (go->ouraddr != wo->ouraddr) {
1842 		warn("Local IP address changed to %I", go->ouraddr);
1843 		script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0);
1844 		wo->ouraddr = go->ouraddr;
1845 	    } else
1846 		script_unsetenv("OLDIPLOCAL");
1847 	    if (ho->hisaddr != wo->hisaddr && wo->hisaddr != 0) {
1848 		warn("Remote IP address changed to %I", ho->hisaddr);
1849 		script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0);
1850 		wo->hisaddr = ho->hisaddr;
1851 	    } else
1852 		script_unsetenv("OLDIPREMOTE");
1853 
1854 	    /* Set the interface to the new addresses */
1855 	    mask = GetMask(go->ouraddr);
1856 	    if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1857 		if (debug)
1858 		    warn("Interface configuration failed");
1859 		ipcp_close(f->unit, "Interface configuration failed");
1860 		return;
1861 	    }
1862 
1863 	    /* assign a default route through the interface if required */
1864 	    if (ipcp_wantoptions[f->unit].default_route)
1865 		if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
1866 		    default_route_set[f->unit] = 1;
1867 
1868 	    /* Make a proxy ARP entry if requested. */
1869 	    if (ho->hisaddr != 0 && ipcp_wantoptions[f->unit].proxy_arp)
1870 		if (sifproxyarp(f->unit, ho->hisaddr))
1871 		    proxy_arp_set[f->unit] = 1;
1872 
1873 	}
1874 	demand_rexmit(PPP_IP);
1875 	sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
1876 
1877     } else {
1878 	/*
1879 	 * Set IP addresses and (if specified) netmask.
1880 	 */
1881 	mask = GetMask(go->ouraddr);
1882 
1883 #if !(defined(SVR4) && (defined(SNI) || defined(__USLC__)))
1884 	if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1885 	    if (debug)
1886 		warn("Interface configuration failed");
1887 	    ipcp_close(f->unit, "Interface configuration failed");
1888 	    return;
1889 	}
1890 #endif
1891 
1892 	/* run the pre-up script, if any, and wait for it to finish */
1893 	ipcp_script(_PATH_IPPREUP, 1);
1894 
1895 	/* bring the interface up for IP */
1896 	if (!sifup(f->unit)) {
1897 	    if (debug)
1898 		warn("Interface failed to come up");
1899 	    ipcp_close(f->unit, "Interface configuration failed");
1900 	    return;
1901 	}
1902 
1903 #if (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
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 #endif
1911 	sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
1912 
1913 	/* assign a default route through the interface if required */
1914 	if (ipcp_wantoptions[f->unit].default_route)
1915 	    if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
1916 		default_route_set[f->unit] = 1;
1917 
1918 	/* Make a proxy ARP entry if requested. */
1919 	if (ho->hisaddr != 0 && ipcp_wantoptions[f->unit].proxy_arp)
1920 	    if (sifproxyarp(f->unit, ho->hisaddr))
1921 		proxy_arp_set[f->unit] = 1;
1922 
1923 	ipcp_wantoptions[0].ouraddr = go->ouraddr;
1924 
1925 	notice("local  IP address %I", go->ouraddr);
1926 	if (ho->hisaddr != 0)
1927 	    notice("remote IP address %I", ho->hisaddr);
1928 	if (go->dnsaddr[0])
1929 	    notice("primary   DNS address %I", go->dnsaddr[0]);
1930 	if (go->dnsaddr[1])
1931 	    notice("secondary DNS address %I", go->dnsaddr[1]);
1932     }
1933 
1934     reset_link_stats(f->unit);
1935 
1936     np_up(f->unit, PPP_IP);
1937     ipcp_is_up = 1;
1938 
1939     notify(ip_up_notifier, 0);
1940     if (ip_up_hook)
1941 	ip_up_hook();
1942 
1943     /*
1944      * Execute the ip-up script, like this:
1945      *	/etc/ppp/ip-up interface tty speed local-IP remote-IP
1946      */
1947     if (ipcp_script_state == s_down && ipcp_script_pid == 0) {
1948 	ipcp_script_state = s_up;
1949 	ipcp_script(_PATH_IPUP, 0);
1950     }
1951 }
1952 
1953 
1954 /*
1955  * ipcp_down - IPCP has gone DOWN.
1956  *
1957  * Take the IP network interface down, clear its addresses
1958  * and delete routes through it.
1959  */
1960 static void
1961 ipcp_down(f)
1962     fsm *f;
1963 {
1964     IPCPDEBUG(("ipcp: down"));
1965     /* XXX a bit IPv4-centric here, we only need to get the stats
1966      * before the interface is marked down. */
1967     /* XXX more correct: we must get the stats before running the notifiers,
1968      * at least for the radius plugin */
1969     update_link_stats(f->unit);
1970     notify(ip_down_notifier, 0);
1971     if (ip_down_hook)
1972 	ip_down_hook();
1973     if (ipcp_is_up) {
1974 	ipcp_is_up = 0;
1975 	np_down(f->unit, PPP_IP);
1976     }
1977     sifvjcomp(f->unit, 0, 0, 0);
1978 
1979     print_link_stats(); /* _after_ running the notifiers and ip_down_hook(),
1980 			 * because print_link_stats() sets link_stats_valid
1981 			 * to 0 (zero) */
1982 
1983     /*
1984      * If we are doing dial-on-demand, set the interface
1985      * to queue up outgoing packets (for now).
1986      */
1987     if (demand) {
1988 	sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE);
1989     } else {
1990 	sifnpmode(f->unit, PPP_IP, NPMODE_DROP);
1991 	sifdown(f->unit);
1992 	ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr,
1993 			 ipcp_hisoptions[f->unit].hisaddr);
1994     }
1995 
1996     /* Execute the ip-down script */
1997     if (ipcp_script_state == s_up && ipcp_script_pid == 0) {
1998 	ipcp_script_state = s_down;
1999 	ipcp_script(_PATH_IPDOWN, 0);
2000     }
2001 }
2002 
2003 
2004 /*
2005  * ipcp_clear_addrs() - clear the interface addresses, routes,
2006  * proxy arp entries, etc.
2007  */
2008 static void
2009 ipcp_clear_addrs(unit, ouraddr, hisaddr)
2010     int unit;
2011     u_int32_t ouraddr;  /* local address */
2012     u_int32_t hisaddr;  /* remote address */
2013 {
2014     if (proxy_arp_set[unit]) {
2015 	cifproxyarp(unit, hisaddr);
2016 	proxy_arp_set[unit] = 0;
2017     }
2018     if (default_route_set[unit]) {
2019 	cifdefaultroute(unit, ouraddr, hisaddr);
2020 	default_route_set[unit] = 0;
2021     }
2022     cifaddr(unit, ouraddr, hisaddr);
2023 }
2024 
2025 
2026 /*
2027  * ipcp_finished - possibly shut down the lower layers.
2028  */
2029 static void
2030 ipcp_finished(f)
2031     fsm *f;
2032 {
2033 	if (ipcp_is_open) {
2034 		ipcp_is_open = 0;
2035 		np_finished(f->unit, PPP_IP);
2036 	}
2037 }
2038 
2039 
2040 /*
2041  * ipcp_script_done - called when the ip-up or ip-down script
2042  * has finished.
2043  */
2044 static void
2045 ipcp_script_done(arg)
2046     void *arg;
2047 {
2048     ipcp_script_pid = 0;
2049     switch (ipcp_script_state) {
2050     case s_up:
2051 	if (ipcp_fsm[0].state != OPENED) {
2052 	    ipcp_script_state = s_down;
2053 	    ipcp_script(_PATH_IPDOWN, 0);
2054 	}
2055 	break;
2056     case s_down:
2057 	if (ipcp_fsm[0].state == OPENED) {
2058 	    ipcp_script_state = s_up;
2059 	    ipcp_script(_PATH_IPUP, 0);
2060 	}
2061 	break;
2062     }
2063 }
2064 
2065 
2066 /*
2067  * ipcp_script - Execute a script with arguments
2068  * interface-name tty-name speed local-IP remote-IP.
2069  */
2070 static void
2071 ipcp_script(script, wait)
2072     char *script;
2073     int wait;
2074 {
2075     char strspeed[32], strlocal[32], strremote[32];
2076     char *argv[8];
2077 
2078     slprintf(strspeed, sizeof(strspeed), "%d", baud_rate);
2079     slprintf(strlocal, sizeof(strlocal), "%I", ipcp_gotoptions[0].ouraddr);
2080     slprintf(strremote, sizeof(strremote), "%I", ipcp_hisoptions[0].hisaddr);
2081 
2082     argv[0] = script;
2083     argv[1] = ifname;
2084     argv[2] = devnam;
2085     argv[3] = strspeed;
2086     argv[4] = strlocal;
2087     argv[5] = strremote;
2088     argv[6] = ipparam;
2089     argv[7] = NULL;
2090     if (wait)
2091 	run_program(script, argv, 0, NULL, NULL, 1);
2092     else
2093 	ipcp_script_pid = run_program(script, argv, 0, ipcp_script_done,
2094 				      NULL, 0);
2095 }
2096 
2097 /*
2098  * create_resolv - create the replacement resolv.conf file
2099  */
2100 static void
2101 create_resolv(peerdns1, peerdns2)
2102     u_int32_t peerdns1, peerdns2;
2103 {
2104     FILE *f;
2105 
2106     f = fopen(_PATH_RESOLV, "w");
2107     if (f == NULL) {
2108 	error("Failed to create %s: %m", _PATH_RESOLV);
2109 	return;
2110     }
2111 
2112     if (peerdns1)
2113 	fprintf(f, "nameserver %s\n", ip_ntoa(peerdns1));
2114 
2115     if (peerdns2)
2116 	fprintf(f, "nameserver %s\n", ip_ntoa(peerdns2));
2117 
2118     if (ferror(f))
2119 	error("Write failed to %s: %m", _PATH_RESOLV);
2120 
2121     fclose(f);
2122 }
2123 
2124 /*
2125  * ipcp_printpkt - print the contents of an IPCP packet.
2126  */
2127 static char *ipcp_codenames[] = {
2128     "ConfReq", "ConfAck", "ConfNak", "ConfRej",
2129     "TermReq", "TermAck", "CodeRej"
2130 };
2131 
2132 static int
2133 ipcp_printpkt(p, plen, printer, arg)
2134     u_char *p;
2135     int plen;
2136     void (*printer) __P((void *, char *, ...));
2137     void *arg;
2138 {
2139     int code, id, len, olen;
2140     u_char *pstart, *optend;
2141     u_short cishort;
2142     u_int32_t cilong;
2143 
2144     if (plen < HEADERLEN)
2145 	return 0;
2146     pstart = p;
2147     GETCHAR(code, p);
2148     GETCHAR(id, p);
2149     GETSHORT(len, p);
2150     if (len < HEADERLEN || len > plen)
2151 	return 0;
2152 
2153     if (code >= 1 && code <= sizeof(ipcp_codenames) / sizeof(char *))
2154 	printer(arg, " %s", ipcp_codenames[code-1]);
2155     else
2156 	printer(arg, " code=0x%x", code);
2157     printer(arg, " id=0x%x", id);
2158     len -= HEADERLEN;
2159     switch (code) {
2160     case CONFREQ:
2161     case CONFACK:
2162     case CONFNAK:
2163     case CONFREJ:
2164 	/* print option list */
2165 	while (len >= 2) {
2166 	    GETCHAR(code, p);
2167 	    GETCHAR(olen, p);
2168 	    p -= 2;
2169 	    if (olen < 2 || olen > len) {
2170 		break;
2171 	    }
2172 	    printer(arg, " <");
2173 	    len -= olen;
2174 	    optend = p + olen;
2175 	    switch (code) {
2176 	    case CI_ADDRS:
2177 		if (olen == CILEN_ADDRS) {
2178 		    p += 2;
2179 		    GETLONG(cilong, p);
2180 		    printer(arg, "addrs %I", htonl(cilong));
2181 		    GETLONG(cilong, p);
2182 		    printer(arg, " %I", htonl(cilong));
2183 		}
2184 		break;
2185 	    case CI_COMPRESSTYPE:
2186 		if (olen >= CILEN_COMPRESS) {
2187 		    p += 2;
2188 		    GETSHORT(cishort, p);
2189 		    printer(arg, "compress ");
2190 		    switch (cishort) {
2191 		    case IPCP_VJ_COMP:
2192 			printer(arg, "VJ");
2193 			break;
2194 		    case IPCP_VJ_COMP_OLD:
2195 			printer(arg, "old-VJ");
2196 			break;
2197 		    default:
2198 			printer(arg, "0x%x", cishort);
2199 		    }
2200 		}
2201 		break;
2202 	    case CI_ADDR:
2203 		if (olen == CILEN_ADDR) {
2204 		    p += 2;
2205 		    GETLONG(cilong, p);
2206 		    printer(arg, "addr %I", htonl(cilong));
2207 		}
2208 		break;
2209 	    case CI_MS_DNS1:
2210 	    case CI_MS_DNS2:
2211 	        p += 2;
2212 		GETLONG(cilong, p);
2213 		printer(arg, "ms-dns%d %I", (code == CI_MS_DNS1? 1: 2),
2214 			htonl(cilong));
2215 		break;
2216 	    case CI_MS_WINS1:
2217 	    case CI_MS_WINS2:
2218 	        p += 2;
2219 		GETLONG(cilong, p);
2220 		printer(arg, "ms-wins %I", htonl(cilong));
2221 		break;
2222 	    }
2223 	    while (p < optend) {
2224 		GETCHAR(code, p);
2225 		printer(arg, " %.2x", code);
2226 	    }
2227 	    printer(arg, ">");
2228 	}
2229 	break;
2230 
2231     case TERMACK:
2232     case TERMREQ:
2233 	if (len > 0 && *p >= ' ' && *p < 0x7f) {
2234 	    printer(arg, " ");
2235 	    print_string((char *)p, len, printer, arg);
2236 	    p += len;
2237 	    len = 0;
2238 	}
2239 	break;
2240     }
2241 
2242     /* print the rest of the bytes in the packet */
2243     for (; len > 0; --len) {
2244 	GETCHAR(code, p);
2245 	printer(arg, " %.2x", code);
2246     }
2247 
2248     return p - pstart;
2249 }
2250 
2251 /*
2252  * ip_active_pkt - see if this IP packet is worth bringing the link up for.
2253  * We don't bring the link up for IP fragments or for TCP FIN packets
2254  * with no data.
2255  */
2256 #define IP_HDRLEN	20	/* bytes */
2257 #define IP_OFFMASK	0x1fff
2258 #ifndef IPPROTO_TCP
2259 #define IPPROTO_TCP	6
2260 #endif
2261 #define TCP_HDRLEN	20
2262 #define TH_FIN		0x01
2263 
2264 /*
2265  * We use these macros because the IP header may be at an odd address,
2266  * and some compilers might use word loads to get th_off or ip_hl.
2267  */
2268 
2269 #define net_short(x)	(((x)[0] << 8) + (x)[1])
2270 #define get_iphl(x)	(((unsigned char *)(x))[0] & 0xF)
2271 #define get_ipoff(x)	net_short((unsigned char *)(x) + 6)
2272 #define get_ipproto(x)	(((unsigned char *)(x))[9])
2273 #define get_tcpoff(x)	(((unsigned char *)(x))[12] >> 4)
2274 #define get_tcpflags(x)	(((unsigned char *)(x))[13])
2275 
2276 static int
2277 ip_active_pkt(pkt, len)
2278     u_char *pkt;
2279     int len;
2280 {
2281     u_char *tcp;
2282     int hlen;
2283 
2284     len -= PPP_HDRLEN;
2285     pkt += PPP_HDRLEN;
2286     if (len < IP_HDRLEN)
2287 	return 0;
2288     if ((get_ipoff(pkt) & IP_OFFMASK) != 0)
2289 	return 0;
2290     if (get_ipproto(pkt) != IPPROTO_TCP)
2291 	return 1;
2292     hlen = get_iphl(pkt) * 4;
2293     if (len < hlen + TCP_HDRLEN)
2294 	return 0;
2295     tcp = pkt + hlen;
2296     if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4)
2297 	return 0;
2298     return 1;
2299 }
2300