75 static u8_t nd6_cached_neighbor_index;
76 static u8_t nd6_cached_destination_index;
79 static ip6_addr_t multicast_address;
82 static u8_t nd6_ra_buffer[
sizeof(
struct prefix_option)];
85 static s8_t nd6_find_neighbor_cache_entry(
const ip6_addr_t * ip6addr);
86 static s8_t nd6_new_neighbor_cache_entry(
void);
87 static void nd6_free_neighbor_cache_entry(
s8_t i);
88 static s8_t nd6_find_destination_cache_entry(
const ip6_addr_t * ip6addr);
89 static s8_t nd6_new_destination_cache_entry(
void);
90 static s8_t nd6_is_prefix_in_netif(
const ip6_addr_t * ip6addr,
struct netif *
netif);
91 static s8_t nd6_get_router(
const ip6_addr_t * router_addr,
struct netif *
netif);
92 static s8_t nd6_new_router(
const ip6_addr_t * router_addr,
struct netif *
netif);
93 static s8_t nd6_get_onlink_prefix(ip6_addr_t * prefix,
struct netif *
netif);
94 static s8_t nd6_new_onlink_prefix(ip6_addr_t * prefix,
struct netif *
netif);
96 #define ND6_SEND_FLAG_MULTICAST_DEST 0x01 97 #define ND6_SEND_FLAG_ALLNODES_DEST 0x02 98 static void nd6_send_ns(
struct netif *
netif,
const ip6_addr_t * target_addr,
u8_t flags);
99 static void nd6_send_na(
struct netif *
netif,
const ip6_addr_t * target_addr,
u8_t flags);
100 #if LWIP_IPV6_SEND_ROUTER_SOLICIT 104 #if LWIP_ND6_QUEUEING 105 static void nd6_free_q(
struct nd6_q_entry *q);
107 #define nd6_free_q(q) pbuf_free(q) 109 static void nd6_send_q(
s8_t i);
119 nd6_input(
struct pbuf *p,
struct netif *inp)
130 struct na_header * na_hdr;
131 struct lladdr_option * lladdr_opt;
134 if (p->
len < (
sizeof(
struct na_header))) {
142 na_hdr = (
struct na_header *)p->
payload;
145 if (ip6_addr_ismulticast(ip6_current_dest_addr())) {
151 if (p->
len < (
sizeof(
struct na_header) + 2)) {
159 lladdr_opt = (
struct lladdr_option *)((
u8_t*)p->
payload +
sizeof(
struct na_header));
161 if (p->
len < (
sizeof(
struct na_header) + (lladdr_opt->length << 3))) {
170 ip6_addr_set(ip6_current_dest_addr(), &(na_hdr->target_address));
172 #if LWIP_IPV6_DUP_DETECT_ATTEMPTS 175 if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) &&
176 ip6_addr_cmp(ip6_current_dest_addr(), netif_ip6_addr(inp, i))) {
178 netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID);
182 ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(inp, i)->addr[3]);
183 mld6_leavegroup(netif_ip6_addr(inp, i), &multicast_address);
186 #if LWIP_IPV6_AUTOCONFIG 188 if (!ip6_addr_islinklocal(ip6_current_dest_addr())) {
189 i = nd6_get_onlink_prefix(ip6_current_dest_addr(), inp);
193 prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_DUPLICATE;
205 i = nd6_find_neighbor_cache_entry(ip6_current_dest_addr());
207 if (na_hdr->flags & ND6_FLAG_OVERRIDE) {
217 ip6_addr_set(ip6_current_dest_addr(), &(na_hdr->target_address));
220 i = nd6_find_neighbor_cache_entry(ip6_current_dest_addr());
228 neighbor_cache[i].netif = inp;
229 neighbor_cache[i].counter.reachable_time = reachable_time;
230 if ((na_hdr->flags & ND6_FLAG_OVERRIDE) ||
231 (neighbor_cache[i].state == ND6_INCOMPLETE)) {
233 if (p->
len < (
sizeof(
struct na_header) + 2)) {
241 lladdr_opt = (
struct lladdr_option *)((
u8_t*)p->
payload +
sizeof(
struct na_header));
243 if (p->
len < (
sizeof(
struct na_header) + (lladdr_opt->length << 3))) {
253 neighbor_cache[i].state = ND6_REACHABLE;
256 if (neighbor_cache[i].q !=
NULL) {
265 struct ns_header * ns_hdr;
266 struct lladdr_option * lladdr_opt;
270 if (p->
len <
sizeof(
struct ns_header)) {
278 ns_hdr = (
struct ns_header *)p->
payload;
281 if (p->
len >= (
sizeof(
struct ns_header) + 2)) {
282 lladdr_opt = (
struct lladdr_option *)((
u8_t*)p->
payload +
sizeof(
struct ns_header));
283 if (p->
len < (
sizeof(
struct ns_header) + (lladdr_opt->length << 3))) {
293 if ((ip6_addr_isvalid(netif_ip6_addr_state(inp, i)) ||
294 (ip6_addr_istentative(netif_ip6_addr_state(inp, i)) &&
295 ip6_addr_isany(ip6_current_src_addr()))) &&
296 ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) {
309 if (ip6_addr_isany(ip6_current_src_addr())) {
312 if (!ip6_addr_isinvalid(netif_ip6_addr_state(inp, i)) &&
313 ip6_addr_cmp(&(ns_hdr->target_address), netif_ip6_addr(inp, i))) {
315 nd6_send_na(inp, netif_ip6_addr(inp, i), ND6_FLAG_OVERRIDE | ND6_SEND_FLAG_ALLNODES_DEST);
316 if (ip6_addr_istentative(netif_ip6_addr_state(inp, i))) {
318 netif_ip6_addr_set_state(inp, i, IP6_ADDR_INVALID);
325 if (lladdr_opt ==
NULL) {
333 i = nd6_find_neighbor_cache_entry(ip6_current_src_addr());
336 if (neighbor_cache[i].state == ND6_INCOMPLETE) {
337 neighbor_cache[i].netif = inp;
341 neighbor_cache[i].state = ND6_DELAY;
348 i = nd6_new_neighbor_cache_entry();
356 neighbor_cache[i].netif = inp;
358 ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr());
362 neighbor_cache[i].state = ND6_DELAY;
367 ip6_addr_set(ip6_current_dest_addr(), &(ns_hdr->target_address));
370 nd6_send_na(inp, ip6_current_dest_addr(), ND6_FLAG_SOLICITED | ND6_FLAG_OVERRIDE);
377 struct ra_header * ra_hdr;
382 if (p->
len <
sizeof(
struct ra_header)) {
390 ra_hdr = (
struct ra_header *)p->
payload;
396 (nd6_send_rs(inp) ==
ERR_OK)) {
402 i = nd6_get_router(ip6_current_src_addr(), inp);
405 i = nd6_new_router(ip6_current_src_addr(), inp);
416 default_router_list[i].invalidation_timer =
htons(ra_hdr->router_lifetime);
419 #if LWIP_ND6_ALLOW_RA_UPDATES 420 if (ra_hdr->retrans_timer > 0) {
421 retrans_timer =
htonl(ra_hdr->retrans_timer);
423 if (ra_hdr->reachable_time > 0) {
424 reachable_time =
htonl(ra_hdr->reachable_time);
432 default_router_list[i].flags = ra_hdr->flags;
435 offset =
sizeof(
struct ra_header);
438 while ((p->
tot_len - offset) > 0) {
443 buffer = nd6_ra_buffer;
447 case ND6_OPTION_TYPE_SOURCE_LLADDR:
449 struct lladdr_option * lladdr_opt;
450 lladdr_opt = (
struct lladdr_option *)buffer;
451 if ((default_router_list[i].neighbor_entry !=
NULL) &&
452 (default_router_list[i].neighbor_entry->state == ND6_INCOMPLETE)) {
453 SMEMCPY(default_router_list[i].neighbor_entry->lladdr, lladdr_opt->addr, inp->
hwaddr_len);
454 default_router_list[i].neighbor_entry->state = ND6_REACHABLE;
455 default_router_list[i].neighbor_entry->counter.reachable_time = reachable_time;
459 case ND6_OPTION_TYPE_MTU:
461 struct mtu_option * mtu_opt;
462 mtu_opt = (
struct mtu_option *)buffer;
463 if (
htonl(mtu_opt->mtu) >= 1280) {
464 #if LWIP_ND6_ALLOW_RA_UPDATES 470 case ND6_OPTION_TYPE_PREFIX_INFO:
472 struct prefix_option * prefix_opt;
473 prefix_opt = (
struct prefix_option *)buffer;
475 if (prefix_opt->flags & ND6_PREFIX_FLAG_ON_LINK) {
480 ip6_addr_set(ip6_current_dest_addr(), &(prefix_opt->prefix));
483 prefix = nd6_get_onlink_prefix(ip6_current_dest_addr(), inp);
486 prefix = nd6_new_onlink_prefix(ip6_current_dest_addr(), inp);
489 prefix_list[prefix].invalidation_timer =
htonl(prefix_opt->valid_lifetime);
491 #if LWIP_IPV6_AUTOCONFIG 492 if (prefix_opt->flags & ND6_PREFIX_FLAG_AUTONOMOUS) {
495 prefix_list[prefix].flags |= ND6_PREFIX_AUTOCONFIG_AUTONOMOUS;
503 case ND6_OPTION_TYPE_ROUTE_INFO:
514 offset += 8 * ((
u16_t)buffer[1]);
521 struct redirect_header * redir_hdr;
522 struct lladdr_option * lladdr_opt;
525 if (p->
len <
sizeof(
struct redirect_header)) {
533 redir_hdr = (
struct redirect_header *)p->
payload;
535 if (p->
len >= (
sizeof(
struct redirect_header) + 2)) {
536 lladdr_opt = (
struct lladdr_option *)((
u8_t*)p->
payload +
sizeof(
struct redirect_header));
537 if (p->
len < (
sizeof(
struct redirect_header) + (lladdr_opt->length << 3))) {
545 ip6_addr_set(ip6_current_src_addr(), &(redir_hdr->destination_address));
548 i = nd6_find_destination_cache_entry(ip6_current_src_addr());
556 ip6_addr_set(&(destination_cache[i].next_hop_addr), &(redir_hdr->target_address));
559 if (lladdr_opt !=
NULL) {
560 if (lladdr_opt->type == ND6_OPTION_TYPE_TARGET_LLADDR) {
562 ip6_addr_set(ip6_current_src_addr(), &(redir_hdr->target_address));
564 i = nd6_find_neighbor_cache_entry(ip6_current_src_addr());
566 i = nd6_new_neighbor_cache_entry();
568 neighbor_cache[i].netif = inp;
570 ip6_addr_set(&(neighbor_cache[i].next_hop_address), ip6_current_src_addr());
574 neighbor_cache[i].state = ND6_DELAY;
579 if (neighbor_cache[i].state == ND6_INCOMPLETE) {
583 neighbor_cache[i].state = ND6_DELAY;
594 struct ip6_hdr * ip6hdr;
610 ip6_addr_set(ip6_current_src_addr(), &(ip6hdr->dest));
613 i = nd6_find_destination_cache_entry(ip6_current_src_addr());
621 pmtu =
htonl(icmp6hdr->data);
654 switch (neighbor_cache[i].
state) {
658 nd6_free_neighbor_cache_entry(i);
661 neighbor_cache[i].counter.probes_sent++;
662 nd6_send_ns(neighbor_cache[i].netif, &(neighbor_cache[i].next_hop_address), ND6_SEND_FLAG_MULTICAST_DEST);
667 if (neighbor_cache[i].q !=
NULL) {
670 if (neighbor_cache[i].counter.reachable_time <= ND6_TMR_INTERVAL) {
672 neighbor_cache[i].state = ND6_STALE;
673 neighbor_cache[i].counter.stale_time = 0;
675 neighbor_cache[i].counter.reachable_time -= ND6_TMR_INTERVAL;
679 neighbor_cache[i].counter.stale_time += ND6_TMR_INTERVAL;
682 if (neighbor_cache[i].counter.delay_time <= ND6_TMR_INTERVAL) {
684 neighbor_cache[i].state = ND6_PROBE;
685 neighbor_cache[i].counter.probes_sent = 0;
687 neighbor_cache[i].counter.delay_time -= ND6_TMR_INTERVAL;
693 nd6_free_neighbor_cache_entry(i);
696 neighbor_cache[i].counter.probes_sent++;
697 nd6_send_ns(neighbor_cache[i].netif, &(neighbor_cache[i].next_hop_address), 0);
709 destination_cache[i].age++;
714 if (default_router_list[i].neighbor_entry !=
NULL) {
716 if (default_router_list[i].invalidation_timer > 0) {
717 default_router_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000;
719 if (default_router_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) {
721 default_router_list[i].neighbor_entry->isrouter = 0;
722 default_router_list[i].neighbor_entry =
NULL;
723 default_router_list[i].invalidation_timer = 0;
724 default_router_list[i].flags = 0;
731 if (prefix_list[i].netif !=
NULL) {
732 if (prefix_list[i].invalidation_timer < ND6_TMR_INTERVAL / 1000) {
734 prefix_list[i].invalidation_timer = 0;
736 #if LWIP_IPV6_AUTOCONFIG 738 if (prefix_list[i].
flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED)
743 if ((netif_ip6_addr_state(prefix_list[i].netif, j) != IP6_ADDR_INVALID) &&
744 ip6_addr_netcmp(&prefix_list[i].prefix, netif_ip6_addr(prefix_list[i].netif, j))) {
745 netif_ip6_addr_set_state(prefix_list[i].netif, j, IP6_ADDR_INVALID);
746 prefix_list[i].flags = 0;
755 prefix_list[i].netif =
NULL;
756 prefix_list[i].flags = 0;
758 prefix_list[i].invalidation_timer -= ND6_TMR_INTERVAL / 1000;
760 #if LWIP_IPV6_AUTOCONFIG 762 if (prefix_list[i].netif->ip6_autoconfig_enabled &&
763 (prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_AUTONOMOUS) &&
764 !(prefix_list[i].flags & ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED)) {
769 if (netif_ip6_addr_state(prefix_list[i].netif, j) == IP6_ADDR_INVALID) {
771 IP_ADDR6(&prefix_list[i].netif->ip6_addr[j],
772 prefix_list[i].prefix.addr[0], prefix_list[i].prefix.addr[1],
773 netif_ip6_addr(prefix_list[i].netif, 0)->addr[2], netif_ip6_addr(prefix_list[i].netif, 0)->addr[3]);
776 netif_ip6_addr_set_state(prefix_list[i].netif, j, IP6_ADDR_TENTATIVE);
779 prefix_list[i].flags |= ND6_PREFIX_AUTOCONFIG_ADDRESS_GENERATED;
795 if (ip6_addr_istentative(netif->ip6_addr_state[i])) {
798 netif->ip6_addr_state[i] = IP6_ADDR_PREFERRED;
802 if ((netif->ip6_addr_state[i] & 0x07) == 0) {
804 ip6_addr_set_solicitednode(&multicast_address, netif_ip6_addr(netif, i)->addr[3]);
805 mld6_joingroup(netif_ip6_addr(netif, i), &multicast_address);
809 nd6_send_ns(netif, netif_ip6_addr(netif, i), ND6_SEND_FLAG_MULTICAST_DEST);
810 (netif->ip6_addr_state[i])++;
818 #if LWIP_IPV6_SEND_ROUTER_SOLICIT 822 (!ip6_addr_isinvalid(netif_ip6_addr_state(netif, 0)))) {
823 if (nd6_send_rs(netif) ==
ERR_OK) {
840 nd6_send_ns(
struct netif * netif,
const ip6_addr_t * target_addr,
u8_t flags)
842 struct ns_header * ns_hdr;
843 struct lladdr_option * lladdr_opt;
845 const ip6_addr_t * src_addr;
846 u16_t lladdr_opt_len;
848 if (ip6_addr_isvalid(netif_ip6_addr_state(netif,0))) {
850 src_addr = netif_ip6_addr(netif, 0);
852 src_addr = IP6_ADDR_ANY6;
864 ns_hdr = (
struct ns_header *)p->
payload;
865 lladdr_opt = (
struct lladdr_option *)((
u8_t*)p->
payload +
sizeof(
struct ns_header));
870 ns_hdr->reserved = 0;
871 ip6_addr_set(&(ns_hdr->target_address), target_addr);
873 lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR;
874 lladdr_opt->length = (
u8_t)lladdr_opt_len;
878 if (flags & ND6_SEND_FLAG_MULTICAST_DEST) {
879 ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]);
880 target_addr = &multicast_address;
883 #if CHECKSUM_GEN_ICMP6 885 ns_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->
len, src_addr,
892 ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ?
NULL : src_addr, target_addr,
905 nd6_send_na(
struct netif * netif,
const ip6_addr_t * target_addr,
u8_t flags)
907 struct na_header * na_hdr;
908 struct lladdr_option * lladdr_opt;
910 const ip6_addr_t * src_addr;
911 const ip6_addr_t * dest_addr;
912 u16_t lladdr_opt_len;
917 src_addr = target_addr;
928 na_hdr = (
struct na_header *)p->
payload;
929 lladdr_opt = (
struct lladdr_option *)((
u8_t*)p->
payload +
sizeof(
struct na_header));
934 na_hdr->flags = flags & 0xf0;
935 na_hdr->reserved[0] = 0;
936 na_hdr->reserved[1] = 0;
937 na_hdr->reserved[2] = 0;
938 ip6_addr_set(&(na_hdr->target_address), target_addr);
940 lladdr_opt->type = ND6_OPTION_TYPE_TARGET_LLADDR;
941 lladdr_opt->length = (
u8_t)lladdr_opt_len;
945 if (flags & ND6_SEND_FLAG_MULTICAST_DEST) {
946 ip6_addr_set_solicitednode(&multicast_address, target_addr->addr[3]);
947 dest_addr = &multicast_address;
948 }
else if (flags & ND6_SEND_FLAG_ALLNODES_DEST) {
949 ip6_addr_set_allnodes_linklocal(&multicast_address);
950 dest_addr = &multicast_address;
952 dest_addr = ip6_current_src_addr();
955 #if CHECKSUM_GEN_ICMP6 957 na_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->
len, src_addr,
964 ip6_output_if(p, src_addr, dest_addr,
969 #if LWIP_IPV6_SEND_ROUTER_SOLICIT 976 nd6_send_rs(
struct netif * netif)
978 struct rs_header * rs_hdr;
979 struct lladdr_option * lladdr_opt;
981 const ip6_addr_t * src_addr;
983 u16_t lladdr_opt_len = 0;
986 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, 0))) {
987 src_addr = netif_ip6_addr(netif, 0);
989 src_addr = IP6_ADDR_ANY6;
993 ip6_addr_set_allrouters_linklocal(&multicast_address);
996 if (src_addr != IP6_ADDR_ANY6) {
1006 rs_hdr = (
struct rs_header *)p->
payload;
1011 rs_hdr->reserved = 0;
1013 if (src_addr != IP6_ADDR_ANY6) {
1015 lladdr_opt = (
struct lladdr_option *)((
u8_t*)p->
payload +
sizeof(
struct rs_header));
1016 lladdr_opt->type = ND6_OPTION_TYPE_SOURCE_LLADDR;
1017 lladdr_opt->length = (
u8_t)lladdr_opt_len;
1021 #if CHECKSUM_GEN_ICMP6 1023 rs_hdr->chksum = ip6_chksum_pseudo(p, IP6_NEXTH_ICMP6, p->
len, src_addr,
1024 &multicast_address);
1031 err = ip6_output_if(p, (src_addr == IP6_ADDR_ANY6) ?
NULL : src_addr, &multicast_address,
1047 nd6_find_neighbor_cache_entry(
const ip6_addr_t * ip6addr)
1051 if (ip6_addr_cmp(ip6addr, &(neighbor_cache[i].next_hop_address))) {
1068 nd6_new_neighbor_cache_entry(
void)
1077 if (neighbor_cache[i].state == ND6_NO_ENTRY) {
1086 if ((neighbor_cache[i].state == ND6_STALE) &&
1087 (!neighbor_cache[i].isrouter)) {
1088 nd6_free_neighbor_cache_entry(i);
1095 if ((neighbor_cache[i].state == ND6_PROBE) &&
1096 (!neighbor_cache[i].isrouter)) {
1097 nd6_free_neighbor_cache_entry(i);
1104 if ((neighbor_cache[i].state == ND6_DELAY) &&
1105 (!neighbor_cache[i].isrouter)) {
1106 nd6_free_neighbor_cache_entry(i);
1112 time = 0xfffffffful;
1115 if ((neighbor_cache[i].state == ND6_REACHABLE) &&
1116 (!neighbor_cache[i].isrouter)) {
1117 if (neighbor_cache[i].counter.reachable_time < time) {
1119 time = neighbor_cache[i].counter.reachable_time;
1124 nd6_free_neighbor_cache_entry(j);
1133 (neighbor_cache[i].q ==
NULL) &&
1134 (neighbor_cache[i].state == ND6_INCOMPLETE) &&
1135 (!neighbor_cache[i].isrouter)) {
1136 if (neighbor_cache[i].counter.probes_sent >= time) {
1138 time = neighbor_cache[i].counter.probes_sent;
1143 nd6_free_neighbor_cache_entry(j);
1151 if ((neighbor_cache[i].state == ND6_INCOMPLETE) &&
1152 (!neighbor_cache[i].isrouter)) {
1153 if (neighbor_cache[i].counter.probes_sent >= time) {
1155 time = neighbor_cache[i].counter.probes_sent;
1160 nd6_free_neighbor_cache_entry(j);
1175 nd6_free_neighbor_cache_entry(
s8_t i)
1177 if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) {
1182 if (neighbor_cache[i].q !=
NULL) {
1183 nd6_free_q(neighbor_cache[i].q);
1184 neighbor_cache[i].q =
NULL;
1187 neighbor_cache[i].state = ND6_NO_ENTRY;
1188 neighbor_cache[i].isrouter = 0;
1189 neighbor_cache[i].netif =
NULL;
1190 neighbor_cache[i].counter.reachable_time = 0;
1191 ip6_addr_set_zero(&(neighbor_cache[i].next_hop_address));
1202 nd6_find_destination_cache_entry(
const ip6_addr_t * ip6addr)
1206 if (ip6_addr_cmp(ip6addr, &(destination_cache[i].destination_addr))) {
1221 nd6_new_destination_cache_entry(
void)
1228 if (ip6_addr_isany(&(destination_cache[i].destination_addr))) {
1235 j = LWIP_ND6_NUM_DESTINATIONS - 1;
1237 if (destination_cache[i].age > age) {
1252 nd6_is_prefix_in_netif(
const ip6_addr_t * ip6addr,
struct netif * netif)
1256 if ((prefix_list[i].netif == netif) &&
1257 (prefix_list[i].invalidation_timer > 0) &&
1258 ip6_addr_netcmp(ip6addr, &(prefix_list[i].prefix))) {
1264 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
1265 ip6_addr_netcmp(ip6addr, netif_ip6_addr(netif, i))) {
1281 nd6_select_router(
const ip6_addr_t * ip6addr,
struct netif * netif)
1287 static s8_t last_router;
1294 if (++last_router >= LWIP_ND6_NUM_ROUTERS) {
1297 if ((default_router_list[i].neighbor_entry !=
NULL) &&
1298 (netif !=
NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) &&
1299 (default_router_list[i].invalidation_timer > 0) &&
1300 (default_router_list[i].neighbor_entry->state == ND6_REACHABLE)) {
1307 if (++last_router >= LWIP_ND6_NUM_ROUTERS) {
1310 if ((default_router_list[i].neighbor_entry !=
NULL) &&
1311 (netif !=
NULL ? netif == default_router_list[i].neighbor_entry->netif : 1) &&
1312 (default_router_list[i].invalidation_timer > 0)) {
1319 if (++last_router >= LWIP_ND6_NUM_ROUTERS) {
1322 if (default_router_list[i].neighbor_entry !=
NULL &&
1323 (netif !=
NULL ? netif == default_router_list[i].neighbor_entry->netif : 1)) {
1340 nd6_get_router(
const ip6_addr_t * router_addr,
struct netif * netif)
1346 if ((default_router_list[i].neighbor_entry !=
NULL) &&
1347 ((netif !=
NULL) ? netif == default_router_list[i].neighbor_entry->netif : 1) &&
1348 ip6_addr_cmp(router_addr, &(default_router_list[i].neighbor_entry->next_hop_address))) {
1365 nd6_new_router(
const ip6_addr_t * router_addr,
struct netif * netif)
1368 s8_t neighbor_index;
1371 neighbor_index = nd6_find_neighbor_cache_entry(router_addr);
1372 if (neighbor_index < 0) {
1374 neighbor_index = nd6_new_neighbor_cache_entry();
1375 if (neighbor_index < 0) {
1379 ip6_addr_set(&(neighbor_cache[neighbor_index].next_hop_address), router_addr);
1380 neighbor_cache[neighbor_index].netif = netif;
1381 neighbor_cache[neighbor_index].q =
NULL;
1382 neighbor_cache[neighbor_index].state = ND6_INCOMPLETE;
1383 neighbor_cache[neighbor_index].counter.probes_sent = 0;
1387 neighbor_cache[neighbor_index].isrouter = 1;
1391 if (default_router_list[router_index].neighbor_entry ==
NULL) {
1392 default_router_list[router_index].neighbor_entry = &(neighbor_cache[neighbor_index]);
1393 return router_index;
1400 neighbor_cache[neighbor_index].isrouter = 0;
1414 nd6_get_onlink_prefix(ip6_addr_t * prefix,
struct netif * netif)
1420 if ((ip6_addr_netcmp(&(prefix_list[i].prefix), prefix)) &&
1421 (prefix_list[i].netif == netif)) {
1438 nd6_new_onlink_prefix(ip6_addr_t * prefix,
struct netif * netif)
1444 if ((prefix_list[i].netif ==
NULL) ||
1445 (prefix_list[i].invalidation_timer == 0)) {
1447 prefix_list[i].netif = netif;
1448 ip6_addr_set(&(prefix_list[i].prefix), prefix);
1449 #if LWIP_IPV6_AUTOCONFIG 1450 prefix_list[i].flags = 0;
1473 nd6_get_next_hop_entry(
const ip6_addr_t * ip6addr,
struct netif * netif)
1477 #if LWIP_NETIF_HWADDRHINT 1478 if (netif->addr_hint !=
NULL) {
1480 u8_t addr_hint = *(netif->addr_hint);
1481 if (addr_hint < LWIP_ND6_NUM_DESTINATIONS) {
1482 nd6_cached_destination_index = addr_hint;
1488 if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) {
1494 i = nd6_find_destination_cache_entry(ip6addr);
1497 nd6_cached_destination_index = i;
1500 i = nd6_new_destination_cache_entry();
1503 nd6_cached_destination_index = i;
1510 ip6_addr_set(&(destination_cache[nd6_cached_destination_index].destination_addr), ip6addr);
1513 if (ip6_addr_islinklocal(ip6addr) ||
1514 nd6_is_prefix_in_netif(ip6addr, netif)) {
1516 destination_cache[nd6_cached_destination_index].pmtu = netif->
mtu;
1517 ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, destination_cache[nd6_cached_destination_index].destination_addr);
1520 i = nd6_select_router(ip6addr, netif);
1523 ip6_addr_set_any(&(destination_cache[nd6_cached_destination_index].destination_addr));
1526 destination_cache[nd6_cached_destination_index].pmtu = netif->
mtu;
1527 ip6_addr_copy(destination_cache[nd6_cached_destination_index].next_hop_addr, default_router_list[i].neighbor_entry->next_hop_address);
1532 #if LWIP_NETIF_HWADDRHINT 1533 if (netif->addr_hint !=
NULL) {
1535 *(netif->addr_hint) = nd6_cached_destination_index;
1540 if (ip6_addr_cmp(&(destination_cache[nd6_cached_destination_index].next_hop_addr),
1541 &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) {
1546 i = nd6_find_neighbor_cache_entry(&(destination_cache[nd6_cached_destination_index].next_hop_addr));
1549 nd6_cached_neighbor_index = i;
1552 i = nd6_new_neighbor_cache_entry();
1555 nd6_cached_neighbor_index = i;
1562 ip6_addr_copy(neighbor_cache[i].next_hop_address,
1563 destination_cache[nd6_cached_destination_index].next_hop_addr);
1564 neighbor_cache[i].isrouter = 0;
1565 neighbor_cache[i].netif = netif;
1566 neighbor_cache[i].
state = ND6_INCOMPLETE;
1567 neighbor_cache[i].counter.probes_sent = 0;
1572 destination_cache[nd6_cached_destination_index].age = 0;
1574 return nd6_cached_neighbor_index;
1585 nd6_queue_packet(
s8_t neighbor_index,
struct pbuf * q)
1589 int copy_needed = 0;
1590 #if LWIP_ND6_QUEUEING 1591 struct nd6_q_entry *new_entry, *r;
1594 if ((neighbor_index < 0) || (neighbor_index >= LWIP_ND6_NUM_NEIGHBORS)) {
1612 while ((p ==
NULL) && (neighbor_cache[neighbor_index].q !=
NULL)) {
1614 #if LWIP_ND6_QUEUEING 1615 r = neighbor_cache[neighbor_index].q;
1616 neighbor_cache[neighbor_index].q = r->next;
1620 pbuf_free(neighbor_cache[neighbor_index].q);
1621 neighbor_cache[neighbor_index].q =
NULL;
1639 #if LWIP_ND6_QUEUEING 1641 new_entry = (
struct nd6_q_entry *)
memp_malloc(MEMP_ND6_QUEUE);
1642 if ((new_entry ==
NULL) && (neighbor_cache[neighbor_index].q !=
NULL)) {
1644 r = neighbor_cache[neighbor_index].q;
1645 neighbor_cache[neighbor_index].q = r->next;
1648 new_entry = (
struct nd6_q_entry *)
memp_malloc(MEMP_ND6_QUEUE);
1650 if (new_entry !=
NULL) {
1651 new_entry->next =
NULL;
1653 if (neighbor_cache[neighbor_index].q !=
NULL) {
1655 r = neighbor_cache[neighbor_index].q;
1656 while (r->next !=
NULL) {
1659 r->
next = new_entry;
1662 neighbor_cache[neighbor_index].q = new_entry;
1674 if (neighbor_cache[neighbor_index].q !=
NULL) {
1675 pbuf_free(neighbor_cache[neighbor_index].q);
1677 neighbor_cache[neighbor_index].q = p;
1689 #if LWIP_ND6_QUEUEING 1696 nd6_free_q(
struct nd6_q_entry *q)
1698 struct nd6_q_entry *r;
1719 struct ip6_hdr *ip6hdr;
1720 #if LWIP_ND6_QUEUEING 1721 struct nd6_q_entry *q;
1724 if ((i < 0) || (i >= LWIP_ND6_NUM_NEIGHBORS)) {
1728 #if LWIP_ND6_QUEUEING 1729 while (neighbor_cache[i].q !=
NULL) {
1731 q = neighbor_cache[i].q;
1733 neighbor_cache[i].q = q->next;
1735 ip6hdr = (
struct ip6_hdr *)(q->p->payload);
1737 ip6_addr_set(ip6_current_dest_addr(), &(ip6hdr->dest));
1739 (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, q->p, ip6_current_dest_addr());
1746 if (neighbor_cache[i].q !=
NULL) {
1748 ip6hdr = (
struct ip6_hdr *)(neighbor_cache[i].q->payload);
1750 ip6_addr_set(ip6_current_dest_addr(), &(ip6hdr->dest));
1752 (neighbor_cache[i].netif)->output_ip6(neighbor_cache[i].netif, neighbor_cache[i].q, ip6_current_dest_addr());
1755 neighbor_cache[i].q =
NULL;
1769 nd6_get_destination_mtu(
const ip6_addr_t * ip6addr,
struct netif * netif)
1773 i = nd6_find_destination_cache_entry(ip6addr);
1775 if (destination_cache[i].pmtu > 0) {
1776 return destination_cache[i].pmtu;
1780 if (netif !=
NULL) {
1788 #if LWIP_ND6_TCP_REACHABILITY_HINTS 1799 nd6_reachability_hint(
const ip6_addr_t * ip6addr)
1804 if (ip6_addr_cmp(ip6addr, &(destination_cache[nd6_cached_destination_index].destination_addr))) {
1805 i = nd6_cached_destination_index;
1808 i = nd6_find_destination_cache_entry(ip6addr);
1815 if (ip6_addr_cmp(&(destination_cache[i].next_hop_addr), &(neighbor_cache[nd6_cached_neighbor_index].next_hop_address))) {
1816 i = nd6_cached_neighbor_index;
1819 i = nd6_find_neighbor_cache_entry(&(destination_cache[i].next_hop_addr));
1826 if (neighbor_cache[i].state == ND6_INCOMPLETE || neighbor_cache[i].state == ND6_NO_ENTRY) {
1831 neighbor_cache[i].state = ND6_REACHABLE;
1832 neighbor_cache[i].counter.reachable_time = reachable_time;
#define LWIP_ND6_NUM_PREFIXES
struct netif * netif_list
u8_t hwaddr[NETIF_MAX_HWADDR_LEN]
#define SMEMCPY(dst, src, len)
#define IF__NETIF_CHECKSUM_ENABLED(netif, chksumflag)
#define MEMCPY(dst, src, len)
void memp_free(memp_t type, void *mem)
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
#define LWIP_ND6_NUM_DESTINATIONS
u8_t pbuf_free(struct pbuf *p)
err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
#define LWIP_ASSERT(message, assertion)
#define LWIP_ND6_NUM_NEIGHBORS
#define IP_ADDR6(ipaddr, i0, i1, i2, i3)
void pbuf_ref(struct pbuf *p)
#define LWIP_ND6_NUM_ROUTERS
#define LWIP_ND6_RETRANS_TIMER
#define LWIP_IPV6_NUM_ADDRESSES
u16_t pbuf_copy_partial(struct pbuf *buf, void *dataptr, u16_t len, u16_t offset)
#define LWIP_ND6_REACHABLE_TIME
#define LWIP_ND6_MAX_MULTICAST_SOLICIT
#define LWIP_ND6_DELAY_FIRST_PROBE_TIME
#define LWIP_IPV6_SEND_ROUTER_SOLICIT
#define LWIP_IPV6_DUP_DETECT_ATTEMPTS
void * memp_malloc(memp_t type)
#define LWIP_DEBUGF(debug, message)