static void host_resolved(gpointer data, gint source, PurpleInputCondition cond) { PurpleDnsQueryData *query_data; int rc, err; GSList *hosts = NULL; struct sockaddr *addr = NULL; size_t addrlen; char message[1024]; query_data = data; purple_debug_info("dns", "Got response for '%s'\n", query_data->hostname); purple_input_remove(query_data->resolver->inpa); query_data->resolver->inpa = 0; rc = read(query_data->resolver->fd_out, &err, sizeof(err)); if ((rc == 4) && (err != 0)) { #ifdef HAVE_GETADDRINFO g_snprintf(message, sizeof(message), _("Error resolving %s:\n%s"), query_data->hostname, purple_gai_strerror(err)); #else g_snprintf(message, sizeof(message), _("Error resolving %s: %d"), query_data->hostname, err); #endif /* Re-read resolv.conf and friends in case DNS servers have changed */ res_init(); purple_dnsquery_failed(query_data, message); } else if (rc > 0) { /* Success! */ while (rc > 0) { rc = read(query_data->resolver->fd_out, &addrlen, sizeof(addrlen)); if (rc > 0 && addrlen > 0 && addrlen < MAX_ADDR_RESPONSE_LEN) { addr = g_malloc(addrlen); rc = read(query_data->resolver->fd_out, addr, addrlen); hosts = g_slist_append(hosts, GINT_TO_POINTER(addrlen)); hosts = g_slist_append(hosts, addr); } else { break; } } /* wait4(resolver->dns_pid, NULL, WNOHANG, NULL); */ purple_dnsquery_resolved(query_data, hosts); } else if (rc == -1) { g_snprintf(message, sizeof(message), _("Error reading from resolver process:\n%s"), g_strerror(errno)); purple_dnsquery_failed(query_data, message); } else if (rc == 0) { g_snprintf(message, sizeof(message), _("Resolver process exited without answering our request")); purple_dnsquery_failed(query_data, message); } handle_next_queued_request(); }
static gpointer dns_thread(gpointer d) { ResolverData *data = (ResolverData *) d; PurpleDnsQueryData *query_data; // #ifdef HAVE_GETADDRINFO int rc; struct addrinfo hints, *res, *tmp; char servname[20]; // #else // struct sockaddr_in sin; // struct hostent *hp; // #endif char *hostname; query_data = data->query_data; // Currently we don't support IDN // #ifdef USE_IDN // if (!dns_str_is_ascii(purple_dnsquery_get_host(query_data))) { // rc = purple_network_convert_idn_to_ascii(purple_dnsquery_get_host(query_data), &hostname); // if (rc != 0) { // data->error_message = g_strdup_printf(_("Error converting %s " // "to punycode: %d"), purple_dnsquery_get_host(query_data), rc); // /* back to main thread */ // purple_timeout_add(0, dns_main_thread_cb, query_data); // return 0; // } // } else /* intentional fallthru */ // #endif hostname = g_strdup(purple_dnsquery_get_host(query_data)); // #ifdef HAVE_GETADDRINFO g_snprintf(servname, sizeof(servname), "%d", purple_dnsquery_get_port(query_data)); memset(&hints,0,sizeof(hints)); /* * This is only used to convert a service * name to a port number. As we know we are * passing a number already, we know this * value will not be really used by the C * library. */ hints.ai_socktype = SOCK_STREAM; // #ifdef AI_ADDRCONFIG // hints.ai_flags |= AI_ADDRCONFIG; // #endif /* AI_ADDRCONFIG */ if ((rc = getaddrinfo(hostname, servname, &hints, &res)) == 0) { tmp = res; while(res) { data->hosts = g_slist_append(data->hosts, GSIZE_TO_POINTER(res->ai_addrlen)); data->hosts = g_slist_append(data->hosts, g_memdup(res->ai_addr, res->ai_addrlen)); res = res->ai_next; } freeaddrinfo(tmp); } else { g_mutex_lock(data->mutex); bool destroyed = data->destroyed; g_mutex_unlock(data->mutex); if (!destroyed) { data->error_message = g_strdup_printf("Error resolving %s:\n%s", purple_dnsquery_get_host(query_data), purple_gai_strerror(rc)); } } // #else // if ((hp = gethostbyname(hostname))) { // memset(&sin, 0, sizeof(struct sockaddr_in)); // memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length); // sin.sin_family = hp->h_addrtype; // sin.sin_port = htons(purple_dnsquery_get_port(query_data)); // // data->hosts = g_slist_append(data->hosts, // GSIZE_TO_POINTER(sizeof(sin))); // data->hosts = g_slist_append(data->hosts, // g_memdup(&sin, sizeof(sin))); // } else { // data->error_message = g_strdup_printf("Error resolving %s: %d", purple_dnsquery_get_host(query_data), h_errno); // } // #endif g_free(hostname); /* back to main thread */ purple_timeout_add(0, dns_main_thread_cb, data); return 0; }
static gpointer dns_thread(gpointer data) { PurpleDnsQueryData *query_data; #ifdef HAVE_GETADDRINFO int rc; struct addrinfo hints, *res, *tmp; char servname[20]; #else struct sockaddr_in sin; struct hostent *hp; #endif char *hostname; query_data = data; #ifdef USE_IDN if (!dns_str_is_ascii(query_data->hostname)) { rc = purple_network_convert_idn_to_ascii(query_data->hostname, &hostname); if (rc != 0) { query_data->error_message = g_strdup_printf(_("Error converting %s " "to punycode: %d"), query_data->hostname, rc); /* back to main thread */ purple_timeout_add(0, dns_main_thread_cb, query_data); return 0; } } else /* intentional fallthru */ #endif hostname = g_strdup(query_data->hostname); #ifdef HAVE_GETADDRINFO g_snprintf(servname, sizeof(servname), "%d", query_data->port); memset(&hints,0,sizeof(hints)); /* * This is only used to convert a service * name to a port number. As we know we are * passing a number already, we know this * value will not be really used by the C * library. */ hints.ai_socktype = SOCK_STREAM; #ifdef AI_ADDRCONFIG hints.ai_flags |= AI_ADDRCONFIG; #endif /* AI_ADDRCONFIG */ if ((rc = getaddrinfo(hostname, servname, &hints, &res)) == 0) { tmp = res; while(res) { query_data->hosts = g_slist_append(query_data->hosts, GSIZE_TO_POINTER(res->ai_addrlen)); query_data->hosts = g_slist_append(query_data->hosts, g_memdup(res->ai_addr, res->ai_addrlen)); res = res->ai_next; } freeaddrinfo(tmp); } else { query_data->error_message = g_strdup_printf(_("Error resolving %s:\n%s"), query_data->hostname, purple_gai_strerror(rc)); } #else if ((hp = gethostbyname(hostname))) { memset(&sin, 0, sizeof(struct sockaddr_in)); memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length); sin.sin_family = hp->h_addrtype; sin.sin_port = htons(query_data->port); query_data->hosts = g_slist_append(query_data->hosts, GSIZE_TO_POINTER(sizeof(sin))); query_data->hosts = g_slist_append(query_data->hosts, g_memdup(&sin, sizeof(sin))); } else { query_data->error_message = g_strdup_printf(_("Error resolving %s: %d"), query_data->hostname, h_errno); } #endif g_free(hostname); /* back to main thread */ purple_timeout_add(0, dns_main_thread_cb, query_data); return 0; }