source: S-port/trunk/Middlewares/Third_Party/LwIP/src/netif/ppp/demand.c

Last change on this file was 1, checked in by AlexLir, 3 years ago
File size: 13.3 KB
Line 
1/*
2 * demand.c - Support routines for demand-dialling.
3 *
4 * Copyright (c) 1996-2002 Paul Mackerras. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
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.
16 *
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>".
21 *
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.
29 */
30
31#include "netif/ppp/ppp_opts.h"
32#if PPP_SUPPORT && DEMAND_SUPPORT /* don't build if not configured for use in lwipopts.h */
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <errno.h>
38#include <fcntl.h>
39#include <netdb.h>
40#include <unistd.h>
41#include <syslog.h>
42#include <sys/param.h>
43#include <sys/types.h>
44#include <sys/wait.h>
45#include <sys/time.h>
46#include <sys/resource.h>
47#include <sys/stat.h>
48#include <sys/socket.h>
49#include <netinet/in.h>
50#include <arpa/inet.h>
51#ifdef PPP_FILTER
52#include <pcap-bpf.h>
53#endif
54
55#include "netif/ppp/ppp_impl.h"
56
57#include "netif/ppp/fsm.h"
58#include "netif/ppp/ipcp.h"
59#include "netif/ppp/lcp.h"
60
61char *frame;
62int framelen;
63int framemax;
64int escape_flag;
65int flush_flag;
66int fcs;
67
68struct packet {
69 int length;
70 struct packet *next;
71 unsigned char data[1];
72};
73
74struct packet *pend_q;
75struct packet *pend_qtail;
76
77static int active_packet (unsigned char *, int);
78
79/*
80 * demand_conf - configure the interface for doing dial-on-demand.
81 */
82void
83demand_conf()
84{
85 int i;
86 const struct protent *protp;
87
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;
100
101 netif_set_mtu(pcb, LWIP_MIN(lcp_allowoptions[0].mru, PPP_MRU));
102 if (ppp_send_config(pcb, PPP_MRU, (u32_t) 0, 0, 0) < 0
103 || ppp_recv_config(pcb, PPP_MRU, (u32_t) 0, 0, 0) < 0)
104 fatal("Couldn't set up demand-dialled PPP interface: %m");
105
106#ifdef PPP_FILTER
107 set_filters(&pass_filter, &active_filter);
108#endif
109
110 /*
111 * Call the demand_conf procedure for each protocol that's got one.
112 */
113 for (i = 0; (protp = protocols[i]) != NULL; ++i)
114 if (protp->demand_conf != NULL)
115 ((*protp->demand_conf)(pcb));
116/* FIXME: find a way to die() here */
117#if 0
118 if (!((*protp->demand_conf)(pcb)))
119 die(1);
120#endif
121}
122
123
124/*
125 * demand_block - set each network protocol to block further packets.
126 */
127void
128demand_block()
129{
130 int i;
131 const struct protent *protp;
132
133 for (i = 0; (protp = protocols[i]) != NULL; ++i)
134 if (protp->demand_conf != NULL)
135 sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_QUEUE);
136 get_loop_output();
137}
138
139/*
140 * demand_discard - set each network protocol to discard packets
141 * with an error.
142 */
143void
144demand_discard()
145{
146 struct packet *pkt, *nextpkt;
147 int i;
148 const struct protent *protp;
149
150 for (i = 0; (protp = protocols[i]) != NULL; ++i)
151 if (protp->demand_conf != NULL)
152 sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_ERROR);
153 get_loop_output();
154
155 /* discard all saved packets */
156 for (pkt = pend_q; pkt != NULL; pkt = nextpkt) {
157 nextpkt = pkt->next;
158 free(pkt);
159 }
160 pend_q = NULL;
161 framelen = 0;
162 flush_flag = 0;
163 escape_flag = 0;
164 fcs = PPP_INITFCS;
165}
166
167/*
168 * demand_unblock - set each enabled network protocol to pass packets.
169 */
170void
171demand_unblock()
172{
173 int i;
174 const struct protent *protp;
175
176 for (i = 0; (protp = protocols[i]) != NULL; ++i)
177 if (protp->demand_conf != NULL)
178 sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_PASS);
179}
180
181/*
182 * FCS lookup table as calculated by genfcstab.
183 */
184static u_short fcstab[256] = {
185 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
186 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
187 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
188 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
189 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
190 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
191 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
192 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
193 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
194 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
195 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
196 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
197 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
198 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
199 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
200 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
201 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
202 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
203 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
204 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
205 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
206 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
207 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
208 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
209 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
210 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
211 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
212 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
213 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
214 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
215 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
216 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
217};
218
219/*
220 * loop_chars - process characters received from the loopback.
221 * Calls loop_frame when a complete frame has been accumulated.
222 * Return value is 1 if we need to bring up the link, 0 otherwise.
223 */
224int
225loop_chars(p, n)
226 unsigned char *p;
227 int n;
228{
229 int c, rv;
230
231 rv = 0;
232
233/* check for synchronous connection... */
234
235 if ( (p[0] == 0xFF) && (p[1] == 0x03) ) {
236 rv = loop_frame(p,n);
237 return rv;
238 }
239
240 for (; n > 0; --n) {
241 c = *p++;
242 if (c == PPP_FLAG) {
243 if (!escape_flag && !flush_flag
244 && framelen > 2 && fcs == PPP_GOODFCS) {
245 framelen -= 2;
246 if (loop_frame((unsigned char *)frame, framelen))
247 rv = 1;
248 }
249 framelen = 0;
250 flush_flag = 0;
251 escape_flag = 0;
252 fcs = PPP_INITFCS;
253 continue;
254 }
255 if (flush_flag)
256 continue;
257 if (escape_flag) {
258 c ^= PPP_TRANS;
259 escape_flag = 0;
260 } else if (c == PPP_ESCAPE) {
261 escape_flag = 1;
262 continue;
263 }
264 if (framelen >= framemax) {
265 flush_flag = 1;
266 continue;
267 }
268 frame[framelen++] = c;
269 fcs = PPP_FCS(fcs, c);
270 }
271 return rv;
272}
273
274/*
275 * loop_frame - given a frame obtained from the loopback,
276 * decide whether to bring up the link or not, and, if we want
277 * to transmit this frame later, put it on the pending queue.
278 * Return value is 1 if we need to bring up the link, 0 otherwise.
279 * We assume that the kernel driver has already applied the
280 * pass_filter, so we won't get packets it rejected.
281 * We apply the active_filter to see if we want this packet to
282 * bring up the link.
283 */
284int
285loop_frame(frame, len)
286 unsigned char *frame;
287 int len;
288{
289 struct packet *pkt;
290
291 /* dbglog("from loop: %P", frame, len); */
292 if (len < PPP_HDRLEN)
293 return 0;
294 if ((PPP_PROTOCOL(frame) & 0x8000) != 0)
295 return 0; /* shouldn't get any of these anyway */
296 if (!active_packet(frame, len))
297 return 0;
298
299 pkt = (struct packet *) malloc(sizeof(struct packet) + len);
300 if (pkt != NULL) {
301 pkt->length = len;
302 pkt->next = NULL;
303 memcpy(pkt->data, frame, len);
304 if (pend_q == NULL)
305 pend_q = pkt;
306 else
307 pend_qtail->next = pkt;
308 pend_qtail = pkt;
309 }
310 return 1;
311}
312
313/*
314 * demand_rexmit - Resend all those frames which we got via the
315 * loopback, now that the real serial link is up.
316 */
317void
318demand_rexmit(proto, newip)
319 int proto;
320 u32_t newip;
321{
322 struct packet *pkt, *prev, *nextpkt;
323 unsigned short checksum;
324 unsigned short pkt_checksum = 0;
325 unsigned iphdr;
326 struct timeval tv;
327 char cv = 0;
328 char ipstr[16];
329
330 prev = NULL;
331 pkt = pend_q;
332 pend_q = NULL;
333 tv.tv_sec = 1;
334 tv.tv_usec = 0;
335 select(0,NULL,NULL,NULL,&tv); /* Sleep for 1 Seconds */
336 for (; pkt != NULL; pkt = nextpkt) {
337 nextpkt = pkt->next;
338 if (PPP_PROTOCOL(pkt->data) == proto) {
339 if ( (proto == PPP_IP) && newip ) {
340 /* Get old checksum */
341
342 iphdr = (pkt->data[4] & 15) << 2;
343 checksum = *((unsigned short *) (pkt->data+14));
344 if (checksum == 0xFFFF) {
345 checksum = 0;
346 }
347
348
349 if (pkt->data[13] == 17) {
350 pkt_checksum = *((unsigned short *) (pkt->data+10+iphdr));
351 if (pkt_checksum) {
352 cv = 1;
353 if (pkt_checksum == 0xFFFF) {
354 pkt_checksum = 0;
355 }
356 }
357 else {
358 cv = 0;
359 }
360 }
361
362 if (pkt->data[13] == 6) {
363 pkt_checksum = *((unsigned short *) (pkt->data+20+iphdr));
364 cv = 1;
365 if (pkt_checksum == 0xFFFF) {
366 pkt_checksum = 0;
367 }
368 }
369
370 /* Delete old Source-IP-Address */
371 checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
372 checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
373
374 pkt_checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
375 pkt_checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
376
377 /* Change Source-IP-Address */
378 * ((u32_t *) (pkt->data + 16)) = newip;
379
380 /* Add new Source-IP-Address */
381 checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
382 checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
383
384 pkt_checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
385 pkt_checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
386
387 /* Write new checksum */
388 if (!checksum) {
389 checksum = 0xFFFF;
390 }
391 *((unsigned short *) (pkt->data+14)) = checksum;
392 if (pkt->data[13] == 6) {
393 *((unsigned short *) (pkt->data+20+iphdr)) = pkt_checksum;
394 }
395 if (cv && (pkt->data[13] == 17) ) {
396 *((unsigned short *) (pkt->data+10+iphdr)) = pkt_checksum;
397 }
398
399 /* Log Packet */
400 strcpy(ipstr,inet_ntoa(*( (struct in_addr *) (pkt->data+16))));
401 if (pkt->data[13] == 1) {
402 syslog(LOG_INFO,"Open ICMP %s -> %s\n",
403 ipstr,
404 inet_ntoa(*( (struct in_addr *) (pkt->data+20))));
405 } else {
406 syslog(LOG_INFO,"Open %s %s:%d -> %s:%d\n",
407 pkt->data[13] == 6 ? "TCP" : "UDP",
408 ipstr,
409 ntohs(*( (short *) (pkt->data+iphdr+4))),
410 inet_ntoa(*( (struct in_addr *) (pkt->data+20))),
411 ntohs(*( (short *) (pkt->data+iphdr+6))));
412 }
413 }
414 output(pcb, pkt->data, pkt->length);
415 free(pkt);
416 } else {
417 if (prev == NULL)
418 pend_q = pkt;
419 else
420 prev->next = pkt;
421 prev = pkt;
422 }
423 }
424 pend_qtail = prev;
425 if (prev != NULL)
426 prev->next = NULL;
427}
428
429/*
430 * Scan a packet to decide whether it is an "active" packet,
431 * that is, whether it is worth bringing up the link for.
432 */
433static int
434active_packet(p, len)
435 unsigned char *p;
436 int len;
437{
438 int proto, i;
439 const struct protent *protp;
440
441 if (len < PPP_HDRLEN)
442 return 0;
443 proto = PPP_PROTOCOL(p);
444#ifdef PPP_FILTER
445 p[0] = 1; /* outbound packet indicator */
446 if ((pass_filter.bf_len != 0
447 && bpf_filter(pass_filter.bf_insns, p, len, len) == 0)
448 || (active_filter.bf_len != 0
449 && bpf_filter(active_filter.bf_insns, p, len, len) == 0)) {
450 p[0] = 0xff;
451 return 0;
452 }
453 p[0] = 0xff;
454#endif
455 for (i = 0; (protp = protocols[i]) != NULL; ++i) {
456 if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
457 if (protp->active_pkt == NULL)
458 return 1;
459 return (*protp->active_pkt)(p, len);
460 }
461 }
462 return 0; /* not a supported protocol !!?? */
463}
464
465#endif /* PPP_SUPPORT && DEMAND_SUPPORT */
Note: See TracBrowser for help on using the repository browser.