2 * Copyright (c) 2004, Swedish Institute of Computer Science.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * This file is part of the Contiki operating system.
32 * $Id: tcpip.c,v 1.28 2010/05/01 13:04:31 joxe Exp $
36 * Code for tunnelling uIP packets over the Rime mesh routing module
38 * \author Adam Dunkels <adam@sics.se>\author
39 * \author Mathilde Durvy <mdurvy@cisco.com> (IPv6 related code)
40 * \author Julien Abeille <jabeille@cisco.com> (IPv6 related code)
42 #include "contiki-net.h"
44 #include "net/uip-split.h"
49 #include "net/uip-nd6.h"
50 #include "net/uip-ds6.h"
56 #define PRINTF(...) printf(__VA_ARGS__)
57 #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])
58 #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])
61 #define PRINT6ADDR(addr)
66 void uip_log(char *msg
);
67 #define UIP_LOG(m) uip_log(m)
72 #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[UIP_LLIPH_LEN + uip_ext_len])
73 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
74 #define UIP_TCP_BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
76 #ifdef UIP_FALLBACK_INTERFACE
77 extern struct uip_fallback_interface UIP_FALLBACK_INTERFACE
;
82 process_event_t tcpip_event
;
84 process_event_t tcpip_icmp6_event
;
85 #endif /* UIP_CONF_ICMP6 */
87 /*static struct tcpip_event_args ev_args;*/
89 /*periodic check of active connections*/
90 static struct etimer periodic
;
92 #if UIP_CONF_IPV6 && UIP_CONF_IPV6_REASSEMBLY
93 /*timer for reassembly*/
94 extern struct etimer uip_reass_timer
;
99 * \internal Structure for holding a TCP port and a process ID.
106 static struct internal_state
{
107 struct listenport listenports
[UIP_LISTENPORTS
];
118 /* Called on IP packet output. */
121 static u8_t (* outputfunc
)(uip_lladdr_t
*a
);
124 tcpip_output(uip_lladdr_t
*a
)
127 if(outputfunc
!= NULL
) {
131 UIP_LOG("tcpip_output: Use tcpip_set_outputfunc() to set an output function");
136 tcpip_set_outputfunc(u8_t (*f
)(uip_lladdr_t
*))
142 static u8_t (* outputfunc
)(void);
146 if(outputfunc
!= NULL
) {
149 UIP_LOG("tcpip_output: Use tcpip_set_outputfunc() to set an output function");
154 tcpip_set_outputfunc(u8_t (*f
)(void))
160 #if UIP_CONF_IP_FORWARD
161 unsigned char tcpip_is_forwarding
; /* Forwarding right now? */
162 #endif /* UIP_CONF_IP_FORWARD */
164 PROCESS(tcpip_process
, "TCP/IP stack");
166 /*---------------------------------------------------------------------------*/
168 start_periodic_tcp_timer(void)
170 if(etimer_expired(&periodic
)) {
171 etimer_restart(&periodic
);
174 /*---------------------------------------------------------------------------*/
176 check_for_tcp_syn(void)
178 /* This is a hack that is needed to start the periodic TCP timer if
179 an incoming packet contains a SYN: since uIP does not inform the
180 application if a SYN arrives, we have no other way of starting
181 this timer. This function is called for every incoming IP packet
182 to check for such SYNs. */
184 if(UIP_IP_BUF
->proto
== UIP_PROTO_TCP
&&
185 (UIP_TCP_BUF
->flags
& TCP_SYN
) == TCP_SYN
) {
186 start_periodic_tcp_timer();
189 /*---------------------------------------------------------------------------*/
193 #if UIP_CONF_IP_FORWARD
195 tcpip_is_forwarding
= 1;
196 if(uip_fw_forward() == UIP_FW_LOCAL
) {
197 tcpip_is_forwarding
= 0;
201 #if UIP_CONF_TCP_SPLIT
203 #else /* UIP_CONF_TCP_SPLIT */
207 PRINTF("tcpip packet_input forward output len %d\n", uip_len
);
210 #endif /* UIP_CONF_TCP_SPLIT */
213 tcpip_is_forwarding
= 0;
215 #else /* UIP_CONF_IP_FORWARD */
220 #if UIP_CONF_TCP_SPLIT
222 #else /* UIP_CONF_TCP_SPLIT */
226 PRINTF("tcpip packet_input output len %d\n", uip_len
);
229 #endif /* UIP_CONF_TCP_SPLIT */
232 #endif /* UIP_CONF_IP_FORWARD */
234 /*---------------------------------------------------------------------------*/
238 tcp_connect(uip_ipaddr_t
*ripaddr
, u16_t port
, void *appstate
)
242 c
= uip_connect(ripaddr
, port
);
247 c
->appstate
.p
= PROCESS_CURRENT();
248 c
->appstate
.state
= appstate
;
254 #endif /* UIP_ACTIVE_OPEN */
255 /*---------------------------------------------------------------------------*/
257 tcp_unlisten(u16_t port
)
259 static unsigned char i
;
260 struct listenport
*l
;
263 for(i
= 0; i
< UIP_LISTENPORTS
; ++i
) {
264 if(l
->port
== port
&&
265 l
->p
== PROCESS_CURRENT()) {
273 /*---------------------------------------------------------------------------*/
275 tcp_listen(u16_t port
)
277 static unsigned char i
;
278 struct listenport
*l
;
281 for(i
= 0; i
< UIP_LISTENPORTS
; ++i
) {
284 l
->p
= PROCESS_CURRENT();
291 /*---------------------------------------------------------------------------*/
293 tcp_attach(struct uip_conn
*conn
,
296 register uip_tcp_appstate_t
*s
;
299 s
->p
= PROCESS_CURRENT();
304 /*---------------------------------------------------------------------------*/
307 udp_attach(struct uip_udp_conn
*conn
,
310 register uip_udp_appstate_t
*s
;
313 s
->p
= PROCESS_CURRENT();
316 /*---------------------------------------------------------------------------*/
317 struct uip_udp_conn
*
318 udp_new(const uip_ipaddr_t
*ripaddr
, u16_t port
, void *appstate
)
320 struct uip_udp_conn
*c
;
321 uip_udp_appstate_t
*s
;
323 c
= uip_udp_new(ripaddr
, port
);
329 s
->p
= PROCESS_CURRENT();
334 /*---------------------------------------------------------------------------*/
335 struct uip_udp_conn
*
336 udp_broadcast_new(u16_t port
, void *appstate
)
339 struct uip_udp_conn
*conn
;
342 uip_create_linklocal_allnodes_mcast(&addr
);
344 uip_ipaddr(&addr
, 255,255,255,255);
345 #endif /* UIP_CONF_IPV6 */
346 conn
= udp_new(&addr
, port
, appstate
);
348 udp_bind(conn
, port
);
353 /*---------------------------------------------------------------------------*/
356 icmp6_new(void *appstate
) {
357 if(uip_icmp6_conns
.appstate
.p
== PROCESS_NONE
) {
358 uip_icmp6_conns
.appstate
.p
= PROCESS_CURRENT();
359 uip_icmp6_conns
.appstate
.state
= appstate
;
366 tcpip_icmp6_call(u8_t type
)
368 if(uip_icmp6_conns
.appstate
.p
!= PROCESS_NONE
) {
369 /* XXX: This is a hack that needs to be updated. Passing a pointer (&type)
370 like this only works with process_post_synch. */
371 process_post_synch(uip_icmp6_conns
.appstate
.p
, tcpip_icmp6_event
, &type
);
375 #endif /* UIP_CONF_ICMP6 */
376 /*---------------------------------------------------------------------------*/
378 eventhandler(process_event_t ev
, process_data_t data
)
381 static unsigned char i
;
382 register struct listenport
*l
;
387 case PROCESS_EVENT_EXITED
:
388 /* This is the event we get if a process has exited. We go through
389 the TCP/IP tables to see if this process had any open
390 connections or listening TCP ports. If so, we'll close those
393 p
= (struct process
*)data
;
396 for(i
= 0; i
< UIP_LISTENPORTS
; ++i
) {
398 uip_unlisten(l
->port
);
406 register struct uip_conn
*cptr
;
408 for(cptr
= &uip_conns
[0]; cptr
< &uip_conns
[UIP_CONNS
]; ++cptr
) {
409 if(cptr
->appstate
.p
== p
) {
410 cptr
->appstate
.p
= PROCESS_NONE
;
411 cptr
->tcpstateflags
= UIP_CLOSED
;
420 register struct uip_udp_conn
*cptr
;
421 for(cptr
= &uip_udp_conns
[0];
422 cptr
< &uip_udp_conns
[UIP_UDP_CONNS
]; ++cptr
) {
423 if(cptr
->appstate
.p
== p
) {
432 case PROCESS_EVENT_TIMER
:
433 /* We get this event if one of our timers have expired. */
435 /* Check the clock so see if we should call the periodic uIP
437 if(data
== &periodic
&&
438 etimer_expired(&periodic
)) {
440 for(i
= 0; i
< UIP_CONNS
; ++i
) {
441 if(uip_conn_active(i
)) {
442 /* Only restart the timer if there are active
444 etimer_restart(&periodic
);
450 PRINTF("tcpip_output from periodic len %d\n", uip_len
);
452 PRINTF("tcpip_output after periodic len %d\n", uip_len
);
454 #endif /* UIP_CONF_IPV6 */
458 #if UIP_CONF_IP_FORWARD
460 #endif /* UIP_CONF_IP_FORWARD */
464 #if UIP_CONF_IPV6_REASSEMBLY
466 * check the timer for reassembly
468 if(data
== &uip_reass_timer
&&
469 etimer_expired(&uip_reass_timer
)) {
473 #endif /* UIP_CONF_IPV6_REASSEMBLY */
475 * check the different timers for neighbor discovery and
476 * stateless autoconfiguration
478 /*if(data == &uip_nd6_timer_periodic &&
479 etimer_expired(&uip_nd6_timer_periodic)) {
484 if(data
== &uip_ds6_timer_rs
&&
485 etimer_expired(&uip_ds6_timer_rs
)){
489 #endif /* !UIP_CONF_ROUTER */
490 if(data
== &uip_ds6_timer_periodic
&&
491 etimer_expired(&uip_ds6_timer_periodic
)){
495 #endif /* UIP_CONF_IPV6 */
505 #else /* UIP_CONF_IPV6 */
507 PRINTF("tcpip_output from tcp poll len %d\n", uip_len
);
510 #endif /* UIP_CONF_IPV6 */
511 /* Start the periodic polling, if it isn't already active. */
512 start_periodic_tcp_timer();
519 uip_udp_periodic_conn(data
);
536 /*---------------------------------------------------------------------------*/
540 process_post_synch(&tcpip_process
, PACKET_INPUT
, NULL
);
544 #endif /*UIP_CONF_IPV6*/
546 /*---------------------------------------------------------------------------*/
549 tcpip_ipv6_output(void)
551 uip_ds6_nbr_t
*nbr
= NULL
;
552 uip_ipaddr_t
* nexthop
;
557 if(uip_len
> UIP_LINK_MTU
){
558 UIP_LOG("tcpip_ipv6_output: Packet to big");
562 if(uip_is_addr_unspecified(&UIP_IP_BUF
->destipaddr
)){
563 UIP_LOG("tcpip_ipv6_output: Destination address unspecified");
567 if(!uip_is_addr_mcast(&UIP_IP_BUF
->destipaddr
)) {
568 /* Next hop determination */
570 if(uip_ds6_is_addr_onlink(&UIP_IP_BUF
->destipaddr
)){
571 nexthop
= &UIP_IP_BUF
->destipaddr
;
573 uip_ds6_route_t
* locrt
;
574 locrt
= uip_ds6_route_lookup(&UIP_IP_BUF
->destipaddr
);
576 if((nexthop
= uip_ds6_defrt_choose()) == NULL
) {
577 #ifdef UIP_FALLBACK_INTERFACE
578 UIP_FALLBACK_INTERFACE
.output();
580 PRINTF("tcpip_ipv6_output: Destination off-link but no route\n");
586 nexthop
= &locrt
->nexthop
;
589 /* end of next hop determination */
590 if((nbr
= uip_ds6_nbr_lookup(nexthop
)) == NULL
) {
591 if((nbr
= uip_ds6_nbr_add(nexthop
, NULL
, 0, NBR_INCOMPLETE
)) == NULL
) {
595 #if UIP_CONF_IPV6_QUEUE_PKT
596 /* copy outgoing pkt in the queuing buffer for later transmmit */
597 memcpy(nbr
->queue_buf
, UIP_IP_BUF
, uip_len
);
598 nbr
->queue_buf_len
= uip_len
;
601 * "If the source address of the packet prompting the solicitation is the
602 * same as one of the addresses assigned to the outgoing interface, that
603 * address SHOULD be placed in the IP Source Address of the outgoing
604 * solicitation. Otherwise, any one of the addresses assigned to the
605 * interface should be used."*/
606 if(uip_ds6_is_my_addr(&UIP_IP_BUF
->srcipaddr
)){
607 uip_nd6_ns_output(&UIP_IP_BUF
->srcipaddr
, NULL
, &nbr
->ipaddr
);
609 uip_nd6_ns_output(NULL
, NULL
, &nbr
->ipaddr
);
612 stimer_set(&(nbr
->sendns
), uip_ds6_if
.retrans_timer
/ 1000);
616 if (nbr
->state
== NBR_INCOMPLETE
){
617 PRINTF("tcpip_ipv6_output: nbr cache entry incomplete\n");
618 #if UIP_CONF_IPV6_QUEUE_PKT
619 /* copy outgoing pkt in the queuing buffer for later transmmit and set
620 the destination nbr to nbr */
621 memcpy(nbr
->queue_buf
, UIP_IP_BUF
, uip_len
);
622 nbr
->queue_buf_len
= uip_len
;
624 #endif /*UIP_CONF_IPV6_QUEUE_PKT*/
627 /* if running NUD (nbc->state == STALE, DELAY, or PROBE ) keep
628 sending in parallel see rfc 4861 Node behavior in section 7.7.3*/
630 if (nbr
->state
== NBR_STALE
){
631 nbr
->state
= NBR_DELAY
;
632 stimer_set(&(nbr
->reachable
),
633 UIP_ND6_DELAY_FIRST_PROBE_TIME
);
635 PRINTF("tcpip_ipv6_output: nbr cache entry stale moving to delay\n");
638 stimer_set(&(nbr
->sendns
),
639 uip_ds6_if
.retrans_timer
/ 1000);
641 tcpip_output(&(nbr
->lladdr
));
644 #if UIP_CONF_IPV6_QUEUE_PKT
645 /* Send the queued packets from here, may not be 100% perfect though.
646 * This happens in a few cases, for example when instead of receiving a
647 * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves
648 *to STALE, and you must both send a NA and the queued packet
650 if(nbr
->queue_buf_len
!= 0) {
651 uip_len
= nbr
->queue_buf_len
;
652 memcpy(UIP_IP_BUF
, nbr
->queue_buf
, uip_len
);
653 nbr
->queue_buf_len
= 0;
654 tcpip_output(&(nbr
->lladdr
));
656 #endif /*UIP_CONF_IPV6_QUEUE_PKT*/
663 /*multicast IP destination address */
670 /*---------------------------------------------------------------------------*/
673 tcpip_poll_udp(struct uip_udp_conn
*conn
)
675 process_post(&tcpip_process
, UDP_POLL
, conn
);
678 /*---------------------------------------------------------------------------*/
681 tcpip_poll_tcp(struct uip_conn
*conn
)
683 process_post(&tcpip_process
, TCP_POLL
, conn
);
686 /*---------------------------------------------------------------------------*/
690 register uip_udp_appstate_t
*ts
;
693 if(uip_conn
!= NULL
) {
694 ts
= &uip_conn
->appstate
;
696 ts
= &uip_udp_conn
->appstate
;
699 ts
= &uip_conn
->appstate
;
704 static unsigned char i
;
705 register struct listenport
*l
;
707 /* If this is a connection request for a listening port, we must
708 mark the connection with the right process ID. */
709 if(uip_connected()) {
710 l
= &s
.listenports
[0];
711 for(i
= 0; i
< UIP_LISTENPORTS
; ++i
) {
712 if(l
->port
== uip_conn
->lport
&&
713 l
->p
!= PROCESS_NONE
) {
721 /* Start the periodic polling, if it isn't already active. */
722 start_periodic_tcp_timer();
728 process_post_synch(ts
->p
, tcpip_event
, ts
->state
);
731 /*---------------------------------------------------------------------------*/
732 PROCESS_THREAD(tcpip_process
, ev
, data
)
738 static unsigned char i
;
740 for(i
= 0; i
< UIP_LISTENPORTS
; ++i
) {
741 s
.listenports
[i
].port
= 0;
743 s
.p
= PROCESS_CURRENT();
747 tcpip_event
= process_alloc_event();
749 tcpip_icmp6_event
= process_alloc_event();
750 #endif /* UIP_CONF_ICMP6 */
751 etimer_set(&periodic
, CLOCK_SECOND
/ 2);
754 #ifdef UIP_FALLBACK_INTERFACE
755 UIP_FALLBACK_INTERFACE
.init();
757 /* initialize RPL if configured for using RPL */
758 #if UIP_CONF_IPV6_RPL
760 #endif /* UIP_CONF_IPV6_RPL */
764 eventhandler(ev
, data
);
769 /*---------------------------------------------------------------------------*/