static gboolean resolve_ip(ResolverData *data) { PurpleDnsQueryData *query_data = (PurpleDnsQueryData *) data->query_data; struct sockaddr_in sin; if (inet_aton(purple_dnsquery_get_host(query_data), &sin.sin_addr)) { // The given "hostname" is actually an IP address, so we don't need to do anything. Log("DNSResolver", "Resolving " << purple_dnsquery_get_host(query_data) << ": It's IP, don't do anything."); GSList *hosts = NULL; sin.sin_family = AF_INET; sin.sin_port = htons(purple_dnsquery_get_port(query_data)); hosts = g_slist_append(hosts, GINT_TO_POINTER(sizeof(sin))); hosts = g_slist_append(hosts, g_memdup(&sin, sizeof(sin))); data->resolved_cb(query_data, hosts); delete data; return TRUE; } return FALSE; }
nsresult purpleDNSRequest::OnLookupComplete(nsICancelable *request, nsIDNSRecord *record, nsresult status) { NS_ASSERTION(NS_IsMainThread(), "wrong thread"); NS_ASSERTION(request == asyncResolv, "wrong request"); purpleAccountScoper scoper(mAccountId); if (NS_FAILED(status)) { Failed("DNS query failed\n"); return NS_OK; } GSList *hosts = NULL; bool more; record->HasMore(&more); if (!more) { Failed("Not found\n"); return NS_OK; } if (NS_FAILED(purpleDNS::Remove(query_data))) { LOG(("DNS resolution completed but result discarded because it was cancelled")); return NS_OK; } mozilla::net::NetAddr netAddr; for (; more; record->HasMore(&more)) { unsigned short port = purple_dnsquery_get_port(query_data); if (NS_FAILED(record->GetNextAddr(port, &netAddr))) { Failed("GetNextAddr failed\n"); return NS_OK; } socklen_t addrlen; struct sockaddr *addr; if (netAddr.raw.family == AF_INET) { addrlen = sizeof(struct sockaddr_in); struct sockaddr_in *s_in = (struct sockaddr_in *)g_malloc0(addrlen); s_in->sin_port = netAddr.inet.port; memcpy(&s_in->sin_addr, &netAddr.inet.ip, sizeof(netAddr.inet.ip)); addr = (struct sockaddr *)s_in; LOG(("Found ip v4 address")); } else if (netAddr.raw.family == AF_INET6) { addrlen = sizeof(struct sockaddr_in6); struct sockaddr_in6 *s_in6 = (struct sockaddr_in6 *)g_malloc0(addrlen); s_in6->sin6_port = netAddr.inet6.port; s_in6->sin6_flowinfo = netAddr.inet6.flowinfo; memcpy(&s_in6->sin6_addr, &netAddr.inet6.ip, sizeof(netAddr.inet6.ip.u8)); s_in6->sin6_scope_id = netAddr.inet6.scope_id; addr = (struct sockaddr *)s_in6; LOG(("Found ip v6 address")); } #ifndef XP_WIN else if (netAddr.raw.family == AF_LOCAL) { addrlen = sizeof(struct sockaddr_un); struct sockaddr_un *s_un = (struct sockaddr_un *)g_malloc0(addrlen); memcpy(&s_un->sun_path, netAddr.local.path, sizeof(netAddr.local.path)); addr = (struct sockaddr *)s_un; LOG(("Found local address")); } #endif else { NS_NOTREACHED("Unknown address type..."); continue; } addr->sa_family = netAddr.raw.family; hosts = g_slist_append(hosts, GINT_TO_POINTER(addrlen)); hosts = g_slist_append(hosts, addr); } LOG(("DNS resolution done")); resolved_cb(query_data, hosts); return NS_OK; }
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; }