static void dns_search_test(void *arg) { struct basic_test_data *data = arg; struct event_base *base = data->base; struct evdns_base *dns = NULL; ev_uint16_t portnum = 0; char buf[64]; struct generic_dns_callback_result r1, r2, r3, r4, r5; tt_assert(regress_dnsserver(base, &portnum, search_table)); evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); dns = evdns_base_new(base, 0); tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); evdns_base_search_add(dns, "a.example.com"); evdns_base_search_add(dns, "b.example.com"); evdns_base_search_add(dns, "c.example.com"); n_replies_left = 5; exit_base = base; evdns_base_resolve_ipv4(dns, "host", 0, generic_dns_callback, &r1); evdns_base_resolve_ipv4(dns, "host2", 0, generic_dns_callback, &r2); evdns_base_resolve_ipv4(dns, "host", DNS_NO_SEARCH, generic_dns_callback, &r3); evdns_base_resolve_ipv4(dns, "host2", DNS_NO_SEARCH, generic_dns_callback, &r4); evdns_base_resolve_ipv4(dns, "host3", 0, generic_dns_callback, &r5); event_base_dispatch(base); tt_int_op(r1.type, ==, DNS_IPv4_A); tt_int_op(r1.count, ==, 1); tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x0b16212c)); tt_int_op(r2.type, ==, DNS_IPv4_A); tt_int_op(r2.count, ==, 1); tt_int_op(((ev_uint32_t*)r2.addrs)[0], ==, htonl(0xc8640064)); tt_int_op(r3.result, ==, DNS_ERR_NOTEXIST); tt_int_op(r4.result, ==, DNS_ERR_NOTEXIST); tt_int_op(r5.result, ==, DNS_ERR_NOTEXIST); end: if (dns) evdns_base_free(dns, 0); regress_clean_dnsserver(); }
static void handle_tcp_connect_stage1(struct async_network_task_s *task) { struct evdns_request *req; struct sockaddr_in sai; memset(&sai, 0, sizeof(sai)); if (inet_pton(AF_INET, task->host, &sai.sin_addr) == 1) { // already a valid IP address handle_tcp_connect_stage2(DNS_ERR_NONE, DNS_IPv4_A, 1, 300, &sai.sin_addr, task); return; } // queue DNS request req = evdns_base_resolve_ipv4(evdns_b, task->host, DNS_QUERY_NO_SEARCH, handle_tcp_connect_stage2, task); // TODO: what about ipv6? if (!req) { trace_warning("%s, early dns resolution failure (%s:%u)\n", __func__, task->host, (unsigned int)task->port); ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, PP_ERROR_NAME_NOT_RESOLVED, 0, __func__); task_destroy(task); return; } }
static void dns_search_test(void *arg) { struct basic_test_data *data = arg; struct event_base *base = data->base; struct evdns_base *dns = NULL; ev_uint16_t portnum = 0; char buf[64]; struct generic_dns_callback_result r[8]; tt_assert(regress_dnsserver(base, &portnum, search_table)); evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); dns = evdns_base_new(base, 0); tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); evdns_base_search_add(dns, "a.example.com"); evdns_base_search_add(dns, "b.example.com"); evdns_base_search_add(dns, "c.example.com"); n_replies_left = sizeof(r)/sizeof(r[0]); exit_base = base; evdns_base_resolve_ipv4(dns, "host", 0, generic_dns_callback, &r[0]); evdns_base_resolve_ipv4(dns, "host2", 0, generic_dns_callback, &r[1]); evdns_base_resolve_ipv4(dns, "host", DNS_NO_SEARCH, generic_dns_callback, &r[2]); evdns_base_resolve_ipv4(dns, "host2", DNS_NO_SEARCH, generic_dns_callback, &r[3]); evdns_base_resolve_ipv4(dns, "host3", 0, generic_dns_callback, &r[4]); evdns_base_resolve_ipv4(dns, "hostn.a.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[5]); evdns_base_resolve_ipv4(dns, "hostn.b.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[6]); evdns_base_resolve_ipv4(dns, "hostn.c.example.com", DNS_NO_SEARCH, generic_dns_callback, &r[7]); event_base_dispatch(base); tt_int_op(r[0].type, ==, DNS_IPv4_A); tt_int_op(r[0].count, ==, 1); tt_int_op(((ev_uint32_t*)r[0].addrs)[0], ==, htonl(0x0b16212c)); tt_int_op(r[1].type, ==, DNS_IPv4_A); tt_int_op(r[1].count, ==, 1); tt_int_op(((ev_uint32_t*)r[1].addrs)[0], ==, htonl(0xc8640064)); tt_int_op(r[2].result, ==, DNS_ERR_NOTEXIST); tt_int_op(r[3].result, ==, DNS_ERR_NOTEXIST); tt_int_op(r[4].result, ==, DNS_ERR_NOTEXIST); tt_int_op(r[5].result, ==, DNS_ERR_NODATA); tt_int_op(r[5].ttl, ==, 42); tt_int_op(r[6].result, ==, DNS_ERR_NOTEXIST); tt_int_op(r[6].ttl, ==, 42); tt_int_op(r[7].result, ==, DNS_ERR_NODATA); tt_int_op(r[7].ttl, ==, 0); end: if (dns) evdns_base_free(dns, 0); regress_clean_dnsserver(); }
bool Server::connect(const char *h, const char *n, int p, const char *alias_) { host = strdup(h); port = p; if(alias_) alias = strdup(alias_); else alias = strdup(h); nick = strdup(n); DEBUGF(evdns_base_resolve_ipv4(client->dnsbase, host, 0, irc_dnscb, this)); return true; }
static void dns_reissue_test(void *arg) { struct basic_test_data *data = arg; struct event_base *base = data->base; struct evdns_server_port *port1 = NULL, *port2 = NULL; struct evdns_base *dns = NULL; struct generic_dns_callback_result r1; ev_uint16_t portnum1 = 0, portnum2=0; char buf1[64], buf2[64]; port1 = regress_get_dnsserver(base, &portnum1, NULL, regress_dns_server_cb, internal_error_table); tt_assert(port1); port2 = regress_get_dnsserver(base, &portnum2, NULL, regress_dns_server_cb, reissue_table); tt_assert(port2); evutil_snprintf(buf1, sizeof(buf1), "127.0.0.1:%d", (int)portnum1); evutil_snprintf(buf2, sizeof(buf2), "127.0.0.1:%d", (int)portnum2); dns = evdns_base_new(base, 0); tt_assert(!evdns_base_nameserver_ip_add(dns, buf1)); tt_assert(! evdns_base_set_option(dns, "timeout:", "0.3")); tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "2")); tt_assert(! evdns_base_set_option(dns, "attempts:", "5")); memset(&r1, 0, sizeof(r1)); evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r1); /* Add this after, so that we are sure to get a reissue. */ tt_assert(!evdns_base_nameserver_ip_add(dns, buf2)); n_replies_left = 1; exit_base = base; event_base_dispatch(base); tt_int_op(r1.result, ==, DNS_ERR_NONE); tt_int_op(r1.type, ==, DNS_IPv4_A); tt_int_op(r1.count, ==, 1); tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0xf00ff00f)); /* Make sure we dropped at least once. */ tt_int_op(internal_error_table[0].seen, >, 0); end: if (dns) evdns_base_free(dns, 0); if (port1) evdns_close_server_port(port1); if (port2) evdns_close_server_port(port2); }
/* 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; }
IoObject *IoEvDNSRequest_resolveIPv4(IoEvDNSRequest *self, IoObject *locals, IoMessage *m) { IoSeq *host = IoObject_seqGetSlot_(self, IOSYMBOL("host")); IoEvDNS *evDns = IoObject_getSlot_(self, IOSYMBOL("evDns")); IOASSERT(ISEVDNS(evDns), "evDns slot not set properly"); struct evdns_base *dnsBase = IoObject_dataPointer(evDns); struct evdns_request *req = evdns_base_resolve_ipv4(dnsBase, CSTRING(host), DNS_QUERY_NO_SEARCH, (EvDNSRequest_callback_type)EvDNSRequest_callback, (void *)self ); IoObject_setDataPointer_(self, req); return self; }
static void dns_inflight_test(void *arg) { struct basic_test_data *data = arg; struct event_base *base = data->base; struct evdns_base *dns = NULL; ev_uint16_t portnum = 53900;/*XXXX let the code pick a port*/ struct generic_dns_callback_result r[20]; int i; tt_assert(regress_dnsserver(base, &portnum, reissue_table)); /* Make sure that having another (very bad!) RNG doesn't mess us * up. */ evdns_set_random_bytes_fn(dumb_bytes_fn); dns = evdns_base_new(base, 0); tt_assert(!evdns_base_nameserver_ip_add(dns, "127.0.0.1:53900")); tt_assert(! evdns_base_set_option(dns, "max-inflight:", "3", DNS_OPTIONS_ALL)); tt_assert(! evdns_base_set_option(dns, "randomize-case:", "0", DNS_OPTIONS_ALL)); for(i=0;i<20;++i) evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r[i]); n_replies_left = 20; exit_base = base; event_base_dispatch(base); for (i=0;i<20;++i) { tt_int_op(r[i].type, ==, DNS_IPv4_A); tt_int_op(r[i].count, ==, 1); tt_int_op(((ev_uint32_t*)r[i].addrs)[0], ==, htonl(0xf00ff00f)); } end: if (dns) evdns_base_free(dns, 0); regress_clean_dnsserver(); }
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; }
static void dns_search_cancel_test(void *arg) { struct basic_test_data *data = arg; struct event_base *base = data->base; struct evdns_base *dns = NULL; struct evdns_server_port *port = NULL; ev_uint16_t portnum = 0; struct generic_dns_callback_result r1; char buf[64]; port = regress_get_dnsserver(base, &portnum, NULL, search_cancel_server_cb, NULL); tt_assert(port); evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); dns = evdns_base_new(base, 0); tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); evdns_base_search_add(dns, "a.example.com"); evdns_base_search_add(dns, "b.example.com"); evdns_base_search_add(dns, "c.example.com"); evdns_base_search_add(dns, "d.example.com"); exit_base = base; request_count = 3; n_replies_left = 1; current_req = evdns_base_resolve_ipv4(dns, "host", 0, generic_dns_callback, &r1); event_base_dispatch(base); tt_int_op(r1.result, ==, DNS_ERR_CANCEL); end: if (port) evdns_close_server_port(port); if (dns) evdns_base_free(dns, 0); }
static void dns_inflight_test(void *arg) { struct basic_test_data *data = arg; struct event_base *base = data->base; struct evdns_base *dns = NULL; ev_uint16_t portnum = 0; char buf[64]; struct generic_dns_callback_result r[20]; int i; tt_assert(regress_dnsserver(base, &portnum, reissue_table)); evutil_snprintf(buf, sizeof(buf), "127.0.0.1:%d", (int)portnum); dns = evdns_base_new(base, 0); tt_assert(!evdns_base_nameserver_ip_add(dns, buf)); tt_assert(! evdns_base_set_option(dns, "max-inflight:", "3")); tt_assert(! evdns_base_set_option(dns, "randomize-case:", "0")); for (i=0;i<20;++i) evdns_base_resolve_ipv4(dns, "foof.example.com", 0, generic_dns_callback, &r[i]); n_replies_left = 20; exit_base = base; event_base_dispatch(base); for (i=0;i<20;++i) { tt_int_op(r[i].type, ==, DNS_IPv4_A); tt_int_op(r[i].count, ==, 1); tt_int_op(((ev_uint32_t*)r[i].addrs)[0], ==, htonl(0xf00ff00f)); } end: if (dns) evdns_base_free(dns, 0); regress_clean_dnsserver(); }
static void dns_retry_test(void *arg) { struct basic_test_data *data = arg; struct event_base *base = data->base; struct evdns_server_port *port = NULL; struct evdns_base *dns = NULL; int drop_count = 2; ev_uint16_t portnum = 53900;/*XXXX let the code pick a port*/ struct generic_dns_callback_result r1; port = regress_get_dnsserver(base, &portnum, NULL, fail_server_cb, &drop_count); tt_assert(port); dns = evdns_base_new(base, 0); tt_assert(!evdns_base_nameserver_ip_add(dns, "127.0.0.1:53900")); tt_assert(! evdns_base_set_option(dns, "timeout", "0.3", DNS_OPTIONS_ALL)); tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "10", DNS_OPTIONS_ALL)); tt_assert(! evdns_base_set_option(dns, "initial-probe-timeout", "0.5", DNS_OPTIONS_ALL)); evdns_base_resolve_ipv4(dns, "host.example.com", 0, generic_dns_callback, &r1); n_replies_left = 1; exit_base = base; event_base_dispatch(base); tt_int_op(drop_count, ==, 0); tt_int_op(r1.type, ==, DNS_IPv4_A); tt_int_op(r1.count, ==, 1); tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x10204080)); /* Now try again, but this time have the server get treated as * failed, so we can send it a test probe. */ drop_count = 4; tt_assert(! evdns_base_set_option(dns, "max-timeouts:", "3", DNS_OPTIONS_ALL)); tt_assert(! evdns_base_set_option(dns, "attempts:", "4", DNS_OPTIONS_ALL)); memset(&r1, 0, sizeof(r1)); evdns_base_resolve_ipv4(dns, "host.example.com", 0, generic_dns_callback, &r1); n_replies_left = 2; /* This will run until it answers the "google.com" probe request. */ event_base_dispatch(base); /* We'll treat the server as failed here. */ tt_int_op(r1.result, ==, DNS_ERR_TIMEOUT); /* It should work this time. */ tt_int_op(drop_count, ==, 0); evdns_base_resolve_ipv4(dns, "host.example.com", 0, generic_dns_callback, &r1); event_base_dispatch(base); tt_int_op(r1.result, ==, DNS_ERR_NONE); tt_int_op(r1.type, ==, DNS_IPv4_A); tt_int_op(r1.count, ==, 1); tt_int_op(((ev_uint32_t*)r1.addrs)[0], ==, htonl(0x10204080)); end: if (dns) evdns_base_free(dns, 0); if (port) evdns_close_server_port(port); }
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); }
static void handle_disconnect_stage1(struct async_network_task_s *task) { struct event *ev = evtimer_new(event_b, handle_disconnect_stage2, task); struct timeval timeout = {.tv_sec = 0}; add_event_mapping(task, ev); event_add(ev, &timeout); } static void handle_udp_recv_stage2(int sock, short event_flags, void *arg) { struct async_network_task_s *task = arg; struct pp_udp_socket_s *us = pp_resource_acquire(task->resource, PP_RESOURCE_UDP_SOCKET); if (!us) { trace_error("%s, bad resource\n", __func__); task_destroy(task); return; } socklen_t len = sizeof(task->addr_from->data); int32_t retval = recvfrom(sock, task->buffer, task->bufsize, 0, (struct sockaddr *)task->addr_from->data, &len); task->addr_from->size = len; if (task->addr_from_resource) pp_resource_unref(task->addr_from_resource); if (retval < 0) retval = get_pp_errno(); else if (retval == 0) { us->seen_eof = 1; // TODO: is it needed? } pp_resource_release(task->resource); ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, retval, 0, __func__); task_destroy(task); } static void handle_udp_recv_stage1(struct async_network_task_s *task) { struct pp_udp_socket_s *us = pp_resource_acquire(task->resource, PP_RESOURCE_UDP_SOCKET); if (!us) { trace_error("%s, bad resource\n", __func__); task_destroy(task); return; } memset(task->addr_from, 0, sizeof(*task->addr_from)); struct event *ev = event_new(event_b, us->sock, EV_READ, handle_udp_recv_stage2, task); pp_resource_release(task->resource); add_event_mapping(task, ev); event_add(ev, NULL); } static void handle_udp_send_stage2(int sock, short event_flags, void *arg) { struct async_network_task_s *task = arg; int retval = sendto(sock, task->buffer, task->bufsize, MSG_NOSIGNAL, (struct sockaddr *)task->netaddr.data, task->netaddr.size); if (retval < 0) retval = get_pp_errno(); ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, retval, 0, __func__); task_destroy(task); } static void handle_udp_send_stage1(struct async_network_task_s *task) { struct pp_udp_socket_s *us = pp_resource_acquire(task->resource, PP_RESOURCE_UDP_SOCKET); if (!us) { trace_error("%s, bad resource\n", __func__); task_destroy(task); return; } // try to send immediately, but don't wait int retval = sendto(us->sock, task->buffer, task->bufsize, MSG_DONTWAIT | MSG_NOSIGNAL, (struct sockaddr *)task->netaddr.data, task->netaddr.size); pp_resource_release(task->resource); if (retval >= 0) { // successfully sent ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, retval, 0, __func__); task_destroy(task); return; } // need to wait struct event *ev = event_new(event_b, us->sock, EV_WRITE, handle_udp_send_stage2, task); add_event_mapping(task, ev); event_add(ev, NULL); } static void handle_host_resolve_stage2(int result, char type, int count, int ttl, void *addresses, void *arg) { struct async_network_task_s *task = arg; if (result != DNS_ERR_NONE || count < 1) { trace_warning("%s, evdns returned code %d, count = %d (%s:%u)\n", __func__, result, count, task->host, (unsigned int)task->port); ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, PP_ERROR_NAME_NOT_RESOLVED, 0, __func__); task_destroy(task); return; } struct pp_host_resolver_s *hr = pp_resource_acquire(task->resource, PP_RESOURCE_HOST_RESOLVER); if (!hr) { trace_error("%s, bad resource\n", __func__); task_destroy(task); return; } hr->addr_count = count; hr->addrs = calloc(count, sizeof(struct PP_NetAddress_Private)); if (type == DNS_IPv4_A) { struct in_addr *ipv4_addrs = addresses; for (int k = 0; k < count; k ++) { struct sockaddr_in sai = { .sin_family = AF_INET, .sin_port = htons(task->port), }; memcpy(&sai.sin_addr, &ipv4_addrs[k], sizeof(struct in_addr)); hr->addrs[k].size = sizeof(struct sockaddr_in); memcpy(hr->addrs[k].data, &sai, sizeof(sai)); } ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, PP_OK, 0, __func__); } else if (type == DNS_IPv6_AAAA) { struct in6_addr *ipv6_addrs = addresses; for (int k = 0; k < count; k ++) { struct sockaddr_in6 sai6 = { .sin6_family = AF_INET6, .sin6_port = htons(task->port), }; memcpy(&sai6.sin6_addr, &ipv6_addrs[k], sizeof(struct in6_addr)); hr->addrs[k].size = sizeof(struct sockaddr_in6); memcpy(hr->addrs[k].data, &sai6, sizeof(sai6)); } ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, PP_OK, 0, __func__); } else { trace_error("%s, bad evdns type %d (%s:%u)\n", __func__, type, task->host, (unsigned int)task->port); ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, PP_ERROR_FAILED, 0, __func__); } pp_resource_release(task->resource); task_destroy(task); } static void handle_host_resolve_stage1(struct async_network_task_s *task) { struct evdns_request *req; // queue DNS request req = evdns_base_resolve_ipv4(evdns_b, task->host, DNS_QUERY_NO_SEARCH, handle_host_resolve_stage2, task); // TODO: what about ipv6? if (!req) { trace_warning("%s, early dns resolution failure (%s:%u)\n", __func__, task->host, (unsigned int)task->port); ppb_message_loop_post_work_with_result(task->callback_ml, task->callback, 0, PP_ERROR_NAME_NOT_RESOLVED, 0, __func__); task_destroy(task); return; } } static void * network_worker_thread(void *param) { event_base_dispatch(event_b); event_base_free(event_b); trace_error("%s, thread terminated\n", __func__); return NULL; }
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(); }
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; }
static void irc_reconnectcb(int fd, short type, void *arg) { printf("Reconnecting...\n"); Server *s = (Server *)arg; DEBUGF(evdns_base_resolve_ipv4(s->client->dnsbase, s->host, 0, irc_dnscb, arg)); }