Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 };
Generated on Tue Jul 12 2022 20:03:21 by
