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