CURLcode Curl_loadhostpairs(struct SessionHandle *data) { struct curl_slist *hostp; char hostname[256]; char address[256]; int port; for(hostp = data->change.resolve; hostp; hostp = hostp->next ) { if(!hostp->data) continue; if(hostp->data[0] == '-') { /* TODO: mark an entry for removal */ } else if(3 == sscanf(hostp->data, "%255[^:]:%d:%255s", hostname, &port, address)) { struct Curl_dns_entry *dns; Curl_addrinfo *addr; char *entry_id; size_t entry_len; addr = Curl_str2addr(address, port); if(!addr) { infof(data, "Resolve %s found illegal!\n", hostp->data); continue; } /* Create an entry id, based upon the hostname and port */ entry_id = create_hostcache_id(hostname, port); /* If we can't create the entry id, fail */ if(!entry_id) { Curl_freeaddrinfo(addr); return CURLE_OUT_OF_MEMORY; } entry_len = strlen(entry_id); if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); /* See if its already in our dns cache */ dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1); /* free the allocated entry_id again */ free(entry_id); if(!dns) /* if not in the cache already, put this host in the cache */ dns = Curl_cache_addr(data, addr, hostname, port); else /* this is a duplicate, free it again */ Curl_freeaddrinfo(addr); if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); if(!dns) { Curl_freeaddrinfo(addr); return CURLE_OUT_OF_MEMORY; } infof(data, "Added %s:%d:%s to DNS cache\n", hostname, port, address); } } data->change.resolve = NULL; /* dealt with now */ return CURLE_OK; }
CURLcode Curl_loadhostpairs(struct SessionHandle *data) { struct curl_slist *hostp; char hostname[256]; char address[256]; int port; for(hostp = data->change.resolve; hostp; hostp = hostp->next) { if(!hostp->data) continue; if(hostp->data[0] == '-') { char *entry_id; size_t entry_len; if(2 != sscanf(hostp->data + 1, "%255[^:]:%d", hostname, &port)) { infof(data, "Couldn't parse CURLOPT_RESOLVE removal entry '%s'!\n", hostp->data); continue; } /* Create an entry id, based upon the hostname and port */ entry_id = create_hostcache_id(hostname, port); /* If we can't create the entry id, fail */ if(!entry_id) { return CURLE_OUT_OF_MEMORY; } entry_len = strlen(entry_id); if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); /* delete entry, ignore if it didn't exist */ Curl_hash_delete(data->dns.hostcache, entry_id, entry_len+1); if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); /* free the allocated entry_id again */ free(entry_id); } else { struct Curl_dns_entry *dns; Curl_addrinfo *addr; char *entry_id; size_t entry_len; if(3 != sscanf(hostp->data, "%255[^:]:%d:%255s", hostname, &port, address)) { infof(data, "Couldn't parse CURLOPT_RESOLVE entry '%s'!\n", hostp->data); continue; } addr = Curl_str2addr(address, port); if(!addr) { infof(data, "Address in '%s' found illegal!\n", hostp->data); continue; } /* Create an entry id, based upon the hostname and port */ entry_id = create_hostcache_id(hostname, port); /* If we can't create the entry id, fail */ if(!entry_id) { Curl_freeaddrinfo(addr); return CURLE_OUT_OF_MEMORY; } entry_len = strlen(entry_id); if(data->share) Curl_share_lock(data, CURL_LOCK_DATA_DNS, CURL_LOCK_ACCESS_SINGLE); /* See if its already in our dns cache */ dns = Curl_hash_pick(data->dns.hostcache, entry_id, entry_len+1); /* free the allocated entry_id again */ free(entry_id); if(!dns) { /* if not in the cache already, put this host in the cache */ dns = Curl_cache_addr(data, addr, hostname, port); if(dns) { dns->timestamp = 0; /* mark as added by CURLOPT_RESOLVE */ /* release the returned reference; the cache itself will keep the * entry alive: */ dns->inuse--; } } else /* this is a duplicate, free it again */ Curl_freeaddrinfo(addr); if(data->share) Curl_share_unlock(data, CURL_LOCK_DATA_DNS); if(!dns) { Curl_freeaddrinfo(addr); return CURLE_OUT_OF_MEMORY; } infof(data, "Added %s:%d:%s to DNS cache\n", hostname, port, address); } } data->change.resolve = NULL; /* dealt with now */ return CURLE_OK; }
/* * Curl_resolver_getaddrinfo() - for getaddrinfo */ Curl_addrinfo *Curl_resolver_getaddrinfo(CURL *data, const char *hostname, int port, int *waitp) { struct connectdata *conn = data->easy_conn; struct addrinfo hints; Curl_addrinfo *res; int error; char sbuf[12]; int pf = PF_INET; *waitp = 0; /* default to synchronous response */ #ifndef USE_RESOLVE_ON_IPS res = Curl_str2addr(hostname, port); if(res) return res; #endif #ifdef CURLRES_IPV6 /* * Check if a limited name resolve has been requested. */ switch(conn->ip_version) { case CURL_IPRESOLVE_V4: pf = PF_INET; break; case CURL_IPRESOLVE_V6: pf = PF_INET6; break; default: pf = PF_UNSPEC; break; } if((pf != PF_INET) && !Curl_ipv6works()) /* The stack seems to be a non-IPv6 one */ pf = PF_INET; #endif /* CURLRES_IPV6 */ memset(&hints, 0, sizeof(hints)); hints.ai_family = pf; hints.ai_socktype = conn->socktype; snprintf(sbuf, sizeof(sbuf), "%d", port); /* fire up a new resolver thread! */ if(init_resolve_thread(conn, hostname, port, &hints)) { *waitp = 1; /* expect asynchronous response */ return NULL; } /* fall-back to blocking version */ infof(data, "init_resolve_thread() failed for %s; %s\n", hostname, Curl_strerror(conn, errno)); error = Curl_getaddrinfo_ex(hostname, sbuf, &hints, &res); if(error) { infof(data, "getaddrinfo() failed for %s:%d; %s\n", hostname, port, Curl_strerror(conn, SOCKERRNO)); return NULL; } else { Curl_addrinfo_set_port(res, port); } return res; }