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
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
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 $"
41 #include <sys/param.h>
42 #include <sys/types.h>
45 #include <sys/resource.h>
47 #include <sys/socket.h>
48 #include <netinet/in.h>
49 #include <arpa/inet.h>
59 static const char rcsid
[] = RCSID
;
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.
86 struct protent
*protp
;
88 /* framemax = lcp_allowoptions[0].mru;
89 if (framemax < PPP_MRU) */
91 framemax
+= PPP_HDRLEN
+ PPP_FCSLEN
;
92 frame
= malloc(framemax
);
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");
107 set_filters(&pass_filter
, &active_filter
);
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)))
121 * demand_block - set each network protocol to block further packets.
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
);
136 * demand_discard - set each network protocol to discard packets
142 struct packet
*pkt
, *nextpkt
;
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
);
151 /* discard all saved packets */
152 for (pkt
= pend_q
; pkt
!= NULL
; pkt
= nextpkt
) {
164 * demand_unblock - set each enabled network protocol to pass packets.
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.
229 /* check for synchronous connection... */
231 if ( (p
[0] == 0xFF) && (p
[1] == 0x03) ) {
232 rv
= loop_frame(p
,n
);
239 if (!escape_flag
&& !flush_flag
240 && framelen
> 2 && fcs
== PPP_GOODFCS
) {
242 if (loop_frame((unsigned char *)frame
, framelen
))
256 } else if (c
== PPP_ESCAPE
) {
260 if (framelen
>= framemax
) {
264 frame
[framelen
++] = c
;
265 fcs
= PPP_FCS(fcs
, c
);
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
281 loop_frame(frame
, len
)
282 unsigned char *frame
;
287 /* dbglog("from loop: %P", frame, len); */
288 if (len
< PPP_HDRLEN
)
290 if ((PPP_PROTOCOL(frame
) & 0x8000) != 0)
291 return 0; /* shouldn't get any of these anyway */
292 if (!active_packet(frame
, len
))
295 pkt
= (struct packet
*) malloc(sizeof(struct packet
) + len
);
299 memcpy(pkt
->data
, frame
, len
);
303 pend_qtail
->next
= pkt
;
310 * demand_rexmit - Resend all those frames which we got via the
311 * loopback, now that the real serial link is up.
314 demand_rexmit(proto
, newip
)
318 struct packet
*pkt
, *prev
, *nextpkt
;
319 unsigned short checksum
;
320 unsigned short pkt_checksum
= 0;
331 select(0,NULL
,NULL
,NULL
,&tv
); /* Sleep for 1 Seconds */
332 for (; pkt
!= NULL
; pkt
= nextpkt
) {
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) {
345 if (pkt
->data
[13] == 17) {
346 pkt_checksum
= *((unsigned short *) (pkt
->data
+10+iphdr
));
349 if (pkt_checksum
== 0xFFFF) {
358 if (pkt
->data
[13] == 6) {
359 pkt_checksum
= *((unsigned short *) (pkt
->data
+20+iphdr
));
361 if (pkt_checksum
== 0xFFFF) {
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 */
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
;
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",
400 inet_ntoa(*( (struct in_addr
*) (pkt
->data
+20))));
402 syslog(LOG_INFO
,"Open %s %s:%d -> %s:%d\n",
403 pkt
->data
[13] == 6 ? "TCP" : "UDP",
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
);
426 * Scan a packet to decide whether it is an "active" packet,
427 * that is, whether it is worth bringing up the link for.
430 active_packet(p
, len
)
435 struct protent
*protp
;
437 if (len
< PPP_HDRLEN
)
439 proto
= PPP_PROTOCOL(p
);
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)) {
451 for (i
= 0; (protp
= protocols
[i
]) != NULL
; ++i
) {
452 if (protp
->protocol
< 0xC000 && (protp
->protocol
& ~0x8000) == proto
) {
453 if (!protp
->enabled_flag
)
455 if (protp
->active_pkt
== NULL
)
457 return (*protp
->active_pkt
)(p
, len
);
460 return 0; /* not a supported protocol !!?? */