aboutsummaryrefslogtreecommitdiff
path: root/src/nat/gnunet-helper-nat-client.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nat/gnunet-helper-nat-client.c')
-rw-r--r--src/nat/gnunet-helper-nat-client.c278
1 files changed, 117 insertions, 161 deletions
diff --git a/src/nat/gnunet-helper-nat-client.c b/src/nat/gnunet-helper-nat-client.c
index 10aa2f438..76f405bf1 100644
--- a/src/nat/gnunet-helper-nat-client.c
+++ b/src/nat/gnunet-helper-nat-client.c
@@ -190,17 +190,16 @@ static uint16_t port;
190 * @return the CRC 16. 190 * @return the CRC 16.
191 */ 191 */
192static uint16_t 192static uint16_t
193calc_checksum (const uint16_t *data, 193calc_checksum (const uint16_t * data, unsigned int bytes)
194 unsigned int bytes)
195{ 194{
196 uint32_t sum; 195 uint32_t sum;
197 unsigned int i; 196 unsigned int i;
198 197
199 sum = 0; 198 sum = 0;
200 for (i=0;i<bytes/2;i++) 199 for (i = 0; i < bytes / 2; i++)
201 sum += data[i]; 200 sum += data[i];
202 sum = (sum & 0xffff) + (sum >> 16); 201 sum = (sum & 0xffff) + (sum >> 16);
203 sum = htons(0xffff - sum); 202 sum = htons (0xffff - sum);
204 return sum; 203 return sum;
205} 204}
206 205
@@ -212,12 +211,11 @@ calc_checksum (const uint16_t *data,
212 * @param other target address 211 * @param other target address
213 */ 212 */
214static void 213static void
215send_icmp_udp (const struct in_addr *my_ip, 214send_icmp_udp (const struct in_addr *my_ip, const struct in_addr *other)
216 const struct in_addr *other)
217{ 215{
218 char packet[sizeof(struct ip_header) * 2 + 216 char packet[sizeof (struct ip_header) * 2 +
219 sizeof(struct icmp_ttl_exceeded_header) + 217 sizeof (struct icmp_ttl_exceeded_header) +
220 sizeof(struct udp_header)]; 218 sizeof (struct udp_header)];
221 struct ip_header ip_pkt; 219 struct ip_header ip_pkt;
222 struct icmp_ttl_exceeded_header icmp_pkt; 220 struct icmp_ttl_exceeded_header icmp_pkt;
223 struct udp_header udp_pkt; 221 struct udp_header udp_pkt;
@@ -230,66 +228,58 @@ send_icmp_udp (const struct in_addr *my_ip,
230 ip_pkt.vers_ihl = 0x45; 228 ip_pkt.vers_ihl = 0x45;
231 ip_pkt.tos = 0; 229 ip_pkt.tos = 0;
232 ip_pkt.pkt_len = htons (sizeof (packet)); 230 ip_pkt.pkt_len = htons (sizeof (packet));
233 ip_pkt.id = htons(256); 231 ip_pkt.id = htons (256);
234 ip_pkt.flags_frag_offset = 0; 232 ip_pkt.flags_frag_offset = 0;
235 ip_pkt.ttl = 128; 233 ip_pkt.ttl = 128;
236 ip_pkt.proto = IPPROTO_ICMP; 234 ip_pkt.proto = IPPROTO_ICMP;
237 ip_pkt.checksum = 0; 235 ip_pkt.checksum = 0;
238 ip_pkt.src_ip = my_ip->s_addr; 236 ip_pkt.src_ip = my_ip->s_addr;
239 ip_pkt.dst_ip = other->s_addr; 237 ip_pkt.dst_ip = other->s_addr;
240 ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, 238 ip_pkt.checksum = htons (calc_checksum ((uint16_t *) & ip_pkt,
241 sizeof (struct ip_header))); 239 sizeof (struct ip_header)));
242 memcpy(&packet[off], 240 memcpy (&packet[off], &ip_pkt, sizeof (struct ip_header));
243 &ip_pkt, 241 off += sizeof (struct ip_header);
244 sizeof(struct ip_header));
245 off += sizeof(struct ip_header);
246 242
247 icmp_pkt.type = ICMP_TIME_EXCEEDED; 243 icmp_pkt.type = ICMP_TIME_EXCEEDED;
248 icmp_pkt.code = 0; 244 icmp_pkt.code = 0;
249 icmp_pkt.checksum = 0; 245 icmp_pkt.checksum = 0;
250 icmp_pkt.unused = 0; 246 icmp_pkt.unused = 0;
251 memcpy(&packet[off], 247 memcpy (&packet[off], &icmp_pkt, sizeof (struct icmp_ttl_exceeded_header));
252 &icmp_pkt, 248 off += sizeof (struct icmp_ttl_exceeded_header);
253 sizeof(struct icmp_ttl_exceeded_header));
254 off += sizeof(struct icmp_ttl_exceeded_header);
255 249
256 /* ip header of the presumably 'lost' udp packet */ 250 /* ip header of the presumably 'lost' udp packet */
257 ip_pkt.vers_ihl = 0x45; 251 ip_pkt.vers_ihl = 0x45;
258 ip_pkt.tos = 0; 252 ip_pkt.tos = 0;
259 ip_pkt.pkt_len = htons(sizeof (struct ip_header) + 253 ip_pkt.pkt_len = htons (sizeof (struct ip_header) +
260 sizeof (struct udp_header)); 254 sizeof (struct udp_header));
261 ip_pkt.id = htons(0); 255 ip_pkt.id = htons (0);
262 ip_pkt.flags_frag_offset = 0; 256 ip_pkt.flags_frag_offset = 0;
263 ip_pkt.ttl = 128; 257 ip_pkt.ttl = 128;
264 ip_pkt.proto = IPPROTO_UDP; 258 ip_pkt.proto = IPPROTO_UDP;
265 ip_pkt.checksum = 0; 259 ip_pkt.checksum = 0;
266 ip_pkt.src_ip = other->s_addr; 260 ip_pkt.src_ip = other->s_addr;
267 ip_pkt.dst_ip = dummy.s_addr; 261 ip_pkt.dst_ip = dummy.s_addr;
268 ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, 262 ip_pkt.checksum = htons (calc_checksum ((uint16_t *) & ip_pkt,
269 sizeof (struct ip_header))); 263 sizeof (struct ip_header)));
270 memcpy(&packet[off], 264 memcpy (&packet[off], &ip_pkt, sizeof (struct ip_header));
271 &ip_pkt, 265 off += sizeof (struct ip_header);
272 sizeof(struct ip_header));
273 off += sizeof(struct ip_header);
274 266
275 /* build UDP header */ 267 /* build UDP header */
276 udp_pkt.src_port = htons(NAT_TRAV_PORT); 268 udp_pkt.src_port = htons (NAT_TRAV_PORT);
277 udp_pkt.dst_port = htons(NAT_TRAV_PORT); 269 udp_pkt.dst_port = htons (NAT_TRAV_PORT);
278 udp_pkt.length = htons (port); 270 udp_pkt.length = htons (port);
279 udp_pkt.crc = 0; 271 udp_pkt.crc = 0;
280 memcpy(&packet[off], 272 memcpy (&packet[off], &udp_pkt, sizeof (struct udp_header));
281 &udp_pkt, 273 off += sizeof (struct udp_header);
282 sizeof(struct udp_header));
283 off += sizeof(struct udp_header);
284 274
285 /* set ICMP checksum */ 275 /* set ICMP checksum */
286 icmp_pkt.checksum = htons(calc_checksum((uint16_t*)&packet[sizeof(struct ip_header)], 276 icmp_pkt.checksum =
287 sizeof (struct icmp_ttl_exceeded_header) + 277 htons (calc_checksum
288 sizeof (struct ip_header) + 278 ((uint16_t *) & packet[sizeof (struct ip_header)],
289 sizeof (struct udp_header))); 279 sizeof (struct icmp_ttl_exceeded_header) +
290 memcpy (&packet[sizeof(struct ip_header)], 280 sizeof (struct ip_header) + sizeof (struct udp_header)));
291 &icmp_pkt, 281 memcpy (&packet[sizeof (struct ip_header)], &icmp_pkt,
292 sizeof (struct icmp_ttl_exceeded_header)); 282 sizeof (struct icmp_ttl_exceeded_header));
293 283
294 memset (&dst, 0, sizeof (dst)); 284 memset (&dst, 0, sizeof (dst));
295 dst.sin_family = AF_INET; 285 dst.sin_family = AF_INET;
@@ -297,21 +287,17 @@ send_icmp_udp (const struct in_addr *my_ip,
297 dst.sin_len = sizeof (struct sockaddr_in); 287 dst.sin_len = sizeof (struct sockaddr_in);
298#endif 288#endif
299 dst.sin_addr = *other; 289 dst.sin_addr = *other;
300 err = sendto(rawsock, 290 err = sendto (rawsock,
301 packet, 291 packet,
302 sizeof (packet), 0, 292 sizeof (packet), 0, (struct sockaddr *) &dst, sizeof (dst));
303 (struct sockaddr*)&dst,
304 sizeof(dst));
305 if (err < 0) 293 if (err < 0)
306 { 294 {
307 fprintf(stderr, 295 fprintf (stderr, "sendto failed: %s\n", strerror (errno));
308 "sendto failed: %s\n", strerror(errno)); 296 }
309 }
310 else if (sizeof (packet) != (size_t) err) 297 else if (sizeof (packet) != (size_t) err)
311 { 298 {
312 fprintf(stderr, 299 fprintf (stderr, "Error: partial send of ICMP message\n");
313 "Error: partial send of ICMP message\n"); 300 }
314 }
315} 301}
316 302
317 303
@@ -322,16 +308,15 @@ send_icmp_udp (const struct in_addr *my_ip,
322 * @param other target address 308 * @param other target address
323 */ 309 */
324static void 310static void
325send_icmp (const struct in_addr *my_ip, 311send_icmp (const struct in_addr *my_ip, const struct in_addr *other)
326 const struct in_addr *other)
327{ 312{
328 struct ip_header ip_pkt; 313 struct ip_header ip_pkt;
329 struct icmp_ttl_exceeded_header icmp_ttl; 314 struct icmp_ttl_exceeded_header icmp_ttl;
330 struct icmp_echo_header icmp_echo; 315 struct icmp_echo_header icmp_echo;
331 struct sockaddr_in dst; 316 struct sockaddr_in dst;
332 char packet[sizeof (struct ip_header) * 2 + 317 char packet[sizeof (struct ip_header) * 2 +
333 sizeof (struct icmp_ttl_exceeded_header) + 318 sizeof (struct icmp_ttl_exceeded_header) +
334 sizeof (struct icmp_echo_header)]; 319 sizeof (struct icmp_echo_header)];
335 size_t off; 320 size_t off;
336 int err; 321 int err;
337 322
@@ -347,11 +332,9 @@ send_icmp (const struct in_addr *my_ip,
347 ip_pkt.checksum = 0; 332 ip_pkt.checksum = 0;
348 ip_pkt.src_ip = my_ip->s_addr; 333 ip_pkt.src_ip = my_ip->s_addr;
349 ip_pkt.dst_ip = other->s_addr; 334 ip_pkt.dst_ip = other->s_addr;
350 ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, 335 ip_pkt.checksum = htons (calc_checksum ((uint16_t *) & ip_pkt,
351 sizeof (struct ip_header))); 336 sizeof (struct ip_header)));
352 memcpy (&packet[off], 337 memcpy (&packet[off], &ip_pkt, sizeof (struct ip_header));
353 &ip_pkt,
354 sizeof (struct ip_header));
355 off = sizeof (ip_pkt); 338 off = sizeof (ip_pkt);
356 339
357 /* icmp reply: time exceeded */ 340 /* icmp reply: time exceeded */
@@ -359,48 +342,42 @@ send_icmp (const struct in_addr *my_ip,
359 icmp_ttl.code = 0; 342 icmp_ttl.code = 0;
360 icmp_ttl.checksum = 0; 343 icmp_ttl.checksum = 0;
361 icmp_ttl.unused = 0; 344 icmp_ttl.unused = 0;
362 memcpy (&packet[off], 345 memcpy (&packet[off], &icmp_ttl, sizeof (struct icmp_ttl_exceeded_header));
363 &icmp_ttl,
364 sizeof (struct icmp_ttl_exceeded_header));
365 off += sizeof (struct icmp_ttl_exceeded_header); 346 off += sizeof (struct icmp_ttl_exceeded_header);
366 347
367 /* ip header of the presumably 'lost' udp packet */ 348 /* ip header of the presumably 'lost' udp packet */
368 ip_pkt.vers_ihl = 0x45; 349 ip_pkt.vers_ihl = 0x45;
369 ip_pkt.tos = 0; 350 ip_pkt.tos = 0;
370 ip_pkt.pkt_len = htons (sizeof (struct ip_header) + sizeof (struct icmp_echo_header)); 351 ip_pkt.pkt_len =
352 htons (sizeof (struct ip_header) + sizeof (struct icmp_echo_header));
371 ip_pkt.id = htons (256); 353 ip_pkt.id = htons (256);
372 ip_pkt.flags_frag_offset = 0; 354 ip_pkt.flags_frag_offset = 0;
373 ip_pkt.ttl = 1; /* real TTL would be 1 on a time exceeded packet */ 355 ip_pkt.ttl = 1; /* real TTL would be 1 on a time exceeded packet */
374 ip_pkt.proto = IPPROTO_ICMP; 356 ip_pkt.proto = IPPROTO_ICMP;
375 ip_pkt.src_ip = other->s_addr; 357 ip_pkt.src_ip = other->s_addr;
376 ip_pkt.dst_ip = dummy.s_addr; 358 ip_pkt.dst_ip = dummy.s_addr;
377 ip_pkt.checksum = 0; 359 ip_pkt.checksum = 0;
378 ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, 360 ip_pkt.checksum = htons (calc_checksum ((uint16_t *) & ip_pkt,
379 sizeof (struct ip_header))); 361 sizeof (struct ip_header)));
380 memcpy (&packet[off], 362 memcpy (&packet[off], &ip_pkt, sizeof (struct ip_header));
381 &ip_pkt,
382 sizeof (struct ip_header));
383 off += sizeof (struct ip_header); 363 off += sizeof (struct ip_header);
384 364
385 icmp_echo.type = ICMP_ECHO; 365 icmp_echo.type = ICMP_ECHO;
386 icmp_echo.code = 0; 366 icmp_echo.code = 0;
387 icmp_echo.reserved = htonl (port); 367 icmp_echo.reserved = htonl (port);
388 icmp_echo.checksum = 0; 368 icmp_echo.checksum = 0;
389 icmp_echo.checksum = htons(calc_checksum((uint16_t*) &icmp_echo, 369 icmp_echo.checksum = htons (calc_checksum ((uint16_t *) & icmp_echo,
390 sizeof (struct icmp_echo_header))); 370 sizeof (struct icmp_echo_header)));
391 memcpy (&packet[off], 371 memcpy (&packet[off], &icmp_echo, sizeof (struct icmp_echo_header));
392 &icmp_echo,
393 sizeof(struct icmp_echo_header));
394 372
395 /* no go back to calculate ICMP packet checksum */ 373 /* no go back to calculate ICMP packet checksum */
396 off = sizeof (struct ip_header); 374 off = sizeof (struct ip_header);
397 icmp_ttl.checksum = htons(calc_checksum((uint16_t*) &packet[off], 375 icmp_ttl.checksum = htons (calc_checksum ((uint16_t *) & packet[off],
398 sizeof (struct icmp_ttl_exceeded_header) + 376 sizeof (struct
399 sizeof (struct ip_header) + 377 icmp_ttl_exceeded_header) +
400 sizeof (struct icmp_echo_header))); 378 sizeof (struct ip_header) +
401 memcpy (&packet[off], 379 sizeof (struct icmp_echo_header)));
402 &icmp_ttl, 380 memcpy (&packet[off], &icmp_ttl, sizeof (struct icmp_ttl_exceeded_header));
403 sizeof (struct icmp_ttl_exceeded_header));
404 381
405 /* prepare for transmission */ 382 /* prepare for transmission */
406 memset (&dst, 0, sizeof (dst)); 383 memset (&dst, 0, sizeof (dst));
@@ -409,21 +386,17 @@ send_icmp (const struct in_addr *my_ip,
409 dst.sin_len = sizeof (struct sockaddr_in); 386 dst.sin_len = sizeof (struct sockaddr_in);
410#endif 387#endif
411 dst.sin_addr = *other; 388 dst.sin_addr = *other;
412 err = sendto(rawsock, 389 err = sendto (rawsock,
413 packet, 390 packet,
414 sizeof (packet), 0, 391 sizeof (packet), 0, (struct sockaddr *) &dst, sizeof (dst));
415 (struct sockaddr*)&dst,
416 sizeof(dst));
417 if (err < 0) 392 if (err < 0)
418 { 393 {
419 fprintf(stderr, 394 fprintf (stderr, "sendto failed: %s\n", strerror (errno));
420 "sendto failed: %s\n", strerror(errno)); 395 }
421 }
422 else if (sizeof (packet) != (size_t) err) 396 else if (sizeof (packet) != (size_t) err)
423 { 397 {
424 fprintf(stderr, 398 fprintf (stderr, "Error: partial send of ICMP message\n");
425 "Error: partial send of ICMP message\n"); 399 }
426 }
427} 400}
428 401
429 402
@@ -440,30 +413,24 @@ make_raw_socket ()
440 413
441 ret = socket (AF_INET, SOCK_RAW, IPPROTO_RAW); 414 ret = socket (AF_INET, SOCK_RAW, IPPROTO_RAW);
442 if (-1 == ret) 415 if (-1 == ret)
443 { 416 {
444 fprintf (stderr, 417 fprintf (stderr, "Error opening RAW socket: %s\n", strerror (errno));
445 "Error opening RAW socket: %s\n", 418 return -1;
446 strerror (errno)); 419 }
447 return -1; 420 if (0 != setsockopt (ret, SOL_SOCKET, SO_BROADCAST,
448 } 421 (char *) &one, sizeof (one)))
449 if (0 != setsockopt(ret, SOL_SOCKET, SO_BROADCAST, 422 {
450 (char *)&one, sizeof(one))) 423 fprintf (stderr, "setsockopt failed: %s\n", strerror (errno));
451 { 424 close (ret);
452 fprintf(stderr, 425 return -1;
453 "setsockopt failed: %s\n", 426 }
454 strerror (errno)); 427 if (0 != setsockopt (ret, IPPROTO_IP, IP_HDRINCL,
455 close (ret); 428 (char *) &one, sizeof (one)))
456 return -1; 429 {
457 } 430 fprintf (stderr, "setsockopt failed: %s\n", strerror (errno));
458 if (0 != setsockopt(ret, IPPROTO_IP, IP_HDRINCL, 431 close (ret);
459 (char *)&one, sizeof(one))) 432 return -1;
460 { 433 }
461 fprintf(stderr,
462 "setsockopt failed: %s\n",
463 strerror (errno));
464 close (ret);
465 return -1;
466 }
467 return ret; 434 return ret;
468} 435}
469 436
@@ -477,49 +444,38 @@ main (int argc, char *const *argv)
477 unsigned int p; 444 unsigned int p;
478 445
479 if (4 != argc) 446 if (4 != argc)
480 { 447 {
481 fprintf (stderr, 448 fprintf (stderr,
482 "This program must be started with our IP, the targets external IP, and our port as arguments.\n"); 449 "This program must be started with our IP, the targets external IP, and our port as arguments.\n");
483 return 1; 450 return 1;
484 } 451 }
485 if ( (1 != inet_pton (AF_INET, argv[1], &external)) || 452 if ((1 != inet_pton (AF_INET, argv[1], &external)) ||
486 (1 != inet_pton (AF_INET, argv[2], &target)) ) 453 (1 != inet_pton (AF_INET, argv[2], &target)))
487 { 454 {
488 fprintf (stderr, 455 fprintf (stderr, "Error parsing IPv4 address: %s\n", strerror (errno));
489 "Error parsing IPv4 address: %s\n", 456 return 1;
490 strerror (errno)); 457 }
491 return 1; 458 if ((1 != sscanf (argv[3], "%u", &p)) || (0 == p) || (0xFFFF < p))
492 } 459 {
493 if ( (1 != sscanf (argv[3], "%u", &p) ) || 460 fprintf (stderr, "Error parsing port value `%s'\n", argv[3]);
494 (0 == p) || 461 return 1;
495 (0xFFFF < p) ) 462 }
496 {
497 fprintf (stderr,
498 "Error parsing port value `%s'\n",
499 argv[3]);
500 return 1;
501 }
502 port = (uint16_t) p; 463 port = (uint16_t) p;
503 if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) 464 if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy))
504 { 465 {
505 fprintf (stderr, 466 fprintf (stderr, "Internal error converting dummy IP to binary.\n");
506 "Internal error converting dummy IP to binary.\n"); 467 return 2;
507 return 2; 468 }
508 } 469 if (-1 == (rawsock = make_raw_socket ()))
509 if (-1 == (rawsock = make_raw_socket()))
510 return 2; 470 return 2;
511 uid = getuid (); 471 uid = getuid ();
512 if (0 != setresuid (uid, uid, uid)) 472 if (0 != setresuid (uid, uid, uid))
513 { 473 {
514 fprintf (stderr, 474 fprintf (stderr, "Failed to setresuid: %s\n", strerror (errno));
515 "Failed to setresuid: %s\n", 475 /* not critical, continue anyway */
516 strerror (errno)); 476 }
517 /* not critical, continue anyway */ 477 send_icmp (&external, &target);
518 } 478 send_icmp_udp (&external, &target);
519 send_icmp (&external,
520 &target);
521 send_icmp_udp (&external,
522 &target);
523 close (rawsock); 479 close (rawsock);
524 return 0; 480 return 0;
525} 481}