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