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