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