Ticket #644: patch-lib_proxy.c

File patch-lib_proxy.c, 4.0 KB (added by Ashish SHUKLA <wahjava@…>, at 2010-08-01T18:32:44Z)

BitlBee IPv6 support diff (updated)

Line 
1
2$FreeBSD$
3
4--- lib/proxy.c.orig
5+++ lib/proxy.c
6@@ -57,27 +57,6 @@
7        gint inpa;
8 };
9 
10-
11-
12-static struct sockaddr_in *gaim_gethostbyname(const char *host, int port)
13-{
14-       static struct sockaddr_in sin;
15-
16-       if (!inet_aton(host, &sin.sin_addr)) {
17-               struct hostent *hp;
18-               if (!(hp = gethostbyname(host))) {
19-                       return NULL;
20-               }
21-               memset(&sin, 0, sizeof(struct sockaddr_in));
22-               memcpy(&sin.sin_addr.s_addr, hp->h_addr, hp->h_length);
23-               sin.sin_family = hp->h_addrtype;
24-       } else
25-               sin.sin_family = AF_INET;
26-       sin.sin_port = htons(port);
27-
28-       return &sin;
29-}
30-
31 static gboolean gaim_io_connected(gpointer data, gint source, b_input_condition cond)
32 {
33        struct PHB *phb = data;
34@@ -112,45 +91,107 @@
35 
36 static int proxy_connect_none(const char *host, unsigned short port, struct PHB *phb)
37 {
38-       struct sockaddr_in *sin;
39-       struct sockaddr_in me;
40+       struct sockaddr*    sin;
41+       struct sockaddr_in6 sin6;
42+       struct sockaddr_in6 me;
43        int fd = -1;
44+       int ret;
45+       int len;
46+       struct addrinfo hints;
47+       struct addrinfo* result;
48+#ifdef __FreeBSD__
49+       struct sockaddr_in  sin4;
50+#endif
51 
52-       if (!(sin = gaim_gethostbyname(host, port))) {
53-               g_free(phb);
54-               return -1;
55-       }
56+       memset(&hints, 0, sizeof(struct addrinfo));
57+#ifdef __FreeBSD__
58+       hints.ai_family = AF_UNSPEC;
59+#else
60+       hints.ai_family = AF_INET6;
61+#endif
62+       hints.ai_socktype = SOCK_STREAM;
63+       hints.ai_protocol = 0;
64+       hints.ai_flags = AI_ADDRCONFIG; 
65 
66-       if ((fd = socket(sin->sin_family, SOCK_STREAM, 0)) < 0) {
67-               g_free(phb);
68-               return -1;
69-       }
70+#ifndef __FreeBSD__
71+       hints.ai_flags |= AI_V4MAPPED;
72+#endif
73 
74-       sock_make_nonblocking(fd);
75+       if(!(ret = getaddrinfo(host, NULL, &hints, &result)))
76+       {
77+               struct addrinfo* rp;
78+
79+               for(rp = result; rp; rp = rp->ai_next)
80+               {
81+                       if ((fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol)) < 0) {
82+                               event_debug( "socket failed: %d\n", errno);
83+                               continue;
84+                       }
85+
86+                       sock_make_nonblocking(fd);
87       
88-       if( global.conf->iface_out )
89+                       if( global.conf->iface_out )
90+                       {
91+                               me.sin6_family = rp->ai_family;
92+                               me.sin6_port = 0;
93+                               inet_pton(AF_INET6, global.conf->iface_out, &me.sin6_addr);
94+                       
95+                               if( bind( fd, (struct sockaddr *) &me, sizeof( me ) ) != 0 )
96+                                       event_debug( "bind( %d, \"%s\" ) failure\n", fd, global.conf->iface_out );
97+                       }
98+
99+                       event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port, fd);
100+       
101+#ifdef __FreeBSD__
102+                       if(rp->ai_family == AF_INET)
103+                       {
104+                               struct sockaddr_in* aisin = (struct sockaddr_in*)rp->ai_addr;
105+
106+                               memset(&sin4, 0, sizeof(struct sockaddr_in));
107+                               sin4.sin_family = AF_INET;
108+                               sin4.sin_port = htons(port);
109+                               sin4.sin_len = sizeof(struct sockaddr_in);
110+                               sin4.sin_addr = aisin->sin_addr;
111+                               sin = (struct sockaddr*)&sin4;
112+                               len = sizeof(struct sockaddr_in);
113+                       }
114+                       else
115+                       {
116+#endif
117+                               memcpy(&sin6, rp->ai_addr, rp->ai_addrlen);
118+
119+                               sin6.sin6_port = htons(port);
120+                               sin = (struct sockaddr*)&sin6;
121+                               len = sizeof(struct sockaddr_in6);
122+#ifdef __FreeBSD__
123+                               sin6.sin6_len = sizeof(struct sockaddr_in6);
124+                       }
125+#endif
126+
127+                       if (connect(fd, sin, len) < 0 && !sockerr_again()) {
128+                               event_debug( "connect failed: %s\n", strerror(errno));
129+                               closesocket(fd);
130+                               fd = -1;
131+                               continue;
132+                       } else {
133+                               phb->inpa = b_input_add(fd, GAIM_INPUT_WRITE, gaim_io_connected, phb);
134+                               phb->fd = fd;
135+                               
136+                               break;
137+                       }
138+               }
139+
140+               freeaddrinfo(result);
141+       }
142+       else
143        {
144-               me.sin_family = AF_INET;
145-               me.sin_port = 0;
146-               me.sin_addr.s_addr = inet_addr( global.conf->iface_out );
147-               
148-               if( bind( fd, (struct sockaddr *) &me, sizeof( me ) ) != 0 )
149-                       event_debug( "bind( %d, \"%s\" ) failure\n", fd, global.conf->iface_out );
150+               event_debug("gai(): %s\n", gai_strerror(ret));
151        }
152       
153-       event_debug("proxy_connect_none( \"%s\", %d ) = %d\n", host, port, fd);
154-       
155-       if (connect(fd, (struct sockaddr *)sin, sizeof(*sin)) < 0 && !sockerr_again()) {
156-               closesocket(fd);
157+       if(fd < 0)
158                g_free(phb);
159-               
160-               return -1;
161-       } else {
162-               phb->inpa = b_input_add(fd, GAIM_INPUT_WRITE, gaim_io_connected, phb);
163-               phb->fd = fd;
164-               
165-               return fd;
166-       }
167+
168+       return fd;
169 }
170 
171