1/* $NetBSD: demand.c,v 1.5 2021/01/09 16:39:28 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 " 36static const char rcsid[] = RCSID; 37#else 38__RCSID("$NetBSD: demand.c,v 1.5 2021/01/09 16:39:28 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 64char *frame; 65int framelen; 66int framemax; 67int escape_flag; 68int flush_flag; 69int fcs; 70 71struct packet { 72 int length; 73 struct packet *next; 74 unsigned char data[1]; 75}; 76 77struct packet *pend_q; 78struct packet *pend_qtail; 79 80static int active_packet(unsigned char *, int); 81 82/* 83 * demand_conf - configure the interface for doing dial-on-demand. 84 */ 85void 86demand_conf(void) 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 */ 127void 128demand_block(void) 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 */ 143void 144demand_discard(void) 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 */ 170void 171demand_unblock(void) 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 */ 184static 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 */ 224int 225loop_chars(unsigned char *p, int n) 226{ 227 int c, rv; 228 229 rv = 0; 230 for (; n > 0; --n) { 231 c = *p++; 232 if (c == PPP_FLAG) { 233 if (!escape_flag && !flush_flag 234 && framelen > 2 && fcs == PPP_GOODFCS) { 235 framelen -= 2; 236 if (loop_frame((unsigned char *)frame, framelen)) 237 rv = 1; 238 } 239 framelen = 0; 240 flush_flag = 0; 241 escape_flag = 0; 242 fcs = PPP_INITFCS; 243 continue; 244 } 245 if (flush_flag) 246 continue; 247 if (escape_flag) { 248 c ^= PPP_TRANS; 249 escape_flag = 0; 250 } else if (c == PPP_ESCAPE) { 251 escape_flag = 1; 252 continue; 253 } 254 if (framelen >= framemax) { 255 flush_flag = 1; 256 continue; 257 } 258 frame[framelen++] = c; 259 fcs = PPP_FCS(fcs, c); 260 } 261 return rv; 262} 263 264/* 265 * loop_frame - given a frame obtained from the loopback, 266 * decide whether to bring up the link or not, and, if we want 267 * to transmit this frame later, put it on the pending queue. 268 * Return value is 1 if we need to bring up the link, 0 otherwise. 269 * We assume that the kernel driver has already applied the 270 * pass_filter, so we won't get packets it rejected. 271 * We apply the active_filter to see if we want this packet to 272 * bring up the link. 273 */ 274int 275loop_frame(unsigned char *frame, int len) 276{ 277 struct packet *pkt; 278 279 /* dbglog("from loop: %P", frame, len); */ 280 if (len < PPP_HDRLEN) 281 return 0; 282 if ((PPP_PROTOCOL(frame) & 0x8000) != 0) 283 return 0; /* shouldn't get any of these anyway */ 284 if (!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 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 which we got via the 303 * loopback, now that the real serial link is up. 304 */ 305void 306demand_rexmit(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 */ 335static int 336active_packet(unsigned char *p, int len) 337{ 338 int proto, i; 339 struct protent *protp; 340 341 if (len < PPP_HDRLEN) 342 return 0; 343 proto = PPP_PROTOCOL(p); 344#ifdef PPP_FILTER 345 p[0] = 1; /* outbound packet indicator */ 346 if ((pass_filter_out.bf_len != 0 347 && bpf_filter(pass_filter_out.bf_insns, p, len, len) == 0) 348 || (active_filter_out.bf_len != 0 349 && bpf_filter(active_filter_out.bf_insns, p, len, len) == 0)) { 350 p[0] = 0xff; 351 return 0; 352 } 353 p[0] = 0xff; 354#endif 355 for (i = 0; (protp = protocols[i]) != NULL; ++i) { 356 if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) { 357 if (!protp->enabled_flag) 358 return 0; 359 if (protp->active_pkt == NULL) 360 return 1; 361 return (*protp->active_pkt)(p, len); 362 } 363 } 364 return 0; /* not a supported protocol !!?? */ 365} 366