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