aboutsummaryrefslogtreecommitdiff
path: root/evdns.c
diff options
context:
space:
mode:
authorHaibo Huang <hhb@google.com>2019-05-31 16:12:39 -0700
committerHaibo Huang <hhb@google.com>2019-06-18 14:58:09 -0700
commitb22796788b72b1daca42bf5773b582d26860ef0a (patch)
tree1d148d55162d1d29b1bc55ea05ff62c1793086d6 /evdns.c
parenteb295e03887a843c88bcef99c80c16dd8c13099a (diff)
downloadlibevent-b22796788b72b1daca42bf5773b582d26860ef0a.tar.gz
Upgrade libevent to release-2.1.10-stableandroid-o-mr1-iot-release-1.0.14
Test: None Change-Id: I24e4275a07a6dcdd932056c7893a6aabdd786b8a
Diffstat (limited to 'evdns.c')
-rw-r--r--evdns.c98
1 files changed, 72 insertions, 26 deletions
diff --git a/evdns.c b/evdns.c
index e9dbc35..1b81536 100644
--- a/evdns.c
+++ b/evdns.c
@@ -863,6 +863,19 @@ reply_schedule_callback(struct request *const req, u32 ttl, u32 err, struct repl
&d->deferred);
}
+
+#define _QR_MASK 0x8000U
+#define _OP_MASK 0x7800U
+#define _AA_MASK 0x0400U
+#define _TC_MASK 0x0200U
+#define _RD_MASK 0x0100U
+#define _RA_MASK 0x0080U
+#define _Z_MASK 0x0040U
+#define _AD_MASK 0x0020U
+#define _CD_MASK 0x0010U
+#define _RCODE_MASK 0x000fU
+#define _Z_MASK_DEPRECATED 0x0070U
+
/* this processes a parsed reply packet */
static void
reply_handle(struct request *const req, u16 flags, u32 ttl, struct reply *reply) {
@@ -876,12 +889,12 @@ reply_handle(struct request *const req, u16 flags, u32 ttl, struct reply *reply)
ASSERT_LOCKED(req->base);
ASSERT_VALID_REQUEST(req);
- if (flags & 0x020f || !reply || !reply->have_answer) {
+ if (flags & (_RCODE_MASK | _TC_MASK) || !reply || !reply->have_answer) {
/* there was an error */
- if (flags & 0x0200) {
+ if (flags & _TC_MASK) {
error = DNS_ERR_TRUNCATED;
- } else if (flags & 0x000f) {
- u16 error_code = (flags & 0x000f) - 1;
+ } else if (flags & _RCODE_MASK) {
+ u16 error_code = (flags & _RCODE_MASK) - 1;
if (error_code > 4) {
error = DNS_ERR_UNKNOWN;
} else {
@@ -1046,8 +1059,8 @@ reply_parse(struct evdns_base *base, u8 *packet, int length) {
memset(&reply, 0, sizeof(reply));
/* If it's not an answer, it doesn't correspond to any request. */
- if (!(flags & 0x8000)) return -1; /* must be an answer */
- if ((flags & 0x020f) && (flags & 0x020f) != DNS_ERR_NOTEXIST) {
+ if (!(flags & _QR_MASK)) return -1; /* must be an answer */
+ if ((flags & (_RCODE_MASK|_TC_MASK)) && (flags & (_RCODE_MASK|_TC_MASK)) != DNS_ERR_NOTEXIST) {
/* there was an error and it's not NXDOMAIN */
goto err;
}
@@ -1236,8 +1249,8 @@ request_parse(u8 *packet, int length, struct evdns_server_port *port, struct soc
(void)additional;
(void)authority;
- if (flags & 0x8000) return -1; /* Must not be an answer. */
- flags &= 0x0110; /* Only RD and CD get preserved. */
+ if (flags & _QR_MASK) return -1; /* Must not be an answer. */
+ flags &= (_RD_MASK|_CD_MASK); /* Only RD and CD get preserved. */
server_req = mm_malloc(sizeof(struct server_request));
if (server_req == NULL) return -1;
@@ -1277,7 +1290,7 @@ request_parse(u8 *packet, int length, struct evdns_server_port *port, struct soc
port->refcnt++;
/* Only standard queries are supported. */
- if (flags & 0x7800) {
+ if (flags & _OP_MASK) {
evdns_server_request_respond(&(server_req->base), DNS_ERR_NOTIMPL);
return -1;
}
@@ -1286,14 +1299,12 @@ request_parse(u8 *packet, int length, struct evdns_server_port *port, struct soc
return 0;
err:
- if (server_req) {
- if (server_req->base.questions) {
- for (i = 0; i < server_req->base.nquestions; ++i)
- mm_free(server_req->base.questions[i]);
- mm_free(server_req->base.questions);
- }
- mm_free(server_req);
+ if (server_req->base.questions) {
+ for (i = 0; i < server_req->base.nquestions; ++i)
+ mm_free(server_req->base.questions[i]);
+ mm_free(server_req->base.questions);
}
+ mm_free(server_req);
return -1;
#undef SKIP_NAME
@@ -1751,6 +1762,7 @@ evdns_close_server_port(struct evdns_server_port *port)
server_port_free(port);
} else {
port->closing = 1;
+ EVDNS_UNLOCK(port);
}
}
@@ -1904,7 +1916,7 @@ evdns_server_request_format_response(struct server_request *req, int err)
/* Set response bit and error code; copy OPCODE and RD fields from
* question; copy RA and AA if set by caller. */
flags = req->base.flags;
- flags |= (0x8000 | err);
+ flags |= (_QR_MASK | err);
dnslabel_table_init(&table);
APPEND16(req->trans_id);
@@ -2265,10 +2277,11 @@ evdns_request_transmit(struct request *req) {
nameserver_write_waiting(req->ns, 1);
return 1;
case 2:
- /* failed to transmit the request entirely. */
+ /* failed to transmit the request entirely. we can fallthrough since
+ * we'll set a timeout, which will time out, and make us retransmit the
+ * request anyway. */
retcode = 1;
- /* fall through: we'll set a timeout, which will time out,
- * and make us retransmit the request anyway. */
+ EVUTIL_FALLTHROUGH;
default:
/* all ok */
log(EVDNS_LOG_DEBUG,
@@ -3313,10 +3326,16 @@ search_request_finished(struct evdns_request *const handle) {
static void
evdns_resolv_set_defaults(struct evdns_base *base, int flags) {
+ int add_default = flags & DNS_OPTION_NAMESERVERS;
+ if (flags & DNS_OPTION_NAMESERVERS_NO_DEFAULT)
+ add_default = 0;
+
/* if the file isn't found then we assume a local resolver */
ASSERT_LOCKED(base);
- if (flags & DNS_OPTION_SEARCH) search_set_from_hostname(base);
- if (flags & DNS_OPTION_NAMESERVERS) evdns_base_nameserver_ip_add(base,"127.0.0.1");
+ if (flags & DNS_OPTION_SEARCH)
+ search_set_from_hostname(base);
+ if (add_default)
+ evdns_base_nameserver_ip_add(base, "127.0.0.1");
}
#ifndef EVENT__HAVE_STRTOK_R
@@ -3612,9 +3631,14 @@ evdns_base_resolv_conf_parse_impl(struct evdns_base *base, int flags, const char
char *resolv;
char *start;
int err = 0;
+ int add_default;
log(EVDNS_LOG_DEBUG, "Parsing resolv.conf file %s", filename);
+ add_default = flags & DNS_OPTION_NAMESERVERS;
+ if (flags & DNS_OPTION_NAMESERVERS_NO_DEFAULT)
+ add_default = 0;
+
if (flags & DNS_OPTION_HOSTSFILE) {
char *fname = evdns_get_default_hosts_filename();
evdns_base_load_hosts(base, fname);
@@ -3622,6 +3646,11 @@ evdns_base_resolv_conf_parse_impl(struct evdns_base *base, int flags, const char
mm_free(fname);
}
+ if (!filename) {
+ evdns_resolv_set_defaults(base, flags);
+ return 1;
+ }
+
if ((err = evutil_read_file_(filename, &resolv, &n, 0)) < 0) {
if (err == -1) {
/* No file. */
@@ -3645,7 +3674,7 @@ evdns_base_resolv_conf_parse_impl(struct evdns_base *base, int flags, const char
}
}
- if (!base->server_head && (flags & DNS_OPTION_NAMESERVERS)) {
+ if (!base->server_head && add_default) {
/* no nameservers were configured. */
evdns_base_nameserver_ip_add(base, "127.0.0.1");
err = 6;
@@ -3946,7 +3975,12 @@ evdns_base_new(struct event_base *event_base, int flags)
TAILQ_INIT(&base->hostsdb);
-#define EVDNS_BASE_ALL_FLAGS (0x8001)
+#define EVDNS_BASE_ALL_FLAGS ( \
+ EVDNS_BASE_INITIALIZE_NAMESERVERS | \
+ EVDNS_BASE_DISABLE_WHEN_INACTIVE | \
+ EVDNS_BASE_NAMESERVERS_NO_DEFAULT | \
+ 0)
+
if (flags & ~EVDNS_BASE_ALL_FLAGS) {
flags = EVDNS_BASE_INITIALIZE_NAMESERVERS;
log(EVDNS_LOG_WARN,
@@ -3957,10 +3991,15 @@ evdns_base_new(struct event_base *event_base, int flags)
if (flags & EVDNS_BASE_INITIALIZE_NAMESERVERS) {
int r;
+ int opts = DNS_OPTIONS_ALL;
+ if (flags & EVDNS_BASE_NAMESERVERS_NO_DEFAULT) {
+ opts |= DNS_OPTION_NAMESERVERS_NO_DEFAULT;
+ }
+
#ifdef _WIN32
r = evdns_base_config_windows_nameservers(base);
#else
- r = evdns_base_resolv_conf_parse(base, DNS_OPTIONS_ALL, "/etc/resolv.conf");
+ r = evdns_base_resolv_conf_parse(base, opts, "/etc/resolv.conf");
#endif
if (r == -1) {
evdns_base_free_and_unlock(base, 0);
@@ -4636,6 +4675,7 @@ evdns_getaddrinfo(struct evdns_base *dns_base,
int err;
int port = 0;
int want_cname = 0;
+ int started = 0;
if (!dns_base) {
dns_base = current_base;
@@ -4714,6 +4754,8 @@ evdns_getaddrinfo(struct evdns_base *dns_base,
* launching those requests. (XXX we don't do that yet.)
*/
+ EVDNS_LOCK(dns_base);
+
if (hints.ai_family != PF_INET6) {
log(EVDNS_LOG_DEBUG, "Sending request for %s on ipv4 as %p",
nodename, &data->ipv4_request);
@@ -4740,7 +4782,11 @@ evdns_getaddrinfo(struct evdns_base *dns_base,
evtimer_assign(&data->timeout, dns_base->event_base,
evdns_getaddrinfo_timeout_cb, data);
- if (data->ipv4_request.r || data->ipv6_request.r) {
+ started = (data->ipv4_request.r || data->ipv6_request.r);
+
+ EVDNS_UNLOCK(dns_base);
+
+ if (started) {
return data;
} else {
mm_free(data);