#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <stdio.h>
#include <sys/time.h>
#include <netdb.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>

#include "os.h"
#include "s_defines.h"

#ifdef RUSNET_IRCD

/*
unsigned long rusnet_vaddr = 0L;
*/

struct rusnet_route
{
	struct sockaddr_in routing_interface;
	struct sockaddr_in server_interface;
	char		   *description;

	struct rusnet_route *next;
};

struct rusnet_route *hdr_rusnet_route = NULL;

/*
int rusnet_virtualized(void)
{
	if (rusnet_vaddr != 0L) return 1;
	return 0;
}

void rusnet_fill_virtual_address(struct sockaddr_in *arg)
{
	memcpy(&(arg->sin_addr.s_addr), &rusnet_vaddr, 4);
}

void rusnet_bind_virtual_address(int sockfd)
{
	struct sockaddr_in myaddr;

	memset(&myaddr, 0, sizeof(myaddr));
	myaddr.sin_family = AF_INET;
	myaddr.sin_addr.s_addr = rusnet_vaddr;
	myaddr.sin_port = 0;

	bind(sockfd, (struct sockaddr *)&myaddr, sizeof(struct sockaddr));
}
*/

void rusnet_add_route(char *server_ip, char *interface_ip, char *desc)
{
        struct rusnet_route *work;

	work = (struct rusnet_route *)MyMalloc(sizeof(struct rusnet_route));

	memset(&(work->routing_interface), 0, sizeof(struct sockaddr_in));
	memset(&(work->server_interface), 0, sizeof(struct sockaddr_in));

	work->routing_interface.sin_family = AF_INET;
	work->server_interface.sin_family = AF_INET;
	work->routing_interface.sin_port = 0;
	work->server_interface.sin_port = 0;

	work->routing_interface.sin_addr.s_addr = inet_addr(interface_ip);
	work->server_interface.sin_addr.s_addr = inet_addr(server_ip);
	DupString(work->description, desc);

	work->next = hdr_rusnet_route;
	hdr_rusnet_route = work;
}

void rusnet_free_routes(void)
{
	struct rusnet_route *work, *work2;

	for (work = hdr_rusnet_route; work != NULL; work = work2)
	{
		work2 = work->next;
		MyFree(work->description);
		MyFree(work);
	}

	hdr_rusnet_route = NULL;
}

int rusnet_bind_interface_address(int fd, struct sockaddr_in *raddr, 
			           char *desc)
{
	struct rusnet_route *work;
	unsigned char c[4];
	int rc, rc2;
	struct sockaddr_in test;

	work = hdr_rusnet_route;

	while (work != NULL)
	{
	      memcpy(c, &(work->server_interface.sin_addr.s_addr), 4);
	      Debug((DEBUG_ERROR,"Server interface: %u.%u.%u.%u",
			(unsigned int)c[0],
		        (unsigned int)c[1],
			(unsigned int)c[2],
			(unsigned int)c[3]));

	      memcpy(c, &(work->routing_interface.sin_addr.s_addr), 4);
	      Debug((DEBUG_ERROR,"Routing interface: %u.%u.%u.%u",
			(unsigned int)c[0],
		        (unsigned int)c[1],
			(unsigned int)c[2],
			(unsigned int)c[3]));

	      if (memcmp(&(work->server_interface.sin_addr.s_addr),
	                 &(raddr->sin_addr.s_addr),
			 4) == 0)
	      {
	          Debug((DEBUG_ERROR,"Binding"));
		  Debug((DEBUG_ERROR,"Socket = %d", fd));
		  Debug((DEBUG_ERROR,"Local port = %d",
			ntohl(work->routing_interface.sin_port)));

	       	  memset(&test, 0, sizeof(test));
		  test.sin_family = AF_INET;
		  memcpy(&test.sin_addr.s_addr,
				&(work->routing_interface.sin_addr.s_addr),
						sizeof(test.sin_addr.s_addr));
	 	  test.sin_port = 0;

		  rc = bind(fd, (struct sockaddr *)&test,
			   sizeof(struct sockaddr_in));
		  rc2 = errno;
	          if (rc) perror("bind"); 
		  if (rc2 == EINPROGRESS || rc2 == EWOULDBLOCK)
			Debug((DEBUG_ERROR, "EINPROGRESS or EWOULDBLOCK"));

		  Debug((DEBUG_ERROR,"bind() retcode = %d", rc));
		  strncpyzt(desc, work->description, 250);
	          return rc;
	      }
	      work = work->next;
	}

	// Otherwise do nothing
	return -1;
}
#endif


syntax highlighted by Code2HTML, v. 0.9.1