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