diff options
author | Haibo Huang <hhb@google.com> | 2019-05-31 16:12:39 -0700 |
---|---|---|
committer | Haibo Huang <hhb@google.com> | 2019-06-18 14:58:09 -0700 |
commit | b22796788b72b1daca42bf5773b582d26860ef0a (patch) | |
tree | 1d148d55162d1d29b1bc55ea05ff62c1793086d6 /evdns.c | |
parent | eb295e03887a843c88bcef99c80c16dd8c13099a (diff) | |
download | libevent-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.c | 98 |
1 files changed, 72 insertions, 26 deletions
@@ -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); |