Subversion Repositories

?revision_form?Rev ?revision_input??revision_submit??revision_endform?

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;