RTC auf true

Committer:
kevman
Date:
Wed Nov 28 15:10:15 2018 +0000
Revision:
0:38ceb79fef03
RTC modified

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kevman 0:38ceb79fef03 1 /* Copyright (c) 2017 ARM Limited
kevman 0:38ceb79fef03 2 *
kevman 0:38ceb79fef03 3 * Licensed under the Apache License, Version 2.0 (the "License");
kevman 0:38ceb79fef03 4 * you may not use this file except in compliance with the License.
kevman 0:38ceb79fef03 5 * You may obtain a copy of the License at
kevman 0:38ceb79fef03 6 *
kevman 0:38ceb79fef03 7 * http://www.apache.org/licenses/LICENSE-2.0
kevman 0:38ceb79fef03 8 *
kevman 0:38ceb79fef03 9 * Unless required by applicable law or agreed to in writing, software
kevman 0:38ceb79fef03 10 * distributed under the License is distributed on an "AS IS" BASIS,
kevman 0:38ceb79fef03 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kevman 0:38ceb79fef03 12 * See the License for the specific language governing permissions and
kevman 0:38ceb79fef03 13 * limitations under the License.
kevman 0:38ceb79fef03 14 */
kevman 0:38ceb79fef03 15
kevman 0:38ceb79fef03 16 #define __STDC_LIMIT_MACROS
kevman 0:38ceb79fef03 17
kevman 0:38ceb79fef03 18 #include "nsapi.h"
kevman 0:38ceb79fef03 19 #include "mbed_interface.h"
kevman 0:38ceb79fef03 20 #include "mbed_assert.h"
kevman 0:38ceb79fef03 21 #include <stdio.h>
kevman 0:38ceb79fef03 22 #include <stdbool.h>
kevman 0:38ceb79fef03 23 #include <string.h>
kevman 0:38ceb79fef03 24 #include <new>
kevman 0:38ceb79fef03 25 #include <stdint.h>
kevman 0:38ceb79fef03 26
kevman 0:38ceb79fef03 27 #include "lwip/opt.h"
kevman 0:38ceb79fef03 28 #include "lwip/api.h"
kevman 0:38ceb79fef03 29 #include "lwip/inet.h"
kevman 0:38ceb79fef03 30 #include "lwip/netif.h"
kevman 0:38ceb79fef03 31 #include "lwip/dhcp.h"
kevman 0:38ceb79fef03 32 #include "lwip/tcpip.h"
kevman 0:38ceb79fef03 33 #include "lwip/tcp.h"
kevman 0:38ceb79fef03 34 #include "lwip/ip.h"
kevman 0:38ceb79fef03 35 #include "lwip/mld6.h"
kevman 0:38ceb79fef03 36 #include "lwip/dns.h"
kevman 0:38ceb79fef03 37 #include "lwip/udp.h"
kevman 0:38ceb79fef03 38
kevman 0:38ceb79fef03 39 #include "ppp_lwip.h"
kevman 0:38ceb79fef03 40
kevman 0:38ceb79fef03 41 #include "LWIPStack.h"
kevman 0:38ceb79fef03 42
kevman 0:38ceb79fef03 43 LWIP::Interface *LWIP::Interface::list;
kevman 0:38ceb79fef03 44
kevman 0:38ceb79fef03 45 LWIP::Interface *LWIP::Interface::our_if_from_netif(struct netif *netif)
kevman 0:38ceb79fef03 46 {
kevman 0:38ceb79fef03 47 for (Interface *interface = list; interface; interface = interface->next) {
kevman 0:38ceb79fef03 48 if (netif == &interface->netif) {
kevman 0:38ceb79fef03 49 return interface;
kevman 0:38ceb79fef03 50 }
kevman 0:38ceb79fef03 51 }
kevman 0:38ceb79fef03 52
kevman 0:38ceb79fef03 53 return NULL;
kevman 0:38ceb79fef03 54 }
kevman 0:38ceb79fef03 55
kevman 0:38ceb79fef03 56 static void add_dns_addr_to_dns_list_index(const u8_t addr_type, const u8_t index)
kevman 0:38ceb79fef03 57 {
kevman 0:38ceb79fef03 58 #if LWIP_IPV6
kevman 0:38ceb79fef03 59 if (addr_type == IPADDR_TYPE_V6) {
kevman 0:38ceb79fef03 60 /* 2001:4860:4860::8888 google */
kevman 0:38ceb79fef03 61 ip_addr_t ipv6_dns_addr = IPADDR6_INIT(
kevman 0:38ceb79fef03 62 PP_HTONL(0x20014860UL),
kevman 0:38ceb79fef03 63 PP_HTONL(0x48600000UL),
kevman 0:38ceb79fef03 64 PP_HTONL(0x00000000UL),
kevman 0:38ceb79fef03 65 PP_HTONL(0x00008888UL));
kevman 0:38ceb79fef03 66 dns_setserver(index, &ipv6_dns_addr);
kevman 0:38ceb79fef03 67 }
kevman 0:38ceb79fef03 68 #endif
kevman 0:38ceb79fef03 69 #if LWIP_IPV4
kevman 0:38ceb79fef03 70 if (addr_type == IPADDR_TYPE_V4) {
kevman 0:38ceb79fef03 71 /* 8.8.8.8 google */
kevman 0:38ceb79fef03 72 ip_addr_t ipv4_dns_addr = IPADDR4_INIT(0x08080808);
kevman 0:38ceb79fef03 73 dns_setserver(index, &ipv4_dns_addr);
kevman 0:38ceb79fef03 74 }
kevman 0:38ceb79fef03 75 #endif
kevman 0:38ceb79fef03 76 }
kevman 0:38ceb79fef03 77
kevman 0:38ceb79fef03 78 static int get_ip_addr_type(const ip_addr_t *ip_addr)
kevman 0:38ceb79fef03 79 {
kevman 0:38ceb79fef03 80 #if LWIP_IPV6
kevman 0:38ceb79fef03 81 if (IP_IS_V6(ip_addr)) {
kevman 0:38ceb79fef03 82 return IPADDR_TYPE_V6;
kevman 0:38ceb79fef03 83 }
kevman 0:38ceb79fef03 84 #endif
kevman 0:38ceb79fef03 85 #if LWIP_IPV4
kevman 0:38ceb79fef03 86 if (IP_IS_V4(ip_addr)) {
kevman 0:38ceb79fef03 87 return IPADDR_TYPE_V4;
kevman 0:38ceb79fef03 88 }
kevman 0:38ceb79fef03 89 #endif
kevman 0:38ceb79fef03 90 #if LWIP_IPV6 && LWIP_IPV4
kevman 0:38ceb79fef03 91 return IPADDR_TYPE_ANY;
kevman 0:38ceb79fef03 92 #endif
kevman 0:38ceb79fef03 93 }
kevman 0:38ceb79fef03 94
kevman 0:38ceb79fef03 95 void LWIP::add_dns_addr(struct netif *lwip_netif)
kevman 0:38ceb79fef03 96 {
kevman 0:38ceb79fef03 97 // Check for existing dns address
kevman 0:38ceb79fef03 98 for (char numdns = 0; numdns < DNS_MAX_SERVERS; numdns++) {
kevman 0:38ceb79fef03 99 const ip_addr_t *dns_ip_addr = dns_getserver(numdns);
kevman 0:38ceb79fef03 100 if (!ip_addr_isany(dns_ip_addr)) {
kevman 0:38ceb79fef03 101 return;
kevman 0:38ceb79fef03 102 }
kevman 0:38ceb79fef03 103 }
kevman 0:38ceb79fef03 104
kevman 0:38ceb79fef03 105 // Get preferred ip version
kevman 0:38ceb79fef03 106 const ip_addr_t *ip_addr = get_ip_addr(false, lwip_netif);
kevman 0:38ceb79fef03 107 u8_t addr_type = IPADDR_TYPE_ANY;
kevman 0:38ceb79fef03 108
kevman 0:38ceb79fef03 109 // Add preferred ip version dns address to index 0
kevman 0:38ceb79fef03 110 if (ip_addr) {
kevman 0:38ceb79fef03 111 addr_type = get_ip_addr_type(ip_addr);
kevman 0:38ceb79fef03 112 add_dns_addr_to_dns_list_index(addr_type, 0);
kevman 0:38ceb79fef03 113 }
kevman 0:38ceb79fef03 114
kevman 0:38ceb79fef03 115 #if LWIP_IPV4 && LWIP_IPV6
kevman 0:38ceb79fef03 116 if (!ip_addr) {
kevman 0:38ceb79fef03 117 // Get address for any ip version
kevman 0:38ceb79fef03 118 ip_addr = get_ip_addr(true, lwip_netif);
kevman 0:38ceb79fef03 119 if (!ip_addr) {
kevman 0:38ceb79fef03 120 return;
kevman 0:38ceb79fef03 121 }
kevman 0:38ceb79fef03 122 addr_type = get_ip_addr_type(ip_addr);
kevman 0:38ceb79fef03 123 // Add the dns address to index 0
kevman 0:38ceb79fef03 124 add_dns_addr_to_dns_list_index(addr_type, 0);
kevman 0:38ceb79fef03 125 }
kevman 0:38ceb79fef03 126
kevman 0:38ceb79fef03 127 if (addr_type == IPADDR_TYPE_V4) {
kevman 0:38ceb79fef03 128 // If ipv4 is preferred and ipv6 is available add ipv6 dns address to index 1
kevman 0:38ceb79fef03 129 ip_addr = get_ipv6_addr(lwip_netif);
kevman 0:38ceb79fef03 130 } else if (addr_type == IPADDR_TYPE_V6) {
kevman 0:38ceb79fef03 131 // If ipv6 is preferred and ipv4 is available add ipv4 dns address to index 1
kevman 0:38ceb79fef03 132 ip_addr = get_ipv4_addr(lwip_netif);
kevman 0:38ceb79fef03 133 } else {
kevman 0:38ceb79fef03 134 ip_addr = NULL;
kevman 0:38ceb79fef03 135 }
kevman 0:38ceb79fef03 136
kevman 0:38ceb79fef03 137 if (ip_addr) {
kevman 0:38ceb79fef03 138 addr_type = get_ip_addr_type(ip_addr);
kevman 0:38ceb79fef03 139 add_dns_addr_to_dns_list_index(addr_type, 1);
kevman 0:38ceb79fef03 140 }
kevman 0:38ceb79fef03 141 #endif
kevman 0:38ceb79fef03 142 }
kevman 0:38ceb79fef03 143
kevman 0:38ceb79fef03 144 nsapi_error_t LWIP::Interface::set_dhcp()
kevman 0:38ceb79fef03 145 {
kevman 0:38ceb79fef03 146 netif_set_up(&netif);
kevman 0:38ceb79fef03 147
kevman 0:38ceb79fef03 148 #if LWIP_DHCP
kevman 0:38ceb79fef03 149 if (dhcp_has_to_be_set) {
kevman 0:38ceb79fef03 150 err_t err = dhcp_start(&netif);
kevman 0:38ceb79fef03 151 dhcp_has_to_be_set = false;
kevman 0:38ceb79fef03 152 if (err) {
kevman 0:38ceb79fef03 153 connected = NSAPI_STATUS_DISCONNECTED;
kevman 0:38ceb79fef03 154 if (client_callback) {
kevman 0:38ceb79fef03 155 client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED);
kevman 0:38ceb79fef03 156 }
kevman 0:38ceb79fef03 157 return NSAPI_ERROR_DHCP_FAILURE;
kevman 0:38ceb79fef03 158 }
kevman 0:38ceb79fef03 159 dhcp_started = true;
kevman 0:38ceb79fef03 160 }
kevman 0:38ceb79fef03 161 #endif
kevman 0:38ceb79fef03 162
kevman 0:38ceb79fef03 163 return NSAPI_ERROR_OK;
kevman 0:38ceb79fef03 164 }
kevman 0:38ceb79fef03 165
kevman 0:38ceb79fef03 166 void LWIP::Interface::netif_link_irq(struct netif *netif)
kevman 0:38ceb79fef03 167 {
kevman 0:38ceb79fef03 168 LWIP::Interface *interface = our_if_from_netif(netif);
kevman 0:38ceb79fef03 169 nsapi_connection_status_t connectedStatusPrev = interface->connected;
kevman 0:38ceb79fef03 170
kevman 0:38ceb79fef03 171 if (netif_is_link_up(&interface->netif) && interface->connected == NSAPI_STATUS_CONNECTING) {
kevman 0:38ceb79fef03 172 nsapi_error_t dhcp_status = interface->set_dhcp();
kevman 0:38ceb79fef03 173
kevman 0:38ceb79fef03 174 if (interface->blocking && dhcp_status == NSAPI_ERROR_OK) {
kevman 0:38ceb79fef03 175 osSemaphoreRelease(interface->linked);
kevman 0:38ceb79fef03 176 } else if (dhcp_status != NSAPI_ERROR_OK) {
kevman 0:38ceb79fef03 177 netif_set_down(&interface->netif);
kevman 0:38ceb79fef03 178 }
kevman 0:38ceb79fef03 179 } else {
kevman 0:38ceb79fef03 180 osSemaphoreRelease(interface->unlinked);
kevman 0:38ceb79fef03 181 if (netif_is_up(&interface->netif)) {
kevman 0:38ceb79fef03 182 interface->connected = NSAPI_STATUS_CONNECTING;
kevman 0:38ceb79fef03 183 }
kevman 0:38ceb79fef03 184 netif_set_down(&interface->netif);
kevman 0:38ceb79fef03 185 }
kevman 0:38ceb79fef03 186
kevman 0:38ceb79fef03 187 if (interface->client_callback && connectedStatusPrev != interface->connected
kevman 0:38ceb79fef03 188 && interface->connected != NSAPI_STATUS_GLOBAL_UP /* advertised by netif_status_irq */
kevman 0:38ceb79fef03 189 && interface->connected != NSAPI_STATUS_DISCONNECTED) /* advertised by bring_down */ {
kevman 0:38ceb79fef03 190 interface->client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, interface->connected);
kevman 0:38ceb79fef03 191 }
kevman 0:38ceb79fef03 192 }
kevman 0:38ceb79fef03 193
kevman 0:38ceb79fef03 194 void LWIP::Interface::netif_status_irq(struct netif *netif)
kevman 0:38ceb79fef03 195 {
kevman 0:38ceb79fef03 196 LWIP::Interface *interface = our_if_from_netif(netif);
kevman 0:38ceb79fef03 197 nsapi_connection_status_t connectedStatusPrev = interface->connected;
kevman 0:38ceb79fef03 198
kevman 0:38ceb79fef03 199 if (netif_is_up(&interface->netif) && netif_is_link_up(&interface->netif)) {
kevman 0:38ceb79fef03 200 bool dns_addr_has_to_be_added = false;
kevman 0:38ceb79fef03 201 if (!(interface->has_addr_state & HAS_ANY_ADDR) && LWIP::get_ip_addr(true, netif)) {
kevman 0:38ceb79fef03 202 if (interface->blocking) {
kevman 0:38ceb79fef03 203 osSemaphoreRelease(interface->has_any_addr);
kevman 0:38ceb79fef03 204 }
kevman 0:38ceb79fef03 205 interface->has_addr_state |= HAS_ANY_ADDR;
kevman 0:38ceb79fef03 206 dns_addr_has_to_be_added = true;
kevman 0:38ceb79fef03 207 }
kevman 0:38ceb79fef03 208 #if PREF_ADDR_TIMEOUT
kevman 0:38ceb79fef03 209 if (!(interface->has_addr_state & HAS_PREF_ADDR) && LWIP::get_ip_addr(false, netif)) {
kevman 0:38ceb79fef03 210 if (interface->blocking) {
kevman 0:38ceb79fef03 211 osSemaphoreRelease(interface->has_pref_addr);
kevman 0:38ceb79fef03 212 }
kevman 0:38ceb79fef03 213 interface->has_addr_state |= HAS_PREF_ADDR;
kevman 0:38ceb79fef03 214 dns_addr_has_to_be_added = true;
kevman 0:38ceb79fef03 215 }
kevman 0:38ceb79fef03 216 #endif
kevman 0:38ceb79fef03 217 #if BOTH_ADDR_TIMEOUT
kevman 0:38ceb79fef03 218 if (!(interface->has_addr_state & HAS_BOTH_ADDR) && LWIP::get_ipv4_addr(netif) && LWIP::get_ipv6_addr(netif)) {
kevman 0:38ceb79fef03 219 if (interface->blocking) {
kevman 0:38ceb79fef03 220 osSemaphoreRelease(interface->has_both_addr);
kevman 0:38ceb79fef03 221 }
kevman 0:38ceb79fef03 222 interface->has_addr_state |= HAS_BOTH_ADDR;
kevman 0:38ceb79fef03 223 dns_addr_has_to_be_added = true;
kevman 0:38ceb79fef03 224 }
kevman 0:38ceb79fef03 225 #endif
kevman 0:38ceb79fef03 226 if (dns_addr_has_to_be_added && !interface->blocking) {
kevman 0:38ceb79fef03 227 add_dns_addr(&interface->netif);
kevman 0:38ceb79fef03 228 }
kevman 0:38ceb79fef03 229
kevman 0:38ceb79fef03 230 if (interface->has_addr_state & HAS_ANY_ADDR) {
kevman 0:38ceb79fef03 231 interface->connected = NSAPI_STATUS_GLOBAL_UP;
kevman 0:38ceb79fef03 232 }
kevman 0:38ceb79fef03 233 } else if (!netif_is_up(&interface->netif) && netif_is_link_up(&interface->netif)) {
kevman 0:38ceb79fef03 234 interface->connected = NSAPI_STATUS_DISCONNECTED;
kevman 0:38ceb79fef03 235 }
kevman 0:38ceb79fef03 236
kevman 0:38ceb79fef03 237 if (interface->client_callback && (connectedStatusPrev != interface->connected)
kevman 0:38ceb79fef03 238 && interface->connected != NSAPI_STATUS_DISCONNECTED) /* advertised by bring_down */ {
kevman 0:38ceb79fef03 239 interface->client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, interface->connected);
kevman 0:38ceb79fef03 240 }
kevman 0:38ceb79fef03 241 }
kevman 0:38ceb79fef03 242
kevman 0:38ceb79fef03 243 void LWIP::Interface::attach(mbed::Callback<void(nsapi_event_t, intptr_t)> status_cb)
kevman 0:38ceb79fef03 244 {
kevman 0:38ceb79fef03 245 client_callback = status_cb;
kevman 0:38ceb79fef03 246 }
kevman 0:38ceb79fef03 247
kevman 0:38ceb79fef03 248 nsapi_connection_status_t LWIP::Interface::get_connection_status() const
kevman 0:38ceb79fef03 249 {
kevman 0:38ceb79fef03 250 return connected;
kevman 0:38ceb79fef03 251 }
kevman 0:38ceb79fef03 252
kevman 0:38ceb79fef03 253 #if LWIP_IPV6
kevman 0:38ceb79fef03 254 static void mbed_lwip_clear_ipv6_addresses(struct netif *netif)
kevman 0:38ceb79fef03 255 {
kevman 0:38ceb79fef03 256 for (u8_t i = 0; i < LWIP_IPV6_NUM_ADDRESSES; i++) {
kevman 0:38ceb79fef03 257 netif_ip6_addr_set_state(netif, i, IP6_ADDR_INVALID);
kevman 0:38ceb79fef03 258 }
kevman 0:38ceb79fef03 259 }
kevman 0:38ceb79fef03 260 #endif
kevman 0:38ceb79fef03 261
kevman 0:38ceb79fef03 262 char *LWIP::Interface::get_mac_address(char *buf, nsapi_size_t buflen)
kevman 0:38ceb79fef03 263 {
kevman 0:38ceb79fef03 264 (void) snprintf(buf, buflen, "%02x:%02x:%02x:%02x:%02x:%02x",
kevman 0:38ceb79fef03 265 netif.hwaddr[0], netif.hwaddr[1], netif.hwaddr[2],
kevman 0:38ceb79fef03 266 netif.hwaddr[3], netif.hwaddr[4], netif.hwaddr[5]);
kevman 0:38ceb79fef03 267 return buf;
kevman 0:38ceb79fef03 268 }
kevman 0:38ceb79fef03 269
kevman 0:38ceb79fef03 270 char *LWIP::Interface::get_ip_address(char *buf, nsapi_size_t buflen)
kevman 0:38ceb79fef03 271 {
kevman 0:38ceb79fef03 272 const ip_addr_t *addr = LWIP::get_ip_addr(true, &netif);
kevman 0:38ceb79fef03 273 if (!addr) {
kevman 0:38ceb79fef03 274 return NULL;
kevman 0:38ceb79fef03 275 }
kevman 0:38ceb79fef03 276 #if LWIP_IPV6
kevman 0:38ceb79fef03 277 if (IP_IS_V6(addr)) {
kevman 0:38ceb79fef03 278 return ip6addr_ntoa_r(ip_2_ip6(addr), buf, buflen);
kevman 0:38ceb79fef03 279 }
kevman 0:38ceb79fef03 280 #endif
kevman 0:38ceb79fef03 281 #if LWIP_IPV4
kevman 0:38ceb79fef03 282 if (IP_IS_V4(addr)) {
kevman 0:38ceb79fef03 283 return ip4addr_ntoa_r(ip_2_ip4(addr), buf, buflen);
kevman 0:38ceb79fef03 284 }
kevman 0:38ceb79fef03 285 #endif
kevman 0:38ceb79fef03 286 #if LWIP_IPV6 && LWIP_IPV4
kevman 0:38ceb79fef03 287 return NULL;
kevman 0:38ceb79fef03 288 #endif
kevman 0:38ceb79fef03 289 }
kevman 0:38ceb79fef03 290
kevman 0:38ceb79fef03 291 char *LWIP::Interface::get_netmask(char *buf, nsapi_size_t buflen)
kevman 0:38ceb79fef03 292 {
kevman 0:38ceb79fef03 293 #if LWIP_IPV4
kevman 0:38ceb79fef03 294 const ip4_addr_t *addr = netif_ip4_netmask(&netif);
kevman 0:38ceb79fef03 295 if (!ip4_addr_isany(addr)) {
kevman 0:38ceb79fef03 296 return ip4addr_ntoa_r(addr, buf, buflen);
kevman 0:38ceb79fef03 297 } else {
kevman 0:38ceb79fef03 298 return NULL;
kevman 0:38ceb79fef03 299 }
kevman 0:38ceb79fef03 300 #else
kevman 0:38ceb79fef03 301 return NULL;
kevman 0:38ceb79fef03 302 #endif
kevman 0:38ceb79fef03 303 }
kevman 0:38ceb79fef03 304
kevman 0:38ceb79fef03 305 char *LWIP::Interface::get_gateway(char *buf, nsapi_size_t buflen)
kevman 0:38ceb79fef03 306 {
kevman 0:38ceb79fef03 307 #if LWIP_IPV4
kevman 0:38ceb79fef03 308 const ip4_addr_t *addr = netif_ip4_gw(&netif);
kevman 0:38ceb79fef03 309 if (!ip4_addr_isany(addr)) {
kevman 0:38ceb79fef03 310 return ip4addr_ntoa_r(addr, buf, buflen);
kevman 0:38ceb79fef03 311 } else {
kevman 0:38ceb79fef03 312 return NULL;
kevman 0:38ceb79fef03 313 }
kevman 0:38ceb79fef03 314 #else
kevman 0:38ceb79fef03 315 return NULL;
kevman 0:38ceb79fef03 316 #endif
kevman 0:38ceb79fef03 317 }
kevman 0:38ceb79fef03 318
kevman 0:38ceb79fef03 319 LWIP::Interface::Interface() :
kevman 0:38ceb79fef03 320 hw(NULL), has_addr_state(0),
kevman 0:38ceb79fef03 321 connected(NSAPI_STATUS_DISCONNECTED),
kevman 0:38ceb79fef03 322 dhcp_started(false), dhcp_has_to_be_set(false), blocking(true), ppp(false)
kevman 0:38ceb79fef03 323 {
kevman 0:38ceb79fef03 324 memset(&netif, 0, sizeof netif);
kevman 0:38ceb79fef03 325
kevman 0:38ceb79fef03 326 osSemaphoreAttr_t attr;
kevman 0:38ceb79fef03 327 attr.name = NULL;
kevman 0:38ceb79fef03 328 attr.attr_bits = 0;
kevman 0:38ceb79fef03 329
kevman 0:38ceb79fef03 330 attr.cb_mem = &linked_sem;
kevman 0:38ceb79fef03 331 attr.cb_size = sizeof linked_sem;
kevman 0:38ceb79fef03 332 linked = osSemaphoreNew(UINT16_MAX, 0, &attr);
kevman 0:38ceb79fef03 333
kevman 0:38ceb79fef03 334 attr.cb_mem = &unlinked_sem;
kevman 0:38ceb79fef03 335 attr.cb_size = sizeof unlinked_sem;
kevman 0:38ceb79fef03 336 unlinked = osSemaphoreNew(UINT16_MAX, 0, &attr);
kevman 0:38ceb79fef03 337
kevman 0:38ceb79fef03 338 attr.cb_mem = &has_any_addr_sem;
kevman 0:38ceb79fef03 339 attr.cb_size = sizeof has_any_addr_sem;
kevman 0:38ceb79fef03 340 has_any_addr = osSemaphoreNew(UINT16_MAX, 0, &attr);
kevman 0:38ceb79fef03 341 #if PREF_ADDR_TIMEOUT
kevman 0:38ceb79fef03 342 attr.cb_mem = &has_pref_addr_sem;
kevman 0:38ceb79fef03 343 attr.cb_size = sizeof has_pref_addr_sem;
kevman 0:38ceb79fef03 344 has_pref_addr = osSemaphoreNew(UINT16_MAX, 0, &attr);
kevman 0:38ceb79fef03 345 #endif
kevman 0:38ceb79fef03 346 #if BOTH_ADDR_TIMEOUT
kevman 0:38ceb79fef03 347 attr.cb_mem = &has_both_addr_sem;
kevman 0:38ceb79fef03 348 attr.cb_size = sizeof has_both_addr_sem;
kevman 0:38ceb79fef03 349 has_both_addr = osSemaphoreNew(UINT16_MAX, 0, &attr);
kevman 0:38ceb79fef03 350 #endif
kevman 0:38ceb79fef03 351
kevman 0:38ceb79fef03 352 next = list;
kevman 0:38ceb79fef03 353 list = this;
kevman 0:38ceb79fef03 354 }
kevman 0:38ceb79fef03 355
kevman 0:38ceb79fef03 356 nsapi_error_t LWIP::add_ethernet_interface(EMAC &emac, bool default_if, OnboardNetworkStack::Interface **interface_out)
kevman 0:38ceb79fef03 357 {
kevman 0:38ceb79fef03 358 #if LWIP_ETHERNET
kevman 0:38ceb79fef03 359 Interface *interface = new (std::nothrow) Interface();
kevman 0:38ceb79fef03 360 if (!interface) {
kevman 0:38ceb79fef03 361 return NSAPI_ERROR_NO_MEMORY;
kevman 0:38ceb79fef03 362 }
kevman 0:38ceb79fef03 363 interface->emac = &emac;
kevman 0:38ceb79fef03 364 interface->memory_manager = &memory_manager;
kevman 0:38ceb79fef03 365 interface->ppp = false;
kevman 0:38ceb79fef03 366
kevman 0:38ceb79fef03 367 #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
kevman 0:38ceb79fef03 368 netif->interface.hwaddr[0] = MBED_MAC_ADDR_0;
kevman 0:38ceb79fef03 369 netif->interface.hwaddr[1] = MBED_MAC_ADDR_1;
kevman 0:38ceb79fef03 370 netif->interface.hwaddr[2] = MBED_MAC_ADDR_2;
kevman 0:38ceb79fef03 371 netif->interface.hwaddr[3] = MBED_MAC_ADDR_3;
kevman 0:38ceb79fef03 372 netif->interface.hwaddr[4] = MBED_MAC_ADDR_4;
kevman 0:38ceb79fef03 373 netif->interface.hwaddr[5] = MBED_MAC_ADDR_5;
kevman 0:38ceb79fef03 374 #else
kevman 0:38ceb79fef03 375 mbed_mac_address((char *) interface->netif.hwaddr);
kevman 0:38ceb79fef03 376 #endif
kevman 0:38ceb79fef03 377
kevman 0:38ceb79fef03 378 interface->netif.hwaddr_len = 6;
kevman 0:38ceb79fef03 379
kevman 0:38ceb79fef03 380 if (!netif_add(&interface->netif,
kevman 0:38ceb79fef03 381 #if LWIP_IPV4
kevman 0:38ceb79fef03 382 0, 0, 0,
kevman 0:38ceb79fef03 383 #endif
kevman 0:38ceb79fef03 384 interface, &LWIP::Interface::emac_if_init, tcpip_input)) {
kevman 0:38ceb79fef03 385 return NSAPI_ERROR_DEVICE_ERROR;
kevman 0:38ceb79fef03 386 }
kevman 0:38ceb79fef03 387
kevman 0:38ceb79fef03 388 if (default_if) {
kevman 0:38ceb79fef03 389 netif_set_default(&interface->netif);
kevman 0:38ceb79fef03 390 default_interface = interface;
kevman 0:38ceb79fef03 391 }
kevman 0:38ceb79fef03 392
kevman 0:38ceb79fef03 393 netif_set_link_callback(&interface->netif, &LWIP::Interface::netif_link_irq);
kevman 0:38ceb79fef03 394 netif_set_status_callback(&interface->netif, &LWIP::Interface::netif_status_irq);
kevman 0:38ceb79fef03 395
kevman 0:38ceb79fef03 396 *interface_out = interface;
kevman 0:38ceb79fef03 397
kevman 0:38ceb79fef03 398 /* Use mac address as additional seed to random number generator */
kevman 0:38ceb79fef03 399 uint64_t seed = interface->netif.hwaddr[0];
kevman 0:38ceb79fef03 400 for (uint8_t i = 1; i < 8; i++) {
kevman 0:38ceb79fef03 401 seed <<= 8;
kevman 0:38ceb79fef03 402 seed |= interface->netif.hwaddr[i % 6];
kevman 0:38ceb79fef03 403 }
kevman 0:38ceb79fef03 404 lwip_add_random_seed(seed);
kevman 0:38ceb79fef03 405
kevman 0:38ceb79fef03 406 return NSAPI_ERROR_OK;
kevman 0:38ceb79fef03 407 #else
kevman 0:38ceb79fef03 408 return NSAPI_ERROR_UNSUPPORTED;
kevman 0:38ceb79fef03 409 #endif //LWIP_ETHERNET
kevman 0:38ceb79fef03 410 }
kevman 0:38ceb79fef03 411
kevman 0:38ceb79fef03 412 /* Internal API to preserve existing PPP functionality - revise to better match mbed_ipstak_add_ethernet_interface later */
kevman 0:38ceb79fef03 413 nsapi_error_t LWIP::_add_ppp_interface(void *hw, bool default_if, nsapi_ip_stack_t stack, LWIP::Interface **interface_out)
kevman 0:38ceb79fef03 414 {
kevman 0:38ceb79fef03 415 #if LWIP_PPP_API
kevman 0:38ceb79fef03 416 Interface *interface = new (std::nothrow) Interface();
kevman 0:38ceb79fef03 417 if (!interface) {
kevman 0:38ceb79fef03 418 return NSAPI_ERROR_NO_MEMORY;
kevman 0:38ceb79fef03 419 }
kevman 0:38ceb79fef03 420 interface->hw = hw;
kevman 0:38ceb79fef03 421 interface->ppp = true;
kevman 0:38ceb79fef03 422
kevman 0:38ceb79fef03 423 nsapi_error_t ret = ppp_lwip_if_init(hw, &interface->netif, stack);
kevman 0:38ceb79fef03 424 if (ret != NSAPI_ERROR_OK) {
kevman 0:38ceb79fef03 425 free(interface);
kevman 0:38ceb79fef03 426 return ret;
kevman 0:38ceb79fef03 427 }
kevman 0:38ceb79fef03 428
kevman 0:38ceb79fef03 429 if (default_if) {
kevman 0:38ceb79fef03 430 netif_set_default(&interface->netif);
kevman 0:38ceb79fef03 431 default_interface = interface;
kevman 0:38ceb79fef03 432 }
kevman 0:38ceb79fef03 433
kevman 0:38ceb79fef03 434 netif_set_link_callback(&interface->netif, &LWIP::Interface::netif_link_irq);
kevman 0:38ceb79fef03 435 netif_set_status_callback(&interface->netif, &LWIP::Interface::netif_status_irq);
kevman 0:38ceb79fef03 436
kevman 0:38ceb79fef03 437 *interface_out = interface;
kevman 0:38ceb79fef03 438
kevman 0:38ceb79fef03 439 return NSAPI_ERROR_OK;
kevman 0:38ceb79fef03 440 #else
kevman 0:38ceb79fef03 441 return NSAPI_ERROR_UNSUPPORTED;
kevman 0:38ceb79fef03 442 #endif //LWIP_PPP_API
kevman 0:38ceb79fef03 443 }
kevman 0:38ceb79fef03 444
kevman 0:38ceb79fef03 445
kevman 0:38ceb79fef03 446 nsapi_error_t LWIP::Interface::bringup(bool dhcp, const char *ip, const char *netmask, const char *gw, const nsapi_ip_stack_t stack, bool block)
kevman 0:38ceb79fef03 447 {
kevman 0:38ceb79fef03 448 // Check if we've already connected
kevman 0:38ceb79fef03 449 if (connected == NSAPI_STATUS_GLOBAL_UP) {
kevman 0:38ceb79fef03 450 return NSAPI_ERROR_IS_CONNECTED;
kevman 0:38ceb79fef03 451 } else if (connected == NSAPI_STATUS_CONNECTING) {
kevman 0:38ceb79fef03 452 return NSAPI_ERROR_ALREADY;
kevman 0:38ceb79fef03 453 }
kevman 0:38ceb79fef03 454
kevman 0:38ceb79fef03 455 connected = NSAPI_STATUS_CONNECTING;
kevman 0:38ceb79fef03 456 blocking = block;
kevman 0:38ceb79fef03 457
kevman 0:38ceb79fef03 458 #if LWIP_DHCP
kevman 0:38ceb79fef03 459 if (stack != IPV6_STACK && dhcp) {
kevman 0:38ceb79fef03 460 dhcp_has_to_be_set = true;
kevman 0:38ceb79fef03 461 }
kevman 0:38ceb79fef03 462 #endif
kevman 0:38ceb79fef03 463
kevman 0:38ceb79fef03 464 #if LWIP_IPV6
kevman 0:38ceb79fef03 465 if (stack != IPV4_STACK) {
kevman 0:38ceb79fef03 466 if (netif.hwaddr_len == 6) {
kevman 0:38ceb79fef03 467 netif_create_ip6_linklocal_address(&netif, 1/*from MAC*/);
kevman 0:38ceb79fef03 468 }
kevman 0:38ceb79fef03 469 #if LWIP_IPV6_MLD
kevman 0:38ceb79fef03 470 /*
kevman 0:38ceb79fef03 471 * For hardware/netifs that implement MAC filtering.
kevman 0:38ceb79fef03 472 * All-nodes link-local is handled by default, so we must let the hardware know
kevman 0:38ceb79fef03 473 * to allow multicast packets in.
kevman 0:38ceb79fef03 474 * Should set mld_mac_filter previously. */
kevman 0:38ceb79fef03 475 if (netif.mld_mac_filter != NULL) {
kevman 0:38ceb79fef03 476 ip6_addr_t ip6_allnodes_ll;
kevman 0:38ceb79fef03 477 ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
kevman 0:38ceb79fef03 478 netif.mld_mac_filter(&netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
kevman 0:38ceb79fef03 479 }
kevman 0:38ceb79fef03 480 #endif /* LWIP_IPV6_MLD */
kevman 0:38ceb79fef03 481
kevman 0:38ceb79fef03 482 #if LWIP_IPV6_AUTOCONFIG
kevman 0:38ceb79fef03 483 /* IPv6 address autoconfiguration not enabled by default */
kevman 0:38ceb79fef03 484 netif.ip6_autoconfig_enabled = 1;
kevman 0:38ceb79fef03 485 #endif /* LWIP_IPV6_AUTOCONFIG */
kevman 0:38ceb79fef03 486 } else {
kevman 0:38ceb79fef03 487 // Disable rourter solicitations
kevman 0:38ceb79fef03 488 netif.rs_count = 0;
kevman 0:38ceb79fef03 489 }
kevman 0:38ceb79fef03 490 #endif /* LWIP_IPV6 */
kevman 0:38ceb79fef03 491
kevman 0:38ceb79fef03 492 #if LWIP_IPV4
kevman 0:38ceb79fef03 493 if (stack != IPV6_STACK) {
kevman 0:38ceb79fef03 494 if (!dhcp && !ppp) {
kevman 0:38ceb79fef03 495 ip4_addr_t ip_addr;
kevman 0:38ceb79fef03 496 ip4_addr_t netmask_addr;
kevman 0:38ceb79fef03 497 ip4_addr_t gw_addr;
kevman 0:38ceb79fef03 498
kevman 0:38ceb79fef03 499 if (!inet_aton(ip, &ip_addr) ||
kevman 0:38ceb79fef03 500 !inet_aton(netmask, &netmask_addr) ||
kevman 0:38ceb79fef03 501 !inet_aton(gw, &gw_addr)) {
kevman 0:38ceb79fef03 502 return NSAPI_ERROR_PARAMETER;
kevman 0:38ceb79fef03 503 }
kevman 0:38ceb79fef03 504
kevman 0:38ceb79fef03 505 netif_set_addr(&netif, &ip_addr, &netmask_addr, &gw_addr);
kevman 0:38ceb79fef03 506 }
kevman 0:38ceb79fef03 507 }
kevman 0:38ceb79fef03 508 #endif
kevman 0:38ceb79fef03 509
kevman 0:38ceb79fef03 510 if (client_callback) {
kevman 0:38ceb79fef03 511 client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_CONNECTING);
kevman 0:38ceb79fef03 512 }
kevman 0:38ceb79fef03 513
kevman 0:38ceb79fef03 514 if (ppp) {
kevman 0:38ceb79fef03 515 err_t err = ppp_lwip_connect(hw);
kevman 0:38ceb79fef03 516 if (err) {
kevman 0:38ceb79fef03 517 connected = NSAPI_STATUS_DISCONNECTED;
kevman 0:38ceb79fef03 518 if (client_callback) {
kevman 0:38ceb79fef03 519 client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, NSAPI_STATUS_DISCONNECTED);
kevman 0:38ceb79fef03 520 }
kevman 0:38ceb79fef03 521 return err_remap(err);
kevman 0:38ceb79fef03 522 }
kevman 0:38ceb79fef03 523 }
kevman 0:38ceb79fef03 524
kevman 0:38ceb79fef03 525 if (!netif_is_link_up(&netif)) {
kevman 0:38ceb79fef03 526 if (blocking) {
kevman 0:38ceb79fef03 527 if (osSemaphoreAcquire(linked, 15000) != osOK) {
kevman 0:38ceb79fef03 528 if (ppp) {
kevman 0:38ceb79fef03 529 (void) ppp_lwip_disconnect(hw);
kevman 0:38ceb79fef03 530 }
kevman 0:38ceb79fef03 531 return NSAPI_ERROR_NO_CONNECTION;
kevman 0:38ceb79fef03 532 }
kevman 0:38ceb79fef03 533 }
kevman 0:38ceb79fef03 534 } else {
kevman 0:38ceb79fef03 535 nsapi_error_t ret = set_dhcp();
kevman 0:38ceb79fef03 536 if (ret != NSAPI_ERROR_OK) {
kevman 0:38ceb79fef03 537 return ret;
kevman 0:38ceb79fef03 538 }
kevman 0:38ceb79fef03 539 }
kevman 0:38ceb79fef03 540
kevman 0:38ceb79fef03 541 if (!blocking) {
kevman 0:38ceb79fef03 542 // Done enough - as addresses are acquired, there will be
kevman 0:38ceb79fef03 543 // connected callbacks.
kevman 0:38ceb79fef03 544 // XXX shouldn't this be NSAPI_ERROR_IN_PROGRESS if in CONNECTING state?
kevman 0:38ceb79fef03 545 return NSAPI_ERROR_OK;
kevman 0:38ceb79fef03 546 }
kevman 0:38ceb79fef03 547
kevman 0:38ceb79fef03 548 // If doesn't have address
kevman 0:38ceb79fef03 549 if (!LWIP::get_ip_addr(true, &netif)) {
kevman 0:38ceb79fef03 550 if (osSemaphoreAcquire(has_any_addr, DHCP_TIMEOUT * 1000) != osOK) {
kevman 0:38ceb79fef03 551 if (ppp) {
kevman 0:38ceb79fef03 552 (void) ppp_lwip_disconnect(hw);
kevman 0:38ceb79fef03 553 }
kevman 0:38ceb79fef03 554 return NSAPI_ERROR_DHCP_FAILURE;
kevman 0:38ceb79fef03 555 }
kevman 0:38ceb79fef03 556 }
kevman 0:38ceb79fef03 557
kevman 0:38ceb79fef03 558 #if PREF_ADDR_TIMEOUT
kevman 0:38ceb79fef03 559 if (stack != IPV4_STACK && stack != IPV6_STACK) {
kevman 0:38ceb79fef03 560 // If address is not for preferred stack waits a while to see
kevman 0:38ceb79fef03 561 // if preferred stack address is acquired
kevman 0:38ceb79fef03 562 if (!LWIP::get_ip_addr(false, &netif)) {
kevman 0:38ceb79fef03 563 osSemaphoreAcquire(has_pref_addr, PREF_ADDR_TIMEOUT * 1000);
kevman 0:38ceb79fef03 564 }
kevman 0:38ceb79fef03 565 }
kevman 0:38ceb79fef03 566 #endif
kevman 0:38ceb79fef03 567 #if BOTH_ADDR_TIMEOUT
kevman 0:38ceb79fef03 568 if (stack != IPV4_STACK && stack != IPV6_STACK) {
kevman 0:38ceb79fef03 569 // If addresses for both stacks are not available waits a while to
kevman 0:38ceb79fef03 570 // see if address for both stacks are acquired
kevman 0:38ceb79fef03 571 if (!(LWIP::get_ipv4_addr(&netif) && LWIP::get_ipv6_addr(&netif))) {
kevman 0:38ceb79fef03 572 osSemaphoreAcquire(has_both_addr, BOTH_ADDR_TIMEOUT * 1000);
kevman 0:38ceb79fef03 573 }
kevman 0:38ceb79fef03 574 }
kevman 0:38ceb79fef03 575 #endif
kevman 0:38ceb79fef03 576
kevman 0:38ceb79fef03 577 add_dns_addr(&netif);
kevman 0:38ceb79fef03 578
kevman 0:38ceb79fef03 579 return NSAPI_ERROR_OK;
kevman 0:38ceb79fef03 580 }
kevman 0:38ceb79fef03 581
kevman 0:38ceb79fef03 582 nsapi_error_t LWIP::Interface::bringdown()
kevman 0:38ceb79fef03 583 {
kevman 0:38ceb79fef03 584 // Check if we've connected
kevman 0:38ceb79fef03 585 if (connected == NSAPI_STATUS_DISCONNECTED) {
kevman 0:38ceb79fef03 586 return NSAPI_ERROR_PARAMETER;
kevman 0:38ceb79fef03 587 }
kevman 0:38ceb79fef03 588
kevman 0:38ceb79fef03 589 #if LWIP_DHCP
kevman 0:38ceb79fef03 590 // Disconnect from the network
kevman 0:38ceb79fef03 591 if (dhcp_started) {
kevman 0:38ceb79fef03 592 dhcp_release(&netif);
kevman 0:38ceb79fef03 593 dhcp_stop(&netif);
kevman 0:38ceb79fef03 594 dhcp_started = false;
kevman 0:38ceb79fef03 595 dhcp_has_to_be_set = false;
kevman 0:38ceb79fef03 596 }
kevman 0:38ceb79fef03 597 #endif
kevman 0:38ceb79fef03 598
kevman 0:38ceb79fef03 599 if (ppp) {
kevman 0:38ceb79fef03 600 /* this is a blocking call, returns when PPP is properly closed */
kevman 0:38ceb79fef03 601 err_t err = ppp_lwip_disconnect(hw);
kevman 0:38ceb79fef03 602 if (err) {
kevman 0:38ceb79fef03 603 return err_remap(err);
kevman 0:38ceb79fef03 604 }
kevman 0:38ceb79fef03 605 MBED_ASSERT(!netif_is_link_up(&netif));
kevman 0:38ceb79fef03 606 /*if (netif_is_link_up(&netif)) {
kevman 0:38ceb79fef03 607 if (sys_arch_sem_wait(&unlinked, 15000) == SYS_ARCH_TIMEOUT) {
kevman 0:38ceb79fef03 608 return NSAPI_ERROR_DEVICE_ERROR;
kevman 0:38ceb79fef03 609 }
kevman 0:38ceb79fef03 610 }*/
kevman 0:38ceb79fef03 611 } else {
kevman 0:38ceb79fef03 612 netif_set_down(&netif);
kevman 0:38ceb79fef03 613 }
kevman 0:38ceb79fef03 614
kevman 0:38ceb79fef03 615 #if LWIP_IPV6
kevman 0:38ceb79fef03 616 mbed_lwip_clear_ipv6_addresses(&netif);
kevman 0:38ceb79fef03 617 #endif
kevman 0:38ceb79fef03 618 #if LWIP_IPV4
kevman 0:38ceb79fef03 619 ip_addr_set_zero(&(netif.ip_addr));
kevman 0:38ceb79fef03 620 ip_addr_set_zero(&(netif.netmask));
kevman 0:38ceb79fef03 621 ip_addr_set_zero(&(netif.gw));
kevman 0:38ceb79fef03 622 #endif
kevman 0:38ceb79fef03 623
kevman 0:38ceb79fef03 624 osSemaphoreDelete(has_any_addr);
kevman 0:38ceb79fef03 625 osSemaphoreAttr_t attr;
kevman 0:38ceb79fef03 626 attr.name = NULL;
kevman 0:38ceb79fef03 627 attr.attr_bits = 0;
kevman 0:38ceb79fef03 628 attr.cb_mem = &has_any_addr_sem;
kevman 0:38ceb79fef03 629 attr.cb_size = sizeof has_any_addr_sem;
kevman 0:38ceb79fef03 630 has_any_addr = osSemaphoreNew(UINT16_MAX, 0, &attr);
kevman 0:38ceb79fef03 631 #if PREF_ADDR_TIMEOUT
kevman 0:38ceb79fef03 632 osSemaphoreDelete(has_pref_addr);
kevman 0:38ceb79fef03 633 attr.cb_mem = &has_pref_addr_sem;
kevman 0:38ceb79fef03 634 attr.cb_size = sizeof has_pref_addr_sem;
kevman 0:38ceb79fef03 635 has_pref_addr = osSemaphoreNew(UINT16_MAX, 0, &attr);
kevman 0:38ceb79fef03 636 #endif
kevman 0:38ceb79fef03 637 #if BOTH_ADDR_TIMEOUT
kevman 0:38ceb79fef03 638 osSemaphoreDelete(has_both_addr);
kevman 0:38ceb79fef03 639 attr.cb_mem = &has_both_addr_sem;
kevman 0:38ceb79fef03 640 attr.cb_size = sizeof has_both_addr_sem;
kevman 0:38ceb79fef03 641 has_both_addr = osSemaphoreNew(UINT16_MAX, 0, &attr);
kevman 0:38ceb79fef03 642 #endif
kevman 0:38ceb79fef03 643 has_addr_state = 0;
kevman 0:38ceb79fef03 644
kevman 0:38ceb79fef03 645 connected = NSAPI_STATUS_DISCONNECTED;
kevman 0:38ceb79fef03 646 if (client_callback) {
kevman 0:38ceb79fef03 647 client_callback(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, connected);
kevman 0:38ceb79fef03 648 }
kevman 0:38ceb79fef03 649 return 0;
kevman 0:38ceb79fef03 650 }