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