root/src/router/pppd.new/pppd/ipcp.c

Revision 12373, 56.6 kB (checked in by BrainSlayer, 5 months ago)

wins patch for stupid 3g isp's

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