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