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