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