diff --git a/core/contiki-net.h b/core/contiki-net.h index 46de38425..be3855836 100644 --- a/core/contiki-net.h +++ b/core/contiki-net.h @@ -30,7 +30,7 @@ * * Author: Adam Dunkels * - * $Id: contiki-net.h,v 1.5 2007/11/18 01:19:31 oliverschmidt Exp $ + * $Id: contiki-net.h,v 1.6 2008/10/14 09:40:56 julienabeille Exp $ */ #ifndef __CONTIKI_NET_H__ #define __CONTIKI_NET_H__ @@ -38,7 +38,6 @@ #include "contiki.h" #include "net/tcpip.h" - #include "net/uip.h" #include "net/uip-fw.h" #include "net/uip-fw-drv.h" @@ -46,6 +45,11 @@ #include "net/uiplib.h" #include "net/uip-udp-packet.h" +#if UIP_CONF_IPV6 +#include "net/uip-icmp6.h" +#include "net/uip-netif.h" +#endif /* UIP_CONF_IPV6 */ + #include "net/resolv.h" #include "net/psock.h" diff --git a/core/net/rime/rimeaddr.c b/core/net/rime/rimeaddr.c index 8cccbd1a5..9c209199e 100644 --- a/core/net/rime/rimeaddr.c +++ b/core/net/rime/rimeaddr.c @@ -33,7 +33,7 @@ * * This file is part of the Contiki operating system. * - * $Id: rimeaddr.c,v 1.7 2008/04/01 13:10:22 nifi Exp $ + * $Id: rimeaddr.c,v 1.8 2008/10/14 09:40:56 julienabeille Exp $ */ /** @@ -46,21 +46,35 @@ #include "net/rime/rimeaddr.h" rimeaddr_t rimeaddr_node_addr; +#if RIMEADDR_SIZE == 2 const rimeaddr_t rimeaddr_null = { { 0, 0 } }; +#else /*RIMEADDR_SIZE == 2*/ +#if RIMEADDR_SIZE == 8 +const rimeaddr_t rimeaddr_null = { { 0, 0, 0, 0, 0, 0, 0, 0 } }; +#endif /*RIMEADDR_SIZE == 8*/ +#endif /*RIMEADDR_SIZE == 2*/ + /*---------------------------------------------------------------------------*/ void rimeaddr_copy(rimeaddr_t *dest, const rimeaddr_t *src) { - dest->u8[0] = src->u8[0]; - dest->u8[1] = src->u8[1]; + u8_t i; + for(i = 0; i < RIMEADDR_SIZE / 2; i++) { + dest->u16[i] = src->u16[i]; + } } /*---------------------------------------------------------------------------*/ int rimeaddr_cmp(const rimeaddr_t *addr1, const rimeaddr_t *addr2) { - return addr1->u8[0] == addr2->u8[0] && - addr1->u8[1] == addr2->u8[1]; + u8_t i; + for(i = 0; i < RIMEADDR_SIZE / 2; i++) { + if(addr1->u16[i] != addr2->u16[i]) { + return 0; + } + } + return 1; } /*---------------------------------------------------------------------------*/ void diff --git a/core/net/tcpip.c b/core/net/tcpip.c index fd7bc413e..1636188ba 100644 --- a/core/net/tcpip.c +++ b/core/net/tcpip.c @@ -28,19 +28,63 @@ * * This file is part of the Contiki operating system. * - * Author: Adam Dunkels * - * $Id: tcpip.c,v 1.12 2008/05/14 19:19:28 adamdunkels Exp $ + * $Id: tcpip.c,v 1.13 2008/10/14 09:40:56 julienabeille Exp $ + */ +/** + * \file + * Code for tunnelling uIP packets over the Rime mesh routing module + * + * \author Adam Dunkels \author + * \author Mathilde Durvy (IPv6 related code) + * \author Julien Abeille (IPv6 related code) */ - #include "contiki-net.h" #include "net/uip-split.h" #include +#if UIP_CONF_IPV6 +#include "net/uip-nd6.h" +#include "net/uip-netif.h" +#endif + +#define DEBUG 0 +#if DEBUG +#include +#define PRINTF(...) printf(__VA_ARGS__) +#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]) +#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]) +#else +#define PRINTF(...) +#define PRINT6ADDR(addr) +#endif + +#if UIP_LOGGING +#include +void uip_log(char *msg); +#define UIP_LOG(m) uip_log(m) +#else +#define UIP_LOG(m) +#endif + +#define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[UIP_LLIPH_LEN + uip_ext_len]) +#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) + process_event_t tcpip_event; +/*static struct tcpip_event_args ev_args;*/ + +/*periodic check of active connections*/ +static struct etimer periodic; + +#if UIP_CONF_IPV6 && UIP_CONF_IPV6_REASSEMBLY +/*timer for reassembly*/ +extern struct etimer uip_reass_timer; +#endif + +#if UIP_TCP /** * \internal Structure for holding a TCP port and a process ID. */ @@ -49,14 +93,11 @@ struct listenport { struct process *p; }; -/*static struct tcpip_event_args ev_args;*/ - -static struct etimer periodic; - static struct internal_state { struct listenport listenports[UIP_LISTENPORTS]; struct process *p; } s; +#endif enum { TCP_POLL, @@ -64,7 +105,12 @@ enum { PACKET_INPUT }; -u8_t (* tcpip_output)(void); /* Called on IP packet output. */ +/* Called on IP packet output. */ +#if UIP_CONF_IPV6 +u8_t (* tcpip_output)(uip_lladdr_t *); +#else +u8_t (* tcpip_output)(void); +#endif #if UIP_CONF_IP_FORWARD unsigned char tcpip_is_forwarding; /* Forwarding right now? */ @@ -84,9 +130,13 @@ packet_input(void) uip_input(); if(uip_len > 0) { #if UIP_CONF_TCP_SPLIT - uip_split_output(); + uip_split_output(); #else /* UIP_CONF_TCP_SPLIT */ - tcpip_output(); +#if UIP_CONF_IPV6 + tcpip_ipv6_output(); +#else + tcpip_output(); +#endif #endif /* UIP_CONF_TCP_SPLIT */ } } @@ -99,13 +149,22 @@ packet_input(void) #if UIP_CONF_TCP_SPLIT uip_split_output(); #else /* UIP_CONF_TCP_SPLIT */ +#if UIP_CONF_IPV6 + tcpip_ipv6_output(); +#else tcpip_output(); +#endif #endif /* UIP_CONF_TCP_SPLIT */ } } #endif /* UIP_CONF_IP_FORWARD */ } + /*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + +#if UIP_TCP + #if UIP_ACTIVE_OPEN struct uip_conn * tcp_connect(uip_ipaddr_t *ripaddr, u16_t port, void *appstate) @@ -172,7 +231,12 @@ tcp_attach(struct uip_conn *conn, s->p = PROCESS_CURRENT(); s->state = appstate; } + +#endif /* UIP_TCP */ + /*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ + #if UIP_UDP void udp_attach(struct uip_udp_conn *conn, @@ -217,111 +281,190 @@ udp_broadcast_new(u16_t port, void *appstate) return conn; } #endif /* UIP_UDP */ + /*---------------------------------------------------------------------------*/ +/*---------------------------------------------------------------------------*/ +#if UIP_CONF_ICMP6 +u8_t +icmp6_new(void *appstate) { + if(uip_icmp6_conns.appstate.p == PROCESS_NONE) { + uip_icmp6_conns.appstate.p = PROCESS_CURRENT(); + uip_icmp6_conns.appstate.state = appstate; + return 0; + } + return 1; +} + +void tcpip_icmp6_call(u8_t type) { + process_post_synch(uip_icmp6_conns.appstate.p, type, 0); + return; +} + +#endif /*UIP_CONF_ICMP6*/ +/*---------------------------------------------------------------------------*/ + static void eventhandler(process_event_t ev, process_data_t data) { +#if UIP_TCP static unsigned char i; register struct listenport *l; +#endif /*UIP_TCP*/ struct process *p; - + switch(ev) { - case PROCESS_EVENT_EXITED: - /* This is the event we get if a process has exited. We go through - the TCP/IP tables to see if this process had any open - connections or listening TCP ports. If so, we'll close those - connections. */ - p = (struct process *)data; - l = s.listenports; - for(i = 0; i < UIP_LISTENPORTS; ++i) { - if(l->p == p) { - uip_unlisten(l->port); - l->port = 0; - l->p = PROCESS_NONE; + case PROCESS_EVENT_EXITED: + /* This is the event we get if a process has exited. We go through + the TCP/IP tables to see if this process had any open + connections or listening TCP ports. If so, we'll close those + connections. */ + + p = (struct process *)data; +#if UIP_TCP + l = s.listenports; + for(i = 0; i < UIP_LISTENPORTS; ++i) { + if(l->p == p) { + uip_unlisten(l->port); + l->port = 0; + l->p = PROCESS_NONE; + } + ++l; } - ++l; - } - - { - register struct uip_conn *cptr; - - for(cptr = &uip_conns[0]; cptr < &uip_conns[UIP_CONNS]; ++cptr) { - if(cptr->appstate.p == p) { - cptr->appstate.p = PROCESS_NONE; - cptr->tcpstateflags = UIP_CLOSED; - } - + + { + register struct uip_conn *cptr; + + for(cptr = &uip_conns[0]; cptr < &uip_conns[UIP_CONNS]; ++cptr) { + if(cptr->appstate.p == p) { + cptr->appstate.p = PROCESS_NONE; + cptr->tcpstateflags = UIP_CLOSED; + } + + } + } - - } +#endif /* UIP_TCP */ #if UIP_UDP - { - register struct uip_udp_conn *cptr; - for(cptr = &uip_udp_conns[0]; - cptr < &uip_udp_conns[UIP_UDP_CONNS]; ++cptr) { - if(cptr->appstate.p == p) { - cptr->lport = 0; - } - } + { + register struct uip_udp_conn *cptr; + for(cptr = &uip_udp_conns[0]; + cptr < &uip_udp_conns[UIP_UDP_CONNS]; ++cptr) { + if(cptr->appstate.p == p) { + cptr->lport = 0; + } + } - } + } #endif /* UIP_UDP */ - break; + break; - case PROCESS_EVENT_TIMER: - /* We get this event if one of our timers have expired. */ - { - static unsigned char i; - - /* Check the clock so see if we should call the periodic uIP - processing. */ - if(etimer_expired(&periodic)) { - for(i = 0; i < UIP_CONNS; ++i) { - if(uip_conn_active(i)) { - /* Only restart the timer if there are active - connections. */ - etimer_restart(&periodic); - uip_periodic(i); - if(uip_len > 0) { - tcpip_output(); - } - } - } + case PROCESS_EVENT_TIMER: + /* We get this event if one of our timers have expired. */ + { + /* Check the clock so see if we should call the periodic uIP + processing. */ + if(data == &periodic && + etimer_expired(&periodic)) { +#if UIP_TCP + for(i = 0; i < UIP_CONNS; ++i) { + if(uip_conn_active(i)) { + /* Only restart the timer if there are active + connections. */ + etimer_restart(&periodic); + uip_periodic(i); +#if UIP_CONF_IPV6 + tcpip_ipv6_output(); +#else + if(uip_len > 0) { + tcpip_output(); + } +#endif /* UIP_CONF_IPV6 */ + } + } +#endif /* UIP_TCP */ #if UIP_CONF_IP_FORWARD - uip_fw_periodic(); + uip_fw_periodic(); #endif /* UIP_CONF_IP_FORWARD */ - } - } - break; - - case TCP_POLL: - if(data != NULL) { - uip_poll_conn(data); - if(uip_len > 0) { - tcpip_output(); - } + } + +#if UIP_CONF_IPV6 +#if UIP_CONF_IPV6_REASSEMBLY + /* + * check the timer for reassembly + */ + if(data == &uip_reass_timer && + etimer_expired(&uip_reass_timer)) { + uip_reass_over(); + tcpip_ipv6_output(); + } +#endif /* UIP_CONF_IPV6_REASSEMBLY */ + /* + * check the different timers for neighbor discovery and + * stateless autoconfiguration + */ + if(data == &uip_nd6_timer_periodic && + etimer_expired(&uip_nd6_timer_periodic)) { + uip_nd6_periodic(); + tcpip_ipv6_output(); + } + + if(data == &uip_netif_timer_dad && + etimer_expired(&uip_netif_timer_dad)){ + uip_netif_dad(); + tcpip_ipv6_output(); + } + + if(data == &uip_netif_timer_rs && + etimer_expired(&uip_netif_timer_rs)){ + uip_netif_send_rs(); + tcpip_ipv6_output(); + } - /* Start the periodic polling, if it isn't already active. */ - if(etimer_expired(&periodic)) { - etimer_restart(&periodic); + if(data == &uip_netif_timer_periodic && + etimer_expired(&uip_netif_timer_periodic)){ + uip_netif_periodic(); + } +#endif /* UIP_CONF_IPV6 */ } - - } - break; + break; + +#if UIP_TCP + case TCP_POLL: + if(data != NULL) { + uip_poll_conn(data); +#if UIP_CONF_IPV6 + tcpip_ipv6_output(); +#else + if(uip_len > 0) { + tcpip_output(); + } +#endif /* UIP_CONF_IPV6 */ + /* Start the periodic polling, if it isn't already active. */ + if(etimer_expired(&periodic)) { + etimer_restart(&periodic); + } + + } + break; +#endif /* UIP_TCP */ #if UIP_UDP - case UDP_POLL: - if(data != NULL) { - uip_udp_periodic_conn(data); - if(uip_len > 0) { - tcpip_output(); + case UDP_POLL: + if(data != NULL) { + uip_udp_periodic_conn(data); +#if UIP_CONF_IPV6 + tcpip_ipv6_output(); +#else + if(uip_len > 0) { + tcpip_output(); + } +#endif /* UIP_UDP */ } - } - break; + break; #endif /* UIP_UDP */ - case PACKET_INPUT: - packet_input(); - break; + case PACKET_INPUT: + packet_input(); + break; }; } /*---------------------------------------------------------------------------*/ @@ -330,8 +473,131 @@ tcpip_input(void) { process_post_synch(&tcpip_process, PACKET_INPUT, NULL); uip_len = 0; +#if UIP_CONF_IPV6 + uip_ext_len = 0; +#endif /*UIP_CONF_IPV6*/ } /*---------------------------------------------------------------------------*/ +#if UIP_CONF_IPV6 +void +tcpip_ipv6_output(void) +{ + struct uip_nd6_neighbor *nbc = NULL; + struct uip_nd6_defrouter *dr = NULL; + + if(uip_len == 0) + return; + + if(uip_len > UIP_LINK_MTU){ + UIP_LOG("tcpip_ipv6_output: Packet to big"); + uip_len = 0; + return; + } + if(uip_is_addr_unspecified(&UIP_IP_BUF->destipaddr)){ + UIP_LOG("tcpip_ipv6_output: Destination address unspecified"); + uip_len = 0; + return; + } + if(!uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) { + /*If destination is on link */ + if(uip_nd6_is_addr_onlink(&UIP_IP_BUF->destipaddr)){ + nbc = uip_nd6_nbrcache_lookup(&UIP_IP_BUF->destipaddr); + } else { + /*destination is not on link*/ + dr = uip_nd6_choose_defrouter(); + if(dr != NULL){ + nbc = dr->nb; + } else { + /* shall we send a icmp error message destination unreachable ?*/ + UIP_LOG("tcpip_ipv6_output: Destination off-link but no router"); + uip_len = 0; + return; + } + } + /* there are two cases where the entry logically does not exist: + * 1 it really does not exist. 2 it is in the NO_STATE state */ + if (nbc == NULL || nbc->state == NO_STATE) { + if (nbc == NULL) { + /* create neighbor cache entry, original packet is replaced by NS*/ + nbc = uip_nd6_nbrcache_add(&UIP_IP_BUF->destipaddr, NULL, 0, INCOMPLETE); + } else { + nbc->state = INCOMPLETE; + } +#if UIP_CONF_IPV6_QUEUE_PKT + /* copy outgoing pkt in the queuing buffer for later transmmit */ + memcpy(nbc->queue_buf, UIP_IP_BUF, uip_len); + nbc->queue_buf_len = uip_len; +#endif + /* RFC4861, 7.2.2: + * "If the source address of the packet prompting the solicitation is the + * same as one of the addresses assigned to the outgoing interface, that + * address SHOULD be placed in the IP Source Address of the outgoing + * solicitation. Otherwise, any one of the addresses assigned to the + * interface should be used."*/ + if(uip_netif_is_addr_my_unicast(&UIP_IP_BUF->srcipaddr)){ + uip_nd6_io_ns_output(&UIP_IP_BUF->srcipaddr, NULL, &nbc->ipaddr); + } else { + uip_nd6_io_ns_output(NULL, NULL, &nbc->ipaddr); + } + + timer_set(&(nbc->last_send), + uip_netif_physical_if.retrans_timer/1000*CLOCK_SECOND); + nbc->count_send = 1; + } else { + if (nbc->state == INCOMPLETE){ + PRINTF("tcpip_ipv6_output: neighbor cache entry incomplete\n"); +#if UIP_CONF_IPV6_QUEUE_PKT + /* copy outgoing pkt in the queuing buffer for later transmmit and set + the destination neighbor to nbc */ + memcpy(nbc->queue_buf, UIP_IP_BUF, uip_len); + nbc->queue_buf_len = uip_len; + uip_len = 0; +#endif /*UIP_CONF_IPV6_QUEUE_PKT*/ + return; + } + /* if running NUD (nbc->state == STALE, DELAY, or PROBE ) keep + sending in parallel see rfc 4861 Node behavior in section 7.7.3*/ + + if (nbc->state == STALE){ + nbc->state = DELAY; + timer_set(&(nbc->reachable), + UIP_ND6_DELAY_FIRST_PROBE_TIME*CLOCK_SECOND); + PRINTF("tcpip_ipv6_output: neighbor cache entry stale moving to delay\n"); + } + + timer_set(&(nbc->last_send), + uip_netif_physical_if.retrans_timer/1000*CLOCK_SECOND); + + tcpip_output(&(nbc->lladdr)); + + +#if UIP_CONF_IPV6_QUEUE_PKT + /* Send the queued packets from here, may not be 100% perfect though. + * This happens in a few cases, for example when instead of receiving a + * NA after sendiong a NS, you receive a NS with SLLAO: the entry moves + *to STALE, and you must both send a NA and the queued packet + */ + if(nbc->queue_buf_len != 0) { + uip_len = nbc->queue_buf_len; + memcpy(UIP_IP_BUF, nbc->queue_buf, uip_len); + nbc->queue_buf_len = 0; + tcpip_output(&(nbc->lladdr)); + } +#endif /*UIP_CONF_IPV6_QUEUE_PKT*/ + + uip_len = 0; + return; + } + } + + /*multicast IP detination address */ + tcpip_output(NULL); + uip_len = 0; + uip_ext_len = 0; + +} +#endif +/*---------------------------------------------------------------------------*/ #if UIP_UDP void tcpip_poll_udp(struct uip_udp_conn *conn) @@ -340,19 +606,19 @@ tcpip_poll_udp(struct uip_udp_conn *conn) } #endif /* UIP_UDP */ /*---------------------------------------------------------------------------*/ +#if UIP_TCP void tcpip_poll_tcp(struct uip_conn *conn) { process_post(&tcpip_process, TCP_POLL, conn); } +#endif /* UIP_TCP */ /*---------------------------------------------------------------------------*/ void tcpip_uipcall(void) { register uip_udp_appstate_t *ts; - static unsigned char i; - register struct listenport *l; - + #if UIP_UDP if(uip_conn != NULL) { ts = &uip_conn->appstate; @@ -363,16 +629,20 @@ tcpip_uipcall(void) ts = &uip_conn->appstate; #endif /* UIP_UDP */ +#if UIP_TCP + static unsigned char i; + register struct listenport *l; + /* If this is a connection request for a listening port, we must mark the connection with the right process ID. */ if(uip_connected()) { l = &s.listenports[0]; for(i = 0; i < UIP_LISTENPORTS; ++i) { if(l->port == uip_conn->lport && - l->p != PROCESS_NONE) { - ts->p = l->p; - ts->state = NULL; - break; + l->p != PROCESS_NONE) { + ts->p = l->p; + ts->state = NULL; + break; } ++l; } @@ -382,7 +652,8 @@ tcpip_uipcall(void) etimer_restart(&periodic); } } - +#endif + if(ts->p != NULL) { process_post_synch(ts->p, tcpip_event, ts->state); } @@ -390,14 +661,17 @@ tcpip_uipcall(void) /*---------------------------------------------------------------------------*/ PROCESS_THREAD(tcpip_process, ev, data) { - int i; - PROCESS_BEGIN(); - + +#if UIP_TCP + static unsigned char i; + for(i = 0; i < UIP_LISTENPORTS; ++i) { s.listenports[i].port = 0; } s.p = PROCESS_CURRENT(); +#endif + tcpip_event = process_alloc_event(); etimer_set(&periodic, CLOCK_SECOND/2); diff --git a/core/net/tcpip.h b/core/net/tcpip.h index 5ee3ffe72..afe451f62 100644 --- a/core/net/tcpip.h +++ b/core/net/tcpip.h @@ -24,10 +24,12 @@ /** * \file - * Header for the Contiki/uIP interface. - * \author - * Adam Dunkels + * Header for the Contiki/uIP interface. + * \author Adam Dunkels + * \author Mathilde Durvy (IPv6 related code) + * \author Julien Abeille (IPv6 related code) */ + /* * Copyright (c) 2004, Swedish Institute of Computer Science. * All rights reserved. @@ -60,7 +62,7 @@ * * Author: Adam Dunkels * - * $Id: tcpip.h,v 1.11 2008/03/29 15:19:25 oliverschmidt Exp $ + * $Id: tcpip.h,v 1.12 2008/10/14 09:40:56 julienabeille Exp $ */ #ifndef __TCPIP_H__ #define __TCPIP_H__ @@ -76,13 +78,14 @@ struct tcpip_uipstate { #define UIP_APPCALL tcpip_uipcall #define UIP_UDP_APPCALL tcpip_uipcall +#define UIP_ICMP6_APPCALL tcpip_icmp6_call + /*#define UIP_APPSTATE_SIZE sizeof(struct tcpip_uipstate)*/ typedef struct tcpip_uipstate uip_udp_appstate_t; typedef struct tcpip_uipstate uip_tcp_appstate_t; - +typedef struct tcpip_uipstate uip_icmp6_appstate_t; #include "net/uip.h" - void tcpip_uipcall(void); /** @@ -272,7 +275,36 @@ struct uip_udp_conn *udp_broadcast_new(u16_t port, void *appstate); CCIF void tcpip_poll_udp(struct uip_udp_conn *conn); /** @} */ + +/** + * \name ICMPv6 functions + * @{ + */ +#if UIP_CONF_ICMP6 +/** + * \brief register an ICMPv6 callback + * \return 0 if success, 1 if failure (one application already registered) + * + * This function just registers a process to be polled when + * an ICMPv6 message is received. + * If no application registers, some ICMPv6 packets will be + * processed by the "kernel" as usual (NS, NA, RS, RA, Echo request), + * others will be dropped. + * If an appplication registers here, it will be polled with a + * process_post_synch everytime an ICMPv6 packet is received. + */ +u8_t icmp6_new(void *appstate); + +/** + * This function is called at reception of an ICMPv6 packet + * If an application registered as an ICMPv6 listener (with + * icmp6_new), it will be called through a process_post_synch() + */ +void tcpip_icmp6_call(u8_t type); +#endif /*UIP_CONF_ICMP6*/ + +/** @} */ /** * The uIP event. * @@ -296,17 +328,36 @@ CCIF extern process_event_t tcpip_event; */ CCIF void tcpip_input(void); -/* - * This function is called on IP packet output. +/** + * \brief Output packet to layer 2 + * The eventual parameter is the MAC address of the destination. */ +#if UIP_CONF_IPV6 +extern u8_t (* tcpip_output)(uip_lladdr_t *); +#else extern u8_t (* tcpip_output)(void); -#define tcpip_set_outputfunc(outputfunc) tcpip_output = (outputfunc) +#endif + +/** + * \brief This function does address resolution and then calls tcpip_output + */ +#if UIP_CONF_IPV6 +void tcpip_ipv6_output(void); +#endif + +/** + * \brief Is forwarding generally enabled? + */ +extern unsigned char tcpip_do_forwarding; /* * Are we at the moment forwarding the contents of uip_buf[]? */ extern unsigned char tcpip_is_forwarding; +#define tcpip_set_outputfunc(outputfunc) tcpip_output = (outputfunc) +#define tcpip_set_forwarding(forwarding) tcpip_do_forwarding = (forwarding) + /** @} */ PROCESS_NAME(tcpip_process); diff --git a/core/net/uip.h b/core/net/uip.h index 95068d84d..b0081af1a 100644 --- a/core/net/uip.h +++ b/core/net/uip.h @@ -7,7 +7,9 @@ /** * \file * Header file for the uIP TCP/IP stack. - * \author Adam Dunkels + * \author Adam Dunkels + * \author Julien Abeille (IPv6 related code) + * \author Mathilde Durvy (IPv6 related code) * * The uIP TCP/IP stack header file contains definitions for a number * of C macros that are used by uIP programs as well as internal uIP @@ -15,7 +17,6 @@ * */ - /* * Copyright (c) 2001-2003, Adam Dunkels. * All rights reserved. @@ -46,7 +47,7 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: uip.h,v 1.17 2008/02/24 21:04:15 adamdunkels Exp $ + * $Id: uip.h,v 1.18 2008/10/14 09:40:56 julienabeille Exp $ * */ @@ -59,26 +60,64 @@ * Representation of an IP address. * */ -typedef union uip_ip4addr_t { - u8_t u8[4]; /* Initializer, must come first!!! */ - u16_t u16[2]; -#if UIP_CONF_UIP_IP4ADDR_T_WITH_U32 - u32_t u32[1]; /* Might cause 32-bit alignment !!! */ -#endif /* UIP_CONF_UIP_IP4ADDR_T_WITH_U32 */ -} uip_ip4addr_t; - +#if UIP_CONF_IPV6 typedef union uip_ip6addr_t { u8_t u8[16]; /* Initializer, must come first!!! */ u16_t u16[8]; - u32_t u32[4]; } uip_ip6addr_t; -#if UIP_CONF_IPV6 typedef uip_ip6addr_t uip_ipaddr_t; #else /* UIP_CONF_IPV6 */ +typedef union uip_ip4addr_t { + u8_t u8[4]; /* Initializer, must come first!!! */ + u16_t u16[2]; +#if 0 + u32_t u32; +#endif +} uip_ip4addr_t; typedef uip_ip4addr_t uip_ipaddr_t; #endif /* UIP_CONF_IPV6 */ + +/*---------------------------------------------------------------------------*/ + +/** \brief 64 bit 802.15.4 address */ +struct uip_802154_shortaddr { + u8_t addr[2]; +}; +/** \brief 16 bit 802.15.4 address */ +struct uip_802154_longaddr { + u8_t addr[8]; +}; + +/** \brief 802.11 address */ +struct uip_80211_addr { + u8_t addr[6]; +}; + +/** \brief 802.3 address */ +struct uip_eth_addr { + u8_t addr[6]; +}; + +#if UIP_CONF_LL_802154 +/** \brief 802.15.4 address */ +typedef struct uip_802154_longaddr uip_lladdr_t; +#define UIP_802154_SHORTADDR_LEN 2 +#define UIP_802154_LONGADDR_LEN 8 +#define UIP_LLADDR_LEN UIP_802154_LONGADDR_LEN +#else /*UIP_CONF_LL_802154*/ +#if UIP_CONF_LL_80211 +/** \brief 802.11 address */ +typedef struct uip_80211_addr uip_lladdr_t; +#define UIP_LLADDR_LEN 6 +#else /*UIP_CONF_LL_80211*/ +/** \brief Etherent address */ +typedef struct uip_eth_addr uip_lladdr_t; +#define UIP_LLADDR_LEN 6 +#endif /*UIP_CONF_LL_80211*/ +#endif /*UIP_CONF_LL_802154*/ + #include "net/tcpip.h" /*---------------------------------------------------------------------------*/ @@ -86,7 +125,6 @@ typedef uip_ip4addr_t uip_ipaddr_t; * system. Initialization, the periodic timer and incoming packets are * handled by the following three functions. */ - /** * \defgroup uipconffunc uIP configuration functions * @{ @@ -234,13 +272,13 @@ void uip_setipid(u16_t id); * The usual way of calling the function is presented by the source * code below. \code - uip_len = devicedriver_poll(); - if(uip_len > 0) { - uip_input(); - if(uip_len > 0) { - devicedriver_send(); - } - } + uip_len = devicedriver_poll(); + if(uip_len > 0) { + uip_input(); + if(uip_len > 0) { + devicedriver_send(); + } + } \endcode * * \note If you are writing a uIP device driver that needs ARP @@ -248,28 +286,29 @@ void uip_setipid(u16_t id); * Ethernet, you will need to call the uIP ARP code before calling * this function: \code - #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) - uip_len = ethernet_devicedrver_poll(); - if(uip_len > 0) { - if(BUF->type == HTONS(UIP_ETHTYPE_IP)) { - uip_arp_ipin(); - uip_input(); - if(uip_len > 0) { - uip_arp_out(); - ethernet_devicedriver_send(); - } - } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) { - uip_arp_arpin(); - if(uip_len > 0) { - ethernet_devicedriver_send(); - } - } + #define BUF ((struct uip_eth_hdr *)&uip_buf[0]) + uip_len = ethernet_devicedrver_poll(); + if(uip_len > 0) { + if(BUF->type == HTONS(UIP_ETHTYPE_IP)) { + uip_arp_ipin(); + uip_input(); + if(uip_len > 0) { + uip_arp_out(); + ethernet_devicedriver_send(); + } + } else if(BUF->type == HTONS(UIP_ETHTYPE_ARP)) { + uip_arp_arpin(); + if(uip_len > 0) { + ethernet_devicedriver_send(); + } + } \endcode * * \hideinitializer */ #define uip_input() uip_process(UIP_DATA) + /** * Periodic processing for a connection identified by its number. * @@ -286,12 +325,12 @@ void uip_setipid(u16_t id); * The ususal way of calling the function is through a for() loop like * this: \code - for(i = 0; i < UIP_CONNS; ++i) { - uip_periodic(i); - if(uip_len > 0) { - devicedriver_send(); - } - } + for(i = 0; i < UIP_CONNS; ++i) { + uip_periodic(i); + if(uip_len > 0) { + devicedriver_send(); + } + } \endcode * * \note If you are writing a uIP device driver that needs ARP @@ -299,21 +338,22 @@ void uip_setipid(u16_t id); * Ethernet, you will need to call the uip_arp_out() function before * calling the device driver: \code - for(i = 0; i < UIP_CONNS; ++i) { - uip_periodic(i); - if(uip_len > 0) { - uip_arp_out(); - ethernet_devicedriver_send(); - } - } + for(i = 0; i < UIP_CONNS; ++i) { + uip_periodic(i); + if(uip_len > 0) { + uip_arp_out(); + ethernet_devicedriver_send(); + } + } \endcode * * \param conn The number of the connection which is to be periodically polled. * * \hideinitializer */ -#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \ - uip_process(UIP_TIMER); } while (0) +#if UIP_TCP +#define uip_periodic(conn) do { uip_conn = &uip_conns[conn]; \ + uip_process(UIP_TIMER); } while (0) /** * @@ -334,8 +374,8 @@ void uip_setipid(u16_t id); * * \hideinitializer */ -#define uip_periodic_conn(conn) do { uip_conn = conn; \ - uip_process(UIP_TIMER); } while (0) +#define uip_periodic_conn(conn) do { uip_conn = conn; \ + uip_process(UIP_TIMER); } while (0) /** * Reuqest that a particular connection should be polled. @@ -348,9 +388,10 @@ void uip_setipid(u16_t id); * * \hideinitializer */ -#define uip_poll_conn(conn) do { uip_conn = conn; \ - uip_process(UIP_POLL_REQUEST); } while (0) +#define uip_poll_conn(conn) do { uip_conn = conn; \ + uip_process(UIP_POLL_REQUEST); } while (0) +#endif /* UIP_TCP */ #if UIP_UDP /** @@ -360,24 +401,24 @@ void uip_setipid(u16_t id); * UDP connections. It is called in a similar fashion as the * uip_periodic() function: \code - for(i = 0; i < UIP_UDP_CONNS; i++) { - uip_udp_periodic(i); - if(uip_len > 0) { - devicedriver_send(); - } - } + for(i = 0; i < UIP_UDP_CONNS; i++) { + uip_udp_periodic(i); + if(uip_len > 0) { + devicedriver_send(); + } + } \endcode * * \note As for the uip_periodic() function, special care has to be * taken when using uIP together with ARP and Ethernet: \code - for(i = 0; i < UIP_UDP_CONNS; i++) { - uip_udp_periodic(i); - if(uip_len > 0) { - uip_arp_out(); - ethernet_devicedriver_send(); - } - } + for(i = 0; i < UIP_UDP_CONNS; i++) { + uip_udp_periodic(i); + if(uip_len > 0) { + uip_arp_out(); + ethernet_devicedriver_send(); + } + } \endcode * * \param conn The number of the UDP connection to be processed. @@ -385,7 +426,7 @@ void uip_setipid(u16_t id); * \hideinitializer */ #define uip_udp_periodic(conn) do { uip_udp_conn = &uip_udp_conns[conn]; \ - uip_process(UIP_UDP_TIMER); } while(0) + uip_process(UIP_UDP_TIMER); } while(0) /** * Periodic processing for a UDP connection identified by a pointer to @@ -401,14 +442,13 @@ void uip_setipid(u16_t id); * * \hideinitializer */ -#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \ - uip_process(UIP_UDP_TIMER); } while(0) - -#else /* UIP_UDP */ -#define uip_udp_periodic(conn) do { } while(0) -#define uip_udp_periodic_conn(conn) do { } while(0) +#define uip_udp_periodic_conn(conn) do { uip_udp_conn = conn; \ + uip_process(UIP_UDP_TIMER); } while(0) #endif /* UIP_UDP */ +/** \brief Abandon the reassembly of the current packet */ +void uip_reass_over(void); + /** * The uIP packet buffer. * @@ -425,25 +465,27 @@ void uip_setipid(u16_t id); void devicedriver_send(void) { - hwsend(&uip_buf[0], UIP_LLH_LEN); - if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN) { - hwsend(&uip_buf[UIP_LLH_LEN], uip_len - UIP_LLH_LEN); - } else { - hwsend(&uip_buf[UIP_LLH_LEN], UIP_TCPIP_HLEN); - hwsend(uip_appdata, uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN); - } + hwsend(&uip_buf[0], UIP_LLH_LEN); + if(uip_len <= UIP_LLH_LEN + UIP_TCPIP_HLEN) { + hwsend(&uip_buf[UIP_LLH_LEN], uip_len - UIP_LLH_LEN); + } else { + hwsend(&uip_buf[UIP_LLH_LEN], UIP_TCPIP_HLEN); + hwsend(uip_appdata, uip_len - UIP_TCPIP_HLEN - UIP_LLH_LEN); + } } \endcode - */ +*/ CCIF extern u8_t uip_buf[UIP_BUFSIZE+2]; + + /** @} */ /*---------------------------------------------------------------------------*/ /* Functions that are used by the uIP application program. Opening and * closing connections, sending and receiving data, etc. is all * handled by the functions below. -*/ + */ /** * \defgroup uipappfunc uIP application functions * @{ @@ -623,9 +665,9 @@ CCIF void uip_send(const void *data, int len); * * \hideinitializer */ -#define uip_restart() do { uip_flags |= UIP_NEWDATA; \ - uip_conn->tcpstateflags &= ~UIP_STOPPED; \ - } while(0) +#define uip_restart() do { uip_flags |= UIP_NEWDATA; \ + uip_conn->tcpstateflags &= ~UIP_STOPPED; \ + } while(0) /* uIP tests that can be made to determine in what state the current @@ -769,7 +811,7 @@ CCIF void uip_send(const void *data, int len); uip_ipaddr(&addr, 192,168,2,1); c = uip_udp_new(&addr, HTONS(12345)); if(c != NULL) { - uip_udp_bind(c, HTONS(12344)); + uip_udp_bind(c, HTONS(12344)); } \endcode * \param ripaddr The IP address of the remote host. @@ -867,12 +909,12 @@ struct uip_udp_conn *uip_udp_new(const uip_ipaddr_t *ripaddr, u16_t rport); * * \hideinitializer */ -#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \ - (addr)->u8[0] = addr0; \ - (addr)->u8[1] = addr1; \ - (addr)->u8[2] = addr2; \ - (addr)->u8[3] = addr3; \ - } while(0) +#define uip_ipaddr(addr, addr0,addr1,addr2,addr3) do { \ + (addr)->u8[0] = addr0; \ + (addr)->u8[1] = addr1; \ + (addr)->u8[2] = addr2; \ + (addr)->u8[3] = addr3; \ + } while(0) /** * Construct an IPv6 address from eight 16-bit words. @@ -882,15 +924,42 @@ struct uip_udp_conn *uip_udp_new(const uip_ipaddr_t *ripaddr, u16_t rport); * \hideinitializer */ #define uip_ip6addr(addr, addr0,addr1,addr2,addr3,addr4,addr5,addr6,addr7) do { \ - (addr)->u16[0] = HTONS(addr0); \ - (addr)->u16[1] = HTONS(addr1); \ - (addr)->u16[2] = HTONS(addr2); \ - (addr)->u16[3] = HTONS(addr3); \ - (addr)->u16[4] = HTONS(addr4); \ - (addr)->u16[5] = HTONS(addr5); \ - (addr)->u16[6] = HTONS(addr6); \ - (addr)->u16[7] = HTONS(addr7); \ - } while(0) + (addr)->u16[0] = HTONS(addr0); \ + (addr)->u16[1] = HTONS(addr1); \ + (addr)->u16[2] = HTONS(addr2); \ + (addr)->u16[3] = HTONS(addr3); \ + (addr)->u16[4] = HTONS(addr4); \ + (addr)->u16[5] = HTONS(addr5); \ + (addr)->u16[6] = HTONS(addr6); \ + (addr)->u16[7] = HTONS(addr7); \ + } while(0) + +/** + * Construct an IPv6 address from eight 8-bit words. + * + * This function constructs an IPv6 address. + * + * \hideinitializer + */ +#define uip_ip6addr_u8(addr, addr0,addr1,addr2,addr3,addr4,addr5,addr6,addr7,addr8,addr9,addr10,addr11,addr12,addr13,addr14,addr15) do { \ + (addr)->u8[0] = addr0; \ + (addr)->u8[1] = addr1; \ + (addr)->u8[2] = addr2; \ + (addr)->u8[3] = addr3; \ + (addr)->u8[4] = addr4; \ + (addr)->u8[5] = addr5; \ + (addr)->u8[6] = addr6; \ + (addr)->u8[7] = addr7; \ + (addr)->u8[8] = addr8; \ + (addr)->u8[9] = addr9; \ + (addr)->u8[10] = addr10; \ + (addr)->u8[11] = addr11; \ + (addr)->u8[12] = addr12; \ + (addr)->u8[13] = addr13; \ + (addr)->u8[14] = addr14; \ + (addr)->u8[15] = addr15; \ + } while(0) + /** * Copy an IP address to another IP address. @@ -925,7 +994,7 @@ struct uip_udp_conn *uip_udp_new(const uip_ipaddr_t *ripaddr, u16_t rport); uip_ipaddr(&ipaddr1, 192,16,1,2); if(uip_ipaddr_cmp(&ipaddr2, &ipaddr1)) { - printf("They are the same"); + printf("They are the same"); } \endcode * @@ -955,7 +1024,7 @@ struct uip_udp_conn *uip_udp_new(const uip_ipaddr_t *ripaddr, u16_t rport); uip_ipaddr(&ipaddr1, 192,16,1,2); uip_ipaddr(&ipaddr2, 192,16,1,3); if(uip_ipaddr_maskcmp(&ipaddr1, &ipaddr2, &mask)) { - printf("They are the same"); + printf("They are the same"); } \endcode * @@ -965,11 +1034,16 @@ struct uip_udp_conn *uip_udp_new(const uip_ipaddr_t *ripaddr, u16_t rport); * * \hideinitializer */ -#define uip_ipaddr_maskcmp(addr1, addr2, mask) \ - (((((u16_t *)addr1)[0] & ((u16_t *)mask)[0]) == \ - (((u16_t *)addr2)[0] & ((u16_t *)mask)[0])) && \ - ((((u16_t *)addr1)[1] & ((u16_t *)mask)[1]) == \ - (((u16_t *)addr2)[1] & ((u16_t *)mask)[1]))) +#if !UIP_CONF_IPV6 +#define uip_ipaddr_maskcmp(addr1, addr2, mask) \ + (((((u16_t *)addr1)[0] & ((u16_t *)mask)[0]) == \ + (((u16_t *)addr2)[0] & ((u16_t *)mask)[0])) && \ + ((((u16_t *)addr1)[1] & ((u16_t *)mask)[1]) == \ + (((u16_t *)addr2)[1] & ((u16_t *)mask)[1]))) +#else +#define uip_ipaddr_prefixcmp(addr1, addr2, length) (memcmp(addr1, addr2, length>>3) == 0) +#endif + /** * Check if an address is a broadcast address for a network. @@ -985,7 +1059,7 @@ struct uip_udp_conn *uip_udp_new(const uip_ipaddr_t *ripaddr, u16_t rport); * \hideinitializer */ /*#define uip_ipaddr_isbroadcast(addr, netaddr, netmask) -((uip_ipaddr_t *)(addr)).u16 & ((uip_ipaddr_t *)(addr)).u16*/ + ((uip_ipaddr_t *)(addr)).u16 & ((uip_ipaddr_t *)(addr)).u16*/ @@ -1013,10 +1087,10 @@ struct uip_udp_conn *uip_udp_new(const uip_ipaddr_t *ripaddr, u16_t rport); * * \hideinitializer */ -#define uip_ipaddr_mask(dest, src, mask) do { \ - ((u16_t *)dest)[0] = ((u16_t *)src)[0] & ((u16_t *)mask)[0]; \ - ((u16_t *)dest)[1] = ((u16_t *)src)[1] & ((u16_t *)mask)[1]; \ - } while(0) +#define uip_ipaddr_mask(dest, src, mask) do { \ + ((u16_t *)dest)[0] = ((u16_t *)src)[0] & ((u16_t *)mask)[0]; \ + ((u16_t *)dest)[1] = ((u16_t *)src)[1] & ((u16_t *)mask)[1]; \ + } while(0) /** * Pick the first octet of an IP address. @@ -1186,6 +1260,10 @@ extern void *uip_urgdata; */ CCIF extern u16_t uip_len; +/** + * The length of the extension headers + */ +extern u8_t uip_ext_len; /** @} */ #if UIP_URGDATA > 0 @@ -1240,9 +1318,13 @@ struct uip_conn { * The uip_conn pointer can be used to access the current TCP * connection. */ + CCIF extern struct uip_conn *uip_conn; +#if UIP_TCP /* The array containing all uIP connections. */ CCIF extern struct uip_conn uip_conns[UIP_CONNS]; +#endif + /** * \addtogroup uiparch * @{ @@ -1252,10 +1334,9 @@ CCIF extern struct uip_conn uip_conns[UIP_CONNS]; * 4-byte array used for the 32-bit sequence number calculations. */ extern u8_t uip_acc32[4]; - /** @} */ - +#if UIP_UDP /** * Representation of a uIP UDP connection. */ @@ -1274,6 +1355,26 @@ struct uip_udp_conn { */ extern struct uip_udp_conn *uip_udp_conn; extern struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; +#endif + +#if UIP_CONF_ICMP6 +struct uip_icmp6_conn { + uip_icmp6_appstate_t appstate; +}; +extern struct uip_icmp6_conn uip_icmp6_conns; +#endif /*UIP_CONF_ICMP6*/ + +/** + * The uIP TCP/IP statistics. + * + * This is the variable in which the uIP TCP/IP statistics are gathered. + */ +#if UIP_STATISTICS == 1 +extern struct uip_stats uip_stat; +#define UIP_STAT(s) s +#else +#define UIP_STAT(s) +#endif /* UIP_STATISTICS == 1 */ /** * The structure holding the TCP/IP statistics that are gathered if @@ -1306,8 +1407,11 @@ struct uip_stats { uip_stats_t sent; /**< Number of sent ICMP packets. */ uip_stats_t drop; /**< Number of dropped ICMP packets. */ uip_stats_t typeerr; /**< Number of ICMP packets with a wrong - type. */ + type. */ + uip_stats_t chkerr; /**< Number of ICMP packets with a bad + checksum. */ } icmp; /**< ICMP statistics. */ +#if UIP_TCP struct { uip_stats_t recv; /**< Number of recived TCP segments. */ uip_stats_t sent; /**< Number of sent TCP segments. */ @@ -1323,6 +1427,7 @@ struct uip_stats { uip_stats_t synrst; /**< Number of SYNs for closed ports, triggering a RST. */ } tcp; /**< TCP statistics. */ +#endif #if UIP_UDP struct { uip_stats_t drop; /**< Number of dropped UDP segments. */ @@ -1332,21 +1437,24 @@ struct uip_stats { checksum. */ } udp; /**< UDP statistics. */ #endif /* UIP_UDP */ +#if UIP_CONF_IPV6 + struct { + uip_stats_t drop; /**< Number of dropped ND6 packets. */ + uip_stats_t recv; /**< Number of recived ND6 packets */ + uip_stats_t sent; /**< Number of sent ND6 packets */ + } nd6; +#endif /*UIP_CONF_IPV6*/ }; -/** - * The uIP TCP/IP statistics. - * - * This is the variable in which the uIP TCP/IP statistics are gathered. - */ -extern struct uip_stats uip_stat; - /*---------------------------------------------------------------------------*/ /* All the stuff below this point is internal to uIP and should not be * used directly by an application or by a device driver. */ /*---------------------------------------------------------------------------*/ + + + /* u8_t uip_flags: * * When the application is called, uip_flags will contain the flags @@ -1392,13 +1500,22 @@ CCIF extern u8_t uip_flags; too many retransmissions. */ +/** + * \brief process the options within a hob by hop or detsination option header + * \retval 0: nothing to send, + * \retval 1: drop pkt + * \retval 2: ICMP error message to send +*/ +/*static u8_t +uip_ext_hdr_options_process(); */ + /* uip_process(flag): * * The actual uIP function which does all the work. */ void uip_process(u8_t flag); - -/* The following flags are passed as an argument to the uip_process() + + /* The following flags are passed as an argument to the uip_process() function. They are used to distinguish between the two cases where uip_process() is called. It can be called either because we have incoming data that should be processed, or because the periodic @@ -1493,16 +1610,11 @@ struct uip_icmpip_hdr { uip_ipaddr_t srcipaddr, destipaddr; #endif /* UIP_CONF_IPV6 */ - /* ICMP (echo) header. */ + /* ICMP header. */ u8_t type, icode; u16_t icmpchksum; #if !UIP_CONF_IPV6 u16_t id, seqno; - u8_t payload[1]; -#else /* !UIP_CONF_IPV6 */ - u8_t flags, reserved1, reserved2, reserved3; - u8_t icmp6data[16]; - u8_t options[1]; #endif /* !UIP_CONF_IPV6 */ }; @@ -1537,6 +1649,145 @@ struct uip_udpip_hdr { u16_t udpchksum; }; +/* + * In IPv6 the length of the L3 headers before the transport header is + * not fixed, due to the possibility to include extension option headers + * after the IP header. hence we split here L3 and L4 headers + */ +/* The IP header */ +struct uip_ip_hdr { +#if UIP_CONF_IPV6 + /* IPV6 header */ + u8_t vtc; + u8_t tcflow; + u16_t flow; + u8_t len[2]; + u8_t proto, ttl; + uip_ip6addr_t srcipaddr, destipaddr; +#else /* UIP_CONF_IPV6 */ + /* IPV4 header */ + u8_t vhl, + tos, + len[2], + ipid[2], + ipoffset[2], + ttl, + proto; + u16_t ipchksum; + uip_ipaddr_t srcipaddr, destipaddr; +#endif /* UIP_CONF_IPV6 */ +}; + + +/* + * IPv6 extension option headers: we are able to process + * the 4 extension headers defined in RFC2460 (IPv6): + * - Hop by hop option header, destination option header: + * These two are not used by any core IPv6 protocol, hence + * we just read them and go to the next. They convey options, + * the options defined in RFC2460 are Pad1 and PadN, which do + * some padding, and that we do not need to read (the length + * field in the header is enough) + * - Routing header: this one is most notably used by MIPv6, + * which we do not implement, hence we just read it and go + * to the next + * - Fragmentation header: we read this header and are able to + * reassemble packets + * + * We do not offer any means to send packets with extension headers + * + * We do not implement Authentication and ESP headers, which are + * used in IPSec and defined in RFC4302,4303,4305,4385 + */ +/* common header part */ +struct uip_ext_hdr { + u8_t next; + u8_t len; +}; + +/* Hop by Hop option header */ +struct uip_hbho_hdr { + u8_t next; + u8_t len; +}; + +/* destination option header */ +struct uip_desto_hdr { + u8_t next; + u8_t len; +}; + +/* We do not define structures for PAD1 and PADN options */ + +/* + * routing header + * the routing header as 4 common bytes, then routing header type + * specific data there are several types of routing header. Type 0 was + * deprecated as per RFC5095 most notable other type is 2, used in + * RFC3775 (MIPv6) here we do not implement MIPv6, so we just need to + * parse the 4 first bytes + */ +struct uip_routing_hdr { + u8_t next; + u8_t len; + u8_t routing_type; + u8_t seg_left; +}; + +/* fragmentation header */ +struct uip_frag_hdr { + u8_t next; + u8_t res; + u16_t offsetresmore; + u32_t id; +}; + +/* + * an option within the destination or hop by hop option headers + * it contains type an length, which is true for all options but PAD1 + */ +struct uip_ext_hdr_opt { + u8_t type; + u8_t len; +}; + +/* PADN option */ +struct uip_ext_hdr_opt_padn { + u8_t opt_type; + u8_t opt_len; +}; + +/* TCP header */ +struct uip_tcp_hdr { + u16_t srcport; + u16_t destport; + u8_t seqno[4]; + u8_t ackno[4]; + u8_t tcpoffset; + u8_t flags; + u8_t wnd[2]; + u16_t tcpchksum; + u8_t urgp[2]; + u8_t optdata[4]; +}; + +/* The ICMP headers. */ +struct uip_icmp_hdr { + u8_t type, icode; + u16_t icmpchksum; +#if !UIP_CONF_IPV6 + u16_t id, seqno; +#endif /* !UIP_CONF_IPV6 */ +}; + + +/* The UDP headers. */ +struct uip_udp_hdr { + u16_t srcport; + u16_t destport; + u16_t udplen; + u16_t udpchksum; +}; /** @@ -1556,27 +1807,86 @@ struct uip_udpip_hdr { #define UIP_APPDATA_SIZE (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN) #define UIP_APPDATA_PTR (void *)&uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN] - #define UIP_PROTO_ICMP 1 #define UIP_PROTO_TCP 6 #define UIP_PROTO_UDP 17 #define UIP_PROTO_ICMP6 58 + +#if UIP_CONF_IPV6 +/** @{ */ +/** \brief extension headers types */ +#define UIP_PROTO_HBHO 0 +#define UIP_PROTO_DESTO 60 +#define UIP_PROTO_ROUTING 43 +#define UIP_PROTO_FRAG 44 +#define UIP_PROTO_NONE 59 +/** @} */ + +/** @{ */ +/** \brief Destination and Hop By Hop extension headers option types */ +#define UIP_EXT_HDR_OPT_PAD1 0 +#define UIP_EXT_HDR_OPT_PADN 1 +/** @} */ + +/** @{ */ +/** + * \brief Bitmaps for extension header processing + * + * When processing extension headers, we should record somehow which one we + * see, because you cannot have twice the same header, except for destination + * We store all this in one u8_t bitmap one bit for each header expected. The + * order in the bitmap is the order recommended in RFC2460 + */ +#define UIP_EXT_HDR_BITMAP_HBHO 0x01 +#define UIP_EXT_HDR_BITMAP_DESTO1 0x02 +#define UIP_EXT_HDR_BITMAP_ROUTING 0x04 +#define UIP_EXT_HDR_BITMAP_FRAG 0x08 +#define UIP_EXT_HDR_BITMAP_AH 0x10 +#define UIP_EXT_HDR_BITMAP_ESP 0x20 +#define UIP_EXT_HDR_BITMAP_DESTO2 0x40 +/** @} */ + + +#endif /* UIP_CONF_IPV6 */ + + /* Header sizes. */ #if UIP_CONF_IPV6 #define UIP_IPH_LEN 40 +#define UIP_FRAGH_LEN 8 #else /* UIP_CONF_IPV6 */ #define UIP_IPH_LEN 20 /* Size of IP header */ #endif /* UIP_CONF_IPV6 */ + #define UIP_UDPH_LEN 8 /* Size of UDP header */ #define UIP_TCPH_LEN 20 /* Size of TCP header */ +#ifdef UIP_IPH_LEN +#define UIP_ICMPH_LEN 4 /* Size of ICMP header */ +#endif #define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN) /* Size of IP + - UDP - header */ + * UDP + * header */ #define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN) /* Size of IP + - TCP - header */ + * TCP + * header */ #define UIP_TCPIP_HLEN UIP_IPTCPH_LEN +#define UIP_IPICMPH_LEN (UIP_IPH_LEN + UIP_ICMPH_LEN) /* size of ICMP + + IP header */ +#define UIP_LLIPH_LEN (UIP_LLH_LEN + UIP_IPH_LEN) /* size of L2 + + IP header */ +#if UIP_CONF_IPV6 +/** + * The sums below are quite used in ND. When used for uip_buf, we + * include link layer length when used for uip_len, we do not, hence + * we need values with and without LLH_LEN we do not use capital + * letters as these values are variable + */ +#define uip_l2_l3_hdr_len (UIP_LLH_LEN + UIP_IPH_LEN + uip_ext_len) +#define uip_l2_l3_icmp_hdr_len (UIP_LLH_LEN + UIP_IPH_LEN + uip_ext_len + UIP_ICMPH_LEN) +#define uip_l3_hdr_len (UIP_IPH_LEN + uip_ext_len) +#define uip_l3_icmp_hdr_len (UIP_IPH_LEN + uip_ext_len + UIP_ICMPH_LEN) +#endif /*UIP_CONF_IPV6*/ #if UIP_FIXEDADDR @@ -1587,13 +1897,146 @@ CCIF extern uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr; CCIF extern const uip_ipaddr_t uip_broadcast_addr; CCIF extern const uip_ipaddr_t uip_all_zeroes_addr; +#if UIP_FIXEDETHADDR +CCIF extern const uip_lladdr_t uip_lladdr; +#else +CCIF extern uip_lladdr_t uip_lladdr; +#endif + + + + +#ifdef UIP_CONF_IPV6 +/** + * \brief Is IPv6 addresss a the unspecified address + * a is of type uip_ipaddr_t + */ +#define uip_is_addr_unspecified(a) \ + ((((a)->u16[0]) == 0) && \ + (((a)->u16[1]) == 0) && \ + (((a)->u16[2]) == 0) && \ + (((a)->u16[3]) == 0) && \ + (((a)->u16[4]) == 0) && \ + (((a)->u16[5]) == 0) && \ + (((a)->u16[6]) == 0) && \ + (((a)->u16[7]) == 0)) + +/** \brief Is IPv6 addresss a the link local all-nodes multicast address */ +#define uip_is_addr_linklocal_allnodes_mcast(a) \ + ((((a)->u8[0]) == 0xff) && \ + (((a)->u8[1]) == 0x02) && \ + (((a)->u16[1]) == 0) && \ + (((a)->u16[2]) == 0) && \ + (((a)->u16[3]) == 0) && \ + (((a)->u16[4]) == 0) && \ + (((a)->u16[5]) == 0) && \ + (((a)->u16[6]) == 0) && \ + (((a)->u8[14]) == 0) && \ + (((a)->u8[15]) == 0x01)) + +/** \brief set IP address a to unspecified */ +#define uip_create_unspecified(a) uip_ip6addr(a, 0, 0, 0, 0, 0, 0, 0, 0) + +/** \brief set IP address a to the link local all-nodes multicast address */ +#define uip_create_linklocal_allnodes_mcast(a) uip_ip6addr(a, 0xff02, 0, 0, 0, 0, 0, 0, 0x0001) + +/** \brief set IP address a to the link local all-routers multicast address */ +#define uip_create_linklocal_allrouters_mcast(a) uip_ip6addr(a, 0xff02, 0, 0, 0, 0, 0, 0, 0x0002) /** - * Representation of a 48-bit Ethernet address. + * \brief is addr (a) a solicited node multicast address, see RFC3513 + * a is of type uip_ipaddr_t* */ -struct uip_eth_addr { - u8_t addr[6]; -}; +#define uip_is_addr_solicited_node(a) \ + ((((a)->u8[0]) == 0xFF) && \ + (((a)->u8[1]) == 0x02) && \ + (((a)->u16[1]) == 0) && \ + (((a)->u16[2]) == 0) && \ + (((a)->u16[3]) == 0) && \ + (((a)->u16[4]) == 0) && \ + (((a)->u16[5]) == 1) && \ + (((a)->u8[12]) == 0xFF)) + +/** + * \briefput in b the solicited node address corresponding to address a + * both a and b are of type uip_ipaddr_t* + * */ +#define uip_create_solicited_node(a, b) \ + (((b)->u8[0]) = 0xFF); \ + (((b)->u8[1]) = 0x02); \ + (((b)->u16[1]) = 0); \ + (((b)->u16[2]) = 0); \ + (((b)->u16[3]) = 0); \ + (((b)->u16[4]) = 0); \ + (((b)->u8[10]) = 0); \ + (((b)->u8[11]) = 0x01); \ + (((b)->u8[12]) = 0xFF); \ + (((b)->u8[13]) = ((a)->u8[13])); \ + (((b)->u16[7]) = ((a)->u16[7])) + +/** + * \brief is addr (a) a link local unicast address, see RFC3513 + * i.e. is (a) on prefix FE80::/10 + * a is of type uip_ipaddr_t* + */ +#define uip_is_addr_link_local(a) \ + ((((a)->u8[0]) == 0xFE) && \ + (((a)->u8[1]) == 0x80)) + +/** + * \brief was addr (a) forged based on the mac address m + * a type is uip_ipaddr_t + * m type is uiplladdr_t + */ +#if UIP_CONF_LL_802154 +#define uip_is_addr_mac_addr_based(a, m) \ + ((((a)->u8[8]) == (((m)->addr[0]) ^ 0x02)) && \ + (((a)->u8[9]) == (m)->addr[1]) && \ + (((a)->u8[10]) == (m)->addr[2]) && \ + (((a)->u8[11]) == (m)->addr[3]) && \ + (((a)->u8[12]) == (m)->addr[4]) && \ + (((a)->u8[13]) == (m)->addr[5]) && \ + (((a)->u8[14]) == (m)->addr[6]) && \ + (((a)->u8[15]) == (m)->addr[7])) +#endif /*UIP_CONF_LL_802154*/ + +/** + * \brief is address a multicast address, see RFC 3513 + * a is of type uip_ipaddr_t* + * */ +#define uip_is_addr_mcast(a) \ + (((a)->u8[0]) == 0xFF) + +/** + * \brief is group-id of multicast address a + * the all nodes group-id + */ +#define uip_is_mcast_group_id_all_nodes(a) \ + ((((a)->u16[1]) == 0) && \ + (((a)->u16[2]) == 0) && \ + (((a)->u16[3]) == 0) && \ + (((a)->u16[4]) == 0) && \ + (((a)->u16[5]) == 0) && \ + (((a)->u16[6]) == 0) && \ + (((a)->u8[14]) == 0) && \ + (((a)->u8[15]) == 1)) + +/** + * \brief is group-id of multicast address a + * the all routers group-id + */ +#define uip_is_mcast_group_id_all_routers(a) \ + ((((a)->u16[1]) == 0) && \ + (((a)->u16[2]) == 0) && \ + (((a)->u16[3]) == 0) && \ + (((a)->u16[4]) == 0) && \ + (((a)->u16[5]) == 0) && \ + (((a)->u16[6]) == 0) && \ + (((a)->u8[14]) == 0) && \ + (((a)->u8[15]) == 2)) + + +#endif /*UIP_CONF_IPV6*/ /** * Calculate the Internet checksum over a buffer. @@ -1646,6 +2089,13 @@ u16_t uip_tcpchksum(void); */ u16_t uip_udpchksum(void); +/** + * Calculate the ICMP checksum of the packet in uip_buf. + * + * \return The ICMP checksum of the ICMP packet in uip_buf + */ +u16_t uip_icmp6chksum(void); + #endif /* __UIP_H__ */ diff --git a/core/net/uipopt.h b/core/net/uipopt.h index e55debb4e..4271c5679 100644 --- a/core/net/uipopt.h +++ b/core/net/uipopt.h @@ -58,7 +58,7 @@ * * This file is part of the uIP TCP/IP stack. * - * $Id: uipopt.h,v 1.7 2007/12/23 20:24:46 oliverschmidt Exp $ + * $Id: uipopt.h,v 1.8 2008/10/14 09:40:56 julienabeille Exp $ * */ @@ -87,8 +87,10 @@ * netmask, default router and Ethernet address are appliciable only * if uIP should be run over Ethernet. * + * This options are meaningful only for the IPv4 code. + * * All of these should be changed to suit your project. -*/ + */ /** * Determines if uIP should use a fixed IP address or not. @@ -145,6 +147,13 @@ */ #define UIP_TTL 64 +/** + * The maximum time an IP fragment should wait in the reassembly + * buffer before it is dropped. + * + */ +#define UIP_REASS_MAXAGE 60 /*60s*/ + /** * Turn on support for IP packet reassembly. * @@ -158,15 +167,62 @@ * * \hideinitializer */ +#ifdef UIP_CONF_REASSEMBLY +#define UIP_REASSEMBLY UIP_CONF_REASSEMBLY +#else /* UIP_CONF_REASSEMBLY */ #define UIP_REASSEMBLY 0 +#endif /* UIP_CONF_REASSEMBLY */ +/** @} */ +/*------------------------------------------------------------------------------*/ /** - * The maximum time an IP fragment should wait in the reassembly - * buffer before it is dropped. + * \defgroup uipoptipv6 IPv6 configuration options + * @{ * */ -#define UIP_REASS_MAXAGE 40 +/** The maximum transmission unit at the IP Layer*/ +#define UIP_LINK_MTU 1280 + +#ifndef UIP_CONF_IPV6 +/** Do we use IPv6 or not (default: no) */ +#define UIP_CONF_IPV6 0 +#endif + +#ifndef UIP_CONF_IPV6_QUEUE_PKT +/** Do we do per %neighbor queuing during address resolution (default: no) */ +#define UIP_CONF_IPV6_QUEUE_PKT 0 +#endif + +#ifndef UIP_CONF_IPV6_CHECKS +/** Do we do IPv6 consistency checks (highly recommended, default: yes) */ +#define UIP_CONF_IPV6_CHECKS 1 +#endif + +#ifndef UIP_CONF_IPV6_REASSEMBLY +/** Do we do IPv6 fragmentation (default: no) */ +#define UIP_CONF_IPV6_REASSEMBLY 0 +#endif + +#ifndef UIP_CONF_NETIF_MAX_ADDRESSES +/** Default number of IPv6 addresses associated to the node's interface */ +#define UIP_CONF_NETIF_MAX_ADDRESSES 3 +#endif + +#ifndef UIP_CONF_ND6_MAX_PREFIXES +/** Default number of IPv6 prefixes associated to the node's interface */ +#define UIP_CONF_ND6_MAX_PREFIXES 3 +#endif + +#ifndef UIP_CONF_ND6_MAX_NEIGHBORS +/** Default number of neighbors that can be stored in the %neighbor cache */ +#define UIP_CONF_ND6_MAX_NEIGHBORS 4 +#endif + +#ifndef UIP_CONF_ND6_MAX_DEFROUTERS +/** Minimum number of default routers */ +#define UIP_CONF_ND6_MAX_DEFROUTERS 2 +#endif /** @} */ /*------------------------------------------------------------------------------*/ @@ -230,6 +286,17 @@ * @{ */ +/** + * Toggles wether UDP support should be compiled in or not. + * + * \hideinitializer + */ +#ifdef UIP_CONF_TCP +#define UIP_TCP UIP_CONF_TCP +#else /* UIP_CONF_UDP */ +#define UIP_TCP 1 +#endif /* UIP_CONF_UDP */ + /** * Determines if support for opening connections from uIP should be * compiled in. @@ -371,6 +438,53 @@ */ #define UIP_ARP_MAXAGE 120 + +/** @} */ + +/*------------------------------------------------------------------------------*/ + +/** + * \defgroup uipoptmac layer 2 options (for ipv6) + * @{ + */ + +#define UIP_DEFAULT_PREFIX_LEN 64 + +/** @} */ + +/*------------------------------------------------------------------------------*/ + +/** + * \defgroup uipoptsics 6lowpan options (for ipv6) + * @{ + */ +/** + * Timeout for packet reassembly at the 6lowpan layer + * (should be < 60s) + */ +#define SICSLOWPAN_REASS_MAXAGE 20 + +/** + * Do we compress the IP header or not (default: no) + */ +#ifndef SICSLOWPAN_CONF_COMPRESSION +#define SICSLOWPAN_CONF_COMPRESSION 0 +#endif + +/** + * If we use IPHC compression, how many address contexts do we support + */ +#ifndef SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS +#define SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS 1 +#endif + +/** + * Do we support 6lowpan fragmentation + */ +#ifndef SICSLOWPAN_CONF_FRAG +#define SICSLOWPAN_CONF_FRAG 0 +#endif + /** @} */ /*------------------------------------------------------------------------------*/ @@ -390,7 +504,7 @@ * \hideinitializer */ #ifndef UIP_CONF_BUFFER_SIZE -#define UIP_BUFSIZE 400 +#define UIP_BUFSIZE UIP_LINK_MTU + UIP_LLH_LEN #else /* UIP_CONF_BUFFER_SIZE */ #define UIP_BUFSIZE UIP_CONF_BUFFER_SIZE #endif /* UIP_CONF_BUFFER_SIZE */ @@ -454,11 +568,16 @@ void uip_log(char *msg); * found. For Ethernet, this should be set to 14. For SLIP, this * should be set to 0. * + * \note we probably won't use this constant for other link layers than + * ethernet as they have variable header length (this is due to variable + * number and type of address fields and to optional security features) + * E.g.: 802.15.4 -> 2 + (1/2*4/8) + 0/5/6/10/14 + * 802.11 -> 4 + (6*3/4) + 2 * \hideinitializer */ #ifdef UIP_CONF_LLH_LEN #define UIP_LLH_LEN UIP_CONF_LLH_LEN -#else /* UIP_CONF_LLH_LEN */ +#else /* UIP_LLH_LEN */ #define UIP_LLH_LEN 14 #endif /* UIP_CONF_LLH_LEN */ @@ -511,18 +630,18 @@ void uip_log(char *msg); * The following example illustrates how this can look. \code -void httpd_appcall(void); -#define UIP_APPCALL httpd_appcall + void httpd_appcall(void); + #define UIP_APPCALL httpd_appcall -struct httpd_state { - u8_t state; - u16_t count; - char *dataptr; - char *script; -}; -typedef struct httpd_state uip_tcp_appstate_t + struct httpd_state { + u8_t state; + u16_t count; + char *dataptr; + char *script; + }; + typedef struct httpd_state uip_tcp_appstate_t \endcode - */ +*/ /** * \var #define UIP_APPCALL