Subversion Repositories

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

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;