diff options
author | Nathan S. Evans <evans@in.tum.de> | 2010-06-08 13:27:51 +0000 |
---|---|---|
committer | Nathan S. Evans <evans@in.tum.de> | 2010-06-08 13:27:51 +0000 |
commit | e16feb9b6a361a08a37ac80e5f76df70fb89ca70 (patch) | |
tree | 2a75028e50eb703290ccf9a1c8875713af935737 | |
parent | 87f73e3aee4a5f582ffb71e925f1f1d4f30e26d2 (diff) | |
download | gnunet-e16feb9b6a361a08a37ac80e5f76df70fb89ca70.tar.gz gnunet-e16feb9b6a361a08a37ac80e5f76df70fb89ca70.zip |
remove unneeded udp crapulence
-rw-r--r-- | src/transport/gnunet-nat-client-udp.c | 375 | ||||
-rw-r--r-- | src/transport/gnunet-nat-server-udp.c | 422 |
2 files changed, 0 insertions, 797 deletions
diff --git a/src/transport/gnunet-nat-client-udp.c b/src/transport/gnunet-nat-client-udp.c deleted file mode 100644 index 0e925dc5d..000000000 --- a/src/transport/gnunet-nat-client-udp.c +++ /dev/null | |||
@@ -1,375 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2010 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | 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 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/transport/gnunet-nat-client-udp.c | ||
23 | * @brief Tool to help bypass NATs using ICMP method; must run as root (SUID will do) | ||
24 | * This code will work under GNU/Linux only. | ||
25 | * @author Christian Grothoff | ||
26 | * | ||
27 | * This program will send ONE ICMP message using RAW sockets | ||
28 | * to the IP address specified as the second argument. The ICMP | ||
29 | * message will have as it's payload a UDP packet. 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 | */ | ||
43 | #define _GNU_SOURCE | ||
44 | #include <sys/types.h> | ||
45 | #include <sys/socket.h> | ||
46 | #include <arpa/inet.h> | ||
47 | #include <sys/types.h> | ||
48 | #include <unistd.h> | ||
49 | #include <stdio.h> | ||
50 | #include <string.h> | ||
51 | #include <errno.h> | ||
52 | #include <stdlib.h> | ||
53 | #include <stdint.h> | ||
54 | #include <netinet/ip.h> | ||
55 | #include <netinet/ip_icmp.h> | ||
56 | #include <netinet/in.h> | ||
57 | |||
58 | /** | ||
59 | * Must match IP given in the server. | ||
60 | */ | ||
61 | #define DUMMY_IP "1.2.3.4" | ||
62 | #define HAVE_PORT 1 | ||
63 | |||
64 | /** | ||
65 | * Port we always try to use. | ||
66 | */ | ||
67 | #define NAT_TRAV_PORT 22225 | ||
68 | |||
69 | struct ip_packet | ||
70 | { | ||
71 | uint8_t vers_ihl; | ||
72 | uint8_t tos; | ||
73 | uint16_t pkt_len; | ||
74 | uint16_t id; | ||
75 | uint16_t flags_frag_offset; | ||
76 | uint8_t ttl; | ||
77 | uint8_t proto; | ||
78 | uint16_t checksum; | ||
79 | uint32_t src_ip; | ||
80 | uint32_t dst_ip; | ||
81 | }; | ||
82 | |||
83 | struct icmp_packet | ||
84 | { | ||
85 | uint8_t type; | ||
86 | uint8_t code; | ||
87 | uint16_t checksum; | ||
88 | uint32_t reserved; | ||
89 | |||
90 | }; | ||
91 | |||
92 | struct icmp_echo_packet | ||
93 | { | ||
94 | uint8_t type; | ||
95 | uint8_t code; | ||
96 | uint16_t checksum; | ||
97 | uint32_t reserved; | ||
98 | uint32_t data; | ||
99 | }; | ||
100 | |||
101 | struct udp_packet | ||
102 | { | ||
103 | uint16_t src_port; | ||
104 | |||
105 | uint16_t dst_port; | ||
106 | |||
107 | uint32_t length; | ||
108 | }; | ||
109 | |||
110 | |||
111 | static int rawsock; | ||
112 | |||
113 | static struct in_addr dummy; | ||
114 | |||
115 | static struct in_addr target; | ||
116 | |||
117 | #if HAVE_PORT | ||
118 | static uint32_t port; | ||
119 | #endif | ||
120 | |||
121 | static uint16_t | ||
122 | calc_checksum(const uint16_t *data, | ||
123 | unsigned int bytes) | ||
124 | { | ||
125 | uint32_t sum; | ||
126 | unsigned int i; | ||
127 | |||
128 | sum = 0; | ||
129 | for (i=0;i<bytes/2;i++) | ||
130 | sum += data[i]; | ||
131 | sum = (sum & 0xffff) + (sum >> 16); | ||
132 | sum = htons(0xffff - sum); | ||
133 | return sum; | ||
134 | } | ||
135 | |||
136 | /** | ||
137 | * Send an ICMP message to the target. | ||
138 | * | ||
139 | * @param my_ip source address | ||
140 | * @param other target address | ||
141 | */ | ||
142 | static void | ||
143 | send_icmp (const struct in_addr *my_ip, | ||
144 | const struct in_addr *other) | ||
145 | { | ||
146 | struct ip_packet ip_pkt; | ||
147 | struct icmp_packet icmp_pkt; | ||
148 | struct udp_packet udp_pkt; | ||
149 | |||
150 | struct sockaddr_in dst; | ||
151 | char packet[sizeof(ip_pkt) * 2 + sizeof(icmp_pkt) * 2 + sizeof(char)]; | ||
152 | |||
153 | #if ORIGINAL | ||
154 | #if HAVE_PORT | ||
155 | char packet[sizeof (struct ip_packet)*2 + sizeof (struct icmp_packet) + sizeof(struct icmp_echo_packet)]; | ||
156 | #else | ||
157 | char packet[sizeof (struct ip_packet)*2 + sizeof (struct icmp_packet)*2]; | ||
158 | #endif | ||
159 | #endif | ||
160 | size_t off; | ||
161 | int err; | ||
162 | |||
163 | /* ip header: send to (known) ip address */ | ||
164 | #if ORIGINAL | ||
165 | off = 0; | ||
166 | memset(&ip_pkt, 0, sizeof(ip_pkt)); | ||
167 | ip_pkt.vers_ihl = 0x45; | ||
168 | ip_pkt.tos = 0; | ||
169 | ip_pkt.pkt_len = sizeof (packet); /* huh? */ | ||
170 | ip_pkt.id = 1; | ||
171 | ip_pkt.flags_frag_offset = 0; | ||
172 | ip_pkt.ttl = IPDEFTTL; | ||
173 | ip_pkt.proto = IPPROTO_ICMP; | ||
174 | ip_pkt.checksum = 0; | ||
175 | ip_pkt.src_ip = my_ip->s_addr; | ||
176 | ip_pkt.dst_ip = other->s_addr; | ||
177 | ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, sizeof (struct ip_packet))); | ||
178 | memcpy (packet, &ip_pkt, sizeof (struct ip_packet)); | ||
179 | off += sizeof (ip_pkt); | ||
180 | /* icmp reply: time exceeded */ | ||
181 | icmp_pkt = (struct icmp_packet*) &packet[off]; | ||
182 | memset(icmp_pkt, 0, sizeof(struct icmp_packet)); | ||
183 | icmp_pkt->type = ICMP_TIME_EXCEEDED; | ||
184 | icmp_pkt->code = 0; | ||
185 | icmp_pkt->reserved = 0; | ||
186 | icmp_pkt->checksum = 0; | ||
187 | |||
188 | off += sizeof (struct icmp_packet); | ||
189 | #endif | ||
190 | |||
191 | off = 0; | ||
192 | memset(&ip_pkt, 0, sizeof(ip_pkt)); | ||
193 | ip_pkt.vers_ihl = 0x45; | ||
194 | ip_pkt.tos = 0; | ||
195 | ip_pkt.pkt_len = htons(sizeof (packet)); | ||
196 | ip_pkt.id = htons(256); | ||
197 | ip_pkt.flags_frag_offset = 0; | ||
198 | ip_pkt.ttl = 128; | ||
199 | ip_pkt.proto = IPPROTO_ICMP; | ||
200 | ip_pkt.checksum = 0; | ||
201 | ip_pkt.src_ip = my_ip->s_addr; | ||
202 | ip_pkt.dst_ip = other->s_addr; | ||
203 | ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, sizeof (ip_pkt))); | ||
204 | memcpy(&packet[off], &ip_pkt, sizeof(ip_pkt)); | ||
205 | off += sizeof(ip_pkt); | ||
206 | |||
207 | /* ip header of the presumably 'lost' udp packet */ | ||
208 | ip_pkt.vers_ihl = 0x45; | ||
209 | ip_pkt.tos = 0; | ||
210 | #if HAVE_PORT | ||
211 | ip_pkt.pkt_len = (sizeof (struct ip_packet) + sizeof (struct icmp_echo_packet)); | ||
212 | #else | ||
213 | ip_pkt.pkt_len = (sizeof (struct ip_packet) + sizeof (struct icmp_packet)); | ||
214 | #endif | ||
215 | |||
216 | icmp_pkt.type = 11; // TTL exceeded | ||
217 | icmp_pkt.code = 0; | ||
218 | icmp_pkt.checksum = 0; | ||
219 | icmp_pkt.reserved = 0; | ||
220 | memcpy(&packet[off], &icmp_pkt, sizeof(icmp_pkt)); | ||
221 | off += sizeof(icmp_pkt); | ||
222 | |||
223 | |||
224 | // build inner IP header | ||
225 | memset(&ip_pkt, 0, sizeof(ip_pkt)); | ||
226 | ip_pkt.vers_ihl = 0x45; | ||
227 | ip_pkt.tos = 0; | ||
228 | ip_pkt.pkt_len = htons(sizeof (ip_pkt) + sizeof(udp_pkt)); | ||
229 | ip_pkt.id = htons(0); | ||
230 | ip_pkt.flags_frag_offset = 0; | ||
231 | ip_pkt.ttl = 128; | ||
232 | ip_pkt.proto = IPPROTO_UDP; | ||
233 | ip_pkt.checksum = 0; | ||
234 | ip_pkt.src_ip = other->s_addr; | ||
235 | ip_pkt.dst_ip = dummy.s_addr; | ||
236 | ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, sizeof (ip_pkt))); | ||
237 | memcpy(&packet[off], &ip_pkt, sizeof(ip_pkt)); | ||
238 | off += sizeof(ip_pkt); | ||
239 | |||
240 | // build UDP header | ||
241 | udp_pkt.src_port = htons(NAT_TRAV_PORT); /* FIXME: does this port matter? */ | ||
242 | udp_pkt.dst_port = htons(NAT_TRAV_PORT); | ||
243 | uint32_t newval = inet_addr("1.2.3.4"); | ||
244 | memcpy(&udp_pkt.length, &newval, sizeof(uint32_t)); | ||
245 | memcpy(&packet[off], &udp_pkt, sizeof(udp_pkt)); | ||
246 | off += sizeof(udp_pkt); | ||
247 | |||
248 | |||
249 | |||
250 | // set ICMP checksum | ||
251 | icmp_pkt.checksum = htons(calc_checksum((uint16_t*)&packet[sizeof(ip_pkt)], | ||
252 | sizeof (icmp_pkt) + sizeof(ip_pkt) + sizeof(udp_pkt))); | ||
253 | memcpy (&packet[sizeof(ip_pkt)], &icmp_pkt, sizeof (icmp_pkt)); | ||
254 | |||
255 | /* End of new code */ | ||
256 | #if ORIGINAL | ||
257 | ip_pkt.id = 1; | ||
258 | ip_pkt.flags_frag_offset = 0; | ||
259 | ip_pkt.ttl = 1; /* real TTL would be 1 on a time exceeded packet */ | ||
260 | ip_pkt.proto = IPPROTO_ICMP; | ||
261 | ip_pkt.src_ip = other->s_addr; | ||
262 | ip_pkt.dst_ip = dummy.s_addr; | ||
263 | ip_pkt.checksum = 0; | ||
264 | ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, sizeof (struct ip_packet))); | ||
265 | memcpy (&packet[off], &ip_pkt, sizeof (struct ip_packet)); | ||
266 | off += sizeof (struct ip_packet); | ||
267 | |||
268 | |||
269 | #if HAVE_PORT | ||
270 | icmp_pkt->checksum = htons(calc_checksum((uint16_t*)icmp_pkt, | ||
271 | sizeof (struct icmp_packet) + sizeof(struct ip_packet) + sizeof(struct icmp_echo_packet))); | ||
272 | |||
273 | #else | ||
274 | icmp_pkt->checksum = htons(calc_checksum((uint16_t*)icmp_pkt, | ||
275 | sizeof (struct icmp_packet)*2 + sizeof(struct ip_packet))); | ||
276 | |||
277 | #endif | ||
278 | |||
279 | |||
280 | #endif | ||
281 | |||
282 | memset (&dst, 0, sizeof (dst)); | ||
283 | dst.sin_family = AF_INET; | ||
284 | dst.sin_addr = *other; | ||
285 | err = sendto(rawsock, | ||
286 | packet, | ||
287 | off, 0, | ||
288 | (struct sockaddr*)&dst, | ||
289 | sizeof(dst)); /* or sizeof 'struct sockaddr'? */ | ||
290 | if (err < 0) | ||
291 | { | ||
292 | fprintf(stderr, | ||
293 | "sendto failed: %s\n", strerror(errno)); | ||
294 | } | ||
295 | else if (err != off) | ||
296 | { | ||
297 | fprintf(stderr, | ||
298 | "Error: partial send of ICMP message\n"); | ||
299 | } | ||
300 | } | ||
301 | |||
302 | |||
303 | static int | ||
304 | make_raw_socket () | ||
305 | { | ||
306 | const int one = 1; | ||
307 | int ret; | ||
308 | |||
309 | ret = socket (AF_INET, SOCK_RAW, IPPROTO_RAW); | ||
310 | if (-1 == ret) | ||
311 | { | ||
312 | fprintf (stderr, | ||
313 | "Error opening RAW socket: %s\n", | ||
314 | strerror (errno)); | ||
315 | return -1; | ||
316 | } | ||
317 | if (setsockopt(ret, SOL_SOCKET, SO_BROADCAST, | ||
318 | (char *)&one, sizeof(one)) == -1) | ||
319 | fprintf(stderr, | ||
320 | "setsockopt failed: %s\n", | ||
321 | strerror (errno)); | ||
322 | if (setsockopt(ret, IPPROTO_IP, IP_HDRINCL, | ||
323 | (char *)&one, sizeof(one)) == -1) | ||
324 | fprintf(stderr, | ||
325 | "setsockopt failed: %s\n", | ||
326 | strerror (errno)); | ||
327 | return ret; | ||
328 | } | ||
329 | |||
330 | |||
331 | int | ||
332 | main (int argc, char *const *argv) | ||
333 | { | ||
334 | struct in_addr external; | ||
335 | uid_t uid; | ||
336 | |||
337 | if (-1 == (rawsock = make_raw_socket())) | ||
338 | return 1; | ||
339 | uid = getuid (); | ||
340 | if (0 != setresuid (uid, uid, uid)) | ||
341 | fprintf (stderr, | ||
342 | "Failed to setresuid: %s\n", | ||
343 | strerror (errno)); | ||
344 | #if HAVE_PORT | ||
345 | if (argc != 4) | ||
346 | { | ||
347 | fprintf (stderr, | ||
348 | "This program must be started with our IP, the targets external IP, and our port as arguments.\n"); | ||
349 | return 1; | ||
350 | } | ||
351 | port = atoi(argv[3]); | ||
352 | #else | ||
353 | if (argc != 3) | ||
354 | { | ||
355 | fprintf (stderr, | ||
356 | "This program must be started with our IP and the targets external IP as arguments.\n"); | ||
357 | return 1; | ||
358 | } | ||
359 | #endif | ||
360 | if ( (1 != inet_pton (AF_INET, argv[1], &external)) || | ||
361 | (1 != inet_pton (AF_INET, argv[2], &target)) ) | ||
362 | { | ||
363 | fprintf (stderr, | ||
364 | "Error parsing IPv4 address: %s\n", | ||
365 | strerror (errno)); | ||
366 | return 1; | ||
367 | } | ||
368 | if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) abort (); | ||
369 | send_icmp (&external, | ||
370 | &target); | ||
371 | close (rawsock); | ||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | /* end of gnunet-nat-client-udp.c */ | ||
diff --git a/src/transport/gnunet-nat-server-udp.c b/src/transport/gnunet-nat-server-udp.c deleted file mode 100644 index 02ff65031..000000000 --- a/src/transport/gnunet-nat-server-udp.c +++ /dev/null | |||
@@ -1,422 +0,0 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2010 Christian Grothoff (and other contributing authors) | ||
4 | |||
5 | GNUnet is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 3, or (at your | ||
8 | 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 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file src/transport/gnunet-nat-server-udp.c | ||
23 | * @brief This program will send ONE UDP message every 500 ms | ||
24 | * to a DUMMY IP address and also listens for ICMP replies. | ||
25 | * | ||
26 | * @author Christian Grothoff | ||
27 | */ | ||
28 | #include <sys/types.h> | ||
29 | #include <sys/socket.h> | ||
30 | #include <arpa/inet.h> | ||
31 | #include <sys/types.h> | ||
32 | #include <unistd.h> | ||
33 | #include <stdio.h> | ||
34 | #include <string.h> | ||
35 | #include <errno.h> | ||
36 | #include <stdlib.h> | ||
37 | #include <stdint.h> | ||
38 | #include <netinet/in.h> | ||
39 | #include <time.h> | ||
40 | |||
41 | |||
42 | #define DUMMY_IP "1.2.3.4" | ||
43 | |||
44 | /** | ||
45 | * How often do we send our UDP message to keep ports open (and to | ||
46 | * try to connect, of course). | ||
47 | */ | ||
48 | #define UDP_SEND_FREQUENCY_MS 500 | ||
49 | |||
50 | /** | ||
51 | * Port we always try to use. | ||
52 | */ | ||
53 | #define NAT_TRAV_PORT 22225 | ||
54 | |||
55 | /** | ||
56 | * Number of UDP ports to send to | ||
57 | */ | ||
58 | #define NUM_UDP_PORTS 1 | ||
59 | |||
60 | /** | ||
61 | * How often do we retry to open and bind a UDP socket before giving up? | ||
62 | */ | ||
63 | #define MAX_BIND_TRIES 10 | ||
64 | |||
65 | #define LOW_PORT 32768 | ||
66 | |||
67 | static struct in_addr dummy; | ||
68 | |||
69 | static int icmpsock; | ||
70 | |||
71 | struct icmp_packet | ||
72 | { | ||
73 | uint8_t type; | ||
74 | uint8_t code; | ||
75 | uint16_t checksum; | ||
76 | uint32_t reserved; | ||
77 | |||
78 | }; | ||
79 | |||
80 | struct udp_packet | ||
81 | { | ||
82 | uint16_t src_port; | ||
83 | |||
84 | uint16_t dst_port; | ||
85 | |||
86 | uint32_t length; | ||
87 | }; | ||
88 | |||
89 | struct ip_packet | ||
90 | { | ||
91 | uint8_t vers_ihl; | ||
92 | uint8_t tos; | ||
93 | uint16_t pkt_len; | ||
94 | uint16_t id; | ||
95 | uint16_t flags_frag_offset; | ||
96 | uint8_t ttl; | ||
97 | uint8_t proto; | ||
98 | uint16_t checksum; | ||
99 | uint32_t src_ip; | ||
100 | uint32_t dst_ip; | ||
101 | }; | ||
102 | |||
103 | #if DUMMY | ||
104 | static uint16_t | ||
105 | calc_checksum(const uint16_t *data, | ||
106 | unsigned int bytes) | ||
107 | { | ||
108 | uint32_t sum; | ||
109 | unsigned int i; | ||
110 | |||
111 | sum = 0; | ||
112 | for (i=0;i<bytes/2;i++) | ||
113 | sum += data[i]; | ||
114 | sum = (sum & 0xffff) + (sum >> 16); | ||
115 | sum = htons(0xffff - sum); | ||
116 | return sum; | ||
117 | } | ||
118 | #endif | ||
119 | |||
120 | /** | ||
121 | * create a fresh udp socket bound to the NAT_TRAV_PORT. | ||
122 | * | ||
123 | * @return -1 on error | ||
124 | */ | ||
125 | static int | ||
126 | make_udp_socket () | ||
127 | { | ||
128 | int ret; | ||
129 | int tries; | ||
130 | struct sockaddr_in src; | ||
131 | |||
132 | for (tries=0; tries<MAX_BIND_TRIES; tries++) | ||
133 | { | ||
134 | ret = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); | ||
135 | if (-1 == ret) | ||
136 | { | ||
137 | fprintf (stderr, | ||
138 | "Error opening udp socket: %s\n", | ||
139 | strerror (errno)); | ||
140 | return -1; | ||
141 | } | ||
142 | if (ret >= FD_SETSIZE) | ||
143 | { | ||
144 | fprintf (stderr, | ||
145 | "Socket number too large (%d > %u)\n", | ||
146 | ret, | ||
147 | (unsigned int) FD_SETSIZE); | ||
148 | close (ret); | ||
149 | return -1; | ||
150 | } | ||
151 | memset (&src, 0, sizeof (src)); | ||
152 | src.sin_family = AF_INET; | ||
153 | src.sin_port = htons (NAT_TRAV_PORT); | ||
154 | |||
155 | if (0 != bind (ret, (struct sockaddr*) &src, sizeof (src))) | ||
156 | { | ||
157 | close (ret); | ||
158 | continue; | ||
159 | } | ||
160 | return ret; | ||
161 | } | ||
162 | fprintf (stderr, | ||
163 | "Error binding udp socket: %s\n", | ||
164 | strerror (errno)); | ||
165 | return -1; | ||
166 | } | ||
167 | |||
168 | #define LOW_PORT 32768 | ||
169 | |||
170 | /** | ||
171 | * create a random port number that is not totally | ||
172 | * unlikely to be chosen by the nat box. | ||
173 | */ | ||
174 | static uint16_t | ||
175 | make_port () | ||
176 | { | ||
177 | return LOW_PORT + ( (unsigned int)rand ()) % (64 * 1024 - LOW_PORT - 2); | ||
178 | } | ||
179 | |||
180 | static int | ||
181 | make_icmp_socket () | ||
182 | { | ||
183 | int ret; | ||
184 | |||
185 | ret = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP); | ||
186 | if (-1 == ret) | ||
187 | { | ||
188 | fprintf (stderr, | ||
189 | "Error opening RAW socket: %s\n", | ||
190 | strerror (errno)); | ||
191 | return -1; | ||
192 | } | ||
193 | if (ret >= FD_SETSIZE) | ||
194 | { | ||
195 | fprintf (stderr, | ||
196 | "Socket number too large (%d > %u)\n", | ||
197 | ret, | ||
198 | (unsigned int) FD_SETSIZE); | ||
199 | close (ret); | ||
200 | return -1; | ||
201 | } | ||
202 | return ret; | ||
203 | } | ||
204 | |||
205 | #if DUMMY | ||
206 | /** | ||
207 | * Send a UDP message to the dummy IP. | ||
208 | * | ||
209 | * @param my_ip source address (our ip address) | ||
210 | */ | ||
211 | static void | ||
212 | send_dummy_udp (const struct in_addr *my_ip) | ||
213 | { | ||
214 | struct sockaddr_in dst; | ||
215 | size_t off; | ||
216 | int err; | ||
217 | struct ip_packet ip_pkt; | ||
218 | struct ip_packet udp_pkt; | ||
219 | char packet[sizeof (ip_pkt) + sizeof (udp_pkt)]; | ||
220 | |||
221 | |||
222 | // build inner IP header | ||
223 | memset(&ip_pkt, 0, sizeof(ip_pkt)); | ||
224 | ip_pkt.vers_ihl = 0x45; | ||
225 | ip_pkt.tos = 0; | ||
226 | ip_pkt.pkt_len = htons(sizeof (ip_pkt) + sizeof(udp_pkt)); | ||
227 | ip_pkt.id = htons(0); | ||
228 | ip_pkt.flags_frag_offset = 0; | ||
229 | ip_pkt.ttl = 128; | ||
230 | ip_pkt.proto = IPPROTO_UDP; | ||
231 | ip_pkt.checksum = 0; | ||
232 | ip_pkt.src_ip = my_ip->s_addr; | ||
233 | ip_pkt.dst_ip = inet_addr(dummy.s_addr); | ||
234 | ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, sizeof (ip_pkt))); | ||
235 | memcpy(&packet[off], &ip_pkt, sizeof(ip_pkt)); | ||
236 | off += sizeof(ip_pkt); | ||
237 | |||
238 | // build UDP header | ||
239 | udp_pkt.src_port = NAT_TRAV_PORT; | ||
240 | udp_pkt.dst_port = htons(NAT_TRAV_PORT); | ||
241 | |||
242 | uint32_t newval = inet_addr("1.2.3.4"); | ||
243 | memcpy(&udp_pkt.length, &newval, sizeof(uint32_t)); | ||
244 | |||
245 | off += sizeof(udp_pkt); | ||
246 | |||
247 | err = sendto(rawsock, | ||
248 | ip_pkt, off, 0, | ||
249 | (struct sockaddr*)&dst, | ||
250 | sizeof(dst)); | ||
251 | if (err < 0) | ||
252 | { | ||
253 | #if VERBOSE | ||
254 | fprintf(stderr, | ||
255 | "sendto failed: %s\n", strerror(errno)); | ||
256 | #endif | ||
257 | } | ||
258 | else if (err != off) | ||
259 | { | ||
260 | fprintf(stderr, | ||
261 | "Error: partial send of UDP message\n"); | ||
262 | } | ||
263 | } | ||
264 | #endif | ||
265 | |||
266 | static void | ||
267 | process_icmp_response() | ||
268 | { | ||
269 | char buf[65536]; | ||
270 | ssize_t have; | ||
271 | struct in_addr sip; | ||
272 | struct ip_packet ip_pkt; | ||
273 | struct icmp_packet icmp_pkt; | ||
274 | size_t off; | ||
275 | int have_port; | ||
276 | //uint32_t port; | ||
277 | |||
278 | have = read (icmpsock, buf, sizeof (buf)); | ||
279 | if (have == -1) | ||
280 | { | ||
281 | fprintf (stderr, | ||
282 | "Error reading raw socket: %s\n", | ||
283 | strerror (errno)); | ||
284 | return; | ||
285 | } | ||
286 | |||
287 | off = 0; | ||
288 | memcpy (&ip_pkt, &buf[off], sizeof (ip_pkt)); | ||
289 | off += sizeof (ip_pkt); | ||
290 | memcpy (&icmp_pkt, &buf[off], sizeof (icmp_pkt)); | ||
291 | off += sizeof (icmp_pkt); | ||
292 | if ( (ip_pkt.proto != IPPROTO_ICMP) || | ||
293 | (icmp_pkt.type != 11) || | ||
294 | (icmp_pkt.code != 0) ) | ||
295 | { | ||
296 | /* maybe we got an actual reply back... */ | ||
297 | return; | ||
298 | } | ||
299 | |||
300 | memcpy(&sip, | ||
301 | &ip_pkt.src_ip, | ||
302 | sizeof (sip)); | ||
303 | |||
304 | fprintf (stderr, | ||
305 | "Received ICMP message of size: %u bytes from %s\n", | ||
306 | (unsigned int) have, | ||
307 | inet_ntop (AF_INET, | ||
308 | &sip, | ||
309 | buf, | ||
310 | sizeof (buf))); | ||
311 | |||
312 | have_port = 0; | ||
313 | if (have == sizeof (struct ip_packet) *2 + sizeof (struct icmp_packet) * 2 + sizeof(uint32_t)) | ||
314 | { | ||
315 | have_port = 1; | ||
316 | } | ||
317 | else if (have != sizeof (struct ip_packet) *2 + sizeof (struct icmp_packet) * 2) | ||
318 | { | ||
319 | #if VERBOSE | ||
320 | fprintf (stderr, | ||
321 | "Received ICMP message of unexpected size: %u bytes\n", | ||
322 | (unsigned int) have); | ||
323 | #endif | ||
324 | return; | ||
325 | } | ||
326 | } | ||
327 | |||
328 | int | ||
329 | main (int argc, char *const *argv) | ||
330 | { | ||
331 | int udpsocks[NUM_UDP_PORTS]; | ||
332 | struct in_addr external; | ||
333 | unsigned int pos; | ||
334 | int i; | ||
335 | struct sockaddr_in dst; | ||
336 | int first_round = 1; | ||
337 | unsigned int tries; | ||
338 | struct timeval tv; | ||
339 | fd_set rs; | ||
340 | time_t stime; | ||
341 | |||
342 | if (argc != 2) | ||
343 | { | ||
344 | fprintf (stderr, | ||
345 | "This program must be started with our (internal) IP as the single argument.\n"); | ||
346 | return 1; | ||
347 | } | ||
348 | if ( (1 != inet_pton (AF_INET, argv[1], &external))) | ||
349 | { | ||
350 | fprintf (stderr, | ||
351 | "Error parsing IPv4 address: %s\n", | ||
352 | strerror (errno)); | ||
353 | return 1; | ||
354 | } | ||
355 | |||
356 | if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) abort (); | ||
357 | |||
358 | fprintf (stderr, | ||
359 | "Trying to connect to %s\n", | ||
360 | DUMMY_IP); | ||
361 | srand (stime = time(NULL)); | ||
362 | for (i=0;i<NUM_UDP_PORTS;i++) | ||
363 | udpsocks[i] = make_udp_socket (i); | ||
364 | |||
365 | if (-1 == (icmpsock = make_icmp_socket())) | ||
366 | return 1; | ||
367 | |||
368 | memset (&dst, 0, sizeof (dst)); | ||
369 | dst.sin_family = AF_INET; | ||
370 | dst.sin_addr = dummy; | ||
371 | pos = 0; | ||
372 | tries = 0; | ||
373 | |||
374 | while (1) | ||
375 | { | ||
376 | tries++; | ||
377 | |||
378 | FD_ZERO (&rs); | ||
379 | FD_SET (icmpsock, &rs); | ||
380 | tv.tv_sec = 0; | ||
381 | tv.tv_usec = UDP_SEND_FREQUENCY_MS * 1000; | ||
382 | select (icmpsock + 1, &rs, NULL, NULL, &tv); | ||
383 | if (FD_ISSET (icmpsock, &rs)) | ||
384 | process_icmp_response (); | ||
385 | |||
386 | if (udpsocks[pos] == -1) | ||
387 | { | ||
388 | udpsocks[pos] = make_udp_socket (pos); | ||
389 | continue; | ||
390 | } | ||
391 | if ( (0 == ((unsigned int)rand() % NUM_UDP_PORTS)) || | ||
392 | (1 == first_round) ) | ||
393 | dst.sin_port = htons (NAT_TRAV_PORT); | ||
394 | else | ||
395 | dst.sin_port = htons (make_port ()); | ||
396 | #if VERBOSE | ||
397 | fprintf (stderr, | ||
398 | "Sending UDP packet to `%s:%u'\n", | ||
399 | DUMMY_IP, | ||
400 | ntohs (dst.sin_port)); | ||
401 | |||
402 | #endif | ||
403 | first_round = 0; | ||
404 | if (-1 == sendto (udpsocks[pos], | ||
405 | NULL, 0, 0, | ||
406 | (struct sockaddr*) &dst, sizeof (dst))) | ||
407 | { | ||
408 | fprintf (stderr, | ||
409 | "sendto failed: %s\n", | ||
410 | strerror (errno)); | ||
411 | close (udpsocks[pos]); | ||
412 | udpsocks[pos] = make_udp_socket (pos); | ||
413 | } | ||
414 | pos = (pos+1) % NUM_UDP_PORTS; | ||
415 | } | ||
416 | fprintf (stderr, | ||
417 | "Giving up after %u tries.\n", | ||
418 | tries); | ||
419 | return 3; | ||
420 | } | ||
421 | |||
422 | /* end of gnunet-nat-server-udp.c */ | ||