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