53 #include "net/rpl/rpl-private.h"
60 #define DEBUG DEBUG_NONE
66 #define RPL_DIO_GROUNDED 0x80
67 #define RPL_DIO_MOP_SHIFT 3
68 #define RPL_DIO_MOP_MASK 0x3c
69 #define RPL_DIO_PREFERENCE_MASK 0x07
71 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
72 #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
73 #define UIP_ICMP_PAYLOAD ((unsigned char *)&uip_buf[uip_l2_l3_icmp_hdr_len])
75 static void dis_input(
void);
76 static void dio_input(
void);
77 static void dao_input(
void);
78 static void dao_ack_input(
void);
81 #ifdef RPL_DEBUG_DIO_INPUT
82 void RPL_DEBUG_DIO_INPUT(uip_ipaddr_t *, rpl_dio_t *);
85 #ifdef RPL_DEBUG_DAO_OUTPUT
86 void RPL_DEBUG_DAO_OUTPUT(rpl_parent_t *);
89 static uint8_t dao_sequence = RPL_LOLLIPOP_INIT;
91 extern rpl_of_t RPL_OF;
93 #if RPL_CONF_MULTICAST
98 UIP_ICMP6_HANDLER(dis_handler,
ICMP6_RPL, RPL_CODE_DIS, dis_input);
99 UIP_ICMP6_HANDLER(dio_handler,
ICMP6_RPL, RPL_CODE_DIO, dio_input);
100 UIP_ICMP6_HANDLER(dao_handler,
ICMP6_RPL, RPL_CODE_DAO, dao_input);
101 UIP_ICMP6_HANDLER(dao_ack_handler,
ICMP6_RPL, RPL_CODE_DAO_ACK, dao_ack_input);
104 get_global_addr(uip_ipaddr_t *addr)
109 for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
110 state = uip_ds6_if.addr_list[i].state;
111 if(uip_ds6_if.addr_list[i].isused &&
114 memcpy(addr, &uip_ds6_if.addr_list[i].ipaddr,
sizeof(uip_ipaddr_t));
123 get32(uint8_t *buffer,
int pos)
125 return (uint32_t)buffer[pos] << 24 | (uint32_t)buffer[pos + 1] << 16 |
126 (uint32_t)buffer[pos + 2] << 8 | buffer[pos + 3];
130 set32(uint8_t *buffer,
int pos, uint32_t value)
132 buffer[pos++] = value >> 24;
133 buffer[pos++] = (value >> 16) & 0xff;
134 buffer[pos++] = (value >> 8) & 0xff;
135 buffer[pos++] = value & 0xff;
139 get16(uint8_t *buffer,
int pos)
141 return (uint16_t)buffer[pos] << 8 | buffer[pos + 1];
145 set16(uint8_t *buffer,
int pos, uint16_t value)
147 buffer[pos++] = value >> 8;
148 buffer[pos++] = value & 0xff;
154 rpl_instance_t *instance;
158 PRINTF(
"RPL: Received a DIS from ");
162 for(instance = &instance_table[0], end = instance + RPL_MAX_INSTANCES;
163 instance < end; ++instance) {
164 if(instance->used == 1) {
167 PRINTF(
"RPL: LEAF ONLY Multicast DIS will NOT reset DIO timer\n");
170 PRINTF(
"RPL: Multicast DIS => reset DIO timer\n");
171 rpl_reset_dio_timer(instance);
174 PRINTF(
"RPL: Unicast DIS, reply to sender\n");
183 dis_output(uip_ipaddr_t *addr)
185 unsigned char *buffer;
186 uip_ipaddr_t tmpaddr;
197 buffer = UIP_ICMP_PAYLOAD;
198 buffer[0] = buffer[1] = 0;
201 uip_create_linklocal_rplnodes_mcast(&tmpaddr);
205 PRINTF(
"RPL: Sending a DIS to ");
215 unsigned char *buffer;
216 uint8_t buffer_length;
224 memset(&dio, 0,
sizeof(dio));
227 dio.dag_intdoubl = RPL_DIO_INTERVAL_DOUBLINGS;
228 dio.dag_intmin = RPL_DIO_INTERVAL_MIN;
229 dio.dag_redund = RPL_DIO_REDUNDANCY;
230 dio.dag_min_hoprankinc = RPL_MIN_HOPRANKINC;
231 dio.dag_max_rankinc = RPL_MAX_RANKINC;
232 dio.ocp = RPL_OF.ocp;
233 dio.default_lifetime = RPL_DEFAULT_LIFETIME;
234 dio.lifetime_unit = RPL_DEFAULT_LIFETIME_UNIT;
239 PRINTF(
"RPL: Received a DIO from ");
243 if((nbr = uip_ds6_nbr_lookup(&from)) ==
NULL) {
245 packetbuf_addr(PACKETBUF_ADDR_SENDER),
246 0, NBR_REACHABLE)) !=
NULL) {
248 stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000);
249 PRINTF(
"RPL: Neighbor added to neighbor cache ");
252 PRINTLLADDR((
uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
255 PRINTF(
"RPL: Out of memory, dropping DIO from ");
258 PRINTLLADDR((
uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
263 PRINTF(
"RPL: Neighbor already in neighbor cache\n");
266 buffer_length =
uip_len - uip_l3_icmp_hdr_len;
270 buffer = UIP_ICMP_PAYLOAD;
272 dio.instance_id = buffer[i++];
273 dio.version = buffer[i++];
274 dio.rank = get16(buffer, i);
277 PRINTF(
"RPL: Incoming DIO (id, ver, rank) = (%u,%u,%u)\n",
278 (
unsigned)dio.instance_id,
279 (
unsigned)dio.version,
282 dio.grounded = buffer[i] & RPL_DIO_GROUNDED;
283 dio.mop = (buffer[i]& RPL_DIO_MOP_MASK) >> RPL_DIO_MOP_SHIFT;
284 dio.preference = buffer[i++] & RPL_DIO_PREFERENCE_MASK;
286 dio.dtsn = buffer[i++];
290 memcpy(&dio.dag_id, buffer + i,
sizeof(dio.dag_id));
291 i +=
sizeof(dio.dag_id);
293 PRINTF(
"RPL: Incoming DIO (dag_id, pref) = (");
294 PRINT6ADDR(&dio.dag_id);
295 PRINTF(
", %u)\n", dio.preference);
298 for(; i < buffer_length; i += len) {
299 subopt_type = buffer[i];
300 if(subopt_type == RPL_OPTION_PAD1) {
304 len = 2 + buffer[i + 1];
307 if(len + i > buffer_length) {
308 PRINTF(
"RPL: Invalid DIO packet\n");
309 RPL_STAT(rpl_stats.malformed_msgs++);
313 PRINTF(
"RPL: DIO option %u, length: %u\n", subopt_type, len - 2);
315 switch(subopt_type) {
316 case RPL_OPTION_DAG_METRIC_CONTAINER:
318 PRINTF(
"RPL: Invalid DAG MC, len = %d\n", len);
319 RPL_STAT(rpl_stats.malformed_msgs++);
322 dio.mc.type = buffer[i + 2];
323 dio.mc.flags = buffer[i + 3] << 1;
324 dio.mc.flags |= buffer[i + 4] >> 7;
325 dio.mc.aggr = (buffer[i + 4] >> 4) & 0x3;
326 dio.mc.prec = buffer[i + 4] & 0xf;
327 dio.mc.length = buffer[i + 5];
329 if(dio.mc.type == RPL_DAG_MC_NONE) {
331 }
else if(dio.mc.type == RPL_DAG_MC_ETX) {
332 dio.mc.obj.etx = get16(buffer, i + 6);
334 PRINTF(
"RPL: DAG MC: type %u, flags %u, aggr %u, prec %u, length %u, ETX %u\n",
335 (
unsigned)dio.mc.type,
336 (
unsigned)dio.mc.flags,
337 (
unsigned)dio.mc.aggr,
338 (
unsigned)dio.mc.prec,
339 (
unsigned)dio.mc.length,
340 (
unsigned)dio.mc.obj.etx);
341 }
else if(dio.mc.type == RPL_DAG_MC_ENERGY) {
342 dio.mc.obj.energy.flags = buffer[i + 6];
343 dio.mc.obj.energy.energy_est = buffer[i + 7];
345 PRINTF(
"RPL: Unhandled DAG MC type: %u\n", (
unsigned)dio.mc.type);
349 case RPL_OPTION_ROUTE_INFO:
351 PRINTF(
"RPL: Invalid destination prefix option, len = %d\n", len);
352 RPL_STAT(rpl_stats.malformed_msgs++);
357 dio.destination_prefix.length = buffer[i + 2];
358 dio.destination_prefix.flags = buffer[i + 3];
359 dio.destination_prefix.lifetime = get32(buffer, i + 4);
361 if(((dio.destination_prefix.length + 7) / 8) + 8 <= len &&
362 dio.destination_prefix.length <= 128) {
363 PRINTF(
"RPL: Copying destination prefix\n");
364 memcpy(&dio.destination_prefix.prefix, &buffer[i + 8],
365 (dio.destination_prefix.length + 7) / 8);
367 PRINTF(
"RPL: Invalid route info option, len = %d\n", len);
368 RPL_STAT(rpl_stats.malformed_msgs++);
373 case RPL_OPTION_DAG_CONF:
375 PRINTF(
"RPL: Invalid DAG configuration option, len = %d\n", len);
376 RPL_STAT(rpl_stats.malformed_msgs++);
381 dio.dag_intdoubl = buffer[i + 3];
382 dio.dag_intmin = buffer[i + 4];
383 dio.dag_redund = buffer[i + 5];
384 dio.dag_max_rankinc = get16(buffer, i + 6);
385 dio.dag_min_hoprankinc = get16(buffer, i + 8);
386 dio.ocp = get16(buffer, i + 10);
388 dio.default_lifetime = buffer[i + 13];
389 dio.lifetime_unit = get16(buffer, i + 14);
390 PRINTF(
"RPL: DAG conf:dbl=%d, min=%d red=%d maxinc=%d mininc=%d ocp=%d d_l=%u l_u=%u\n",
391 dio.dag_intdoubl, dio.dag_intmin, dio.dag_redund,
392 dio.dag_max_rankinc, dio.dag_min_hoprankinc, dio.ocp,
393 dio.default_lifetime, dio.lifetime_unit);
395 case RPL_OPTION_PREFIX_INFO:
397 PRINTF(
"RPL: Invalid DAG prefix info, len != 32\n");
398 RPL_STAT(rpl_stats.malformed_msgs++);
401 dio.prefix_info.length = buffer[i + 2];
402 dio.prefix_info.flags = buffer[i + 3];
405 dio.prefix_info.lifetime = get32(buffer, i + 8);
407 PRINTF(
"RPL: Copying prefix information\n");
408 memcpy(&dio.prefix_info.prefix, &buffer[i + 16], 16);
411 PRINTF(
"RPL: Unsupported suboption type in DIO: %u\n",
412 (
unsigned)subopt_type);
416 #ifdef RPL_DEBUG_DIO_INPUT
417 RPL_DEBUG_DIO_INPUT(&from, &dio);
420 rpl_process_dio(&from, &dio);
426 dio_output(rpl_instance_t *instance, uip_ipaddr_t *uc_addr)
428 unsigned char *buffer;
430 rpl_dag_t *dag = instance->current_dag;
438 if(uc_addr ==
NULL) {
439 PRINTF(
"RPL: LEAF ONLY have multicast addr: skip dio_output\n");
447 buffer = UIP_ICMP_PAYLOAD;
448 buffer[pos++] = instance->instance_id;
449 buffer[pos++] = dag->version;
452 PRINTF(
"RPL: LEAF ONLY DIO rank set to INFINITE_RANK\n");
453 set16(buffer, pos, INFINITE_RANK);
455 set16(buffer, pos, dag->rank);
461 buffer[pos] |= RPL_DIO_GROUNDED;
464 buffer[pos] |= instance->mop << RPL_DIO_MOP_SHIFT;
465 buffer[pos] |= dag->preference & RPL_DIO_PREFERENCE_MASK;
468 buffer[pos++] = instance->dtsn_out;
471 RPL_LOLLIPOP_INCREMENT(instance->dtsn_out);
477 memcpy(buffer + pos, &dag->dag_id,
sizeof(dag->dag_id));
481 if(instance->mc.type != RPL_DAG_MC_NONE) {
482 instance->of->update_metric_container(instance);
484 buffer[pos++] = RPL_OPTION_DAG_METRIC_CONTAINER;
486 buffer[pos++] = instance->mc.type;
487 buffer[pos++] = instance->mc.flags >> 1;
488 buffer[pos] = (instance->mc.flags & 1) << 7;
489 buffer[pos++] |= (instance->mc.aggr << 4) | instance->mc.prec;
490 if(instance->mc.type == RPL_DAG_MC_ETX) {
492 set16(buffer, pos, instance->mc.obj.etx);
494 }
else if(instance->mc.type == RPL_DAG_MC_ENERGY) {
496 buffer[pos++] = instance->mc.obj.energy.flags;
497 buffer[pos++] = instance->mc.obj.energy.energy_est;
499 PRINTF(
"RPL: Unable to send DIO because of unhandled DAG MC type %u\n",
500 (
unsigned)instance->mc.type);
507 buffer[pos++] = RPL_OPTION_DAG_CONF;
510 buffer[pos++] = instance->dio_intdoubl;
511 buffer[pos++] = instance->dio_intmin;
512 buffer[pos++] = instance->dio_redundancy;
513 set16(buffer, pos, instance->max_rankinc);
515 set16(buffer, pos, instance->min_hoprankinc);
518 set16(buffer, pos, instance->of->ocp);
521 buffer[pos++] = instance->default_lifetime;
522 set16(buffer, pos, instance->lifetime_unit);
526 if(dag->prefix_info.length > 0) {
527 buffer[pos++] = RPL_OPTION_PREFIX_INFO;
529 buffer[pos++] = dag->prefix_info.length;
530 buffer[pos++] = dag->prefix_info.flags;
531 set32(buffer, pos, dag->prefix_info.lifetime);
533 set32(buffer, pos, dag->prefix_info.lifetime);
535 memset(&buffer[pos], 0, 4);
537 memcpy(&buffer[pos], &dag->prefix_info.prefix, 16);
539 PRINTF(
"RPL: Sending prefix info in DIO for ");
540 PRINT6ADDR(&dag->prefix_info.prefix);
543 PRINTF(
"RPL: No prefix to announce (len %d)\n",
544 dag->prefix_info.length);
548 #if (DEBUG) & DEBUG_PRINT
549 if(uc_addr ==
NULL) {
550 PRINTF(
"RPL: LEAF ONLY sending unicast-DIO from multicast-DIO\n");
553 PRINTF(
"RPL: Sending unicast-DIO with rank %u to ",
554 (
unsigned)dag->rank);
560 if(uc_addr ==
NULL) {
561 PRINTF(
"RPL: Sending a multicast-DIO with rank %u\n",
562 (
unsigned)instance->current_dag->rank);
563 uip_create_linklocal_rplnodes_mcast(&addr);
566 PRINTF(
"RPL: Sending unicast-DIO with rank %u to ",
567 (
unsigned)instance->current_dag->rank);
578 uip_ipaddr_t dao_sender_addr;
580 rpl_instance_t *instance;
581 unsigned char *buffer;
594 uint8_t buffer_length;
599 rpl_parent_t *parent;
608 PRINTF(
"RPL: Received a DAO from ");
609 PRINT6ADDR(&dao_sender_addr);
612 buffer = UIP_ICMP_PAYLOAD;
613 buffer_length =
uip_len - uip_l3_icmp_hdr_len;
616 instance_id = buffer[pos++];
618 instance = rpl_get_instance(instance_id);
619 if(instance ==
NULL) {
620 PRINTF(
"RPL: Ignoring a DAO for an unknown RPL instance(%u)\n",
625 lifetime = instance->default_lifetime;
627 flags = buffer[pos++];
630 sequence = buffer[pos++];
632 dag = instance->current_dag;
634 if(flags & RPL_DAO_D_FLAG) {
635 if(memcmp(&dag->dag_id, &buffer[pos],
sizeof(dag->dag_id))) {
636 PRINTF(
"RPL: Ignoring a DAO for a DAG different from ours\n");
643 RPL_ROUTE_FROM_MULTICAST_DAO : RPL_ROUTE_FROM_UNICAST_DAO;
645 PRINTF(
"RPL: DAO from %s\n",
646 learned_from == RPL_ROUTE_FROM_UNICAST_DAO?
"unicast":
"multicast");
647 if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) {
649 parent = rpl_find_parent(dag, &dao_sender_addr);
653 DAG_RANK(parent->rank, instance) < DAG_RANK(dag->rank, instance)) {
654 PRINTF(
"RPL: Loop detected when receiving a unicast DAO from a node with a lower rank! (%u < %u)\n",
655 DAG_RANK(parent->rank, instance), DAG_RANK(dag->rank, instance));
656 parent->rank = INFINITE_RANK;
657 parent->flags |= RPL_PARENT_FLAG_UPDATED;
662 if(parent !=
NULL && parent == dag->preferred_parent) {
663 PRINTF(
"RPL: Loop detected when receiving a unicast DAO from our parent\n");
664 parent->rank = INFINITE_RANK;
665 parent->flags |= RPL_PARENT_FLAG_UPDATED;
671 for(i = pos; i < buffer_length; i += len) {
672 subopt_type = buffer[i];
673 if(subopt_type == RPL_OPTION_PAD1) {
677 len = 2 + buffer[i + 1];
680 switch(subopt_type) {
681 case RPL_OPTION_TARGET:
683 prefixlen = buffer[i + 3];
684 memset(&prefix, 0,
sizeof(prefix));
685 memcpy(&prefix, buffer + i + 4, (prefixlen + 7) / CHAR_BIT);
687 case RPL_OPTION_TRANSIT:
691 lifetime = buffer[i + 5];
697 PRINTF(
"RPL: DAO lifetime: %u, prefix length: %u prefix: ",
698 (
unsigned)lifetime, (
unsigned)prefixlen);
702 #if RPL_CONF_MULTICAST
704 mcast_group = uip_mcast6_route_add(&prefix);
706 mcast_group->dag = dag;
707 mcast_group->lifetime = RPL_LIFETIME(instance, lifetime);
713 rep = uip_ds6_route_lookup(&prefix);
715 if(lifetime == RPL_ZERO_LIFETIME) {
716 PRINTF(
"RPL: No-Path DAO received\n");
719 rep->state.nopath_received == 0 &&
720 rep->length == prefixlen &&
721 uip_ds6_route_nexthop(rep) !=
NULL &&
722 uip_ipaddr_cmp(uip_ds6_route_nexthop(rep), &dao_sender_addr)) {
723 PRINTF(
"RPL: Setting expiration timer for prefix ");
726 rep->state.nopath_received = 1;
727 rep->state.lifetime = DAO_EXPIRATION_TIMEOUT;
731 if(dag->preferred_parent !=
NULL &&
732 rpl_get_parent_ipaddr(dag->preferred_parent) !=
NULL) {
733 PRINTF(
"RPL: Forwarding no-path DAO to parent ");
734 PRINT6ADDR(rpl_get_parent_ipaddr(dag->preferred_parent));
739 if(flags & RPL_DAO_K_FLAG) {
740 dao_ack_output(instance, &dao_sender_addr, sequence);
746 PRINTF(
"RPL: adding DAO route\n");
748 if((nbr = uip_ds6_nbr_lookup(&dao_sender_addr)) ==
NULL) {
751 0, NBR_REACHABLE)) !=
NULL) {
753 stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000);
754 PRINTF(
"RPL: Neighbor added to neighbor cache ");
755 PRINT6ADDR(&dao_sender_addr);
757 PRINTLLADDR((
uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
760 PRINTF(
"RPL: Out of Memory, dropping DAO from ");
761 PRINT6ADDR(&dao_sender_addr);
763 PRINTLLADDR((
uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
768 PRINTF(
"RPL: Neighbor already in neighbor cache\n");
771 rpl_lock_parent(parent);
773 rep = rpl_add_route(dag, &prefix, prefixlen, &dao_sender_addr);
775 RPL_STAT(rpl_stats.mem_overflows++);
776 PRINTF(
"RPL: Could not add a route after receiving a DAO\n");
780 rep->state.lifetime = RPL_LIFETIME(instance, lifetime);
781 rep->state.learned_from = learned_from;
783 #if RPL_CONF_MULTICAST
787 if(learned_from == RPL_ROUTE_FROM_UNICAST_DAO) {
788 if(dag->preferred_parent !=
NULL &&
789 rpl_get_parent_ipaddr(dag->preferred_parent) !=
NULL) {
790 PRINTF(
"RPL: Forwarding DAO to parent ");
791 PRINT6ADDR(rpl_get_parent_ipaddr(dag->preferred_parent));
796 if(flags & RPL_DAO_K_FLAG) {
797 dao_ack_output(instance, &dao_sender_addr, sequence);
804 dao_output(rpl_parent_t *parent, uint8_t lifetime)
809 if(get_global_addr(&prefix) == 0) {
810 PRINTF(
"RPL: No global address set for this node - suppressing DAO\n");
815 dao_output_target(parent, &prefix, lifetime);
819 dao_output_target(rpl_parent_t *parent, uip_ipaddr_t *prefix, uint8_t lifetime)
822 rpl_instance_t *instance;
823 unsigned char *buffer;
835 PRINTF(
"RPL dao_output_target error parent NULL\n");
841 PRINTF(
"RPL dao_output_target error dag NULL\n");
845 instance = dag->instance;
847 if(instance ==
NULL) {
848 PRINTF(
"RPL dao_output_target error instance NULL\n");
852 PRINTF(
"RPL dao_output_target error prefix NULL\n");
855 #ifdef RPL_DEBUG_DAO_OUTPUT
856 RPL_DEBUG_DAO_OUTPUT(parent);
859 buffer = UIP_ICMP_PAYLOAD;
861 RPL_LOLLIPOP_INCREMENT(dao_sequence);
864 buffer[pos++] = instance->instance_id;
866 #if RPL_DAO_SPECIFY_DAG
867 buffer[pos] |= RPL_DAO_D_FLAG;
870 buffer[pos] |= RPL_DAO_K_FLAG;
874 buffer[pos++] = dao_sequence;
875 #if RPL_DAO_SPECIFY_DAG
876 memcpy(buffer + pos, &dag->dag_id,
sizeof(dag->dag_id));
877 pos+=
sizeof(dag->dag_id);
881 prefixlen =
sizeof(*prefix) * CHAR_BIT;
882 buffer[pos++] = RPL_OPTION_TARGET;
883 buffer[pos++] = 2 + ((prefixlen + 7) / CHAR_BIT);
885 buffer[pos++] = prefixlen;
886 memcpy(buffer + pos, prefix, (prefixlen + 7) / CHAR_BIT);
887 pos += ((prefixlen + 7) / CHAR_BIT);
890 buffer[pos++] = RPL_OPTION_TRANSIT;
895 buffer[pos++] = lifetime;
897 PRINTF(
"RPL: Sending DAO with prefix ");
900 PRINT6ADDR(rpl_get_parent_ipaddr(parent));
903 if(rpl_get_parent_ipaddr(parent) !=
NULL) {
912 unsigned char *buffer;
913 uint8_t buffer_length;
918 buffer = UIP_ICMP_PAYLOAD;
919 buffer_length =
uip_len - uip_l3_icmp_hdr_len;
921 instance_id = buffer[0];
922 sequence = buffer[2];
925 PRINTF(
"RPL: Received a DAO ACK with sequence number %d and status %d from ",
934 dao_ack_output(rpl_instance_t *instance, uip_ipaddr_t *dest, uint8_t sequence)
936 unsigned char *buffer;
938 PRINTF(
"RPL: Sending a DAO ACK with sequence number %d to ", sequence);
942 buffer = UIP_ICMP_PAYLOAD;
944 buffer[0] = instance->instance_id;
946 buffer[2] = sequence;
953 rpl_icmp6_register_handlers()
uip_len
The length of the packet in the uip_buf buffer.
An entry in the routing table.
#define uip_is_addr_mcast(a)
is address a multicast address, see RFC 3513 a is of type uip_ipaddr_t*
Neighbor discovery (RFC 4861)
#define uip_is_addr_link_local(a)
is addr (a) a link local unicast address, see RFC3513 i.e.
This header file contains configuration directives for uIPv6 multicast support.
Header file for the uIP TCP/IP stack.
Header for the Contiki/uIP interface.
Network interface and stateless autoconfiguration (RFC 4862)
Header file for the Rime buffer (packetbuf) management
#define NULL
The null pointer.
An entry in the multicast routing table.
#define uip_is_addr_mcast_global(a)
is address a global multicast address (FFxE::/16), a is of type uip_ip6addr_t*
void uip_icmp6_register_input_handler(uip_icmp6_input_handler_t *handler)
Register a handler which can handle a specific ICMPv6 message type.
void stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
#define UIP_IP_BUF
Pointer to IP header.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
void uip_icmp6_send(const uip_ipaddr_t *dest, int type, int code, int payload_len)
Send an icmpv6 message.
ICMPv6 echo request and error messages (RFC 4443)
enum rpl_mode rpl_get_mode(void)
Get the RPL mode.
#define ADDR_TENTATIVE
Possible states for the an address (RFC 4862)
A set of debugging macros.
uip_ds6_nbr_t * uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr, uint8_t isrouter, uint8_t state)
Neighbor Cache basic routines.
An entry in the nbr cache.