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