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