mirror of https://github.com/ARMmbed/mbed-os.git
nsapi - Added access to gethostbyname and add_dns_server
For performing DNS resolution explicitly through the network-socket user API. This interface does not require implementation changes and can rely entirely on the dns query library in the network-socket API.pull/2652/head
parent
98030475af
commit
3858a13b75
|
|
@ -15,9 +15,11 @@
|
|||
*/
|
||||
|
||||
#include "network-socket/NetworkInterface.h"
|
||||
#include "network-socket/NetworkStack.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
// Default network-interface state
|
||||
const char *NetworkInterface::get_mac_address()
|
||||
{
|
||||
return 0;
|
||||
|
|
@ -52,3 +54,19 @@ int NetworkInterface::set_dhcp(bool dhcp)
|
|||
}
|
||||
}
|
||||
|
||||
// DNS operations go through the underlying stack by default
|
||||
int NetworkInterface::gethostbyname(SocketAddress *address, const char *name)
|
||||
{
|
||||
return get_stack()->gethostbyname(address, name);
|
||||
}
|
||||
|
||||
int NetworkInterface::gethostbyname(SocketAddress *address, const char *name, nsapi_version_t version)
|
||||
{
|
||||
return get_stack()->gethostbyname(address, name, version);
|
||||
}
|
||||
|
||||
int NetworkInterface::add_dns_server(const SocketAddress &address)
|
||||
{
|
||||
return get_stack()->add_dns_server(address);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#define NETWORK_INTERFACE_H
|
||||
|
||||
#include "network-socket/nsapi_types.h"
|
||||
#include "network-socket/SocketAddress.h"
|
||||
|
||||
// Predeclared class
|
||||
class NetworkStack;
|
||||
|
|
@ -99,6 +100,42 @@ public:
|
|||
*/
|
||||
virtual int disconnect() = 0;
|
||||
|
||||
/** Translates a hostname to an IP address
|
||||
*
|
||||
* The hostname may be either a domain name or an IP address. If the
|
||||
* hostname is an IP address, no network transactions will be performed.
|
||||
*
|
||||
* If no stack-specific DNS resolution is provided, the hostname
|
||||
* will be resolve using a UDP socket on the stack.
|
||||
*
|
||||
* @param host Hostname to resolve
|
||||
* @param address Destination for the host SocketAddress
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual int gethostbyname(SocketAddress *address, const char *host);
|
||||
|
||||
/** Translates a hostname to an IP address with specific version
|
||||
*
|
||||
* The hostname may be either a domain name or an IP address. If the
|
||||
* hostname is an IP address, no network transactions will be performed.
|
||||
*
|
||||
* If no stack-specific DNS resolution is provided, the hostname
|
||||
* will be resolve using a UDP socket on the stack.
|
||||
*
|
||||
* @param address Destination for the host SocketAddress
|
||||
* @param host Hostname to resolve
|
||||
* @param version IP version of address to resolve
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual int gethostbyname(SocketAddress *address, const char *host, nsapi_version_t version);
|
||||
|
||||
/** Add a domain name server to list of servers to query
|
||||
*
|
||||
* @param addr Destination for the host address
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual int add_dns_server(const SocketAddress &address);
|
||||
|
||||
protected:
|
||||
friend class Socket;
|
||||
friend class UDPSocket;
|
||||
|
|
|
|||
|
|
@ -27,6 +27,16 @@ int NetworkStack::gethostbyname(SocketAddress *address, const char *name)
|
|||
return nsapi_dns_query(this, address, name);
|
||||
}
|
||||
|
||||
int NetworkStack::gethostbyname(SocketAddress *address, const char *name, nsapi_version_t version)
|
||||
{
|
||||
return nsapi_dns_query(this, address, name, version);
|
||||
}
|
||||
|
||||
int NetworkStack::add_dns_server(const SocketAddress &address)
|
||||
{
|
||||
return nsapi_dns_add_server(address);
|
||||
}
|
||||
|
||||
int NetworkStack::setstackopt(int level, int optname, const void *optval, unsigned optlen)
|
||||
{
|
||||
return NSAPI_ERROR_UNSUPPORTED;
|
||||
|
|
@ -88,6 +98,15 @@ public:
|
|||
return err;
|
||||
}
|
||||
|
||||
virtual int add_dns_server(const SocketAddress &address)
|
||||
{
|
||||
if (!_stack_api()->add_dns_server) {
|
||||
return NetworkStack::add_dns_server(address);
|
||||
}
|
||||
|
||||
return _stack_api()->add_dns_server(_stack(), address.get_addr());
|
||||
}
|
||||
|
||||
virtual int setstackopt(int level, int optname, const void *optval, unsigned optlen)
|
||||
{
|
||||
if (!_stack_api()->setstackopt) {
|
||||
|
|
|
|||
|
|
@ -45,9 +45,9 @@ public:
|
|||
*
|
||||
* The hostname may be either a domain name or an IP address. If the
|
||||
* hostname is an IP address, no network transactions will be performed.
|
||||
*
|
||||
*
|
||||
* If no stack-specific DNS resolution is provided, the hostname
|
||||
* will be resolve using a UDP socket on the stack.
|
||||
* will be resolve using a UDP socket on the stack.
|
||||
*
|
||||
* @param address Destination for the host SocketAddress
|
||||
* @param host Hostname to resolve
|
||||
|
|
@ -55,6 +55,28 @@ public:
|
|||
*/
|
||||
virtual int gethostbyname(SocketAddress *address, const char *host);
|
||||
|
||||
/** Translates a hostname to an IP address with specific version
|
||||
*
|
||||
* The hostname may be either a domain name or an IP address. If the
|
||||
* hostname is an IP address, no network transactions will be performed.
|
||||
*
|
||||
* If no stack-specific DNS resolution is provided, the hostname
|
||||
* will be resolve using a UDP socket on the stack.
|
||||
*
|
||||
* @param host Hostname to resolve
|
||||
* @param address Destination for the host SocketAddress
|
||||
* @param version IP version of address to resolve
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual int gethostbyname(SocketAddress *address, const char *host, nsapi_version_t version);
|
||||
|
||||
/** Add a domain name server to list of servers to query
|
||||
*
|
||||
* @param addr Destination for the host address
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
virtual int add_dns_server(const SocketAddress &address);
|
||||
|
||||
/* Set stack-specific stack options
|
||||
*
|
||||
* The setstackopt allow an application to pass stack-specific hints
|
||||
|
|
@ -66,7 +88,7 @@ public:
|
|||
* @param optval Option value
|
||||
* @param optlen Length of the option value
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
*/
|
||||
virtual int setstackopt(int level, int optname, const void *optval, unsigned optlen);
|
||||
|
||||
/* Get stack-specific stack options
|
||||
|
|
@ -80,7 +102,7 @@ public:
|
|||
* @param optval Destination for option value
|
||||
* @param optlen Length of the option value
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
*/
|
||||
virtual int getstackopt(int level, int optname, void *optval, unsigned *optlen);
|
||||
|
||||
protected:
|
||||
|
|
@ -260,7 +282,7 @@ protected:
|
|||
* @param optval Option value
|
||||
* @param optlen Length of the option value
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
*/
|
||||
virtual int setsockopt(nsapi_socket_t handle, int level, int optname, const void *optval, unsigned optlen);
|
||||
|
||||
/* Get stack-specific socket options
|
||||
|
|
@ -275,7 +297,7 @@ protected:
|
|||
* @param optval Destination for option value
|
||||
* @param optlen Length of the option value
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
*/
|
||||
virtual int getsockopt(nsapi_socket_t handle, int level, int optname, void *optval, unsigned *optlen);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -41,8 +41,14 @@ public:
|
|||
* @param stack Network stack to use for DNS resolution
|
||||
* @param host Hostname to resolve
|
||||
* @param port Optional 16-bit port
|
||||
* @deprecated
|
||||
* Constructors hide possible errors. Replaced by
|
||||
* NetworkInterface::gethostbyname.
|
||||
*/
|
||||
template <typename S>
|
||||
MBED_DEPRECATED_SINCE("mbed-os-5.1.3",
|
||||
"Constructors hide possible errors. Replaced by "
|
||||
"NetworkInterface::gethostbyname.")
|
||||
SocketAddress(S *stack, const char *host, uint16_t port = 0)
|
||||
{
|
||||
_SocketAddress(nsapi_create_stack(stack), host, port);
|
||||
|
|
|
|||
|
|
@ -51,11 +51,14 @@ int TCPSocket::connect(const SocketAddress &address)
|
|||
|
||||
int TCPSocket::connect(const char *host, uint16_t port)
|
||||
{
|
||||
SocketAddress address(_stack, host, port);
|
||||
if (!address) {
|
||||
SocketAddress address;
|
||||
int err = _stack->gethostbyname(&address, host);
|
||||
if (err) {
|
||||
return NSAPI_ERROR_DNS_FAILURE;
|
||||
}
|
||||
|
||||
address.set_port(port);
|
||||
|
||||
// connect is thread safe
|
||||
return connect(address);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,11 +36,14 @@ nsapi_protocol_t UDPSocket::get_proto()
|
|||
|
||||
int UDPSocket::sendto(const char *host, uint16_t port, const void *data, unsigned size)
|
||||
{
|
||||
SocketAddress address(_stack, host, port);
|
||||
if (!address) {
|
||||
SocketAddress address;
|
||||
int err = _stack->gethostbyname(&address, host);
|
||||
if (err) {
|
||||
return NSAPI_ERROR_DNS_FAILURE;
|
||||
}
|
||||
|
||||
address.set_port(port);
|
||||
|
||||
// sendto is thread safe
|
||||
return sendto(address, data, size);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "network-socket/UDPSocket.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
// DNS options
|
||||
|
|
@ -44,6 +45,111 @@ extern "C" int nsapi_dns_add_server(nsapi_addr_t addr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// IP parsing
|
||||
static bool dns_parse_ipv4(const char *host, nsapi_addr_t *addr)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
// Check each digit for [0-9.]
|
||||
for (; host[i]; i++) {
|
||||
if (!(host[i] >= '0' && host[i] <= '9') && host[i] != '.') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Ending with '.' garuntees host
|
||||
if (i > 0 && host[i-1] == '.') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Build up the ip address
|
||||
addr->version = NSAPI_IPv4;
|
||||
i = 0;
|
||||
|
||||
for (int count = 0; count < NSAPI_IPv4_BYTES; count++) {
|
||||
int scanned = sscanf(&host[i], "%hhu", &addr->bytes[count]);
|
||||
if (scanned < 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (; host[i] != '.'; i++) {
|
||||
if (!host[i]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int dns_parse_ipv6_chunk(const char *chunk, uint16_t *shorts) {
|
||||
int count = 0;
|
||||
int i = 0;
|
||||
|
||||
for (; count < NSAPI_IPv6_BYTES/2; count++) {
|
||||
int scanned = sscanf(&chunk[i], "%hx", &shorts[count]);
|
||||
if (scanned < 1) {
|
||||
return count;
|
||||
}
|
||||
|
||||
for (; chunk[i] != ':'; i++) {
|
||||
if (!chunk[i]) {
|
||||
return count+1;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static bool dns_parse_ipv6(const char *host, nsapi_addr_t *addr)
|
||||
{
|
||||
// Check each digit for [0-9a-fA-F:]
|
||||
for (int i = 0; host[i]; i++) {
|
||||
if (!(host[i] >= '0' && host[i] <= '9') &&
|
||||
!(host[i] >= 'a' && host[i] <= 'f') &&
|
||||
!(host[i] >= 'A' && host[i] <= 'F') &&
|
||||
host[i] != ':') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Build up address
|
||||
addr->version = NSAPI_IPv6;
|
||||
|
||||
// Start with zeroed address
|
||||
uint16_t shorts[NSAPI_IPv6_BYTES/2];
|
||||
memset(shorts, 0, sizeof shorts);
|
||||
|
||||
int suffix = 0;
|
||||
|
||||
// Find double colons and scan suffix
|
||||
for (int i = 0; host[i]; i++) {
|
||||
if (host[i] == ':' && host[i+1] == ':') {
|
||||
suffix = dns_parse_ipv6_chunk(&host[i+2], shorts);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Move suffix to end
|
||||
memmove(&shorts[NSAPI_IPv6_BYTES/2-suffix], &shorts[0],
|
||||
suffix*sizeof(uint16_t));
|
||||
|
||||
// Scan prefix
|
||||
dns_parse_ipv6_chunk(&host[0], shorts);
|
||||
|
||||
// Flip bytes
|
||||
for (int i = 0; i < NSAPI_IPv6_BYTES/2; i++) {
|
||||
addr->bytes[2*i+0] = (uint8_t)(shorts[i] >> 8);
|
||||
addr->bytes[2*i+1] = (uint8_t)(shorts[i] >> 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// DNS packet parsing
|
||||
static void dns_append_byte(uint8_t **p, uint8_t byte)
|
||||
|
|
@ -199,6 +305,17 @@ static int nsapi_dns_query_multiple(NetworkStack *stack,
|
|||
return NSAPI_ERROR_PARAMETER;
|
||||
}
|
||||
|
||||
// check for simple ip addresses
|
||||
if (version == NSAPI_IPv4) {
|
||||
if (dns_parse_ipv4(host, addr)) {
|
||||
return 0;
|
||||
}
|
||||
} else if (version == NSAPI_IPv6) {
|
||||
if (dns_parse_ipv6(host, addr)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// create a udp socket
|
||||
UDPSocket socket;
|
||||
int err = socket.open(stack);
|
||||
|
|
|
|||
|
|
@ -201,6 +201,13 @@ typedef struct nsapi_stack_api
|
|||
*/
|
||||
int (*gethostbyname)(nsapi_stack_t *stack, nsapi_addr_t *addr, const char *host);
|
||||
|
||||
/** Add a domain name server to list of servers to query
|
||||
*
|
||||
* @param addr Destination for the host address
|
||||
* @return 0 on success, negative error code on failure
|
||||
*/
|
||||
int (*add_dns_server)(nsapi_stack_t *stack, nsapi_addr_t addr);
|
||||
|
||||
/* Set stack-specific stack options
|
||||
*
|
||||
* The setstackopt allow an application to pass stack-specific hints
|
||||
|
|
|
|||
Loading…
Reference in New Issue