1/* 2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* 24 * demand.c - Support routines for demand-dialling. 25 * 26 * Copyright (c) 1996-2002 Paul Mackerras. All rights reserved. 27 * 28 * Redistribution and use in source and binary forms, with or without 29 * modification, are permitted provided that the following conditions 30 * are met: 31 * 32 * 1. Redistributions of source code must retain the above copyright 33 * notice, this list of conditions and the following disclaimer. 34 * 35 * 2. Redistributions in binary form must reproduce the above copyright 36 * notice, this list of conditions and the following disclaimer in 37 * the documentation and/or other materials provided with the 38 * distribution. 39 * 40 * 3. The name(s) of the authors of this software must not be used to 41 * endorse or promote products derived from this software without 42 * prior written permission. 43 * 44 * 4. Redistributions of any form whatsoever must retain the following 45 * acknowledgment: 46 * "This product includes software developed by Paul Mackerras 47 * <paulus@samba.org>". 48 * 49 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO 50 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 51 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY 52 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 53 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 54 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 55 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 56 */ 57 58#define RCSID "$Id: demand.c,v 1.7 2004/03/04 01:36:32 lindak Exp $" 59 60#include <stdio.h> 61#include <stdlib.h> 62#include <string.h> 63#include <errno.h> 64#include <fcntl.h> 65#include <netdb.h> 66#include <sys/param.h> 67#include <sys/types.h> 68#include <sys/wait.h> 69#include <sys/time.h> 70#include <sys/resource.h> 71#include <sys/stat.h> 72#include <sys/socket.h> 73#ifdef PPP_FILTER 74#include <net/if.h> 75#include <net/bpf.h> 76#include <pcap.h> 77#endif 78 79#include "pppd.h" 80#include "fsm.h" 81#include "ipcp.h" 82#include "lcp.h" 83 84#ifndef lint 85static const char rcsid[] = RCSID; 86#endif 87 88char *frame; 89int framelen; 90int framemax; 91int escape_flag; 92int flush_flag; 93int fcs; 94 95struct packet { 96 int length; 97 struct packet *next; 98 unsigned char data[1]; 99}; 100 101struct packet *pend_q; 102struct packet *pend_qtail; 103 104static int active_packet __P((unsigned char *, int)); 105 106/* 107 * demand_conf - configure the interface for doing dial-on-demand. 108 */ 109void 110demand_conf() 111{ 112 int i; 113 struct protent *protp; 114 115/* framemax = lcp_allowoptions[0].mru; 116 if (framemax < PPP_MRU) */ 117 framemax = PPP_MRU; 118 framemax += PPP_HDRLEN + PPP_FCSLEN; 119 frame = malloc(framemax); 120 if (frame == NULL) 121 novm("demand frame"); 122 framelen = 0; 123 pend_q = NULL; 124 escape_flag = 0; 125 flush_flag = 0; 126 fcs = PPP_INITFCS; 127 128 netif_set_mtu(0, MIN(lcp_allowoptions[0].mru, PPP_MRU)); 129 if (ppp_send_config(0, PPP_MRU, (u_int32_t) 0, 0, 0) < 0 130 || ppp_recv_config(0, PPP_MRU, (u_int32_t) 0, 0, 0) < 0) 131 fatal("Couldn't set up demand-dialled PPP interface: %m"); 132 133#ifdef PPP_FILTER 134 set_filters(&pass_filter, &active_filter); 135#endif 136 137 /* 138 * Call the demand_conf procedure for each protocol that's got one. 139 */ 140 for (i = 0; (protp = protocols[i]) != NULL; ++i) 141 if (protp->enabled_flag && protp->demand_conf != NULL) 142 if (!((*protp->demand_conf)(0))) 143 die(1); 144} 145 146 147/* 148 * demand_block - set each network protocol to block further packets. 149 */ 150void 151demand_block() 152{ 153 int i; 154 struct protent *protp; 155 156 for (i = 0; (protp = protocols[i]) != NULL; ++i) 157 if (protp->enabled_flag && protp->demand_conf != NULL) 158 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_QUEUE); 159 get_loop_output(); 160} 161 162/* 163 * demand_discard - set each network protocol to discard packets 164 * with an error. 165 */ 166void 167demand_discard() 168{ 169 struct packet *pkt, *nextpkt; 170 int i; 171 struct protent *protp; 172 173 for (i = 0; (protp = protocols[i]) != NULL; ++i) 174 if (protp->enabled_flag && protp->demand_conf != NULL) 175 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_ERROR); 176 get_loop_output(); 177 178 /* discard all saved packets */ 179 for (pkt = pend_q; pkt != NULL; pkt = nextpkt) { 180 nextpkt = pkt->next; 181 free(pkt); 182 } 183 pend_q = NULL; 184 framelen = 0; 185 flush_flag = 0; 186 escape_flag = 0; 187 fcs = PPP_INITFCS; 188} 189 190/* 191 * demand_unblock - set each enabled network protocol to pass packets. 192 */ 193void 194demand_unblock() 195{ 196 int i; 197 struct protent *protp; 198 199 for (i = 0; (protp = protocols[i]) != NULL; ++i) 200 if (protp->enabled_flag && protp->demand_conf != NULL) 201 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_PASS); 202} 203 204/* 205 * FCS lookup table as calculated by genfcstab. 206 */ 207static u_short fcstab[256] = { 208 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 209 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 210 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 211 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 212 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 213 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 214 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 215 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 216 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 217 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 218 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 219 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 220 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 221 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 222 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 223 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 224 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 225 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 226 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 227 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 228 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 229 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 230 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 231 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 232 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 233 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 234 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 235 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 236 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 237 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 238 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 239 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 240}; 241 242/* 243 * loop_chars - process characters received from the loopback. 244 * Calls loop_frame when a complete frame has been accumulated. 245 * Return value is 1 if we need to bring up the link, 0 otherwise. 246 */ 247int 248loop_chars(p, n) 249 unsigned char *p; 250 int n; 251{ 252 int c, rv; 253 254 rv = 0; 255 for (; n > 0; --n) { 256 c = *p++; 257 if (c == PPP_FLAG) { 258 if (!escape_flag && !flush_flag 259 && framelen > 2 && fcs == PPP_GOODFCS) { 260 framelen -= 2; 261 if (loop_frame((unsigned char *)frame, framelen)) 262 rv = 1; 263 } 264 framelen = 0; 265 flush_flag = 0; 266 escape_flag = 0; 267 fcs = PPP_INITFCS; 268 continue; 269 } 270 if (flush_flag) 271 continue; 272 if (escape_flag) { 273 c ^= PPP_TRANS; 274 escape_flag = 0; 275 } else if (c == PPP_ESCAPE) { 276 escape_flag = 1; 277 continue; 278 } 279 if (framelen >= framemax) { 280 flush_flag = 1; 281 continue; 282 } 283 frame[framelen++] = c; 284 fcs = PPP_FCS(fcs, c); 285 } 286 return rv; 287} 288 289/* 290 * loop_frame - given a frame obtained from the loopback, 291 * decide whether to bring up the link or not, and, if we want 292 * to transmit this frame later, put it on the pending queue. 293 * Return value is 1 if we need to bring up the link, 0 otherwise. 294 * We assume that the kernel driver has already applied the 295 * pass_filter, so we won't get packets it rejected. 296 * We apply the active_filter to see if we want this packet to 297 * bring up the link. 298 */ 299int 300loop_frame(frame, len) 301 unsigned char *frame; 302 int len; 303{ 304 struct packet *pkt; 305 306 dbglog("Dial on demand: %P", frame, len); 307 if (len < PPP_HDRLEN) 308 return 0; 309 if ((PPP_PROTOCOL(frame) & 0x8000) != 0) 310 return 0; /* shouldn't get any of these anyway */ 311 if (!active_packet(frame, len)) 312 return 0; 313 314 pkt = (struct packet *) malloc(sizeof(struct packet) + len); 315 if (pkt != NULL) { 316 pkt->length = len; 317 pkt->next = NULL; 318 memcpy(pkt->data, frame, len); 319 if (pend_q == NULL) 320 pend_q = pkt; 321 else 322 pend_qtail->next = pkt; 323 pend_qtail = pkt; 324 } 325 return 1; 326} 327 328/* 329 * demand_rexmit - Resend all those frames which we got via the 330 * loopback, now that the real serial link is up. 331 */ 332void 333demand_rexmit(proto) 334 int proto; 335{ 336 struct packet *pkt, *prev, *nextpkt; 337 338 prev = NULL; 339 pkt = pend_q; 340 pend_q = NULL; 341 for (; pkt != NULL; pkt = nextpkt) { 342 nextpkt = pkt->next; 343 if (PPP_PROTOCOL(pkt->data) == proto) { 344 output(0, pkt->data, pkt->length); 345 free(pkt); 346 } else { 347 if (prev == NULL) 348 pend_q = pkt; 349 else 350 prev->next = pkt; 351 prev = pkt; 352 } 353 } 354 pend_qtail = prev; 355 if (prev != NULL) 356 prev->next = NULL; 357} 358 359/* 360 * Scan a packet to decide whether it is an "active" packet, 361 * that is, whether it is worth bringing up the link for. 362 */ 363static int 364active_packet(p, len) 365 unsigned char *p; 366 int len; 367{ 368 int proto, i; 369 struct protent *protp; 370 371 if (len < PPP_HDRLEN) 372 return 0; 373 proto = PPP_PROTOCOL(p); 374#ifdef PPP_FILTER 375 if (pass_filter.bf_len != 0 376 && bpf_filter(pass_filter.bf_insns, p, len, len) == 0) 377 return 0; 378 if (active_filter.bf_len != 0 379 && bpf_filter(active_filter.bf_insns, p, len, len) == 0) 380 return 0; 381#endif 382 for (i = 0; (protp = protocols[i]) != NULL; ++i) { 383 if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) { 384 if (!protp->enabled_flag) 385 return 0; 386 if (protp->active_pkt == NULL) 387 return 1; 388 return (*protp->active_pkt)(p, len); 389 } 390 } 391 return 0; /* not a supported protocol !!?? */ 392} 393