aboutsummaryrefslogtreecommitdiff
path: root/src/nat/gnunet-helper-nat-server.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nat/gnunet-helper-nat-server.c')
-rw-r--r--src/nat/gnunet-helper-nat-server.c583
1 files changed, 290 insertions, 293 deletions
diff --git a/src/nat/gnunet-helper-nat-server.c b/src/nat/gnunet-helper-nat-server.c
index 78b926037..f087590c8 100644
--- a/src/nat/gnunet-helper-nat-server.c
+++ b/src/nat/gnunet-helper-nat-server.c
@@ -11,12 +11,12 @@
11 WITHOUT ANY WARRANTY; without even the implied warranty of 11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details. 13 Affero General Public License for more details.
14 14
15 You should have received a copy of the GNU Affero General Public License 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/>. 16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 17
18 SPDX-License-Identifier: AGPL3.0-or-later 18 SPDX-License-Identifier: AGPL3.0-or-later
19*/ 19 */
20 20
21/** 21/**
22 * @file src/nat/gnunet-helper-nat-server.c 22 * @file src/nat/gnunet-helper-nat-server.c
@@ -79,7 +79,7 @@
79 * @param src source of the copy, may be NULL if @a n is zero 79 * @param src source of the copy, may be NULL if @a n is zero
80 * @param n number of bytes to copy 80 * @param n number of bytes to copy
81 */ 81 */
82#define GNUNET_memcpy(dst,src,n) do { if (0 != n) { (void) memcpy (dst,src,n); } } while (0) 82#define GNUNET_memcpy(dst, src, n) do { if (0 != n) { (void)memcpy(dst, src, n); } } while (0)
83 83
84/** 84/**
85 * Should we print some debug output? 85 * Should we print some debug output?
@@ -109,9 +109,7 @@
109/** 109/**
110 * IPv4 header. 110 * IPv4 header.
111 */ 111 */
112struct ip_header 112struct ip_header {
113{
114
115 /** 113 /**
116 * Version (4 bits) + Internet header length (4 bits) 114 * Version (4 bits) + Internet header length (4 bits)
117 */ 115 */
@@ -166,8 +164,7 @@ struct ip_header
166/** 164/**
167 * Format of ICMP packet. 165 * Format of ICMP packet.
168 */ 166 */
169struct icmp_ttl_exceeded_header 167struct icmp_ttl_exceeded_header {
170{
171 uint8_t type; 168 uint8_t type;
172 169
173 uint8_t code; 170 uint8_t code;
@@ -179,8 +176,7 @@ struct icmp_ttl_exceeded_header
179 /* followed by original payload */ 176 /* followed by original payload */
180}; 177};
181 178
182struct icmp_echo_header 179struct icmp_echo_header {
183{
184 uint8_t type; 180 uint8_t type;
185 181
186 uint8_t code; 182 uint8_t code;
@@ -194,8 +190,7 @@ struct icmp_echo_header
194/** 190/**
195 * Beginning of UDP packet. 191 * Beginning of UDP packet.
196 */ 192 */
197struct udp_header 193struct udp_header {
198{
199 uint16_t src_port; 194 uint16_t src_port;
200 195
201 uint16_t dst_port; 196 uint16_t dst_port;
@@ -234,7 +229,7 @@ static struct in_addr dummy;
234 * @return the CRC 16. 229 * @return the CRC 16.
235 */ 230 */
236static uint16_t 231static uint16_t
237calc_checksum (const uint16_t * data, unsigned int bytes) 232calc_checksum(const uint16_t * data, unsigned int bytes)
238{ 233{
239 uint32_t sum; 234 uint32_t sum;
240 unsigned int i; 235 unsigned int i;
@@ -243,7 +238,7 @@ calc_checksum (const uint16_t * data, unsigned int bytes)
243 for (i = 0; i < bytes / 2; i++) 238 for (i = 0; i < bytes / 2; i++)
244 sum += data[i]; 239 sum += data[i];
245 sum = (sum & 0xffff) + (sum >> 16); 240 sum = (sum & 0xffff) + (sum >> 16);
246 sum = htons (0xffff - sum); 241 sum = htons(0xffff - sum);
247 return sum; 242 return sum;
248} 243}
249 244
@@ -254,9 +249,9 @@ calc_checksum (const uint16_t * data, unsigned int bytes)
254 * @param my_ip source address (our ip address) 249 * @param my_ip source address (our ip address)
255 */ 250 */
256static void 251static void
257send_icmp_echo (const struct in_addr *my_ip) 252send_icmp_echo(const struct in_addr *my_ip)
258{ 253{
259 char packet[sizeof (struct ip_header) + sizeof (struct icmp_echo_header)]; 254 char packet[sizeof(struct ip_header) + sizeof(struct icmp_echo_header)];
260 struct icmp_echo_header icmp_echo; 255 struct icmp_echo_header icmp_echo;
261 struct ip_header ip_pkt; 256 struct ip_header ip_pkt;
262 struct sockaddr_in dst; 257 struct sockaddr_in dst;
@@ -266,8 +261,8 @@ send_icmp_echo (const struct in_addr *my_ip)
266 off = 0; 261 off = 0;
267 ip_pkt.vers_ihl = 0x45; 262 ip_pkt.vers_ihl = 0x45;
268 ip_pkt.tos = 0; 263 ip_pkt.tos = 0;
269 ip_pkt.pkt_len = htons (sizeof (packet)); 264 ip_pkt.pkt_len = htons(sizeof(packet));
270 ip_pkt.id = htons (PACKET_ID); 265 ip_pkt.id = htons(PACKET_ID);
271 ip_pkt.flags_frag_offset = 0; 266 ip_pkt.flags_frag_offset = 0;
272 ip_pkt.ttl = IPDEFTTL; 267 ip_pkt.ttl = IPDEFTTL;
273 ip_pkt.proto = IPPROTO_ICMP; 268 ip_pkt.proto = IPPROTO_ICMP;
@@ -275,51 +270,51 @@ send_icmp_echo (const struct in_addr *my_ip)
275 ip_pkt.src_ip = my_ip->s_addr; 270 ip_pkt.src_ip = my_ip->s_addr;
276 ip_pkt.dst_ip = dummy.s_addr; 271 ip_pkt.dst_ip = dummy.s_addr;
277 ip_pkt.checksum = 272 ip_pkt.checksum =
278 htons (calc_checksum ((uint16_t *) & ip_pkt, 273 htons(calc_checksum((uint16_t *)&ip_pkt,
279 sizeof (struct ip_header))); 274 sizeof(struct ip_header)));
280 GNUNET_memcpy (&packet[off], 275 GNUNET_memcpy(&packet[off],
281 &ip_pkt, 276 &ip_pkt,
282 sizeof (struct ip_header)); 277 sizeof(struct ip_header));
283 off += sizeof (struct ip_header); 278 off += sizeof(struct ip_header);
284 279
285 icmp_echo.type = ICMP_ECHO; 280 icmp_echo.type = ICMP_ECHO;
286 icmp_echo.code = 0; 281 icmp_echo.code = 0;
287 icmp_echo.checksum = 0; 282 icmp_echo.checksum = 0;
288 icmp_echo.reserved = 0; 283 icmp_echo.reserved = 0;
289 icmp_echo.checksum = 284 icmp_echo.checksum =
290 htons (calc_checksum 285 htons(calc_checksum
291 ((uint16_t *) & icmp_echo, 286 ((uint16_t *)&icmp_echo,
292 sizeof (struct icmp_echo_header))); 287 sizeof(struct icmp_echo_header)));
293 GNUNET_memcpy (&packet[off], 288 GNUNET_memcpy(&packet[off],
294 &icmp_echo, 289 &icmp_echo,
295 sizeof (struct icmp_echo_header)); 290 sizeof(struct icmp_echo_header));
296 off += sizeof (struct icmp_echo_header); 291 off += sizeof(struct icmp_echo_header);
297 292
298 memset (&dst, 0, sizeof (dst)); 293 memset(&dst, 0, sizeof(dst));
299 dst.sin_family = AF_INET; 294 dst.sin_family = AF_INET;
300#if HAVE_SOCKADDR_IN_SIN_LEN 295#if HAVE_SOCKADDR_IN_SIN_LEN
301 dst.sin_len = sizeof (struct sockaddr_in); 296 dst.sin_len = sizeof(struct sockaddr_in);
302#endif 297#endif
303 dst.sin_addr = dummy; 298 dst.sin_addr = dummy;
304 err = sendto (rawsock, 299 err = sendto(rawsock,
305 packet, 300 packet,
306 off, 301 off,
307 0, 302 0,
308 (struct sockaddr *) &dst, 303 (struct sockaddr *)&dst,
309 sizeof (dst)); 304 sizeof(dst));
310 if (err < 0) 305 if (err < 0)
311 { 306 {
312#if VERBOSE 307#if VERBOSE
313 fprintf (stderr, 308 fprintf(stderr,
314 "sendto failed: %s\n", 309 "sendto failed: %s\n",
315 strerror (errno)); 310 strerror(errno));
316#endif 311#endif
317 } 312 }
318 else if (sizeof (packet) != err) 313 else if (sizeof(packet) != err)
319 { 314 {
320 fprintf (stderr, 315 fprintf(stderr,
321 "Error: partial send of ICMP message\n"); 316 "Error: partial send of ICMP message\n");
322 } 317 }
323} 318}
324 319
325 320
@@ -327,37 +322,37 @@ send_icmp_echo (const struct in_addr *my_ip)
327 * Send a UDP message to the dummy IP. 322 * Send a UDP message to the dummy IP.
328 */ 323 */
329static void 324static void
330send_udp () 325send_udp()
331{ 326{
332 struct sockaddr_in dst; 327 struct sockaddr_in dst;
333 ssize_t err; 328 ssize_t err;
334 329
335 memset (&dst, 0, sizeof (dst)); 330 memset(&dst, 0, sizeof(dst));
336 dst.sin_family = AF_INET; 331 dst.sin_family = AF_INET;
337#if HAVE_SOCKADDR_IN_SIN_LEN 332#if HAVE_SOCKADDR_IN_SIN_LEN
338 dst.sin_len = sizeof (struct sockaddr_in); 333 dst.sin_len = sizeof(struct sockaddr_in);
339#endif 334#endif
340 dst.sin_addr = dummy; 335 dst.sin_addr = dummy;
341 dst.sin_port = htons (NAT_TRAV_PORT); 336 dst.sin_port = htons(NAT_TRAV_PORT);
342 err = sendto (udpsock, 337 err = sendto(udpsock,
343 NULL, 338 NULL,
344 0, 339 0,
345 0, 340 0,
346 (struct sockaddr *) &dst, 341 (struct sockaddr *)&dst,
347 sizeof (dst)); 342 sizeof(dst));
348 if (err < 0) 343 if (err < 0)
349 { 344 {
350#if VERBOSE 345#if VERBOSE
351 fprintf (stderr, 346 fprintf(stderr,
352 "sendto failed: %s\n", 347 "sendto failed: %s\n",
353 strerror (errno)); 348 strerror(errno));
354#endif 349#endif
355 } 350 }
356 else if (0 != err) 351 else if (0 != err)
357 { 352 {
358 fprintf (stderr, 353 fprintf(stderr,
359 "Error: partial send of ICMP message\n"); 354 "Error: partial send of ICMP message\n");
360 } 355 }
361} 356}
362 357
363 358
@@ -365,7 +360,7 @@ send_udp ()
365 * We've received an ICMP response. Process it. 360 * We've received an ICMP response. Process it.
366 */ 361 */
367static void 362static void
368process_icmp_response () 363process_icmp_response()
369{ 364{
370 char buf[65536]; 365 char buf[65536];
371 ssize_t have; 366 ssize_t have;
@@ -377,94 +372,96 @@ process_icmp_response ()
377 size_t off; 372 size_t off;
378 uint16_t port; 373 uint16_t port;
379 374
380 have = read (icmpsock, buf, sizeof (buf)); 375 have = read(icmpsock, buf, sizeof(buf));
381 if (-1 == have) 376 if (-1 == have)
382 { 377 {
383 fprintf (stderr, 378 fprintf(stderr,
384 "Error reading raw socket: %s\n", 379 "Error reading raw socket: %s\n",
385 strerror (errno)); 380 strerror(errno));
386 return; 381 return;
387 } 382 }
388#if VERBOSE 383#if VERBOSE
389 fprintf (stderr, 384 fprintf(stderr,
390 "Received message of %u bytes\n", 385 "Received message of %u bytes\n",
391 (unsigned int) have); 386 (unsigned int)have);
392#endif 387#endif
393 if (have < 388 if (have <
394 (ssize_t) (sizeof (struct ip_header) + 389 (ssize_t)(sizeof(struct ip_header) +
395 sizeof (struct icmp_ttl_exceeded_header) + 390 sizeof(struct icmp_ttl_exceeded_header) +
396 sizeof (struct ip_header))) 391 sizeof(struct ip_header)))
397 { 392 {
398 /* malformed */ 393 /* malformed */
399 return; 394 return;
400 } 395 }
401 off = 0; 396 off = 0;
402 GNUNET_memcpy (&ip_pkt, 397 GNUNET_memcpy(&ip_pkt,
403 &buf[off], 398 &buf[off],
404 sizeof (struct ip_header)); 399 sizeof(struct ip_header));
405 off += sizeof (struct ip_header); 400 off += sizeof(struct ip_header);
406 GNUNET_memcpy (&icmp_ttl, 401 GNUNET_memcpy(&icmp_ttl,
407 &buf[off], 402 &buf[off],
408 sizeof (struct icmp_ttl_exceeded_header)); 403 sizeof(struct icmp_ttl_exceeded_header));
409 off += sizeof (struct icmp_ttl_exceeded_header); 404 off += sizeof(struct icmp_ttl_exceeded_header);
410 if ((ICMP_TIME_EXCEEDED != icmp_ttl.type) || (0 != icmp_ttl.code)) 405 if ((ICMP_TIME_EXCEEDED != icmp_ttl.type) || (0 != icmp_ttl.code))
411 { 406 {
412 /* different type than what we want */ 407 /* different type than what we want */
413 return; 408 return;
414 } 409 }
415 /* grab source IP of 1st IP header */ 410 /* grab source IP of 1st IP header */
416 source_ip.s_addr = ip_pkt.src_ip; 411 source_ip.s_addr = ip_pkt.src_ip;
417 412
418 /* skip 2nd IP header */ 413 /* skip 2nd IP header */
419 GNUNET_memcpy (&ip_pkt, 414 GNUNET_memcpy(&ip_pkt,
420 &buf[off], 415 &buf[off],
421 sizeof (struct ip_header)); 416 sizeof(struct ip_header));
422 off += sizeof (struct ip_header); 417 off += sizeof(struct ip_header);
423 418
424 switch (ip_pkt.proto) 419 switch (ip_pkt.proto)
425 {
426 case IPPROTO_ICMP:
427 if (have !=
428 (sizeof (struct ip_header) * 2 +
429 sizeof (struct icmp_ttl_exceeded_header) +
430 sizeof (struct icmp_echo_header)))
431 { 420 {
432 /* malformed */ 421 case IPPROTO_ICMP:
433 return; 422 if (have !=
434 } 423 (sizeof(struct ip_header) * 2 +
435 /* grab ICMP ECHO content */ 424 sizeof(struct icmp_ttl_exceeded_header) +
436 GNUNET_memcpy (&icmp_echo, 425 sizeof(struct icmp_echo_header)))
437 &buf[off], 426 {
438 sizeof (struct icmp_echo_header)); 427 /* malformed */
439 port = (uint16_t) ntohl (icmp_echo.reserved); 428 return;
440 break; 429 }
441 case IPPROTO_UDP: 430 /* grab ICMP ECHO content */
442 if (have != 431 GNUNET_memcpy(&icmp_echo,
443 (sizeof (struct ip_header) * 2 + 432 &buf[off],
444 sizeof (struct icmp_ttl_exceeded_header) + sizeof (struct udp_header))) 433 sizeof(struct icmp_echo_header));
445 { 434 port = (uint16_t)ntohl(icmp_echo.reserved);
446 /* malformed */ 435 break;
436
437 case IPPROTO_UDP:
438 if (have !=
439 (sizeof(struct ip_header) * 2 +
440 sizeof(struct icmp_ttl_exceeded_header) + sizeof(struct udp_header)))
441 {
442 /* malformed */
443 return;
444 }
445 /* grab UDP content */
446 GNUNET_memcpy(&udp_pkt,
447 &buf[off],
448 sizeof(struct udp_header));
449 port = ntohs(udp_pkt.length);
450 break;
451
452 default:
453 /* different type than what we want */
447 return; 454 return;
448 } 455 }
449 /* grab UDP content */
450 GNUNET_memcpy (&udp_pkt,
451 &buf[off],
452 sizeof (struct udp_header));
453 port = ntohs (udp_pkt.length);
454 break;
455 default:
456 /* different type than what we want */
457 return;
458 }
459 456
460 if (port == 0) 457 if (port == 0)
461 fprintf (stdout, "%s\n", 458 fprintf(stdout, "%s\n",
462 inet_ntop (AF_INET, &source_ip, buf, sizeof (buf))); 459 inet_ntop(AF_INET, &source_ip, buf, sizeof(buf)));
463 else 460 else
464 fprintf (stdout, "%s:%u\n", 461 fprintf(stdout, "%s:%u\n",
465 inet_ntop (AF_INET, &source_ip, buf, sizeof (buf)), 462 inet_ntop(AF_INET, &source_ip, buf, sizeof(buf)),
466 (unsigned int) port); 463 (unsigned int)port);
467 fflush (stdout); 464 fflush(stdout);
468} 465}
469 466
470 467
@@ -474,34 +471,34 @@ process_icmp_response ()
474 * @return -1 on error, 0 on success 471 * @return -1 on error, 0 on success
475 */ 472 */
476static int 473static int
477setup_raw_socket () 474setup_raw_socket()
478{ 475{
479 const int one = 1; 476 const int one = 1;
480 477
481 if (-1 == 478 if (-1 ==
482 setsockopt (rawsock, 479 setsockopt(rawsock,
483 SOL_SOCKET, 480 SOL_SOCKET,
484 SO_BROADCAST, 481 SO_BROADCAST,
485 (char *) &one, 482 (char *)&one,
486 sizeof (one))) 483 sizeof(one)))
487 { 484 {
488 fprintf (stderr, 485 fprintf(stderr,
489 "setsockopt failed: %s\n", 486 "setsockopt failed: %s\n",
490 strerror (errno)); 487 strerror(errno));
491 return -1; 488 return -1;
492 } 489 }
493 if (-1 == 490 if (-1 ==
494 setsockopt (rawsock, 491 setsockopt(rawsock,
495 IPPROTO_IP, 492 IPPROTO_IP,
496 IP_HDRINCL, 493 IP_HDRINCL,
497 (char *) &one, 494 (char *)&one,
498 sizeof (one))) 495 sizeof(one)))
499 { 496 {
500 fprintf (stderr, 497 fprintf(stderr,
501 "setsockopt failed: %s\n", 498 "setsockopt failed: %s\n",
502 strerror (errno)); 499 strerror(errno));
503 return -1; 500 return -1;
504 } 501 }
505 return 0; 502 return 0;
506} 503}
507 504
@@ -513,45 +510,45 @@ setup_raw_socket ()
513 * @return -1 on error 510 * @return -1 on error
514 */ 511 */
515static int 512static int
516make_udp_socket (const struct in_addr *my_ip) 513make_udp_socket(const struct in_addr *my_ip)
517{ 514{
518 int ret; 515 int ret;
519 struct sockaddr_in addr; 516 struct sockaddr_in addr;
520 517
521 ret = socket (AF_INET, SOCK_DGRAM, 0); 518 ret = socket(AF_INET, SOCK_DGRAM, 0);
522 if (-1 == ret) 519 if (-1 == ret)
523 { 520 {
524 fprintf (stderr, 521 fprintf(stderr,
525 "Error opening UDP socket: %s\n", 522 "Error opening UDP socket: %s\n",
526 strerror (errno)); 523 strerror(errno));
527 return -1; 524 return -1;
528 } 525 }
529 memset (&addr, 0, sizeof (addr)); 526 memset(&addr, 0, sizeof(addr));
530 addr.sin_family = AF_INET; 527 addr.sin_family = AF_INET;
531#if HAVE_SOCKADDR_IN_SIN_LEN 528#if HAVE_SOCKADDR_IN_SIN_LEN
532 addr.sin_len = sizeof (struct sockaddr_in); 529 addr.sin_len = sizeof(struct sockaddr_in);
533#endif 530#endif
534 addr.sin_addr = *my_ip; 531 addr.sin_addr = *my_ip;
535 addr.sin_port = htons (NAT_TRAV_PORT); 532 addr.sin_port = htons(NAT_TRAV_PORT);
536 533
537 if (0 != bind (ret, 534 if (0 != bind(ret,
538 (struct sockaddr *) &addr, 535 (struct sockaddr *)&addr,
539 sizeof (addr))) 536 sizeof(addr)))
540 { 537 {
541 fprintf (stderr, 538 fprintf(stderr,
542 "Error binding UDP socket to port %u: %s\n", 539 "Error binding UDP socket to port %u: %s\n",
543 NAT_TRAV_PORT, 540 NAT_TRAV_PORT,
544 strerror (errno)); 541 strerror(errno));
545 (void) close (ret); 542 (void)close(ret);
546 return -1; 543 return -1;
547 } 544 }
548 return ret; 545 return ret;
549} 546}
550 547
551 548
552int 549int
553main (int argc, 550main(int argc,
554 char *const *argv) 551 char *const *argv)
555{ 552{
556 struct in_addr external; 553 struct in_addr external;
557 fd_set rs; 554 fd_set rs;
@@ -563,147 +560,147 @@ main (int argc,
563 int global_ret; 560 int global_ret;
564 561
565 /* Create an ICMP raw socket for reading (we'll check errors later) */ 562 /* Create an ICMP raw socket for reading (we'll check errors later) */
566 icmpsock = socket (AF_INET, 563 icmpsock = socket(AF_INET,
567 SOCK_RAW, 564 SOCK_RAW,
568 IPPROTO_ICMP); 565 IPPROTO_ICMP);
569 icmp_eno = errno; 566 icmp_eno = errno;
570 567
571 /* Create an (ICMP) raw socket for writing (we'll check errors later) */ 568 /* Create an (ICMP) raw socket for writing (we'll check errors later) */
572 rawsock = socket (AF_INET, 569 rawsock = socket(AF_INET,
573 SOCK_RAW, 570 SOCK_RAW,
574 IPPROTO_RAW); 571 IPPROTO_RAW);
575 raw_eno = errno; 572 raw_eno = errno;
576 udpsock = -1; 573 udpsock = -1;
577 574
578 /* drop root rights */ 575 /* drop root rights */
579 uid = getuid (); 576 uid = getuid();
580#ifdef HAVE_SETRESUID 577#ifdef HAVE_SETRESUID
581 if (0 != setresuid (uid, uid, uid)) 578 if (0 != setresuid(uid, uid, uid))
582 { 579 {
583 fprintf (stderr, 580 fprintf(stderr,
584 "Failed to setresuid: %s\n", 581 "Failed to setresuid: %s\n",
585 strerror (errno)); 582 strerror(errno));
586 global_ret = 1; 583 global_ret = 1;
587 goto error_exit; 584 goto error_exit;
588 } 585 }
589#else 586#else
590 if (0 != (setuid (uid) | seteuid (uid))) 587 if (0 != (setuid(uid) | seteuid(uid)))
591 { 588 {
592 fprintf (stderr, 589 fprintf(stderr,
593 "Failed to setuid: %s\n", 590 "Failed to setuid: %s\n",
594 strerror (errno)); 591 strerror(errno));
595 global_ret = 2; 592 global_ret = 2;
596 goto error_exit; 593 goto error_exit;
597 } 594 }
598#endif 595#endif
599 596
600 /* Now that we run without root rights, we can do error checking... */ 597 /* Now that we run without root rights, we can do error checking... */
601 if (2 != argc) 598 if (2 != argc)
602 { 599 {
603 fprintf (stderr, 600 fprintf(stderr,
604 "This program must be started with our (internal NAT) IP as the only argument.\n"); 601 "This program must be started with our (internal NAT) IP as the only argument.\n");
605 global_ret = 3; 602 global_ret = 3;
606 goto error_exit; 603 goto error_exit;
607 } 604 }
608 if (1 != inet_pton (AF_INET, argv[1], &external)) 605 if (1 != inet_pton(AF_INET, argv[1], &external))
609 { 606 {
610 fprintf (stderr, 607 fprintf(stderr,
611 "Error parsing IPv4 address: %s\n", 608 "Error parsing IPv4 address: %s\n",
612 strerror (errno)); 609 strerror(errno));
613 global_ret = 4; 610 global_ret = 4;
614 goto error_exit; 611 goto error_exit;
615 } 612 }
616 if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) 613 if (1 != inet_pton(AF_INET, DUMMY_IP, &dummy))
617 { 614 {
618 fprintf (stderr, 615 fprintf(stderr,
619 "Internal error converting dummy IP to binary.\n"); 616 "Internal error converting dummy IP to binary.\n");
620 global_ret = 5; 617 global_ret = 5;
621 goto error_exit; 618 goto error_exit;
622 } 619 }
623 620
624 /* error checking icmpsock */ 621 /* error checking icmpsock */
625 if (-1 == icmpsock) 622 if (-1 == icmpsock)
626 { 623 {
627 fprintf (stderr, 624 fprintf(stderr,
628 "Error opening RAW socket: %s\n", 625 "Error opening RAW socket: %s\n",
629 strerror (icmp_eno)); 626 strerror(icmp_eno));
630 global_ret = 6; 627 global_ret = 6;
631 goto error_exit; 628 goto error_exit;
632 } 629 }
633 if (icmpsock >= FD_SETSIZE) 630 if (icmpsock >= FD_SETSIZE)
634 { 631 {
635 /* this could happen if we were started with a large number of already-open 632 /* this could happen if we were started with a large number of already-open
636 file descriptors... */ 633 file descriptors... */
637 fprintf (stderr, 634 fprintf(stderr,
638 "Socket number too large (%d > %u)\n", 635 "Socket number too large (%d > %u)\n",
639 icmpsock, 636 icmpsock,
640 (unsigned int) FD_SETSIZE); 637 (unsigned int)FD_SETSIZE);
641 global_ret = 7; 638 global_ret = 7;
642 goto error_exit; 639 goto error_exit;
643 } 640 }
644 641
645 /* error checking rawsock */ 642 /* error checking rawsock */
646 if (-1 == rawsock) 643 if (-1 == rawsock)
647 { 644 {
648 fprintf (stderr, 645 fprintf(stderr,
649 "Error opening RAW socket: %s\n", 646 "Error opening RAW socket: %s\n",
650 strerror (raw_eno)); 647 strerror(raw_eno));
651 global_ret = 8; 648 global_ret = 8;
652 goto error_exit; 649 goto error_exit;
653 } 650 }
654 /* no need to check 'rawsock' against FD_SETSIZE as it is never used 651 /* no need to check 'rawsock' against FD_SETSIZE as it is never used
655 with 'select' */ 652 with 'select' */
656 653
657 if (0 != setup_raw_socket ()) 654 if (0 != setup_raw_socket())
658 { 655 {
659 global_ret = 9; 656 global_ret = 9;
660 goto error_exit; 657 goto error_exit;
661 } 658 }
662 659
663 if (-1 == (udpsock = make_udp_socket (&external))) 660 if (-1 == (udpsock = make_udp_socket(&external)))
664 { 661 {
665 global_ret = 10; 662 global_ret = 10;
666 goto error_exit; 663 goto error_exit;
667 } 664 }
668 665
669 alt = 0; 666 alt = 0;
670 while (1) 667 while (1)
671 {
672 FD_ZERO (&rs);
673 FD_SET (icmpsock, &rs);
674 tv.tv_sec = 0;
675 tv.tv_usec = ICMP_SEND_FREQUENCY_MS * 1000;
676 if (-1 == select (icmpsock + 1, &rs, NULL, NULL, &tv))
677 {
678 if (errno == EINTR)
679 continue;
680 fprintf (stderr,
681 "select failed: %s\n",
682 strerror (errno));
683 break;
684 }
685 if (1 == getppid ()) /* Check the parent process id, if 1 the parent has died, so we should die too */
686 break;
687 if (FD_ISSET (icmpsock, &rs))
688 { 668 {
689 process_icmp_response (); 669 FD_ZERO(&rs);
690 continue; 670 FD_SET(icmpsock, &rs);
671 tv.tv_sec = 0;
672 tv.tv_usec = ICMP_SEND_FREQUENCY_MS * 1000;
673 if (-1 == select(icmpsock + 1, &rs, NULL, NULL, &tv))
674 {
675 if (errno == EINTR)
676 continue;
677 fprintf(stderr,
678 "select failed: %s\n",
679 strerror(errno));
680 break;
681 }
682 if (1 == getppid()) /* Check the parent process id, if 1 the parent has died, so we should die too */
683 break;
684 if (FD_ISSET(icmpsock, &rs))
685 {
686 process_icmp_response();
687 continue;
688 }
689 if (0 == (++alt % 2))
690 send_icmp_echo(&external);
691 else
692 send_udp();
691 } 693 }
692 if (0 == (++alt % 2))
693 send_icmp_echo (&external);
694 else
695 send_udp ();
696 }
697 694
698 /* select failed (internal error or OS out of resources) */ 695 /* select failed (internal error or OS out of resources) */
699 global_ret = 11; 696 global_ret = 11;
700error_exit: 697error_exit:
701 if (-1 != icmpsock) 698 if (-1 != icmpsock)
702 (void) close (icmpsock); 699 (void)close(icmpsock);
703 if (-1 != rawsock) 700 if (-1 != rawsock)
704 (void) close (rawsock); 701 (void)close(rawsock);
705 if (-1 != udpsock) 702 if (-1 != udpsock)
706 (void) close (udpsock); 703 (void)close(udpsock);
707 return global_ret; 704 return global_ret;
708} 705}
709 706