IPv6 fixes. Everything now keeps both v4 and v6 addresses in memory and

at connect() time it's decided which one should be used.


git-svn-id: http://svn.irssi.org/repos/irssi/trunk@1334 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
Timo Sirainen 2001-03-04 01:47:13 +00:00 committed by cras
commit 4c7b07ed3f
21 changed files with 216 additions and 127 deletions

View file

@ -47,8 +47,6 @@ union sockaddr_union {
# define g_io_channel_new(handle) g_io_channel_unix_new(handle)
#endif
static unsigned short default_family = 0;
/* Cygwin need this, don't know others.. */
/*#define BLOCKING_SOCKETS 1*/
@ -138,16 +136,37 @@ int sin_get_port(union sockaddr_union *so)
/* Connect to socket */
GIOChannel *net_connect(const char *addr, int port, IPADDR *my_ip)
{
IPADDR ip;
IPADDR ip4, ip6, *ip;
int family;
g_return_val_if_fail(addr != NULL, NULL);
family = my_ip == NULL ? 0 : my_ip->family;
if (net_gethostbyname(addr, &ip, family) == -1)
if (net_gethostbyname(addr, &ip4, &ip6) == -1)
return NULL;
return net_connect_ip(&ip, port, my_ip);
if (my_ip == NULL) {
/* prefer IPv4 addresses */
ip = ip4.family != 0 ? &ip4 : &ip6;
} else if (IPADDR_IS_V6(my_ip)) {
/* my_ip is IPv6 address, use it if possible */
if (ip6.family != 0)
ip = &ip6;
else {
my_ip = NULL;
ip = &ip4;
}
} else {
/* my_ip is IPv4 address, use it if possible */
if (ip4.family != 0)
ip = &ip4;
else {
my_ip = NULL;
ip = &ip6;
}
}
return net_connect_ip(ip, port, my_ip);
}
/* Connect to socket with ip address */
@ -156,6 +175,11 @@ GIOChannel *net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip)
union sockaddr_union so;
int handle, ret, opt = 1;
if (my_ip != NULL && ip->family != my_ip->family) {
g_warning("net_connect_ip(): ip->family != my_ip->family");
my_ip = NULL;
}
/* create the socket */
memset(&so, 0, sizeof(so));
so.sin.sin_family = ip->family;
@ -334,28 +358,28 @@ int net_getsockname(GIOChannel *handle, IPADDR *addr, int *port)
return 0;
}
/* Get IP address for host. family specifies if we should prefer to
IPv4 or IPv6 address (0 = default, AF_INET or AF_INET6).
returns 0 = ok, others = error code for net_gethosterror() */
int net_gethostbyname(const char *addr, IPADDR *ip, int family)
/* Get IP addresses for host, both IPv4 and IPv6 if possible.
If ip->family is 0, the address wasn't found.
Returns 0 = ok, others = error code for net_gethosterror() */
int net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6)
{
#ifdef HAVE_IPV6
union sockaddr_union *so;
struct addrinfo hints, *ai;
struct addrinfo hints, *ai, *origai;
char hbuf[NI_MAXHOST];
int host_error;
int host_error, count;
#else
struct hostent *hp;
#endif
g_return_val_if_fail(addr != NULL, -1);
#ifdef HAVE_IPV6
memset(ip, 0, sizeof(IPADDR));
memset(ip4, 0, sizeof(IPADDR));
memset(ip6, 0, sizeof(IPADDR));
#ifdef HAVE_IPV6
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_socktype = SOCK_STREAM;
hints.ai_family = family != 0 ? family : default_family;
/* save error to host_error for later use */
host_error = getaddrinfo(addr, NULL, &hints, &ai);
@ -366,27 +390,31 @@ int net_gethostbyname(const char *addr, IPADDR *ip, int family)
sizeof(hbuf), NULL, 0, NI_NUMERICHOST))
return 1;
so = (union sockaddr_union *) ai->ai_addr;
sin_get_ip(so, ip);
freeaddrinfo(ai);
origai = ai; count = 0;
while (ai != NULL && count < 2) {
so = (union sockaddr_union *) ai->ai_addr;
if (ai->ai_family == AF_INET6 && ip6->family == 0) {
sin_get_ip(so, ip6);
count++;
} else if (ai->ai_family == AF_INET && ip4->family == 0) {
sin_get_ip(so, ip4);
count++;
}
ai = ai->ai_next;
}
freeaddrinfo(origai);
#else
hp = gethostbyname(addr);
if (hp == NULL) return h_errno;
ip->family = AF_INET;
memcpy(&ip->addr, hp->h_addr, 4);
ip4->family = AF_INET;
memcpy(&ip4->addr, hp->h_addr, 4);
#endif
return 0;
}
/* Set the default address family to use with host resolving
(AF_INET or AF_INET6) */
void net_host_resolver_set_default_family(unsigned short family)
{
default_family = family;
}
/* Get name for host, *name should be g_free()'d unless it's NULL.
Return values are the same as with net_gethostbyname() */
int net_gethostbyaddr(IPADDR *ip, char **name)