const ip_addr_t *mbed_lwip_get_ip_addr(bool any_addr, const struct netif *netif) { const ip_addr_t *pref_ip_addr = 0; const ip_addr_t *npref_ip_addr = 0; #if LWIP_IPV4 && LWIP_IPV6 #if IP_VERSION_PREF == PREF_IPV4 pref_ip_addr = mbed_lwip_get_ipv4_addr(netif); npref_ip_addr = mbed_lwip_get_ipv6_addr(netif); #else pref_ip_addr = mbed_lwip_get_ipv6_addr(netif); npref_ip_addr = mbed_lwip_get_ipv4_addr(netif); #endif #elif LWIP_IPV6 pref_ip_addr = mbed_lwip_get_ipv6_addr(netif); #elif LWIP_IPV4 pref_ip_addr = mbed_lwip_get_ipv4_addr(netif); #endif if (pref_ip_addr) { return pref_ip_addr; } else if (npref_ip_addr && any_addr) { return npref_ip_addr; } return NULL; }
/* LWIP network stack implementation */ static nsapi_error_t mbed_lwip_gethostbyname(nsapi_stack_t *stack, const char *host, nsapi_addr_t *addr, nsapi_version_t version) { ip_addr_t lwip_addr; #if LWIP_IPV4 && LWIP_IPV6 u8_t addr_type; if (version == NSAPI_UNSPEC) { const ip_addr_t *ip_addr; ip_addr = mbed_lwip_get_ip_addr(true, &lwip_netif); // Prefer IPv6 if (IP_IS_V6(ip_addr)) { // If IPv4 is available use it as backup if (mbed_lwip_get_ipv4_addr(&lwip_netif)) { addr_type = NETCONN_DNS_IPV6_IPV4; } else { addr_type = NETCONN_DNS_IPV6; } // Prefer IPv4 } else { // If IPv6 is available use it as backup if (mbed_lwip_get_ipv6_addr(&lwip_netif)) { addr_type = NETCONN_DNS_IPV4_IPV6; } else { addr_type = NETCONN_DNS_IPV4; } } } else if (version == NSAPI_IPv4) { addr_type = NETCONN_DNS_IPV4; } else if (version == NSAPI_IPv6) { addr_type = NETCONN_DNS_IPV6; } else { return NSAPI_ERROR_DNS_FAILURE; } err_t err = netconn_gethostbyname_addrtype(host, &lwip_addr, addr_type); #elif LWIP_IPV4 if (version != NSAPI_IPv4 && version != NSAPI_UNSPEC) { return NSAPI_ERROR_DNS_FAILURE; } err_t err = netconn_gethostbyname(host, &lwip_addr); #elif LWIP_IPV6 if (version != NSAPI_IPv6 && version != NSAPI_UNSPEC) { return NSAPI_ERROR_DNS_FAILURE; } err_t err = netconn_gethostbyname(host, &lwip_addr); #endif if (err != ERR_OK) { return NSAPI_ERROR_DNS_FAILURE; } convert_lwip_addr_to_mbed(addr, &lwip_addr); return 0; }
void add_dns_addr(struct netif *lwip_netif) { // Check for existing dns address for (char numdns = 0; numdns < DNS_MAX_SERVERS; numdns++) { const ip_addr_t *dns_ip_addr = dns_getserver(numdns); if (!ip_addr_isany(dns_ip_addr)) { return; } } // Get preferred ip version const ip_addr_t *ip_addr = mbed_lwip_get_ip_addr(false, lwip_netif); u8_t addr_type = IPADDR_TYPE_ANY; // Add preferred ip version dns address to index 0 if (ip_addr) { addr_type = get_ip_addr_type(ip_addr); add_dns_addr_to_dns_list_index(addr_type, 0); } #if LWIP_IPV4 && LWIP_IPV6 if (!ip_addr) { // Get address for any ip version ip_addr = mbed_lwip_get_ip_addr(true, lwip_netif); if (!ip_addr) { return; } addr_type = get_ip_addr_type(ip_addr); // Add the dns address to index 0 add_dns_addr_to_dns_list_index(addr_type, 0); } if (addr_type == IPADDR_TYPE_V4) { // If ipv4 is preferred and ipv6 is available add ipv6 dns address to index 1 ip_addr = mbed_lwip_get_ipv6_addr(lwip_netif); } else if (addr_type == IPADDR_TYPE_V6) { // If ipv6 is preferred and ipv4 is available add ipv4 dns address to index 1 ip_addr = mbed_lwip_get_ipv4_addr(lwip_netif); } else { ip_addr = NULL; } if (ip_addr) { addr_type = get_ip_addr_type(ip_addr); add_dns_addr_to_dns_list_index(addr_type, 1); } #endif }
nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const char *netmask, const char *gw, const nsapi_ip_stack_t stack) { // Check if we've already connected if (lwip_connected == NSAPI_STATUS_GLOBAL_UP) { return NSAPI_ERROR_IS_CONNECTED; } else if (lwip_connected == NSAPI_STATUS_CONNECTING) { return NSAPI_ERROR_ALREADY; } lwip_connected = NSAPI_STATUS_CONNECTING; lwip_ppp = ppp; #if LWIP_DHCP lwip_dhcp_has_to_be_set = true; if (stack != IPV6_STACK) { lwip_dhcp = dhcp; } else { lwip_dhcp = false; } #endif mbed_lwip_core_init(); nsapi_error_t ret; if (netif_inited) { /* Can't cope with changing mode */ if (netif_is_ppp == ppp) { ret = NSAPI_ERROR_OK; } else { ret = NSAPI_ERROR_PARAMETER; } } else { if (ppp) { ret = ppp_lwip_if_init(&lwip_netif, stack); } else { ret = mbed_lwip_emac_init(NULL); } } if (ret != NSAPI_ERROR_OK) { lwip_connected = NSAPI_STATUS_DISCONNECTED; return ret; } if (lwip_client_callback) { lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_CONNECTING); } netif_inited = true; if (ppp) { netif_is_ppp = ppp; } netif_set_default(&lwip_netif); netif_set_link_callback(&lwip_netif, mbed_lwip_netif_link_irq); netif_set_status_callback(&lwip_netif, mbed_lwip_netif_status_irq); #if LWIP_IPV6 if (stack != IPV4_STACK) { if (lwip_netif.hwaddr_len == ETH_HWADDR_LEN) { netif_create_ip6_linklocal_address(&lwip_netif, 1/*from MAC*/); } #if LWIP_IPV6_MLD /* * For hardware/netifs that implement MAC filtering. * All-nodes link-local is handled by default, so we must let the hardware know * to allow multicast packets in. * Should set mld_mac_filter previously. */ if (lwip_netif.mld_mac_filter != NULL) { ip6_addr_t ip6_allnodes_ll; ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); lwip_netif.mld_mac_filter(&lwip_netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); } #endif /* LWIP_IPV6_MLD */ #if LWIP_IPV6_AUTOCONFIG /* IPv6 address autoconfiguration not enabled by default */ lwip_netif.ip6_autoconfig_enabled = 1; } else { // Disable router solidifications lwip_netif.rs_count = 0; } #endif /* LWIP_IPV6_AUTOCONFIG */ #endif // LWIP_IPV6 #if LWIP_IPV4 if (stack != IPV6_STACK) { if (!dhcp && !ppp) { ip4_addr_t ip_addr; ip4_addr_t netmask_addr; ip4_addr_t gw_addr; if (!inet_aton(ip, &ip_addr) || !inet_aton(netmask, &netmask_addr) || !inet_aton(gw, &gw_addr)) { lwip_connected = NSAPI_STATUS_DISCONNECTED; if (lwip_client_callback) { lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED); } return NSAPI_ERROR_PARAMETER; } netif_set_addr(&lwip_netif, &ip_addr, &netmask_addr, &gw_addr); } } #endif if (ppp) { err_t err = ppp_lwip_connect(); if (err) { lwip_connected = NSAPI_STATUS_DISCONNECTED; if (lwip_client_callback) { lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED); } return mbed_lwip_err_remap(err); } } if (!netif_is_link_up(&lwip_netif)) { if (lwip_blocking) { if (sys_arch_sem_wait(&lwip_netif_linked, 15000) == SYS_ARCH_TIMEOUT) { if (ppp) { ppp_lwip_disconnect(); } return NSAPI_ERROR_NO_CONNECTION; } } } else { ret = mbed_set_dhcp(&lwip_netif); if (ret != NSAPI_ERROR_OK) { return ret; } } if (lwip_blocking) { // If doesn't have address if (!mbed_lwip_get_ip_addr(true, &lwip_netif)) { if (sys_arch_sem_wait(&lwip_netif_has_any_addr, DHCP_TIMEOUT * 1000) == SYS_ARCH_TIMEOUT) { if (ppp) { ppp_lwip_disconnect(); } return NSAPI_ERROR_DHCP_FAILURE; } } } else { return NSAPI_ERROR_OK; } #if PREF_ADDR_TIMEOUT if (stack != IPV4_STACK && stack != IPV6_STACK) { // If address is not for preferred stack waits a while to see // if preferred stack address is acquired if (!mbed_lwip_get_ip_addr(false, &lwip_netif)) { sys_arch_sem_wait(&lwip_netif_has_pref_addr, PREF_ADDR_TIMEOUT * 1000); } } #endif #if BOTH_ADDR_TIMEOUT if (stack != IPV4_STACK && stack != IPV6_STACK) { // If addresses for both stacks are not available waits a while to // see if address for both stacks are acquired if (!(mbed_lwip_get_ipv4_addr(&lwip_netif) && mbed_lwip_get_ipv6_addr(&lwip_netif))) { sys_arch_sem_wait(&lwip_netif_has_both_addr, BOTH_ADDR_TIMEOUT * 1000); } } #endif add_dns_addr(&lwip_netif); return NSAPI_ERROR_OK; }
static void mbed_lwip_netif_status_irq(struct netif *lwip_netif) { if (netif_is_up(lwip_netif)) { bool dns_addr_has_to_be_added = false; if (!(lwip_has_addr_state & HAS_ANY_ADDR) && mbed_lwip_get_ip_addr(true, lwip_netif)) { if (lwip_blocking) { sys_sem_signal(&lwip_netif_has_any_addr); } lwip_has_addr_state |= HAS_ANY_ADDR; dns_addr_has_to_be_added = true; } #if PREF_ADDR_TIMEOUT if (!(lwip_has_addr_state & HAS_PREF_ADDR) && mbed_lwip_get_ip_addr(false, lwip_netif)) { if (lwip_blocking) { sys_sem_signal(&lwip_netif_has_pref_addr); } lwip_has_addr_state |= HAS_PREF_ADDR; dns_addr_has_to_be_added = true; } #endif #if BOTH_ADDR_TIMEOUT if (!(lwip_has_addr_state & HAS_BOTH_ADDR) && mbed_lwip_get_ipv4_addr(lwip_netif) && mbed_lwip_get_ipv6_addr(lwip_netif)) { if (lwip_blocking) { sys_sem_signal(&lwip_netif_has_both_addr); } lwip_has_addr_state |= HAS_BOTH_ADDR; dns_addr_has_to_be_added = true; } #endif if (dns_addr_has_to_be_added && !lwip_blocking) { add_dns_addr(lwip_netif); } if (lwip_has_addr_state & HAS_ANY_ADDR) { lwip_connected = NSAPI_STATUS_GLOBAL_UP; } } else { lwip_connected = NSAPI_STATUS_DISCONNECTED; } if (lwip_client_callback) { lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE, lwip_connected); } }
static void mbed_lwip_netif_status_irq(struct netif *lwip_netif) { if (netif_is_up(lwip_netif)) { if (!(lwip_has_addr_state & HAS_ANY_ADDR) && mbed_lwip_get_ip_addr(true, lwip_netif)) { sys_sem_signal(&lwip_netif_has_any_addr); lwip_has_addr_state |= HAS_ANY_ADDR; } #if PREF_ADDR_TIMEOUT if (!(lwip_has_addr_state & HAS_PREF_ADDR) && mbed_lwip_get_ip_addr(false, lwip_netif)) { sys_sem_signal(&lwip_netif_has_pref_addr); lwip_has_addr_state |= HAS_PREF_ADDR; } #endif #if BOTH_ADDR_TIMEOUT if (!(lwip_has_addr_state & HAS_BOTH_ADDR) && mbed_lwip_get_ipv4_addr(lwip_netif) && mbed_lwip_get_ipv6_addr(lwip_netif)) { sys_sem_signal(&lwip_netif_has_both_addr); lwip_has_addr_state |= HAS_BOTH_ADDR; } #endif } }