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 $"
39 #include <sys/param.h>
40 #include <sys/types.h>
43 #include <sys/resource.h>
45 #include <sys/socket.h>
66 unsigned char data[1];
69 struct packet *pend_q;
70 struct packet *pend_qtail;
72 static int active_packet(unsigned char *, int);
75 * demand_conf - configure the interface for doing dial-on-demand.
81 struct protent *protp;
83 /* framemax = lcp_allowoptions[0].mru;
84 if (framemax < PPP_MRU) */
86 framemax += PPP_HDRLEN + PPP_FCSLEN;
87 frame = malloc(framemax);
96 netif_set_mtu(0, MIN(lcp_allowoptions[0].mru, PPP_MRU));
97 if (ppp_send_config(0, PPP_MRU, (u_int32_t) 0, 0, 0) < 0
98 || ppp_recv_config(0, PPP_MRU, (u_int32_t) 0, 0, 0) < 0)
99 fatal("Couldn't set up demand-dialled PPP interface: %m");
102 set_filters(&pass_filter, &active_filter);
106 * Call the demand_conf procedure for each protocol that's got one.
108 for (i = 0; (protp = protocols[i]) != NULL; ++i)
109 if (protp->enabled_flag && protp->demand_conf != NULL)
110 if (!((*protp->demand_conf)(0)))
116 * demand_block - set each network protocol to block further packets.
122 struct protent *protp;
124 for (i = 0; (protp = protocols[i]) != NULL; ++i)
125 if (protp->enabled_flag && protp->demand_conf != NULL)
126 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_QUEUE);
131 * demand_discard - set each network protocol to discard packets
137 struct packet *pkt, *nextpkt;
139 struct protent *protp;
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_ERROR);
146 /* discard all saved packets */
147 for (pkt = pend_q; pkt != NULL; pkt = nextpkt) {
159 * demand_unblock - set each enabled network protocol to pass packets.
165 struct protent *protp;
167 for (i = 0; (protp = protocols[i]) != NULL; ++i)
168 if (protp->enabled_flag && protp->demand_conf != NULL)
169 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_PASS);
173 * FCS lookup table as calculated by genfcstab.
175 static u_short fcstab[256] = {
176 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
177 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
178 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
179 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
180 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
181 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
182 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
183 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
184 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
185 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
186 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
187 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
188 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
189 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
190 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
191 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
192 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
193 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
194 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
195 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
196 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
197 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
198 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
199 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
200 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
201 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
202 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
203 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
204 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
205 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
206 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
207 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
211 * loop_chars - process characters received from the loopback.
212 * Calls loop_frame when a complete frame has been accumulated.
213 * Return value is 1 if we need to bring up the link, 0 otherwise.
216 loop_chars(unsigned char *p, int n)
224 if (!escape_flag && !flush_flag
225 && framelen > 2 && fcs == PPP_GOODFCS) {
227 if (loop_frame((unsigned char *)frame, framelen))
241 } else if (c == PPP_ESCAPE) {
245 if (framelen >= framemax) {
249 frame[framelen++] = c;
250 fcs = PPP_FCS(fcs, c);
256 * loop_frame - given a frame obtained from the loopback,
257 * decide whether to bring up the link or not, and, if we want
258 * to transmit this frame later, put it on the pending queue.
259 * Return value is 1 if we need to bring up the link, 0 otherwise.
260 * We assume that the kernel driver has already applied the
261 * pass_filter, so we won't get packets it rejected.
262 * We apply the active_filter to see if we want this packet to
266 loop_frame(unsigned char *frame, int len)
270 /* dbglog("from loop: %P", frame, len); */
271 if (len < PPP_HDRLEN)
273 if ((PPP_PROTOCOL(frame) & 0x8000) != 0)
274 return 0; /* shouldn't get any of these anyway */
275 if (!active_packet(frame, len))
278 pkt = (struct packet *) malloc(sizeof(struct packet) + len);
282 memcpy(pkt->data, frame, len);
286 pend_qtail->next = pkt;
293 * demand_rexmit - Resend all those frames which we got via the
294 * loopback, now that the real serial link is up.
297 demand_rexmit(int proto)
299 struct packet *pkt, *prev, *nextpkt;
304 for (; pkt != NULL; pkt = nextpkt) {
306 if (PPP_PROTOCOL(pkt->data) == proto) {
307 output(0, pkt->data, pkt->length);
323 * Scan a packet to decide whether it is an "active" packet,
324 * that is, whether it is worth bringing up the link for.
327 active_packet(unsigned char *p, int len)
330 struct protent *protp;
332 if (len < PPP_HDRLEN)
334 proto = PPP_PROTOCOL(p);
336 p[0] = 1; /* outbound packet indicator */
337 if ((pass_filter.bf_len != 0
338 && bpf_filter(pass_filter.bf_insns, p, len, len) == 0)
339 || (active_filter.bf_len != 0
340 && bpf_filter(active_filter.bf_insns, p, len, len) == 0)) {
346 for (i = 0; (protp = protocols[i]) != NULL; ++i) {
347 if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
348 if (!protp->enabled_flag)
350 if (protp->active_pkt == NULL)
352 return (*protp->active_pkt)(p, len);
355 return 0; /* not a supported protocol !!?? */