75 #include "lib/random.h"
86 #define UIP_LOG(m) uip_log(m)
104 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
105 #define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
107 #define UIP_ND6_RS_BUF ((uip_nd6_rs *)&uip_buf[uip_l2_l3_icmp_hdr_len])
108 #define UIP_ND6_RA_BUF ((uip_nd6_ra *)&uip_buf[uip_l2_l3_icmp_hdr_len])
109 #define UIP_ND6_NS_BUF ((uip_nd6_ns *)&uip_buf[uip_l2_l3_icmp_hdr_len])
110 #define UIP_ND6_NA_BUF ((uip_nd6_na *)&uip_buf[uip_l2_l3_icmp_hdr_len])
113 #define UIP_ND6_OPT_HDR_BUF ((uip_nd6_opt_hdr *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
114 #define UIP_ND6_OPT_PREFIX_BUF ((uip_nd6_opt_prefix_info *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
115 #define UIP_ND6_OPT_MTU_BUF ((uip_nd6_opt_mtu *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
118 static uint8_t nd6_opt_offset;
119 static uint8_t *nd6_opt_llao;
121 #if !UIP_CONF_ROUTER // TBD see if we move it to ra_input
123 static uip_ipaddr_t ipaddr;
132 create_llao(uint8_t *llao, uint8_t type) {
133 llao[UIP_ND6_OPT_TYPE_OFFSET] = type;
135 memcpy(&llao[UIP_ND6_OPT_DATA_OFFSET], &
uip_lladdr, UIP_LLADDR_LEN);
137 memset(&llao[UIP_ND6_OPT_DATA_OFFSET + UIP_LLADDR_LEN], 0,
148 PRINTF(
"Received NS from ");
152 PRINTF(
" with target address");
153 PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NS_BUF->tgtipaddr));
157 #if UIP_CONF_IPV6_CHECKS
161 PRINTF(
"NS received is bad\n");
168 nd6_opt_offset = UIP_ND6_NS_LEN;
169 while(uip_l3_icmp_hdr_len + nd6_opt_offset <
uip_len) {
170 #if UIP_CONF_IPV6_CHECKS
172 PRINTF(
"NS received is bad\n");
177 case UIP_ND6_OPT_SLLAO:
178 nd6_opt_llao = &uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset];
179 #if UIP_CONF_IPV6_CHECKS
182 PRINTF(
"NS received is bad\n");
186 nbr = uip_ds6_nbr_lookup(&
UIP_IP_BUF->srcipaddr);
193 if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
194 lladdr, UIP_LLADDR_LEN) != 0) {
195 memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
197 nbr->state = NBR_STALE;
200 nbr->state = NBR_STALE;
204 #if UIP_CONF_IPV6_CHECKS
209 PRINTF(
"ND option not supported in NS");
215 addr = uip_ds6_addr_lookup(&UIP_ND6_NS_BUF->tgtipaddr);
217 #if UIP_ND6_DEF_MAXDADNS > 0
220 #if UIP_CONF_IPV6_CHECKS
222 PRINTF(
"NS received is bad\n");
229 flags = UIP_ND6_NA_FLAG_OVERRIDE;
233 uip_ds6_dad_failed(addr);
242 #if UIP_CONF_IPV6_CHECKS
243 if(uip_ds6_is_my_addr(&
UIP_IP_BUF->srcipaddr)) {
250 PRINTF(
"NS received is bad\n");
259 flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE;
264 if(uip_ds6_addr_lookup(&
UIP_IP_BUF->destipaddr) == addr) {
267 flags = UIP_ND6_NA_FLAG_SOLICITED | UIP_ND6_NA_FLAG_OVERRIDE;
270 #if UIP_CONF_IPV6_CHECKS
271 PRINTF(
"NS received is bad\n");
283 flags = flags | UIP_ND6_NA_FLAG_ROUTER;
297 UIP_ND6_NA_BUF->flagsreserved = flags;
298 memcpy(&UIP_ND6_NA_BUF->tgtipaddr, &addr->ipaddr,
sizeof(uip_ipaddr_t));
300 create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NA_LEN],
310 PRINTF(
"Sending NA to ");
314 PRINTF(
" with target address ");
315 PRINT6ADDR(&UIP_ND6_NA_BUF->tgtipaddr);
344 UIP_ND6_NS_BUF->reserved = 0;
351 if(!(uip_ds6_is_my_addr(tgt))) {
358 PRINTF(
"Dropping NS due to no suitable source address\n");
365 create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NS_LEN],
372 UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NS_LEN;
373 uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NS_LEN;
380 PRINTF(
"Sending NS to");
384 PRINTF(
"with target address");
412 uint8_t is_solicited;
415 PRINTF(
"Received NA from");
419 PRINTF(
"with target address");
420 PRINT6ADDR((uip_ipaddr_t *) (&UIP_ND6_NA_BUF->tgtipaddr));
429 is_router = ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_ROUTER));
431 ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_SOLICITED));
433 ((UIP_ND6_NA_BUF->flagsreserved & UIP_ND6_NA_FLAG_OVERRIDE));
435 #if UIP_CONF_IPV6_CHECKS
440 PRINTF(
"NA received is bad\n");
446 nd6_opt_offset = UIP_ND6_NA_LEN;
448 while(uip_l3_icmp_hdr_len + nd6_opt_offset <
uip_len) {
449 #if UIP_CONF_IPV6_CHECKS
451 PRINTF(
"NA received is bad\n");
456 case UIP_ND6_OPT_TLLAO:
460 PRINTF(
"ND option not supported in NA\n");
465 addr = uip_ds6_addr_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
468 #if UIP_ND6_DEF_MAXDADNS > 0
470 uip_ds6_dad_failed(addr);
473 PRINTF(
"NA received is bad\n");
477 nbr = uip_ds6_nbr_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
482 if(nd6_opt_llao != 0) {
484 memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], (
void *)lladdr,
488 if(nd6_opt_llao ==
NULL) {
491 memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
494 nbr->state = NBR_REACHABLE;
498 stimer_set(&(nbr->reachable), uip_ds6_if.reachable_time / 1000);
501 nbr->state = NBR_STALE;
503 nbr->isrouter = is_router;
505 if(!is_override && is_llchange) {
506 if(nbr->state == NBR_REACHABLE) {
507 nbr->state = NBR_STALE;
511 if(is_override || (!is_override && nd6_opt_llao != 0 && !is_llchange)
512 || nd6_opt_llao == 0) {
513 if(nd6_opt_llao != 0) {
514 memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
518 nbr->state = NBR_REACHABLE;
520 stimer_set(&(nbr->reachable), uip_ds6_if.reachable_time / 1000);
522 if(nd6_opt_llao != 0 && is_llchange) {
523 nbr->state = NBR_STALE;
528 if(nbr->isrouter && !is_router) {
529 defrt = uip_ds6_defrt_lookup(&
UIP_IP_BUF->srcipaddr);
531 uip_ds6_defrt_rm(defrt);
534 nbr->isrouter = is_router;
537 #if UIP_CONF_IPV6_QUEUE_PKT
545 if(uip_packetqueue_buflen(&nbr->packethandle) != 0) {
546 uip_len = uip_packetqueue_buflen(&nbr->packethandle);
548 uip_packetqueue_free(&nbr->packethandle);
567 PRINTF(
"Received RS from");
575 #if UIP_CONF_IPV6_CHECKS
582 PRINTF(
"RS received is bad\n");
589 nd6_opt_offset = UIP_ND6_RS_LEN;
592 while(uip_l3_icmp_hdr_len + nd6_opt_offset <
uip_len) {
593 #if UIP_CONF_IPV6_CHECKS
595 PRINTF(
"RS received is bad\n");
600 case UIP_ND6_OPT_SLLAO:
604 PRINTF(
"ND option not supported in RS\n");
610 if(nd6_opt_llao !=
NULL) {
611 #if UIP_CONF_IPV6_CHECKS
613 PRINTF(
"RS received is bad\n");
620 (
uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 0, NBR_STALE);
623 if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
624 uip_ds6_nbr_get_ll(nbr), UIP_LLADDR_LEN) != 0) {
628 (
uip_lladdr_t *)&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET], 0, NBR_STALE);
629 nbr->reachable = nbr_data.reachable;
630 nbr->sendns = nbr_data.sendns;
631 nbr->nscount = nbr_data.nscount;
635 #if UIP_CONF_IPV6_CHECKS
641 uip_ds6_send_ra_sollicited();
650 uip_nd6_ra_output(uip_ipaddr_t * dest)
670 UIP_ND6_RA_BUF->cur_ttl = uip_ds6_if.cur_hop_limit;
672 UIP_ND6_RA_BUF->flags_reserved =
673 (UIP_ND6_M_FLAG << 7) | (UIP_ND6_O_FLAG << 6);
675 UIP_ND6_RA_BUF->router_lifetime =
uip_htons(UIP_ND6_ROUTER_LIFETIME);
678 UIP_ND6_RA_BUF->reachable_time = 0;
679 UIP_ND6_RA_BUF->retrans_timer = 0;
681 uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_RA_LEN;
682 nd6_opt_offset = UIP_ND6_RA_LEN;
689 if((prefix->isused) && (prefix->advertise)) {
690 UIP_ND6_OPT_PREFIX_BUF->type = UIP_ND6_OPT_PREFIX_INFO;
691 UIP_ND6_OPT_PREFIX_BUF->len = UIP_ND6_OPT_PREFIX_INFO_LEN / 8;
692 UIP_ND6_OPT_PREFIX_BUF->preflen = prefix->length;
693 UIP_ND6_OPT_PREFIX_BUF->flagsreserved1 = prefix->l_a_reserved;
694 UIP_ND6_OPT_PREFIX_BUF->validlt = uip_htonl(prefix->vlifetime);
695 UIP_ND6_OPT_PREFIX_BUF->preferredlt = uip_htonl(prefix->plifetime);
696 UIP_ND6_OPT_PREFIX_BUF->reserved2 = 0;
698 nd6_opt_offset += UIP_ND6_OPT_PREFIX_INFO_LEN;
699 uip_len += UIP_ND6_OPT_PREFIX_INFO_LEN;
711 UIP_ND6_OPT_MTU_BUF->type = UIP_ND6_OPT_MTU;
712 UIP_ND6_OPT_MTU_BUF->len = UIP_ND6_OPT_MTU_LEN >> 3;
713 UIP_ND6_OPT_MTU_BUF->reserved = 0;
715 UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(1500);
717 uip_len += UIP_ND6_OPT_MTU_LEN;
718 nd6_opt_offset += UIP_ND6_OPT_MTU_LEN;
727 PRINTF(
"Sending RA to");
754 UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_RS_LEN;
755 uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN;
761 create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_RS_LEN],
769 PRINTF(
"Sendin RS to");
789 PRINTF(
"Received RA from");
796 #if UIP_CONF_IPV6_CHECKS
800 PRINTF(
"RA received is bad");
805 if(UIP_ND6_RA_BUF->cur_ttl != 0) {
806 uip_ds6_if.cur_hop_limit = UIP_ND6_RA_BUF->cur_ttl;
807 PRINTF(
"uip_ds6_if.cur_hop_limit %u\n", uip_ds6_if.cur_hop_limit);
810 if(UIP_ND6_RA_BUF->reachable_time != 0) {
811 if(uip_ds6_if.base_reachable_time !=
812 uip_ntohl(UIP_ND6_RA_BUF->reachable_time)) {
813 uip_ds6_if.base_reachable_time = uip_ntohl(UIP_ND6_RA_BUF->reachable_time);
817 if(UIP_ND6_RA_BUF->retrans_timer != 0) {
818 uip_ds6_if.retrans_timer = uip_ntohl(UIP_ND6_RA_BUF->retrans_timer);
822 nd6_opt_offset = UIP_ND6_RA_LEN;
823 while(uip_l3_icmp_hdr_len + nd6_opt_offset <
uip_len) {
825 PRINTF(
"RA received is bad");
829 case UIP_ND6_OPT_SLLAO:
830 PRINTF(
"Processing SLLAO option in RA\n");
832 nbr = uip_ds6_nbr_lookup(&
UIP_IP_BUF->srcipaddr);
840 nbr->state = NBR_STALE;
842 if(memcmp(&nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
843 lladdr, UIP_LLADDR_LEN) != 0) {
844 memcpy(lladdr, &nd6_opt_llao[UIP_ND6_OPT_DATA_OFFSET],
846 nbr->state = NBR_STALE;
851 case UIP_ND6_OPT_MTU:
852 PRINTF(
"Processing MTU option in RA\n");
853 uip_ds6_if.link_mtu =
856 case UIP_ND6_OPT_PREFIX_INFO:
857 PRINTF(
"Processing PREFIX option in RA\n");
859 if((uip_ntohl(nd6_opt_prefix_info->validlt) >=
860 uip_ntohl(nd6_opt_prefix_info->preferredlt))
863 if(nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_ONLINK) {
865 uip_ds6_prefix_lookup(&nd6_opt_prefix_info->prefix,
866 nd6_opt_prefix_info->preflen);
868 if(nd6_opt_prefix_info->validlt != 0) {
870 prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix,
871 nd6_opt_prefix_info->preflen,
872 uip_ntohl(nd6_opt_prefix_info->
875 prefix = uip_ds6_prefix_add(&nd6_opt_prefix_info->prefix,
876 nd6_opt_prefix_info->preflen, 0);
880 switch (nd6_opt_prefix_info->validlt) {
882 uip_ds6_prefix_rm(prefix);
885 prefix->isinfinite = 1;
888 PRINTF(
"Updating timer of prefix");
889 PRINT6ADDR(&prefix->ipaddr);
890 PRINTF(
"new value %lu\n", uip_ntohl(nd6_opt_prefix_info->validlt));
892 uip_ntohl(nd6_opt_prefix_info->validlt));
893 prefix->isinfinite = 0;
900 if((nd6_opt_prefix_info->flagsreserved1 & UIP_ND6_RA_FLAG_AUTONOMOUS)
901 && (nd6_opt_prefix_info->validlt != 0)
902 && (nd6_opt_prefix_info->preflen == UIP_DEFAULT_PREFIX_LEN)) {
906 addr = uip_ds6_addr_lookup(&ipaddr);
907 if((addr !=
NULL) && (addr->type == ADDR_AUTOCONF)) {
910 if((uip_ntohl(nd6_opt_prefix_info->validlt) > 2 * 60 * 60) ||
911 (uip_ntohl(nd6_opt_prefix_info->validlt) >
913 PRINTF(
"Updating timer of address");
914 PRINT6ADDR(&addr->ipaddr);
915 PRINTF(
"new value %lu\n",
916 uip_ntohl(nd6_opt_prefix_info->validlt));
918 uip_ntohl(nd6_opt_prefix_info->validlt));
921 PRINTF(
"Updating timer of address ");
922 PRINT6ADDR(&addr->ipaddr);
923 PRINTF(
"new value %lu\n", (
unsigned long)(2 * 60 * 60));
925 addr->isinfinite = 0;
927 addr->isinfinite = 1;
930 if(uip_ntohl(nd6_opt_prefix_info->validlt) ==
932 uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
934 uip_ds6_addr_add(&ipaddr, uip_ntohl(nd6_opt_prefix_info->validlt),
943 PRINTF(
"ND option not supported in RA");
949 defrt = uip_ds6_defrt_lookup(&
UIP_IP_BUF->srcipaddr);
950 if(UIP_ND6_RA_BUF->router_lifetime != 0) {
957 long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime)));
960 (
unsigned long)(uip_ntohs(UIP_ND6_RA_BUF->router_lifetime)));
964 uip_ds6_defrt_rm(defrt);
968 #if UIP_CONF_IPV6_QUEUE_PKT
977 if(nbr !=
NULL && uip_packetqueue_buflen(&nbr->packethandle) != 0) {
978 uip_len = uip_packetqueue_buflen(&nbr->packethandle);
980 uip_packetqueue_free(&nbr->packethandle);
994 UIP_ICMP6_HANDLER(ns_input_handler,
ICMP6_NS, UIP_ICMP6_HANDLER_CODE_ANY,
996 UIP_ICMP6_HANDLER(na_input_handler,
ICMP6_NA, UIP_ICMP6_HANDLER_CODE_ANY,
1000 #if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
1001 UIP_ICMP6_HANDLER(rs_input_handler,
ICMP6_RS, UIP_ICMP6_HANDLER_CODE_ANY,
1005 #if !UIP_CONF_ROUTER
1006 UIP_ICMP6_HANDLER(ra_input_handler,
ICMP6_RA, UIP_ICMP6_HANDLER_CODE_ANY,
1027 #if UIP_CONF_ROUTER && UIP_ND6_SEND_RA
1032 #if !UIP_CONF_ROUTER
#define uip_create_unspecified(a)
set IP address a to unspecified
#define UIP_ND6_OPT_HDR_BUF
Pointer to ND option.
uip_len
The length of the packet in the uip_buf buffer.
#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.
CCIF uip_lladdr_t uip_lladdr
Host L2 address.
Unicast address structure.
void uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
set the last 64 bits of an IP address based on the MAC address
#define ICMP6_RS
Router Solicitation.
void uip_nd6_rs_output(void)
Send a Router Solicitation.
Network interface and stateless autoconfiguration (RFC 4862)
ND option prefix information.
#define UIP_ND6_OPT_LLAO_LEN
length of a ND6 LLAO option for default L2 type (e.g.
#define uip_is_addr_solicited_node(a)
is addr (a) a solicited node multicast address, see RFC3513 a is of type uip_ipaddr_t* ...
#define NULL
The null pointer.
#define NBR_INCOMPLETE
Possible states for the nbr cache entries.
#define uip_create_solicited_node(a, b)
put in b the solicited node address corresponding to address a both a and b are of type uip_ipaddr_t*...
void uip_log(char *msg)
Print out a uIP log message.
void uip_nd6_init()
Initialise the uIP ND core.
#define UIP_ND6_INFINITE_LIFETIME
INFINITE lifetime.
void uip_icmp6_register_input_handler(uip_icmp6_input_handler_t *handler)
Register a handler which can handle a specific ICMPv6 message type.
#define uip_create_linklocal_allrouters_mcast(a)
set IP address a to the link local all-routers multicast address
void stimer_set(struct stimer *t, unsigned long interval)
Set a timer.
uip_ds6_prefix_t uip_ds6_prefix_list[UIP_DS6_PREFIX_NB]
The single interface.
#define UIP_STAT(s)
The uIP TCP/IP statistics.
#define ICMP6_NS
Neighbor Solicitation.
#define UIP_IP_BUF
Pointer to IP header.
#define uip_is_addr_unspecified(a)
Is IPv6 address a the unspecified address a is of type uip_ipaddr_t.
uint16_t uip_icmp6chksum(void)
Calculate the ICMP checksum of the packet in uip_buf.
#define uip_ipaddr_copy(dest, src)
Copy an IP address from one place to another.
#define ICMP6_RA
Router Advertisement.
CCIF uint16_t uip_htons(uint16_t val)
Convert a 16-bit quantity from host byte order to network byte order.
uint8_t uip_ext_len
The length of the extension headers.
ICMPv6 echo request and error messages (RFC 4443)
#define uip_create_linklocal_allnodes_mcast(a)
set IP address a to the link local all-nodes multicast address
void uip_ds6_select_src(uip_ipaddr_t *src, uip_ipaddr_t *dst)
Source address selection, see RFC 3484.
#define UIP_ICMP_BUF
Pointer to ICMP header.
#define ADDR_TENTATIVE
Possible states for the an address (RFC 4862)
#define ICMP6_NA
Neighbor advertisement.
A set of debugging macros.
#define UIP_ND6_HOP_LIMIT
HOP LIMIT to be used when sending ND messages (255)
uint32_t uip_ds6_compute_reachable_time(void)
Compute the reachable time based on base reachable time, see RFC 4861.
An entry in the default router list.
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.
void uip_nd6_ns_output(uip_ipaddr_t *src, uip_ipaddr_t *dest, uip_ipaddr_t *tgt)
Send a neighbor solicitation, send a Neighbor Advertisement.
unsigned long stimer_remaining(struct stimer *t)
The time until the timer expires.
An entry in the nbr cache.