Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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 "LWIPStack.h"
00040 #include "lwip_tools.h"
00041 
00042 LWIP::Interface *LWIP::Interface::list;
00043 
00044 LWIP::Interface *LWIP::Interface::our_if_from_netif(struct netif *netif)
00045 {
00046     for (Interface *interface = list; interface; interface = interface->next) {
00047         if (netif == &interface->netif) {
00048             return interface;
00049         }
00050     }
00051 
00052     return NULL;
00053 }
00054 
00055 static void add_dns_addr_to_dns_list_index(const u8_t addr_type, const u8_t index, struct netif *netif)
00056 {
00057 #if LWIP_IPV6
00058     if (addr_type == IPADDR_TYPE_V6) {
00059         /* 2001:4860:4860::8888 google */
00060         ip_addr_t ipv6_dns_addr = IPADDR6_INIT(
00061                                       PP_HTONL(0x20014860UL),
00062                                       PP_HTONL(0x48600000UL),
00063                                       PP_HTONL(0x00000000UL),
00064                                       PP_HTONL(0x00008888UL));
00065         dns_setserver(index, &ipv6_dns_addr, netif);
00066     }
00067 #endif
00068 #if LWIP_IPV4
00069     if (addr_type == IPADDR_TYPE_V4) {
00070         /* 8.8.8.8 google */
00071         ip_addr_t ipv4_dns_addr = IPADDR4_INIT(0x08080808);
00072         dns_setserver(index, &ipv4_dns_addr, netif);
00073     }
00074 #endif
00075 }
00076 
00077 static int get_ip_addr_type(const ip_addr_t *ip_addr)
00078 {
00079 #if LWIP_IPV6
00080     if (IP_IS_V6(ip_addr)) {
00081         return IPADDR_TYPE_V6;
00082     }
00083 #endif
00084 #if LWIP_IPV4
00085     if (IP_IS_V4(ip_addr)) {
00086         return IPADDR_TYPE_V4;
00087     }
00088 #endif
00089 #if LWIP_IPV6 && LWIP_IPV4
00090     return IPADDR_TYPE_ANY;
00091 #endif
00092 }
00093 
00094 void LWIP::add_dns_addr(struct netif *lwip_netif, const char *interface_name)
00095 {
00096     // Check for existing dns address
00097     for (char numdns = 0; numdns < DNS_MAX_SERVERS; numdns++) {
00098         const ip_addr_t *dns_ip_addr = dns_getserver(numdns, interface_name);
00099         if (!ip_addr_isany(dns_ip_addr)) {
00100             return;
00101         }
00102     }
00103 
00104     // Get preferred ip version
00105     const ip_addr_t *ip_addr = get_ip_addr(false, lwip_netif);
00106     u8_t addr_type = IPADDR_TYPE_ANY;
00107 
00108     // Add preferred ip version dns address to index 0
00109     if (ip_addr) {
00110         addr_type = get_ip_addr_type(ip_addr);
00111         add_dns_addr_to_dns_list_index(addr_type, 0, lwip_netif);
00112     }
00113 
00114 #if LWIP_IPV4 && LWIP_IPV6
00115     if (!ip_addr) {
00116         // Get address for any ip version
00117         ip_addr = get_ip_addr(true, lwip_netif);
00118         if (!ip_addr) {
00119             return;
00120         }
00121         addr_type = get_ip_addr_type(ip_addr);
00122         // Add the dns address to index 0
00123         add_dns_addr_to_dns_list_index(addr_type, 0, lwip_netif);
00124     }
00125 
00126     if (addr_type == IPADDR_TYPE_V4) {
00127         // If ipv4 is preferred and ipv6 is available add ipv6 dns address to index 1
00128         ip_addr = get_ipv6_addr(lwip_netif);
00129     } else if (addr_type == IPADDR_TYPE_V6) {
00130         // If ipv6 is preferred and ipv4 is available add ipv4 dns address to index 1
00131         ip_addr = get_ipv4_addr(lwip_netif);
00132     } else {
00133         ip_addr = NULL;
00134     }
00135 
00136     if (ip_addr) {
00137         addr_type = get_ip_addr_type(ip_addr);
00138         add_dns_addr_to_dns_list_index(addr_type, 1, lwip_netif);
00139     }
00140 #endif
00141 }
00142 
00143 nsapi_error_t LWIP::Interface::set_dhcp()
00144 {
00145     netif_set_up(&netif);
00146 
00147 #if LWIP_DHCP
00148     if (dhcp_has_to_be_set) {
00149         err_t err = dhcp_start(&netif);
00150         dhcp_has_to_be_set = false;
00151         if (err) {
00152             connected = NSAPI_STATUS_DISCONNECTED ;
00153             if (client_callback) {
00154                 client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_DISCONNECTED );
00155             }
00156             return NSAPI_ERROR_DHCP_FAILURE ;
00157         }
00158         dhcp_started = true;
00159     }
00160 #endif
00161 
00162     return NSAPI_ERROR_OK ;
00163 }
00164 
00165 void LWIP::Interface::netif_link_irq(struct netif *netif)
00166 {
00167     LWIP::Interface *interface = our_if_from_netif(netif);
00168     nsapi_connection_status_t connectedStatusPrev = interface->connected;
00169 
00170     if (netif_is_link_up(&interface->netif) && interface->connected == NSAPI_STATUS_CONNECTING ) {
00171         nsapi_error_t dhcp_status = interface->set_dhcp();
00172 
00173         if (interface->blocking && dhcp_status == NSAPI_ERROR_OK ) {
00174             osSemaphoreRelease(interface->linked);
00175         } else if (dhcp_status != NSAPI_ERROR_OK ) {
00176             netif_set_down(&interface->netif);
00177         }
00178     } else {
00179         osSemaphoreRelease(interface->unlinked);
00180         if (netif_is_up(&interface->netif)) {
00181             interface->connected = NSAPI_STATUS_CONNECTING ;
00182         }
00183         netif_set_down(&interface->netif);
00184     }
00185 
00186     if (interface->client_callback && connectedStatusPrev != interface->connected
00187             && interface->connected != NSAPI_STATUS_GLOBAL_UP  /* advertised by netif_status_irq */
00188             && interface->connected != NSAPI_STATUS_DISCONNECTED ) { /* advertised by bring_down */
00189         interface->client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE , interface->connected);
00190     }
00191 }
00192 
00193 void LWIP::Interface::netif_status_irq(struct netif *netif)
00194 {
00195     LWIP::Interface *interface = our_if_from_netif(netif);
00196     nsapi_connection_status_t connectedStatusPrev = interface->connected;
00197 
00198     if (netif_is_up(&interface->netif) && netif_is_link_up(&interface->netif)) {
00199         bool dns_addr_has_to_be_added = false;
00200         if (!(interface->has_addr_state & HAS_ANY_ADDR) && LWIP::get_ip_addr(true, netif)) {
00201             if (interface->blocking) {
00202                 osSemaphoreRelease(interface->has_any_addr);
00203             }
00204             interface->has_addr_state |= HAS_ANY_ADDR;
00205             dns_addr_has_to_be_added = true;
00206         }
00207 #if PREF_ADDR_TIMEOUT
00208         if (!(interface->has_addr_state & HAS_PREF_ADDR) && LWIP::get_ip_addr(false, netif)) {
00209             if (interface->blocking) {
00210                 osSemaphoreRelease(interface->has_pref_addr);
00211             }
00212             interface->has_addr_state |= HAS_PREF_ADDR;
00213             dns_addr_has_to_be_added = true;
00214         }
00215 #endif
00216 #if BOTH_ADDR_TIMEOUT
00217         if (!(interface->has_addr_state & HAS_BOTH_ADDR) && LWIP::get_ipv4_addr(netif) && LWIP::get_ipv6_addr(netif)) {
00218             if (interface->blocking) {
00219                 osSemaphoreRelease(interface->has_both_addr);
00220             }
00221             interface->has_addr_state |= HAS_BOTH_ADDR;
00222             dns_addr_has_to_be_added = true;
00223         }
00224 #endif
00225         if (dns_addr_has_to_be_added && !interface->blocking) {
00226             add_dns_addr(&interface->netif, interface->get_interface_name(interface->_interface_name));
00227         }
00228 
00229         if (interface->has_addr_state & HAS_ANY_ADDR) {
00230             interface->connected = NSAPI_STATUS_GLOBAL_UP ;
00231 #if LWIP_IPV6
00232             if (ip_addr_islinklocal(get_ipv6_addr(netif))) {
00233                 interface->connected = NSAPI_STATUS_LOCAL_UP ;
00234             }
00235 #endif
00236         }
00237 
00238     } else if (!netif_is_up(&interface->netif) && netif_is_link_up(&interface->netif)) {
00239         interface->connected = NSAPI_STATUS_DISCONNECTED ;
00240     }
00241 
00242     if (interface->client_callback && (connectedStatusPrev != interface->connected)
00243             && interface->connected != NSAPI_STATUS_DISCONNECTED ) { /* advertised by bring_down */
00244         interface->client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE , interface->connected);
00245     }
00246 }
00247 
00248 void LWIP::Interface::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
00249 {
00250     client_callback = status_cb;
00251 }
00252 
00253 nsapi_connection_status_t LWIP::Interface::get_connection_status() const
00254 {
00255     return connected;
00256 }
00257 
00258 #if LWIP_IPV6
00259 static void mbed_lwip_clear_ipv6_addresses(struct netif *netif)
00260 {
00261     for (u8_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
00262         netif_ip6_addr_set_state(netif, i, IP6_ADDR_INVALID);
00263     }
00264 }
00265 #endif
00266 
00267 char *LWIP::Interface::get_mac_address(char *buf, nsapi_size_t buflen)
00268 {
00269     (void) snprintf(buf, buflen, "%02x:%02x:%02x:%02x:%02x:%02x",
00270                     netif.hwaddr[0], netif.hwaddr[1], netif.hwaddr[2],
00271                     netif.hwaddr[3], netif.hwaddr[4], netif.hwaddr[5]);
00272     return buf;
00273 }
00274 
00275 char *LWIP::Interface::get_interface_name(char *buf)
00276 {
00277     sprintf(buf, "%c%c%d", netif.name[0], netif.name[1], netif.num);
00278     return buf;
00279 }
00280 
00281 nsapi_error_t LWIP::Interface::get_ipv6_link_local_address(SocketAddress *address)
00282 {
00283 #if LWIP_IPV6
00284     const ip_addr_t *addr = LWIP::get_ipv6_link_local_addr(&netif);
00285     nsapi_addr_t out;
00286     bool ret;
00287 
00288     if (!addr) {
00289         return NSAPI_ERROR_PARAMETER ;
00290     }
00291 
00292     ret = convert_lwip_addr_to_mbed(&out, addr);
00293     if (ret != true) {
00294         return NSAPI_ERROR_PARAMETER ;
00295     }
00296 
00297     address->set_addr(out);
00298 
00299     return NSAPI_ERROR_OK ;
00300 #else
00301     return NSAPI_ERROR_UNSUPPORTED ;
00302 #endif
00303 }
00304 
00305 nsapi_error_t LWIP::Interface::get_ip_address(SocketAddress *address)
00306 {
00307     if (!address) {
00308         return NSAPI_ERROR_PARAMETER ;
00309     }
00310     const ip_addr_t *addr = LWIP::get_ip_addr(true, &netif);
00311     if (!addr) {
00312         return NSAPI_ERROR_NO_ADDRESS ;
00313     }
00314 #if LWIP_IPV6
00315     if (IP_IS_V6(addr)) {
00316         char buf[NSAPI_IPv6_SIZE];
00317         address->set_ip_address(ip6addr_ntoa_r(ip_2_ip6(addr), buf, NSAPI_IPv6_SIZE));
00318         return NSAPI_ERROR_OK ;
00319     }
00320 #endif
00321 #if LWIP_IPV4
00322     if (IP_IS_V4(addr)) {
00323         char buf[NSAPI_IPv4_SIZE];
00324         address->set_ip_address(ip4addr_ntoa_r(ip_2_ip4(addr), buf, NSAPI_IPv4_SIZE));
00325         return NSAPI_ERROR_OK ;
00326     }
00327 #endif
00328     return NSAPI_ERROR_UNSUPPORTED ;
00329 }
00330 
00331 char *LWIP::Interface::get_ip_address(char *buf, nsapi_size_t buflen)
00332 {
00333     const ip_addr_t *addr = LWIP::get_ip_addr(true, &netif);
00334     if (!addr) {
00335         return NULL;
00336     }
00337 #if LWIP_IPV6
00338     if (IP_IS_V6(addr)) {
00339         return ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen);
00340     }
00341 #endif
00342 #if LWIP_IPV4
00343     if (IP_IS_V4(addr)) {
00344         return ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen);
00345     }
00346 #endif
00347 #if LWIP_IPV6 && LWIP_IPV4
00348     return NULL;
00349 #endif
00350 }
00351 
00352 nsapi_error_t LWIP::Interface::get_netmask(SocketAddress *address)
00353 {
00354     if (!address) {
00355         return NSAPI_ERROR_PARAMETER ;
00356     }
00357 #if LWIP_IPV4
00358     const ip4_addr_t *addr = netif_ip4_netmask(&netif);
00359     if (!ip4_addr_isany(addr)) {
00360         char buf[NSAPI_IPv4_SIZE];
00361         address->set_ip_address(ip4addr_ntoa_r(addr, buf, NSAPI_IPv4_SIZE));
00362         return NSAPI_ERROR_OK ;
00363     } else {
00364         return NSAPI_ERROR_NO_ADDRESS ;
00365     }
00366 #else
00367     return NSAPI_ERROR_UNSUPPORTED ;
00368 #endif
00369 }
00370 
00371 char *LWIP::Interface::get_netmask(char *buf, nsapi_size_t buflen)
00372 {
00373 #if LWIP_IPV4
00374     const ip4_addr_t *addr = netif_ip4_netmask(&netif);
00375     if (!ip4_addr_isany(addr)) {
00376         return ip4addr_ntoa_r(addr, buf, buflen);
00377     } else {
00378         return NULL;
00379     }
00380 #else
00381     return NULL;
00382 #endif
00383 }
00384 
00385 nsapi_error_t LWIP::Interface::get_gateway(SocketAddress *address)
00386 {
00387     if (!address) {
00388         return NSAPI_ERROR_PARAMETER ;
00389     }
00390 #if LWIP_IPV4
00391     const ip4_addr_t *addr = netif_ip4_gw(&netif);
00392     if (!ip4_addr_isany(addr)) {
00393         char buf[NSAPI_IPv4_SIZE];
00394         address->set_ip_address(ip4addr_ntoa_r(addr, buf, NSAPI_IPv4_SIZE));
00395         return NSAPI_ERROR_OK ;
00396     } else {
00397         return NSAPI_ERROR_NO_ADDRESS ;
00398     }
00399 #else
00400     return NSAPI_ERROR_UNSUPPORTED ;
00401 #endif
00402 }
00403 
00404 char *LWIP::Interface::get_gateway(char *buf, nsapi_size_t buflen)
00405 {
00406 #if LWIP_IPV4
00407     const ip4_addr_t *addr = netif_ip4_gw(&netif);
00408     if (!ip4_addr_isany(addr)) {
00409         return ip4addr_ntoa_r(addr, buf, buflen);
00410     } else {
00411         return NULL;
00412     }
00413 #else
00414     return NULL;
00415 #endif
00416 }
00417 
00418 LWIP::Interface::Interface() :
00419     hw(NULL), has_addr_state(0),
00420     connected(NSAPI_STATUS_DISCONNECTED ),
00421     dhcp_started(false), dhcp_has_to_be_set(false), blocking(true), ppp_enabled(false)
00422 {
00423     memset(&netif, 0, sizeof netif);
00424 
00425     osSemaphoreAttr_t attr;
00426     attr.name = NULL;
00427     attr.attr_bits = 0;
00428 
00429     attr.cb_mem = &linked_sem;
00430     attr.cb_size = sizeof linked_sem;
00431     linked = osSemaphoreNew(UINT16_MAX, 0, &attr);
00432 
00433     attr.cb_mem = &unlinked_sem;
00434     attr.cb_size = sizeof unlinked_sem;
00435     unlinked = osSemaphoreNew(UINT16_MAX, 0, &attr);
00436 
00437     attr.cb_mem = &has_any_addr_sem;
00438     attr.cb_size = sizeof has_any_addr_sem;
00439     has_any_addr = osSemaphoreNew(UINT16_MAX, 0, &attr);
00440 #if PREF_ADDR_TIMEOUT
00441     attr.cb_mem = &has_pref_addr_sem;
00442     attr.cb_size = sizeof has_pref_addr_sem;
00443     has_pref_addr = osSemaphoreNew(UINT16_MAX, 0, &attr);
00444 #endif
00445 #if BOTH_ADDR_TIMEOUT
00446     attr.cb_mem = &has_both_addr_sem;
00447     attr.cb_size = sizeof has_both_addr_sem;
00448     has_both_addr = osSemaphoreNew(UINT16_MAX, 0, &attr);
00449 #endif
00450 
00451     next = list;
00452     list = this;
00453 }
00454 
00455 nsapi_error_t LWIP::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out)
00456 {
00457 #if LWIP_ETHERNET
00458     Interface *interface = new (std::nothrow) Interface();
00459     if (!interface) {
00460         return NSAPI_ERROR_NO_MEMORY ;
00461     }
00462     interface->emac = &emac;
00463     interface->memory_manager = &memory_manager;
00464     interface->ppp_enabled = false;
00465 
00466 #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
00467     netif->interface.hwaddr[0] = MBED_MAC_ADDR_0;
00468     netif->interface.hwaddr[1] = MBED_MAC_ADDR_1;
00469     netif->interface.hwaddr[2] = MBED_MAC_ADDR_2;
00470     netif->interface.hwaddr[3] = MBED_MAC_ADDR_3;
00471     netif->interface.hwaddr[4] = MBED_MAC_ADDR_4;
00472     netif->interface.hwaddr[5] = MBED_MAC_ADDR_5;
00473 #else
00474     mbed_mac_address((char *) interface->netif.hwaddr);
00475 #endif
00476 
00477     interface->netif.hwaddr_len = 6;
00478 
00479     if (!netif_add(&interface->netif,
00480 #if LWIP_IPV4
00481                    0, 0, 0,
00482 #endif
00483                    interface, &LWIP::Interface::emac_if_init, tcpip_input)) {
00484         return NSAPI_ERROR_DEVICE_ERROR ;
00485     }
00486 
00487     if (default_if) {
00488         netif_set_default(&interface->netif);
00489         default_interface = interface;
00490     }
00491 
00492     netif_set_link_callback(&interface->netif, &LWIP::Interface::netif_link_irq);
00493     netif_set_status_callback(&interface->netif, &LWIP::Interface::netif_status_irq);
00494 
00495     *interface_out = interface;
00496 
00497     /* Use mac address as additional seed to random number generator */
00498     uint64_t seed = interface->netif.hwaddr[0];
00499     for (uint8_t i = 1; i < 8; i++) {
00500         seed <<= 8;
00501         seed |= interface->netif.hwaddr[i % 6];
00502     }
00503     lwip_add_random_seed(seed);
00504 
00505     return NSAPI_ERROR_OK ;
00506 #else
00507     return NSAPI_ERROR_UNSUPPORTED ;
00508 #endif //LWIP_ETHERNET
00509 }
00510 
00511 
00512 nsapi_error_t LWIP::add_l3ip_interface(L3IP &l3ip, bool default_if, OnboardNetworkStack::Interface **interface_out)
00513 {
00514 #if LWIP_L3IP
00515     Interface *interface = new (std::nothrow) Interface();
00516     if (!interface) {
00517         return NSAPI_ERROR_NO_MEMORY ;
00518     }
00519     interface->l3ip = &l3ip;
00520     interface->memory_manager = &memory_manager;
00521     interface->ppp_enabled = false;
00522 
00523 
00524 
00525     // interface->netif.hwaddr_len = 0; should we set?
00526 
00527     if (!netif_add(&interface->netif,
00528 #if LWIP_IPV4
00529                    0, 0, 0,
00530 #endif
00531                    interface, &LWIP::Interface::l3ip_if_init, ip_input)) {
00532         return NSAPI_ERROR_DEVICE_ERROR ;
00533     }
00534 
00535     if (default_if) {
00536         netif_set_default(&interface->netif);
00537         default_interface = interface;
00538     }
00539 
00540     netif_set_link_callback(&interface->netif, &LWIP::Interface::netif_link_irq);
00541     netif_set_status_callback(&interface->netif, &LWIP::Interface::netif_status_irq);
00542 
00543     *interface_out = interface;
00544 
00545 
00546     //lwip_add_random_seed(seed); to do?
00547 
00548     return NSAPI_ERROR_OK ;
00549 
00550 #else
00551     return NSAPI_ERROR_UNSUPPORTED ;
00552 
00553 #endif //LWIP_L3IP
00554 }
00555 
00556 nsapi_error_t LWIP::remove_l3ip_interface(OnboardNetworkStack::Interface **interface_out)
00557 {
00558 #if LWIP_L3IP
00559     if ((interface_out != NULL) && (*interface_out != NULL)) {
00560 
00561         Interface *lwip = static_cast<Interface *>(*interface_out);
00562         Interface *node = lwip->list;
00563 
00564         if (lwip->list != NULL) {
00565             if (lwip->list == lwip) {
00566                 lwip->list = lwip->list->next;
00567                 netif_remove(&node->netif);
00568                 delete node;
00569             } else {
00570                 while (node->next != NULL && node->next != lwip) {
00571                     node = node->next;
00572                 }
00573                 if (node->next != NULL && node->next == lwip) {
00574                     Interface *remove = node->next;
00575                     node->next = node->next->next;
00576                     remove->l3ip->power_down();
00577                     netif_remove(&remove->netif);
00578                     delete remove;
00579                 }
00580             }
00581         }
00582     }
00583 
00584     return NSAPI_ERROR_OK ;
00585 #else
00586     return NSAPI_ERROR_UNSUPPORTED ;
00587 
00588 #endif //LWIP_L3IP
00589 }
00590 
00591 
00592 nsapi_error_t LWIP::add_ppp_interface(PPP &ppp, bool default_if, OnboardNetworkStack::Interface **interface_out)
00593 {
00594 #if PPP_SUPPORT
00595     Interface *interface = new (std::nothrow) Interface();
00596     if (!interface) {
00597         return NSAPI_ERROR_NO_MEMORY ;
00598     }
00599     interface->ppp = &ppp;
00600     interface->memory_manager = &memory_manager;
00601     interface->ppp_enabled = true;
00602 
00603     // interface->netif.hwaddr_len = 0; should we set?
00604 
00605     if (!netif_add(&interface->netif,
00606 #if LWIP_IPV4
00607                    0, 0, 0,
00608 #endif
00609                    interface, &LWIP::Interface::ppp_if_init, tcpip_input)) {
00610         return NSAPI_ERROR_DEVICE_ERROR ;
00611     }
00612 
00613     if (default_if) {
00614         netif_set_default(&interface->netif);
00615         default_interface = interface;
00616     }
00617 
00618     netif_set_link_callback(&interface->netif, &LWIP::Interface::netif_link_irq);
00619     netif_set_status_callback(&interface->netif, &LWIP::Interface::netif_status_irq);
00620 
00621     *interface_out = interface;
00622 
00623     //lwip_add_random_seed(seed); to do?
00624 
00625     return NSAPI_ERROR_OK ;
00626 
00627 #else
00628     return NSAPI_ERROR_UNSUPPORTED ;
00629 
00630 #endif //PPP_SUPPORT
00631 }
00632 
00633 nsapi_error_t LWIP::remove_ppp_interface(OnboardNetworkStack::Interface **interface_out)
00634 {
00635 #if PPP_SUPPORT
00636     if ((interface_out != NULL) && (*interface_out != NULL)) {
00637 
00638         Interface *lwip = static_cast<Interface *>(*interface_out);
00639         Interface *node = lwip->list;
00640 
00641         if (lwip->list != NULL) {
00642             if (lwip->list == lwip) {
00643                 // Power down PPP service
00644                 lwip->ppp->power_down();
00645                 if (netif_is_link_up(&lwip->netif)) {
00646                     // Wait PPP service to report link down
00647                     osSemaphoreAcquire(lwip->unlinked, osWaitForever);
00648                 }
00649                 netif_remove(&node->netif);
00650                 lwip->list = lwip->list->next;
00651                 delete node;
00652             } else {
00653                 while (node->next != NULL && node->next != lwip) {
00654                     node = node->next;
00655                 }
00656                 if (node->next != NULL && node->next == lwip) {
00657                     Interface *remove = node->next;
00658                     // Power down PPP service
00659                     remove->ppp->power_down();
00660                     if (netif_is_link_up(&lwip->netif)) {
00661                         // Wait PPP service to report link down
00662                         osSemaphoreAcquire(lwip->unlinked, osWaitForever);
00663                     }
00664                     netif_remove(&remove->netif);
00665                     node->next = node->next->next;
00666                     delete remove;
00667                 }
00668             }
00669         }
00670     }
00671 
00672     return NSAPI_ERROR_OK ;
00673 #else
00674     return NSAPI_ERROR_UNSUPPORTED ;
00675 
00676 #endif //PPP_SUPPORT
00677 }
00678 
00679 void LWIP::set_default_interface(OnboardNetworkStack::Interface *interface)
00680 {
00681     if (interface) {
00682         default_interface = static_cast<LWIP::Interface *>(interface);
00683         netif_set_default(&default_interface->netif);
00684     }
00685 }
00686 
00687 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)
00688 {
00689     // Check if we've already connected
00690     if (connected == NSAPI_STATUS_GLOBAL_UP ) {
00691         return NSAPI_ERROR_IS_CONNECTED ;
00692     } else if (connected == NSAPI_STATUS_CONNECTING ) {
00693         return NSAPI_ERROR_BUSY ;
00694     }
00695 
00696     connected = NSAPI_STATUS_CONNECTING ;
00697     blocking = block;
00698 
00699 #if LWIP_DHCP
00700     if (stack != IPV6_STACK && dhcp) {
00701         dhcp_has_to_be_set = true;
00702     }
00703 #endif
00704 
00705 #if LWIP_IPV6
00706     if (stack != IPV4_STACK) {
00707         if (netif.hwaddr_len == 6) {
00708             netif_create_ip6_linklocal_address(&netif, 1/*from MAC*/);
00709         }
00710 #if LWIP_IPV6_MLD
00711         /*
00712          * For hardware/netifs that implement MAC filtering.
00713          * All-nodes link-local is handled by default, so we must let the hardware know
00714          * to allow multicast packets in.
00715          * Should set mld_mac_filter previously. */
00716         if (netif.mld_mac_filter != NULL) {
00717             ip6_addr_t ip6_allnodes_ll;
00718             ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
00719             netif.mld_mac_filter(&netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
00720         }
00721 #endif /* LWIP_IPV6_MLD */
00722 
00723 #if LWIP_IPV6_AUTOCONFIG
00724         /* IPv6 address autoconfiguration not enabled by default */
00725         netif.ip6_autoconfig_enabled = 1;
00726 #endif /* LWIP_IPV6_AUTOCONFIG */
00727     } else {
00728         // Disable rourter solicitations
00729         netif.rs_count = 0;
00730     }
00731 #endif /* LWIP_IPV6 */
00732 
00733 #if LWIP_IPV4
00734     if (stack != IPV6_STACK) {
00735         if (!dhcp && !ppp_enabled) {
00736             ip4_addr_t ip_addr;
00737             ip4_addr_t netmask_addr;
00738             ip4_addr_t gw_addr;
00739 
00740             if (!inet_aton(ip, &ip_addr) ||
00741                     !inet_aton(netmask, &netmask_addr) ||
00742                     !inet_aton(gw, &gw_addr)) {
00743                 return NSAPI_ERROR_PARAMETER ;
00744             }
00745 
00746             netif_set_addr(&netif, &ip_addr, &netmask_addr, &gw_addr);
00747         }
00748     }
00749 #endif
00750 
00751     if (client_callback) {
00752         client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_CONNECTING );
00753     }
00754 
00755 
00756     if (!netif_is_link_up(&netif)) {
00757         if (blocking) {
00758             if (osSemaphoreAcquire(linked, LINK_TIMEOUT * 1000) != osOK) {
00759                 return NSAPI_ERROR_NO_CONNECTION ;
00760             }
00761         }
00762     } else {
00763         nsapi_error_t ret = set_dhcp();
00764         if (ret != NSAPI_ERROR_OK ) {
00765             return ret;
00766         }
00767     }
00768 
00769     if (!blocking) {
00770         // Done enough - as addresses are acquired, there will be
00771         // connected callbacks.
00772         return NSAPI_ERROR_OK ;
00773     }
00774 
00775     // If doesn't have address
00776     if (!LWIP::get_ip_addr(true, &netif)) {
00777         if (osSemaphoreAcquire(has_any_addr, DHCP_TIMEOUT * 1000) != osOK) {
00778             return NSAPI_ERROR_DHCP_FAILURE ;
00779         }
00780     }
00781 
00782 #if PREF_ADDR_TIMEOUT
00783     if (stack != IPV4_STACK && stack != IPV6_STACK) {
00784         // If address is not for preferred stack waits a while to see
00785         // if preferred stack address is acquired
00786         if (!LWIP::get_ip_addr(false, &netif)) {
00787             osSemaphoreAcquire(has_pref_addr, PREF_ADDR_TIMEOUT * 1000);
00788         }
00789     }
00790 #endif
00791 #if BOTH_ADDR_TIMEOUT
00792     if (stack != IPV4_STACK && stack != IPV6_STACK) {
00793         // If addresses for both stacks are not available waits a while to
00794         // see if address for both stacks are acquired
00795         if (!(LWIP::get_ipv4_addr(&netif) && LWIP::get_ipv6_addr(&netif))) {
00796             osSemaphoreAcquire(has_both_addr, BOTH_ADDR_TIMEOUT * 1000);
00797         }
00798     }
00799 #endif
00800 
00801     add_dns_addr(&netif, get_interface_name(_interface_name));
00802 
00803     return NSAPI_ERROR_OK ;
00804 }
00805 
00806 nsapi_error_t LWIP::Interface::bringdown()
00807 {
00808     // Check if we've connected
00809     if (connected == NSAPI_STATUS_DISCONNECTED ) {
00810         return NSAPI_ERROR_NO_CONNECTION ;
00811     }
00812 
00813 #if LWIP_DHCP
00814     // Disconnect from the network
00815     if (dhcp_started) {
00816         dhcp_release(&netif);
00817         dhcp_stop(&netif);
00818         dhcp_started = false;
00819         dhcp_has_to_be_set = false;
00820     }
00821 #endif
00822 
00823     netif_set_down(&netif);
00824 
00825 #if LWIP_IPV6
00826     mbed_lwip_clear_ipv6_addresses(&netif);
00827 #endif
00828 #if LWIP_IPV4
00829     ip_addr_set_zero(&(netif.ip_addr));
00830     ip_addr_set_zero(&(netif.netmask));
00831     ip_addr_set_zero(&(netif.gw));
00832 #endif
00833 
00834     osSemaphoreDelete(has_any_addr);
00835     osSemaphoreAttr_t attr;
00836     attr.name = NULL;
00837     attr.attr_bits = 0;
00838     attr.cb_mem = &has_any_addr_sem;
00839     attr.cb_size = sizeof has_any_addr_sem;
00840     has_any_addr = osSemaphoreNew(UINT16_MAX, 0, &attr);
00841 #if PREF_ADDR_TIMEOUT
00842     osSemaphoreDelete(has_pref_addr);
00843     attr.cb_mem = &has_pref_addr_sem;
00844     attr.cb_size = sizeof has_pref_addr_sem;
00845     has_pref_addr = osSemaphoreNew(UINT16_MAX, 0, &attr);
00846 #endif
00847 #if BOTH_ADDR_TIMEOUT
00848     osSemaphoreDelete(has_both_addr);
00849     attr.cb_mem = &has_both_addr_sem;
00850     attr.cb_size = sizeof has_both_addr_sem;
00851     has_both_addr = osSemaphoreNew(UINT16_MAX, 0, &attr);
00852 #endif
00853     has_addr_state = 0;
00854 
00855     connected = NSAPI_STATUS_DISCONNECTED ;
00856     if (client_callback) {
00857         client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE , connected);
00858     }
00859     return 0;
00860 }