Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Release 1.0
[palacios.git] / geekos / src / lwip / netif / ppp / ipcp.c
1 /*****************************************************************************
2 * ipcp.c - Network PPP IP Control Protocol program file.
3 *
4 * Copyright (c) 2003 by Marc Boucher, Services Informatiques (MBSI) inc.
5 * portions Copyright (c) 1997 by Global Election Systems Inc.
6 *
7 * The authors hereby grant permission to use, copy, modify, distribute,
8 * and license this software and its documentation for any purpose, provided
9 * that existing copyright notices are retained in all copies and that this
10 * notice and the following disclaimer are included verbatim in any 
11 * distributions. No written agreement, license, or royalty fee is required
12 * for any of the authorized uses.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
17 * IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 *
25 ******************************************************************************
26 * REVISION HISTORY
27 *
28 * 03-01-01 Marc Boucher <marc@mbsi.ca>
29 *   Ported to lwIP.
30 * 97-12-08 Guy Lancaster <lancasterg@acm.org>, Global Election Systems Inc.
31 *   Original.
32 *****************************************************************************/
33 /*
34  * ipcp.c - PPP IP Control Protocol.
35  *
36  * Copyright (c) 1989 Carnegie Mellon University.
37  * All rights reserved.
38  *
39  * Redistribution and use in source and binary forms are permitted
40  * provided that the above copyright notice and this paragraph are
41  * duplicated in all such forms and that any documentation,
42  * advertising materials, and other materials related to such
43  * distribution and use acknowledge that the software was developed
44  * by Carnegie Mellon University.  The name of the
45  * University may not be used to endorse or promote products derived
46  * from this software without specific prior written permission.
47  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
48  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
49  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
50  */
51
52 #include "lwip/opt.h"
53
54 #if PPP_SUPPORT /* don't build if not configured for use in lwipopts.h */
55
56 #include "ppp.h"
57 #include "pppdebug.h"
58
59 #include "auth.h"
60 #include "fsm.h"
61 #include "vj.h"
62 #include "ipcp.h"
63
64 #include <string.h>
65
66 /*************************/
67 /*** LOCAL DEFINITIONS ***/
68 /*************************/
69 /* #define OLD_CI_ADDRS 1 */ /* Support deprecated address negotiation. */
70
71 /*
72  * Lengths of configuration options.
73  */
74 #define CILEN_VOID     2
75 #define CILEN_COMPRESS 4  /* min length for compression protocol opt. */
76 #define CILEN_VJ       6  /* length for RFC1332 Van-Jacobson opt. */
77 #define CILEN_ADDR     6  /* new-style single address option */
78 #define CILEN_ADDRS    10 /* old-style dual address option */
79
80
81
82 /***********************************/
83 /*** LOCAL FUNCTION DECLARATIONS ***/
84 /***********************************/
85 /*
86  * Callbacks for fsm code.  (CI = Configuration Information)
87  */
88 static void ipcp_resetci (fsm *);                     /* Reset our CI */
89 static int  ipcp_cilen (fsm *);                       /* Return length of our CI */
90 static void ipcp_addci (fsm *, u_char *, int *);      /* Add our CI */
91 static int  ipcp_ackci (fsm *, u_char *, int);        /* Peer ack'd our CI */
92 static int  ipcp_nakci (fsm *, u_char *, int);        /* Peer nak'd our CI */
93 static int  ipcp_rejci (fsm *, u_char *, int);        /* Peer rej'd our CI */
94 static int  ipcp_reqci (fsm *, u_char *, int *, int); /* Rcv CI */
95 static void ipcp_up (fsm *);                          /* We're UP */
96 static void ipcp_down (fsm *);                        /* We're DOWN */
97 #if 0
98 static void ipcp_script (fsm *, char *); /* Run an up/down script */
99 #endif
100 static void ipcp_finished (fsm *);                    /* Don't need lower layer */
101
102 /*
103  * Protocol entry points from main code.
104  */
105 static void ipcp_init (int);
106 static void ipcp_open (int);
107 static void ipcp_close (int, char *);
108 static void ipcp_lowerup (int);
109 static void ipcp_lowerdown (int);
110 static void ipcp_input (int, u_char *, int);
111 static void ipcp_protrej (int);
112
113 static void ipcp_clear_addrs (int);
114
115 #define CODENAME(x) ((x) == CONFACK ? "ACK" : \
116                      (x) == CONFNAK ? "NAK" : "REJ")
117
118
119
120 /******************************/
121 /*** PUBLIC DATA STRUCTURES ***/
122 /******************************/
123 /* global vars */
124 ipcp_options ipcp_wantoptions[NUM_PPP];  /* Options that we want to request */
125 ipcp_options ipcp_gotoptions[NUM_PPP];   /* Options that peer ack'd */
126 ipcp_options ipcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
127 ipcp_options ipcp_hisoptions[NUM_PPP];   /* Options that we ack'd */
128
129 fsm ipcp_fsm[NUM_PPP]; /* IPCP fsm structure */
130
131 struct protent ipcp_protent = {
132   PPP_IPCP,
133   ipcp_init,
134   ipcp_input,
135   ipcp_protrej,
136   ipcp_lowerup,
137   ipcp_lowerdown,
138   ipcp_open,
139   ipcp_close,
140 #if 0
141   ipcp_printpkt,
142   NULL,
143 #endif
144   1,
145   "IPCP",
146 #if 0
147   ip_check_options,
148   NULL,
149   ip_active_pkt
150 #endif
151 };
152
153
154
155 /*****************************/
156 /*** LOCAL DATA STRUCTURES ***/
157 /*****************************/
158 /* local vars */
159 static int cis_received[NUM_PPP];      /* # Conf-Reqs received */
160 static int default_route_set[NUM_PPP]; /* Have set up a default route */
161
162 static fsm_callbacks ipcp_callbacks = { /* IPCP callback routines */
163   ipcp_resetci,  /* Reset our Configuration Information */
164   ipcp_cilen,    /* Length of our Configuration Information */
165   ipcp_addci,    /* Add our Configuration Information */
166   ipcp_ackci,    /* ACK our Configuration Information */
167   ipcp_nakci,    /* NAK our Configuration Information */
168   ipcp_rejci,    /* Reject our Configuration Information */
169   ipcp_reqci,    /* Request peer's Configuration Information */
170   ipcp_up,       /* Called when fsm reaches LS_OPENED state */
171   ipcp_down,     /* Called when fsm leaves LS_OPENED state */
172   NULL,          /* Called when we want the lower layer up */
173   ipcp_finished, /* Called when we want the lower layer down */
174   NULL,          /* Called when Protocol-Reject received */
175   NULL,          /* Retransmission is necessary */
176   NULL,          /* Called to handle protocol-specific codes */
177   "IPCP"         /* String name of protocol */
178 };
179
180
181
182 /**********************************/
183 /*** LOCAL FUNCTION DEFINITIONS ***/
184 /**********************************/
185
186 /*
187  * Non-standard inet_ntoa left here for compat with original ppp
188  * sources. Assumes u32_t instead of struct in_addr.
189  */ 
190
191 char *
192 _inet_ntoa(u32_t n)
193 {
194   struct in_addr ia;
195   ia.s_addr = n;
196   return inet_ntoa(ia);
197 }
198
199 #define inet_ntoa _inet_ntoa
200
201 /*
202  * ipcp_init - Initialize IPCP.
203  */
204 static void
205 ipcp_init(int unit)
206 {
207   fsm           *f = &ipcp_fsm[unit];
208   ipcp_options *wo = &ipcp_wantoptions[unit];
209   ipcp_options *ao = &ipcp_allowoptions[unit];
210
211   f->unit      = unit;
212   f->protocol  = PPP_IPCP;
213   f->callbacks = &ipcp_callbacks;
214   fsm_init(&ipcp_fsm[unit]);
215
216   memset(wo, 0, sizeof(*wo));
217   memset(ao, 0, sizeof(*ao));
218
219   wo->neg_addr      = 1;
220   wo->ouraddr       = 0;
221 #if VJ_SUPPORT
222   wo->neg_vj        = 1;
223 #else  /* VJ_SUPPORT */
224   wo->neg_vj        = 0;
225 #endif /* VJ_SUPPORT */
226   wo->vj_protocol   = IPCP_VJ_COMP;
227   wo->maxslotindex  = MAX_SLOTS - 1;
228   wo->cflag         = 0;
229   wo->default_route = 1;
230
231   ao->neg_addr      = 1;
232 #if VJ_SUPPORT
233   ao->neg_vj        = 1;
234 #else  /* VJ_SUPPORT */
235   ao->neg_vj        = 0;
236 #endif /* VJ_SUPPORT */
237   ao->maxslotindex  = MAX_SLOTS - 1;
238   ao->cflag         = 1;
239   ao->default_route = 1;
240 }
241
242
243 /*
244  * ipcp_open - IPCP is allowed to come up.
245  */
246 static void
247 ipcp_open(int unit)
248 {
249   fsm_open(&ipcp_fsm[unit]);
250 }
251
252
253 /*
254  * ipcp_close - Take IPCP down.
255  */
256 static void
257 ipcp_close(int unit, char *reason)
258 {
259   fsm_close(&ipcp_fsm[unit], reason);
260 }
261
262
263 /*
264  * ipcp_lowerup - The lower layer is up.
265  */
266 static void
267 ipcp_lowerup(int unit)
268 {
269   fsm_lowerup(&ipcp_fsm[unit]);
270 }
271
272
273 /*
274  * ipcp_lowerdown - The lower layer is down.
275  */
276 static void
277 ipcp_lowerdown(int unit)
278 {
279   fsm_lowerdown(&ipcp_fsm[unit]);
280 }
281
282
283 /*
284  * ipcp_input - Input IPCP packet.
285  */
286 static void
287 ipcp_input(int unit, u_char *p, int len)
288 {
289   fsm_input(&ipcp_fsm[unit], p, len);
290 }
291
292
293 /*
294  * ipcp_protrej - A Protocol-Reject was received for IPCP.
295  *
296  * Pretend the lower layer went down, so we shut up.
297  */
298 static void
299 ipcp_protrej(int unit)
300 {
301   fsm_lowerdown(&ipcp_fsm[unit]);
302 }
303
304
305 /*
306  * ipcp_resetci - Reset our CI.
307  */
308 static void
309 ipcp_resetci(fsm *f)
310 {
311   ipcp_options *wo = &ipcp_wantoptions[f->unit];
312   
313   wo->req_addr = wo->neg_addr && ipcp_allowoptions[f->unit].neg_addr;
314   if (wo->ouraddr == 0) {
315     wo->accept_local = 1;
316   }
317   if (wo->hisaddr == 0) {
318     wo->accept_remote = 1;
319   }
320   /* Request DNS addresses from the peer */
321   wo->req_dns1 = ppp_settings.usepeerdns;
322   wo->req_dns2 = ppp_settings.usepeerdns;
323   ipcp_gotoptions[f->unit] = *wo;
324   cis_received[f->unit] = 0;
325 }
326
327
328 /*
329  * ipcp_cilen - Return length of our CI.
330  */
331 static int
332 ipcp_cilen(fsm *f)
333 {
334   ipcp_options *go = &ipcp_gotoptions[f->unit];
335   ipcp_options *wo = &ipcp_wantoptions[f->unit];
336   ipcp_options *ho = &ipcp_hisoptions[f->unit];
337
338 #define LENCIVJ(neg, old)   (neg ? (old? CILEN_COMPRESS : CILEN_VJ) : 0)
339 #define LENCIADDR(neg, old) (neg ? (old? CILEN_ADDRS : CILEN_ADDR) : 0)
340 #define LENCIDNS(neg)       (neg ? (CILEN_ADDR) : 0)
341
342   /*
343    * First see if we want to change our options to the old
344    * forms because we have received old forms from the peer.
345    */
346   if (wo->neg_addr && !go->neg_addr && !go->old_addrs) {
347     /* use the old style of address negotiation */
348     go->neg_addr = 1;
349     go->old_addrs = 1;
350   }
351   if (wo->neg_vj && !go->neg_vj && !go->old_vj) {
352     /* try an older style of VJ negotiation */
353     if (cis_received[f->unit] == 0) {
354       /* keep trying the new style until we see some CI from the peer */
355       go->neg_vj = 1;
356     } else {
357       /* use the old style only if the peer did */
358       if (ho->neg_vj && ho->old_vj) {
359         go->neg_vj = 1;
360         go->old_vj = 1;
361         go->vj_protocol = ho->vj_protocol;
362       }
363     }
364   }
365
366   return (LENCIADDR(go->neg_addr, go->old_addrs) +
367           LENCIVJ(go->neg_vj, go->old_vj) +
368           LENCIDNS(go->req_dns1) +
369           LENCIDNS(go->req_dns2));
370 }
371
372
373 /*
374  * ipcp_addci - Add our desired CIs to a packet.
375  */
376 static void
377 ipcp_addci(fsm *f, u_char *ucp, int *lenp)
378 {
379   ipcp_options *go = &ipcp_gotoptions[f->unit];
380   int len = *lenp;
381
382 #define ADDCIVJ(opt, neg, val, old, maxslotindex, cflag) \
383   if (neg) { \
384     int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
385     if (len >= vjlen) { \
386       PUTCHAR(opt, ucp); \
387       PUTCHAR(vjlen, ucp); \
388       PUTSHORT(val, ucp); \
389       if (!old) { \
390         PUTCHAR(maxslotindex, ucp); \
391         PUTCHAR(cflag, ucp); \
392       } \
393       len -= vjlen; \
394     } else { \
395       neg = 0; \
396     } \
397   }
398
399 #define ADDCIADDR(opt, neg, old, val1, val2) \
400   if (neg) { \
401     int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
402     if (len >= addrlen) { \
403       u32_t l; \
404       PUTCHAR(opt, ucp); \
405       PUTCHAR(addrlen, ucp); \
406       l = ntohl(val1); \
407       PUTLONG(l, ucp); \
408       if (old) { \
409         l = ntohl(val2); \
410         PUTLONG(l, ucp); \
411       } \
412       len -= addrlen; \
413     } else { \
414       neg = 0; \
415     } \
416   }
417
418 #define ADDCIDNS(opt, neg, addr) \
419   if (neg) { \
420     if (len >= CILEN_ADDR) { \
421       u32_t l; \
422       PUTCHAR(opt, ucp); \
423       PUTCHAR(CILEN_ADDR, ucp); \
424       l = ntohl(addr); \
425       PUTLONG(l, ucp); \
426       len -= CILEN_ADDR; \
427     } else { \
428       neg = 0; \
429     } \
430   }
431
432   ADDCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
433       go->old_addrs, go->ouraddr, go->hisaddr);
434
435   ADDCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
436       go->maxslotindex, go->cflag);
437
438   ADDCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
439
440   ADDCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
441
442   *lenp -= len;
443 }
444
445
446 /*
447  * ipcp_ackci - Ack our CIs.
448  *
449  * Returns:
450  *  0 - Ack was bad.
451  *  1 - Ack was good.
452  */
453 static int
454 ipcp_ackci(fsm *f, u_char *p, int len)
455 {
456   ipcp_options *go = &ipcp_gotoptions[f->unit];
457   u_short cilen, citype, cishort;
458   u32_t cilong;
459   u_char cimaxslotindex, cicflag;
460
461   /*
462    * CIs must be in exactly the same order that we sent...
463    * Check packet length and CI length at each step.
464    * If we find any deviations, then this packet is bad.
465    */
466
467 #define ACKCIVJ(opt, neg, val, old, maxslotindex, cflag) \
468   if (neg) { \
469     int vjlen = old? CILEN_COMPRESS : CILEN_VJ; \
470     if ((len -= vjlen) < 0) { \
471       goto bad; \
472     } \
473     GETCHAR(citype, p); \
474     GETCHAR(cilen, p); \
475     if (cilen != vjlen || \
476         citype != opt) { \
477       goto bad; \
478     } \
479     GETSHORT(cishort, p); \
480     if (cishort != val) { \
481       goto bad; \
482     } \
483     if (!old) { \
484       GETCHAR(cimaxslotindex, p); \
485       if (cimaxslotindex != maxslotindex) { \
486         goto bad; \
487       } \
488       GETCHAR(cicflag, p); \
489       if (cicflag != cflag) { \
490         goto bad; \
491       } \
492     } \
493   }
494   
495 #define ACKCIADDR(opt, neg, old, val1, val2) \
496   if (neg) { \
497     int addrlen = (old? CILEN_ADDRS: CILEN_ADDR); \
498     u32_t l; \
499     if ((len -= addrlen) < 0) { \
500       goto bad; \
501     } \
502     GETCHAR(citype, p); \
503     GETCHAR(cilen, p); \
504     if (cilen != addrlen || \
505         citype != opt) { \
506       goto bad; \
507     } \
508     GETLONG(l, p); \
509     cilong = htonl(l); \
510     if (val1 != cilong) { \
511       goto bad; \
512     } \
513     if (old) { \
514       GETLONG(l, p); \
515       cilong = htonl(l); \
516       if (val2 != cilong) { \
517         goto bad; \
518       } \
519     } \
520   }
521
522 #define ACKCIDNS(opt, neg, addr) \
523   if (neg) { \
524     u32_t l; \
525     if ((len -= CILEN_ADDR) < 0) { \
526       goto bad; \
527     } \
528     GETCHAR(citype, p); \
529     GETCHAR(cilen, p); \
530     if (cilen != CILEN_ADDR || \
531         citype != opt) { \
532       goto bad; \
533     } \
534     GETLONG(l, p); \
535     cilong = htonl(l); \
536     if (addr != cilong) { \
537       goto bad; \
538     } \
539   }
540
541   ACKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), go->neg_addr,
542         go->old_addrs, go->ouraddr, go->hisaddr);
543
544   ACKCIVJ(CI_COMPRESSTYPE, go->neg_vj, go->vj_protocol, go->old_vj,
545       go->maxslotindex, go->cflag);
546
547   ACKCIDNS(CI_MS_DNS1, go->req_dns1, go->dnsaddr[0]);
548
549   ACKCIDNS(CI_MS_DNS2, go->req_dns2, go->dnsaddr[1]);
550
551   /*
552    * If there are any remaining CIs, then this packet is bad.
553    */
554   if (len != 0) {
555     goto bad;
556   }
557   return (1);
558   
559 bad:
560   IPCPDEBUG((LOG_INFO, "ipcp_ackci: received bad Ack!\n"));
561   return (0);
562 }
563
564 /*
565  * ipcp_nakci - Peer has sent a NAK for some of our CIs.
566  * This should not modify any state if the Nak is bad
567  * or if IPCP is in the LS_OPENED state.
568  *
569  * Returns:
570  *  0 - Nak was bad.
571  *  1 - Nak was good.
572  */
573 static int
574 ipcp_nakci(fsm *f, u_char *p, int len)
575 {
576   ipcp_options *go = &ipcp_gotoptions[f->unit];
577   u_char cimaxslotindex, cicflag;
578   u_char citype, cilen, *next;
579   u_short cishort;
580   u32_t ciaddr1, ciaddr2, l, cidnsaddr;
581   ipcp_options no;    /* options we've seen Naks for */
582   ipcp_options try;    /* options to request next time */
583
584   BZERO(&no, sizeof(no));
585   try = *go;
586
587   /*
588    * Any Nak'd CIs must be in exactly the same order that we sent.
589    * Check packet length and CI length at each step.
590    * If we find any deviations, then this packet is bad.
591    */
592 #define NAKCIADDR(opt, neg, old, code) \
593   if (go->neg && \
594       len >= (cilen = (old? CILEN_ADDRS: CILEN_ADDR)) && \
595       p[1] == cilen && \
596       p[0] == opt) { \
597     len -= cilen; \
598     INCPTR(2, p); \
599     GETLONG(l, p); \
600     ciaddr1 = htonl(l); \
601     if (old) { \
602       GETLONG(l, p); \
603       ciaddr2 = htonl(l); \
604       no.old_addrs = 1; \
605     } else { \
606       ciaddr2 = 0; \
607     } \
608     no.neg = 1; \
609     code \
610   }
611
612 #define NAKCIVJ(opt, neg, code) \
613   if (go->neg && \
614       ((cilen = p[1]) == CILEN_COMPRESS || cilen == CILEN_VJ) && \
615       len >= cilen && \
616       p[0] == opt) { \
617     len -= cilen; \
618     INCPTR(2, p); \
619     GETSHORT(cishort, p); \
620     no.neg = 1; \
621     code \
622   }
623   
624 #define NAKCIDNS(opt, neg, code) \
625   if (go->neg && \
626       ((cilen = p[1]) == CILEN_ADDR) && \
627       len >= cilen && \
628       p[0] == opt) { \
629     len -= cilen; \
630     INCPTR(2, p); \
631     GETLONG(l, p); \
632     cidnsaddr = htonl(l); \
633     no.neg = 1; \
634     code \
635   }
636
637   /*
638    * Accept the peer's idea of {our,his} address, if different
639    * from our idea, only if the accept_{local,remote} flag is set.
640    */
641   NAKCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr, go->old_addrs,
642     if (go->accept_local && ciaddr1) { /* Do we know our address? */
643       try.ouraddr = ciaddr1;
644       IPCPDEBUG((LOG_INFO, "local IP address %s\n",
645            inet_ntoa(ciaddr1)));
646     }
647     if (go->accept_remote && ciaddr2) { /* Does he know his? */
648       try.hisaddr = ciaddr2;
649       IPCPDEBUG((LOG_INFO, "remote IP address %s\n",
650            inet_ntoa(ciaddr2)));
651     }
652   );
653
654   /*
655    * Accept the peer's value of maxslotindex provided that it
656    * is less than what we asked for.  Turn off slot-ID compression
657    * if the peer wants.  Send old-style compress-type option if
658    * the peer wants.
659    */
660   NAKCIVJ(CI_COMPRESSTYPE, neg_vj,
661     if (cilen == CILEN_VJ) {
662       GETCHAR(cimaxslotindex, p);
663       GETCHAR(cicflag, p);
664       if (cishort == IPCP_VJ_COMP) {
665         try.old_vj = 0;
666         if (cimaxslotindex < go->maxslotindex) {
667           try.maxslotindex = cimaxslotindex;
668         }
669         if (!cicflag) {
670           try.cflag = 0;
671         }
672       } else {
673         try.neg_vj = 0;
674       }
675     } else {
676       if (cishort == IPCP_VJ_COMP || cishort == IPCP_VJ_COMP_OLD) {
677         try.old_vj = 1;
678         try.vj_protocol = cishort;
679       } else {
680         try.neg_vj = 0;
681       }
682     }
683   );
684
685   NAKCIDNS(CI_MS_DNS1, req_dns1,
686       try.dnsaddr[0] = cidnsaddr;
687         IPCPDEBUG((LOG_INFO, "primary DNS address %s\n", inet_ntoa(cidnsaddr)));
688       );
689
690   NAKCIDNS(CI_MS_DNS2, req_dns2,
691       try.dnsaddr[1] = cidnsaddr;
692         IPCPDEBUG((LOG_INFO, "secondary DNS address %s\n", inet_ntoa(cidnsaddr)));
693       );
694
695   /*
696   * There may be remaining CIs, if the peer is requesting negotiation
697   * on an option that we didn't include in our request packet.
698   * If they want to negotiate about IP addresses, we comply.
699   * If they want us to ask for compression, we refuse.
700   */
701   while (len > CILEN_VOID) {
702     GETCHAR(citype, p);
703     GETCHAR(cilen, p);
704     if( (len -= cilen) < 0 ) {
705       goto bad;
706     }
707     next = p + cilen - 2;
708
709     switch (citype) {
710       case CI_COMPRESSTYPE:
711         if (go->neg_vj || no.neg_vj ||
712             (cilen != CILEN_VJ && cilen != CILEN_COMPRESS)) {
713           goto bad;
714         }
715         no.neg_vj = 1;
716         break;
717       case CI_ADDRS:
718         if ((go->neg_addr && go->old_addrs) || no.old_addrs
719             || cilen != CILEN_ADDRS) {
720           goto bad;
721         }
722         try.neg_addr = 1;
723         try.old_addrs = 1;
724         GETLONG(l, p);
725         ciaddr1 = htonl(l);
726         if (ciaddr1 && go->accept_local) {
727           try.ouraddr = ciaddr1;
728         }
729         GETLONG(l, p);
730         ciaddr2 = htonl(l);
731         if (ciaddr2 && go->accept_remote) {
732           try.hisaddr = ciaddr2;
733         }
734         no.old_addrs = 1;
735         break;
736       case CI_ADDR:
737         if (go->neg_addr || no.neg_addr || cilen != CILEN_ADDR) {
738           goto bad;
739         }
740         try.old_addrs = 0;
741         GETLONG(l, p);
742         ciaddr1 = htonl(l);
743         if (ciaddr1 && go->accept_local) {
744           try.ouraddr = ciaddr1;
745         }
746         if (try.ouraddr != 0) {
747           try.neg_addr = 1;
748         }
749         no.neg_addr = 1;
750         break;
751     }
752     p = next;
753   }
754
755   /* If there is still anything left, this packet is bad. */
756   if (len != 0) {
757     goto bad;
758   }
759
760   /*
761    * OK, the Nak is good.  Now we can update state.
762    */
763   if (f->state != LS_OPENED) {
764     *go = try;
765   }
766
767   return 1;
768
769 bad:
770   IPCPDEBUG((LOG_INFO, "ipcp_nakci: received bad Nak!\n"));
771   return 0;
772 }
773
774
775 /*
776  * ipcp_rejci - Reject some of our CIs.
777  */
778 static int
779 ipcp_rejci(fsm *f, u_char *p, int len)
780 {
781   ipcp_options *go = &ipcp_gotoptions[f->unit];
782   u_char cimaxslotindex, ciflag, cilen;
783   u_short cishort;
784   u32_t cilong;
785   ipcp_options try;    /* options to request next time */
786
787   try = *go;
788   /*
789    * Any Rejected CIs must be in exactly the same order that we sent.
790    * Check packet length and CI length at each step.
791    * If we find any deviations, then this packet is bad.
792    */
793 #define REJCIADDR(opt, neg, old, val1, val2) \
794   if (go->neg && \
795       len >= (cilen = old? CILEN_ADDRS: CILEN_ADDR) && \
796       p[1] == cilen && \
797       p[0] == opt) { \
798     u32_t l; \
799     len -= cilen; \
800     INCPTR(2, p); \
801     GETLONG(l, p); \
802     cilong = htonl(l); \
803     /* Check rejected value. */ \
804     if (cilong != val1) { \
805       goto bad; \
806     } \
807     if (old) { \
808       GETLONG(l, p); \
809       cilong = htonl(l); \
810       /* Check rejected value. */ \
811       if (cilong != val2) { \
812         goto bad; \
813       } \
814     } \
815     try.neg = 0; \
816   }
817
818 #define REJCIVJ(opt, neg, val, old, maxslot, cflag) \
819   if (go->neg && \
820       p[1] == (old? CILEN_COMPRESS : CILEN_VJ) && \
821       len >= p[1] && \
822       p[0] == opt) { \
823     len -= p[1]; \
824     INCPTR(2, p); \
825     GETSHORT(cishort, p); \
826     /* Check rejected value. */  \
827     if (cishort != val) { \
828       goto bad; \
829     } \
830     if (!old) { \
831       GETCHAR(cimaxslotindex, p); \
832       if (cimaxslotindex != maxslot) { \
833         goto bad; \
834       } \
835       GETCHAR(ciflag, p); \
836       if (ciflag != cflag) { \
837         goto bad; \
838       } \
839     } \
840     try.neg = 0; \
841   }
842
843 #define REJCIDNS(opt, neg, dnsaddr) \
844   if (go->neg && \
845       ((cilen = p[1]) == CILEN_ADDR) && \
846       len >= cilen && \
847       p[0] == opt) { \
848     u32_t l; \
849     len -= cilen; \
850     INCPTR(2, p); \
851     GETLONG(l, p); \
852     cilong = htonl(l); \
853     /* Check rejected value. */ \
854     if (cilong != dnsaddr) { \
855       goto bad; \
856     } \
857     try.neg = 0; \
858   }
859
860   REJCIADDR((go->old_addrs? CI_ADDRS: CI_ADDR), neg_addr,
861         go->old_addrs, go->ouraddr, go->hisaddr);
862
863   REJCIVJ(CI_COMPRESSTYPE, neg_vj, go->vj_protocol, go->old_vj,
864       go->maxslotindex, go->cflag);
865
866   REJCIDNS(CI_MS_DNS1, req_dns1, go->dnsaddr[0]);
867
868   REJCIDNS(CI_MS_DNS2, req_dns2, go->dnsaddr[1]);
869
870   /*
871    * If there are any remaining CIs, then this packet is bad.
872    */
873   if (len != 0) {
874     goto bad;
875   }
876   /*
877    * Now we can update state.
878    */
879   if (f->state != LS_OPENED) {
880     *go = try;
881   }
882   return 1;
883
884 bad:
885   IPCPDEBUG((LOG_INFO, "ipcp_rejci: received bad Reject!\n"));
886   return 0;
887 }
888
889
890 /*
891  * ipcp_reqci - Check the peer's requested CIs and send appropriate response.
892  *
893  * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
894  * appropriately.  If reject_if_disagree is non-zero, doesn't return
895  * CONFNAK; returns CONFREJ if it can't return CONFACK.
896  */
897 static int
898 ipcp_reqci(fsm *f, u_char *inp/* Requested CIs */,int *len/* Length of requested CIs */,int reject_if_disagree)
899 {
900   ipcp_options *wo = &ipcp_wantoptions[f->unit];
901   ipcp_options *ho = &ipcp_hisoptions[f->unit];
902   ipcp_options *ao = &ipcp_allowoptions[f->unit];
903 #ifdef OLD_CI_ADDRS
904   ipcp_options *go = &ipcp_gotoptions[f->unit];
905 #endif
906   u_char *cip, *next;     /* Pointer to current and next CIs */
907   u_short cilen, citype;  /* Parsed len, type */
908   u_short cishort;        /* Parsed short value */
909   u32_t tl, ciaddr1;      /* Parsed address values */
910 #ifdef OLD_CI_ADDRS
911   u32_t ciaddr2;          /* Parsed address values */
912 #endif
913   int rc = CONFACK;       /* Final packet return code */
914   int orc;                /* Individual option return code */
915   u_char *p;              /* Pointer to next char to parse */
916   u_char *ucp = inp;      /* Pointer to current output char */
917   int l = *len;           /* Length left */
918   u_char maxslotindex, cflag;
919   int d;
920
921   cis_received[f->unit] = 1;
922
923   /*
924    * Reset all his options.
925    */
926   BZERO(ho, sizeof(*ho));
927
928   /*
929    * Process all his options.
930    */
931   next = inp;
932   while (l) {
933     orc = CONFACK;       /* Assume success */
934     cip = p = next;      /* Remember begining of CI */
935     if (l < 2 ||         /* Not enough data for CI header or */
936         p[1] < 2 ||      /*  CI length too small or */
937         p[1] > l) {      /*  CI length too big? */
938       IPCPDEBUG((LOG_INFO, "ipcp_reqci: bad CI length!\n"));
939       orc = CONFREJ;     /* Reject bad CI */
940       cilen = l;         /* Reject till end of packet */
941       l = 0;             /* Don't loop again */
942       goto endswitch;
943     }
944     GETCHAR(citype, p);  /* Parse CI type */
945     GETCHAR(cilen, p);   /* Parse CI length */
946     l -= cilen;          /* Adjust remaining length */
947     next += cilen;       /* Step to next CI */
948
949     switch (citype) {      /* Check CI type */
950 #ifdef OLD_CI_ADDRS /* Need to save space... */
951       case CI_ADDRS:
952         IPCPDEBUG((LOG_INFO, "ipcp_reqci: received ADDRS\n"));
953         if (!ao->neg_addr ||
954             cilen != CILEN_ADDRS) {  /* Check CI length */
955           orc = CONFREJ;    /* Reject CI */
956           break;
957         }
958
959         /*
960          * If he has no address, or if we both have his address but
961          * disagree about it, then NAK it with our idea.
962          * In particular, if we don't know his address, but he does,
963          * then accept it.
964          */
965         GETLONG(tl, p);    /* Parse source address (his) */
966         ciaddr1 = htonl(tl);
967         IPCPDEBUG((LOG_INFO, "his addr %s\n", inet_ntoa(ciaddr1)));
968         if (ciaddr1 != wo->hisaddr
969             && (ciaddr1 == 0 || !wo->accept_remote)) {
970           orc = CONFNAK;
971           if (!reject_if_disagree) {
972             DECPTR(sizeof(u32_t), p);
973             tl = ntohl(wo->hisaddr);
974             PUTLONG(tl, p);
975           }
976         } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
977           /*
978            * If neither we nor he knows his address, reject the option.
979            */
980           orc = CONFREJ;
981           wo->req_addr = 0;  /* don't NAK with 0.0.0.0 later */
982           break;
983         }
984
985         /*
986          * If he doesn't know our address, or if we both have our address
987          * but disagree about it, then NAK it with our idea.
988          */
989         GETLONG(tl, p);    /* Parse desination address (ours) */
990         ciaddr2 = htonl(tl);
991         IPCPDEBUG((LOG_INFO, "our addr %s\n", inet_ntoa(ciaddr2)));
992         if (ciaddr2 != wo->ouraddr) {
993           if (ciaddr2 == 0 || !wo->accept_local) {
994             orc = CONFNAK;
995             if (!reject_if_disagree) {
996               DECPTR(sizeof(u32_t), p);
997               tl = ntohl(wo->ouraddr);
998               PUTLONG(tl, p);
999             }
1000           } else {
1001             go->ouraddr = ciaddr2;  /* accept peer's idea */
1002           }
1003         }
1004
1005         ho->neg_addr = 1;
1006         ho->old_addrs = 1;
1007         ho->hisaddr = ciaddr1;
1008         ho->ouraddr = ciaddr2;
1009         break;
1010 #endif
1011
1012       case CI_ADDR:
1013         if (!ao->neg_addr) {
1014           IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR not allowed\n"));
1015           orc = CONFREJ;        /* Reject CI */
1016           break;
1017         } else if (cilen != CILEN_ADDR) {  /* Check CI length */
1018           IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR bad len\n"));
1019           orc = CONFREJ;        /* Reject CI */
1020           break;
1021         }
1022
1023         /*
1024          * If he has no address, or if we both have his address but
1025          * disagree about it, then NAK it with our idea.
1026          * In particular, if we don't know his address, but he does,
1027          * then accept it.
1028          */
1029         GETLONG(tl, p);  /* Parse source address (his) */
1030         ciaddr1 = htonl(tl);
1031         if (ciaddr1 != wo->hisaddr
1032             && (ciaddr1 == 0 || !wo->accept_remote)) {
1033           orc = CONFNAK;
1034           if (!reject_if_disagree) {
1035             DECPTR(sizeof(u32_t), p);
1036             tl = ntohl(wo->hisaddr);
1037             PUTLONG(tl, p);
1038           }
1039           IPCPDEBUG((LOG_INFO, "ipcp_reqci: Nak ADDR %s\n", inet_ntoa(ciaddr1)));
1040         } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
1041           /*
1042            * Don't ACK an address of 0.0.0.0 - reject it instead.
1043            */
1044           IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR %s\n", inet_ntoa(ciaddr1)));
1045           orc = CONFREJ;
1046           wo->req_addr = 0;  /* don't NAK with 0.0.0.0 later */
1047           break;
1048         }
1049
1050         ho->neg_addr = 1;
1051         ho->hisaddr = ciaddr1;
1052         IPCPDEBUG((LOG_INFO, "ipcp_reqci: ADDR %s\n", inet_ntoa(ciaddr1)));
1053         break;
1054
1055       case CI_MS_DNS1:
1056       case CI_MS_DNS2:
1057         /* Microsoft primary or secondary DNS request */
1058         d = citype == CI_MS_DNS2;
1059
1060         /* If we do not have a DNS address then we cannot send it */
1061         if (ao->dnsaddr[d] == 0 ||
1062             cilen != CILEN_ADDR) {  /* Check CI length */
1063           IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting DNS%d Request\n", d+1));
1064           orc = CONFREJ;        /* Reject CI */
1065           break;
1066         }
1067         GETLONG(tl, p);
1068         if (htonl(tl) != ao->dnsaddr[d]) {
1069           IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking DNS%d Request %d\n",
1070                 d+1, inet_ntoa(tl)));
1071           DECPTR(sizeof(u32_t), p);
1072           tl = ntohl(ao->dnsaddr[d]);
1073           PUTLONG(tl, p);
1074           orc = CONFNAK;
1075         }
1076         IPCPDEBUG((LOG_INFO, "ipcp_reqci: received DNS%d Request\n", d+1));
1077         break;
1078
1079       case CI_MS_WINS1:
1080       case CI_MS_WINS2:
1081         /* Microsoft primary or secondary WINS request */
1082         d = citype == CI_MS_WINS2;
1083         IPCPDEBUG((LOG_INFO, "ipcp_reqci: received WINS%d Request\n", d+1));
1084
1085         /* If we do not have a DNS address then we cannot send it */
1086         if (ao->winsaddr[d] == 0 ||
1087           cilen != CILEN_ADDR) {  /* Check CI length */
1088           orc = CONFREJ;      /* Reject CI */
1089           break;
1090         }
1091         GETLONG(tl, p);
1092         if (htonl(tl) != ao->winsaddr[d]) {
1093           DECPTR(sizeof(u32_t), p);
1094           tl = ntohl(ao->winsaddr[d]);
1095           PUTLONG(tl, p);
1096           orc = CONFNAK;
1097         }
1098         break;
1099
1100       case CI_COMPRESSTYPE:
1101         if (!ao->neg_vj) {
1102           IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE not allowed\n"));
1103           orc = CONFREJ;
1104           break;
1105         } else if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) {
1106           IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE len=%d\n", cilen));
1107           orc = CONFREJ;
1108           break;
1109         }
1110         GETSHORT(cishort, p);
1111
1112         if (!(cishort == IPCP_VJ_COMP ||
1113             (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {
1114           IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE %d\n", cishort));
1115           orc = CONFREJ;
1116           break;
1117         }
1118
1119         ho->neg_vj = 1;
1120         ho->vj_protocol = cishort;
1121         if (cilen == CILEN_VJ) {
1122           GETCHAR(maxslotindex, p);
1123           if (maxslotindex > ao->maxslotindex) { 
1124             IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ max slot %d\n", maxslotindex));
1125             orc = CONFNAK;
1126             if (!reject_if_disagree) {
1127               DECPTR(1, p);
1128               PUTCHAR(ao->maxslotindex, p);
1129             }
1130           }
1131           GETCHAR(cflag, p);
1132           if (cflag && !ao->cflag) {
1133             IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ cflag %d\n", cflag));
1134             orc = CONFNAK;
1135             if (!reject_if_disagree) {
1136               DECPTR(1, p);
1137               PUTCHAR(wo->cflag, p);
1138             }
1139           }
1140           ho->maxslotindex = maxslotindex;
1141           ho->cflag = cflag;
1142         } else {
1143           ho->old_vj = 1;
1144           ho->maxslotindex = MAX_SLOTS - 1;
1145           ho->cflag = 1;
1146         }
1147         IPCPDEBUG((LOG_INFO, 
1148               "ipcp_reqci: received COMPRESSTYPE p=%d old=%d maxslot=%d cflag=%d\n",
1149               ho->vj_protocol, ho->old_vj, ho->maxslotindex, ho->cflag));
1150         break;
1151
1152       default:
1153         IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting unknown CI type %d\n", citype));
1154         orc = CONFREJ;
1155         break;
1156     }
1157
1158 endswitch:
1159     if (orc == CONFACK &&    /* Good CI */
1160         rc != CONFACK) {     /*  but prior CI wasnt? */
1161       continue;              /* Don't send this one */
1162     }
1163
1164     if (orc == CONFNAK) {    /* Nak this CI? */
1165       if (reject_if_disagree) {  /* Getting fed up with sending NAKs? */
1166         IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting too many naks\n"));
1167         orc = CONFREJ;       /* Get tough if so */
1168       } else {
1169         if (rc == CONFREJ) { /* Rejecting prior CI? */
1170           continue;          /* Don't send this one */
1171         }
1172         if (rc == CONFACK) { /* Ack'd all prior CIs? */
1173           rc = CONFNAK;      /* Not anymore... */
1174           ucp = inp;         /* Backup */
1175         }
1176       }
1177     }
1178
1179     if (orc == CONFREJ &&    /* Reject this CI */
1180         rc != CONFREJ) {  /*  but no prior ones? */
1181       rc = CONFREJ;
1182       ucp = inp;        /* Backup */
1183     }
1184     
1185     /* Need to move CI? */
1186     if (ucp != cip) {
1187       BCOPY(cip, ucp, cilen);  /* Move it */
1188     }
1189
1190     /* Update output pointer */
1191     INCPTR(cilen, ucp);
1192   }
1193
1194   /*
1195    * If we aren't rejecting this packet, and we want to negotiate
1196    * their address, and they didn't send their address, then we
1197    * send a NAK with a CI_ADDR option appended.  We assume the
1198    * input buffer is long enough that we can append the extra
1199    * option safely.
1200    */
1201   if (rc != CONFREJ && !ho->neg_addr &&
1202       wo->req_addr && !reject_if_disagree) {
1203     IPCPDEBUG((LOG_INFO, "ipcp_reqci: Requesting peer address\n"));
1204     if (rc == CONFACK) {
1205       rc = CONFNAK;
1206       ucp = inp;        /* reset pointer */
1207       wo->req_addr = 0;    /* don't ask again */
1208     }
1209     PUTCHAR(CI_ADDR, ucp);
1210     PUTCHAR(CILEN_ADDR, ucp);
1211     tl = ntohl(wo->hisaddr);
1212     PUTLONG(tl, ucp);
1213   }
1214
1215   *len = (int)(ucp - inp);    /* Compute output length */
1216   IPCPDEBUG((LOG_INFO, "ipcp_reqci: returning Configure-%s\n", CODENAME(rc)));
1217   return (rc);      /* Return final code */
1218 }
1219
1220
1221 #if 0
1222 /*
1223  * ip_check_options - check that any IP-related options are OK,
1224  * and assign appropriate defaults.
1225  */
1226 static void
1227 ip_check_options(u_long localAddr)
1228 {
1229   ipcp_options *wo = &ipcp_wantoptions[0];
1230
1231   /*
1232    * Load our default IP address but allow the remote host to give us
1233    * a new address.
1234    */
1235   if (wo->ouraddr == 0 && !ppp_settings.disable_defaultip) {
1236     wo->accept_local = 1;  /* don't insist on this default value */
1237     wo->ouraddr = htonl(localAddr);
1238   }
1239 }
1240 #endif
1241
1242
1243 /*
1244  * ipcp_up - IPCP has come UP.
1245  *
1246  * Configure the IP network interface appropriately and bring it up.
1247  */
1248 static void
1249 ipcp_up(fsm *f)
1250 {
1251   u32_t mask;
1252   ipcp_options *ho = &ipcp_hisoptions[f->unit];
1253   ipcp_options *go = &ipcp_gotoptions[f->unit];
1254   ipcp_options *wo = &ipcp_wantoptions[f->unit];
1255
1256   np_up(f->unit, PPP_IP);
1257   IPCPDEBUG((LOG_INFO, "ipcp: up\n"));
1258
1259   /*
1260    * We must have a non-zero IP address for both ends of the link.
1261    */
1262   if (!ho->neg_addr) {
1263     ho->hisaddr = wo->hisaddr;
1264   }
1265
1266   if (ho->hisaddr == 0) {
1267     IPCPDEBUG((LOG_ERR, "Could not determine remote IP address\n"));
1268     ipcp_close(f->unit, "Could not determine remote IP address");
1269     return;
1270   }
1271   if (go->ouraddr == 0) {
1272     IPCPDEBUG((LOG_ERR, "Could not determine local IP address\n"));
1273     ipcp_close(f->unit, "Could not determine local IP address");
1274     return;
1275   }
1276
1277   if (ppp_settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) {
1278     /*pppGotDNSAddrs(go->dnsaddr[0], go->dnsaddr[1]);*/
1279   }
1280
1281   /*
1282    * Check that the peer is allowed to use the IP address it wants.
1283    */
1284   if (!auth_ip_addr(f->unit, ho->hisaddr)) {
1285     IPCPDEBUG((LOG_ERR, "Peer is not authorized to use remote address %s\n",
1286         inet_ntoa(ho->hisaddr)));
1287     ipcp_close(f->unit, "Unauthorized remote IP address");
1288     return;
1289   }
1290
1291   /* set tcp compression */
1292   sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex);
1293
1294   /*
1295    * Set IP addresses and (if specified) netmask.
1296    */
1297   mask = GetMask(go->ouraddr);
1298
1299   if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask, go->dnsaddr[0], go->dnsaddr[1])) {
1300     IPCPDEBUG((LOG_WARNING, "sifaddr failed\n"));
1301     ipcp_close(f->unit, "Interface configuration failed");
1302     return;
1303   }
1304
1305   /* bring the interface up for IP */
1306   if (!sifup(f->unit)) {
1307     IPCPDEBUG((LOG_WARNING, "sifup failed\n"));
1308     ipcp_close(f->unit, "Interface configuration failed");
1309     return;
1310   }
1311
1312   sifnpmode(f->unit, PPP_IP, NPMODE_PASS);
1313
1314   /* assign a default route through the interface if required */
1315   if (ipcp_wantoptions[f->unit].default_route) {
1316     if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) {
1317       default_route_set[f->unit] = 1;
1318     }
1319   }
1320
1321   IPCPDEBUG((LOG_NOTICE, "local  IP address %s\n", inet_ntoa(go->ouraddr)));
1322   IPCPDEBUG((LOG_NOTICE, "remote IP address %s\n", inet_ntoa(ho->hisaddr)));
1323   if (go->dnsaddr[0]) {
1324     IPCPDEBUG((LOG_NOTICE, "primary   DNS address %s\n", inet_ntoa(go->dnsaddr[0])));
1325   }
1326   if (go->dnsaddr[1]) {
1327     IPCPDEBUG((LOG_NOTICE, "secondary DNS address %s\n", inet_ntoa(go->dnsaddr[1])));
1328   }
1329 }
1330
1331
1332 /*
1333  * ipcp_down - IPCP has gone DOWN.
1334  *
1335  * Take the IP network interface down, clear its addresses
1336  * and delete routes through it.
1337  */
1338 static void
1339 ipcp_down(fsm *f)
1340 {
1341   IPCPDEBUG((LOG_INFO, "ipcp: down\n"));
1342   np_down(f->unit, PPP_IP);
1343   sifvjcomp(f->unit, 0, 0, 0);
1344
1345   sifdown(f->unit);
1346   ipcp_clear_addrs(f->unit);
1347 }
1348
1349
1350 /*
1351  * ipcp_clear_addrs() - clear the interface addresses, routes, etc.
1352  */
1353 static void
1354 ipcp_clear_addrs(int unit)
1355 {
1356   u32_t ouraddr, hisaddr;
1357
1358   ouraddr = ipcp_gotoptions[unit].ouraddr;
1359   hisaddr = ipcp_hisoptions[unit].hisaddr;
1360   if (default_route_set[unit]) {
1361     cifdefaultroute(unit, ouraddr, hisaddr);
1362     default_route_set[unit] = 0;
1363   }
1364   cifaddr(unit, ouraddr, hisaddr);
1365 }
1366
1367
1368 /*
1369  * ipcp_finished - possibly shut down the lower layers.
1370  */
1371 static void
1372 ipcp_finished(fsm *f)
1373 {
1374   np_finished(f->unit, PPP_IP);
1375 }
1376
1377 #if 0
1378 static int
1379 ipcp_printpkt(u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg)
1380 {
1381   LWIP_UNUSED_ARG(p);
1382   LWIP_UNUSED_ARG(plen);
1383   LWIP_UNUSED_ARG(printer);
1384   LWIP_UNUSED_ARG(arg);
1385   return 0;
1386 }
1387
1388 /*
1389  * ip_active_pkt - see if this IP packet is worth bringing the link up for.
1390  * We don't bring the link up for IP fragments or for TCP FIN packets
1391  * with no data.
1392  */
1393 #define IP_HDRLEN   20  /* bytes */
1394 #define IP_OFFMASK  0x1fff
1395 #define IPPROTO_TCP 6
1396 #define TCP_HDRLEN  20
1397 #define TH_FIN      0x01
1398
1399 /*
1400  * We use these macros because the IP header may be at an odd address,
1401  * and some compilers might use word loads to get th_off or ip_hl.
1402  */
1403
1404 #define net_short(x)    (((x)[0] << 8) + (x)[1])
1405 #define get_iphl(x)     (((unsigned char *)(x))[0] & 0xF)
1406 #define get_ipoff(x)    net_short((unsigned char *)(x) + 6)
1407 #define get_ipproto(x)  (((unsigned char *)(x))[9])
1408 #define get_tcpoff(x)   (((unsigned char *)(x))[12] >> 4)
1409 #define get_tcpflags(x) (((unsigned char *)(x))[13])
1410
1411 static int
1412 ip_active_pkt(u_char *pkt, int len)
1413 {
1414   u_char *tcp;
1415   int hlen;
1416
1417   len -= PPP_HDRLEN;
1418   pkt += PPP_HDRLEN;
1419   if (len < IP_HDRLEN) {
1420     return 0;
1421   }
1422   if ((get_ipoff(pkt) & IP_OFFMASK) != 0) {
1423     return 0;
1424   }
1425   if (get_ipproto(pkt) != IPPROTO_TCP) {
1426     return 1;
1427   }
1428   hlen = get_iphl(pkt) * 4;
1429   if (len < hlen + TCP_HDRLEN) {
1430     return 0;
1431   }
1432   tcp = pkt + hlen;
1433   if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) {
1434     return 0;
1435   }
1436   return 1;
1437 }
1438 #endif
1439
1440 #endif /* PPP_SUPPORT */