]> git.ozlabs.org Git - ppp.git/blob - pppd/ipcp.c
Move the tty-related stuff out to tty.c as far as possible.
[ppp.git] / pppd / ipcp.c
1 /*
2  * ipcp.c - PPP IP Control Protocol.
3  *
4  * Copyright (c) 1989 Carnegie Mellon University.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms are permitted
8  * provided that the above copyright notice and this paragraph are
9  * duplicated in all such forms and that any documentation,
10  * advertising materials, and other materials related to such
11  * distribution and use acknowledge that the software was developed
12  * by Carnegie Mellon University.  The name of the
13  * University may not be used to endorse or promote products derived
14  * from this software without specific prior written permission.
15  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18  */
19
20 #define RCSID   "$Id: ipcp.c,v 1.55 2000/06/30 04:54:20 paulus Exp $"
21
22 /*
23  * TODO:
24  */
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <netdb.h>
29 #include <sys/param.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <arpa/inet.h>
34
35 #include "pppd.h"
36 #include "fsm.h"
37 #include "ipcp.h"
38 #include "pathnames.h"
39
40 static const char rcsid[] = RCSID;
41
42 /* global vars */
43 ipcp_options ipcp_wantoptions[NUM_PPP]; /* Options that we want to request */
44 ipcp_options ipcp_gotoptions[NUM_PPP];  /* Options that peer ack'd */
45 ipcp_options ipcp_allowoptions[NUM_PPP];        /* Options we allow peer to request */
46 ipcp_options ipcp_hisoptions[NUM_PPP];  /* Options that we ack'd */
47
48 bool    disable_defaultip = 0;  /* Don't use hostname for default IP adrs */
49
50 /* Hook for a plugin to know when IP protocol has come up */
51 void (*ip_up_hook) __P((void)) = NULL;
52
53 /* Hook for a plugin to know when IP protocol has come down */
54 void (*ip_down_hook) __P((void)) = NULL;
55
56 /* Hook for a plugin to choose the remote IP address */
57 void (*ip_choose_hook) __P((u_int32_t *)) = NULL;
58
59 /* local vars */
60 static int default_route_set[NUM_PPP];  /* Have set up a default route */
61 static int proxy_arp_set[NUM_PPP];      /* Have created proxy arp entry */
62 static bool usepeerdns;                 /* Ask peer for DNS addrs */
63 static int ipcp_is_up;                  /* have called np_up() */
64 static bool ask_for_local;              /* request our address from peer */
65
66 /*
67  * Callbacks for fsm code.  (CI = Configuration Information)
68  */
69 static void ipcp_resetci __P((fsm *));  /* Reset our CI */
70 static int  ipcp_cilen __P((fsm *));            /* Return length of our CI */
71 static void ipcp_addci __P((fsm *, u_char *, int *)); /* Add our CI */
72 static int  ipcp_ackci __P((fsm *, u_char *, int));     /* Peer ack'd our CI */
73 static int  ipcp_nakci __P((fsm *, u_char *, int));     /* Peer nak'd our CI */
74 static int  ipcp_rejci __P((fsm *, u_char *, int));     /* Peer rej'd our CI */
75 static int  ipcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */
76 static void ipcp_up __P((fsm *));               /* We're UP */
77 static void ipcp_down __P((fsm *));             /* We're DOWN */
78 static void ipcp_finished __P((fsm *)); /* Don't need lower layer */
79
80 fsm ipcp_fsm[NUM_PPP];          /* IPCP fsm structure */
81
82 static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
83     ipcp_resetci,               /* Reset our Configuration Information */
84     ipcp_cilen,                 /* Length of our Configuration Information */
85     ipcp_addci,                 /* Add our Configuration Information */
86     ipcp_ackci,                 /* ACK our Configuration Information */
87     ipcp_nakci,                 /* NAK our Configuration Information */
88     ipcp_rejci,                 /* Reject our Configuration Information */
89     ipcp_reqci,                 /* Request peer's Configuration Information */
90     ipcp_up,                    /* Called when fsm reaches OPENED state */
91     ipcp_down,                  /* Called when fsm leaves OPENED state */
92     NULL,                       /* Called when we want the lower layer up */
93     ipcp_finished,              /* Called when we want the lower layer down */
94     NULL,                       /* Called when Protocol-Reject received */
95     NULL,                       /* Retransmission is necessary */
96     NULL,                       /* Called to handle protocol-specific codes */
97     "IPCP"                      /* String name of protocol */
98 };
99
100 /*
101  * Command-line options.
102  */
103 static int setvjslots __P((char **));
104 static int setdnsaddr __P((char **));
105 static int setwinsaddr __P((char **));
106
107 static option_t ipcp_option_list[] = {
108     { "noip", o_bool, &ipcp_protent.enabled_flag,
109       "Disable IP and IPCP" },
110     { "-ip", o_bool, &ipcp_protent.enabled_flag,
111       "Disable IP and IPCP" },
112     { "novj", o_bool, &ipcp_wantoptions[0].neg_vj,
113       "Disable VJ compression", OPT_A2COPY, &ipcp_allowoptions[0].neg_vj },
114     { "-vj", o_bool, &ipcp_wantoptions[0].neg_vj,
115       "Disable VJ compression", OPT_A2COPY, &ipcp_allowoptions[0].neg_vj },
116     { "novjccomp", o_bool, &ipcp_wantoptions[0].cflag,
117       "Disable VJ connection-ID compression", OPT_A2COPY,
118       &ipcp_allowoptions[0].cflag },
119     { "-vjccomp", o_bool, &ipcp_wantoptions[0].cflag,
120       "Disable VJ connection-ID compression", OPT_A2COPY,
121       &ipcp_allowoptions[0].cflag },
122     { "vj-max-slots", 1, (void *)setvjslots,
123       "Set maximum VJ header slots" },
124     { "ipcp-accept-local", o_bool, &ipcp_wantoptions[0].accept_local,
125       "Accept peer's address for us", 1 },
126     { "ipcp-accept-remote", o_bool, &ipcp_wantoptions[0].accept_remote,
127       "Accept peer's address for it", 1 },
128     { "ipparam", o_string, &ipparam,
129       "Set ip script parameter" },
130     { "noipdefault", o_bool, &disable_defaultip,
131       "Don't use name for default IP adrs", 1 },
132     { "ms-dns", 1, (void *)setdnsaddr,
133       "DNS address for the peer's use" },
134     { "ms-wins", 1, (void *)setwinsaddr,
135       "Nameserver for SMB over TCP/IP for peer" },
136     { "ipcp-restart", o_int, &ipcp_fsm[0].timeouttime,
137       "Set timeout for IPCP" },
138     { "ipcp-max-terminate", o_int, &ipcp_fsm[0].maxtermtransmits,
139       "Set max #xmits for term-reqs" },
140     { "ipcp-max-configure", o_int, &ipcp_fsm[0].maxconfreqtransmits,
141       "Set max #xmits for conf-reqs" },
142     { "ipcp-max-failure", o_int, &ipcp_fsm[0].maxnakloops,
143       "Set max #conf-naks for IPCP" },
144     { "defaultroute", o_bool, &ipcp_wantoptions[0].default_route,
145       "Add default route", OPT_ENABLE|1, &ipcp_allowoptions[0].default_route },
146     { "nodefaultroute", o_bool, &ipcp_allowoptions[0].default_route,
147       "disable defaultroute option", OPT_A2COPY,
148       &ipcp_wantoptions[0].default_route },
149     { "-defaultroute", o_bool, &ipcp_allowoptions[0].default_route,
150       "disable defaultroute option", OPT_A2COPY,
151       &ipcp_wantoptions[0].default_route },
152     { "proxyarp", o_bool, &ipcp_wantoptions[0].proxy_arp,
153       "Add proxy ARP entry", OPT_ENABLE|1, &ipcp_allowoptions[0].proxy_arp },
154     { "noproxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
155       "disable proxyarp option", OPT_A2COPY,
156       &ipcp_wantoptions[0].proxy_arp },
157     { "-proxyarp", o_bool, &ipcp_allowoptions[0].proxy_arp,
158       "disable proxyarp option", OPT_A2COPY,
159       &ipcp_wantoptions[0].proxy_arp },
160     { "usepeerdns", o_bool, &usepeerdns,
161       "Ask peer for DNS address(es)", 1 },
162     { NULL }
163 };
164
165 /*
166  * Protocol entry points from main code.
167  */
168 static void ipcp_init __P((int));
169 static void ipcp_open __P((int));
170 static void ipcp_close __P((int, char *));
171 static void ipcp_lowerup __P((int));
172 static void ipcp_lowerdown __P((int));
173 static void ipcp_input __P((int, u_char *, int));
174 static void ipcp_protrej __P((int));
175 static int  ipcp_printpkt __P((u_char *, int,
176                                void (*) __P((void *, char *, ...)), void *));
177 static void ip_check_options __P((void));
178 static int  ip_demand_conf __P((int));
179 static int  ip_active_pkt __P((u_char *, int));
180 static void create_resolv __P((u_int32_t, u_int32_t));
181
182 struct protent ipcp_protent = {
183     PPP_IPCP,
184     ipcp_init,
185     ipcp_input,
186     ipcp_protrej,
187     ipcp_lowerup,
188     ipcp_lowerdown,
189     ipcp_open,
190     ipcp_close,
191     ipcp_printpkt,
192     NULL,
193     1,
194     "IPCP",
195     "IP",
196     ipcp_option_list,
197     ip_check_options,
198     ip_demand_conf,
199     ip_active_pkt
200 };
201
202 static void ipcp_clear_addrs __P((int, u_int32_t, u_int32_t));
203 static void ipcp_script __P((char *));          /* Run an up/down script */
204 static void ipcp_script_done __P((void *));
205
206 /*
207  * Lengths of configuration options.
208  */
209 #define CILEN_VOID      2
210 #define CILEN_COMPRESS  4       /* min length for compression protocol opt. */
211 #define CILEN_VJ        6       /* length for RFC1332 Van-Jacobson opt. */
212 #define CILEN_ADDR      6       /* new-style single address option */
213 #define CILEN_ADDRS     10      /* old-style dual address option */
214
215
216 #define CODENAME(x)     ((x) == CONFACK ? "ACK" : \
217                          (x) == CONFNAK ? "NAK" : "REJ")
218
219 /*
220  * This state variable is used to ensure that we don't
221  * run an ipcp-up/down script while one is already running.
222  */
223 static enum script_state {
224     s_down,
225     s_up,
226 } ipcp_script_state;
227 static pid_t ipcp_script_pid;
228
229 /*
230  * Make a string representation of a network IP address.
231  */
232 char *
233 ip_ntoa(ipaddr)
234 u_int32_t ipaddr;
235 {
236     static char b[64];
237
238     slprintf(b, sizeof(b), "%I", ipaddr);
239     return b;
240 }
241
242 /*
243  * Option parsing.
244  */
245
246 /*
247  * setvjslots - set maximum number of connection slots for VJ compression
248  */
249 static int
250 setvjslots(argv)
251     char **argv;
252 {
253     int value;
254
255     if (!int_option(*argv, &value))
256         return 0;
257     if (value < 2 || value > 16) {
258         option_error("vj-max-slots value must be between 2 and 16");
259         return 0;
260     }
261     ipcp_wantoptions [0].maxslotindex =
262         ipcp_allowoptions[0].maxslotindex = value - 1;
263     return 1;
264 }
265
266 /*
267  * setdnsaddr - set the dns address(es)
268  */
269 static int
270 setdnsaddr(argv)
271     char **argv;
272 {
273     u_int32_t dns;
274     struct hostent *hp;
275
276     dns = inet_addr(*argv);
277     if (dns == (u_int32_t) -1) {
278         if ((hp = gethostbyname(*argv)) == NULL) {
279             option_error("invalid address parameter '%s' for ms-dns option",
280                          *argv);
281             return 0;
282         }
283         dns = *(u_int32_t *)hp->h_addr;
284     }
285
286     /* if there is no primary then update it. */
287     if (ipcp_allowoptions[0].dnsaddr[0] == 0)
288         ipcp_allowoptions[0].dnsaddr[0] = dns;
289
290     /* always set the secondary address value to the same value. */
291     ipcp_allowoptions[0].dnsaddr[1] = dns;
292
293     return (1);
294 }
295
296 /*
297  * setwinsaddr - set the wins address(es)
298  * This is primrarly used with the Samba package under UNIX or for pointing
299  * the caller to the existing WINS server on a Windows NT platform.
300  */
301 static int
302 setwinsaddr(argv)
303     char **argv;
304 {
305     u_int32_t wins;
306     struct hostent *hp;
307
308     wins = inet_addr(*argv);
309     if (wins == (u_int32_t) -1) {
310         if ((hp = gethostbyname(*argv)) == NULL) {
311             option_error("invalid address parameter '%s' for ms-wins option",
312                          *argv);
313             return 0;
314         }
315         wins = *(u_int32_t *)hp->h_addr;
316     }
317
318     /* if there is no primary then update it. */
319     if (ipcp_allowoptions[0].winsaddr[0] == 0)
320         ipcp_allowoptions[0].winsaddr[0] = wins;
321
322     /* always set the secondary address value to the same value. */
323     ipcp_allowoptions[0].winsaddr[1] = wins;
324
325     return (1);
326 }
327
328
329 /*
330  * ipcp_init - Initialize IPCP.
331  */
332 static void
333 ipcp_init(unit)
334     int unit;
335 {
336     fsm *f = &ipcp_fsm[unit];
337     ipcp_options *wo = &ipcp_wantoptions[unit];
338     ipcp_options *ao = &ipcp_allowoptions[unit];
339
340     f->unit = unit;
341     f->protocol = PPP_IPCP;
342     f->callbacks = &ipcp_callbacks;
343     fsm_init(&ipcp_fsm[unit]);
344
345     memset(wo, 0, sizeof(*wo));
346     memset(ao, 0, sizeof(*ao));
347
348     wo->neg_addr = 1;
349     wo->neg_vj = 1;
350     wo->vj_protocol = IPCP_VJ_COMP;
351     wo->maxslotindex = MAX_STATES - 1; /* really max index */
352     wo->cflag = 1;
353
354
355     /* max slots and slot-id compression are currently hardwired in */
356     /* ppp_if.c to 16 and 1, this needs to be changed (among other */
357     /* things) gmc */
358
359     ao->neg_addr = 1;
360     ao->neg_vj = 1;
361     ao->maxslotindex = MAX_STATES - 1;
362     ao->cflag = 1;
363
364     /*
365      * XXX These control whether the user may use the proxyarp
366      * and defaultroute options.
367      */
368     ao->proxy_arp = 1;
369     ao->default_route = 1;
370 }
371
372
373 /*
374  * ipcp_open - IPCP is allowed to come up.
375  */
376 static void
377 ipcp_open(unit)
378     int unit;
379 {
380     fsm_open(&ipcp_fsm[unit]);
381 }
382
383
384 /*
385  * ipcp_close - Take IPCP down.
386  */
387 static void
388 ipcp_close(unit, reason)
389     int unit;
390     char *reason;
391 {
392     fsm_close(&ipcp_fsm[unit], reason);
393 }
394
395
396 /*
397  * ipcp_lowerup - The lower layer is up.
398  */
399 static void
400 ipcp_lowerup(unit)
401     int unit;
402 {
403     fsm_lowerup(&ipcp_fsm[unit]);
404 }
405
406
407 /*
408  * ipcp_lowerdown - The lower layer is down.
409  */
410 static void
411 ipcp_lowerdown(unit)
412     int unit;
413 {
414     fsm_lowerdown(&ipcp_fsm[unit]);
415 }
416
417
418 /*
419  * ipcp_input - Input IPCP packet.
420  */
421 static void
422 ipcp_input(unit, p, len)
423     int unit;
424     u_char *p;
425     int len;
426 {
427     fsm_input(&ipcp_fsm[unit], p, len);
428 }
429
430
431 /*
432  * ipcp_protrej - A Protocol-Reject was received for IPCP.
433  *
434  * Pretend the lower layer went down, so we shut up.
435  */
436 static void
437 ipcp_protrej(unit)
438     int unit;
439 {
440     fsm_lowerdown(&ipcp_fsm[unit]);
441 }
442
443
444 /*
445  * ipcp_resetci - Reset our CI.
446  * Called by fsm_sconfreq, Send Configure Request.
447  */
448 static void
449 ipcp_resetci(f)
450     fsm *f;
451 {
452     ipcp_options *wo = &ipcp_wantoptions[f->unit];
453     ipcp_options *go = &ipcp_gotoptions[f->unit];
454
455     wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr;
456     if (wo->ouraddr == 0)
457         wo->accept_local = 1;
458     if (wo->hisaddr == 0)
459         wo->accept_remote = 1;
460     wo->req_dns1 = usepeerdns;  /* Request DNS addresses from the peer */
461     wo->req_dns2 = usepeerdns;
462     *go = *wo;
463     if (!ask_for_local)
464         go->ouraddr = 0;
465     if (ip_choose_hook)
466         ip_choose_hook(&wo->hisaddr);
467 }
468
469
470 /*
471  * ipcp_cilen - Return length of our CI.
472  * Called by fsm_sconfreq, Send Configure Request.
473  */
474 static int
475 ipcp_cilen(f)
476     fsm *f;
477 {
478     ipcp_options *go = &ipcp_gotoptions[f->unit];
479     ipcp_options *wo = &ipcp_wantoptions[f->unit];
480     ipcp_options *ho = &ipcp_hisoptions[f->unit];
481
482 #define LENCIVJ(neg, old)       (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0)
483 #define LENCIADDR(neg, old)     (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0)
484 #define LENCIDNS(neg)           (neg ? (CILEN_ADDR) : 0)
485
486     /*
487      * First see if we want to change our options to the old
488      * forms because we have received old forms from the peer.
489      */
490     if (wo->neg_addr && !go->neg_addr && !go->old_addrs) {
491         /* use the old style of address negotiation */
492         go->neg_addr = 1;
493         go->old_addrs = 1;
494     }
495     if (wo->neg_vj && !go->neg_vj && !go->old_vj) {
496         /* try an older style of VJ negotiation */
497         /* use the old style only if the peer did */
498         if (ho->neg_vj && ho->old_vj) {
499             go->neg_vj = 1;
500             go->old_vj = 1;
501             go->vj_protocol = ho->vj_protocol;
502         }
503     }
504
505     return (LENCIADDR(go->neg_addr, go->old_addrs) +
506             LENCIVJ(go->neg_vj, go->old_vj) +
507             LENCIDNS(go->req_dns1) +
508             LENCIDNS(go->req_dns2)) ;
509 }
510
511
512 /*
513  * ipcp_addci - Add our desired CIs to a packet.
514  * Called by fsm_sconfreq, Send Configure Request.
515  */
516 static void
517 ipcp_addci(f, ucp, lenp)
518     fsm *f;
519     u_char *ucp;
520     int *lenp;
521 {
522     ipcp_options *go = &ipcp_gotoptions[f->unit];
523     int len = *lenp;
524
525 #define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \
526     if (neg) { \
527         int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
528         if (len >= vjlen) { \
529             PUTCHAR(opt, ucp); \
530             PUTCHAR(vjlen, ucp); \
531             PUTSHORT(val, ucp); \
532             if (!old) { \
533                 PUTCHAR(maxslotindex, ucp); \
534                 PUTCHAR(cflag, ucp); \
535             } \
536             len -= vjlen; \
537         } else \
538             neg = 0; \
539     }
540
541 #define ADDCIADDR(opt, neg, old, val1, val2) \
542     if (neg) { \
543         int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
544         if (len >= addrlen) { \
545             u_int32_t l; \
546             PUTCHAR(opt, ucp); \
547             PUTCHAR(addrlen, ucp); \
548             l = ntohl(val1); \
549             PUTLONG(l, ucp); \
550             if (old) { \
551                 l = ntohl(val2); \
552                 PUTLONG(l, ucp); \
553             } \
554             len -= addrlen; \
555         } else \
556             neg = 0; \
557     }
558
559 #define ADDCIDNS(opt, neg, addr) \
560     if (neg) { \
561         if (len >= CILEN_ADDR) { \
562             u_int32_t l; \
563             PUTCHAR(opt, ucp); \
564             PUTCHAR(CILEN_ADDR, ucp); \
565             l = ntohl(addr); \
566             PUTLONG(l, ucp); \
567             len -= CILEN_ADDR; \
568         } else \
569             neg = 0; \
570     }
571
572     ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
573               go->old_addrs, go->ouraddr, go->hisaddr);
574
575     ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
576             go->maxslotindex, go->cflag);
577
578     ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
579
580     ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
581
582     *lenp -= len;
583 }
584
585
586 /*
587  * ipcp_ackci - Ack our CIs.
588  * Called by fsm_rconfack, Receive Configure ACK.
589  *
590  * Returns:
591  *      0 - Ack was bad.
592  *      1 - Ack was good.
593  */
594 static int
595 ipcp_ackci(f, p, len)
596     fsm *f;
597     u_char *p;
598     int len;
599 {
600     ipcp_options *go = &ipcp_gotoptions[f->unit];
601     u_short cilen, citype, cishort;
602     u_int32_t cilong;
603     u_char cimaxslotindex, cicflag;
604
605     /*
606      * CIs must be in exactly the same order that we sent...
607      * Check packet length and CI length at each step.
608      * If we find any deviations, then this packet is bad.
609      */
610
611 #define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \
612     if (neg) { \
613         int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
614         if ((len -= vjlen) < 0) \
615             goto bad; \
616         GETCHAR(citype, p); \
617         GETCHAR(cilen, p); \
618         if (cilen != vjlen || \
619             citype != opt)  \
620             goto bad; \
621         GETSHORT(cishort, p); \
622         if (cishort != val) \
623             goto bad; \
624         if (!old) { \
625             GETCHAR(cimaxslotindex, p); \
626             if (cimaxslotindex != maxslotindex) \
627                 goto bad; \
628             GETCHAR(cicflag, p); \
629             if (cicflag != cflag) \
630                 goto bad; \
631         } \
632     }
633
634 #define ACKCIADDR(opt, neg, old, val1, val2) \
635     if (neg) { \
636         int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
637         u_int32_t l; \
638         if ((len -= addrlen) < 0) \
639             goto bad; \
640         GETCHAR(citype, p); \
641         GETCHAR(cilen, p); \
642         if (cilen != addrlen || \
643             citype != opt) \
644             goto bad; \
645         GETLONG(l, p); \
646         cilong = htonl(l); \
647         if (val1 != cilong) \
648             goto bad; \
649         if (old) { \
650             GETLONG(l, p); \
651             cilong = htonl(l); \
652             if (val2 != cilong) \
653                 goto bad; \
654         } \
655     }
656
657 #define ACKCIDNS(opt, neg, addr) \
658     if (neg) { \
659         u_int32_t l; \
660         if ((len -= CILEN_ADDR) < 0) \
661             goto bad; \
662         GETCHAR(citype, p); \
663         GETCHAR(cilen, p); \
664         if (cilen != CILEN_ADDR || citype != opt) \
665             goto bad; \
666         GETLONG(l, p); \
667         cilong = htonl(l); \
668         if (addr != cilong) \
669             goto bad; \
670     }
671
672     ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
673               go->old_addrs, go->ouraddr, go->hisaddr);
674
675     ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
676             go->maxslotindex, go->cflag);
677
678     ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
679
680     ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
681
682     /*
683      * If there are any remaining CIs, then this packet is bad.
684      */
685     if (len != 0)
686         goto bad;
687     return (1);
688
689 bad:
690     IPCPDEBUG(("ipcp_ackci: received bad Ack!"));
691     return (0);
692 }
693
694 /*
695  * ipcp_nakci - Peer has sent a NAK for some of our CIs.
696  * This should not modify any state if the Nak is bad
697  * or if IPCP is in the OPENED state.
698  * Calback from fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject.
699  *
700  * Returns:
701  *      0 - Nak was bad.
702  *      1 - Nak was good.
703  */
704 static int
705 ipcp_nakci(f, p, len)
706     fsm *f;
707     u_char *p;
708     int len;
709 {
710     ipcp_options *go = &ipcp_gotoptions[f->unit];
711     u_char cimaxslotindex, cicflag;
712     u_char citype, cilen, *next;
713     u_short cishort;
714     u_int32_t ciaddr1, ciaddr2, l, cidnsaddr;
715     ipcp_options no;            /* options we've seen Naks for */
716     ipcp_options try;           /* options to request next time */
717
718     BZERO(&no, sizeof(no));
719     try = *go;
720
721     /*
722      * Any Nak'd CIs must be in exactly the same order that we sent.
723      * Check packet length and CI length at each step.
724      * If we find any deviations, then this packet is bad.
725      */
726 #define NAKCIADDR(opt, neg, old, code) \
727     if (go->neg && \
728         len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \
729         p[1] == cilen && \
730         p[0] == opt) { \
731         len -= cilen; \
732         INCPTR(2, p); \
733         GETLONG(l, p); \
734         ciaddr1 = htonl(l); \
735         if (old) { \
736             GETLONG(l, p); \
737             ciaddr2 = htonl(l); \
738             no.old_addrs = 1; \
739         } else \
740             ciaddr2 = 0; \
741         no.neg = 1; \
742         code \
743     }
744
745 #define NAKCIVJ(opt, neg, code) \
746     if (go->neg && \
747         ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \
748         len >= cilen && \
749         p[0] == opt) { \
750         len -= cilen; \
751         INCPTR(2, p); \
752         GETSHORT(cishort, p); \
753         no.neg = 1; \
754         code \
755     }
756
757 #define NAKCIDNS(opt, neg, code) \
758     if (go->neg && \
759         ((cilen = p[1]) == CILEN_ADDR) && \
760         len >= cilen && \
761         p[0] == opt) { \
762         len -= cilen; \
763         INCPTR(2, p); \
764         GETLONG(l, p); \
765         cidnsaddr = htonl(l); \
766         no.neg = 1; \
767         code \
768     }
769
770     /*
771      * Accept the peer's idea of {our,his} address, if different
772      * from our idea, only if the accept_{local,remote} flag is set.
773      */
774     NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs,
775               if (go->accept_local && ciaddr1) { /* Do we know our address? */
776                   try.ouraddr = ciaddr1;
777               }
778               if (go->accept_remote && ciaddr2) { /* Does he know his? */
779                   try.hisaddr = ciaddr2;
780               }
781               );
782
783     /*
784      * Accept the peer's value of maxslotindex provided that it
785      * is less than what we asked for.  Turn off slot-ID compression
786      * if the peer wants.  Send old-style compress-type option if
787      * the peer wants.
788      */
789     NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
790             if (cilen == CILEN_VJ) {
791                 GETCHAR(cimaxslotindex, p);
792                 GETCHAR(cicflag, p);
793                 if (cishort == IPCP_VJ_COMP) {
794                     try.old_vj = 0;
795                     if (cimaxslotindex < go->maxslotindex)
796                         try.maxslotindex = cimaxslotindex;
797                     if (!cicflag)
798                         try.cflag = 0;
799                 } else {
800                     try.neg_vj = 0;
801                 }
802             } else {
803                 if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) {
804                     try.old_vj = 1;
805                     try.vj_protocol = cishort;
806                 } else {
807                     try.neg_vj = 0;
808                 }
809             }
810             );
811
812     NAKCIDNS(CI_MS_DNS1, req_dns1,
813             try.dnsaddr[0] = cidnsaddr;
814             );
815
816     NAKCIDNS(CI_MS_DNS2, req_dns2,
817             try.dnsaddr[1] = cidnsaddr;
818             );
819
820     /*
821      * There may be remaining CIs, if the peer is requesting negotiation
822      * on an option that we didn't include in our request packet.
823      * If they want to negotiate about IP addresses, we comply.
824      * If they want us to ask for compression, we refuse.
825      */
826     while (len > CILEN_VOID) {
827         GETCHAR(citype, p);
828         GETCHAR(cilen, p);
829         if( (len -= cilen) < 0 )
830             goto bad;
831         next = p + cilen - 2;
832
833         switch (citype) {
834         case CI_COMPRESSTYPE:
835             if (go->neg_vj || no.neg_vj ||
836                 (cilen != CILEN_VJ && cilen != CILEN_COMPRESS))
837                 goto bad;
838             no.neg_vj = 1;
839             break;
840         case CI_ADDRS:
841             if ((go->neg_addr && go->old_addrs) || no.old_addrs
842                 || cilen != CILEN_ADDRS)
843                 goto bad;
844             try.neg_addr = 1;
845             try.old_addrs = 1;
846             GETLONG(l, p);
847             ciaddr1 = htonl(l);
848             if (ciaddr1 && go->accept_local)
849                 try.ouraddr = ciaddr1;
850             GETLONG(l, p);
851             ciaddr2 = htonl(l);
852             if (ciaddr2 && go->accept_remote)
853                 try.hisaddr = ciaddr2;
854             no.old_addrs = 1;
855             break;
856         case CI_ADDR:
857             if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR)
858                 goto bad;
859             try.old_addrs = 0;
860             GETLONG(l, p);
861             ciaddr1 = htonl(l);
862             if (ciaddr1 && go->accept_local)
863                 try.ouraddr = ciaddr1;
864             if (try.ouraddr != 0)
865                 try.neg_addr = 1;
866             no.neg_addr = 1;
867             break;
868         }
869         p = next;
870     }
871
872     /*
873      * OK, the Nak is good.  Now we can update state.
874      * If there are any remaining options, we ignore them.
875      */
876     if (f->state != OPENED)
877         *go = try;
878
879     return 1;
880
881 bad:
882     IPCPDEBUG(("ipcp_nakci: received bad Nak!"));
883     return 0;
884 }
885
886
887 /*
888  * ipcp_rejci - Reject some of our CIs.
889  * Callback from fsm_rconfnakrej.
890  */
891 static int
892 ipcp_rejci(f, p, len)
893     fsm *f;
894     u_char *p;
895     int len;
896 {
897     ipcp_options *go = &ipcp_gotoptions[f->unit];
898     u_char cimaxslotindex, ciflag, cilen;
899     u_short cishort;
900     u_int32_t cilong;
901     ipcp_options try;           /* options to request next time */
902
903     try = *go;
904     /*
905      * Any Rejected CIs must be in exactly the same order that we sent.
906      * Check packet length and CI length at each step.
907      * If we find any deviations, then this packet is bad.
908      */
909 #define REJCIADDR(opt, neg, old, val1, val2) \
910     if (go->neg && \
911         len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \
912         p[1] == cilen && \
913         p[0] == opt) { \
914         u_int32_t l; \
915         len -= cilen; \
916         INCPTR(2, p); \
917         GETLONG(l, p); \
918         cilong = htonl(l); \
919         /* Check rejected value. */ \
920         if (cilong != val1) \
921             goto bad; \
922         if (old) { \
923             GETLONG(l, p); \
924             cilong = htonl(l); \
925             /* Check rejected value. */ \
926             if (cilong != val2) \
927                 goto bad; \
928         } \
929         try.neg = 0; \
930     }
931
932 #define REJCIVJ(opt, neg, val, old, maxslot, cflag) \
933     if (go->neg && \
934         p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \
935         len >= p[1] && \
936         p[0] == opt) { \
937         len -= p[1]; \
938         INCPTR(2, p); \
939         GETSHORT(cishort, p); \
940         /* Check rejected value. */  \
941         if (cishort != val) \
942             goto bad; \
943         if (!old) { \
944            GETCHAR(cimaxslotindex, p); \
945            if (cimaxslotindex != maxslot) \
946              goto bad; \
947            GETCHAR(ciflag, p); \
948            if (ciflag != cflag) \
949              goto bad; \
950         } \
951         try.neg = 0; \
952      }
953
954 #define REJCIDNS(opt, neg, dnsaddr) \
955     if (go->neg && \
956         ((cilen = p[1]) == CILEN_ADDR) && \
957         len >= cilen && \
958         p[0] == opt) { \
959         u_int32_t l; \
960         len -= cilen; \
961         INCPTR(2, p); \
962         GETLONG(l, p); \
963         cilong = htonl(l); \
964         /* Check rejected value. */ \
965         if (cilong != dnsaddr) \
966             goto bad; \
967         try.neg = 0; \
968     }
969
970
971     REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr,
972               go->old_addrs, go->ouraddr, go->hisaddr);
973
974     REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj,
975             go->maxslotindex, go->cflag);
976
977     REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]);
978
979     REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]);
980
981     /*
982      * If there are any remaining CIs, then this packet is bad.
983      */
984     if (len != 0)
985         goto bad;
986     /*
987      * Now we can update state.
988      */
989     if (f->state != OPENED)
990         *go = try;
991     return 1;
992
993 bad:
994     IPCPDEBUG(("ipcp_rejci: received bad Reject!"));
995     return 0;
996 }
997
998
999 /*
1000  * ipcp_reqci - Check the peer's requested CIs and send appropriate response.
1001  * Callback from fsm_rconfreq, Receive Configure Request
1002  *
1003  * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
1004  * appropriately.  If reject_if_disagree is non-zero, doesn't return
1005  * CONFNAK; returns CONFREJ if it can't return CONFACK.
1006  */
1007 static int
1008 ipcp_reqci(f, inp, len, reject_if_disagree)
1009     fsm *f;
1010     u_char *inp;                /* Requested CIs */
1011     int *len;                   /* Length of requested CIs */
1012     int reject_if_disagree;
1013 {
1014     ipcp_options *wo = &ipcp_wantoptions[f->unit];
1015     ipcp_options *ho = &ipcp_hisoptions[f->unit];
1016     ipcp_options *ao = &ipcp_allowoptions[f->unit];
1017     ipcp_options *go = &ipcp_gotoptions[f->unit];
1018     u_char *cip, *next;         /* Pointer to current and next CIs */
1019     u_short cilen, citype;      /* Parsed len, type */
1020     u_short cishort;            /* Parsed short value */
1021     u_int32_t tl, ciaddr1, ciaddr2;/* Parsed address values */
1022     int rc = CONFACK;           /* Final packet return code */
1023     int orc;                    /* Individual option return code */
1024     u_char *p;                  /* Pointer to next char to parse */
1025     u_char *ucp = inp;          /* Pointer to current output char */
1026     int l = *len;               /* Length left */
1027     u_char maxslotindex, cflag;
1028     int d;
1029
1030     /*
1031      * Reset all his options.
1032      */
1033     BZERO(ho, sizeof(*ho));
1034     
1035     /*
1036      * Process all his options.
1037      */
1038     next = inp;
1039     while (l) {
1040         orc = CONFACK;                  /* Assume success */
1041         cip = p = next;                 /* Remember begining of CI */
1042         if (l < 2 ||                    /* Not enough data for CI header or */
1043             p[1] < 2 ||                 /*  CI length too small or */
1044             p[1] > l) {                 /*  CI length too big? */
1045             IPCPDEBUG(("ipcp_reqci: bad CI length!"));
1046             orc = CONFREJ;              /* Reject bad CI */
1047             cilen = l;                  /* Reject till end of packet */
1048             l = 0;                      /* Don't loop again */
1049             goto endswitch;
1050         }
1051         GETCHAR(citype, p);             /* Parse CI type */
1052         GETCHAR(cilen, p);              /* Parse CI length */
1053         l -= cilen;                     /* Adjust remaining length */
1054         next += cilen;                  /* Step to next CI */
1055
1056         switch (citype) {               /* Check CI type */
1057         case CI_ADDRS:
1058             if (!ao->neg_addr ||
1059                 cilen != CILEN_ADDRS) { /* Check CI length */
1060                 orc = CONFREJ;          /* Reject CI */
1061                 break;
1062             }
1063
1064             /*
1065              * If he has no address, or if we both have his address but
1066              * disagree about it, then NAK it with our idea.
1067              * In particular, if we don't know his address, but he does,
1068              * then accept it.
1069              */
1070             GETLONG(tl, p);             /* Parse source address (his) */
1071             ciaddr1 = htonl(tl);
1072             if (ciaddr1 != wo->hisaddr
1073                 && (ciaddr1 == 0 || !wo->accept_remote)) {
1074                 orc = CONFNAK;
1075                 if (!reject_if_disagree) {
1076                     DECPTR(sizeof(u_int32_t), p);
1077                     tl = ntohl(wo->hisaddr);
1078                     PUTLONG(tl, p);
1079                 }
1080             } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
1081                 /*
1082                  * If neither we nor he knows his address, reject the option.
1083                  */
1084                 orc = CONFREJ;
1085                 wo->req_addr = 0;       /* don't NAK with 0.0.0.0 later */
1086                 break;
1087             }
1088
1089             /*
1090              * If he doesn't know our address, or if we both have our address
1091              * but disagree about it, then NAK it with our idea.
1092              */
1093             GETLONG(tl, p);             /* Parse desination address (ours) */
1094             ciaddr2 = htonl(tl);
1095             if (ciaddr2 != wo->ouraddr) {
1096                 if (ciaddr2 == 0 || !wo->accept_local) {
1097                     orc = CONFNAK;
1098                     if (!reject_if_disagree) {
1099                         DECPTR(sizeof(u_int32_t), p);
1100                         tl = ntohl(wo->ouraddr);
1101                         PUTLONG(tl, p);
1102                     }
1103                 } else {
1104                     go->ouraddr = ciaddr2;      /* accept peer's idea */
1105                 }
1106             }
1107
1108             ho->neg_addr = 1;
1109             ho->old_addrs = 1;
1110             ho->hisaddr = ciaddr1;
1111             ho->ouraddr = ciaddr2;
1112             break;
1113
1114         case CI_ADDR:
1115             if (!ao->neg_addr ||
1116                 cilen != CILEN_ADDR) {  /* Check CI length */
1117                 orc = CONFREJ;          /* Reject CI */
1118                 break;
1119             }
1120
1121             /*
1122              * If he has no address, or if we both have his address but
1123              * disagree about it, then NAK it with our idea.
1124              * In particular, if we don't know his address, but he does,
1125              * then accept it.
1126              */
1127             GETLONG(tl, p);     /* Parse source address (his) */
1128             ciaddr1 = htonl(tl);
1129             if (ciaddr1 != wo->hisaddr
1130                 && (ciaddr1 == 0 || !wo->accept_remote)) {
1131                 orc = CONFNAK;
1132                 if (!reject_if_disagree) {
1133                     DECPTR(sizeof(u_int32_t), p);
1134                     tl = ntohl(wo->hisaddr);
1135                     PUTLONG(tl, p);
1136                 }
1137             } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
1138                 /*
1139                  * Don't ACK an address of 0.0.0.0 - reject it instead.
1140                  */
1141                 orc = CONFREJ;
1142                 wo->req_addr = 0;       /* don't NAK with 0.0.0.0 later */
1143                 break;
1144             }
1145         
1146             ho->neg_addr = 1;
1147             ho->hisaddr = ciaddr1;
1148             break;
1149
1150         case CI_MS_DNS1:
1151         case CI_MS_DNS2:
1152             /* Microsoft primary or secondary DNS request */
1153             d = citype == CI_MS_DNS2;
1154
1155             /* If we do not have a DNS address then we cannot send it */
1156             if (ao->dnsaddr[d] == 0 ||
1157                 cilen != CILEN_ADDR) {  /* Check CI length */
1158                 orc = CONFREJ;          /* Reject CI */
1159                 break;
1160             }
1161             GETLONG(tl, p);
1162             if (htonl(tl) != ao->dnsaddr[d]) {
1163                 DECPTR(sizeof(u_int32_t), p);
1164                 tl = ntohl(ao->dnsaddr[d]);
1165                 PUTLONG(tl, p);
1166                 orc = CONFNAK;
1167             }
1168             break;
1169
1170         case CI_MS_WINS1:
1171         case CI_MS_WINS2:
1172             /* Microsoft primary or secondary WINS request */
1173             d = citype == CI_MS_WINS2;
1174
1175             /* If we do not have a DNS address then we cannot send it */
1176             if (ao->winsaddr[d] == 0 ||
1177                 cilen != CILEN_ADDR) {  /* Check CI length */
1178                 orc = CONFREJ;          /* Reject CI */
1179                 break;
1180             }
1181             GETLONG(tl, p);
1182             if (htonl(tl) != ao->winsaddr[d]) {
1183                 DECPTR(sizeof(u_int32_t), p);
1184                 tl = ntohl(ao->winsaddr[d]);
1185                 PUTLONG(tl, p);
1186                 orc = CONFNAK;
1187             }
1188             break;
1189         
1190         case CI_COMPRESSTYPE:
1191             if (!ao->neg_vj ||
1192                 (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) {
1193                 orc = CONFREJ;
1194                 break;
1195             }
1196             GETSHORT(cishort, p);
1197
1198             if (!(cishort == IPCP_VJ_COMP ||
1199                   (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {
1200                 orc = CONFREJ;
1201                 break;
1202             }
1203
1204             ho->neg_vj = 1;
1205             ho->vj_protocol = cishort;
1206             if (cilen == CILEN_VJ) {
1207                 GETCHAR(maxslotindex, p);
1208                 if (maxslotindex > ao->maxslotindex) { 
1209                     orc = CONFNAK;
1210                     if (!reject_if_disagree){
1211                         DECPTR(1, p);
1212                         PUTCHAR(ao->maxslotindex, p);
1213                     }
1214                 }
1215                 GETCHAR(cflag, p);
1216                 if (cflag && !ao->cflag) {
1217                     orc = CONFNAK;
1218                     if (!reject_if_disagree){
1219                         DECPTR(1, p);
1220                         PUTCHAR(wo->cflag, p);
1221                     }
1222                 }
1223                 ho->maxslotindex = maxslotindex;
1224                 ho->cflag = cflag;
1225             } else {
1226                 ho->old_vj = 1;
1227                 ho->maxslotindex = MAX_STATES - 1;
1228                 ho->cflag = 1;
1229             }
1230             break;
1231
1232         default:
1233             orc = CONFREJ;
1234             break;
1235         }
1236 endswitch:
1237         if (orc == CONFACK &&           /* Good CI */
1238             rc != CONFACK)              /*  but prior CI wasnt? */
1239             continue;                   /* Don't send this one */
1240
1241         if (orc == CONFNAK) {           /* Nak this CI? */
1242             if (reject_if_disagree)     /* Getting fed up with sending NAKs? */
1243                 orc = CONFREJ;          /* Get tough if so */
1244             else {
1245                 if (rc == CONFREJ)      /* Rejecting prior CI? */
1246                     continue;           /* Don't send this one */
1247                 if (rc == CONFACK) {    /* Ack'd all prior CIs? */
1248                     rc = CONFNAK;       /* Not anymore... */
1249                     ucp = inp;          /* Backup */
1250                 }
1251             }
1252         }
1253
1254         if (orc == CONFREJ &&           /* Reject this CI */
1255             rc != CONFREJ) {            /*  but no prior ones? */
1256             rc = CONFREJ;
1257             ucp = inp;                  /* Backup */
1258         }
1259
1260         /* Need to move CI? */
1261         if (ucp != cip)
1262             BCOPY(cip, ucp, cilen);     /* Move it */
1263
1264         /* Update output pointer */
1265         INCPTR(cilen, ucp);
1266     }
1267
1268     /*
1269      * If we aren't rejecting this packet, and we want to negotiate
1270      * their address, and they didn't send their address, then we
1271      * send a NAK with a CI_ADDR option appended.  We assume the
1272      * input buffer is long enough that we can append the extra
1273      * option safely.
1274      */
1275     if (rc != CONFREJ && !ho->neg_addr &&
1276         wo->req_addr && !reject_if_disagree) {
1277         if (rc == CONFACK) {
1278             rc = CONFNAK;
1279             ucp = inp;                  /* reset pointer */
1280             wo->req_addr = 0;           /* don't ask again */
1281         }
1282         PUTCHAR(CI_ADDR, ucp);
1283         PUTCHAR(CILEN_ADDR, ucp);
1284         tl = ntohl(wo->hisaddr);
1285         PUTLONG(tl, ucp);
1286     }
1287
1288     *len = ucp - inp;                   /* Compute output length */
1289     IPCPDEBUG(("ipcp: returning Configure-%s", CODENAME(rc)));
1290     return (rc);                        /* Return final code */
1291 }
1292
1293
1294 /*
1295  * ip_check_options - check that any IP-related options are OK,
1296  * and assign appropriate defaults.
1297  */
1298 static void
1299 ip_check_options()
1300 {
1301     struct hostent *hp;
1302     u_int32_t local;
1303     ipcp_options *wo = &ipcp_wantoptions[0];
1304
1305     /*
1306      * Default our local IP address based on our hostname.
1307      * If local IP address already given, don't bother.
1308      */
1309     if (wo->ouraddr == 0 && !disable_defaultip) {
1310         /*
1311          * Look up our hostname (possibly with domain name appended)
1312          * and take the first IP address as our local IP address.
1313          * If there isn't an IP address for our hostname, too bad.
1314          */
1315         wo->accept_local = 1;   /* don't insist on this default value */
1316         if ((hp = gethostbyname(hostname)) != NULL) {
1317             local = *(u_int32_t *)hp->h_addr;
1318             if (local != 0 && !bad_ip_adrs(local))
1319                 wo->ouraddr = local;
1320         }
1321     }
1322     ask_for_local = wo->ouraddr != 0 || !disable_defaultip;
1323 }
1324
1325
1326 /*
1327  * ip_demand_conf - configure the interface as though
1328  * IPCP were up, for use with dial-on-demand.
1329  */
1330 static int
1331 ip_demand_conf(u)
1332     int u;
1333 {
1334     ipcp_options *wo = &ipcp_wantoptions[u];
1335
1336     if (wo->hisaddr == 0) {
1337         /* make up an arbitrary address for the peer */
1338         wo->hisaddr = htonl(0x0a707070 + ifunit);
1339         wo->accept_remote = 1;
1340     }
1341     if (wo->ouraddr == 0) {
1342         /* make up an arbitrary address for us */
1343         wo->ouraddr = htonl(0x0a404040 + ifunit);
1344         wo->accept_local = 1;
1345         ask_for_local = 0;      /* don't tell the peer this address */
1346     }
1347     if (!sifaddr(u, wo->ouraddr, wo->hisaddr, GetMask(wo->ouraddr)))
1348         return 0;
1349     if (!sifup(u))
1350         return 0;
1351     if (!sifnpmode(u, PPP_IP, NPMODE_QUEUE))
1352         return 0;
1353     if (wo->default_route)
1354         if (sifdefaultroute(u, wo->ouraddr, wo->hisaddr))
1355             default_route_set[u] = 1;
1356     if (wo->proxy_arp)
1357         if (sifproxyarp(u, wo->hisaddr))
1358             proxy_arp_set[u] = 1;
1359
1360     notice("local  IP address %I", wo->ouraddr);
1361     notice("remote IP address %I", wo->hisaddr);
1362
1363     return 1;
1364 }
1365
1366
1367 /*
1368  * ipcp_up - IPCP has come UP.
1369  *
1370  * Configure the IP network interface appropriately and bring it up.
1371  */
1372 static void
1373 ipcp_up(f)
1374     fsm *f;
1375 {
1376     u_int32_t mask;
1377     ipcp_options *ho = &ipcp_hisoptions[f->unit];
1378     ipcp_options *go = &ipcp_gotoptions[f->unit];
1379     ipcp_options *wo = &ipcp_wantoptions[f->unit];
1380
1381     IPCPDEBUG(("ipcp: up"));
1382
1383     /*
1384      * We must have a non-zero IP address for both ends of the link.
1385      */
1386     if (!ho->neg_addr)
1387         ho->hisaddr = wo->hisaddr;
1388
1389     if (go->ouraddr == 0) {
1390         error("Could not determine local IP address");
1391         ipcp_close(f->unit, "Could not determine local IP address");
1392         return;
1393     }
1394     if (ho->hisaddr == 0) {
1395         ho->hisaddr = htonl(0x0a404040 + ifunit);
1396         warn("Could not determine remote IP address: defaulting to %I",
1397              ho->hisaddr);
1398     }
1399     script_setenv("IPLOCAL", ip_ntoa(go->ouraddr), 0);
1400     script_setenv("IPREMOTE", ip_ntoa(ho->hisaddr), 1);
1401
1402     if (usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) {
1403         script_setenv("USEPEERDNS", "1", 0);
1404         if (go->dnsaddr[0])
1405             script_setenv("DNS1", ip_ntoa(go->dnsaddr[0]), 0);
1406         if (go->dnsaddr[1])
1407             script_setenv("DNS2", ip_ntoa(go->dnsaddr[1]), 0);
1408         create_resolv(go->dnsaddr[0], go->dnsaddr[1]);
1409     }
1410
1411     /*
1412      * Check that the peer is allowed to use the IP address it wants.
1413      */
1414     if (!auth_ip_addr(f->unit, ho->hisaddr)) {
1415         error("Peer is not authorized to use remote address %I", ho->hisaddr);
1416         ipcp_close(f->unit, "Unauthorized remote IP address");
1417         return;
1418     }
1419
1420     /* set tcp compression */
1421     sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex);
1422
1423     /*
1424      * If we are doing dial-on-demand, the interface is already
1425      * configured, so we put out any saved-up packets, then set the
1426      * interface to pass IP packets.
1427      */
1428     if (demand) {
1429         if (go->ouraddr != wo->ouraddr || ho->hisaddr != wo->hisaddr) {
1430             ipcp_clear_addrs(f->unit, wo->ouraddr, wo->hisaddr);
1431             if (go->ouraddr != wo->ouraddr) {
1432                 warn("Local IP address changed to %I", go->ouraddr);
1433                 script_setenv("OLDIPLOCAL", ip_ntoa(wo->ouraddr), 0);
1434                 wo->ouraddr = go->ouraddr;
1435             } else
1436                 script_unsetenv("OLDIPLOCAL");
1437             if (ho->hisaddr != wo->hisaddr) {
1438                 warn("Remote IP address changed to %I", ho->hisaddr);
1439                 script_setenv("OLDIPREMOTE", ip_ntoa(wo->hisaddr), 0);
1440                 wo->hisaddr = ho->hisaddr;
1441             } else
1442                 script_unsetenv("OLDIPREMOTE");
1443
1444             /* Set the interface to the new addresses */
1445             mask = GetMask(go->ouraddr);
1446             if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1447                 if (debug)
1448                     warn("Interface configuration failed");
1449                 ipcp_close(f->unit, "Interface configuration failed");
1450                 return;
1451             }
1452
1453             /* assign a default route through the interface if required */
1454             if (ipcp_wantoptions[f->unit].default_route) 
1455                 if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
1456                     default_route_set[f->unit] = 1;
1457
1458             /* Make a proxy ARP entry if requested. */
1459             if (ipcp_wantoptions[f->unit].proxy_arp)
1460                 if (sifproxyarp(f->unit, ho->hisaddr))
1461                     proxy_arp_set[f->unit] = 1;
1462
1463         }
1464         demand_rexmit(PPP_IP);
1465         sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
1466
1467     } else {
1468         /*
1469          * Set IP addresses and (if specified) netmask.
1470          */
1471         mask = GetMask(go->ouraddr);
1472
1473 #if !(defined(SVR4) && (defined(SNI) || defined(__USLC__)))
1474         if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1475             if (debug)
1476                 warn("Interface configuration failed");
1477             ipcp_close(f->unit, "Interface configuration failed");
1478             return;
1479         }
1480 #endif
1481
1482         /* bring the interface up for IP */
1483         if (!sifup(f->unit)) {
1484             if (debug)
1485                 warn("Interface failed to come up");
1486             ipcp_close(f->unit, "Interface configuration failed");
1487             return;
1488         }
1489
1490 #if (defined(SVR4) && (defined(SNI) || defined(__USLC__)))
1491         if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask)) {
1492             if (debug)
1493                 warn("Interface configuration failed");
1494             ipcp_close(f->unit, "Interface configuration failed");
1495             return;
1496         }
1497 #endif
1498         sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
1499
1500         /* assign a default route through the interface if required */
1501         if (ipcp_wantoptions[f->unit].default_route) 
1502             if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr))
1503                 default_route_set[f->unit] = 1;
1504
1505         /* Make a proxy ARP entry if requested. */
1506         if (ipcp_wantoptions[f->unit].proxy_arp)
1507             if (sifproxyarp(f->unit, ho->hisaddr))
1508                 proxy_arp_set[f->unit] = 1;
1509
1510         ipcp_wantoptions[0].ouraddr = go->ouraddr;
1511
1512         notice("local  IP address %I", go->ouraddr);
1513         notice("remote IP address %I", ho->hisaddr);
1514         if (go->dnsaddr[0])
1515             notice("primary   DNS address %I", go->dnsaddr[0]);
1516         if (go->dnsaddr[1])
1517             notice("secondary DNS address %I", go->dnsaddr[1]);
1518     }
1519
1520     np_up(f->unit, PPP_IP);
1521     ipcp_is_up = 1;
1522
1523     if (ip_up_hook)
1524         ip_up_hook();
1525
1526     /*
1527      * Execute the ip-up script, like this:
1528      *  /etc/ppp/ip-up interface tty speed local-IP remote-IP
1529      */
1530     if (ipcp_script_state == s_down && ipcp_script_pid == 0) {
1531         ipcp_script_state = s_up;
1532         ipcp_script(_PATH_IPUP);
1533     }
1534 }
1535
1536
1537 /*
1538  * ipcp_down - IPCP has gone DOWN.
1539  *
1540  * Take the IP network interface down, clear its addresses
1541  * and delete routes through it.
1542  */
1543 static void
1544 ipcp_down(f)
1545     fsm *f;
1546 {
1547     IPCPDEBUG(("ipcp: down"));
1548     /* XXX a bit IPv4-centric here, we only need to get the stats
1549      * before the interface is marked down. */
1550     update_link_stats(f->unit);
1551     if (ip_down_hook)
1552         ip_down_hook();
1553     if (ipcp_is_up) {
1554         ipcp_is_up = 0;
1555         np_down(f->unit, PPP_IP);
1556     }
1557     sifvjcomp(f->unit, 0, 0, 0);
1558
1559     /*
1560      * If we are doing dial-on-demand, set the interface
1561      * to queue up outgoing packets (for now).
1562      */
1563     if (demand) {
1564         sifnpmode(f->unit, PPP_IP, NPMODE_QUEUE);
1565     } else {
1566         sifnpmode(f->unit, PPP_IP, NPMODE_DROP);
1567         sifdown(f->unit);
1568         ipcp_clear_addrs(f->unit, ipcp_gotoptions[f->unit].ouraddr,
1569                          ipcp_hisoptions[f->unit].hisaddr);
1570     }
1571
1572     /* Execute the ip-down script */
1573     if (ipcp_script_state == s_up && ipcp_script_pid == 0) {
1574         ipcp_script_state = s_down;
1575         ipcp_script(_PATH_IPDOWN);
1576     }
1577 }
1578
1579
1580 /*
1581  * ipcp_clear_addrs() - clear the interface addresses, routes,
1582  * proxy arp entries, etc.
1583  */
1584 static void
1585 ipcp_clear_addrs(unit, ouraddr, hisaddr)
1586     int unit;
1587     u_int32_t ouraddr;  /* local address */
1588     u_int32_t hisaddr;  /* remote address */
1589 {
1590     if (proxy_arp_set[unit]) {
1591         cifproxyarp(unit, hisaddr);
1592         proxy_arp_set[unit] = 0;
1593     }
1594     if (default_route_set[unit]) {
1595         cifdefaultroute(unit, ouraddr, hisaddr);
1596         default_route_set[unit] = 0;
1597     }
1598     cifaddr(unit, ouraddr, hisaddr);
1599 }
1600
1601
1602 /*
1603  * ipcp_finished - possibly shut down the lower layers.
1604  */
1605 static void
1606 ipcp_finished(f)
1607     fsm *f;
1608 {
1609     np_finished(f->unit, PPP_IP);
1610 }
1611
1612
1613 /*
1614  * ipcp_script_done - called when the ip-up or ip-down script
1615  * has finished.
1616  */
1617 static void
1618 ipcp_script_done(arg)
1619     void *arg;
1620 {
1621     ipcp_script_pid = 0;
1622     switch (ipcp_script_state) {
1623     case s_up:
1624         if (ipcp_fsm[0].state != OPENED) {
1625             ipcp_script_state = s_down;
1626             ipcp_script(_PATH_IPDOWN);
1627         }
1628         break;
1629     case s_down:
1630         if (ipcp_fsm[0].state == OPENED) {
1631             ipcp_script_state = s_up;
1632             ipcp_script(_PATH_IPUP);
1633         }
1634         break;
1635     }
1636 }
1637
1638
1639 /*
1640  * ipcp_script - Execute a script with arguments
1641  * interface-name tty-name speed local-IP remote-IP.
1642  */
1643 static void
1644 ipcp_script(script)
1645     char *script;
1646 {
1647     char strspeed[32], strlocal[32], strremote[32];
1648     char *argv[8];
1649
1650     slprintf(strspeed, sizeof(strspeed), "%d", baud_rate);
1651     slprintf(strlocal, sizeof(strlocal), "%I", ipcp_gotoptions[0].ouraddr);
1652     slprintf(strremote, sizeof(strremote), "%I", ipcp_hisoptions[0].hisaddr);
1653
1654     argv[0] = script;
1655     argv[1] = ifname;
1656     argv[2] = devnam;
1657     argv[3] = strspeed;
1658     argv[4] = strlocal;
1659     argv[5] = strremote;
1660     argv[6] = ipparam;
1661     argv[7] = NULL;
1662     ipcp_script_pid = run_program(script, argv, 0, ipcp_script_done, NULL);
1663 }
1664
1665 /*
1666  * create_resolv - create the replacement resolv.conf file
1667  */
1668 static void
1669 create_resolv(peerdns1, peerdns2)
1670     u_int32_t peerdns1, peerdns2;
1671 {
1672     FILE *f;
1673
1674     f = fopen(_PATH_RESOLV, "w");
1675     if (f == NULL) {
1676         error("Failed to create %s: %m", _PATH_RESOLV);
1677         return;
1678     }
1679
1680     if (peerdns1)
1681         fprintf(f, "nameserver %s\n", ip_ntoa(peerdns1));
1682
1683     if (peerdns2)
1684         fprintf(f, "nameserver %s\n", ip_ntoa(peerdns2));
1685
1686     if (ferror(f))
1687         error("Write failed to %s: %m", _PATH_RESOLV);
1688
1689     fclose(f);
1690 }
1691
1692 /*
1693  * ipcp_printpkt - print the contents of an IPCP packet.
1694  */
1695 static char *ipcp_codenames[] = {
1696     "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1697     "TermReq", "TermAck", "CodeRej"
1698 };
1699
1700 static int
1701 ipcp_printpkt(p, plen, printer, arg)
1702     u_char *p;
1703     int plen;
1704     void (*printer) __P((void *, char *, ...));
1705     void *arg;
1706 {
1707     int code, id, len, olen;
1708     u_char *pstart, *optend;
1709     u_short cishort;
1710     u_int32_t cilong;
1711
1712     if (plen < HEADERLEN)
1713         return 0;
1714     pstart = p;
1715     GETCHAR(code, p);
1716     GETCHAR(id, p);
1717     GETSHORT(len, p);
1718     if (len < HEADERLEN || len > plen)
1719         return 0;
1720
1721     if (code >= 1 && code <= sizeof(ipcp_codenames) / sizeof(char *))
1722         printer(arg, " %s", ipcp_codenames[code-1]);
1723     else
1724         printer(arg, " code=0x%x", code);
1725     printer(arg, " id=0x%x", id);
1726     len -= HEADERLEN;
1727     switch (code) {
1728     case CONFREQ:
1729     case CONFACK:
1730     case CONFNAK:
1731     case CONFREJ:
1732         /* print option list */
1733         while (len >= 2) {
1734             GETCHAR(code, p);
1735             GETCHAR(olen, p);
1736             p -= 2;
1737             if (olen < 2 || olen > len) {
1738                 break;
1739             }
1740             printer(arg, " <");
1741             len -= olen;
1742             optend = p + olen;
1743             switch (code) {
1744             case CI_ADDRS:
1745                 if (olen == CILEN_ADDRS) {
1746                     p += 2;
1747                     GETLONG(cilong, p);
1748                     printer(arg, "addrs %I", htonl(cilong));
1749                     GETLONG(cilong, p);
1750                     printer(arg, " %I", htonl(cilong));
1751                 }
1752                 break;
1753             case CI_COMPRESSTYPE:
1754                 if (olen >= CILEN_COMPRESS) {
1755                     p += 2;
1756                     GETSHORT(cishort, p);
1757                     printer(arg, "compress ");
1758                     switch (cishort) {
1759                     case IPCP_VJ_COMP:
1760                         printer(arg, "VJ");
1761                         break;
1762                     case IPCP_VJ_COMP_OLD:
1763                         printer(arg, "old-VJ");
1764                         break;
1765                     default:
1766                         printer(arg, "0x%x", cishort);
1767                     }
1768                 }
1769                 break;
1770             case CI_ADDR:
1771                 if (olen == CILEN_ADDR) {
1772                     p += 2;
1773                     GETLONG(cilong, p);
1774                     printer(arg, "addr %I", htonl(cilong));
1775                 }
1776                 break;
1777             case CI_MS_DNS1:
1778             case CI_MS_DNS2:
1779                 p += 2;
1780                 GETLONG(cilong, p);
1781                 printer(arg, "ms-dns%d %I", code - CI_MS_DNS1 + 1,
1782                         htonl(cilong));
1783                 break;
1784             case CI_MS_WINS1:
1785             case CI_MS_WINS2:
1786                 p += 2;
1787                 GETLONG(cilong, p);
1788                 printer(arg, "ms-wins %I", htonl(cilong));
1789                 break;
1790             }
1791             while (p < optend) {
1792                 GETCHAR(code, p);
1793                 printer(arg, " %.2x", code);
1794             }
1795             printer(arg, ">");
1796         }
1797         break;
1798
1799     case TERMACK:
1800     case TERMREQ:
1801         if (len > 0 && *p >= ' ' && *p < 0x7f) {
1802             printer(arg, " ");
1803             print_string((char *)p, len, printer, arg);
1804             p += len;
1805             len = 0;
1806         }
1807         break;
1808     }
1809
1810     /* print the rest of the bytes in the packet */
1811     for (; len > 0; --len) {
1812         GETCHAR(code, p);
1813         printer(arg, " %.2x", code);
1814     }
1815
1816     return p - pstart;
1817 }
1818
1819 /*
1820  * ip_active_pkt - see if this IP packet is worth bringing the link up for.
1821  * We don't bring the link up for IP fragments or for TCP FIN packets
1822  * with no data.
1823  */
1824 #define IP_HDRLEN       20      /* bytes */
1825 #define IP_OFFMASK      0x1fff
1826 #define IPPROTO_TCP     6
1827 #define TCP_HDRLEN      20
1828 #define TH_FIN          0x01
1829
1830 /*
1831  * We use these macros because the IP header may be at an odd address,
1832  * and some compilers might use word loads to get th_off or ip_hl.
1833  */
1834
1835 #define net_short(x)    (((x)[0] << 8) + (x)[1])
1836 #define get_iphl(x)     (((unsigned char *)(x))[0] & 0xF)
1837 #define get_ipoff(x)    net_short((unsigned char *)(x) + 6)
1838 #define get_ipproto(x)  (((unsigned char *)(x))[9])
1839 #define get_tcpoff(x)   (((unsigned char *)(x))[12] >> 4)
1840 #define get_tcpflags(x) (((unsigned char *)(x))[13])
1841
1842 static int
1843 ip_active_pkt(pkt, len)
1844     u_char *pkt;
1845     int len;
1846 {
1847     u_char *tcp;
1848     int hlen;
1849
1850     len -= PPP_HDRLEN;
1851     pkt += PPP_HDRLEN;
1852     if (len < IP_HDRLEN)
1853         return 0;
1854     if ((get_ipoff(pkt) & IP_OFFMASK) != 0)
1855         return 0;
1856     if (get_ipproto(pkt) != IPPROTO_TCP)
1857         return 1;
1858     hlen = get_iphl(pkt) * 4;
1859     if (len < hlen + TCP_HDRLEN)
1860         return 0;
1861     tcp = pkt + hlen;
1862     if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4)
1863         return 0;
1864     return 1;
1865 }