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