2 * demand.c - Support routines for demand-dialling.
4 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5 * Use is subject to license terms.
7 * Copyright (c) 1993 The Australian National University.
10 * Redistribution and use in source and binary forms are permitted
11 * provided that the above copyright notice and this paragraph are
12 * duplicated in all such forms and that any documentation,
13 * advertising materials, and other materials related to such
14 * distribution and use acknowledge that the software was developed
15 * by the Australian National University. The name of the University
16 * may not be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
23 #define RCSID "$Id: demand.c,v 1.13 2000/04/15 01:27:11 masputra Exp $"
31 #include <sys/param.h>
32 #include <sys/types.h>
35 #include <sys/resource.h>
37 #include <sys/socket.h>
48 static const char rcsid
[] = RCSID
;
53 static int escape_flag
;
54 static int flush_flag
;
60 unsigned char data
[1];
63 static struct packet
*pend_q
;
64 static struct packet
*pend_qtail
;
66 static int active_packet
__P((unsigned char *, int));
69 * demand_conf - configure the interface for doing dial-on-demand.
75 struct protent
*protp
;
78 framemax
= lcp_wantoptions
[0].mru
;
79 if (framemax
< PPP_MRU
)
81 framemax
+= PPP_HDRLEN
+ PPP_FCSLEN
;
82 frame
= malloc(framemax
);
91 if ((mtu
= lcp_allowoptions
[0].mru
) == 0)
93 ppp_send_config(0, mtu
, (u_int32_t
) 0, 0, 0);
94 ppp_recv_config(0, framemax
, (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)))
106 fatal("unable to set demand configuration on %s", protp
->name
);
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
))
122 fatal("unable to enable queuing for %s", protp
->name
);
123 /* Intentionally discard return value; we're on our way up now. */
124 (void) get_loop_output();
128 * demand_discard - set each network protocol to discard packets
134 struct packet
*pkt
, *nextpkt
;
136 struct protent
*protp
;
138 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
)
139 if (protp
->enabled_flag
&& protp
->demand_conf
!= NULL
&&
140 !sifnpmode(0, protp
->protocol
& ~0x8000, NPMODE_DROP
))
141 fatal("unable to disable %s", protp
->name
);
143 /* Intentionally discard return value; we're on our way down now. */
144 (void) get_loop_output();
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
))
170 fatal("unable to enable %s", protp
->name
);
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 if (len
< PPP_HDRLEN
)
277 if ((PPP_PROTOCOL(frame
) & 0x8000) != 0)
278 return 0; /* shouldn't get any of these anyway */
280 /* Note - once we have pending packets, we don't drop any more. */
281 if (pend_q
== NULL
&& !active_packet(frame
, len
))
284 pkt
= (struct packet
*) malloc(sizeof(struct packet
) + len
);
288 (void) memcpy(pkt
->data
, frame
, len
);
292 pend_qtail
->next
= pkt
;
299 * demand_rexmit - Resend all those frames that we got via the
300 * loopback, now that the real serial link is up.
306 struct packet
*pkt
, *prev
, *nextpkt
;
311 for (; pkt
!= NULL
; pkt
= nextpkt
) {
313 if (PPP_PROTOCOL(pkt
->data
) == proto
) {
314 output(0, pkt
->data
, pkt
->length
);
330 * Scan a packet to decide whether it is an "active" packet,
331 * that is, whether it is worth bringing up the link for.
334 active_packet(p
, len
)
339 struct protent
*protp
;
343 if (len
< PPP_HDRLEN
)
346 if (active_filter
.bf_len
!= 0
347 && bpf_filter(active_filter
.bf_insns
, frame
, len
, len
) == 0) {
348 dbglog("BPF identified packet as not worth bringing up the link.");
352 proto
= PPP_PROTOCOL(p
);
353 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
) {
354 if (protp
->protocol
< 0xC000 && (protp
->protocol
& ~0x8000) == proto
) {
355 if (!protp
->enabled_flag
) {
356 dbglog("%s: not enabled; not bringing up link", protp
->name
);
359 if (protp
->active_pkt
== NULL
) {
360 notice("%s: no active test; bringing up link", protp
->name
);
363 i
= (*protp
->active_pkt
)(p
, len
);
365 notice("%s: active test; bringing up link", protp
->name
);
367 dbglog("%s: active test; not bringing up link",
372 if ((cp
= protocol_name(proto
)) == NULL
) {
373 (void) slprintf(pbuf
, sizeof (pbuf
), "0x#X", proto
);
374 cp
= (const char *)pbuf
;
376 dbglog("%s: unknown protocol; not bringing up link", cp
);
377 return 0; /* not a supported protocol !!?? */