//==================================================== file = udprelay.c =====
//=  A unicast UDP relay/reflector for Windoes or Unix                       =
//============================================================================
//=  Notes:                                                                  =
//=    1) Conditionally compiles for Winsock and BSD sockets.  Manually      =
//=       set the initial #define to WIN or BSD as appropriate.              =
//=    2) Relects or relays as manually set in #define MODE                  =
//=    3) For #define MODE RELAY, IP address must be entered manually        =
//=    4) For #deffine MODE REFLECT, port numbers must be entered manually   =
//=--------------------------------------------------------------------------=
//=  Build: bcc32 udprelay.c or cl udprelay.c wsock32.lib for Winsock        =
//=         gcc udprelay.c -lsocket -lnsl for BSD                            =
//=--------------------------------------------------------------------------=
//=  History:  KJC (06/18/02) - Genesis (from server1.c)                     =
//=            JNS (06/19/02) - Updated, fixed REFLECT and RELAY             =
//============================================================================
#define  WIN                // WIN for Winsock and BSD for BSD sockets

//----- Include files -------------------------------------------------------
#include <stdio.h>          // Needed for printf()
#include <stdlib.h>         // Needed for memcpy()
#include <string.h>         // Needed for strcpy()
#ifdef WIN
  #include <windows.h>      // Needed for all Winsock stuff
#endif
#ifdef BSD
  #include <sys/types.h>    // Needed for system defined identifiers.
  #include <netinet/in.h>   // Needed for internet address structure.
  #include <sys/socket.h>   // Needed for socket(), bind(), etc...
  #include <arpa/inet.h>    // Needed for inet_ntoa()
  #include <fcntl.h>
  #include <netdb.h>
#endif

//----- Defines -------------------------------------------------------------
#define FALSE        0  // Boolean false
#define TRUE         1  // Boolean true
#define RELAY        0  // Define for relay function
#define REFLECT      1  // Define for reflector function

#define VERBOSE   TRUE                    // Verbose mode (TRUE or FALSE)
#define MODE      REFLECT                 // Define REFLECT or RELAY

#define PORT_NUM_FROM    1056             // Port number client sends to
#define PORT_NUM_TO      1050             // Port number client receives from
#define RELAY_IP_ADDRESS "131.247.3.230"  // IP to relay to

//===== Main program ========================================================
void main(void)
{
#ifdef WIN
  WORD wVersionRequested = MAKEWORD(1,1);       // Stuff for WSA functions
  WSADATA wsaData;                              // Stuff for WSA functions
#endif

  unsigned int         server_s;      // Server socket descriptor
  struct sockaddr_in   server_addr;   // Server Internet address
  struct sockaddr_in   client_addr;   // Client Internet address
  struct in_addr       recv_ip_addr;  // Received IP address
  int                  addr_len;      // Internet address length
  int                  retcode;       // Return code
  char                 buffer[8192];  // Datagram buffer
  int                  i;             // Loop counter

#ifdef WIN
  // This stuff initializes winsock
  WSAStartup(wVersionRequested, &wsaData);
#endif

  // Create my (server) socket and fill-in address information
  server_s = socket(AF_INET, SOCK_DGRAM, 0);
  server_addr.sin_family = AF_INET;
  server_addr.sin_port = htons(PORT_NUM_FROM);
  server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  bind(server_s, (struct sockaddr *)&server_addr, sizeof(server_addr));

  // Fill-in client's socket information
  client_addr.sin_family = AF_INET;

  // Set addr_len
  addr_len = sizeof(client_addr);

  // Reflect or relay UDP datagrams forever
  if (MODE == REFLECT)
    printf("BEGIN reflecting packets... \n");
  else
    printf("BEGIN relaying packets... \n");
  while(TRUE)
  {
    // Receive a datagram
    retcode = recvfrom(server_s, buffer, sizeof(buffer), 0,
      (struct sockaddr *)&client_addr, &addr_len);

    // Save client address for VERBOSE output
    recv_ip_addr = client_addr.sin_addr;

    // Replace client address with source address if reflecting
    if (MODE == REFLECT)
    {
      // Change the port number
      client_addr.sin_port = htons(PORT_NUM_TO);
    }
    else if (MODE == RELAY)
    {
      // Insert the relay IP address
      client_addr.sin_addr.s_addr = inet_addr(RELAY_IP_ADDRESS);
    }

    // Output buffer if verbose is true
    if (VERBOSE == TRUE)
    {
      printf("----------------------------------------------------------- \n");
      printf("Source = %s   ", inet_ntoa(recv_ip_addr));
      printf("Dest = %s \n", inet_ntoa(client_addr.sin_addr));
      printf("Buffer = ");
      for (i=0; i<retcode; i++)
        printf("%02X", buffer[i]);
      printf("\n");
    }

    // Send the datagram
    sendto(server_s, buffer, retcode, 0, (struct sockaddr *)&client_addr,
           sizeof(client_addr));
  }

  // Close and clean-up
#ifdef WIN
  closesocket(server_s);
  WSACleanup();
#endif
#ifdef BSD
  close(server_s);
#endif
}

