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 #if !defined(lint) && !defined(_lint)
49 static const char rcsid
[] = RCSID
;
55 static int escape_flag
;
56 static int flush_flag
;
62 unsigned char data
[1];
65 static struct packet
*pend_q
;
66 static struct packet
*pend_qtail
;
68 static int active_packet
__P((unsigned char *, int));
71 * demand_conf - configure the interface for doing dial-on-demand.
77 struct protent
*protp
;
80 framemax
= lcp_wantoptions
[0].mru
;
81 if (framemax
< PPP_MRU
)
83 framemax
+= PPP_HDRLEN
+ PPP_FCSLEN
;
84 frame
= malloc(framemax
);
93 if ((mtu
= lcp_allowoptions
[0].mru
) == 0)
95 ppp_send_config(0, mtu
, (u_int32_t
) 0, 0, 0);
96 ppp_recv_config(0, framemax
, (u_int32_t
) 0, 0, 0);
99 set_filters(&pass_filter
, &active_filter
);
103 * Call the demand_conf procedure for each protocol that's got one.
105 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
)
106 if (protp
->enabled_flag
&& protp
->demand_conf
!= NULL
)
107 if (!((*protp
->demand_conf
)(0)))
108 fatal("unable to set demand configuration on %s", protp
->name
);
113 * demand_block - set each network protocol to block further packets.
119 struct protent
*protp
;
121 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
)
122 if (protp
->enabled_flag
&& protp
->demand_conf
!= NULL
&&
123 !sifnpmode(0, protp
->protocol
& ~0x8000, NPMODE_QUEUE
))
124 fatal("unable to enable queuing for %s", protp
->name
);
125 /* Intentionally discard return value; we're on our way up now. */
126 (void) get_loop_output();
130 * demand_discard - set each network protocol to discard packets
136 struct packet
*pkt
, *nextpkt
;
138 struct protent
*protp
;
140 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
)
141 if (protp
->enabled_flag
&& protp
->demand_conf
!= NULL
&&
142 !sifnpmode(0, protp
->protocol
& ~0x8000, NPMODE_DROP
))
143 fatal("unable to disable %s", protp
->name
);
145 /* Intentionally discard return value; we're on our way down now. */
146 (void) get_loop_output();
148 /* discard all saved packets */
149 for (pkt
= pend_q
; pkt
!= NULL
; pkt
= nextpkt
) {
161 * demand_unblock - set each enabled network protocol to pass packets.
167 struct protent
*protp
;
169 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
)
170 if (protp
->enabled_flag
&& protp
->demand_conf
!= NULL
&&
171 !sifnpmode(0, protp
->protocol
& ~0x8000, NPMODE_PASS
))
172 fatal("unable to enable %s", protp
->name
);
176 * FCS lookup table as calculated by genfcstab.
178 static u_short fcstab
[256] = {
179 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
180 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
181 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
182 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
183 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
184 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
185 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
186 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
187 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
188 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
189 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
190 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
191 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
192 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
193 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
194 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
195 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
196 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
197 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
198 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
199 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
200 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
201 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
202 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
203 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
204 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
205 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
206 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
207 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
208 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
209 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
210 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
214 * loop_chars - process characters received from the loopback.
215 * Calls loop_frame when a complete frame has been accumulated.
216 * Return value is 1 if we need to bring up the link, 0 otherwise.
229 if (!escape_flag
&& !flush_flag
230 && framelen
> 2 && fcs
== PPP_GOODFCS
) {
232 if (loop_frame((unsigned char *)frame
, framelen
))
246 } else if (c
== PPP_ESCAPE
) {
250 if (framelen
>= framemax
) {
254 frame
[framelen
++] = c
;
255 fcs
= PPP_FCS(fcs
, c
);
261 * loop_frame - given a frame obtained from the loopback,
262 * decide whether to bring up the link or not, and, if we want
263 * to transmit this frame later, put it on the pending queue.
264 * Return value is 1 if we need to bring up the link, 0 otherwise.
265 * We assume that the kernel driver has already applied the
266 * pass_filter, so we won't get packets it rejected.
267 * We apply the active_filter to see if we want this packet to
271 loop_frame(frame
, len
)
272 unsigned char *frame
;
277 if (len
< PPP_HDRLEN
)
279 if ((PPP_PROTOCOL(frame
) & 0x8000) != 0)
280 return 0; /* shouldn't get any of these anyway */
282 /* Note - once we have pending packets, we don't drop any more. */
283 if (pend_q
== NULL
&& !active_packet(frame
, len
))
286 pkt
= (struct packet
*) malloc(sizeof(struct packet
) + len
);
290 (void) memcpy(pkt
->data
, frame
, len
);
294 pend_qtail
->next
= pkt
;
301 * demand_rexmit - Resend all those frames that we got via the
302 * loopback, now that the real serial link is up.
308 struct packet
*pkt
, *prev
, *nextpkt
;
313 for (; pkt
!= NULL
; pkt
= nextpkt
) {
315 if (PPP_PROTOCOL(pkt
->data
) == proto
) {
316 output(0, pkt
->data
, pkt
->length
);
332 * Scan a packet to decide whether it is an "active" packet,
333 * that is, whether it is worth bringing up the link for.
336 active_packet(p
, len
)
341 struct protent
*protp
;
345 if (len
< PPP_HDRLEN
)
348 if (active_filter
.bf_len
!= 0
349 && bpf_filter(active_filter
.bf_insns
, frame
, len
, len
) == 0) {
350 dbglog("BPF identified packet as not worth bringing up the link.");
354 proto
= PPP_PROTOCOL(p
);
355 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
) {
356 if (protp
->protocol
< 0xC000 && (protp
->protocol
& ~0x8000) == proto
) {
357 if (!protp
->enabled_flag
) {
358 dbglog("%s: not enabled; not bringing up link", protp
->name
);
361 if (protp
->active_pkt
== NULL
) {
362 notice("%s: no active test; bringing up link", protp
->name
);
365 i
= (*protp
->active_pkt
)(p
, len
);
367 notice("%s: active test; bringing up link", protp
->name
);
369 dbglog("%s: active test; not bringing up link",
374 if ((cp
= protocol_name(proto
)) == NULL
) {
375 (void) slprintf(pbuf
, sizeof (pbuf
), "0x#X", proto
);
376 cp
= (const char *)pbuf
;
378 dbglog("%s: unknown protocol; not bringing up link", cp
);
379 return 0; /* not a supported protocol !!?? */