Contiki-NG
rpl-ext-header.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009, Swedish Institute of Computer Science.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
16  *
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
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  */
31 
32 /**
33  * \addtogroup rpl-lite
34  * @{
35  *
36  * \file
37  * Management of extension headers for ContikiRPL.
38  *
39  * \author Vincent Brillault <vincent.brillault@imag.fr>,
40  * Joakim Eriksson <joakime@sics.se>,
41  * Niclas Finne <nfi@sics.se>,
42  * Nicolas Tsiftes <nvt@sics.se>,
43  * Simon Duquennoy <simon.duquennoy@inria.fr>
44  */
45 
46 #include "net/routing/routing.h"
47 #include "net/routing/rpl-lite/rpl.h"
48 #include "net/ipv6/uip-sr.h"
49 #include "net/packetbuf.h"
50 
51 /* Log configuration */
52 #include "sys/log.h"
53 #define LOG_MODULE "RPL"
54 #define LOG_LEVEL LOG_LEVEL_RPL
55 
56 /*---------------------------------------------------------------------------*/
57 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
58 #define UIP_EXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len])
59 #define UIP_HBHO_BUF ((struct uip_hbho_hdr *)&uip_buf[uip_l2_l3_hdr_len])
60 #define UIP_HBHO_NEXT_BUF ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_HOP_BY_HOP_LEN])
61 #define UIP_RH_BUF ((struct uip_routing_hdr *)&uip_buf[uip_l2_l3_hdr_len])
62 #define UIP_RPL_SRH_BUF ((struct uip_rpl_srh_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_RH_LEN])
63 #define UIP_EXT_HDR_OPT_BUF ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
64 #define UIP_EXT_HDR_OPT_PADN_BUF ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
65 #define UIP_EXT_HDR_OPT_RPL_BUF ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
66 
67 /*---------------------------------------------------------------------------*/
68 int
70 {
71  uint8_t *uip_next_hdr;
72  int last_uip_ext_len = uip_ext_len;
73  uip_sr_node_t *dest_node;
74  uip_sr_node_t *root_node;
75 
76  uip_ext_len = 0;
77  uip_next_hdr = &UIP_IP_BUF->proto;
78 
79  /* Look for routing header */
80  while(uip_next_hdr != NULL && *uip_next_hdr != UIP_PROTO_ROUTING) {
81  switch(*uip_next_hdr) {
82  case UIP_PROTO_HBHO:
83  case UIP_PROTO_DESTO:
84  /*
85  * As per RFC 2460, only the Hop-by-Hop Options header and
86  * Destination Options header can appear before the Routing header.
87  */
88  uip_next_hdr = &UIP_EXT_BUF->next;
89  uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
90  break;
91  default:
92  uip_next_hdr = NULL;
93  break;
94  }
95  }
96 
97  if(!rpl_is_addr_in_our_dag(&UIP_IP_BUF->destipaddr)) {
98  return 0;
99  }
100 
101  root_node = uip_sr_get_node(NULL, &curr_instance.dag.dag_id);
102  dest_node = uip_sr_get_node(NULL, &UIP_IP_BUF->destipaddr);
103 
104  if((uip_next_hdr != NULL && *uip_next_hdr == UIP_PROTO_ROUTING
105  && UIP_RH_BUF->routing_type == RPL_RH_TYPE_SRH) ||
106  (dest_node != NULL && root_node != NULL &&
107  dest_node->parent == root_node)) {
108  /* Routing header found or the packet destined for a direct child of the root.
109  * The next hop should be already copied as the IPv6 destination
110  * address, via rpl_ext_header_srh_update. We turn this address into a link-local to enable
111  * forwarding to next hop */
112  uip_ipaddr_copy(ipaddr, &UIP_IP_BUF->destipaddr);
113  uip_create_linklocal_prefix(ipaddr);
114  uip_ext_len = last_uip_ext_len;
115  return 1;
116  }
117 
118  LOG_DBG("no SRH found\n");
119  uip_ext_len = last_uip_ext_len;
120  return 0;
121 }
122 /*---------------------------------------------------------------------------*/
123 int
125 {
126  uint8_t *uip_next_hdr;
127  int last_uip_ext_len = uip_ext_len;
128  uint8_t cmpri, cmpre;
129  uint8_t ext_len;
130  uint8_t padding;
131  uint8_t path_len;
132  uint8_t segments_left;
133  uip_ipaddr_t current_dest_addr;
134 
135  uip_ext_len = 0;
136  uip_next_hdr = &UIP_IP_BUF->proto;
137 
138  /* Look for routing header */
139  while(uip_next_hdr != NULL && *uip_next_hdr != UIP_PROTO_ROUTING) {
140  switch(*uip_next_hdr) {
141  case UIP_PROTO_HBHO:
142  case UIP_PROTO_DESTO:
143  /*
144  * As per RFC 2460, only the Hop-by-Hop Options header and
145  * Destination Options header can appear before the Routing header.
146  */
147  uip_next_hdr = &UIP_EXT_BUF->next;
148  uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
149  break;
150  default:
151  uip_next_hdr = NULL;
152  break;
153  }
154  }
155 
156  if(uip_next_hdr == NULL || *uip_next_hdr != UIP_PROTO_ROUTING
157  || UIP_RH_BUF->routing_type != RPL_RH_TYPE_SRH) {
158  LOG_INFO("SRH not found\n");
159  uip_ext_len = last_uip_ext_len;
160  return 0;
161  }
162 
163  /* Parse SRH */
164  segments_left = UIP_RH_BUF->seg_left;
165  ext_len = (UIP_RH_BUF->len * 8) + 8;
166  cmpri = UIP_RPL_SRH_BUF->cmpr >> 4;
167  cmpre = UIP_RPL_SRH_BUF->cmpr & 0x0f;
168  padding = UIP_RPL_SRH_BUF->pad >> 4;
169  path_len = ((ext_len - padding - RPL_RH_LEN - RPL_SRH_LEN - (16 - cmpre)) / (16 - cmpri)) + 1;
170  (void)path_len;
171 
172  LOG_INFO("read SRH, path len %u, segments left %u, Cmpri %u, Cmpre %u, ext len %u (padding %u)\n",
173  path_len, segments_left, cmpri, cmpre, ext_len, padding);
174 
175  /* Update SRH in-place */
176  if(segments_left == 0) {
177  /* We are the final destination, do nothing */
178  } else {
179  uint8_t i = path_len - segments_left; /* The index of the next address to be visited */
180  uint8_t *addr_ptr = ((uint8_t *)UIP_RH_BUF) + RPL_RH_LEN + RPL_SRH_LEN + (i * (16 - cmpri));
181  uint8_t cmpr = segments_left == 1 ? cmpre : cmpri;
182 
183  /* As per RFC6554: swap the IPv6 destination address with address[i] */
184 
185  /* First, copy the current IPv6 destination address */
186  uip_ipaddr_copy(&current_dest_addr, &UIP_IP_BUF->destipaddr);
187  /* Second, update the IPv6 destination address with addresses[i] */
188  memcpy(((uint8_t *)&UIP_IP_BUF->destipaddr) + cmpr, addr_ptr, 16 - cmpr);
189  /* Third, write current_dest_addr to addresses[i] */
190  memcpy(addr_ptr, ((uint8_t *)&current_dest_addr) + cmpr, 16 - cmpr);
191 
192  /* Update segments left field */
193  UIP_RH_BUF->seg_left--;
194 
195  LOG_INFO("SRH next hop ");
196  LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
197  LOG_INFO_("\n");
198  }
199 
200  uip_ext_len = last_uip_ext_len;
201  return 1;
202 }
203 /*---------------------------------------------------------------------------*/
204 /* Utility function for SRH. Counts the number of bytes in common between
205  * two addresses at p1 and p2. */
206 static int
207 count_matching_bytes(const void *p1, const void *p2, size_t n)
208 {
209  int i = 0;
210  for(i = 0; i < n; i++) {
211  if(((uint8_t *)p1)[i] != ((uint8_t *)p2)[i]) {
212  return i;
213  }
214  }
215  return n;
216 }
217 /*---------------------------------------------------------------------------*/
218 /* Used by rpl_ext_header_update to insert a RPL SRH extension header. This
219  * is used at the root, to initiate downward routing. Returns 1 on success,
220  * 0 on failure.
221 */
222 static int
223 insert_srh_header(void)
224 {
225  /* Implementation of RFC6554 */
226  uint8_t temp_len;
227  uint8_t path_len;
228  uint8_t ext_len;
229  uint8_t cmpri, cmpre; /* ComprI and ComprE fields of the RPL Source Routing Header */
230  uint8_t *hop_ptr;
231  uint8_t padding;
232  uip_sr_node_t *dest_node;
233  uip_sr_node_t *root_node;
234  uip_sr_node_t *node;
235  uip_ipaddr_t node_addr;
236 
237  LOG_INFO("SRH creating source routing header with destination ");
238  LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
239  LOG_INFO_(" \n");
240 
241  /* Construct source route. We do not do this recursively to keep the runtime stack usage constant. */
242 
243  /* Get link of the destination and root */
244 
245  if(!rpl_is_addr_in_our_dag(&UIP_IP_BUF->destipaddr)) {
246  /* The destination is not in our DAG, skip SRH insertion */
247  LOG_INFO("SRH destination not in our DAG, skip SRH insertion\n");
248  return 1;
249  }
250 
251  dest_node = uip_sr_get_node(NULL, &UIP_IP_BUF->destipaddr);
252  if(dest_node == NULL) {
253  /* The destination is not found, skip SRH insertion */
254  LOG_INFO("SRH node not found, skip SRH insertion\n");
255  return 1;
256  }
257 
258  root_node = uip_sr_get_node(NULL, &curr_instance.dag.dag_id);
259  if(root_node == NULL) {
260  LOG_ERR("SRH root node not found\n");
261  return 0;
262  }
263 
264  if(!uip_sr_is_addr_reachable(NULL, &UIP_IP_BUF->destipaddr)) {
265  LOG_ERR("SRH no path found to destination\n");
266  return 0;
267  }
268 
269  /* Compute path length and compression factors (we use cmpri == cmpre) */
270  path_len = 0;
271  node = dest_node->parent;
272  /* For simplicity, we use cmpri = cmpre */
273  cmpri = 15;
274  cmpre = 15;
275 
276  /* Note that in case of a direct child (node == root_node), we insert
277  SRH anyway, as RFC 6553 mandates that routed datagrams must include
278  SRH or the RPL option (or both) */
279 
280  while(node != NULL && node != root_node) {
281 
282  NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, node);
283 
284  /* How many bytes in common between all nodes in the path? */
285  cmpri = MIN(cmpri, count_matching_bytes(&node_addr, &UIP_IP_BUF->destipaddr, 16));
286  cmpre = cmpri;
287 
288  LOG_INFO("SRH Hop ");
289  LOG_INFO_6ADDR(&node_addr);
290  LOG_INFO_("\n");
291  node = node->parent;
292  path_len++;
293  }
294 
295  /* Extension header length: fixed headers + (n-1) * (16-ComprI) + (16-ComprE)*/
296  ext_len = RPL_RH_LEN + RPL_SRH_LEN
297  + (path_len - 1) * (16 - cmpre)
298  + (16 - cmpri);
299 
300  padding = ext_len % 8 == 0 ? 0 : (8 - (ext_len % 8));
301  ext_len += padding;
302 
303  LOG_INFO("SRH path len: %u, ComprI %u, ComprE %u, ext len %u (padding %u)\n",
304  path_len, cmpri, cmpre, ext_len, padding);
305 
306  /* Check if there is enough space to store the extension header */
307  if(uip_len + ext_len > UIP_BUFSIZE - UIP_LLH_LEN) {
308  LOG_ERR("packet too long: impossible to add source routing header (%u bytes)\n", ext_len);
309  return 0;
310  }
311 
312  /* Move existing ext headers and payload uip_ext_len further */
313  memmove(uip_buf + uip_l2_l3_hdr_len + ext_len,
314  uip_buf + uip_l2_l3_hdr_len, uip_len - UIP_IPH_LEN);
315  memset(uip_buf + uip_l2_l3_hdr_len, 0, ext_len);
316 
317  /* Insert source routing header */
318  UIP_RH_BUF->next = UIP_IP_BUF->proto;
319  UIP_IP_BUF->proto = UIP_PROTO_ROUTING;
320 
321  /* Initialize IPv6 Routing Header */
322  UIP_RH_BUF->len = (ext_len - 8) / 8;
323  UIP_RH_BUF->routing_type = RPL_RH_TYPE_SRH;
324  UIP_RH_BUF->seg_left = path_len;
325 
326  /* Initialize RPL Source Routing Header */
327  UIP_RPL_SRH_BUF->cmpr = (cmpri << 4) + cmpre;
328  UIP_RPL_SRH_BUF->pad = padding << 4;
329 
330  /* Initialize addresses field (the actual source route).
331  * From last to first. */
332  node = dest_node;
333  hop_ptr = ((uint8_t *)UIP_RH_BUF) + ext_len - padding; /* Pointer where to write the next hop compressed address */
334 
335  while(node != NULL && node->parent != root_node) {
336  NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, node);
337 
338  hop_ptr -= (16 - cmpri);
339  memcpy(hop_ptr, ((uint8_t*)&node_addr) + cmpri, 16 - cmpri);
340 
341  node = node->parent;
342  }
343 
344  /* The next hop (i.e. node whose parent is the root) is placed as the current IPv6 destination */
345  NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, node);
346  uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &node_addr);
347 
348  /* In-place update of IPv6 length field */
349  temp_len = UIP_IP_BUF->len[1];
350  UIP_IP_BUF->len[1] += ext_len;
351  if(UIP_IP_BUF->len[1] < temp_len) {
352  UIP_IP_BUF->len[0]++;
353  }
354 
355  uip_ext_len += ext_len;
356  uip_len += ext_len;
357 
358  return 1;
359 }
360 /*---------------------------------------------------------------------------*/
361 int
363 {
364  int down;
365  int rank_error_signaled;
366  int loop_detected;
367  uint16_t sender_rank;
368  uint8_t sender_closer;
369  rpl_nbr_t *sender;
370  uint8_t opt_type = UIP_EXT_HDR_OPT_RPL_BUF->opt_type;
371  uint8_t opt_len = UIP_EXT_HDR_OPT_RPL_BUF->opt_len;
372 
373  if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)
374  || opt_type != UIP_EXT_HDR_OPT_RPL
375  || opt_len != RPL_HDR_OPT_LEN) {
376  LOG_ERR("hop-by-hop extension header has wrong size or type (%u %u %u)\n",
377  UIP_HBHO_BUF->len, opt_type, opt_len);
378  return 0; /* Drop */
379  }
380 
381  if(!curr_instance.used || curr_instance.instance_id != UIP_EXT_HDR_OPT_RPL_BUF->instance) {
382  LOG_ERR("unknown instance: %u\n",
383  UIP_EXT_HDR_OPT_RPL_BUF->instance);
384  return 0; /* Drop */
385  }
386 
387  if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_FWD_ERR) {
388  LOG_ERR("forward error!\n");
389  return 0; /* Drop */
390  }
391 
392  down = (UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN) ? 1 : 0;
393  sender_rank = UIP_HTONS(UIP_EXT_HDR_OPT_RPL_BUF->senderrank);
394  sender = nbr_table_get_from_lladdr(rpl_neighbors, packetbuf_addr(PACKETBUF_ADDR_SENDER));
395  rank_error_signaled = (UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) ? 1 : 0;
396  sender_closer = sender_rank < curr_instance.dag.rank;
397  loop_detected = (down && !sender_closer) || (!down && sender_closer);
398 
399  LOG_INFO("ext hdr: packet from ");
400  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
401  LOG_INFO_(" to ");
402  LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
403  LOG_INFO_(" going %s, sender closer %d (%d < %d), rank error %u, loop detected %u\n",
404  down == 1 ? "down" : "up", sender_closer, sender_rank,
405  curr_instance.dag.rank, rank_error_signaled, loop_detected);
406 
407  if(loop_detected) {
408  /* Set forward error flag */
409  UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_RANK_ERR;
410  }
411 
412  return rpl_process_hbh(sender, sender_rank, loop_detected, rank_error_signaled);
413 }
414 /*---------------------------------------------------------------------------*/
415 /* In-place update of the RPL HBH extension header, when already present
416  * in the uIP packet. Used by insert_hbh_header and rpl_ext_header_update.
417  * Returns 1 on success, 0 on failure. */
418 static int
419 update_hbh_header(void)
420 {
421  int uip_ext_opt_offset;
422  int last_uip_ext_len;
423 
424  last_uip_ext_len = uip_ext_len;
425  uip_ext_len = 0;
426  uip_ext_opt_offset = 2;
427 
428  if(UIP_IP_BUF->proto == UIP_PROTO_HBHO && UIP_EXT_HDR_OPT_RPL_BUF->opt_type == UIP_EXT_HDR_OPT_RPL) {
429  if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)
430  || UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) {
431 
432  LOG_ERR("hop-by-hop extension header has wrong size (%u %u)\n",
433  UIP_EXT_HDR_OPT_RPL_BUF->opt_len, uip_ext_len);
434  return 0; /* Drop */
435  }
436 
437  if(!curr_instance.used || curr_instance.instance_id != UIP_EXT_HDR_OPT_RPL_BUF->instance) {
438  LOG_ERR("unable to add/update hop-by-hop extension header: incorrect instance\n");
439  uip_ext_len = last_uip_ext_len;
440  return 0; /* Drop */
441  }
442 
443  /* Update sender rank and instance, will update flags next */
444  UIP_EXT_HDR_OPT_RPL_BUF->senderrank = UIP_HTONS(curr_instance.dag.rank);
445  UIP_EXT_HDR_OPT_RPL_BUF->instance = curr_instance.instance_id;
446  }
447 
448  uip_ext_len = last_uip_ext_len;
449  return 1;
450 }
451 /*---------------------------------------------------------------------------*/
452 /* Used by rpl_ext_header_update on packets without an HBH extension header,
453  * for packets initated by non-root nodes.
454  * Inserts and initalizes (via update_hbh_header) a RPL HBH ext header.
455  * Returns 1 on success, 0 on failure. */
456 static int
457 insert_hbh_header(void)
458 {
459  int uip_ext_opt_offset;
460  int last_uip_ext_len;
461  uint8_t temp_len;
462 
463  last_uip_ext_len = uip_ext_len;
464  uip_ext_len = 0;
465  uip_ext_opt_offset = 2;
466 
467  /* Insert hop-by-hop header */
468  LOG_INFO("creating hop-by-hop option\n");
469  if(uip_len + RPL_HOP_BY_HOP_LEN > UIP_BUFSIZE - UIP_LLH_LEN) {
470  LOG_ERR("packet too long: impossible to add hop-by-hop option\n");
471  uip_ext_len = last_uip_ext_len;
472  return 0;
473  }
474 
475  /* Move existing ext headers and payload UIP_EXT_BUF further */
476  memmove(UIP_HBHO_NEXT_BUF, UIP_EXT_BUF, uip_len - UIP_IPH_LEN);
477  memset(UIP_HBHO_BUF, 0, RPL_HOP_BY_HOP_LEN);
478 
479  /* Update IP and HBH protocol and fields */
480  UIP_HBHO_BUF->next = UIP_IP_BUF->proto;
481  UIP_IP_BUF->proto = UIP_PROTO_HBHO;
482 
483  /* Initialize HBH option */
484  UIP_HBHO_BUF->len = (RPL_HOP_BY_HOP_LEN - 8) / 8;
485  UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL;
486  UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN;
487  UIP_EXT_HDR_OPT_RPL_BUF->flags = 0;
488  UIP_EXT_HDR_OPT_RPL_BUF->senderrank = UIP_HTONS(curr_instance.dag.rank);
489  UIP_EXT_HDR_OPT_RPL_BUF->instance = curr_instance.instance_id;
490  uip_len += RPL_HOP_BY_HOP_LEN;
491  temp_len = UIP_IP_BUF->len[1];
492  UIP_IP_BUF->len[1] += RPL_HOP_BY_HOP_LEN;
493  if(UIP_IP_BUF->len[1] < temp_len) {
494  UIP_IP_BUF->len[0]++;
495  }
496 
497  uip_ext_len = last_uip_ext_len + RPL_HOP_BY_HOP_LEN;
498 
499  /* Update header before returning */
500  return update_hbh_header();
501 }
502 /*---------------------------------------------------------------------------*/
503 int
505 {
506  if(!curr_instance.used
507  || uip_is_addr_linklocal(&UIP_IP_BUF->destipaddr)
508  || uip_is_addr_mcast(&UIP_IP_BUF->destipaddr)) {
509  return 1;
510  }
511 
512  if(rpl_dag_root_is_root()) {
513  /* At the root, remove headers if any, and insert SRH or HBH
514  * (SRH is inserted only if the destination is down the DODAG) */
516  /* Insert SRH (if needed) */
517  return insert_srh_header();
518  } else {
519  if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr)
520  && UIP_IP_BUF->ttl == uip_ds6_if.cur_hop_limit) {
521  /* Insert HBH option at source. Checking the address is not sufficient because
522  * in non-storing mode, a packet may go up and then down the same path again */
523  return insert_hbh_header();
524  } else {
525  /* Update HBH option at forwarders */
526  return update_hbh_header();
527  }
528  }
529 }
530 /*---------------------------------------------------------------------------*/
531 void
533 {
534  uint8_t temp_len;
535  uint8_t rpl_ext_hdr_len;
536  int uip_ext_opt_offset;
537  uint8_t *uip_next_hdr;
538 
539  uip_ext_len = 0;
540  uip_ext_opt_offset = 2;
541  uip_next_hdr = &UIP_IP_BUF->proto;
542 
543  /* Look for hop-by-hop and routing headers */
544  while(uip_next_hdr != NULL) {
545  switch(*uip_next_hdr) {
546  case UIP_PROTO_HBHO:
547  case UIP_PROTO_ROUTING:
548  if((*uip_next_hdr != UIP_PROTO_HBHO || UIP_EXT_HDR_OPT_RPL_BUF->opt_type == UIP_EXT_HDR_OPT_RPL)) {
549  /* Remove hop-by-hop and routing headers */
550  *uip_next_hdr = UIP_EXT_BUF->next;
551  rpl_ext_hdr_len = (UIP_EXT_BUF->len * 8) + 8;
552  temp_len = UIP_IP_BUF->len[1];
553  uip_len -= rpl_ext_hdr_len;
554  UIP_IP_BUF->len[1] -= rpl_ext_hdr_len;
555  if(UIP_IP_BUF->len[1] > temp_len) {
556  UIP_IP_BUF->len[0]--;
557  }
558  LOG_INFO("removing RPL extension header (type %u, len %u)\n", *uip_next_hdr, rpl_ext_hdr_len);
559  memmove(UIP_EXT_BUF, ((uint8_t *)UIP_EXT_BUF) + rpl_ext_hdr_len, uip_len - UIP_IPH_LEN);
560  } else {
561  uip_next_hdr = &UIP_EXT_BUF->next;
562  uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
563  }
564  break;
565  case UIP_PROTO_DESTO:
566  /*
567  * As per RFC 2460, any header other than the Destination
568  * Options header does not appear between the Hop-by-Hop
569  * Options header and the Routing header.
570  *
571  * We're moving to the next header only if uip_next_hdr has
572  * UIP_PROTO_DESTO. Otherwise, we'll return.
573  */
574  /* Move to next header */
575  uip_next_hdr = &UIP_EXT_BUF->next;
576  uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
577  break;
578  default:
579  return;
580  }
581  }
582 }
583 
584 /** @}*/
static uip_ipaddr_t ipaddr
Pointer to prefix information option in uip_buf.
Definition: uip-nd6.c:125
#define UIP_IP_BUF
Pointer to IP header.
Definition: uip-nd6.c:97
void rpl_ext_header_remove(void)
Removes all RPL extension headers.
#define uip_l2_l3_hdr_len
The sums below are quite used in ND.
Definition: uip.h:75
int rpl_ext_header_hbh_update(int uip_ext_opt_offset)
Process and update the RPL hop-by-hop extension headers of the current uIP packet.
uint16_t uip_len
The length of the packet in the uip_buf buffer.
Definition: uip6.c:179
#define UIP_PROTO_HBHO
extension headers types
Definition: uip.h:1904
#define UIP_BUFSIZE
The size of the uIP packet buffer.
Definition: uipopt.h:154
int rpl_is_addr_in_our_dag(const uip_ipaddr_t *addr)
Tells whether a given global IPv6 address is in our current DAG.
Definition: rpl-dag.c:158
int rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr)
Look for next hop from SRH of current uIP packet.
int rpl_ext_header_update(void)
Adds/updates all RPL extension headers to current uIP packet.
int rpl_dag_root_is_root(void)
Tells whether we are DAG root or not.
Definition: rpl-dag-root.c:147
Source routing support.
uint8_t uip_ext_opt_offset
length of the header options read
Definition: uip6.c:134
#define UIP_LLH_LEN
The link level header length.
Definition: uipopt.h:141
Routing driver header file
#define uip_buf
Macro to access uip_aligned_buf as an array of bytes.
Definition: uip.h:513
All information related to a RPL neighbor.
Definition: rpl-types.h:136
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
Definition: uip.h:1018
uip_sr_node_t * uip_sr_get_node(void *graph, const uip_ipaddr_t *addr)
Looks up for a source routing node from its IPv6 global address.
Definition: uip-sr.c:81
#define uip_is_addr_mcast(a)
is address a multicast address, see RFC 4291 a is of type uip_ipaddr_t*
Definition: uip.h:2107
#define UIP_HTONS(n)
Convert 16-bit quantity from host byte order to network byte order.
Definition: uip.h:1230
uint8_t uip_ext_len
The length of the extension headers.
Definition: uip6.c:132
uip_ds6_netif_t uip_ds6_if
The single interface.
Definition: uip-ds6.c:75
uint8_t * uip_next_hdr
Type of the next header in IPv6 header or extension headers.
Definition: uip6.c:125
int rpl_process_hbh(rpl_nbr_t *sender, uint16_t sender_rank, int loop_detected, int rank_error_signaled)
Processes Hop-by-Hop (HBH) Extension Header of a packet currently being forwrded. ...
Definition: rpl-dag.c:672
int(* get_sr_node_ipaddr)(uip_ipaddr_t *addr, const uip_sr_node_t *node)
Returns the global IPv6 address of a source routing node.
Definition: routing.h:90
Header file for the Packet buffer (packetbuf) management
#define uip_is_addr_linklocal(a)
is addr (a) a link local unicast address, see RFC 4291 i.e.
Definition: uip.h:2023
Header file for the logging system
int uip_sr_is_addr_reachable(void *graph, const uip_ipaddr_t *addr)
Telle whether an address is reachable, i.e.
Definition: uip-sr.c:94
A node in a source routing graph, stored at the root and representing all child-parent relationship...
Definition: uip-sr.h:92
int rpl_ext_header_srh_update(void)
Process and update SRH in-place, i.e.