/* 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;
}
Exemple #2
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;
}
Exemple #3
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;
}
Exemple #4
0
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();
}
Exemple #5
0
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);
}