Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
lwip_demand.c
00001 /* 00002 * demand.c - Support routines for demand-dialling. 00003 * 00004 * Copyright (c) 1996-2002 Paul Mackerras. All rights reserved. 00005 * 00006 * Redistribution and use in source and binary forms, with or without 00007 * modification, are permitted provided that the following conditions 00008 * are met: 00009 * 00010 * 1. Redistributions of source code must retain the above copyright 00011 * notice, this list of conditions and the following disclaimer. 00012 * 00013 * 2. The name(s) of the authors of this software must not be used to 00014 * endorse or promote products derived from this software without 00015 * prior written permission. 00016 * 00017 * 3. Redistributions of any form whatsoever must retain the following 00018 * acknowledgment: 00019 * "This product includes software developed by Paul Mackerras 00020 * <paulus@samba.org>". 00021 * 00022 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO 00023 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 00024 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY 00025 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 00026 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 00027 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 00028 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00029 */ 00030 00031 #include "netif/ppp/ppp_opts.h" 00032 #if PPP_SUPPORT && DEMAND_SUPPORT /* don't build if not configured for use in lwipopts.h */ 00033 00034 #include <stdio.h> 00035 #include <stdlib.h> 00036 #include <string.h> 00037 #include <errno.h> 00038 #include <fcntl.h> 00039 #include <netdb.h> 00040 #include <unistd.h> 00041 #include <syslog.h> 00042 #include <sys/param.h> 00043 #include <sys/types.h> 00044 #include <sys/wait.h> 00045 #include <sys/time.h> 00046 #include <sys/resource.h> 00047 #include <sys/stat.h> 00048 #include <sys/socket.h> 00049 #include <netinet/in.h> 00050 #include <arpa/inet.h> 00051 #ifdef PPP_FILTER 00052 #include <pcap-bpf.h> 00053 #endif 00054 00055 #include "netif/ppp/ppp_impl.h" 00056 00057 #include "netif/ppp/fsm.h" 00058 #include "netif/ppp/ipcp.h" 00059 #include "netif/ppp/lcp.h" 00060 00061 char *frame; 00062 int framelen; 00063 int framemax; 00064 int escape_flag; 00065 int flush_flag; 00066 int fcs; 00067 00068 struct packet { 00069 int length; 00070 struct packet *next; 00071 unsigned char data[1]; 00072 }; 00073 00074 struct packet *pend_q; 00075 struct packet *pend_qtail; 00076 00077 static int active_packet (unsigned char *, int); 00078 00079 /* 00080 * demand_conf - configure the interface for doing dial-on-demand. 00081 */ 00082 void 00083 demand_conf() 00084 { 00085 int i; 00086 const struct protent *protp; 00087 00088 /* framemax = lcp_allowoptions[0].mru; 00089 if (framemax < PPP_MRU) */ 00090 framemax = PPP_MRU; 00091 framemax += PPP_HDRLEN + PPP_FCSLEN; 00092 frame = malloc(framemax); 00093 if (frame == NULL) 00094 novm("demand frame"); 00095 framelen = 0; 00096 pend_q = NULL; 00097 escape_flag = 0; 00098 flush_flag = 0; 00099 fcs = PPP_INITFCS; 00100 00101 netif_set_mtu(pcb, LWIP_MIN(lcp_allowoptions[0].mru, PPP_MRU)); 00102 if (ppp_send_config(pcb, PPP_MRU, (u32_t) 0, 0, 0) < 0 00103 || ppp_recv_config(pcb, PPP_MRU, (u32_t) 0, 0, 0) < 0) 00104 fatal("Couldn't set up demand-dialled PPP interface: %m"); 00105 00106 #ifdef PPP_FILTER 00107 set_filters(&pass_filter, &active_filter); 00108 #endif 00109 00110 /* 00111 * Call the demand_conf procedure for each protocol that's got one. 00112 */ 00113 for (i = 0; (protp = protocols[i]) != NULL; ++i) 00114 if (protp->demand_conf != NULL) 00115 ((*protp->demand_conf)(pcb)); 00116 /* FIXME: find a way to die() here */ 00117 #if 0 00118 if (!((*protp->demand_conf)(pcb))) 00119 die(1); 00120 #endif 00121 } 00122 00123 00124 /* 00125 * demand_block - set each network protocol to block further packets. 00126 */ 00127 void 00128 demand_block() 00129 { 00130 int i; 00131 const struct protent *protp; 00132 00133 for (i = 0; (protp = protocols[i]) != NULL; ++i) 00134 if (protp->demand_conf != NULL) 00135 sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_QUEUE); 00136 get_loop_output(); 00137 } 00138 00139 /* 00140 * demand_discard - set each network protocol to discard packets 00141 * with an error. 00142 */ 00143 void 00144 demand_discard() 00145 { 00146 struct packet *pkt, *nextpkt; 00147 int i; 00148 const struct protent *protp; 00149 00150 for (i = 0; (protp = protocols[i]) != NULL; ++i) 00151 if (protp->demand_conf != NULL) 00152 sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_ERROR); 00153 get_loop_output(); 00154 00155 /* discard all saved packets */ 00156 for (pkt = pend_q; pkt != NULL; pkt = nextpkt) { 00157 nextpkt = pkt->next; 00158 free(pkt); 00159 } 00160 pend_q = NULL; 00161 framelen = 0; 00162 flush_flag = 0; 00163 escape_flag = 0; 00164 fcs = PPP_INITFCS; 00165 } 00166 00167 /* 00168 * demand_unblock - set each enabled network protocol to pass packets. 00169 */ 00170 void 00171 demand_unblock() 00172 { 00173 int i; 00174 const struct protent *protp; 00175 00176 for (i = 0; (protp = protocols[i]) != NULL; ++i) 00177 if (protp->demand_conf != NULL) 00178 sifnpmode(pcb, protp->protocol & ~0x8000, NPMODE_PASS); 00179 } 00180 00181 /* 00182 * FCS lookup table as calculated by genfcstab. 00183 */ 00184 static u_short fcstab[256] = { 00185 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 00186 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 00187 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 00188 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 00189 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 00190 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 00191 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 00192 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 00193 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 00194 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 00195 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 00196 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 00197 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 00198 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 00199 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 00200 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 00201 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 00202 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 00203 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 00204 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 00205 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 00206 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 00207 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 00208 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 00209 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 00210 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 00211 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 00212 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 00213 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 00214 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 00215 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 00216 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 00217 }; 00218 00219 /* 00220 * loop_chars - process characters received from the loopback. 00221 * Calls loop_frame when a complete frame has been accumulated. 00222 * Return value is 1 if we need to bring up the link, 0 otherwise. 00223 */ 00224 int 00225 loop_chars(p, n) 00226 unsigned char *p; 00227 int n; 00228 { 00229 int c, rv; 00230 00231 rv = 0; 00232 00233 /* check for synchronous connection... */ 00234 00235 if ( (p[0] == 0xFF) && (p[1] == 0x03) ) { 00236 rv = loop_frame(p,n); 00237 return rv; 00238 } 00239 00240 for (; n > 0; --n) { 00241 c = *p++; 00242 if (c == PPP_FLAG) { 00243 if (!escape_flag && !flush_flag 00244 && framelen > 2 && fcs == PPP_GOODFCS) { 00245 framelen -= 2; 00246 if (loop_frame((unsigned char *)frame, framelen)) 00247 rv = 1; 00248 } 00249 framelen = 0; 00250 flush_flag = 0; 00251 escape_flag = 0; 00252 fcs = PPP_INITFCS; 00253 continue; 00254 } 00255 if (flush_flag) 00256 continue; 00257 if (escape_flag) { 00258 c ^= PPP_TRANS; 00259 escape_flag = 0; 00260 } else if (c == PPP_ESCAPE) { 00261 escape_flag = 1; 00262 continue; 00263 } 00264 if (framelen >= framemax) { 00265 flush_flag = 1; 00266 continue; 00267 } 00268 frame[framelen++] = c; 00269 fcs = PPP_FCS(fcs, c); 00270 } 00271 return rv; 00272 } 00273 00274 /* 00275 * loop_frame - given a frame obtained from the loopback, 00276 * decide whether to bring up the link or not, and, if we want 00277 * to transmit this frame later, put it on the pending queue. 00278 * Return value is 1 if we need to bring up the link, 0 otherwise. 00279 * We assume that the kernel driver has already applied the 00280 * pass_filter, so we won't get packets it rejected. 00281 * We apply the active_filter to see if we want this packet to 00282 * bring up the link. 00283 */ 00284 int 00285 loop_frame(frame, len) 00286 unsigned char *frame; 00287 int len; 00288 { 00289 struct packet *pkt; 00290 00291 /* dbglog("from loop: %P", frame, len); */ 00292 if (len < PPP_HDRLEN) 00293 return 0; 00294 if ((PPP_PROTOCOL(frame) & 0x8000) != 0) 00295 return 0; /* shouldn't get any of these anyway */ 00296 if (!active_packet(frame, len)) 00297 return 0; 00298 00299 pkt = (struct packet *) malloc(sizeof(struct packet) + len); 00300 if (pkt != NULL) { 00301 pkt->length = len; 00302 pkt->next = NULL; 00303 memcpy(pkt->data, frame, len); 00304 if (pend_q == NULL) 00305 pend_q = pkt; 00306 else 00307 pend_qtail->next = pkt; 00308 pend_qtail = pkt; 00309 } 00310 return 1; 00311 } 00312 00313 /* 00314 * demand_rexmit - Resend all those frames which we got via the 00315 * loopback, now that the real serial link is up. 00316 */ 00317 void 00318 demand_rexmit(proto, newip) 00319 int proto; 00320 u32_t newip; 00321 { 00322 struct packet *pkt, *prev, *nextpkt; 00323 unsigned short checksum; 00324 unsigned short pkt_checksum = 0; 00325 unsigned iphdr; 00326 struct timeval tv; 00327 char cv = 0; 00328 char ipstr[16]; 00329 00330 prev = NULL; 00331 pkt = pend_q; 00332 pend_q = NULL; 00333 tv.tv_sec = 1; 00334 tv.tv_usec = 0; 00335 select(0,NULL,NULL,NULL,&tv); /* Sleep for 1 Seconds */ 00336 for (; pkt != NULL; pkt = nextpkt) { 00337 nextpkt = pkt->next; 00338 if (PPP_PROTOCOL(pkt->data) == proto) { 00339 if ( (proto == PPP_IP) && newip ) { 00340 /* Get old checksum */ 00341 00342 iphdr = (pkt->data[4] & 15) << 2; 00343 checksum = *((unsigned short *) (pkt->data+14)); 00344 if (checksum == 0xFFFF) { 00345 checksum = 0; 00346 } 00347 00348 00349 if (pkt->data[13] == 17) { 00350 pkt_checksum = *((unsigned short *) (pkt->data+10+iphdr)); 00351 if (pkt_checksum) { 00352 cv = 1; 00353 if (pkt_checksum == 0xFFFF) { 00354 pkt_checksum = 0; 00355 } 00356 } 00357 else { 00358 cv = 0; 00359 } 00360 } 00361 00362 if (pkt->data[13] == 6) { 00363 pkt_checksum = *((unsigned short *) (pkt->data+20+iphdr)); 00364 cv = 1; 00365 if (pkt_checksum == 0xFFFF) { 00366 pkt_checksum = 0; 00367 } 00368 } 00369 00370 /* Delete old Source-IP-Address */ 00371 checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; 00372 checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; 00373 00374 pkt_checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; 00375 pkt_checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; 00376 00377 /* Change Source-IP-Address */ 00378 * ((u32_t *) (pkt->data + 16)) = newip; 00379 00380 /* Add new Source-IP-Address */ 00381 checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; 00382 checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; 00383 00384 pkt_checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF; 00385 pkt_checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF; 00386 00387 /* Write new checksum */ 00388 if (!checksum) { 00389 checksum = 0xFFFF; 00390 } 00391 *((unsigned short *) (pkt->data+14)) = checksum; 00392 if (pkt->data[13] == 6) { 00393 *((unsigned short *) (pkt->data+20+iphdr)) = pkt_checksum; 00394 } 00395 if (cv && (pkt->data[13] == 17) ) { 00396 *((unsigned short *) (pkt->data+10+iphdr)) = pkt_checksum; 00397 } 00398 00399 /* Log Packet */ 00400 strcpy(ipstr,inet_ntoa(*( (struct in_addr *) (pkt->data+16)))); 00401 if (pkt->data[13] == 1) { 00402 syslog(LOG_INFO,"Open ICMP %s -> %s\n", 00403 ipstr, 00404 inet_ntoa(*( (struct in_addr *) (pkt->data+20)))); 00405 } else { 00406 syslog(LOG_INFO,"Open %s %s:%d -> %s:%d\n", 00407 pkt->data[13] == 6 ? "TCP" : "UDP", 00408 ipstr, 00409 ntohs(*( (short *) (pkt->data+iphdr+4))), 00410 inet_ntoa(*( (struct in_addr *) (pkt->data+20))), 00411 ntohs(*( (short *) (pkt->data+iphdr+6)))); 00412 } 00413 } 00414 output(pcb, pkt->data, pkt->length); 00415 free(pkt); 00416 } else { 00417 if (prev == NULL) 00418 pend_q = pkt; 00419 else 00420 prev->next = pkt; 00421 prev = pkt; 00422 } 00423 } 00424 pend_qtail = prev; 00425 if (prev != NULL) 00426 prev->next = NULL; 00427 } 00428 00429 /* 00430 * Scan a packet to decide whether it is an "active" packet, 00431 * that is, whether it is worth bringing up the link for. 00432 */ 00433 static int 00434 active_packet(p, len) 00435 unsigned char *p; 00436 int len; 00437 { 00438 int proto, i; 00439 const struct protent *protp; 00440 00441 if (len < PPP_HDRLEN) 00442 return 0; 00443 proto = PPP_PROTOCOL(p); 00444 #ifdef PPP_FILTER 00445 p[0] = 1; /* outbound packet indicator */ 00446 if ((pass_filter.bf_len != 0 00447 && bpf_filter(pass_filter.bf_insns, p, len, len) == 0) 00448 || (active_filter.bf_len != 0 00449 && bpf_filter(active_filter.bf_insns, p, len, len) == 0)) { 00450 p[0] = 0xff; 00451 return 0; 00452 } 00453 p[0] = 0xff; 00454 #endif 00455 for (i = 0; (protp = protocols[i]) != NULL; ++i) { 00456 if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) { 00457 if (protp->active_pkt == NULL) 00458 return 1; 00459 return (*protp->active_pkt)(p, len); 00460 } 00461 } 00462 return 0; /* not a supported protocol !!?? */ 00463 } 00464 00465 #endif /* PPP_SUPPORT && DEMAND_SUPPORT */
Generated on Sun Jul 17 2022 08:25:24 by 1.7.2