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