Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
28 | magnus | 1 | Description: IPv6 support. |
2 | |||
3 | --- a/sockets.c |
||
4 | +++ b/sockets.c |
||
5 | @@ -99,42 +99,66 @@ WriteExact(int sock, char *buf, int n) |
||
6 | */ |
||
7 | |||
8 | int |
||
9 | -ConnectToTcpAddr(unsigned int host, int port) |
||
10 | +ConnectToTcpAddr(const char *hostname, int port) |
||
11 | { |
||
12 | - int sock; |
||
13 | - struct sockaddr_in addr; |
||
14 | + int sock = -1; |
||
15 | int one = 1; |
||
16 | |||
17 | - addr.sin_family = AF_INET; |
||
18 | - addr.sin_port = htons(port); |
||
19 | - addr.sin_addr.s_addr = host; |
||
20 | - |
||
21 | + struct addrinfo hints; |
||
22 | + memset(&hints, 0, sizeof(struct addrinfo)); |
||
23 | + hints.ai_socktype = SOCK_STREAM; |
||
24 | + hints.ai_flags = AI_NUMERICSERV; |
||
25 | + |
||
26 | + char portstr[3*sizeof(int)+1]; |
||
27 | if(useSSHTunnel) |
||
28 | { |
||
29 | - char *remote, *gateway; |
||
30 | + const char *remote, *gateway; |
||
31 | if(useSSHGateway) |
||
32 | { |
||
33 | gateway=useSSHGateway; |
||
34 | - remote=inet_ntoa(addr.sin_addr); |
||
35 | + remote=hostname; |
||
36 | }else{ |
||
37 | - gateway=inet_ntoa(addr.sin_addr); |
||
38 | - remote="127.0.0.1"; |
||
39 | + gateway=hostname; |
||
40 | + remote="localhost"; |
||
41 | } |
||
42 | - addr.sin_port=htons(tunnel(gateway, remote, port)); |
||
43 | - inet_aton("127.0.0.1",& addr.sin_addr); |
||
44 | + sprintf(portstr, "%i", tunnel(gateway, remote, port)); |
||
45 | + hostname = 0; /* Request loopback address from getaddrinfo() */ |
||
46 | + } else { |
||
47 | + sprintf(portstr, "%i", port); |
||
48 | } |
||
49 | - |
||
50 | - sock = socket(AF_INET, SOCK_STREAM, 0); |
||
51 | - if (sock < 0) { |
||
52 | - fprintf(stderr,"%s",programName); |
||
53 | - perror(": ConnectToTcpAddr: socket"); |
||
54 | - return -1; |
||
55 | + |
||
56 | + struct addrinfo *res; |
||
57 | + int eai = getaddrinfo(hostname, portstr, &hints, &res); |
||
58 | + if (eai) { |
||
59 | + if (eai == EAI_SYSTEM) { |
||
60 | + fprintf(stderr,"%s",programName); |
||
61 | + perror(": ConnectToTcpAddr: getaddrinfo"); |
||
62 | + } else { |
||
63 | + fprintf(stderr, "%s: ConnectToTcpAddr: getaddrinfo: %s\n", programName, gai_strerror(eai)); |
||
64 | + return -1; |
||
65 | + } |
||
66 | } |
||
67 | + struct addrinfo *ai; |
||
68 | + for (ai = res; ai; ai = ai->ai_next) { |
||
69 | + sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); |
||
70 | + if (sock < 0) { |
||
71 | + fprintf(stderr,"%s",programName); |
||
72 | + perror(": ConnectToTcpAddr: socket"); |
||
73 | + continue; |
||
74 | + } |
||
75 | |||
76 | - if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { |
||
77 | - fprintf(stderr,"%s",programName); |
||
78 | - perror(": ConnectToTcpAddr: connect"); |
||
79 | - close(sock); |
||
80 | + if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) { |
||
81 | + fprintf(stderr,"%s",programName); |
||
82 | + perror(": ConnectToTcpAddr: connect"); |
||
83 | + close(sock); |
||
84 | + sock = -1; |
||
85 | + } else { |
||
86 | + break; |
||
87 | + } |
||
88 | + } |
||
89 | + freeaddrinfo(res); |
||
90 | + if (sock < 0) { |
||
91 | + fprintf(stderr,"%s: Could not connect to any address\n", programName); |
||
92 | return -1; |
||
93 | } |
||
94 | |||
95 | @@ -157,41 +181,64 @@ ConnectToTcpAddr(unsigned int host, int |
||
96 | int |
||
97 | ListenAtTcpPort(int port) |
||
98 | { |
||
99 | - int sock; |
||
100 | - struct sockaddr_in addr; |
||
101 | - int one = 1; |
||
102 | - |
||
103 | - addr.sin_family = AF_INET; |
||
104 | - addr.sin_port = htons(port); |
||
105 | - addr.sin_addr.s_addr = INADDR_ANY; |
||
106 | - |
||
107 | - sock = socket(AF_INET, SOCK_STREAM, 0); |
||
108 | - if (sock < 0) { |
||
109 | - fprintf(stderr,"%s",programName); |
||
110 | - perror(": ListenAtTcpPort: socket"); |
||
111 | - return -1; |
||
112 | - } |
||
113 | + int sock = -1; |
||
114 | + int one = 1, zero = 0; |
||
115 | + |
||
116 | + struct sockaddr_storage addr; |
||
117 | + socklen_t addrlen; |
||
118 | |||
119 | - if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, |
||
120 | - (const char *)&one, sizeof(one)) < 0) { |
||
121 | - fprintf(stderr,"%s",programName); |
||
122 | - perror(": ListenAtTcpPort: setsockopt"); |
||
123 | - close(sock); |
||
124 | - return -1; |
||
125 | - } |
||
126 | + for (addr.ss_family = AF_INET6; sock < 0 && addr.ss_family; |
||
127 | + addr.ss_family = (addr.ss_family == AF_INET6 ? AF_INET : 0)) { |
||
128 | |||
129 | - if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { |
||
130 | - fprintf(stderr,"%s",programName); |
||
131 | - perror(": ListenAtTcpPort: bind"); |
||
132 | - close(sock); |
||
133 | - return -1; |
||
134 | - } |
||
135 | - |
||
136 | - if (listen(sock, 5) < 0) { |
||
137 | - fprintf(stderr,"%s",programName); |
||
138 | - perror(": ListenAtTcpPort: listen"); |
||
139 | - close(sock); |
||
140 | - return -1; |
||
141 | + sock = socket(addr.ss_family, SOCK_STREAM, 0); |
||
142 | + if (sock < 0) { |
||
143 | + fprintf(stderr,"%s",programName); |
||
144 | + perror(": ListenAtTcpPort: socket"); |
||
145 | + continue; |
||
146 | + } |
||
147 | + |
||
148 | + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, |
||
149 | + (const char *)&one, sizeof(one)) < 0) { |
||
150 | + fprintf(stderr,"%s",programName); |
||
151 | + perror(": ListenAtTcpPort: setsockopt"); |
||
152 | + close(sock); sock = -1; |
||
153 | + continue; |
||
154 | + } |
||
155 | + |
||
156 | + if (addr.ss_family == AF_INET6) { |
||
157 | + struct sockaddr_in6 *addr6 = (struct sockaddr_in6*)&addr; |
||
158 | + addr6->sin6_port = htons(port); |
||
159 | + memcpy(addr6->sin6_addr.s6_addr, &in6addr_any, sizeof(in6addr_any)); |
||
160 | + addrlen = sizeof(struct sockaddr_in6); |
||
161 | + if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, |
||
162 | + &zero, sizeof(zero)) < 0) { |
||
163 | + fprintf(stderr,"%s",programName); |
||
164 | + perror(": Warning: ListenAtTcpPort: setsockopt"); |
||
165 | + } |
||
166 | + } else { |
||
167 | + struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr; |
||
168 | + addr4->sin_port = htons(port); |
||
169 | + addr4->sin_addr.s_addr = INADDR_ANY; |
||
170 | + addrlen = sizeof(struct sockaddr_in); |
||
171 | + } |
||
172 | + |
||
173 | + if (bind(sock, (struct sockaddr *)&addr, addrlen) < 0 |
||
174 | + && (addr.ss_family != AF_INET6 |
||
175 | + || setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, |
||
176 | + &one, sizeof(one)) < 0 |
||
177 | + || bind(sock, (struct sockaddr *)&addr, addrlen) < 0)) { |
||
178 | + fprintf(stderr,"%s",programName); |
||
179 | + perror(": ListenAtTcpPort: bind"); |
||
180 | + close(sock); sock = -1; |
||
181 | + continue; |
||
182 | + } |
||
183 | + |
||
184 | + if (listen(sock, 5) < 0) { |
||
185 | + fprintf(stderr,"%s",programName); |
||
186 | + perror(": ListenAtTcpPort: listen"); |
||
187 | + close(sock); sock = -1; |
||
188 | + continue; |
||
189 | + } |
||
190 | } |
||
191 | |||
192 | return sock; |
||
193 | @@ -208,22 +255,39 @@ int getFreePort(void) |
||
194 | for(x=0;x<100;x++) |
||
195 | { |
||
196 | int port = 5500 + last % 100; |
||
197 | + char portstr[3*sizeof(int)+1]; |
||
198 | + sprintf(portstr, "%i", port); |
||
199 | last+=4711; |
||
200 | - |
||
201 | - addr.sin_family = AF_INET; |
||
202 | - addr.sin_port = htons(port); |
||
203 | - addr.sin_addr.s_addr = INADDR_ANY; |
||
204 | - |
||
205 | - sock = socket(AF_INET, SOCK_STREAM, 0); |
||
206 | - if (sock < 0 || |
||
207 | - setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, |
||
208 | - (const char *)&one, sizeof(one)) < 0 || |
||
209 | - bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) |
||
210 | - { |
||
211 | - close(sock); |
||
212 | - }else{ |
||
213 | - close(sock); |
||
214 | - return port; |
||
215 | + |
||
216 | + struct addrinfo *res = 0; |
||
217 | + struct addrinfo hints; |
||
218 | + memset(&hints, 0, sizeof(struct addrinfo)); |
||
219 | + hints.ai_socktype = SOCK_STREAM; |
||
220 | + |
||
221 | + int eai = getaddrinfo(0, portstr, &hints, &res); |
||
222 | + if (eai) { |
||
223 | + fprintf(stderr, "%s: getaddrinfo() failed when finding a free port: %s\n", |
||
224 | + programName, gai_strerror(eai)); |
||
225 | + return -1; |
||
226 | + } |
||
227 | + for (struct addrinfo *ai = res; ai; ai = ai->ai_next) { |
||
228 | + sock = socket(ai->ai_family, SOCK_STREAM, 0); |
||
229 | + if (sock < 0 || |
||
230 | + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, |
||
231 | + &one, sizeof(one)) < 0 || |
||
232 | + (ai->ai_family == AF_INET6 && setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, |
||
233 | + &one, sizeof(one)) < 0) || |
||
234 | + bind(sock, ai->ai_addr, ai->ai_addrlen) < 0) { |
||
235 | + close(sock); |
||
236 | + sock = -1; |
||
237 | + freeaddrinfo(res); |
||
238 | + break; |
||
239 | + } else { |
||
240 | + close(sock); |
||
241 | + } |
||
242 | + } |
||
243 | + if (sock > 0) { |
||
244 | + return port; |
||
245 | } |
||
246 | } |
||
247 | return -1; |
||
248 | @@ -238,7 +302,7 @@ int |
||
249 | AcceptTcpConnection(int listenSock) |
||
250 | { |
||
251 | int sock; |
||
252 | - struct sockaddr_in addr; |
||
253 | + struct sockaddr_storage addr; |
||
254 | int addrlen = sizeof(addr); |
||
255 | int one = 1; |
||
256 | |||
257 | --- a/rfbproto.c |
||
258 | +++ b/rfbproto.c |
||
259 | @@ -60,15 +60,8 @@ static char buffer[BUFFER_SIZE]; |
||
260 | Bool |
||
261 | ConnectToRFBServer(const char *hostname, int port) |
||
262 | { |
||
263 | - unsigned int host; |
||
264 | |||
265 | - if (!StringToIPAddr(hostname, &host)) { |
||
266 | - fprintf(stderr,"%s: couldn't convert '%s' to host address\n", |
||
267 | - programName,hostname); |
||
268 | - return False; |
||
269 | - } |
||
270 | - |
||
271 | - rfbsock = ConnectToTcpAddr(host, port); |
||
272 | + rfbsock = ConnectToTcpAddr(hostname, port); |
||
273 | |||
274 | if (rfbsock < 0) { |
||
275 | fprintf(stderr,"%s: unable to connect to VNC server\n", |
||
276 | --- a/x2vnc.h |
||
277 | +++ b/x2vnc.h |
||
278 | @@ -140,7 +140,7 @@ extern Bool ReadExact(int sock, char *bu |
||
279 | extern Bool WriteExact(int sock, char *buf, int n); |
||
280 | extern int ListenAtTcpPort(int port); |
||
281 | extern int getFreePort(); |
||
282 | -extern int ConnectToTcpAddr(unsigned int host, int port); |
||
283 | +extern int ConnectToTcpAddr(const char *host, int port); |
||
284 | extern int AcceptTcpConnection(int listenSock); |
||
285 | extern int StringToIPAddr(const char *str, unsigned int *addr); |
||
286 | extern Bool SameMachine(int sock); |
||
287 | --- a/args.c |
||
288 | +++ b/args.c |
||
289 | @@ -251,7 +251,8 @@ void processArgs(int argc, char **argv) |
||
290 | |||
291 | argumentSpecified = True; |
||
292 | |||
293 | - if (sscanf(argv[i], "%[^:]:%d", hostname, &port) != 2) usage(); |
||
294 | + if (sscanf(argv[i], "[%255[0-9a-f:]]:%d", hostname, &port) != 2 |
||
295 | + && sscanf(argv[i], "%255[^:]:%d", hostname, &port) != 2) usage(); |
||
296 | |||
297 | if (port < 100) |
||
298 | port += SERVERPORT; |