8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.bin / pppd / ipcp.c
blob897df4316007a685a11c6e8d1396bdfbb5705ccd
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 #if !defined(lint) && !defined(_lint)
51 static const char rcsid[] = RCSID;
52 #endif
54 /* global vars */
55 ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */
56 ipcp_options ipcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
57 ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
58 ipcp_options ipcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
60 bool ipcp_from_hostname = 0; /* Local IP address is from hostname lookup */
62 /* Hook for a plugin to know when IP protocol has come up */
63 void (*ip_up_hook) __P((void)) = NULL;
65 /* Hook for a plugin to know when IP protocol has come down */
66 void (*ip_down_hook) __P((void)) = NULL;
68 /* local vars */
69 static bool default_route_set[NUM_PPP]; /* Have set up a default route */
70 static bool proxy_arp_set[NUM_PPP]; /* Have created proxy arp entry */
71 static bool ipcp_is_up[NUM_PPP]; /* have called np_up() */
72 static bool proxy_arp_quiet[NUM_PPP]; /* We should be quiet on error */
73 static bool disable_defaultip = 0; /* Don't use hostname for IP addr */
76 * Callbacks for fsm code. (CI = Configuration Information)
78 static void ipcp_resetci __P((fsm *)); /* Reset our CI */
79 static int ipcp_cilen __P((fsm *)); /* Return length of our CI */
80 static void ipcp_addci __P((fsm *, u_char *, int *)); /* Add our CI */
81 static int ipcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */
82 static int ipcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */
83 static int ipcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */
84 static int ipcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */
85 static void ipcp_up __P((fsm *)); /* We're UP */
86 static void ipcp_down __P((fsm *)); /* We're DOWN */
87 static void ipcp_finished __P((fsm *)); /* Don't need lower layer */
88 static int setmsservaddr __P((char *, u_int32_t *));
90 fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */
92 static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
93 ipcp_resetci, /* Reset our Configuration Information */
94 ipcp_cilen, /* Length of our Configuration Information */
95 ipcp_addci, /* Add our Configuration Information */
96 ipcp_ackci, /* ACK our Configuration Information */
97 ipcp_nakci, /* NAK our Configuration Information */
98 ipcp_rejci, /* Reject our Configuration Information */
99 ipcp_reqci, /* Request peer's Configuration Information */
100 ipcp_up, /* Called when fsm reaches OPENED state */
101 ipcp_down, /* Called when fsm leaves OPENED state */
102 NULL, /* Called when we want the lower layer up */
103 ipcp_finished, /* Called when we want the lower layer down */
104 NULL, /* Retransmission is necessary */
105 NULL, /* Called to handle protocol-specific codes */
106 "IPCP", /* String name of protocol */
107 NULL /* Peer rejected a code number */
111 * Command-line options.
113 static int setvjslots __P((char **));
114 static int setdnsaddr __P((char **));
115 static int setwinsaddr __P((char **));
116 static int autoproxyarp __P((char **));
118 static option_t ipcp_option_list[] = {
119 { "noip", o_bool, &ipcp_protent.enabled_flag,
120 "Disable IP and IPCP" },
121 { "-ip", o_bool, &ipcp_protent.enabled_flag,
122 "Disable IP and IPCP" },
123 { "novj", o_bool, &ipcp_wantoptions[0].neg_vj,
124 "Disable VJ compression", OPT_A2COPY, &ipcp_allowoptions[0].neg_vj },
125 { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj,
126 "Disable VJ compression", OPT_A2COPY, &ipcp_allowoptions[0].neg_vj },
127 { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag,
128 "Disable VJ connection-ID compression", OPT_A2COPY,
129 &ipcp_allowoptions[0].cflag },
130 { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag,
131 "Disable VJ connection-ID compression", OPT_A2COPY,
132 &ipcp_allowoptions[0].cflag },
133 { "vj-max-slots", o_special, (void *)setvjslots,
134 "Set maximum VJ header slots" },
135 { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local,
136 "Accept peer's address for us", 1 },
137 { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote,
138 "Accept peer's address for it", 1 },
139 { "ipparam", o_string, &ipparam,
140 "Set ip script parameter" },
141 { "noipdefault", o_bool, &disable_defaultip,
142 "Don't use name for default IP adrs", 1 },
143 { "ms-dns", o_special, (void *)setdnsaddr,
144 "DNS address for the peer's use" },
145 { "ms-wins", o_special, (void *)setwinsaddr,
146 "Nameserver for SMB over TCP/IP for peer" },
147 { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime,
148 "Set timeout for IPCP" },
149 { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits,
150 "Set max #xmits for term-reqs" },
151 { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits,
152 "Set max #xmits for conf-reqs" },
153 { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops,
154 "Set max #conf-naks for IPCP" },
155 { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route,
156 "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route },
157 { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route,
158 "disable defaultroute option", OPT_A2COPY,
159 &ipcp_wantoptions[0].default_route },
160 { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route,
161 "disable defaultroute option", OPT_A2COPY,
162 &ipcp_wantoptions[0].default_route },
163 { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp,
164 "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp },
165 { "autoproxyarp", o_special_noarg, (void *)autoproxyarp,
166 "Add proxy ARP entry if needed", OPT_ENABLE,
167 &ipcp_allowoptions[0].proxy_arp },
168 { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
169 "disable proxyarp option", OPT_A2COPY, &ipcp_wantoptions[0].proxy_arp },
170 { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
171 "disable proxyarp option", OPT_A2COPY, &ipcp_wantoptions[0].proxy_arp },
172 { "usepeerdns", o_bool, &ipcp_wantoptions[0].req_dns1,
173 "Ask peer for DNS address(es)", OPT_A2COPY|1,
174 &ipcp_wantoptions[0].req_dns2 },
175 { NULL }
179 * Protocol entry points from main code.
181 static void ipcp_init __P((int));
182 static void ipcp_open __P((int));
183 static void ipcp_close __P((int, char *));
184 static void ipcp_lowerup __P((int));
185 static void ipcp_lowerdown __P((int));
186 static void ipcp_input __P((int, u_char *, int));
187 static void ipcp_protrej __P((int));
188 static int ipcp_printpkt __P((u_char *, int,
189 void (*) __P((void *, const char *, ...)), void *));
190 static void ip_check_options __P((void));
191 static int ip_demand_conf __P((int));
192 static int ip_active_pkt __P((u_char *, int));
193 static void ipcp_print_stat __P((int, FILE *));
195 static void create_resolv __P((u_int32_t, u_int32_t));
197 struct protent ipcp_protent = {
198 PPP_IPCP,
199 ipcp_init,
200 ipcp_input,
201 ipcp_protrej,
202 ipcp_lowerup,
203 ipcp_lowerdown,
204 ipcp_open,
205 ipcp_close,
206 ipcp_printpkt,
207 NULL,
209 "IPCP",
210 "IP",
211 ipcp_option_list,
212 ip_check_options,
213 ip_demand_conf,
214 ip_active_pkt,
215 ipcp_print_stat
218 static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t));
219 static void ipcp_script __P((char *)); /* Run an up/down script */
220 static void ipcp_script_done __P((void *, int));
223 * Lengths of configuration options.
225 #define CILEN_VOID 2
226 #define CILEN_COMPRESS 4 /* min length for compression protocol opt. */
227 #define CILEN_VJ 6 /* length for RFC1332 Van-Jacobson opt. */
228 #define CILEN_ADDR 6 /* new-style single address option */
229 #define CILEN_ADDRS 10 /* old-style dual address option */
233 * This state variable is used to ensure that we don't
234 * run an ipcp-up/down script while one is already running.
236 static enum script_state {
237 s_down,
238 s_up
239 } ipcp_script_state;
240 static pid_t ipcp_script_pid;
243 * Make a string representation of a network IP address.
245 char *
246 ip_ntoa(ipaddr)
247 u_int32_t ipaddr;
249 static char b[64];
251 (void) slprintf(b, sizeof(b), "%I", ipaddr);
252 return b;
256 * Option parsing.
260 * setvjslots - set maximum number of connection slots for VJ compression
262 static int
263 setvjslots(argv)
264 char **argv;
266 int value;
268 if (!int_option(*argv, &value))
269 return 0;
270 if (value < 2 || value > 16) {
271 option_error("vj-max-slots value must be between 2 and 16");
272 return 0;
274 ipcp_wantoptions [0].maxslotindex =
275 ipcp_allowoptions[0].maxslotindex = value - 1;
276 return 1;
280 * setmsservaddr - Set the primary and secondary server addresses in the
281 * array. setdnsaddr() and setwinsaddr() call this function with either
282 * dnsaddr[] or winsaddr[] as the serverarray argument.
284 static int
285 setmsservaddr(servname, serverarray)
286 char *servname;
287 u_int32_t *serverarray;
289 u_int32_t addr;
290 struct hostent *hp = NULL;
292 addr = inet_addr(servname);
293 if (addr == (u_int32_t) -1) {
294 if ((hp = gethostbyname(servname)) == NULL)
295 return 0;
296 BCOPY(hp->h_addr, &addr, sizeof (u_int32_t));
300 * If there is no primary then this is the first instance of the
301 * option, we must set the primary. In that case, try to set the
302 * secondary to h_addr_list[1]. If the primary is already set, then
303 * this is the second instance of the option, and we must set
304 * the secondary.
306 if (serverarray[0] == 0) {
307 serverarray[0] = addr;
308 if (hp != NULL && hp->h_addr_list[1] != NULL)
309 BCOPY(hp->h_addr_list[1], &serverarray[1], sizeof (u_int32_t));
310 else
311 serverarray[1] = addr;
312 } else {
313 serverarray[1] = addr;
316 return (1);
320 * setdnsaddr - set the dns address(es)
322 static int
323 setdnsaddr(argv)
324 char **argv;
326 if (setmsservaddr(*argv, &(ipcp_allowoptions[0].dnsaddr[0])) == 0) {
327 option_error("invalid address parameter '%s' for ms-dns option", *argv);
328 return (0);
331 return (1);
335 * setwinsaddr - set the wins address(es)
336 * This is primrarly used with the Samba package under UNIX or for pointing
337 * the caller to the existing WINS server on a Windows NT platform.
339 static int
340 setwinsaddr(argv)
341 char **argv;
343 if (setmsservaddr(*argv, &(ipcp_allowoptions[0].winsaddr[0])) == 0) {
344 option_error("invalid address parameter '%s' for ms-wins option",
345 *argv);
346 return (0);
349 return (1);
353 * autoproxyarp -- enable proxy ARP but don't emit error messages if
354 * it's not actually needed.
356 /*ARGSUSED*/
357 static int
358 autoproxyarp(argv)
359 char **argv;
361 ipcp_wantoptions[0].proxy_arp = 1;
362 proxy_arp_quiet[0] = 1;
364 return (1);
369 * ipcp_init - Initialize IPCP.
371 static void
372 ipcp_init(unit)
373 int unit;
375 fsm *f = &ipcp_fsm[unit];
376 ipcp_options *wo = &ipcp_wantoptions[unit];
377 ipcp_options *ao = &ipcp_allowoptions[unit];
379 f->unit = unit;
380 f->protocol = PPP_IPCP;
381 f->callbacks = &ipcp_callbacks;
382 fsm_init(&ipcp_fsm[unit]);
384 BZERO(wo, sizeof(*wo));
385 BZERO(ao, sizeof(*ao));
387 wo->neg_addr = wo->old_addrs = 1;
388 wo->neg_vj = 1;
389 wo->vj_protocol = IPCP_VJ_COMP;
390 wo->maxslotindex = MAX_STATES - 1; /* really max index */
391 wo->cflag = 1;
393 ao->neg_addr = ao->old_addrs = 1;
394 ao->neg_vj = 1;
395 ao->maxslotindex = MAX_STATES - 1;
396 ao->cflag = 1;
399 * These aren't actually negotiated. Instead, they control
400 * whether the user may use the proxyarp and defaultroute options.
402 ao->proxy_arp = 1;
403 ao->default_route = 1;
404 proxy_arp_quiet[unit] = 0;
409 * ipcp_open - IPCP is allowed to come up.
411 static void
412 ipcp_open(unit)
413 int unit;
415 fsm_open(&ipcp_fsm[unit]);
420 * ipcp_close - Take IPCP down.
422 static void
423 ipcp_close(unit, reason)
424 int unit;
425 char *reason;
427 fsm_close(&ipcp_fsm[unit], reason);
432 * ipcp_lowerup - The lower layer is up.
434 static void
435 ipcp_lowerup(unit)
436 int unit;
438 fsm_lowerup(&ipcp_fsm[unit]);
443 * ipcp_lowerdown - The lower layer is down.
445 static void
446 ipcp_lowerdown(unit)
447 int unit;
449 fsm_lowerdown(&ipcp_fsm[unit]);
454 * ipcp_input - Input IPCP packet.
456 static void
457 ipcp_input(unit, p, len)
458 int unit;
459 u_char *p;
460 int len;
462 fsm_input(&ipcp_fsm[unit], p, len);
467 * ipcp_protrej - A Protocol-Reject was received for IPCP.
469 static void
470 ipcp_protrej(unit)
471 int unit;
473 fsm_protreject(&ipcp_fsm[unit]);
478 * ipcp_resetci - Reset our CI.
479 * Called by fsm_sconfreq, Send Configure Request.
481 static void
482 ipcp_resetci(f)
483 fsm *f;
485 ipcp_options *wo = &ipcp_wantoptions[f->unit];
486 ipcp_options *go = &ipcp_gotoptions[f->unit];
487 ipcp_options *ao = &ipcp_allowoptions[f->unit];
489 wo->req_addr = (wo->neg_addr || wo->old_addrs) &&
490 (ao->neg_addr || ao->old_addrs);
491 if (wo->ouraddr == 0 || disable_defaultip)
492 wo->accept_local = 1;
493 if (wo->hisaddr == 0)
494 wo->accept_remote = 1;
495 *go = *wo;
496 if (disable_defaultip)
497 go->ouraddr = 0;
502 * ipcp_cilen - Return length of our CI.
503 * Called by fsm_sconfreq, Send Configure Request.
505 static int
506 ipcp_cilen(f)
507 fsm *f;
509 ipcp_options *go = &ipcp_gotoptions[f->unit];
510 ipcp_options *wo = &ipcp_wantoptions[f->unit];
511 ipcp_options *ho = &ipcp_hisoptions[f->unit];
513 #define LENCIADDRS(neg) (neg ? CILEN_ADDRS : 0)
514 #define LENCIVJ(neg, old) (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0)
515 #define LENCIADDR(neg) (neg ? (CILEN_ADDR) : 0)
518 * First see if we want to change our options to the old
519 * forms because we have received old forms from the peer.
521 if (go->neg_addr && go->old_addrs && !ho->neg_addr && ho->old_addrs)
522 /* use the old style of address negotiation */
523 go->neg_addr = 0;
524 if (wo->neg_vj && !go->neg_vj && !go->old_vj) {
525 /* try an older style of VJ negotiation */
526 /* use the old style only if the peer did */
527 if (ho->neg_vj && ho->old_vj) {
528 go->neg_vj = 1;
529 go->old_vj = 1;
530 go->vj_protocol = ho->vj_protocol;
534 return (LENCIADDRS(!go->neg_addr && go->old_addrs) +
535 LENCIVJ(go->neg_vj, go->old_vj) +
536 LENCIADDR(go->neg_addr) +
537 LENCIADDR(go->req_dns1) +
538 LENCIADDR(go->req_dns2)) ;
543 * ipcp_addci - Add our desired CIs to a packet.
544 * Called by fsm_sconfreq, Send Configure Request.
546 static void
547 ipcp_addci(f, ucp, lenp)
548 fsm *f;
549 u_char *ucp;
550 int *lenp;
552 ipcp_options *go = &ipcp_gotoptions[f->unit];
553 int len = *lenp;
555 #define ADDCIADDRS(opt, neg, val1, val2) \
556 if (neg) { \
557 if (len >= CILEN_ADDRS) { \
558 PUTCHAR(opt, ucp); \
559 PUTCHAR(CILEN_ADDRS, ucp); \
560 PUTNLONG(val1, ucp); \
561 PUTNLONG(val2, ucp); \
562 len -= CILEN_ADDRS; \
563 } else \
564 go->old_addrs = 0; \
567 #define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \
568 if (neg) { \
569 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
570 if (len >= vjlen) { \
571 PUTCHAR(opt, ucp); \
572 PUTCHAR(vjlen, ucp); \
573 PUTSHORT(val, ucp); \
574 if (!old) { \
575 PUTCHAR(maxslotindex, ucp); \
576 PUTCHAR(cflag, ucp); \
578 len -= vjlen; \
579 } else \
580 neg = 0; \
583 #define ADDCIADDR(opt, neg, val) \
584 if (neg) { \
585 if (len >= CILEN_ADDR) { \
586 PUTCHAR(opt, ucp); \
587 PUTCHAR(CILEN_ADDR, ucp); \
588 PUTNLONG(val, ucp); \
589 len -= CILEN_ADDR; \
590 } else \
591 neg = 0; \
594 ADDCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr,
595 go->hisaddr);
597 ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
598 go->maxslotindex, go->cflag);
600 ADDCIADDR(CI_ADDR, go->neg_addr, go->ouraddr);
602 ADDCIADDR(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
604 ADDCIADDR(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
606 *lenp -= len;
611 * ipcp_ackci - Ack our CIs.
612 * Called by fsm_rconfack, Receive Configure ACK.
614 * Returns:
615 * 0 - Ack was bad.
616 * 1 - Ack was good.
618 static int
619 ipcp_ackci(f, p, len)
620 fsm *f;
621 u_char *p;
622 int len;
624 ipcp_options *go = &ipcp_gotoptions[f->unit];
625 u_short cilen, citype, cishort;
626 u_int32_t cilong;
627 u_char cimaxslotindex, cicflag;
630 * CIs must be in exactly the same order that we sent...
631 * Check packet length and CI length at each step.
632 * If we find any deviations, then this packet is bad.
635 #define ACKCHECK(opt, olen) \
636 if ((len -= olen) < 0) \
637 goto bad; \
638 GETCHAR(citype, p); \
639 GETCHAR(cilen, p); \
640 if (cilen != olen || \
641 citype != opt) \
642 goto bad;
644 #define ACKCIADDRS(opt, neg, val1, val2) \
645 if (neg) { \
646 ACKCHECK(opt, CILEN_ADDRS) \
647 GETNLONG(cilong, p); \
648 if (val1 != cilong) \
649 goto bad; \
650 GETNLONG(cilong, p); \
651 if (val2 != cilong) \
652 goto bad; \
655 #define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \
656 if (neg) { \
657 int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
658 ACKCHECK(opt, vjlen) \
659 GETSHORT(cishort, p); \
660 if (cishort != val) \
661 goto bad; \
662 if (!old) { \
663 GETCHAR(cimaxslotindex, p); \
664 if (cimaxslotindex != maxslotindex) \
665 goto bad; \
666 GETCHAR(cicflag, p); \
667 if (cicflag != cflag) \
668 goto bad; \
672 #define ACKCIADDR(opt, neg, val) \
673 if (neg) { \
674 ACKCHECK(opt, CILEN_ADDR) \
675 GETNLONG(cilong, p); \
676 if (val != cilong) \
677 goto bad; \
680 ACKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs, go->ouraddr,
681 go->hisaddr);
683 ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
684 go->maxslotindex, go->cflag);
686 ACKCIADDR(CI_ADDR, go->neg_addr, go->ouraddr);
688 ACKCIADDR(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
690 ACKCIADDR(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
693 * If there are any remaining CIs, then this packet is bad.
695 if (len != 0)
696 goto bad;
697 return (1);
699 bad:
700 IPCPDEBUG(("ipcp_ackci: received bad Ack!"));
701 return (0);
705 * ipcp_nakci - Peer has sent a NAK for some of our CIs.
706 * This should not modify any state if the Nak is bad
707 * or if IPCP is in the OPENED state.
708 * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
710 * Returns:
711 * 0 - Nak was bad.
712 * 1 - Nak was good.
714 static int
715 ipcp_nakci(f, p, len)
716 fsm *f;
717 u_char *p;
718 int len;
720 ipcp_options *go = &ipcp_gotoptions[f->unit];
721 u_char cimaxslotindex, cicflag;
722 u_char citype, cilen, *next;
723 u_short cishort;
724 u_int32_t ciaddr1, ciaddr2;
725 ipcp_options no; /* options we've seen Naks for */
726 ipcp_options try; /* options to request next time */
728 BZERO(&no, sizeof(no));
729 try = *go;
732 * Any Nak'd CIs must be in exactly the same order that we sent.
733 * Check packet length and CI length at each step.
734 * If we find any deviations, then this packet is bad.
736 #define NAKCIADDRS(opt, neg, code) \
737 if ((neg) && \
738 (cilen = p[1]) == CILEN_ADDRS && \
739 len >= cilen && \
740 p[0] == opt) { \
741 len -= cilen; \
742 INCPTR(2, p); \
743 GETNLONG(ciaddr1, p); \
744 GETNLONG(ciaddr2, p); \
745 no.old_addrs = 1; \
746 code \
749 #define NAKCIVJ(opt, neg, code) \
750 if (go->neg && \
751 ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \
752 len >= cilen && \
753 p[0] == opt) { \
754 len -= cilen; \
755 INCPTR(2, p); \
756 GETSHORT(cishort, p); \
757 no.neg = 1; \
758 code \
761 #define NAKCIADDR(opt, neg, code) \
762 if (go->neg && \
763 (cilen = p[1]) == CILEN_ADDR && \
764 len >= cilen && \
765 p[0] == opt) { \
766 len -= cilen; \
767 INCPTR(2, p); \
768 GETNLONG(ciaddr1, p); \
769 no.neg = 1; \
770 code \
774 * Accept the peer's idea of {our,its} address, if different
775 * from our idea, only if the accept_{local,remote} flag is set.
777 NAKCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs,
778 if (go->accept_local && ciaddr1) { /* Do we know our address? */
779 try.ouraddr = ciaddr1;
781 if (go->accept_remote && ciaddr2) { /* Does it know its? */
782 try.hisaddr = ciaddr2;
787 * Accept the peer's value of maxslotindex provided that it
788 * is less than what we asked for. Turn off slot-ID compression
789 * if the peer wants. Send old-style compress-type option if
790 * the peer wants.
792 NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
793 if (cilen == CILEN_VJ) {
794 GETCHAR(cimaxslotindex, p);
795 GETCHAR(cicflag, p);
796 if (cishort == IPCP_VJ_COMP) {
797 try.old_vj = 0;
798 if (cimaxslotindex < go->maxslotindex)
799 try.maxslotindex = cimaxslotindex;
800 if (!cicflag)
801 try.cflag = 0;
802 } else {
803 try.neg_vj = 0;
805 } else {
806 if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) {
807 try.old_vj = 1;
808 try.vj_protocol = cishort;
809 } else {
810 try.neg_vj = 0;
815 NAKCIADDR(CI_ADDR, neg_addr,
816 if (go->accept_local && ciaddr1) { /* Do we know our address? */
817 try.ouraddr = ciaddr1;
821 NAKCIADDR(CI_MS_DNS1, req_dns1,
822 try.dnsaddr[0] = ciaddr1;
825 NAKCIADDR(CI_MS_DNS2, req_dns2,
826 try.dnsaddr[1] = ciaddr1;
830 * There may be remaining CIs, if the peer is requesting negotiation
831 * on an option that we didn't include in our request packet.
832 * If they want to negotiate about IP addresses, we comply.
833 * If they want us to ask for compression, we refuse.
835 while (len > CILEN_VOID) {
836 GETCHAR(citype, p);
837 GETCHAR(cilen, p);
838 if( (len -= cilen) < 0 )
839 goto bad;
840 next = p + cilen - 2;
842 switch (citype) {
843 case CI_COMPRESSTYPE:
844 if (go->neg_vj || no.neg_vj ||
845 (cilen != CILEN_VJ && cilen != CILEN_COMPRESS))
846 goto bad;
847 no.neg_vj = 1;
848 break;
849 case CI_ADDRS:
850 if ((!go->neg_addr && go->old_addrs) || no.old_addrs
851 || cilen != CILEN_ADDRS)
852 goto bad;
853 try.neg_addr = 1;
854 try.old_addrs = 1;
855 GETNLONG(ciaddr1, p);
856 if (ciaddr1 && go->accept_local)
857 try.ouraddr = ciaddr1;
858 GETNLONG(ciaddr2, p);
859 if (ciaddr2 && go->accept_remote)
860 try.hisaddr = ciaddr2;
861 no.old_addrs = 1;
862 break;
863 case CI_ADDR:
864 if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR)
865 goto bad;
866 try.old_addrs = 0;
867 GETNLONG(ciaddr1, p);
868 if (ciaddr1 && go->accept_local)
869 try.ouraddr = ciaddr1;
870 if (try.ouraddr != 0)
871 try.neg_addr = 1;
872 no.neg_addr = 1;
873 break;
875 p = next;
879 * OK, the Nak is good. Now we can update state.
880 * If there are any remaining options, we ignore them.
882 if (f->state != OPENED)
883 *go = try;
885 return 1;
887 bad:
888 IPCPDEBUG(("ipcp_nakci: received bad Nak!"));
889 return 0;
894 * ipcp_rejci - Reject some of our CIs.
895 * Callback from fsm_rconfnakrej.
897 static int
898 ipcp_rejci(f, p, len)
899 fsm *f;
900 u_char *p;
901 int len;
903 ipcp_options *go = &ipcp_gotoptions[f->unit];
904 u_char cimaxslotindex, ciflag, cilen;
905 u_short cishort;
906 u_int32_t cilong;
907 ipcp_options try; /* options to request next time */
909 try = *go;
911 * Any Rejected CIs must be in exactly the same order that we sent.
912 * Check packet length and CI length at each step.
913 * If we find any deviations, then this packet is bad.
915 #define REJCIADDRS(opt, neg, val1, val2) \
916 if ((neg) && \
917 (cilen = p[1]) == CILEN_ADDRS && \
918 len >= cilen && \
919 p[0] == opt) { \
920 len -= cilen; \
921 INCPTR(2, p); \
922 GETNLONG(cilong, p); \
923 /* Check rejected value. */ \
924 if (cilong != val1) \
925 goto bad; \
926 GETNLONG(cilong, p); \
927 /* Check rejected value. */ \
928 if (cilong != val2) \
929 goto bad; \
930 try.old_addrs = 0; \
933 #define REJCIVJ(opt, neg, val, old, maxslot, cflag) \
934 if (go->neg && \
935 p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \
936 len >= p[1] && \
937 p[0] == opt) { \
938 len -= p[1]; \
939 INCPTR(2, p); \
940 GETSHORT(cishort, p); \
941 /* Check rejected value. */ \
942 if (cishort != val) \
943 goto bad; \
944 if (!old) { \
945 GETCHAR(cimaxslotindex, p); \
946 if (cimaxslotindex != maxslot) \
947 goto bad; \
948 GETCHAR(ciflag, p); \
949 if (ciflag != cflag) \
950 goto bad; \
952 try.neg = 0; \
955 #define REJCIADDR(opt, neg, addr) \
956 if (go->neg && \
957 ((cilen = p[1]) == CILEN_ADDR) && \
958 len >= cilen && \
959 p[0] == opt) { \
960 len -= cilen; \
961 INCPTR(2, p); \
962 GETNLONG(cilong, p); \
963 /* Check rejected value. */ \
964 if (cilong != addr) \
965 goto bad; \
966 try.neg = 0; \
969 REJCIADDRS(CI_ADDRS, !go->neg_addr && go->old_addrs,
970 go->ouraddr, go->hisaddr);
972 REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj,
973 go->maxslotindex, go->cflag);
975 REJCIADDR(CI_ADDR, neg_addr, go->ouraddr);
977 REJCIADDR(CI_MS_DNS1, req_dns1, go->dnsaddr[0]);
979 REJCIADDR(CI_MS_DNS2, req_dns2, go->dnsaddr[1]);
982 * If there are any remaining CIs, then this packet is bad.
984 if (len != 0)
985 goto bad;
987 * Now we can update state.
989 if (f->state != OPENED)
990 *go = try;
991 return 1;
993 bad:
994 IPCPDEBUG(("ipcp_rejci: received bad Reject!"));
995 return 0;
1000 * ipcp_reqci - Check the peer's requested CIs and send appropriate response.
1001 * Callback from fsm_rconfreq, Receive Configure Request
1003 * Returns: CODE_CONFACK, CODE_CONFNAK or CODE_CONFREJ and input
1004 * packet modified appropriately. If reject_if_disagree is non-zero,
1005 * doesn't return CODE_CONFNAK; returns CODE_CONFREJ if it can't
1006 * return CODE_CONFACK.
1008 static int
1009 ipcp_reqci(f, p, lenp, dont_nak)
1010 fsm *f;
1011 u_char *p; /* Requested CIs */
1012 int *lenp; /* Length of requested CIs */
1013 bool dont_nak;
1015 ipcp_options *wo = &ipcp_wantoptions[f->unit];
1016 ipcp_options *ho = &ipcp_hisoptions[f->unit];
1017 ipcp_options *ao = &ipcp_allowoptions[f->unit];
1018 ipcp_options *go = &ipcp_gotoptions[f->unit];
1019 int ret, newret;
1020 u_char *p0, *nakp, *rejp, *prev;
1021 u_short cishort;
1022 int len, cilen, type;
1023 u_int32_t tl, ciaddr1, ciaddr2; /* Parsed address values */
1024 u_char maxslotindex, cflag;
1025 int d;
1027 ret = CODE_CONFACK;
1028 rejp = p0 = p;
1029 nakp = nak_buffer;
1032 * Reset all its options.
1034 BZERO(ho, sizeof(*ho));
1037 * Process all its options.
1039 for (len = *lenp; len > 0; len -= cilen, p = prev + cilen) {
1040 if ((len < 2) || p[1] > len) {
1042 * RFC 1661 page 40 -- if the option extends beyond the
1043 * packet, then discard the entire packet.
1045 return (0);
1048 newret = CODE_CONFACK;
1049 prev = p;
1050 GETCHAR(type, p);
1051 GETCHAR(cilen, p);
1053 switch (type) { /* Check CI type */
1054 case CI_ADDRS:
1055 if (!ao->old_addrs || ho->neg_addr) {
1056 newret = CODE_CONFREJ;
1057 break;
1060 if (cilen != CILEN_ADDRS) {
1062 * rfc1661, page 40 -- a recongnized option with an
1063 * invalid length should be Nak'ed.
1065 newret = CODE_CONFNAK;
1066 ciaddr1 = wo->hisaddr;
1067 ciaddr2 = wo->ouraddr;
1068 } else {
1071 * If it has no address, or if we both have its
1072 * address but disagree about it, then NAK it with our
1073 * idea. In particular, if we don't know its address,
1074 * but it does, then accept it.
1076 GETNLONG(ciaddr1, p);
1077 if (ciaddr1 != wo->hisaddr &&
1078 (ciaddr1 == 0 || !wo->accept_remote)) {
1079 newret = CODE_CONFNAK;
1080 ciaddr1 = wo->hisaddr;
1081 } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
1083 * If neither we nor he knows his address, reject
1084 * the option.
1086 newret = CODE_CONFREJ;
1087 wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */
1088 break;
1089 } else if (ciaddr1 != 0) {
1090 go->hisaddr = ciaddr1;
1094 * If he doesn't know our address, or if we both have
1095 * our address * but disagree about it, then NAK it
1096 * with our idea.
1098 GETNLONG(ciaddr2, p);
1099 if (ciaddr2 != wo->ouraddr) {
1100 if (ciaddr2 == 0 || !wo->accept_local) {
1101 newret = CODE_CONFNAK;
1102 ciaddr2 = wo->ouraddr;
1103 } else {
1104 go->ouraddr = ciaddr2; /* accept peer's idea */
1109 if (newret == CODE_CONFNAK) {
1110 PUTCHAR(type, nakp);
1111 PUTCHAR(CILEN_ADDRS, nakp);
1112 PUTNLONG(ciaddr1, nakp);
1113 PUTNLONG(ciaddr2, nakp);
1116 ho->old_addrs = 1;
1117 ho->hisaddr = ciaddr1;
1118 ho->ouraddr = ciaddr2;
1119 break;
1121 case CI_ADDR:
1122 if (!ao->neg_addr || ho->old_addrs) {
1123 newret = CODE_CONFREJ;
1124 break;
1127 if (cilen != CILEN_ADDR) {
1129 * rfc1661, page 40 -- a recongnized option with an
1130 * invalid length should be Nak'ed.
1132 newret = CODE_CONFNAK;
1133 ciaddr1 = wo->hisaddr;
1134 } else {
1137 * If he has no address, or if we both have his
1138 * address but disagree about it, then NAK it with our
1139 * idea. In particular, if we don't know his address,
1140 * but he does, then accept it.
1142 GETNLONG(ciaddr1, p);
1143 if (ciaddr1 != wo->hisaddr &&
1144 (ciaddr1 == 0 || !wo->accept_remote)) {
1145 newret = CODE_CONFNAK;
1146 ciaddr1 = wo->hisaddr;
1147 } else if (ciaddr1 == 0 && wo->hisaddr == 0 &&
1148 wo->default_route != 0) {
1149 newret = CODE_CONFNAK;
1151 * If this is a dialup line (default_route is
1152 * set), and neither side knows about its address,
1153 * suggest an arbitrary rfc1918 address.
1155 ciaddr1 = htonl(0xc0a80101 + ifunit);
1156 dbglog("Peer address unknown; suggesting %I", ciaddr1);
1157 } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
1159 * If this is not a dialup line, don't ACK an
1160 * address of 0.0.0.0 - reject it instead.
1162 newret = CODE_CONFREJ;
1163 wo->req_addr = 0; /* don't NAK with 0.0.0.0 later */
1164 break;
1168 if (newret == CODE_CONFNAK) {
1169 PUTCHAR(type, nakp);
1170 PUTCHAR(CILEN_ADDR, nakp);
1171 PUTNLONG(ciaddr1, nakp);
1174 ho->neg_addr = 1;
1175 ho->hisaddr = ciaddr1;
1176 break;
1178 case CI_MS_DNS1:
1179 case CI_MS_DNS2:
1180 /* Warning -- these options work backwards. */
1181 /* Microsoft primary or secondary DNS request */
1182 d = (type == CI_MS_DNS2 ? 1 : 0);
1184 if (ao->dnsaddr[d] == 0) {
1185 newret = CODE_CONFREJ;
1186 break;
1189 if (cilen != CILEN_ADDR) {
1190 newret = CODE_CONFNAK;
1191 } else {
1192 GETNLONG(tl, p);
1193 if (tl != ao->dnsaddr[d]) {
1194 newret = CODE_CONFNAK;
1198 if (newret == CODE_CONFNAK) {
1199 PUTCHAR(type, nakp);
1200 PUTCHAR(CILEN_ADDR, nakp);
1201 PUTNLONG(ao->dnsaddr[d], nakp);
1203 break;
1205 case CI_MS_WINS1:
1206 case CI_MS_WINS2:
1207 /* Warning -- these options work backwards. */
1208 /* Microsoft primary or secondary WINS request */
1209 d = (type == CI_MS_WINS2 ? 1 : 0);
1211 if (ao->winsaddr[d] == 0) {
1212 newret = CODE_CONFREJ;
1213 break;
1216 if (cilen != CILEN_ADDR) {
1217 newret = CODE_CONFNAK;
1218 } else {
1219 GETNLONG(tl, p);
1220 if (tl != ao->winsaddr[d]) {
1221 newret = CODE_CONFNAK;
1225 if (newret == CODE_CONFNAK) {
1226 PUTCHAR(type, nakp);
1227 PUTCHAR(CILEN_ADDR, nakp);
1228 PUTNLONG(ao->winsaddr[d], nakp);
1230 break;
1232 case CI_COMPRESSTYPE:
1233 if (!ao->neg_vj) {
1234 newret = CODE_CONFREJ;
1235 break;
1238 maxslotindex = ao->maxslotindex;
1239 cflag = ao->cflag;
1240 if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) {
1241 newret = CODE_CONFNAK;
1242 cishort = IPCP_VJ_COMP;
1243 } else {
1244 GETSHORT(cishort, p);
1245 if (cishort != IPCP_VJ_COMP &&
1246 (cishort != IPCP_VJ_COMP_OLD || cilen != CILEN_COMPRESS)) {
1247 newret = CODE_CONFNAK;
1248 cishort = IPCP_VJ_COMP;
1249 } else if (cilen == CILEN_VJ) {
1250 GETCHAR(maxslotindex, p);
1251 if (maxslotindex > ao->maxslotindex) {
1252 newret = CODE_CONFNAK;
1253 maxslotindex = ao->maxslotindex;
1255 GETCHAR(cflag, p);
1256 if (cflag != 0 && ao->cflag == 0) {
1257 newret = CODE_CONFNAK;
1258 cflag = 0;
1260 } else {
1261 ho->old_vj = 1;
1262 maxslotindex = MAX_STATES - 1;
1263 cflag = 1;
1267 if (newret == CODE_CONFNAK) {
1268 PUTCHAR(type, nakp);
1269 if (cishort == IPCP_VJ_COMP) {
1270 PUTCHAR(CILEN_VJ, nakp);
1271 PUTSHORT(cishort, nakp);
1272 PUTCHAR(maxslotindex, nakp);
1273 PUTCHAR(cflag, nakp);
1274 } else {
1275 PUTCHAR(CILEN_COMPRESS, nakp);
1276 PUTSHORT(cishort, nakp);
1279 ho->neg_vj = 1;
1280 ho->vj_protocol = cishort;
1281 ho->maxslotindex = maxslotindex;
1282 ho->cflag = cflag;
1283 break;
1285 default:
1286 newret = CODE_CONFREJ;
1287 break;
1290 /* Cope with confused peers. */
1291 if (cilen < 2)
1292 cilen = 2;
1295 * If this is an Ack'able CI, but we're sending back a Nak,
1296 * don't include this CI.
1298 if (newret == CODE_CONFACK && ret != CODE_CONFACK)
1299 continue;
1301 if (newret == CODE_CONFNAK) {
1302 if (dont_nak) {
1303 newret = CODE_CONFREJ;
1304 } else {
1305 /* Ignore subsequent Nak'able things if rejecting. */
1306 if (ret == CODE_CONFREJ)
1307 continue;
1308 ret = CODE_CONFNAK;
1312 if (newret == CODE_CONFREJ) {
1313 ret = CODE_CONFREJ;
1314 if (prev != rejp)
1315 BCOPY(prev, rejp, cilen);
1316 rejp += cilen;
1321 * If we aren't rejecting this packet, and we want to negotiate
1322 * their address, and they didn't send their address, then we
1323 * send a NAK with a CI_ADDR option appended. We assume the
1324 * input buffer is long enough that we can append the extra
1325 * option safely.
1327 if (ret != CODE_CONFREJ && !ho->neg_addr && !ho->old_addrs &&
1328 wo->req_addr && !dont_nak) {
1329 if (ret == CODE_CONFACK)
1330 wo->req_addr = 0; /* don't ask again */
1331 ret = CODE_CONFNAK;
1332 PUTCHAR(CI_ADDR, nakp);
1333 PUTCHAR(CILEN_ADDR, nakp);
1334 PUTNLONG(wo->hisaddr, nakp);
1337 switch (ret) {
1338 case CODE_CONFACK:
1339 *lenp = p - p0;
1340 sys_block_proto(PPP_IP);
1341 break;
1342 case CODE_CONFNAK:
1343 *lenp = nakp - nak_buffer;
1344 BCOPY(nak_buffer, p0, *lenp);
1345 break;
1346 case CODE_CONFREJ:
1347 *lenp = rejp - p0;
1348 break;
1351 return (ret); /* Return final code */
1356 * ip_check_options - check that any IP-related options are OK,
1357 * and assign appropriate defaults.
1359 static void
1360 ip_check_options()
1362 struct hostent *hp;
1363 u_int32_t local;
1364 ipcp_options *wo = &ipcp_wantoptions[0];
1367 * Default our local IP address based on our hostname.
1368 * If local IP address already given, don't bother.
1370 if (wo->ouraddr == 0) {
1372 * Look up our hostname (possibly with domain name appended)
1373 * and take the first IP address as our local IP address.
1374 * If there isn't an IP address for our hostname, too bad.
1376 wo->accept_local = 1; /* don't insist on this default value */
1377 if ((hp = gethostbyname(hostname)) != NULL) {
1378 BCOPY(hp->h_addr, &local, sizeof (hp->h_addr));
1379 if (local != 0 && !bad_ip_adrs(local)) {
1380 wo->ouraddr = local;
1381 ipcp_from_hostname = 1;
1389 * ip_demand_conf - configure the interface as though
1390 * IPCP were up, for use with dial-on-demand.
1392 static int
1393 ip_demand_conf(u)
1394 int u;
1396 ipcp_options *wo = &ipcp_wantoptions[u];
1398 if (wo->hisaddr == 0) {
1399 /* make up an arbitrary address for the peer */
1400 wo->hisaddr = htonl(0x0a707070 + ifunit);
1401 wo->accept_remote = 1;
1403 if (wo->ouraddr == 0) {
1404 /* make up an arbitrary address for us */
1405 wo->ouraddr = htonl(0x0a404040 + ifunit);
1406 wo->accept_local = 1;
1407 disable_defaultip = 1; /* don't tell the peer this address */
1409 if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr)))
1410 return 0;
1411 if (!sifup(u))
1412 return 0;
1413 if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
1414 return 0;
1415 if (wo->default_route && sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
1416 default_route_set[u] = 1;
1417 if (wo->proxy_arp && sifproxyarp(u, wo->hisaddr, proxy_arp_quiet[u]))
1418 proxy_arp_set[u] = 1;
1420 notice("local IP address %I", wo->ouraddr);
1421 notice("remote IP address %I", wo->hisaddr);
1423 return 1;
1428 * ipcp_up - IPCP has come UP.
1430 * Configure the IP network interface appropriately and bring it up.
1432 static void
1433 ipcp_up(f)
1434 fsm *f;
1436 u_int32_t mask;
1437 ipcp_options *ho = &ipcp_hisoptions[f->unit];
1438 ipcp_options *go = &ipcp_gotoptions[f->unit];
1439 ipcp_options *wo = &ipcp_wantoptions[f->unit];
1441 IPCPDEBUG(("ipcp: up"));
1444 * We must have a non-zero IP address for both ends of the link.
1446 if (ho->hisaddr == 0)
1447 ho->hisaddr = wo->hisaddr;
1449 if (ho->hisaddr == 0) {
1450 if (wo->accept_remote) {
1451 /* Pick some rfc1918 address. */
1452 ho->hisaddr = htonl(0xc0a80101 + ifunit);
1453 dbglog("Peer refused to provide his address; assuming %I",
1454 ho->hisaddr);
1455 } else {
1456 error("Could not determine remote IP address");
1457 ipcp_close(f->unit, "Could not determine remote IP address");
1458 return;
1461 if (go->ouraddr == 0) {
1462 error("Could not determine local IP address");
1463 ipcp_close(f->unit, "Could not determine local IP address");
1464 return;
1466 script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0);
1467 script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1);
1470 * Check that the peer is allowed to use the IP address it wants.
1472 if (!auth_ip_addr(f->unit, ho->hisaddr)) {
1473 error("Peer is not authorized to use remote address %I", ho->hisaddr);
1474 ipcp_close(f->unit, "Unauthorized remote IP address");
1475 return;
1478 if ((go->req_dns1 && go->dnsaddr[0] != 0) ||
1479 (go->req_dns2 && go->dnsaddr[1] != 0)) {
1480 script_setenv("USEPEERDNS", "1", 0);
1481 if (go->dnsaddr[0] != 0)
1482 script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0);
1483 if (go->dnsaddr[1] != 0)
1484 script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0);
1485 create_resolv(go->dnsaddr[0], go->dnsaddr[1]);
1488 /* set tcp compression */
1489 if (sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex) != 1) {
1490 ipcp_close(f->unit, "Could not enable VJ TCP header compression");
1491 return;
1495 * If we are doing dial-on-demand, the interface is already
1496 * configured, so we put out any saved-up packets, then set the
1497 * interface to pass IP packets.
1499 if (demand) {
1500 if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
1501 ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr);
1502 if (go->ouraddr != wo->ouraddr) {
1503 warn("Local IP address changed to %I", go->ouraddr);
1504 script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0);
1505 wo->ouraddr = go->ouraddr;
1506 } else
1507 script_unsetenv("OLDIPLOCAL");
1508 if (ho->hisaddr != wo->hisaddr) {
1509 warn("Remote IP address changed to %I", ho->hisaddr);
1510 script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0);
1511 wo->hisaddr = ho->hisaddr;
1512 } else
1513 script_unsetenv("OLDIPREMOTE");
1515 /* Set the interface to the new addresses */
1516 mask = GetMask(go->ouraddr);
1517 if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1518 warn("Interface configuration failed");
1519 ipcp_close(f->unit, "Interface configuration failed");
1520 return;
1523 /* assign a default route through the interface if required */
1524 if (wo->default_route)
1525 if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
1526 default_route_set[f->unit] = 1;
1528 /* Make a proxy ARP entry if requested. */
1529 if (wo->proxy_arp &&
1530 sifproxyarp(f->unit, ho->hisaddr, proxy_arp_quiet[f->unit]))
1531 proxy_arp_set[f->unit] = 1;
1534 demand_rexmit(PPP_IP);
1535 if (sifnpmode(f->unit, PPP_IP, NPMODE_PASS) != 1) {
1536 ipcp_close(f->unit, "Interface configuration failed.");
1537 return;
1540 } else {
1542 * Set IP addresses and (if specified) netmask.
1544 mask = GetMask(go->ouraddr);
1546 #if SIFUPFIRST
1547 /* bring the interface up for IP */
1548 if (!sifup(f->unit)) {
1549 warn("Interface failed to come up");
1550 ipcp_close(f->unit, "Interface configuration failed");
1551 return;
1553 #endif
1555 if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1556 warn("Interface configuration failed");
1557 ipcp_close(f->unit, "Interface configuration failed");
1558 return;
1561 #if !SIFUPFIRST
1562 /* bring the interface up for IP */
1563 if (!sifup(f->unit)) {
1564 warn("Interface failed to come up");
1565 ipcp_close(f->unit, "Interface configuration failed");
1566 return;
1568 #endif
1570 if (sifnpmode(f->unit, PPP_IP, NPMODE_PASS) != 1) {
1571 ipcp_close(f->unit, "Interface configuration failed.");
1572 return;
1575 /* assign a default route through the interface if required */
1576 if (wo->default_route)
1577 if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
1578 default_route_set[f->unit] = 1;
1580 /* Make a proxy ARP entry if requested. */
1581 if (wo->proxy_arp &&
1582 sifproxyarp(f->unit, ho->hisaddr, proxy_arp_quiet[f->unit]))
1583 proxy_arp_set[f->unit] = 1;
1585 wo->ouraddr = go->ouraddr;
1587 notice("local IP address %I", go->ouraddr);
1588 notice("remote IP address %I", ho->hisaddr);
1589 if (go->dnsaddr[0] != 0)
1590 notice("primary DNS address %I", go->dnsaddr[0]);
1591 if (go->dnsaddr[1] != 0)
1592 notice("secondary DNS address %I", go->dnsaddr[1]);
1595 np_up(f->unit, PPP_IP);
1596 ipcp_is_up[f->unit] = 1;
1598 if (ip_up_hook != NULL)
1599 (*ip_up_hook)();
1602 * Execute the ip-up script, like this:
1603 * /etc/ppp/ip-up interface tty speed local-IP remote-IP
1605 if (ipcp_script_state == s_down && ipcp_script_pid == 0) {
1606 ipcp_script_state = s_up;
1607 ipcp_script(_PATH_IPUP);
1609 sys_unblock_proto(PPP_IP);
1614 * ipcp_down - IPCP has gone DOWN.
1616 * Take the IP network interface down, clear its addresses
1617 * and delete routes through it.
1619 static void
1620 ipcp_down(f)
1621 fsm *f;
1623 IPCPDEBUG(("ipcp: down"));
1624 /* XXX a bit IPv4-centric here, we only need to get the stats
1625 * before the interface is marked down. */
1626 update_link_stats(f->unit);
1627 if (ip_down_hook != NULL)
1628 (*ip_down_hook)();
1629 if (ipcp_is_up[f->unit]) {
1630 ipcp_is_up[f->unit] = 0;
1631 np_down(f->unit, PPP_IP);
1633 if (sifvjcomp(f->unit, 0, 0, 0) != 1) {
1634 if (debug)
1635 warn("Failed to disable VJ TCP header compression.");
1639 * If we are doing dial-on-demand, set the interface
1640 * to queue up outgoing packets (for now).
1642 if (demand) {
1643 if (sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE) != 1) {
1644 if (debug)
1645 warn("Failed to enable Queueing on outgoing packets.");
1647 } else {
1648 if (sifnpmode(f->unit, PPP_IP, NPMODE_ERROR) != 1) {
1649 if (debug)
1650 warn("Could not set interface to drop packets.");
1652 if (sifdown(f->unit) != 1)
1653 warn("Could not bring interface down.");
1654 ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr,
1655 ipcp_hisoptions[f->unit].hisaddr);
1658 /* Execute the ip-down script */
1659 if (ipcp_script_state == s_up && ipcp_script_pid == 0) {
1660 ipcp_script_state = s_down;
1661 ipcp_script(_PATH_IPDOWN);
1667 * ipcp_clear_addrs() - clear the interface addresses, routes,
1668 * proxy arp entries, etc.
1670 static void
1671 ipcp_clear_addrs(unit, ouraddr, hisaddr)
1672 int unit;
1673 u_int32_t ouraddr; /* local address */
1674 u_int32_t hisaddr; /* remote address */
1676 if (proxy_arp_set[unit]) {
1677 (void) cifproxyarp(unit, hisaddr);
1678 proxy_arp_set[unit] = 0;
1680 if (default_route_set[unit]) {
1681 (void) cifdefaultroute(unit, ouraddr, hisaddr);
1682 default_route_set[unit] = 0;
1684 if (cifaddr(unit, ouraddr, hisaddr) != 1)
1685 warn("Could not clear addresses");
1690 * ipcp_finished - possibly shut down the lower layers.
1692 static void
1693 ipcp_finished(f)
1694 fsm *f;
1696 np_finished(f->unit, PPP_IP);
1701 * ipcp_script_done - called when the ip-up or ip-down script
1702 * has finished.
1704 /*ARGSUSED*/
1705 static void
1706 ipcp_script_done(arg, status)
1707 void *arg;
1708 int status;
1710 ipcp_script_pid = 0;
1711 switch (ipcp_script_state) {
1712 case s_up:
1713 if (ipcp_fsm[0].state != OPENED) {
1714 ipcp_script_state = s_down;
1715 ipcp_script(_PATH_IPDOWN);
1717 break;
1718 case s_down:
1719 if (ipcp_fsm[0].state == OPENED) {
1720 ipcp_script_state = s_up;
1721 ipcp_script(_PATH_IPUP);
1723 break;
1729 * ipcp_script - Execute a script with arguments
1730 * interface-name tty-name speed local-IP remote-IP.
1732 static void
1733 ipcp_script(script)
1734 char *script;
1736 char strspeed[32], strlocal[32], strremote[32];
1737 char *argv[8];
1739 (void) slprintf(strspeed, sizeof(strspeed), "%d", baud_rate);
1740 (void) slprintf(strlocal, sizeof(strlocal), "%I",
1741 ipcp_gotoptions[0].ouraddr);
1742 (void) slprintf(strremote, sizeof(strremote), "%I",
1743 ipcp_hisoptions[0].hisaddr);
1745 argv[0] = script;
1746 argv[1] = ifname;
1747 argv[2] = devnam;
1748 argv[3] = strspeed;
1749 argv[4] = strlocal;
1750 argv[5] = strremote;
1751 argv[6] = ipparam;
1752 argv[7] = NULL;
1753 ipcp_script_pid = run_program(script, argv, 0, ipcp_script_done, NULL);
1757 * create_resolv - create the replacement resolv.conf file
1759 static void
1760 create_resolv(peerdns1, peerdns2)
1761 u_int32_t peerdns1, peerdns2;
1763 FILE *f;
1765 f = fopen(_PATH_RESOLV, "w");
1766 if (f == NULL) {
1767 error("Failed to create %s: %m", _PATH_RESOLV);
1768 return;
1771 if (peerdns1)
1772 if (fprintf(f, "nameserver %s\n", ip_ntoa(peerdns1)) <= 0)
1773 error("Write failed to %s: %m", _PATH_RESOLV);
1775 if (peerdns2)
1776 if (fprintf(f, "nameserver %s\n", ip_ntoa(peerdns2)) <= 0)
1777 error("Write failed to %s: %m", _PATH_RESOLV);
1779 if (fclose(f) != 0)
1780 error("Failed to close %s: %m", _PATH_RESOLV);
1784 * ipcp_printpkt - print the contents of an IPCP packet.
1786 static int
1787 ipcp_printpkt(p, plen, printer, arg)
1788 u_char *p;
1789 int plen;
1790 void (*printer) __P((void *, const char *, ...));
1791 void *arg;
1793 int code, id, len, olen;
1794 u_char *pstart, *optend;
1795 u_short cishort;
1796 u_int32_t cilong;
1798 if (plen < HEADERLEN)
1799 return 0;
1800 pstart = p;
1801 GETCHAR(code, p);
1802 GETCHAR(id, p);
1803 GETSHORT(len, p);
1804 if (len < HEADERLEN || len > plen)
1805 return 0;
1807 printer(arg, " %s id=0x%x", code_name(code, 1), id);
1808 len -= HEADERLEN;
1809 switch (code) {
1810 case CODE_CONFREQ:
1811 case CODE_CONFACK:
1812 case CODE_CONFNAK:
1813 case CODE_CONFREJ:
1814 /* print option list */
1815 while (len >= 2) {
1816 GETCHAR(code, p);
1817 GETCHAR(olen, p);
1818 p -= 2;
1819 if (olen < 2 || olen > len) {
1820 break;
1822 printer(arg, " <");
1823 len -= olen;
1824 optend = p + olen;
1825 switch (code) {
1826 case CI_ADDRS:
1827 if (olen == CILEN_ADDRS) {
1828 p += 2;
1829 GETNLONG(cilong, p);
1830 printer(arg, "addrs %I", cilong);
1831 GETNLONG(cilong, p);
1832 printer(arg, " %I", cilong);
1834 break;
1835 case CI_COMPRESSTYPE:
1836 if (olen >= CILEN_COMPRESS) {
1837 p += 2;
1838 GETSHORT(cishort, p);
1839 printer(arg, "compress ");
1840 switch (cishort) {
1841 case IPCP_VJ_COMP:
1842 printer(arg, "VJ");
1843 break;
1844 case IPCP_VJ_COMP_OLD:
1845 printer(arg, "old-VJ");
1846 break;
1847 default:
1848 printer(arg, "0x%x", cishort);
1851 break;
1852 case CI_ADDR:
1853 if (olen == CILEN_ADDR) {
1854 p += 2;
1855 GETNLONG(cilong, p);
1856 printer(arg, "addr %I", cilong);
1858 break;
1859 case CI_MS_DNS1:
1860 case CI_MS_DNS2:
1861 p += 2;
1862 GETNLONG(cilong, p);
1863 printer(arg, "ms-dns%d %I", (code == CI_MS_DNS1 ? 1 : 2),
1864 cilong);
1865 break;
1866 case CI_MS_WINS1:
1867 case CI_MS_WINS2:
1868 p += 2;
1869 GETNLONG(cilong, p);
1870 printer(arg, "ms-wins%d %I", (code == CI_MS_WINS1 ? 1 : 2),
1871 cilong);
1872 break;
1873 case CI_SUBNET:
1874 p += 2;
1875 GETNLONG(cilong, p);
1876 printer(arg, "subnet %I", cilong);
1877 break;
1879 while (p < optend) {
1880 GETCHAR(code, p);
1881 printer(arg, " %.2x", code);
1883 printer(arg, ">");
1885 break;
1887 case CODE_TERMACK:
1888 case CODE_TERMREQ:
1889 if (len > 0 && *p >= ' ' && *p < 0x7f) {
1890 printer(arg, " ");
1891 print_string((char *)p, len, printer, arg);
1892 p += len;
1893 len = 0;
1895 break;
1898 /* print the rest of the bytes in the packet */
1899 for (; len > 0; --len) {
1900 GETCHAR(code, p);
1901 printer(arg, " %.2x", code);
1904 return p - pstart;
1907 char *
1908 tcp_flag_decode(val)
1909 int val;
1911 static char buf[32];
1912 char *cp = buf;
1914 if (val & TH_URG)
1915 *cp++ = 'U';
1916 if (val & TH_ACK)
1917 *cp++ = 'A';
1918 if (val & TH_PUSH)
1919 *cp++ = 'P';
1920 if (val & TH_RST)
1921 *cp++ = 'R';
1922 if (val & TH_SYN)
1923 *cp++ = 'S';
1924 if (val & TH_FIN)
1925 *cp++ = 'F';
1926 if (cp != buf)
1927 *cp++ = ' ';
1928 *cp = '\0';
1929 return buf;
1933 * ip_active_pkt - see if this IP packet is worth bringing the link up for.
1934 * We don't bring the link up for IP fragments or for TCP FIN packets
1935 * with no data.
1938 static int
1939 ip_active_pkt(pkt, len)
1940 u_char *pkt;
1941 int len;
1943 u_char *tcp;
1944 struct protoent *pep;
1945 int val;
1946 int hlen;
1947 char buf[32], *cp;
1948 u_int32_t src, dst;
1950 len -= PPP_HDRLEN;
1951 pkt += PPP_HDRLEN;
1952 if (len < IP_HDRLEN) {
1953 dbglog("IP packet of length %d is not activity", len);
1954 return 0;
1956 src = get_ipsrc(pkt);
1957 dst = get_ipdst(pkt);
1958 if ((get_ipoff(pkt) & IP_OFFMASK) != 0) {
1959 dbglog("IP fragment from %I->%I is not activity", src, dst);
1960 return 0;
1962 val = get_ipproto(pkt);
1963 if (val != IPPROTO_TCP) {
1964 if (debug) {
1965 if ((pep = getprotobynumber(val)) != NULL) {
1966 cp = pep->p_name;
1967 } else {
1968 (void) slprintf(buf, sizeof (buf), "IP proto %d", val);
1969 cp = buf;
1971 info("%s from %I->%I is activity", cp, src, dst);
1973 return 1;
1975 hlen = get_iphl(pkt) * 4;
1976 if (len < hlen + TCP_HDRLEN) {
1977 dbglog("Bad TCP length %d<%d+%d %I->%I is not activity", len, hlen,
1978 TCP_HDRLEN, src, dst);
1979 return 0;
1981 tcp = pkt + hlen;
1982 val = get_tcpflags(tcp);
1983 hlen += get_tcpoff(tcp) * 4;
1984 if ((val & TH_FIN) != 0 && len == hlen) {
1985 dbglog("Empty TCP FIN %I->%I is not activity", src, dst);
1986 return 0;
1988 info("TCP %d data %s%I->%I is activity", len - hlen,
1989 tcp_flag_decode(get_tcpflags(tcp)), src, dst);
1990 return 1;
1993 static void
1994 ipcp_print_stat(unit, strptr)
1995 int unit;
1996 FILE *strptr;
1998 ipcp_options *go = &ipcp_gotoptions[unit];
1999 ipcp_options *ho = &ipcp_hisoptions[unit];
2000 char *proto_name = ipcp_protent.name;
2002 if (!ipcp_protent.enabled_flag) {
2003 (void) flprintf(strptr, "%s disabled\n", proto_name);
2004 return;
2007 (void) flprintf(strptr, "%s state: %s", proto_name,
2008 fsm_state(ipcp_fsm[unit].state));
2009 (void) flprintf(strptr, "%s local %I remote %I", proto_name, go->ouraddr,
2010 ho->ouraddr);