From f4b804ed9fce1d9876dee03869c218c1279de7a2 Mon Sep 17 00:00:00 2001 From: Vincent Brillault Date: Mon, 11 Jul 2011 16:53:02 +0200 Subject: [PATCH] =?UTF-8?q?Add=20support=20of=20RPL=20Option=20(http://too?= =?UTF-8?q?ls.ietf.org/html/draft-ietf-6man-rpl-option-03):=20-=20Auto-ins?= =?UTF-8?q?ersion=20when=20forwarding=20messages=20-=20Delete=20messages?= =?UTF-8?q?=20with=202=20rank=20errors=20Not=20supported=20yet=20:=20-=20R?= =?UTF-8?q?outing=20depending=20on=20InstanceID=20-=20DAO=20inconsistency?= =?UTF-8?q?=20loop=20recovery=20-=20Full=20UDP=20or=20TCP=20support=20(Bug?= =?UTF-8?q?s=20in=20=C2=B5IPv6)=20-=20Real=20Option=20Type=20(TBD=20by=20I?= =?UTF-8?q?ANA)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/net/tcpip.c | 9 +++- core/net/uip-icmp6.c | 115 +++++++++++++++++++++++++++++++------------ core/net/uip.h | 15 ++++++ core/net/uip6.c | 52 ++++++++++++++++++- 4 files changed, 157 insertions(+), 34 deletions(-) diff --git a/core/net/tcpip.c b/core/net/tcpip.c index bdb68fd4d..52386e0a3 100644 --- a/core/net/tcpip.c +++ b/core/net/tcpip.c @@ -80,7 +80,8 @@ extern struct uip_fallback_interface UIP_FALLBACK_INTERFACE; #endif #if UIP_CONF_IPV6_RPL void rpl_init(void); -#endif +int rpl_update_header_final(uip_ipaddr_t *addr); +#endif /* UIP_CONF_IPV6_RPL */ process_event_t tcpip_event; #if UIP_CONF_ICMP6 process_event_t tcpip_icmp6_event; @@ -590,6 +591,12 @@ tcpip_ipv6_output(void) } } /* end of next hop determination */ +#if UIP_CONF_IPV6_RPL + if (rpl_update_header_final(nexthop)) { + uip_len = 0; + return; + } +#endif /* UIP_CONF_IPV6_RPL */ if((nbr = uip_ds6_nbr_lookup(nexthop)) == NULL) { // printf("add1 %d\n", nexthop->u8[15]); if((nbr = uip_ds6_nbr_add(nexthop, NULL, 0, NBR_INCOMPLETE)) == NULL) { diff --git a/core/net/uip-icmp6.c b/core/net/uip-icmp6.c index 3bb554461..fb2016b23 100644 --- a/core/net/uip-icmp6.c +++ b/core/net/uip-icmp6.c @@ -60,14 +60,25 @@ #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len]) #define UIP_ICMP6_ERROR_BUF ((struct uip_icmp6_error *)&uip_buf[uip_l2_l3_icmp_hdr_len]) +#if UIP_CONF_IPV6_RPL +#define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len]) +#define UIP_FIRST_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[UIP_LLIPH_LEN]) +#endif /* UIP_CONF_IPV6_RPL */ /** \brief temporary IP address */ static uip_ipaddr_t tmp_ipaddr; +#if UIP_CONF_IPV6_RPL +int rpl_invert_header(void); +#endif /* UIP_CONF_IPV6_RPL */ + /*---------------------------------------------------------------------------*/ void uip_icmp6_echo_request_input(void) { +#if UIP_CONF_IPV6_RPL + u8_t temp_ext_len; +#endif /* UIP_CONF_IPV6_RPL */ /* * we send an echo reply. It is trivial if there was no extension * headers in the request otherwise we need to remove the extension @@ -78,7 +89,7 @@ uip_icmp6_echo_request_input(void) PRINTF("to"); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("\n"); - + /* IP header */ UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit; @@ -92,30 +103,54 @@ uip_icmp6_echo_request_input(void) } if(uip_ext_len > 0) { - /* If there were extension headers*/ - UIP_IP_BUF->proto = UIP_PROTO_ICMP6; - uip_len -= uip_ext_len; - UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); - UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); - /* move the echo request payload (starting after the icmp header) - * to the new location in the reply. - * The shift is equal to the length of the extension headers present - * Note: UIP_ICMP_BUF still points to the echo request at this stage - */ - memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - uip_ext_len, - (uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, - (uip_len - UIP_IPH_LEN - UIP_ICMPH_LEN)); +#if UIP_CONF_IPV6_RPL + if ((temp_ext_len=rpl_invert_header())) { + /* If there were other extension headers*/ + UIP_FIRST_EXT_BUF->next = UIP_PROTO_ICMP6; + if (uip_ext_len != temp_ext_len) { + uip_len -= (uip_ext_len - temp_ext_len); + UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); + /* move the echo request payload (starting after the icmp header) + * to the new location in the reply. + * The shift is equal to the length of the remaining extension headers present + * Note: UIP_ICMP_BUF still points to the echo request at this stage + */ + memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - (uip_ext_len - temp_ext_len), + (uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, + (uip_len - UIP_IPH_LEN - temp_ext_len - UIP_ICMPH_LEN)); + } + uip_ext_len=temp_ext_len; + } else { +#endif /* UIP_CONF_IPV6_RPL */ + /* If there were extension headers*/ + UIP_IP_BUF->proto = UIP_PROTO_ICMP6; + uip_len -= uip_ext_len; + UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8); + UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff); + /* move the echo request payload (starting after the icmp header) + * to the new location in the reply. + * The shift is equal to the length of the extension headers present + * Note: UIP_ICMP_BUF still points to the echo request at this stage + */ + memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - uip_ext_len, + (uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN, + (uip_len - UIP_IPH_LEN - UIP_ICMPH_LEN)); + uip_ext_len = 0; +#if UIP_CONF_IPV6_RPL + } +#endif /* UIP_CONF_IPV6_RPL */ } /* Below is important for the correctness of UIP_ICMP_BUF and the * checksum */ - uip_ext_len = 0; + /* Note: now UIP_ICMP_BUF points to the beginning of the echo reply */ UIP_ICMP_BUF->type = ICMP6_ECHO_REPLY; UIP_ICMP_BUF->icode = 0; UIP_ICMP_BUF->icmpchksum = 0; UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum(); - + PRINTF("Sending Echo Reply to"); PRINT6ADDR(&UIP_IP_BUF->destipaddr); PRINTF("from"); @@ -127,29 +162,45 @@ uip_icmp6_echo_request_input(void) /*---------------------------------------------------------------------------*/ void uip_icmp6_error_output(u8_t type, u8_t code, u32_t param) { - uip_ext_len = 0; /* check if originating packet is not an ICMP error*/ - if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128){ - uip_len = 0; - return; + if (uip_ext_len) { + if(UIP_EXT_BUF->next == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128){ + uip_len = 0; + return; + } + } else { + if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128){ + uip_len = 0; + return; + } } - /* remember data of original packet before shifting */ - uip_ipaddr_copy(&tmp_ipaddr, &UIP_IP_BUF->destipaddr); - - uip_len += UIP_IPICMPH_LEN + UIP_ICMP6_ERROR_LEN; - - if(uip_len > UIP_LINK_MTU) - uip_len = UIP_LINK_MTU; +#if UIP_CONF_IPV6_RPL + uip_ext_len = rpl_invert_header(); +#else /* UIP_CONF_IPV6_RPL */ + uip_ext_len = 0; +#endif /* UIP_CONF_IPV6_RPL */ - memmove((uint8_t *)UIP_ICMP6_ERROR_BUF + UIP_ICMP6_ERROR_LEN, - (void *)UIP_IP_BUF, uip_len - UIP_IPICMPH_LEN - UIP_ICMP6_ERROR_LEN); + /* remember data of original packet before shifting */ + uip_ipaddr_copy(&tmp_ipaddr, &UIP_IP_BUF->destipaddr); + + uip_len += UIP_IPICMPH_LEN + UIP_ICMP6_ERROR_LEN; + + if(uip_len > UIP_LINK_MTU) + uip_len = UIP_LINK_MTU; + + memmove((uint8_t *)UIP_ICMP6_ERROR_BUF + uip_ext_len + UIP_ICMP6_ERROR_LEN, + (void *)UIP_IP_BUF, uip_len - UIP_IPICMPH_LEN - uip_ext_len - UIP_ICMP6_ERROR_LEN); UIP_IP_BUF->vtc = 0x60; UIP_IP_BUF->tcflow = 0; UIP_IP_BUF->flow = 0; - UIP_IP_BUF->proto = UIP_PROTO_ICMP6; + if (uip_ext_len) { + UIP_FIRST_EXT_BUF->next = UIP_PROTO_ICMP6; + } else { + UIP_IP_BUF->proto = UIP_PROTO_ICMP6; + } UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit; /* the source should not be unspecified nor multicast, the check for @@ -158,7 +209,7 @@ uip_icmp6_error_output(u8_t type, u8_t code, u32_t param) { uip_len = 0; return; } - + uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr); if(uip_is_addr_mcast(&tmp_ipaddr)){ @@ -176,7 +227,7 @@ uip_icmp6_error_output(u8_t type, u8_t code, u32_t param) { uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &tmp_ipaddr); #endif } - + UIP_ICMP_BUF->type = type; UIP_ICMP_BUF->icode = code; UIP_ICMP6_ERROR_BUF->param = uip_htonl(param); diff --git a/core/net/uip.h b/core/net/uip.h index f04ebd0d9..d9bd88855 100644 --- a/core/net/uip.h +++ b/core/net/uip.h @@ -1770,6 +1770,17 @@ typedef struct uip_ext_hdr_opt_padn { u8_t opt_len; } uip_ext_hdr_opt_padn; +#if UIP_CONF_IPV6_RPL +/* RPL option */ +typedef struct uip_ext_hdr_opt_rpl { + u8_t opt_type; + u8_t opt_len; + u8_t flags; + u8_t instance; + u16_t senderrank; +} uip_ext_hdr_opt_rpl; +#endif /* UIP_CONF_IPV6_RPL */ + /* TCP header */ struct uip_tcp_hdr { u16_t srcport; @@ -1840,6 +1851,10 @@ struct uip_udp_hdr { /** \brief Destination and Hop By Hop extension headers option types */ #define UIP_EXT_HDR_OPT_PAD1 0 #define UIP_EXT_HDR_OPT_PADN 1 +#if UIP_CONF_IPV6_RPL +#define UIP_EXT_HDR_OPT_RPL 0x63 +#endif /* UIP_CONF_IPV6_RPL */ + /** @} */ /** @{ */ diff --git a/core/net/uip6.c b/core/net/uip6.c index 1ae674b3b..2c74d6e9a 100644 --- a/core/net/uip6.c +++ b/core/net/uip6.c @@ -96,6 +96,8 @@ #if UIP_CONF_IPV6_RPL void uip_rpl_input(void); +void rpl_update_header_empty(void); +int rpl_verify_header(int uip_ext_opt_offset); #endif /* UIP_CONF_IPV6_RPL */ #if UIP_LOGGING == 1 @@ -163,6 +165,9 @@ u8_t uip_ext_opt_offset = 0; #define UIP_DESTO_BUF ((struct uip_desto_hdr *)&uip_buf[uip_l2_l3_hdr_len]) #define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) #define UIP_EXT_HDR_OPT_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) +#if UIP_CONF_IPV6_RPL +#define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) +#endif /* UIP_CONF_IPV6_RPL */ #define UIP_ICMP6_ERROR_BUF ((struct uip_icmp6_error *)&uip_buf[uip_l2_l3_icmp_hdr_len]) /** @} */ /** \name Buffer variables @@ -827,6 +832,16 @@ ext_hdr_options_process() { PRINTF("Processing PADN option\n"); uip_ext_opt_offset += UIP_EXT_HDR_OPT_PADN_BUF->opt_len + 2; break; +#if UIP_CONF_IPV6_RPL + case UIP_EXT_HDR_OPT_RPL: + PRINTF("Processing RPL option\n"); + if (rpl_verify_header(uip_ext_opt_offset)) { + PRINTF("RPL Option Error : Dropping Packet"); + return 1; + } + uip_ext_opt_offset += (UIP_EXT_HDR_OPT_RPL_BUF->opt_len) + 2; + return 0; +#endif /* UIP_CONF_IPV6_RPL */ default: /* * check the two highest order bits of the option @@ -1078,6 +1093,35 @@ uip_process(u8_t flag) } #if UIP_CONF_ROUTER + /* + * Next header field processing. In IPv6, we can have extension headers, + * if present, the Hop-by-Hop Option must be processed before forwarding + * the packet. + */ + uip_next_hdr = &UIP_IP_BUF->proto; + uip_ext_len = 0; + uip_ext_bitmap = 0; + if (*uip_next_hdr == UIP_PROTO_HBHO) { +#if UIP_CONF_IPV6_CHECKS + uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_HBHO; +#endif /*UIP_CONF_IPV6_CHECKS*/ + switch(ext_hdr_options_process()) { + case 0: + /*continue*/ + uip_next_hdr = &UIP_EXT_BUF->next; + uip_ext_len += (UIP_EXT_BUF->len << 3) + 8; + break; + case 1: + /*silently discard*/ + goto drop; + case 2: + /* send icmp error message (created in ext_hdr_options_process) + * and discard*/ + goto send; + } + } + + /* TBD Some Parameter problem messages */ if(!uip_ds6_is_my_addr(&UIP_IP_BUF->destipaddr) && !uip_ds6_is_my_maddr(&UIP_IP_BUF->destipaddr)) { @@ -1101,6 +1145,11 @@ uip_process(u8_t flag) UIP_STAT(++uip_stat.ip.drop); goto send; } + +#if UIP_CONF_IPV6_RPL + rpl_update_header_empty(); +#endif /* UIP_CONF_IPV6_RPL */ + UIP_IP_BUF->ttl = UIP_IP_BUF->ttl - 1; PRINTF("Forwarding packet to "); PRINT6ADDR(&UIP_IP_BUF->destipaddr); @@ -1131,7 +1180,6 @@ uip_process(u8_t flag) UIP_STAT(++uip_stat.ip.drop); goto drop; } -#endif /* UIP_CONF_ROUTER */ /* * Next header field processing. In IPv6, we can have extension headers, @@ -1140,6 +1188,8 @@ uip_process(u8_t flag) uip_next_hdr = &UIP_IP_BUF->proto; uip_ext_len = 0; uip_ext_bitmap = 0; +#endif /* UIP_CONF_ROUTER */ + while(1) { switch(*uip_next_hdr){ #if UIP_TCP