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.
21 static char rcsid[] = "$Id: demand.c,v 1.4 1996/07/01 01:12:52 paulus Exp $";
31 #include <sys/param.h>
32 #include <sys/types.h>
35 #include <sys/resource.h>
37 #include <sys/socket.h>
55 unsigned char data[1];
58 struct packet *pend_q;
59 struct packet *pend_qtail;
61 static int active_packet __P((unsigned char *, int));
64 * demand_conf - configure the interface for doing dial-on-demand.
70 struct protent *protp;
72 /* framemax = lcp_allowoptions[0].mru;
73 if (framemax < PPP_MRU) */
75 framemax += PPP_HDRLEN + PPP_FCSLEN;
76 frame = malloc(framemax);
85 ppp_send_config(0, PPP_MRU, (u_int32_t) 0, 0, 0);
86 ppp_recv_config(0, PPP_MRU, (u_int32_t) 0, 0, 0);
89 set_filters(&pass_filter, &active_filter);
93 * Call the demand_conf procedure for each protocol that's got one.
95 for (i = 0; (protp = protocols[i]) != NULL; ++i)
96 if (protp->enabled_flag && protp->demand_conf != NULL)
97 if (!((*protp->demand_conf)(0)))
103 * demand_block - set each network protocol to block further packets.
109 struct protent *protp;
111 for (i = 0; (protp = protocols[i]) != NULL; ++i)
112 if (protp->enabled_flag && protp->demand_conf != NULL)
113 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_QUEUE);
118 * demand_discard - set each network protocol to discard packets
124 struct packet *pkt, *nextpkt;
126 struct protent *protp;
128 for (i = 0; (protp = protocols[i]) != NULL; ++i)
129 if (protp->enabled_flag && protp->demand_conf != NULL)
130 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_ERROR);
133 /* discard all saved packets */
134 for (pkt = pend_q; pkt != NULL; pkt = nextpkt) {
146 * demand_unblock - set each enabled network protocol to pass packets.
152 struct protent *protp;
154 for (i = 0; (protp = protocols[i]) != NULL; ++i)
155 if (protp->enabled_flag && protp->demand_conf != NULL)
156 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_PASS);
160 * FCS lookup table as calculated by genfcstab.
162 static u_short fcstab[256] = {
163 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
164 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
165 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
166 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
167 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
168 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
169 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
170 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
171 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
172 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
173 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
174 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
175 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
176 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
177 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
178 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
179 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
180 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
181 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
182 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
183 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
184 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
185 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
186 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
187 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
188 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
189 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
190 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
191 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
192 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
193 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
194 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
198 * loop_chars - process characters received from the loopback.
199 * Calls loop_frame when a complete frame has been accumulated.
200 * Return value is 1 if we need to bring up the link, 0 otherwise.
213 if (!escape_flag && !flush_flag
214 && framelen > 2 && fcs == PPP_GOODFCS) {
216 if (loop_frame(frame, framelen))
230 } else if (c == PPP_ESCAPE) {
234 if (framelen >= framemax) {
238 frame[framelen++] = c;
239 fcs = PPP_FCS(fcs, c);
245 * loop_frame - given a frame obtained from the loopback,
246 * decide whether to bring up the link or not, and, if we want
247 * to transmit this frame later, put it on the pending queue.
248 * Return value is 1 if we need to bring up the link, 0 otherwise.
251 loop_frame(frame, len)
252 unsigned char *frame;
257 if (len < PPP_HDRLEN)
259 if ((PPP_PROTOCOL(frame) & 0x8000) != 0)
260 return 0; /* shouldn't get any of these anyway */
261 if (!active_packet(frame, len))
264 pkt = (struct packet *) malloc(sizeof(struct packet) + len);
268 memcpy(pkt->data, frame, len);
272 pend_qtail->next = pkt;
279 * demand_rexmit - Resend all those frames which we got via the
280 * loopback, now that the real serial link is up.
286 struct packet *pkt, *prev, *nextpkt;
291 for (; pkt != NULL; pkt = nextpkt) {
293 if (PPP_PROTOCOL(pkt->data) == proto) {
294 output(0, pkt->data, pkt->length);
310 * Scan a packet to decide whether it is an "active" packet,
311 * that is, whether it is worth bringing up the link for.
314 active_packet(p, len)
319 struct protent *protp;
321 if (len < PPP_HDRLEN)
323 proto = PPP_PROTOCOL(p);
324 for (i = 0; (protp = protocols[i]) != NULL; ++i) {
325 if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
326 if (!protp->enabled_flag)
328 if (protp->active_pkt == NULL)
330 return (*protp->active_pkt)(p, len);
333 return 0; /* not a supported protocol !!?? */