/** * @ingroup netif_ip6 * Change the state of an IPv6 address of a network interface * (INVALID, TEMPTATIVE, PREFERRED, DEPRECATED, where TEMPTATIVE * includes the number of checks done, see ip6_addr.h) * * @param netif the network interface to change * @param addr_idx index of the IPv6 address * @param state the new IPv6 address state */ void netif_ip6_addr_set_state(struct netif* netif, s8_t addr_idx, u8_t state) { u8_t old_state; LWIP_ASSERT("netif != NULL", netif != NULL); LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); old_state = netif_ip6_addr_state(netif, addr_idx); /* state is actually being changed? */ if (old_state != state) { u8_t old_valid = old_state & IP6_ADDR_VALID; u8_t new_valid = state & IP6_ADDR_VALID; LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set_state: netif address state being changed\n")); if (old_valid && !new_valid) { /* address about to be removed by setting invalid */ #if LWIP_TCP tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); #endif /* LWIP_TCP */ #if LWIP_UDP udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); #endif /* LWIP_UDP */ #if LWIP_RAW raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), NULL); #endif /* LWIP_RAW */ /* @todo: remove mib2 ip6 entries? */ } netif->ip6_addr_state[addr_idx] = state; if (!old_valid && new_valid) { /* address added by setting valid */ /* @todo: add mib2 ip6 entries? */ netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); } if ((old_state & IP6_ADDR_PREFERRED) != (state & IP6_ADDR_PREFERRED)) { /* address state has changed (valid flag changed or switched between preferred and deprecated) -> call the callback function */ NETIF_STATUS_CALLBACK(netif); } } LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IPv6 address %d of interface %c%c set to %s/0x%"X8_F"\n", addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), netif_ip6_addr_state(netif, addr_idx))); }
/* * Change an IPv6 address of a network interface (internal version taking 4 * u32_t) * * @param netif the network interface to change * @param addr_idx index of the IPv6 address * @param i0 word0 of the new IPv6 address * @param i1 word1 of the new IPv6 address * @param i2 word2 of the new IPv6 address * @param i3 word3 of the new IPv6 address */ void netif_ip6_addr_set_parts(struct netif *netif, s8_t addr_idx, u32_t i0, u32_t i1, u32_t i2, u32_t i3) { const ip6_addr_t *old_addr; LWIP_ASSERT("netif != NULL", netif != NULL); LWIP_ASSERT("invalid index", addr_idx < LWIP_IPV6_NUM_ADDRESSES); old_addr = netif_ip6_addr(netif, addr_idx); /* address is actually being changed? */ if ((old_addr->addr[0] != i0) || (old_addr->addr[1] != i1) || (old_addr->addr[2] != i2) || (old_addr->addr[3] != i3)) { LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_STATE, ("netif_ip6_addr_set: netif address being changed\n")); if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) { #if LWIP_TCP || LWIP_UDP ip_addr_t new_ipaddr; IP_ADDR6(&new_ipaddr, i0, i1, i2, i3); #endif /* LWIP_TCP || LWIP_UDP */ #if LWIP_TCP tcp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); #endif /* LWIP_TCP */ #if LWIP_UDP udp_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); #endif /* LWIP_UDP */ #if LWIP_RAW raw_netif_ip_addr_changed(netif_ip_addr6(netif, addr_idx), &new_ipaddr); #endif /* LWIP_RAW */ } /* @todo: remove/readd mib2 ip6 entries? */ IP6_ADDR(ip_2_ip6(&(netif->ip6_addr[addr_idx])), i0, i1, i2, i3); IP_SET_TYPE_VAL(netif->ip6_addr[addr_idx], IPADDR_TYPE_V6); if (netif_ip6_addr_state(netif, addr_idx) & IP6_ADDR_VALID) { netif_issue_reports(netif, NETIF_REPORT_TYPE_IPV6); NETIF_STATUS_CALLBACK(netif); } } LWIP_DEBUGF(NETIF_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_STATE, ("netif: IPv6 address %d of interface %c%c set to %s/0x%"X8_F"\n", addr_idx, netif->name[0], netif->name[1], ip6addr_ntoa(netif_ip6_addr(netif, addr_idx)), netif_ip6_addr_state(netif, addr_idx))); }
const ip_addr_t *LWIP::get_ipv6_addr(const struct netif *netif) { if (!netif_is_up(netif)) { return NULL; } for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && !ip6_addr_islinklocal(netif_ip6_addr(netif, i))) { return netif_ip_addr6(netif, i); } } return NULL; }
/** * Select the best IPv6 source address for a given destination * IPv6 address. Loosely follows RFC 3484. "Strong host" behavior * is assumed. * * @param netif the netif on which to send a packet * @param dest the destination we are trying to reach * @return the most suitable source address to use, or NULL if no suitable * source address is found */ const ip_addr_t * ip6_select_source_address(struct netif *netif, const ip6_addr_t * dest) { const ip_addr_t *src = NULL; u8_t i; /* If dest is link-local, choose a link-local source. */ if (ip6_addr_islinklocal(dest) || ip6_addr_ismulticast_linklocal(dest) || ip6_addr_ismulticast_iflocal(dest)) { for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && ip6_addr_islinklocal(netif_ip6_addr(netif, i))) { return netif_ip_addr6(netif, i); } } } /* Choose a site-local with matching prefix. */ if (ip6_addr_issitelocal(dest) || ip6_addr_ismulticast_sitelocal(dest)) { for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && ip6_addr_issitelocal(netif_ip6_addr(netif, i)) && ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { return netif_ip_addr6(netif, i); } } } /* Choose a unique-local with matching prefix. */ if (ip6_addr_isuniquelocal(dest) || ip6_addr_ismulticast_orglocal(dest)) { for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && ip6_addr_isuniquelocal(netif_ip6_addr(netif, i)) && ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { return netif_ip_addr6(netif, i); } } } /* Choose a global with best matching prefix. */ if (ip6_addr_isglobal(dest) || ip6_addr_ismulticast_global(dest)) { for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && ip6_addr_isglobal(netif_ip6_addr(netif, i))) { if (src == NULL) { src = netif_ip_addr6(netif, i); } else { /* Replace src only if we find a prefix match. */ /* TODO find longest matching prefix. */ if ((!(ip6_addr_netcmp(ip_2_ip6(src), dest))) && ip6_addr_netcmp(netif_ip6_addr(netif, i), dest)) { src = netif_ip_addr6(netif, i); } } } } if (src != NULL) { return src; } } /* Last resort: see if arbitrary prefix matches. */ for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && ip6_addr_netcmp(dest, netif_ip6_addr(netif, i))) { return netif_ip_addr6(netif, i); } } return NULL; }
/** * @ingroup netif * Remove a network interface from the list of lwIP netifs. * * @param netif the network interface to remove */ void netif_remove(struct netif *netif) { #if LWIP_IPV6 int i; #endif if (netif == NULL) { return; } #if LWIP_IPV4 if (!ip4_addr_isany_val(*netif_ip4_addr(netif))) { #if LWIP_TCP tcp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); #endif /* LWIP_TCP */ #if LWIP_UDP udp_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); #endif /* LWIP_UDP */ #if LWIP_RAW raw_netif_ip_addr_changed(netif_ip_addr4(netif), NULL); #endif /* LWIP_RAW */ } #if LWIP_IGMP /* stop IGMP processing */ if (netif->flags & NETIF_FLAG_IGMP) { igmp_stop(netif); } #endif /* LWIP_IGMP */ #endif /* LWIP_IPV4*/ #if LWIP_IPV6 for (i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i))) { #if LWIP_TCP tcp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); #endif /* LWIP_TCP */ #if LWIP_UDP udp_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); #endif /* LWIP_UDP */ #if LWIP_RAW raw_netif_ip_addr_changed(netif_ip_addr6(netif, i), NULL); #endif /* LWIP_RAW */ } } #if LWIP_IPV6_MLD /* stop MLD processing */ mld6_stop(netif); #endif /* LWIP_IPV6_MLD */ #endif /* LWIP_IPV6 */ if (netif_is_up(netif)) { /* set netif down before removing (call callback function) */ netif_set_down(netif); } mib2_remove_ip4(netif); /* this netif is default? */ if (netif_default == netif) { /* reset default netif */ netif_set_default(NULL); } /* is it the first netif? */ if (netif_list == netif) { netif_list = netif->next; } else { /* look for netif further down the list */ struct netif * tmp_netif; for (tmp_netif = netif_list; tmp_netif != NULL; tmp_netif = tmp_netif->next) { if (tmp_netif->next == netif) { tmp_netif->next = netif->next; break; } } if (tmp_netif == NULL) { return; /* netif is not on the list */ } } mib2_netif_removed(netif); #if LWIP_NETIF_REMOVE_CALLBACK if (netif->remove_callback) { netif->remove_callback(netif); } #endif /* LWIP_NETIF_REMOVE_CALLBACK */ LWIP_DEBUGF( NETIF_DEBUG, ("netif_remove: removed netif\n") ); }