dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.bin / pppd / demand.c
bloba691e677255ac046d475739759437177f3fe21b8
1 /*
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.
8 * All rights reserved.
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 $"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <fcntl.h>
30 #include <netdb.h>
31 #include <sys/param.h>
32 #include <sys/types.h>
33 #include <sys/wait.h>
34 #include <sys/time.h>
35 #include <sys/resource.h>
36 #include <sys/stat.h>
37 #include <sys/socket.h>
38 #ifdef PPP_FILTER
39 #include <net/if.h>
40 #include <net/bpf.h>
41 #include <pcap.h>
42 #endif
44 #include "pppd.h"
45 #include "fsm.h"
46 #include "lcp.h"
48 static const char rcsid[] = RCSID;
50 static char *frame;
51 static int framelen;
52 static int framemax;
53 static int escape_flag;
54 static int flush_flag;
55 static int fcs;
57 struct packet {
58 int length;
59 struct packet *next;
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.
71 void
72 demand_conf()
74 int i;
75 struct protent *protp;
76 int mtu;
78 framemax = lcp_wantoptions[0].mru;
79 if (framemax < PPP_MRU)
80 framemax = PPP_MRU;
81 framemax += PPP_HDRLEN + PPP_FCSLEN;
82 frame = malloc(framemax);
83 if (frame == NULL)
84 novm("demand frame");
85 framelen = 0;
86 pend_q = NULL;
87 escape_flag = 0;
88 flush_flag = 0;
89 fcs = PPP_INITFCS;
91 if ((mtu = lcp_allowoptions[0].mru) == 0)
92 mtu = PPP_MTU;
93 ppp_send_config(0, mtu, (u_int32_t) 0, 0, 0);
94 ppp_recv_config(0, framemax, (u_int32_t) 0, 0, 0);
96 #ifdef PPP_FILTER
97 set_filters(&pass_filter, &active_filter);
98 #endif
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.
113 void
114 demand_block()
116 int i;
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
129 * with an error.
131 void
132 demand_discard()
134 struct packet *pkt, *nextpkt;
135 int i;
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) {
148 nextpkt = pkt->next;
149 free(pkt);
151 pend_q = NULL;
152 framelen = 0;
153 flush_flag = 0;
154 escape_flag = 0;
155 fcs = PPP_INITFCS;
159 * demand_unblock - set each enabled network protocol to pass packets.
161 void
162 demand_unblock()
164 int i;
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.
217 loop_chars(p, n)
218 unsigned char *p;
219 int n;
221 int c, rv;
223 rv = 0;
224 for (; n > 0; --n) {
225 c = *p++;
226 if (c == PPP_FLAG) {
227 if (!escape_flag && !flush_flag
228 && framelen > 2 && fcs == PPP_GOODFCS) {
229 framelen -= 2;
230 if (loop_frame((unsigned char *)frame, framelen))
231 rv = 1;
233 framelen = 0;
234 flush_flag = 0;
235 escape_flag = 0;
236 fcs = PPP_INITFCS;
237 continue;
239 if (flush_flag)
240 continue;
241 if (escape_flag) {
242 c ^= PPP_TRANS;
243 escape_flag = 0;
244 } else if (c == PPP_ESCAPE) {
245 escape_flag = 1;
246 continue;
248 if (framelen >= framemax) {
249 flush_flag = 1;
250 continue;
252 frame[framelen++] = c;
253 fcs = PPP_FCS(fcs, c);
255 return rv;
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
266 * bring up the link.
269 loop_frame(frame, len)
270 unsigned char *frame;
271 int len;
273 struct packet *pkt;
275 if (len < PPP_HDRLEN)
276 return 0;
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))
282 return 0;
284 pkt = (struct packet *) malloc(sizeof(struct packet) + len);
285 if (pkt != NULL) {
286 pkt->length = len;
287 pkt->next = NULL;
288 (void) memcpy(pkt->data, frame, len);
289 if (pend_q == NULL)
290 pend_q = pkt;
291 else
292 pend_qtail->next = pkt;
293 pend_qtail = pkt;
295 return 1;
299 * demand_rexmit - Resend all those frames that we got via the
300 * loopback, now that the real serial link is up.
302 void
303 demand_rexmit(proto)
304 int proto;
306 struct packet *pkt, *prev, *nextpkt;
308 prev = NULL;
309 pkt = pend_q;
310 pend_q = NULL;
311 for (; pkt != NULL; pkt = nextpkt) {
312 nextpkt = pkt->next;
313 if (PPP_PROTOCOL(pkt->data) == proto) {
314 output(0, pkt->data, pkt->length);
315 free(pkt);
316 } else {
317 if (prev == NULL)
318 pend_q = pkt;
319 else
320 prev->next = pkt;
321 prev = pkt;
324 pend_qtail = prev;
325 if (prev != NULL)
326 prev->next = NULL;
330 * Scan a packet to decide whether it is an "active" packet,
331 * that is, whether it is worth bringing up the link for.
333 static int
334 active_packet(p, len)
335 unsigned char *p;
336 int len;
338 int proto, i;
339 struct protent *protp;
340 const char *cp;
341 char pbuf[32];
343 if (len < PPP_HDRLEN)
344 return 0;
345 #ifdef PPP_FILTER
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.");
349 return 0;
351 #endif
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);
357 return 0;
359 if (protp->active_pkt == NULL) {
360 notice("%s: no active test; bringing up link", protp->name);
361 return 1;
363 i = (*protp->active_pkt)(p, len);
364 if (i != 0)
365 notice("%s: active test; bringing up link", protp->name);
366 else
367 dbglog("%s: active test; not bringing up link",
368 protp->name);
369 return i;
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 !!?? */