#include "setup.h"
#include <string.h>
#ifdef NEED_MALLOC_H
#include <malloc.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
#ifdef HAVE_ARPA_INET_H
#include <arpa/inet.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef VMS
#include <in.h>
#include <inet.h>
#include <stdlib.h>
#endif
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif
#ifdef HAVE_PROCESS_H
#include <process.h>
#endif
#include "urldata.h"
#include "sendf.h"
#include "hostip.h"
#include "hash.h"
#include "share.h"
#include "strerror.h"
#include "url.h"
#include "inet_pton.h"
#include "connect.h"
#define _MPRINTF_REPLACE
#include <curl/mprintf.h>
#if defined(HAVE_INET_NTOA_R) && !defined(HAVE_INET_NTOA_R_DECL)
#include "inet_ntoa_r.h"
#endif
#include "memory.h"
#include "memdebug.h"
#ifdef CURLRES_IPV6
#ifndef CURLRES_ARES
void Curl_freeaddrinfo(Curl_addrinfo *p)
{
freeaddrinfo(p);
}
#ifdef CURLRES_ASYNCH
Curl_addrinfo *Curl_addrinfo_copy(const void *orig, int port)
{
(void) port;
return (Curl_addrinfo*)orig;
}
#endif
#endif
#ifdef CURLDEBUG
int curl_dogetaddrinfo(const char *hostname, const char *service,
struct addrinfo *hints,
struct addrinfo **result,
int line, const char *source)
{
int res=(getaddrinfo)(hostname, service, hints, result);
if(0 == res) {
if(logfile)
fprintf(logfile, "ADDR %s:%d getaddrinfo() = %p\n",
source, line, (void *)*result);
}
else {
if(logfile)
fprintf(logfile, "ADDR %s:%d getaddrinfo() failed\n",
source, line);
}
return res;
}
#ifdef HAVE_GETNAMEINFO
int curl_dogetnameinfo(GETNAMEINFO_QUAL_ARG1 GETNAMEINFO_TYPE_ARG1 sa,
GETNAMEINFO_TYPE_ARG2 salen,
char *host, GETNAMEINFO_TYPE_ARG46 hostlen,
char *serv, GETNAMEINFO_TYPE_ARG46 servlen,
GETNAMEINFO_TYPE_ARG7 flags,
int line, const char *source)
{
int res = (getnameinfo)(sa, salen,
host, hostlen,
serv, servlen,
flags);
if(0 == res) {
if(logfile)
fprintf(logfile, "GETNAME %s:%d getnameinfo()\n",
source, line);
}
else {
if(logfile)
fprintf(logfile, "GETNAME %s:%d getnameinfo() failed = %d\n",
source, line, res);
}
return res;
}
#endif
void curl_dofreeaddrinfo(struct addrinfo *freethis,
int line, const char *source)
{
(freeaddrinfo)(freethis);
if(logfile)
fprintf(logfile, "ADDR %s:%d freeaddrinfo(%p)\n",
source, line, (void *)freethis);
}
#endif
bool Curl_ipvalid(struct SessionHandle *data)
{
if(data->set.ip_version == CURL_IPRESOLVE_V6) {
curl_socket_t s = socket(PF_INET6, SOCK_DGRAM, 0);
if (s == CURL_SOCKET_BAD)
return FALSE;
sclose(s);
}
return TRUE;
}
#if !defined(USE_THREADING_GETADDRINFO) && !defined(CURLRES_ARES)
#ifdef DEBUG_ADDRINFO
static void dump_addrinfo(struct connectdata *conn, const struct addrinfo *ai)
{
printf("dump_addrinfo:\n");
for ( ; ai; ai = ai->ai_next) {
char buf[INET6_ADDRSTRLEN];
printf(" fam %2d, CNAME %s, ",
ai->ai_family, ai->ai_canonname ? ai->ai_canonname : "<none>");
if (Curl_printable_address(ai, buf, sizeof(buf)))
printf("%s\n", buf);
else
printf("failed; %s\n", Curl_strerror(conn, SOCKERRNO));
}
}
#else
#define dump_addrinfo(x,y)
#endif
Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
const char *hostname,
int port,
int *waitp)
{
struct addrinfo hints, *res;
int error;
char sbuf[NI_MAXSERV];
char *sbufptr = NULL;
char addrbuf[128];
curl_socket_t s;
int pf;
struct SessionHandle *data = conn->data;
*waitp=0;
s = socket(PF_INET6, SOCK_DGRAM, 0);
if (s == CURL_SOCKET_BAD) {
pf = PF_INET;
}
else {
sclose(s);
switch(data->set.ip_version) {
case CURL_IPRESOLVE_V4:
pf = PF_INET;
break;
case CURL_IPRESOLVE_V6:
pf = PF_INET6;
break;
default:
pf = PF_UNSPEC;
break;
}
}
memset(&hints, 0, sizeof(hints));
hints.ai_family = pf;
hints.ai_socktype = conn->socktype;
if((1 == Curl_inet_pton(AF_INET, hostname, addrbuf)) ||
(1 == Curl_inet_pton(AF_INET6, hostname, addrbuf))) {
hints.ai_flags = AI_NUMERICHOST;
}
#if 0
else
hints.ai_flags = AI_CANONNAME;
#endif
if(port) {
snprintf(sbuf, sizeof(sbuf), "%d", port);
sbufptr=sbuf;
}
error = getaddrinfo(hostname, sbufptr, &hints, &res);
if (error) {
infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port);
return NULL;
}
dump_addrinfo(conn, res);
return res;
}
#endif
#endif