]> git.ozlabs.org Git - ppp.git/blob - pppd/ipcp.c
New options system with priorities for option values, with options
[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 #define RCSID   "$Id: ipcp.c,v 1.57 2001/03/08 05:11:12 paulus Exp $"
21
22 /*
23  * TODO:
24  */
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <netdb.h>
30 #include <sys/param.h>
31 #include <sys/types.h>
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
35
36 #include "pppd.h"
37 #include "fsm.h"
38 #include "ipcp.h"
39 #include "pathnames.h"
40
41 static const char rcsid[] = RCSID;
42
43 /* global vars */
44 ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */
45 ipcp_options ipcp_gotoptions[NUM_PPP];  /* Options that peer ack'd */
46 ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
47 ipcp_options ipcp_hisoptions[NUM_PPP];  /* Options that we ack'd */
48
49 u_int32_t netmask = 0;          /* IP netmask to set on interface */
50
51 bool    disable_defaultip = 0;  /* Don't use hostname for default IP adrs */
52
53 /* Hook for a plugin to know when IP protocol has come up */
54 void (*ip_up_hook) __P((void)) = NULL;
55
56 /* Hook for a plugin to know when IP protocol has come down */
57 void (*ip_down_hook) __P((void)) = NULL;
58
59 /* Hook for a plugin to choose the remote IP address */
60 void (*ip_choose_hook) __P((u_int32_t *)) = NULL;
61
62 /* local vars */
63 static int default_route_set[NUM_PPP];  /* Have set up a default route */
64 static int proxy_arp_set[NUM_PPP];      /* Have created proxy arp entry */
65 static bool usepeerdns;                 /* Ask peer for DNS addrs */
66 static int ipcp_is_up;                  /* have called np_up() */
67 static bool ask_for_local;              /* request our address from peer */
68 static char vj_value[8];                /* string form of vj option value */
69 static char netmask_str[20];            /* string form of netmask value */
70
71 /*
72  * Callbacks for fsm code.  (CI = Configuration Information)
73  */
74 static void ipcp_resetci __P((fsm *));  /* Reset our CI */
75 static int  ipcp_cilen __P((fsm *));            /* Return length of our CI */
76 static void ipcp_addci __P((fsm *, u_char *, int *)); /* Add our CI */
77 static int  ipcp_ackci __P((fsm *, u_char *, int));     /* Peer ack'd our CI */
78 static int  ipcp_nakci __P((fsm *, u_char *, int));     /* Peer nak'd our CI */
79 static int  ipcp_rejci __P((fsm *, u_char *, int));     /* Peer rej'd our CI */
80 static int  ipcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */
81 static void ipcp_up __P((fsm *));               /* We're UP */
82 static void ipcp_down __P((fsm *));             /* We're DOWN */
83 static void ipcp_finished __P((fsm *)); /* Don't need lower layer */
84
85 fsm ipcp_fsm[NUM_PPP];          /* IPCP fsm structure */
86
87 static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
88     ipcp_resetci,               /* Reset our Configuration Information */
89     ipcp_cilen,                 /* Length of our Configuration Information */
90     ipcp_addci,                 /* Add our Configuration Information */
91     ipcp_ackci,                 /* ACK our Configuration Information */
92     ipcp_nakci,                 /* NAK our Configuration Information */
93     ipcp_rejci,                 /* Reject our Configuration Information */
94     ipcp_reqci,                 /* Request peer's Configuration Information */
95     ipcp_up,                    /* Called when fsm reaches OPENED state */
96     ipcp_down,                  /* Called when fsm leaves OPENED state */
97     NULL,                       /* Called when we want the lower layer up */
98     ipcp_finished,              /* Called when we want the lower layer down */
99     NULL,                       /* Called when Protocol-Reject received */
100     NULL,                       /* Retransmission is necessary */
101     NULL,                       /* Called to handle protocol-specific codes */
102     "IPCP"                      /* String name of protocol */
103 };
104
105 /*
106  * Command-line options.
107  */
108 static int setvjslots __P((char **));
109 static int setdnsaddr __P((char **));
110 static int setwinsaddr __P((char **));
111 static int setnetmask __P((char **));
112 static int setipaddr __P((char *, char **, int));
113 static void printipaddr __P((option_t *, void (*)(void *, char *,...),void *));
114
115 static option_t ipcp_option_list[] = {
116     { "noip", o_bool, &ipcp_protent.enabled_flag,
117       "Disable IP and IPCP" },
118     { "-ip", o_bool, &ipcp_protent.enabled_flag,
119       "Disable IP and IPCP", OPT_ALIAS },
120
121     { "novj", o_bool, &ipcp_wantoptions[0].neg_vj,
122       "Disable VJ compression", OPT_A2CLR, &ipcp_allowoptions[0].neg_vj },
123     { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj,
124       "Disable VJ compression", OPT_ALIAS | OPT_A2CLR,
125       &ipcp_allowoptions[0].neg_vj },
126
127     { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag,
128       "Disable VJ connection-ID compression", OPT_A2CLR,
129       &ipcp_allowoptions[0].cflag },
130     { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag,
131       "Disable VJ connection-ID compression", OPT_ALIAS | OPT_A2CLR,
132       &ipcp_allowoptions[0].cflag },
133
134     { "vj-max-slots", o_special, (void *)setvjslots,
135       "Set maximum VJ header slots",
136       OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, vj_value },
137
138     { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local,
139       "Accept peer's address for us", 1 },
140     { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote,
141       "Accept peer's address for it", 1 },
142
143     { "ipparam", o_string, &ipparam,
144       "Set ip script parameter", OPT_PRIO },
145
146     { "noipdefault", o_bool, &disable_defaultip,
147       "Don't use name for default IP adrs", 1 },
148
149     { "ms-dns", 1, (void *)setdnsaddr,
150       "DNS address for the peer's use" },
151     { "ms-wins", 1, (void *)setwinsaddr,
152       "Nameserver for SMB over TCP/IP for peer" },
153
154     { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime,
155       "Set timeout for IPCP", OPT_PRIO },
156     { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits,
157       "Set max #xmits for term-reqs", OPT_PRIO },
158     { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits,
159       "Set max #xmits for conf-reqs", OPT_PRIO },
160     { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops,
161       "Set max #conf-naks for IPCP", OPT_PRIO },
162
163     { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route,
164       "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route },
165     { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route,
166       "disable defaultroute option", OPT_A2CLR,
167       &ipcp_wantoptions[0].default_route },
168     { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route,
169       "disable defaultroute option", OPT_ALIAS | OPT_A2CLR,
170       &ipcp_wantoptions[0].default_route },
171
172     { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp,
173       "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp },
174     { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
175       "disable proxyarp option", OPT_A2CLR,
176       &ipcp_wantoptions[0].proxy_arp },
177     { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
178       "disable proxyarp option", OPT_ALIAS | OPT_A2CLR,
179       &ipcp_wantoptions[0].proxy_arp },
180
181     { "usepeerdns", o_bool, &usepeerdns,
182       "Ask peer for DNS address(es)", 1 },
183
184     { "netmask", o_special, (void *)setnetmask,
185       "set netmask", OPT_PRIO | OPT_A2STRVAL | OPT_STATIC, netmask_str },
186
187     { "IP addresses", o_wild, (void *) &setipaddr,
188       "set local and remote IP addresses",
189       OPT_NOARG | OPT_A2PRINTER, (void *) &printipaddr },
190
191     { NULL }
192 };
193
194 /*
195  * Protocol entry points from main code.
196  */
197 static void ipcp_init __P((int));
198 static void ipcp_open __P((int));
199 static void ipcp_close __P((int, char *));
200 static void ipcp_lowerup __P((int));
201 static void ipcp_lowerdown __P((int));
202 static void ipcp_input __P((int, u_char *, int));
203 static void ipcp_protrej __P((int));
204 static int  ipcp_printpkt __P((u_char *, int,
205                                void (*) __P((void *, char *, ...)), void *));
206 static void ip_check_options __P((void));
207 static int  ip_demand_conf __P((int));
208 static int  ip_active_pkt __P((u_char *, int));
209 static void create_resolv __P((u_int32_t, u_int32_t));
210
211 struct protent ipcp_protent = {
212     PPP_IPCP,
213     ipcp_init,
214     ipcp_input,
215     ipcp_protrej,
216     ipcp_lowerup,
217     ipcp_lowerdown,
218     ipcp_open,
219     ipcp_close,
220     ipcp_printpkt,
221     NULL,
222     1,
223     "IPCP",
224     "IP",
225     ipcp_option_list,
226     ip_check_options,
227     ip_demand_conf,
228     ip_active_pkt
229 };
230
231 static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t));
232 static void ipcp_script __P((char *));          /* Run an up/down script */
233 static void ipcp_script_done __P((void *));
234
235 /*
236  * Lengths of configuration options.
237  */
238 #define CILEN_VOID      2
239 #define CILEN_COMPRESS  4       /* min length for compression protocol opt. */
240 #define CILEN_VJ        6       /* length for RFC1332 Van-Jacobson opt. */
241 #define CILEN_ADDR      6       /* new-style single address option */
242 #define CILEN_ADDRS     10      /* old-style dual address option */
243
244
245 #define CODENAME(x)     ((x) == CONFACK ? "ACK" : \
246                          (x) == CONFNAK ? "NAK" : "REJ")
247
248 /*
249  * This state variable is used to ensure that we don't
250  * run an ipcp-up/down script while one is already running.
251  */
252 static enum script_state {
253     s_down,
254     s_up,
255 } ipcp_script_state;
256 static pid_t ipcp_script_pid;
257
258 /*
259  * Make a string representation of a network IP address.
260  */
261 char *
262 ip_ntoa(ipaddr)
263 u_int32_t ipaddr;
264 {
265     static char b[64];
266
267     slprintf(b, sizeof(b), "%I", ipaddr);
268     return b;
269 }
270
271 /*
272  * Option parsing.
273  */
274
275 /*
276  * setvjslots - set maximum number of connection slots for VJ compression
277  */
278 static int
279 setvjslots(argv)
280     char **argv;
281 {
282     int value;
283
284     if (!int_option(*argv, &value))
285         return 0;
286     if (value < 2 || value > 16) {
287         option_error("vj-max-slots value must be between 2 and 16");
288         return 0;
289     }
290     ipcp_wantoptions [0].maxslotindex =
291         ipcp_allowoptions[0].maxslotindex = value - 1;
292     slprintf(vj_value, sizeof(vj_value), "%d", value);
293     return 1;
294 }
295
296 /*
297  * setdnsaddr - set the dns address(es)
298  */
299 static int
300 setdnsaddr(argv)
301     char **argv;
302 {
303     u_int32_t dns;
304     struct hostent *hp;
305
306     dns = inet_addr(*argv);
307     if (dns == (u_int32_t) -1) {
308         if ((hp = gethostbyname(*argv)) == NULL) {
309             option_error("invalid address parameter '%s' for ms-dns option",
310                          *argv);
311             return 0;
312         }
313         dns = *(u_int32_t *)hp->h_addr;
314     }
315
316     /* We take the last 2 values given, the 2nd-last as the primary
317        and the last as the secondary.  If only one is given it
318        becomes both primary and secondary. */
319     if (ipcp_allowoptions[0].dnsaddr[1] == 0)
320         ipcp_allowoptions[0].dnsaddr[0] = dns;
321     else
322         ipcp_allowoptions[0].dnsaddr[0] = ipcp_allowoptions[0].dnsaddr[1];
323
324     /* always set the secondary address value. */
325     ipcp_allowoptions[0].dnsaddr[1] = dns;
326
327     return (1);
328 }
329
330 /*
331  * setwinsaddr - set the wins address(es)
332  * This is primrarly used with the Samba package under UNIX or for pointing
333  * the caller to the existing WINS server on a Windows NT platform.
334  */
335 static int
336 setwinsaddr(argv)
337     char **argv;
338 {
339     u_int32_t wins;
340     struct hostent *hp;
341
342     wins = inet_addr(*argv);
343     if (wins == (u_int32_t) -1) {
344         if ((hp = gethostbyname(*argv)) == NULL) {
345             option_error("invalid address parameter '%s' for ms-wins option",
346                          *argv);
347             return 0;
348         }
349         wins = *(u_int32_t *)hp->h_addr;
350     }
351
352     /* We take the last 2 values given, the 2nd-last as the primary
353        and the last as the secondary.  If only one is given it
354        becomes both primary and secondary. */
355     if (ipcp_allowoptions[0].winsaddr[1] == 0)
356         ipcp_allowoptions[0].winsaddr[0] = wins;
357     else
358         ipcp_allowoptions[0].winsaddr[0] = ipcp_allowoptions[0].winsaddr[1];
359
360     /* always set the secondary address value. */
361     ipcp_allowoptions[0].winsaddr[1] = wins;
362
363     return (1);
364 }
365
366 /*
367  * setipaddr - Set the IP address
368  * If doit is 0, the call is to check whether this option is
369  * potentially an IP address specification.
370  */
371 static int
372 setipaddr(arg, argv, doit)
373     char *arg;
374     char **argv;
375     int doit;
376 {
377     struct hostent *hp;
378     char *colon;
379     u_int32_t local, remote;
380     ipcp_options *wo = &ipcp_wantoptions[0];
381     static int prio_local = 0, prio_remote = 0;
382
383     /*
384      * IP address pair separated by ":".
385      */
386     if ((colon = strchr(arg, ':')) == NULL)
387         return 0;
388     if (!doit)
389         return 1;
390   
391     /*
392      * If colon first character, then no local addr.
393      */
394     if (colon != arg && option_priority >= prio_local) {
395         *colon = '\0';
396         if ((local = inet_addr(arg)) == (u_int32_t) -1) {
397             if ((hp = gethostbyname(arg)) == NULL) {
398                 option_error("unknown host: %s", arg);
399                 return 0;
400             }
401             local = *(u_int32_t *)hp->h_addr;
402         }
403         if (bad_ip_adrs(local)) {
404             option_error("bad local IP address %s", ip_ntoa(local));
405             return 0;
406         }
407         if (local != 0)
408             wo->ouraddr = local;
409         *colon = ':';
410         prio_local = option_priority;
411     }
412   
413     /*
414      * If colon last character, then no remote addr.
415      */
416     if (*++colon != '\0' && option_priority >= prio_remote) {
417         if ((remote = inet_addr(colon)) == (u_int32_t) -1) {
418             if ((hp = gethostbyname(colon)) == NULL) {
419                 option_error("unknown host: %s", colon);
420                 return 0;
421             }
422             remote = *(u_int32_t *)hp->h_addr;
423             if (remote_name[0] == 0)
424                 strlcpy(remote_name, colon, sizeof(remote_name));
425         }
426         if (bad_ip_adrs(remote)) {
427             option_error("bad remote IP address %s", ip_ntoa(remote));
428             return 0;
429         }
430         if (remote != 0)
431             wo->hisaddr = remote;
432         prio_remote = option_priority;
433     }
434
435     return 1;
436 }
437
438 static void
439 printipaddr(opt, printer, arg)
440     option_t *opt;
441     void (*printer) __P((void *, char *, ...));
442     void *arg;
443 {
444         ipcp_options *wo = &ipcp_wantoptions[0];
445
446         if (wo->ouraddr != 0)
447                 printer(arg, "%I", wo->ouraddr);
448         printer(arg, ":");
449         if (wo->hisaddr != 0)
450                 printer(arg, "%I", wo->hisaddr);
451 }
452
453 /*
454  * setnetmask - set the netmask to be used on the interface.
455  */
456 static int
457 setnetmask(argv)
458     char **argv;
459 {
460     u_int32_t mask;
461     int n;
462     char *p;
463
464     /*
465      * Unfortunately, if we use inet_addr, we can't tell whether
466      * a result of all 1s is an error or a valid 255.255.255.255.
467      */
468     p = *argv;
469     n = parse_dotted_ip(p, &mask);
470
471     mask = htonl(mask);
472
473     if (n == 0 || p[n] != 0 || (netmask & ~mask) != 0) {
474         option_error("invalid netmask value '%s'", *argv);
475         return 0;
476     }
477
478     netmask = mask;
479     slprintf(netmask_str, sizeof(netmask_str), "%I", mask);
480
481     return (1);
482 }
483
484 int
485 parse_dotted_ip(p, vp)
486     char *p;
487     u_int32_t *vp;
488 {
489     int n;
490     u_int32_t v, b;
491     char *endp, *p0 = p;
492
493     v = 0;
494     for (n = 3;; --n) {
495         b = strtoul(p, &endp, 0);
496         if (endp == p)
497             return 0;
498         if (b > 255) {
499             if (n < 3)
500                 return 0;
501             /* accept e.g. 0xffffff00 */
502             *vp = b;
503             return endp - p0;
504         }
505         v |= b << (n * 8);
506         p = endp;
507         if (n == 0)
508             break;
509         if (*p != '.')
510             return 0;
511         ++p;
512     }
513     *vp = v;
514     return p - p0;
515 }
516
517
518 /*
519  * ipcp_init - Initialize IPCP.
520  */
521 static void
522 ipcp_init(unit)
523     int unit;
524 {
525     fsm *f = &ipcp_fsm[unit];
526     ipcp_options *wo = &ipcp_wantoptions[unit];
527     ipcp_options *ao = &ipcp_allowoptions[unit];
528
529     f->unit = unit;
530     f->protocol = PPP_IPCP;
531     f->callbacks = &ipcp_callbacks;
532     fsm_init(&ipcp_fsm[unit]);
533
534     memset(wo, 0, sizeof(*wo));
535     memset(ao, 0, sizeof(*ao));
536
537     wo->neg_addr = 1;
538     wo->neg_vj = 1;
539     wo->vj_protocol = IPCP_VJ_COMP;
540     wo->maxslotindex = MAX_STATES - 1; /* really max index */
541     wo->cflag = 1;
542
543
544     /* max slots and slot-id compression are currently hardwired in */
545     /* ppp_if.c to 16 and 1, this needs to be changed (among other */
546     /* things) gmc */
547
548     ao->neg_addr = 1;
549     ao->neg_vj = 1;
550     ao->maxslotindex = MAX_STATES - 1;
551     ao->cflag = 1;
552
553     /*
554      * XXX These control whether the user may use the proxyarp
555      * and defaultroute options.
556      */
557     ao->proxy_arp = 1;
558     ao->default_route = 1;
559 }
560
561
562 /*
563  * ipcp_open - IPCP is allowed to come up.
564  */
565 static void
566 ipcp_open(unit)
567     int unit;
568 {
569     fsm_open(&ipcp_fsm[unit]);
570 }
571
572
573 /*
574  * ipcp_close - Take IPCP down.
575  */
576 static void
577 ipcp_close(unit, reason)
578     int unit;
579     char *reason;
580 {
581     fsm_close(&ipcp_fsm[unit], reason);
582 }
583
584
585 /*
586  * ipcp_lowerup - The lower layer is up.
587  */
588 static void
589 ipcp_lowerup(unit)
590     int unit;
591 {
592     fsm_lowerup(&ipcp_fsm[unit]);
593 }
594
595
596 /*
597  * ipcp_lowerdown - The lower layer is down.
598  */
599 static void
600 ipcp_lowerdown(unit)
601     int unit;
602 {
603     fsm_lowerdown(&ipcp_fsm[unit]);
604 }
605
606
607 /*
608  * ipcp_input - Input IPCP packet.
609  */
610 static void
611 ipcp_input(unit, p, len)
612     int unit;
613     u_char *p;
614     int len;
615 {
616     fsm_input(&ipcp_fsm[unit], p, len);
617 }
618
619
620 /*
621  * ipcp_protrej - A Protocol-Reject was received for IPCP.
622  *
623  * Pretend the lower layer went down, so we shut up.
624  */
625 static void
626 ipcp_protrej(unit)
627     int unit;
628 {
629     fsm_lowerdown(&ipcp_fsm[unit]);
630 }
631
632
633 /*
634  * ipcp_resetci - Reset our CI.
635  * Called by fsm_sconfreq, Send Configure Request.
636  */
637 static void
638 ipcp_resetci(f)
639     fsm *f;
640 {
641     ipcp_options *wo = &ipcp_wantoptions[f->unit];
642     ipcp_options *go = &ipcp_gotoptions[f->unit];
643
644     wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr;
645     if (wo->ouraddr == 0)
646         wo->accept_local = 1;
647     if (wo->hisaddr == 0)
648         wo->accept_remote = 1;
649     wo->req_dns1 = usepeerdns;  /* Request DNS addresses from the peer */
650     wo->req_dns2 = usepeerdns;
651     *go = *wo;
652     if (!ask_for_local)
653         go->ouraddr = 0;
654     if (ip_choose_hook)
655         ip_choose_hook(&wo->hisaddr);
656 }
657
658
659 /*
660  * ipcp_cilen - Return length of our CI.
661  * Called by fsm_sconfreq, Send Configure Request.
662  */
663 static int
664 ipcp_cilen(f)
665     fsm *f;
666 {
667     ipcp_options *go = &ipcp_gotoptions[f->unit];
668     ipcp_options *wo = &ipcp_wantoptions[f->unit];
669     ipcp_options *ho = &ipcp_hisoptions[f->unit];
670
671 #define LENCIVJ(neg, old)       (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0)
672 #define LENCIADDR(neg, old)     (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0)
673 #define LENCIDNS(neg)           (neg ? (CILEN_ADDR) : 0)
674
675     /*
676      * First see if we want to change our options to the old
677      * forms because we have received old forms from the peer.
678      */
679     if (wo->neg_addr && !go->neg_addr && !go->old_addrs) {
680         /* use the old style of address negotiation */
681         go->neg_addr = 1;
682         go->old_addrs = 1;
683     }
684     if (wo->neg_vj && !go->neg_vj && !go->old_vj) {
685         /* try an older style of VJ negotiation */
686         /* use the old style only if the peer did */
687         if (ho->neg_vj && ho->old_vj) {
688             go->neg_vj = 1;
689             go->old_vj = 1;
690             go->vj_protocol = ho->vj_protocol;
691         }
692     }
693
694     return (LENCIADDR(go->neg_addr, go->old_addrs) +
695             LENCIVJ(go->neg_vj, go->old_vj) +
696             LENCIDNS(go->req_dns1) +
697             LENCIDNS(go->req_dns2)) ;
698 }
699
700
701 /*
702  * ipcp_addci - Add our desired CIs to a packet.
703  * Called by fsm_sconfreq, Send Configure Request.
704  */
705 static void
706 ipcp_addci(f, ucp, lenp)
707     fsm *f;
708     u_char *ucp;
709     int *lenp;
710 {
711     ipcp_options *go = &ipcp_gotoptions[f->unit];
712     int len = *lenp;
713
714 #define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \
715     if (neg) { \
716         int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
717         if (len >= vjlen) { \
718             PUTCHAR(opt, ucp); \
719             PUTCHAR(vjlen, ucp); \
720             PUTSHORT(val, ucp); \
721             if (!old) { \
722                 PUTCHAR(maxslotindex, ucp); \
723                 PUTCHAR(cflag, ucp); \
724             } \
725             len -= vjlen; \
726         } else \
727             neg = 0; \
728     }
729
730 #define ADDCIADDR(opt, neg, old, val1, val2) \
731     if (neg) { \
732         int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
733         if (len >= addrlen) { \
734             u_int32_t l; \
735             PUTCHAR(opt, ucp); \
736             PUTCHAR(addrlen, ucp); \
737             l = ntohl(val1); \
738             PUTLONG(l, ucp); \
739             if (old) { \
740                 l = ntohl(val2); \
741                 PUTLONG(l, ucp); \
742             } \
743             len -= addrlen; \
744         } else \
745             neg = 0; \
746     }
747
748 #define ADDCIDNS(opt, neg, addr) \
749     if (neg) { \
750         if (len >= CILEN_ADDR) { \
751             u_int32_t l; \
752             PUTCHAR(opt, ucp); \
753             PUTCHAR(CILEN_ADDR, ucp); \
754             l = ntohl(addr); \
755             PUTLONG(l, ucp); \
756             len -= CILEN_ADDR; \
757         } else \
758             neg = 0; \
759     }
760
761     ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
762               go->old_addrs, go->ouraddr, go->hisaddr);
763
764     ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
765             go->maxslotindex, go->cflag);
766
767     ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
768
769     ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
770
771     *lenp -= len;
772 }
773
774
775 /*
776  * ipcp_ackci - Ack our CIs.
777  * Called by fsm_rconfack, Receive Configure ACK.
778  *
779  * Returns:
780  *      0 - Ack was bad.
781  *      1 - Ack was good.
782  */
783 static int
784 ipcp_ackci(f, p, len)
785     fsm *f;
786     u_char *p;
787     int len;
788 {
789     ipcp_options *go = &ipcp_gotoptions[f->unit];
790     u_short cilen, citype, cishort;
791     u_int32_t cilong;
792     u_char cimaxslotindex, cicflag;
793
794     /*
795      * CIs must be in exactly the same order that we sent...
796      * Check packet length and CI length at each step.
797      * If we find any deviations, then this packet is bad.
798      */
799
800 #define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \
801     if (neg) { \
802         int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
803         if ((len -= vjlen) < 0) \
804             goto bad; \
805         GETCHAR(citype, p); \
806         GETCHAR(cilen, p); \
807         if (cilen != vjlen || \
808             citype != opt)  \
809             goto bad; \
810         GETSHORT(cishort, p); \
811         if (cishort != val) \
812             goto bad; \
813         if (!old) { \
814             GETCHAR(cimaxslotindex, p); \
815             if (cimaxslotindex != maxslotindex) \
816                 goto bad; \
817             GETCHAR(cicflag, p); \
818             if (cicflag != cflag) \
819                 goto bad; \
820         } \
821     }
822
823 #define ACKCIADDR(opt, neg, old, val1, val2) \
824     if (neg) { \
825         int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
826         u_int32_t l; \
827         if ((len -= addrlen) < 0) \
828             goto bad; \
829         GETCHAR(citype, p); \
830         GETCHAR(cilen, p); \
831         if (cilen != addrlen || \
832             citype != opt) \
833             goto bad; \
834         GETLONG(l, p); \
835         cilong = htonl(l); \
836         if (val1 != cilong) \
837             goto bad; \
838         if (old) { \
839             GETLONG(l, p); \
840             cilong = htonl(l); \
841             if (val2 != cilong) \
842                 goto bad; \
843         } \
844     }
845
846 #define ACKCIDNS(opt, neg, addr) \
847     if (neg) { \
848         u_int32_t l; \
849         if ((len -= CILEN_ADDR) < 0) \
850             goto bad; \
851         GETCHAR(citype, p); \
852         GETCHAR(cilen, p); \
853         if (cilen != CILEN_ADDR || citype != opt) \
854             goto bad; \
855         GETLONG(l, p); \
856         cilong = htonl(l); \
857         if (addr != cilong) \
858             goto bad; \
859     }
860
861     ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
862               go->old_addrs, go->ouraddr, go->hisaddr);
863
864     ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
865             go->maxslotindex, go->cflag);
866
867     ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
868
869     ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
870
871     /*
872      * If there are any remaining CIs, then this packet is bad.
873      */
874     if (len != 0)
875         goto bad;
876     return (1);
877
878 bad:
879     IPCPDEBUG(("ipcp_ackci: received bad Ack!"));
880     return (0);
881 }
882
883 /*
884  * ipcp_nakci - Peer has sent a NAK for some of our CIs.
885  * This should not modify any state if the Nak is bad
886  * or if IPCP is in the OPENED state.
887  * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
888  *
889  * Returns:
890  *      0 - Nak was bad.
891  *      1 - Nak was good.
892  */
893 static int
894 ipcp_nakci(f, p, len)
895     fsm *f;
896     u_char *p;
897     int len;
898 {
899     ipcp_options *go = &ipcp_gotoptions[f->unit];
900     u_char cimaxslotindex, cicflag;
901     u_char citype, cilen, *next;
902     u_short cishort;
903     u_int32_t ciaddr1, ciaddr2, l, cidnsaddr;
904     ipcp_options no;            /* options we've seen Naks for */
905     ipcp_options try;           /* options to request next time */
906
907     BZERO(&no, sizeof(no));
908     try = *go;
909
910     /*
911      * Any Nak'd CIs must be in exactly the same order that we sent.
912      * Check packet length and CI length at each step.
913      * If we find any deviations, then this packet is bad.
914      */
915 #define NAKCIADDR(opt, neg, old, code) \
916     if (go->neg && \
917         len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \
918         p[1] == cilen && \
919         p[0] == opt) { \
920         len -= cilen; \
921         INCPTR(2, p); \
922         GETLONG(l, p); \
923         ciaddr1 = htonl(l); \
924         if (old) { \
925             GETLONG(l, p); \
926             ciaddr2 = htonl(l); \
927             no.old_addrs = 1; \
928         } else \
929             ciaddr2 = 0; \
930         no.neg = 1; \
931         code \
932     }
933
934 #define NAKCIVJ(opt, neg, code) \
935     if (go->neg && \
936         ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \
937         len >= cilen && \
938         p[0] == opt) { \
939         len -= cilen; \
940         INCPTR(2, p); \
941         GETSHORT(cishort, p); \
942         no.neg = 1; \
943         code \
944     }
945
946 #define NAKCIDNS(opt, neg, code) \
947     if (go->neg && \
948         ((cilen = p[1]) == CILEN_ADDR) && \
949         len >= cilen && \
950         p[0] == opt) { \
951         len -= cilen; \
952         INCPTR(2, p); \
953         GETLONG(l, p); \
954         cidnsaddr = htonl(l); \
955         no.neg = 1; \
956         code \
957     }
958
959     /*
960      * Accept the peer's idea of {our,his} address, if different
961      * from our idea, only if the accept_{local,remote} flag is set.
962      */
963     NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs,
964               if (go->accept_local && ciaddr1) { /* Do we know our address? */
965                   try.ouraddr = ciaddr1;
966               }
967               if (go->accept_remote && ciaddr2) { /* Does he know his? */
968                   try.hisaddr = ciaddr2;
969               }
970               );
971
972     /*
973      * Accept the peer's value of maxslotindex provided that it
974      * is less than what we asked for.  Turn off slot-ID compression
975      * if the peer wants.  Send old-style compress-type option if
976      * the peer wants.
977      */
978     NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
979             if (cilen == CILEN_VJ) {
980                 GETCHAR(cimaxslotindex, p);
981                 GETCHAR(cicflag, p);
982                 if (cishort == IPCP_VJ_COMP) {
983                     try.old_vj = 0;
984                     if (cimaxslotindex < go->maxslotindex)
985                         try.maxslotindex = cimaxslotindex;
986                     if (!cicflag)
987                         try.cflag = 0;
988                 } else {
989                     try.neg_vj = 0;
990                 }
991             } else {
992                 if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) {
993                     try.old_vj = 1;
994                     try.vj_protocol = cishort;
995                 } else {
996                     try.neg_vj = 0;
997                 }
998             }
999             );
1000
1001     NAKCIDNS(CI_MS_DNS1, req_dns1,
1002             try.dnsaddr[0] = cidnsaddr;
1003             );
1004
1005     NAKCIDNS(CI_MS_DNS2, req_dns2,
1006             try.dnsaddr[1] = cidnsaddr;
1007             );
1008
1009     /*
1010      * There may be remaining CIs, if the peer is requesting negotiation
1011      * on an option that we didn't include in our request packet.
1012      * If they want to negotiate about IP addresses, we comply.
1013      * If they want us to ask for compression, we refuse.
1014      */
1015     while (len > CILEN_VOID) {
1016         GETCHAR(citype, p);
1017         GETCHAR(cilen, p);
1018         if( (len -= cilen) < 0 )
1019             goto bad;
1020         next = p + cilen - 2;
1021
1022         switch (citype) {
1023         case CI_COMPRESSTYPE:
1024             if (go->neg_vj || no.neg_vj ||
1025                 (cilen != CILEN_VJ && cilen != CILEN_COMPRESS))
1026                 goto bad;
1027             no.neg_vj = 1;
1028             break;
1029         case CI_ADDRS:
1030             if ((go->neg_addr && go->old_addrs) || no.old_addrs
1031                 || cilen != CILEN_ADDRS)
1032                 goto bad;
1033             try.neg_addr = 1;
1034             try.old_addrs = 1;
1035             GETLONG(l, p);
1036             ciaddr1 = htonl(l);
1037             if (ciaddr1 && go->accept_local)
1038                 try.ouraddr = ciaddr1;
1039             GETLONG(l, p);
1040             ciaddr2 = htonl(l);
1041             if (ciaddr2 && go->accept_remote)
1042                 try.hisaddr = ciaddr2;
1043             no.old_addrs = 1;
1044             break;
1045         case CI_ADDR:
1046             if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR)
1047                 goto bad;
1048             try.old_addrs = 0;
1049             GETLONG(l, p);
1050             ciaddr1 = htonl(l);
1051             if (ciaddr1 && go->accept_local)
1052                 try.ouraddr = ciaddr1;
1053             if (try.ouraddr != 0)
1054                 try.neg_addr = 1;
1055             no.neg_addr = 1;
1056             break;
1057         }
1058         p = next;
1059     }
1060
1061     /*
1062      * OK, the Nak is good.  Now we can update state.
1063      * If there are any remaining options, we ignore them.
1064      */
1065     if (f->state != OPENED)
1066         *go = try;
1067
1068     return 1;
1069
1070 bad:
1071     IPCPDEBUG(("ipcp_nakci: received bad Nak!"));
1072     return 0;
1073 }
1074
1075
1076 /*
1077  * ipcp_rejci - Reject some of our CIs.
1078  * Callback from fsm_rconfnakrej.
1079  */
1080 static int
1081 ipcp_rejci(f, p, len)
1082     fsm *f;
1083     u_char *p;
1084     int len;
1085 {
1086     ipcp_options *go = &ipcp_gotoptions[f->unit];
1087     u_char cimaxslotindex, ciflag, cilen;
1088     u_short cishort;
1089     u_int32_t cilong;
1090     ipcp_options try;           /* options to request next time */
1091
1092     try = *go;
1093     /*
1094      * Any Rejected CIs must be in exactly the same order that we sent.
1095      * Check packet length and CI length at each step.
1096      * If we find any deviations, then this packet is bad.
1097      */
1098 #define REJCIADDR(opt, neg, old, val1, val2) \
1099     if (go->neg && \
1100         len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \
1101         p[1] == cilen && \
1102         p[0] == opt) { \
1103         u_int32_t l; \
1104         len -= cilen; \
1105         INCPTR(2, p); \
1106         GETLONG(l, p); \
1107         cilong = htonl(l); \
1108         /* Check rejected value. */ \
1109         if (cilong != val1) \
1110             goto bad; \
1111         if (old) { \
1112             GETLONG(l, p); \
1113             cilong = htonl(l); \
1114             /* Check rejected value. */ \
1115             if (cilong != val2) \
1116                 goto bad; \
1117         } \
1118         try.neg = 0; \
1119     }
1120
1121 #define REJCIVJ(opt, neg, val, old, maxslot, cflag) \
1122     if (go->neg && \
1123         p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \
1124         len >= p[1] && \
1125         p[0] == opt) { \
1126         len -= p[1]; \
1127         INCPTR(2, p); \
1128         GETSHORT(cishort, p); \
1129         /* Check rejected value. */  \
1130         if (cishort != val) \
1131             goto bad; \
1132         if (!old) { \
1133            GETCHAR(cimaxslotindex, p); \
1134            if (cimaxslotindex != maxslot) \
1135              goto bad; \
1136            GETCHAR(ciflag, p); \
1137            if (ciflag != cflag) \
1138              goto bad; \
1139         } \
1140         try.neg = 0; \
1141      }
1142
1143 #define REJCIDNS(opt, neg, dnsaddr) \
1144     if (go->neg && \
1145         ((cilen = p[1]) == CILEN_ADDR) && \
1146         len >= cilen && \
1147         p[0] == opt) { \
1148         u_int32_t l; \
1149         len -= cilen; \
1150         INCPTR(2, p); \
1151         GETLONG(l, p); \
1152         cilong = htonl(l); \
1153         /* Check rejected value. */ \
1154         if (cilong != dnsaddr) \
1155             goto bad; \
1156         try.neg = 0; \
1157     }
1158
1159
1160     REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr,
1161               go->old_addrs, go->ouraddr, go->hisaddr);
1162
1163     REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj,
1164             go->maxslotindex, go->cflag);
1165
1166     REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]);
1167
1168     REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]);
1169
1170     /*
1171      * If there are any remaining CIs, then this packet is bad.
1172      */
1173     if (len != 0)
1174         goto bad;
1175     /*
1176      * Now we can update state.
1177      */
1178     if (f->state != OPENED)
1179         *go = try;
1180     return 1;
1181
1182 bad:
1183     IPCPDEBUG(("ipcp_rejci: received bad Reject!"));
1184     return 0;
1185 }
1186
1187
1188 /*
1189  * ipcp_reqci - Check the peer's requested CIs and send appropriate response.
1190  * Callback from fsm_rconfreq, Receive Configure Request
1191  *
1192  * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
1193  * appropriately.  If reject_if_disagree is non-zero, doesn't return
1194  * CONFNAK; returns CONFREJ if it can't return CONFACK.
1195  */
1196 static int
1197 ipcp_reqci(f, inp, len, reject_if_disagree)
1198     fsm *f;
1199     u_char *inp;                /* Requested CIs */
1200     int *len;                   /* Length of requested CIs */
1201     int reject_if_disagree;
1202 {
1203     ipcp_options *wo = &ipcp_wantoptions[f->unit];
1204     ipcp_options *ho = &ipcp_hisoptions[f->unit];
1205     ipcp_options *ao = &ipcp_allowoptions[f->unit];
1206     ipcp_options *go = &ipcp_gotoptions[f->unit];
1207     u_char *cip, *next;         /* Pointer to current and next CIs */
1208     u_short cilen, citype;      /* Parsed len, type */
1209     u_short cishort;            /* Parsed short value */
1210     u_int32_t tl, ciaddr1, ciaddr2;/* Parsed address values */
1211     int rc = CONFACK;           /* Final packet return code */
1212     int orc;                    /* Individual option return code */
1213     u_char *p;                  /* Pointer to next char to parse */
1214     u_char *ucp = inp;          /* Pointer to current output char */
1215     int l = *len;               /* Length left */
1216     u_char maxslotindex, cflag;
1217     int d;
1218
1219     /*
1220      * Reset all his options.
1221      */
1222     BZERO(ho, sizeof(*ho));
1223     
1224     /*
1225      * Process all his options.
1226      */
1227     next = inp;
1228     while (l) {
1229         orc = CONFACK;                  /* Assume success */
1230         cip = p = next;                 /* Remember begining of CI */
1231         if (l < 2 ||                    /* Not enough data for CI header or */
1232             p[1] < 2 ||                 /*  CI length too small or */
1233             p[1] > l) {                 /*  CI length too big? */
1234             IPCPDEBUG(("ipcp_reqci: bad CI length!"));
1235             orc = CONFREJ;              /* Reject bad CI */
1236             cilen = l;                  /* Reject till end of packet */
1237             l = 0;                      /* Don't loop again */
1238             goto endswitch;
1239         }
1240         GETCHAR(citype, p);             /* Parse CI type */
1241         GETCHAR(cilen, p);              /* Parse CI length */
1242         l -= cilen;                     /* Adjust remaining length */
1243         next += cilen;                  /* Step to next CI */
1244
1245         switch (citype) {               /* Check CI type */
1246         case CI_ADDRS:
1247             if (!ao->neg_addr ||
1248                 cilen != CILEN_ADDRS) { /* Check CI length */
1249                 orc = CONFREJ;          /* Reject CI */
1250                 break;
1251             }
1252
1253             /*
1254              * If he has no address, or if we both have his address but
1255              * disagree about it, then NAK it with our idea.
1256              * In particular, if we don't know his address, but he does,
1257              * then accept it.
1258              */
1259             GETLONG(tl, p);             /* Parse source address (his) */
1260             ciaddr1 = htonl(tl);
1261             if (ciaddr1 != wo->hisaddr
1262                 && (ciaddr1 == 0 || !wo->accept_remote)) {
1263                 orc = CONFNAK;
1264                 if (!reject_if_disagree) {
1265                     DECPTR(sizeof(u_int32_t), p);
1266                     tl = ntohl(wo->hisaddr);
1267                     PUTLONG(tl, p);
1268                 }
1269             } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
1270                 /*
1271                  * If neither we nor he knows his address, reject the option.
1272                  */
1273                 orc = CONFREJ;
1274                 wo->req_addr = 0;       /* don't NAK with 0.0.0.0 later */
1275                 break;
1276             }
1277
1278             /*
1279              * If he doesn't know our address, or if we both have our address
1280              * but disagree about it, then NAK it with our idea.
1281              */
1282             GETLONG(tl, p);             /* Parse desination address (ours) */
1283             ciaddr2 = htonl(tl);
1284             if (ciaddr2 != wo->ouraddr) {
1285                 if (ciaddr2 == 0 || !wo->accept_local) {
1286                     orc = CONFNAK;
1287                     if (!reject_if_disagree) {
1288                         DECPTR(sizeof(u_int32_t), p);
1289                         tl = ntohl(wo->ouraddr);
1290                         PUTLONG(tl, p);
1291                     }
1292                 } else {
1293                     go->ouraddr = ciaddr2;      /* accept peer's idea */
1294                 }
1295             }
1296
1297             ho->neg_addr = 1;
1298             ho->old_addrs = 1;
1299             ho->hisaddr = ciaddr1;
1300             ho->ouraddr = ciaddr2;
1301             break;
1302
1303         case CI_ADDR:
1304             if (!ao->neg_addr ||
1305                 cilen != CILEN_ADDR) {  /* Check CI length */
1306                 orc = CONFREJ;          /* Reject CI */
1307                 break;
1308             }
1309
1310             /*
1311              * If he has no address, or if we both have his address but
1312              * disagree about it, then NAK it with our idea.
1313              * In particular, if we don't know his address, but he does,
1314              * then accept it.
1315              */
1316             GETLONG(tl, p);     /* Parse source address (his) */
1317             ciaddr1 = htonl(tl);
1318             if (ciaddr1 != wo->hisaddr
1319                 && (ciaddr1 == 0 || !wo->accept_remote)) {
1320                 orc = CONFNAK;
1321                 if (!reject_if_disagree) {
1322                     DECPTR(sizeof(u_int32_t), p);
1323                     tl = ntohl(wo->hisaddr);
1324                     PUTLONG(tl, p);
1325                 }
1326             } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
1327                 /*
1328                  * Don't ACK an address of 0.0.0.0 - reject it instead.
1329                  */
1330                 orc = CONFREJ;
1331                 wo->req_addr = 0;       /* don't NAK with 0.0.0.0 later */
1332                 break;
1333             }
1334         
1335             ho->neg_addr = 1;
1336             ho->hisaddr = ciaddr1;
1337             break;
1338
1339         case CI_MS_DNS1:
1340         case CI_MS_DNS2:
1341             /* Microsoft primary or secondary DNS request */
1342             d = citype == CI_MS_DNS2;
1343
1344             /* If we do not have a DNS address then we cannot send it */
1345             if (ao->dnsaddr[d] == 0 ||
1346                 cilen != CILEN_ADDR) {  /* Check CI length */
1347                 orc = CONFREJ;          /* Reject CI */
1348                 break;
1349             }
1350             GETLONG(tl, p);
1351             if (htonl(tl) != ao->dnsaddr[d]) {
1352                 DECPTR(sizeof(u_int32_t), p);
1353                 tl = ntohl(ao->dnsaddr[d]);
1354                 PUTLONG(tl, p);
1355                 orc = CONFNAK;
1356             }
1357             break;
1358
1359         case CI_MS_WINS1:
1360         case CI_MS_WINS2:
1361             /* Microsoft primary or secondary WINS request */
1362             d = citype == CI_MS_WINS2;
1363
1364             /* If we do not have a DNS address then we cannot send it */
1365             if (ao->winsaddr[d] == 0 ||
1366                 cilen != CILEN_ADDR) {  /* Check CI length */
1367                 orc = CONFREJ;          /* Reject CI */
1368                 break;
1369             }
1370             GETLONG(tl, p);
1371             if (htonl(tl) != ao->winsaddr[d]) {
1372                 DECPTR(sizeof(u_int32_t), p);
1373                 tl = ntohl(ao->winsaddr[d]);
1374                 PUTLONG(tl, p);
1375                 orc = CONFNAK;
1376             }
1377             break;
1378         
1379         case CI_COMPRESSTYPE:
1380             if (!ao->neg_vj ||
1381                 (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) {
1382                 orc = CONFREJ;
1383                 break;
1384             }
1385             GETSHORT(cishort, p);
1386
1387             if (!(cishort == IPCP_VJ_COMP ||
1388                   (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {
1389                 orc = CONFREJ;
1390                 break;
1391             }
1392
1393             ho->neg_vj = 1;
1394             ho->vj_protocol = cishort;
1395             if (cilen == CILEN_VJ) {
1396                 GETCHAR(maxslotindex, p);
1397                 if (maxslotindex > ao->maxslotindex) { 
1398                     orc = CONFNAK;
1399                     if (!reject_if_disagree){
1400                         DECPTR(1, p);
1401                         PUTCHAR(ao->maxslotindex, p);
1402                     }
1403                 }
1404                 GETCHAR(cflag, p);
1405                 if (cflag && !ao->cflag) {
1406                     orc = CONFNAK;
1407                     if (!reject_if_disagree){
1408                         DECPTR(1, p);
1409                         PUTCHAR(wo->cflag, p);
1410                     }
1411                 }
1412                 ho->maxslotindex = maxslotindex;
1413                 ho->cflag = cflag;
1414             } else {
1415                 ho->old_vj = 1;
1416                 ho->maxslotindex = MAX_STATES - 1;
1417                 ho->cflag = 1;
1418             }
1419             break;
1420
1421         default:
1422             orc = CONFREJ;
1423             break;
1424         }
1425 endswitch:
1426         if (orc == CONFACK &&           /* Good CI */
1427             rc != CONFACK)              /*  but prior CI wasnt? */
1428             continue;                   /* Don't send this one */
1429
1430         if (orc == CONFNAK) {           /* Nak this CI? */
1431             if (reject_if_disagree)     /* Getting fed up with sending NAKs? */
1432                 orc = CONFREJ;          /* Get tough if so */
1433             else {
1434                 if (rc == CONFREJ)      /* Rejecting prior CI? */
1435                     continue;           /* Don't send this one */
1436                 if (rc == CONFACK) {    /* Ack'd all prior CIs? */
1437                     rc = CONFNAK;       /* Not anymore... */
1438                     ucp = inp;          /* Backup */
1439                 }
1440             }
1441         }
1442
1443         if (orc == CONFREJ &&           /* Reject this CI */
1444             rc != CONFREJ) {            /*  but no prior ones? */
1445             rc = CONFREJ;
1446             ucp = inp;                  /* Backup */
1447         }
1448
1449         /* Need to move CI? */
1450         if (ucp != cip)
1451             BCOPY(cip, ucp, cilen);     /* Move it */
1452
1453         /* Update output pointer */
1454         INCPTR(cilen, ucp);
1455     }
1456
1457     /*
1458      * If we aren't rejecting this packet, and we want to negotiate
1459      * their address, and they didn't send their address, then we
1460      * send a NAK with a CI_ADDR option appended.  We assume the
1461      * input buffer is long enough that we can append the extra
1462      * option safely.
1463      */
1464     if (rc != CONFREJ && !ho->neg_addr &&
1465         wo->req_addr && !reject_if_disagree) {
1466         if (rc == CONFACK) {
1467             rc = CONFNAK;
1468             ucp = inp;                  /* reset pointer */
1469             wo->req_addr = 0;           /* don't ask again */
1470         }
1471         PUTCHAR(CI_ADDR, ucp);
1472         PUTCHAR(CILEN_ADDR, ucp);
1473         tl = ntohl(wo->hisaddr);
1474         PUTLONG(tl, ucp);
1475     }
1476
1477     *len = ucp - inp;                   /* Compute output length */
1478     IPCPDEBUG(("ipcp: returning Configure-%s", CODENAME(rc)));
1479     return (rc);                        /* Return final code */
1480 }
1481
1482
1483 /*
1484  * ip_check_options - check that any IP-related options are OK,
1485  * and assign appropriate defaults.
1486  */
1487 static void
1488 ip_check_options()
1489 {
1490     struct hostent *hp;
1491     u_int32_t local;
1492     ipcp_options *wo = &ipcp_wantoptions[0];
1493
1494     /*
1495      * Default our local IP address based on our hostname.
1496      * If local IP address already given, don't bother.
1497      */
1498     if (wo->ouraddr == 0 && !disable_defaultip) {
1499         /*
1500          * Look up our hostname (possibly with domain name appended)
1501          * and take the first IP address as our local IP address.
1502          * If there isn't an IP address for our hostname, too bad.
1503          */
1504         wo->accept_local = 1;   /* don't insist on this default value */
1505         if ((hp = gethostbyname(hostname)) != NULL) {
1506             local = *(u_int32_t *)hp->h_addr;
1507             if (local != 0 && !bad_ip_adrs(local))
1508                 wo->ouraddr = local;
1509         }
1510     }
1511     ask_for_local = wo->ouraddr != 0 || !disable_defaultip;
1512 }
1513
1514
1515 /*
1516  * ip_demand_conf - configure the interface as though
1517  * IPCP were up, for use with dial-on-demand.
1518  */
1519 static int
1520 ip_demand_conf(u)
1521     int u;
1522 {
1523     ipcp_options *wo = &ipcp_wantoptions[u];
1524
1525     if (wo->hisaddr == 0) {
1526         /* make up an arbitrary address for the peer */
1527         wo->hisaddr = htonl(0x0a707070 + ifunit);
1528         wo->accept_remote = 1;
1529     }
1530     if (wo->ouraddr == 0) {
1531         /* make up an arbitrary address for us */
1532         wo->ouraddr = htonl(0x0a404040 + ifunit);
1533         wo->accept_local = 1;
1534         ask_for_local = 0;      /* don't tell the peer this address */
1535     }
1536     if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr)))
1537         return 0;
1538     if (!sifup(u))
1539         return 0;
1540     if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
1541         return 0;
1542     if (wo->default_route)
1543         if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
1544             default_route_set[u] = 1;
1545     if (wo->proxy_arp)
1546         if (sifproxyarp(u, wo->hisaddr))
1547             proxy_arp_set[u] = 1;
1548
1549     notice("local  IP address %I", wo->ouraddr);
1550     notice("remote IP address %I", wo->hisaddr);
1551
1552     return 1;
1553 }
1554
1555
1556 /*
1557  * ipcp_up - IPCP has come UP.
1558  *
1559  * Configure the IP network interface appropriately and bring it up.
1560  */
1561 static void
1562 ipcp_up(f)
1563     fsm *f;
1564 {
1565     u_int32_t mask;
1566     ipcp_options *ho = &ipcp_hisoptions[f->unit];
1567     ipcp_options *go = &ipcp_gotoptions[f->unit];
1568     ipcp_options *wo = &ipcp_wantoptions[f->unit];
1569
1570     IPCPDEBUG(("ipcp: up"));
1571
1572     /*
1573      * We must have a non-zero IP address for both ends of the link.
1574      */
1575     if (!ho->neg_addr)
1576         ho->hisaddr = wo->hisaddr;
1577
1578     if (go->ouraddr == 0) {
1579         error("Could not determine local IP address");
1580         ipcp_close(f->unit, "Could not determine local IP address");
1581         return;
1582     }
1583     if (ho->hisaddr == 0) {
1584         ho->hisaddr = htonl(0x0a404040 + ifunit);
1585         warn("Could not determine remote IP address: defaulting to %I",
1586              ho->hisaddr);
1587     }
1588     script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0);
1589     script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1);
1590
1591     if (usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) {
1592         script_setenv("USEPEERDNS", "1", 0);
1593         if (go->dnsaddr[0])
1594             script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0);
1595         if (go->dnsaddr[1])
1596             script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0);
1597         create_resolv(go->dnsaddr[0], go->dnsaddr[1]);
1598     }
1599
1600     /*
1601      * Check that the peer is allowed to use the IP address it wants.
1602      */
1603     if (!auth_ip_addr(f->unit, ho->hisaddr)) {
1604         error("Peer is not authorized to use remote address %I", ho->hisaddr);
1605         ipcp_close(f->unit, "Unauthorized remote IP address");
1606         return;
1607     }
1608
1609     /* set tcp compression */
1610     sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex);
1611
1612     /*
1613      * If we are doing dial-on-demand, the interface is already
1614      * configured, so we put out any saved-up packets, then set the
1615      * interface to pass IP packets.
1616      */
1617     if (demand) {
1618         if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
1619             ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr);
1620             if (go->ouraddr != wo->ouraddr) {
1621                 warn("Local IP address changed to %I", go->ouraddr);
1622                 script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0);
1623                 wo->ouraddr = go->ouraddr;
1624             } else
1625                 script_unsetenv("OLDIPLOCAL");
1626             if (ho->hisaddr != wo->hisaddr) {
1627                 warn("Remote IP address changed to %I", ho->hisaddr);
1628                 script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0);
1629                 wo->hisaddr = ho->hisaddr;
1630             } else
1631                 script_unsetenv("OLDIPREMOTE");
1632
1633             /* Set the interface to the new addresses */
1634             mask = GetMask(go->ouraddr);
1635             if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1636                 if (debug)
1637                     warn("Interface configuration failed");
1638                 ipcp_close(f->unit, "Interface configuration failed");
1639                 return;
1640             }
1641
1642             /* assign a default route through the interface if required */
1643             if (ipcp_wantoptions[f->unit].default_route) 
1644                 if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
1645                     default_route_set[f->unit] = 1;
1646
1647             /* Make a proxy ARP entry if requested. */
1648             if (ipcp_wantoptions[f->unit].proxy_arp)
1649                 if (sifproxyarp(f->unit, ho->hisaddr))
1650                     proxy_arp_set[f->unit] = 1;
1651
1652         }
1653         demand_rexmit(PPP_IP);
1654         sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
1655
1656     } else {
1657         /*
1658          * Set IP addresses and (if specified) netmask.
1659          */
1660         mask = GetMask(go->ouraddr);
1661
1662 #if !(defined(SVR4) && (defined(SNI) || defined(__USLC__)))
1663         if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1664             if (debug)
1665                 warn("Interface configuration failed");
1666             ipcp_close(f->unit, "Interface configuration failed");
1667             return;
1668         }
1669 #endif
1670
1671         /* bring the interface up for IP */
1672         if (!sifup(f->unit)) {
1673             if (debug)
1674                 warn("Interface failed to come up");
1675             ipcp_close(f->unit, "Interface configuration failed");
1676             return;
1677         }
1678
1679 #if (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
1680         if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1681             if (debug)
1682                 warn("Interface configuration failed");
1683             ipcp_close(f->unit, "Interface configuration failed");
1684             return;
1685         }
1686 #endif
1687         sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
1688
1689         /* assign a default route through the interface if required */
1690         if (ipcp_wantoptions[f->unit].default_route) 
1691             if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
1692                 default_route_set[f->unit] = 1;
1693
1694         /* Make a proxy ARP entry if requested. */
1695         if (ipcp_wantoptions[f->unit].proxy_arp)
1696             if (sifproxyarp(f->unit, ho->hisaddr))
1697                 proxy_arp_set[f->unit] = 1;
1698
1699         ipcp_wantoptions[0].ouraddr = go->ouraddr;
1700
1701         notice("local  IP address %I", go->ouraddr);
1702         notice("remote IP address %I", ho->hisaddr);
1703         if (go->dnsaddr[0])
1704             notice("primary   DNS address %I", go->dnsaddr[0]);
1705         if (go->dnsaddr[1])
1706             notice("secondary DNS address %I", go->dnsaddr[1]);
1707     }
1708
1709     np_up(f->unit, PPP_IP);
1710     ipcp_is_up = 1;
1711
1712     if (ip_up_hook)
1713         ip_up_hook();
1714
1715     /*
1716      * Execute the ip-up script, like this:
1717      *  /etc/ppp/ip-up interface tty speed local-IP remote-IP
1718      */
1719     if (ipcp_script_state == s_down && ipcp_script_pid == 0) {
1720         ipcp_script_state = s_up;
1721         ipcp_script(_PATH_IPUP);
1722     }
1723 }
1724
1725
1726 /*
1727  * ipcp_down - IPCP has gone DOWN.
1728  *
1729  * Take the IP network interface down, clear its addresses
1730  * and delete routes through it.
1731  */
1732 static void
1733 ipcp_down(f)
1734     fsm *f;
1735 {
1736     IPCPDEBUG(("ipcp: down"));
1737     /* XXX a bit IPv4-centric here, we only need to get the stats
1738      * before the interface is marked down. */
1739     update_link_stats(f->unit);
1740     if (ip_down_hook)
1741         ip_down_hook();
1742     if (ipcp_is_up) {
1743         ipcp_is_up = 0;
1744         np_down(f->unit, PPP_IP);
1745     }
1746     sifvjcomp(f->unit, 0, 0, 0);
1747
1748     /*
1749      * If we are doing dial-on-demand, set the interface
1750      * to queue up outgoing packets (for now).
1751      */
1752     if (demand) {
1753         sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE);
1754     } else {
1755         sifnpmode(f->unit, PPP_IP, NPMODE_DROP);
1756         sifdown(f->unit);
1757         ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr,
1758                          ipcp_hisoptions[f->unit].hisaddr);
1759     }
1760
1761     /* Execute the ip-down script */
1762     if (ipcp_script_state == s_up && ipcp_script_pid == 0) {
1763         ipcp_script_state = s_down;
1764         ipcp_script(_PATH_IPDOWN);
1765     }
1766 }
1767
1768
1769 /*
1770  * ipcp_clear_addrs() - clear the interface addresses, routes,
1771  * proxy arp entries, etc.
1772  */
1773 static void
1774 ipcp_clear_addrs(unit, ouraddr, hisaddr)
1775     int unit;
1776     u_int32_t ouraddr;  /* local address */
1777     u_int32_t hisaddr;  /* remote address */
1778 {
1779     if (proxy_arp_set[unit]) {
1780         cifproxyarp(unit, hisaddr);
1781         proxy_arp_set[unit] = 0;
1782     }
1783     if (default_route_set[unit]) {
1784         cifdefaultroute(unit, ouraddr, hisaddr);
1785         default_route_set[unit] = 0;
1786     }
1787     cifaddr(unit, ouraddr, hisaddr);
1788 }
1789
1790
1791 /*
1792  * ipcp_finished - possibly shut down the lower layers.
1793  */
1794 static void
1795 ipcp_finished(f)
1796     fsm *f;
1797 {
1798     np_finished(f->unit, PPP_IP);
1799 }
1800
1801
1802 /*
1803  * ipcp_script_done - called when the ip-up or ip-down script
1804  * has finished.
1805  */
1806 static void
1807 ipcp_script_done(arg)
1808     void *arg;
1809 {
1810     ipcp_script_pid = 0;
1811     switch (ipcp_script_state) {
1812     case s_up:
1813         if (ipcp_fsm[0].state != OPENED) {
1814             ipcp_script_state = s_down;
1815             ipcp_script(_PATH_IPDOWN);
1816         }
1817         break;
1818     case s_down:
1819         if (ipcp_fsm[0].state == OPENED) {
1820             ipcp_script_state = s_up;
1821             ipcp_script(_PATH_IPUP);
1822         }
1823         break;
1824     }
1825 }
1826
1827
1828 /*
1829  * ipcp_script - Execute a script with arguments
1830  * interface-name tty-name speed local-IP remote-IP.
1831  */
1832 static void
1833 ipcp_script(script)
1834     char *script;
1835 {
1836     char strspeed[32], strlocal[32], strremote[32];
1837     char *argv[8];
1838
1839     slprintf(strspeed, sizeof(strspeed), "%d", baud_rate);
1840     slprintf(strlocal, sizeof(strlocal), "%I", ipcp_gotoptions[0].ouraddr);
1841     slprintf(strremote, sizeof(strremote), "%I", ipcp_hisoptions[0].hisaddr);
1842
1843     argv[0] = script;
1844     argv[1] = ifname;
1845     argv[2] = devnam;
1846     argv[3] = strspeed;
1847     argv[4] = strlocal;
1848     argv[5] = strremote;
1849     argv[6] = ipparam;
1850     argv[7] = NULL;
1851     ipcp_script_pid = run_program(script, argv, 0, ipcp_script_done, NULL);
1852 }
1853
1854 /*
1855  * create_resolv - create the replacement resolv.conf file
1856  */
1857 static void
1858 create_resolv(peerdns1, peerdns2)
1859     u_int32_t peerdns1, peerdns2;
1860 {
1861     FILE *f;
1862
1863     f = fopen(_PATH_RESOLV, "w");
1864     if (f == NULL) {
1865         error("Failed to create %s: %m", _PATH_RESOLV);
1866         return;
1867     }
1868
1869     if (peerdns1)
1870         fprintf(f, "nameserver %s\n", ip_ntoa(peerdns1));
1871
1872     if (peerdns2)
1873         fprintf(f, "nameserver %s\n", ip_ntoa(peerdns2));
1874
1875     if (ferror(f))
1876         error("Write failed to %s: %m", _PATH_RESOLV);
1877
1878     fclose(f);
1879 }
1880
1881 /*
1882  * ipcp_printpkt - print the contents of an IPCP packet.
1883  */
1884 static char *ipcp_codenames[] = {
1885     "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1886     "TermReq", "TermAck", "CodeRej"
1887 };
1888
1889 static int
1890 ipcp_printpkt(p, plen, printer, arg)
1891     u_char *p;
1892     int plen;
1893     void (*printer) __P((void *, char *, ...));
1894     void *arg;
1895 {
1896     int code, id, len, olen;
1897     u_char *pstart, *optend;
1898     u_short cishort;
1899     u_int32_t cilong;
1900
1901     if (plen < HEADERLEN)
1902         return 0;
1903     pstart = p;
1904     GETCHAR(code, p);
1905     GETCHAR(id, p);
1906     GETSHORT(len, p);
1907     if (len < HEADERLEN || len > plen)
1908         return 0;
1909
1910     if (code >= 1 && code <= sizeof(ipcp_codenames) / sizeof(char *))
1911         printer(arg, " %s", ipcp_codenames[code-1]);
1912     else
1913         printer(arg, " code=0x%x", code);
1914     printer(arg, " id=0x%x", id);
1915     len -= HEADERLEN;
1916     switch (code) {
1917     case CONFREQ:
1918     case CONFACK:
1919     case CONFNAK:
1920     case CONFREJ:
1921         /* print option list */
1922         while (len >= 2) {
1923             GETCHAR(code, p);
1924             GETCHAR(olen, p);
1925             p -= 2;
1926             if (olen < 2 || olen > len) {
1927                 break;
1928             }
1929             printer(arg, " <");
1930             len -= olen;
1931             optend = p + olen;
1932             switch (code) {
1933             case CI_ADDRS:
1934                 if (olen == CILEN_ADDRS) {
1935                     p += 2;
1936                     GETLONG(cilong, p);
1937                     printer(arg, "addrs %I", htonl(cilong));
1938                     GETLONG(cilong, p);
1939                     printer(arg, " %I", htonl(cilong));
1940                 }
1941                 break;
1942             case CI_COMPRESSTYPE:
1943                 if (olen >= CILEN_COMPRESS) {
1944                     p += 2;
1945                     GETSHORT(cishort, p);
1946                     printer(arg, "compress ");
1947                     switch (cishort) {
1948                     case IPCP_VJ_COMP:
1949                         printer(arg, "VJ");
1950                         break;
1951                     case IPCP_VJ_COMP_OLD:
1952                         printer(arg, "old-VJ");
1953                         break;
1954                     default:
1955                         printer(arg, "0x%x", cishort);
1956                     }
1957                 }
1958                 break;
1959             case CI_ADDR:
1960                 if (olen == CILEN_ADDR) {
1961                     p += 2;
1962                     GETLONG(cilong, p);
1963                     printer(arg, "addr %I", htonl(cilong));
1964                 }
1965                 break;
1966             case CI_MS_DNS1:
1967             case CI_MS_DNS2:
1968                 p += 2;
1969                 GETLONG(cilong, p);
1970                 printer(arg, "ms-dns%d %I", code - CI_MS_DNS1 + 1,
1971                         htonl(cilong));
1972                 break;
1973             case CI_MS_WINS1:
1974             case CI_MS_WINS2:
1975                 p += 2;
1976                 GETLONG(cilong, p);
1977                 printer(arg, "ms-wins %I", htonl(cilong));
1978                 break;
1979             }
1980             while (p < optend) {
1981                 GETCHAR(code, p);
1982                 printer(arg, " %.2x", code);
1983             }
1984             printer(arg, ">");
1985         }
1986         break;
1987
1988     case TERMACK:
1989     case TERMREQ:
1990         if (len > 0 && *p >= ' ' && *p < 0x7f) {
1991             printer(arg, " ");
1992             print_string((char *)p, len, printer, arg);
1993             p += len;
1994             len = 0;
1995         }
1996         break;
1997     }
1998
1999     /* print the rest of the bytes in the packet */
2000     for (; len > 0; --len) {
2001         GETCHAR(code, p);
2002         printer(arg, " %.2x", code);
2003     }
2004
2005     return p - pstart;
2006 }
2007
2008 /*
2009  * ip_active_pkt - see if this IP packet is worth bringing the link up for.
2010  * We don't bring the link up for IP fragments or for TCP FIN packets
2011  * with no data.
2012  */
2013 #define IP_HDRLEN       20      /* bytes */
2014 #define IP_OFFMASK      0x1fff
2015 #define IPPROTO_TCP     6
2016 #define TCP_HDRLEN      20
2017 #define TH_FIN          0x01
2018
2019 /*
2020  * We use these macros because the IP header may be at an odd address,
2021  * and some compilers might use word loads to get th_off or ip_hl.
2022  */
2023
2024 #define net_short(x)    (((x)[0] << 8) + (x)[1])
2025 #define get_iphl(x)     (((unsigned char *)(x))[0] & 0xF)
2026 #define get_ipoff(x)    net_short((unsigned char *)(x) + 6)
2027 #define get_ipproto(x)  (((unsigned char *)(x))[9])
2028 #define get_tcpoff(x)   (((unsigned char *)(x))[12] >> 4)
2029 #define get_tcpflags(x) (((unsigned char *)(x))[13])
2030
2031 static int
2032 ip_active_pkt(pkt, len)
2033     u_char *pkt;
2034     int len;
2035 {
2036     u_char *tcp;
2037     int hlen;
2038
2039     len -= PPP_HDRLEN;
2040     pkt += PPP_HDRLEN;
2041     if (len < IP_HDRLEN)
2042         return 0;
2043     if ((get_ipoff(pkt) & IP_OFFMASK) != 0)
2044         return 0;
2045     if (get_ipproto(pkt) != IPPROTO_TCP)
2046         return 1;
2047     hlen = get_iphl(pkt) * 4;
2048     if (len < hlen + TCP_HDRLEN)
2049         return 0;
2050     tcp = pkt + hlen;
2051     if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4)
2052         return 0;
2053     return 1;
2054 }