dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.bin / pppd / ipcp.c
blob118c990a06e3d0a19e3a4f1bda57b09936b4014c
1 /*
2 * ipcp.c - PPP IP Control Protocol.
4 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5 * Use is subject to license terms.
7 * Copyright (c) 1989 Carnegie Mellon University.
8 * All rights reserved.
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.
23 * Copyright (c) 2016 by Delphix. All rights reserved.
26 #define RCSID "$Id: ipcp.c,v 1.54 2000/04/15 01:27:11 masputra Exp $"
29 * TODO:
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>
45 #include "pppd.h"
46 #include "fsm.h"
47 #include "ipcp.h"
48 #include "pathnames.h"
50 static const char rcsid[] = RCSID;
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 */
58 bool ipcp_from_hostname = 0; /* Local IP address is from hostname lookup */
60 /* Hook for a plugin to know when IP protocol has come up */
61 void (*ip_up_hook) __P((void)) = NULL;
63 /* Hook for a plugin to know when IP protocol has come down */
64 void (*ip_down_hook) __P((void)) = NULL;
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 */
74 * Callbacks for fsm code. (CI = Configuration Information)
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 *));
88 fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */
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 */
109 * Command-line options.
111 static int setvjslots __P((char **));
112 static int setdnsaddr __P((char **));
113 static int setwinsaddr __P((char **));
114 static int autoproxyarp __P((char **));
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 }
177 * Protocol entry points from main code.
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 *));
193 static void create_resolv __P((u_int32_t, u_int32_t));
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,
207 "IPCP",
208 "IP",
209 ipcp_option_list,
210 ip_check_options,
211 ip_demand_conf,
212 ip_active_pkt,
213 ipcp_print_stat
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));
221 * Lengths of configuration options.
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 */
231 * This state variable is used to ensure that we don't
232 * run an ipcp-up/down script while one is already running.
234 static enum script_state {
235 s_down,
236 s_up
237 } ipcp_script_state;
238 static pid_t ipcp_script_pid;
241 * Make a string representation of a network IP address.
243 char *
244 ip_ntoa(ipaddr)
245 u_int32_t ipaddr;
247 static char b[64];
249 (void) slprintf(b, sizeof(b), "%I", ipaddr);
250 return b;
254 * Option parsing.
258 * setvjslots - set maximum number of connection slots for VJ compression
260 static int
261 setvjslots(argv)
262 char **argv;
264 int value;
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;
272 ipcp_wantoptions [0].maxslotindex =
273 ipcp_allowoptions[0].maxslotindex = value - 1;
274 return 1;
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.
282 static int
283 setmsservaddr(servname, serverarray)
284 char *servname;
285 u_int32_t *serverarray;
287 u_int32_t addr;
288 struct hostent *hp = NULL;
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));
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.
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;
314 return (1);
318 * setdnsaddr - set the dns address(es)
320 static int
321 setdnsaddr(argv)
322 char **argv;
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);
329 return (1);
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.
337 static int
338 setwinsaddr(argv)
339 char **argv;
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);
347 return (1);
351 * autoproxyarp -- enable proxy ARP but don't emit error messages if
352 * it's not actually needed.
354 /*ARGSUSED*/
355 static int
356 autoproxyarp(argv)
357 char **argv;
359 ipcp_wantoptions[0].proxy_arp = 1;
360 proxy_arp_quiet[0] = 1;
362 return (1);
367 * ipcp_init - Initialize IPCP.
369 static void
370 ipcp_init(unit)
371 int unit;
373 fsm *f = &ipcp_fsm[unit];
374 ipcp_options *wo = &ipcp_wantoptions[unit];
375 ipcp_options *ao = &ipcp_allowoptions[unit];
377 f->unit = unit;
378 f->protocol = PPP_IPCP;
379 f->callbacks = &ipcp_callbacks;
380 fsm_init(&ipcp_fsm[unit]);
382 BZERO(wo, sizeof(*wo));
383 BZERO(ao, sizeof(*ao));
385 wo->neg_addr = wo->old_addrs = 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;
391 ao->neg_addr = ao->old_addrs = 1;
392 ao->neg_vj = 1;
393 ao->maxslotindex = MAX_STATES - 1;
394 ao->cflag = 1;
397 * These aren't actually negotiated. Instead, they control
398 * whether the user may use the proxyarp and defaultroute options.
400 ao->proxy_arp = 1;
401 ao->default_route = 1;
402 proxy_arp_quiet[unit] = 0;
407 * ipcp_open - IPCP is allowed to come up.
409 static void
410 ipcp_open(unit)
411 int unit;
413 fsm_open(&ipcp_fsm[unit]);
418 * ipcp_close - Take IPCP down.
420 static void
421 ipcp_close(unit, reason)
422 int unit;
423 char *reason;
425 fsm_close(&ipcp_fsm[unit], reason);
430 * ipcp_lowerup - The lower layer is up.
432 static void
433 ipcp_lowerup(unit)
434 int unit;
436 fsm_lowerup(&ipcp_fsm[unit]);
441 * ipcp_lowerdown - The lower layer is down.
443 static void
444 ipcp_lowerdown(unit)
445 int unit;
447 fsm_lowerdown(&ipcp_fsm[unit]);
452 * ipcp_input - Input IPCP packet.
454 static void
455 ipcp_input(unit, p, len)
456 int unit;
457 u_char *p;
458 int len;
460 fsm_input(&ipcp_fsm[unit], p, len);
465 * ipcp_protrej - A Protocol-Reject was received for IPCP.
467 static void
468 ipcp_protrej(unit)
469 int unit;
471 fsm_protreject(&ipcp_fsm[unit]);
476 * ipcp_resetci - Reset our CI.
477 * Called by fsm_sconfreq, Send Configure Request.
479 static void
480 ipcp_resetci(f)
481 fsm *f;
483 ipcp_options *wo = &ipcp_wantoptions[f->unit];
484 ipcp_options *go = &ipcp_gotoptions[f->unit];
485 ipcp_options *ao = &ipcp_allowoptions[f->unit];
487 wo->req_addr = (wo->neg_addr || wo->old_addrs) &&
488 (ao->neg_addr || ao->old_addrs);
489 if (wo->ouraddr == 0 || disable_defaultip)
490 wo->accept_local = 1;
491 if (wo->hisaddr == 0)
492 wo->accept_remote = 1;
493 *go = *wo;
494 if (disable_defaultip)
495 go->ouraddr = 0;
500 * ipcp_cilen - Return length of our CI.
501 * Called by fsm_sconfreq, Send Configure Request.
503 static int
504 ipcp_cilen(f)
505 fsm *f;
507 ipcp_options *go = &ipcp_gotoptions[f->unit];
508 ipcp_options *wo = &ipcp_wantoptions[f->unit];
509 ipcp_options *ho = &ipcp_hisoptions[f->unit];
511 #define LENCIADDRS(neg) (neg ? CILEN_ADDRS : 0)
512 #define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0)
513 #define LENCIADDR(neg) (neg ? (CILEN_ADDR) : 0)
516 * First see if we want to change our options to the old
517 * forms because we have received old forms from the peer.
519 if (go->neg_addr && go->old_addrs && !ho->neg_addr && ho->old_addrs)
520 /* use the old style of address negotiation */
521 go->neg_addr = 0;
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;
532 return (LENCIADDRS(!go->neg_addr && go->old_addrs) +
533 LENCIVJ(go->neg_vj, go->old_vj) +
534 LENCIADDR(go->neg_addr) +
535 LENCIADDR(go->req_dns1) +
536 LENCIADDR(go->req_dns2)) ;
541 * ipcp_addci - Add our desired CIs to a packet.
542 * Called by fsm_sconfreq, Send Configure Request.
544 static void
545 ipcp_addci(f, ucp, lenp)
546 fsm *f;
547 u_char *ucp;
548 int *lenp;
550 ipcp_options *go = &ipcp_gotoptions[f->unit];
551 int len = *lenp;
553 #define ADDCIADDRS(opt, neg, val1, val2) \
554 if (neg) { \
555 if (len >= CILEN_ADDRS) { \
556 PUTCHAR(opt, ucp); \
557 PUTCHAR(CILEN_ADDRS, ucp); \
558 PUTNLONG(val1, ucp); \
559 PUTNLONG(val2, ucp); \
560 len -= CILEN_ADDRS; \
561 } else \
562 go->old_addrs = 0; \
565 #define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \
566 if (neg) { \
567 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
568 if (len >= vjlen) { \
569 PUTCHAR(opt, ucp); \
570 PUTCHAR(vjlen, ucp); \
571 PUTSHORT(val, ucp); \
572 if (!old) { \
573 PUTCHAR(maxslotindex, ucp); \
574 PUTCHAR(cflag, ucp); \
576 len -= vjlen; \
577 } else \
578 neg = 0; \
581 #define ADDCIADDR(opt, neg, val) \
582 if (neg) { \
583 if (len >= CILEN_ADDR) { \
584 PUTCHAR(opt, ucp); \
585 PUTCHAR(CILEN_ADDR, ucp); \
586 PUTNLONG(val, ucp); \
587 len -= CILEN_ADDR; \
588 } else \
589 neg = 0; \
592 ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr,
593 go->hisaddr);
595 ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
596 go->maxslotindex, go->cflag);
598 ADDCIADDR(CI_ADDR, go->neg_addr, go->ouraddr);
600 ADDCIADDR(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
602 ADDCIADDR(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
604 *lenp -= len;
609 * ipcp_ackci - Ack our CIs.
610 * Called by fsm_rconfack, Receive Configure ACK.
612 * Returns:
613 * 0 - Ack was bad.
614 * 1 - Ack was good.
616 static int
617 ipcp_ackci(f, p, len)
618 fsm *f;
619 u_char *p;
620 int len;
622 ipcp_options *go = &ipcp_gotoptions[f->unit];
623 u_short cilen, citype, cishort;
624 u_int32_t cilong;
625 u_char cimaxslotindex, cicflag;
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.
633 #define ACKCHECK(opt, olen) \
634 if ((len -= olen) < 0) \
635 goto bad; \
636 GETCHAR(citype, p); \
637 GETCHAR(cilen, p); \
638 if (cilen != olen || \
639 citype != opt) \
640 goto bad;
642 #define ACKCIADDRS(opt, neg, val1, val2) \
643 if (neg) { \
644 ACKCHECK(opt, CILEN_ADDRS) \
645 GETNLONG(cilong, p); \
646 if (val1 != cilong) \
647 goto bad; \
648 GETNLONG(cilong, p); \
649 if (val2 != cilong) \
650 goto bad; \
653 #define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \
654 if (neg) { \
655 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
656 ACKCHECK(opt, vjlen) \
657 GETSHORT(cishort, p); \
658 if (cishort != val) \
659 goto bad; \
660 if (!old) { \
661 GETCHAR(cimaxslotindex, p); \
662 if (cimaxslotindex != maxslotindex) \
663 goto bad; \
664 GETCHAR(cicflag, p); \
665 if (cicflag != cflag) \
666 goto bad; \
670 #define ACKCIADDR(opt, neg, val) \
671 if (neg) { \
672 ACKCHECK(opt, CILEN_ADDR) \
673 GETNLONG(cilong, p); \
674 if (val != cilong) \
675 goto bad; \
678 ACKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr,
679 go->hisaddr);
681 ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
682 go->maxslotindex, go->cflag);
684 ACKCIADDR(CI_ADDR, go->neg_addr, go->ouraddr);
686 ACKCIADDR(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
688 ACKCIADDR(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
691 * If there are any remaining CIs, then this packet is bad.
693 if (len != 0)
694 goto bad;
695 return (1);
697 bad:
698 IPCPDEBUG(("ipcp_ackci: received bad Ack!"));
699 return (0);
703 * ipcp_nakci - Peer has sent a NAK for some of our CIs.
704 * This should not modify any state if the Nak is bad
705 * or if IPCP is in the OPENED state.
706 * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
708 * Returns:
709 * 0 - Nak was bad.
710 * 1 - Nak was good.
712 static int
713 ipcp_nakci(f, p, len)
714 fsm *f;
715 u_char *p;
716 int len;
718 ipcp_options *go = &ipcp_gotoptions[f->unit];
719 u_char cimaxslotindex, cicflag;
720 u_char citype, cilen, *next;
721 u_short cishort;
722 u_int32_t ciaddr1, ciaddr2;
723 ipcp_options no; /* options we've seen Naks for */
724 ipcp_options try; /* options to request next time */
726 BZERO(&no, sizeof(no));
727 try = *go;
730 * Any Nak'd CIs must be in exactly the same order that we sent.
731 * Check packet length and CI length at each step.
732 * If we find any deviations, then this packet is bad.
734 #define NAKCIADDRS(opt, neg, code) \
735 if ((neg) && \
736 (cilen = p[1]) == CILEN_ADDRS && \
737 len >= cilen && \
738 p[0] == opt) { \
739 len -= cilen; \
740 INCPTR(2, p); \
741 GETNLONG(ciaddr1, p); \
742 GETNLONG(ciaddr2, p); \
743 no.old_addrs = 1; \
744 code \
747 #define NAKCIVJ(opt, neg, code) \
748 if (go->neg && \
749 ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \
750 len >= cilen && \
751 p[0] == opt) { \
752 len -= cilen; \
753 INCPTR(2, p); \
754 GETSHORT(cishort, p); \
755 no.neg = 1; \
756 code \
759 #define NAKCIADDR(opt, neg, code) \
760 if (go->neg && \
761 (cilen = p[1]) == CILEN_ADDR && \
762 len >= cilen && \
763 p[0] == opt) { \
764 len -= cilen; \
765 INCPTR(2, p); \
766 GETNLONG(ciaddr1, p); \
767 no.neg = 1; \
768 code \
772 * Accept the peer's idea of {our,its} address, if different
773 * from our idea, only if the accept_{local,remote} flag is set.
775 NAKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs,
776 if (go->accept_local && ciaddr1) { /* Do we know our address? */
777 try.ouraddr = ciaddr1;
779 if (go->accept_remote && ciaddr2) { /* Does it know its? */
780 try.hisaddr = ciaddr2;
785 * Accept the peer's value of maxslotindex provided that it
786 * is less than what we asked for. Turn off slot-ID compression
787 * if the peer wants. Send old-style compress-type option if
788 * the peer wants.
790 NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
791 if (cilen == CILEN_VJ) {
792 GETCHAR(cimaxslotindex, p);
793 GETCHAR(cicflag, p);
794 if (cishort == IPCP_VJ_COMP) {
795 try.old_vj = 0;
796 if (cimaxslotindex < go->maxslotindex)
797 try.maxslotindex = cimaxslotindex;
798 if (!cicflag)
799 try.cflag = 0;
800 } else {
801 try.neg_vj = 0;
803 } else {
804 if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) {
805 try.old_vj = 1;
806 try.vj_protocol = cishort;
807 } else {
808 try.neg_vj = 0;
813 NAKCIADDR(CI_ADDR, neg_addr,
814 if (go->accept_local && ciaddr1) { /* Do we know our address? */
815 try.ouraddr = ciaddr1;
819 NAKCIADDR(CI_MS_DNS1, req_dns1,
820 try.dnsaddr[0] = ciaddr1;
823 NAKCIADDR(CI_MS_DNS2, req_dns2,
824 try.dnsaddr[1] = ciaddr1;
828 * There may be remaining CIs, if the peer is requesting negotiation
829 * on an option that we didn't include in our request packet.
830 * If they want to negotiate about IP addresses, we comply.
831 * If they want us to ask for compression, we refuse.
833 while (len > CILEN_VOID) {
834 GETCHAR(citype, p);
835 GETCHAR(cilen, p);
836 if( (len -= cilen) < 0 )
837 goto bad;
838 next = p + cilen - 2;
840 switch (citype) {
841 case CI_COMPRESSTYPE:
842 if (go->neg_vj || no.neg_vj ||
843 (cilen != CILEN_VJ && cilen != CILEN_COMPRESS))
844 goto bad;
845 no.neg_vj = 1;
846 break;
847 case CI_ADDRS:
848 if ((!go->neg_addr && go->old_addrs) || no.old_addrs
849 || cilen != CILEN_ADDRS)
850 goto bad;
851 try.neg_addr = 1;
852 try.old_addrs = 1;
853 GETNLONG(ciaddr1, p);
854 if (ciaddr1 && go->accept_local)
855 try.ouraddr = ciaddr1;
856 GETNLONG(ciaddr2, p);
857 if (ciaddr2 && go->accept_remote)
858 try.hisaddr = ciaddr2;
859 no.old_addrs = 1;
860 break;
861 case CI_ADDR:
862 if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR)
863 goto bad;
864 try.old_addrs = 0;
865 GETNLONG(ciaddr1, p);
866 if (ciaddr1 && go->accept_local)
867 try.ouraddr = ciaddr1;
868 if (try.ouraddr != 0)
869 try.neg_addr = 1;
870 no.neg_addr = 1;
871 break;
873 p = next;
877 * OK, the Nak is good. Now we can update state.
878 * If there are any remaining options, we ignore them.
880 if (f->state != OPENED)
881 *go = try;
883 return 1;
885 bad:
886 IPCPDEBUG(("ipcp_nakci: received bad Nak!"));
887 return 0;
892 * ipcp_rejci - Reject some of our CIs.
893 * Callback from fsm_rconfnakrej.
895 static int
896 ipcp_rejci(f, p, len)
897 fsm *f;
898 u_char *p;
899 int len;
901 ipcp_options *go = &ipcp_gotoptions[f->unit];
902 u_char cimaxslotindex, ciflag, cilen;
903 u_short cishort;
904 u_int32_t cilong;
905 ipcp_options try; /* options to request next time */
907 try = *go;
909 * Any Rejected CIs must be in exactly the same order that we sent.
910 * Check packet length and CI length at each step.
911 * If we find any deviations, then this packet is bad.
913 #define REJCIADDRS(opt, neg, val1, val2) \
914 if ((neg) && \
915 (cilen = p[1]) == CILEN_ADDRS && \
916 len >= cilen && \
917 p[0] == opt) { \
918 len -= cilen; \
919 INCPTR(2, p); \
920 GETNLONG(cilong, p); \
921 /* Check rejected value. */ \
922 if (cilong != val1) \
923 goto bad; \
924 GETNLONG(cilong, p); \
925 /* Check rejected value. */ \
926 if (cilong != val2) \
927 goto bad; \
928 try.old_addrs = 0; \
931 #define REJCIVJ(opt, neg, val, old, maxslot, cflag) \
932 if (go->neg && \
933 p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \
934 len >= p[1] && \
935 p[0] == opt) { \
936 len -= p[1]; \
937 INCPTR(2, p); \
938 GETSHORT(cishort, p); \
939 /* Check rejected value. */ \
940 if (cishort != val) \
941 goto bad; \
942 if (!old) { \
943 GETCHAR(cimaxslotindex, p); \
944 if (cimaxslotindex != maxslot) \
945 goto bad; \
946 GETCHAR(ciflag, p); \
947 if (ciflag != cflag) \
948 goto bad; \
950 try.neg = 0; \
953 #define REJCIADDR(opt, neg, addr) \
954 if (go->neg && \
955 ((cilen = p[1]) == CILEN_ADDR) && \
956 len >= cilen && \
957 p[0] == opt) { \
958 len -= cilen; \
959 INCPTR(2, p); \
960 GETNLONG(cilong, p); \
961 /* Check rejected value. */ \
962 if (cilong != addr) \
963 goto bad; \
964 try.neg = 0; \
967 REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs,
968 go->ouraddr, go->hisaddr);
970 REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj,
971 go->maxslotindex, go->cflag);
973 REJCIADDR(CI_ADDR, neg_addr, go->ouraddr);
975 REJCIADDR(CI_MS_DNS1, req_dns1, go->dnsaddr[0]);
977 REJCIADDR(CI_MS_DNS2, req_dns2, go->dnsaddr[1]);
980 * If there are any remaining CIs, then this packet is bad.
982 if (len != 0)
983 goto bad;
985 * Now we can update state.
987 if (f->state != OPENED)
988 *go = try;
989 return 1;
991 bad:
992 IPCPDEBUG(("ipcp_rejci: received bad Reject!"));
993 return 0;
998 * ipcp_reqci - Check the peer's requested CIs and send appropriate response.
999 * Callback from fsm_rconfreq, Receive Configure Request
1001 * Returns: CODE_CONFACK, CODE_CONFNAK or CODE_CONFREJ and input
1002 * packet modified appropriately. If reject_if_disagree is non-zero,
1003 * doesn't return CODE_CONFNAK; returns CODE_CONFREJ if it can't
1004 * return CODE_CONFACK.
1006 static int
1007 ipcp_reqci(f, p, lenp, dont_nak)
1008 fsm *f;
1009 u_char *p; /* Requested CIs */
1010 int *lenp; /* Length of requested CIs */
1011 bool dont_nak;
1013 ipcp_options *wo = &ipcp_wantoptions[f->unit];
1014 ipcp_options *ho = &ipcp_hisoptions[f->unit];
1015 ipcp_options *ao = &ipcp_allowoptions[f->unit];
1016 ipcp_options *go = &ipcp_gotoptions[f->unit];
1017 int ret, newret;
1018 u_char *p0, *nakp, *rejp, *prev;
1019 u_short cishort;
1020 int len, cilen, type;
1021 u_int32_t tl, ciaddr1, ciaddr2; /* Parsed address values */
1022 u_char maxslotindex, cflag;
1023 int d;
1025 ret = CODE_CONFACK;
1026 rejp = p0 = p;
1027 nakp = nak_buffer;
1030 * Reset all its options.
1032 BZERO(ho, sizeof(*ho));
1035 * Process all its options.
1037 for (len = *lenp; len > 0; len -= cilen, p = prev + cilen) {
1038 if ((len < 2) || p[1] > len) {
1040 * RFC 1661 page 40 -- if the option extends beyond the
1041 * packet, then discard the entire packet.
1043 return (0);
1046 newret = CODE_CONFACK;
1047 prev = p;
1048 GETCHAR(type, p);
1049 GETCHAR(cilen, p);
1051 switch (type) { /* Check CI type */
1052 case CI_ADDRS:
1053 if (!ao->old_addrs || ho->neg_addr) {
1054 newret = CODE_CONFREJ;
1055 break;
1058 if (cilen != CILEN_ADDRS) {
1060 * rfc1661, page 40 -- a recongnized option with an
1061 * invalid length should be Nak'ed.
1063 newret = CODE_CONFNAK;
1064 ciaddr1 = wo->hisaddr;
1065 ciaddr2 = wo->ouraddr;
1066 } else {
1069 * If it has no address, or if we both have its
1070 * address but disagree about it, then NAK it with our
1071 * idea. In particular, if we don't know its address,
1072 * but it does, then accept it.
1074 GETNLONG(ciaddr1, p);
1075 if (ciaddr1 != wo->hisaddr &&
1076 (ciaddr1 == 0 || !wo->accept_remote)) {
1077 newret = CODE_CONFNAK;
1078 ciaddr1 = wo->hisaddr;
1079 } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
1081 * If neither we nor he knows his address, reject
1082 * the option.
1084 newret = CODE_CONFREJ;
1085 wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */
1086 break;
1087 } else if (ciaddr1 != 0) {
1088 go->hisaddr = ciaddr1;
1092 * If he doesn't know our address, or if we both have
1093 * our address * but disagree about it, then NAK it
1094 * with our idea.
1096 GETNLONG(ciaddr2, p);
1097 if (ciaddr2 != wo->ouraddr) {
1098 if (ciaddr2 == 0 || !wo->accept_local) {
1099 newret = CODE_CONFNAK;
1100 ciaddr2 = wo->ouraddr;
1101 } else {
1102 go->ouraddr = ciaddr2; /* accept peer's idea */
1107 if (newret == CODE_CONFNAK) {
1108 PUTCHAR(type, nakp);
1109 PUTCHAR(CILEN_ADDRS, nakp);
1110 PUTNLONG(ciaddr1, nakp);
1111 PUTNLONG(ciaddr2, nakp);
1114 ho->old_addrs = 1;
1115 ho->hisaddr = ciaddr1;
1116 ho->ouraddr = ciaddr2;
1117 break;
1119 case CI_ADDR:
1120 if (!ao->neg_addr || ho->old_addrs) {
1121 newret = CODE_CONFREJ;
1122 break;
1125 if (cilen != CILEN_ADDR) {
1127 * rfc1661, page 40 -- a recongnized option with an
1128 * invalid length should be Nak'ed.
1130 newret = CODE_CONFNAK;
1131 ciaddr1 = wo->hisaddr;
1132 } else {
1135 * If he has no address, or if we both have his
1136 * address but disagree about it, then NAK it with our
1137 * idea. In particular, if we don't know his address,
1138 * but he does, then accept it.
1140 GETNLONG(ciaddr1, p);
1141 if (ciaddr1 != wo->hisaddr &&
1142 (ciaddr1 == 0 || !wo->accept_remote)) {
1143 newret = CODE_CONFNAK;
1144 ciaddr1 = wo->hisaddr;
1145 } else if (ciaddr1 == 0 && wo->hisaddr == 0 &&
1146 wo->default_route != 0) {
1147 newret = CODE_CONFNAK;
1149 * If this is a dialup line (default_route is
1150 * set), and neither side knows about its address,
1151 * suggest an arbitrary rfc1918 address.
1153 ciaddr1 = htonl(0xc0a80101 + ifunit);
1154 dbglog("Peer address unknown; suggesting %I", ciaddr1);
1155 } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
1157 * If this is not a dialup line, don't ACK an
1158 * address of 0.0.0.0 - reject it instead.
1160 newret = CODE_CONFREJ;
1161 wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */
1162 break;
1166 if (newret == CODE_CONFNAK) {
1167 PUTCHAR(type, nakp);
1168 PUTCHAR(CILEN_ADDR, nakp);
1169 PUTNLONG(ciaddr1, nakp);
1172 ho->neg_addr = 1;
1173 ho->hisaddr = ciaddr1;
1174 break;
1176 case CI_MS_DNS1:
1177 case CI_MS_DNS2:
1178 /* Warning -- these options work backwards. */
1179 /* Microsoft primary or secondary DNS request */
1180 d = (type == CI_MS_DNS2 ? 1 : 0);
1182 if (ao->dnsaddr[d] == 0) {
1183 newret = CODE_CONFREJ;
1184 break;
1187 if (cilen != CILEN_ADDR) {
1188 newret = CODE_CONFNAK;
1189 } else {
1190 GETNLONG(tl, p);
1191 if (tl != ao->dnsaddr[d]) {
1192 newret = CODE_CONFNAK;
1196 if (newret == CODE_CONFNAK) {
1197 PUTCHAR(type, nakp);
1198 PUTCHAR(CILEN_ADDR, nakp);
1199 PUTNLONG(ao->dnsaddr[d], nakp);
1201 break;
1203 case CI_MS_WINS1:
1204 case CI_MS_WINS2:
1205 /* Warning -- these options work backwards. */
1206 /* Microsoft primary or secondary WINS request */
1207 d = (type == CI_MS_WINS2 ? 1 : 0);
1209 if (ao->winsaddr[d] == 0) {
1210 newret = CODE_CONFREJ;
1211 break;
1214 if (cilen != CILEN_ADDR) {
1215 newret = CODE_CONFNAK;
1216 } else {
1217 GETNLONG(tl, p);
1218 if (tl != ao->winsaddr[d]) {
1219 newret = CODE_CONFNAK;
1223 if (newret == CODE_CONFNAK) {
1224 PUTCHAR(type, nakp);
1225 PUTCHAR(CILEN_ADDR, nakp);
1226 PUTNLONG(ao->winsaddr[d], nakp);
1228 break;
1230 case CI_COMPRESSTYPE:
1231 if (!ao->neg_vj) {
1232 newret = CODE_CONFREJ;
1233 break;
1236 maxslotindex = ao->maxslotindex;
1237 cflag = ao->cflag;
1238 if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) {
1239 newret = CODE_CONFNAK;
1240 cishort = IPCP_VJ_COMP;
1241 } else {
1242 GETSHORT(cishort, p);
1243 if (cishort != IPCP_VJ_COMP &&
1244 (cishort != IPCP_VJ_COMP_OLD || cilen != CILEN_COMPRESS)) {
1245 newret = CODE_CONFNAK;
1246 cishort = IPCP_VJ_COMP;
1247 } else if (cilen == CILEN_VJ) {
1248 GETCHAR(maxslotindex, p);
1249 if (maxslotindex > ao->maxslotindex) {
1250 newret = CODE_CONFNAK;
1251 maxslotindex = ao->maxslotindex;
1253 GETCHAR(cflag, p);
1254 if (cflag != 0 && ao->cflag == 0) {
1255 newret = CODE_CONFNAK;
1256 cflag = 0;
1258 } else {
1259 ho->old_vj = 1;
1260 maxslotindex = MAX_STATES - 1;
1261 cflag = 1;
1265 if (newret == CODE_CONFNAK) {
1266 PUTCHAR(type, nakp);
1267 if (cishort == IPCP_VJ_COMP) {
1268 PUTCHAR(CILEN_VJ, nakp);
1269 PUTSHORT(cishort, nakp);
1270 PUTCHAR(maxslotindex, nakp);
1271 PUTCHAR(cflag, nakp);
1272 } else {
1273 PUTCHAR(CILEN_COMPRESS, nakp);
1274 PUTSHORT(cishort, nakp);
1277 ho->neg_vj = 1;
1278 ho->vj_protocol = cishort;
1279 ho->maxslotindex = maxslotindex;
1280 ho->cflag = cflag;
1281 break;
1283 default:
1284 newret = CODE_CONFREJ;
1285 break;
1288 /* Cope with confused peers. */
1289 if (cilen < 2)
1290 cilen = 2;
1293 * If this is an Ack'able CI, but we're sending back a Nak,
1294 * don't include this CI.
1296 if (newret == CODE_CONFACK && ret != CODE_CONFACK)
1297 continue;
1299 if (newret == CODE_CONFNAK) {
1300 if (dont_nak) {
1301 newret = CODE_CONFREJ;
1302 } else {
1303 /* Ignore subsequent Nak'able things if rejecting. */
1304 if (ret == CODE_CONFREJ)
1305 continue;
1306 ret = CODE_CONFNAK;
1310 if (newret == CODE_CONFREJ) {
1311 ret = CODE_CONFREJ;
1312 if (prev != rejp)
1313 BCOPY(prev, rejp, cilen);
1314 rejp += cilen;
1319 * If we aren't rejecting this packet, and we want to negotiate
1320 * their address, and they didn't send their address, then we
1321 * send a NAK with a CI_ADDR option appended. We assume the
1322 * input buffer is long enough that we can append the extra
1323 * option safely.
1325 if (ret != CODE_CONFREJ && !ho->neg_addr && !ho->old_addrs &&
1326 wo->req_addr && !dont_nak) {
1327 if (ret == CODE_CONFACK)
1328 wo->req_addr = 0; /* don't ask again */
1329 ret = CODE_CONFNAK;
1330 PUTCHAR(CI_ADDR, nakp);
1331 PUTCHAR(CILEN_ADDR, nakp);
1332 PUTNLONG(wo->hisaddr, nakp);
1335 switch (ret) {
1336 case CODE_CONFACK:
1337 *lenp = p - p0;
1338 sys_block_proto(PPP_IP);
1339 break;
1340 case CODE_CONFNAK:
1341 *lenp = nakp - nak_buffer;
1342 BCOPY(nak_buffer, p0, *lenp);
1343 break;
1344 case CODE_CONFREJ:
1345 *lenp = rejp - p0;
1346 break;
1349 return (ret); /* Return final code */
1354 * ip_check_options - check that any IP-related options are OK,
1355 * and assign appropriate defaults.
1357 static void
1358 ip_check_options()
1360 struct hostent *hp;
1361 u_int32_t local;
1362 ipcp_options *wo = &ipcp_wantoptions[0];
1365 * Default our local IP address based on our hostname.
1366 * If local IP address already given, don't bother.
1368 if (wo->ouraddr == 0) {
1370 * Look up our hostname (possibly with domain name appended)
1371 * and take the first IP address as our local IP address.
1372 * If there isn't an IP address for our hostname, too bad.
1374 wo->accept_local = 1; /* don't insist on this default value */
1375 if ((hp = gethostbyname(hostname)) != NULL) {
1376 BCOPY(hp->h_addr, &local, sizeof (hp->h_addr));
1377 if (local != 0 && !bad_ip_adrs(local)) {
1378 wo->ouraddr = local;
1379 ipcp_from_hostname = 1;
1387 * ip_demand_conf - configure the interface as though
1388 * IPCP were up, for use with dial-on-demand.
1390 static int
1391 ip_demand_conf(u)
1392 int u;
1394 ipcp_options *wo = &ipcp_wantoptions[u];
1396 if (wo->hisaddr == 0) {
1397 /* make up an arbitrary address for the peer */
1398 wo->hisaddr = htonl(0x0a707070 + ifunit);
1399 wo->accept_remote = 1;
1401 if (wo->ouraddr == 0) {
1402 /* make up an arbitrary address for us */
1403 wo->ouraddr = htonl(0x0a404040 + ifunit);
1404 wo->accept_local = 1;
1405 disable_defaultip = 1; /* don't tell the peer this address */
1407 if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr)))
1408 return 0;
1409 if (!sifup(u))
1410 return 0;
1411 if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
1412 return 0;
1413 if (wo->default_route && sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
1414 default_route_set[u] = 1;
1415 if (wo->proxy_arp && sifproxyarp(u, wo->hisaddr, proxy_arp_quiet[u]))
1416 proxy_arp_set[u] = 1;
1418 notice("local IP address %I", wo->ouraddr);
1419 notice("remote IP address %I", wo->hisaddr);
1421 return 1;
1426 * ipcp_up - IPCP has come UP.
1428 * Configure the IP network interface appropriately and bring it up.
1430 static void
1431 ipcp_up(f)
1432 fsm *f;
1434 u_int32_t mask;
1435 ipcp_options *ho = &ipcp_hisoptions[f->unit];
1436 ipcp_options *go = &ipcp_gotoptions[f->unit];
1437 ipcp_options *wo = &ipcp_wantoptions[f->unit];
1439 IPCPDEBUG(("ipcp: up"));
1442 * We must have a non-zero IP address for both ends of the link.
1444 if (ho->hisaddr == 0)
1445 ho->hisaddr = wo->hisaddr;
1447 if (ho->hisaddr == 0) {
1448 if (wo->accept_remote) {
1449 /* Pick some rfc1918 address. */
1450 ho->hisaddr = htonl(0xc0a80101 + ifunit);
1451 dbglog("Peer refused to provide his address; assuming %I",
1452 ho->hisaddr);
1453 } else {
1454 error("Could not determine remote IP address");
1455 ipcp_close(f->unit, "Could not determine remote IP address");
1456 return;
1459 if (go->ouraddr == 0) {
1460 error("Could not determine local IP address");
1461 ipcp_close(f->unit, "Could not determine local IP address");
1462 return;
1464 script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0);
1465 script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1);
1468 * Check that the peer is allowed to use the IP address it wants.
1470 if (!auth_ip_addr(f->unit, ho->hisaddr)) {
1471 error("Peer is not authorized to use remote address %I", ho->hisaddr);
1472 ipcp_close(f->unit, "Unauthorized remote IP address");
1473 return;
1476 if ((go->req_dns1 && go->dnsaddr[0] != 0) ||
1477 (go->req_dns2 && go->dnsaddr[1] != 0)) {
1478 script_setenv("USEPEERDNS", "1", 0);
1479 if (go->dnsaddr[0] != 0)
1480 script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0);
1481 if (go->dnsaddr[1] != 0)
1482 script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0);
1483 create_resolv(go->dnsaddr[0], go->dnsaddr[1]);
1486 /* set tcp compression */
1487 if (sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex) != 1) {
1488 ipcp_close(f->unit, "Could not enable VJ TCP header compression");
1489 return;
1493 * If we are doing dial-on-demand, the interface is already
1494 * configured, so we put out any saved-up packets, then set the
1495 * interface to pass IP packets.
1497 if (demand) {
1498 if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
1499 ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr);
1500 if (go->ouraddr != wo->ouraddr) {
1501 warn("Local IP address changed to %I", go->ouraddr);
1502 script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0);
1503 wo->ouraddr = go->ouraddr;
1504 } else
1505 script_unsetenv("OLDIPLOCAL");
1506 if (ho->hisaddr != wo->hisaddr) {
1507 warn("Remote IP address changed to %I", ho->hisaddr);
1508 script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0);
1509 wo->hisaddr = ho->hisaddr;
1510 } else
1511 script_unsetenv("OLDIPREMOTE");
1513 /* Set the interface to the new addresses */
1514 mask = GetMask(go->ouraddr);
1515 if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1516 warn("Interface configuration failed");
1517 ipcp_close(f->unit, "Interface configuration failed");
1518 return;
1521 /* assign a default route through the interface if required */
1522 if (wo->default_route)
1523 if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
1524 default_route_set[f->unit] = 1;
1526 /* Make a proxy ARP entry if requested. */
1527 if (wo->proxy_arp &&
1528 sifproxyarp(f->unit, ho->hisaddr, proxy_arp_quiet[f->unit]))
1529 proxy_arp_set[f->unit] = 1;
1532 demand_rexmit(PPP_IP);
1533 if (sifnpmode(f->unit, PPP_IP, NPMODE_PASS) != 1) {
1534 ipcp_close(f->unit, "Interface configuration failed.");
1535 return;
1538 } else {
1540 * Set IP addresses and (if specified) netmask.
1542 mask = GetMask(go->ouraddr);
1544 #if SIFUPFIRST
1545 /* bring the interface up for IP */
1546 if (!sifup(f->unit)) {
1547 warn("Interface failed to come up");
1548 ipcp_close(f->unit, "Interface configuration failed");
1549 return;
1551 #endif
1553 if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1554 warn("Interface configuration failed");
1555 ipcp_close(f->unit, "Interface configuration failed");
1556 return;
1559 #if !SIFUPFIRST
1560 /* bring the interface up for IP */
1561 if (!sifup(f->unit)) {
1562 warn("Interface failed to come up");
1563 ipcp_close(f->unit, "Interface configuration failed");
1564 return;
1566 #endif
1568 if (sifnpmode(f->unit, PPP_IP, NPMODE_PASS) != 1) {
1569 ipcp_close(f->unit, "Interface configuration failed.");
1570 return;
1573 /* assign a default route through the interface if required */
1574 if (wo->default_route)
1575 if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
1576 default_route_set[f->unit] = 1;
1578 /* Make a proxy ARP entry if requested. */
1579 if (wo->proxy_arp &&
1580 sifproxyarp(f->unit, ho->hisaddr, proxy_arp_quiet[f->unit]))
1581 proxy_arp_set[f->unit] = 1;
1583 wo->ouraddr = go->ouraddr;
1585 notice("local IP address %I", go->ouraddr);
1586 notice("remote IP address %I", ho->hisaddr);
1587 if (go->dnsaddr[0] != 0)
1588 notice("primary DNS address %I", go->dnsaddr[0]);
1589 if (go->dnsaddr[1] != 0)
1590 notice("secondary DNS address %I", go->dnsaddr[1]);
1593 np_up(f->unit, PPP_IP);
1594 ipcp_is_up[f->unit] = 1;
1596 if (ip_up_hook != NULL)
1597 (*ip_up_hook)();
1600 * Execute the ip-up script, like this:
1601 * /etc/ppp/ip-up interface tty speed local-IP remote-IP
1603 if (ipcp_script_state == s_down && ipcp_script_pid == 0) {
1604 ipcp_script_state = s_up;
1605 ipcp_script(_PATH_IPUP);
1607 sys_unblock_proto(PPP_IP);
1612 * ipcp_down - IPCP has gone DOWN.
1614 * Take the IP network interface down, clear its addresses
1615 * and delete routes through it.
1617 static void
1618 ipcp_down(f)
1619 fsm *f;
1621 IPCPDEBUG(("ipcp: down"));
1622 /* XXX a bit IPv4-centric here, we only need to get the stats
1623 * before the interface is marked down. */
1624 update_link_stats(f->unit);
1625 if (ip_down_hook != NULL)
1626 (*ip_down_hook)();
1627 if (ipcp_is_up[f->unit]) {
1628 ipcp_is_up[f->unit] = 0;
1629 np_down(f->unit, PPP_IP);
1631 if (sifvjcomp(f->unit, 0, 0, 0) != 1) {
1632 if (debug)
1633 warn("Failed to disable VJ TCP header compression.");
1637 * If we are doing dial-on-demand, set the interface
1638 * to queue up outgoing packets (for now).
1640 if (demand) {
1641 if (sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE) != 1) {
1642 if (debug)
1643 warn("Failed to enable Queueing on outgoing packets.");
1645 } else {
1646 if (sifnpmode(f->unit, PPP_IP, NPMODE_ERROR) != 1) {
1647 if (debug)
1648 warn("Could not set interface to drop packets.");
1650 if (sifdown(f->unit) != 1)
1651 warn("Could not bring interface down.");
1652 ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr,
1653 ipcp_hisoptions[f->unit].hisaddr);
1656 /* Execute the ip-down script */
1657 if (ipcp_script_state == s_up && ipcp_script_pid == 0) {
1658 ipcp_script_state = s_down;
1659 ipcp_script(_PATH_IPDOWN);
1665 * ipcp_clear_addrs() - clear the interface addresses, routes,
1666 * proxy arp entries, etc.
1668 static void
1669 ipcp_clear_addrs(unit, ouraddr, hisaddr)
1670 int unit;
1671 u_int32_t ouraddr; /* local address */
1672 u_int32_t hisaddr; /* remote address */
1674 if (proxy_arp_set[unit]) {
1675 (void) cifproxyarp(unit, hisaddr);
1676 proxy_arp_set[unit] = 0;
1678 if (default_route_set[unit]) {
1679 (void) cifdefaultroute(unit, ouraddr, hisaddr);
1680 default_route_set[unit] = 0;
1682 if (cifaddr(unit, ouraddr, hisaddr) != 1)
1683 warn("Could not clear addresses");
1688 * ipcp_finished - possibly shut down the lower layers.
1690 static void
1691 ipcp_finished(f)
1692 fsm *f;
1694 np_finished(f->unit, PPP_IP);
1699 * ipcp_script_done - called when the ip-up or ip-down script
1700 * has finished.
1702 /*ARGSUSED*/
1703 static void
1704 ipcp_script_done(arg, status)
1705 void *arg;
1706 int status;
1708 ipcp_script_pid = 0;
1709 switch (ipcp_script_state) {
1710 case s_up:
1711 if (ipcp_fsm[0].state != OPENED) {
1712 ipcp_script_state = s_down;
1713 ipcp_script(_PATH_IPDOWN);
1715 break;
1716 case s_down:
1717 if (ipcp_fsm[0].state == OPENED) {
1718 ipcp_script_state = s_up;
1719 ipcp_script(_PATH_IPUP);
1721 break;
1727 * ipcp_script - Execute a script with arguments
1728 * interface-name tty-name speed local-IP remote-IP.
1730 static void
1731 ipcp_script(script)
1732 char *script;
1734 char strspeed[32], strlocal[32], strremote[32];
1735 char *argv[8];
1737 (void) slprintf(strspeed, sizeof(strspeed), "%d", baud_rate);
1738 (void) slprintf(strlocal, sizeof(strlocal), "%I",
1739 ipcp_gotoptions[0].ouraddr);
1740 (void) slprintf(strremote, sizeof(strremote), "%I",
1741 ipcp_hisoptions[0].hisaddr);
1743 argv[0] = script;
1744 argv[1] = ifname;
1745 argv[2] = devnam;
1746 argv[3] = strspeed;
1747 argv[4] = strlocal;
1748 argv[5] = strremote;
1749 argv[6] = ipparam;
1750 argv[7] = NULL;
1751 ipcp_script_pid = run_program(script, argv, 0, ipcp_script_done, NULL);
1755 * create_resolv - create the replacement resolv.conf file
1757 static void
1758 create_resolv(peerdns1, peerdns2)
1759 u_int32_t peerdns1, peerdns2;
1761 FILE *f;
1763 f = fopen(_PATH_RESOLV, "w");
1764 if (f == NULL) {
1765 error("Failed to create %s: %m", _PATH_RESOLV);
1766 return;
1769 if (peerdns1)
1770 if (fprintf(f, "nameserver %s\n", ip_ntoa(peerdns1)) <= 0)
1771 error("Write failed to %s: %m", _PATH_RESOLV);
1773 if (peerdns2)
1774 if (fprintf(f, "nameserver %s\n", ip_ntoa(peerdns2)) <= 0)
1775 error("Write failed to %s: %m", _PATH_RESOLV);
1777 if (fclose(f) != 0)
1778 error("Failed to close %s: %m", _PATH_RESOLV);
1782 * ipcp_printpkt - print the contents of an IPCP packet.
1784 static int
1785 ipcp_printpkt(p, plen, printer, arg)
1786 u_char *p;
1787 int plen;
1788 void (*printer) __P((void *, const char *, ...));
1789 void *arg;
1791 int code, id, len, olen;
1792 u_char *pstart, *optend;
1793 u_short cishort;
1794 u_int32_t cilong;
1796 if (plen < HEADERLEN)
1797 return 0;
1798 pstart = p;
1799 GETCHAR(code, p);
1800 GETCHAR(id, p);
1801 GETSHORT(len, p);
1802 if (len < HEADERLEN || len > plen)
1803 return 0;
1805 printer(arg, " %s id=0x%x", code_name(code, 1), id);
1806 len -= HEADERLEN;
1807 switch (code) {
1808 case CODE_CONFREQ:
1809 case CODE_CONFACK:
1810 case CODE_CONFNAK:
1811 case CODE_CONFREJ:
1812 /* print option list */
1813 while (len >= 2) {
1814 GETCHAR(code, p);
1815 GETCHAR(olen, p);
1816 p -= 2;
1817 if (olen < 2 || olen > len) {
1818 break;
1820 printer(arg, " <");
1821 len -= olen;
1822 optend = p + olen;
1823 switch (code) {
1824 case CI_ADDRS:
1825 if (olen == CILEN_ADDRS) {
1826 p += 2;
1827 GETNLONG(cilong, p);
1828 printer(arg, "addrs %I", cilong);
1829 GETNLONG(cilong, p);
1830 printer(arg, " %I", cilong);
1832 break;
1833 case CI_COMPRESSTYPE:
1834 if (olen >= CILEN_COMPRESS) {
1835 p += 2;
1836 GETSHORT(cishort, p);
1837 printer(arg, "compress ");
1838 switch (cishort) {
1839 case IPCP_VJ_COMP:
1840 printer(arg, "VJ");
1841 break;
1842 case IPCP_VJ_COMP_OLD:
1843 printer(arg, "old-VJ");
1844 break;
1845 default:
1846 printer(arg, "0x%x", cishort);
1849 break;
1850 case CI_ADDR:
1851 if (olen == CILEN_ADDR) {
1852 p += 2;
1853 GETNLONG(cilong, p);
1854 printer(arg, "addr %I", cilong);
1856 break;
1857 case CI_MS_DNS1:
1858 case CI_MS_DNS2:
1859 p += 2;
1860 GETNLONG(cilong, p);
1861 printer(arg, "ms-dns%d %I", (code == CI_MS_DNS1 ? 1 : 2),
1862 cilong);
1863 break;
1864 case CI_MS_WINS1:
1865 case CI_MS_WINS2:
1866 p += 2;
1867 GETNLONG(cilong, p);
1868 printer(arg, "ms-wins%d %I", (code == CI_MS_WINS1 ? 1 : 2),
1869 cilong);
1870 break;
1871 case CI_SUBNET:
1872 p += 2;
1873 GETNLONG(cilong, p);
1874 printer(arg, "subnet %I", cilong);
1875 break;
1877 while (p < optend) {
1878 GETCHAR(code, p);
1879 printer(arg, " %.2x", code);
1881 printer(arg, ">");
1883 break;
1885 case CODE_TERMACK:
1886 case CODE_TERMREQ:
1887 if (len > 0 && *p >= ' ' && *p < 0x7f) {
1888 printer(arg, " ");
1889 print_string((char *)p, len, printer, arg);
1890 p += len;
1891 len = 0;
1893 break;
1896 /* print the rest of the bytes in the packet */
1897 for (; len > 0; --len) {
1898 GETCHAR(code, p);
1899 printer(arg, " %.2x", code);
1902 return p - pstart;
1905 char *
1906 tcp_flag_decode(val)
1907 int val;
1909 static char buf[32];
1910 char *cp = buf;
1912 if (val & TH_URG)
1913 *cp++ = 'U';
1914 if (val & TH_ACK)
1915 *cp++ = 'A';
1916 if (val & TH_PUSH)
1917 *cp++ = 'P';
1918 if (val & TH_RST)
1919 *cp++ = 'R';
1920 if (val & TH_SYN)
1921 *cp++ = 'S';
1922 if (val & TH_FIN)
1923 *cp++ = 'F';
1924 if (cp != buf)
1925 *cp++ = ' ';
1926 *cp = '\0';
1927 return buf;
1931 * ip_active_pkt - see if this IP packet is worth bringing the link up for.
1932 * We don't bring the link up for IP fragments or for TCP FIN packets
1933 * with no data.
1936 static int
1937 ip_active_pkt(pkt, len)
1938 u_char *pkt;
1939 int len;
1941 u_char *tcp;
1942 struct protoent *pep;
1943 int val;
1944 int hlen;
1945 char buf[32], *cp;
1946 u_int32_t src, dst;
1948 len -= PPP_HDRLEN;
1949 pkt += PPP_HDRLEN;
1950 if (len < IP_HDRLEN) {
1951 dbglog("IP packet of length %d is not activity", len);
1952 return 0;
1954 src = get_ipsrc(pkt);
1955 dst = get_ipdst(pkt);
1956 if ((get_ipoff(pkt) & IP_OFFMASK) != 0) {
1957 dbglog("IP fragment from %I->%I is not activity", src, dst);
1958 return 0;
1960 val = get_ipproto(pkt);
1961 if (val != IPPROTO_TCP) {
1962 if (debug) {
1963 if ((pep = getprotobynumber(val)) != NULL) {
1964 cp = pep->p_name;
1965 } else {
1966 (void) slprintf(buf, sizeof (buf), "IP proto %d", val);
1967 cp = buf;
1969 info("%s from %I->%I is activity", cp, src, dst);
1971 return 1;
1973 hlen = get_iphl(pkt) * 4;
1974 if (len < hlen + TCP_HDRLEN) {
1975 dbglog("Bad TCP length %d<%d+%d %I->%I is not activity", len, hlen,
1976 TCP_HDRLEN, src, dst);
1977 return 0;
1979 tcp = pkt + hlen;
1980 val = get_tcpflags(tcp);
1981 hlen += get_tcpoff(tcp) * 4;
1982 if ((val & TH_FIN) != 0 && len == hlen) {
1983 dbglog("Empty TCP FIN %I->%I is not activity", src, dst);
1984 return 0;
1986 info("TCP %d data %s%I->%I is activity", len - hlen,
1987 tcp_flag_decode(get_tcpflags(tcp)), src, dst);
1988 return 1;
1991 static void
1992 ipcp_print_stat(unit, strptr)
1993 int unit;
1994 FILE *strptr;
1996 ipcp_options *go = &ipcp_gotoptions[unit];
1997 ipcp_options *ho = &ipcp_hisoptions[unit];
1998 char *proto_name = ipcp_protent.name;
2000 if (!ipcp_protent.enabled_flag) {
2001 (void) flprintf(strptr, "%s disabled\n", proto_name);
2002 return;
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);