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