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.18 2004/10/28 00:15:08 paulus Exp $"
44 #include <sys/param.h>
45 #include <sys/types.h>
48 #include <sys/resource.h>
50 #include <sys/socket.h>
60 static const char rcsid[] = RCSID;
72 unsigned char data[1];
75 struct packet *pend_q;
76 struct packet *pend_qtail;
78 static int active_packet __P((unsigned char *, int));
81 * demand_conf - configure the interface for doing dial-on-demand.
87 struct protent *protp;
89 /* framemax = lcp_allowoptions[0].mru;
90 if (framemax < PPP_MRU) */
92 framemax += PPP_HDRLEN + PPP_FCSLEN;
93 frame = malloc(framemax);
102 netif_set_mtu(0, MIN(lcp_allowoptions[0].mru, PPP_MRU));
103 if (ppp_send_config(0, PPP_MRU, (u_int32_t) 0, 0, 0) < 0
104 || ppp_recv_config(0, PPP_MRU, (u_int32_t) 0, 0, 0) < 0)
105 fatal("Couldn't set up demand-dialled PPP interface: %m");
108 set_filters(&pass_filter, &active_filter);
112 * Call the demand_conf procedure for each protocol that's got one.
114 for (i = 0; (protp = protocols[i]) != NULL; ++i)
115 if (protp->enabled_flag && protp->demand_conf != NULL)
116 if (!((*protp->demand_conf)(0)))
122 * demand_block - set each network protocol to block further packets.
128 struct protent *protp;
130 for (i = 0; (protp = protocols[i]) != NULL; ++i)
131 if (protp->enabled_flag && protp->demand_conf != NULL)
132 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_QUEUE);
137 * demand_discard - set each network protocol to discard packets
143 struct packet *pkt, *nextpkt;
145 struct protent *protp;
147 for (i = 0; (protp = protocols[i]) != NULL; ++i)
148 if (protp->enabled_flag && protp->demand_conf != NULL)
149 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_ERROR);
152 /* discard all saved packets */
153 for (pkt = pend_q; pkt != NULL; pkt = nextpkt) {
165 * demand_unblock - set each enabled network protocol to pass packets.
171 struct protent *protp;
173 for (i = 0; (protp = protocols[i]) != NULL; ++i)
174 if (protp->enabled_flag && protp->demand_conf != NULL)
175 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_PASS);
179 * FCS lookup table as calculated by genfcstab.
181 static u_short fcstab[256] = {
182 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
183 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
184 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
185 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
186 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
187 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
188 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
189 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
190 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
191 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
192 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
193 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
194 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
195 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
196 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
197 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
198 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
199 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
200 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
201 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
202 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
203 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
204 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
205 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
206 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
207 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
208 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
209 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
210 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
211 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
212 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
213 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
217 * loop_chars - process characters received from the loopback.
218 * Calls loop_frame when a complete frame has been accumulated.
219 * Return value is 1 if we need to bring up the link, 0 otherwise.
232 if (!escape_flag && !flush_flag
233 && framelen > 2 && fcs == PPP_GOODFCS) {
235 if (loop_frame((unsigned char *)frame, framelen))
249 } else if (c == PPP_ESCAPE) {
253 if (framelen >= framemax) {
257 frame[framelen++] = c;
258 fcs = PPP_FCS(fcs, c);
264 * loop_frame - given a frame obtained from the loopback,
265 * decide whether to bring up the link or not, and, if we want
266 * to transmit this frame later, put it on the pending queue.
267 * Return value is 1 if we need to bring up the link, 0 otherwise.
268 * We assume that the kernel driver has already applied the
269 * pass_filter, so we won't get packets it rejected.
270 * We apply the active_filter to see if we want this packet to
274 loop_frame(frame, len)
275 unsigned char *frame;
280 /* dbglog("from loop: %P", frame, len); */
281 if (len < PPP_HDRLEN)
283 if ((PPP_PROTOCOL(frame) & 0x8000) != 0)
284 return 0; /* shouldn't get any of these anyway */
285 if (!active_packet(frame, len))
288 pkt = (struct packet *) malloc(sizeof(struct packet) + len);
292 memcpy(pkt->data, frame, len);
296 pend_qtail->next = pkt;
303 * demand_rexmit - Resend all those frames which we got via the
304 * loopback, now that the real serial link is up.
310 struct packet *pkt, *prev, *nextpkt;
315 for (; pkt != NULL; pkt = nextpkt) {
317 if (PPP_PROTOCOL(pkt->data) == proto) {
318 output(0, pkt->data, pkt->length);
334 * Scan a packet to decide whether it is an "active" packet,
335 * that is, whether it is worth bringing up the link for.
338 active_packet(p, len)
343 struct protent *protp;
345 if (len < PPP_HDRLEN)
347 proto = PPP_PROTOCOL(p);
349 if (pass_filter.bf_len != 0
350 && bpf_filter(pass_filter.bf_insns, p, len, len) == 0)
352 if (active_filter.bf_len != 0
353 && bpf_filter(active_filter.bf_insns, p, len, len) == 0)
356 for (i = 0; (protp = protocols[i]) != NULL; ++i) {
357 if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
358 if (!protp->enabled_flag)
360 if (protp->active_pkt == NULL)
362 return (*protp->active_pkt)(p, len);
365 return 0; /* not a supported protocol !!?? */