2 * demand.c - Support routines for demand-dialling.
4 * Copyright (c) 1996-2002 Paul Mackerras. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. The name(s) of the authors of this software must not be used to
14 * endorse or promote products derived from this software without
15 * prior written permission.
17 * 3. Redistributions of any form whatsoever must retain the following
19 * "This product includes software developed by Paul Mackerras
20 * <paulus@samba.org>".
22 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
23 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
24 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
26 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
27 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
28 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31 #define RCSID "$Id: demand.c,v 1.20 2005/08/25 12:14:18 paulus Exp $"
43 #include <sys/param.h>
44 #include <sys/types.h>
47 #include <sys/resource.h>
49 #include <sys/socket.h>
50 #ifdef PPP_WITH_FILTER
70 unsigned char data[1];
73 struct packet *pend_q;
74 struct packet *pend_qtail;
76 static int active_packet(unsigned char *, int);
79 * demand_conf - configure the interface for doing dial-on-demand.
85 struct protent *protp;
87 /* framemax = lcp_allowoptions[0].mru;
88 if (framemax < PPP_MRU) */
90 framemax += PPP_HDRLEN + PPP_FCSLEN;
91 frame = malloc(framemax);
100 netif_set_mtu(0, MIN(lcp_allowoptions[0].mru, PPP_MRU));
101 if (ppp_send_config(0, PPP_MRU, (u_int32_t) 0, 0, 0) < 0
102 || ppp_recv_config(0, PPP_MRU, (u_int32_t) 0, 0, 0) < 0)
103 fatal("Couldn't set up demand-dialled PPP interface: %m");
105 #ifdef PPP_WITH_FILTER
106 set_filters(&pass_filter, &active_filter);
110 * Call the demand_conf procedure for each protocol that's got one.
112 for (i = 0; (protp = protocols[i]) != NULL; ++i)
113 if (protp->enabled_flag && protp->demand_conf != NULL)
114 if (!((*protp->demand_conf)(0)))
120 * demand_block - set each network protocol to block further packets.
126 struct protent *protp;
128 for (i = 0; (protp = protocols[i]) != NULL; ++i)
129 if (protp->enabled_flag && protp->demand_conf != NULL)
130 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_QUEUE);
135 * demand_discard - set each network protocol to discard packets
141 struct packet *pkt, *nextpkt;
143 struct protent *protp;
145 for (i = 0; (protp = protocols[i]) != NULL; ++i)
146 if (protp->enabled_flag && protp->demand_conf != NULL)
147 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_ERROR);
150 /* discard all saved packets */
151 for (pkt = pend_q; pkt != NULL; pkt = nextpkt) {
163 * demand_unblock - set each enabled network protocol to pass packets.
169 struct protent *protp;
171 for (i = 0; (protp = protocols[i]) != NULL; ++i)
172 if (protp->enabled_flag && protp->demand_conf != NULL)
173 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_PASS);
177 * FCS lookup table as calculated by genfcstab.
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
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.
220 loop_chars(unsigned char *p, int n)
228 if (!escape_flag && !flush_flag
229 && framelen > 2 && fcs == PPP_GOODFCS) {
231 if (loop_frame((unsigned char *)frame, framelen))
245 } else if (c == PPP_ESCAPE) {
249 if (framelen >= framemax) {
253 frame[framelen++] = c;
254 fcs = PPP_FCS(fcs, c);
260 * loop_frame - given a frame obtained from the loopback,
261 * decide whether to bring up the link or not, and, if we want
262 * to transmit this frame later, put it on the pending queue.
263 * Return value is 1 if we need to bring up the link, 0 otherwise.
264 * We assume that the kernel driver has already applied the
265 * pass_filter, so we won't get packets it rejected.
266 * We apply the active_filter to see if we want this packet to
270 loop_frame(unsigned char *frame, int len)
274 /* dbglog("from loop: %P", frame, len); */
275 if (len < PPP_HDRLEN)
277 if ((PPP_PROTOCOL(frame) & 0x8000) != 0)
278 return 0; /* shouldn't get any of these anyway */
279 if (!active_packet(frame, len))
282 pkt = (struct packet *) malloc(sizeof(struct packet) + len);
286 memcpy(pkt->data, frame, len);
290 pend_qtail->next = pkt;
297 * demand_rexmit - Resend all those frames which we got via the
298 * loopback, now that the real serial link is up.
301 demand_rexmit(int proto)
303 struct packet *pkt, *prev, *nextpkt;
308 for (; pkt != NULL; pkt = nextpkt) {
310 if (PPP_PROTOCOL(pkt->data) == proto) {
311 output(0, pkt->data, pkt->length);
327 * Scan a packet to decide whether it is an "active" packet,
328 * that is, whether it is worth bringing up the link for.
331 active_packet(unsigned char *p, int len)
334 struct protent *protp;
336 if (len < PPP_HDRLEN)
338 proto = PPP_PROTOCOL(p);
339 #ifdef PPP_WITH_FILTER
340 p[0] = 1; /* outbound packet indicator */
341 if ((pass_filter.bf_len != 0
342 && bpf_filter(pass_filter.bf_insns, p, len, len) == 0)
343 || (active_filter.bf_len != 0
344 && bpf_filter(active_filter.bf_insns, p, len, len) == 0)) {
350 for (i = 0; (protp = protocols[i]) != NULL; ++i) {
351 if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
352 if (!protp->enabled_flag)
354 if (protp->active_pkt == NULL)
356 return (*protp->active_pkt)(p, len);
359 return 0; /* not a supported protocol !!?? */