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