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 #include "contiki-net.h"
00043
00044 #include "net/uip-split.h"
00045
00046 #include "net/uip-packetqueue.h"
00047
00048 #include <string.h>
00049
00050 #if UIP_CONF_IPV6
00051 #include "net/uip-nd6.h"
00052 #include "net/uip-ds6.h"
00053 #endif
00054
00055 #define DEBUG 0
00056 #if DEBUG
00057 #include <stdio.h>
00058 #define PRINTF(...) printf(__VA_ARGS__)
00059 #define PRINT6ADDR(addr) PRINTF(" %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x ", ((u8_t *)addr)[0], ((u8_t *)addr)[1], ((u8_t *)addr)[2], ((u8_t *)addr)[3], ((u8_t *)addr)[4], ((u8_t *)addr)[5], ((u8_t *)addr)[6], ((u8_t *)addr)[7], ((u8_t *)addr)[8], ((u8_t *)addr)[9], ((u8_t *)addr)[10], ((u8_t *)addr)[11], ((u8_t *)addr)[12], ((u8_t *)addr)[13], ((u8_t *)addr)[14], ((u8_t *)addr)[15])
00060 #define PRINTLLADDR(lladdr) PRINTF(" %02x:%02x:%02x:%02x:%02x:%02x ",lladdr->addr[0], lladdr->addr[1], lladdr->addr[2], lladdr->addr[3],lladdr->addr[4], lladdr->addr[5])
00061 #else
00062 #define PRINTF(...)
00063 #define PRINT6ADDR(addr)
00064 #endif
00065
00066 #if UIP_LOGGING
00067 #include <stdio.h>
00068 void uip_log(char *msg);
00069 #define UIP_LOG(m) uip_log(m)
00070 #else
00071 #define UIP_LOG(m)
00072 #endif
00073
00074 #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[UIP_LLIPH_LEN + uip_ext_len])
00075 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
00076 #define UIP_TCP_BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
00077
00078 #ifdef UIP_FALLBACK_INTERFACE
00079 extern struct uip_fallback_interface UIP_FALLBACK_INTERFACE;
00080 #endif
00081 #if UIP_CONF_IPV6_RPL
00082 void rpl_init(void);
00083 #endif
00084 process_event_t tcpip_event;
00085 #if UIP_CONF_ICMP6
00086 process_event_t tcpip_icmp6_event;
00087 #endif
00088
00089
00090
00091
00092 static struct etimer periodic;
00093
00094 #if UIP_CONF_IPV6 && UIP_CONF_IPV6_REASSEMBLY
00095
00096 extern struct etimer uip_reass_timer;
00097 #endif
00098
00099 #if UIP_TCP
00100
00101
00102
00103 struct listenport {
00104 u16_t port;
00105 struct process *p;
00106 };
00107
00108 static struct internal_state {
00109 struct listenport listenports[UIP_LISTENPORTS];
00110 struct process *p;
00111 } s;
00112 #endif
00113
00114 enum {
00115 TCP_POLL,
00116 UDP_POLL,
00117 PACKET_INPUT
00118 };
00119
00120
00121 #if UIP_CONF_IPV6
00122
00123 static u8_t (* outputfunc)(uip_lladdr_t *a);
00124
00125 u8_t
00126 tcpip_output(uip_lladdr_t *a)
00127 {
00128 int ret;
00129 if(outputfunc != NULL) {
00130 ret = outputfunc(a);
00131 return ret;
00132 }
00133 UIP_LOG("tcpip_output: Use tcpip_set_outputfunc() to set an output function");
00134 return 0;
00135 }
00136
00137 void
00138 tcpip_set_outputfunc(u8_t (*f)(uip_lladdr_t *))
00139 {
00140 outputfunc = f;
00141 }
00142 #else
00143
00144 static u8_t (* outputfunc)(void);
00145 u8_t
00146 tcpip_output(void)
00147 {
00148 if(outputfunc != NULL) {
00149 return outputfunc();
00150 }
00151 UIP_LOG("tcpip_output: Use tcpip_set_outputfunc() to set an output function");
00152 return 0;
00153 }
00154
00155 void
00156 tcpip_set_outputfunc(u8_t (*f)(void))
00157 {
00158 outputfunc = f;
00159 }
00160 #endif
00161
00162 #if UIP_CONF_IP_FORWARD
00163 unsigned char tcpip_is_forwarding;
00164 #endif
00165
00166 PROCESS(tcpip_process, "TCP/IP stack");
00167
00168
00169 static void
00170 start_periodic_tcp_timer(void)
00171 {
00172 if(etimer_expired(&periodic)) {
00173 etimer_restart(&periodic);
00174 }
00175 }
00176
00177 static void
00178 check_for_tcp_syn(void)
00179 {
00180
00181
00182
00183
00184
00185 #define TCP_SYN 0x02
00186 if(UIP_IP_BUF->proto == UIP_PROTO_TCP &&
00187 (UIP_TCP_BUF->flags & TCP_SYN) == TCP_SYN) {
00188 start_periodic_tcp_timer();
00189 }
00190 }
00191
00192 static void
00193 packet_input(void)
00194 {
00195 #if UIP_CONF_IP_FORWARD
00196 if(uip_len > 0) {
00197 tcpip_is_forwarding = 1;
00198 if(uip_fw_forward() == UIP_FW_LOCAL) {
00199 tcpip_is_forwarding = 0;
00200 check_for_tcp_syn();
00201 uip_input();
00202 if(uip_len > 0) {
00203 #if UIP_CONF_TCP_SPLIT
00204 uip_split_output();
00205 #else
00206 #if UIP_CONF_IPV6
00207 tcpip_ipv6_output();
00208 #else
00209 PRINTF("tcpip packet_input forward output len %d\n", uip_len);
00210 tcpip_output();
00211 #endif
00212 #endif
00213 }
00214 }
00215 tcpip_is_forwarding = 0;
00216 }
00217 #else
00218 if(uip_len > 0) {
00219 check_for_tcp_syn();
00220 uip_input();
00221 if(uip_len > 0) {
00222 #if UIP_CONF_TCP_SPLIT
00223 uip_split_output();
00224 #else
00225 #if UIP_CONF_IPV6
00226 tcpip_ipv6_output();
00227 #else
00228 PRINTF("tcpip packet_input output len %d\n", uip_len);
00229 tcpip_output();
00230 #endif
00231 #endif
00232 }
00233 }
00234 #endif
00235 }
00236
00237 #if UIP_TCP
00238 #if UIP_ACTIVE_OPEN
00239 struct uip_conn *
00240 tcp_connect(uip_ipaddr_t *ripaddr, u16_t port, void *appstate)
00241 {
00242 struct uip_conn *c;
00243
00244 c = uip_connect(ripaddr, port);
00245 if(c == NULL) {
00246 return NULL;
00247 }
00248
00249 c->appstate.p = PROCESS_CURRENT();
00250 c->appstate.state = appstate;
00251
00252 tcpip_poll_tcp(c);
00253
00254 return c;
00255 }
00256 #endif
00257
00258 void
00259 tcp_unlisten(u16_t port)
00260 {
00261 static unsigned char i;
00262 struct listenport *l;
00263
00264 l = s.listenports;
00265 for(i = 0; i < UIP_LISTENPORTS; ++i) {
00266 if(l->port == port &&
00267 l->p == PROCESS_CURRENT()) {
00268 l->port = 0;
00269 uip_unlisten(port);
00270 break;
00271 }
00272 ++l;
00273 }
00274 }
00275
00276 void
00277 tcp_listen(u16_t port)
00278 {
00279 static unsigned char i;
00280 struct listenport *l;
00281
00282 l = s.listenports;
00283 for(i = 0; i < UIP_LISTENPORTS; ++i) {
00284 if(l->port == 0) {
00285 l->port = port;
00286 l->p = PROCESS_CURRENT();
00287 uip_listen(port);
00288 break;
00289 }
00290 ++l;
00291 }
00292 }
00293
00294 void
00295 tcp_attach(struct uip_conn *conn,
00296 void *appstate)
00297 {
00298 register uip_tcp_appstate_t *s;
00299
00300 s = &conn->appstate;
00301 s->p = PROCESS_CURRENT();
00302 s->state = appstate;
00303 }
00304
00305 #endif
00306
00307 #if UIP_UDP
00308 void
00309 udp_attach(struct uip_udp_conn *conn,
00310 void *appstate)
00311 {
00312 register uip_udp_appstate_t *s;
00313
00314 s = &conn->appstate;
00315 s->p = PROCESS_CURRENT();
00316 s->state = appstate;
00317 }
00318
00319 struct uip_udp_conn *
00320 udp_new(const uip_ipaddr_t *ripaddr, u16_t port, void *appstate)
00321 {
00322 struct uip_udp_conn *c;
00323 uip_udp_appstate_t *s;
00324
00325 c = uip_udp_new(ripaddr, port);
00326 if(c == NULL) {
00327 return NULL;
00328 }
00329
00330 s = &c->appstate;
00331 s->p = PROCESS_CURRENT();
00332 s->state = appstate;
00333
00334 return c;
00335 }
00336
00337 struct uip_udp_conn *
00338 udp_broadcast_new(u16_t port, void *appstate)
00339 {
00340 uip_ipaddr_t addr;
00341 struct uip_udp_conn *conn;
00342
00343 #if UIP_CONF_IPV6
00344 uip_create_linklocal_allnodes_mcast(&addr);
00345 #else
00346 uip_ipaddr(&addr, 255,255,255,255);
00347 #endif
00348 conn = udp_new(&addr, port, appstate);
00349 if(conn != NULL) {
00350 udp_bind(conn, port);
00351 }
00352 return conn;
00353 }
00354 #endif
00355
00356 #if UIP_CONF_ICMP6
00357 u8_t
00358 icmp6_new(void *appstate) {
00359 if(uip_icmp6_conns.appstate.p == PROCESS_NONE) {
00360 uip_icmp6_conns.appstate.p = PROCESS_CURRENT();
00361 uip_icmp6_conns.appstate.state = appstate;
00362 return 0;
00363 }
00364 return 1;
00365 }
00366
00367 void
00368 tcpip_icmp6_call(u8_t type)
00369 {
00370 if(uip_icmp6_conns.appstate.p != PROCESS_NONE) {
00371
00372
00373 process_post_synch(uip_icmp6_conns.appstate.p, tcpip_icmp6_event, &type);
00374 }
00375 return;
00376 }
00377 #endif
00378
00379 static void
00380 eventhandler(process_event_t ev, process_data_t data)
00381 {
00382 #if UIP_TCP
00383 static unsigned char i;
00384 register struct listenport *l;
00385 #endif
00386 struct process *p;
00387
00388 switch(ev) {
00389 case PROCESS_EVENT_EXITED:
00390
00391
00392
00393
00394
00395 p = (struct process *)data;
00396 #if UIP_TCP
00397 l = s.listenports;
00398 for(i = 0; i < UIP_LISTENPORTS; ++i) {
00399 if(l->p == p) {
00400 uip_unlisten(l->port);
00401 l->port = 0;
00402 l->p = PROCESS_NONE;
00403 }
00404 ++l;
00405 }
00406
00407 {
00408 register struct uip_conn *cptr;
00409
00410 for(cptr = &uip_conns[0]; cptr < &uip_conns[UIP_CONNS]; ++cptr) {
00411 if(cptr->appstate.p == p) {
00412 cptr->appstate.p = PROCESS_NONE;
00413 cptr->tcpstateflags = UIP_CLOSED;
00414 }
00415
00416 }
00417
00418 }
00419 #endif
00420 #if UIP_UDP
00421 {
00422 register struct uip_udp_conn *cptr;
00423 for(cptr = &uip_udp_conns[0];
00424 cptr < &uip_udp_conns[UIP_UDP_CONNS]; ++cptr) {
00425 if(cptr->appstate.p == p) {
00426 cptr->lport = 0;
00427 }
00428 }
00429
00430 }
00431 #endif
00432 break;
00433
00434 case PROCESS_EVENT_TIMER:
00435
00436 {
00437
00438
00439 if(data == &periodic &&
00440 etimer_expired(&periodic)) {
00441 #if UIP_TCP
00442 for(i = 0; i < UIP_CONNS; ++i) {
00443 if(uip_conn_active(i)) {
00444
00445
00446 etimer_restart(&periodic);
00447 uip_periodic(i);
00448 #if UIP_CONF_IPV6
00449 tcpip_ipv6_output();
00450 #else
00451 if(uip_len > 0) {
00452 PRINTF("tcpip_output from periodic len %d\n", uip_len);
00453 tcpip_output();
00454 PRINTF("tcpip_output after periodic len %d\n", uip_len);
00455 }
00456 #endif
00457 }
00458 }
00459 #endif
00460 #if UIP_CONF_IP_FORWARD
00461 uip_fw_periodic();
00462 #endif
00463 }
00464
00465 #if UIP_CONF_IPV6
00466 #if UIP_CONF_IPV6_REASSEMBLY
00467
00468
00469
00470 if(data == &uip_reass_timer &&
00471 etimer_expired(&uip_reass_timer)) {
00472 uip_reass_over();
00473 tcpip_ipv6_output();
00474 }
00475 #endif
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485 #if !UIP_CONF_ROUTER
00486 if(data == &uip_ds6_timer_rs &&
00487 etimer_expired(&uip_ds6_timer_rs)){
00488 uip_ds6_send_rs();
00489 tcpip_ipv6_output();
00490 }
00491 #endif
00492 if(data == &uip_ds6_timer_periodic &&
00493 etimer_expired(&uip_ds6_timer_periodic)){
00494 uip_ds6_periodic();
00495 tcpip_ipv6_output();
00496 }
00497 #endif
00498 }
00499 break;
00500
00501 #if UIP_TCP
00502 case TCP_POLL:
00503 if(data != NULL) {
00504 uip_poll_conn(data);
00505 #if UIP_CONF_IPV6
00506 tcpip_ipv6_output();
00507 #else
00508 if(uip_len > 0) {
00509 PRINTF("tcpip_output from tcp poll len %d\n", uip_len);
00510 tcpip_output();
00511 }
00512 #endif
00513
00514 start_periodic_tcp_timer();
00515 }
00516 break;
00517 #endif
00518 #if UIP_UDP
00519 case UDP_POLL:
00520 if(data != NULL) {
00521 uip_udp_periodic_conn(data);
00522 #if UIP_CONF_IPV6
00523 tcpip_ipv6_output();
00524 #else
00525 if(uip_len > 0) {
00526 tcpip_output();
00527 }
00528 #endif
00529 }
00530 break;
00531 #endif
00532
00533 case PACKET_INPUT:
00534 packet_input();
00535 break;
00536 };
00537 }
00538
00539 void
00540 tcpip_input(void)
00541 {
00542 process_post_synch(&tcpip_process, PACKET_INPUT, NULL);
00543 uip_len = 0;
00544 #if UIP_CONF_IPV6
00545 uip_ext_len = 0;
00546 #endif
00547 }
00548
00549 #if UIP_CONF_IPV6
00550 void
00551 tcpip_ipv6_output(void)
00552 {
00553 uip_ds6_nbr_t *nbr = NULL;
00554 uip_ipaddr_t* nexthop;
00555
00556 if(uip_len == 0) {
00557 return;
00558 }
00559
00560 if(uip_len > UIP_LINK_MTU) {
00561 UIP_LOG("tcpip_ipv6_output: Packet to big");
00562 uip_len = 0;
00563 return;
00564 }
00565 if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){
00566 UIP_LOG("tcpip_ipv6_output: Destination address unspecified");
00567 uip_len = 0;
00568 return;
00569 }
00570 if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
00571
00572 nbr = NULL;
00573 if(uip_ds6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){
00574 nexthop = &UIP_IP_BUF->destipaddr;
00575 } else {
00576 uip_ds6_route_t* locrt;
00577 locrt = uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr);
00578 if(locrt == NULL) {
00579 if((nexthop = uip_ds6_defrt_choose()) == NULL) {
00580 #ifdef UIP_FALLBACK_INTERFACE
00581 UIP_FALLBACK_INTERFACE.output();
00582 #else
00583 PRINTF("tcpip_ipv6_output: Destination off-link but no route\n");
00584 #endif
00585 uip_len = 0;
00586 return;
00587 }
00588 } else {
00589 nexthop = &locrt->nexthop;
00590 }
00591 }
00592
00593 if((nbr = uip_ds6_nbr_lookup(nexthop)) == NULL) {
00594
00595 if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) {
00596
00597 uip_len = 0;
00598 return;
00599 } else {
00600 #if UIP_CONF_IPV6_QUEUE_PKT
00601
00602 if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) {
00603 memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len);
00604 uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
00605 }
00606 #endif
00607
00608
00609
00610
00611
00612
00613 if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)){
00614 uip_nd6_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbr->ipaddr);
00615 } else {
00616 uip_nd6_ns_output(NULL, NULL, &nbr->ipaddr);
00617 }
00618
00619 stimer_set(&(nbr->sendns), uip_ds6_if.retrans_timer / 1000);
00620 nbr->nscount = 1;
00621 }
00622 } else {
00623 if(nbr->state == NBR_INCOMPLETE) {
00624 PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n");
00625 #if UIP_CONF_IPV6_QUEUE_PKT
00626
00627
00628 if(uip_packetqueue_alloc(&nbr->packethandle, UIP_DS6_NBR_PACKET_LIFETIME) != NULL) {
00629 memcpy(uip_packetqueue_buf(&nbr->packethandle), UIP_IP_BUF, uip_len);
00630 uip_packetqueue_set_buflen(&nbr->packethandle, uip_len);
00631 }
00632
00633
00634 uip_len = 0;
00635 #endif
00636 return;
00637 }
00638
00639
00640
00641 if(nbr->state == NBR_STALE) {
00642 nbr->state = NBR_DELAY;
00643 stimer_set(&(nbr->reachable),
00644 UIP_ND6_DELAY_FIRST_PROBE_TIME);
00645 nbr->nscount = 0;
00646 PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n");
00647 }
00648
00649 stimer_set(&(nbr->sendns),
00650 uip_ds6_if.retrans_timer / 1000);
00651
00652 tcpip_output(&(nbr->lladdr));
00653
00654
00655 #if UIP_CONF_IPV6_QUEUE_PKT
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667 if(uip_packetqueue_buflen(&nbr->packethandle) != 0) {
00668 uip_len = uip_packetqueue_buflen(&nbr->packethandle);
00669 memcpy(UIP_IP_BUF, uip_packetqueue_buf(&nbr->packethandle), uip_len);
00670 uip_packetqueue_free(&nbr->packethandle);
00671 tcpip_output(&(nbr->lladdr));
00672 }
00673 #endif
00674
00675 uip_len = 0;
00676 return;
00677 }
00678 }
00679
00680
00681 tcpip_output(NULL);
00682 uip_len = 0;
00683 uip_ext_len = 0;
00684
00685 }
00686 #endif
00687
00688 #if UIP_UDP
00689 void
00690 tcpip_poll_udp(struct uip_udp_conn *conn)
00691 {
00692 process_post(&tcpip_process, UDP_POLL, conn);
00693 }
00694 #endif
00695
00696 #if UIP_TCP
00697 void
00698 tcpip_poll_tcp(struct uip_conn *conn)
00699 {
00700 process_post(&tcpip_process, TCP_POLL, conn);
00701 }
00702 #endif
00703
00704 void
00705 tcpip_uipcall(void)
00706 {
00707 register uip_udp_appstate_t *ts;
00708
00709 #if UIP_UDP
00710 if(uip_conn != NULL) {
00711 ts = &uip_conn->appstate;
00712 } else {
00713 ts = &uip_udp_conn->appstate;
00714 }
00715 #else
00716 ts = &uip_conn->appstate;
00717 #endif
00718
00719 #if UIP_TCP
00720 {
00721 static unsigned char i;
00722 register struct listenport *l;
00723
00724
00725
00726 if(uip_connected()) {
00727 l = &s.listenports[0];
00728 for(i = 0; i < UIP_LISTENPORTS; ++i) {
00729 if(l->port == uip_conn->lport &&
00730 l->p != PROCESS_NONE) {
00731 ts->p = l->p;
00732 ts->state = NULL;
00733 break;
00734 }
00735 ++l;
00736 }
00737
00738
00739 start_periodic_tcp_timer();
00740 }
00741 }
00742 #endif
00743
00744 if(ts->p != NULL) {
00745 process_post_synch(ts->p, tcpip_event, ts->state);
00746 }
00747 }
00748
00749 PROCESS_THREAD(tcpip_process, ev, data)
00750 {
00751 PROCESS_BEGIN();
00752
00753 #if UIP_TCP
00754 {
00755 static unsigned char i;
00756
00757 for(i = 0; i < UIP_LISTENPORTS; ++i) {
00758 s.listenports[i].port = 0;
00759 }
00760 s.p = PROCESS_CURRENT();
00761 }
00762 #endif
00763
00764 tcpip_event = process_alloc_event();
00765 #if UIP_CONF_ICMP6
00766 tcpip_icmp6_event = process_alloc_event();
00767 #endif
00768 etimer_set(&periodic, CLOCK_SECOND / 2);
00769
00770 uip_init();
00771 #ifdef UIP_FALLBACK_INTERFACE
00772 UIP_FALLBACK_INTERFACE.init();
00773 #endif
00774
00775 #if UIP_CONF_IPV6_RPL
00776 rpl_init();
00777 #endif
00778
00779 while(1) {
00780 PROCESS_YIELD();
00781 eventhandler(ev, data);
00782 }
00783
00784 PROCESS_END();
00785 }
00786