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