diff options
author | ng0 <ng0@n0.is> | 2019-09-10 16:59:32 +0000 |
---|---|---|
committer | ng0 <ng0@n0.is> | 2019-09-10 16:59:32 +0000 |
commit | 04b6df21cd281e8cd540139f8d9ae85defc1961c (patch) | |
tree | 6357199445df8d5c0c631bc8f10aef838b1f9f1e /src/nat | |
parent | 483b0139a218a5f8a8311bda3eb23bcd88f57688 (diff) | |
download | gnunet-04b6df21cd281e8cd540139f8d9ae85defc1961c.tar.gz gnunet-04b6df21cd281e8cd540139f8d9ae85defc1961c.zip |
remove CYGWIN codeblocks, drop vendored Windows openvpn, drop win32 specific files.
configures and builds okay.
testsuite wasn't checked, will be checked.
diff including the plibc removal is now around 14370 lines of code less.
Diffstat (limited to 'src/nat')
-rw-r--r-- | src/nat/Makefile.am | 9 | ||||
-rw-r--r-- | src/nat/gnunet-helper-nat-client-windows.c | 529 | ||||
-rw-r--r-- | src/nat/gnunet-helper-nat-server-windows.c | 614 |
3 files changed, 1 insertions, 1151 deletions
diff --git a/src/nat/Makefile.am b/src/nat/Makefile.am index f0d5639a1..db104d194 100644 --- a/src/nat/Makefile.am +++ b/src/nat/Makefile.am | |||
@@ -1,13 +1,6 @@ | |||
1 | # This Makefile.am is in the public domain | 1 | # This Makefile.am is in the public domain |
2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include | 2 | AM_CPPFLAGS = -I$(top_srcdir)/src/include |
3 | 3 | ||
4 | if MINGW | ||
5 | WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols | ||
6 | NATBIN = gnunet-helper-nat-server gnunet-helper-nat-client | ||
7 | NATSERVER = gnunet-helper-nat-server-windows.c | ||
8 | NATCLIENT = gnunet-helper-nat-client-windows.c | ||
9 | endif | ||
10 | |||
11 | libexecdir= $(pkglibdir)/libexec/ | 4 | libexecdir= $(pkglibdir)/libexec/ |
12 | 5 | ||
13 | pkgcfgdir= $(pkgdatadir)/config.d/ | 6 | pkgcfgdir= $(pkgdatadir)/config.d/ |
@@ -45,7 +38,7 @@ gnunet_helper_nat_server_SOURCES = \ | |||
45 | $(NATSERVER) | 38 | $(NATSERVER) |
46 | 39 | ||
47 | gnunet_helper_nat_client_SOURCES = \ | 40 | gnunet_helper_nat_client_SOURCES = \ |
48 | $(NATCLIENT) | 41 | $(NATCLIENT) |
49 | 42 | ||
50 | 43 | ||
51 | gnunet_nat_SOURCES = \ | 44 | gnunet_nat_SOURCES = \ |
diff --git a/src/nat/gnunet-helper-nat-client-windows.c b/src/nat/gnunet-helper-nat-client-windows.c deleted file mode 100644 index 1be31ae42..000000000 --- a/src/nat/gnunet-helper-nat-client-windows.c +++ /dev/null | |||
@@ -1,529 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2010 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/nat/gnunet-helper-nat-client-windows.c | ||
23 | * @brief Tool to help bypass NATs using ICMP method; must run as | ||
24 | * administrator on W32 | ||
25 | * This code is for W32. | ||
26 | * @author Nathan Evans | ||
27 | * | ||
28 | * This program will send ONE ICMP message using RAW sockets | ||
29 | * to the IP address specified as the second argument. Since | ||
30 | * it uses RAW sockets, it must be installed SUID or run as 'root'. | ||
31 | * In order to keep the security risk of the resulting SUID binary | ||
32 | * minimal, the program ONLY opens the RAW socket with root | ||
33 | * privileges, then drops them and only then starts to process | ||
34 | * command line arguments. The code also does not link against | ||
35 | * any shared libraries (except libc) and is strictly minimal | ||
36 | * (except for checking for errors). The following list of people | ||
37 | * have reviewed this code and considered it safe since the last | ||
38 | * modification (if you reviewed it, please have your name added | ||
39 | * to the list): | ||
40 | * | ||
41 | * - Christian Grothoff | ||
42 | * - Nathan Evans | ||
43 | */ | ||
44 | #define _GNU_SOURCE | ||
45 | /* Instead of including gnunet_common.h */ | ||
46 | #define GNUNET_memcpy(dst, src, n) do { if (0 != n) { (void)memcpy(dst, src, n); } } while (0) | ||
47 | |||
48 | #define FD_SETSIZE 1024 | ||
49 | #include <winsock2.h> | ||
50 | #include <ws2tcpip.h> | ||
51 | #include <sys/time.h> | ||
52 | #include <sys/types.h> | ||
53 | #include <unistd.h> | ||
54 | #include <stdio.h> | ||
55 | #include <string.h> | ||
56 | #include <errno.h> | ||
57 | #include <stdlib.h> | ||
58 | #include <stdint.h> | ||
59 | #include <time.h> | ||
60 | |||
61 | |||
62 | #define ICMP_ECHO 8 | ||
63 | #define IPDEFTTL 64 | ||
64 | #define ICMP_TIME_EXCEEDED 11 | ||
65 | |||
66 | /** | ||
67 | * Must match IP given in the server. | ||
68 | */ | ||
69 | #define DUMMY_IP "192.0.2.86" | ||
70 | |||
71 | #define NAT_TRAV_PORT 22225 | ||
72 | |||
73 | /** | ||
74 | * IPv4 header. | ||
75 | */ | ||
76 | struct ip_header { | ||
77 | /** | ||
78 | * Version (4 bits) + Internet header length (4 bits) | ||
79 | */ | ||
80 | uint8_t vers_ihl; | ||
81 | |||
82 | /** | ||
83 | * Type of service | ||
84 | */ | ||
85 | uint8_t tos; | ||
86 | |||
87 | /** | ||
88 | * Total length | ||
89 | */ | ||
90 | uint16_t pkt_len; | ||
91 | |||
92 | /** | ||
93 | * Identification | ||
94 | */ | ||
95 | uint16_t id; | ||
96 | |||
97 | /** | ||
98 | * Flags (3 bits) + Fragment offset (13 bits) | ||
99 | */ | ||
100 | uint16_t flags_frag_offset; | ||
101 | |||
102 | /** | ||
103 | * Time to live | ||
104 | */ | ||
105 | uint8_t ttl; | ||
106 | |||
107 | /** | ||
108 | * Protocol | ||
109 | */ | ||
110 | uint8_t proto; | ||
111 | |||
112 | /** | ||
113 | * Header checksum | ||
114 | */ | ||
115 | uint16_t checksum; | ||
116 | |||
117 | /** | ||
118 | * Source address | ||
119 | */ | ||
120 | uint32_t src_ip; | ||
121 | |||
122 | /** | ||
123 | * Destination address | ||
124 | */ | ||
125 | uint32_t dst_ip; | ||
126 | }; | ||
127 | |||
128 | |||
129 | /** | ||
130 | * Format of ICMP packet. | ||
131 | */ | ||
132 | struct icmp_ttl_exceeded_header { | ||
133 | uint8_t type; | ||
134 | |||
135 | uint8_t code; | ||
136 | |||
137 | uint16_t checksum; | ||
138 | |||
139 | uint32_t unused; | ||
140 | |||
141 | /* followed by original payload */ | ||
142 | }; | ||
143 | |||
144 | struct icmp_echo_header { | ||
145 | uint8_t type; | ||
146 | |||
147 | uint8_t code; | ||
148 | |||
149 | uint16_t checksum; | ||
150 | |||
151 | uint32_t reserved; | ||
152 | }; | ||
153 | |||
154 | /** | ||
155 | * Beginning of UDP packet. | ||
156 | */ | ||
157 | struct udp_header { | ||
158 | uint16_t src_port; | ||
159 | |||
160 | uint16_t dst_port; | ||
161 | |||
162 | uint16_t length; | ||
163 | |||
164 | uint16_t crc; | ||
165 | }; | ||
166 | |||
167 | /** | ||
168 | * Will this binary be run in permissions testing mode? | ||
169 | */ | ||
170 | static boolean privilege_testing = FALSE; | ||
171 | |||
172 | /** | ||
173 | * Socket we use to send our ICMP packets. | ||
174 | */ | ||
175 | static _win_socket rawsock; | ||
176 | |||
177 | /** | ||
178 | * Target "dummy" address. | ||
179 | */ | ||
180 | static struct in_addr dummy; | ||
181 | |||
182 | /** | ||
183 | * Port we are listening on (communicated to the server). | ||
184 | */ | ||
185 | static uint16_t port; | ||
186 | |||
187 | |||
188 | |||
189 | /** | ||
190 | * Convert IPv4 address from text to binary form. | ||
191 | * | ||
192 | * @param af address family | ||
193 | * @param cp the address to print | ||
194 | * @param buf where to write the address result | ||
195 | * @return 1 on success | ||
196 | */ | ||
197 | static int | ||
198 | inet_pton(int af, const char *cp, struct in_addr *buf) | ||
199 | { | ||
200 | buf->s_addr = inet_addr(cp); | ||
201 | if (buf->s_addr == INADDR_NONE) | ||
202 | { | ||
203 | fprintf(stderr, "Error %d handling address %s", WSAGetLastError(), cp); | ||
204 | return 0; | ||
205 | } | ||
206 | return 1; | ||
207 | } | ||
208 | |||
209 | |||
210 | /** | ||
211 | * CRC-16 for IP/ICMP headers. | ||
212 | * | ||
213 | * @param data what to calculate the CRC over | ||
214 | * @param bytes number of bytes in data (must be multiple of 2) | ||
215 | * @return the CRC 16. | ||
216 | */ | ||
217 | static uint16_t | ||
218 | calc_checksum(const uint16_t * data, unsigned int bytes) | ||
219 | { | ||
220 | uint32_t sum; | ||
221 | unsigned int i; | ||
222 | |||
223 | sum = 0; | ||
224 | for (i = 0; i < bytes / 2; i++) | ||
225 | sum += data[i]; | ||
226 | sum = (sum & 0xffff) + (sum >> 16); | ||
227 | sum = htons(0xffff - sum); | ||
228 | return sum; | ||
229 | } | ||
230 | |||
231 | |||
232 | /** | ||
233 | * Send an ICMP message to the target. | ||
234 | * | ||
235 | * @param my_ip source address | ||
236 | * @param other target address | ||
237 | */ | ||
238 | static void | ||
239 | send_icmp_udp(const struct in_addr *my_ip, const struct in_addr *other) | ||
240 | { | ||
241 | char packet[sizeof(struct ip_header) * 2 + | ||
242 | sizeof(struct icmp_ttl_exceeded_header) + | ||
243 | sizeof(struct udp_header)]; | ||
244 | struct ip_header ip_pkt; | ||
245 | struct icmp_ttl_exceeded_header icmp_pkt; | ||
246 | struct udp_header udp_pkt; | ||
247 | struct sockaddr_in dst; | ||
248 | size_t off; | ||
249 | int err; | ||
250 | |||
251 | /* ip header: send to (known) ip address */ | ||
252 | off = 0; | ||
253 | ip_pkt.vers_ihl = 0x45; | ||
254 | ip_pkt.tos = 0; | ||
255 | ip_pkt.pkt_len = htons(sizeof(packet)); | ||
256 | ip_pkt.id = htons(256); | ||
257 | ip_pkt.flags_frag_offset = 0; | ||
258 | ip_pkt.ttl = 128; | ||
259 | ip_pkt.proto = IPPROTO_ICMP; | ||
260 | ip_pkt.checksum = 0; | ||
261 | ip_pkt.src_ip = my_ip->s_addr; | ||
262 | ip_pkt.dst_ip = other->s_addr; | ||
263 | ip_pkt.checksum = | ||
264 | htons(calc_checksum((uint16_t *)&ip_pkt, sizeof(struct ip_header))); | ||
265 | GNUNET_memcpy(&packet[off], &ip_pkt, sizeof(struct ip_header)); | ||
266 | off += sizeof(struct ip_header); | ||
267 | |||
268 | icmp_pkt.type = ICMP_TIME_EXCEEDED; | ||
269 | icmp_pkt.code = 0; | ||
270 | icmp_pkt.checksum = 0; | ||
271 | icmp_pkt.unused = 0; | ||
272 | GNUNET_memcpy(&packet[off], &icmp_pkt, sizeof(struct icmp_ttl_exceeded_header)); | ||
273 | off += sizeof(struct icmp_ttl_exceeded_header); | ||
274 | |||
275 | /* ip header of the presumably 'lost' udp packet */ | ||
276 | ip_pkt.vers_ihl = 0x45; | ||
277 | ip_pkt.tos = 0; | ||
278 | ip_pkt.pkt_len = | ||
279 | htons(sizeof(struct ip_header) + sizeof(struct udp_header)); | ||
280 | ip_pkt.id = htons(0); | ||
281 | ip_pkt.flags_frag_offset = 0; | ||
282 | ip_pkt.ttl = 128; | ||
283 | ip_pkt.proto = IPPROTO_UDP; | ||
284 | ip_pkt.checksum = 0; | ||
285 | ip_pkt.src_ip = other->s_addr; | ||
286 | ip_pkt.dst_ip = dummy.s_addr; | ||
287 | ip_pkt.checksum = | ||
288 | htons(calc_checksum((uint16_t *)&ip_pkt, sizeof(struct ip_header))); | ||
289 | GNUNET_memcpy(&packet[off], &ip_pkt, sizeof(struct ip_header)); | ||
290 | off += sizeof(struct ip_header); | ||
291 | |||
292 | /* build UDP header */ | ||
293 | udp_pkt.src_port = htons(NAT_TRAV_PORT); | ||
294 | udp_pkt.dst_port = htons(NAT_TRAV_PORT); | ||
295 | udp_pkt.length = htons(port); | ||
296 | udp_pkt.crc = 0; | ||
297 | GNUNET_memcpy(&packet[off], &udp_pkt, sizeof(struct udp_header)); | ||
298 | off += sizeof(struct udp_header); | ||
299 | |||
300 | /* no go back to calculate ICMP packet checksum */ | ||
301 | icmp_pkt.checksum = | ||
302 | htons(calc_checksum | ||
303 | ((uint16_t *)&packet[off], | ||
304 | sizeof(struct icmp_ttl_exceeded_header) + | ||
305 | sizeof(struct ip_header) + sizeof(struct udp_header))); | ||
306 | GNUNET_memcpy(&packet[sizeof(struct ip_header)], &icmp_pkt, | ||
307 | sizeof(struct icmp_ttl_exceeded_header)); | ||
308 | |||
309 | memset(&dst, 0, sizeof(dst)); | ||
310 | dst.sin_family = AF_INET; | ||
311 | dst.sin_addr = *other; | ||
312 | err = | ||
313 | sendto(rawsock, packet, sizeof(packet), 0, (struct sockaddr *)&dst, | ||
314 | sizeof(dst)); | ||
315 | if (err < 0) | ||
316 | { | ||
317 | fprintf(stderr, "sendto failed: %s\n", strerror(errno)); | ||
318 | } | ||
319 | else if (sizeof(packet) != (size_t)err) | ||
320 | { | ||
321 | fprintf(stderr, "Error: partial send of ICMP message\n"); | ||
322 | } | ||
323 | } | ||
324 | |||
325 | |||
326 | /** | ||
327 | * Send an ICMP message to the target. | ||
328 | * | ||
329 | * @param my_ip source address | ||
330 | * @param other target address | ||
331 | */ | ||
332 | static void | ||
333 | send_icmp(const struct in_addr *my_ip, const struct in_addr *other) | ||
334 | { | ||
335 | struct ip_header ip_pkt; | ||
336 | struct icmp_ttl_exceeded_header icmp_ttl; | ||
337 | struct icmp_echo_header icmp_echo; | ||
338 | struct sockaddr_in dst; | ||
339 | char packet[sizeof(struct ip_header) * 2 + | ||
340 | sizeof(struct icmp_ttl_exceeded_header) + | ||
341 | sizeof(struct icmp_echo_header)]; | ||
342 | size_t off; | ||
343 | int err; | ||
344 | |||
345 | /* ip header: send to (known) ip address */ | ||
346 | off = 0; | ||
347 | ip_pkt.vers_ihl = 0x45; | ||
348 | ip_pkt.tos = 0; | ||
349 | ip_pkt.pkt_len = htons(sizeof(packet)); | ||
350 | ip_pkt.id = htons(256); | ||
351 | ip_pkt.flags_frag_offset = 0; | ||
352 | ip_pkt.ttl = IPDEFTTL; | ||
353 | ip_pkt.proto = IPPROTO_ICMP; | ||
354 | ip_pkt.checksum = 0; | ||
355 | ip_pkt.src_ip = my_ip->s_addr; | ||
356 | ip_pkt.dst_ip = other->s_addr; | ||
357 | ip_pkt.checksum = | ||
358 | htons(calc_checksum((uint16_t *)&ip_pkt, sizeof(struct ip_header))); | ||
359 | GNUNET_memcpy(&packet[off], &ip_pkt, sizeof(struct ip_header)); | ||
360 | off += sizeof(ip_pkt); | ||
361 | |||
362 | /* icmp reply: time exceeded */ | ||
363 | icmp_ttl.type = ICMP_TIME_EXCEEDED; | ||
364 | icmp_ttl.code = 0; | ||
365 | icmp_ttl.checksum = 0; | ||
366 | icmp_ttl.unused = 0; | ||
367 | GNUNET_memcpy(&packet[off], &icmp_ttl, sizeof(struct icmp_ttl_exceeded_header)); | ||
368 | off += sizeof(struct icmp_ttl_exceeded_header); | ||
369 | |||
370 | /* ip header of the presumably 'lost' udp packet */ | ||
371 | ip_pkt.vers_ihl = 0x45; | ||
372 | ip_pkt.tos = 0; | ||
373 | ip_pkt.pkt_len = | ||
374 | htons(sizeof(struct ip_header) + sizeof(struct icmp_echo_header)); | ||
375 | ip_pkt.id = htons(256); | ||
376 | ip_pkt.flags_frag_offset = 0; | ||
377 | ip_pkt.ttl = 1; /* real TTL would be 1 on a time exceeded packet */ | ||
378 | ip_pkt.proto = IPPROTO_ICMP; | ||
379 | ip_pkt.src_ip = other->s_addr; | ||
380 | ip_pkt.dst_ip = dummy.s_addr; | ||
381 | ip_pkt.checksum = 0; | ||
382 | ip_pkt.checksum = | ||
383 | htons(calc_checksum((uint16_t *)&ip_pkt, sizeof(struct ip_header))); | ||
384 | GNUNET_memcpy(&packet[off], &ip_pkt, sizeof(struct ip_header)); | ||
385 | off += sizeof(struct ip_header); | ||
386 | |||
387 | icmp_echo.type = ICMP_ECHO; | ||
388 | icmp_echo.code = 0; | ||
389 | icmp_echo.reserved = htonl(port); | ||
390 | icmp_echo.checksum = 0; | ||
391 | icmp_echo.checksum = | ||
392 | htons(calc_checksum | ||
393 | ((uint16_t *)&icmp_echo, sizeof(struct icmp_echo_header))); | ||
394 | GNUNET_memcpy(&packet[off], &icmp_echo, sizeof(struct icmp_echo_header)); | ||
395 | |||
396 | /* no go back to calculate ICMP packet checksum */ | ||
397 | off = sizeof(struct ip_header); | ||
398 | icmp_ttl.checksum = | ||
399 | htons(calc_checksum | ||
400 | ((uint16_t *)&packet[off], | ||
401 | sizeof(struct icmp_ttl_exceeded_header) + | ||
402 | sizeof(struct ip_header) + sizeof(struct icmp_echo_header))); | ||
403 | GNUNET_memcpy(&packet[off], &icmp_ttl, sizeof(struct icmp_ttl_exceeded_header)); | ||
404 | |||
405 | memset(&dst, 0, sizeof(dst)); | ||
406 | dst.sin_family = AF_INET; | ||
407 | dst.sin_addr = *other; | ||
408 | |||
409 | err = | ||
410 | sendto(rawsock, packet, sizeof(packet), 0, (struct sockaddr *)&dst, | ||
411 | sizeof(dst)); | ||
412 | |||
413 | if (err < 0) | ||
414 | { | ||
415 | fprintf(stderr, "sendto failed: %s\n", strerror(errno)); | ||
416 | } | ||
417 | else if (sizeof(packet) != (size_t)err) | ||
418 | { | ||
419 | fprintf(stderr, "Error: partial send of ICMP message\n"); | ||
420 | } | ||
421 | } | ||
422 | |||
423 | |||
424 | /** | ||
425 | * Create an ICMP raw socket. | ||
426 | * | ||
427 | * @return INVALID_SOCKET on error | ||
428 | */ | ||
429 | static _win_socket | ||
430 | make_raw_socket() | ||
431 | { | ||
432 | DWORD bOptVal = TRUE; | ||
433 | int bOptLen = sizeof(bOptVal); | ||
434 | _win_socket ret; | ||
435 | |||
436 | ret = _win_socket(AF_INET, SOCK_RAW, IPPROTO_RAW); | ||
437 | if (INVALID_SOCKET == ret) | ||
438 | { | ||
439 | fprintf(stderr, "Error opening RAW socket: %s\n", strerror(errno)); | ||
440 | return INVALID_SOCKET; | ||
441 | } | ||
442 | if (0 != | ||
443 | _win_setsockopt(ret, SOL_SOCKET, SO_BROADCAST, (char *)&bOptVal, bOptLen)) | ||
444 | { | ||
445 | fprintf(stderr, "Error setting SO_BROADCAST to ON: %s\n", | ||
446 | strerror(errno)); | ||
447 | closesocket(rawsock); | ||
448 | return INVALID_SOCKET; | ||
449 | } | ||
450 | |||
451 | if (0 != _win_setsockopt(ret, IPPROTO_IP, IP_HDRINCL, (char *)&bOptVal, bOptLen)) | ||
452 | { | ||
453 | fprintf(stderr, "Error setting IP_HDRINCL to ON: %s\n", strerror(errno)); | ||
454 | closesocket(rawsock); | ||
455 | return INVALID_SOCKET; | ||
456 | } | ||
457 | return ret; | ||
458 | } | ||
459 | |||
460 | |||
461 | int | ||
462 | main(int argc, char *const *argv) | ||
463 | { | ||
464 | struct in_addr external; | ||
465 | struct in_addr target; | ||
466 | WSADATA wsaData; | ||
467 | unsigned int p; | ||
468 | |||
469 | if (argc > 1 && 0 != strcmp(argv[1], "-d")) | ||
470 | { | ||
471 | privilege_testing = TRUE; | ||
472 | fprintf(stderr, | ||
473 | "%s", | ||
474 | "DEBUG: Running binary in privilege testing mode."); | ||
475 | argv++; | ||
476 | argc--; | ||
477 | } | ||
478 | |||
479 | if (argc != 4) | ||
480 | { | ||
481 | fprintf(stderr, | ||
482 | "%s", | ||
483 | "This program must be started with our IP, the targets external IP, and our port as arguments.\n"); | ||
484 | return 1; | ||
485 | } | ||
486 | if ((1 != inet_pton(AF_INET, argv[1], &external)) || | ||
487 | (1 != inet_pton(AF_INET, argv[2], &target))) | ||
488 | { | ||
489 | fprintf(stderr, | ||
490 | "Error parsing IPv4 address: %s\n", | ||
491 | strerror(errno)); | ||
492 | return 1; | ||
493 | } | ||
494 | if ((1 != sscanf(argv[3], "%u", &p)) || (0 == p) || (0xFFFF < p)) | ||
495 | { | ||
496 | fprintf(stderr, | ||
497 | "Error parsing port value `%s'\n", | ||
498 | argv[3]); | ||
499 | return 1; | ||
500 | } | ||
501 | port = (uint16_t)p; | ||
502 | |||
503 | if (0 != WSAStartup(MAKEWORD(2, 1), &wsaData)) | ||
504 | { | ||
505 | fprintf(stderr, | ||
506 | "%s", | ||
507 | "Failed to find Winsock 2.1 or better.\n"); | ||
508 | return 2; | ||
509 | } | ||
510 | if (1 != inet_pton(AF_INET, DUMMY_IP, &dummy)) | ||
511 | { | ||
512 | fprintf(stderr, | ||
513 | "%s", | ||
514 | "Internal error converting dummy IP to binary.\n"); | ||
515 | return 2; | ||
516 | } | ||
517 | if (-1 == (rawsock = make_raw_socket())) | ||
518 | return 3; | ||
519 | if (!privilege_testing) | ||
520 | { | ||
521 | send_icmp(&external, &target); | ||
522 | send_icmp_udp(&external, &target); | ||
523 | } | ||
524 | closesocket(rawsock); | ||
525 | WSACleanup(); | ||
526 | return 0; | ||
527 | } | ||
528 | |||
529 | /* end of gnunet-helper-nat-client-windows.c */ | ||
diff --git a/src/nat/gnunet-helper-nat-server-windows.c b/src/nat/gnunet-helper-nat-server-windows.c deleted file mode 100644 index 688dde165..000000000 --- a/src/nat/gnunet-helper-nat-server-windows.c +++ /dev/null | |||
@@ -1,614 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | Copyright (C) 2010 GNUnet e.V. | ||
4 | |||
5 | GNUnet is free software: you can redistribute it and/or modify it | ||
6 | under the terms of the GNU Affero General Public License as published | ||
7 | by the Free Software Foundation, either version 3 of the License, | ||
8 | or (at your option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | Affero General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU Affero General Public License | ||
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | |||
18 | SPDX-License-Identifier: AGPL3.0-or-later | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/nat/gnunet-helper-nat-server-windows.c | ||
23 | * @brief Windows tool to help bypass NATs using ICMP method | ||
24 | * This code will work under W32 only | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * This program will send ONE ICMP message every 500 ms RAW sockets | ||
28 | * to a DUMMY IP address and also listens for ICMP replies. Since | ||
29 | * it uses RAW sockets, it must be run as an administrative user. | ||
30 | * In order to keep the security risk of the resulting binary | ||
31 | * minimal, the program ONLY opens the two RAW sockets with administrative | ||
32 | * privileges, then drops them and only then starts to process | ||
33 | * command line arguments. The code also does not link against | ||
34 | * any shared libraries (except libc) and is strictly minimal | ||
35 | * (except for checking for errors). The following list of people | ||
36 | * have reviewed this code and considered it safe since the last | ||
37 | * modification (if you reviewed it, please have your name added | ||
38 | * to the list): | ||
39 | * | ||
40 | * - Nathan Evans | ||
41 | * - Christian Grothoff | ||
42 | */ | ||
43 | #define _GNU_SOURCE | ||
44 | /* Instead of including gnunet_common.h */ | ||
45 | #define GNUNET_memcpy(dst, src, n) do { if (0 != n) { (void)memcpy(dst, src, n); } } while (0) | ||
46 | |||
47 | #define FD_SETSIZE 1024 | ||
48 | #include <winsock2.h> | ||
49 | #include <ws2tcpip.h> | ||
50 | #include <sys/time.h> | ||
51 | #include <sys/types.h> | ||
52 | #include <unistd.h> | ||
53 | #include <stdio.h> | ||
54 | #include <string.h> | ||
55 | #include <errno.h> | ||
56 | #include <stdlib.h> | ||
57 | #include <stdint.h> | ||
58 | #include <time.h> | ||
59 | |||
60 | /** | ||
61 | * Should we print some debug output? | ||
62 | */ | ||
63 | #define VERBOSE 0 | ||
64 | |||
65 | /** | ||
66 | * Must match IP given in the client. | ||
67 | */ | ||
68 | #define DUMMY_IP "192.0.2.86" | ||
69 | |||
70 | /** | ||
71 | * Default Port | ||
72 | */ | ||
73 | #define NAT_TRAV_PORT 22225 | ||
74 | |||
75 | /** | ||
76 | * Must match packet ID used by gnunet-helper-nat-client.c | ||
77 | */ | ||
78 | #define PACKET_ID 256 | ||
79 | |||
80 | /** | ||
81 | * TTL to use for our outgoing messages. | ||
82 | */ | ||
83 | #define IPDEFTTL 64 | ||
84 | |||
85 | #define ICMP_ECHO 8 | ||
86 | |||
87 | #define ICMP_TIME_EXCEEDED 11 | ||
88 | |||
89 | /** | ||
90 | * How often do we send our ICMP messages to receive replies? | ||
91 | */ | ||
92 | #define ICMP_SEND_FREQUENCY_MS 500 | ||
93 | |||
94 | /** | ||
95 | * IPv4 header. | ||
96 | */ | ||
97 | struct ip_header { | ||
98 | /** | ||
99 | * Version (4 bits) + Internet header length (4 bits) | ||
100 | */ | ||
101 | uint8_t vers_ihl; | ||
102 | |||
103 | /** | ||
104 | * Type of service | ||
105 | */ | ||
106 | uint8_t tos; | ||
107 | |||
108 | /** | ||
109 | * Total length | ||
110 | */ | ||
111 | uint16_t pkt_len; | ||
112 | |||
113 | /** | ||
114 | * Identification | ||
115 | */ | ||
116 | uint16_t id; | ||
117 | |||
118 | /** | ||
119 | * Flags (3 bits) + Fragment offset (13 bits) | ||
120 | */ | ||
121 | uint16_t flags_frag_offset; | ||
122 | |||
123 | /** | ||
124 | * Time to live | ||
125 | */ | ||
126 | uint8_t ttl; | ||
127 | |||
128 | /** | ||
129 | * Protocol | ||
130 | */ | ||
131 | uint8_t proto; | ||
132 | |||
133 | /** | ||
134 | * Header checksum | ||
135 | */ | ||
136 | uint16_t checksum; | ||
137 | |||
138 | /** | ||
139 | * Source address | ||
140 | */ | ||
141 | uint32_t src_ip; | ||
142 | |||
143 | /** | ||
144 | * Destination address | ||
145 | */ | ||
146 | uint32_t dst_ip; | ||
147 | }; | ||
148 | |||
149 | /** | ||
150 | * Format of ICMP packet. | ||
151 | */ | ||
152 | struct icmp_ttl_exceeded_header { | ||
153 | uint8_t type; | ||
154 | |||
155 | uint8_t code; | ||
156 | |||
157 | uint16_t checksum; | ||
158 | |||
159 | uint32_t unused; | ||
160 | |||
161 | /* followed by original payload */ | ||
162 | }; | ||
163 | |||
164 | struct icmp_echo_header { | ||
165 | uint8_t type; | ||
166 | |||
167 | uint8_t code; | ||
168 | |||
169 | uint16_t checksum; | ||
170 | |||
171 | uint32_t reserved; | ||
172 | }; | ||
173 | |||
174 | /** | ||
175 | * Beginning of UDP packet. | ||
176 | */ | ||
177 | struct udp_header { | ||
178 | uint16_t src_port; | ||
179 | |||
180 | uint16_t dst_port; | ||
181 | |||
182 | uint16_t length; | ||
183 | |||
184 | uint16_t crc; | ||
185 | }; | ||
186 | |||
187 | /** | ||
188 | * Will this binary be run in permissions testing mode? | ||
189 | */ | ||
190 | static boolean privilege_testing = FALSE; | ||
191 | |||
192 | /** | ||
193 | * Socket we use to receive "fake" ICMP replies. | ||
194 | */ | ||
195 | static _win_socket icmpsock; | ||
196 | |||
197 | /** | ||
198 | * Socket we use to send our ICMP requests. | ||
199 | */ | ||
200 | static _win_socket rawsock; | ||
201 | |||
202 | /** | ||
203 | * Socket we use to send our UDP requests. | ||
204 | */ | ||
205 | static _win_socket udpsock; | ||
206 | |||
207 | /** | ||
208 | * Target "dummy" address. | ||
209 | */ | ||
210 | static struct in_addr dummy; | ||
211 | |||
212 | |||
213 | /** | ||
214 | * CRC-16 for IP/ICMP headers. | ||
215 | * | ||
216 | * @param data what to calculate the CRC over | ||
217 | * @param bytes number of bytes in data (must be multiple of 2) | ||
218 | * @return the CRC 16. | ||
219 | */ | ||
220 | static uint16_t | ||
221 | calc_checksum(const uint16_t * data, unsigned int bytes) | ||
222 | { | ||
223 | uint32_t sum; | ||
224 | unsigned int i; | ||
225 | |||
226 | sum = 0; | ||
227 | for (i = 0; i < bytes / 2; i++) | ||
228 | sum += data[i]; | ||
229 | sum = (sum & 0xffff) + (sum >> 16); | ||
230 | sum = htons(0xffff - sum); | ||
231 | return sum; | ||
232 | } | ||
233 | |||
234 | |||
235 | /** | ||
236 | * Convert IPv4 address from text to binary form. | ||
237 | * | ||
238 | * @param af address family | ||
239 | * @param cp the address to print | ||
240 | * @param buf where to write the address result | ||
241 | * @return 1 on success | ||
242 | */ | ||
243 | static int | ||
244 | inet_pton(int af, const char *cp, struct in_addr *buf) | ||
245 | { | ||
246 | buf->s_addr = inet_addr(cp); | ||
247 | if (buf->s_addr == INADDR_NONE) | ||
248 | { | ||
249 | fprintf(stderr, "Error %d handling address %s", WSAGetLastError(), cp); | ||
250 | return 0; | ||
251 | } | ||
252 | return 1; | ||
253 | } | ||
254 | |||
255 | |||
256 | /** | ||
257 | * Send an ICMP message to the dummy IP. | ||
258 | * | ||
259 | * @param my_ip source address (our ip address) | ||
260 | */ | ||
261 | static void | ||
262 | send_icmp_echo(const struct in_addr *my_ip) | ||
263 | { | ||
264 | char packet[sizeof(struct ip_header) + sizeof(struct icmp_echo_header)]; | ||
265 | struct icmp_echo_header icmp_echo; | ||
266 | struct ip_header ip_pkt; | ||
267 | struct sockaddr_in dst; | ||
268 | size_t off; | ||
269 | int err; | ||
270 | |||
271 | off = 0; | ||
272 | ip_pkt.vers_ihl = 0x45; | ||
273 | ip_pkt.tos = 0; | ||
274 | ip_pkt.pkt_len = htons(sizeof(packet)); | ||
275 | ip_pkt.id = htons(PACKET_ID); | ||
276 | ip_pkt.flags_frag_offset = 0; | ||
277 | ip_pkt.ttl = IPDEFTTL; | ||
278 | ip_pkt.proto = IPPROTO_ICMP; | ||
279 | ip_pkt.checksum = 0; | ||
280 | ip_pkt.src_ip = my_ip->s_addr; | ||
281 | ip_pkt.dst_ip = dummy.s_addr; | ||
282 | ip_pkt.checksum = | ||
283 | htons(calc_checksum((uint16_t *)&ip_pkt, sizeof(struct ip_header))); | ||
284 | GNUNET_memcpy(&packet[off], &ip_pkt, sizeof(struct ip_header)); | ||
285 | off += sizeof(struct ip_header); | ||
286 | |||
287 | icmp_echo.type = ICMP_ECHO; | ||
288 | icmp_echo.code = 0; | ||
289 | icmp_echo.reserved = 0; | ||
290 | icmp_echo.checksum = 0; | ||
291 | icmp_echo.checksum = | ||
292 | htons(calc_checksum | ||
293 | ((uint16_t *)&icmp_echo, sizeof(struct icmp_echo_header))); | ||
294 | GNUNET_memcpy(&packet[off], &icmp_echo, sizeof(struct icmp_echo_header)); | ||
295 | off += sizeof(struct icmp_echo_header); | ||
296 | |||
297 | memset(&dst, 0, sizeof(dst)); | ||
298 | dst.sin_family = AF_INET; | ||
299 | dst.sin_addr = dummy; | ||
300 | err = | ||
301 | sendto(rawsock, packet, off, 0, (struct sockaddr *)&dst, sizeof(dst)); | ||
302 | if (err < 0) | ||
303 | { | ||
304 | #if VERBOSE | ||
305 | fprintf(stderr, "sendto failed: %s\n", strerror(errno)); | ||
306 | #endif | ||
307 | } | ||
308 | else if (err != off) | ||
309 | { | ||
310 | fprintf(stderr, "Error: partial send of ICMP message\n"); | ||
311 | } | ||
312 | } | ||
313 | |||
314 | |||
315 | /** | ||
316 | * Send a UDP message to the dummy IP. | ||
317 | */ | ||
318 | static void | ||
319 | send_udp() | ||
320 | { | ||
321 | struct sockaddr_in dst; | ||
322 | ssize_t err; | ||
323 | |||
324 | memset(&dst, 0, sizeof(dst)); | ||
325 | dst.sin_family = AF_INET; | ||
326 | dst.sin_addr = dummy; | ||
327 | dst.sin_port = htons(NAT_TRAV_PORT); | ||
328 | err = sendto(udpsock, NULL, 0, 0, (struct sockaddr *)&dst, sizeof(dst)); | ||
329 | if (err < 0) | ||
330 | { | ||
331 | #if VERBOSE | ||
332 | fprintf(stderr, "sendto failed: %s\n", strerror(errno)); | ||
333 | #endif | ||
334 | } | ||
335 | else if (0 != err) | ||
336 | { | ||
337 | fprintf(stderr, "Error: partial send of ICMP message\n"); | ||
338 | } | ||
339 | } | ||
340 | |||
341 | |||
342 | /** | ||
343 | * We've received an ICMP response. Process it. | ||
344 | */ | ||
345 | static void | ||
346 | process_icmp_response() | ||
347 | { | ||
348 | char buf[65536]; | ||
349 | ssize_t have; | ||
350 | struct in_addr source_ip; | ||
351 | struct ip_header ip_pkt; | ||
352 | struct icmp_ttl_exceeded_header icmp_ttl; | ||
353 | struct icmp_echo_header icmp_echo; | ||
354 | struct udp_header udp_pkt; | ||
355 | size_t off; | ||
356 | uint16_t port; | ||
357 | DWORD ssize; | ||
358 | |||
359 | have = read(icmpsock, buf, sizeof(buf)); | ||
360 | if (have == -1) | ||
361 | { | ||
362 | fprintf(stderr, "Error reading raw socket: %s\n", strerror(errno)); | ||
363 | return; | ||
364 | } | ||
365 | #if VERBOSE | ||
366 | fprintf(stderr, "Received message of %u bytes\n", (unsigned int)have); | ||
367 | #endif | ||
368 | if (have < | ||
369 | (ssize_t)(sizeof(struct ip_header) + | ||
370 | sizeof(struct icmp_ttl_exceeded_header) + | ||
371 | sizeof(struct ip_header))) | ||
372 | { | ||
373 | /* malformed */ | ||
374 | return; | ||
375 | } | ||
376 | off = 0; | ||
377 | GNUNET_memcpy(&ip_pkt, &buf[off], sizeof(struct ip_header)); | ||
378 | off += sizeof(struct ip_header); | ||
379 | GNUNET_memcpy(&source_ip, &ip_pkt.src_ip, sizeof(source_ip)); | ||
380 | GNUNET_memcpy(&icmp_ttl, &buf[off], sizeof(struct icmp_ttl_exceeded_header)); | ||
381 | off += sizeof(struct icmp_ttl_exceeded_header); | ||
382 | if ((ICMP_TIME_EXCEEDED != icmp_ttl.type) || (0 != icmp_ttl.code)) | ||
383 | { | ||
384 | /* different type than what we want */ | ||
385 | return; | ||
386 | } | ||
387 | /* skip 2nd IP header */ | ||
388 | GNUNET_memcpy(&ip_pkt, &buf[off], sizeof(struct ip_header)); | ||
389 | off += sizeof(struct ip_header); | ||
390 | |||
391 | switch (ip_pkt.proto) | ||
392 | { | ||
393 | case IPPROTO_ICMP: | ||
394 | if (have != | ||
395 | (sizeof(struct ip_header) * 2 + | ||
396 | sizeof(struct icmp_ttl_exceeded_header) + | ||
397 | sizeof(struct icmp_echo_header))) | ||
398 | { | ||
399 | /* malformed */ | ||
400 | return; | ||
401 | } | ||
402 | /* grab ICMP ECHO content */ | ||
403 | GNUNET_memcpy(&icmp_echo, &buf[off], sizeof(struct icmp_echo_header)); | ||
404 | port = (uint16_t)ntohl(icmp_echo.reserved); | ||
405 | break; | ||
406 | |||
407 | case IPPROTO_UDP: | ||
408 | if (have != | ||
409 | (sizeof(struct ip_header) * 2 + | ||
410 | sizeof(struct icmp_ttl_exceeded_header) + sizeof(struct udp_header))) | ||
411 | { | ||
412 | /* malformed */ | ||
413 | return; | ||
414 | } | ||
415 | /* grab UDP content */ | ||
416 | GNUNET_memcpy(&udp_pkt, &buf[off], sizeof(struct udp_header)); | ||
417 | port = ntohs(udp_pkt.length); | ||
418 | break; | ||
419 | |||
420 | default: | ||
421 | /* different type than what we want */ | ||
422 | return; | ||
423 | } | ||
424 | |||
425 | ssize = sizeof(buf); | ||
426 | WSAAddressToString((LPSOCKADDR)&source_ip, sizeof(source_ip), NULL, buf, | ||
427 | &ssize); | ||
428 | if (port == 0) | ||
429 | fprintf(stdout, "%s\n", buf); | ||
430 | else | ||
431 | fprintf(stdout, "%s:%u\n", buf, (unsigned int)port); | ||
432 | fflush(stdout); | ||
433 | } | ||
434 | |||
435 | |||
436 | /** | ||
437 | * Create an ICMP raw socket for reading. | ||
438 | * | ||
439 | * @return INVALID_SOCKET on error | ||
440 | */ | ||
441 | static _win_socket | ||
442 | make_icmp_socket() | ||
443 | { | ||
444 | _win_socket ret; | ||
445 | |||
446 | ret = _win_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); | ||
447 | if (INVALID_SOCKET == ret) | ||
448 | { | ||
449 | fprintf(stderr, "Error opening RAW socket: %s\n", strerror(errno)); | ||
450 | return INVALID_SOCKET; | ||
451 | } | ||
452 | return ret; | ||
453 | } | ||
454 | |||
455 | |||
456 | /** | ||
457 | * Create an ICMP raw socket for writing. | ||
458 | * | ||
459 | * @return INVALID_SOCKET on error | ||
460 | */ | ||
461 | static _win_socket | ||
462 | make_raw_socket() | ||
463 | { | ||
464 | DWORD bOptVal = TRUE; | ||
465 | int bOptLen = sizeof(bOptVal); | ||
466 | |||
467 | rawsock = _win_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); | ||
468 | if (INVALID_SOCKET == rawsock) | ||
469 | { | ||
470 | fprintf(stderr, "Error opening RAW socket: %s\n", strerror(errno)); | ||
471 | return INVALID_SOCKET; | ||
472 | } | ||
473 | |||
474 | if (0 != | ||
475 | _win_setsockopt(rawsock, SOL_SOCKET, SO_BROADCAST, (char *)&bOptVal, | ||
476 | bOptLen)) | ||
477 | { | ||
478 | fprintf(stderr, "Error setting SO_BROADCAST to ON: %s\n", | ||
479 | strerror(errno)); | ||
480 | closesocket(rawsock); | ||
481 | return INVALID_SOCKET; | ||
482 | } | ||
483 | if (0 != | ||
484 | _win_setsockopt(rawsock, IPPROTO_IP, IP_HDRINCL, (char *)&bOptVal, bOptLen)) | ||
485 | { | ||
486 | fprintf(stderr, "Error setting IP_HDRINCL to ON: %s\n", strerror(errno)); | ||
487 | closesocket(rawsock); | ||
488 | return INVALID_SOCKET; | ||
489 | } | ||
490 | return rawsock; | ||
491 | } | ||
492 | |||
493 | |||
494 | /** | ||
495 | * Create a UDP socket for writing. | ||
496 | * | ||
497 | * @param my_ip source address (our ip address) | ||
498 | * @return INVALID_SOCKET on error | ||
499 | */ | ||
500 | static _win_socket | ||
501 | make_udp_socket(const struct in_addr *my_ip) | ||
502 | { | ||
503 | _win_socket ret; | ||
504 | struct sockaddr_in addr; | ||
505 | |||
506 | ret = _win_socket(AF_INET, SOCK_DGRAM, 0); | ||
507 | if (INVALID_SOCKET == ret) | ||
508 | { | ||
509 | fprintf(stderr, "Error opening UDP socket: %s\n", strerror(errno)); | ||
510 | return INVALID_SOCKET; | ||
511 | } | ||
512 | memset(&addr, 0, sizeof(addr)); | ||
513 | addr.sin_family = AF_INET; | ||
514 | addr.sin_addr = *my_ip; | ||
515 | addr.sin_port = htons(NAT_TRAV_PORT); | ||
516 | if (0 != bind(ret, (struct sockaddr *)&addr, sizeof(addr))) | ||
517 | { | ||
518 | fprintf(stderr, "Error binding UDP socket to port %u: %s\n", NAT_TRAV_PORT, | ||
519 | strerror(errno)); | ||
520 | /* likely problematic, but not certain, try to continue */ | ||
521 | } | ||
522 | return ret; | ||
523 | } | ||
524 | |||
525 | |||
526 | int | ||
527 | main(int argc, char *const *argv) | ||
528 | { | ||
529 | struct in_addr external; | ||
530 | fd_set rs; | ||
531 | struct timeval tv; | ||
532 | WSADATA wsaData; | ||
533 | unsigned int alt = 0; | ||
534 | |||
535 | if ((argc > 1) && (0 != strcmp(argv[1], "-d"))) | ||
536 | { | ||
537 | privilege_testing = TRUE; | ||
538 | fprintf(stderr, | ||
539 | "%s", | ||
540 | "DEBUG: Running binary in privilege testing mode."); | ||
541 | argv++; | ||
542 | argc--; | ||
543 | } | ||
544 | |||
545 | if (2 != argc) | ||
546 | { | ||
547 | fprintf(stderr, | ||
548 | "This program must be started with our (internal NAT) IP as the only argument.\n"); | ||
549 | return 1; | ||
550 | } | ||
551 | if (1 != inet_pton(AF_INET, argv[1], &external)) | ||
552 | { | ||
553 | fprintf(stderr, "Error parsing IPv4 address: %s, error %s\n", argv[1], | ||
554 | strerror(errno)); | ||
555 | return 1; | ||
556 | } | ||
557 | if (1 != inet_pton(AF_INET, DUMMY_IP, &dummy)) | ||
558 | { | ||
559 | fprintf(stderr, "Internal error converting dummy IP to binary.\n"); | ||
560 | return 2; | ||
561 | } | ||
562 | if (WSAStartup(MAKEWORD(2, 1), &wsaData) != 0) | ||
563 | { | ||
564 | fprintf(stderr, "Failed to find Winsock 2.1 or better.\n"); | ||
565 | return 2; | ||
566 | } | ||
567 | if (INVALID_SOCKET == (icmpsock = make_icmp_socket())) | ||
568 | { | ||
569 | return 3; | ||
570 | } | ||
571 | if (INVALID_SOCKET == (make_raw_socket())) | ||
572 | { | ||
573 | closesocket(icmpsock); | ||
574 | return 3; | ||
575 | } | ||
576 | if (INVALID_SOCKET == (udpsock = make_udp_socket(&external))) | ||
577 | { | ||
578 | closesocket(icmpsock); | ||
579 | closesocket(rawsock); | ||
580 | return 3; | ||
581 | } | ||
582 | |||
583 | while (!privilege_testing) | ||
584 | { | ||
585 | FD_ZERO(&rs); | ||
586 | FD_SET(icmpsock, &rs); | ||
587 | tv.tv_sec = 0; | ||
588 | tv.tv_usec = ICMP_SEND_FREQUENCY_MS * 1000; | ||
589 | if (-1 == select(icmpsock + 1, &rs, NULL, NULL, &tv)) | ||
590 | { | ||
591 | if (errno == EINTR) | ||
592 | continue; | ||
593 | fprintf(stderr, "select failed: %s\n", strerror(errno)); | ||
594 | break; | ||
595 | } | ||
596 | if (FD_ISSET(icmpsock, &rs)) | ||
597 | process_icmp_response(); | ||
598 | if (0 == (++alt % 2)) | ||
599 | send_icmp_echo(&external); | ||
600 | else | ||
601 | send_udp(); | ||
602 | } | ||
603 | /* select failed (internal error or OS out of resources) */ | ||
604 | closesocket(icmpsock); | ||
605 | closesocket(rawsock); | ||
606 | closesocket(udpsock); | ||
607 | WSACleanup(); | ||
608 | if (privilege_testing) | ||
609 | return 0; | ||
610 | return 4; | ||
611 | } | ||
612 | |||
613 | |||
614 | /* end of gnunet-helper-nat-server-windows.c */ | ||