]> git.ozlabs.org Git - ppp.git/blob - pppd/ipcp.c
fix compression negotiation
[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.31 1997/04/30 05:52:48 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 (demand && wo->accept_remote) {
1089         option_error("ipcp-accept-remote is incompatible with demand\n");
1090         exit(1);
1091     }
1092 }
1093
1094
1095 /*
1096  * ip_demand_conf - configure the interface as though
1097  * IPCP were up, for use with dial-on-demand.
1098  */
1099 static int
1100 ip_demand_conf(u)
1101     int u;
1102 {
1103     ipcp_options *wo = &ipcp_wantoptions[u];
1104
1105     if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr)))
1106         return 0;
1107     if (!sifup(u))
1108         return 0;
1109     if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
1110         return 0;
1111     if (wo->default_route)
1112         if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
1113             default_route_set[u] = 1;
1114     if (wo->proxy_arp)
1115         if (sifproxyarp(u, wo->hisaddr))
1116             proxy_arp_set[u] = 1;
1117
1118     syslog(LOG_NOTICE, "local  IP address %s", ip_ntoa(wo->ouraddr));
1119     syslog(LOG_NOTICE, "remote IP address %s", ip_ntoa(wo->hisaddr));
1120
1121     return 1;
1122 }
1123
1124
1125 /*
1126  * ipcp_up - IPCP has come UP.
1127  *
1128  * Configure the IP network interface appropriately and bring it up.
1129  */
1130 static void
1131 ipcp_up(f)
1132     fsm *f;
1133 {
1134     u_int32_t mask;
1135     ipcp_options *ho = &ipcp_hisoptions[f->unit];
1136     ipcp_options *go = &ipcp_gotoptions[f->unit];
1137     ipcp_options *wo = &ipcp_wantoptions[f->unit];
1138
1139     np_up(f->unit, PPP_IP);
1140     IPCPDEBUG((LOG_INFO, "ipcp: up"));
1141
1142     /*
1143      * We must have a non-zero IP address for both ends of the link.
1144      */
1145     if (!ho->neg_addr)
1146         ho->hisaddr = wo->hisaddr;
1147
1148     if (ho->hisaddr == 0) {
1149         syslog(LOG_ERR, "Could not determine remote IP address");
1150         ipcp_close(f->unit, "Could not determine remote IP address");
1151         return;
1152     }
1153     if (go->ouraddr == 0) {
1154         syslog(LOG_ERR, "Could not determine local IP address");
1155         ipcp_close(f->unit, "Could not determine local IP address");
1156         return;
1157     }
1158
1159     /*
1160      * Check that the peer is allowed to use the IP address it wants.
1161      */
1162     if (!auth_ip_addr(f->unit, ho->hisaddr)) {
1163         syslog(LOG_ERR, "Peer is not authorized to use remote address %s",
1164                ip_ntoa(ho->hisaddr));
1165         ipcp_close(f->unit, "Unauthorized remote IP address");
1166         return;
1167     }
1168
1169     /* set tcp compression */
1170     sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex);
1171
1172     /*
1173      * If we are doing dial-on-demand, the interface is already
1174      * configured, so we put out any saved-up packets, then set the
1175      * interface to pass IP packets.
1176      */
1177     if (demand) {
1178         if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
1179             if (go->ouraddr != wo->ouraddr)
1180                 syslog(LOG_WARNING, "Local IP address changed to %s",
1181                        ip_ntoa(go->ouraddr));
1182             if (ho->hisaddr != wo->hisaddr)
1183                 syslog(LOG_WARNING, "Remote IP address changed to %s",
1184                        ip_ntoa(ho->hisaddr));
1185             ipcp_clear_addrs(f->unit);
1186
1187             /* Set the interface to the new addresses */
1188             mask = GetMask(go->ouraddr);
1189             if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1190                 IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
1191                 ipcp_close(f->unit, "Interface configuration failed");
1192                 return;
1193             }
1194
1195             /* assign a default route through the interface if required */
1196             if (ipcp_wantoptions[f->unit].default_route) 
1197                 if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
1198                     default_route_set[f->unit] = 1;
1199
1200             /* Make a proxy ARP entry if requested. */
1201             if (ipcp_wantoptions[f->unit].proxy_arp)
1202                 if (sifproxyarp(f->unit, ho->hisaddr))
1203                     proxy_arp_set[f->unit] = 1;
1204
1205         }
1206         demand_rexmit(PPP_IP);
1207         sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
1208
1209     } else {
1210         /*
1211          * Set IP addresses and (if specified) netmask.
1212          */
1213         mask = GetMask(go->ouraddr);
1214
1215 #if !(defined(SVR4) && (defined(SNI) || defined(__USLC__)))
1216         if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1217             IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
1218             ipcp_close(f->unit, "Interface configuration failed");
1219             return;
1220         }
1221 #endif
1222
1223         /* bring the interface up for IP */
1224         if (!sifup(f->unit)) {
1225             IPCPDEBUG((LOG_WARNING, "sifup failed"));
1226             ipcp_close(f->unit, "Interface configuration failed");
1227             return;
1228         }
1229
1230 #if (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
1231         if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1232             IPCPDEBUG((LOG_WARNING, "sifaddr failed"));
1233             ipcp_close(f->unit, "Interface configuration failed");
1234             return;
1235         }
1236 #endif
1237         sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
1238
1239         /* assign a default route through the interface if required */
1240         if (ipcp_wantoptions[f->unit].default_route) 
1241             if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
1242                 default_route_set[f->unit] = 1;
1243
1244         /* Make a proxy ARP entry if requested. */
1245         if (ipcp_wantoptions[f->unit].proxy_arp)
1246             if (sifproxyarp(f->unit, ho->hisaddr))
1247                 proxy_arp_set[f->unit] = 1;
1248
1249         syslog(LOG_NOTICE, "local  IP address %s", ip_ntoa(go->ouraddr));
1250         syslog(LOG_NOTICE, "remote IP address %s", ip_ntoa(ho->hisaddr));
1251     }
1252
1253     /*
1254      * Execute the ip-up script, like this:
1255      *  /etc/ppp/ip-up interface tty speed local-IP remote-IP
1256      */
1257     ipcp_script(f, _PATH_IPUP);
1258
1259 }
1260
1261
1262 /*
1263  * ipcp_down - IPCP has gone DOWN.
1264  *
1265  * Take the IP network interface down, clear its addresses
1266  * and delete routes through it.
1267  */
1268 static void
1269 ipcp_down(f)
1270     fsm *f;
1271 {
1272     IPCPDEBUG((LOG_INFO, "ipcp: down"));
1273     np_down(f->unit, PPP_IP);
1274     sifvjcomp(f->unit, 0, 0, 0);
1275
1276     /*
1277      * If we are doing dial-on-demand, set the interface
1278      * to queue up outgoing packets (for now).
1279      */
1280     if (demand) {
1281         sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE);
1282     } else {
1283         sifdown(f->unit);
1284         ipcp_clear_addrs(f->unit);
1285     }
1286
1287     /* Execute the ip-down script */
1288     ipcp_script(f, _PATH_IPDOWN);
1289 }
1290
1291
1292 /*
1293  * ipcp_clear_addrs() - clear the interface addresses, routes,
1294  * proxy arp entries, etc.
1295  */
1296 static void
1297 ipcp_clear_addrs(unit)
1298     int unit;
1299 {
1300     u_int32_t ouraddr, hisaddr;
1301
1302     ouraddr = ipcp_gotoptions[unit].ouraddr;
1303     hisaddr = ipcp_hisoptions[unit].hisaddr;
1304     if (proxy_arp_set[unit]) {
1305         cifproxyarp(unit, hisaddr);
1306         proxy_arp_set[unit] = 0;
1307     }
1308     if (default_route_set[unit]) {
1309         cifdefaultroute(unit, ouraddr, hisaddr);
1310         default_route_set[unit] = 0;
1311     }
1312     cifaddr(unit, ouraddr, hisaddr);
1313 }
1314
1315
1316 /*
1317  * ipcp_finished - possibly shut down the lower layers.
1318  */
1319 static void
1320 ipcp_finished(f)
1321     fsm *f;
1322 {
1323     np_finished(f->unit, PPP_IP);
1324 }
1325
1326
1327 /*
1328  * ipcp_script - Execute a script with arguments
1329  * interface-name tty-name speed local-IP remote-IP.
1330  */
1331 static void
1332 ipcp_script(f, script)
1333     fsm *f;
1334     char *script;
1335 {
1336     char strspeed[32], strlocal[32], strremote[32];
1337     char *argv[8];
1338
1339     sprintf(strspeed, "%d", baud_rate);
1340     strcpy(strlocal, ip_ntoa(ipcp_gotoptions[f->unit].ouraddr));
1341     strcpy(strremote, ip_ntoa(ipcp_hisoptions[f->unit].hisaddr));
1342
1343     argv[0] = script;
1344     argv[1] = ifname;
1345     argv[2] = devnam;
1346     argv[3] = strspeed;
1347     argv[4] = strlocal;
1348     argv[5] = strremote;
1349     argv[6] = ipparam;
1350     argv[7] = NULL;
1351     run_program(script, argv, 0);
1352 }
1353
1354 /*
1355  * ipcp_printpkt - print the contents of an IPCP packet.
1356  */
1357 static char *ipcp_codenames[] = {
1358     "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1359     "TermReq", "TermAck", "CodeRej"
1360 };
1361
1362 static int
1363 ipcp_printpkt(p, plen, printer, arg)
1364     u_char *p;
1365     int plen;
1366     void (*printer) __P((void *, char *, ...));
1367     void *arg;
1368 {
1369     int code, id, len, olen;
1370     u_char *pstart, *optend;
1371     u_short cishort;
1372     u_int32_t cilong;
1373
1374     if (plen < HEADERLEN)
1375         return 0;
1376     pstart = p;
1377     GETCHAR(code, p);
1378     GETCHAR(id, p);
1379     GETSHORT(len, p);
1380     if (len < HEADERLEN || len > plen)
1381         return 0;
1382
1383     if (code >= 1 && code <= sizeof(ipcp_codenames) / sizeof(char *))
1384         printer(arg, " %s", ipcp_codenames[code-1]);
1385     else
1386         printer(arg, " code=0x%x", code);
1387     printer(arg, " id=0x%x", id);
1388     len -= HEADERLEN;
1389     switch (code) {
1390     case CONFREQ:
1391     case CONFACK:
1392     case CONFNAK:
1393     case CONFREJ:
1394         /* print option list */
1395         while (len >= 2) {
1396             GETCHAR(code, p);
1397             GETCHAR(olen, p);
1398             p -= 2;
1399             if (olen < 2 || olen > len) {
1400                 break;
1401             }
1402             printer(arg, " <");
1403             len -= olen;
1404             optend = p + olen;
1405             switch (code) {
1406             case CI_ADDRS:
1407                 if (olen == CILEN_ADDRS) {
1408                     p += 2;
1409                     GETLONG(cilong, p);
1410                     printer(arg, "addrs %s", ip_ntoa(htonl(cilong)));
1411                     GETLONG(cilong, p);
1412                     printer(arg, " %s", ip_ntoa(htonl(cilong)));
1413                 }
1414                 break;
1415             case CI_COMPRESSTYPE:
1416                 if (olen >= CILEN_COMPRESS) {
1417                     p += 2;
1418                     GETSHORT(cishort, p);
1419                     printer(arg, "compress ");
1420                     switch (cishort) {
1421                     case IPCP_VJ_COMP:
1422                         printer(arg, "VJ");
1423                         break;
1424                     case IPCP_VJ_COMP_OLD:
1425                         printer(arg, "old-VJ");
1426                         break;
1427                     default:
1428                         printer(arg, "0x%x", cishort);
1429                     }
1430                 }
1431                 break;
1432             case CI_ADDR:
1433                 if (olen == CILEN_ADDR) {
1434                     p += 2;
1435                     GETLONG(cilong, p);
1436                     printer(arg, "addr %s", ip_ntoa(htonl(cilong)));
1437                 }
1438                 break;
1439             case CI_MS_DNS1:
1440             case CI_MS_DNS2:
1441                 p += 2;
1442                 GETLONG(cilong, p);
1443                 printer(arg, "dns-addr %s", ip_ntoa(htonl(cilong)));
1444                 break;
1445             case CI_MS_WINS1:
1446             case CI_MS_WINS2:
1447                 p += 2;
1448                 GETLONG(cilong, p);
1449                 printer(arg, "wins-addr %s", ip_ntoa(htonl(cilong)));
1450                 break;
1451             }
1452             while (p < optend) {
1453                 GETCHAR(code, p);
1454                 printer(arg, " %.2x", code);
1455             }
1456             printer(arg, ">");
1457         }
1458         break;
1459
1460     case TERMACK:
1461     case TERMREQ:
1462         if (len > 0 && *p >= ' ' && *p < 0x7f) {
1463             printer(arg, " ");
1464             print_string(p, len, printer, arg);
1465             p += len;
1466             len = 0;
1467         }
1468         break;
1469     }
1470
1471     /* print the rest of the bytes in the packet */
1472     for (; len > 0; --len) {
1473         GETCHAR(code, p);
1474         printer(arg, " %.2x", code);
1475     }
1476
1477     return p - pstart;
1478 }
1479
1480 /*
1481  * ip_active_pkt - see if this IP packet is worth bringing the link up for.
1482  * We don't bring the link up for IP fragments or for TCP FIN packets
1483  * with no data.
1484  */
1485 #define IP_HDRLEN       20      /* bytes */
1486 #define IP_OFFMASK      0x1fff
1487 #define IPPROTO_TCP     6
1488 #define TCP_HDRLEN      20
1489 #define TH_FIN          0x01
1490
1491 /*
1492  * We use these macros because the IP header may be at an odd address,
1493  * and some compilers might use word loads to get th_off or ip_hl.
1494  */
1495
1496 #define net_short(x)    (((x)[0] << 8) + (x)[1])
1497 #define get_iphl(x)     (((unsigned char *)(x))[0] & 0xF)
1498 #define get_ipoff(x)    net_short((unsigned char *)(x) + 6)
1499 #define get_ipproto(x)  (((unsigned char *)(x))[9])
1500 #define get_tcpoff(x)   (((unsigned char *)(x))[12] >> 4)
1501 #define get_tcpflags(x) (((unsigned char *)(x))[13])
1502
1503 static int
1504 ip_active_pkt(pkt, len)
1505     u_char *pkt;
1506     int len;
1507 {
1508     u_char *tcp;
1509     int hlen;
1510
1511     len -= PPP_HDRLEN;
1512     pkt += PPP_HDRLEN;
1513     if (len < IP_HDRLEN)
1514         return 0;
1515     if ((get_ipoff(pkt) & IP_OFFMASK) != 0)
1516         return 0;
1517     if (get_ipproto(pkt) != IPPROTO_TCP)
1518         return 1;
1519     hlen = get_iphl(pkt) * 4;
1520     if (len < hlen + TCP_HDRLEN)
1521         return 0;
1522     tcp = pkt + hlen;
1523     if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4)
1524         return 0;
1525     return 1;
1526 }