minidlna support now Samsung TV C550/C650 (thx amir909)
[tomato.git] / release / src / router / ppp / pppd / demand.c
blobb062f2b7cd692d7939be7eff710c74334e82b503
1 /*
2 * demand.c - Support routines for demand-dialling.
4 * Copyright (c) 1993 The Australian National University.
5 * All rights reserved.
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.
20 #define RCSID "$Id: demand.c,v 1.1.1.4 2003/10/14 08:09:53 sparq Exp $"
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <netdb.h>
28 #include <sys/param.h>
29 #include <sys/types.h>
30 #include <sys/wait.h>
31 #include <sys/time.h>
32 #include <sys/resource.h>
33 #include <sys/stat.h>
34 #include <sys/socket.h>
35 #ifdef PPP_FILTER
36 #include <net/if.h>
37 #include <net/bpf.h>
38 #include <pcap.h>
39 #endif
41 #include <pppd.h>
42 #include "fsm.h"
43 #include "ipcp.h"
44 #include "lcp.h"
46 static const char rcsid[] = RCSID;
48 char *frame;
49 int framelen;
50 int framemax;
51 int escape_flag;
52 int flush_flag;
53 int fcs;
55 struct packet {
56 int length;
57 struct packet *next;
58 unsigned char data[1];
61 struct packet *pend_q;
62 struct packet *pend_qtail;
64 static int active_packet __P((unsigned char *, int));
66 #ifndef PPP_FCS
67 #define PPP_FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
68 #endif
71 * demand_conf - configure the interface for doing dial-on-demand.
73 void
74 demand_conf()
76 int i;
77 struct protent *protp;
79 /* framemax = lcp_allowoptions[0].mru;
80 if (framemax < PPP_MRU) */
81 framemax = PPP_MRU;
82 framemax += PPP_HDRLEN + PPP_FCSLEN;
83 frame = malloc(framemax);
84 if (frame == NULL)
85 novm("demand frame");
86 framelen = 0;
87 pend_q = NULL;
88 escape_flag = 0;
89 flush_flag = 0;
90 fcs = PPP_INITFCS;
92 netif_set_mtu(0, MIN(lcp_allowoptions[0].mru, PPP_MRU));
93 ppp_send_config(0, PPP_MRU, (u_int32_t) 0, 0, 0);
94 ppp_recv_config(0, PPP_MRU, (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 die(1);
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 get_loop_output();
126 * demand_discard - set each network protocol to discard packets
127 * with an error.
129 void
130 demand_discard()
132 struct packet *pkt, *nextpkt;
133 int i;
134 struct protent *protp;
136 for (i = 0; (protp = protocols[i]) != NULL; ++i)
137 if (protp->enabled_flag && protp->demand_conf != NULL)
138 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_ERROR);
139 get_loop_output();
141 /* discard all saved packets */
142 for (pkt = pend_q; pkt != NULL; pkt = nextpkt) {
143 nextpkt = pkt->next;
144 free(pkt);
146 pend_q = NULL;
147 framelen = 0;
148 flush_flag = 0;
149 escape_flag = 0;
150 fcs = PPP_INITFCS;
154 * demand_unblock - set each enabled network protocol to pass packets.
156 void
157 demand_unblock()
159 int i;
160 struct protent *protp;
162 for (i = 0; (protp = protocols[i]) != NULL; ++i)
163 if (protp->enabled_flag && protp->demand_conf != NULL)
164 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_PASS);
168 * FCS lookup table as calculated by genfcstab.
170 static u_short fcstab[256] = {
171 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
172 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
173 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
174 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
175 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
176 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
177 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
178 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
179 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
180 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
181 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
182 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
183 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
184 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
185 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
186 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
187 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
188 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
189 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
190 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
191 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
192 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
193 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
194 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
195 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
196 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
197 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
198 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
199 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
200 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
201 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
202 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
206 * loop_chars - process characters received from the loopback.
207 * Calls loop_frame when a complete frame has been accumulated.
208 * Return value is 1 if we need to bring up the link, 0 otherwise.
211 loop_chars(p, n)
212 unsigned char *p;
213 int n;
215 int c, rv;
217 rv = 0;
218 for (; n > 0; --n) {
219 c = *p++;
220 if (c == PPP_FLAG) {
221 if (!escape_flag && !flush_flag
222 && framelen > 2 && fcs == PPP_GOODFCS) {
223 framelen -= 2;
224 if (loop_frame((unsigned char *)frame, framelen))
225 rv = 1;
227 framelen = 0;
228 flush_flag = 0;
229 escape_flag = 0;
230 fcs = PPP_INITFCS;
231 continue;
233 if (flush_flag)
234 continue;
235 if (escape_flag) {
236 c ^= PPP_TRANS;
237 escape_flag = 0;
238 } else if (c == PPP_ESCAPE) {
239 escape_flag = 1;
240 continue;
242 if (framelen >= framemax) {
243 flush_flag = 1;
244 continue;
246 frame[framelen++] = c;
247 fcs = PPP_FCS(fcs, c);
249 return rv;
253 * loop_frame - given a frame obtained from the loopback,
254 * decide whether to bring up the link or not, and, if we want
255 * to transmit this frame later, put it on the pending queue.
256 * Return value is 1 if we need to bring up the link, 0 otherwise.
257 * We assume that the kernel driver has already applied the
258 * pass_filter, so we won't get packets it rejected.
259 * We apply the active_filter to see if we want this packet to
260 * bring up the link.
263 loop_frame(frame, len)
264 unsigned char *frame;
265 int len;
267 struct packet *pkt;
269 /* dbglog("from loop: %P", frame, len); */
270 if (len < PPP_HDRLEN)
271 return 0;
272 if ((PPP_PROTOCOL(frame) & 0x8000) != 0)
273 return 0; /* shouldn't get any of these anyway */
274 if (!active_packet(frame, len))
275 return 0;
277 pkt = (struct packet *) malloc(sizeof(struct packet) + len);
278 if (pkt != NULL) {
279 pkt->length = len;
280 pkt->next = NULL;
281 memcpy(pkt->data, frame, len);
282 if (pend_q == NULL)
283 pend_q = pkt;
284 else
285 pend_qtail->next = pkt;
286 pend_qtail = pkt;
288 return 1;
292 * demand_rexmit - Resend all those frames which we got via the
293 * loopback, now that the real serial link is up.
295 void
296 demand_rexmit(proto)
297 int proto;
299 struct packet *pkt, *prev, *nextpkt;
301 prev = NULL;
302 pkt = pend_q;
303 pend_q = NULL;
304 for (; pkt != NULL; pkt = nextpkt) {
305 nextpkt = pkt->next;
306 if (PPP_PROTOCOL(pkt->data) == proto) {
307 output(0, pkt->data, pkt->length);
308 free(pkt);
309 } else {
310 if (prev == NULL)
311 pend_q = pkt;
312 else
313 prev->next = pkt;
314 prev = pkt;
317 pend_qtail = prev;
318 if (prev != NULL)
319 prev->next = NULL;
323 * Scan a packet to decide whether it is an "active" packet,
324 * that is, whether it is worth bringing up the link for.
326 static int
327 active_packet(p, len)
328 unsigned char *p;
329 int len;
331 int proto, i;
332 struct protent *protp;
334 if (len < PPP_HDRLEN)
335 return 0;
336 proto = PPP_PROTOCOL(p);
337 #ifdef PPP_FILTER
338 if (pass_filter.bf_len != 0
339 && bpf_filter(pass_filter.bf_insns, p, len, len) == 0)
340 return 0;
341 if (active_filter.bf_len != 0
342 && bpf_filter(active_filter.bf_insns, p, len, len) == 0)
343 return 0;
344 #endif
345 for (i = 0; (protp = protocols[i]) != NULL; ++i) {
346 if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
347 if (!protp->enabled_flag)
348 return 0;
349 if (protp->active_pkt == NULL)
350 return 1;
351 return (*protp->active_pkt)(p, len);
354 return 0; /* not a supported protocol !!?? */