Added ipv6 support to lwip dns adaptation and updated dchp functionality

pull/2767/head
Mika Leppänen 2016-09-22 14:24:11 +03:00
parent 283ee52228
commit 95383dde32
3 changed files with 109 additions and 62 deletions

View File

@ -29,7 +29,9 @@
#include "lwip/tcpip.h"
#include "lwip/tcp.h"
#include "lwip/ip.h"
#include "lwip/mld6.h"
#include "lwip/dns.h"
#include "lwip/udp.h"
/* Static arena of sockets */
static struct lwip_socket {
@ -94,6 +96,7 @@ static struct netif lwip_netif;
static bool lwip_dhcp = false;
static char lwip_mac_address[NSAPI_MAC_SIZE] = "\0";
#if !LWIP_IPV4 || !LWIP_IPV6
static bool all_zeros(const uint8_t *p, int len)
{
for (int i = 0; i < len; i++) {
@ -104,6 +107,7 @@ static bool all_zeros(const uint8_t *p, int len)
return true;
}
#endif
static bool convert_mbed_addr_to_lwip(ip_addr_t *out, const nsapi_addr_t *in)
{
@ -196,8 +200,8 @@ static const ip_addr_t *lwip_get_ipv6_addr(const struct netif *netif)
const ip_addr_t *lwip_get_ip_addr(bool any_addr, const struct netif *netif)
{
const ip_addr_t *pref_ip_addr;
const ip_addr_t *npref_ip_addr;
const ip_addr_t *pref_ip_addr = 0;
const ip_addr_t *npref_ip_addr = 0;
#if IP_VERSION_PREF == PREF_IPV4
pref_ip_addr = lwip_get_ipv4_addr(netif);
@ -216,6 +220,37 @@ const ip_addr_t *lwip_get_ip_addr(bool any_addr, const struct netif *netif)
return NULL;
}
#if LWIP_IPV6
void add_dns_addr(struct netif *lwip_netif)
{
const ip_addr_t *ip_addr = lwip_get_ip_addr(true, lwip_netif);
if (ip_addr) {
if (IP_IS_V6(ip_addr)) {
const ip_addr_t *dns_ip_addr;
bool dns_addr_exists = false;
for (char numdns = 0; numdns < DNS_MAX_SERVERS; numdns++) {
dns_ip_addr = dns_getserver(numdns);
if (!ip_addr_isany(dns_ip_addr)) {
dns_addr_exists = true;
break;
}
}
if (!dns_addr_exists) {
/* 2001:4860:4860::8888 google */
ip_addr_t ipv6_dns_addr = IPADDR6_INIT(
PP_HTONL(0x20014860UL),
PP_HTONL(0x48600000UL),
PP_HTONL(0x00000000UL),
PP_HTONL(0x00008888UL));
dns_setserver(0, &ipv6_dns_addr);
}
}
}
}
#endif
static sys_sem_t lwip_tcpip_inited;
static void lwip_tcpip_init_irq(void *eh)
{
@ -353,28 +388,6 @@ int lwip_bringup(bool dhcp, const char *ip, const char *netmask, const char *gw)
// Zero out socket set
lwip_arena_init();
// Connect to the network
lwip_dhcp = dhcp;
if (lwip_dhcp) {
err_t err = dhcp_start(&lwip_netif);
if (err) {
return NSAPI_ERROR_DHCP_FAILURE;
}
} else {
ip_addr_t ip_addr;
ip_addr_t netmask_addr;
ip_addr_t gw_addr;
if (!inet_aton(ip, &ip_addr) ||
!inet_aton(netmask, &netmask_addr) ||
!inet_aton(gw, &gw_addr)) {
return NSAPI_ERROR_PARAMETER;
}
netif_set_addr(&lwip_netif, &ip_addr, &netmask_addr, &gw_addr);
netif_set_up(&lwip_netif);
}
#if LWIP_IPV6
netif_create_ip6_linklocal_address(&lwip_netif, 1/*from MAC*/);
#if LWIP_IPV6_MLD
@ -386,7 +399,7 @@ int lwip_bringup(bool dhcp, const char *ip, const char *netmask, const char *gw)
if (lwip_netif.mld_mac_filter != NULL) {
ip6_addr_t ip6_allnodes_ll;
ip6_addr_set_allnodes_linklocal(&ip6_allnodes_ll);
lwip_netif.mld_mac_filter(&lwip_netif, &ip6_allnodes_ll, NETIF_ADD_MAC_FILTER);
lwip_netif.mld_mac_filter(&lwip_netif, &ip6_allnodes_ll, MLD6_ADD_MAC_FILTER);
}
#endif /* LWIP_IPV6_MLD */
@ -407,13 +420,40 @@ int lwip_bringup(bool dhcp, const char *ip, const char *netmask, const char *gw)
}
}
#if LWIP_IPV4
if (!dhcp) {
ip4_addr_t ip_addr;
ip4_addr_t netmask_addr;
ip4_addr_t gw_addr;
if (!inet_aton(ip, &ip_addr) ||
!inet_aton(netmask, &netmask_addr) ||
!inet_aton(gw, &gw_addr)) {
return NSAPI_ERROR_PARAMETER;
}
netif_set_addr(&lwip_netif, &ip_addr, &netmask_addr, &gw_addr);
}
#endif
netif_set_up(&lwip_netif);
#if LWIP_IPV4
// Connect to the network
lwip_dhcp = dhcp;
if (lwip_dhcp) {
err_t err = dhcp_start(&lwip_netif);
if (err) {
return NSAPI_ERROR_DHCP_FAILURE;
}
}
#endif
// If doesn't have address
if (!lwip_get_ip_addr(true, &lwip_netif)) {
//ret = sys_arch_sem_wait(&lwip_netif_has_addr, 15000);
ret = sys_arch_sem_wait(&lwip_netif_has_addr, 30000);
if (ret == SYS_ARCH_TIMEOUT) {
return NSAPI_ERROR_DHCP_FAILURE;
}
@ -428,6 +468,10 @@ int lwip_bringup(bool dhcp, const char *ip, const char *netmask, const char *gw)
}
#endif
#if LWIP_IPV6
add_dns_addr(&lwip_netif);
#endif
return 0;
}
@ -454,7 +498,6 @@ int lwip_bringdown(void)
return 0;
}
/* LWIP error remapping */
static int lwip_err_remap(err_t err) {
switch (err) {
@ -484,12 +527,27 @@ static int lwip_err_remap(err_t err) {
/* LWIP network stack implementation */
static int lwip_gethostbyname(nsapi_stack_t *stack, const char *host, nsapi_addr_t *addr)
{
err_t err = netconn_gethostbyname(host, (ip_addr_t *)addr->bytes);
ip_addr_t lwip_addr;
#if LWIP_IPV4 && LWIP_IPV6
u8_t addr_type;
const ip_addr_t *ip_addr;
ip_addr = lwip_get_ip_addr(true, &lwip_netif);
if (IP_IS_V6(ip_addr)) {
addr_type = NETCONN_DNS_IPV6;
} else {
addr_type = NETCONN_DNS_IPV4;
}
err_t err = netconn_gethostbyname_addrtype(host, &lwip_addr, addr_type);
#else
err_t err = netconn_gethostbyname(host, &lwip_addr);
#endif
if (err != ERR_OK) {
return NSAPI_ERROR_DNS_FAILURE;
}
addr->version = NSAPI_IPv4;
convert_lwip_addr_to_mbed(addr, &lwip_addr);
return 0;
}
@ -509,7 +567,7 @@ static int lwip_socket_open(nsapi_stack_t *stack, nsapi_socket_t *handle, nsapi_
u8_t lwip_proto = proto == NSAPI_TCP ? NETCONN_TCP : NETCONN_UDP;
#if LWIP_IPV6 && LWIP_IPV4
ip_addr_t *ip_addr;
const ip_addr_t *ip_addr;
ip_addr = lwip_get_ip_addr(true, &lwip_netif);
if (IP_IS_V6(ip_addr)) {

View File

@ -289,22 +289,11 @@ void SocketAddress::_SocketAddress(NetworkStack *iface, const char *host, uint16
{
_ip_address[0] = '\0';
// Check for valid IP addresses
if (host && ipv4_is_valid(host)) {
_addr.version = NSAPI_IPv4;
ipv4_from_address(_addr.bytes, host);
_port = port;
} else if (host && ipv6_is_valid(host)) {
_addr.version = NSAPI_IPv6;
ipv6_from_address(_addr.bytes, host);
_port = port;
} else {
// DNS lookup
int err = iface->gethostbyname(host, this);
_port = port;
if (err) {
_addr = nsapi_addr_t();
_port = 0;
}
// gethostbyname must check for literals, so can call it directly
int err = iface->gethostbyname(host, this);
_port = port;
if (err) {
_addr = nsapi_addr_t();
_port = 0;
}
}

View File

@ -20,6 +20,10 @@
#include <stdlib.h>
#include <stdio.h>
#define CLASS_IN 1
#define RR_A 1
#define RR_AAAA 28
// DNS options
#define DNS_BUFFER_SIZE 512
@ -34,7 +38,6 @@ nsapi_addr_t dns_servers[DNS_SERVERS_SIZE] = {
{NSAPI_IPv4, {208, 67, 222, 222}},
};
// DNS server configuration
extern "C" int nsapi_dns_add_server(nsapi_addr_t addr)
{
@ -100,11 +103,11 @@ static void dns_append_question(uint8_t **p, const char *host, nsapi_version_t v
// fill out question footer
if (version == NSAPI_IPv4) {
dns_append_word(p, 1); // qtype = ipv4
dns_append_word(p, RR_A); // qtype = ipv4
} else {
dns_append_word(p, 28); // qtype = ipv6
dns_append_word(p, RR_AAAA); // qtype = ipv6
}
dns_append_word(p, 1); // qclass = 1
dns_append_word(p, CLASS_IN);
}
static int dns_scan_response(const uint8_t **p, nsapi_addr_t *addr, unsigned addr_count)
@ -162,7 +165,7 @@ static int dns_scan_response(const uint8_t **p, nsapi_addr_t *addr, unsigned add
*p += 4; // ttl
uint16_t rdlength = dns_scan_word(p); // rdlength
if (rtype == 1 && rclass == 1 && rdlength == NSAPI_IPv4_BYTES) {
if (rtype == RR_A && rclass == CLASS_IN && rdlength == NSAPI_IPv4_BYTES) {
// accept A record
addr->version = NSAPI_IPv4;
for (int i = 0; i < NSAPI_IPv4_BYTES; i++) {
@ -171,7 +174,7 @@ static int dns_scan_response(const uint8_t **p, nsapi_addr_t *addr, unsigned add
addr += 1;
count += 1;
} else if (rtype == 28 && rclass == 1 && rdlength == NSAPI_IPv6_BYTES) {
} else if (rtype == RR_AAAA && rclass == CLASS_IN && rdlength == NSAPI_IPv6_BYTES) {
// accept AAAA record
addr->version = NSAPI_IPv6;
for (int i = 0; i < NSAPI_IPv6_BYTES; i++) {
@ -219,8 +222,8 @@ static int nsapi_dns_query_multiple(NetworkStack *stack, const char *host,
// check against each dns server
for (unsigned i = 0; i < DNS_SERVERS_SIZE; i++) {
// send the question
uint8_t *p = packet;
dns_append_question(&p, host, version);
uint8_t *question = packet;
dns_append_question(&question, host, version);
err = socket.sendto(SocketAddress(dns_servers[i], 53), packet, DNS_BUFFER_SIZE);
if (err == NSAPI_ERROR_WOULD_BLOCK) {
@ -239,12 +242,9 @@ static int nsapi_dns_query_multiple(NetworkStack *stack, const char *host,
break;
}
p = packet;
int found = dns_scan_response((const uint8_t **)&p, addr, addr_count);
if (found) {
result = found;
break;
}
const uint8_t *response = packet;
dns_scan_response(&response, addr, addr_count);
break;
}
// clean up packet