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