uip-fw.c
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 #include <string.h>
00057
00058 #include "contiki-conf.h"
00059
00060 #include "net/uip.h"
00061 #include "net/uip_arch.h"
00062 #include "net/uip-fw.h"
00063 #ifdef AODV_COMPLIANCE
00064 #include "net/uaodv-def.h"
00065 #endif
00066
00067
00068
00069
00070 static struct uip_fw_netif *netifs = NULL;
00071
00072
00073
00074
00075 static struct uip_fw_netif *defaultnetif = NULL;
00076
00077 struct tcpip_hdr {
00078
00079 u8_t vhl,
00080 tos;
00081 u16_t len,
00082 ipid,
00083 ipoffset;
00084 u8_t ttl,
00085 proto;
00086 u16_t ipchksum;
00087 uip_ipaddr_t srcipaddr, destipaddr;
00088
00089
00090 u16_t srcport,
00091 destport;
00092 u8_t seqno[4],
00093 ackno[4],
00094 tcpoffset,
00095 flags,
00096 wnd[2];
00097 u16_t tcpchksum;
00098 u8_t urgp[2];
00099 u8_t optdata[4];
00100 };
00101
00102 struct icmpip_hdr {
00103
00104 u8_t vhl,
00105 tos,
00106 len[2],
00107 ipid[2],
00108 ipoffset[2],
00109 ttl,
00110 proto;
00111 u16_t ipchksum;
00112 uip_ipaddr_t srcipaddr, destipaddr;
00113
00114 u8_t type, icode;
00115 u16_t icmpchksum;
00116 u16_t id, seqno;
00117 u8_t payload[1];
00118 };
00119
00120
00121 #define ICMP_ECHO 8
00122
00123
00124 #define ICMP_TE 11
00125
00126
00127
00128
00129 #define BUF ((struct tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
00130
00131
00132
00133
00134 #define ICMPBUF ((struct icmpip_hdr *)&uip_buf[UIP_LLH_LEN])
00135
00136
00137
00138
00139
00140 struct fwcache_entry {
00141 u16_t timer;
00142
00143 uip_ipaddr_t srcipaddr;
00144 uip_ipaddr_t destipaddr;
00145 u16_t ipid;
00146 u8_t proto;
00147 u8_t unused;
00148
00149 #if notdef
00150 u16_t payload[2];
00151 #endif
00152
00153 #if UIP_REASSEMBLY > 0
00154 u16_t len, offset;
00155 #endif
00156 };
00157
00158
00159
00160
00161 #ifdef UIP_CONF_FWCACHE_SIZE
00162 #define FWCACHE_SIZE UIP_CONF_FWCACHE_SIZE
00163 #else
00164 #define FWCACHE_SIZE 2
00165 #endif
00166
00167
00168
00169
00170
00171
00172 static struct fwcache_entry fwcache[FWCACHE_SIZE];
00173
00174
00175
00176
00177
00178 #define FW_TIME 20
00179
00180
00181
00182
00183
00184
00185 void
00186 uip_fw_init(void)
00187 {
00188 struct uip_fw_netif *t;
00189 defaultnetif = NULL;
00190 while(netifs != NULL) {
00191 t = netifs;
00192 netifs = netifs->next;
00193 t->next = NULL;
00194 }
00195 }
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 static unsigned char
00210 ipaddr_maskcmp(uip_ipaddr_t *ipaddr,
00211 uip_ipaddr_t *netipaddr,
00212 uip_ipaddr_t *netmask)
00213 {
00214 return (ipaddr->u16[0] & netmask->u16[0]) == (netipaddr->u16[0] & netmask->u16[0]) &&
00215 (ipaddr->u16[1] & netmask->u16[1]) == (netipaddr->u16[1] & netmask->u16[1]);
00216 }
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226 static void
00227 time_exceeded(void)
00228 {
00229
00230
00231 if(ICMPBUF->proto == UIP_PROTO_ICMP &&
00232 ICMPBUF->type != ICMP_ECHO) {
00233 uip_len = 0;
00234 return;
00235 }
00236
00237 memcpy(&(ICMPBUF->payload[0]), ICMPBUF, UIP_IPH_LEN + 8);
00238
00239
00240 ICMPBUF->type = ICMP_TE;
00241 ICMPBUF->icode = 0;
00242
00243
00244 ICMPBUF->icmpchksum = 0;
00245 ICMPBUF->icmpchksum = ~uip_chksum((u16_t *)&(ICMPBUF->type), 36);
00246
00247
00248
00249 uip_ipaddr_copy(&BUF->destipaddr, &BUF->srcipaddr);
00250
00251
00252 uip_ipaddr_copy(&BUF->srcipaddr, &uip_hostaddr);
00253
00254
00255
00256 uip_len = 56;
00257 ICMPBUF->len[0] = 0;
00258 ICMPBUF->len[1] = (u8_t)uip_len;
00259
00260
00261 ICMPBUF->vhl = 0x45;
00262 ICMPBUF->tos = 0;
00263 ICMPBUF->ipoffset[0] = ICMPBUF->ipoffset[1] = 0;
00264 ICMPBUF->ttl = UIP_TTL;
00265 ICMPBUF->proto = UIP_PROTO_ICMP;
00266
00267
00268 ICMPBUF->ipchksum = 0;
00269 ICMPBUF->ipchksum = ~(uip_ipchksum());
00270
00271
00272 }
00273
00274
00275
00276
00277
00278
00279
00280 static void
00281 fwcache_register(void)
00282 {
00283 struct fwcache_entry *fw;
00284 int i, oldest;
00285
00286 oldest = FW_TIME;
00287 fw = NULL;
00288
00289
00290 for(i = 0; i < FWCACHE_SIZE; ++i) {
00291 if(fwcache[i].timer == 0) {
00292 fw = &fwcache[i];
00293 break;
00294 } else if(fwcache[i].timer <= oldest) {
00295 fw = &fwcache[i];
00296 oldest = fwcache[i].timer;
00297 }
00298 }
00299
00300 fw->timer = FW_TIME;
00301 fw->ipid = BUF->ipid;
00302 uip_ipaddr_copy(&fw->srcipaddr, &BUF->srcipaddr);
00303 uip_ipaddr_copy(&fw->destipaddr, &BUF->destipaddr);
00304 fw->proto = BUF->proto;
00305 #if notdef
00306 fw->payload[0] = BUF->srcport;
00307 fw->payload[1] = BUF->destport;
00308 #endif
00309 #if UIP_REASSEMBLY > 0
00310 fw->len = BUF->len;
00311 fw->offset = BUF->ipoffset;
00312 #endif
00313 }
00314
00315
00316
00317
00318
00319
00320 static struct uip_fw_netif *
00321 find_netif(void)
00322 {
00323 struct uip_fw_netif *netif;
00324
00325
00326 for(netif = netifs; netif != NULL; netif = netif->next) {
00327 if(ipaddr_maskcmp(&BUF->destipaddr, &netif->ipaddr,
00328 &netif->netmask)) {
00329
00330 return netif;
00331 }
00332 }
00333
00334
00335 return defaultnetif;
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 u8_t
00355 uip_fw_output(void)
00356 {
00357 struct uip_fw_netif *netif;
00358 #if UIP_BROADCAST
00359 const struct uip_udpip_hdr *udp = (void *)BUF;
00360 #endif
00361
00362 if(uip_len == 0) {
00363 return UIP_FW_ZEROLEN;
00364 }
00365
00366 fwcache_register();
00367
00368 #if UIP_BROADCAST
00369
00370 if(uip_ipaddr_cmp(&udp->destipaddr, &uip_broadcast_addr)) {
00371 if(defaultnetif != NULL) {
00372 defaultnetif->output();
00373 }
00374 for(netif = netifs; netif != NULL; netif = netif->next) {
00375 netif->output();
00376 }
00377 return UIP_FW_OK;
00378 }
00379 #endif
00380
00381 netif = find_netif();
00382
00383
00384
00385
00386 if(netif == NULL) {
00387 return UIP_FW_NOROUTE;
00388 }
00389
00390
00391 return netif->output();
00392 }
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 u8_t
00404 uip_fw_forward(void)
00405 {
00406 struct fwcache_entry *fw;
00407
00408
00409
00410 if(uip_ipaddr_cmp(&BUF->destipaddr, &uip_hostaddr)) {
00411 return UIP_FW_LOCAL;
00412 }
00413
00414 #ifdef AODV_COMPLIANCE
00415 #define udp ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
00416 if(udp->proto == UIP_PROTO_UDP && udp->destport == UIP_HTONS(UAODV_UDPPORT)) {
00417 return UIP_FW_LOCAL;
00418 }
00419 #endif
00420
00421
00422
00423 #if UIP_PINGADDRCONF
00424 if(uip_ipaddr_cmp(&uip_hostaddr, &uip_all_zeroes_addr) &&
00425 BUF->proto == UIP_PROTO_ICMP &&
00426 ICMPBUF->type == ICMP_ECHO) {
00427 return UIP_FW_LOCAL;
00428 }
00429 #endif
00430
00431
00432
00433
00434 for(fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw) {
00435 if(fw->timer != 0 &&
00436 #if UIP_REASSEMBLY > 0
00437 fw->len == BUF->len &&
00438 fw->offset == BUF->ipoffset &&
00439 #endif
00440 fw->ipid == BUF->ipid &&
00441 uip_ipaddr_cmp(&fw->srcipaddr, &BUF->srcipaddr) &&
00442 uip_ipaddr_cmp(&fw->destipaddr, &BUF->destipaddr) &&
00443 #if notdef
00444 fw->payload[0] == BUF->srcport &&
00445 fw->payload[1] == BUF->destport &&
00446 #endif
00447 fw->proto == BUF->proto) {
00448
00449 return UIP_FW_FORWARDED;
00450 }
00451 }
00452
00453
00454
00455
00456
00457 if(BUF->ttl <= 1) {
00458
00459 if(uip_ipaddr_cmp(&BUF->destipaddr, &uip_broadcast_addr)) {
00460 return UIP_FW_LOCAL;
00461 }
00462 time_exceeded();
00463 }
00464
00465
00466 BUF->ttl = BUF->ttl - 1;
00467
00468
00469 if(BUF->ipchksum >= UIP_HTONS(0xffff - 0x0100)) {
00470 BUF->ipchksum = BUF->ipchksum + UIP_HTONS(0x0100) + 1;
00471 } else {
00472 BUF->ipchksum = BUF->ipchksum + UIP_HTONS(0x0100);
00473 }
00474
00475 if(uip_len > 0) {
00476 uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN];
00477 uip_fw_output();
00478 }
00479
00480 #if UIP_BROADCAST
00481 if(uip_ipaddr_cmp(&BUF->destipaddr, &uip_broadcast_addr)) {
00482 return UIP_FW_LOCAL;
00483 }
00484 #endif
00485
00486
00487
00488 return UIP_FW_FORWARDED;
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498 void
00499 uip_fw_register(struct uip_fw_netif *netif)
00500 {
00501 netif->next = netifs;
00502 netifs = netif;
00503 }
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515 void
00516 uip_fw_default(struct uip_fw_netif *netif)
00517 {
00518 defaultnetif = netif;
00519 }
00520
00521
00522
00523
00524
00525 void
00526 uip_fw_periodic(void)
00527 {
00528 struct fwcache_entry *fw;
00529 for(fw = fwcache; fw < &fwcache[FWCACHE_SIZE]; ++fw) {
00530 if(fw->timer > 0) {
00531 --fw->timer;
00532 }
00533 }
00534 }
00535
00536
00537