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