LwIP with PPP & Ethernet integration

Dependents:   NetworkingCoreLib

This is the mbed port of the LwIP stack: http://savannah.nongnu.org/projects/lwip/

It includes contributed content from NXP's port for LPCxxxx devices: http://www.lpcware.com/content/project/lightweight-ip-lwip-networking-stack

Licence

LwIP is licenced under the BSD licence:

Copyright (c) 2001-2004 Swedish Institute of Computer Science. 
All rights reserved. 
Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met: 
1. Redistributions of source code must retain the above copyright notice, 
this list of conditions and the following disclaimer. 
2. Redistributions in binary form must reproduce the above copyright notice, 
this list of conditions and the following disclaimer in the documentation 
and/or other materials provided with the distribution. 
3. The name of the author may not be used to endorse or promote products 
derived from this software without specific prior written permission. 
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 
SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
Committer:
donatien
Date:
Fri May 25 08:56:35 2012 +0000
Revision:
2:1a87f74b8e3b
Parent:
0:8e01dca41002
Removed compilation of EMAC driver when using PPP

Who changed what in which revision?

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