GNUnet  0.10.x
Data Structures | Macros | Functions | Variables
gnunet-helper-nat-server-windows.c File Reference

Windows tool to help bypass NATs using ICMP method This code will work under W32 only. More...

#include <winsock2.h>
#include <ws2tcpip.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
Include dependency graph for gnunet-helper-nat-server-windows.c:

Go to the source code of this file.

Data Structures

struct  ip_header
 IPv4 header. More...
 
struct  icmp_ttl_exceeded_header
 Format of ICMP packet. More...
 
struct  icmp_echo_header
 
struct  udp_header
 Beginning of UDP packet. More...
 

Macros

#define _GNU_SOURCE
 
#define GNUNET_memcpy(dst, src, n)   do { if (0 != n) { (void) memcpy (dst,src,n); } } while (0)
 
#define FD_SETSIZE   1024
 
#define VERBOSE   0
 Should we print some debug output? More...
 
#define DUMMY_IP   "192.0.2.86"
 Must match IP given in the client. More...
 
#define NAT_TRAV_PORT   22225
 Default Port. More...
 
#define PACKET_ID   256
 Must match packet ID used by gnunet-helper-nat-client.c. More...
 
#define IPDEFTTL   64
 TTL to use for our outgoing messages. More...
 
#define ICMP_ECHO   8
 
#define ICMP_TIME_EXCEEDED   11
 
#define ICMP_SEND_FREQUENCY_MS   500
 How often do we send our ICMP messages to receive replies? More...
 

Functions

static uint16_t calc_checksum (const uint16_t *data, unsigned int bytes)
 CRC-16 for IP/ICMP headers. More...
 
static int inet_pton (int af, const char *cp, struct in_addr *buf)
 Convert IPv4 address from text to binary form. More...
 
static void send_icmp_echo (const struct in_addr *my_ip)
 Send an ICMP message to the dummy IP. More...
 
static void send_udp ()
 Send a UDP message to the dummy IP. More...
 
static void process_icmp_response ()
 We've received an ICMP response. More...
 
static SOCKET make_icmp_socket ()
 Create an ICMP raw socket for reading. More...
 
static SOCKET make_raw_socket ()
 Create an ICMP raw socket for writing. More...
 
static SOCKET make_udp_socket (const struct in_addr *my_ip)
 Create a UDP socket for writing. More...
 
int main (int argc, char *const *argv)
 

Variables

static boolean privilege_testing = FALSE
 Will this binary be run in permissions testing mode? More...
 
static SOCKET icmpsock
 Socket we use to receive "fake" ICMP replies. More...
 
static SOCKET rawsock
 Socket we use to send our ICMP requests. More...
 
static SOCKET udpsock
 Socket we use to send our UDP requests. More...
 
static struct in_addr dummy
 Target "dummy" address. More...
 

Detailed Description

Windows tool to help bypass NATs using ICMP method This code will work under W32 only.

Author
Christian Grothoff

This program will send ONE ICMP message every 500 ms RAW sockets to a DUMMY IP address and also listens for ICMP replies. Since it uses RAW sockets, it must be run as an administrative user. In order to keep the security risk of the resulting binary minimal, the program ONLY opens the two RAW sockets with administrative 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):

Definition in file gnunet-helper-nat-server-windows.c.

Macro Definition Documentation

◆ _GNU_SOURCE

#define _GNU_SOURCE

Definition at line 43 of file gnunet-helper-nat-server-windows.c.

◆ GNUNET_memcpy

#define GNUNET_memcpy (   dst,
  src,
 
)    do { if (0 != n) { (void) memcpy (dst,src,n); } } while (0)

Definition at line 45 of file gnunet-helper-nat-server-windows.c.

Referenced by process_icmp_response(), and send_icmp_echo().

◆ FD_SETSIZE

#define FD_SETSIZE   1024

Definition at line 47 of file gnunet-helper-nat-server-windows.c.

◆ VERBOSE

#define VERBOSE   0

Should we print some debug output?

Definition at line 63 of file gnunet-helper-nat-server-windows.c.

◆ DUMMY_IP

#define DUMMY_IP   "192.0.2.86"

Must match IP given in the client.

Definition at line 68 of file gnunet-helper-nat-server-windows.c.

Referenced by main().

◆ NAT_TRAV_PORT

#define NAT_TRAV_PORT   22225

Default Port.

Definition at line 73 of file gnunet-helper-nat-server-windows.c.

Referenced by make_udp_socket(), and send_udp().

◆ PACKET_ID

#define PACKET_ID   256

Must match packet ID used by gnunet-helper-nat-client.c.

Definition at line 78 of file gnunet-helper-nat-server-windows.c.

Referenced by send_icmp_echo().

◆ IPDEFTTL

#define IPDEFTTL   64

TTL to use for our outgoing messages.

Definition at line 83 of file gnunet-helper-nat-server-windows.c.

Referenced by send_icmp_echo().

◆ ICMP_ECHO

#define ICMP_ECHO   8

Definition at line 85 of file gnunet-helper-nat-server-windows.c.

Referenced by send_icmp_echo().

◆ ICMP_TIME_EXCEEDED

#define ICMP_TIME_EXCEEDED   11

Definition at line 87 of file gnunet-helper-nat-server-windows.c.

Referenced by process_icmp_response().

◆ ICMP_SEND_FREQUENCY_MS

#define ICMP_SEND_FREQUENCY_MS   500

How often do we send our ICMP messages to receive replies?

Definition at line 92 of file gnunet-helper-nat-server-windows.c.

Referenced by main().

Function Documentation

◆ calc_checksum()

static uint16_t calc_checksum ( const uint16_t *  data,
unsigned int  bytes 
)
static

CRC-16 for IP/ICMP headers.

Parameters
datawhat to calculate the CRC over
bytesnumber of bytes in data (must be multiple of 2)
Returns
the CRC 16.

Definition at line 226 of file gnunet-helper-nat-server-windows.c.

Referenced by send_icmp_echo().

227 {
228  uint32_t sum;
229  unsigned int i;
230 
231  sum = 0;
232  for (i = 0; i < bytes / 2; i++)
233  sum += data[i];
234  sum = (sum & 0xffff) + (sum >> 16);
235  sum = htons (0xffff - sum);
236  return sum;
237 }
uint32_t data
The data value.
Here is the caller graph for this function:

◆ inet_pton()

static int inet_pton ( int  af,
const char *  cp,
struct in_addr *  buf 
)
static

Convert IPv4 address from text to binary form.

Parameters
afaddress family
cpthe address to print
bufwhere to write the address result
Returns
1 on success

Definition at line 249 of file gnunet-helper-nat-server-windows.c.

Referenced by main().

250 {
251  buf->s_addr = inet_addr (cp);
252  if (buf->s_addr == INADDR_NONE)
253  {
254  fprintf (stderr, "Error %d handling address %s", WSAGetLastError (), cp);
255  return 0;
256  }
257  return 1;
258 }
static char buf[2048]
Here is the caller graph for this function:

◆ send_icmp_echo()

static void send_icmp_echo ( const struct in_addr *  my_ip)
static

Send an ICMP message to the dummy IP.

Parameters
my_ipsource address (our ip address)

Definition at line 267 of file gnunet-helper-nat-server-windows.c.

References calc_checksum(), ip_header::checksum, icmp_echo_header::checksum, icmp_echo_header::code, ip_header::dst_ip, dummy, ip_header::flags_frag_offset, GNUNET_memcpy, ICMP_ECHO, ip_header::id, IPDEFTTL, PACKET_ID, ip_header::pkt_len, ip_header::proto, rawsock, icmp_echo_header::reserved, ip_header::src_ip, ip_header::tos, ip_header::ttl, icmp_echo_header::type, and ip_header::vers_ihl.

Referenced by main().

268 {
269  char packet[sizeof (struct ip_header) + sizeof (struct icmp_echo_header)];
270  struct icmp_echo_header icmp_echo;
271  struct ip_header ip_pkt;
272  struct sockaddr_in dst;
273  size_t off;
274  int err;
275 
276  off = 0;
277  ip_pkt.vers_ihl = 0x45;
278  ip_pkt.tos = 0;
279  ip_pkt.pkt_len = htons (sizeof (packet));
280  ip_pkt.id = htons (PACKET_ID);
281  ip_pkt.flags_frag_offset = 0;
282  ip_pkt.ttl = IPDEFTTL;
283  ip_pkt.proto = IPPROTO_ICMP;
284  ip_pkt.checksum = 0;
285  ip_pkt.src_ip = my_ip->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  icmp_echo.type = ICMP_ECHO;
293  icmp_echo.code = 0;
294  icmp_echo.reserved = 0;
295  icmp_echo.checksum = 0;
296  icmp_echo.checksum =
297  htons (calc_checksum
298  ((uint16_t *) & icmp_echo, sizeof (struct icmp_echo_header)));
299  GNUNET_memcpy (&packet[off], &icmp_echo, sizeof (struct icmp_echo_header));
300  off += sizeof (struct icmp_echo_header);
301 
302  memset (&dst, 0, sizeof (dst));
303  dst.sin_family = AF_INET;
304  dst.sin_addr = dummy;
305  err =
306  sendto (rawsock, packet, off, 0, (struct sockaddr *) &dst, sizeof (dst));
307  if (err < 0)
308  {
309 #if VERBOSE
310  fprintf (stderr, "sendto failed: %s\n", strerror (errno));
311 #endif
312  }
313  else if (err != off)
314  {
315  fprintf (stderr, "Error: partial send of ICMP message\n");
316  }
317 }
uint8_t vers_ihl
Version (4 bits) + Internet header length (4 bits)
static struct in_addr dummy
Target "dummy" address.
#define IPDEFTTL
TTL to use for our outgoing messages.
#define PACKET_ID
Must match packet ID used by gnunet-helper-nat-client.c.
static uint16_t calc_checksum(const uint16_t *data, unsigned int bytes)
CRC-16 for IP/ICMP headers.
static SOCKET rawsock
Socket we use to send our ICMP requests.
#define GNUNET_memcpy(dst, src, n)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ send_udp()

static void send_udp ( )
static

Send a UDP message to the dummy IP.

Definition at line 324 of file gnunet-helper-nat-server-windows.c.

References dummy, NAT_TRAV_PORT, and udpsock.

Referenced by main().

325 {
326  struct sockaddr_in dst;
327  ssize_t err;
328 
329  memset (&dst, 0, sizeof (dst));
330  dst.sin_family = AF_INET;
331  dst.sin_addr = dummy;
332  dst.sin_port = htons (NAT_TRAV_PORT);
333  err = sendto (udpsock, NULL, 0, 0, (struct sockaddr *) &dst, sizeof (dst));
334  if (err < 0)
335  {
336 #if VERBOSE
337  fprintf (stderr, "sendto failed: %s\n", strerror (errno));
338 #endif
339  }
340  else if (0 != err)
341  {
342  fprintf (stderr, "Error: partial send of ICMP message\n");
343  }
344 }
static SOCKET udpsock
Socket we use to send our UDP requests.
static struct in_addr dummy
Target "dummy" address.
#define NAT_TRAV_PORT
Default Port.
Here is the caller graph for this function:

◆ process_icmp_response()

static void process_icmp_response ( )
static

We've received an ICMP response.

Process it.

Definition at line 351 of file gnunet-helper-nat-server-windows.c.

References buf, icmp_ttl_exceeded_header::code, GNUNET_memcpy, ICMP_TIME_EXCEEDED, icmpsock, udp_header::length, port, ip_header::proto, icmp_echo_header::reserved, SOCKET, ip_header::src_ip, and icmp_ttl_exceeded_header::type.

Referenced by main().

352 {
353  char buf[65536];
354  ssize_t have;
355  struct in_addr source_ip;
356  struct ip_header ip_pkt;
357  struct icmp_ttl_exceeded_header icmp_ttl;
358  struct icmp_echo_header icmp_echo;
359  struct udp_header udp_pkt;
360  size_t off;
361  uint16_t port;
362  DWORD ssize;
363 
364  have = read (icmpsock, buf, sizeof (buf));
365  if (have == -1)
366  {
367  fprintf (stderr, "Error reading raw socket: %s\n", strerror (errno));
368  return;
369  }
370 #if VERBOSE
371  fprintf (stderr, "Received message of %u bytes\n", (unsigned int) have);
372 #endif
373  if (have <
374  (ssize_t) (sizeof (struct ip_header) +
375  sizeof (struct icmp_ttl_exceeded_header) +
376  sizeof (struct ip_header)))
377  {
378  /* malformed */
379  return;
380  }
381  off = 0;
382  GNUNET_memcpy (&ip_pkt, &buf[off], sizeof (struct ip_header));
383  off += sizeof (struct ip_header);
384  GNUNET_memcpy (&source_ip, &ip_pkt.src_ip, sizeof (source_ip));
385  GNUNET_memcpy (&icmp_ttl, &buf[off], sizeof (struct icmp_ttl_exceeded_header));
386  off += sizeof (struct icmp_ttl_exceeded_header);
387  if ((ICMP_TIME_EXCEEDED != icmp_ttl.type) || (0 != icmp_ttl.code))
388  {
389  /* different type than what we want */
390  return;
391  }
392  /* skip 2nd IP header */
393  GNUNET_memcpy (&ip_pkt, &buf[off], sizeof (struct ip_header));
394  off += sizeof (struct ip_header);
395 
396  switch (ip_pkt.proto)
397  {
398  case IPPROTO_ICMP:
399  if (have !=
400  (sizeof (struct ip_header) * 2 +
401  sizeof (struct icmp_ttl_exceeded_header) +
402  sizeof (struct icmp_echo_header)))
403  {
404  /* malformed */
405  return;
406  }
407  /* grab ICMP ECHO content */
408  GNUNET_memcpy (&icmp_echo, &buf[off], sizeof (struct icmp_echo_header));
409  port = (uint16_t) ntohl (icmp_echo.reserved);
410  break;
411  case IPPROTO_UDP:
412  if (have !=
413  (sizeof (struct ip_header) * 2 +
414  sizeof (struct icmp_ttl_exceeded_header) + sizeof (struct udp_header)))
415  {
416  /* malformed */
417  return;
418  }
419  /* grab UDP content */
420  GNUNET_memcpy (&udp_pkt, &buf[off], sizeof (struct udp_header));
421  port = ntohs (udp_pkt.length);
422  break;
423  default:
424  /* different type than what we want */
425  return;
426  }
427 
428  ssize = sizeof (buf);
429  WSAAddressToString ((LPSOCKADDR) & source_ip, sizeof (source_ip), NULL, buf,
430  &ssize);
431  if (port == 0)
432  fprintf (stdout, "%s\n", buf);
433  else
434  fprintf (stdout, "%s:%u\n", buf, (unsigned int) port);
435  fflush (stdout);
436 }
static char buf[2048]
static SOCKET icmpsock
Socket we use to receive "fake" ICMP replies.
static uint16_t port
Port number.
Definition: gnunet-bcd.c:79
#define ICMP_TIME_EXCEEDED
Beginning of UDP packet.
#define GNUNET_memcpy(dst, src, n)
Here is the caller graph for this function:

◆ make_icmp_socket()

static SOCKET make_icmp_socket ( )
static

Create an ICMP raw socket for reading.

Returns
INVALID_SOCKET on error

Definition at line 445 of file gnunet-helper-nat-server-windows.c.

References INVALID_SOCKET, ret, and SOCKET.

Referenced by main().

446 {
447  SOCKET ret;
448 
449  ret = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
450  if (INVALID_SOCKET == ret)
451  {
452  fprintf (stderr, "Error opening RAW socket: %s\n", strerror (errno));
453  return INVALID_SOCKET;
454  }
455  return ret;
456 }
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define INVALID_SOCKET
Definition: network.c:39
#define SOCKET(a, t, p)
Definition: plibc.h:711
Here is the caller graph for this function:

◆ make_raw_socket()

static SOCKET make_raw_socket ( )
static

Create an ICMP raw socket for writing.

Returns
INVALID_SOCKET on error

Definition at line 465 of file gnunet-helper-nat-server-windows.c.

References INVALID_SOCKET, rawsock, and SOCKET.

Referenced by main().

466 {
467  DWORD bOptVal = TRUE;
468  int bOptLen = sizeof (bOptVal);
469 
470  rawsock = socket (AF_INET, SOCK_RAW, IPPROTO_ICMP);
471  if (INVALID_SOCKET == rawsock)
472  {
473  fprintf (stderr, "Error opening RAW socket: %s\n", strerror (errno));
474  return INVALID_SOCKET;
475  }
476 
477  if (0 !=
478  setsockopt (rawsock, SOL_SOCKET, SO_BROADCAST, (char *) &bOptVal,
479  bOptLen))
480  {
481  fprintf (stderr, "Error setting SO_BROADCAST to ON: %s\n",
482  strerror (errno));
483  closesocket (rawsock);
484  return INVALID_SOCKET;
485  }
486  if (0 !=
487  setsockopt (rawsock, IPPROTO_IP, IP_HDRINCL, (char *) &bOptVal, bOptLen))
488  {
489  fprintf (stderr, "Error setting IP_HDRINCL to ON: %s\n", strerror (errno));
490  closesocket (rawsock);
491  return INVALID_SOCKET;
492  }
493  return rawsock;
494 }
#define INVALID_SOCKET
Definition: network.c:39
static SOCKET rawsock
Socket we use to send our ICMP requests.
Here is the caller graph for this function:

◆ make_udp_socket()

static SOCKET make_udp_socket ( const struct in_addr *  my_ip)
static

Create a UDP socket for writing.

Parameters
my_ipsource address (our ip address)
Returns
INVALID_SOCKET on error

Definition at line 504 of file gnunet-helper-nat-server-windows.c.

References INVALID_SOCKET, NAT_TRAV_PORT, ret, and SOCKET.

Referenced by main().

505 {
506  SOCKET ret;
507  struct sockaddr_in addr;
508 
509  ret = socket (AF_INET, SOCK_DGRAM, 0);
510  if (INVALID_SOCKET == ret)
511  {
512  fprintf (stderr, "Error opening UDP socket: %s\n", strerror (errno));
513  return INVALID_SOCKET;
514  }
515  memset (&addr, 0, sizeof (addr));
516  addr.sin_family = AF_INET;
517  addr.sin_addr = *my_ip;
518  addr.sin_port = htons (NAT_TRAV_PORT);
519  if (0 != bind (ret, (struct sockaddr *) &addr, sizeof (addr)))
520  {
521  fprintf (stderr, "Error binding UDP socket to port %u: %s\n", NAT_TRAV_PORT,
522  strerror (errno));
523  /* likely problematic, but not certain, try to continue */
524  }
525  return ret;
526 }
static int ret
Final status code.
Definition: gnunet-arm.c:89
#define INVALID_SOCKET
Definition: network.c:39
#define SOCKET(a, t, p)
Definition: plibc.h:711
#define NAT_TRAV_PORT
Default Port.
Here is the caller graph for this function:

◆ main()

int main ( int  argc,
char *const *  argv 
)

Definition at line 530 of file gnunet-helper-nat-server-windows.c.

References dummy, DUMMY_IP, ICMP_SEND_FREQUENCY_MS, icmpsock, inet_pton(), INVALID_SOCKET, make_icmp_socket(), make_raw_socket(), make_udp_socket(), privilege_testing, process_icmp_response(), rawsock, send_icmp_echo(), send_udp(), and udpsock.

531 {
532  struct in_addr external;
533  fd_set rs;
534  struct timeval tv;
535  WSADATA wsaData;
536  unsigned int alt = 0;
537 
538  if ( (argc > 1) && (0 != strcmp (argv[1], "-d")))
539  {
540  privilege_testing = TRUE;
541  fprintf (stderr,
542  "%s",
543  "DEBUG: Running binary in privilege testing mode.");
544  argv++;
545  argc--;
546  }
547 
548  if (2 != argc)
549  {
550  fprintf (stderr,
551  "This program must be started with our (internal NAT) IP as the only argument.\n");
552  return 1;
553  }
554  if (1 != inet_pton (AF_INET, argv[1], &external))
555  {
556  fprintf (stderr, "Error parsing IPv4 address: %s, error %s\n", argv[1],
557  strerror (errno));
558  return 1;
559  }
560  if (1 != inet_pton (AF_INET, DUMMY_IP, &dummy))
561  {
562  fprintf (stderr, "Internal error converting dummy IP to binary.\n");
563  return 2;
564  }
565  if (WSAStartup (MAKEWORD (2, 1), &wsaData) != 0)
566  {
567  fprintf (stderr, "Failed to find Winsock 2.1 or better.\n");
568  return 2;
569  }
571  {
572  return 3;
573  }
574  if (INVALID_SOCKET == (make_raw_socket ()))
575  {
576  closesocket (icmpsock);
577  return 3;
578  }
579  if (INVALID_SOCKET == (udpsock = make_udp_socket (&external)))
580  {
581  closesocket (icmpsock);
582  closesocket (rawsock);
583  return 3;
584  }
585 
586  while ( ! privilege_testing)
587  {
588  FD_ZERO (&rs);
589  FD_SET (icmpsock, &rs);
590  tv.tv_sec = 0;
591  tv.tv_usec = ICMP_SEND_FREQUENCY_MS * 1000;
592  if (-1 == select (icmpsock + 1, &rs, NULL, NULL, &tv))
593  {
594  if (errno == EINTR)
595  continue;
596  fprintf (stderr, "select failed: %s\n", strerror (errno));
597  break;
598  }
599  if (FD_ISSET (icmpsock, &rs))
601  if (0 == (++alt % 2))
602  send_icmp_echo (&external);
603  else
604  send_udp ();
605  }
606  /* select failed (internal error or OS out of resources) */
607  closesocket (icmpsock);
608  closesocket (rawsock);
609  closesocket (udpsock);
610  WSACleanup ();
611  if (privilege_testing)
612  return 0;
613  return 4;
614 }
static SOCKET make_raw_socket()
Create an ICMP raw socket for writing.
static int inet_pton(int af, const char *cp, struct in_addr *buf)
Convert IPv4 address from text to binary form.
static boolean privilege_testing
Will this binary be run in permissions testing mode?
static void process_icmp_response()
We&#39;ve received an ICMP response.
static SOCKET udpsock
Socket we use to send our UDP requests.
#define INVALID_SOCKET
Definition: network.c:39
static SOCKET make_udp_socket(const struct in_addr *my_ip)
Create a UDP socket for writing.
static struct in_addr dummy
Target "dummy" address.
static SOCKET icmpsock
Socket we use to receive "fake" ICMP replies.
static void send_udp()
Send a UDP message to the dummy IP.
static void send_icmp_echo(const struct in_addr *my_ip)
Send an ICMP message to the dummy IP.
static SOCKET make_icmp_socket()
Create an ICMP raw socket for reading.
#define DUMMY_IP
Must match IP given in the client.
static SOCKET rawsock
Socket we use to send our ICMP requests.
#define ICMP_SEND_FREQUENCY_MS
How often do we send our ICMP messages to receive replies?
Here is the call graph for this function:

Variable Documentation

◆ privilege_testing

boolean privilege_testing = FALSE
static

Will this binary be run in permissions testing mode?

Definition at line 195 of file gnunet-helper-nat-server-windows.c.

Referenced by main().

◆ icmpsock

SOCKET icmpsock
static

Socket we use to receive "fake" ICMP replies.

Definition at line 200 of file gnunet-helper-nat-server-windows.c.

Referenced by main(), and process_icmp_response().

◆ rawsock

SOCKET rawsock
static

Socket we use to send our ICMP requests.

Definition at line 205 of file gnunet-helper-nat-server-windows.c.

Referenced by main(), make_raw_socket(), and send_icmp_echo().

◆ udpsock

SOCKET udpsock
static

Socket we use to send our UDP requests.

Definition at line 210 of file gnunet-helper-nat-server-windows.c.

Referenced by main(), and send_udp().

◆ dummy

struct in_addr dummy
static

Target "dummy" address.

Definition at line 215 of file gnunet-helper-nat-server-windows.c.

Referenced by main(), send_icmp_echo(), and send_udp().