Lee Shen / FTHR_USB_serial_qSPI
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lwip_stack.c Source File

lwip_stack.c

00001 /* LWIP implementation of NetworkInterfaceAPI
00002  * Copyright (c) 2015 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #include "nsapi.h"
00018 #include "mbed_interface.h"
00019 #include "mbed_assert.h"
00020 #include <stdio.h>
00021 #include <stdbool.h>
00022 #include <string.h>
00023 #include "lwip_stack.h"
00024 
00025 #include "eth_arch.h"
00026 #include "lwip/opt.h"
00027 #include "lwip/api.h"
00028 #include "lwip/inet.h"
00029 #include "lwip/netif.h"
00030 #include "lwip/dhcp.h"
00031 #include "lwip/tcpip.h"
00032 #include "lwip/tcp.h"
00033 #include "lwip/ip.h"
00034 #include "lwip/mld6.h"
00035 #include "lwip/dns.h"
00036 #include "lwip/udp.h"
00037 #include "netif/lwip_ethernet.h"
00038 #include "emac_api.h"
00039 #include "ppp_lwip.h"
00040 
00041 static nsapi_error_t mbed_lwip_err_remap(err_t err);
00042 
00043 #if DEVICE_EMAC
00044     #define MBED_NETIF_INIT_FN emac_lwip_if_init
00045 #else
00046     #define MBED_NETIF_INIT_FN eth_arch_enetif_init
00047 #endif
00048 
00049 /* Static arena of sockets */
00050 static struct lwip_socket {
00051     bool in_use;
00052 
00053     struct netconn *conn;
00054     struct netbuf *buf;
00055     u16_t offset;
00056 
00057     void (*cb)(void *);
00058     void *data;
00059 } lwip_arena[MEMP_NUM_NETCONN];
00060 
00061 static bool lwip_inited = false;
00062 static bool lwip_connected = false;
00063 static bool netif_inited = false;
00064 static bool netif_is_ppp = false;
00065 
00066 static struct lwip_socket *mbed_lwip_arena_alloc(void)
00067 {
00068     sys_prot_t prot = sys_arch_protect();
00069 
00070     for (int i = 0; i < MEMP_NUM_NETCONN; i++) {
00071         if (!lwip_arena[i].in_use) {
00072             struct lwip_socket *s = &lwip_arena[i];
00073             memset(s, 0, sizeof *s);
00074             s->in_use = true;
00075             sys_arch_unprotect(prot);
00076             return s;
00077         }
00078     }
00079 
00080     sys_arch_unprotect(prot);
00081     return 0;
00082 }
00083 
00084 static void mbed_lwip_arena_dealloc(struct lwip_socket *s)
00085 {
00086     s->in_use = false;
00087 }
00088 
00089 static void mbed_lwip_socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len)
00090 {
00091     // Filter send minus events
00092     if (eh == NETCONN_EVT_SENDMINUS && nc->state == NETCONN_WRITE) {
00093         return;
00094     }
00095 
00096     sys_prot_t prot = sys_arch_protect();
00097 
00098     for (int i = 0; i < MEMP_NUM_NETCONN; i++) {
00099         if (lwip_arena[i].in_use
00100             && lwip_arena[i].conn == nc
00101             && lwip_arena[i].cb) {
00102             lwip_arena[i].cb(lwip_arena[i].data);
00103         }
00104     }
00105 
00106     sys_arch_unprotect(prot);
00107 }
00108 
00109 
00110 /* TCP/IP and Network Interface Initialisation */
00111 static struct netif lwip_netif;
00112 #if LWIP_DHCP
00113 static bool lwip_dhcp = false;
00114 #endif
00115 static char lwip_mac_address[NSAPI_MAC_SIZE];
00116 
00117 #if !LWIP_IPV4 || !LWIP_IPV6
00118 static bool all_zeros(const uint8_t *p, int len)
00119 {
00120     for (int i = 0; i < len; i++) {
00121         if (p[i]) {
00122             return false;
00123         }
00124     }
00125 
00126     return true;
00127 }
00128 #endif
00129 
00130 static bool convert_mbed_addr_to_lwip(ip_addr_t *out, const nsapi_addr_t *in)
00131 {
00132 #if LWIP_IPV6
00133     if (in->version == NSAPI_IPv6 ) {
00134          IP_SET_TYPE(out, IPADDR_TYPE_V6);
00135          MEMCPY(ip_2_ip6(out), in->bytes, sizeof(ip6_addr_t));
00136          return true;
00137     }
00138 #if !LWIP_IPV4
00139     /* For bind() and other purposes, need to accept "null" of other type */
00140     /* (People use IPv4 0.0.0.0 as a general null) */
00141     if (in->version == NSAPI_UNSPEC  ||
00142         (in->version == NSAPI_IPv4  && all_zeros(in->bytes, 4))) {
00143         ip_addr_set_zero_ip6(out);
00144         return true;
00145     }
00146 #endif
00147 #endif
00148 
00149 #if LWIP_IPV4
00150     if (in->version == NSAPI_IPv4 ) {
00151          IP_SET_TYPE(out, IPADDR_TYPE_V4);
00152          MEMCPY(ip_2_ip4(out), in->bytes, sizeof(ip4_addr_t));
00153          return true;
00154     }
00155 #if !LWIP_IPV6
00156     /* For symmetry with above, accept IPv6 :: as a general null */
00157     if (in->version == NSAPI_UNSPEC  ||
00158         (in->version == NSAPI_IPv6  && all_zeros(in->bytes, 16))) {
00159         ip_addr_set_zero_ip4(out);
00160         return true;
00161     }
00162 #endif
00163 #endif
00164 
00165 #if LWIP_IPV4 && LWIP_IPV6
00166     if (in->version == NSAPI_UNSPEC ) {
00167 #if IP_VERSION_PREF == PREF_IPV4
00168         ip_addr_set_zero_ip4(out);
00169 #else
00170         ip_addr_set_zero_ip6(out);
00171 #endif
00172         return true;
00173     }
00174 #endif
00175 
00176     return false;
00177 }
00178 
00179 static bool convert_lwip_addr_to_mbed(nsapi_addr_t *out, const ip_addr_t *in)
00180 {
00181 #if LWIP_IPV6
00182     if (IP_IS_V6(in)) {
00183         out->version = NSAPI_IPv6 ;
00184         MEMCPY(out->bytes, ip_2_ip6(in), sizeof(ip6_addr_t));
00185         return true;
00186     }
00187 #endif
00188 #if LWIP_IPV4
00189     if (IP_IS_V4(in)) {
00190         out->version = NSAPI_IPv4 ;
00191         MEMCPY(out->bytes, ip_2_ip4(in), sizeof(ip4_addr_t));
00192         return true;
00193     }
00194 #endif
00195 #if LWIP_IPV6 && LWIP_IPV4
00196     return false;
00197 #endif
00198 }
00199 
00200 #if LWIP_IPV4
00201 static const ip_addr_t *mbed_lwip_get_ipv4_addr(const struct netif *netif)
00202 {
00203     if (!netif_is_up(netif)) {
00204         return NULL;
00205     }
00206 
00207     if (!ip4_addr_isany(netif_ip4_addr(netif))) {
00208         return netif_ip_addr4(netif);
00209     }
00210 
00211     return NULL;
00212 }
00213 #endif
00214 
00215 #if LWIP_IPV6
00216 static const ip_addr_t *mbed_lwip_get_ipv6_addr(const struct netif *netif)
00217 {
00218 
00219     if (!netif_is_up(netif)) {
00220         return NULL;
00221     }
00222 
00223     for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
00224         if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
00225                 !ip6_addr_islinklocal(netif_ip6_addr(netif, i))) {
00226             return netif_ip_addr6(netif, i);
00227         }
00228     }
00229 
00230     return NULL;
00231 }
00232 #endif
00233 
00234 const ip_addr_t *mbed_lwip_get_ip_addr(bool any_addr, const struct netif *netif)
00235 {
00236     const ip_addr_t *pref_ip_addr = 0;
00237     const ip_addr_t *npref_ip_addr = 0;
00238 
00239 #if LWIP_IPV4 && LWIP_IPV6
00240 #if IP_VERSION_PREF == PREF_IPV4
00241     pref_ip_addr = mbed_lwip_get_ipv4_addr(netif);
00242     npref_ip_addr = mbed_lwip_get_ipv6_addr(netif);
00243 #else
00244     pref_ip_addr = mbed_lwip_get_ipv6_addr(netif);
00245     npref_ip_addr = mbed_lwip_get_ipv4_addr(netif);
00246 #endif
00247 #elif LWIP_IPV6
00248     pref_ip_addr = mbed_lwip_get_ipv6_addr(netif);
00249 #elif LWIP_IPV4
00250     pref_ip_addr = mbed_lwip_get_ipv4_addr(netif);
00251 #endif
00252 
00253     if (pref_ip_addr) {
00254         return pref_ip_addr;
00255     } else if (npref_ip_addr && any_addr) {
00256         return npref_ip_addr;
00257     }
00258 
00259     return NULL;
00260 }
00261 
00262 static void add_dns_addr_to_dns_list_index(const u8_t addr_type, const u8_t index)
00263 {
00264 #if LWIP_IPV6
00265     if (addr_type == IPADDR_TYPE_V6) {
00266         /* 2001:4860:4860::8888 google */
00267         ip_addr_t ipv6_dns_addr = IPADDR6_INIT(
00268                 PP_HTONL(0x20014860UL),
00269                 PP_HTONL(0x48600000UL),
00270                 PP_HTONL(0x00000000UL),
00271                 PP_HTONL(0x00008888UL));
00272         dns_setserver(index, &ipv6_dns_addr);
00273     }
00274 #endif
00275 #if LWIP_IPV4
00276     if (addr_type == IPADDR_TYPE_V4) {
00277         /* 8.8.8.8 google */
00278         ip_addr_t ipv4_dns_addr = IPADDR4_INIT(0x08080808);
00279         dns_setserver(index, &ipv4_dns_addr);
00280     }
00281 #endif
00282 }
00283 
00284 static int get_ip_addr_type(const ip_addr_t *ip_addr)
00285 {
00286 #if LWIP_IPV6
00287     if (IP_IS_V6(ip_addr)) {
00288         return IPADDR_TYPE_V6;
00289     }
00290 #endif
00291 #if LWIP_IPV4
00292     if (IP_IS_V4(ip_addr)) {
00293         return IPADDR_TYPE_V4;
00294     }
00295 #endif
00296     return IPADDR_TYPE_ANY;
00297 }
00298 
00299 void add_dns_addr(struct netif *lwip_netif)
00300 {
00301     // Check for existing dns address
00302     for (char numdns = 0; numdns < DNS_MAX_SERVERS; numdns++) {
00303         const ip_addr_t *dns_ip_addr = dns_getserver(numdns);
00304         if (!ip_addr_isany(dns_ip_addr)) {
00305             return;
00306         }
00307     }
00308 
00309     // Get preferred ip version
00310     const ip_addr_t *ip_addr = mbed_lwip_get_ip_addr(false, lwip_netif);
00311     u8_t addr_type = IPADDR_TYPE_ANY;
00312 
00313     // Add preferred ip version dns address to index 0
00314     if (ip_addr) {
00315         addr_type = get_ip_addr_type(ip_addr);
00316         add_dns_addr_to_dns_list_index(addr_type, 0);
00317     }
00318 
00319 #if LWIP_IPV4 && LWIP_IPV6
00320     if (!ip_addr) {
00321         // Get address for any ip version
00322         ip_addr = mbed_lwip_get_ip_addr(true, lwip_netif);
00323         if (!ip_addr) {
00324             return;
00325         }
00326         addr_type = get_ip_addr_type(ip_addr);
00327         // Add the dns address to index 0
00328         add_dns_addr_to_dns_list_index(addr_type, 0);
00329     }
00330 
00331     if (addr_type == IPADDR_TYPE_V4) {
00332         // If ipv4 is preferred and ipv6 is available add ipv6 dns address to index 1
00333         ip_addr = mbed_lwip_get_ipv6_addr(lwip_netif);
00334     } else if (addr_type == IPADDR_TYPE_V6) {
00335         // If ipv6 is preferred and ipv4 is available add ipv4 dns address to index 1
00336         ip_addr = mbed_lwip_get_ipv4_addr(lwip_netif);
00337     } else {
00338         ip_addr = NULL;
00339     }
00340 
00341     if (ip_addr) {
00342         addr_type = get_ip_addr_type(ip_addr);
00343         add_dns_addr_to_dns_list_index(addr_type, 1);
00344     }
00345 #endif
00346 }
00347 
00348 static sys_sem_t lwip_tcpip_inited;
00349 static void mbed_lwip_tcpip_init_irq(void *eh)
00350 {
00351     sys_sem_signal(&lwip_tcpip_inited);
00352 }
00353 
00354 static sys_sem_t lwip_netif_linked;
00355 static sys_sem_t lwip_netif_unlinked;
00356 static void mbed_lwip_netif_link_irq(struct netif *lwip_netif)
00357 {
00358     if (netif_is_link_up(lwip_netif)) {
00359         sys_sem_signal(&lwip_netif_linked);
00360     } else {
00361         sys_sem_signal(&lwip_netif_unlinked);
00362     }
00363 }
00364 
00365 static char lwip_has_addr_state = 0;
00366 
00367 #define HAS_ANY_ADDR  1
00368 static sys_sem_t lwip_netif_has_any_addr;
00369 #if PREF_ADDR_TIMEOUT
00370 #define HAS_PREF_ADDR 2
00371 static sys_sem_t lwip_netif_has_pref_addr;
00372 #endif
00373 #if BOTH_ADDR_TIMEOUT
00374 #define HAS_BOTH_ADDR 4
00375 static sys_sem_t lwip_netif_has_both_addr;
00376 #endif
00377 
00378 static void mbed_lwip_netif_status_irq(struct netif *lwip_netif)
00379 {
00380     if (netif_is_up(lwip_netif)) {
00381         if (!(lwip_has_addr_state & HAS_ANY_ADDR) && mbed_lwip_get_ip_addr(true, lwip_netif)) {
00382             sys_sem_signal(&lwip_netif_has_any_addr);
00383             lwip_has_addr_state |= HAS_ANY_ADDR;
00384         }
00385 #if PREF_ADDR_TIMEOUT
00386         if (!(lwip_has_addr_state & HAS_PREF_ADDR) && mbed_lwip_get_ip_addr(false, lwip_netif)) {
00387             sys_sem_signal(&lwip_netif_has_pref_addr);
00388             lwip_has_addr_state |= HAS_PREF_ADDR;
00389         }
00390 #endif
00391 #if BOTH_ADDR_TIMEOUT
00392         if (!(lwip_has_addr_state & HAS_BOTH_ADDR) && mbed_lwip_get_ipv4_addr(lwip_netif) && mbed_lwip_get_ipv6_addr(lwip_netif)) {
00393             sys_sem_signal(&lwip_netif_has_both_addr);
00394             lwip_has_addr_state |= HAS_BOTH_ADDR;
00395         }
00396 #endif
00397     }
00398 }
00399 
00400 #if LWIP_ETHERNET
00401 static void mbed_lwip_set_mac_address(struct netif *netif)
00402 {
00403 #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
00404     netif->hwaddr[0] = MBED_MAC_ADDR_0;
00405     netif->hwaddr[1] = MBED_MAC_ADDR_1;
00406     netif->hwaddr[2] = MBED_MAC_ADDR_2;
00407     netif->hwaddr[3] = MBED_MAC_ADDR_3;
00408     netif->hwaddr[4] = MBED_MAC_ADDR_4;
00409     netif->hwaddr[5] = MBED_MAC_ADDR_5;
00410 #else
00411     mbed_mac_address((char *)netif->hwaddr);
00412 #endif
00413 
00414     netif->hwaddr_len = ETH_HWADDR_LEN;
00415 
00416     /* Use mac address as additional seed to random number generator */
00417     uint64_t seed = netif->hwaddr[0];
00418     for (uint8_t i = 1; i < 8; i++) {
00419         seed <<= 8;
00420         seed |= netif->hwaddr[i % 6];
00421     }
00422     lwip_add_random_seed(seed);
00423 }
00424 
00425 static void mbed_lwip_record_mac_address(const struct netif *netif)
00426 {
00427     const u8_t *mac = netif->hwaddr;
00428     snprintf(lwip_mac_address, NSAPI_MAC_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x",
00429              mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
00430 }
00431 #endif // LWIP_ETHERNET
00432 
00433 /* LWIP interface implementation */
00434 const char *mbed_lwip_get_mac_address(void)
00435 {
00436     return lwip_mac_address[0] ? lwip_mac_address : NULL;
00437 }
00438 
00439 char *mbed_lwip_get_ip_address(char *buf, nsapi_size_t buflen)
00440 {
00441     const ip_addr_t *addr = mbed_lwip_get_ip_addr(true, &lwip_netif);
00442     if (!addr) {
00443         return NULL;
00444     }
00445 #if LWIP_IPV6
00446     if (IP_IS_V6(addr)) {
00447         return ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen);
00448     }
00449 #endif
00450 #if LWIP_IPV4
00451     if (IP_IS_V4(addr)) {
00452         return ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen);
00453     }
00454 #endif
00455 #if LWIP_IPV6 && LWIP_IPV4
00456     return NULL;
00457 #endif
00458 }
00459 
00460 char *mbed_lwip_get_netmask(char *buf, nsapi_size_t buflen)
00461 {
00462 #if LWIP_IPV4
00463     const ip4_addr_t *addr = netif_ip4_netmask(&lwip_netif);
00464     if (!ip4_addr_isany(addr)) {
00465         return ip4addr_ntoa_r(addr, buf, buflen);
00466     } else {
00467         return NULL;
00468     }
00469 #else
00470     return NULL;
00471 #endif
00472 }
00473 
00474 char *mbed_lwip_get_gateway(char *buf, nsapi_size_t buflen)
00475 {
00476 #if LWIP_IPV4
00477     const ip4_addr_t *addr = netif_ip4_gw(&lwip_netif);
00478     if (!ip4_addr_isany(addr)) {
00479         return ip4addr_ntoa_r(addr, buf, buflen);
00480     } else {
00481         return NULL;
00482     }
00483 #else
00484     return NULL;
00485 #endif
00486 }
00487 
00488 static void mbed_lwip_core_init(void)
00489 {
00490 
00491     // Check if we've already brought up lwip
00492     if (!lwip_inited) {
00493     // Seed lwip random
00494         lwip_seed_random();
00495 
00496         // Initialise TCP sequence number
00497         uint32_t tcp_isn_secret[4];
00498         for (int i = 0; i < 4; i++) {
00499             tcp_isn_secret[i] = LWIP_RAND();
00500         }
00501         lwip_init_tcp_isn(0, (u8_t *) &tcp_isn_secret);
00502 
00503         sys_sem_new(&lwip_tcpip_inited, 0);
00504         sys_sem_new(&lwip_netif_linked, 0);
00505         sys_sem_new(&lwip_netif_unlinked, 0);
00506         sys_sem_new(&lwip_netif_has_any_addr, 0);
00507 #if PREF_ADDR_TIMEOUT
00508         sys_sem_new(&lwip_netif_has_pref_addr, 0);
00509 #endif
00510 #if BOTH_ADDR_TIMEOUT
00511         sys_sem_new(&lwip_netif_has_both_addr, 0);
00512 #endif
00513         tcpip_init(mbed_lwip_tcpip_init_irq, NULL);
00514         sys_arch_sem_wait(&lwip_tcpip_inited, 0);
00515 
00516         lwip_inited = true;
00517     }
00518 }
00519 
00520 nsapi_error_t mbed_lwip_emac_init(emac_interface_t *emac)
00521 {
00522 #if LWIP_ETHERNET
00523     // Choose a MAC address - driver can override
00524     mbed_lwip_set_mac_address(&lwip_netif);
00525 
00526     // Set up network
00527     if (!netif_add(&lwip_netif,
00528 #if LWIP_IPV4
00529                    0, 0, 0,
00530 #endif
00531                    emac, MBED_NETIF_INIT_FN, tcpip_input)) {
00532         return NSAPI_ERROR_DEVICE_ERROR ;
00533     }
00534 
00535     // Note the MAC address actually in use
00536     mbed_lwip_record_mac_address(&lwip_netif);
00537 
00538 #if !DEVICE_EMAC
00539     eth_arch_enable_interrupts();
00540 #endif
00541 
00542     return NSAPI_ERROR_OK ;
00543 #else
00544     return NSAPI_ERROR_UNSUPPORTED ;
00545 #endif //LWIP_ETHERNET
00546 }
00547 
00548 // Backwards compatibility with people using DEVICE_EMAC
00549 nsapi_error_t mbed_lwip_init(emac_interface_t *emac)
00550 {
00551     nsapi_error_t ret;
00552     mbed_lwip_core_init();
00553     ret = mbed_lwip_emac_init(emac);
00554     if (ret == NSAPI_ERROR_OK ) {
00555         netif_inited = true;
00556     }
00557     return ret;
00558 }
00559 
00560 // Backwards compatibility with people using DEVICE_EMAC
00561 nsapi_error_t mbed_lwip_bringup(bool dhcp, const char *ip, const char *netmask, const char *gw)
00562 {
00563     return mbed_lwip_bringup_2(dhcp, false, ip, netmask, gw, DEFAULT_STACK);
00564 }
00565 
00566 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)
00567 {
00568     // Check if we've already connected
00569     if (lwip_connected) {
00570         return NSAPI_ERROR_PARAMETER ;
00571     }
00572 
00573     mbed_lwip_core_init();
00574 
00575     nsapi_error_t ret;
00576     if (netif_inited) {
00577         /* Can't cope with changing mode */
00578         if (netif_is_ppp == ppp) {
00579             ret = NSAPI_ERROR_OK ;
00580         } else {
00581             ret = NSAPI_ERROR_PARAMETER ;
00582         }
00583     } else {
00584         if (ppp) {
00585             ret = ppp_lwip_if_init(&lwip_netif, stack);
00586         } else {
00587             ret = mbed_lwip_emac_init(NULL);
00588         }
00589     }
00590 
00591     if (ret != NSAPI_ERROR_OK ) {
00592         return ret;
00593     }
00594 
00595     netif_inited = true;
00596     if (ppp) {
00597         netif_is_ppp = ppp;
00598     }
00599 
00600     netif_set_default(&lwip_netif);
00601     netif_set_link_callback(&lwip_netif, mbed_lwip_netif_link_irq);
00602     netif_set_status_callback(&lwip_netif, mbed_lwip_netif_status_irq);
00603 
00604 #if LWIP_IPV6
00605     if (stack != IPV4_STACK) {
00606         if (lwip_netif.hwaddr_len == ETH_HWADDR_LEN) {
00607             netif_create_ip6_linklocal_address(&lwip_netif, 1/*from MAC*/);
00608         }
00609 
00610 #if LWIP_IPV6_MLD
00611         /*
00612          * For hardware/netifs that implement MAC filtering.
00613          * All-nodes link-local is handled by default, so we must let the hardware know
00614          * to allow multicast packets in.
00615          * Should set mld_mac_filter previously. */
00616         if (lwip_netif.mld_mac_filter != NULL) {
00617             ip6_addr_t ip6_allnodes_ll;
00618             ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
00619             lwip_netif.mld_mac_filter(&lwip_netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
00620         }
00621 #endif /* LWIP_IPV6_MLD */
00622 
00623 #if LWIP_IPV6_AUTOCONFIG
00624         /* IPv6 address autoconfiguration not enabled by default */
00625         lwip_netif.ip6_autoconfig_enabled = 1;
00626     } else {
00627         // Disable router solidifications
00628         lwip_netif.rs_count = 0;
00629     }
00630 #endif /* LWIP_IPV6_AUTOCONFIG */
00631 #endif // LWIP_IPV6
00632 
00633 #if LWIP_IPV4
00634     if (stack != IPV6_STACK) {
00635         if (!dhcp && !ppp) {
00636             ip4_addr_t ip_addr;
00637             ip4_addr_t netmask_addr;
00638             ip4_addr_t gw_addr;
00639 
00640             if (!inet_aton(ip, &ip_addr) ||
00641                 !inet_aton(netmask, &netmask_addr) ||
00642                 !inet_aton(gw, &gw_addr)) {
00643                 return NSAPI_ERROR_PARAMETER ;
00644             }
00645 
00646             netif_set_addr(&lwip_netif, &ip_addr, &netmask_addr, &gw_addr);
00647         }
00648     }
00649 #endif
00650 
00651     if (ppp) {
00652        err_t err = ppp_lwip_connect();
00653        if (err) {
00654            return mbed_lwip_err_remap(err);
00655        }
00656     }
00657 
00658     if (!netif_is_link_up(&lwip_netif)) {
00659         if (sys_arch_sem_wait(&lwip_netif_linked, 15000) == SYS_ARCH_TIMEOUT) {
00660             if (ppp) {
00661                 ppp_lwip_disconnect();
00662             }
00663             return NSAPI_ERROR_NO_CONNECTION ;
00664         }
00665     }
00666 
00667     if (!ppp) {
00668         netif_set_up(&lwip_netif);
00669     }
00670 
00671 #if LWIP_DHCP
00672     if (stack != IPV6_STACK) {
00673         // Connect to the network
00674         lwip_dhcp = dhcp;
00675 
00676         if (lwip_dhcp) {
00677             err_t err = dhcp_start(&lwip_netif);
00678             if (err) {
00679                 return NSAPI_ERROR_DHCP_FAILURE ;
00680             }
00681         }
00682     }
00683 #endif
00684 
00685     // If doesn't have address
00686     if (!mbed_lwip_get_ip_addr(true, &lwip_netif)) {
00687         if (sys_arch_sem_wait(&lwip_netif_has_any_addr, DHCP_TIMEOUT * 1000) == SYS_ARCH_TIMEOUT) {
00688             if (ppp) {
00689                 ppp_lwip_disconnect();
00690             }
00691             return NSAPI_ERROR_DHCP_FAILURE ;
00692         }
00693     }
00694 
00695 #if PREF_ADDR_TIMEOUT
00696     if (stack != IPV4_STACK && stack != IPV6_STACK) {
00697         // If address is not for preferred stack waits a while to see
00698         // if preferred stack address is acquired
00699         if (!mbed_lwip_get_ip_addr(false, &lwip_netif)) {
00700             sys_arch_sem_wait(&lwip_netif_has_pref_addr, PREF_ADDR_TIMEOUT * 1000);
00701         }
00702     }
00703 #endif
00704 #if BOTH_ADDR_TIMEOUT
00705     if (stack != IPV4_STACK && stack != IPV6_STACK) {
00706         // If addresses for both stacks are not available waits a while to
00707         // see if address for both stacks are acquired
00708         if (!(mbed_lwip_get_ipv4_addr(&lwip_netif) && mbed_lwip_get_ipv6_addr(&lwip_netif))) {
00709             sys_arch_sem_wait(&lwip_netif_has_both_addr, BOTH_ADDR_TIMEOUT * 1000);
00710         }
00711     }
00712 #endif
00713 
00714     add_dns_addr(&lwip_netif);
00715 
00716     lwip_connected = true;
00717     return 0;
00718 }
00719 
00720 #if LWIP_IPV6
00721 void mbed_lwip_clear_ipv6_addresses(struct netif *lwip_netif)
00722 {
00723     for (u8_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
00724         netif_ip6_addr_set_state(lwip_netif, i, IP6_ADDR_INVALID);
00725     }
00726 }
00727 #endif
00728 
00729 // Backwards compatibility with people using DEVICE_EMAC
00730 nsapi_error_t mbed_lwip_bringdown(void)
00731 {
00732     return mbed_lwip_bringdown_2(false);
00733 }
00734 
00735 nsapi_error_t mbed_lwip_bringdown_2(bool ppp)
00736 {
00737     // Check if we've connected
00738     if (!lwip_connected) {
00739         return NSAPI_ERROR_PARAMETER ;
00740     }
00741 
00742 #if LWIP_DHCP
00743     // Disconnect from the network
00744     if (lwip_dhcp) {
00745         dhcp_release(&lwip_netif);
00746         dhcp_stop(&lwip_netif);
00747         lwip_dhcp = false;
00748     }
00749 #endif
00750 
00751     if (ppp) {
00752         /* this is a blocking call, returns when PPP is properly closed */
00753        err_t err = ppp_lwip_disconnect();
00754        if (err) {
00755            return mbed_lwip_err_remap(err);
00756        }
00757        MBED_ASSERT(!netif_is_link_up(&lwip_netif));
00758        /*if (netif_is_link_up(&lwip_netif)) {
00759            if (sys_arch_sem_wait(&lwip_netif_unlinked, 15000) == SYS_ARCH_TIMEOUT) {
00760                return NSAPI_ERROR_DEVICE_ERROR;
00761            }
00762        }*/
00763     } else {
00764         netif_set_down(&lwip_netif);
00765     }
00766 
00767 #if LWIP_IPV6
00768     mbed_lwip_clear_ipv6_addresses(&lwip_netif);
00769 #endif
00770 
00771     sys_sem_free(&lwip_netif_has_any_addr);
00772     sys_sem_new(&lwip_netif_has_any_addr, 0);
00773 #if PREF_ADDR_TIMEOUT
00774     sys_sem_free(&lwip_netif_has_pref_addr);
00775     sys_sem_new(&lwip_netif_has_pref_addr, 0);
00776 #endif
00777 #if BOTH_ADDR_TIMEOUT
00778     sys_sem_free(&lwip_netif_has_both_addr);
00779     sys_sem_new(&lwip_netif_has_both_addr, 0);
00780 #endif
00781     lwip_has_addr_state = 0;
00782     lwip_connected = false;
00783     return 0;
00784 }
00785 
00786 /* LWIP error remapping */
00787 static nsapi_error_t mbed_lwip_err_remap(err_t err) {
00788     switch (err) {
00789         case ERR_OK:
00790         case ERR_CLSD:
00791             return 0;
00792         case ERR_MEM:
00793         case ERR_BUF:
00794             return NSAPI_ERROR_NO_MEMORY ;
00795         case ERR_CONN:
00796         case ERR_RST:
00797         case ERR_ABRT:
00798             return NSAPI_ERROR_NO_CONNECTION ;
00799         case ERR_TIMEOUT:
00800         case ERR_RTE:
00801         case ERR_WOULDBLOCK:
00802             return NSAPI_ERROR_WOULD_BLOCK ;
00803         case ERR_VAL:
00804         case ERR_USE:
00805         case ERR_ARG:
00806             return NSAPI_ERROR_PARAMETER ;
00807         case ERR_INPROGRESS:
00808             return NSAPI_ERROR_IN_PROGRESS ;
00809         case ERR_ALREADY:
00810             return NSAPI_ERROR_ALREADY ;
00811         case ERR_ISCONN:
00812             return NSAPI_ERROR_IS_CONNECTED ;
00813         default:
00814             return NSAPI_ERROR_DEVICE_ERROR ;
00815     }
00816 }
00817 
00818 /* LWIP network stack implementation */
00819 static nsapi_error_t mbed_lwip_gethostbyname(nsapi_stack_t *stack, const char *host, nsapi_addr_t *addr, nsapi_version_t version)
00820 {
00821     ip_addr_t lwip_addr;
00822 
00823 #if LWIP_IPV4 && LWIP_IPV6
00824     u8_t addr_type;
00825     if (version == NSAPI_UNSPEC ) {
00826         const ip_addr_t *ip_addr;
00827         ip_addr = mbed_lwip_get_ip_addr(true, &lwip_netif);
00828         // Prefer IPv6
00829         if (IP_IS_V6(ip_addr)) {
00830             // If IPv4 is available use it as backup
00831             if (mbed_lwip_get_ipv4_addr(&lwip_netif)) {
00832                 addr_type = NETCONN_DNS_IPV6_IPV4;
00833             } else {
00834                 addr_type = NETCONN_DNS_IPV6;
00835             }
00836         // Prefer IPv4
00837         } else {
00838             // If IPv6 is available use it as backup
00839             if (mbed_lwip_get_ipv6_addr(&lwip_netif)) {
00840                 addr_type = NETCONN_DNS_IPV4_IPV6;
00841             } else {
00842                 addr_type = NETCONN_DNS_IPV4;
00843             }
00844         }
00845     } else if (version == NSAPI_IPv4 ) {
00846         addr_type = NETCONN_DNS_IPV4;
00847     } else if (version == NSAPI_IPv6 ) {
00848         addr_type = NETCONN_DNS_IPV6;
00849     } else {
00850         return NSAPI_ERROR_DNS_FAILURE ;
00851     }
00852     err_t err = netconn_gethostbyname_addrtype(host, &lwip_addr, addr_type);
00853 #elif LWIP_IPV4
00854     if (version != NSAPI_IPv4  && version != NSAPI_UNSPEC ) {
00855         return NSAPI_ERROR_DNS_FAILURE ;
00856     }
00857     err_t err = netconn_gethostbyname(host, &lwip_addr);
00858 #elif LWIP_IPV6
00859     if (version != NSAPI_IPv6  && version != NSAPI_UNSPEC ) {
00860         return NSAPI_ERROR_DNS_FAILURE ;
00861     }
00862     err_t err = netconn_gethostbyname(host, &lwip_addr);
00863 #endif
00864 
00865     if (err != ERR_OK) {
00866         return NSAPI_ERROR_DNS_FAILURE ;
00867     }
00868 
00869     convert_lwip_addr_to_mbed(addr, &lwip_addr);
00870 
00871     return 0;
00872 }
00873 
00874 static nsapi_error_t mbed_lwip_add_dns_server(nsapi_stack_t *stack, nsapi_addr_t addr)
00875 {
00876     // Shift all dns servers down to give precedence to new server
00877     for (int i = DNS_MAX_SERVERS-1; i > 0; i--) {
00878         dns_setserver(i, dns_getserver(i-1));
00879     }
00880 
00881     ip_addr_t ip_addr;
00882     if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
00883         return NSAPI_ERROR_PARAMETER ;
00884     }
00885 
00886     dns_setserver(0, &ip_addr);
00887     return 0;
00888 }
00889 
00890 static nsapi_error_t mbed_lwip_socket_open(nsapi_stack_t *stack, nsapi_socket_t *handle, nsapi_protocol_t proto)
00891 {
00892     // check if network is connected
00893     if (!lwip_connected) {
00894         return NSAPI_ERROR_NO_CONNECTION ;
00895     }
00896 
00897     // allocate a socket
00898     struct lwip_socket *s = mbed_lwip_arena_alloc();
00899     if (!s) {
00900         return NSAPI_ERROR_NO_SOCKET ;
00901     }
00902 
00903     enum netconn_type lwip_proto = proto == NSAPI_TCP  ? NETCONN_TCP : NETCONN_UDP;
00904 
00905 #if LWIP_IPV6
00906     // Enable IPv6 (or dual-stack)
00907     lwip_proto |= NETCONN_TYPE_IPV6;
00908 #endif
00909 
00910     s->conn = netconn_new_with_callback(lwip_proto, mbed_lwip_socket_callback);
00911 
00912     if (!s->conn) {
00913         mbed_lwip_arena_dealloc(s);
00914         return NSAPI_ERROR_NO_SOCKET ;
00915     }
00916 
00917     netconn_set_recvtimeout(s->conn, 1);
00918     *(struct lwip_socket **)handle = s;
00919     return 0;
00920 }
00921 
00922 static nsapi_error_t mbed_lwip_socket_close(nsapi_stack_t *stack, nsapi_socket_t handle)
00923 {
00924     struct lwip_socket *s = (struct lwip_socket *)handle;
00925 
00926     netbuf_delete(s->buf);
00927     err_t err = netconn_delete(s->conn);
00928     mbed_lwip_arena_dealloc(s);
00929     return mbed_lwip_err_remap(err);
00930 }
00931 
00932 static nsapi_error_t mbed_lwip_socket_bind(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port)
00933 {
00934     struct lwip_socket *s = (struct lwip_socket *)handle;
00935     ip_addr_t ip_addr;
00936 
00937     if (
00938 #if LWIP_TCP
00939         (s->conn->type == NETCONN_TCP && s->conn->pcb.tcp->local_port != 0) ||
00940 #endif
00941         (s->conn->type == NETCONN_UDP && s->conn->pcb.udp->local_port != 0)) {
00942         return NSAPI_ERROR_PARAMETER ;
00943     }
00944 
00945     if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
00946         return NSAPI_ERROR_PARAMETER ;
00947     }
00948 
00949     err_t err = netconn_bind(s->conn, &ip_addr, port);
00950     return mbed_lwip_err_remap(err);
00951 }
00952 
00953 static nsapi_error_t mbed_lwip_socket_listen(nsapi_stack_t *stack, nsapi_socket_t handle, int backlog)
00954 {
00955     struct lwip_socket *s = (struct lwip_socket *)handle;
00956 
00957     err_t err = netconn_listen_with_backlog(s->conn, backlog);
00958     return mbed_lwip_err_remap(err);
00959 }
00960 
00961 static nsapi_error_t mbed_lwip_socket_connect(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port)
00962 {
00963     struct lwip_socket *s = (struct lwip_socket *)handle;
00964     ip_addr_t ip_addr;
00965 
00966     if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
00967         return NSAPI_ERROR_PARAMETER ;
00968     }
00969 
00970     netconn_set_nonblocking(s->conn, false);
00971     err_t err = netconn_connect(s->conn, &ip_addr, port);
00972     netconn_set_nonblocking(s->conn, true);
00973 
00974     return mbed_lwip_err_remap(err);
00975 }
00976 
00977 static nsapi_error_t mbed_lwip_socket_accept(nsapi_stack_t *stack, nsapi_socket_t server, nsapi_socket_t *handle, nsapi_addr_t *addr, uint16_t *port)
00978 {
00979     struct lwip_socket *s = (struct lwip_socket *)server;
00980     struct lwip_socket *ns = mbed_lwip_arena_alloc();
00981     if (!ns) {
00982         return NSAPI_ERROR_NO_SOCKET ;
00983     }
00984 
00985     err_t err = netconn_accept(s->conn, &ns->conn);
00986     if (err != ERR_OK) {
00987         mbed_lwip_arena_dealloc(ns);
00988         return mbed_lwip_err_remap(err);
00989     }
00990 
00991     netconn_set_recvtimeout(ns->conn, 1);
00992     *(struct lwip_socket **)handle = ns;
00993 
00994     ip_addr_t peer_addr;
00995     (void) netconn_peer(ns->conn, &peer_addr, port);
00996     convert_lwip_addr_to_mbed(addr, &peer_addr);
00997 
00998     netconn_set_nonblocking(ns->conn, true);
00999 
01000     return 0;
01001 }
01002 
01003 static nsapi_size_or_error_t mbed_lwip_socket_send(nsapi_stack_t *stack, nsapi_socket_t handle, const void *data, nsapi_size_t size)
01004 {
01005     struct lwip_socket *s = (struct lwip_socket *)handle;
01006     size_t bytes_written = 0;
01007 
01008     err_t err = netconn_write_partly(s->conn, data, size, NETCONN_COPY, &bytes_written);
01009     if (err != ERR_OK) {
01010         return mbed_lwip_err_remap(err);
01011     }
01012 
01013     return (nsapi_size_or_error_t)bytes_written;
01014 }
01015 
01016 static nsapi_size_or_error_t mbed_lwip_socket_recv(nsapi_stack_t *stack, nsapi_socket_t handle, void *data, nsapi_size_t size)
01017 {
01018     struct lwip_socket *s = (struct lwip_socket *)handle;
01019 
01020     if (!s->buf) {
01021         err_t err = netconn_recv(s->conn, &s->buf);
01022         s->offset = 0;
01023 
01024         if (err != ERR_OK) {
01025             return mbed_lwip_err_remap(err);
01026         }
01027     }
01028 
01029     u16_t recv = netbuf_copy_partial(s->buf, data, (u16_t)size, s->offset);
01030     s->offset += recv;
01031 
01032     if (s->offset >= netbuf_len(s->buf)) {
01033         netbuf_delete(s->buf);
01034         s->buf = 0;
01035     }
01036 
01037     return recv;
01038 }
01039 
01040 static nsapi_size_or_error_t mbed_lwip_socket_sendto(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port, const void *data, nsapi_size_t size)
01041 {
01042     struct lwip_socket *s = (struct lwip_socket *)handle;
01043     ip_addr_t ip_addr;
01044 
01045     if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
01046         return NSAPI_ERROR_PARAMETER ;
01047     }
01048 
01049     struct netbuf *buf = netbuf_new();
01050     err_t err = netbuf_ref(buf, data, (u16_t)size);
01051     if (err != ERR_OK) {
01052         netbuf_free(buf);
01053         return mbed_lwip_err_remap(err);
01054     }
01055 
01056     err = netconn_sendto(s->conn, buf, &ip_addr, port);
01057     netbuf_delete(buf);
01058     if (err != ERR_OK) {
01059         return mbed_lwip_err_remap(err);
01060     }
01061 
01062     return size;
01063 }
01064 
01065 static nsapi_size_or_error_t mbed_lwip_socket_recvfrom(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t *addr, uint16_t *port, void *data, nsapi_size_t size)
01066 {
01067     struct lwip_socket *s = (struct lwip_socket *)handle;
01068     struct netbuf *buf;
01069 
01070     err_t err = netconn_recv(s->conn, &buf);
01071     if (err != ERR_OK) {
01072         return mbed_lwip_err_remap(err);
01073     }
01074 
01075     convert_lwip_addr_to_mbed(addr, netbuf_fromaddr(buf));
01076     *port = netbuf_fromport(buf);
01077 
01078     u16_t recv = netbuf_copy(buf, data, (u16_t)size);
01079     netbuf_delete(buf);
01080 
01081     return recv;
01082 }
01083 
01084 static nsapi_error_t mbed_lwip_setsockopt(nsapi_stack_t *stack, nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen)
01085 {
01086     struct lwip_socket *s = (struct lwip_socket *)handle;
01087 
01088     switch (optname) {
01089 #if LWIP_TCP
01090         case NSAPI_KEEPALIVE :
01091             if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) {
01092                 return NSAPI_ERROR_UNSUPPORTED ;
01093             }
01094 
01095             s->conn->pcb.tcp->so_options |= SOF_KEEPALIVE;
01096             return 0;
01097 
01098         case NSAPI_KEEPIDLE :
01099             if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) {
01100                 return NSAPI_ERROR_UNSUPPORTED ;
01101             }
01102 
01103             s->conn->pcb.tcp->keep_idle = *(int*)optval;
01104             return 0;
01105 
01106         case NSAPI_KEEPINTVL :
01107             if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) {
01108                 return NSAPI_ERROR_UNSUPPORTED ;
01109             }
01110 
01111             s->conn->pcb.tcp->keep_intvl = *(int*)optval;
01112             return 0;
01113 #endif
01114 
01115         case NSAPI_REUSEADDR :
01116             if (optlen != sizeof(int)) {
01117                 return NSAPI_ERROR_UNSUPPORTED ;
01118             }
01119 
01120             if (*(int *)optval) {
01121                 ip_set_option(s->conn->pcb.ip, SOF_REUSEADDR);
01122             } else {
01123                 ip_reset_option(s->conn->pcb.ip, SOF_REUSEADDR);
01124             }
01125             return 0;
01126 
01127         default:
01128             return NSAPI_ERROR_UNSUPPORTED ;
01129     }
01130 }
01131 
01132 static void mbed_lwip_socket_attach(nsapi_stack_t *stack, nsapi_socket_t handle, void (*callback)(void *), void *data)
01133 {
01134     struct lwip_socket *s = (struct lwip_socket *)handle;
01135 
01136     s->cb = callback;
01137     s->data = data;
01138 }
01139 
01140 /* LWIP network stack */
01141 const nsapi_stack_api_t lwip_stack_api = {
01142     .gethostbyname      = mbed_lwip_gethostbyname,
01143     .add_dns_server     = mbed_lwip_add_dns_server,
01144     .socket_open        = mbed_lwip_socket_open,
01145     .socket_close       = mbed_lwip_socket_close,
01146     .socket_bind        = mbed_lwip_socket_bind,
01147     .socket_listen      = mbed_lwip_socket_listen,
01148     .socket_connect     = mbed_lwip_socket_connect,
01149     .socket_accept      = mbed_lwip_socket_accept,
01150     .socket_send        = mbed_lwip_socket_send,
01151     .socket_recv        = mbed_lwip_socket_recv,
01152     .socket_sendto      = mbed_lwip_socket_sendto,
01153     .socket_recvfrom    = mbed_lwip_socket_recvfrom,
01154     .setsockopt         = mbed_lwip_setsockopt,
01155     .socket_attach      = mbed_lwip_socket_attach,
01156 };
01157 
01158 nsapi_stack_t lwip_stack = {
01159     .stack_api = &lwip_stack_api,
01160 };