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