Contiki 2.6

rpl-ext-header.c

Go to the documentation of this file.
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 /************************************************************************/