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.
29 #include <sys/param.h>
30 #include <sys/types.h>
33 #include <sys/resource.h>
35 #include <sys/socket.h>
49 static int escape_flag
;
50 static int flush_flag
;
56 unsigned char data
[1];
59 static struct packet
*pend_q
;
60 static struct packet
*pend_qtail
;
62 static int active_packet
__P((unsigned char *, int));
65 * demand_conf - configure the interface for doing dial-on-demand.
71 struct protent
*protp
;
74 framemax
= lcp_wantoptions
[0].mru
;
75 if (framemax
< PPP_MRU
)
77 framemax
+= PPP_HDRLEN
+ PPP_FCSLEN
;
78 frame
= malloc(framemax
);
87 if ((mtu
= lcp_allowoptions
[0].mru
) == 0)
89 ppp_send_config(0, mtu
, (u_int32_t
) 0, 0, 0);
90 ppp_recv_config(0, framemax
, (u_int32_t
) 0, 0, 0);
93 set_filters(&pass_filter
, &active_filter
);
97 * Call the demand_conf procedure for each protocol that's got one.
99 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
)
100 if (protp
->enabled_flag
&& protp
->demand_conf
!= NULL
)
101 if (!((*protp
->demand_conf
)(0)))
102 fatal("unable to set demand configuration on %s", protp
->name
);
107 * demand_block - set each network protocol to block further packets.
113 struct protent
*protp
;
115 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
)
116 if (protp
->enabled_flag
&& protp
->demand_conf
!= NULL
&&
117 !sifnpmode(0, protp
->protocol
& ~0x8000, NPMODE_QUEUE
))
118 fatal("unable to enable queuing for %s", protp
->name
);
119 /* Intentionally discard return value; we're on our way up now. */
120 (void) get_loop_output();
124 * demand_discard - set each network protocol to discard packets
130 struct packet
*pkt
, *nextpkt
;
132 struct protent
*protp
;
134 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
)
135 if (protp
->enabled_flag
&& protp
->demand_conf
!= NULL
&&
136 !sifnpmode(0, protp
->protocol
& ~0x8000, NPMODE_DROP
))
137 fatal("unable to disable %s", protp
->name
);
139 /* Intentionally discard return value; we're on our way down now. */
140 (void) get_loop_output();
142 /* discard all saved packets */
143 for (pkt
= pend_q
; pkt
!= NULL
; pkt
= nextpkt
) {
155 * demand_unblock - set each enabled network protocol to pass packets.
161 struct protent
*protp
;
163 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
)
164 if (protp
->enabled_flag
&& protp
->demand_conf
!= NULL
&&
165 !sifnpmode(0, protp
->protocol
& ~0x8000, NPMODE_PASS
))
166 fatal("unable to enable %s", protp
->name
);
170 * FCS lookup table as calculated by genfcstab.
172 static u_short fcstab
[256] = {
173 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
174 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
175 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
176 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
177 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
178 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
179 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
180 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
181 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
182 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
183 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
184 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
185 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
186 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
187 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
188 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
189 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
190 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
191 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
192 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
193 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
194 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
195 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
196 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
197 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
198 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
199 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
200 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
201 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
202 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
203 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
204 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
208 * loop_chars - process characters received from the loopback.
209 * Calls loop_frame when a complete frame has been accumulated.
210 * Return value is 1 if we need to bring up the link, 0 otherwise.
223 if (!escape_flag
&& !flush_flag
224 && framelen
> 2 && fcs
== PPP_GOODFCS
) {
226 if (loop_frame((unsigned char *)frame
, framelen
))
240 } else if (c
== PPP_ESCAPE
) {
244 if (framelen
>= framemax
) {
248 frame
[framelen
++] = c
;
249 fcs
= PPP_FCS(fcs
, c
);
255 * loop_frame - given a frame obtained from the loopback,
256 * decide whether to bring up the link or not, and, if we want
257 * to transmit this frame later, put it on the pending queue.
258 * Return value is 1 if we need to bring up the link, 0 otherwise.
259 * We assume that the kernel driver has already applied the
260 * pass_filter, so we won't get packets it rejected.
261 * We apply the active_filter to see if we want this packet to
265 loop_frame(frame
, len
)
266 unsigned char *frame
;
271 if (len
< PPP_HDRLEN
)
273 if ((PPP_PROTOCOL(frame
) & 0x8000) != 0)
274 return 0; /* shouldn't get any of these anyway */
276 /* Note - once we have pending packets, we don't drop any more. */
277 if (pend_q
== NULL
&& !active_packet(frame
, len
))
280 pkt
= (struct packet
*) malloc(sizeof(struct packet
) + len
);
284 (void) memcpy(pkt
->data
, frame
, len
);
288 pend_qtail
->next
= pkt
;
295 * demand_rexmit - Resend all those frames that we got via the
296 * loopback, now that the real serial link is up.
302 struct packet
*pkt
, *prev
, *nextpkt
;
307 for (; pkt
!= NULL
; pkt
= nextpkt
) {
309 if (PPP_PROTOCOL(pkt
->data
) == proto
) {
310 output(0, pkt
->data
, pkt
->length
);
326 * Scan a packet to decide whether it is an "active" packet,
327 * that is, whether it is worth bringing up the link for.
330 active_packet(p
, len
)
335 struct protent
*protp
;
339 if (len
< PPP_HDRLEN
)
342 if (active_filter
.bf_len
!= 0
343 && bpf_filter(active_filter
.bf_insns
, frame
, len
, len
) == 0) {
344 dbglog("BPF identified packet as not worth bringing up the link.");
348 proto
= PPP_PROTOCOL(p
);
349 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
) {
350 if (protp
->protocol
< 0xC000 && (protp
->protocol
& ~0x8000) == proto
) {
351 if (!protp
->enabled_flag
) {
352 dbglog("%s: not enabled; not bringing up link", protp
->name
);
355 if (protp
->active_pkt
== NULL
) {
356 notice("%s: no active test; bringing up link", protp
->name
);
359 i
= (*protp
->active_pkt
)(p
, len
);
361 notice("%s: active test; bringing up link", protp
->name
);
363 dbglog("%s: active test; not bringing up link",
368 if ((cp
= protocol_name(proto
)) == NULL
) {
369 (void) slprintf(pbuf
, sizeof (pbuf
), "0x#X", proto
);
370 cp
= (const char *)pbuf
;
372 dbglog("%s: unknown protocol; not bringing up link", cp
);
373 return 0; /* not a supported protocol !!?? */