dnscrypto-proxy: Update to release 1.3.0
[tomato.git] / release / src / router / pppd / pppd / demand.c
blob3eddf3016d987ff5bc045212d67e34557b306b76
1 /*
2 * demand.c - Support routines for demand-dialling.
4 * Copyright (c) 1996-2002 Paul Mackerras. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. The name(s) of the authors of this software must not be used to
14 * endorse or promote products derived from this software without
15 * prior written permission.
17 * 3. Redistributions of any form whatsoever must retain the following
18 * acknowledgment:
19 * "This product includes software developed by Paul Mackerras
20 * <paulus@samba.org>".
22 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
23 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
24 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
26 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
27 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
28 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
31 #define RCSID "$Id: demand.c,v 1.20 2005/08/25 12:14:18 paulus Exp $"
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <fcntl.h>
38 #include <netdb.h>
39 #include <unistd.h>
40 #include <syslog.h>
41 #include <sys/param.h>
42 #include <sys/types.h>
43 #include <sys/wait.h>
44 #include <sys/time.h>
45 #include <sys/resource.h>
46 #include <sys/stat.h>
47 #include <sys/socket.h>
48 #include <netinet/in.h>
49 #include <arpa/inet.h>
50 #ifdef PPP_FILTER
51 #include <pcap-bpf.h>
52 #endif
54 #include "pppd.h"
55 #include "fsm.h"
56 #include "ipcp.h"
57 #include "lcp.h"
59 static const char rcsid[] = RCSID;
61 char *frame;
62 int framelen;
63 int framemax;
64 int escape_flag;
65 int flush_flag;
66 int fcs;
68 struct packet {
69 int length;
70 struct packet *next;
71 unsigned char data[1];
74 struct packet *pend_q;
75 struct packet *pend_qtail;
77 static int active_packet __P((unsigned char *, int));
80 * demand_conf - configure the interface for doing dial-on-demand.
82 void
83 demand_conf()
85 int i;
86 struct protent *protp;
88 /* framemax = lcp_allowoptions[0].mru;
89 if (framemax < PPP_MRU) */
90 framemax = PPP_MRU;
91 framemax += PPP_HDRLEN + PPP_FCSLEN;
92 frame = malloc(framemax);
93 if (frame == NULL)
94 novm("demand frame");
95 framelen = 0;
96 pend_q = NULL;
97 escape_flag = 0;
98 flush_flag = 0;
99 fcs = PPP_INITFCS;
101 netif_set_mtu(0, MIN(lcp_allowoptions[0].mru, PPP_MRU));
102 if (ppp_send_config(0, PPP_MRU, (u_int32_t) 0, 0, 0) < 0
103 || ppp_recv_config(0, PPP_MRU, (u_int32_t) 0, 0, 0) < 0)
104 fatal("Couldn't set up demand-dialled PPP interface: %m");
106 #ifdef PPP_FILTER
107 set_filters(&pass_filter, &active_filter);
108 #endif
111 * Call the demand_conf procedure for each protocol that's got one.
113 for (i = 0; (protp = protocols[i]) != NULL; ++i)
114 if (protp->enabled_flag && protp->demand_conf != NULL)
115 if (!((*protp->demand_conf)(0)))
116 die(1);
121 * demand_block - set each network protocol to block further packets.
123 void
124 demand_block()
126 int i;
127 struct protent *protp;
129 for (i = 0; (protp = protocols[i]) != NULL; ++i)
130 if (protp->enabled_flag && protp->demand_conf != NULL)
131 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_QUEUE);
132 get_loop_output();
136 * demand_discard - set each network protocol to discard packets
137 * with an error.
139 void
140 demand_discard()
142 struct packet *pkt, *nextpkt;
143 int i;
144 struct protent *protp;
146 for (i = 0; (protp = protocols[i]) != NULL; ++i)
147 if (protp->enabled_flag && protp->demand_conf != NULL)
148 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_ERROR);
149 get_loop_output();
151 /* discard all saved packets */
152 for (pkt = pend_q; pkt != NULL; pkt = nextpkt) {
153 nextpkt = pkt->next;
154 free(pkt);
156 pend_q = NULL;
157 framelen = 0;
158 flush_flag = 0;
159 escape_flag = 0;
160 fcs = PPP_INITFCS;
164 * demand_unblock - set each enabled network protocol to pass packets.
166 void
167 demand_unblock()
169 int i;
170 struct protent *protp;
172 for (i = 0; (protp = protocols[i]) != NULL; ++i)
173 if (protp->enabled_flag && protp->demand_conf != NULL)
174 sifnpmode(0, protp->protocol & ~0x8000, NPMODE_PASS);
178 * FCS lookup table as calculated by genfcstab.
180 static u_short fcstab[256] = {
181 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
182 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
183 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
184 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
185 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
186 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
187 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
188 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
189 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
190 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
191 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
192 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
193 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
194 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
195 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
196 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
197 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
198 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
199 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
200 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
201 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
202 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
203 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
204 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
205 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
206 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
207 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
208 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
209 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
210 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
211 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
212 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
216 * loop_chars - process characters received from the loopback.
217 * Calls loop_frame when a complete frame has been accumulated.
218 * Return value is 1 if we need to bring up the link, 0 otherwise.
221 loop_chars(p, n)
222 unsigned char *p;
223 int n;
225 int c, rv;
227 rv = 0;
229 /* check for synchronous connection... */
231 if ( (p[0] == 0xFF) && (p[1] == 0x03) ) {
232 rv = loop_frame(p,n);
233 return rv;
236 for (; n > 0; --n) {
237 c = *p++;
238 if (c == PPP_FLAG) {
239 if (!escape_flag && !flush_flag
240 && framelen > 2 && fcs == PPP_GOODFCS) {
241 framelen -= 2;
242 if (loop_frame((unsigned char *)frame, framelen))
243 rv = 1;
245 framelen = 0;
246 flush_flag = 0;
247 escape_flag = 0;
248 fcs = PPP_INITFCS;
249 continue;
251 if (flush_flag)
252 continue;
253 if (escape_flag) {
254 c ^= PPP_TRANS;
255 escape_flag = 0;
256 } else if (c == PPP_ESCAPE) {
257 escape_flag = 1;
258 continue;
260 if (framelen >= framemax) {
261 flush_flag = 1;
262 continue;
264 frame[framelen++] = c;
265 fcs = PPP_FCS(fcs, c);
267 return rv;
271 * loop_frame - given a frame obtained from the loopback,
272 * decide whether to bring up the link or not, and, if we want
273 * to transmit this frame later, put it on the pending queue.
274 * Return value is 1 if we need to bring up the link, 0 otherwise.
275 * We assume that the kernel driver has already applied the
276 * pass_filter, so we won't get packets it rejected.
277 * We apply the active_filter to see if we want this packet to
278 * bring up the link.
281 loop_frame(frame, len)
282 unsigned char *frame;
283 int len;
285 struct packet *pkt;
287 /* dbglog("from loop: %P", frame, len); */
288 if (len < PPP_HDRLEN)
289 return 0;
290 if ((PPP_PROTOCOL(frame) & 0x8000) != 0)
291 return 0; /* shouldn't get any of these anyway */
292 if (!active_packet(frame, len))
293 return 0;
295 pkt = (struct packet *) malloc(sizeof(struct packet) + len);
296 if (pkt != NULL) {
297 pkt->length = len;
298 pkt->next = NULL;
299 memcpy(pkt->data, frame, len);
300 if (pend_q == NULL)
301 pend_q = pkt;
302 else
303 pend_qtail->next = pkt;
304 pend_qtail = pkt;
306 return 1;
310 * demand_rexmit - Resend all those frames which we got via the
311 * loopback, now that the real serial link is up.
313 void
314 demand_rexmit(proto, newip)
315 int proto;
316 u_int32_t newip;
318 struct packet *pkt, *prev, *nextpkt;
319 unsigned short checksum;
320 unsigned short pkt_checksum = 0;
321 unsigned iphdr;
322 struct timeval tv;
323 char cv = 0;
324 char ipstr[16];
326 prev = NULL;
327 pkt = pend_q;
328 pend_q = NULL;
329 tv.tv_sec = 1;
330 tv.tv_usec = 0;
331 select(0,NULL,NULL,NULL,&tv); /* Sleep for 1 Seconds */
332 for (; pkt != NULL; pkt = nextpkt) {
333 nextpkt = pkt->next;
334 if (PPP_PROTOCOL(pkt->data) == proto) {
335 if ( (proto == PPP_IP) && newip ) {
336 /* Get old checksum */
338 iphdr = (pkt->data[4] & 15) << 2;
339 checksum = *((unsigned short *) (pkt->data+14));
340 if (checksum == 0xFFFF) {
341 checksum = 0;
345 if (pkt->data[13] == 17) {
346 pkt_checksum = *((unsigned short *) (pkt->data+10+iphdr));
347 if (pkt_checksum) {
348 cv = 1;
349 if (pkt_checksum == 0xFFFF) {
350 pkt_checksum = 0;
353 else {
354 cv = 0;
358 if (pkt->data[13] == 6) {
359 pkt_checksum = *((unsigned short *) (pkt->data+20+iphdr));
360 cv = 1;
361 if (pkt_checksum == 0xFFFF) {
362 pkt_checksum = 0;
366 /* Delete old Source-IP-Address */
367 checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
368 checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
370 pkt_checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
371 pkt_checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
373 /* Change Source-IP-Address */
374 * ((u_int32_t *) (pkt->data + 16)) = newip;
376 /* Add new Source-IP-Address */
377 checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
378 checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
380 pkt_checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
381 pkt_checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
383 /* Write new checksum */
384 if (!checksum) {
385 checksum = 0xFFFF;
387 *((unsigned short *) (pkt->data+14)) = checksum;
388 if (pkt->data[13] == 6) {
389 *((unsigned short *) (pkt->data+20+iphdr)) = pkt_checksum;
391 if (cv && (pkt->data[13] == 17) ) {
392 *((unsigned short *) (pkt->data+10+iphdr)) = pkt_checksum;
395 /* Log Packet */
396 strcpy(ipstr,inet_ntoa(*( (struct in_addr *) (pkt->data+16))));
397 if (pkt->data[13] == 1) {
398 syslog(LOG_INFO,"Open ICMP %s -> %s\n",
399 ipstr,
400 inet_ntoa(*( (struct in_addr *) (pkt->data+20))));
401 } else {
402 syslog(LOG_INFO,"Open %s %s:%d -> %s:%d\n",
403 pkt->data[13] == 6 ? "TCP" : "UDP",
404 ipstr,
405 ntohs(*( (short *) (pkt->data+iphdr+4))),
406 inet_ntoa(*( (struct in_addr *) (pkt->data+20))),
407 ntohs(*( (short *) (pkt->data+iphdr+6))));
410 output(0, pkt->data, pkt->length);
411 free(pkt);
412 } else {
413 if (prev == NULL)
414 pend_q = pkt;
415 else
416 prev->next = pkt;
417 prev = pkt;
420 pend_qtail = prev;
421 if (prev != NULL)
422 prev->next = NULL;
426 * Scan a packet to decide whether it is an "active" packet,
427 * that is, whether it is worth bringing up the link for.
429 static int
430 active_packet(p, len)
431 unsigned char *p;
432 int len;
434 int proto, i;
435 struct protent *protp;
437 if (len < PPP_HDRLEN)
438 return 0;
439 proto = PPP_PROTOCOL(p);
440 #ifdef PPP_FILTER
441 p[0] = 1; /* outbound packet indicator */
442 if ((pass_filter.bf_len != 0
443 && bpf_filter(pass_filter.bf_insns, p, len, len) == 0)
444 || (active_filter.bf_len != 0
445 && bpf_filter(active_filter.bf_insns, p, len, len) == 0)) {
446 p[0] = 0xff;
447 return 0;
449 p[0] = 0xff;
450 #endif
451 for (i = 0; (protp = protocols[i]) != NULL; ++i) {
452 if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
453 if (!protp->enabled_flag)
454 return 0;
455 if (protp->active_pkt == NULL)
456 return 1;
457 return (*protp->active_pkt)(p, len);
460 return 0; /* not a supported protocol !!?? */