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:
@@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user