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