Contiki 2.6
|
00001 /** 00002 * \addtogroup uip6 00003 * @{ 00004 */ 00005 /* 00006 * Copyright (c) 2009, Swedish Institute of Computer Science. 00007 * All rights reserved. 00008 * 00009 * Redistribution and use in source and binary forms, with or without 00010 * modification, are permitted provided that the following conditions 00011 * are met: 00012 * 1. Redistributions of source code must retain the above copyright 00013 * notice, this list of conditions and the following disclaimer. 00014 * 2. Redistributions in binary form must reproduce the above copyright 00015 * notice, this list of conditions and the following disclaimer in the 00016 * documentation and/or other materials provided with the distribution. 00017 * 3. Neither the name of the Institute nor the names of its contributors 00018 * may be used to endorse or promote products derived from this software 00019 * without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00022 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00023 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00024 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00025 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00026 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00027 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00028 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00029 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00030 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00031 * SUCH DAMAGE. 00032 * 00033 * This file is part of the Contiki operating system. 00034 */ 00035 /** 00036 * \file 00037 * Management of extension headers for ContikiRPL. 00038 * 00039 * \author Vincent Brillault <vincent.brillault@imag.fr>, 00040 * Joakim Eriksson <joakime@sics.se>, 00041 * Niclas Finne <nfi@sics.se>, 00042 * Nicolas Tsiftes <nvt@sics.se>. 00043 */ 00044 00045 #include "net/uip.h" 00046 #include "net/tcpip.h" 00047 #include "net/uip-ds6.h" 00048 #include "net/rpl/rpl-private.h" 00049 00050 #define DEBUG DEBUG_NONE 00051 #include "net/uip-debug.h" 00052 00053 #include <limits.h> 00054 #include <string.h> 00055 00056 /************************************************************************/ 00057 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) 00058 #define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len]) 00059 #define UIP_HBHO_BUF ((struct uip_hbho_hdr *)&uip_buf[uip_l2_l3_hdr_len]) 00060 #define UIP_HBHO_NEXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_HOP_BY_HOP_LEN]) 00061 #define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) 00062 #define UIP_EXT_HDR_OPT_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) 00063 #define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset]) 00064 /************************************************************************/ 00065 int 00066 rpl_verify_header(int uip_ext_opt_offset) 00067 { 00068 rpl_instance_t *instance; 00069 int down; 00070 uint8_t sender_closer; 00071 00072 if(UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) { 00073 PRINTF("RPL: Bad header option! (wrong length)\n"); 00074 return 1; 00075 } 00076 00077 if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_FWD_ERR) { 00078 PRINTF("RPL: Forward error!\n"); 00079 /* We should try to repair it, not implemented for the moment */ 00080 return 2; 00081 } 00082 00083 instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance); 00084 if(instance == NULL) { 00085 PRINTF("RPL: Unknown instance: %u\n", 00086 UIP_EXT_HDR_OPT_RPL_BUF->instance); 00087 return 1; 00088 } 00089 00090 if(!instance->current_dag->joined) { 00091 PRINTF("RPL: No DAG in the instance\n"); 00092 return 1; 00093 } 00094 00095 down = 0; 00096 if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN) { 00097 down = 1; 00098 } 00099 00100 PRINTF("RPL: Packet going %s\n", down == 1 ? "down" : "up"); 00101 00102 sender_closer = UIP_EXT_HDR_OPT_RPL_BUF->senderrank < instance->current_dag->rank; 00103 if((down && !sender_closer) || (!down && sender_closer)) { 00104 PRINTF("RPL: Loop detected - senderrank: %d my-rank: %d sender_closer: %d\n", 00105 UIP_EXT_HDR_OPT_RPL_BUF->senderrank, instance->current_dag->rank, 00106 sender_closer); 00107 if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) { 00108 PRINTF("RPL: Rank error signalled in RPL option!\n"); 00109 /* We should try to repair it, not implemented for the moment */ 00110 return 3; 00111 } 00112 PRINTF("RPL: Single error tolerated\n"); 00113 UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_RANK_ERR; 00114 return 0; 00115 } 00116 00117 PRINTF("RPL: Rank OK\n"); 00118 00119 return 0; 00120 } 00121 /************************************************************************/ 00122 static void 00123 set_rpl_opt(unsigned uip_ext_opt_offset) 00124 { 00125 uint8_t temp_len; 00126 00127 memmove(UIP_HBHO_NEXT_BUF, UIP_EXT_BUF, uip_len - UIP_IPH_LEN); 00128 memset(UIP_HBHO_BUF, 0, RPL_HOP_BY_HOP_LEN); 00129 UIP_HBHO_BUF->next = UIP_IP_BUF->proto; 00130 UIP_IP_BUF->proto = UIP_PROTO_HBHO; 00131 UIP_HBHO_BUF->len = RPL_HOP_BY_HOP_LEN - 8; 00132 UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL; 00133 UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN; 00134 UIP_EXT_HDR_OPT_RPL_BUF->flags = 0; 00135 UIP_EXT_HDR_OPT_RPL_BUF->instance = 0; 00136 UIP_EXT_HDR_OPT_RPL_BUF->senderrank = 0; 00137 uip_len += RPL_HOP_BY_HOP_LEN; 00138 temp_len = UIP_IP_BUF->len[1]; 00139 UIP_IP_BUF->len[1] += UIP_HBHO_BUF->len + 8; 00140 if(UIP_IP_BUF->len[1] < temp_len) { 00141 UIP_IP_BUF->len[0]++; 00142 } 00143 } 00144 /************************************************************************/ 00145 void 00146 rpl_update_header_empty(void) 00147 { 00148 rpl_instance_t *instance; 00149 int uip_ext_opt_offset; 00150 int last_uip_ext_len; 00151 00152 last_uip_ext_len = uip_ext_len; 00153 uip_ext_len = 0; 00154 uip_ext_opt_offset = 2; 00155 00156 PRINTF("RPL: Verifying the presence of the RPL header option\n"); 00157 00158 switch(UIP_IP_BUF->proto) { 00159 case UIP_PROTO_HBHO: 00160 if(UIP_HBHO_BUF->len != RPL_HOP_BY_HOP_LEN - 8) { 00161 PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n"); 00162 uip_ext_len = last_uip_ext_len; 00163 return; 00164 } 00165 instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance); 00166 if(instance == NULL || !instance->used || !instance->current_dag->joined) { 00167 PRINTF("RPL: Unable to add hop-by-hop extension header: incorrect instance\n"); 00168 return; 00169 } 00170 break; 00171 default: 00172 PRINTF("RPL: No hop-by-hop option found, creating it\n"); 00173 if(uip_len + RPL_HOP_BY_HOP_LEN > UIP_BUFSIZE) { 00174 PRINTF("RPL: Packet too long: impossible to add hop-by-hop option\n"); 00175 uip_ext_len = last_uip_ext_len; 00176 return; 00177 } 00178 set_rpl_opt(uip_ext_opt_offset); 00179 uip_ext_len = last_uip_ext_len + RPL_HOP_BY_HOP_LEN; 00180 return; 00181 } 00182 00183 switch(UIP_EXT_HDR_OPT_BUF->type) { 00184 case UIP_EXT_HDR_OPT_RPL: 00185 PRINTF("RPL: Updating RPL option\n"); 00186 UIP_EXT_HDR_OPT_RPL_BUF->senderrank=instance->current_dag->rank; 00187 uip_ext_len = last_uip_ext_len; 00188 return; 00189 default: 00190 PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); 00191 uip_ext_len = last_uip_ext_len; 00192 return; 00193 } 00194 } 00195 /************************************************************************/ 00196 int 00197 rpl_update_header_final(uip_ipaddr_t *addr) 00198 { 00199 rpl_parent_t *parent; 00200 int uip_ext_opt_offset; 00201 int last_uip_ext_len; 00202 00203 last_uip_ext_len = uip_ext_len; 00204 uip_ext_len = 0; 00205 uip_ext_opt_offset = 2; 00206 00207 if(UIP_IP_BUF->proto == UIP_PROTO_HBHO) { 00208 if(UIP_HBHO_BUF->len != RPL_HOP_BY_HOP_LEN - 8) { 00209 PRINTF("RPL: Non RPL Hop-by-hop options support not implemented\n"); 00210 uip_ext_len = last_uip_ext_len; 00211 return 0; 00212 } 00213 00214 if(UIP_EXT_HDR_OPT_BUF->type == UIP_EXT_HDR_OPT_RPL) { 00215 if(UIP_EXT_HDR_OPT_RPL_BUF->senderrank == 0) { 00216 PRINTF("RPL: Updating RPL option\n"); 00217 if(default_instance == NULL || !default_instance->used || !default_instance->current_dag->joined) { 00218 PRINTF("RPL: Unable to add hop-by-hop extension header: incorrect default instance\n"); 00219 return 1; 00220 } 00221 parent = rpl_find_parent(default_instance->current_dag, addr); 00222 if(parent == NULL || parent != parent->dag->preferred_parent) { 00223 UIP_EXT_HDR_OPT_RPL_BUF->flags = RPL_HDR_OPT_DOWN; 00224 } 00225 UIP_EXT_HDR_OPT_RPL_BUF->instance = default_instance->instance_id; 00226 UIP_EXT_HDR_OPT_RPL_BUF->senderrank = default_instance->current_dag->rank; 00227 uip_ext_len = last_uip_ext_len; 00228 } 00229 } 00230 } 00231 return 0; 00232 } 00233 /************************************************************************/ 00234 void 00235 rpl_remove_header(void) 00236 { 00237 int last_uip_ext_len; 00238 uint8_t temp_len; 00239 00240 last_uip_ext_len = uip_ext_len; 00241 uip_ext_len = 0; 00242 00243 PRINTF("RPL: Verifying the presence of the RPL header option\n"); 00244 switch(UIP_IP_BUF->proto){ 00245 case UIP_PROTO_HBHO: 00246 PRINTF("RPL: Removing the RPL header option\n"); 00247 UIP_IP_BUF->proto = UIP_HBHO_BUF->next; 00248 temp_len = UIP_IP_BUF->len[1]; 00249 uip_len -= UIP_HBHO_BUF->len + 8; 00250 UIP_IP_BUF->len[1] -= UIP_HBHO_BUF->len + 8; 00251 if(UIP_IP_BUF->len[1] > temp_len) { 00252 UIP_IP_BUF->len[0]--; 00253 } 00254 memmove(UIP_EXT_BUF, UIP_HBHO_NEXT_BUF, uip_len - UIP_IPH_LEN); 00255 break; 00256 default: 00257 PRINTF("RPL: No hop-by-hop Option found\n"); 00258 } 00259 } 00260 /************************************************************************/ 00261 uint8_t 00262 rpl_invert_header(void) 00263 { 00264 uint8_t uip_ext_opt_offset; 00265 uint8_t last_uip_ext_len; 00266 00267 last_uip_ext_len = uip_ext_len; 00268 uip_ext_len = 0; 00269 uip_ext_opt_offset = 2; 00270 00271 PRINTF("RPL: Verifying the presence of the RPL header option\n"); 00272 switch(UIP_IP_BUF->proto) { 00273 case UIP_PROTO_HBHO: 00274 break; 00275 default: 00276 PRINTF("RPL: No hop-by-hop Option found\n"); 00277 uip_ext_len = last_uip_ext_len; 00278 return 0; 00279 } 00280 00281 switch (UIP_EXT_HDR_OPT_BUF->type) { 00282 case UIP_EXT_HDR_OPT_RPL: 00283 PRINTF("RPL: Updating RPL option (switching direction)\n"); 00284 UIP_EXT_HDR_OPT_RPL_BUF->flags &= RPL_HDR_OPT_DOWN; 00285 UIP_EXT_HDR_OPT_RPL_BUF->flags ^= RPL_HDR_OPT_DOWN; 00286 UIP_EXT_HDR_OPT_RPL_BUF->senderrank = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance)->current_dag->rank; 00287 uip_ext_len = last_uip_ext_len; 00288 return RPL_HOP_BY_HOP_LEN; 00289 default: 00290 PRINTF("RPL: Multi Hop-by-hop options not implemented\n"); 00291 uip_ext_len = last_uip_ext_len; 00292 return 0; 00293 } 00294 } 00295 /************************************************************************/