From: Nathan S. Evans Date: Tue, 8 Jun 2010 13:27:11 +0000 (+0000) Subject: add UDP inside ICMP for NAT punch X-Git-Tag: initial-import-from-subversion-38251~21452 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=87f73e3aee4a5f582ffb71e925f1f1d4f30e26d2;p=oweals%2Fgnunet.git add UDP inside ICMP for NAT punch --- diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index f42202c45..da925bc0d 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -53,7 +53,6 @@ gnunet_nat_server_SOURCES = \ gnunet_nat_client_SOURCES = \ gnunet-nat-client.c - gnunet_transport_SOURCES = \ gnunet-transport.c gnunet_transport_LDADD = \ diff --git a/src/transport/gnunet-nat-client-udp.c b/src/transport/gnunet-nat-client-udp.c index f594db20a..0e925dc5d 100644 --- a/src/transport/gnunet-nat-client-udp.c +++ b/src/transport/gnunet-nat-client-udp.c @@ -20,9 +20,27 @@ /** * @file src/transport/gnunet-nat-client-udp.c - * @brief Test for NAT traversal using ICMP method. + * @brief Tool to help bypass NATs using ICMP method; must run as root (SUID will do) + * This code will work under GNU/Linux only. * @author Christian Grothoff + * + * This program will send ONE ICMP message using RAW sockets + * to the IP address specified as the second argument. The ICMP + * message will have as it's payload a UDP packet. Since + * it uses RAW sockets, it must be installed SUID or run as 'root'. + * In order to keep the security risk of the resulting SUID binary + * minimal, the program ONLY opens the RAW socket with root + * privileges, then drops them and only then starts to process + * command line arguments. The code also does not link against + * any shared libraries (except libc) and is strictly minimal + * (except for checking for errors). The following list of people + * have reviewed this code and considered it safe since the last + * modification (if you reviewed it, please have your name added + * to the list): + * + * - Christian Grothoff */ +#define _GNU_SOURCE #include #include #include @@ -33,143 +51,312 @@ #include #include #include +#include +#include #include -#include /** - * How often do we send our UDP messages to keep ports open (and to - * try to connect, of course). Use small value since we are the - * initiator and should hence be rather aggressive. + * Must match IP given in the server. */ -#define UDP_SEND_FREQUENCY_MS 5 +#define DUMMY_IP "1.2.3.4" +#define HAVE_PORT 1 /** * Port we always try to use. */ -#define NAT_TRAV_PORT 22223 +#define NAT_TRAV_PORT 22225 -/** - * Number of UDP ports to keep open at the same time (typically >= 256). - * Should be less than FD_SETSIZE. - */ -#define NUM_UDP_PORTS 1000 +struct ip_packet +{ + uint8_t vers_ihl; + uint8_t tos; + uint16_t pkt_len; + uint16_t id; + uint16_t flags_frag_offset; + uint8_t ttl; + uint8_t proto; + uint16_t checksum; + uint32_t src_ip; + uint32_t dst_ip; +}; -/** - * How often do we retry to open and bind a UDP socket before giving up? - */ -#define MAX_BIND_TRIES 10 +struct icmp_packet +{ + uint8_t type; + uint8_t code; + uint16_t checksum; + uint32_t reserved; -/** - * How often do we try at most? We expect to need (for the worst kind - * of NAT) on average 64512 / 512 = 126 attempts to have the right - * destination port and we then need to also (in the worst case) have - * the right source port (so 126 * 64512 = 8128512 packets on - * average!). That's obviously a bit much, so we give up earlier. The - * given value corresponds to about 1 minute of runtime (for a send - * frequency of one packet per ms). - * - * NOW: if the *server* would listen for Linux-generated ICMP - * "Destination unreachables" we *might* increase our chances since - * maybe the firewall has some older/other UDP rules (this was - * the case during testing for me), but obviously that would mean - * more SUID'ed code. Yuck. - */ -#define MAX_TRIES 62500 +}; -#define LOW_PORT 32768 +struct icmp_echo_packet +{ + uint8_t type; + uint8_t code; + uint16_t checksum; + uint32_t reserved; + uint32_t data; +}; + +struct udp_packet +{ + uint16_t src_port; + + uint16_t dst_port; + + uint32_t length; +}; + + +static int rawsock; + +static struct in_addr dummy; + +static struct in_addr target; + +#if HAVE_PORT + static uint32_t port; +#endif -/** - * create a random port number that is not totally - * unlikely to be chosen by the nat box. - */ static uint16_t -make_port () +calc_checksum(const uint16_t *data, + unsigned int bytes) { - return LOW_PORT + ( (unsigned int)rand ()) % (64 * 1024 - LOW_PORT); -} + uint32_t sum; + unsigned int i; + sum = 0; + for (i=0;i> 16); + sum = htons(0xffff - sum); + return sum; +} /** - * create a fresh udp socket bound to a random local port, - * or, if the argument is zero, to the NAT_TRAV_PORT. + * Send an ICMP message to the target. * - * @param i counter - * @return -1 on error + * @param my_ip source address + * @param other target address */ -static int -make_udp_socket (int i) +static void +send_icmp (const struct in_addr *my_ip, + const struct in_addr *other) { - int ret; - int tries; - struct sockaddr_in src; + struct ip_packet ip_pkt; + struct icmp_packet icmp_pkt; + struct udp_packet udp_pkt; + + struct sockaddr_in dst; + char packet[sizeof(ip_pkt) * 2 + sizeof(icmp_pkt) * 2 + sizeof(char)]; + +#if ORIGINAL +#if HAVE_PORT + char packet[sizeof (struct ip_packet)*2 + sizeof (struct icmp_packet) + sizeof(struct icmp_echo_packet)]; +#else + char packet[sizeof (struct ip_packet)*2 + sizeof (struct icmp_packet)*2]; +#endif +#endif + size_t off; + int err; + + /* ip header: send to (known) ip address */ +#if ORIGINAL + off = 0; + memset(&ip_pkt, 0, sizeof(ip_pkt)); + ip_pkt.vers_ihl = 0x45; + ip_pkt.tos = 0; + ip_pkt.pkt_len = sizeof (packet); /* huh? */ + ip_pkt.id = 1; + ip_pkt.flags_frag_offset = 0; + ip_pkt.ttl = IPDEFTTL; + ip_pkt.proto = IPPROTO_ICMP; + ip_pkt.checksum = 0; + ip_pkt.src_ip = my_ip->s_addr; + ip_pkt.dst_ip = other->s_addr; + ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, sizeof (struct ip_packet))); + memcpy (packet, &ip_pkt, sizeof (struct ip_packet)); + off += sizeof (ip_pkt); + /* icmp reply: time exceeded */ + icmp_pkt = (struct icmp_packet*) &packet[off]; + memset(icmp_pkt, 0, sizeof(struct icmp_packet)); + icmp_pkt->type = ICMP_TIME_EXCEEDED; + icmp_pkt->code = 0; + icmp_pkt->reserved = 0; + icmp_pkt->checksum = 0; + + off += sizeof (struct icmp_packet); +#endif + + off = 0; + memset(&ip_pkt, 0, sizeof(ip_pkt)); + ip_pkt.vers_ihl = 0x45; + ip_pkt.tos = 0; + ip_pkt.pkt_len = htons(sizeof (packet)); + ip_pkt.id = htons(256); + ip_pkt.flags_frag_offset = 0; + ip_pkt.ttl = 128; + ip_pkt.proto = IPPROTO_ICMP; + ip_pkt.checksum = 0; + ip_pkt.src_ip = my_ip->s_addr; + ip_pkt.dst_ip = other->s_addr; + ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, sizeof (ip_pkt))); + memcpy(&packet[off], &ip_pkt, sizeof(ip_pkt)); + off += sizeof(ip_pkt); + + /* ip header of the presumably 'lost' udp packet */ + ip_pkt.vers_ihl = 0x45; + ip_pkt.tos = 0; +#if HAVE_PORT + ip_pkt.pkt_len = (sizeof (struct ip_packet) + sizeof (struct icmp_echo_packet)); +#else + ip_pkt.pkt_len = (sizeof (struct ip_packet) + sizeof (struct icmp_packet)); +#endif + + icmp_pkt.type = 11; // TTL exceeded + icmp_pkt.code = 0; + icmp_pkt.checksum = 0; + icmp_pkt.reserved = 0; + memcpy(&packet[off], &icmp_pkt, sizeof(icmp_pkt)); + off += sizeof(icmp_pkt); + + + // build inner IP header + memset(&ip_pkt, 0, sizeof(ip_pkt)); + ip_pkt.vers_ihl = 0x45; + ip_pkt.tos = 0; + ip_pkt.pkt_len = htons(sizeof (ip_pkt) + sizeof(udp_pkt)); + ip_pkt.id = htons(0); + ip_pkt.flags_frag_offset = 0; + ip_pkt.ttl = 128; + ip_pkt.proto = IPPROTO_UDP; + ip_pkt.checksum = 0; + ip_pkt.src_ip = other->s_addr; + ip_pkt.dst_ip = dummy.s_addr; + ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, sizeof (ip_pkt))); + memcpy(&packet[off], &ip_pkt, sizeof(ip_pkt)); + off += sizeof(ip_pkt); + + // build UDP header + udp_pkt.src_port = htons(NAT_TRAV_PORT); /* FIXME: does this port matter? */ + udp_pkt.dst_port = htons(NAT_TRAV_PORT); + uint32_t newval = inet_addr("1.2.3.4"); + memcpy(&udp_pkt.length, &newval, sizeof(uint32_t)); + memcpy(&packet[off], &udp_pkt, sizeof(udp_pkt)); + off += sizeof(udp_pkt); - for (tries=0;triess_addr; + ip_pkt.dst_ip = dummy.s_addr; + ip_pkt.checksum = 0; + ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, sizeof (struct ip_packet))); + memcpy (&packet[off], &ip_pkt, sizeof (struct ip_packet)); + off += sizeof (struct ip_packet); + + +#if HAVE_PORT + icmp_pkt->checksum = htons(calc_checksum((uint16_t*)icmp_pkt, + sizeof (struct icmp_packet) + sizeof(struct ip_packet) + sizeof(struct icmp_echo_packet))); + +#else + icmp_pkt->checksum = htons(calc_checksum((uint16_t*)icmp_pkt, + sizeof (struct icmp_packet)*2 + sizeof(struct ip_packet))); + +#endif + + +#endif + + memset (&dst, 0, sizeof (dst)); + dst.sin_family = AF_INET; + dst.sin_addr = *other; + err = sendto(rawsock, + packet, + off, 0, + (struct sockaddr*)&dst, + sizeof(dst)); /* or sizeof 'struct sockaddr'? */ + if (err < 0) { - ret = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (-1 == ret) - { - fprintf (stderr, - "Error opening udp socket: %s\n", - strerror (errno)); - return -1; - } - if (ret >= FD_SETSIZE) - { - fprintf (stderr, - "Socket number too large (%d > %u)\n", - ret, - (unsigned int) FD_SETSIZE); - close (ret); - return -1; - } - memset (&src, 0, sizeof (src)); - src.sin_family = AF_INET; - if (i == 0) - src.sin_port = htons (NAT_TRAV_PORT); - else - src.sin_port = htons (make_port ()); - if (0 != bind (ret, (struct sockaddr*) &src, sizeof (src))) - { - close (ret); - continue; - } - return ret; + fprintf(stderr, + "sendto failed: %s\n", strerror(errno)); + } + else if (err != off) + { + fprintf(stderr, + "Error: partial send of ICMP message\n"); } - fprintf (stderr, - "Error binding udp socket: %s\n", - strerror (errno)); - return -1; } +static int +make_raw_socket () +{ + const int one = 1; + int ret; + + ret = socket (AF_INET, SOCK_RAW, IPPROTO_RAW); + if (-1 == ret) + { + fprintf (stderr, + "Error opening RAW socket: %s\n", + strerror (errno)); + return -1; + } + if (setsockopt(ret, SOL_SOCKET, SO_BROADCAST, + (char *)&one, sizeof(one)) == -1) + fprintf(stderr, + "setsockopt failed: %s\n", + strerror (errno)); + if (setsockopt(ret, IPPROTO_IP, IP_HDRINCL, + (char *)&one, sizeof(one)) == -1) + fprintf(stderr, + "setsockopt failed: %s\n", + strerror (errno)); + return ret; +} int main (int argc, char *const *argv) { - int udpsocks[NUM_UDP_PORTS]; - char command[512]; struct in_addr external; - struct in_addr target; - int ret; - unsigned int pos; - int i; - int max; - struct sockaddr_in dst; - struct sockaddr_in src; - int first_round = 1; - char dummybuf[65536]; - unsigned int tries; - struct timeval tv; - socklen_t slen; - fd_set rs; - + uid_t uid; + + if (-1 == (rawsock = make_raw_socket())) + return 1; + uid = getuid (); + if (0 != setresuid (uid, uid, uid)) + fprintf (stderr, + "Failed to setresuid: %s\n", + strerror (errno)); +#if HAVE_PORT + if (argc != 4) + { + fprintf (stderr, + "This program must be started with our IP, the targets external IP, and our port as arguments.\n"); + return 1; + } + port = atoi(argv[3]); +#else if (argc != 3) { fprintf (stderr, - "This program must be started with our IP and the targets external IP as arguments.\n"); + "This program must be started with our IP and the targets external IP as arguments.\n"); return 1; } +#endif if ( (1 != inet_pton (AF_INET, argv[1], &external)) || (1 != inet_pton (AF_INET, argv[2], &target)) ) { @@ -178,121 +365,11 @@ main (int argc, char *const *argv) strerror (errno)); return 1; } - snprintf (command, - sizeof (command), - "gnunet-nat-client %s %s", - argv[1], - argv[2]); - if (0 != (ret = system (command))) - { - if (ret == -1) - fprintf (stderr, - "Error running `%s': %s\n", - command, - strerror (errno)); - return 1; - } - fprintf (stderr, - "Trying to connect to `%s'\n", - argv[2]); - srand (time(NULL)); - for (i=0;i tries++) - { - FD_ZERO (&rs); - for (i=0;i max) - max = udpsocks[i]; - } - tv.tv_sec = 0; - tv.tv_usec = UDP_SEND_FREQUENCY_MS * 1000; - select (max + 1, &rs, NULL, NULL, &tv); - for (i=0;is_addr; + ip_pkt.dst_ip = other->s_addr; + ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, sizeof (ip_pkt))); + memcpy(&packet[off], &ip_pkt, sizeof(ip_pkt)); + off += sizeof(ip_pkt); + + /* ip header of the presumably 'lost' udp packet */ + ip_pkt.vers_ihl = 0x45; + ip_pkt.tos = 0; + ip_pkt.pkt_len = (sizeof (struct ip_packet) + sizeof (struct icmp_echo_packet)); + + icmp_pkt.type = 11; /* TTL exceeded */ + icmp_pkt.code = 0; + icmp_pkt.checksum = 0; + icmp_pkt.reserved = 0; + memcpy(&packet[off], &icmp_pkt, sizeof(icmp_pkt)); + off += sizeof(icmp_pkt); + + /* build inner IP header */ + memset(&ip_pkt, 0, sizeof(ip_pkt)); + ip_pkt.vers_ihl = 0x45; + ip_pkt.tos = 0; + ip_pkt.pkt_len = htons(sizeof (ip_pkt) + sizeof(udp_pkt)); + ip_pkt.id = htons(0); + ip_pkt.flags_frag_offset = 0; + ip_pkt.ttl = 128; + ip_pkt.proto = IPPROTO_UDP; + ip_pkt.checksum = 0; + ip_pkt.src_ip = other->s_addr; + ip_pkt.dst_ip = dummy.s_addr; + ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, sizeof (ip_pkt))); + memcpy(&packet[off], &ip_pkt, sizeof(ip_pkt)); + off += sizeof(ip_pkt); + + /* build UDP header */ + udp_pkt.src_port = htons(NAT_TRAV_PORT); /* FIXME: does this port matter? */ + udp_pkt.dst_port = htons(NAT_TRAV_PORT); + + memset(&udp_pkt.length, 0, sizeof(uint32_t)); +#if HAVE_PORT + udp_pkt.length = htonl(port); +#endif + memcpy(&packet[off], &udp_pkt, sizeof(udp_pkt)); + off += sizeof(udp_pkt); + + /* set ICMP checksum */ + icmp_pkt.checksum = htons(calc_checksum((uint16_t*)&packet[sizeof(ip_pkt)], + sizeof (icmp_pkt) + sizeof(ip_pkt) + sizeof(udp_pkt))); + memcpy (&packet[sizeof(ip_pkt)], &icmp_pkt, sizeof (icmp_pkt)); + + + memset (&dst, 0, sizeof (dst)); + dst.sin_family = AF_INET; + dst.sin_addr = *other; + err = sendto(rawsock, + packet, + off, 0, + (struct sockaddr*)&dst, + sizeof(dst)); + + if (err < 0) + { + fprintf(stderr, + "sendto failed: %s\n", strerror(errno)); + } + else if (err != off) + { + fprintf(stderr, + "Error: partial send of ICMP message\n"); + } +} + /** * Send an ICMP message to the target. @@ -334,6 +447,8 @@ main (int argc, char *const *argv) if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) abort (); send_icmp (&external, &target); + send_icmp_udp (&external, + &target); close (rawsock); return 0; } diff --git a/src/transport/gnunet-nat-server-udp.c b/src/transport/gnunet-nat-server-udp.c index b1d221294..02ff65031 100644 --- a/src/transport/gnunet-nat-server-udp.c +++ b/src/transport/gnunet-nat-server-udp.c @@ -20,7 +20,9 @@ /** * @file src/transport/gnunet-nat-server-udp.c - * @brief Test for NAT traversal using ICMP method. + * @brief This program will send ONE UDP message every 500 ms + * to a DUMMY IP address and also listens for ICMP replies. + * * @author Christian Grothoff */ #include @@ -37,16 +39,13 @@ #include +#define DUMMY_IP "1.2.3.4" /** - * How often do we send our UDP messages to keep ports open (and to - * try to connect, of course). Assuming the NAT closes UDP ports - * after 60s, we need at least about 100ms here for 512 ports; - * however, we should open the ports quickly (and we don't yet - * differentiate between the first round and later rounds), so we pick - * a much lower value here for now. + * How often do we send our UDP message to keep ports open (and to + * try to connect, of course). */ -#define UDP_SEND_FREQUENCY_MS 50 +#define UDP_SEND_FREQUENCY_MS 500 /** * Port we always try to use. @@ -54,50 +53,83 @@ #define NAT_TRAV_PORT 22225 /** - * Number of UDP ports to keep open at the same time (typically >= 256). - * Should be less than FD_SETSIZE. + * Number of UDP ports to send to */ -#define NUM_UDP_PORTS 1000 +#define NUM_UDP_PORTS 1 /** * How often do we retry to open and bind a UDP socket before giving up? */ #define MAX_BIND_TRIES 10 -/** - * How long do we try at most? We expect the other side to give - * up after about one minute for now. - */ -#define MAX_DURATION 60000 - #define LOW_PORT 32768 -/** - * create a random port number that is not totally - * unlikely to be chosen by the nat box. - */ -static uint16_t -make_port () +static struct in_addr dummy; + +static int icmpsock; + +struct icmp_packet { - return LOW_PORT + ( (unsigned int)rand ()) % (64 * 1024 - LOW_PORT - 2); -} + uint8_t type; + uint8_t code; + uint16_t checksum; + uint32_t reserved; +}; + +struct udp_packet +{ + uint16_t src_port; + + uint16_t dst_port; + + uint32_t length; +}; + +struct ip_packet +{ + uint8_t vers_ihl; + uint8_t tos; + uint16_t pkt_len; + uint16_t id; + uint16_t flags_frag_offset; + uint8_t ttl; + uint8_t proto; + uint16_t checksum; + uint32_t src_ip; + uint32_t dst_ip; +}; + +#if DUMMY +static uint16_t +calc_checksum(const uint16_t *data, + unsigned int bytes) +{ + uint32_t sum; + unsigned int i; + + sum = 0; + for (i=0;i> 16); + sum = htons(0xffff - sum); + return sum; +} +#endif /** - * create a fresh udp socket bound to a random local port, - * or, if the argument is zero, to the NAT_TRAV_PORT. + * create a fresh udp socket bound to the NAT_TRAV_PORT. * - * @param i counter * @return -1 on error */ static int -make_udp_socket (int i) +make_udp_socket () { int ret; int tries; struct sockaddr_in src; - for (tries=0;tries= FD_SETSIZE) + { + fprintf (stderr, + "Socket number too large (%d > %u)\n", + ret, + (unsigned int) FD_SETSIZE); + close (ret); + return -1; + } + return ret; +} + +#if DUMMY +/** + * Send a UDP message to the dummy IP. + * + * @param my_ip source address (our ip address) + */ +static void +send_dummy_udp (const struct in_addr *my_ip) +{ + struct sockaddr_in dst; + size_t off; + int err; + struct ip_packet ip_pkt; + struct ip_packet udp_pkt; + char packet[sizeof (ip_pkt) + sizeof (udp_pkt)]; + + + // build inner IP header + memset(&ip_pkt, 0, sizeof(ip_pkt)); + ip_pkt.vers_ihl = 0x45; + ip_pkt.tos = 0; + ip_pkt.pkt_len = htons(sizeof (ip_pkt) + sizeof(udp_pkt)); + ip_pkt.id = htons(0); + ip_pkt.flags_frag_offset = 0; + ip_pkt.ttl = 128; + ip_pkt.proto = IPPROTO_UDP; + ip_pkt.checksum = 0; + ip_pkt.src_ip = my_ip->s_addr; + ip_pkt.dst_ip = inet_addr(dummy.s_addr); + ip_pkt.checksum = htons(calc_checksum((uint16_t*)&ip_pkt, sizeof (ip_pkt))); + memcpy(&packet[off], &ip_pkt, sizeof(ip_pkt)); + off += sizeof(ip_pkt); + + // build UDP header + udp_pkt.src_port = NAT_TRAV_PORT; + udp_pkt.dst_port = htons(NAT_TRAV_PORT); + + uint32_t newval = inet_addr("1.2.3.4"); + memcpy(&udp_pkt.length, &newval, sizeof(uint32_t)); + + off += sizeof(udp_pkt); + + err = sendto(rawsock, + ip_pkt, off, 0, + (struct sockaddr*)&dst, + sizeof(dst)); + if (err < 0) + { +#if VERBOSE + fprintf(stderr, + "sendto failed: %s\n", strerror(errno)); +#endif + } + else if (err != off) + { + fprintf(stderr, + "Error: partial send of UDP message\n"); + } +} +#endif + +static void +process_icmp_response() +{ + char buf[65536]; + ssize_t have; + struct in_addr sip; + struct ip_packet ip_pkt; + struct icmp_packet icmp_pkt; + size_t off; + int have_port; + //uint32_t port; + + have = read (icmpsock, buf, sizeof (buf)); + if (have == -1) + { + fprintf (stderr, + "Error reading raw socket: %s\n", + strerror (errno)); + return; + } + + off = 0; + memcpy (&ip_pkt, &buf[off], sizeof (ip_pkt)); + off += sizeof (ip_pkt); + memcpy (&icmp_pkt, &buf[off], sizeof (icmp_pkt)); + off += sizeof (icmp_pkt); + if ( (ip_pkt.proto != IPPROTO_ICMP) || + (icmp_pkt.type != 11) || + (icmp_pkt.code != 0) ) + { + /* maybe we got an actual reply back... */ + return; + } + + memcpy(&sip, + &ip_pkt.src_ip, + sizeof (sip)); + + fprintf (stderr, + "Received ICMP message of size: %u bytes from %s\n", + (unsigned int) have, + inet_ntop (AF_INET, + &sip, + buf, + sizeof (buf))); + + have_port = 0; + if (have == sizeof (struct ip_packet) *2 + sizeof (struct icmp_packet) * 2 + sizeof(uint32_t)) + { + have_port = 1; + } + else if (have != sizeof (struct ip_packet) *2 + sizeof (struct icmp_packet) * 2) + { +#if VERBOSE + fprintf (stderr, + "Received ICMP message of unexpected size: %u bytes\n", + (unsigned int) have); +#endif + return; + } +} int main (int argc, char *const *argv) { int udpsocks[NUM_UDP_PORTS]; - char command[512]; struct in_addr external; - struct in_addr target; - int ret; unsigned int pos; int i; - int max; struct sockaddr_in dst; - struct sockaddr_in src; int first_round = 1; - char dummybuf[65536]; unsigned int tries; struct timeval tv; - socklen_t slen; fd_set rs; time_t stime; - if (argc != 3) + if (argc != 2) { fprintf (stderr, - "This program must be started with our IP and the targets external IP as arguments.\n"); + "This program must be started with our (internal) IP as the single argument.\n"); return 1; } - if ( (1 != inet_pton (AF_INET, argv[1], &external)) || - (1 != inet_pton (AF_INET, argv[2], &target)) ) + if ( (1 != inet_pton (AF_INET, argv[1], &external))) { fprintf (stderr, "Error parsing IPv4 address: %s\n", strerror (errno)); return 1; } + + if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy)) abort (); + fprintf (stderr, "Trying to connect to %s\n", - argv[2]); + DUMMY_IP); srand (stime = time(NULL)); for (i=0;i= time (NULL)) + + while (1) { tries++; + FD_ZERO (&rs); - for (i=0;i max) - max = udpsocks[i]; - } + FD_SET (icmpsock, &rs); tv.tv_sec = 0; tv.tv_usec = UDP_SEND_FREQUENCY_MS * 1000; - select (max + 1, &rs, NULL, NULL, &tv); - for (i=0;i