2 * demand.c - Support routines for demand-dialling.
4 * Copyright (c) 1993 The Australian National University.
7 * Redistribution and use in source and binary forms are permitted
8 * provided that the above copyright notice and this paragraph are
9 * duplicated in all such forms and that any documentation,
10 * advertising materials, and other materials related to such
11 * distribution and use acknowledge that the software was developed
12 * by the Australian National University. The name of the University
13 * may not be used to endorse or promote products derived from this
14 * software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 #define RCSID "$Id: demand.c,v 1.1.1.4 2003/10/14 08:09:53 sparq Exp $"
28 #include <sys/param.h>
29 #include <sys/types.h>
32 #include <sys/resource.h>
34 #include <sys/socket.h>
46 static const char rcsid
[] = RCSID
;
58 unsigned char data
[1];
61 struct packet
*pend_q
;
62 struct packet
*pend_qtail
;
64 static int active_packet
__P((unsigned char *, int));
67 #define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
71 * demand_conf - configure the interface for doing dial-on-demand.
77 struct protent
*protp
;
79 /* framemax = lcp_allowoptions[0].mru;
80 if (framemax < PPP_MRU) */
82 framemax
+= PPP_HDRLEN
+ PPP_FCSLEN
;
83 frame
= malloc(framemax
);
92 netif_set_mtu(0, MIN(lcp_allowoptions
[0].mru
, PPP_MRU
));
93 ppp_send_config(0, PPP_MRU
, (u_int32_t
) 0, 0, 0);
94 ppp_recv_config(0, PPP_MRU
, (u_int32_t
) 0, 0, 0);
97 set_filters(&pass_filter
, &active_filter
);
101 * Call the demand_conf procedure for each protocol that's got one.
103 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
)
104 if (protp
->enabled_flag
&& protp
->demand_conf
!= NULL
)
105 if (!((*protp
->demand_conf
)(0)))
111 * demand_block - set each network protocol to block further packets.
117 struct protent
*protp
;
119 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
)
120 if (protp
->enabled_flag
&& protp
->demand_conf
!= NULL
)
121 sifnpmode(0, protp
->protocol
& ~0x8000, NPMODE_QUEUE
);
126 * demand_discard - set each network protocol to discard packets
132 struct packet
*pkt
, *nextpkt
;
134 struct protent
*protp
;
136 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
)
137 if (protp
->enabled_flag
&& protp
->demand_conf
!= NULL
)
138 sifnpmode(0, protp
->protocol
& ~0x8000, NPMODE_ERROR
);
141 /* discard all saved packets */
142 for (pkt
= pend_q
; pkt
!= NULL
; pkt
= nextpkt
) {
154 * demand_unblock - set each enabled network protocol to pass packets.
160 struct protent
*protp
;
162 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
)
163 if (protp
->enabled_flag
&& protp
->demand_conf
!= NULL
)
164 sifnpmode(0, protp
->protocol
& ~0x8000, NPMODE_PASS
);
168 * FCS lookup table as calculated by genfcstab.
170 static u_short fcstab
[256] = {
171 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
172 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
173 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
174 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
175 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
176 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
177 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
178 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
179 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
180 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
181 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
182 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
183 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
184 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
185 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
186 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
187 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
188 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
189 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
190 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
191 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
192 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
193 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
194 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
195 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
196 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
197 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
198 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
199 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
200 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
201 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
202 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
206 * loop_chars - process characters received from the loopback.
207 * Calls loop_frame when a complete frame has been accumulated.
208 * Return value is 1 if we need to bring up the link, 0 otherwise.
221 if (!escape_flag
&& !flush_flag
222 && framelen
> 2 && fcs
== PPP_GOODFCS
) {
224 if (loop_frame((unsigned char *)frame
, framelen
))
238 } else if (c
== PPP_ESCAPE
) {
242 if (framelen
>= framemax
) {
246 frame
[framelen
++] = c
;
247 fcs
= PPP_FCS(fcs
, c
);
253 * loop_frame - given a frame obtained from the loopback,
254 * decide whether to bring up the link or not, and, if we want
255 * to transmit this frame later, put it on the pending queue.
256 * Return value is 1 if we need to bring up the link, 0 otherwise.
257 * We assume that the kernel driver has already applied the
258 * pass_filter, so we won't get packets it rejected.
259 * We apply the active_filter to see if we want this packet to
263 loop_frame(frame
, len
)
264 unsigned char *frame
;
269 /* dbglog("from loop: %P", frame, len); */
270 if (len
< PPP_HDRLEN
)
272 if ((PPP_PROTOCOL(frame
) & 0x8000) != 0)
273 return 0; /* shouldn't get any of these anyway */
274 if (!active_packet(frame
, len
))
277 pkt
= (struct packet
*) malloc(sizeof(struct packet
) + len
);
281 memcpy(pkt
->data
, frame
, len
);
285 pend_qtail
->next
= pkt
;
292 * demand_rexmit - Resend all those frames which we got via the
293 * loopback, now that the real serial link is up.
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(p
, len
)
332 struct protent
*protp
;
334 if (len
< PPP_HDRLEN
)
336 proto
= PPP_PROTOCOL(p
);
338 if (pass_filter
.bf_len
!= 0
339 && bpf_filter(pass_filter
.bf_insns
, p
, len
, len
) == 0)
341 if (active_filter
.bf_len
!= 0
342 && bpf_filter(active_filter
.bf_insns
, p
, len
, len
) == 0)
345 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
) {
346 if (protp
->protocol
< 0xC000 && (protp
->protocol
& ~0x8000) == proto
) {
347 if (!protp
->enabled_flag
)
349 if (protp
->active_pkt
== NULL
)
351 return (*protp
->active_pkt
)(p
, len
);
354 return 0; /* not a supported protocol !!?? */