PES4 / Mbed OS Queue_02
Committer:
demayer
Date:
Sat Apr 11 08:15:48 2020 +0000
Revision:
1:b36bbc1c6d27
Parent:
0:6bf0743ece18
IMU-library in .h und .cpp file aufgeteilt

Who changed what in which revision?

UserRevisionLine numberNew contents of line
demayer 0:6bf0743ece18 1 /* LWIP implementation of NetworkInterfaceAPI
demayer 0:6bf0743ece18 2 * Copyright (c) 2015 ARM Limited
demayer 0:6bf0743ece18 3 *
demayer 0:6bf0743ece18 4 * Licensed under the Apache License, Version 2.0 (the "License");
demayer 0:6bf0743ece18 5 * you may not use this file except in compliance with the License.
demayer 0:6bf0743ece18 6 * You may obtain a copy of the License at
demayer 0:6bf0743ece18 7 *
demayer 0:6bf0743ece18 8 * http://www.apache.org/licenses/LICENSE-2.0
demayer 0:6bf0743ece18 9 *
demayer 0:6bf0743ece18 10 * Unless required by applicable law or agreed to in writing, software
demayer 0:6bf0743ece18 11 * distributed under the License is distributed on an "AS IS" BASIS,
demayer 0:6bf0743ece18 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
demayer 0:6bf0743ece18 13 * See the License for the specific language governing permissions and
demayer 0:6bf0743ece18 14 * limitations under the License.
demayer 0:6bf0743ece18 15 */
demayer 0:6bf0743ece18 16
demayer 0:6bf0743ece18 17 #include "nsapi.h"
demayer 0:6bf0743ece18 18 #include "mbed_interface.h"
demayer 0:6bf0743ece18 19 #include "mbed_assert.h"
demayer 0:6bf0743ece18 20 #include <stdio.h>
demayer 0:6bf0743ece18 21 #include <stdbool.h>
demayer 0:6bf0743ece18 22 #include <string.h>
demayer 0:6bf0743ece18 23 #include "lwip_stack.h"
demayer 0:6bf0743ece18 24
demayer 0:6bf0743ece18 25 #include "eth_arch.h"
demayer 0:6bf0743ece18 26 #include "lwip/opt.h"
demayer 0:6bf0743ece18 27 #include "lwip/api.h"
demayer 0:6bf0743ece18 28 #include "lwip/inet.h"
demayer 0:6bf0743ece18 29 #include "lwip/netif.h"
demayer 0:6bf0743ece18 30 #include "lwip/dhcp.h"
demayer 0:6bf0743ece18 31 #include "lwip/tcpip.h"
demayer 0:6bf0743ece18 32 #include "lwip/tcp.h"
demayer 0:6bf0743ece18 33 #include "lwip/ip.h"
demayer 0:6bf0743ece18 34 #include "lwip/mld6.h"
demayer 0:6bf0743ece18 35 #include "lwip/igmp.h"
demayer 0:6bf0743ece18 36 #include "lwip/dns.h"
demayer 0:6bf0743ece18 37 #include "lwip/udp.h"
demayer 0:6bf0743ece18 38 #include "lwip_errno.h"
demayer 0:6bf0743ece18 39 #include "netif/lwip_ethernet.h"
demayer 0:6bf0743ece18 40 #include "emac_api.h"
demayer 0:6bf0743ece18 41 #include "ppp_lwip.h"
demayer 0:6bf0743ece18 42
demayer 0:6bf0743ece18 43 static nsapi_error_t mbed_lwip_err_remap(err_t err);
demayer 0:6bf0743ece18 44
demayer 0:6bf0743ece18 45 #if DEVICE_EMAC
demayer 0:6bf0743ece18 46 #define MBED_NETIF_INIT_FN emac_lwip_if_init
demayer 0:6bf0743ece18 47 #else
demayer 0:6bf0743ece18 48 #define MBED_NETIF_INIT_FN eth_arch_enetif_init
demayer 0:6bf0743ece18 49 #endif
demayer 0:6bf0743ece18 50
demayer 0:6bf0743ece18 51 #ifndef LWIP_SOCKET_MAX_MEMBERSHIPS
demayer 0:6bf0743ece18 52 #define LWIP_SOCKET_MAX_MEMBERSHIPS 4
demayer 0:6bf0743ece18 53 #endif
demayer 0:6bf0743ece18 54
demayer 0:6bf0743ece18 55 /* Static arena of sockets */
demayer 0:6bf0743ece18 56 static struct lwip_socket {
demayer 0:6bf0743ece18 57 bool in_use;
demayer 0:6bf0743ece18 58
demayer 0:6bf0743ece18 59 struct netconn *conn;
demayer 0:6bf0743ece18 60 struct netbuf *buf;
demayer 0:6bf0743ece18 61 u16_t offset;
demayer 0:6bf0743ece18 62
demayer 0:6bf0743ece18 63 void (*cb)(void *);
demayer 0:6bf0743ece18 64 void *data;
demayer 0:6bf0743ece18 65
demayer 0:6bf0743ece18 66 // Track multicast addresses subscribed to by this socket
demayer 0:6bf0743ece18 67 nsapi_ip_mreq_t *multicast_memberships;
demayer 0:6bf0743ece18 68 uint32_t multicast_memberships_count;
demayer 0:6bf0743ece18 69 uint32_t multicast_memberships_registry;
demayer 0:6bf0743ece18 70
demayer 0:6bf0743ece18 71 } lwip_arena[MEMP_NUM_NETCONN];
demayer 0:6bf0743ece18 72
demayer 0:6bf0743ece18 73 static bool lwip_inited = false;
demayer 0:6bf0743ece18 74 static bool lwip_connected = false;
demayer 0:6bf0743ece18 75 static bool netif_inited = false;
demayer 0:6bf0743ece18 76 static bool netif_is_ppp = false;
demayer 0:6bf0743ece18 77
demayer 0:6bf0743ece18 78 static nsapi_error_t mbed_lwip_setsockopt(nsapi_stack_t *stack, nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen);
demayer 0:6bf0743ece18 79
demayer 0:6bf0743ece18 80 static inline uint32_t next_registered_multicast_member(const struct lwip_socket *s, uint32_t index) {
demayer 0:6bf0743ece18 81 while (!(s->multicast_memberships_registry & (0x0001 << index))) { index++; }
demayer 0:6bf0743ece18 82 return index;
demayer 0:6bf0743ece18 83 }
demayer 0:6bf0743ece18 84
demayer 0:6bf0743ece18 85 static inline uint32_t next_free_multicast_member(const struct lwip_socket *s, uint32_t index) {
demayer 0:6bf0743ece18 86 while ((s->multicast_memberships_registry & (0x0001 << index))) { index++; }
demayer 0:6bf0743ece18 87 return index;
demayer 0:6bf0743ece18 88 }
demayer 0:6bf0743ece18 89
demayer 0:6bf0743ece18 90 static inline void set_multicast_member_registry_bit(struct lwip_socket *s, uint32_t index) {
demayer 0:6bf0743ece18 91 s->multicast_memberships_registry |= (0x0001 << index);
demayer 0:6bf0743ece18 92 }
demayer 0:6bf0743ece18 93
demayer 0:6bf0743ece18 94 static inline void clear_multicast_member_registry_bit(struct lwip_socket *s, uint32_t index) {
demayer 0:6bf0743ece18 95 s->multicast_memberships_registry &= ~(0x0001 << index);
demayer 0:6bf0743ece18 96 }
demayer 0:6bf0743ece18 97
demayer 0:6bf0743ece18 98 static struct lwip_socket *mbed_lwip_arena_alloc(void)
demayer 0:6bf0743ece18 99 {
demayer 0:6bf0743ece18 100 sys_prot_t prot = sys_arch_protect();
demayer 0:6bf0743ece18 101
demayer 0:6bf0743ece18 102 for (int i = 0; i < MEMP_NUM_NETCONN; i++) {
demayer 0:6bf0743ece18 103 if (!lwip_arena[i].in_use) {
demayer 0:6bf0743ece18 104 struct lwip_socket *s = &lwip_arena[i];
demayer 0:6bf0743ece18 105 memset(s, 0, sizeof *s);
demayer 0:6bf0743ece18 106 s->in_use = true;
demayer 0:6bf0743ece18 107 sys_arch_unprotect(prot);
demayer 0:6bf0743ece18 108 return s;
demayer 0:6bf0743ece18 109 }
demayer 0:6bf0743ece18 110 }
demayer 0:6bf0743ece18 111
demayer 0:6bf0743ece18 112 sys_arch_unprotect(prot);
demayer 0:6bf0743ece18 113 return 0;
demayer 0:6bf0743ece18 114 }
demayer 0:6bf0743ece18 115
demayer 0:6bf0743ece18 116 static void mbed_lwip_arena_dealloc(struct lwip_socket *s)
demayer 0:6bf0743ece18 117 {
demayer 0:6bf0743ece18 118 s->in_use = false;
demayer 0:6bf0743ece18 119
demayer 0:6bf0743ece18 120 while (s->multicast_memberships_count > 0) {
demayer 0:6bf0743ece18 121 uint32_t index = 0;
demayer 0:6bf0743ece18 122 index = next_registered_multicast_member(s, index);
demayer 0:6bf0743ece18 123
demayer 0:6bf0743ece18 124 mbed_lwip_setsockopt(NULL, s, NSAPI_SOCKET, NSAPI_DROP_MEMBERSHIP, &s->multicast_memberships[index],
demayer 0:6bf0743ece18 125 sizeof(s->multicast_memberships[index]));
demayer 0:6bf0743ece18 126 index++;
demayer 0:6bf0743ece18 127 }
demayer 0:6bf0743ece18 128
demayer 0:6bf0743ece18 129 free(s->multicast_memberships);
demayer 0:6bf0743ece18 130 s->multicast_memberships = NULL;
demayer 0:6bf0743ece18 131 }
demayer 0:6bf0743ece18 132
demayer 0:6bf0743ece18 133 static void mbed_lwip_socket_callback(struct netconn *nc, enum netconn_evt eh, u16_t len)
demayer 0:6bf0743ece18 134 {
demayer 0:6bf0743ece18 135 // Filter send minus events
demayer 0:6bf0743ece18 136 if (eh == NETCONN_EVT_SENDMINUS && nc->state == NETCONN_WRITE) {
demayer 0:6bf0743ece18 137 return;
demayer 0:6bf0743ece18 138 }
demayer 0:6bf0743ece18 139
demayer 0:6bf0743ece18 140 sys_prot_t prot = sys_arch_protect();
demayer 0:6bf0743ece18 141
demayer 0:6bf0743ece18 142 for (int i = 0; i < MEMP_NUM_NETCONN; i++) {
demayer 0:6bf0743ece18 143 if (lwip_arena[i].in_use
demayer 0:6bf0743ece18 144 && lwip_arena[i].conn == nc
demayer 0:6bf0743ece18 145 && lwip_arena[i].cb) {
demayer 0:6bf0743ece18 146 lwip_arena[i].cb(lwip_arena[i].data);
demayer 0:6bf0743ece18 147 }
demayer 0:6bf0743ece18 148 }
demayer 0:6bf0743ece18 149
demayer 0:6bf0743ece18 150 sys_arch_unprotect(prot);
demayer 0:6bf0743ece18 151 }
demayer 0:6bf0743ece18 152
demayer 0:6bf0743ece18 153
demayer 0:6bf0743ece18 154 /* TCP/IP and Network Interface Initialisation */
demayer 0:6bf0743ece18 155 static struct netif lwip_netif;
demayer 0:6bf0743ece18 156 #if LWIP_DHCP
demayer 0:6bf0743ece18 157 static bool lwip_dhcp = false;
demayer 0:6bf0743ece18 158 #endif
demayer 0:6bf0743ece18 159 static char lwip_mac_address[NSAPI_MAC_SIZE];
demayer 0:6bf0743ece18 160
demayer 0:6bf0743ece18 161 #if !LWIP_IPV4 || !LWIP_IPV6
demayer 0:6bf0743ece18 162 static bool all_zeros(const uint8_t *p, int len)
demayer 0:6bf0743ece18 163 {
demayer 0:6bf0743ece18 164 for (int i = 0; i < len; i++) {
demayer 0:6bf0743ece18 165 if (p[i]) {
demayer 0:6bf0743ece18 166 return false;
demayer 0:6bf0743ece18 167 }
demayer 0:6bf0743ece18 168 }
demayer 0:6bf0743ece18 169
demayer 0:6bf0743ece18 170 return true;
demayer 0:6bf0743ece18 171 }
demayer 0:6bf0743ece18 172 #endif
demayer 0:6bf0743ece18 173
demayer 0:6bf0743ece18 174 static bool convert_mbed_addr_to_lwip(ip_addr_t *out, const nsapi_addr_t *in)
demayer 0:6bf0743ece18 175 {
demayer 0:6bf0743ece18 176 #if LWIP_IPV6
demayer 0:6bf0743ece18 177 if (in->version == NSAPI_IPv6) {
demayer 0:6bf0743ece18 178 IP_SET_TYPE(out, IPADDR_TYPE_V6);
demayer 0:6bf0743ece18 179 MEMCPY(ip_2_ip6(out), in->bytes, sizeof(ip6_addr_t));
demayer 0:6bf0743ece18 180 return true;
demayer 0:6bf0743ece18 181 }
demayer 0:6bf0743ece18 182 #if !LWIP_IPV4
demayer 0:6bf0743ece18 183 /* For bind() and other purposes, need to accept "null" of other type */
demayer 0:6bf0743ece18 184 /* (People use IPv4 0.0.0.0 as a general null) */
demayer 0:6bf0743ece18 185 if (in->version == NSAPI_UNSPEC ||
demayer 0:6bf0743ece18 186 (in->version == NSAPI_IPv4 && all_zeros(in->bytes, 4))) {
demayer 0:6bf0743ece18 187 ip_addr_set_zero_ip6(out);
demayer 0:6bf0743ece18 188 return true;
demayer 0:6bf0743ece18 189 }
demayer 0:6bf0743ece18 190 #endif
demayer 0:6bf0743ece18 191 #endif
demayer 0:6bf0743ece18 192
demayer 0:6bf0743ece18 193 #if LWIP_IPV4
demayer 0:6bf0743ece18 194 if (in->version == NSAPI_IPv4) {
demayer 0:6bf0743ece18 195 IP_SET_TYPE(out, IPADDR_TYPE_V4);
demayer 0:6bf0743ece18 196 MEMCPY(ip_2_ip4(out), in->bytes, sizeof(ip4_addr_t));
demayer 0:6bf0743ece18 197 return true;
demayer 0:6bf0743ece18 198 }
demayer 0:6bf0743ece18 199 #if !LWIP_IPV6
demayer 0:6bf0743ece18 200 /* For symmetry with above, accept IPv6 :: as a general null */
demayer 0:6bf0743ece18 201 if (in->version == NSAPI_UNSPEC ||
demayer 0:6bf0743ece18 202 (in->version == NSAPI_IPv6 && all_zeros(in->bytes, 16))) {
demayer 0:6bf0743ece18 203 ip_addr_set_zero_ip4(out);
demayer 0:6bf0743ece18 204 return true;
demayer 0:6bf0743ece18 205 }
demayer 0:6bf0743ece18 206 #endif
demayer 0:6bf0743ece18 207 #endif
demayer 0:6bf0743ece18 208
demayer 0:6bf0743ece18 209 #if LWIP_IPV4 && LWIP_IPV6
demayer 0:6bf0743ece18 210 if (in->version == NSAPI_UNSPEC) {
demayer 0:6bf0743ece18 211 #if IP_VERSION_PREF == PREF_IPV4
demayer 0:6bf0743ece18 212 ip_addr_set_zero_ip4(out);
demayer 0:6bf0743ece18 213 #else
demayer 0:6bf0743ece18 214 ip_addr_set_zero_ip6(out);
demayer 0:6bf0743ece18 215 #endif
demayer 0:6bf0743ece18 216 return true;
demayer 0:6bf0743ece18 217 }
demayer 0:6bf0743ece18 218 #endif
demayer 0:6bf0743ece18 219
demayer 0:6bf0743ece18 220 return false;
demayer 0:6bf0743ece18 221 }
demayer 0:6bf0743ece18 222
demayer 0:6bf0743ece18 223 static bool convert_lwip_addr_to_mbed(nsapi_addr_t *out, const ip_addr_t *in)
demayer 0:6bf0743ece18 224 {
demayer 0:6bf0743ece18 225 #if LWIP_IPV6
demayer 0:6bf0743ece18 226 if (IP_IS_V6(in)) {
demayer 0:6bf0743ece18 227 out->version = NSAPI_IPv6;
demayer 0:6bf0743ece18 228 MEMCPY(out->bytes, ip_2_ip6(in), sizeof(ip6_addr_t));
demayer 0:6bf0743ece18 229 return true;
demayer 0:6bf0743ece18 230 }
demayer 0:6bf0743ece18 231 #endif
demayer 0:6bf0743ece18 232 #if LWIP_IPV4
demayer 0:6bf0743ece18 233 if (IP_IS_V4(in)) {
demayer 0:6bf0743ece18 234 out->version = NSAPI_IPv4;
demayer 0:6bf0743ece18 235 MEMCPY(out->bytes, ip_2_ip4(in), sizeof(ip4_addr_t));
demayer 0:6bf0743ece18 236 return true;
demayer 0:6bf0743ece18 237 }
demayer 0:6bf0743ece18 238 #endif
demayer 0:6bf0743ece18 239 #if LWIP_IPV6 && LWIP_IPV4
demayer 0:6bf0743ece18 240 return false;
demayer 0:6bf0743ece18 241 #endif
demayer 0:6bf0743ece18 242 }
demayer 0:6bf0743ece18 243
demayer 0:6bf0743ece18 244 #if LWIP_IPV4
demayer 0:6bf0743ece18 245 static const ip_addr_t *mbed_lwip_get_ipv4_addr(const struct netif *netif)
demayer 0:6bf0743ece18 246 {
demayer 0:6bf0743ece18 247 if (!netif_is_up(netif)) {
demayer 0:6bf0743ece18 248 return NULL;
demayer 0:6bf0743ece18 249 }
demayer 0:6bf0743ece18 250
demayer 0:6bf0743ece18 251 if (!ip4_addr_isany(netif_ip4_addr(netif))) {
demayer 0:6bf0743ece18 252 return netif_ip_addr4(netif);
demayer 0:6bf0743ece18 253 }
demayer 0:6bf0743ece18 254
demayer 0:6bf0743ece18 255 return NULL;
demayer 0:6bf0743ece18 256 }
demayer 0:6bf0743ece18 257 #endif
demayer 0:6bf0743ece18 258
demayer 0:6bf0743ece18 259 #if LWIP_IPV6
demayer 0:6bf0743ece18 260 static const ip_addr_t *mbed_lwip_get_ipv6_addr(const struct netif *netif)
demayer 0:6bf0743ece18 261 {
demayer 0:6bf0743ece18 262
demayer 0:6bf0743ece18 263 if (!netif_is_up(netif)) {
demayer 0:6bf0743ece18 264 return NULL;
demayer 0:6bf0743ece18 265 }
demayer 0:6bf0743ece18 266
demayer 0:6bf0743ece18 267 for (int i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
demayer 0:6bf0743ece18 268 if (ip6_addr_isvalid(netif_ip6_addr_state(netif, i)) &&
demayer 0:6bf0743ece18 269 !ip6_addr_islinklocal(netif_ip6_addr(netif, i))) {
demayer 0:6bf0743ece18 270 return netif_ip_addr6(netif, i);
demayer 0:6bf0743ece18 271 }
demayer 0:6bf0743ece18 272 }
demayer 0:6bf0743ece18 273
demayer 0:6bf0743ece18 274 return NULL;
demayer 0:6bf0743ece18 275 }
demayer 0:6bf0743ece18 276 #endif
demayer 0:6bf0743ece18 277
demayer 0:6bf0743ece18 278 const ip_addr_t *mbed_lwip_get_ip_addr(bool any_addr, const struct netif *netif)
demayer 0:6bf0743ece18 279 {
demayer 0:6bf0743ece18 280 const ip_addr_t *pref_ip_addr = 0;
demayer 0:6bf0743ece18 281 const ip_addr_t *npref_ip_addr = 0;
demayer 0:6bf0743ece18 282
demayer 0:6bf0743ece18 283 #if LWIP_IPV4 && LWIP_IPV6
demayer 0:6bf0743ece18 284 #if IP_VERSION_PREF == PREF_IPV4
demayer 0:6bf0743ece18 285 pref_ip_addr = mbed_lwip_get_ipv4_addr(netif);
demayer 0:6bf0743ece18 286 npref_ip_addr = mbed_lwip_get_ipv6_addr(netif);
demayer 0:6bf0743ece18 287 #else
demayer 0:6bf0743ece18 288 pref_ip_addr = mbed_lwip_get_ipv6_addr(netif);
demayer 0:6bf0743ece18 289 npref_ip_addr = mbed_lwip_get_ipv4_addr(netif);
demayer 0:6bf0743ece18 290 #endif
demayer 0:6bf0743ece18 291 #elif LWIP_IPV6
demayer 0:6bf0743ece18 292 pref_ip_addr = mbed_lwip_get_ipv6_addr(netif);
demayer 0:6bf0743ece18 293 #elif LWIP_IPV4
demayer 0:6bf0743ece18 294 pref_ip_addr = mbed_lwip_get_ipv4_addr(netif);
demayer 0:6bf0743ece18 295 #endif
demayer 0:6bf0743ece18 296
demayer 0:6bf0743ece18 297 if (pref_ip_addr) {
demayer 0:6bf0743ece18 298 return pref_ip_addr;
demayer 0:6bf0743ece18 299 } else if (npref_ip_addr && any_addr) {
demayer 0:6bf0743ece18 300 return npref_ip_addr;
demayer 0:6bf0743ece18 301 }
demayer 0:6bf0743ece18 302
demayer 0:6bf0743ece18 303 return NULL;
demayer 0:6bf0743ece18 304 }
demayer 0:6bf0743ece18 305
demayer 0:6bf0743ece18 306 static void add_dns_addr_to_dns_list_index(const u8_t addr_type, const u8_t index)
demayer 0:6bf0743ece18 307 {
demayer 0:6bf0743ece18 308 #if LWIP_IPV6
demayer 0:6bf0743ece18 309 if (addr_type == IPADDR_TYPE_V6) {
demayer 0:6bf0743ece18 310 /* 2001:4860:4860::8888 google */
demayer 0:6bf0743ece18 311 ip_addr_t ipv6_dns_addr = IPADDR6_INIT(
demayer 0:6bf0743ece18 312 PP_HTONL(0x20014860UL),
demayer 0:6bf0743ece18 313 PP_HTONL(0x48600000UL),
demayer 0:6bf0743ece18 314 PP_HTONL(0x00000000UL),
demayer 0:6bf0743ece18 315 PP_HTONL(0x00008888UL));
demayer 0:6bf0743ece18 316 dns_setserver(index, &ipv6_dns_addr);
demayer 0:6bf0743ece18 317 }
demayer 0:6bf0743ece18 318 #endif
demayer 0:6bf0743ece18 319 #if LWIP_IPV4
demayer 0:6bf0743ece18 320 if (addr_type == IPADDR_TYPE_V4) {
demayer 0:6bf0743ece18 321 /* 8.8.8.8 google */
demayer 0:6bf0743ece18 322 ip_addr_t ipv4_dns_addr = IPADDR4_INIT(0x08080808);
demayer 0:6bf0743ece18 323 dns_setserver(index, &ipv4_dns_addr);
demayer 0:6bf0743ece18 324 }
demayer 0:6bf0743ece18 325 #endif
demayer 0:6bf0743ece18 326 }
demayer 0:6bf0743ece18 327
demayer 0:6bf0743ece18 328 static int get_ip_addr_type(const ip_addr_t *ip_addr)
demayer 0:6bf0743ece18 329 {
demayer 0:6bf0743ece18 330 #if LWIP_IPV6
demayer 0:6bf0743ece18 331 if (IP_IS_V6(ip_addr)) {
demayer 0:6bf0743ece18 332 return IPADDR_TYPE_V6;
demayer 0:6bf0743ece18 333 }
demayer 0:6bf0743ece18 334 #endif
demayer 0:6bf0743ece18 335 #if LWIP_IPV4
demayer 0:6bf0743ece18 336 if (IP_IS_V4(ip_addr)) {
demayer 0:6bf0743ece18 337 return IPADDR_TYPE_V4;
demayer 0:6bf0743ece18 338 }
demayer 0:6bf0743ece18 339 #endif
demayer 0:6bf0743ece18 340 #if LWIP_IPV6 && LWIP_IPV4
demayer 0:6bf0743ece18 341 return IPADDR_TYPE_ANY;
demayer 0:6bf0743ece18 342 #endif
demayer 0:6bf0743ece18 343 }
demayer 0:6bf0743ece18 344
demayer 0:6bf0743ece18 345 void add_dns_addr(struct netif *lwip_netif)
demayer 0:6bf0743ece18 346 {
demayer 0:6bf0743ece18 347 // Check for existing dns address
demayer 0:6bf0743ece18 348 for (char numdns = 0; numdns < DNS_MAX_SERVERS; numdns++) {
demayer 0:6bf0743ece18 349 const ip_addr_t *dns_ip_addr = dns_getserver(numdns);
demayer 0:6bf0743ece18 350 if (!ip_addr_isany(dns_ip_addr)) {
demayer 0:6bf0743ece18 351 return;
demayer 0:6bf0743ece18 352 }
demayer 0:6bf0743ece18 353 }
demayer 0:6bf0743ece18 354
demayer 0:6bf0743ece18 355 // Get preferred ip version
demayer 0:6bf0743ece18 356 const ip_addr_t *ip_addr = mbed_lwip_get_ip_addr(false, lwip_netif);
demayer 0:6bf0743ece18 357 u8_t addr_type = IPADDR_TYPE_ANY;
demayer 0:6bf0743ece18 358
demayer 0:6bf0743ece18 359 // Add preferred ip version dns address to index 0
demayer 0:6bf0743ece18 360 if (ip_addr) {
demayer 0:6bf0743ece18 361 addr_type = get_ip_addr_type(ip_addr);
demayer 0:6bf0743ece18 362 add_dns_addr_to_dns_list_index(addr_type, 0);
demayer 0:6bf0743ece18 363 }
demayer 0:6bf0743ece18 364
demayer 0:6bf0743ece18 365 #if LWIP_IPV4 && LWIP_IPV6
demayer 0:6bf0743ece18 366 if (!ip_addr) {
demayer 0:6bf0743ece18 367 // Get address for any ip version
demayer 0:6bf0743ece18 368 ip_addr = mbed_lwip_get_ip_addr(true, lwip_netif);
demayer 0:6bf0743ece18 369 if (!ip_addr) {
demayer 0:6bf0743ece18 370 return;
demayer 0:6bf0743ece18 371 }
demayer 0:6bf0743ece18 372 addr_type = get_ip_addr_type(ip_addr);
demayer 0:6bf0743ece18 373 // Add the dns address to index 0
demayer 0:6bf0743ece18 374 add_dns_addr_to_dns_list_index(addr_type, 0);
demayer 0:6bf0743ece18 375 }
demayer 0:6bf0743ece18 376
demayer 0:6bf0743ece18 377 if (addr_type == IPADDR_TYPE_V4) {
demayer 0:6bf0743ece18 378 // If ipv4 is preferred and ipv6 is available add ipv6 dns address to index 1
demayer 0:6bf0743ece18 379 ip_addr = mbed_lwip_get_ipv6_addr(lwip_netif);
demayer 0:6bf0743ece18 380 } else if (addr_type == IPADDR_TYPE_V6) {
demayer 0:6bf0743ece18 381 // If ipv6 is preferred and ipv4 is available add ipv4 dns address to index 1
demayer 0:6bf0743ece18 382 ip_addr = mbed_lwip_get_ipv4_addr(lwip_netif);
demayer 0:6bf0743ece18 383 } else {
demayer 0:6bf0743ece18 384 ip_addr = NULL;
demayer 0:6bf0743ece18 385 }
demayer 0:6bf0743ece18 386
demayer 0:6bf0743ece18 387 if (ip_addr) {
demayer 0:6bf0743ece18 388 addr_type = get_ip_addr_type(ip_addr);
demayer 0:6bf0743ece18 389 add_dns_addr_to_dns_list_index(addr_type, 1);
demayer 0:6bf0743ece18 390 }
demayer 0:6bf0743ece18 391 #endif
demayer 0:6bf0743ece18 392 }
demayer 0:6bf0743ece18 393
demayer 0:6bf0743ece18 394 static sys_sem_t lwip_tcpip_inited;
demayer 0:6bf0743ece18 395 static void mbed_lwip_tcpip_init_irq(void *eh)
demayer 0:6bf0743ece18 396 {
demayer 0:6bf0743ece18 397 sys_sem_signal(&lwip_tcpip_inited);
demayer 0:6bf0743ece18 398 }
demayer 0:6bf0743ece18 399
demayer 0:6bf0743ece18 400 static sys_sem_t lwip_netif_linked;
demayer 0:6bf0743ece18 401 static sys_sem_t lwip_netif_unlinked;
demayer 0:6bf0743ece18 402 static void mbed_lwip_netif_link_irq(struct netif *lwip_netif)
demayer 0:6bf0743ece18 403 {
demayer 0:6bf0743ece18 404 if (netif_is_link_up(lwip_netif)) {
demayer 0:6bf0743ece18 405 sys_sem_signal(&lwip_netif_linked);
demayer 0:6bf0743ece18 406 } else {
demayer 0:6bf0743ece18 407 sys_sem_signal(&lwip_netif_unlinked);
demayer 0:6bf0743ece18 408 }
demayer 0:6bf0743ece18 409 }
demayer 0:6bf0743ece18 410
demayer 0:6bf0743ece18 411 static char lwip_has_addr_state = 0;
demayer 0:6bf0743ece18 412
demayer 0:6bf0743ece18 413 #define HAS_ANY_ADDR 1
demayer 0:6bf0743ece18 414 static sys_sem_t lwip_netif_has_any_addr;
demayer 0:6bf0743ece18 415 #if PREF_ADDR_TIMEOUT
demayer 0:6bf0743ece18 416 #define HAS_PREF_ADDR 2
demayer 0:6bf0743ece18 417 static sys_sem_t lwip_netif_has_pref_addr;
demayer 0:6bf0743ece18 418 #endif
demayer 0:6bf0743ece18 419 #if BOTH_ADDR_TIMEOUT
demayer 0:6bf0743ece18 420 #define HAS_BOTH_ADDR 4
demayer 0:6bf0743ece18 421 static sys_sem_t lwip_netif_has_both_addr;
demayer 0:6bf0743ece18 422 #endif
demayer 0:6bf0743ece18 423
demayer 0:6bf0743ece18 424 static void mbed_lwip_netif_status_irq(struct netif *lwip_netif)
demayer 0:6bf0743ece18 425 {
demayer 0:6bf0743ece18 426 if (netif_is_up(lwip_netif)) {
demayer 0:6bf0743ece18 427 if (!(lwip_has_addr_state & HAS_ANY_ADDR) && mbed_lwip_get_ip_addr(true, lwip_netif)) {
demayer 0:6bf0743ece18 428 sys_sem_signal(&lwip_netif_has_any_addr);
demayer 0:6bf0743ece18 429 lwip_has_addr_state |= HAS_ANY_ADDR;
demayer 0:6bf0743ece18 430 }
demayer 0:6bf0743ece18 431 #if PREF_ADDR_TIMEOUT
demayer 0:6bf0743ece18 432 if (!(lwip_has_addr_state & HAS_PREF_ADDR) && mbed_lwip_get_ip_addr(false, lwip_netif)) {
demayer 0:6bf0743ece18 433 sys_sem_signal(&lwip_netif_has_pref_addr);
demayer 0:6bf0743ece18 434 lwip_has_addr_state |= HAS_PREF_ADDR;
demayer 0:6bf0743ece18 435 }
demayer 0:6bf0743ece18 436 #endif
demayer 0:6bf0743ece18 437 #if BOTH_ADDR_TIMEOUT
demayer 0:6bf0743ece18 438 if (!(lwip_has_addr_state & HAS_BOTH_ADDR) && mbed_lwip_get_ipv4_addr(lwip_netif) && mbed_lwip_get_ipv6_addr(lwip_netif)) {
demayer 0:6bf0743ece18 439 sys_sem_signal(&lwip_netif_has_both_addr);
demayer 0:6bf0743ece18 440 lwip_has_addr_state |= HAS_BOTH_ADDR;
demayer 0:6bf0743ece18 441 }
demayer 0:6bf0743ece18 442 #endif
demayer 0:6bf0743ece18 443 }
demayer 0:6bf0743ece18 444 }
demayer 0:6bf0743ece18 445
demayer 0:6bf0743ece18 446 #if LWIP_ETHERNET
demayer 0:6bf0743ece18 447 static void mbed_lwip_set_mac_address(struct netif *netif)
demayer 0:6bf0743ece18 448 {
demayer 0:6bf0743ece18 449 #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
demayer 0:6bf0743ece18 450 netif->hwaddr[0] = MBED_MAC_ADDR_0;
demayer 0:6bf0743ece18 451 netif->hwaddr[1] = MBED_MAC_ADDR_1;
demayer 0:6bf0743ece18 452 netif->hwaddr[2] = MBED_MAC_ADDR_2;
demayer 0:6bf0743ece18 453 netif->hwaddr[3] = MBED_MAC_ADDR_3;
demayer 0:6bf0743ece18 454 netif->hwaddr[4] = MBED_MAC_ADDR_4;
demayer 0:6bf0743ece18 455 netif->hwaddr[5] = MBED_MAC_ADDR_5;
demayer 0:6bf0743ece18 456 #else
demayer 0:6bf0743ece18 457 mbed_mac_address((char *)netif->hwaddr);
demayer 0:6bf0743ece18 458 #endif
demayer 0:6bf0743ece18 459
demayer 0:6bf0743ece18 460 netif->hwaddr_len = ETH_HWADDR_LEN;
demayer 0:6bf0743ece18 461
demayer 0:6bf0743ece18 462 /* Use mac address as additional seed to random number generator */
demayer 0:6bf0743ece18 463 uint64_t seed = netif->hwaddr[0];
demayer 0:6bf0743ece18 464 for (uint8_t i = 1; i < 8; i++) {
demayer 0:6bf0743ece18 465 seed <<= 8;
demayer 0:6bf0743ece18 466 seed |= netif->hwaddr[i % 6];
demayer 0:6bf0743ece18 467 }
demayer 0:6bf0743ece18 468 lwip_add_random_seed(seed);
demayer 0:6bf0743ece18 469 }
demayer 0:6bf0743ece18 470
demayer 0:6bf0743ece18 471 static void mbed_lwip_record_mac_address(const struct netif *netif)
demayer 0:6bf0743ece18 472 {
demayer 0:6bf0743ece18 473 const u8_t *mac = netif->hwaddr;
demayer 0:6bf0743ece18 474 snprintf(lwip_mac_address, NSAPI_MAC_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x",
demayer 0:6bf0743ece18 475 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
demayer 0:6bf0743ece18 476 }
demayer 0:6bf0743ece18 477 #endif // LWIP_ETHERNET
demayer 0:6bf0743ece18 478
demayer 0:6bf0743ece18 479 /* LWIP interface implementation */
demayer 0:6bf0743ece18 480 const char *mbed_lwip_get_mac_address(void)
demayer 0:6bf0743ece18 481 {
demayer 0:6bf0743ece18 482 return lwip_mac_address[0] ? lwip_mac_address : NULL;
demayer 0:6bf0743ece18 483 }
demayer 0:6bf0743ece18 484
demayer 0:6bf0743ece18 485 char *mbed_lwip_get_ip_address(char *buf, nsapi_size_t buflen)
demayer 0:6bf0743ece18 486 {
demayer 0:6bf0743ece18 487 const ip_addr_t *addr = mbed_lwip_get_ip_addr(true, &lwip_netif);
demayer 0:6bf0743ece18 488 if (!addr) {
demayer 0:6bf0743ece18 489 return NULL;
demayer 0:6bf0743ece18 490 }
demayer 0:6bf0743ece18 491 #if LWIP_IPV6
demayer 0:6bf0743ece18 492 if (IP_IS_V6(addr)) {
demayer 0:6bf0743ece18 493 return ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen);
demayer 0:6bf0743ece18 494 }
demayer 0:6bf0743ece18 495 #endif
demayer 0:6bf0743ece18 496 #if LWIP_IPV4
demayer 0:6bf0743ece18 497 if (IP_IS_V4(addr)) {
demayer 0:6bf0743ece18 498 return ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen);
demayer 0:6bf0743ece18 499 }
demayer 0:6bf0743ece18 500 #endif
demayer 0:6bf0743ece18 501 #if LWIP_IPV6 && LWIP_IPV4
demayer 0:6bf0743ece18 502 return NULL;
demayer 0:6bf0743ece18 503 #endif
demayer 0:6bf0743ece18 504 }
demayer 0:6bf0743ece18 505
demayer 0:6bf0743ece18 506 char *mbed_lwip_get_netmask(char *buf, nsapi_size_t buflen)
demayer 0:6bf0743ece18 507 {
demayer 0:6bf0743ece18 508 #if LWIP_IPV4
demayer 0:6bf0743ece18 509 const ip4_addr_t *addr = netif_ip4_netmask(&lwip_netif);
demayer 0:6bf0743ece18 510 if (!ip4_addr_isany(addr)) {
demayer 0:6bf0743ece18 511 return ip4addr_ntoa_r(addr, buf, buflen);
demayer 0:6bf0743ece18 512 } else {
demayer 0:6bf0743ece18 513 return NULL;
demayer 0:6bf0743ece18 514 }
demayer 0:6bf0743ece18 515 #else
demayer 0:6bf0743ece18 516 return NULL;
demayer 0:6bf0743ece18 517 #endif
demayer 0:6bf0743ece18 518 }
demayer 0:6bf0743ece18 519
demayer 0:6bf0743ece18 520 char *mbed_lwip_get_gateway(char *buf, nsapi_size_t buflen)
demayer 0:6bf0743ece18 521 {
demayer 0:6bf0743ece18 522 #if LWIP_IPV4
demayer 0:6bf0743ece18 523 const ip4_addr_t *addr = netif_ip4_gw(&lwip_netif);
demayer 0:6bf0743ece18 524 if (!ip4_addr_isany(addr)) {
demayer 0:6bf0743ece18 525 return ip4addr_ntoa_r(addr, buf, buflen);
demayer 0:6bf0743ece18 526 } else {
demayer 0:6bf0743ece18 527 return NULL;
demayer 0:6bf0743ece18 528 }
demayer 0:6bf0743ece18 529 #else
demayer 0:6bf0743ece18 530 return NULL;
demayer 0:6bf0743ece18 531 #endif
demayer 0:6bf0743ece18 532 }
demayer 0:6bf0743ece18 533
demayer 0:6bf0743ece18 534 static void mbed_lwip_core_init(void)
demayer 0:6bf0743ece18 535 {
demayer 0:6bf0743ece18 536
demayer 0:6bf0743ece18 537 // Check if we've already brought up lwip
demayer 0:6bf0743ece18 538 if (!lwip_inited) {
demayer 0:6bf0743ece18 539 // Seed lwip random
demayer 0:6bf0743ece18 540 lwip_seed_random();
demayer 0:6bf0743ece18 541
demayer 0:6bf0743ece18 542 // Initialise TCP sequence number
demayer 0:6bf0743ece18 543 uint32_t tcp_isn_secret[4];
demayer 0:6bf0743ece18 544 for (int i = 0; i < 4; i++) {
demayer 0:6bf0743ece18 545 tcp_isn_secret[i] = LWIP_RAND();
demayer 0:6bf0743ece18 546 }
demayer 0:6bf0743ece18 547 lwip_init_tcp_isn(0, (u8_t *) &tcp_isn_secret);
demayer 0:6bf0743ece18 548
demayer 0:6bf0743ece18 549 sys_sem_new(&lwip_tcpip_inited, 0);
demayer 0:6bf0743ece18 550 sys_sem_new(&lwip_netif_linked, 0);
demayer 0:6bf0743ece18 551 sys_sem_new(&lwip_netif_unlinked, 0);
demayer 0:6bf0743ece18 552 sys_sem_new(&lwip_netif_has_any_addr, 0);
demayer 0:6bf0743ece18 553 #if PREF_ADDR_TIMEOUT
demayer 0:6bf0743ece18 554 sys_sem_new(&lwip_netif_has_pref_addr, 0);
demayer 0:6bf0743ece18 555 #endif
demayer 0:6bf0743ece18 556 #if BOTH_ADDR_TIMEOUT
demayer 0:6bf0743ece18 557 sys_sem_new(&lwip_netif_has_both_addr, 0);
demayer 0:6bf0743ece18 558 #endif
demayer 0:6bf0743ece18 559 tcpip_init(mbed_lwip_tcpip_init_irq, NULL);
demayer 0:6bf0743ece18 560 sys_arch_sem_wait(&lwip_tcpip_inited, 0);
demayer 0:6bf0743ece18 561
demayer 0:6bf0743ece18 562 lwip_inited = true;
demayer 0:6bf0743ece18 563 }
demayer 0:6bf0743ece18 564 }
demayer 0:6bf0743ece18 565
demayer 0:6bf0743ece18 566 nsapi_error_t mbed_lwip_emac_init(emac_interface_t *emac)
demayer 0:6bf0743ece18 567 {
demayer 0:6bf0743ece18 568 #if LWIP_ETHERNET
demayer 0:6bf0743ece18 569 // Choose a MAC address - driver can override
demayer 0:6bf0743ece18 570 mbed_lwip_set_mac_address(&lwip_netif);
demayer 0:6bf0743ece18 571
demayer 0:6bf0743ece18 572 // Set up network
demayer 0:6bf0743ece18 573 if (!netif_add(&lwip_netif,
demayer 0:6bf0743ece18 574 #if LWIP_IPV4
demayer 0:6bf0743ece18 575 0, 0, 0,
demayer 0:6bf0743ece18 576 #endif
demayer 0:6bf0743ece18 577 emac, MBED_NETIF_INIT_FN, tcpip_input)) {
demayer 0:6bf0743ece18 578 return NSAPI_ERROR_DEVICE_ERROR;
demayer 0:6bf0743ece18 579 }
demayer 0:6bf0743ece18 580
demayer 0:6bf0743ece18 581 // Note the MAC address actually in use
demayer 0:6bf0743ece18 582 mbed_lwip_record_mac_address(&lwip_netif);
demayer 0:6bf0743ece18 583
demayer 0:6bf0743ece18 584 #if !DEVICE_EMAC
demayer 0:6bf0743ece18 585 eth_arch_enable_interrupts();
demayer 0:6bf0743ece18 586 #endif
demayer 0:6bf0743ece18 587
demayer 0:6bf0743ece18 588 return NSAPI_ERROR_OK;
demayer 0:6bf0743ece18 589 #else
demayer 0:6bf0743ece18 590 return NSAPI_ERROR_UNSUPPORTED;
demayer 0:6bf0743ece18 591 #endif //LWIP_ETHERNET
demayer 0:6bf0743ece18 592 }
demayer 0:6bf0743ece18 593
demayer 0:6bf0743ece18 594 // Backwards compatibility with people using DEVICE_EMAC
demayer 0:6bf0743ece18 595 nsapi_error_t mbed_lwip_init(emac_interface_t *emac)
demayer 0:6bf0743ece18 596 {
demayer 0:6bf0743ece18 597 nsapi_error_t ret;
demayer 0:6bf0743ece18 598 mbed_lwip_core_init();
demayer 0:6bf0743ece18 599 ret = mbed_lwip_emac_init(emac);
demayer 0:6bf0743ece18 600 if (ret == NSAPI_ERROR_OK) {
demayer 0:6bf0743ece18 601 netif_inited = true;
demayer 0:6bf0743ece18 602 }
demayer 0:6bf0743ece18 603 return ret;
demayer 0:6bf0743ece18 604 }
demayer 0:6bf0743ece18 605
demayer 0:6bf0743ece18 606 // Backwards compatibility with people using DEVICE_EMAC
demayer 0:6bf0743ece18 607 nsapi_error_t mbed_lwip_bringup(bool dhcp, const char *ip, const char *netmask, const char *gw)
demayer 0:6bf0743ece18 608 {
demayer 0:6bf0743ece18 609 return mbed_lwip_bringup_2(dhcp, false, ip, netmask, gw, DEFAULT_STACK);
demayer 0:6bf0743ece18 610 }
demayer 0:6bf0743ece18 611
demayer 0:6bf0743ece18 612 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)
demayer 0:6bf0743ece18 613 {
demayer 0:6bf0743ece18 614 // Check if we've already connected
demayer 0:6bf0743ece18 615 if (lwip_connected) {
demayer 0:6bf0743ece18 616 return NSAPI_ERROR_PARAMETER;
demayer 0:6bf0743ece18 617 }
demayer 0:6bf0743ece18 618
demayer 0:6bf0743ece18 619 mbed_lwip_core_init();
demayer 0:6bf0743ece18 620
demayer 0:6bf0743ece18 621 nsapi_error_t ret;
demayer 0:6bf0743ece18 622 if (netif_inited) {
demayer 0:6bf0743ece18 623 /* Can't cope with changing mode */
demayer 0:6bf0743ece18 624 if (netif_is_ppp == ppp) {
demayer 0:6bf0743ece18 625 ret = NSAPI_ERROR_OK;
demayer 0:6bf0743ece18 626 } else {
demayer 0:6bf0743ece18 627 ret = NSAPI_ERROR_PARAMETER;
demayer 0:6bf0743ece18 628 }
demayer 0:6bf0743ece18 629 } else {
demayer 0:6bf0743ece18 630 if (ppp) {
demayer 0:6bf0743ece18 631 ret = ppp_lwip_if_init(&lwip_netif, stack);
demayer 0:6bf0743ece18 632 } else {
demayer 0:6bf0743ece18 633 ret = mbed_lwip_emac_init(NULL);
demayer 0:6bf0743ece18 634 }
demayer 0:6bf0743ece18 635 }
demayer 0:6bf0743ece18 636
demayer 0:6bf0743ece18 637 if (ret != NSAPI_ERROR_OK) {
demayer 0:6bf0743ece18 638 return ret;
demayer 0:6bf0743ece18 639 }
demayer 0:6bf0743ece18 640
demayer 0:6bf0743ece18 641 netif_inited = true;
demayer 0:6bf0743ece18 642 if (ppp) {
demayer 0:6bf0743ece18 643 netif_is_ppp = ppp;
demayer 0:6bf0743ece18 644 }
demayer 0:6bf0743ece18 645
demayer 0:6bf0743ece18 646 netif_set_default(&lwip_netif);
demayer 0:6bf0743ece18 647 netif_set_link_callback(&lwip_netif, mbed_lwip_netif_link_irq);
demayer 0:6bf0743ece18 648 netif_set_status_callback(&lwip_netif, mbed_lwip_netif_status_irq);
demayer 0:6bf0743ece18 649
demayer 0:6bf0743ece18 650 #if LWIP_IPV6
demayer 0:6bf0743ece18 651 if (stack != IPV4_STACK) {
demayer 0:6bf0743ece18 652 if (lwip_netif.hwaddr_len == ETH_HWADDR_LEN) {
demayer 0:6bf0743ece18 653 netif_create_ip6_linklocal_address(&lwip_netif, 1/*from MAC*/);
demayer 0:6bf0743ece18 654 }
demayer 0:6bf0743ece18 655
demayer 0:6bf0743ece18 656 #if LWIP_IPV6_MLD
demayer 0:6bf0743ece18 657 /*
demayer 0:6bf0743ece18 658 * For hardware/netifs that implement MAC filtering.
demayer 0:6bf0743ece18 659 * All-nodes link-local is handled by default, so we must let the hardware know
demayer 0:6bf0743ece18 660 * to allow multicast packets in.
demayer 0:6bf0743ece18 661 * Should set mld_mac_filter previously. */
demayer 0:6bf0743ece18 662 if (lwip_netif.mld_mac_filter != NULL) {
demayer 0:6bf0743ece18 663 ip6_addr_t ip6_allnodes_ll;
demayer 0:6bf0743ece18 664 ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
demayer 0:6bf0743ece18 665 lwip_netif.mld_mac_filter(&lwip_netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
demayer 0:6bf0743ece18 666 }
demayer 0:6bf0743ece18 667 #endif /* LWIP_IPV6_MLD */
demayer 0:6bf0743ece18 668
demayer 0:6bf0743ece18 669 #if LWIP_IPV6_AUTOCONFIG
demayer 0:6bf0743ece18 670 /* IPv6 address autoconfiguration not enabled by default */
demayer 0:6bf0743ece18 671 lwip_netif.ip6_autoconfig_enabled = 1;
demayer 0:6bf0743ece18 672 } else {
demayer 0:6bf0743ece18 673 // Disable router solidifications
demayer 0:6bf0743ece18 674 lwip_netif.rs_count = 0;
demayer 0:6bf0743ece18 675 }
demayer 0:6bf0743ece18 676 #endif /* LWIP_IPV6_AUTOCONFIG */
demayer 0:6bf0743ece18 677 #endif // LWIP_IPV6
demayer 0:6bf0743ece18 678
demayer 0:6bf0743ece18 679 #if LWIP_IPV4
demayer 0:6bf0743ece18 680 if (stack != IPV6_STACK) {
demayer 0:6bf0743ece18 681 if (!dhcp && !ppp) {
demayer 0:6bf0743ece18 682 ip4_addr_t ip_addr;
demayer 0:6bf0743ece18 683 ip4_addr_t netmask_addr;
demayer 0:6bf0743ece18 684 ip4_addr_t gw_addr;
demayer 0:6bf0743ece18 685
demayer 0:6bf0743ece18 686 if (!inet_aton(ip, &ip_addr) ||
demayer 0:6bf0743ece18 687 !inet_aton(netmask, &netmask_addr) ||
demayer 0:6bf0743ece18 688 !inet_aton(gw, &gw_addr)) {
demayer 0:6bf0743ece18 689 return NSAPI_ERROR_PARAMETER;
demayer 0:6bf0743ece18 690 }
demayer 0:6bf0743ece18 691
demayer 0:6bf0743ece18 692 netif_set_addr(&lwip_netif, &ip_addr, &netmask_addr, &gw_addr);
demayer 0:6bf0743ece18 693 }
demayer 0:6bf0743ece18 694 }
demayer 0:6bf0743ece18 695 #endif
demayer 0:6bf0743ece18 696
demayer 0:6bf0743ece18 697 if (ppp) {
demayer 0:6bf0743ece18 698 err_t err = ppp_lwip_connect();
demayer 0:6bf0743ece18 699 if (err) {
demayer 0:6bf0743ece18 700 return mbed_lwip_err_remap(err);
demayer 0:6bf0743ece18 701 }
demayer 0:6bf0743ece18 702 }
demayer 0:6bf0743ece18 703
demayer 0:6bf0743ece18 704 if (!netif_is_link_up(&lwip_netif)) {
demayer 0:6bf0743ece18 705 if (sys_arch_sem_wait(&lwip_netif_linked, 15000) == SYS_ARCH_TIMEOUT) {
demayer 0:6bf0743ece18 706 if (ppp) {
demayer 0:6bf0743ece18 707 (void) ppp_lwip_disconnect();
demayer 0:6bf0743ece18 708 }
demayer 0:6bf0743ece18 709 return NSAPI_ERROR_NO_CONNECTION;
demayer 0:6bf0743ece18 710 }
demayer 0:6bf0743ece18 711 }
demayer 0:6bf0743ece18 712
demayer 0:6bf0743ece18 713 if (!ppp) {
demayer 0:6bf0743ece18 714 netif_set_up(&lwip_netif);
demayer 0:6bf0743ece18 715 }
demayer 0:6bf0743ece18 716
demayer 0:6bf0743ece18 717 #if LWIP_DHCP
demayer 0:6bf0743ece18 718 if (stack != IPV6_STACK) {
demayer 0:6bf0743ece18 719 // Connect to the network
demayer 0:6bf0743ece18 720 lwip_dhcp = dhcp;
demayer 0:6bf0743ece18 721
demayer 0:6bf0743ece18 722 if (lwip_dhcp) {
demayer 0:6bf0743ece18 723 err_t err = dhcp_start(&lwip_netif);
demayer 0:6bf0743ece18 724 if (err) {
demayer 0:6bf0743ece18 725 return NSAPI_ERROR_DHCP_FAILURE;
demayer 0:6bf0743ece18 726 }
demayer 0:6bf0743ece18 727 }
demayer 0:6bf0743ece18 728 }
demayer 0:6bf0743ece18 729 #endif
demayer 0:6bf0743ece18 730
demayer 0:6bf0743ece18 731 // If doesn't have address
demayer 0:6bf0743ece18 732 if (!mbed_lwip_get_ip_addr(true, &lwip_netif)) {
demayer 0:6bf0743ece18 733 if (sys_arch_sem_wait(&lwip_netif_has_any_addr, DHCP_TIMEOUT * 1000) == SYS_ARCH_TIMEOUT) {
demayer 0:6bf0743ece18 734 if (ppp) {
demayer 0:6bf0743ece18 735 (void) ppp_lwip_disconnect();
demayer 0:6bf0743ece18 736 }
demayer 0:6bf0743ece18 737 return NSAPI_ERROR_DHCP_FAILURE;
demayer 0:6bf0743ece18 738 }
demayer 0:6bf0743ece18 739 }
demayer 0:6bf0743ece18 740
demayer 0:6bf0743ece18 741 #if PREF_ADDR_TIMEOUT
demayer 0:6bf0743ece18 742 if (stack != IPV4_STACK && stack != IPV6_STACK) {
demayer 0:6bf0743ece18 743 // If address is not for preferred stack waits a while to see
demayer 0:6bf0743ece18 744 // if preferred stack address is acquired
demayer 0:6bf0743ece18 745 if (!mbed_lwip_get_ip_addr(false, &lwip_netif)) {
demayer 0:6bf0743ece18 746 sys_arch_sem_wait(&lwip_netif_has_pref_addr, PREF_ADDR_TIMEOUT * 1000);
demayer 0:6bf0743ece18 747 }
demayer 0:6bf0743ece18 748 }
demayer 0:6bf0743ece18 749 #endif
demayer 0:6bf0743ece18 750 #if BOTH_ADDR_TIMEOUT
demayer 0:6bf0743ece18 751 if (stack != IPV4_STACK && stack != IPV6_STACK) {
demayer 0:6bf0743ece18 752 // If addresses for both stacks are not available waits a while to
demayer 0:6bf0743ece18 753 // see if address for both stacks are acquired
demayer 0:6bf0743ece18 754 if (!(mbed_lwip_get_ipv4_addr(&lwip_netif) && mbed_lwip_get_ipv6_addr(&lwip_netif))) {
demayer 0:6bf0743ece18 755 sys_arch_sem_wait(&lwip_netif_has_both_addr, BOTH_ADDR_TIMEOUT * 1000);
demayer 0:6bf0743ece18 756 }
demayer 0:6bf0743ece18 757 }
demayer 0:6bf0743ece18 758 #endif
demayer 0:6bf0743ece18 759
demayer 0:6bf0743ece18 760 add_dns_addr(&lwip_netif);
demayer 0:6bf0743ece18 761
demayer 0:6bf0743ece18 762 lwip_connected = true;
demayer 0:6bf0743ece18 763 return 0;
demayer 0:6bf0743ece18 764 }
demayer 0:6bf0743ece18 765
demayer 0:6bf0743ece18 766 #if LWIP_IPV6
demayer 0:6bf0743ece18 767 void mbed_lwip_clear_ipv6_addresses(struct netif *lwip_netif)
demayer 0:6bf0743ece18 768 {
demayer 0:6bf0743ece18 769 for (u8_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
demayer 0:6bf0743ece18 770 netif_ip6_addr_set_state(lwip_netif, i, IP6_ADDR_INVALID);
demayer 0:6bf0743ece18 771 }
demayer 0:6bf0743ece18 772 }
demayer 0:6bf0743ece18 773 #endif
demayer 0:6bf0743ece18 774
demayer 0:6bf0743ece18 775 // Backwards compatibility with people using DEVICE_EMAC
demayer 0:6bf0743ece18 776 nsapi_error_t mbed_lwip_bringdown(void)
demayer 0:6bf0743ece18 777 {
demayer 0:6bf0743ece18 778 return mbed_lwip_bringdown_2(false);
demayer 0:6bf0743ece18 779 }
demayer 0:6bf0743ece18 780
demayer 0:6bf0743ece18 781 nsapi_error_t mbed_lwip_bringdown_2(bool ppp)
demayer 0:6bf0743ece18 782 {
demayer 0:6bf0743ece18 783 // Check if we've connected
demayer 0:6bf0743ece18 784 if (!lwip_connected) {
demayer 0:6bf0743ece18 785 return NSAPI_ERROR_PARAMETER;
demayer 0:6bf0743ece18 786 }
demayer 0:6bf0743ece18 787
demayer 0:6bf0743ece18 788 #if LWIP_DHCP
demayer 0:6bf0743ece18 789 // Disconnect from the network
demayer 0:6bf0743ece18 790 if (lwip_dhcp) {
demayer 0:6bf0743ece18 791 dhcp_release(&lwip_netif);
demayer 0:6bf0743ece18 792 dhcp_stop(&lwip_netif);
demayer 0:6bf0743ece18 793 lwip_dhcp = false;
demayer 0:6bf0743ece18 794 }
demayer 0:6bf0743ece18 795 #endif
demayer 0:6bf0743ece18 796
demayer 0:6bf0743ece18 797 if (ppp) {
demayer 0:6bf0743ece18 798 /* this is a blocking call, returns when PPP is properly closed */
demayer 0:6bf0743ece18 799 err_t err = ppp_lwip_disconnect();
demayer 0:6bf0743ece18 800 if (err) {
demayer 0:6bf0743ece18 801 return mbed_lwip_err_remap(err);
demayer 0:6bf0743ece18 802 }
demayer 0:6bf0743ece18 803 MBED_ASSERT(!netif_is_link_up(&lwip_netif));
demayer 0:6bf0743ece18 804 /*if (netif_is_link_up(&lwip_netif)) {
demayer 0:6bf0743ece18 805 if (sys_arch_sem_wait(&lwip_netif_unlinked, 15000) == SYS_ARCH_TIMEOUT) {
demayer 0:6bf0743ece18 806 return NSAPI_ERROR_DEVICE_ERROR;
demayer 0:6bf0743ece18 807 }
demayer 0:6bf0743ece18 808 }*/
demayer 0:6bf0743ece18 809 } else {
demayer 0:6bf0743ece18 810 netif_set_down(&lwip_netif);
demayer 0:6bf0743ece18 811 }
demayer 0:6bf0743ece18 812
demayer 0:6bf0743ece18 813 #if LWIP_IPV6
demayer 0:6bf0743ece18 814 mbed_lwip_clear_ipv6_addresses(&lwip_netif);
demayer 0:6bf0743ece18 815 #endif
demayer 0:6bf0743ece18 816
demayer 0:6bf0743ece18 817 sys_sem_free(&lwip_netif_has_any_addr);
demayer 0:6bf0743ece18 818 sys_sem_new(&lwip_netif_has_any_addr, 0);
demayer 0:6bf0743ece18 819 #if PREF_ADDR_TIMEOUT
demayer 0:6bf0743ece18 820 sys_sem_free(&lwip_netif_has_pref_addr);
demayer 0:6bf0743ece18 821 sys_sem_new(&lwip_netif_has_pref_addr, 0);
demayer 0:6bf0743ece18 822 #endif
demayer 0:6bf0743ece18 823 #if BOTH_ADDR_TIMEOUT
demayer 0:6bf0743ece18 824 sys_sem_free(&lwip_netif_has_both_addr);
demayer 0:6bf0743ece18 825 sys_sem_new(&lwip_netif_has_both_addr, 0);
demayer 0:6bf0743ece18 826 #endif
demayer 0:6bf0743ece18 827 lwip_has_addr_state = 0;
demayer 0:6bf0743ece18 828 lwip_connected = false;
demayer 0:6bf0743ece18 829 return 0;
demayer 0:6bf0743ece18 830 }
demayer 0:6bf0743ece18 831
demayer 0:6bf0743ece18 832 /* LWIP error remapping */
demayer 0:6bf0743ece18 833 static nsapi_error_t mbed_lwip_err_remap(err_t err) {
demayer 0:6bf0743ece18 834 switch (err) {
demayer 0:6bf0743ece18 835 case ERR_OK:
demayer 0:6bf0743ece18 836 case ERR_CLSD:
demayer 0:6bf0743ece18 837 return 0;
demayer 0:6bf0743ece18 838 case ERR_MEM:
demayer 0:6bf0743ece18 839 case ERR_BUF:
demayer 0:6bf0743ece18 840 return NSAPI_ERROR_NO_MEMORY;
demayer 0:6bf0743ece18 841 case ERR_CONN:
demayer 0:6bf0743ece18 842 case ERR_RST:
demayer 0:6bf0743ece18 843 case ERR_ABRT:
demayer 0:6bf0743ece18 844 return NSAPI_ERROR_NO_CONNECTION;
demayer 0:6bf0743ece18 845 case ERR_TIMEOUT:
demayer 0:6bf0743ece18 846 case ERR_RTE:
demayer 0:6bf0743ece18 847 case ERR_WOULDBLOCK:
demayer 0:6bf0743ece18 848 return NSAPI_ERROR_WOULD_BLOCK;
demayer 0:6bf0743ece18 849 case ERR_VAL:
demayer 0:6bf0743ece18 850 case ERR_USE:
demayer 0:6bf0743ece18 851 case ERR_ARG:
demayer 0:6bf0743ece18 852 return NSAPI_ERROR_PARAMETER;
demayer 0:6bf0743ece18 853 case ERR_INPROGRESS:
demayer 0:6bf0743ece18 854 return NSAPI_ERROR_IN_PROGRESS;
demayer 0:6bf0743ece18 855 case ERR_ALREADY:
demayer 0:6bf0743ece18 856 return NSAPI_ERROR_ALREADY;
demayer 0:6bf0743ece18 857 case ERR_ISCONN:
demayer 0:6bf0743ece18 858 return NSAPI_ERROR_IS_CONNECTED;
demayer 0:6bf0743ece18 859 default:
demayer 0:6bf0743ece18 860 return NSAPI_ERROR_DEVICE_ERROR;
demayer 0:6bf0743ece18 861 }
demayer 0:6bf0743ece18 862 }
demayer 0:6bf0743ece18 863
demayer 0:6bf0743ece18 864 /* LWIP network stack implementation */
demayer 0:6bf0743ece18 865 static nsapi_error_t mbed_lwip_gethostbyname(nsapi_stack_t *stack, const char *host, nsapi_addr_t *addr, nsapi_version_t version)
demayer 0:6bf0743ece18 866 {
demayer 0:6bf0743ece18 867 ip_addr_t lwip_addr;
demayer 0:6bf0743ece18 868
demayer 0:6bf0743ece18 869 #if LWIP_IPV4 && LWIP_IPV6
demayer 0:6bf0743ece18 870 u8_t addr_type;
demayer 0:6bf0743ece18 871 if (version == NSAPI_UNSPEC) {
demayer 0:6bf0743ece18 872 const ip_addr_t *ip_addr;
demayer 0:6bf0743ece18 873 ip_addr = mbed_lwip_get_ip_addr(true, &lwip_netif);
demayer 0:6bf0743ece18 874 // Prefer IPv6
demayer 0:6bf0743ece18 875 if (IP_IS_V6(ip_addr)) {
demayer 0:6bf0743ece18 876 // If IPv4 is available use it as backup
demayer 0:6bf0743ece18 877 if (mbed_lwip_get_ipv4_addr(&lwip_netif)) {
demayer 0:6bf0743ece18 878 addr_type = NETCONN_DNS_IPV6_IPV4;
demayer 0:6bf0743ece18 879 } else {
demayer 0:6bf0743ece18 880 addr_type = NETCONN_DNS_IPV6;
demayer 0:6bf0743ece18 881 }
demayer 0:6bf0743ece18 882 // Prefer IPv4
demayer 0:6bf0743ece18 883 } else {
demayer 0:6bf0743ece18 884 // If IPv6 is available use it as backup
demayer 0:6bf0743ece18 885 if (mbed_lwip_get_ipv6_addr(&lwip_netif)) {
demayer 0:6bf0743ece18 886 addr_type = NETCONN_DNS_IPV4_IPV6;
demayer 0:6bf0743ece18 887 } else {
demayer 0:6bf0743ece18 888 addr_type = NETCONN_DNS_IPV4;
demayer 0:6bf0743ece18 889 }
demayer 0:6bf0743ece18 890 }
demayer 0:6bf0743ece18 891 } else if (version == NSAPI_IPv4) {
demayer 0:6bf0743ece18 892 addr_type = NETCONN_DNS_IPV4;
demayer 0:6bf0743ece18 893 } else if (version == NSAPI_IPv6) {
demayer 0:6bf0743ece18 894 addr_type = NETCONN_DNS_IPV6;
demayer 0:6bf0743ece18 895 } else {
demayer 0:6bf0743ece18 896 return NSAPI_ERROR_DNS_FAILURE;
demayer 0:6bf0743ece18 897 }
demayer 0:6bf0743ece18 898 err_t err = netconn_gethostbyname_addrtype(host, &lwip_addr, addr_type);
demayer 0:6bf0743ece18 899 #elif LWIP_IPV4
demayer 0:6bf0743ece18 900 if (version != NSAPI_IPv4 && version != NSAPI_UNSPEC) {
demayer 0:6bf0743ece18 901 return NSAPI_ERROR_DNS_FAILURE;
demayer 0:6bf0743ece18 902 }
demayer 0:6bf0743ece18 903 err_t err = netconn_gethostbyname(host, &lwip_addr);
demayer 0:6bf0743ece18 904 #elif LWIP_IPV6
demayer 0:6bf0743ece18 905 if (version != NSAPI_IPv6 && version != NSAPI_UNSPEC) {
demayer 0:6bf0743ece18 906 return NSAPI_ERROR_DNS_FAILURE;
demayer 0:6bf0743ece18 907 }
demayer 0:6bf0743ece18 908 err_t err = netconn_gethostbyname(host, &lwip_addr);
demayer 0:6bf0743ece18 909 #endif
demayer 0:6bf0743ece18 910
demayer 0:6bf0743ece18 911 if (err != ERR_OK) {
demayer 0:6bf0743ece18 912 return NSAPI_ERROR_DNS_FAILURE;
demayer 0:6bf0743ece18 913 }
demayer 0:6bf0743ece18 914
demayer 0:6bf0743ece18 915 convert_lwip_addr_to_mbed(addr, &lwip_addr);
demayer 0:6bf0743ece18 916
demayer 0:6bf0743ece18 917 return 0;
demayer 0:6bf0743ece18 918 }
demayer 0:6bf0743ece18 919
demayer 0:6bf0743ece18 920 static nsapi_error_t mbed_lwip_add_dns_server(nsapi_stack_t *stack, nsapi_addr_t addr)
demayer 0:6bf0743ece18 921 {
demayer 0:6bf0743ece18 922 // Shift all dns servers down to give precedence to new server
demayer 0:6bf0743ece18 923 for (int i = DNS_MAX_SERVERS-1; i > 0; i--) {
demayer 0:6bf0743ece18 924 dns_setserver(i, dns_getserver(i-1));
demayer 0:6bf0743ece18 925 }
demayer 0:6bf0743ece18 926
demayer 0:6bf0743ece18 927 ip_addr_t ip_addr;
demayer 0:6bf0743ece18 928 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
demayer 0:6bf0743ece18 929 return NSAPI_ERROR_PARAMETER;
demayer 0:6bf0743ece18 930 }
demayer 0:6bf0743ece18 931
demayer 0:6bf0743ece18 932 dns_setserver(0, &ip_addr);
demayer 0:6bf0743ece18 933 return 0;
demayer 0:6bf0743ece18 934 }
demayer 0:6bf0743ece18 935
demayer 0:6bf0743ece18 936 static nsapi_error_t mbed_lwip_socket_open(nsapi_stack_t *stack, nsapi_socket_t *handle, nsapi_protocol_t proto)
demayer 0:6bf0743ece18 937 {
demayer 0:6bf0743ece18 938 // check if network is connected
demayer 0:6bf0743ece18 939 if (!lwip_connected) {
demayer 0:6bf0743ece18 940 return NSAPI_ERROR_NO_CONNECTION;
demayer 0:6bf0743ece18 941 }
demayer 0:6bf0743ece18 942
demayer 0:6bf0743ece18 943 // allocate a socket
demayer 0:6bf0743ece18 944 struct lwip_socket *s = mbed_lwip_arena_alloc();
demayer 0:6bf0743ece18 945 if (!s) {
demayer 0:6bf0743ece18 946 return NSAPI_ERROR_NO_SOCKET;
demayer 0:6bf0743ece18 947 }
demayer 0:6bf0743ece18 948
demayer 0:6bf0743ece18 949 enum netconn_type lwip_proto = proto == NSAPI_TCP ? NETCONN_TCP : NETCONN_UDP;
demayer 0:6bf0743ece18 950
demayer 0:6bf0743ece18 951 #if LWIP_IPV6
demayer 0:6bf0743ece18 952 // Enable IPv6 (or dual-stack)
demayer 0:6bf0743ece18 953 lwip_proto |= NETCONN_TYPE_IPV6;
demayer 0:6bf0743ece18 954 #endif
demayer 0:6bf0743ece18 955
demayer 0:6bf0743ece18 956 s->conn = netconn_new_with_callback(lwip_proto, mbed_lwip_socket_callback);
demayer 0:6bf0743ece18 957
demayer 0:6bf0743ece18 958 if (!s->conn) {
demayer 0:6bf0743ece18 959 mbed_lwip_arena_dealloc(s);
demayer 0:6bf0743ece18 960 return NSAPI_ERROR_NO_SOCKET;
demayer 0:6bf0743ece18 961 }
demayer 0:6bf0743ece18 962
demayer 0:6bf0743ece18 963 netconn_set_recvtimeout(s->conn, 1);
demayer 0:6bf0743ece18 964 *(struct lwip_socket **)handle = s;
demayer 0:6bf0743ece18 965 return 0;
demayer 0:6bf0743ece18 966 }
demayer 0:6bf0743ece18 967
demayer 0:6bf0743ece18 968 static nsapi_error_t mbed_lwip_socket_close(nsapi_stack_t *stack, nsapi_socket_t handle)
demayer 0:6bf0743ece18 969 {
demayer 0:6bf0743ece18 970 struct lwip_socket *s = (struct lwip_socket *)handle;
demayer 0:6bf0743ece18 971
demayer 0:6bf0743ece18 972 netbuf_delete(s->buf);
demayer 0:6bf0743ece18 973 err_t err = netconn_delete(s->conn);
demayer 0:6bf0743ece18 974 mbed_lwip_arena_dealloc(s);
demayer 0:6bf0743ece18 975 return mbed_lwip_err_remap(err);
demayer 0:6bf0743ece18 976 }
demayer 0:6bf0743ece18 977
demayer 0:6bf0743ece18 978 static nsapi_error_t mbed_lwip_socket_bind(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port)
demayer 0:6bf0743ece18 979 {
demayer 0:6bf0743ece18 980 struct lwip_socket *s = (struct lwip_socket *)handle;
demayer 0:6bf0743ece18 981 ip_addr_t ip_addr;
demayer 0:6bf0743ece18 982
demayer 0:6bf0743ece18 983 if (
demayer 0:6bf0743ece18 984 #if LWIP_TCP
demayer 0:6bf0743ece18 985 (s->conn->type == NETCONN_TCP && s->conn->pcb.tcp->local_port != 0) ||
demayer 0:6bf0743ece18 986 #endif
demayer 0:6bf0743ece18 987 (s->conn->type == NETCONN_UDP && s->conn->pcb.udp->local_port != 0)) {
demayer 0:6bf0743ece18 988 return NSAPI_ERROR_PARAMETER;
demayer 0:6bf0743ece18 989 }
demayer 0:6bf0743ece18 990
demayer 0:6bf0743ece18 991 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
demayer 0:6bf0743ece18 992 return NSAPI_ERROR_PARAMETER;
demayer 0:6bf0743ece18 993 }
demayer 0:6bf0743ece18 994
demayer 0:6bf0743ece18 995 err_t err = netconn_bind(s->conn, &ip_addr, port);
demayer 0:6bf0743ece18 996 return mbed_lwip_err_remap(err);
demayer 0:6bf0743ece18 997 }
demayer 0:6bf0743ece18 998
demayer 0:6bf0743ece18 999 static nsapi_error_t mbed_lwip_socket_listen(nsapi_stack_t *stack, nsapi_socket_t handle, int backlog)
demayer 0:6bf0743ece18 1000 {
demayer 0:6bf0743ece18 1001 struct lwip_socket *s = (struct lwip_socket *)handle;
demayer 0:6bf0743ece18 1002
demayer 0:6bf0743ece18 1003 err_t err = netconn_listen_with_backlog(s->conn, backlog);
demayer 0:6bf0743ece18 1004 return mbed_lwip_err_remap(err);
demayer 0:6bf0743ece18 1005 }
demayer 0:6bf0743ece18 1006
demayer 0:6bf0743ece18 1007 static nsapi_error_t mbed_lwip_socket_connect(nsapi_stack_t *stack, nsapi_socket_t handle, nsapi_addr_t addr, uint16_t port)
demayer 0:6bf0743ece18 1008 {
demayer 0:6bf0743ece18 1009 struct lwip_socket *s = (struct lwip_socket *)handle;
demayer 0:6bf0743ece18 1010 ip_addr_t ip_addr;
demayer 0:6bf0743ece18 1011
demayer 0:6bf0743ece18 1012 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
demayer 0:6bf0743ece18 1013 return NSAPI_ERROR_PARAMETER;
demayer 0:6bf0743ece18 1014 }
demayer 0:6bf0743ece18 1015
demayer 0:6bf0743ece18 1016 netconn_set_nonblocking(s->conn, false);
demayer 0:6bf0743ece18 1017 err_t err = netconn_connect(s->conn, &ip_addr, port);
demayer 0:6bf0743ece18 1018 netconn_set_nonblocking(s->conn, true);
demayer 0:6bf0743ece18 1019
demayer 0:6bf0743ece18 1020 return mbed_lwip_err_remap(err);
demayer 0:6bf0743ece18 1021 }
demayer 0:6bf0743ece18 1022
demayer 0:6bf0743ece18 1023 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)
demayer 0:6bf0743ece18 1024 {
demayer 0:6bf0743ece18 1025 struct lwip_socket *s = (struct lwip_socket *)server;
demayer 0:6bf0743ece18 1026 struct lwip_socket *ns = mbed_lwip_arena_alloc();
demayer 0:6bf0743ece18 1027 if (!ns) {
demayer 0:6bf0743ece18 1028 return NSAPI_ERROR_NO_SOCKET;
demayer 0:6bf0743ece18 1029 }
demayer 0:6bf0743ece18 1030
demayer 0:6bf0743ece18 1031 err_t err = netconn_accept(s->conn, &ns->conn);
demayer 0:6bf0743ece18 1032 if (err != ERR_OK) {
demayer 0:6bf0743ece18 1033 mbed_lwip_arena_dealloc(ns);
demayer 0:6bf0743ece18 1034 return mbed_lwip_err_remap(err);
demayer 0:6bf0743ece18 1035 }
demayer 0:6bf0743ece18 1036
demayer 0:6bf0743ece18 1037 netconn_set_recvtimeout(ns->conn, 1);
demayer 0:6bf0743ece18 1038 *(struct lwip_socket **)handle = ns;
demayer 0:6bf0743ece18 1039
demayer 0:6bf0743ece18 1040 ip_addr_t peer_addr;
demayer 0:6bf0743ece18 1041 (void) netconn_peer(ns->conn, &peer_addr, port);
demayer 0:6bf0743ece18 1042 convert_lwip_addr_to_mbed(addr, &peer_addr);
demayer 0:6bf0743ece18 1043
demayer 0:6bf0743ece18 1044 netconn_set_nonblocking(ns->conn, true);
demayer 0:6bf0743ece18 1045
demayer 0:6bf0743ece18 1046 return 0;
demayer 0:6bf0743ece18 1047 }
demayer 0:6bf0743ece18 1048
demayer 0:6bf0743ece18 1049 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)
demayer 0:6bf0743ece18 1050 {
demayer 0:6bf0743ece18 1051 struct lwip_socket *s = (struct lwip_socket *)handle;
demayer 0:6bf0743ece18 1052 size_t bytes_written = 0;
demayer 0:6bf0743ece18 1053
demayer 0:6bf0743ece18 1054 err_t err = netconn_write_partly(s->conn, data, size, NETCONN_COPY, &bytes_written);
demayer 0:6bf0743ece18 1055 if (err != ERR_OK) {
demayer 0:6bf0743ece18 1056 return mbed_lwip_err_remap(err);
demayer 0:6bf0743ece18 1057 }
demayer 0:6bf0743ece18 1058
demayer 0:6bf0743ece18 1059 return (nsapi_size_or_error_t)bytes_written;
demayer 0:6bf0743ece18 1060 }
demayer 0:6bf0743ece18 1061
demayer 0:6bf0743ece18 1062 static nsapi_size_or_error_t mbed_lwip_socket_recv(nsapi_stack_t *stack, nsapi_socket_t handle, void *data, nsapi_size_t size)
demayer 0:6bf0743ece18 1063 {
demayer 0:6bf0743ece18 1064 struct lwip_socket *s = (struct lwip_socket *)handle;
demayer 0:6bf0743ece18 1065
demayer 0:6bf0743ece18 1066 if (!s->buf) {
demayer 0:6bf0743ece18 1067 err_t err = netconn_recv(s->conn, &s->buf);
demayer 0:6bf0743ece18 1068 s->offset = 0;
demayer 0:6bf0743ece18 1069
demayer 0:6bf0743ece18 1070 if (err != ERR_OK) {
demayer 0:6bf0743ece18 1071 return mbed_lwip_err_remap(err);
demayer 0:6bf0743ece18 1072 }
demayer 0:6bf0743ece18 1073 }
demayer 0:6bf0743ece18 1074
demayer 0:6bf0743ece18 1075 u16_t recv = netbuf_copy_partial(s->buf, data, (u16_t)size, s->offset);
demayer 0:6bf0743ece18 1076 s->offset += recv;
demayer 0:6bf0743ece18 1077
demayer 0:6bf0743ece18 1078 if (s->offset >= netbuf_len(s->buf)) {
demayer 0:6bf0743ece18 1079 netbuf_delete(s->buf);
demayer 0:6bf0743ece18 1080 s->buf = 0;
demayer 0:6bf0743ece18 1081 }
demayer 0:6bf0743ece18 1082
demayer 0:6bf0743ece18 1083 return recv;
demayer 0:6bf0743ece18 1084 }
demayer 0:6bf0743ece18 1085
demayer 0:6bf0743ece18 1086 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)
demayer 0:6bf0743ece18 1087 {
demayer 0:6bf0743ece18 1088 struct lwip_socket *s = (struct lwip_socket *)handle;
demayer 0:6bf0743ece18 1089 ip_addr_t ip_addr;
demayer 0:6bf0743ece18 1090
demayer 0:6bf0743ece18 1091 if (!convert_mbed_addr_to_lwip(&ip_addr, &addr)) {
demayer 0:6bf0743ece18 1092 return NSAPI_ERROR_PARAMETER;
demayer 0:6bf0743ece18 1093 }
demayer 0:6bf0743ece18 1094
demayer 0:6bf0743ece18 1095 struct netbuf *buf = netbuf_new();
demayer 0:6bf0743ece18 1096 err_t err = netbuf_ref(buf, data, (u16_t)size);
demayer 0:6bf0743ece18 1097 if (err != ERR_OK) {
demayer 0:6bf0743ece18 1098 netbuf_free(buf);
demayer 0:6bf0743ece18 1099 return mbed_lwip_err_remap(err);
demayer 0:6bf0743ece18 1100 }
demayer 0:6bf0743ece18 1101
demayer 0:6bf0743ece18 1102 err = netconn_sendto(s->conn, buf, &ip_addr, port);
demayer 0:6bf0743ece18 1103 netbuf_delete(buf);
demayer 0:6bf0743ece18 1104 if (err != ERR_OK) {
demayer 0:6bf0743ece18 1105 return mbed_lwip_err_remap(err);
demayer 0:6bf0743ece18 1106 }
demayer 0:6bf0743ece18 1107
demayer 0:6bf0743ece18 1108 return size;
demayer 0:6bf0743ece18 1109 }
demayer 0:6bf0743ece18 1110
demayer 0:6bf0743ece18 1111 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)
demayer 0:6bf0743ece18 1112 {
demayer 0:6bf0743ece18 1113 struct lwip_socket *s = (struct lwip_socket *)handle;
demayer 0:6bf0743ece18 1114 struct netbuf *buf;
demayer 0:6bf0743ece18 1115
demayer 0:6bf0743ece18 1116 err_t err = netconn_recv(s->conn, &buf);
demayer 0:6bf0743ece18 1117 if (err != ERR_OK) {
demayer 0:6bf0743ece18 1118 return mbed_lwip_err_remap(err);
demayer 0:6bf0743ece18 1119 }
demayer 0:6bf0743ece18 1120
demayer 0:6bf0743ece18 1121 convert_lwip_addr_to_mbed(addr, netbuf_fromaddr(buf));
demayer 0:6bf0743ece18 1122 *port = netbuf_fromport(buf);
demayer 0:6bf0743ece18 1123
demayer 0:6bf0743ece18 1124 u16_t recv = netbuf_copy(buf, data, (u16_t)size);
demayer 0:6bf0743ece18 1125 netbuf_delete(buf);
demayer 0:6bf0743ece18 1126
demayer 0:6bf0743ece18 1127 return recv;
demayer 0:6bf0743ece18 1128 }
demayer 0:6bf0743ece18 1129
demayer 0:6bf0743ece18 1130 static int32_t find_multicast_member(const struct lwip_socket *s, const nsapi_ip_mreq_t *imr) {
demayer 0:6bf0743ece18 1131 uint32_t count = 0;
demayer 0:6bf0743ece18 1132 uint32_t index = 0;
demayer 0:6bf0743ece18 1133 // Set upper limit on while loop, should break out when the membership pair is found
demayer 0:6bf0743ece18 1134 while (count < s->multicast_memberships_count) {
demayer 0:6bf0743ece18 1135 index = next_registered_multicast_member(s, index);
demayer 0:6bf0743ece18 1136
demayer 0:6bf0743ece18 1137 if (memcmp(&s->multicast_memberships[index].imr_multiaddr, &imr->imr_multiaddr, sizeof(nsapi_addr_t)) == 0 &&
demayer 0:6bf0743ece18 1138 memcmp(&s->multicast_memberships[index].imr_interface, &imr->imr_interface, sizeof(nsapi_addr_t)) == 0) {
demayer 0:6bf0743ece18 1139 return index;
demayer 0:6bf0743ece18 1140 }
demayer 0:6bf0743ece18 1141 count++;
demayer 0:6bf0743ece18 1142 index++;
demayer 0:6bf0743ece18 1143 }
demayer 0:6bf0743ece18 1144
demayer 0:6bf0743ece18 1145 return -1;
demayer 0:6bf0743ece18 1146 }
demayer 0:6bf0743ece18 1147
demayer 0:6bf0743ece18 1148 static nsapi_error_t mbed_lwip_setsockopt(nsapi_stack_t *stack, nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen)
demayer 0:6bf0743ece18 1149 {
demayer 0:6bf0743ece18 1150 struct lwip_socket *s = (struct lwip_socket *)handle;
demayer 0:6bf0743ece18 1151
demayer 0:6bf0743ece18 1152 switch (optname) {
demayer 0:6bf0743ece18 1153 #if LWIP_TCP
demayer 0:6bf0743ece18 1154 case NSAPI_KEEPALIVE:
demayer 0:6bf0743ece18 1155 if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) {
demayer 0:6bf0743ece18 1156 return NSAPI_ERROR_UNSUPPORTED;
demayer 0:6bf0743ece18 1157 }
demayer 0:6bf0743ece18 1158
demayer 0:6bf0743ece18 1159 s->conn->pcb.tcp->so_options |= SOF_KEEPALIVE;
demayer 0:6bf0743ece18 1160 return 0;
demayer 0:6bf0743ece18 1161
demayer 0:6bf0743ece18 1162 case NSAPI_KEEPIDLE:
demayer 0:6bf0743ece18 1163 if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) {
demayer 0:6bf0743ece18 1164 return NSAPI_ERROR_UNSUPPORTED;
demayer 0:6bf0743ece18 1165 }
demayer 0:6bf0743ece18 1166
demayer 0:6bf0743ece18 1167 s->conn->pcb.tcp->keep_idle = *(int*)optval;
demayer 0:6bf0743ece18 1168 return 0;
demayer 0:6bf0743ece18 1169
demayer 0:6bf0743ece18 1170 case NSAPI_KEEPINTVL:
demayer 0:6bf0743ece18 1171 if (optlen != sizeof(int) || s->conn->type != NETCONN_TCP) {
demayer 0:6bf0743ece18 1172 return NSAPI_ERROR_UNSUPPORTED;
demayer 0:6bf0743ece18 1173 }
demayer 0:6bf0743ece18 1174
demayer 0:6bf0743ece18 1175 s->conn->pcb.tcp->keep_intvl = *(int*)optval;
demayer 0:6bf0743ece18 1176 return 0;
demayer 0:6bf0743ece18 1177 #endif
demayer 0:6bf0743ece18 1178
demayer 0:6bf0743ece18 1179 case NSAPI_REUSEADDR:
demayer 0:6bf0743ece18 1180 if (optlen != sizeof(int)) {
demayer 0:6bf0743ece18 1181 return NSAPI_ERROR_UNSUPPORTED;
demayer 0:6bf0743ece18 1182 }
demayer 0:6bf0743ece18 1183
demayer 0:6bf0743ece18 1184 if (*(int *)optval) {
demayer 0:6bf0743ece18 1185 ip_set_option(s->conn->pcb.ip, SOF_REUSEADDR);
demayer 0:6bf0743ece18 1186 } else {
demayer 0:6bf0743ece18 1187 ip_reset_option(s->conn->pcb.ip, SOF_REUSEADDR);
demayer 0:6bf0743ece18 1188 }
demayer 0:6bf0743ece18 1189 return 0;
demayer 0:6bf0743ece18 1190
demayer 0:6bf0743ece18 1191 case NSAPI_ADD_MEMBERSHIP:
demayer 0:6bf0743ece18 1192 case NSAPI_DROP_MEMBERSHIP: {
demayer 0:6bf0743ece18 1193 if (optlen != sizeof(nsapi_ip_mreq_t)) {
demayer 0:6bf0743ece18 1194 return NSAPI_ERROR_PARAMETER;
demayer 0:6bf0743ece18 1195 }
demayer 0:6bf0743ece18 1196 err_t igmp_err;
demayer 0:6bf0743ece18 1197 const nsapi_ip_mreq_t *imr = optval;
demayer 0:6bf0743ece18 1198
demayer 0:6bf0743ece18 1199 /* Check interface address type matches group, or is unspecified */
demayer 0:6bf0743ece18 1200 if (imr->imr_interface.version != NSAPI_UNSPEC && imr->imr_interface.version != imr->imr_multiaddr.version) {
demayer 0:6bf0743ece18 1201 return NSAPI_ERROR_PARAMETER;
demayer 0:6bf0743ece18 1202 }
demayer 0:6bf0743ece18 1203
demayer 0:6bf0743ece18 1204 ip_addr_t if_addr;
demayer 0:6bf0743ece18 1205 ip_addr_t multi_addr;
demayer 0:6bf0743ece18 1206
demayer 0:6bf0743ece18 1207 /* Convert the group address */
demayer 0:6bf0743ece18 1208 if (!convert_mbed_addr_to_lwip(&multi_addr, &imr->imr_multiaddr)) {
demayer 0:6bf0743ece18 1209 return NSAPI_ERROR_PARAMETER;
demayer 0:6bf0743ece18 1210 }
demayer 0:6bf0743ece18 1211
demayer 0:6bf0743ece18 1212 /* Convert the interface address, or make sure it's the correct sort of "any" */
demayer 0:6bf0743ece18 1213 if (imr->imr_interface.version != NSAPI_UNSPEC) {
demayer 0:6bf0743ece18 1214 if (!convert_mbed_addr_to_lwip(&if_addr, &imr->imr_interface)) {
demayer 0:6bf0743ece18 1215 return NSAPI_ERROR_PARAMETER;
demayer 0:6bf0743ece18 1216 }
demayer 0:6bf0743ece18 1217 } else {
demayer 0:6bf0743ece18 1218 ip_addr_set_any(IP_IS_V6(&if_addr), &if_addr);
demayer 0:6bf0743ece18 1219 }
demayer 0:6bf0743ece18 1220
demayer 0:6bf0743ece18 1221 igmp_err = ERR_USE; // Maps to NSAPI_ERROR_UNSUPPORTED
demayer 0:6bf0743ece18 1222 int32_t member_pair_index = find_multicast_member(s, imr);
demayer 0:6bf0743ece18 1223
demayer 0:6bf0743ece18 1224 if (optname == NSAPI_ADD_MEMBERSHIP) {
demayer 0:6bf0743ece18 1225 if (!s->multicast_memberships) {
demayer 0:6bf0743ece18 1226 // First multicast join on this socket, allocate space for membership tracking
demayer 0:6bf0743ece18 1227 s->multicast_memberships = malloc(sizeof(nsapi_ip_mreq_t) * LWIP_SOCKET_MAX_MEMBERSHIPS);
demayer 0:6bf0743ece18 1228 if (!s->multicast_memberships) {
demayer 0:6bf0743ece18 1229 return NSAPI_ERROR_NO_MEMORY;
demayer 0:6bf0743ece18 1230 }
demayer 0:6bf0743ece18 1231 } else if(s->multicast_memberships_count == LWIP_SOCKET_MAX_MEMBERSHIPS) {
demayer 0:6bf0743ece18 1232 return NSAPI_ERROR_NO_MEMORY;
demayer 0:6bf0743ece18 1233 }
demayer 0:6bf0743ece18 1234
demayer 0:6bf0743ece18 1235 if (member_pair_index != -1) {
demayer 0:6bf0743ece18 1236 return NSAPI_ERROR_ADDRESS_IN_USE;
demayer 0:6bf0743ece18 1237 }
demayer 0:6bf0743ece18 1238
demayer 0:6bf0743ece18 1239 member_pair_index = next_free_multicast_member(s, 0);
demayer 0:6bf0743ece18 1240
demayer 0:6bf0743ece18 1241 sys_prot_t prot = sys_arch_protect();
demayer 0:6bf0743ece18 1242
demayer 0:6bf0743ece18 1243 #if LWIP_IPV4
demayer 0:6bf0743ece18 1244 if (IP_IS_V4(&if_addr)) {
demayer 0:6bf0743ece18 1245 igmp_err = igmp_joingroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr));
demayer 0:6bf0743ece18 1246 }
demayer 0:6bf0743ece18 1247 #endif
demayer 0:6bf0743ece18 1248 #if LWIP_IPV6
demayer 0:6bf0743ece18 1249 if (IP_IS_V6(&if_addr)) {
demayer 0:6bf0743ece18 1250 igmp_err = mld6_joingroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr));
demayer 0:6bf0743ece18 1251 }
demayer 0:6bf0743ece18 1252 #endif
demayer 0:6bf0743ece18 1253
demayer 0:6bf0743ece18 1254 sys_arch_unprotect(prot);
demayer 0:6bf0743ece18 1255
demayer 0:6bf0743ece18 1256 if (igmp_err == ERR_OK) {
demayer 0:6bf0743ece18 1257 set_multicast_member_registry_bit(s, member_pair_index);
demayer 0:6bf0743ece18 1258 s->multicast_memberships[member_pair_index] = *imr;
demayer 0:6bf0743ece18 1259 s->multicast_memberships_count++;
demayer 0:6bf0743ece18 1260 }
demayer 0:6bf0743ece18 1261 } else {
demayer 0:6bf0743ece18 1262 if (member_pair_index == -1) {
demayer 0:6bf0743ece18 1263 return NSAPI_ERROR_NO_ADDRESS;
demayer 0:6bf0743ece18 1264 }
demayer 0:6bf0743ece18 1265
demayer 0:6bf0743ece18 1266 clear_multicast_member_registry_bit(s, member_pair_index);
demayer 0:6bf0743ece18 1267 s->multicast_memberships_count--;
demayer 0:6bf0743ece18 1268
demayer 0:6bf0743ece18 1269 sys_prot_t prot = sys_arch_protect();
demayer 0:6bf0743ece18 1270
demayer 0:6bf0743ece18 1271 #if LWIP_IPV4
demayer 0:6bf0743ece18 1272 if (IP_IS_V4(&if_addr)) {
demayer 0:6bf0743ece18 1273 igmp_err = igmp_leavegroup(ip_2_ip4(&if_addr), ip_2_ip4(&multi_addr));
demayer 0:6bf0743ece18 1274 }
demayer 0:6bf0743ece18 1275 #endif
demayer 0:6bf0743ece18 1276 #if LWIP_IPV6
demayer 0:6bf0743ece18 1277 if (IP_IS_V6(&if_addr)) {
demayer 0:6bf0743ece18 1278 igmp_err = mld6_leavegroup(ip_2_ip6(&if_addr), ip_2_ip6(&multi_addr));
demayer 0:6bf0743ece18 1279 }
demayer 0:6bf0743ece18 1280 #endif
demayer 0:6bf0743ece18 1281
demayer 0:6bf0743ece18 1282 sys_arch_unprotect(prot);
demayer 0:6bf0743ece18 1283 }
demayer 0:6bf0743ece18 1284
demayer 0:6bf0743ece18 1285 return mbed_lwip_err_remap(igmp_err);
demayer 0:6bf0743ece18 1286 }
demayer 0:6bf0743ece18 1287
demayer 0:6bf0743ece18 1288 default:
demayer 0:6bf0743ece18 1289 return NSAPI_ERROR_UNSUPPORTED;
demayer 0:6bf0743ece18 1290 }
demayer 0:6bf0743ece18 1291 }
demayer 0:6bf0743ece18 1292
demayer 0:6bf0743ece18 1293 static void mbed_lwip_socket_attach(nsapi_stack_t *stack, nsapi_socket_t handle, void (*callback)(void *), void *data)
demayer 0:6bf0743ece18 1294 {
demayer 0:6bf0743ece18 1295 struct lwip_socket *s = (struct lwip_socket *)handle;
demayer 0:6bf0743ece18 1296
demayer 0:6bf0743ece18 1297 s->cb = callback;
demayer 0:6bf0743ece18 1298 s->data = data;
demayer 0:6bf0743ece18 1299 }
demayer 0:6bf0743ece18 1300
demayer 0:6bf0743ece18 1301 /* LWIP network stack */
demayer 0:6bf0743ece18 1302 const nsapi_stack_api_t lwip_stack_api = {
demayer 0:6bf0743ece18 1303 .gethostbyname = mbed_lwip_gethostbyname,
demayer 0:6bf0743ece18 1304 .add_dns_server = mbed_lwip_add_dns_server,
demayer 0:6bf0743ece18 1305 .socket_open = mbed_lwip_socket_open,
demayer 0:6bf0743ece18 1306 .socket_close = mbed_lwip_socket_close,
demayer 0:6bf0743ece18 1307 .socket_bind = mbed_lwip_socket_bind,
demayer 0:6bf0743ece18 1308 .socket_listen = mbed_lwip_socket_listen,
demayer 0:6bf0743ece18 1309 .socket_connect = mbed_lwip_socket_connect,
demayer 0:6bf0743ece18 1310 .socket_accept = mbed_lwip_socket_accept,
demayer 0:6bf0743ece18 1311 .socket_send = mbed_lwip_socket_send,
demayer 0:6bf0743ece18 1312 .socket_recv = mbed_lwip_socket_recv,
demayer 0:6bf0743ece18 1313 .socket_sendto = mbed_lwip_socket_sendto,
demayer 0:6bf0743ece18 1314 .socket_recvfrom = mbed_lwip_socket_recvfrom,
demayer 0:6bf0743ece18 1315 .setsockopt = mbed_lwip_setsockopt,
demayer 0:6bf0743ece18 1316 .socket_attach = mbed_lwip_socket_attach,
demayer 0:6bf0743ece18 1317 };
demayer 0:6bf0743ece18 1318
demayer 0:6bf0743ece18 1319 nsapi_stack_t lwip_stack = {
demayer 0:6bf0743ece18 1320 .stack_api = &lwip_stack_api,
demayer 0:6bf0743ece18 1321 };