On 2/1/23 15:52, Frode Nordahl wrote:
> Commit 08e9e5337383 fixed proper initialization of the dns-resolve
> module, and made DNS resolution asynchronous.
>
> A side effect of that change revealed a long standing logic bug
> which broke ovsdb-server listener configuration using DNS names.
>
> Previously this worked because the DNS resolution would block,
> now that DNS resolution is asynchronous the code before this
> change would assume the error from jsonrpc_pstream_open meant
> the listener was in fact a specification for an active
> outgoing connection, even when that was not the case.
>
> To fix this a couple of changes was made to socket-util:
> 1) Pass optional result of dns resolution from inet_parse_passive.
>
> When (re-)configuring listeners that use DNS names, we may need
> to know whether the provided connection string is invalid or if
> the provided DNS name has finished resolving.
>
> 2) Check dns resolution status in inet_open_passive.
>
> If the connection string is valid, and contains a DNS name,
> inet_open_passive will now return -ENODATA if dns resolution
> failed. DNS resolution failure may either mean the asynchronous
> resolver has not completed yet, or that the name does not resolve.
>
> Reported-at: https://bugs.launchpad.net/bugs/1998781
> Fixes: 08e9e5337383 ("ovsdb: raft: Fix inability to read the database with
> DNS host names.")
> Fixes: 771680d96fb6 ("DNS: Add basic support for asynchronous DNS resolving")
> Signed-off-by: Frode Nordahl <[email protected]>
> ---
> lib/socket-util.c | 13 ++++++++++---
> lib/socket-util.h | 3 ++-
> ovsdb/jsonrpc-server.c | 43 ++++++++++++++++++++++++++----------------
> 3 files changed, 39 insertions(+), 20 deletions(-)
Hi, Frode. Thanks for v2.
I was trying to run tests with this patch and, apparently, FreeBSD
doesn't have ENODATA:
lib/socket-util.c:720:21: error: 'ENODATA' undeclared (first use in this
function); did you mean 'NO_DATA'?
720 | return -ENODATA;
| ^~~~~~~
| NO_DATA
We should, probably, use some other errno here.
Best regards, Ilya Maximets.
>
> diff --git a/lib/socket-util.c b/lib/socket-util.c
> index 38705cc51..eba350ccb 100644
> --- a/lib/socket-util.c
> +++ b/lib/socket-util.c
> @@ -660,7 +660,8 @@ exit:
> * zeros '*ss' and returns false. */
> bool
> inet_parse_passive(const char *target_, int default_port,
> - struct sockaddr_storage *ss)
> + struct sockaddr_storage *ss,
> + bool resolve_host, bool *dns_failure)
> {
> char *target = xstrdup(target_);
> char *port, *host;
> @@ -672,7 +673,7 @@ inet_parse_passive(const char *target_, int default_port,
> ok = false;
> } else {
> ok = parse_sockaddr_components(ss, host, port, default_port,
> - target_, true, NULL);
> + target_, resolve_host, dns_failure);
> }
> if (!ok) {
> memset(ss, 0, sizeof *ss);
> @@ -710,8 +711,14 @@ inet_open_passive(int style, const char *target, int
> default_port,
> struct sockaddr_storage ss;
> int fd = 0, error;
> unsigned int yes = 1;
> + bool dns_failure;
>
> - if (!inet_parse_passive(target, default_port, &ss)) {
> + if (!inet_parse_passive(target, default_port, &ss, true, &dns_failure)) {
> + if (dns_failure) {
> + /* DNS failure means asynchronous DNS resolution is in progress,
> + * or that the name does currently not resolve. */
> + return -ENODATA;
> + }
> return -EAFNOSUPPORT;
> }
> kernel_chooses_port = ss_get_port(&ss) == 0;
> diff --git a/lib/socket-util.h b/lib/socket-util.h
> index bf66393df..4eec627e3 100644
> --- a/lib/socket-util.h
> +++ b/lib/socket-util.h
> @@ -55,7 +55,8 @@ int inet_open_active(int style, const char *target, int
> default_port,
> struct sockaddr_storage *ssp, int *fdp, uint8_t dscp);
>
> bool inet_parse_passive(const char *target, int default_port,
> - struct sockaddr_storage *ssp);
> + struct sockaddr_storage *ssp,
> + bool resolve_host, bool *dns_failure);
> int inet_open_passive(int style, const char *target, int default_port,
> struct sockaddr_storage *ssp, uint8_t dscp,
> bool kernel_print_port);
> diff --git a/ovsdb/jsonrpc-server.c b/ovsdb/jsonrpc-server.c
> index 916a1f414..b4eb17467 100644
> --- a/ovsdb/jsonrpc-server.c
> +++ b/ovsdb/jsonrpc-server.c
> @@ -267,25 +267,36 @@ ovsdb_jsonrpc_server_add_remote(struct
> ovsdb_jsonrpc_server *svr,
> int error;
>
> error = jsonrpc_pstream_open(name, &listener, options->dscp);
> - if (error && error != EAFNOSUPPORT) {
> - VLOG_ERR_RL(&rl, "%s: listen failed: %s", name, ovs_strerror(error));
> - return NULL;
> - }
> + switch (error) {
> + case 0:
> + case EAFNOSUPPORT:
> + remote = xmalloc(sizeof *remote);
> + remote->server = svr;
> + remote->listener = listener;
> + ovs_list_init(&remote->sessions);
> + remote->dscp = options->dscp;
> + remote->read_only = options->read_only;
> + remote->role = nullable_xstrdup(options->role);
> + shash_add(&svr->remotes, name, remote);
> + if (!listener) {
> + /* Not a listener, attempt creation of active jsonrpc sesssion.
> */
> + ovsdb_jsonrpc_session_create(remote,
> + jsonrpc_session_open(name, true),
> + svr->read_only ||
> remote->read_only);
> + }
> + return remote;
>
> - remote = xmalloc(sizeof *remote);
> - remote->server = svr;
> - remote->listener = listener;
> - ovs_list_init(&remote->sessions);
> - remote->dscp = options->dscp;
> - remote->read_only = options->read_only;
> - remote->role = nullable_xstrdup(options->role);
> - shash_add(&svr->remotes, name, remote);
> + case ENODATA:
> + VLOG_DBG_RL(&rl, "%s: listen failed: "
> + "DNS resolution in progress or host not found",
> name);
> + return NULL;
>
> - if (!listener) {
> - ovsdb_jsonrpc_session_create(remote, jsonrpc_session_open(name,
> true),
> - svr->read_only || remote->read_only);
> + default:
> + VLOG_ERR_RL(&rl, "%s: listen failed: %s", name,
> + ovs_strerror(error));
> + return NULL;
> }
> - return remote;
> + OVS_NOT_REACHED();
> }
>
> static void
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev