BA
/
BaBoRo1
Embed:
(wiki syntax)
Show/hide line numbers
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 netif_set_up(lwip_netif); 00448 00449 #if LWIP_DHCP 00450 if (lwip_dhcp && lwip_dhcp_has_to_be_set) { 00451 err_t err = dhcp_start(lwip_netif); 00452 lwip_dhcp_has_to_be_set = false; 00453 if (err) { 00454 lwip_connected = NSAPI_STATUS_DISCONNECTED ; 00455 if (lwip_client_callback) { 00456 lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_DISCONNECTED ); 00457 } 00458 return NSAPI_ERROR_DHCP_FAILURE ; 00459 } 00460 } 00461 #endif 00462 00463 return NSAPI_ERROR_OK ; 00464 } 00465 00466 static sys_sem_t lwip_netif_linked; 00467 static sys_sem_t lwip_netif_unlinked; 00468 static void mbed_lwip_netif_link_irq(struct netif *lwip_netif) 00469 { 00470 if (netif_is_link_up(lwip_netif)) { 00471 00472 nsapi_error_t dhcp_status = mbed_set_dhcp(lwip_netif); 00473 00474 if (lwip_blocking && dhcp_status == NSAPI_ERROR_OK ) { 00475 sys_sem_signal(&lwip_netif_linked); 00476 } else if (dhcp_status != NSAPI_ERROR_OK ) { 00477 netif_set_down(lwip_netif); 00478 } 00479 00480 00481 } else { 00482 sys_sem_signal(&lwip_netif_unlinked); 00483 netif_set_down(lwip_netif); 00484 } 00485 } 00486 00487 00488 00489 00490 static char lwip_has_addr_state = 0; 00491 00492 #define HAS_ANY_ADDR 1 00493 static sys_sem_t lwip_netif_has_any_addr; 00494 #if PREF_ADDR_TIMEOUT 00495 #define HAS_PREF_ADDR 2 00496 static sys_sem_t lwip_netif_has_pref_addr; 00497 #endif 00498 #if BOTH_ADDR_TIMEOUT 00499 #define HAS_BOTH_ADDR 4 00500 static sys_sem_t lwip_netif_has_both_addr; 00501 #endif 00502 00503 00504 static void mbed_lwip_netif_status_irq(struct netif *lwip_netif) 00505 { 00506 if (netif_is_up(lwip_netif)) { 00507 bool dns_addr_has_to_be_added = false; 00508 if (!(lwip_has_addr_state & HAS_ANY_ADDR) && mbed_lwip_get_ip_addr(true, lwip_netif)) { 00509 if (lwip_blocking) { 00510 sys_sem_signal(&lwip_netif_has_any_addr); 00511 } 00512 lwip_has_addr_state |= HAS_ANY_ADDR; 00513 dns_addr_has_to_be_added = true; 00514 } 00515 #if PREF_ADDR_TIMEOUT 00516 if (!(lwip_has_addr_state & HAS_PREF_ADDR) && mbed_lwip_get_ip_addr(false, lwip_netif)) { 00517 if (lwip_blocking) { 00518 sys_sem_signal(&lwip_netif_has_pref_addr); 00519 } 00520 lwip_has_addr_state |= HAS_PREF_ADDR; 00521 dns_addr_has_to_be_added = true; 00522 } 00523 #endif 00524 #if BOTH_ADDR_TIMEOUT 00525 if (!(lwip_has_addr_state & HAS_BOTH_ADDR) && mbed_lwip_get_ipv4_addr(lwip_netif) && mbed_lwip_get_ipv6_addr(lwip_netif)) { 00526 if (lwip_blocking) { 00527 sys_sem_signal(&lwip_netif_has_both_addr); 00528 } 00529 lwip_has_addr_state |= HAS_BOTH_ADDR; 00530 dns_addr_has_to_be_added = true; 00531 } 00532 #endif 00533 00534 if (dns_addr_has_to_be_added && !lwip_blocking) { 00535 add_dns_addr(lwip_netif); 00536 } 00537 00538 00539 if (lwip_has_addr_state & HAS_ANY_ADDR) { 00540 lwip_connected = NSAPI_STATUS_GLOBAL_UP ; 00541 } 00542 } else { 00543 lwip_connected = NSAPI_STATUS_DISCONNECTED ; 00544 } 00545 00546 if (lwip_client_callback) { 00547 lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE , lwip_connected); 00548 } 00549 } 00550 00551 void mbed_lwip_set_blocking(bool blocking) 00552 { 00553 lwip_blocking = blocking; 00554 } 00555 00556 void mbed_lwip_attach(mbed_lwip_client_callback client_callback, void *status_cb_handle) 00557 { 00558 lwip_client_callback = client_callback; 00559 lwip_status_cb_handle = status_cb_handle; 00560 } 00561 00562 nsapi_connection_status_t mbed_lwip_netif_status_check(void) 00563 { 00564 return lwip_connected; 00565 } 00566 00567 00568 #if LWIP_ETHERNET 00569 static void mbed_lwip_set_mac_address(struct netif *netif) 00570 { 00571 #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE) 00572 netif->hwaddr[0] = MBED_MAC_ADDR_0; 00573 netif->hwaddr[1] = MBED_MAC_ADDR_1; 00574 netif->hwaddr[2] = MBED_MAC_ADDR_2; 00575 netif->hwaddr[3] = MBED_MAC_ADDR_3; 00576 netif->hwaddr[4] = MBED_MAC_ADDR_4; 00577 netif->hwaddr[5] = MBED_MAC_ADDR_5; 00578 #else 00579 mbed_mac_address((char *)netif->hwaddr); 00580 #endif 00581 00582 netif->hwaddr_len = ETH_HWADDR_LEN; 00583 00584 /* Use mac address as additional seed to random number generator */ 00585 uint64_t seed = netif->hwaddr[0]; 00586 for (uint8_t i = 1; i < 8; i++) { 00587 seed <<= 8; 00588 seed |= netif->hwaddr[i % 6]; 00589 } 00590 lwip_add_random_seed(seed); 00591 } 00592 00593 static void mbed_lwip_record_mac_address(const struct netif *netif) 00594 { 00595 const u8_t *mac = netif->hwaddr; 00596 snprintf(lwip_mac_address, NSAPI_MAC_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x", 00597 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 00598 } 00599 #endif // LWIP_ETHERNET 00600 00601 /* LWIP interface implementation */ 00602 const char *mbed_lwip_get_mac_address(void) 00603 { 00604 return lwip_mac_address[0] ? lwip_mac_address : NULL; 00605 } 00606 00607 char *mbed_lwip_get_ip_address(char *buf, nsapi_size_t buflen) 00608 { 00609 const ip_addr_t *addr = mbed_lwip_get_ip_addr(true, &lwip_netif); 00610 if (!addr) { 00611 return NULL; 00612 } 00613 #if LWIP_IPV6 00614 if (IP_IS_V6(addr)) { 00615 return ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen); 00616 } 00617 #endif 00618 #if LWIP_IPV4 00619 if (IP_IS_V4(addr)) { 00620 return ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen); 00621 } 00622 #endif 00623 #if LWIP_IPV6 && LWIP_IPV4 00624 return NULL; 00625 #endif 00626 } 00627 00628 char *mbed_lwip_get_netmask(char *buf, nsapi_size_t buflen) 00629 { 00630 #if LWIP_IPV4 00631 const ip4_addr_t *addr = netif_ip4_netmask(&lwip_netif); 00632 if (!ip4_addr_isany(addr)) { 00633 return ip4addr_ntoa_r(addr, buf, buflen); 00634 } else { 00635 return NULL; 00636 } 00637 #else 00638 return NULL; 00639 #endif 00640 } 00641 00642 char *mbed_lwip_get_gateway(char *buf, nsapi_size_t buflen) 00643 { 00644 #if LWIP_IPV4 00645 const ip4_addr_t *addr = netif_ip4_gw(&lwip_netif); 00646 if (!ip4_addr_isany(addr)) { 00647 return ip4addr_ntoa_r(addr, buf, buflen); 00648 } else { 00649 return NULL; 00650 } 00651 #else 00652 return NULL; 00653 #endif 00654 } 00655 00656 static void mbed_lwip_core_init(void) 00657 { 00658 00659 // Check if we've already brought up lwip 00660 if (!lwip_inited) { 00661 // Seed lwip random 00662 lwip_seed_random(); 00663 00664 // Initialise TCP sequence number 00665 uint32_t tcp_isn_secret[4]; 00666 for (int i = 0; i < 4; i++) { 00667 tcp_isn_secret[i] = LWIP_RAND(); 00668 } 00669 lwip_init_tcp_isn(0, (u8_t *) &tcp_isn_secret); 00670 00671 sys_sem_new(&lwip_tcpip_inited, 0); 00672 sys_sem_new(&lwip_netif_linked, 0); 00673 sys_sem_new(&lwip_netif_unlinked, 0); 00674 sys_sem_new(&lwip_netif_has_any_addr, 0); 00675 #if PREF_ADDR_TIMEOUT 00676 sys_sem_new(&lwip_netif_has_pref_addr, 0); 00677 #endif 00678 #if BOTH_ADDR_TIMEOUT 00679 sys_sem_new(&lwip_netif_has_both_addr, 0); 00680 #endif 00681 tcpip_init(mbed_lwip_tcpip_init_irq, NULL); 00682 sys_arch_sem_wait(&lwip_tcpip_inited, 0); 00683 00684 lwip_inited = true; 00685 } 00686 } 00687 00688 nsapi_error_t mbed_lwip_emac_init(emac_interface_t *emac) 00689 { 00690 #if LWIP_ETHERNET 00691 // Choose a MAC address - driver can override 00692 mbed_lwip_set_mac_address(&lwip_netif); 00693 // Set up network 00694 if (!netif_add(&lwip_netif, 00695 #if LWIP_IPV4 00696 0, 0, 0, 00697 #endif 00698 emac, MBED_NETIF_INIT_FN, tcpip_input)) { 00699 return NSAPI_ERROR_DEVICE_ERROR ; 00700 } 00701 // Note the MAC address actually in use 00702 mbed_lwip_record_mac_address(&lwip_netif); 00703 #if !DEVICE_EMAC 00704 eth_arch_enable_interrupts(); 00705 #endif 00706 00707 return NSAPI_ERROR_OK ; 00708 #else 00709 return NSAPI_ERROR_UNSUPPORTED ; 00710 #endif //LWIP_ETHERNET 00711 } 00712 00713 // Backwards compatibility with people using DEVICE_EMAC 00714 nsapi_error_t mbed_lwip_init(emac_interface_t *emac) 00715 { 00716 nsapi_error_t ret; 00717 mbed_lwip_core_init(); 00718 ret = mbed_lwip_emac_init(emac); 00719 if (ret == NSAPI_ERROR_OK ) { 00720 netif_inited = true; 00721 } 00722 return ret; 00723 } 00724 00725 00726 // Backwards compatibility with people using DEVICE_EMAC 00727 nsapi_error_t mbed_lwip_bringup(bool dhcp, const char *ip, const char *netmask, const char *gw) 00728 { 00729 return mbed_lwip_bringup_2(dhcp, false, ip, netmask, gw, DEFAULT_STACK); 00730 } 00731 00732 nsapi_error_t mbed_lwip_bringup_2(bool dhcp, bool ppp, const char *ip, const char *netmask, const char *gw, 00733 const nsapi_ip_stack_t stack) 00734 { 00735 // Check if we've already connected 00736 00737 if (lwip_connected == NSAPI_STATUS_GLOBAL_UP ) { 00738 return NSAPI_ERROR_IS_CONNECTED ; 00739 } else if (lwip_connected == NSAPI_STATUS_CONNECTING ) { 00740 return NSAPI_ERROR_ALREADY ; 00741 } 00742 00743 lwip_connected = NSAPI_STATUS_CONNECTING ; 00744 lwip_ppp = ppp; 00745 #if LWIP_DHCP 00746 lwip_dhcp_has_to_be_set = true; 00747 if (stack != IPV6_STACK) { 00748 lwip_dhcp = dhcp; 00749 } else { 00750 lwip_dhcp = false; 00751 } 00752 #endif 00753 mbed_lwip_core_init(); 00754 00755 nsapi_error_t ret; 00756 if (netif_inited) { 00757 /* Can't cope with changing mode */ 00758 if (netif_is_ppp == ppp) { 00759 ret = NSAPI_ERROR_OK ; 00760 } else { 00761 ret = NSAPI_ERROR_PARAMETER ; 00762 } 00763 } else { 00764 if (ppp) { 00765 ret = ppp_lwip_if_init(&lwip_netif, stack); 00766 } else { 00767 ret = mbed_lwip_emac_init(NULL); 00768 } 00769 } 00770 00771 if (ret != NSAPI_ERROR_OK ) { 00772 lwip_connected = NSAPI_STATUS_DISCONNECTED ; 00773 return ret; 00774 } 00775 00776 00777 if (lwip_client_callback) { 00778 lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_CONNECTING ); 00779 } 00780 00781 netif_inited = true; 00782 if (ppp) { 00783 netif_is_ppp = ppp; 00784 } 00785 00786 netif_set_default(&lwip_netif); 00787 netif_set_link_callback(&lwip_netif, mbed_lwip_netif_link_irq); 00788 netif_set_status_callback(&lwip_netif, mbed_lwip_netif_status_irq); 00789 00790 #if LWIP_IPV6 00791 if (stack != IPV4_STACK) { 00792 if (lwip_netif.hwaddr_len == ETH_HWADDR_LEN) { 00793 netif_create_ip6_linklocal_address(&lwip_netif, 1/*from MAC*/); 00794 } 00795 00796 #if LWIP_IPV6_MLD 00797 /* 00798 * For hardware/netifs that implement MAC filtering. 00799 * All-nodes link-local is handled by default, so we must let the hardware know 00800 * to allow multicast packets in. 00801 * Should set mld_mac_filter previously. */ 00802 if (lwip_netif.mld_mac_filter != NULL) { 00803 ip6_addr_t ip6_allnodes_ll; 00804 ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll); 00805 lwip_netif.mld_mac_filter(&lwip_netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER); 00806 } 00807 #endif /* LWIP_IPV6_MLD */ 00808 00809 #if LWIP_IPV6_AUTOCONFIG 00810 /* IPv6 address autoconfiguration not enabled by default */ 00811 lwip_netif.ip6_autoconfig_enabled = 1; 00812 } else { 00813 // Disable router solidifications 00814 lwip_netif.rs_count = 0; 00815 } 00816 #endif /* LWIP_IPV6_AUTOCONFIG */ 00817 #endif // LWIP_IPV6 00818 00819 #if LWIP_IPV4 00820 if (stack != IPV6_STACK) { 00821 if (!dhcp && !ppp) { 00822 ip4_addr_t ip_addr; 00823 ip4_addr_t netmask_addr; 00824 ip4_addr_t gw_addr; 00825 00826 if (!inet_aton(ip, &ip_addr) || 00827 !inet_aton(netmask, &netmask_addr) || 00828 !inet_aton(gw, &gw_addr)) { 00829 lwip_connected = NSAPI_STATUS_DISCONNECTED ; 00830 if (lwip_client_callback) { 00831 lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_DISCONNECTED ); 00832 } 00833 return NSAPI_ERROR_PARAMETER ; 00834 } 00835 00836 netif_set_addr(&lwip_netif, &ip_addr, &netmask_addr, &gw_addr); 00837 } 00838 } 00839 #endif 00840 00841 if (ppp) { 00842 err_t err = ppp_lwip_connect(); 00843 if (err) { 00844 lwip_connected = NSAPI_STATUS_DISCONNECTED ; 00845 if (lwip_client_callback) { 00846 lwip_client_callback(lwip_status_cb_handle, NSAPI_EVENT_CONNECTION_STATUS_CHANGE , NSAPI_STATUS_DISCONNECTED ); 00847 } 00848 return mbed_lwip_err_remap(err); 00849 } 00850 } 00851 00852 00853 00854 if (!netif_is_link_up(&lwip_netif)) { 00855 if (lwip_blocking) { 00856 if (sys_arch_sem_wait(&lwip_netif_linked, 15000) == SYS_ARCH_TIMEOUT) { 00857 if (ppp) { 00858 ppp_lwip_disconnect(); 00859 } 00860 return NSAPI_ERROR_NO_CONNECTION ; 00861 } 00862 } 00863 } else { 00864 ret = mbed_set_dhcp(&lwip_netif); 00865 if (ret != NSAPI_ERROR_OK ) { 00866 return ret; 00867 } 00868 } 00869 00870 if (lwip_blocking) { 00871 // If doesn't have address 00872 if (!mbed_lwip_get_ip_addr(true, &lwip_netif)) { 00873 if (sys_arch_sem_wait(&lwip_netif_has_any_addr, DHCP_TIMEOUT * 1000) == SYS_ARCH_TIMEOUT) { 00874 if (ppp) { 00875 ppp_lwip_disconnect(); 00876 } 00877 return NSAPI_ERROR_DHCP_FAILURE ; 00878 } 00879 } 00880 } else { 00881 return NSAPI_ERROR_OK ; 00882 } 00883 00884 #if PREF_ADDR_TIMEOUT 00885 if (stack != IPV4_STACK && stack != IPV6_STACK) { 00886 // If address is not for preferred stack waits a while to see 00887 // if preferred stack address is acquired 00888 if (!mbed_lwip_get_ip_addr(false, &lwip_netif)) { 00889 sys_arch_sem_wait(&lwip_netif_has_pref_addr, PREF_ADDR_TIMEOUT * 1000); 00890 } 00891 } 00892 #endif 00893 #if BOTH_ADDR_TIMEOUT 00894 if (stack != IPV4_STACK && stack != IPV6_STACK) { 00895 // If addresses for both stacks are not available waits a while to 00896 // see if address for both stacks are acquired 00897 if (!(mbed_lwip_get_ipv4_addr(&lwip_netif) && mbed_lwip_get_ipv6_addr(&lwip_netif))) { 00898 sys_arch_sem_wait(&lwip_netif_has_both_addr, BOTH_ADDR_TIMEOUT * 1000); 00899 } 00900 } 00901 #endif 00902 00903 add_dns_addr(&lwip_netif); 00904 00905 return NSAPI_ERROR_OK ; 00906 } 00907 00908 #if LWIP_IPV6 00909 void mbed_lwip_clear_ipv6_addresses(struct netif *lwip_netif) 00910 { 00911 for (u8_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) { 00912 netif_ip6_addr_set_state(lwip_netif, i, IP6_ADDR_INVALID); 00913 } 00914 } 00915 #endif 00916 00917 // Backwards compatibility with people using DEVICE_EMAC 00918 nsapi_error_t mbed_lwip_bringdown(void) 00919 { 00920 return mbed_lwip_bringdown_2(false); 00921 } 00922 00923 nsapi_error_t mbed_lwip_bringdown_2(bool ppp) 00924 { 00925 // Check if we've connected 00926 if (lwip_connected == NSAPI_STATUS_DISCONNECTED ) { 00927 return NSAPI_ERROR_PARAMETER ; 00928 } 00929 00930 #if LWIP_DHCP 00931 // Disconnect from the network 00932 if (lwip_dhcp) { 00933 dhcp_release(&lwip_netif); 00934 dhcp_stop(&lwip_netif); 00935 lwip_dhcp = false; 00936 lwip_dhcp_has_to_be_set = false; 00937 } 00938 #endif 00939 00940 if (ppp) { 00941 /* this is a blocking call, returns when PPP is properly closed */ 00942 err_t err = ppp_lwip_disconnect(); 00943 if (err) { 00944 return mbed_lwip_err_remap(err); 00945 } 00946 MBED_ASSERT(!netif_is_link_up(&lwip_netif)); 00947 /*if (netif_is_link_up(&lwip_netif)) { 00948 if (sys_arch_sem_wait(&lwip_netif_unlinked, 15000) == SYS_ARCH_TIMEOUT) { 00949 return NSAPI_ERROR_DEVICE_ERROR; 00950 } 00951 }*/ 00952 } else { 00953 netif_set_down(&lwip_netif); 00954 } 00955 00956 #if LWIP_IPV6 00957 mbed_lwip_clear_ipv6_addresses(&lwip_netif); 00958 #endif 00959 00960 sys_sem_free(&lwip_netif_has_any_addr); 00961 sys_sem_new(&lwip_netif_has_any_addr, 0); 00962 #if PREF_ADDR_TIMEOUT 00963 sys_sem_free(&lwip_netif_has_pref_addr); 00964 sys_sem_new(&lwip_netif_has_pref_addr, 0); 00965 #endif 00966 #if BOTH_ADDR_TIMEOUT 00967 sys_sem_free(&lwip_netif_has_both_addr); 00968 sys_sem_new(&lwip_netif_has_both_addr, 0); 00969 #endif 00970 lwip_has_addr_state = 0; 00971 lwip_connected = NSAPI_STATUS_DISCONNECTED ; 00972 return 0; 00973 } 00974 00975 /* LWIP error remapping */ 00976 static nsapi_error_t mbed_lwip_err_remap(err_t err) { 00977 switch (err) { 00978 case ERR_OK: 00979 case ERR_CLSD: 00980 return 0; 00981 case ERR_MEM: 00982 case ERR_BUF: 00983 return NSAPI_ERROR_NO_MEMORY ; 00984 case ERR_CONN: 00985 case ERR_RST: 00986 case ERR_ABRT: 00987 return NSAPI_ERROR_NO_CONNECTION ; 00988 case ERR_TIMEOUT: 00989 case ERR_RTE: 00990 case ERR_WOULDBLOCK: 00991 return NSAPI_ERROR_WOULD_BLOCK ; 00992 case ERR_VAL: 00993 case ERR_USE: 00994 case ERR_ARG: 00995 return NSAPI_ERROR_PARAMETER ; 00996 case ERR_INPROGRESS: 00997 return NSAPI_ERROR_IN_PROGRESS ; 00998 case ERR_ALREADY: 00999 return NSAPI_ERROR_ALREADY ; 01000 case ERR_ISCONN: 01001 return NSAPI_ERROR_IS_CONNECTED ; 01002 default: 01003 return NSAPI_ERROR_DEVICE_ERROR ; 01004 } 01005 } 01006 01007 /* LWIP network stack implementation */ 01008 static nsapi_error_t mbed_lwip_gethostbyname(nsapi_stack_t *stack, const char *host, nsapi_addr_t *addr, nsapi_version_t version) 01009 { 01010 ip_addr_t lwip_addr; 01011 01012 #if LWIP_IPV4 && LWIP_IPV6 01013 u8_t addr_type; 01014 if (version == NSAPI_UNSPEC ) { 01015 const ip_addr_t *ip_addr; 01016 ip_addr = mbed_lwip_get_ip_addr(true, &lwip_netif); 01017 // Prefer IPv6 01018 if (IP_IS_V6(ip_addr)) { 01019 // If IPv4 is available use it as backup 01020 if (mbed_lwip_get_ipv4_addr(&lwip_netif)) { 01021 addr_type = NETCONN_DNS_IPV6_IPV4; 01022 } else { 01023 addr_type = NETCONN_DNS_IPV6; 01024 } 01025 // Prefer IPv4 01026 } else { 01027 // If IPv6 is available use it as backup 01028 if (mbed_lwip_get_ipv6_addr(&lwip_netif)) { 01029 addr_type = NETCONN_DNS_IPV4_IPV6; 01030 } else { 01031 addr_type = NETCONN_DNS_IPV4; 01032 } 01033 } 01034 } else if (version == NSAPI_IPv4 ) { 01035 addr_type = NETCONN_DNS_IPV4; 01036 } else if (version == NSAPI_IPv6 ) { 01037 addr_type = NETCONN_DNS_IPV6; 01038 } else { 01039 return NSAPI_ERROR_DNS_FAILURE ; 01040 } 01041 err_t err = netconn_gethostbyname_addrtype(host, &lwip_addr, addr_type); 01042 #elif LWIP_IPV4 01043 if (version != NSAPI_IPv4 && version != NSAPI_UNSPEC ) { 01044 return NSAPI_ERROR_DNS_FAILURE ; 01045 } 01046 err_t err = netconn_gethostbyname(host, &lwip_addr); 01047 #elif LWIP_IPV6 01048 if (version != NSAPI_IPv6 && version != NSAPI_UNSPEC ) { 01049 return NSAPI_ERROR_DNS_FAILURE ; 01050 } 01051 err_t err = netconn_gethostbyname(host, &lwip_addr); 01052 #endif 01053 01054 if (err != ERR_OK) { 01055 return NSAPI_ERROR_DNS_FAILURE ; 01056 } 01057 01058 convert_lwip_addr_to_mbed(addr, &lwip_addr); 01059 01060 return 0; 01061 } 01062 01063 static nsapi_error_t mbed_lwip_add_dns_server(nsapi_stack_t *stack, nsapi_addr_t addr) 01064 { 01065 // Shift all dns servers down to give precedence to new server 01066 for (int i = DNS_MAX_SERVERS-1; i > 0; i--) { 01067 dns_setserver(i, dns_getserver(i-1)); 01068 } 01069 01070 ip_addr_t ip_addr; 01071 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { 01072 return NSAPI_ERROR_PARAMETER ; 01073 } 01074 01075 dns_setserver(0, &ip_addr); 01076 return 0; 01077 } 01078 01079 static nsapi_error_t mbed_lwip_socket_open(nsapi_stack_t *stack, nsapi_socket_t *handle, nsapi_protocol_t proto) 01080 { 01081 // check if network is connected 01082 if (lwip_connected == NSAPI_STATUS_DISCONNECTED ) { 01083 return NSAPI_ERROR_NO_CONNECTION ; 01084 } 01085 01086 // allocate a socket 01087 struct lwip_socket *s = mbed_lwip_arena_alloc(); 01088 if (!s) { 01089 return NSAPI_ERROR_NO_SOCKET ; 01090 } 01091 01092 enum netconn_type lwip_proto = proto == NSAPI_TCP ? NETCONN_TCP : NETCONN_UDP; 01093 01094 #if LWIP_IPV6 01095 // Enable IPv6 (or dual-stack) 01096 lwip_proto |= NETCONN_TYPE_IPV6; 01097 #endif 01098 01099 s->conn = netconn_new_with_callback(lwip_proto, mbed_lwip_socket_callback); 01100 01101 if (!s->conn) { 01102 mbed_lwip_arena_dealloc(s); 01103 return NSAPI_ERROR_NO_SOCKET ; 01104 } 01105 01106 netconn_set_recvtimeout(s->conn, 1); 01107 *(struct lwip_socket **)handle = s; 01108 return 0; 01109 } 01110 01111 static nsapi_error_t mbed_lwip_socket_close(nsapi_stack_t *stack, nsapi_socket_t handle) 01112 { 01113 struct lwip_socket *s = (struct lwip_socket *)handle; 01114 01115 netbuf_delete(s->buf); 01116 err_t err = netconn_delete(s->conn); 01117 mbed_lwip_arena_dealloc(s); 01118 return mbed_lwip_err_remap(err); 01119 } 01120 01121 static nsapi_error_t mbed_lwip_socket_bind(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port) 01122 { 01123 struct lwip_socket *s = (struct lwip_socket *)handle; 01124 ip_addr_t ip_addr; 01125 01126 if ( 01127 #if LWIP_TCP 01128 (NETCONNTYPE_GROUP(s->conn->type) == NETCONN_TCP && s->conn->pcb.tcp->local_port != 0) || 01129 #endif 01130 (NETCONNTYPE_GROUP(s->conn->type) == NETCONN_UDP && s->conn->pcb.udp->local_port != 0)) { 01131 return NSAPI_ERROR_PARAMETER ; 01132 } 01133 01134 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { 01135 return NSAPI_ERROR_PARAMETER ; 01136 } 01137 01138 if (!ip_addr_isany(&ip_addr) && !mbed_lwip_is_local_addr(&ip_addr)) { 01139 return NSAPI_ERROR_PARAMETER ; 01140 } 01141 01142 err_t err = netconn_bind(s->conn, &ip_addr, port); 01143 return mbed_lwip_err_remap(err); 01144 } 01145 01146 static nsapi_error_t mbed_lwip_socket_listen(nsapi_stack_t *stack, nsapi_socket_t handle, int backlog) 01147 { 01148 #if LWIP_TCP 01149 struct lwip_socket *s = (struct lwip_socket *)handle; 01150 01151 if (s->conn->pcb.tcp->local_port == 0) { 01152 return NSAPI_ERROR_PARAMETER ; 01153 } 01154 01155 err_t err = netconn_listen_with_backlog(s->conn, backlog); 01156 return mbed_lwip_err_remap(err); 01157 #else 01158 return NSAPI_ERROR_UNSUPPORTED ; 01159 #endif 01160 } 01161 01162 static nsapi_error_t mbed_lwip_socket_connect(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port) 01163 { 01164 struct lwip_socket *s = (struct lwip_socket *)handle; 01165 ip_addr_t ip_addr; 01166 01167 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { 01168 return NSAPI_ERROR_PARAMETER ; 01169 } 01170 01171 netconn_set_nonblocking(s->conn, false); 01172 err_t err = netconn_connect(s->conn, &ip_addr, port); 01173 netconn_set_nonblocking(s->conn, true); 01174 01175 return mbed_lwip_err_remap(err); 01176 } 01177 01178 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) 01179 { 01180 #if LWIP_TCP 01181 struct lwip_socket *s = (struct lwip_socket *)server; 01182 struct lwip_socket *ns = mbed_lwip_arena_alloc(); 01183 if (!ns) { 01184 return NSAPI_ERROR_NO_SOCKET ; 01185 } 01186 01187 if (s->conn->pcb.tcp->state != LISTEN) { 01188 return NSAPI_ERROR_PARAMETER ; 01189 } 01190 01191 err_t err = netconn_accept(s->conn, &ns->conn); 01192 if (err != ERR_OK) { 01193 mbed_lwip_arena_dealloc(ns); 01194 return mbed_lwip_err_remap(err); 01195 } 01196 01197 netconn_set_recvtimeout(ns->conn, 1); 01198 *(struct lwip_socket **)handle = ns; 01199 01200 ip_addr_t peer_addr; 01201 (void) netconn_peer(ns->conn, &peer_addr, port); 01202 convert_lwip_addr_to_mbed(addr, &peer_addr); 01203 01204 netconn_set_nonblocking(ns->conn, true); 01205 01206 return 0; 01207 #else 01208 return NSAPI_ERROR_UNSUPPORTED ; 01209 #endif 01210 } 01211 01212 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) 01213 { 01214 struct lwip_socket *s = (struct lwip_socket *)handle; 01215 size_t bytes_written = 0; 01216 01217 err_t err = netconn_write_partly(s->conn, data, size, NETCONN_COPY, &bytes_written); 01218 if (err != ERR_OK) { 01219 return mbed_lwip_err_remap(err); 01220 } 01221 01222 return (nsapi_size_or_error_t)bytes_written; 01223 } 01224 01225 static nsapi_size_or_error_t mbed_lwip_socket_recv(nsapi_stack_t *stack, nsapi_socket_t handle, void *data, nsapi_size_t size) 01226 { 01227 struct lwip_socket *s = (struct lwip_socket *)handle; 01228 01229 if (!s->buf) { 01230 err_t err = netconn_recv(s->conn, &s->buf); 01231 s->offset = 0; 01232 01233 if (err != ERR_OK) { 01234 return mbed_lwip_err_remap(err); 01235 } 01236 } 01237 01238 u16_t recv = netbuf_copy_partial(s->buf, data, (u16_t)size, s->offset); 01239 s->offset += recv; 01240 01241 if (s->offset >= netbuf_len(s->buf)) { 01242 netbuf_delete(s->buf); 01243 s->buf = 0; 01244 } 01245 01246 return recv; 01247 } 01248 01249 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) 01250 { 01251 struct lwip_socket *s = (struct lwip_socket *)handle; 01252 ip_addr_t ip_addr; 01253 01254 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) { 01255 return NSAPI_ERROR_PARAMETER ; 01256 } 01257 01258 struct netbuf *buf = netbuf_new(); 01259 err_t err = netbuf_ref(buf, data, (u16_t)size); 01260 if (err != ERR_OK) { 01261 netbuf_free(buf); 01262 return mbed_lwip_err_remap(err); 01263 } 01264 01265 err = netconn_sendto(s->conn, buf, &ip_addr, port); 01266 netbuf_delete(buf); 01267 if (err != ERR_OK) { 01268 return mbed_lwip_err_remap(err); 01269 } 01270 01271 return size; 01272 } 01273 01274 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) 01275 { 01276 struct lwip_socket *s = (struct lwip_socket *)handle; 01277 struct netbuf *buf; 01278 01279 err_t err = netconn_recv(s->conn, &buf); 01280 if (err != ERR_OK) { 01281 return mbed_lwip_err_remap(err); 01282 } 01283 01284 convert_lwip_addr_to_mbed(addr, netbuf_fromaddr(buf)); 01285 *port = netbuf_fromport(buf); 01286 01287 u16_t recv = netbuf_copy(buf, data, (u16_t)size); 01288 netbuf_delete(buf); 01289 01290 return recv; 01291 } 01292 01293 static int32_t find_multicast_member(const struct lwip_socket *s, const nsapi_ip_mreq_t *imr) { 01294 uint32_t count = 0; 01295 uint32_t index = 0; 01296 // Set upper limit on while loop, should break out when the membership pair is found 01297 while (count < s->multicast_memberships_count) { 01298 index = next_registered_multicast_member(s, index); 01299 01300 if (memcmp(&s->multicast_memberships[index].imr_multiaddr, &imr->imr_multiaddr, sizeof(nsapi_addr_t)) == 0 && 01301 memcmp(&s->multicast_memberships[index].imr_interface, &imr->imr_interface, sizeof(nsapi_addr_t)) == 0) { 01302 return index; 01303 } 01304 count++; 01305 index++; 01306 } 01307 01308 return -1; 01309 } 01310 01311 static nsapi_error_t mbed_lwip_setsockopt(nsapi_stack_t *stack, nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen) 01312 { 01313 struct lwip_socket *s = (struct lwip_socket *)handle; 01314 01315 switch (optname) { 01316 #if LWIP_TCP 01317 case NSAPI_KEEPALIVE : 01318 if (optlen != sizeof(int) || NETCONNTYPE_GROUP(s->conn->type) != NETCONN_TCP) { 01319 return NSAPI_ERROR_UNSUPPORTED ; 01320 } 01321 01322 s->conn->pcb.tcp->so_options |= SOF_KEEPALIVE; 01323 return 0; 01324 01325 case NSAPI_KEEPIDLE : 01326 if (optlen != sizeof(int) || NETCONNTYPE_GROUP(s->conn->type) != NETCONN_TCP) { 01327 return NSAPI_ERROR_UNSUPPORTED ; 01328 } 01329 01330 s->conn->pcb.tcp->keep_idle = *(int*)optval; 01331 return 0; 01332 01333 case NSAPI_KEEPINTVL : 01334 if (optlen != sizeof(int) || NETCONNTYPE_GROUP(s->conn->type) != NETCONN_TCP) { 01335 return NSAPI_ERROR_UNSUPPORTED ; 01336 } 01337 01338 s->conn->pcb.tcp->keep_intvl = *(int*)optval; 01339 return 0; 01340 #endif 01341 01342 case NSAPI_REUSEADDR : 01343 if (optlen != sizeof(int)) { 01344 return NSAPI_ERROR_UNSUPPORTED ; 01345 } 01346 01347 if (*(int *)optval) { 01348 ip_set_option(s->conn->pcb.ip, SOF_REUSEADDR); 01349 } else { 01350 ip_reset_option(s->conn->pcb.ip, SOF_REUSEADDR); 01351 } 01352 return 0; 01353 01354 case NSAPI_ADD_MEMBERSHIP : 01355 case NSAPI_DROP_MEMBERSHIP : { 01356 if (optlen != sizeof(nsapi_ip_mreq_t)) { 01357 return NSAPI_ERROR_PARAMETER ; 01358 } 01359 err_t igmp_err; 01360 const nsapi_ip_mreq_t *imr = optval; 01361 01362 /* Check interface address type matches group, or is unspecified */ 01363 if (imr->imr_interface.version != NSAPI_UNSPEC && imr->imr_interface.version != imr->imr_multiaddr.version) { 01364 return NSAPI_ERROR_PARAMETER ; 01365 } 01366 01367 ip_addr_t if_addr; 01368 ip_addr_t multi_addr; 01369 01370 /* Convert the group address */ 01371 if (!convert_mbed_addr_to_lwip(&multi_addr, &imr->imr_multiaddr)) { 01372 return NSAPI_ERROR_PARAMETER ; 01373 } 01374 01375 /* Convert the interface address, or make sure it's the correct sort of "any" */ 01376 if (imr->imr_interface.version != NSAPI_UNSPEC ) { 01377 if (!convert_mbed_addr_to_lwip(&if_addr, &imr->imr_interface)) { 01378 return NSAPI_ERROR_PARAMETER ; 01379 } 01380 } else { 01381 ip_addr_set_any(IP_IS_V6(&if_addr), &if_addr); 01382 } 01383 01384 igmp_err = ERR_USE; // Maps to NSAPI_ERROR_UNSUPPORTED 01385 int32_t member_pair_index = find_multicast_member(s, imr); 01386 01387 if (optname == NSAPI_ADD_MEMBERSHIP ) { 01388 if (!s->multicast_memberships) { 01389 // First multicast join on this socket, allocate space for membership tracking 01390 s->multicast_memberships = malloc(sizeof(nsapi_ip_mreq_t) * LWIP_SOCKET_MAX_MEMBERSHIPS); 01391 if (!s->multicast_memberships) { 01392 return NSAPI_ERROR_NO_MEMORY ; 01393 } 01394 } else if(s->multicast_memberships_count == LWIP_SOCKET_MAX_MEMBERSHIPS) { 01395 return NSAPI_ERROR_NO_MEMORY ; 01396 } 01397 01398 if (member_pair_index != -1) { 01399 return NSAPI_ERROR_ADDRESS_IN_USE ; 01400 } 01401 01402 member_pair_index = next_free_multicast_member(s, 0); 01403 01404 sys_prot_t prot = sys_arch_protect(); 01405 01406 #if LWIP_IPV4 01407 if (IP_IS_V4(&if_addr)) { 01408 igmp_err = igmp_joingroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr)); 01409 } 01410 #endif 01411 #if LWIP_IPV6 01412 if (IP_IS_V6(&if_addr)) { 01413 igmp_err = mld6_joingroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr)); 01414 } 01415 #endif 01416 01417 sys_arch_unprotect(prot); 01418 01419 if (igmp_err == ERR_OK) { 01420 set_multicast_member_registry_bit(s, member_pair_index); 01421 s->multicast_memberships[member_pair_index] = *imr; 01422 s->multicast_memberships_count++; 01423 } 01424 } else { 01425 if (member_pair_index == -1) { 01426 return NSAPI_ERROR_NO_ADDRESS ; 01427 } 01428 01429 clear_multicast_member_registry_bit(s, member_pair_index); 01430 s->multicast_memberships_count--; 01431 01432 sys_prot_t prot = sys_arch_protect(); 01433 01434 #if LWIP_IPV4 01435 if (IP_IS_V4(&if_addr)) { 01436 igmp_err = igmp_leavegroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr)); 01437 } 01438 #endif 01439 #if LWIP_IPV6 01440 if (IP_IS_V6(&if_addr)) { 01441 igmp_err = mld6_leavegroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr)); 01442 } 01443 #endif 01444 01445 sys_arch_unprotect(prot); 01446 } 01447 01448 return mbed_lwip_err_remap(igmp_err); 01449 } 01450 01451 default: 01452 return NSAPI_ERROR_UNSUPPORTED ; 01453 } 01454 } 01455 01456 static void mbed_lwip_socket_attach(nsapi_stack_t *stack, nsapi_socket_t handle, void (*callback)(void *), void *data) 01457 { 01458 struct lwip_socket *s = (struct lwip_socket *)handle; 01459 01460 s->cb = callback; 01461 s->data = data; 01462 } 01463 01464 /* LWIP network stack */ 01465 const nsapi_stack_api_t lwip_stack_api = { 01466 .gethostbyname = mbed_lwip_gethostbyname, 01467 .add_dns_server = mbed_lwip_add_dns_server, 01468 .socket_open = mbed_lwip_socket_open, 01469 .socket_close = mbed_lwip_socket_close, 01470 .socket_bind = mbed_lwip_socket_bind, 01471 .socket_listen = mbed_lwip_socket_listen, 01472 .socket_connect = mbed_lwip_socket_connect, 01473 .socket_accept = mbed_lwip_socket_accept, 01474 .socket_send = mbed_lwip_socket_send, 01475 .socket_recv = mbed_lwip_socket_recv, 01476 .socket_sendto = mbed_lwip_socket_sendto, 01477 .socket_recvfrom = mbed_lwip_socket_recvfrom, 01478 .setsockopt = mbed_lwip_setsockopt, 01479 .socket_attach = mbed_lwip_socket_attach, 01480 }; 01481 01482 nsapi_stack_t lwip_stack = { 01483 .stack_api = &lwip_stack_api, 01484 };
Generated on Tue Jul 12 2022 12:22:02 by
