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