Kenji Arai / TYBLE16_mbedlized_os5_several_examples_1st

Dependencies:   nRF51_Vdd TextLCD BME280

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LWIPInterface.cpp Source File

LWIPInterface.cpp

00001 /* Copyright (c) 2017 ARM Limited
00002  *
00003  * Licensed under the Apache License, Version 2.0 (the "License");
00004  * you may not use this file except in compliance with the License.
00005  * You may obtain a copy of the License at
00006  *
00007  *     http://www.apache.org/licenses/LICENSE-2.0
00008  *
00009  * Unless required by applicable law or agreed to in writing, software
00010  * distributed under the License is distributed on an "AS IS" BASIS,
00011  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00012  * See the License for the specific language governing permissions and
00013  * limitations under the License.
00014  */
00015 
00016 #define __STDC_LIMIT_MACROS
00017 
00018 #include "nsapi.h"
00019 #include "mbed_interface.h"
00020 #include "mbed_assert.h"
00021 #include <stdio.h>
00022 #include <stdbool.h>
00023 #include <string.h>
00024 #include <new>
00025 #include <stdint.h>
00026 
00027 #include "lwip/opt.h"
00028 #include "lwip/api.h"
00029 #include "lwip/inet.h"
00030 #include "lwip/netif.h"
00031 #include "lwip/dhcp.h"
00032 #include "lwip/tcpip.h"
00033 #include "lwip/tcp.h"
00034 #include "lwip/ip.h"
00035 #include "lwip/mld6.h"
00036 #include "lwip/dns.h"
00037 #include "lwip/udp.h"
00038 
00039 #include "ppp_lwip.h"
00040 
00041 #include "LWIPStack.h"
00042 
00043 LWIP::Interface *LWIP::Interface::list;
00044 
00045 LWIP::Interface *LWIP::Interface::our_if_from_netif(struct netif *netif)
00046 {
00047     for (Interface *interface = list; interface; interface = interface->next) {
00048         if (netif == &interface->netif) {
00049             return interface;
00050         }
00051     }
00052 
00053     return NULL;
00054 }
00055 
00056 static void add_dns_addr_to_dns_list_index(const u8_t addr_type, const u8_t index)
00057 {
00058 #if LWIP_IPV6
00059     if (addr_type == IPADDR_TYPE_V6) {
00060         /* 2001:4860:4860::8888 google */
00061         ip_addr_t ipv6_dns_addr = IPADDR6_INIT(
00062                 PP_HTONL(0x20014860UL),
00063                 PP_HTONL(0x48600000UL),
00064                 PP_HTONL(0x00000000UL),
00065                 PP_HTONL(0x00008888UL));
00066         dns_setserver(index, &ipv6_dns_addr);
00067     }
00068 #endif
00069 #if LWIP_IPV4
00070     if (addr_type == IPADDR_TYPE_V4) {
00071         /* 8.8.8.8 google */
00072         ip_addr_t ipv4_dns_addr = IPADDR4_INIT(0x08080808);
00073         dns_setserver(index, &ipv4_dns_addr);
00074     }
00075 #endif
00076 }
00077 
00078 static int get_ip_addr_type(const ip_addr_t *ip_addr)
00079 {
00080 #if LWIP_IPV6
00081     if (IP_IS_V6(ip_addr)) {
00082         return IPADDR_TYPE_V6;
00083     }
00084 #endif
00085 #if LWIP_IPV4
00086     if (IP_IS_V4(ip_addr)) {
00087         return IPADDR_TYPE_V4;
00088     }
00089 #endif
00090 #if LWIP_IPV6 && LWIP_IPV4
00091     return IPADDR_TYPE_ANY;
00092 #endif
00093 }
00094 
00095 void LWIP::add_dns_addr(struct netif *lwip_netif)
00096 {
00097     // Check for existing dns address
00098     for (char numdns = 0; numdns < DNS_MAX_SERVERS; numdns++) {
00099         const ip_addr_t *dns_ip_addr = dns_getserver(numdns);
00100         if (!ip_addr_isany(dns_ip_addr)) {
00101             return;
00102         }
00103     }
00104 
00105     // Get preferred ip version
00106     const ip_addr_t *ip_addr = get_ip_addr(false, lwip_netif);
00107     u8_t addr_type = IPADDR_TYPE_ANY;
00108 
00109     // Add preferred ip version dns address to index 0
00110     if (ip_addr) {
00111         addr_type = get_ip_addr_type(ip_addr);
00112         add_dns_addr_to_dns_list_index(addr_type, 0);
00113     }
00114 
00115 #if LWIP_IPV4 && LWIP_IPV6
00116     if (!ip_addr) {
00117         // Get address for any ip version
00118         ip_addr = get_ip_addr(true, lwip_netif);
00119         if (!ip_addr) {
00120             return;
00121         }
00122         addr_type = get_ip_addr_type(ip_addr);
00123         // Add the dns address to index 0
00124         add_dns_addr_to_dns_list_index(addr_type, 0);
00125     }
00126 
00127     if (addr_type == IPADDR_TYPE_V4) {
00128         // If ipv4 is preferred and ipv6 is available add ipv6 dns address to index 1
00129         ip_addr = get_ipv6_addr(lwip_netif);
00130     } else if (addr_type == IPADDR_TYPE_V6) {
00131         // If ipv6 is preferred and ipv4 is available add ipv4 dns address to index 1
00132         ip_addr = get_ipv4_addr(lwip_netif);
00133     } else {
00134         ip_addr = NULL;
00135     }
00136 
00137     if (ip_addr) {
00138         addr_type = get_ip_addr_type(ip_addr);
00139         add_dns_addr_to_dns_list_index(addr_type, 1);
00140     }
00141 #endif
00142 }
00143 
00144 nsapi_error_t LWIP::Interface::set_dhcp()
00145 {
00146     netif_set_up(&netif);
00147 
00148 #if LWIP_DHCP
00149     if (dhcp_has_to_be_set) {
00150         err_t err = dhcp_start(&netif);
00151         dhcp_has_to_be_set = false;
00152         if (err) {
00153             connected = NSAPI_STATUS_DISCONNECTED ;
00154             if (client_callback) {
00155                 client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_DISCONNECTED );
00156             }
00157             return NSAPI_ERROR_DHCP_FAILURE ;
00158         }
00159         dhcp_started = true;
00160     }
00161 #endif
00162 
00163     return NSAPI_ERROR_OK ;
00164 }
00165 
00166 void LWIP::Interface::netif_link_irq(struct netif *netif)
00167 {
00168     LWIP::Interface *interface = our_if_from_netif(netif);
00169     nsapi_connection_status_t connectedStatusPrev = interface->connected;
00170 
00171     if (netif_is_link_up(&interface->netif) && interface->connected == NSAPI_STATUS_CONNECTING ) {
00172         nsapi_error_t dhcp_status = interface->set_dhcp();
00173 
00174         if (interface->blocking && dhcp_status == NSAPI_ERROR_OK ) {
00175             osSemaphoreRelease(interface->linked);
00176         } else if (dhcp_status != NSAPI_ERROR_OK ) {
00177             netif_set_down(&interface->netif);
00178         }
00179     } else {
00180         osSemaphoreRelease(interface->unlinked);
00181         if (netif_is_up(&interface->netif)) {
00182             interface->connected = NSAPI_STATUS_CONNECTING ;
00183         }
00184         netif_set_down(&interface->netif);
00185     }
00186 
00187     if (interface->client_callback && connectedStatusPrev != interface->connected
00188             && interface->connected != NSAPI_STATUS_GLOBAL_UP  /* advertised by netif_status_irq */
00189             && interface->connected != NSAPI_STATUS_DISCONNECTED ) /* advertised by bring_down */ {
00190         interface->client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE , interface->connected);
00191     }
00192 }
00193 
00194 void LWIP::Interface::netif_status_irq(struct netif *netif)
00195 {
00196     LWIP::Interface *interface = our_if_from_netif(netif);
00197     nsapi_connection_status_t connectedStatusPrev = interface->connected;
00198 
00199     if (netif_is_up(&interface->netif) && netif_is_link_up(&interface->netif)) {
00200         bool dns_addr_has_to_be_added = false;
00201         if (!(interface->has_addr_state & HAS_ANY_ADDR) && LWIP::get_ip_addr(true, netif)) {
00202             if (interface->blocking) {
00203                 osSemaphoreRelease(interface->has_any_addr);
00204             }
00205             interface->has_addr_state |= HAS_ANY_ADDR;
00206             dns_addr_has_to_be_added = true;
00207         }
00208 #if PREF_ADDR_TIMEOUT
00209         if (!(interface->has_addr_state & HAS_PREF_ADDR) && LWIP::get_ip_addr(false, netif)) {
00210             if (interface->blocking) {
00211                 osSemaphoreRelease(interface->has_pref_addr);
00212             }
00213             interface->has_addr_state |= HAS_PREF_ADDR;
00214             dns_addr_has_to_be_added = true;
00215         }
00216 #endif
00217 #if BOTH_ADDR_TIMEOUT
00218         if (!(interface->has_addr_state & HAS_BOTH_ADDR) && LWIP::get_ipv4_addr(netif) && LWIP::get_ipv6_addr(netif)) {
00219             if (interface->blocking) {
00220                 osSemaphoreRelease(interface->has_both_addr);
00221             }
00222             interface->has_addr_state |= HAS_BOTH_ADDR;
00223             dns_addr_has_to_be_added = true;
00224         }
00225 #endif
00226         if (dns_addr_has_to_be_added && !interface->blocking) {
00227             add_dns_addr(&interface->netif);
00228         }
00229 
00230         if (interface->has_addr_state & HAS_ANY_ADDR) {
00231             interface->connected = NSAPI_STATUS_GLOBAL_UP ;
00232         }
00233     } else if (!netif_is_up(&interface->netif) && netif_is_link_up(&interface->netif)) {
00234         interface->connected = NSAPI_STATUS_DISCONNECTED ;
00235     }
00236 
00237     if (interface->client_callback && (connectedStatusPrev != interface->connected)
00238             && interface->connected != NSAPI_STATUS_DISCONNECTED ) /* advertised by bring_down */ {
00239         interface->client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE , interface->connected);
00240     }
00241 }
00242 
00243 void LWIP::Interface::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
00244 {
00245     client_callback = status_cb;
00246 }
00247 
00248 nsapi_connection_status_t LWIP::Interface::get_connection_status() const
00249 {
00250     return connected;
00251 }
00252 
00253 #if LWIP_IPV6
00254 static void mbed_lwip_clear_ipv6_addresses(struct netif *netif)
00255 {
00256     for (u8_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
00257         netif_ip6_addr_set_state(netif, i, IP6_ADDR_INVALID);
00258     }
00259 }
00260 #endif
00261 
00262 char *LWIP::Interface::get_mac_address(char *buf, nsapi_size_t buflen)
00263 {
00264     (void) snprintf(buf, buflen, "%02x:%02x:%02x:%02x:%02x:%02x",
00265              netif.hwaddr[0], netif.hwaddr[1], netif.hwaddr[2],
00266              netif.hwaddr[3], netif.hwaddr[4], netif.hwaddr[5]);
00267     return buf;
00268 }
00269 
00270 char *LWIP::Interface::get_ip_address(char *buf, nsapi_size_t buflen)
00271 {
00272     const ip_addr_t *addr = LWIP::get_ip_addr(true, &netif);
00273     if (!addr) {
00274         return NULL;
00275     }
00276 #if LWIP_IPV6
00277     if (IP_IS_V6(addr)) {
00278         return ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen);
00279     }
00280 #endif
00281 #if LWIP_IPV4
00282     if (IP_IS_V4(addr)) {
00283         return ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen);
00284     }
00285 #endif
00286 #if LWIP_IPV6 && LWIP_IPV4
00287     return NULL;
00288 #endif
00289 }
00290 
00291 char *LWIP::Interface::get_netmask(char *buf, nsapi_size_t buflen)
00292 {
00293 #if LWIP_IPV4
00294     const ip4_addr_t *addr = netif_ip4_netmask(&netif);
00295     if (!ip4_addr_isany(addr)) {
00296         return ip4addr_ntoa_r(addr, buf, buflen);
00297     } else {
00298         return NULL;
00299     }
00300 #else
00301     return NULL;
00302 #endif
00303 }
00304 
00305 char *LWIP::Interface::get_gateway(char *buf, nsapi_size_t buflen)
00306 {
00307 #if LWIP_IPV4
00308     const ip4_addr_t *addr = netif_ip4_gw(&netif);
00309     if (!ip4_addr_isany(addr)) {
00310         return ip4addr_ntoa_r(addr, buf, buflen);
00311     } else {
00312         return NULL;
00313     }
00314 #else
00315     return NULL;
00316 #endif
00317 }
00318 
00319 LWIP::Interface::Interface() :
00320         hw(NULL), has_addr_state(0),
00321         connected(NSAPI_STATUS_DISCONNECTED ),
00322         dhcp_started(false), dhcp_has_to_be_set(false), blocking(true), ppp(false)
00323 {
00324     memset(&netif, 0, sizeof netif);
00325 
00326     osSemaphoreAttr_t attr;
00327     attr.name = NULL;
00328     attr.attr_bits = 0;
00329 
00330     attr.cb_mem = &linked_sem;
00331     attr.cb_size = sizeof linked_sem;
00332     linked = osSemaphoreNew(UINT16_MAX, 0, &attr);
00333 
00334     attr.cb_mem = &unlinked_sem;
00335     attr.cb_size = sizeof unlinked_sem;
00336     unlinked = osSemaphoreNew(UINT16_MAX, 0, &attr);
00337 
00338     attr.cb_mem = &has_any_addr_sem;
00339     attr.cb_size = sizeof has_any_addr_sem;
00340     has_any_addr = osSemaphoreNew(UINT16_MAX, 0, &attr);
00341 #if PREF_ADDR_TIMEOUT
00342     attr.cb_mem = &has_pref_addr_sem;
00343     attr.cb_size = sizeof has_pref_addr_sem;
00344     has_pref_addr = osSemaphoreNew(UINT16_MAX, 0, &attr);
00345 #endif
00346 #if BOTH_ADDR_TIMEOUT
00347     attr.cb_mem = &has_both_addr_sem;
00348     attr.cb_size = sizeof has_both_addr_sem;
00349     has_both_addr = osSemaphoreNew(UINT16_MAX, 0, &attr);
00350 #endif
00351 
00352     next = list;
00353     list = this;
00354 }
00355 
00356 nsapi_error_t LWIP::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out)
00357 {
00358 #if LWIP_ETHERNET
00359     Interface *interface = new (std::nothrow) Interface();
00360     if (!interface) {
00361         return NSAPI_ERROR_NO_MEMORY ;
00362     }
00363     interface->emac = &emac;
00364     interface->memory_manager = &memory_manager;
00365     interface->ppp = false;
00366 
00367 #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
00368     netif->interface.hwaddr[0] = MBED_MAC_ADDR_0;
00369     netif->interface.hwaddr[1] = MBED_MAC_ADDR_1;
00370     netif->interface.hwaddr[2] = MBED_MAC_ADDR_2;
00371     netif->interface.hwaddr[3] = MBED_MAC_ADDR_3;
00372     netif->interface.hwaddr[4] = MBED_MAC_ADDR_4;
00373     netif->interface.hwaddr[5] = MBED_MAC_ADDR_5;
00374 #else
00375     mbed_mac_address((char *) interface->netif.hwaddr);
00376 #endif
00377 
00378     interface->netif.hwaddr_len = 6;
00379 
00380     if (!netif_add(&interface->netif,
00381 #if LWIP_IPV4
00382             0, 0, 0,
00383 #endif
00384             interface, &LWIP::Interface::emac_if_init, tcpip_input)) {
00385         return NSAPI_ERROR_DEVICE_ERROR ;
00386     }
00387 
00388     if (default_if) {
00389         netif_set_default(&interface->netif);
00390         default_interface = interface;
00391     }
00392 
00393     netif_set_link_callback(&interface->netif, &LWIP::Interface::netif_link_irq);
00394     netif_set_status_callback(&interface->netif, &LWIP::Interface::netif_status_irq);
00395 
00396     *interface_out = interface;
00397 
00398     /* Use mac address as additional seed to random number generator */
00399     uint64_t seed = interface->netif.hwaddr[0];
00400     for (uint8_t i = 1; i < 8; i++) {
00401         seed <<= 8;
00402         seed |= interface->netif.hwaddr[i % 6];
00403     }
00404     lwip_add_random_seed(seed);
00405 
00406     return NSAPI_ERROR_OK ;
00407 #else
00408     return NSAPI_ERROR_UNSUPPORTED ;
00409 #endif //LWIP_ETHERNET
00410 }
00411 
00412 /* Internal API to preserve existing PPP functionality - revise to better match mbed_ipstak_add_ethernet_interface later */
00413 nsapi_error_t LWIP::_add_ppp_interface(void *hw, bool default_if, nsapi_ip_stack_t stack, LWIP::Interface **interface_out)
00414 {
00415 #if LWIP_PPP_API
00416     Interface *interface = new (std::nothrow) Interface();
00417     if (!interface) {
00418         return NSAPI_ERROR_NO_MEMORY ;
00419     }
00420     interface->hw = hw;
00421     interface->ppp = true;
00422 
00423     nsapi_error_t ret = ppp_lwip_if_init(hw, &interface->netif, stack);
00424     if (ret != NSAPI_ERROR_OK ) {
00425         free(interface);
00426         return ret;
00427     }
00428 
00429     if (default_if) {
00430         netif_set_default(&interface->netif);
00431         default_interface = interface;
00432     }
00433 
00434     netif_set_link_callback(&interface->netif, &LWIP::Interface::netif_link_irq);
00435     netif_set_status_callback(&interface->netif, &LWIP::Interface::netif_status_irq);
00436 
00437     *interface_out = interface;
00438 
00439     return NSAPI_ERROR_OK ;
00440 #else
00441     return NSAPI_ERROR_UNSUPPORTED ;
00442 #endif //LWIP_PPP_API
00443 }
00444 
00445 
00446 nsapi_error_t LWIP::Interface::bringup(bool dhcp, const char *ip, const char *netmask, const char *gw, const nsapi_ip_stack_t stack, bool block)
00447 {
00448     // Check if we've already connected
00449     if (connected == NSAPI_STATUS_GLOBAL_UP ) {
00450         return NSAPI_ERROR_IS_CONNECTED ;
00451     } else if (connected == NSAPI_STATUS_CONNECTING ) {
00452         return NSAPI_ERROR_ALREADY ;
00453     }
00454 
00455     connected = NSAPI_STATUS_CONNECTING ;
00456     blocking = block;
00457 
00458 #if LWIP_DHCP
00459     if (stack != IPV6_STACK && dhcp) {
00460         dhcp_has_to_be_set = true;
00461     }
00462 #endif
00463 
00464 #if LWIP_IPV6
00465     if (stack != IPV4_STACK) {
00466         if (netif.hwaddr_len == 6) {
00467             netif_create_ip6_linklocal_address(&netif, 1/*from MAC*/);
00468         }
00469 #if LWIP_IPV6_MLD
00470         /*
00471          * For hardware/netifs that implement MAC filtering.
00472          * All-nodes link-local is handled by default, so we must let the hardware know
00473          * to allow multicast packets in.
00474          * Should set mld_mac_filter previously. */
00475         if (netif.mld_mac_filter != NULL) {
00476             ip6_addr_t ip6_allnodes_ll;
00477             ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
00478             netif.mld_mac_filter(&netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
00479         }
00480 #endif /* LWIP_IPV6_MLD */
00481 
00482 #if LWIP_IPV6_AUTOCONFIG
00483         /* IPv6 address autoconfiguration not enabled by default */
00484         netif.ip6_autoconfig_enabled = 1;
00485 #endif /* LWIP_IPV6_AUTOCONFIG */
00486     } else {
00487         // Disable rourter solicitations
00488         netif.rs_count = 0;
00489     }
00490 #endif /* LWIP_IPV6 */
00491 
00492 #if LWIP_IPV4
00493     if (stack != IPV6_STACK) {
00494         if (!dhcp && !ppp) {
00495             ip4_addr_t ip_addr;
00496             ip4_addr_t netmask_addr;
00497             ip4_addr_t gw_addr;
00498 
00499             if (!inet_aton(ip, &ip_addr) ||
00500                 !inet_aton(netmask, &netmask_addr) ||
00501                 !inet_aton(gw, &gw_addr)) {
00502                 return NSAPI_ERROR_PARAMETER ;
00503             }
00504 
00505             netif_set_addr(&netif, &ip_addr, &netmask_addr, &gw_addr);
00506         }
00507     }
00508 #endif
00509 
00510     if (client_callback) {
00511         client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_CONNECTING );
00512     }
00513 
00514     if (ppp) {
00515        err_t err = ppp_lwip_connect(hw);
00516        if (err) {
00517            connected = NSAPI_STATUS_DISCONNECTED ;
00518            if (client_callback) {
00519                client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_DISCONNECTED );
00520            }
00521           return err_remap(err);
00522        }
00523     }
00524 
00525     if (!netif_is_link_up(&netif)) {
00526         if (blocking) {
00527             if (osSemaphoreAcquire(linked, 15000) != osOK) {
00528                 if (ppp) {
00529                     (void) ppp_lwip_disconnect(hw);
00530                 }
00531                 return NSAPI_ERROR_NO_CONNECTION ;
00532             }
00533         }
00534     } else {
00535         nsapi_error_t ret = set_dhcp();
00536         if (ret != NSAPI_ERROR_OK ) {
00537             return ret;
00538         }
00539     }
00540 
00541     if (!blocking) {
00542         // Done enough - as addresses are acquired, there will be
00543         // connected callbacks.
00544         // XXX shouldn't this be NSAPI_ERROR_IN_PROGRESS if in CONNECTING state?
00545         return NSAPI_ERROR_OK ;
00546     }
00547 
00548     // If doesn't have address
00549     if (!LWIP::get_ip_addr(true, &netif)) {
00550         if (osSemaphoreAcquire(has_any_addr, DHCP_TIMEOUT * 1000) != osOK) {
00551             if (ppp) {
00552                 (void) ppp_lwip_disconnect(hw);
00553             }
00554             return NSAPI_ERROR_DHCP_FAILURE ;
00555         }
00556     }
00557 
00558 #if PREF_ADDR_TIMEOUT
00559     if (stack != IPV4_STACK && stack != IPV6_STACK) {
00560         // If address is not for preferred stack waits a while to see
00561         // if preferred stack address is acquired
00562         if (!LWIP::get_ip_addr(false, &netif)) {
00563             osSemaphoreAcquire(has_pref_addr, PREF_ADDR_TIMEOUT * 1000);
00564         }
00565     }
00566 #endif
00567 #if BOTH_ADDR_TIMEOUT
00568     if (stack != IPV4_STACK && stack != IPV6_STACK) {
00569         // If addresses for both stacks are not available waits a while to
00570         // see if address for both stacks are acquired
00571         if (!(LWIP::get_ipv4_addr(&netif) && LWIP::get_ipv6_addr(&netif))) {
00572             osSemaphoreAcquire(has_both_addr, BOTH_ADDR_TIMEOUT * 1000);
00573         }
00574     }
00575 #endif
00576 
00577     add_dns_addr(&netif);
00578 
00579     return NSAPI_ERROR_OK ;
00580 }
00581 
00582 nsapi_error_t LWIP::Interface::bringdown()
00583 {
00584     // Check if we've connected
00585     if (connected == NSAPI_STATUS_DISCONNECTED ) {
00586         return NSAPI_ERROR_PARAMETER ;
00587     }
00588 
00589 #if LWIP_DHCP
00590     // Disconnect from the network
00591     if (dhcp_started) {
00592         dhcp_release(&netif);
00593         dhcp_stop(&netif);
00594         dhcp_started = false;
00595         dhcp_has_to_be_set = false;
00596     }
00597 #endif
00598 
00599     if (ppp) {
00600         /* this is a blocking call, returns when PPP is properly closed */
00601        err_t err = ppp_lwip_disconnect(hw);
00602        if (err) {
00603            return err_remap(err);
00604        }
00605        MBED_ASSERT(!netif_is_link_up(&netif));
00606        /*if (netif_is_link_up(&netif)) {
00607            if (sys_arch_sem_wait(&unlinked, 15000) == SYS_ARCH_TIMEOUT) {
00608                return NSAPI_ERROR_DEVICE_ERROR;
00609            }
00610        }*/
00611     } else {
00612         netif_set_down(&netif);
00613     }
00614 
00615 #if LWIP_IPV6
00616     mbed_lwip_clear_ipv6_addresses(&netif);
00617 #endif
00618 #if LWIP_IPV4
00619     ip_addr_set_zero(&(netif.ip_addr));
00620     ip_addr_set_zero(&(netif.netmask));
00621     ip_addr_set_zero(&(netif.gw));
00622 #endif
00623 
00624     osSemaphoreDelete(has_any_addr);
00625     osSemaphoreAttr_t attr;
00626     attr.name = NULL;
00627     attr.attr_bits = 0;
00628     attr.cb_mem = &has_any_addr_sem;
00629     attr.cb_size = sizeof has_any_addr_sem;
00630     has_any_addr = osSemaphoreNew(UINT16_MAX, 0, &attr);
00631 #if PREF_ADDR_TIMEOUT
00632     osSemaphoreDelete(has_pref_addr);
00633     attr.cb_mem = &has_pref_addr_sem;
00634     attr.cb_size = sizeof has_pref_addr_sem;
00635     has_pref_addr = osSemaphoreNew(UINT16_MAX, 0, &attr);
00636 #endif
00637 #if BOTH_ADDR_TIMEOUT
00638     osSemaphoreDelete(has_both_addr);
00639     attr.cb_mem = &has_both_addr_sem;
00640     attr.cb_size = sizeof has_both_addr_sem;
00641     has_both_addr = osSemaphoreNew(UINT16_MAX, 0, &attr);
00642 #endif
00643     has_addr_state = 0;
00644 
00645     connected = NSAPI_STATUS_DISCONNECTED ;
00646     if (client_callback) {
00647         client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE , connected);
00648     }
00649     return 0;
00650 }