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 gboolean resolve_ip(PurpleDnsQueryData *query_data) { #if defined(HAVE_GETADDRINFO) && defined(AI_NUMERICHOST) struct addrinfo hints, *res; char servname[20]; g_snprintf(servname, sizeof(servname), "%d", query_data->port); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_flags |= AI_NUMERICHOST; if (0 == getaddrinfo(query_data->hostname, servname, &hints, &res)) { GSList *hosts = NULL; hosts = g_slist_append(hosts, GINT_TO_POINTER(res->ai_addrlen)); hosts = g_slist_append(hosts, g_memdup(res->ai_addr, res->ai_addrlen)); purple_dnsquery_resolved(query_data, hosts); freeaddrinfo(res); return TRUE; } #else /* defined(HAVE_GETADDRINFO) && defined(AI_NUMERICHOST) */ struct sockaddr_in sin; if (inet_aton(query_data->hostname, &sin.sin_addr)) { /* * The given "hostname" is actually an IP address, so we * don't need to do anything. */ GSList *hosts = NULL; sin.sin_family = AF_INET; sin.sin_port = htons(query_data->port); hosts = g_slist_append(hosts, GINT_TO_POINTER(sizeof(sin))); hosts = g_slist_append(hosts, g_memdup(&sin, sizeof(sin))); purple_dnsquery_resolved(query_data, hosts); return TRUE; } #endif return FALSE; }
static gboolean resolve_host(gpointer data) { PurpleDnsQueryData *query_data; struct sockaddr_in sin; GError *err = NULL; query_data = data; query_data->timeout = 0; if (purple_dnsquery_ui_resolve(query_data)) { /* The UI is handling the resolve; we're done */ return FALSE; } if (inet_aton(query_data->hostname, &sin.sin_addr)) { /* * The given "hostname" is actually an IP address, so we * don't need to do anything. */ GSList *hosts = NULL; sin.sin_family = AF_INET; sin.sin_port = htons(query_data->port); hosts = g_slist_append(hosts, GINT_TO_POINTER(sizeof(sin))); hosts = g_slist_append(hosts, g_memdup(&sin, sizeof(sin))); purple_dnsquery_resolved(query_data, hosts); } else { /* * Spin off a separate thread to perform the DNS lookup so * that we don't block the UI. */ query_data->resolver = g_thread_create(dns_thread, query_data, FALSE, &err); if (query_data->resolver == NULL) { char message[1024]; g_snprintf(message, sizeof(message), _("Thread creation failure: %s"), (err && err->message) ? err->message : _("Unknown reason")); g_error_free(err); purple_dnsquery_failed(query_data, message); } } return FALSE; }
static void resolve_host(PurpleDnsQueryData *query_data) { struct sockaddr_in sin; GSList *hosts = NULL; struct hostent *hp; gchar *hostname; #ifdef USE_IDN if (!dns_str_is_ascii(query_data->hostname)) { int ret = purple_network_convert_idn_to_ascii(query_data->hostname, &hostname); if (ret != 0) { char message[1024]; g_snprintf(message, sizeof(message), _("Error resolving %s: %d"), query_data->hostname, ret); purple_dnsquery_failed(query_data, message); return; } } else /* fallthrough is intentional to the g_strdup */ #endif hostname = g_strdup(query_data->hostname); if(!(hp = gethostbyname(hostname))) { char message[1024]; g_snprintf(message, sizeof(message), _("Error resolving %s: %d"), query_data->hostname, h_errno); purple_dnsquery_failed(query_data, message); g_free(hostname); return; } 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; g_free(hostname); sin.sin_port = htons(query_data->port); hosts = g_slist_append(hosts, GINT_TO_POINTER(sizeof(sin))); hosts = g_slist_append(hosts, g_memdup(&sin, sizeof(sin))); purple_dnsquery_resolved(query_data, hosts); }
static gboolean dns_main_thread_cb(gpointer data) { PurpleDnsQueryData *query_data; query_data = data; if (query_data->error_message != NULL) purple_dnsquery_failed(query_data, query_data->error_message); else { GSList *hosts; /* We don't want purple_dns_query_resolved() to free(hosts) */ hosts = query_data->hosts; query_data->hosts = NULL; purple_dnsquery_resolved(query_data, hosts); } return FALSE; }
static gboolean resolve_host(gpointer data) { PurpleDnsQueryData *query_data; struct sockaddr_in sin; GSList *hosts = NULL; query_data = data; query_data->timeout = 0; if (purple_dnsquery_ui_resolve(query_data)) { /* The UI is handling the resolve; we're done */ return FALSE; } if (!inet_aton(query_data->hostname, &sin.sin_addr)) { struct hostent *hp; if(!(hp = gethostbyname(query_data->hostname))) { char message[1024]; g_snprintf(message, sizeof(message), _("Error resolving %s: %d"), query_data->hostname, h_errno); purple_dnsquery_failed(query_data, message); return FALSE; } 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; } else sin.sin_family = AF_INET; sin.sin_port = htons(query_data->port); hosts = g_slist_append(hosts, GINT_TO_POINTER(sizeof(sin))); hosts = g_slist_append(hosts, g_memdup(&sin, sizeof(sin))); purple_dnsquery_resolved(query_data, hosts); return FALSE; }
static gboolean dns_main_thread_cb(gpointer data) { PurpleDnsQueryData *query_data = data; /* We're done, so purple_dnsquery_destroy() shouldn't think it is canceling an in-progress lookup */ query_data->resolver = NULL; if (query_data->error_message != NULL) purple_dnsquery_failed(query_data, query_data->error_message); else { GSList *hosts; /* We don't want purple_dns_query_resolved() to free(hosts) */ hosts = query_data->hosts; query_data->hosts = NULL; purple_dnsquery_resolved(query_data, hosts); } return FALSE; }