Modified version of NetServices. Fixes an issue where connections failed should the HTTP response status line be received in a packet on its own prior to any further headers. Changes are made to the HTTPClient.cpp file's readHeaders method.

Committer:
andrewbonney
Date:
Fri Apr 08 14:39:41 2011 +0000
Revision:
0:ec559500a63f

        

Who changed what in which revision?

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