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