1 /*	$OpenBSD: ipcp.c,v 1.11 2003/07/18 22:58:56 david 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 #ifndef lint
46 #if 0
47 static char rcsid[] = "Id: ipcp.c,v 1.34 1998/04/28 23:38:09 paulus Exp $";
48 #else
49 static char rcsid[] = "$OpenBSD: ipcp.c,v 1.11 2003/07/18 22:58:56 david Exp $";
50 #endif
51 #endif
52 
53 /*
54  * TODO:
55  */
56 
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <syslog.h>
61 #include <netdb.h>
62 #include <sys/param.h>
63 #include <sys/types.h>
64 #include <sys/socket.h>
65 #include <netinet/in.h>
66 
67 #include "pppd.h"
68 #include "fsm.h"
69 #include "ipcp.h"
70 #include "pathnames.h"
71 
72 /* global vars */
73 ipcp_options ipcp_wantoptions[NUM_PPP];	/* Options that we want to request */
74 ipcp_options ipcp_gotoptions[NUM_PPP];	/* Options that peer ack'd */
75 ipcp_options ipcp_allowoptions[NUM_PPP];	/* Options we allow peer to request */
76 ipcp_options ipcp_hisoptions[NUM_PPP];	/* Options that we ack'd */
77 
78 /* local vars */
79 static int cis_received[NUM_PPP];	/* # Conf-Reqs received */
80 static int default_route_set[NUM_PPP];	/* Have set up a default route */
81 static int proxy_arp_set[NUM_PPP];	/* Have created proxy arp entry */
82 
83 /*
84  * Callbacks for fsm code.  (CI = Configuration Information)
85  */
86 static void ipcp_resetci(fsm *);	/* Reset our CI */
87 static int  ipcp_cilen(fsm *);	        /* Return length of our CI */
88 static void ipcp_addci(fsm *, u_char *, int *);	/* Add our CI */
89 static int  ipcp_ackci(fsm *, u_char *, int);	/* Peer ack'd our CI */
90 static int  ipcp_nakci(fsm *, u_char *, int);	/* Peer nak'd our CI */
91 static int  ipcp_rejci(fsm *, u_char *, int);	/* Peer rej'd our CI */
92 static int  ipcp_reqci(fsm *, u_char *, int *, int); /* Rcv CI */
93 static void ipcp_up(fsm *);		/* We're UP */
94 static void ipcp_down(fsm *);		/* We're DOWN */
95 static void ipcp_script(fsm *, char *); /* Run an up/down script */
96 static void ipcp_finished(fsm *);	/* Don't need lower layer */
97 
98 fsm ipcp_fsm[NUM_PPP];		/* IPCP fsm structure */
99 
100 static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
101     ipcp_resetci,		/* Reset our Configuration Information */
102     ipcp_cilen,			/* Length of our Configuration Information */
103     ipcp_addci,			/* Add our Configuration Information */
104     ipcp_ackci,			/* ACK our Configuration Information */
105     ipcp_nakci,			/* NAK our Configuration Information */
106     ipcp_rejci,			/* Reject our Configuration Information */
107     ipcp_reqci,			/* Request peer's Configuration Information */
108     ipcp_up,			/* Called when fsm reaches OPENED state */
109     ipcp_down,			/* Called when fsm leaves OPENED state */
110     NULL,			/* Called when we want the lower layer up */
111     ipcp_finished,		/* Called when we want the lower layer down */
112     NULL,			/* Called when Protocol-Reject received */
113     NULL,			/* Retransmission is necessary */
114     NULL,			/* Called to handle protocol-specific codes */
115     "IPCP"			/* String name of protocol */
116 };
117 
118 /*
119  * Protocol entry points from main code.
120  */
121 static void ipcp_init(int);
122 static void ipcp_open(int);
123 static void ipcp_close(int, char *);
124 static void ipcp_lowerup(int);
125 static void ipcp_lowerdown(int);
126 static void ipcp_input(int, u_char *, int);
127 static void ipcp_protrej(int);
128 static int  ipcp_printpkt(u_char *, int, void (*)(void *, char *, ...), void *);
129 static void ip_check_options(void);
130 static int  ip_demand_conf(int);
131 static int  ip_active_pkt(u_char *, int);
132 
133 struct protent ipcp_protent = {
134     PPP_IPCP,
135     ipcp_init,
136     ipcp_input,
137     ipcp_protrej,
138     ipcp_lowerup,
139     ipcp_lowerdown,
140     ipcp_open,
141     ipcp_close,
142     ipcp_printpkt,
143     NULL,
144     1,
145     "IPCP",
146     ip_check_options,
147     ip_demand_conf,
148     ip_active_pkt
149 };
150 
151 static void ipcp_clear_addrs(int);
152 
153 /*
154  * Lengths of configuration options.
155  */
156 #define CILEN_VOID	2
157 #define CILEN_COMPRESS	4	/* min length for compression protocol opt. */
158 #define CILEN_VJ	6	/* length for RFC1332 Van-Jacobson opt. */
159 #define CILEN_ADDR	6	/* new-style single address option */
160 #define CILEN_ADDRS	10	/* old-style dual address option */
161 
162 
163 #define CODENAME(x)	((x) == CONFACK ? "ACK" : \
164 			 (x) == CONFNAK ? "NAK" : "REJ")
165 
166 
167 /*
168  * Make a string representation of a network IP address.
169  */
170 char *
ip_ntoa(ipaddr)171 ip_ntoa(ipaddr)
172 u_int32_t ipaddr;
173 {
174     static char b[64];
175 
176     ipaddr = ntohl(ipaddr);
177 
178     snprintf(b, sizeof b, "%d.%d.%d.%d",
179 	    (u_char)(ipaddr >> 24),
180 	    (u_char)(ipaddr >> 16),
181 	    (u_char)(ipaddr >> 8),
182 	    (u_char)(ipaddr));
183     return b;
184 }
185 
186 
187 /*
188  * ipcp_init - Initialize IPCP.
189  */
190 static void
ipcp_init(unit)191 ipcp_init(unit)
192     int unit;
193 {
194     fsm *f = &ipcp_fsm[unit];
195     ipcp_options *wo = &ipcp_wantoptions[unit];
196     ipcp_options *ao = &ipcp_allowoptions[unit];
197 
198     f->unit = unit;
199     f->protocol = PPP_IPCP;
200     f->callbacks = &ipcp_callbacks;
201     fsm_init(&ipcp_fsm[unit]);
202 
203     memset(wo, 0, sizeof(*wo));
204     memset(ao, 0, sizeof(*ao));
205 
206     wo->neg_addr = 1;
207     wo->neg_vj = 1;
208     wo->vj_protocol = IPCP_VJ_COMP;
209     wo->maxslotindex = MAX_STATES - 1; /* really max index */
210     wo->cflag = 1;
211 
212     /* max slots and slot-id compression are currently hardwired in */
213     /* ppp_if.c to 16 and 1, this needs to be changed (among other */
214     /* things) gmc */
215 
216     ao->neg_addr = 1;
217     ao->neg_vj = 1;
218     ao->maxslotindex = MAX_STATES - 1;
219     ao->cflag = 1;
220 
221     /*
222      * XXX These control whether the user may use the proxyarp
223      * and defaultroute options.
224      */
225     ao->proxy_arp = 1;
226     ao->default_route = 1;
227 }
228 
229 
230 /*
231  * ipcp_open - IPCP is allowed to come up.
232  */
233 static void
ipcp_open(unit)234 ipcp_open(unit)
235     int unit;
236 {
237     fsm_open(&ipcp_fsm[unit]);
238 }
239 
240 
241 /*
242  * ipcp_close - Take IPCP down.
243  */
244 static void
ipcp_close(unit,reason)245 ipcp_close(unit, reason)
246     int unit;
247     char *reason;
248 {
249     fsm_close(&ipcp_fsm[unit], reason);
250 }
251 
252 
253 /*
254  * ipcp_lowerup - The lower layer is up.
255  */
256 static void
ipcp_lowerup(unit)257 ipcp_lowerup(unit)
258     int unit;
259 {
260     fsm_lowerup(&ipcp_fsm[unit]);
261 }
262 
263 
264 /*
265  * ipcp_lowerdown - The lower layer is down.
266  */
267 static void
ipcp_lowerdown(unit)268 ipcp_lowerdown(unit)
269     int unit;
270 {
271     fsm_lowerdown(&ipcp_fsm[unit]);
272 }
273 
274 
275 /*
276  * ipcp_input - Input IPCP packet.
277  */
278 static void
ipcp_input(unit,p,len)279 ipcp_input(unit, p, len)
280     int unit;
281     u_char *p;
282     int len;
283 {
284     fsm_input(&ipcp_fsm[unit], p, len);
285 }
286 
287 
288 /*
289  * ipcp_protrej - A Protocol-Reject was received for IPCP.
290  *
291  * Pretend the lower layer went down, so we shut up.
292  */
293 static void
ipcp_protrej(unit)294 ipcp_protrej(unit)
295     int unit;
296 {
297     fsm_lowerdown(&ipcp_fsm[unit]);
298 }
299 
300 
301 /*
302  * ipcp_resetci - Reset our CI.
303  */
304 static void
ipcp_resetci(f)305 ipcp_resetci(f)
306     fsm *f;
307 {
308     ipcp_options *wo = &ipcp_wantoptions[f->unit];
309 
310     wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr;
311     if (wo->ouraddr == 0)
312 	wo->accept_local = 1;
313     if (wo->hisaddr == 0)
314 	wo->accept_remote = 1;
315     ipcp_gotoptions[f->unit] = *wo;
316     cis_received[f->unit] = 0;
317 }
318 
319 
320 /*
321  * ipcp_cilen - Return length of our CI.
322  */
323 static int
ipcp_cilen(f)324 ipcp_cilen(f)
325     fsm *f;
326 {
327     ipcp_options *go = &ipcp_gotoptions[f->unit];
328     ipcp_options *wo = &ipcp_wantoptions[f->unit];
329     ipcp_options *ho = &ipcp_hisoptions[f->unit];
330 
331 #define LENCIVJ(neg, old)	(neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0)
332 #define LENCIADDR(neg, old)	(neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0)
333 
334     /*
335      * First see if we want to change our options to the old
336      * forms because we have received old forms from the peer.
337      */
338     if (wo->neg_addr && !go->neg_addr && !go->old_addrs) {
339 	/* use the old style of address negotiation */
340 	go->neg_addr = 1;
341 	go->old_addrs = 1;
342     }
343     if (wo->neg_vj && !go->neg_vj && !go->old_vj) {
344 	/* try an older style of VJ negotiation */
345 	if (cis_received[f->unit] == 0) {
346 	    /* keep trying the new style until we see some CI from the peer */
347 	    go->neg_vj = 1;
348 	} else {
349 	    /* use the old style only if the peer did */
350 	    if (ho->neg_vj && ho->old_vj) {
351 		go->neg_vj = 1;
352 		go->old_vj = 1;
353 		go->vj_protocol = ho->vj_protocol;
354 	    }
355 	}
356     }
357 
358     return (LENCIADDR(go->neg_addr, go->old_addrs) +
359 	    LENCIVJ(go->neg_vj, go->old_vj));
360 }
361 
362 
363 /*
364  * ipcp_addci - Add our desired CIs to a packet.
365  */
366 static void
ipcp_addci(f,ucp,lenp)367 ipcp_addci(f, ucp, lenp)
368     fsm *f;
369     u_char *ucp;
370     int *lenp;
371 {
372     ipcp_options *go = &ipcp_gotoptions[f->unit];
373     int len = *lenp;
374 
375 #define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \
376     if (neg) { \
377 	int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
378 	if (len >= vjlen) { \
379 	    PUTCHAR(opt, ucp); \
380 	    PUTCHAR(vjlen, ucp); \
381 	    PUTSHORT(val, ucp); \
382 	    if (!old) { \
383 		PUTCHAR(maxslotindex, ucp); \
384 		PUTCHAR(cflag, ucp); \
385 	    } \
386 	    len -= vjlen; \
387 	} else \
388 	    neg = 0; \
389     }
390 
391 #define ADDCIADDR(opt, neg, old, val1, val2) \
392     if (neg) { \
393 	int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
394 	if (len >= addrlen) { \
395 	    u_int32_t l; \
396 	    PUTCHAR(opt, ucp); \
397 	    PUTCHAR(addrlen, ucp); \
398 	    l = ntohl(val1); \
399 	    PUTLONG(l, ucp); \
400 	    if (old) { \
401 		l = ntohl(val2); \
402 		PUTLONG(l, ucp); \
403 	    } \
404 	    len -= addrlen; \
405 	} else \
406 	    neg = 0; \
407     }
408 
409     ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
410 	      go->old_addrs, go->ouraddr, go->hisaddr);
411 
412     ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
413 	    go->maxslotindex, go->cflag);
414 
415     *lenp -= len;
416 }
417 
418 
419 /*
420  * ipcp_ackci - Ack our CIs.
421  *
422  * Returns:
423  *	0 - Ack was bad.
424  *	1 - Ack was good.
425  */
426 static int
ipcp_ackci(f,p,len)427 ipcp_ackci(f, p, len)
428     fsm *f;
429     u_char *p;
430     int len;
431 {
432     ipcp_options *go = &ipcp_gotoptions[f->unit];
433     u_short cilen, citype, cishort;
434     u_int32_t cilong;
435     u_char cimaxslotindex, cicflag;
436 
437     /*
438      * CIs must be in exactly the same order that we sent...
439      * Check packet length and CI length at each step.
440      * If we find any deviations, then this packet is bad.
441      */
442 
443 #define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \
444     if (neg) { \
445 	int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
446 	if ((len -= vjlen) < 0) \
447 	    goto bad; \
448 	GETCHAR(citype, p); \
449 	GETCHAR(cilen, p); \
450 	if (cilen != vjlen || \
451 	    citype != opt)  \
452 	    goto bad; \
453 	GETSHORT(cishort, p); \
454 	if (cishort != val) \
455 	    goto bad; \
456 	if (!old) { \
457 	    GETCHAR(cimaxslotindex, p); \
458 	    if (cimaxslotindex != maxslotindex) \
459 		goto bad; \
460 	    GETCHAR(cicflag, p); \
461 	    if (cicflag != cflag) \
462 		goto bad; \
463 	} \
464     }
465 
466 #define ACKCIADDR(opt, neg, old, val1, val2) \
467     if (neg) { \
468 	int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
469 	u_int32_t l; \
470 	if ((len -= addrlen) < 0) \
471 	    goto bad; \
472 	GETCHAR(citype, p); \
473 	GETCHAR(cilen, p); \
474 	if (cilen != addrlen || \
475 	    citype != opt) \
476 	    goto bad; \
477 	GETLONG(l, p); \
478 	cilong = htonl(l); \
479 	if (val1 != cilong) \
480 	    goto bad; \
481 	if (old) { \
482 	    GETLONG(l, p); \
483 	    cilong = htonl(l); \
484 	    if (val2 != cilong) \
485 		goto bad; \
486 	} \
487     }
488 
489     ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
490 	      go->old_addrs, go->ouraddr, go->hisaddr);
491 
492     ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
493 	    go->maxslotindex, go->cflag);
494 
495     /*
496      * If there are any remaining CIs, then this packet is bad.
497      */
498     if (len != 0)
499 	goto bad;
500     return (1);
501 
502 bad:
503     IPCPDEBUG((LOG_INFO, "ipcp_ackci: received bad Ack!"));
504     return (0);
505 }
506 
507 /*
508  * ipcp_nakci - Peer has sent a NAK for some of our CIs.
509  * This should not modify any state if the Nak is bad
510  * or if IPCP is in the OPENED state.
511  *
512  * Returns:
513  *	0 - Nak was bad.
514  *	1 - Nak was good.
515  */
516 static int
ipcp_nakci(f,p,len)517 ipcp_nakci(f, p, len)
518     fsm *f;
519     u_char *p;
520     int len;
521 {
522     ipcp_options *go = &ipcp_gotoptions[f->unit];
523     u_char cimaxslotindex, cicflag;
524     u_char citype, cilen, *next;
525     u_short cishort;
526     u_int32_t ciaddr1, ciaddr2, l;
527     ipcp_options no;		/* options we've seen Naks for */
528     ipcp_options try;		/* options to request next time */
529 
530     BZERO(&no, sizeof(no));
531     try = *go;
532 
533     /*
534      * Any Nak'd CIs must be in exactly the same order that we sent.
535      * Check packet length and CI length at each step.
536      * If we find any deviations, then this packet is bad.
537      */
538 #define NAKCIADDR(opt, neg, old, code) \
539     if (go->neg && \
540 	len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \
541 	p[1] == cilen && \
542 	p[0] == opt) { \
543 	len -= cilen; \
544 	INCPTR(2, p); \
545 	GETLONG(l, p); \
546 	ciaddr1 = htonl(l); \
547 	if (old) { \
548 	    GETLONG(l, p); \
549 	    ciaddr2 = htonl(l); \
550 	    no.old_addrs = 1; \
551 	} else \
552 	    ciaddr2 = 0; \
553 	no.neg = 1; \
554 	code \
555     }
556 
557 #define NAKCIVJ(opt, neg, code) \
558     if (go->neg && \
559 	((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \
560 	len >= cilen && \
561 	p[0] == opt) { \
562 	len -= cilen; \
563 	INCPTR(2, p); \
564 	GETSHORT(cishort, p); \
565 	no.neg = 1; \
566         code \
567     }
568 
569     /*
570      * Accept the peer's idea of {our,his} address, if different
571      * from our idea, only if the accept_{local,remote} flag is set.
572      */
573     NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs,
574 	      if (go->accept_local && ciaddr1) { /* Do we know our address? */
575 		  try.ouraddr = ciaddr1;
576 		  IPCPDEBUG((LOG_INFO, "local IP address %s",
577 			     ip_ntoa(ciaddr1)));
578 	      }
579 	      if (go->accept_remote && ciaddr2) { /* Does he know his? */
580 		  try.hisaddr = ciaddr2;
581 		  IPCPDEBUG((LOG_INFO, "remote IP address %s",
582 			     ip_ntoa(ciaddr2)));
583 	      }
584 	      );
585 
586     /*
587      * Accept the peer's value of maxslotindex provided that it
588      * is less than what we asked for.  Turn off slot-ID compression
589      * if the peer wants.  Send old-style compress-type option if
590      * the peer wants.
591      */
592     NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
593 	    if (cilen == CILEN_VJ) {
594 		GETCHAR(cimaxslotindex, p);
595 		GETCHAR(cicflag, p);
596 		if (cishort == IPCP_VJ_COMP) {
597 		    try.old_vj = 0;
598 		    if (cimaxslotindex < go->maxslotindex)
599 			try.maxslotindex = cimaxslotindex;
600 		    if (!cicflag)
601 			try.cflag = 0;
602 		} else {
603 		    try.neg_vj = 0;
604 		}
605 	    } else {
606 		if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) {
607 		    try.old_vj = 1;
608 		    try.vj_protocol = cishort;
609 		} else {
610 		    try.neg_vj = 0;
611 		}
612 	    }
613 	    );
614 
615     /*
616      * There may be remaining CIs, if the peer is requesting negotiation
617      * on an option that we didn't include in our request packet.
618      * If they want to negotiate about IP addresses, we comply.
619      * If they want us to ask for compression, we refuse.
620      */
621     while (len > CILEN_VOID) {
622 	GETCHAR(citype, p);
623 	GETCHAR(cilen, p);
624 	if( (len -= cilen) < 0 )
625 	    goto bad;
626 	next = p + cilen - 2;
627 
628 	switch (citype) {
629 	case CI_COMPRESSTYPE:
630 	    if (go->neg_vj || no.neg_vj ||
631 		(cilen != CILEN_VJ && cilen != CILEN_COMPRESS))
632 		goto bad;
633 	    no.neg_vj = 1;
634 	    break;
635 	case CI_ADDRS:
636 	    if ((go->neg_addr && go->old_addrs) || no.old_addrs
637 		|| cilen != CILEN_ADDRS)
638 		goto bad;
639 	    try.neg_addr = 1;
640 	    try.old_addrs = 1;
641 	    GETLONG(l, p);
642 	    ciaddr1 = htonl(l);
643 	    if (ciaddr1 && go->accept_local)
644 		try.ouraddr = ciaddr1;
645 	    GETLONG(l, p);
646 	    ciaddr2 = htonl(l);
647 	    if (ciaddr2 && go->accept_remote)
648 		try.hisaddr = ciaddr2;
649 	    no.old_addrs = 1;
650 	    break;
651 	case CI_ADDR:
652 	    if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR)
653 		goto bad;
654 	    try.old_addrs = 0;
655 	    GETLONG(l, p);
656 	    ciaddr1 = htonl(l);
657 	    if (ciaddr1 && go->accept_local)
658 		try.ouraddr = ciaddr1;
659 	    if (try.ouraddr != 0)
660 		try.neg_addr = 1;
661 	    no.neg_addr = 1;
662 	    break;
663 	}
664 	p = next;
665     }
666 
667     /* If there is still anything left, this packet is bad. */
668     if (len != 0)
669 	goto bad;
670 
671     /*
672      * OK, the Nak is good.  Now we can update state.
673      */
674     if (f->state != OPENED)
675 	*go = try;
676 
677     return 1;
678 
679 bad:
680     IPCPDEBUG((LOG_INFO, "ipcp_nakci: received bad Nak!"));
681     return 0;
682 }
683 
684 
685 /*
686  * ipcp_rejci - Reject some of our CIs.
687  */
688 static int
ipcp_rejci(f,p,len)689 ipcp_rejci(f, p, len)
690     fsm *f;
691     u_char *p;
692     int len;
693 {
694     ipcp_options *go = &ipcp_gotoptions[f->unit];
695     u_char cimaxslotindex, ciflag, cilen;
696     u_short cishort;
697     u_int32_t cilong;
698     ipcp_options try;		/* options to request next time */
699 
700     try = *go;
701     /*
702      * Any Rejected CIs must be in exactly the same order that we sent.
703      * Check packet length and CI length at each step.
704      * If we find any deviations, then this packet is bad.
705      */
706 #define REJCIADDR(opt, neg, old, val1, val2) \
707     if (go->neg && \
708 	len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \
709 	p[1] == cilen && \
710 	p[0] == opt) { \
711 	u_int32_t l; \
712 	len -= cilen; \
713 	INCPTR(2, p); \
714 	GETLONG(l, p); \
715 	cilong = htonl(l); \
716 	/* Check rejected value. */ \
717 	if (cilong != val1) \
718 	    goto bad; \
719 	if (old) { \
720 	    GETLONG(l, p); \
721 	    cilong = htonl(l); \
722 	    /* Check rejected value. */ \
723 	    if (cilong != val2) \
724 		goto bad; \
725 	} \
726 	try.neg = 0; \
727     }
728 
729 #define REJCIVJ(opt, neg, val, old, maxslot, cflag) \
730     if (go->neg && \
731 	p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \
732 	len >= p[1] && \
733 	p[0] == opt) { \
734 	len -= p[1]; \
735 	INCPTR(2, p); \
736 	GETSHORT(cishort, p); \
737 	/* Check rejected value. */  \
738 	if (cishort != val) \
739 	    goto bad; \
740 	if (!old) { \
741 	   GETCHAR(cimaxslotindex, p); \
742 	   if (cimaxslotindex != maxslot) \
743 	     goto bad; \
744 	   GETCHAR(ciflag, p); \
745 	   if (ciflag != cflag) \
746 	     goto bad; \
747         } \
748 	try.neg = 0; \
749      }
750 
751     REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr,
752 	      go->old_addrs, go->ouraddr, go->hisaddr);
753 
754     REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj,
755 	    go->maxslotindex, go->cflag);
756 
757     /*
758      * If there are any remaining CIs, then this packet is bad.
759      */
760     if (len != 0)
761 	goto bad;
762     /*
763      * Now we can update state.
764      */
765     if (f->state != OPENED)
766 	*go = try;
767     return 1;
768 
769 bad:
770     IPCPDEBUG((LOG_INFO, "ipcp_rejci: received bad Reject!"));
771     return 0;
772 }
773 
774 
775 /*
776  * ipcp_reqci - Check the peer's requested CIs and send appropriate response.
777  *
778  * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
779  * appropriately.  If reject_if_disagree is non-zero, doesn't return
780  * CONFNAK; returns CONFREJ if it can't return CONFACK.
781  */
782 static int
ipcp_reqci(f,inp,len,reject_if_disagree)783 ipcp_reqci(f, inp, len, reject_if_disagree)
784     fsm *f;
785     u_char *inp;		/* Requested CIs */
786     int *len;			/* Length of requested CIs */
787     int reject_if_disagree;
788 {
789     ipcp_options *wo = &ipcp_wantoptions[f->unit];
790     ipcp_options *ho = &ipcp_hisoptions[f->unit];
791     ipcp_options *ao = &ipcp_allowoptions[f->unit];
792     ipcp_options *go = &ipcp_gotoptions[f->unit];
793     u_char *cip, *next;		/* Pointer to current and next CIs */
794     u_short cilen, citype;	/* Parsed len, type */
795     u_short cishort;		/* Parsed short value */
796     u_int32_t tl, ciaddr1, ciaddr2;/* Parsed address values */
797     int rc = CONFACK;		/* Final packet return code */
798     int orc;			/* Individual option return code */
799     u_char *p;			/* Pointer to next char to parse */
800     u_char *ucp = inp;		/* Pointer to current output char */
801     int l = *len;		/* Length left */
802     u_char maxslotindex, cflag;
803     int d;
804 
805     cis_received[f->unit] = 1;
806 
807     /*
808      * Reset all his options.
809      */
810     BZERO(ho, sizeof(*ho));
811 
812     /*
813      * Process all his options.
814      */
815     next = inp;
816     while (l) {
817 	orc = CONFACK;			/* Assume success */
818 	cip = p = next;			/* Remember begining of CI */
819 	if (l < 2 ||			/* Not enough data for CI header or */
820 	    p[1] < 2 ||			/*  CI length too small or */
821 	    p[1] > l) {			/*  CI length too big? */
822 	    IPCPDEBUG((LOG_INFO, "ipcp_reqci: bad CI length!"));
823 	    orc = CONFREJ;		/* Reject bad CI */
824 	    cilen = l;			/* Reject till end of packet */
825 	    l = 0;			/* Don't loop again */
826 	    goto endswitch;
827 	}
828 	GETCHAR(citype, p);		/* Parse CI type */
829 	GETCHAR(cilen, p);		/* Parse CI length */
830 	l -= cilen;			/* Adjust remaining length */
831 	next += cilen;			/* Step to next CI */
832 
833 	switch (citype) {		/* Check CI type */
834 	case CI_ADDRS:
835 	    IPCPDEBUG((LOG_INFO, "ipcp: received ADDRS "));
836 	    if (!ao->neg_addr ||
837 		cilen != CILEN_ADDRS) {	/* Check CI length */
838 		orc = CONFREJ;		/* Reject CI */
839 		break;
840 	    }
841 
842 	    /*
843 	     * If he has no address, or if we both have his address but
844 	     * disagree about it, then NAK it with our idea.
845 	     * In particular, if we don't know his address, but he does,
846 	     * then accept it.
847 	     */
848 	    GETLONG(tl, p);		/* Parse source address (his) */
849 	    ciaddr1 = htonl(tl);
850 	    IPCPDEBUG((LOG_INFO, "(%s:", ip_ntoa(ciaddr1)));
851 	    if (ciaddr1 != wo->hisaddr
852 		&& (ciaddr1 == 0 || !wo->accept_remote)) {
853 		orc = CONFNAK;
854 		if (!reject_if_disagree) {
855 		    DECPTR(sizeof(u_int32_t), p);
856 		    tl = ntohl(wo->hisaddr);
857 		    PUTLONG(tl, p);
858 		}
859 	    } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
860 		/*
861 		 * If neither we nor he knows his address, reject the option.
862 		 */
863 		orc = CONFREJ;
864 		wo->req_addr = 0;	/* don't NAK with 0.0.0.0 later */
865 		break;
866 	    }
867 
868 	    /*
869 	     * If he doesn't know our address, or if we both have our address
870 	     * but disagree about it, then NAK it with our idea.
871 	     */
872 	    GETLONG(tl, p);		/* Parse desination address (ours) */
873 	    ciaddr2 = htonl(tl);
874 	    IPCPDEBUG((LOG_INFO, "%s)", ip_ntoa(ciaddr2)));
875 	    if (ciaddr2 != wo->ouraddr) {
876 		if (ciaddr2 == 0 || !wo->accept_local) {
877 		    orc = CONFNAK;
878 		    if (!reject_if_disagree) {
879 			DECPTR(sizeof(u_int32_t), p);
880 			tl = ntohl(wo->ouraddr);
881 			PUTLONG(tl, p);
882 		    }
883 		} else {
884 		    go->ouraddr = ciaddr2;	/* accept peer's idea */
885 		}
886 	    }
887 
888 	    ho->neg_addr = 1;
889 	    ho->old_addrs = 1;
890 	    ho->hisaddr = ciaddr1;
891 	    ho->ouraddr = ciaddr2;
892 	    break;
893 
894 	case CI_ADDR:
895 	    IPCPDEBUG((LOG_INFO, "ipcp: received ADDR "));
896 
897 	    if (!ao->neg_addr ||
898 		cilen != CILEN_ADDR) {	/* Check CI length */
899 		orc = CONFREJ;		/* Reject CI */
900 		break;
901 	    }
902 
903 	    /*
904 	     * If he has no address, or if we both have his address but
905 	     * disagree about it, then NAK it with our idea.
906 	     * In particular, if we don't know his address, but he does,
907 	     * then accept it.
908 	     */
909 	    GETLONG(tl, p);	/* Parse source address (his) */
910 	    ciaddr1 = htonl(tl);
911 	    IPCPDEBUG((LOG_INFO, "(%s)", ip_ntoa(ciaddr1)));
912 	    if (ciaddr1 != wo->hisaddr
913 		&& (ciaddr1 == 0 || !wo->accept_remote)) {
914 		orc = CONFNAK;
915 		if (!reject_if_disagree) {
916 		    DECPTR(sizeof(u_int32_t), p);
917 		    tl = ntohl(wo->hisaddr);
918 		    PUTLONG(tl, p);
919 		}
920 	    } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
921 		/*
922 		 * Don't ACK an address of 0.0.0.0 - reject it instead.
923 		 */
924 		orc = CONFREJ;
925 		wo->req_addr = 0;	/* don't NAK with 0.0.0.0 later */
926 		break;
927 	    }
928 
929 	    ho->neg_addr = 1;
930 	    ho->hisaddr = ciaddr1;
931 	    break;
932 
933 	case CI_MS_DNS1:
934 	case CI_MS_DNS2:
935 	    /* Microsoft primary or secondary DNS request */
936 	    d = citype == CI_MS_DNS2;
937 	    IPCPDEBUG((LOG_INFO, "ipcp: received DNS%d Request ", d+1));
938 
939 	    /* If we do not have a DNS address then we cannot send it */
940 	    if (ao->dnsaddr[d] == 0 ||
941 		cilen != CILEN_ADDR) {	/* Check CI length */
942 		orc = CONFREJ;		/* Reject CI */
943 		break;
944 	    }
945 	    GETLONG(tl, p);
946 	    if (htonl(tl) != ao->dnsaddr[d]) {
947                 DECPTR(sizeof(u_int32_t), p);
948 		tl = ntohl(ao->dnsaddr[d]);
949 		PUTLONG(tl, p);
950 		orc = CONFNAK;
951             }
952             break;
953 
954 	case CI_MS_WINS1:
955 	case CI_MS_WINS2:
956 	    /* Microsoft primary or secondary WINS request */
957 	    d = citype == CI_MS_WINS2;
958 	    IPCPDEBUG((LOG_INFO, "ipcp: received WINS%d Request ", d+1));
959 
960 	    /* If we do not have a DNS address then we cannot send it */
961 	    if (ao->winsaddr[d] == 0 ||
962 		cilen != CILEN_ADDR) {	/* Check CI length */
963 		orc = CONFREJ;		/* Reject CI */
964 		break;
965 	    }
966 	    GETLONG(tl, p);
967 	    if (htonl(tl) != ao->winsaddr[d]) {
968 		DECPTR(sizeof(u_int32_t), p);
969 		tl = ntohl(ao->winsaddr[d]);
970 		PUTLONG(tl, p);
971 		orc = CONFNAK;
972 	    }
973 	    break;
974 
975 	case CI_COMPRESSTYPE:
976 	    IPCPDEBUG((LOG_INFO, "ipcp: received COMPRESSTYPE "));
977 	    if (!ao->neg_vj ||
978 		(cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) {
979 		orc = CONFREJ;
980 		break;
981 	    }
982 	    GETSHORT(cishort, p);
983 	    IPCPDEBUG((LOG_INFO, "(%d)", cishort));
984 
985 	    if (!(cishort == IPCP_VJ_COMP ||
986 		  (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {
987 		orc = CONFREJ;
988 		break;
989 	    }
990 
991 	    ho->neg_vj = 1;
992 	    ho->vj_protocol = cishort;
993 	    if (cilen == CILEN_VJ) {
994 		GETCHAR(maxslotindex, p);
995 		if (maxslotindex > ao->maxslotindex) {
996 		    orc = CONFNAK;
997 		    if (!reject_if_disagree){
998 			DECPTR(1, p);
999 			PUTCHAR(ao->maxslotindex, p);
1000 		    }
1001 		}
1002 		GETCHAR(cflag, p);
1003 		if (cflag && !ao->cflag) {
1004 		    orc = CONFNAK;
1005 		    if (!reject_if_disagree){
1006 			DECPTR(1, p);
1007 			PUTCHAR(wo->cflag, p);
1008 		    }
1009 		}
1010 		ho->maxslotindex = maxslotindex;
1011 		ho->cflag = cflag;
1012 	    } else {
1013 		ho->old_vj = 1;
1014 		ho->maxslotindex = MAX_STATES - 1;
1015 		ho->cflag = 1;
1016 	    }
1017 	    break;
1018 
1019 	default:
1020 	    orc = CONFREJ;
1021 	    break;
1022 	}
1023 
1024 endswitch:
1025 	IPCPDEBUG((LOG_INFO, " (%s)\n", CODENAME(orc)));
1026 
1027 	if (orc == CONFACK &&		/* Good CI */
1028 	    rc != CONFACK)		/*  but prior CI wasnt? */
1029 	    continue;			/* Don't send this one */
1030 
1031 	if (orc == CONFNAK) {		/* Nak this CI? */
1032 	    if (reject_if_disagree)	/* Getting fed up with sending NAKs? */
1033 		orc = CONFREJ;		/* Get tough if so */
1034 	    else {
1035 		if (rc == CONFREJ)	/* Rejecting prior CI? */
1036 		    continue;		/* Don't send this one */
1037 		if (rc == CONFACK) {	/* Ack'd all prior CIs? */
1038 		    rc = CONFNAK;	/* Not anymore... */
1039 		    ucp = inp;		/* Backup */
1040 		}
1041 	    }
1042 	}
1043 
1044 	if (orc == CONFREJ &&		/* Reject this CI */
1045 	    rc != CONFREJ) {		/*  but no prior ones? */
1046 	    rc = CONFREJ;
1047 	    ucp = inp;			/* Backup */
1048 	}
1049 
1050 	/* Need to move CI? */
1051 	if (ucp != cip)
1052 	    BCOPY(cip, ucp, cilen);	/* Move it */
1053 
1054 	/* Update output pointer */
1055 	INCPTR(cilen, ucp);
1056     }
1057 
1058     /*
1059      * If we aren't rejecting this packet, and we want to negotiate
1060      * their address, and they didn't send their address, then we
1061      * send a NAK with a CI_ADDR option appended.  We assume the
1062      * input buffer is long enough that we can append the extra
1063      * option safely.
1064      */
1065     if (rc != CONFREJ && !ho->neg_addr &&
1066 	wo->req_addr && !reject_if_disagree) {
1067 	if (rc == CONFACK) {
1068 	    rc = CONFNAK;
1069 	    ucp = inp;			/* reset pointer */
1070 	    wo->req_addr = 0;		/* don't ask again */
1071 	}
1072 	PUTCHAR(CI_ADDR, ucp);
1073 	PUTCHAR(CILEN_ADDR, ucp);
1074 	tl = ntohl(wo->hisaddr);
1075 	PUTLONG(tl, ucp);
1076     }
1077 
1078     *len = ucp - inp;			/* Compute output length */
1079     IPCPDEBUG((LOG_INFO, "ipcp: returning Configure-%s", CODENAME(rc)));
1080     return (rc);			/* Return final code */
1081 }
1082 
1083 
1084 /*
1085  * ip_check_options - check that any IP-related options are OK,
1086  * and assign appropriate defaults.
1087  */
1088 static void
ip_check_options()1089 ip_check_options()
1090 {
1091     struct hostent *hp;
1092     u_int32_t local;
1093     ipcp_options *wo = &ipcp_wantoptions[0];
1094 
1095     /*
1096      * Default our local IP address based on our hostname.
1097      * If local IP address already given, don't bother.
1098      */
1099     if (wo->ouraddr == 0 && !disable_defaultip) {
1100 	/*
1101 	 * Look up our hostname (possibly with domain name appended)
1102 	 * and take the first IP address as our local IP address.
1103 	 * If there isn't an IP address for our hostname, too bad.
1104 	 */
1105 	wo->accept_local = 1;	/* don't insist on this default value */
1106 	if ((hp = gethostbyname(hostname)) != NULL) {
1107 	    local = *(u_int32_t *)hp->h_addr;
1108 	    if (local != 0 && !bad_ip_adrs(local))
1109 		wo->ouraddr = local;
1110 	}
1111     }
1112 
1113     if (demand && wo->hisaddr == 0) {
1114 	option_error("remote IP address required for demand-dialling\n");
1115 	exit(1);
1116     }
1117 #if 0
1118     if (demand && wo->accept_remote) {
1119 	option_error("ipcp-accept-remote is incompatible with demand\n");
1120 	exit(1);
1121     }
1122 #endif
1123 }
1124 
1125 
1126 /*
1127  * ip_demand_conf - configure the interface as though
1128  * IPCP were up, for use with dial-on-demand.
1129  */
1130 static int
ip_demand_conf(u)1131 ip_demand_conf(u)
1132     int u;
1133 {
1134     ipcp_options *wo = &ipcp_wantoptions[u];
1135 
1136     if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr)))
1137 	return 0;
1138     if (!sifup(u))
1139 	return 0;
1140     if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
1141 	return 0;
1142     if (wo->default_route)
1143 	if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
1144 	    default_route_set[u] = 1;
1145     if (wo->proxy_arp)
1146 	if (sifproxyarp(u, wo->hisaddr))
1147 	    proxy_arp_set[u] = 1;
1148 
1149     syslog(LOG_NOTICE, "local  IP address %s", ip_ntoa(wo->ouraddr));
1150     syslog(LOG_NOTICE, "remote IP address %s", ip_ntoa(wo->hisaddr));
1151 
1152     return 1;
1153 }
1154 
1155 
1156 /*
1157  * ipcp_up - IPCP has come UP.
1158  *
1159  * Configure the IP network interface appropriately and bring it up.
1160  */
1161 static void
ipcp_up(f)1162 ipcp_up(f)
1163     fsm *f;
1164 {
1165     u_int32_t mask;
1166     ipcp_options *ho = &ipcp_hisoptions[f->unit];
1167     ipcp_options *go = &ipcp_gotoptions[f->unit];
1168     ipcp_options *wo = &ipcp_wantoptions[f->unit];
1169 
1170     np_up(f->unit, PPP_IP);
1171     IPCPDEBUG((LOG_INFO, "ipcp: up"));
1172 
1173     /*
1174      * We must have a non-zero IP address for both ends of the link.
1175      */
1176     if (!ho->neg_addr)
1177 	ho->hisaddr = wo->hisaddr;
1178 
1179     if (ho->hisaddr == 0) {
1180 	syslog(LOG_ERR, "Could not determine remote IP address");
1181 	ipcp_close(f->unit, "Could not determine remote IP address");
1182 	return;
1183     }
1184     if (go->ouraddr == 0) {
1185 	syslog(LOG_ERR, "Could not determine local IP address");
1186 	ipcp_close(f->unit, "Could not determine local IP address");
1187 	return;
1188     }
1189     script_setenv("IPLOCAL", ip_ntoa(go->ouraddr));
1190     script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr));
1191 
1192     /*
1193      * Check that the peer is allowed to use the IP address it wants.
1194      */
1195     if (!auth_ip_addr(f->unit, ho->hisaddr)) {
1196 	syslog(LOG_ERR, "Peer is not authorized to use remote address %s",
1197 	       ip_ntoa(ho->hisaddr));
1198 	ipcp_close(f->unit, "Unauthorized remote IP address");
1199 	return;
1200     }
1201 
1202     /* set tcp compression */
1203     sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex);
1204 
1205     /*
1206      * If we are doing dial-on-demand, the interface is already
1207      * configured, so we put out any saved-up packets, then set the
1208      * interface to pass IP packets.
1209      */
1210     if (demand) {
1211 	if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
1212 	    if (go->ouraddr != wo->ouraddr)
1213 		syslog(LOG_WARNING, "Local IP address changed to %s",
1214 		       ip_ntoa(go->ouraddr));
1215 	    if (ho->hisaddr != wo->hisaddr)
1216 		syslog(LOG_WARNING, "Remote IP address changed to %s",
1217 		       ip_ntoa(ho->hisaddr));
1218 	    ipcp_clear_addrs(f->unit);
1219 
1220 	    /* Set the interface to the new addresses */
1221 	    mask = GetMask(go->ouraddr);
1222 	    if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1223 		IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
1224 		ipcp_close(f->unit, "Interface configuration failed");
1225 		return;
1226 	    }
1227 
1228 	    /* assign a default route through the interface if required */
1229 	    if (ipcp_wantoptions[f->unit].default_route)
1230 		if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
1231 		    default_route_set[f->unit] = 1;
1232 
1233 	    /* Make a proxy ARP entry if requested. */
1234 	    if (ipcp_wantoptions[f->unit].proxy_arp)
1235 		if (sifproxyarp(f->unit, ho->hisaddr))
1236 		    proxy_arp_set[f->unit] = 1;
1237 
1238 	}
1239 	demand_rexmit(PPP_IP);
1240 	sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
1241 
1242     } else {
1243 	/*
1244 	 * Set IP addresses and (if specified) netmask.
1245 	 */
1246 	mask = GetMask(go->ouraddr);
1247 
1248 #if !(defined(SVR4) && (defined(SNI) || defined(__USLC__)))
1249 	if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1250 	    IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
1251 	    ipcp_close(f->unit, "Interface configuration failed");
1252 	    return;
1253 	}
1254 #endif
1255 
1256 	/* bring the interface up for IP */
1257 	if (!sifup(f->unit)) {
1258 	    IPCPDEBUG((LOG_WARNING, "sifup failed"));
1259 	    ipcp_close(f->unit, "Interface configuration failed");
1260 	    return;
1261 	}
1262 
1263 #if (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
1264 	if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1265 	    IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
1266 	    ipcp_close(f->unit, "Interface configuration failed");
1267 	    return;
1268 	}
1269 #endif
1270 	sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
1271 
1272 	/* assign a default route through the interface if required */
1273 	if (ipcp_wantoptions[f->unit].default_route)
1274 	    if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
1275 		default_route_set[f->unit] = 1;
1276 
1277 	/* Make a proxy ARP entry if requested. */
1278 	if (ipcp_wantoptions[f->unit].proxy_arp)
1279 	    if (sifproxyarp(f->unit, ho->hisaddr))
1280 		proxy_arp_set[f->unit] = 1;
1281 
1282 	syslog(LOG_NOTICE, "local  IP address %s", ip_ntoa(go->ouraddr));
1283 	syslog(LOG_NOTICE, "remote IP address %s", ip_ntoa(ho->hisaddr));
1284     }
1285 
1286     /*
1287      * Execute the ip-up script, like this:
1288      *	/etc/ppp/ip-up interface tty speed local-IP remote-IP
1289      */
1290     ipcp_script(f, _PATH_IPUP);
1291 
1292 }
1293 
1294 
1295 /*
1296  * ipcp_down - IPCP has gone DOWN.
1297  *
1298  * Take the IP network interface down, clear its addresses
1299  * and delete routes through it.
1300  */
1301 static void
ipcp_down(f)1302 ipcp_down(f)
1303     fsm *f;
1304 {
1305     IPCPDEBUG((LOG_INFO, "ipcp: down"));
1306     np_down(f->unit, PPP_IP);
1307     sifvjcomp(f->unit, 0, 0, 0);
1308 
1309     /*
1310      * If we are doing dial-on-demand, set the interface
1311      * to queue up outgoing packets (for now).
1312      */
1313     if (demand) {
1314 	sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE);
1315     } else {
1316 	sifdown(f->unit);
1317 	ipcp_clear_addrs(f->unit);
1318     }
1319 
1320     /* Execute the ip-down script */
1321     ipcp_script(f, _PATH_IPDOWN);
1322 }
1323 
1324 
1325 /*
1326  * ipcp_clear_addrs() - clear the interface addresses, routes,
1327  * proxy arp entries, etc.
1328  */
1329 static void
ipcp_clear_addrs(unit)1330 ipcp_clear_addrs(unit)
1331     int unit;
1332 {
1333     u_int32_t ouraddr, hisaddr;
1334 
1335     ouraddr = ipcp_gotoptions[unit].ouraddr;
1336     hisaddr = ipcp_hisoptions[unit].hisaddr;
1337     if (proxy_arp_set[unit]) {
1338 	cifproxyarp(unit, hisaddr);
1339 	proxy_arp_set[unit] = 0;
1340     }
1341     if (default_route_set[unit]) {
1342 	cifdefaultroute(unit, ouraddr, hisaddr);
1343 	default_route_set[unit] = 0;
1344     }
1345     cifaddr(unit, ouraddr, hisaddr);
1346 }
1347 
1348 
1349 /*
1350  * ipcp_finished - possibly shut down the lower layers.
1351  */
1352 static void
ipcp_finished(f)1353 ipcp_finished(f)
1354     fsm *f;
1355 {
1356     np_finished(f->unit, PPP_IP);
1357 }
1358 
1359 
1360 /*
1361  * ipcp_script - Execute a script with arguments
1362  * interface-name tty-name speed local-IP remote-IP.
1363  */
1364 static void
ipcp_script(f,script)1365 ipcp_script(f, script)
1366     fsm *f;
1367     char *script;
1368 {
1369     char strspeed[32], strlocal[32], strremote[32];
1370     char *argv[8];
1371 
1372     snprintf(strspeed, sizeof strspeed, "%d", baud_rate);
1373     strlcpy(strlocal, ip_ntoa(ipcp_gotoptions[f->unit].ouraddr),
1374 	sizeof strlocal);
1375     strlcpy(strremote, ip_ntoa(ipcp_hisoptions[f->unit].hisaddr),
1376 	sizeof strremote);
1377 
1378     argv[0] = script;
1379     argv[1] = ifname;
1380     argv[2] = devnam;
1381     argv[3] = strspeed;
1382     argv[4] = strlocal;
1383     argv[5] = strremote;
1384     argv[6] = ipparam;
1385     argv[7] = NULL;
1386     run_program(script, argv, 0);
1387 }
1388 
1389 /*
1390  * ipcp_printpkt - print the contents of an IPCP packet.
1391  */
1392 static char *ipcp_codenames[] = {
1393     "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1394     "TermReq", "TermAck", "CodeRej"
1395 };
1396 
1397 static int
ipcp_printpkt(p,plen,printer,arg)1398 ipcp_printpkt(p, plen, printer, arg)
1399     u_char *p;
1400     int plen;
1401     void (*printer)(void *, char *, ...);
1402     void *arg;
1403 {
1404     int code, id, len, olen;
1405     u_char *pstart, *optend;
1406     u_short cishort;
1407     u_int32_t cilong;
1408 
1409     if (plen < HEADERLEN)
1410 	return 0;
1411     pstart = p;
1412     GETCHAR(code, p);
1413     GETCHAR(id, p);
1414     GETSHORT(len, p);
1415     if (len < HEADERLEN || len > plen)
1416 	return 0;
1417 
1418     if (code >= 1 && code <= sizeof(ipcp_codenames) / sizeof(char *))
1419 	printer(arg, " %s", ipcp_codenames[code-1]);
1420     else
1421 	printer(arg, " code=0x%x", code);
1422     printer(arg, " id=0x%x", id);
1423     len -= HEADERLEN;
1424     switch (code) {
1425     case CONFREQ:
1426     case CONFACK:
1427     case CONFNAK:
1428     case CONFREJ:
1429 	/* print option list */
1430 	while (len >= 2) {
1431 	    GETCHAR(code, p);
1432 	    GETCHAR(olen, p);
1433 	    p -= 2;
1434 	    if (olen < 2 || olen > len) {
1435 		break;
1436 	    }
1437 	    printer(arg, " <");
1438 	    len -= olen;
1439 	    optend = p + olen;
1440 	    switch (code) {
1441 	    case CI_ADDRS:
1442 		if (olen == CILEN_ADDRS) {
1443 		    p += 2;
1444 		    GETLONG(cilong, p);
1445 		    printer(arg, "addrs %I", htonl(cilong));
1446 		    GETLONG(cilong, p);
1447 		    printer(arg, " %I", htonl(cilong));
1448 		}
1449 		break;
1450 	    case CI_COMPRESSTYPE:
1451 		if (olen >= CILEN_COMPRESS) {
1452 		    p += 2;
1453 		    GETSHORT(cishort, p);
1454 		    printer(arg, "compress ");
1455 		    switch (cishort) {
1456 		    case IPCP_VJ_COMP:
1457 			printer(arg, "VJ");
1458 			break;
1459 		    case IPCP_VJ_COMP_OLD:
1460 			printer(arg, "old-VJ");
1461 			break;
1462 		    default:
1463 			printer(arg, "0x%x", cishort);
1464 		    }
1465 		}
1466 		break;
1467 	    case CI_ADDR:
1468 		if (olen == CILEN_ADDR) {
1469 		    p += 2;
1470 		    GETLONG(cilong, p);
1471 		    printer(arg, "addr %I", htonl(cilong));
1472 		}
1473 		break;
1474 	    case CI_MS_DNS1:
1475 	    case CI_MS_DNS2:
1476 		p += 2;
1477 		GETLONG(cilong, p);
1478 		printer(arg, "ms-dns %I", htonl(cilong));
1479 		break;
1480 	    case CI_MS_WINS1:
1481 	    case CI_MS_WINS2:
1482 		p += 2;
1483 		GETLONG(cilong, p);
1484 		printer(arg, "ms-wins %I", htonl(cilong));
1485 		break;
1486 	    }
1487 	    while (p < optend) {
1488 		GETCHAR(code, p);
1489 		printer(arg, " %.2x", code);
1490 	    }
1491 	    printer(arg, ">");
1492 	}
1493 	break;
1494 
1495     case TERMACK:
1496     case TERMREQ:
1497 	if (len > 0 && *p >= ' ' && *p < 0x7f) {
1498 	    printer(arg, " ");
1499 	    print_string(p, len, printer, arg);
1500 	    p += len;
1501 	    len = 0;
1502 	}
1503         break;
1504     }
1505 
1506     /* print the rest of the bytes in the packet */
1507     for (; len > 0; --len) {
1508 	GETCHAR(code, p);
1509 	printer(arg, " %.2x", code);
1510     }
1511 
1512     return p - pstart;
1513 }
1514 
1515 /*
1516  * ip_active_pkt - see if this IP packet is worth bringing the link up for.
1517  * We don't bring the link up for IP fragments or for TCP FIN packets
1518  * with no data.
1519  */
1520 #define IP_HDRLEN	20	/* bytes */
1521 #define IP_OFFMASK	0x1fff
1522 #define IPPROTO_TCP	6
1523 #define TCP_HDRLEN	20
1524 #define TH_FIN		0x01
1525 
1526 /*
1527  * We use these macros because the IP header may be at an odd address,
1528  * and some compilers might use word loads to get th_off or ip_hl.
1529  */
1530 
1531 #define net_short(x)	(((x)[0] << 8) + (x)[1])
1532 #define get_iphl(x)	(((unsigned char *)(x))[0] & 0xF)
1533 #define get_ipoff(x)	net_short((unsigned char *)(x) + 6)
1534 #define get_ipproto(x)	(((unsigned char *)(x))[9])
1535 #define get_tcpoff(x)	(((unsigned char *)(x))[12] >> 4)
1536 #define get_tcpflags(x)	(((unsigned char *)(x))[13])
1537 
1538 static int
ip_active_pkt(pkt,len)1539 ip_active_pkt(pkt, len)
1540     u_char *pkt;
1541     int len;
1542 {
1543     u_char *tcp;
1544     int hlen;
1545 
1546     len -= PPP_HDRLEN;
1547     pkt += PPP_HDRLEN;
1548     if (len < IP_HDRLEN)
1549 	return 0;
1550     if ((get_ipoff(pkt) & IP_OFFMASK) != 0)
1551 	return 0;
1552     if (get_ipproto(pkt) != IPPROTO_TCP)
1553 	return 1;
1554     hlen = get_iphl(pkt) * 4;
1555     if (len < hlen + TCP_HDRLEN)
1556 	return 0;
1557     tcp = pkt + hlen;
1558     if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4)
1559 	return 0;
1560     return 1;
1561 }
1562