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. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
18 * 3. The name(s) of the authors of this software must not be used to
19 * endorse or promote products derived from this software without
20 * prior written permission.
22 * 4. Redistributions of any form whatsoever must retain the following
24 * "This product includes software developed by Paul Mackerras
25 * <paulus@samba.org>".
27 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
28 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
29 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
30 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
31 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
32 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
33 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
36 #define RCSID "$Id: demand.c,v 1.16 2002/12/04 23:03:32 paulus Exp $"
44 #include <sys/param.h>
45 #include <sys/types.h>
48 #include <sys/resource.h>
50 #include <sys/socket.h>
62 static const char rcsid[] = RCSID;
74 unsigned char data[1];
77 struct packet *pend_q;
78 struct packet *pend_qtail;
80 static int active_packet __P((unsigned char *, int));
83 * demand_conf - configure the interface for doing dial-on-demand.
89 struct protent *protp;
91 /* framemax = lcp_allowoptions[0].mru;
92 if (framemax < PPP_MRU) */
94 framemax += PPP_HDRLEN + PPP_FCSLEN;
95 frame = malloc(framemax);
104 netif_set_mtu(0, MIN(lcp_allowoptions[0].mru, PPP_MRU));
105 ppp_send_config(0, PPP_MRU, (u_int32_t) 0, 0, 0);
106 ppp_recv_config(0, PPP_MRU, (u_int32_t) 0, 0, 0);
109 set_filters(&pass_filter, &active_filter);
113 * Call the demand_conf procedure for each protocol that's got one.
115 for (i = 0; (protp = protocols[i]) != NULL; ++i)
116 if (protp->enabled_flag && protp->demand_conf != NULL)
117 if (!((*protp->demand_conf)(0)))
123 * demand_block - set each network protocol to block further packets.
129 struct protent *protp;
131 for (i = 0; (protp = protocols[i]) != NULL; ++i)
132 if (protp->enabled_flag && protp->demand_conf != NULL)
133 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_QUEUE);
138 * demand_discard - set each network protocol to discard packets
144 struct packet *pkt, *nextpkt;
146 struct protent *protp;
148 for (i = 0; (protp = protocols[i]) != NULL; ++i)
149 if (protp->enabled_flag && protp->demand_conf != NULL)
150 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_ERROR);
153 /* discard all saved packets */
154 for (pkt = pend_q; pkt != NULL; pkt = nextpkt) {
166 * demand_unblock - set each enabled network protocol to pass packets.
172 struct protent *protp;
174 for (i = 0; (protp = protocols[i]) != NULL; ++i)
175 if (protp->enabled_flag && protp->demand_conf != NULL)
176 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_PASS);
180 * FCS lookup table as calculated by genfcstab.
182 static u_short fcstab[256] = {
183 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
184 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
185 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
186 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
187 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
188 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
189 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
190 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
191 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
192 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
193 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
194 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
195 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
196 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
197 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
198 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
199 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
200 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
201 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
202 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
203 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
204 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
205 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
206 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
207 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
208 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
209 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
210 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
211 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
212 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
213 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
214 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
218 * loop_chars - process characters received from the loopback.
219 * Calls loop_frame when a complete frame has been accumulated.
220 * Return value is 1 if we need to bring up the link, 0 otherwise.
233 if (!escape_flag && !flush_flag
234 && framelen > 2 && fcs == PPP_GOODFCS) {
236 if (loop_frame((unsigned char *)frame, framelen))
250 } else if (c == PPP_ESCAPE) {
254 if (framelen >= framemax) {
258 frame[framelen++] = c;
259 fcs = PPP_FCS(fcs, c);
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
275 loop_frame(frame, len)
276 unsigned char *frame;
281 /* dbglog("from loop: %P", frame, len); */
282 if (len < PPP_HDRLEN)
284 if ((PPP_PROTOCOL(frame) & 0x8000) != 0)
285 return 0; /* shouldn't get any of these anyway */
286 if (!active_packet(frame, len))
289 pkt = (struct packet *) malloc(sizeof(struct packet) + len);
293 memcpy(pkt->data, frame, len);
297 pend_qtail->next = pkt;
304 * demand_rexmit - Resend all those frames which we got via the
305 * loopback, now that the real serial link is up.
311 struct packet *pkt, *prev, *nextpkt;
316 for (; pkt != NULL; pkt = nextpkt) {
318 if (PPP_PROTOCOL(pkt->data) == proto) {
319 output(0, pkt->data, pkt->length);
335 * Scan a packet to decide whether it is an "active" packet,
336 * that is, whether it is worth bringing up the link for.
339 active_packet(p, len)
344 struct protent *protp;
346 if (len < PPP_HDRLEN)
348 proto = PPP_PROTOCOL(p);
350 if (pass_filter.bf_len != 0
351 && bpf_filter(pass_filter.bf_insns, p, len, len) == 0)
353 if (active_filter.bf_len != 0
354 && bpf_filter(active_filter.bf_insns, p, len, len) == 0)
357 for (i = 0; (protp = protocols[i]) != NULL; ++i) {
358 if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
359 if (!protp->enabled_flag)
361 if (protp->active_pkt == NULL)
363 return (*protp->active_pkt)(p, len);
366 return 0; /* not a supported protocol !!?? */