/* Implements the asynchronous-resolve side of * bufferevent_socket_connect_hostname(). */ int _bufferevent_socket_connect_hostname_evdns( struct bufferevent *bufev, struct evdns_base *evdns_base, int family, const char *hostname, int port) { struct evdns_request *r; struct resolveinfo *resolveinfo; if (family == AF_UNSPEC) family = AF_INET; /* XXXX handle "unspec" correctly */ if (family != AF_INET && family != AF_INET6) return -1; if (!bufev || !evdns_base || !hostname) return -1; if (port < 1 || port > 65535) return -1; resolveinfo = mm_calloc(1, sizeof(resolveinfo)); if (!resolveinfo) return -1; resolveinfo->family = family; resolveinfo->port = htons(port); resolveinfo->bev = bufev; if (family == AF_INET) { r = evdns_base_resolve_ipv4(evdns_base, hostname, 0, dns_reply_callback, resolveinfo); } else { r = evdns_base_resolve_ipv6(evdns_base, hostname, 0, dns_reply_callback, resolveinfo); } if (!r) { mm_free(resolveinfo); return -1; } /* We either need to incref the bufferevent here, or have some code to * cancel the resolve if the bufferevent gets freed. Let's take the * first approach. */ bufferevent_incref(bufev); return 0; }
int main(int argc, char *argv[]) { struct evdns_base *evdns_base; if (options_parse(&app_context, argc, argv) != 0) { return 1; } #ifdef _WIN32 WSADATA wsa_data; WSAStartup(MAKEWORD(2, 2), &wsa_data); #endif if ((app_context.event_loop = event_base_new()) == NULL) { perror("event_base_new"); return 1; } if ((evdns_base = evdns_base_new(app_context.event_loop, 0)) == NULL) { perror("evdns_base"); return 1; } evdns_base_set_option(evdns_base, "use-tcp", "on-tc"); evdns_base_set_option(evdns_base, "randomize-case", "0"); if (evdns_base_nameserver_ip_add(evdns_base, app_context.resolver_ip) != 0) { fprintf(stderr, "Unable to use [%s] as a resolver\n", app_context.resolver_ip); return 1; } if (app_context.want_ipv6 != 0) { evdns_base_resolve_ipv6(evdns_base, app_context.host_name, DNS_QUERY_NO_SEARCH, ipv6_query_cb, &app_context); } else { evdns_base_resolve_ipv4(evdns_base, app_context.host_name, DNS_QUERY_NO_SEARCH, ipv4_query_cb, &app_context); } event_base_dispatch(app_context.event_loop); event_base_free(app_context.event_loop); return 0; }
void IghtConnectionState::resolve(IghtConnectionState *self) { struct sockaddr_storage storage; int result; if (!self->connecting) abort(); if (self->closing) { delete (self); return; } // If self->address is a valid IPv4 address, connect directly memset(&storage, 0, sizeof (storage)); result = inet_pton(PF_INET, self->address, &storage); if (result == 1) { ight_info("resolve - address %s", self->address); ight_info("resolve - family PF_INET"); if (self->addrlist->append(self->address) != 0 || self->pflist->append("PF_INET") != 0) { ight_warn("resolve - cannot append"); self->connecting = 0; self->on_error(IghtError(-4)); return; } self->connect_next(); return; } // If self->address is a valid IPv6 address, connect directly memset(&storage, 0, sizeof (storage)); result = inet_pton(PF_INET6, self->address, &storage); if (result == 1) { ight_info("resolve - address %s", self->address); ight_info("resolve - family PF_INET6"); if (self->addrlist->append(self->address) != 0 || self->pflist->append("PF_INET6") != 0) { ight_warn("resolve - cannot append"); self->connecting = 0; self->on_error(IghtError(-4)); return; } self->connect_next(); return; } auto dns_base = ight_get_global_evdns_base(); // Note: PF_UNSPEC6 means that we try with IPv6 first if (strcmp(self->family, "PF_INET") == 0) self->must_resolve_ipv4 = 1; else if (strcmp(self->family, "PF_INET6") == 0) self->must_resolve_ipv6 = 1; else if (strcmp(self->family, "PF_UNSPEC") == 0) self->must_resolve_ipv4 = 1; else if (strcmp(self->family, "PF_UNSPEC6") == 0) self->must_resolve_ipv6 = 1; else { ight_warn("connection::resolve - invalid PF_xxx"); self->connecting = 0; self->on_error(IghtError(-5)); return; } evdns_request *request; if (self->must_resolve_ipv4) { self->must_resolve_ipv4 = 0; request = evdns_base_resolve_ipv4(dns_base, self->address, DNS_QUERY_NO_SEARCH, self->handle_resolve, self); } else { self->must_resolve_ipv6 = 0; request = evdns_base_resolve_ipv6(dns_base, self->address, DNS_QUERY_NO_SEARCH, self->handle_resolve, self); } if (request == NULL) { self->connecting = 0; self->on_error(IghtError(-6)); return; } // Arrange for the next resolve operation that we will need if (strcmp(self->family, "PF_UNSPEC") == 0) self->must_resolve_ipv6 = 1; else if (strcmp(self->family, "PF_UNSPEC6") == 0) self->must_resolve_ipv4 = 1; }
void IghtConnectionState::handle_resolve(int result, char type, int count, int ttl, void *addresses, void *opaque) { auto self = (IghtConnectionState *) opaque; const char *_family; const char *p; int error, family, size; char string[128]; (void) ttl; ight_info("handle_resolve - enter"); if (!self->connecting) abort(); if (self->closing) { delete (self); return; } if (result != DNS_ERR_NONE) goto finally; switch (type) { case DNS_IPv4_A: ight_info("handle_resolve - IPv4"); family = PF_INET; _family = "PF_INET"; size = 4; break; case DNS_IPv6_AAAA: ight_info("handle_resolve - IPv6"); family = PF_INET6; _family = "PF_INET6"; size = 16; break; default: abort(); } while (--count >= 0) { if (count > INT_MAX / size) { continue; } // Note: address already in network byte order p = inet_ntop(family, (char *)addresses + count * size, string, sizeof (string)); if (p == NULL) { ight_warn("handle_resolve - inet_ntop() failed"); continue; } ight_info("handle_resolve - address %s", p); error = self->addrlist->append(string); if (error != 0) { ight_warn("handle_resolve - cannot append"); continue; } ight_info("handle_resolve - family %s", _family); error = self->pflist->append(_family); if (error != 0) { ight_warn("handle_resolve - cannot append"); // Oops the two vectors are not in sync anymore now self->connecting = 0; self->on_error(IghtError(-3)); return; } } finally: auto dns_base = ight_get_global_evdns_base(); if (self->must_resolve_ipv6) { self->must_resolve_ipv6 = 0; evdns_request *request = evdns_base_resolve_ipv6(dns_base, self->address, DNS_QUERY_NO_SEARCH, self->handle_resolve, self); if (request != NULL) return; /* FALLTHROUGH */ } if (self->must_resolve_ipv4) { self->must_resolve_ipv4 = 0; evdns_request *request = evdns_base_resolve_ipv4(dns_base, self->address, DNS_QUERY_NO_SEARCH, self->handle_resolve, self); if (request != NULL) return; /* FALLTHROUGH */ } self->connect_next(); }
static void dns_server(void) { evutil_socket_t sock=-1; struct sockaddr_in my_addr; struct evdns_server_port *port=NULL; struct in_addr resolve_addr; struct in6_addr resolve_addr6; struct evdns_base *base=NULL; struct evdns_request *req=NULL; dns_ok = 1; base = evdns_base_new(NULL, 0); /* Add ourself as the only nameserver, and make sure we really are * the only nameserver. */ evdns_base_nameserver_ip_add(base, "127.0.0.1:35353"); tt_int_op(evdns_base_count_nameservers(base), ==, 1); /* Now configure a nameserver port. */ sock = socket(AF_INET, SOCK_DGRAM, 0); if (sock<0) { tt_abort_perror("socket"); } evutil_make_socket_nonblocking(sock); memset(&my_addr, 0, sizeof(my_addr)); my_addr.sin_family = AF_INET; my_addr.sin_port = htons(35353); my_addr.sin_addr.s_addr = htonl(0x7f000001UL); if (bind(sock, (struct sockaddr*)&my_addr, sizeof(my_addr)) < 0) { tt_abort_perror("bind"); } port = evdns_add_server_port(sock, 0, dns_server_request_cb, NULL); /* Send some queries. */ evdns_base_resolve_ipv4(base, "zz.example.com", DNS_QUERY_NO_SEARCH, dns_server_gethostbyname_cb, NULL); evdns_base_resolve_ipv6(base, "zz.example.com", DNS_QUERY_NO_SEARCH, dns_server_gethostbyname_cb, NULL); resolve_addr.s_addr = htonl(0xc0a80b0bUL); /* 192.168.11.11 */ evdns_base_resolve_reverse(base, &resolve_addr, 0, dns_server_gethostbyname_cb, NULL); memcpy(resolve_addr6.s6_addr, "\xff\xf0\x00\x00\x00\x00\xaa\xaa" "\x11\x11\x00\x00\x00\x00\xef\xef", 16); evdns_base_resolve_reverse_ipv6(base, &resolve_addr6, 0, dns_server_gethostbyname_cb, (void*)6); req = evdns_base_resolve_ipv4(base, "drop.example.com", DNS_QUERY_NO_SEARCH, dns_server_gethostbyname_cb, (void*)(char*)90909); evdns_cancel_request(base, req); event_dispatch(); tt_assert(dns_got_cancel); test_ok = dns_ok; end: if (port) evdns_close_server_port(port); if (sock >= 0) EVUTIL_CLOSESOCKET(sock); if (base) evdns_base_free(base, 0); }