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/igmp.h" 00036 #include "lwip/dns.h" 00037 #include "lwip/udp.h" 00038 #include "lwip_errno.h" 00039 #include "netif/lwip_ethernet.h" 00040 #include "emac_api.h" 00041 #include "ppp_lwip.h" 00042 00043 static nsapi_error_t mbed_lwip_err_remap(err_t err); 00044 00045 #if DEVICE_EMAC 00046 #define MBED_NETIF_INIT_FN emac_lwip_if_init 00047 #else 00048 #define MBED_NETIF_INIT_FN eth_arch_enetif_init 00049 #endif 00050 00051 #ifndef LWIP_SOCKET_MAX_MEMBERSHIPS 00052 #define LWIP_SOCKET_MAX_MEMBERSHIPS 4 00053 #endif 00054 00055 /* Static arena of sockets */ 00056 static struct lwip_socket { 00057 bool in_use; 00058 00059 struct netconn *conn; 00060 struct netbuf *buf; 00061 u16_t offset; 00062 00063 void (*cb)(void *); 00064 void *data; 00065 00066 // Track multicast addresses subscribed to by this socket 00067 nsapi_ip_mreq_t *multicast_memberships; 00068 uint32_t multicast_memberships_count; 00069 uint32_t multicast_memberships_registry; 00070 00071 } lwip_arena[MEMP_NUM_NETCONN]; 00072 00073 static bool lwip_inited = false; 00074 static nsapi_connection_status_t lwip_connected = NSAPI_STATUS_DISCONNECTED ; 00075 static bool netif_inited = false; 00076 static bool netif_is_ppp = false; 00077 00078 static nsapi_error_t mbed_lwip_setsockopt(nsapi_stack_t *stack, nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen); 00079 00080 static inline uint32_t next_registered_multicast_member(const struct lwip_socket *s, uint32_t index) { 00081 while (!(s->multicast_memberships_registry & (0x0001 << index))) { index++; } 00082 return index; 00083 } 00084 00085 static inline uint32_t next_free_multicast_member(const struct lwip_socket *s, uint32_t index) { 00086 while ((s->multicast_memberships_registry & (0x0001 << index))) { index++; } 00087 return index; 00088 } 00089 00090 static inline void set_multicast_member_registry_bit(struct lwip_socket *s, uint32_t index) { 00091 s->multicast_memberships_registry |= (0x0001 << index); 00092 } 00093 00094 static inline void clear_multicast_member_registry_bit(struct lwip_socket *s, uint32_t index) { 00095 s->multicast_memberships_registry &= ~(0x0001 << index); 00096 } 00097 00098 static struct lwip_socket *mbed_lwip_arena_alloc(void) 00099 { 00100 sys_prot_t prot = sys_arch_protect(); 00101 00102 for (int i = 0; i < MEMP_NUM_NETCONN; i++) { 00103 if (!lwip_arena[i].in_use) { 00104 struct lwip_socket *s = &lwip_arena[i]; 00105 memset(s, 0, sizeof *s); 00106 s->in_use = true; 00107 sys_arch_unprotect(prot); 00108 return s; 00109 } 00110 } 00111 00112 sys_arch_unprotect(prot); 00113 return 0; 00114 } 00115 00116 static void mbed_lwip_arena_dealloc(struct lwip_socket *s) 00117 { 00118 s->in_use = false; 00119 00120 while (s->multicast_memberships_count > 0) { 00121 uint32_t index = 0; 00122 index = next_registered_multicast_member(s, index); 00123 00124 mbed_lwip_setsockopt(NULL, s, NSAPI_SOCKET , NSAPI_DROP_MEMBERSHIP , &s->multicast_memberships[index], 00125 sizeof(s->multicast_memberships[index])); 00126 index++; 00127 } 00128 00129 free(s->multicast_memberships); 00130 s->multicast_memberships = NULL; 00131 } 00132 00133 static void mbed_lwip_socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len) 00134 { 00135 // Filter send minus events 00136 if (eh == NETCONN_EVT_SENDMINUS && nc->state == NETCONN_WRITE) { 00137 return; 00138 } 00139 00140 sys_prot_t prot = sys_arch_protect(); 00141 00142 for (int i = 0; i < MEMP_NUM_NETCONN; i++) { 00143 if (lwip_arena[i].in_use 00144 && lwip_arena[i].conn == nc 00145 && lwip_arena[i].cb) { 00146 lwip_arena[i].cb(lwip_arena[i].data); 00147 } 00148 } 00149 00150 sys_arch_unprotect(prot); 00151 } 00152 00153 00154 /* TCP/IP and Network Interface Initialisation */ 00155 static struct netif lwip_netif; 00156 #if LWIP_DHCP 00157 static bool lwip_dhcp = false; 00158 static bool lwip_dhcp_has_to_be_set = false; 00159 #endif 00160 static char lwip_mac_address[NSAPI_MAC_SIZE]; 00161 00162 #if !LWIP_IPV4 || !LWIP_IPV6 00163 static bool all_zeros(const uint8_t *p, int len) 00164 { 00165 for (int i = 0; i < len; i++) { 00166 if (p[i]) { 00167 return false; 00168 } 00169 } 00170 00171 return true; 00172 } 00173 #endif 00174 00175 static bool convert_mbed_addr_to_lwip(ip_addr_t *out, const nsapi_addr_t *in) 00176 { 00177 #if LWIP_IPV6 00178 if (in->version == NSAPI_IPv6 ) { 00179 IP_SET_TYPE(out, IPADDR_TYPE_V6); 00180 MEMCPY(ip_2_ip6(out), in->bytes, sizeof(ip6_addr_t)); 00181 return true; 00182 } 00183 #if !LWIP_IPV4 00184 /* For bind() and other purposes, need to accept "null" of other type */ 00185 /* (People use IPv4 0.0.0.0 as a general null) */ 00186 if (in->version == NSAPI_UNSPEC || 00187 (in->version == NSAPI_IPv4 && all_zeros(in->bytes, 4))) { 00188 ip_addr_set_zero_ip6(out); 00189 return true; 00190 } 00191 #endif 00192 #endif 00193 00194 #if LWIP_IPV4 00195 if (in->version == NSAPI_IPv4 ) { 00196 IP_SET_TYPE(out, IPADDR_TYPE_V4); 00197 MEMCPY(ip_2_ip4(out), in->bytes, sizeof(ip4_addr_t)); 00198 return true; 00199 } 00200 #if !LWIP_IPV6 00201 /* For symmetry with above, accept IPv6 :: as a general null */ 00202 if (in->version == NSAPI_UNSPEC || 00203 (in->version == NSAPI_IPv6 && all_zeros(in->bytes, 16))) { 00204 ip_addr_set_zero_ip4(out); 00205 return true; 00206 } 00207 #endif 00208 #endif 00209 00210 #if LWIP_IPV4 && LWIP_IPV6 00211 if (in->version == NSAPI_UNSPEC ) { 00212 #if IP_VERSION_PREF == PREF_IPV4 00213 ip_addr_set_zero_ip4(out); 00214 #else 00215 ip_addr_set_zero_ip6(out); 00216 #endif 00217 return true; 00218 } 00219 #endif 00220 00221 return false; 00222 } 00223 00224 static bool convert_lwip_addr_to_mbed(nsapi_addr_t *out, const ip_addr_t *in) 00225 { 00226 #if LWIP_IPV6 00227 if (IP_IS_V6(in)) { 00228 out->version = NSAPI_IPv6 ; 00229 MEMCPY(out->bytes, ip_2_ip6(in), sizeof(ip6_addr_t)); 00230 return true; 00231 } 00232 #endif 00233 #if LWIP_IPV4 00234 if (IP_IS_V4(in)) { 00235 out->version = NSAPI_IPv4 ; 00236 MEMCPY(out->bytes, ip_2_ip4(in), sizeof(ip4_addr_t)); 00237 return true; 00238 } 00239 #endif 00240 #if LWIP_IPV6 && LWIP_IPV4 00241 return false; 00242 #endif 00243 } 00244 00245 #if LWIP_IPV4 00246 static const ip_addr_t *mbed_lwip_get_ipv4_addr(const struct netif *netif) 00247 { 00248 if (!netif_is_up(netif)) { 00249 return NULL; 00250 } 00251 00252 if (!ip4_addr_isany(netif_ip4_addr(netif))) { 00253 return netif_ip_addr4(netif); 00254 } 00255 00256 return NULL; 00257 } 00258 #endif 00259 00260 #if LWIP_IPV6 00261 static const ip_addr_t *mbed_lwip_get_ipv6_addr(const struct netif *netif) 00262 { 00263 00264 if (!netif_is_up(netif)) { 00265 return NULL; 00266 } 00267 00268 for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00269 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 00270 !ip6_addr_islinklocal(netif_ip6_addr(netif, i))) { 00271 return netif_ip_addr6(netif, i); 00272 } 00273 } 00274 00275 return NULL; 00276 } 00277 #endif 00278 00279 static bool mbed_lwip_is_local_addr(const ip_addr_t *ip_addr) 00280 { 00281 struct netif *netif; 00282 00283 for (netif = netif_list; netif != NULL; netif = netif->next) { 00284 if (!netif_is_up(netif)) { 00285 continue; 00286 } 00287 #if LWIP_IPV6 00288 if (IP_IS_V6(ip_addr)) { 00289 for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00290 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) && 00291 ip6_addr_cmp(netif_ip6_addr(netif, i), ip_2_ip6(ip_addr))) { 00292 return true; 00293 } 00294 } 00295 } 00296 #endif 00297 00298 #if LWIP_IPV4 00299 if (IP_IS_V4(ip_addr)) { 00300 if (!ip4_addr_isany(netif_ip4_addr(netif)) && 00301 ip4_addr_cmp(netif_ip4_addr(netif), ip_2_ip4(ip_addr))) { 00302 return true; 00303 } 00304 } 00305 #endif 00306 } 00307 return false; 00308 } 00309 00310 const ip_addr_t *mbed_lwip_get_ip_addr(bool any_addr, const struct netif *netif) 00311 { 00312 const ip_addr_t *pref_ip_addr = 0; 00313 const ip_addr_t *npref_ip_addr = 0; 00314 00315 #if LWIP_IPV4 && LWIP_IPV6 00316 #if IP_VERSION_PREF == PREF_IPV4 00317 pref_ip_addr = mbed_lwip_get_ipv4_addr(netif); 00318 npref_ip_addr = mbed_lwip_get_ipv6_addr(netif); 00319 #else 00320 pref_ip_addr = mbed_lwip_get_ipv6_addr(netif); 00321 npref_ip_addr = mbed_lwip_get_ipv4_addr(netif); 00322 #endif 00323 #elif LWIP_IPV6 00324 pref_ip_addr = mbed_lwip_get_ipv6_addr(netif); 00325 #elif LWIP_IPV4 00326 pref_ip_addr = mbed_lwip_get_ipv4_addr(netif); 00327 #endif 00328 00329 if (pref_ip_addr) { 00330 return pref_ip_addr; 00331 } else if (npref_ip_addr && any_addr) { 00332 return npref_ip_addr; 00333 } 00334 00335 return NULL; 00336 } 00337 00338 static void add_dns_addr_to_dns_list_index(const u8_t addr_type, const u8_t index) 00339 { 00340 #if LWIP_IPV6 00341 if (addr_type == IPADDR_TYPE_V6) { 00342 /* 2001:4860:4860::8888 google */ 00343 ip_addr_t ipv6_dns_addr = IPADDR6_INIT( 00344 PP_HTONL(0x20014860UL), 00345 PP_HTONL(0x48600000UL), 00346 PP_HTONL(0x00000000UL), 00347 PP_HTONL(0x00008888UL)); 00348 dns_setserver(index, &ipv6_dns_addr); 00349 } 00350 #endif 00351 #if LWIP_IPV4 00352 if (addr_type == IPADDR_TYPE_V4) { 00353 /* 8.8.8.8 google */ 00354 ip_addr_t ipv4_dns_addr = IPADDR4_INIT(0x08080808); 00355 dns_setserver(index, &ipv4_dns_addr); 00356 } 00357 #endif 00358 } 00359 00360 static int get_ip_addr_type(const ip_addr_t *ip_addr) 00361 { 00362 #if LWIP_IPV6 00363 if (IP_IS_V6(ip_addr)) { 00364 return IPADDR_TYPE_V6; 00365 } 00366 #endif 00367 #if LWIP_IPV4 00368 if (IP_IS_V4(ip_addr)) { 00369 return IPADDR_TYPE_V4; 00370 } 00371 #endif 00372 #if LWIP_IPV6 && LWIP_IPV4 00373 return IPADDR_TYPE_ANY; 00374 #endif 00375 } 00376 00377 void add_dns_addr(struct netif *lwip_netif) 00378 { 00379 // Check for existing dns address 00380 for (char numdns = 0; numdns < DNS_MAX_SERVERS; numdns++) { 00381 const ip_addr_t *dns_ip_addr = dns_getserver(numdns); 00382 if (!ip_addr_isany(dns_ip_addr)) { 00383 return; 00384 } 00385 } 00386 00387 // Get preferred ip version 00388 const ip_addr_t *ip_addr = mbed_lwip_get_ip_addr(false, lwip_netif); 00389 u8_t addr_type = IPADDR_TYPE_ANY; 00390 00391 // Add preferred ip version dns address to index 0 00392 if (ip_addr) { 00393 addr_type = get_ip_addr_type(ip_addr); 00394 add_dns_addr_to_dns_list_index(addr_type, 0); 00395 } 00396 00397 #if LWIP_IPV4 && LWIP_IPV6 00398 if (!ip_addr) { 00399 // Get address for any ip version 00400 ip_addr = mbed_lwip_get_ip_addr(true, lwip_netif); 00401 if (!ip_addr) { 00402 return; 00403 } 00404 addr_type = get_ip_addr_type(ip_addr); 00405 // Add the dns address to index 0 00406 add_dns_addr_to_dns_list_index(addr_type, 0); 00407 } 00408 00409 if (addr_type == IPADDR_TYPE_V4) { 00410 // If ipv4 is preferred and ipv6 is available add ipv6 dns address to index 1 00411 ip_addr = mbed_lwip_get_ipv6_addr(lwip_netif); 00412 } else if (addr_type == IPADDR_TYPE_V6) { 00413 // If ipv6 is preferred and ipv4 is available add ipv4 dns address to index 1 00414 ip_addr = mbed_lwip_get_ipv4_addr(lwip_netif); 00415 } else { 00416 ip_addr = NULL; 00417 } 00418 00419 if (ip_addr) { 00420 addr_type = get_ip_addr_type(ip_addr); 00421 add_dns_addr_to_dns_list_index(addr_type, 1); 00422 } 00423 #endif 00424 } 00425 00426 static sys_sem_t lwip_tcpip_inited; 00427 static void mbed_lwip_tcpip_init_irq(void *eh) 00428 { 00429 sys_sem_signal(&lwip_tcpip_inited); 00430 } 00431 00432 /** This is a pointer to an Ethernet IF, whose callback will be called in case 00433 * of network connection status changes 00434 */ 00435 static void *lwip_status_cb_handle = NULL; 00436 /** This function is called when the netif state is set to up or down 00437 */ 00438 static mbed_lwip_client_callback lwip_client_callback = NULL; 00439 /** The blocking status of the if 00440 */ 00441 static bool lwip_blocking = true; 00442 static bool lwip_ppp = false; 00443 00444 00445 static nsapi_error_t mbed_set_dhcp(struct netif *lwip_netif) 00446 { 00447 if (!lwip_ppp) { 00448 netif_set_up(lwip_netif); 00449 } 00450 00451 #if LWIP_DHCP 00452 if (lwip_dhcp && lwip_dhcp_has_to_be_set) { 00453 err_t err = dhcp_start(lwip_netif); 00454 lwip_dhcp_has_to_be_set = false; 00455 if (err) { 00456 lwip_connected = NSAPI_STATUS_DISCONNECTED ; 00457 if (lwip_client_callback) { 00458 lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_DISCONNECTED ); 00459 } 00460 return NSAPI_ERROR_DHCP_FAILURE ; 00461 } 00462 } 00463 #endif 00464 00465 return NSAPI_ERROR_OK ; 00466 } 00467 00468 static sys_sem_t lwip_netif_linked; 00469 static sys_sem_t lwip_netif_unlinked; 00470 static void mbed_lwip_netif_link_irq(struct netif *lwip_netif) 00471 { 00472 if (netif_is_link_up(lwip_netif)) { 00473 00474 nsapi_error_t dhcp_status = mbed_set_dhcp(lwip_netif); 00475 00476 if (lwip_blocking && dhcp_status == NSAPI_ERROR_OK ) { 00477 sys_sem_signal(&lwip_netif_linked); 00478 } else if (dhcp_status != NSAPI_ERROR_OK ) { 00479 netif_set_down(lwip_netif); 00480 } 00481 00482 00483 } else { 00484 sys_sem_signal(&lwip_netif_unlinked); 00485 netif_set_down(lwip_netif); 00486 } 00487 } 00488 00489 00490 00491 00492 static char lwip_has_addr_state = 0; 00493 00494 #define HAS_ANY_ADDR 1 00495 static sys_sem_t lwip_netif_has_any_addr; 00496 #if PREF_ADDR_TIMEOUT 00497 #define HAS_PREF_ADDR 2 00498 static sys_sem_t lwip_netif_has_pref_addr; 00499 #endif 00500 #if BOTH_ADDR_TIMEOUT 00501 #define HAS_BOTH_ADDR 4 00502 static sys_sem_t lwip_netif_has_both_addr; 00503 #endif 00504 00505 00506 static void mbed_lwip_netif_status_irq(struct netif *lwip_netif) 00507 { 00508 if (netif_is_up(lwip_netif)) { 00509 bool dns_addr_has_to_be_added = false; 00510 if (!(lwip_has_addr_state & HAS_ANY_ADDR) && mbed_lwip_get_ip_addr(true, lwip_netif)) { 00511 if (lwip_blocking) { 00512 sys_sem_signal(&lwip_netif_has_any_addr); 00513 } 00514 lwip_has_addr_state |= HAS_ANY_ADDR; 00515 dns_addr_has_to_be_added = true; 00516 } 00517 #if PREF_ADDR_TIMEOUT 00518 if (!(lwip_has_addr_state & HAS_PREF_ADDR) && mbed_lwip_get_ip_addr(false, lwip_netif)) { 00519 if (lwip_blocking) { 00520 sys_sem_signal(&lwip_netif_has_pref_addr); 00521 } 00522 lwip_has_addr_state |= HAS_PREF_ADDR; 00523 dns_addr_has_to_be_added = true; 00524 } 00525 #endif 00526 #if BOTH_ADDR_TIMEOUT 00527 if (!(lwip_has_addr_state & HAS_BOTH_ADDR) && mbed_lwip_get_ipv4_addr(lwip_netif) && mbed_lwip_get_ipv6_addr(lwip_netif)) { 00528 if (lwip_blocking) { 00529 sys_sem_signal(&lwip_netif_has_both_addr); 00530 } 00531 lwip_has_addr_state |= HAS_BOTH_ADDR; 00532 dns_addr_has_to_be_added = true; 00533 } 00534 #endif 00535 00536 if (dns_addr_has_to_be_added && !lwip_blocking) { 00537 add_dns_addr(lwip_netif); 00538 } 00539 00540 00541 if (lwip_has_addr_state & HAS_ANY_ADDR) { 00542 lwip_connected = NSAPI_STATUS_GLOBAL_UP ; 00543 } 00544 } else { 00545 lwip_connected = NSAPI_STATUS_DISCONNECTED ; 00546 } 00547 00548 if (lwip_client_callback) { 00549 lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE , lwip_connected); 00550 } 00551 } 00552 00553 void mbed_lwip_set_blocking(bool blocking) 00554 { 00555 lwip_blocking = blocking; 00556 } 00557 00558 void mbed_lwip_attach(mbed_lwip_client_callback client_callback, void *status_cb_handle) 00559 { 00560 lwip_client_callback = client_callback; 00561 lwip_status_cb_handle = status_cb_handle; 00562 } 00563 00564 nsapi_connection_status_t mbed_lwip_netif_status_check(void) 00565 { 00566 return lwip_connected; 00567 } 00568 00569 00570 #if LWIP_ETHERNET 00571 static void mbed_lwip_set_mac_address(struct netif *netif) 00572 { 00573 #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE) 00574 netif->hwaddr[0] = MBED_MAC_ADDR_0; 00575 netif->hwaddr[1] = MBED_MAC_ADDR_1; 00576 netif->hwaddr[2] = MBED_MAC_ADDR_2; 00577 netif->hwaddr[3] = MBED_MAC_ADDR_3; 00578 netif->hwaddr[4] = MBED_MAC_ADDR_4; 00579 netif->hwaddr[5] = MBED_MAC_ADDR_5; 00580 #else 00581 mbed_mac_address((char *)netif->hwaddr); 00582 #endif 00583 00584 netif->hwaddr_len = ETH_HWADDR_LEN; 00585 00586 /* Use mac address as additional seed to random number generator */ 00587 uint64_t seed = netif->hwaddr[0]; 00588 for (uint8_t i = 1; i < 8; i++) { 00589 seed <<= 8; 00590 seed |= netif->hwaddr[i % 6]; 00591 } 00592 lwip_add_random_seed(seed); 00593 } 00594 00595 static void mbed_lwip_record_mac_address(const struct netif *netif) 00596 { 00597 const u8_t *mac = netif->hwaddr; 00598 snprintf(lwip_mac_address, NSAPI_MAC_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x", 00599 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 00600 } 00601 #endif // LWIP_ETHERNET 00602 00603 /* LWIP interface implementation */ 00604 const char *mbed_lwip_get_mac_address(void) 00605 { 00606 return lwip_mac_address[0] ? lwip_mac_address : NULL; 00607 } 00608 00609 char *mbed_lwip_get_ip_address(char *buf, nsapi_size_t buflen) 00610 { 00611 const ip_addr_t *addr = mbed_lwip_get_ip_addr(true, &lwip_netif); 00612 if (!addr) { 00613 return NULL; 00614 } 00615 #if LWIP_IPV6 00616 if (IP_IS_V6(addr)) { 00617 return ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen); 00618 } 00619 #endif 00620 #if LWIP_IPV4 00621 if (IP_IS_V4(addr)) { 00622 return ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen); 00623 } 00624 #endif 00625 #if LWIP_IPV6 && LWIP_IPV4 00626 return NULL; 00627 #endif 00628 } 00629 00630 char *mbed_lwip_get_netmask(char *buf, nsapi_size_t buflen) 00631 { 00632 #if LWIP_IPV4 00633 const ip4_addr_t *addr = netif_ip4_netmask(&lwip_netif); 00634 if (!ip4_addr_isany(addr)) { 00635 return ip4addr_ntoa_r(addr, buf, buflen); 00636 } else { 00637 return NULL; 00638 } 00639 #else 00640 return NULL; 00641 #endif 00642 } 00643 00644 char *mbed_lwip_get_gateway(char *buf, nsapi_size_t buflen) 00645 { 00646 #if LWIP_IPV4 00647 const ip4_addr_t *addr = netif_ip4_gw(&lwip_netif); 00648 if (!ip4_addr_isany(addr)) { 00649 return ip4addr_ntoa_r(addr, buf, buflen); 00650 } else { 00651 return NULL; 00652 } 00653 #else 00654 return NULL; 00655 #endif 00656 } 00657 00658 static void mbed_lwip_core_init(void) 00659 { 00660 00661 // Check if we've already brought up lwip 00662 if (!lwip_inited) { 00663 // Seed lwip random 00664 lwip_seed_random(); 00665 00666 // Initialise TCP sequence number 00667 uint32_t tcp_isn_secret[4]; 00668 for (int i = 0; i < 4; i++) { 00669 tcp_isn_secret[i] = LWIP_RAND(); 00670 } 00671 lwip_init_tcp_isn(0, (u8_t *) &tcp_isn_secret); 00672 00673 sys_sem_new(&lwip_tcpip_inited, 0); 00674 sys_sem_new(&lwip_netif_linked, 0); 00675 sys_sem_new(&lwip_netif_unlinked, 0); 00676 sys_sem_new(&lwip_netif_has_any_addr, 0); 00677 #if PREF_ADDR_TIMEOUT 00678 sys_sem_new(&lwip_netif_has_pref_addr, 0); 00679 #endif 00680 #if BOTH_ADDR_TIMEOUT 00681 sys_sem_new(&lwip_netif_has_both_addr, 0); 00682 #endif 00683 tcpip_init(mbed_lwip_tcpip_init_irq, NULL); 00684 sys_arch_sem_wait(&lwip_tcpip_inited, 0); 00685 00686 lwip_inited = true; 00687 } 00688 } 00689 00690 nsapi_error_t mbed_lwip_emac_init(emac_interface_t *emac) 00691 { 00692 #if LWIP_ETHERNET 00693 // Choose a MAC address - driver can override 00694 mbed_lwip_set_mac_address(&lwip_netif); 00695 // Set up network 00696 if (!netif_add(&lwip_netif, 00697 #if LWIP_IPV4 00698 0, 0, 0, 00699 #endif 00700 emac, MBED_NETIF_INIT_FN, tcpip_input)) { 00701 return NSAPI_ERROR_DEVICE_ERROR ; 00702 } 00703 // Note the MAC address actually in use 00704 mbed_lwip_record_mac_address(&lwip_netif); 00705 #if !DEVICE_EMAC 00706 eth_arch_enable_interrupts(); 00707 #endif 00708 00709 return NSAPI_ERROR_OK ; 00710 #else 00711 return NSAPI_ERROR_UNSUPPORTED ; 00712 #endif //LWIP_ETHERNET 00713 } 00714 00715 // Backwards compatibility with people using DEVICE_EMAC 00716 nsapi_error_t mbed_lwip_init(emac_interface_t *emac) 00717 { 00718 nsapi_error_t ret; 00719 mbed_lwip_core_init(); 00720 ret = mbed_lwip_emac_init(emac); 00721 if (ret == NSAPI_ERROR_OK ) { 00722 netif_inited = true; 00723 } 00724 return ret; 00725 } 00726 00727 00728 // Backwards compatibility with people using DEVICE_EMAC 00729 nsapi_error_t mbed_lwip_bringup(bool dhcp, const char *ip, const char *netmask, const char *gw) 00730 { 00731 return mbed_lwip_bringup_2(dhcp, false, ip, netmask, gw, DEFAULT_STACK); 00732 } 00733 00734 nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const char *netmask, const char *gw, 00735 const nsapi_ip_stack_t stack) 00736 { 00737 // Check if we've already connected 00738 00739 if (lwip_connected == NSAPI_STATUS_GLOBAL_UP ) { 00740 return NSAPI_ERROR_IS_CONNECTED ; 00741 } else if (lwip_connected == NSAPI_STATUS_CONNECTING ) { 00742 return NSAPI_ERROR_ALREADY ; 00743 } 00744 00745 lwip_connected = NSAPI_STATUS_CONNECTING ; 00746 lwip_ppp = ppp; 00747 #if LWIP_DHCP 00748 lwip_dhcp_has_to_be_set = true; 00749 if (stack != IPV6_STACK) { 00750 lwip_dhcp = dhcp; 00751 } else { 00752 lwip_dhcp = false; 00753 } 00754 #endif 00755 mbed_lwip_core_init(); 00756 00757 nsapi_error_t ret; 00758 if (netif_inited) { 00759 /* Can't cope with changing mode */ 00760 if (netif_is_ppp == ppp) { 00761 ret = NSAPI_ERROR_OK ; 00762 } else { 00763 ret = NSAPI_ERROR_PARAMETER ; 00764 } 00765 } else { 00766 if (ppp) { 00767 ret = ppp_lwip_if_init(&lwip_netif, stack); 00768 } else { 00769 ret = mbed_lwip_emac_init(NULL); 00770 } 00771 } 00772 00773 if (ret != NSAPI_ERROR_OK ) { 00774 lwip_connected = NSAPI_STATUS_DISCONNECTED ; 00775 return ret; 00776 } 00777 00778 00779 if (lwip_client_callback) { 00780 lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_CONNECTING ); 00781 } 00782 00783 netif_inited = true; 00784 if (ppp) { 00785 netif_is_ppp = ppp; 00786 } 00787 00788 netif_set_default(&lwip_netif); 00789 netif_set_link_callback(&lwip_netif, mbed_lwip_netif_link_irq); 00790 netif_set_status_callback(&lwip_netif, mbed_lwip_netif_status_irq); 00791 00792 #if LWIP_IPV6 00793 if (stack != IPV4_STACK) { 00794 if (lwip_netif.hwaddr_len == ETH_HWADDR_LEN) { 00795 netif_create_ip6_linklocal_address(&lwip_netif, 1/*from MAC*/); 00796 } 00797 00798 #if LWIP_IPV6_MLD 00799 /* 00800 * For hardware/netifs that implement MAC filtering. 00801 * All-nodes link-local is handled by default, so we must let the hardware know 00802 * to allow multicast packets in. 00803 * Should set mld_mac_filter previously. */ 00804 if (lwip_netif.mld_mac_filter != NULL) { 00805 ip6_addr_t ip6_allnodes_ll; 00806 ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); 00807 lwip_netif.mld_mac_filter(&lwip_netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); 00808 } 00809 #endif /* LWIP_IPV6_MLD */ 00810 00811 #if LWIP_IPV6_AUTOCONFIG 00812 /* IPv6 address autoconfiguration not enabled by default */ 00813 lwip_netif.ip6_autoconfig_enabled = 1; 00814 } else { 00815 // Disable router solidifications 00816 lwip_netif.rs_count = 0; 00817 } 00818 #endif /* LWIP_IPV6_AUTOCONFIG */ 00819 #endif // LWIP_IPV6 00820 00821 #if LWIP_IPV4 00822 if (stack != IPV6_STACK) { 00823 if (!dhcp && !ppp) { 00824 ip4_addr_t ip_addr; 00825 ip4_addr_t netmask_addr; 00826 ip4_addr_t gw_addr; 00827 00828 if (!inet_aton(ip, &ip_addr) || 00829 !inet_aton(netmask, &netmask_addr) || 00830 !inet_aton(gw, &gw_addr)) { 00831 lwip_connected = NSAPI_STATUS_DISCONNECTED ; 00832 if (lwip_client_callback) { 00833 lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_DISCONNECTED ); 00834 } 00835 return NSAPI_ERROR_PARAMETER ; 00836 } 00837 00838 netif_set_addr(&lwip_netif, &ip_addr, &netmask_addr, &gw_addr); 00839 } 00840 } 00841 #endif 00842 00843 if (ppp) { 00844 err_t err = ppp_lwip_connect(); 00845 if (err) { 00846 lwip_connected = NSAPI_STATUS_DISCONNECTED ; 00847 if (lwip_client_callback) { 00848 lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_DISCONNECTED ); 00849 } 00850 return mbed_lwip_err_remap(err); 00851 } 00852 } 00853 00854 00855 00856 if (!netif_is_link_up(&lwip_netif)) { 00857 if (lwip_blocking) { 00858 if (sys_arch_sem_wait(&lwip_netif_linked, 15000) == SYS_ARCH_TIMEOUT) { 00859 if (ppp) { 00860 ppp_lwip_disconnect(); 00861 } 00862 return NSAPI_ERROR_NO_CONNECTION ; 00863 } 00864 } 00865 } else { 00866 ret = mbed_set_dhcp(&lwip_netif); 00867 if (ret != NSAPI_ERROR_OK ) { 00868 return ret; 00869 } 00870 } 00871 00872 if (lwip_blocking) { 00873 // If doesn't have address 00874 if (!mbed_lwip_get_ip_addr(true, &lwip_netif)) { 00875 if (sys_arch_sem_wait(&lwip_netif_has_any_addr, DHCP_TIMEOUT * 1000) == SYS_ARCH_TIMEOUT) { 00876 if (ppp) { 00877 ppp_lwip_disconnect(); 00878 } 00879 return NSAPI_ERROR_DHCP_FAILURE ; 00880 } 00881 } 00882 } else { 00883 return NSAPI_ERROR_OK ; 00884 } 00885 00886 #if PREF_ADDR_TIMEOUT 00887 if (stack != IPV4_STACK && stack != IPV6_STACK) { 00888 // If address is not for preferred stack waits a while to see 00889 // if preferred stack address is acquired 00890 if (!mbed_lwip_get_ip_addr(false, &lwip_netif)) { 00891 sys_arch_sem_wait(&lwip_netif_has_pref_addr, PREF_ADDR_TIMEOUT * 1000); 00892 } 00893 } 00894 #endif 00895 #if BOTH_ADDR_TIMEOUT 00896 if (stack != IPV4_STACK && stack != IPV6_STACK) { 00897 // If addresses for both stacks are not available waits a while to 00898 // see if address for both stacks are acquired 00899 if (!(mbed_lwip_get_ipv4_addr(&lwip_netif) && mbed_lwip_get_ipv6_addr(&lwip_netif))) { 00900 sys_arch_sem_wait(&lwip_netif_has_both_addr, BOTH_ADDR_TIMEOUT * 1000); 00901 } 00902 } 00903 #endif 00904 00905 add_dns_addr(&lwip_netif); 00906 00907 return NSAPI_ERROR_OK ; 00908 } 00909 00910 #if LWIP_IPV6 00911 void mbed_lwip_clear_ipv6_addresses(struct netif *lwip_netif) 00912 { 00913 for (u8_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00914 netif_ip6_addr_set_state(lwip_netif, i, IP6_ADDR_INVALID); 00915 } 00916 } 00917 #endif 00918 00919 // Backwards compatibility with people using DEVICE_EMAC 00920 nsapi_error_t mbed_lwip_bringdown(void) 00921 { 00922 return mbed_lwip_bringdown_2(false); 00923 } 00924 00925 nsapi_error_t mbed_lwip_bringdown_2(bool ppp) 00926 { 00927 // Check if we've connected 00928 if (lwip_connected == NSAPI_STATUS_DISCONNECTED ) { 00929 return NSAPI_ERROR_PARAMETER ; 00930 } 00931 00932 #if LWIP_DHCP 00933 // Disconnect from the network 00934 if (lwip_dhcp) { 00935 dhcp_release(&lwip_netif); 00936 dhcp_stop(&lwip_netif); 00937 lwip_dhcp = false; 00938 lwip_dhcp_has_to_be_set = false; 00939 } 00940 #endif 00941 00942 if (ppp) { 00943 /* this is a blocking call, returns when PPP is properly closed */ 00944 err_t err = ppp_lwip_disconnect(); 00945 if (err) { 00946 return mbed_lwip_err_remap(err); 00947 } 00948 MBED_ASSERT(!netif_is_link_up(&lwip_netif)); 00949 /*if (netif_is_link_up(&lwip_netif)) { 00950 if (sys_arch_sem_wait(&lwip_netif_unlinked, 15000) == SYS_ARCH_TIMEOUT) { 00951 return NSAPI_ERROR_DEVICE_ERROR; 00952 } 00953 }*/ 00954 } else { 00955 netif_set_down(&lwip_netif); 00956 } 00957 00958 #if LWIP_IPV6 00959 mbed_lwip_clear_ipv6_addresses(&lwip_netif); 00960 #endif 00961 00962 sys_sem_free(&lwip_netif_has_any_addr); 00963 sys_sem_new(&lwip_netif_has_any_addr, 0); 00964 #if PREF_ADDR_TIMEOUT 00965 sys_sem_free(&lwip_netif_has_pref_addr); 00966 sys_sem_new(&lwip_netif_has_pref_addr, 0); 00967 #endif 00968 #if BOTH_ADDR_TIMEOUT 00969 sys_sem_free(&lwip_netif_has_both_addr); 00970 sys_sem_new(&lwip_netif_has_both_addr, 0); 00971 #endif 00972 lwip_has_addr_state = 0; 00973 lwip_connected = NSAPI_STATUS_DISCONNECTED ; 00974 return 0; 00975 } 00976 00977 /* LWIP error remapping */ 00978 static nsapi_error_t mbed_lwip_err_remap(err_t err) { 00979 switch (err) { 00980 case ERR_OK: 00981 case ERR_CLSD: 00982 return 0; 00983 case ERR_MEM: 00984 case ERR_BUF: 00985 return NSAPI_ERROR_NO_MEMORY ; 00986 case ERR_CONN: 00987 case ERR_RST: 00988 case ERR_ABRT: 00989 return NSAPI_ERROR_NO_CONNECTION ; 00990 case ERR_TIMEOUT: 00991 case ERR_RTE: 00992 case ERR_WOULDBLOCK: 00993 return NSAPI_ERROR_WOULD_BLOCK ; 00994 case ERR_VAL: 00995 case ERR_USE: 00996 case ERR_ARG: 00997 return NSAPI_ERROR_PARAMETER ; 00998 case ERR_INPROGRESS: 00999 return NSAPI_ERROR_IN_PROGRESS ; 01000 case ERR_ALREADY: 01001 return NSAPI_ERROR_ALREADY ; 01002 case ERR_ISCONN: 01003 return NSAPI_ERROR_IS_CONNECTED ; 01004 default: 01005 return NSAPI_ERROR_DEVICE_ERROR ; 01006 } 01007 } 01008 01009 /* LWIP network stack implementation */ 01010 static nsapi_error_t mbed_lwip_gethostbyname(nsapi_stack_t *stack, const char *host, nsapi_addr_t *addr, nsapi_version_t version) 01011 { 01012 ip_addr_t lwip_addr; 01013 01014 #if LWIP_IPV4 && LWIP_IPV6 01015 u8_t addr_type; 01016 if (version == NSAPI_UNSPEC ) { 01017 const ip_addr_t *ip_addr; 01018 ip_addr = mbed_lwip_get_ip_addr(true, &lwip_netif); 01019 // Prefer IPv6 01020 if (IP_IS_V6(ip_addr)) { 01021 // If IPv4 is available use it as backup 01022 if (mbed_lwip_get_ipv4_addr(&lwip_netif)) { 01023 addr_type = NETCONN_DNS_IPV6_IPV4; 01024 } else { 01025 addr_type = NETCONN_DNS_IPV6; 01026 } 01027 // Prefer IPv4 01028 } else { 01029 // If IPv6 is available use it as backup 01030 if (mbed_lwip_get_ipv6_addr(&lwip_netif)) { 01031 addr_type = NETCONN_DNS_IPV4_IPV6; 01032 } else { 01033 addr_type = NETCONN_DNS_IPV4; 01034 } 01035 } 01036 } else if (version == NSAPI_IPv4 ) { 01037 addr_type = NETCONN_DNS_IPV4; 01038 } else if (version == NSAPI_IPv6 ) { 01039 addr_type = NETCONN_DNS_IPV6; 01040 } else { 01041 return NSAPI_ERROR_DNS_FAILURE ; 01042 } 01043 err_t err = netconn_gethostbyname_addrtype(host, &lwip_addr, addr_type); 01044 #elif LWIP_IPV4 01045 if (version != NSAPI_IPv4 && version != NSAPI_UNSPEC ) { 01046 return NSAPI_ERROR_DNS_FAILURE ; 01047 } 01048 err_t err = netconn_gethostbyname(host, &lwip_addr); 01049 #elif LWIP_IPV6 01050 if (version != NSAPI_IPv6 && version != NSAPI_UNSPEC ) { 01051 return NSAPI_ERROR_DNS_FAILURE ; 01052 } 01053 err_t err = netconn_gethostbyname(host, &lwip_addr); 01054 #endif 01055 01056 if (err != ERR_OK) { 01057 return NSAPI_ERROR_DNS_FAILURE ; 01058 } 01059 01060 convert_lwip_addr_to_mbed(addr, &lwip_addr); 01061 01062 return 0; 01063 } 01064 01065 static nsapi_error_t mbed_lwip_add_dns_server(nsapi_stack_t *stack, nsapi_addr_t addr) 01066 { 01067 // Shift all dns servers down to give precedence to new server 01068 for (int i = DNS_MAX_SERVERS-1; i > 0; i--) { 01069 dns_setserver(i, dns_getserver(i-1)); 01070 } 01071 01072 ip_addr_t ip_addr; 01073 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { 01074 return NSAPI_ERROR_PARAMETER ; 01075 } 01076 01077 dns_setserver(0, &ip_addr); 01078 return 0; 01079 } 01080 01081 static nsapi_error_t mbed_lwip_socket_open(nsapi_stack_t *stack, nsapi_socket_t *handle, nsapi_protocol_t proto) 01082 { 01083 // check if network is connected 01084 if (lwip_connected == NSAPI_STATUS_DISCONNECTED ) { 01085 return NSAPI_ERROR_NO_CONNECTION ; 01086 } 01087 01088 // allocate a socket 01089 struct lwip_socket *s = mbed_lwip_arena_alloc(); 01090 if (!s) { 01091 return NSAPI_ERROR_NO_SOCKET ; 01092 } 01093 01094 enum netconn_type lwip_proto = proto == NSAPI_TCP ? NETCONN_TCP : NETCONN_UDP; 01095 01096 #if LWIP_IPV6 01097 // Enable IPv6 (or dual-stack) 01098 lwip_proto |= NETCONN_TYPE_IPV6; 01099 #endif 01100 01101 s->conn = netconn_new_with_callback(lwip_proto, mbed_lwip_socket_callback); 01102 01103 if (!s->conn) { 01104 mbed_lwip_arena_dealloc(s); 01105 return NSAPI_ERROR_NO_SOCKET ; 01106 } 01107 01108 netconn_set_recvtimeout(s->conn, 1); 01109 *(struct lwip_socket **)handle = s; 01110 return 0; 01111 } 01112 01113 static nsapi_error_t mbed_lwip_socket_close(nsapi_stack_t *stack, nsapi_socket_t handle) 01114 { 01115 struct lwip_socket *s = (struct lwip_socket *)handle; 01116 01117 netbuf_delete(s->buf); 01118 err_t err = netconn_delete(s->conn); 01119 mbed_lwip_arena_dealloc(s); 01120 return mbed_lwip_err_remap(err); 01121 } 01122 01123 static nsapi_error_t mbed_lwip_socket_bind(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port) 01124 { 01125 struct lwip_socket *s = (struct lwip_socket *)handle; 01126 ip_addr_t ip_addr; 01127 01128 if ( 01129 #if LWIP_TCP 01130 (s->conn->type == NETCONN_TCP && s->conn->pcb.tcp->local_port != 0) || 01131 #endif 01132 (s->conn->type == NETCONN_UDP && s->conn->pcb.udp->local_port != 0)) { 01133 return NSAPI_ERROR_PARAMETER ; 01134 } 01135 01136 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { 01137 return NSAPI_ERROR_PARAMETER ; 01138 } 01139 01140 if (!ip_addr_isany(&ip_addr) && !mbed_lwip_is_local_addr(&ip_addr)) { 01141 return NSAPI_ERROR_PARAMETER ; 01142 } 01143 01144 err_t err = netconn_bind(s->conn, &ip_addr, port); 01145 return mbed_lwip_err_remap(err); 01146 } 01147 01148 static nsapi_error_t mbed_lwip_socket_listen(nsapi_stack_t *stack, nsapi_socket_t handle, int backlog) 01149 { 01150 struct lwip_socket *s = (struct lwip_socket *)handle; 01151 01152 if (s->conn->pcb.tcp->local_port == 0) { 01153 return NSAPI_ERROR_PARAMETER ; 01154 } 01155 01156 err_t err = netconn_listen_with_backlog(s->conn, backlog); 01157 return mbed_lwip_err_remap(err); 01158 } 01159 01160 static nsapi_error_t mbed_lwip_socket_connect(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port) 01161 { 01162 struct lwip_socket *s = (struct lwip_socket *)handle; 01163 ip_addr_t ip_addr; 01164 01165 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { 01166 return NSAPI_ERROR_PARAMETER ; 01167 } 01168 01169 netconn_set_nonblocking(s->conn, false); 01170 err_t err = netconn_connect(s->conn, &ip_addr, port); 01171 netconn_set_nonblocking(s->conn, true); 01172 01173 return mbed_lwip_err_remap(err); 01174 } 01175 01176 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) 01177 { 01178 struct lwip_socket *s = (struct lwip_socket *)server; 01179 struct lwip_socket *ns = mbed_lwip_arena_alloc(); 01180 if (!ns) { 01181 return NSAPI_ERROR_NO_SOCKET ; 01182 } 01183 01184 if (s->conn->pcb.tcp->state != LISTEN) { 01185 return NSAPI_ERROR_PARAMETER ; 01186 } 01187 01188 err_t err = netconn_accept(s->conn, &ns->conn); 01189 if (err != ERR_OK) { 01190 mbed_lwip_arena_dealloc(ns); 01191 return mbed_lwip_err_remap(err); 01192 } 01193 01194 netconn_set_recvtimeout(ns->conn, 1); 01195 *(struct lwip_socket **)handle = ns; 01196 01197 ip_addr_t peer_addr; 01198 (void) netconn_peer(ns->conn, &peer_addr, port); 01199 convert_lwip_addr_to_mbed(addr, &peer_addr); 01200 01201 netconn_set_nonblocking(ns->conn, true); 01202 01203 return 0; 01204 } 01205 01206 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) 01207 { 01208 struct lwip_socket *s = (struct lwip_socket *)handle; 01209 size_t bytes_written = 0; 01210 01211 err_t err = netconn_write_partly(s->conn, data, size, NETCONN_COPY, &bytes_written); 01212 if (err != ERR_OK) { 01213 return mbed_lwip_err_remap(err); 01214 } 01215 01216 return (nsapi_size_or_error_t)bytes_written; 01217 } 01218 01219 static nsapi_size_or_error_t mbed_lwip_socket_recv(nsapi_stack_t *stack, nsapi_socket_t handle, void *data, nsapi_size_t size) 01220 { 01221 struct lwip_socket *s = (struct lwip_socket *)handle; 01222 01223 if (!s->buf) { 01224 err_t err = netconn_recv(s->conn, &s->buf); 01225 s->offset = 0; 01226 01227 if (err != ERR_OK) { 01228 return mbed_lwip_err_remap(err); 01229 } 01230 } 01231 01232 u16_t recv = netbuf_copy_partial(s->buf, data, (u16_t)size, s->offset); 01233 s->offset += recv; 01234 01235 if (s->offset >= netbuf_len(s->buf)) { 01236 netbuf_delete(s->buf); 01237 s->buf = 0; 01238 } 01239 01240 return recv; 01241 } 01242 01243 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) 01244 { 01245 struct lwip_socket *s = (struct lwip_socket *)handle; 01246 ip_addr_t ip_addr; 01247 01248 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { 01249 return NSAPI_ERROR_PARAMETER ; 01250 } 01251 01252 struct netbuf *buf = netbuf_new(); 01253 err_t err = netbuf_ref(buf, data, (u16_t)size); 01254 if (err != ERR_OK) { 01255 netbuf_free(buf); 01256 return mbed_lwip_err_remap(err); 01257 } 01258 01259 err = netconn_sendto(s->conn, buf, &ip_addr, port); 01260 netbuf_delete(buf); 01261 if (err != ERR_OK) { 01262 return mbed_lwip_err_remap(err); 01263 } 01264 01265 return size; 01266 } 01267 01268 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) 01269 { 01270 struct lwip_socket *s = (struct lwip_socket *)handle; 01271 struct netbuf *buf; 01272 01273 err_t err = netconn_recv(s->conn, &buf); 01274 if (err != ERR_OK) { 01275 return mbed_lwip_err_remap(err); 01276 } 01277 01278 convert_lwip_addr_to_mbed(addr, netbuf_fromaddr(buf)); 01279 *port = netbuf_fromport(buf); 01280 01281 u16_t recv = netbuf_copy(buf, data, (u16_t)size); 01282 netbuf_delete(buf); 01283 01284 return recv; 01285 } 01286 01287 static int32_t find_multicast_member(const struct lwip_socket *s, const nsapi_ip_mreq_t *imr) { 01288 uint32_t count = 0; 01289 uint32_t index = 0; 01290 // Set upper limit on while loop, should break out when the membership pair is found 01291 while (count < s->multicast_memberships_count) { 01292 index = next_registered_multicast_member(s, index); 01293 01294 if (memcmp(&s->multicast_memberships[index].imr_multiaddr, &imr->imr_multiaddr, sizeof(nsapi_addr_t)) == 0 && 01295 memcmp(&s->multicast_memberships[index].imr_interface, &imr->imr_interface, sizeof(nsapi_addr_t)) == 0) { 01296 return index; 01297 } 01298 count++; 01299 index++; 01300 } 01301 01302 return -1; 01303 } 01304 01305 static nsapi_error_t mbed_lwip_setsockopt(nsapi_stack_t *stack, nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen) 01306 { 01307 struct lwip_socket *s = (struct lwip_socket *)handle; 01308 01309 switch (optname) { 01310 #if LWIP_TCP 01311 case NSAPI_KEEPALIVE : 01312 if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { 01313 return NSAPI_ERROR_UNSUPPORTED ; 01314 } 01315 01316 s->conn->pcb.tcp->so_options |= SOF_KEEPALIVE; 01317 return 0; 01318 01319 case NSAPI_KEEPIDLE : 01320 if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { 01321 return NSAPI_ERROR_UNSUPPORTED ; 01322 } 01323 01324 s->conn->pcb.tcp->keep_idle = *(int*)optval; 01325 return 0; 01326 01327 case NSAPI_KEEPINTVL : 01328 if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) { 01329 return NSAPI_ERROR_UNSUPPORTED ; 01330 } 01331 01332 s->conn->pcb.tcp->keep_intvl = *(int*)optval; 01333 return 0; 01334 #endif 01335 01336 case NSAPI_REUSEADDR : 01337 if (optlen != sizeof(int)) { 01338 return NSAPI_ERROR_UNSUPPORTED ; 01339 } 01340 01341 if (*(int *)optval) { 01342 ip_set_option(s->conn->pcb.ip, SOF_REUSEADDR); 01343 } else { 01344 ip_reset_option(s->conn->pcb.ip, SOF_REUSEADDR); 01345 } 01346 return 0; 01347 01348 case NSAPI_ADD_MEMBERSHIP : 01349 case NSAPI_DROP_MEMBERSHIP : { 01350 if (optlen != sizeof(nsapi_ip_mreq_t)) { 01351 return NSAPI_ERROR_PARAMETER ; 01352 } 01353 err_t igmp_err; 01354 const nsapi_ip_mreq_t *imr = optval; 01355 01356 /* Check interface address type matches group, or is unspecified */ 01357 if (imr->imr_interface.version != NSAPI_UNSPEC && imr->imr_interface.version != imr->imr_multiaddr.version) { 01358 return NSAPI_ERROR_PARAMETER ; 01359 } 01360 01361 ip_addr_t if_addr; 01362 ip_addr_t multi_addr; 01363 01364 /* Convert the group address */ 01365 if (!convert_mbed_addr_to_lwip(&multi_addr, &imr->imr_multiaddr)) { 01366 return NSAPI_ERROR_PARAMETER ; 01367 } 01368 01369 /* Convert the interface address, or make sure it's the correct sort of "any" */ 01370 if (imr->imr_interface.version != NSAPI_UNSPEC ) { 01371 if (!convert_mbed_addr_to_lwip(&if_addr, &imr->imr_interface)) { 01372 return NSAPI_ERROR_PARAMETER ; 01373 } 01374 } else { 01375 ip_addr_set_any(IP_IS_V6(&if_addr), &if_addr); 01376 } 01377 01378 igmp_err = ERR_USE; // Maps to NSAPI_ERROR_UNSUPPORTED 01379 int32_t member_pair_index = find_multicast_member(s, imr); 01380 01381 if (optname == NSAPI_ADD_MEMBERSHIP ) { 01382 if (!s->multicast_memberships) { 01383 // First multicast join on this socket, allocate space for membership tracking 01384 s->multicast_memberships = malloc(sizeof(nsapi_ip_mreq_t) * LWIP_SOCKET_MAX_MEMBERSHIPS); 01385 if (!s->multicast_memberships) { 01386 return NSAPI_ERROR_NO_MEMORY ; 01387 } 01388 } else if(s->multicast_memberships_count == LWIP_SOCKET_MAX_MEMBERSHIPS) { 01389 return NSAPI_ERROR_NO_MEMORY ; 01390 } 01391 01392 if (member_pair_index != -1) { 01393 return NSAPI_ERROR_ADDRESS_IN_USE ; 01394 } 01395 01396 member_pair_index = next_free_multicast_member(s, 0); 01397 01398 sys_prot_t prot = sys_arch_protect(); 01399 01400 #if LWIP_IPV4 01401 if (IP_IS_V4(&if_addr)) { 01402 igmp_err = igmp_joingroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr)); 01403 } 01404 #endif 01405 #if LWIP_IPV6 01406 if (IP_IS_V6(&if_addr)) { 01407 igmp_err = mld6_joingroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr)); 01408 } 01409 #endif 01410 01411 sys_arch_unprotect(prot); 01412 01413 if (igmp_err == ERR_OK) { 01414 set_multicast_member_registry_bit(s, member_pair_index); 01415 s->multicast_memberships[member_pair_index] = *imr; 01416 s->multicast_memberships_count++; 01417 } 01418 } else { 01419 if (member_pair_index == -1) { 01420 return NSAPI_ERROR_NO_ADDRESS ; 01421 } 01422 01423 clear_multicast_member_registry_bit(s, member_pair_index); 01424 s->multicast_memberships_count--; 01425 01426 sys_prot_t prot = sys_arch_protect(); 01427 01428 #if LWIP_IPV4 01429 if (IP_IS_V4(&if_addr)) { 01430 igmp_err = igmp_leavegroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr)); 01431 } 01432 #endif 01433 #if LWIP_IPV6 01434 if (IP_IS_V6(&if_addr)) { 01435 igmp_err = mld6_leavegroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr)); 01436 } 01437 #endif 01438 01439 sys_arch_unprotect(prot); 01440 } 01441 01442 return mbed_lwip_err_remap(igmp_err); 01443 } 01444 01445 default: 01446 return NSAPI_ERROR_UNSUPPORTED ; 01447 } 01448 } 01449 01450 static void mbed_lwip_socket_attach(nsapi_stack_t *stack, nsapi_socket_t handle, void (*callback)(void *), void *data) 01451 { 01452 struct lwip_socket *s = (struct lwip_socket *)handle; 01453 01454 s->cb = callback; 01455 s->data = data; 01456 } 01457 01458 /* LWIP network stack */ 01459 const nsapi_stack_api_t lwip_stack_api = { 01460 .gethostbyname = mbed_lwip_gethostbyname, 01461 .add_dns_server = mbed_lwip_add_dns_server, 01462 .socket_open = mbed_lwip_socket_open, 01463 .socket_close = mbed_lwip_socket_close, 01464 .socket_bind = mbed_lwip_socket_bind, 01465 .socket_listen = mbed_lwip_socket_listen, 01466 .socket_connect = mbed_lwip_socket_connect, 01467 .socket_accept = mbed_lwip_socket_accept, 01468 .socket_send = mbed_lwip_socket_send, 01469 .socket_recv = mbed_lwip_socket_recv, 01470 .socket_sendto = mbed_lwip_socket_sendto, 01471 .socket_recvfrom = mbed_lwip_socket_recvfrom, 01472 .setsockopt = mbed_lwip_setsockopt, 01473 .socket_attach = mbed_lwip_socket_attach, 01474 }; 01475 01476 nsapi_stack_t lwip_stack = { 01477 .stack_api = &lwip_stack_api, 01478 };
Generated on Tue Jul 12 2022 13:24:51 by
1.7.2