2
0
mirror of https://github.com/openvswitch/ovs synced 2025-09-01 14:55:18 +00:00

DNS: Add basic support for asynchronous DNS resolving

This patch is a simple implementation for the proposal discussed in
https://mail.openvswitch.org/pipermail/ovs-dev/2017-August/337038.html and
https://mail.openvswitch.org/pipermail/ovs-dev/2017-October/340013.html.

It enables ovs-vswitchd and other utilities to use DNS names when specifying
OpenFlow and OVSDB remotes.

Below are some of the features and limitations of this patch:
    - Resolving is asynchornous in daemon context, avoiding blocking main loop;
    - Resolving is synchronous in general utility context;
    - Both IPv4 and IPv6 are supported;
    - The resolving API is thread-safe;
    - Depends on the unbound library;
    - When multiple ip addresses are returned, only the first one is used;
    - /etc/nsswitch.conf isn't respected as unbound library doesn't look at it;
    - For async-resolving, caller need to retry later; there is no callback.

Signed-off-by: Yifeng Sun <pkusunyifeng@gmail.com>
Signed-off-by: Ben Pfaff <blp@ovn.org>
This commit is contained in:
Yifeng Sun
2018-06-26 14:06:21 -07:00
committed by Ben Pfaff
parent def5b366a3
commit 771680d96f
25 changed files with 604 additions and 165 deletions

View File

@@ -48,6 +48,7 @@
#include "netlink-protocol.h"
#include "netlink-socket.h"
#endif
#include "dns-resolve.h"
VLOG_DEFINE_THIS_MODULE(socket_util);
@@ -56,6 +57,12 @@ static int getsockopt_int(int fd, int level, int option, const char *optname,
static struct sockaddr_in *sin_cast(const struct sockaddr *);
static struct sockaddr_in6 *sin6_cast(const struct sockaddr *);
static const struct sockaddr *sa_cast(const struct sockaddr_storage *);
static bool parse_sockaddr_components(struct sockaddr_storage *ss,
char *host_s,
const char *port_s,
uint16_t default_port,
const char *s,
bool resolve_host);
/* Sets 'fd' to non-blocking mode. Returns 0 if successful, otherwise a
* positive errno value. */
@@ -419,11 +426,31 @@ inet_parse_port_host_tokens(char *s, char **portp, char **hostp)
inet_parse_tokens__(s, 1, hostp, portp);
}
static bool
parse_sockaddr_components_dns(struct sockaddr_storage *ss OVS_UNUSED,
char *host_s,
const char *port_s OVS_UNUSED,
uint16_t default_port OVS_UNUSED,
const char *s OVS_UNUSED)
{
char *tmp_host_s;
dns_resolve(host_s, &tmp_host_s);
if (tmp_host_s != NULL) {
parse_sockaddr_components(ss, tmp_host_s, port_s,
default_port, s, false);
free(tmp_host_s);
return true;
}
return false;
}
static bool
parse_sockaddr_components(struct sockaddr_storage *ss,
char *host_s,
const char *port_s, uint16_t default_port,
const char *s)
const char *s,
bool resolve_host)
{
struct sockaddr_in *sin = sin_cast(sa_cast(ss));
int port;
@@ -445,7 +472,6 @@ parse_sockaddr_components(struct sockaddr_storage *ss,
sin6->sin6_family = AF_INET6;
sin6->sin6_port = htons(port);
if (!addr || !*addr || !ipv6_parse(addr, &sin6->sin6_addr)) {
VLOG_ERR("%s: bad IPv6 address \"%s\"", s, addr ? addr : "");
goto exit;
}
@@ -468,13 +494,19 @@ parse_sockaddr_components(struct sockaddr_storage *ss,
sin->sin_family = AF_INET;
sin->sin_port = htons(port);
if (host_s && !ip_parse(host_s, &sin->sin_addr.s_addr)) {
VLOG_ERR("%s: bad IPv4 address \"%s\"", s, host_s);
goto exit;
goto resolve;
}
}
return true;
resolve:
if (resolve_host && parse_sockaddr_components_dns(ss, host_s, port_s,
default_port, s)) {
return true;
} else if (!resolve_host) {
VLOG_ERR("%s: bad IP address \"%s\"", s, host_s);
}
exit:
memset(ss, 0, sizeof *ss);
return false;
@@ -505,7 +537,8 @@ inet_parse_active(const char *target_, int default_port,
VLOG_ERR("%s: port must be specified", target_);
ok = false;
} else {
ok = parse_sockaddr_components(ss, host, port, default_port, target_);
ok = parse_sockaddr_components(ss, host, port, default_port,
target_, true);
}
if (!ok) {
memset(ss, 0, sizeof *ss);
@@ -625,7 +658,8 @@ inet_parse_passive(const char *target_, int default_port,
VLOG_ERR("%s: port must be specified", target_);
ok = false;
} else {
ok = parse_sockaddr_components(ss, host, port, default_port, target_);
ok = parse_sockaddr_components(ss, host, port, default_port,
target_, true);
}
if (!ok) {
memset(ss, 0, sizeof *ss);
@@ -747,7 +781,7 @@ inet_parse_address(const char *target_, struct sockaddr_storage *ss)
{
char *target = xstrdup(target_);
char *host = unbracket(target);
bool ok = parse_sockaddr_components(ss, host, NULL, 0, target_);
bool ok = parse_sockaddr_components(ss, host, NULL, 0, target_, false);
if (!ok) {
memset(ss, 0, sizeof *ss);
}