68#ifdef LWIP_HOOK_FILENAME
69#include LWIP_HOOK_FILENAME
72#if LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK
73#error LWIP_IPV6_DUP_DETECT_ATTEMPTS > IP6_ADDR_TENTATIVE_COUNT_MASK
75#if LWIP_ND6_NUM_NEIGHBORS > 127
76#error LWIP_ND6_NUM_NEIGHBORS must fit into an s8_t (max value: 127)
78#if LWIP_ND6_NUM_DESTINATIONS > 32767
79#error LWIP_ND6_NUM_DESTINATIONS must fit into an s16_t (max value: 32767)
81#if LWIP_ND6_NUM_PREFIXES > 127
82#error LWIP_ND6_NUM_PREFIXES must fit into an s8_t (max value: 127)
84#if LWIP_ND6_NUM_ROUTERS > 127
85#error LWIP_ND6_NUM_ROUTERS must fit into an s8_t (max value: 127)
99static u8_t nd6_queue_size = 0;
106static ip6_addr_t multicast_address;
108static u8_t nd6_tmr_rs_reduction;
115#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
119static union ra_options nd6_ra_buffer;
122static s8_t nd6_find_neighbor_cache_entry(
const ip6_addr_t *ip6addr);
123static s8_t nd6_new_neighbor_cache_entry(
void);
124static void nd6_free_neighbor_cache_entry(
s8_t i);
125static s16_t nd6_find_destination_cache_entry(
const ip6_addr_t *ip6addr);
126static s16_t nd6_new_destination_cache_entry(
void);
127static int nd6_is_prefix_in_netif(
const ip6_addr_t *ip6addr,
struct netif *
netif);
128static s8_t nd6_select_router(
const ip6_addr_t *ip6addr,
struct netif *
netif);
129static s8_t nd6_get_router(
const ip6_addr_t *router_addr,
struct netif *
netif);
130static s8_t nd6_new_router(
const ip6_addr_t *router_addr,
struct netif *
netif);
133static s8_t nd6_get_next_hop_entry(
const ip6_addr_t *ip6addr,
struct netif *
netif);
134static err_t nd6_queue_packet(
s8_t neighbor_index,
struct pbuf *
q);
136#define ND6_SEND_FLAG_MULTICAST_DEST 0x01
137#define ND6_SEND_FLAG_ALLNODES_DEST 0x02
138#define ND6_SEND_FLAG_ANY_SRC 0x04
141static void nd6_send_neighbor_cache_probe(
struct nd6_neighbor_cache_entry *
entry,
u8_t flags);
142#if LWIP_IPV6_SEND_ROUTER_SOLICIT
147static void nd6_free_q(
struct nd6_q_entry *
q);
149#define nd6_free_q(q) pbuf_free(q)
151static void nd6_send_q(
s8_t i);
170 netif_ip6_addr_set_state(
netif, addr_idx, IP6_ADDR_DUPLICATED);
172#if LWIP_IPV6_AUTOCONFIG
181 if (!ip6_addr_isinvalid(netif_ip6_addr_state(
netif,
i)) &&
182 !netif_ip6_addr_isstatic(
netif,
i)) {
183 netif_ip6_addr_set_state(
netif,
i, IP6_ADDR_DUPLICATED);
190#if LWIP_IPV6_AUTOCONFIG
201nd6_process_autoconfig_prefix(
struct netif *
netif,
202 struct prefix_option *prefix_opt,
const ip6_addr_t *prefix_addr)
205 u32_t valid_life, pref_life;
211 valid_life =
lwip_htonl(prefix_opt->valid_lifetime);
212 pref_life =
lwip_htonl(prefix_opt->preferred_lifetime);
213 if (pref_life > valid_life || prefix_opt->prefix_length != 64) {
226 addr_state = netif_ip6_addr_state(
netif,
i);
227 if (!ip6_addr_isinvalid(addr_state) && !netif_ip6_addr_isstatic(
netif,
i) &&
228 ip6_addr_net_eq(prefix_addr, netif_ip6_addr(
netif,
i))) {
231 u32_t remaining_life = netif_ip6_addr_valid_life(
netif,
i);
232 if (valid_life > ND6_2HRS || valid_life > remaining_life) {
233 netif_ip6_addr_set_valid_life(
netif,
i, valid_life);
234 }
else if (remaining_life > ND6_2HRS) {
235 netif_ip6_addr_set_valid_life(
netif,
i, ND6_2HRS);
241 if (pref_life > 0 && addr_state == IP6_ADDR_DEPRECATED) {
242 netif_ip6_addr_set_state(
netif,
i, IP6_ADDR_PREFERRED);
244 netif_ip6_addr_set_pref_life(
netif,
i, pref_life);
258 addr_state = netif_ip6_addr_state(
netif, 0);
259 if (!
netif->ip6_autoconfig_enabled || valid_life == IP6_ADDR_LIFE_STATIC ||
260 ip6_addr_isinvalid(addr_state) || ip6_addr_isduplicated(addr_state)) {
269 IP6_ADDR(&ip6addr, prefix_addr->addr[0], prefix_addr->addr[1],
271 ip6_addr_assign_zone(&ip6addr, IP6_UNICAST,
netif);
275 if (!ip6_addr_isinvalid(netif_ip6_addr_state(
netif,
i))) {
276 if (ip6_addr_eq(&ip6addr, netif_ip6_addr(
netif,
i))) {
279 }
else if (free_idx == 0) {
289 netif_ip6_addr_set_valid_life(
netif, free_idx, valid_life);
290 netif_ip6_addr_set_pref_life(
netif, free_idx, pref_life);
291 netif_ip6_addr_set_state(
netif, free_idx, IP6_ADDR_TENTATIVE);
316 ip6_addr_t target_address;
330 ip6_addr_copy_from_packed(target_address, na_hdr->target_address);
331 ip6_addr_assign_zone(&target_address, IP6_UNICAST, inp);
334 if (
IP6H_HOPLIM(ip6_current_header()) != ND6_HOPLIM || na_hdr->code != 0 ||
335 ip6_addr_ismulticast(&target_address)) {
346 if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
351#if LWIP_IPV6_DUP_DETECT_ATTEMPTS
354 if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp,
i)) &&
355 !ip6_addr_isduplicated(netif_ip6_addr_state(inp,
i)) &&
356 ip6_addr_eq(&target_address, netif_ip6_addr(inp,
i))) {
358 nd6_duplicate_addr_detected(inp,
i);
367 if (
p->len < (
sizeof(
struct na_header) + 2)) {
377 if (
p->len < (
sizeof(
struct na_header) + (lladdr_opt->length << 3))) {
386 i = nd6_find_neighbor_cache_entry(&target_address);
398 i = nd6_find_neighbor_cache_entry(&target_address);
407 (neighbor_cache[
i].state == ND6_INCOMPLETE)) {
409 if (
p->len < (
sizeof(
struct na_header) + 2)) {
419 if (
p->len < (
sizeof(
struct na_header) + (lladdr_opt->length << 3))) {
430 neighbor_cache[
i].netif = inp;
431 neighbor_cache[
i].
state = ND6_REACHABLE;
432 neighbor_cache[
i].counter.reachable_time = reachable_time;
435 if (neighbor_cache[
i].
q !=
NULL) {
446 ip6_addr_t target_address;
461 ip6_addr_copy_from_packed(target_address, ns_hdr->target_address);
462 ip6_addr_assign_zone(&target_address, IP6_UNICAST, inp);
465 if (
IP6H_HOPLIM(ip6_current_header()) != ND6_HOPLIM || ns_hdr->code != 0 ||
466 ip6_addr_ismulticast(&target_address)) {
478 if (
p->len >= (
sizeof(
struct ns_header) + 2)) {
480 if (
p->len < (
sizeof(
struct ns_header) + (lladdr_opt->length << 3))) {
490 if ((ip6_addr_isvalid(netif_ip6_addr_state(inp,
i)) ||
491 (ip6_addr_istentative(netif_ip6_addr_state(inp,
i)) &&
492 ip6_addr_isany(ip6_current_src_addr()))) &&
493 ip6_addr_eq(&target_address, netif_ip6_addr(inp,
i))) {
506 if (ip6_addr_isany(ip6_current_src_addr())) {
509 if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp,
i)) &&
510 ip6_addr_eq(&target_address, netif_ip6_addr(inp,
i))) {
512 nd6_send_na(inp, netif_ip6_addr(inp,
i),
ND6_FLAG_OVERRIDE | ND6_SEND_FLAG_ALLNODES_DEST);
513 if (ip6_addr_istentative(netif_ip6_addr_state(inp,
i))) {
515 nd6_duplicate_addr_detected(inp,
i);
522 if (lladdr_opt ==
NULL) {
530 i = nd6_find_neighbor_cache_entry(ip6_current_src_addr());
533 if (neighbor_cache[
i].
state == ND6_INCOMPLETE) {
534 neighbor_cache[
i].netif = inp;
538 neighbor_cache[
i].state = ND6_DELAY;
545 i = nd6_new_neighbor_cache_entry();
553 neighbor_cache[
i].netif = inp;
555 ip6_addr_set(&(neighbor_cache[
i].next_hop_address), ip6_current_src_addr());
559 neighbor_cache[
i].state = ND6_DELAY;
574#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
576 u8_t rdnss_server_idx = 0;
591 if (!ip6_addr_islinklocal(ip6_current_src_addr()) ||
592 IP6H_HOPLIM(ip6_current_header()) != ND6_HOPLIM || ra_hdr->code != 0) {
602#if LWIP_IPV6_SEND_ROUTER_SOLICIT
605 (nd6_send_rs(inp) ==
ERR_OK)) {
613 i = nd6_get_router(ip6_current_src_addr(), inp);
616 i = nd6_new_router(ip6_current_src_addr(), inp);
627 default_router_list[
i].invalidation_timer =
lwip_htons(ra_hdr->router_lifetime);
630#if LWIP_ND6_ALLOW_RA_UPDATES
631 if (ra_hdr->retrans_timer > 0) {
632 retrans_timer =
lwip_htonl(ra_hdr->retrans_timer);
634 if (ra_hdr->reachable_time > 0) {
635 reachable_time =
lwip_htonl(ra_hdr->reachable_time);
643 default_router_list[
i].flags = ra_hdr->flags;
655 while ((
p->tot_len -
offset) >= 2) {
659 if (option_len8 <= 0) {
661 goto lenerr_drop_free_return;
663 option_len = ((
u8_t)option_len8) << 3;
664 if (option_len >
p->tot_len -
offset) {
666 goto lenerr_drop_free_return;
668 if (
p->len ==
p->tot_len) {
673 if (option_len >
sizeof(nd6_ra_buffer)) {
677 goto lenerr_drop_free_return;
680 option_len =
sizeof(nd6_ra_buffer);
686 switch (option_type) {
691 goto lenerr_drop_free_return;
694 if ((default_router_list[
i].neighbor_entry !=
NULL) &&
695 (default_router_list[
i].neighbor_entry->state == ND6_INCOMPLETE)) {
696 SMEMCPY(default_router_list[
i].neighbor_entry->lladdr, lladdr_opt->addr, inp->
hwaddr_len);
697 default_router_list[
i].neighbor_entry->state = ND6_REACHABLE;
698 default_router_list[
i].neighbor_entry->counter.reachable_time = reachable_time;
707 goto lenerr_drop_free_return;
712#if LWIP_ND6_ALLOW_RA_UPDATES
717 inp->mtu6 = (
u16_t)mtu32;
726 ip6_addr_t prefix_addr;
728 goto lenerr_drop_free_return;
734 ip6_addr_copy_from_packed(prefix_addr, prefix_opt->prefix);
735 ip6_addr_assign_zone(&prefix_addr, IP6_UNICAST, inp);
737 if (!ip6_addr_islinklocal(&prefix_addr)) {
739 (prefix_opt->prefix_length == 64)) {
744 valid_life =
lwip_htonl(prefix_opt->valid_lifetime);
747 prefix = nd6_get_onlink_prefix(&prefix_addr, inp);
748 if (prefix < 0 && valid_life > 0) {
750 prefix = nd6_new_onlink_prefix(&prefix_addr, inp);
753 prefix_list[
prefix].invalidation_timer = valid_life;
756#if LWIP_IPV6_AUTOCONFIG
759 nd6_process_autoconfig_prefix(inp, prefix_opt, &prefix_addr);
772#if LWIP_ND6_RDNSS_MAX_DNS_SERVERS
779 goto lenerr_drop_free_return;
783 num = (rdnss_opt->length - 1) / 2;
790 ip6_addr_assign_zone(
ip_2_ip6(&rdnss_address), IP6_UNKNOWN, inp);
792 if (
htonl(rdnss_opt->lifetime) > 0) {
794 dns_setserver(rdnss_server_idx++, &rdnss_address);
801 dns_setserver(
s,
NULL);
825 ip6_addr_t destination_address, target_address;
839 ip6_addr_copy_from_packed(destination_address, redir_hdr->destination_address);
840 ip6_addr_assign_zone(&destination_address, IP6_UNICAST, inp);
843 if (!ip6_addr_islinklocal(ip6_current_src_addr()) ||
845 redir_hdr->code != 0 || ip6_addr_ismulticast(&destination_address)) {
858 if (
p->len < (
sizeof(
struct redirect_header) + (lladdr_opt->length << 3))) {
866 dest_idx = nd6_find_destination_cache_entry(&destination_address);
874 ip6_addr_copy_from_packed(target_address, redir_hdr->target_address);
875 ip6_addr_assign_zone(&target_address, IP6_UNICAST, inp);
878 ip6_addr_copy(destination_cache[dest_idx].next_hop_addr, target_address);
881 if (lladdr_opt !=
NULL) {
883 i = nd6_find_neighbor_cache_entry(&target_address);
885 i = nd6_new_neighbor_cache_entry();
887 neighbor_cache[
i].netif = inp;
889 ip6_addr_copy(neighbor_cache[
i].next_hop_address, target_address);
893 neighbor_cache[
i].state = ND6_DELAY;
898 if (neighbor_cache[
i].
state == ND6_INCOMPLETE) {
902 neighbor_cache[
i].state = ND6_DELAY;
915 ip6_addr_t destination_address;
930 ip6_addr_copy_from_packed(destination_address, ip6hdr->dest);
931 ip6_addr_assign_zone(&destination_address, IP6_UNKNOWN, inp);
934 dest_idx = nd6_find_destination_cache_entry(&destination_address);
943 destination_cache[dest_idx].pmtu = (
u16_t)
LWIP_MIN(pmtu, 0xFFFF);
956lenerr_drop_free_return:
981 switch (neighbor_cache[
i].
state) {
984 (!neighbor_cache[
i].isrouter)) {
986 nd6_free_neighbor_cache_entry(
i);
989 neighbor_cache[
i].counter.probes_sent++;
990 nd6_send_neighbor_cache_probe(&neighbor_cache[
i], ND6_SEND_FLAG_MULTICAST_DEST);
995 if (neighbor_cache[
i].
q !=
NULL) {
998 if (neighbor_cache[
i].
counter.reachable_time <= ND6_TMR_INTERVAL) {
1000 neighbor_cache[
i].state = ND6_STALE;
1001 neighbor_cache[
i].counter.stale_time = 0;
1003 neighbor_cache[
i].counter.reachable_time -= ND6_TMR_INTERVAL;
1007 neighbor_cache[
i].counter.stale_time++;
1010 if (neighbor_cache[
i].
counter.delay_time <= 1) {
1012 neighbor_cache[
i].state = ND6_PROBE;
1013 neighbor_cache[
i].counter.probes_sent = 0;
1015 neighbor_cache[
i].counter.delay_time--;
1020 (!neighbor_cache[
i].isrouter)) {
1022 nd6_free_neighbor_cache_entry(
i);
1025 neighbor_cache[
i].counter.probes_sent++;
1026 nd6_send_neighbor_cache_probe(&neighbor_cache[
i], 0);
1038 destination_cache[
i].age++;
1043 if (default_router_list[
i].neighbor_entry !=
NULL) {
1045 if (default_router_list[
i].invalidation_timer <= ND6_TMR_INTERVAL / 1000) {
1050 if (ip6_addr_eq(&destination_cache[
j].next_hop_addr,
1051 &default_router_list[
i].neighbor_entry->next_hop_address)) {
1052 ip6_addr_set_any(&destination_cache[
j].destination_addr);
1055 default_router_list[
i].neighbor_entry->isrouter = 0;
1056 default_router_list[
i].neighbor_entry =
NULL;
1057 default_router_list[
i].invalidation_timer = 0;
1058 default_router_list[
i].flags = 0;
1060 default_router_list[
i].invalidation_timer -= ND6_TMR_INTERVAL / 1000;
1068 if (prefix_list[
i].invalidation_timer <= ND6_TMR_INTERVAL / 1000) {
1070 prefix_list[
i].invalidation_timer = 0;
1071 prefix_list[
i].netif =
NULL;
1073 prefix_list[
i].invalidation_timer -= ND6_TMR_INTERVAL / 1000;
1082#if LWIP_IPV6_ADDRESS_LIFETIMES
1084 addr_state = netif_ip6_addr_state(
netif,
i);
1098 if (!ip6_addr_isinvalid(addr_state) &&
1099 !netif_ip6_addr_isstatic(
netif,
i)) {
1101 if (life <= ND6_TMR_INTERVAL / 1000) {
1103 netif_ip6_addr_set_valid_life(
netif,
i, 0);
1104 netif_ip6_addr_set_pref_life(
netif,
i, 0);
1105 netif_ip6_addr_set_state(
netif,
i, IP6_ADDR_INVALID);
1107 if (!ip6_addr_life_isinfinite(life)) {
1108 life -= ND6_TMR_INTERVAL / 1000;
1109 LWIP_ASSERT(
"bad valid lifetime", life != IP6_ADDR_LIFE_STATIC);
1110 netif_ip6_addr_set_valid_life(
netif,
i, life);
1113 life = netif_ip6_addr_pref_life(
netif,
i);
1114 if (life <= ND6_TMR_INTERVAL / 1000) {
1117 netif_ip6_addr_set_pref_life(
netif,
i, 0);
1118 if (addr_state == IP6_ADDR_PREFERRED)
1119 netif_ip6_addr_set_state(
netif,
i, IP6_ADDR_DEPRECATED);
1120 }
else if (!ip6_addr_life_isinfinite(life)) {
1121 life -= ND6_TMR_INTERVAL / 1000;
1122 netif_ip6_addr_set_pref_life(
netif,
i, life);
1129 addr_state = netif_ip6_addr_state(
netif,
i);
1130 if (ip6_addr_istentative(addr_state)) {
1135 addr_state = IP6_ADDR_PREFERRED;
1136#if LWIP_IPV6_ADDRESS_LIFETIMES
1137 if (!netif_ip6_addr_isstatic(
netif,
i) &&
1138 netif_ip6_addr_pref_life(
netif,
i) == 0) {
1139 addr_state = IP6_ADDR_DEPRECATED;
1142 netif_ip6_addr_set_state(
netif,
i, addr_state);
1145 netif_ip6_addr_set_state(
netif,
i, addr_state + 1);
1150 ND6_SEND_FLAG_MULTICAST_DEST | ND6_SEND_FLAG_ANY_SRC);
1156#if LWIP_IPV6_SEND_ROUTER_SOLICIT
1158 if (!nd6_tmr_rs_reduction) {
1159 nd6_tmr_rs_reduction = (ND6_RTR_SOLICITATION_INTERVAL / ND6_TMR_INTERVAL) - 1;
1163 !ip6_addr_isinvalid(netif_ip6_addr_state(
netif, 0)) &&
1164 !ip6_addr_isduplicated(netif_ip6_addr_state(
netif, 0))) {
1171 nd6_tmr_rs_reduction--;
1183nd6_send_neighbor_cache_probe(
struct nd6_neighbor_cache_entry *
entry,
u8_t flags)
1200 const ip6_addr_t *src_addr =
NULL;
1201 u16_t lladdr_opt_len;
1205 if (!(
flags & ND6_SEND_FLAG_ANY_SRC)) {
1208 if (ip6_addr_isvalid(netif_ip6_addr_state(
netif,
i)) &&
1209 ip6_addr_net_eq(target_addr, netif_ip6_addr(
netif,
i))) {
1210 src_addr = netif_ip6_addr(
netif,
i);
1224 src_addr = IP6_ADDR_ANY6;
1242 ns_hdr->reserved = 0;
1243 ip6_addr_copy_to_packed(ns_hdr->target_address, *target_addr);
1245 if (lladdr_opt_len != 0) {
1248 lladdr_opt->length = (
u8_t)lladdr_opt_len;
1253 if (
flags & ND6_SEND_FLAG_MULTICAST_DEST) {
1254 ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]);
1255 ip6_addr_assign_zone(&multicast_address, IP6_MULTICAST,
netif);
1256 target_addr = &multicast_address;
1259#if CHECKSUM_GEN_ICMP6
1268 ip6_output_if(
p, (src_addr == IP6_ADDR_ANY6) ?
NULL : src_addr, target_addr,
1286 const ip6_addr_t *src_addr;
1287 const ip6_addr_t *dest_addr;
1288 u16_t lladdr_opt_len;
1295 src_addr = target_addr;
1312 na_hdr->flags =
flags & 0xf0;
1313 na_hdr->reserved[0] = 0;
1314 na_hdr->reserved[1] = 0;
1315 na_hdr->reserved[2] = 0;
1316 ip6_addr_copy_to_packed(na_hdr->target_address, *target_addr);
1319 lladdr_opt->length = (
u8_t)lladdr_opt_len;
1323 if (
flags & ND6_SEND_FLAG_MULTICAST_DEST) {
1324 ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]);
1325 ip6_addr_assign_zone(&multicast_address, IP6_MULTICAST,
netif);
1326 dest_addr = &multicast_address;
1327 }
else if (
flags & ND6_SEND_FLAG_ALLNODES_DEST) {
1328 ip6_addr_set_allnodes_linklocal(&multicast_address);
1329 ip6_addr_assign_zone(&multicast_address, IP6_MULTICAST,
netif);
1330 dest_addr = &multicast_address;
1332 dest_addr = ip6_current_src_addr();
1335#if CHECKSUM_GEN_ICMP6
1344 ip6_output_if(
p, src_addr, dest_addr,
1349#if LWIP_IPV6_SEND_ROUTER_SOLICIT
1361 const ip6_addr_t *src_addr;
1363 u16_t lladdr_opt_len = 0;
1366 if (ip6_addr_isvalid(netif_ip6_addr_state(
netif, 0))) {
1367 src_addr = netif_ip6_addr(
netif, 0);
1369 src_addr = IP6_ADDR_ANY6;
1373 ip6_addr_set_allrouters_linklocal(&multicast_address);
1374 ip6_addr_assign_zone(&multicast_address, IP6_MULTICAST,
netif);
1377 if (src_addr != IP6_ADDR_ANY6) {
1392 rs_hdr->reserved = 0;
1394 if (src_addr != IP6_ADDR_ANY6) {
1398 lladdr_opt->length = (
u8_t)lladdr_opt_len;
1402#if CHECKSUM_GEN_ICMP6
1405 &multicast_address);
1412 err = ip6_output_if(
p, (src_addr == IP6_ADDR_ANY6) ?
NULL : src_addr, &multicast_address,
1428nd6_find_neighbor_cache_entry(
const ip6_addr_t *ip6addr)
1432 if (ip6_addr_eq(ip6addr, &(neighbor_cache[
i].next_hop_address))) {
1449nd6_new_neighbor_cache_entry(
void)
1458 if (neighbor_cache[
i].
state == ND6_NO_ENTRY) {
1467 if ((neighbor_cache[
i].
state == ND6_STALE) &&
1468 (!neighbor_cache[
i].isrouter)) {
1469 nd6_free_neighbor_cache_entry(
i);
1476 if ((neighbor_cache[
i].
state == ND6_PROBE) &&
1477 (!neighbor_cache[
i].isrouter)) {
1478 nd6_free_neighbor_cache_entry(
i);
1485 if ((neighbor_cache[
i].
state == ND6_DELAY) &&
1486 (!neighbor_cache[
i].isrouter)) {
1487 nd6_free_neighbor_cache_entry(
i);
1493 time = 0xfffffffful;
1496 if ((neighbor_cache[
i].
state == ND6_REACHABLE) &&
1497 (!neighbor_cache[
i].isrouter)) {
1500 time = neighbor_cache[
i].counter.reachable_time;
1505 nd6_free_neighbor_cache_entry(
j);
1514 (neighbor_cache[
i].
q ==
NULL) &&
1515 (neighbor_cache[
i].
state == ND6_INCOMPLETE) &&
1516 (!neighbor_cache[
i].isrouter)) {
1519 time = neighbor_cache[
i].counter.probes_sent;
1524 nd6_free_neighbor_cache_entry(
j);
1532 if ((neighbor_cache[
i].
state == ND6_INCOMPLETE) &&
1533 (!neighbor_cache[
i].isrouter)) {
1536 time = neighbor_cache[
i].counter.probes_sent;
1541 nd6_free_neighbor_cache_entry(
j);
1556nd6_free_neighbor_cache_entry(
s8_t i)
1561 if (neighbor_cache[
i].isrouter) {
1567 if (neighbor_cache[
i].
q !=
NULL) {
1568 nd6_free_q(neighbor_cache[
i].
q);
1569 neighbor_cache[
i].q =
NULL;
1572 neighbor_cache[
i].state = ND6_NO_ENTRY;
1573 neighbor_cache[
i].isrouter = 0;
1574 neighbor_cache[
i].netif =
NULL;
1575 neighbor_cache[
i].counter.reachable_time = 0;
1576 ip6_addr_set_zero(&(neighbor_cache[
i].next_hop_address));
1587nd6_find_destination_cache_entry(
const ip6_addr_t *ip6addr)
1591 IP6_ADDR_ZONECHECK(ip6addr);
1594 if (ip6_addr_eq(ip6addr, &(destination_cache[
i].destination_addr))) {
1609nd6_new_destination_cache_entry(
void)
1616 if (ip6_addr_isany(&(destination_cache[
i].destination_addr))) {
1625 if (destination_cache[
i].age > age) {
1640nd6_clear_destination_cache(
void)
1645 ip6_addr_set_any(&destination_cache[
i].destination_addr);
1657nd6_is_prefix_in_netif(
const ip6_addr_t *ip6addr,
struct netif *
netif)
1664 (prefix_list[
i].invalidation_timer > 0) &&
1665 ip6_addr_net_eq(ip6addr, &(prefix_list[
i].
prefix))) {
1674 if (ip6_addr_isvalid(netif_ip6_addr_state(
netif,
i)) &&
1675 netif_ip6_addr_isstatic(
netif,
i) &&
1676 ip6_addr_net_eq(ip6addr, netif_ip6_addr(
netif,
i))) {
1697nd6_select_router(
const ip6_addr_t *ip6addr,
struct netif *
netif)
1699 struct netif *router_netif;
1701 static s8_t last_router;
1711 if (default_router_list[
i].neighbor_entry !=
NULL) {
1712 router_netif = default_router_list[
i].neighbor_entry->netif;
1718 if (default_router_list[
i].neighbor_entry->state != ND6_INCOMPLETE) {
1720 if (default_router_list[
i].neighbor_entry->state == ND6_REACHABLE) {
1722 }
else if (valid_router < 0) {
1729 if (valid_router >= 0) {
1730 return valid_router;
1742 if (default_router_list[
i].neighbor_entry !=
NULL) {
1743 router_netif = default_router_list[
i].neighbor_entry->netif;
1769nd6_find_route(
const ip6_addr_t *ip6addr)
1779 netif = prefix_list[
i].netif;
1787 i = nd6_select_router(ip6addr,
NULL);
1789 LWIP_ASSERT(
"selected router must have a neighbor entry",
1790 default_router_list[
i].neighbor_entry !=
NULL);
1791 return default_router_list[
i].neighbor_entry->netif;
1805nd6_get_router(
const ip6_addr_t *router_addr,
struct netif *
netif)
1809 IP6_ADDR_ZONECHECK_NETIF(router_addr,
netif);
1813 if ((default_router_list[
i].neighbor_entry !=
NULL) &&
1814 ((
netif !=
NULL) ?
netif == default_router_list[
i].neighbor_entry->netif : 1) &&
1815 ip6_addr_eq(router_addr, &(default_router_list[
i].neighbor_entry->next_hop_address))) {
1832nd6_new_router(
const ip6_addr_t *router_addr,
struct netif *
netif)
1835 s8_t free_router_index;
1836 s8_t neighbor_index;
1838 IP6_ADDR_ZONECHECK_NETIF(router_addr,
netif);
1841 neighbor_index = nd6_find_neighbor_cache_entry(router_addr);
1842 if (neighbor_index < 0) {
1844 neighbor_index = nd6_new_neighbor_cache_entry();
1845 if (neighbor_index < 0) {
1849 ip6_addr_set(&(neighbor_cache[neighbor_index].next_hop_address), router_addr);
1850 neighbor_cache[neighbor_index].netif =
netif;
1851 neighbor_cache[neighbor_index].q =
NULL;
1852 neighbor_cache[neighbor_index].state = ND6_INCOMPLETE;
1853 neighbor_cache[neighbor_index].counter.probes_sent = 1;
1854 nd6_send_neighbor_cache_probe(&neighbor_cache[neighbor_index], ND6_SEND_FLAG_MULTICAST_DEST);
1858 neighbor_cache[neighbor_index].isrouter = 1;
1865 if(default_router_list[router_index].neighbor_entry == &(neighbor_cache[neighbor_index])){
1866 return router_index;
1868 if (default_router_list[router_index].neighbor_entry ==
NULL) {
1870 free_router_index = router_index;
1874 default_router_list[free_router_index].neighbor_entry = &(neighbor_cache[neighbor_index]);
1875 return free_router_index;
1881 neighbor_cache[neighbor_index].isrouter = 0;
1926 (prefix_list[
i].invalidation_timer == 0)) {
1928 prefix_list[
i].netif =
netif;
1951nd6_get_next_hop_entry(
const ip6_addr_t *ip6addr,
struct netif *
netif)
1953#ifdef LWIP_HOOK_ND6_GET_GW
1954 const ip6_addr_t *next_hop_addr;
1958 struct nd6_destination_cache_entry *
dest;
1960 IP6_ADDR_ZONECHECK_NETIF(ip6addr,
netif);
1962#if LWIP_NETIF_HWADDRHINT
1967 nd6_cached_destination_index = addr_hint;
1975 dest = &destination_cache[nd6_cached_destination_index];
1976 if (ip6_addr_eq(ip6addr, &
dest->destination_addr)) {
1982 dst_idx = nd6_find_destination_cache_entry(ip6addr);
1987 dest = &destination_cache[dst_idx];
1990 dst_idx = nd6_new_destination_cache_entry();
1995 dest = &destination_cache[dst_idx];
2002 ip6_addr_set(&
dest->destination_addr, ip6addr);
2005 if (ip6_addr_islinklocal(ip6addr) ||
2006 nd6_is_prefix_in_netif(ip6addr,
netif)) {
2009 ip6_addr_copy(
dest->next_hop_addr,
dest->destination_addr);
2010#ifdef LWIP_HOOK_ND6_GET_GW
2011 }
else if ((next_hop_addr = LWIP_HOOK_ND6_GET_GW(
netif, ip6addr)) !=
NULL) {
2014 ip6_addr_set(&
dest->next_hop_addr, next_hop_addr);
2018 i = nd6_select_router(ip6addr,
netif);
2021 ip6_addr_set_any(&
dest->destination_addr);
2025 ip6_addr_copy(
dest->next_hop_addr, default_router_list[
i].neighbor_entry->next_hop_address);
2028#if LWIP_NETIF_HWADDRHINT
2031 netif->hints->addr_hint = nd6_cached_destination_index;
2037 if (ip6_addr_eq(&
dest->next_hop_addr,
2038 &(neighbor_cache[
dest->cached_neighbor_idx].next_hop_address))) {
2043 i = nd6_find_neighbor_cache_entry(&
dest->next_hop_addr);
2046 dest->cached_neighbor_idx =
i;
2049 i = nd6_new_neighbor_cache_entry();
2052 dest->cached_neighbor_idx =
i;
2059 ip6_addr_copy(neighbor_cache[
i].next_hop_address,
dest->next_hop_addr);
2060 neighbor_cache[
i].isrouter = 0;
2061 neighbor_cache[
i].netif =
netif;
2062 neighbor_cache[
i].
state = ND6_INCOMPLETE;
2063 neighbor_cache[
i].counter.probes_sent = 1;
2064 nd6_send_neighbor_cache_probe(&neighbor_cache[
i], ND6_SEND_FLAG_MULTICAST_DEST);
2071 return dest->cached_neighbor_idx;
2082nd6_queue_packet(
s8_t neighbor_index,
struct pbuf *
q)
2086 int copy_needed = 0;
2087#if LWIP_ND6_QUEUEING
2088 struct nd6_q_entry *new_entry, *
r;
2108 while ((
p ==
NULL) && (neighbor_cache[neighbor_index].
q !=
NULL)) {
2110#if LWIP_ND6_QUEUEING
2111 r = neighbor_cache[neighbor_index].q;
2112 neighbor_cache[neighbor_index].q =
r->next;
2117 neighbor_cache[neighbor_index].q =
NULL;
2129#if LWIP_ND6_QUEUEING
2133 new_entry = (
struct nd6_q_entry *)
memp_malloc(MEMP_ND6_QUEUE);
2136 if ((new_entry ==
NULL) && (neighbor_cache[neighbor_index].q !=
NULL)) {
2138 r = neighbor_cache[neighbor_index].q;
2139 neighbor_cache[neighbor_index].q =
r->next;
2142 new_entry = (
struct nd6_q_entry *)
memp_malloc(MEMP_ND6_QUEUE);
2145 if (new_entry !=
NULL) {
2146 new_entry->next =
NULL;
2148 if (neighbor_cache[neighbor_index].
q !=
NULL) {
2150 r = neighbor_cache[neighbor_index].q;
2151 while (
r->next !=
NULL) {
2154 r->next = new_entry;
2157 neighbor_cache[neighbor_index].q = new_entry;
2169 if (neighbor_cache[neighbor_index].
q !=
NULL) {
2172 neighbor_cache[neighbor_index].q =
p;
2184#if LWIP_ND6_QUEUEING
2191nd6_free_q(
struct nd6_q_entry *
q)
2193 struct nd6_q_entry *
r;
2217#if LWIP_ND6_QUEUEING
2218 struct nd6_q_entry *
q;
2225#if LWIP_ND6_QUEUEING
2226 while (neighbor_cache[
i].
q !=
NULL) {
2228 q = neighbor_cache[
i].q;
2230 neighbor_cache[
i].q =
q->next;
2232 ip6hdr = (
struct ip6_hdr *)(
q->p->payload);
2234 ip6_addr_copy_from_packed(
dest, ip6hdr->dest);
2236 ip6_addr_assign_zone(&
dest, IP6_UNKNOWN, neighbor_cache[
i].
netif);
2238 (neighbor_cache[
i].netif)->output_ip6(neighbor_cache[
i].
netif,
q->p, &
dest);
2246 if (neighbor_cache[
i].
q !=
NULL) {
2248 ip6hdr = (
struct ip6_hdr *)(neighbor_cache[
i].
q->payload);
2250 ip6_addr_copy_from_packed(
dest, ip6hdr->dest);
2252 ip6_addr_assign_zone(&
dest, IP6_UNKNOWN, neighbor_cache[
i].
netif);
2254 (neighbor_cache[
i].netif)->output_ip6(neighbor_cache[
i].
netif, neighbor_cache[
i].
q, &
dest);
2257 neighbor_cache[
i].q =
NULL;
2285nd6_get_next_hop_addr_or_queue(
struct netif *
netif,
struct pbuf *
q,
const ip6_addr_t *ip6addr,
const u8_t **hwaddrp)
2290 i = nd6_get_next_hop_entry(ip6addr,
netif);
2297 if (neighbor_cache[
i].
state == ND6_STALE) {
2299 neighbor_cache[
i].state = ND6_DELAY;
2303 if ((neighbor_cache[
i].
state == ND6_REACHABLE) ||
2304 (neighbor_cache[
i].
state == ND6_DELAY) ||
2305 (neighbor_cache[
i].
state == ND6_PROBE)) {
2308 *hwaddrp = neighbor_cache[
i].lladdr;
2314 return nd6_queue_packet(
i,
q);
2326nd6_get_destination_mtu(
const ip6_addr_t *ip6addr,
struct netif *
netif)
2330 i = nd6_find_destination_cache_entry(ip6addr);
2332 if (destination_cache[
i].pmtu > 0) {
2333 return destination_cache[
i].pmtu;
2338 return netif_mtu6(
netif);
2345#if LWIP_ND6_TCP_REACHABILITY_HINTS
2356nd6_reachability_hint(
const ip6_addr_t *ip6addr)
2360 struct nd6_destination_cache_entry *
dest;
2363 if (ip6_addr_eq(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) {
2364 dst_idx = nd6_cached_destination_index;
2367 dst_idx = nd6_find_destination_cache_entry(ip6addr);
2374 dest = &destination_cache[dst_idx];
2375 if (ip6_addr_eq(&
dest->next_hop_addr, &(neighbor_cache[
dest->cached_neighbor_idx].next_hop_address))) {
2376 i =
dest->cached_neighbor_idx;
2379 i = nd6_find_neighbor_cache_entry(&
dest->next_hop_addr);
2386 if (neighbor_cache[
i].
state == ND6_INCOMPLETE || neighbor_cache[
i].
state == ND6_NO_ENTRY) {
2391 neighbor_cache[
i].state = ND6_REACHABLE;
2392 neighbor_cache[
i].counter.reachable_time = reachable_time;
2408 prefix_list[
i].netif =
NULL;
2414 if (default_router_list[router_index].neighbor_entry == &neighbor_cache[
i]) {
2415 default_router_list[router_index].neighbor_entry =
NULL;
2416 default_router_list[router_index].flags = 0;
2419 neighbor_cache[
i].isrouter = 0;
2420 nd6_free_neighbor_cache_entry(
i);
2426 nd6_clear_destination_cache();
2441 u8_t old_state, old_member, new_member;
2443 old_state = netif_ip6_addr_state(
netif, addr_idx);
2448 old_member = (old_state != IP6_ADDR_INVALID && old_state != IP6_ADDR_DUPLICATED && old_state != IP6_ADDR_TENTATIVE);
2449 new_member = (new_state != IP6_ADDR_INVALID && new_state != IP6_ADDR_DUPLICATED && new_state != IP6_ADDR_TENTATIVE);
2451 if (old_member != new_member) {
2452 ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(
netif, addr_idx)->
addr[3]);
2453 ip6_addr_assign_zone(&multicast_address, IP6_MULTICAST,
netif);
2456 mld6_joingroup_netif(
netif, &multicast_address);
2458 mld6_leavegroup_netif(
netif, &multicast_address);
2468#if LWIP_IPV6_SEND_ROUTER_SOLICIT
#define LWIP_DEBUGF(debug, message)
#define LWIP_ASSERT(message, assertion)
GLdouble GLdouble GLdouble r
GLdouble GLdouble GLdouble GLdouble q
GLenum const GLvoid * addr
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
#define LWIP_UNUSED_ARG(x)
#define LWIP_DBG_LEVEL_WARNING
#define LWIP_IPV6_NUM_ADDRESSES
#define LWIP_IPV6_DUP_DETECT_ATTEMPTS
#define SMEMCPY(dst, src, len)
#define LWIP_ND6_REACHABLE_TIME
#define LWIP_ND6_DELAY_FIRST_PROBE_TIME
#define LWIP_ND6_RETRANS_TIMER
#define LWIP_ND6_NUM_ROUTERS
#define LWIP_ND6_MAX_MULTICAST_SOLICIT
#define LWIP_ND6_NUM_NEIGHBORS
#define MEMP_NUM_ND6_QUEUE
#define LWIP_ND6_NUM_DESTINATIONS
#define LWIP_ND6_NUM_PREFIXES
#define netif_is_up(netif)
u8_t pbuf_get_at(const struct pbuf *p, u16_t offset)
void pbuf_ref(struct pbuf *p)
int pbuf_try_get_at(const struct pbuf *p, u16_t offset)
#define PBUF_NEEDS_COPY(p)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
u8_t pbuf_free(struct pbuf *p)
u16_t pbuf_copy_partial(const struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
struct pbuf * pbuf_clone(pbuf_layer layer, pbuf_type type, struct pbuf *p)
#define ip_addr_eq(addr1, addr2)
#define IP_SET_TYPE_VAL(ipaddr, iptype)
#define ip_addr_copy_from_ip6(dest, src)
#define MEMCPY(DST, SRC, BYTES)
void * memp_malloc(memp_t type)
void memp_free(memp_t type, void *mem)
#define NETIF_ADDR_IDX_MAX
#define netif_is_link_up(netif)
#define NETIF_FOREACH(netif)
#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag)
#define IP6_MIN_MTU_LENGTH
typedefPACK_STRUCT_END struct ip6_addr_packed ip6_addr_p_t
#define ND6_OPTION_TYPE_PREFIX_INFO
#define ND6_RA_FLAG_OTHER_CONFIG
#define ND6_OPTION_TYPE_RDNSS
#define ND6_FLAG_OVERRIDE
#define ND6_PREFIX_FLAG_ON_LINK
#define ND6_OPTION_TYPE_SOURCE_LLADDR
#define ND6_OPTION_TYPE_TARGET_LLADDR
#define ND6_RA_FLAG_MANAGED_ADDR_CONFIG
#define ND6_OPTION_TYPE_MTU
#define ND6_PREFIX_FLAG_AUTONOMOUS
#define ND6_FLAG_SOLICITED
#define SIZEOF_RDNSS_OPTION_BASE
#define ND6_OPTION_TYPE_ROUTE_INFO
static void accepted(enum accept_stat, struct rpc_err *)
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]
Character const *const prefix