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