diff options
| author | Wilmer van der Gaast <wilmer@gaast.net> | 2010-08-07 15:55:18 +0100 | 
|---|---|---|
| committer | Wilmer van der Gaast <wilmer@gaast.net> | 2010-08-07 15:55:18 +0100 | 
| commit | 289bd2d47ff58f42879ad50ebbc1b193831e4a78 (patch) | |
| tree | b5c25bb67cb35ee4c948a00d334e4911e435b7af | |
| parent | e193aeb224c2d0d39033ca543235f6530edc0445 (diff) | |
Applied patch from wahjava (with some modifications) for bug #644. This
lets proxy_connect() connect to IPv6 hosts.
| -rw-r--r-- | lib/proxy.c | 105 | 
1 files changed, 54 insertions, 51 deletions
| diff --git a/lib/proxy.c b/lib/proxy.c index baf5823a..0b1866ea 100644 --- a/lib/proxy.c +++ b/lib/proxy.c @@ -57,27 +57,6 @@ struct PHB {  	gint inpa;  }; - - -static struct sockaddr_in *gaim_gethostbyname(const char *host, int port) -{ -	static struct sockaddr_in sin; - -	if (!inet_aton(host, &sin.sin_addr)) { -		struct hostent *hp; -		if (!(hp = gethostbyname(host))) { -			return NULL; -		} -		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(port); - -	return &sin; -} -  static gboolean gaim_io_connected(gpointer data, gint source, b_input_condition cond)  {  	struct PHB *phb = data; @@ -110,47 +89,71 @@ static gboolean gaim_io_connected(gpointer data, gint source, b_input_condition  	return FALSE;  } -static int proxy_connect_none(const char *host, unsigned short port, struct PHB *phb) +static int proxy_connect_none(const char *host, unsigned short port_, struct PHB *phb)  { -	struct sockaddr_in *sin;  	struct sockaddr_in me;  	int fd = -1; +	int ret; +	char port[6]; +	struct addrinfo hints; +	struct addrinfo* result; -	if (!(sin = gaim_gethostbyname(host, port))) { -		g_free(phb); -		return -1; -	} +	g_snprintf(port, sizeof(port), "%d", port_); -	if ((fd = socket(sin->sin_family, SOCK_STREAM, 0)) < 0) { -		g_free(phb); -		return -1; -	} +	memset(&hints, 0, sizeof(struct addrinfo)); +	hints.ai_family = AF_UNSPEC; +	hints.ai_socktype = SOCK_STREAM; +	hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV; -	sock_make_nonblocking(fd); +	if (!(ret = getaddrinfo(host, port, &hints, &result))) +	{ +		struct addrinfo* rp; + +		for (rp = result; rp; rp = rp->ai_next) +		{ +			if ((fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) < 0) { +				event_debug( "socket failed: %d\n", errno); +				continue; +			} + +			sock_make_nonblocking(fd); + +			if (global.conf->iface_out) +			{ +				me.sin_family = AF_INET; +				me.sin_port = 0; +				me.sin_addr.s_addr = inet_addr( global.conf->iface_out ); +				 +				if (bind(fd, (struct sockaddr *) &me, sizeof(me)) != 0) +					event_debug("bind( %d, \"%s\" ) failure\n", fd, global.conf->iface_out); +			} + +			event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port, fd); -	if( global.conf->iface_out ) +			if (connect(fd, rp->ai_addr, rp->ai_addrlen) < 0 && !sockerr_again()) { +				event_debug( "connect failed: %s\n", strerror(errno)); +				closesocket(fd); +				fd = -1; +				continue; +			} else { +				phb->inpa = b_input_add(fd, B_EV_IO_WRITE, gaim_io_connected, phb); +				phb->fd = fd; +				 +				break; +			} +		} + +		freeaddrinfo(result); +	} +	else  	{ -		me.sin_family = AF_INET; -		me.sin_port = 0; -		me.sin_addr.s_addr = inet_addr( global.conf->iface_out ); -		 -		if( bind( fd, (struct sockaddr *) &me, sizeof( me ) ) != 0 ) -			event_debug( "bind( %d, \"%s\" ) failure\n", fd, global.conf->iface_out ); +		event_debug("gai(): %s\n", gai_strerror(ret));  	} -	event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port, fd); -	 -	if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0 && !sockerr_again()) { -		closesocket(fd); +	if(fd < 0)  		g_free(phb); -		 -		return -1; -	} else { -		phb->inpa = b_input_add(fd, B_EV_IO_WRITE, gaim_io_connected, phb); -		phb->fd = fd; -		 -		return fd; -	} + +	return fd;  } | 
