TCP Proxy for Windows

This is the Windows version of TCP Proxy.

/* 
 *  A simple TCP proxy for Windows
 *  by Martin Broadhurst (www.martinbroadhurst.com)
 *  Link with Ws2_32.lib
 *  Usage: tcpproxy local_host local_port remote_host remote_port
 */

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#define _WINSOCK_DEPRECATED_NO_WARNINGS /* inet_ntoa */

#include <stdio.h>
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>

#define BACKLOG  10      /* Passed to listen() */
#define BUF_SIZE 4096    /* Buffer for  transfers */

unsigned int transfer(SOCKET from, SOCKET to)
{
	char buf[BUF_SIZE];
	unsigned int disconnected = 0;
	size_t bytes_read, bytes_written;
	bytes_read = recv(from, buf, BUF_SIZE, 0);
	if (bytes_read == 0) {
		disconnected = 1;
	}
	else {
		bytes_written = send(to, buf, bytes_read, 0);
		if (bytes_written == -1) {
			disconnected = 1;
		}
	}
	return disconnected;
}

void handle(SOCKET client, const char *remote_host, const char *remote_port)
{
	struct addrinfo hints, *res;
	SOCKET server = -1;
	unsigned int disconnected = 0;
	fd_set set;
	unsigned int max_sock;

	/* Get the address info */
	ZeroMemory(&hints, sizeof hints);
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	if (getaddrinfo(remote_host, remote_port, &hints, &res) != 0) {
		perror("getaddrinfo");
		closesocket(client);
		return;
	}

	/* Create the socket */
    server = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
	if (server == INVALID_SOCKET) {
		perror("socket");
		closesocket(client);
		return;
	}

	/* Connect to the host */
	if (connect(server, res->ai_addr, res->ai_addrlen) == -1) {
		perror("connect");
		closesocket(client);
		return;
    }

	if (client > server) {
		max_sock = client;
	}
	else {
		max_sock = server;
	}

	/* Main transfer loop */
	while (!disconnected) {
		FD_ZERO(&set);
		FD_SET(client, &set);
		FD_SET(server, &set);
		if (select(max_sock + 1, &set, NULL, NULL, NULL) == SOCKET_ERROR) {
			perror("select");
			break;
		}
		if (FD_ISSET(client, &set)) {
			disconnected = transfer(client, server);
		}
		if (FD_ISSET(server, &set)) {
			disconnected = transfer(server, client);
		}
	}
	if (server != -1) {
		closesocket(server);
	}
	closesocket(client);
}

int main(int argc, char **argv)
{
	WORD wVersion = MAKEWORD(2, 2);
	WSADATA wsaData;
	int iResult;
    SOCKET sock;
	struct addrinfo hints, *res;
	int reuseaddr = 1; /* True */
	const char *local_host, *local_port, *remote_host, *remote_port;

	/* Initialise Winsock */
	if (iResult = (WSAStartup(wVersion, &wsaData)) != 0) {
		fprintf(stderr, "WSAStartup failed: %d\n", iResult);
		return 1;
	}

	/* Get the local and remote hosts and ports from the command line */
	if (argc < 5) {
		fprintf(stderr, "Usage: tcpproxy local_host local_port remote_host remote_port\n");
		return 1;
	}
	local_host = argv[1];
	local_port = argv[2];
	remote_host = argv[3];
	remote_port = argv[4];

	/* Get the address info */
	ZeroMemory(&hints, sizeof hints);
	hints.ai_family = AF_INET;
	hints.ai_socktype = SOCK_STREAM;
	if (getaddrinfo(local_host, local_port, &hints, &res) != 0) {
		perror("getaddrinfo");
		WSACleanup();
		return 1;
	}

	/* Create the socket */
    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
	if (sock == INVALID_SOCKET) {
		perror("socket");
		WSACleanup();
		return 1;
	}

	/* Enable the socket to reuse the address */
	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuseaddr, 
		sizeof(int)) == SOCKET_ERROR) {
		perror("setsockopt");
		WSACleanup();
		return 1;
	}

	/* Bind to the address */
    if (bind(sock, res->ai_addr, res->ai_addrlen) == SOCKET_ERROR) {
        perror("bind");
		WSACleanup();
        return 1;
    }

	/* Listen */
    if (listen(sock, BACKLOG) == SOCKET_ERROR) {
        perror("listen");
		WSACleanup();
        return 1;
    }

	freeaddrinfo(res);
 
	/* Main loop */
	while (1) {
		size_t size = sizeof(struct sockaddr_in);
		struct sockaddr_in their_addr;
		int newsock = accept(sock, (struct sockaddr*)&their_addr, &size);

		if (newsock == INVALID_SOCKET) {
			perror("accept");
		}
		else {
			printf("Got a connection from %s on port %d\n", 
					inet_ntoa(their_addr.sin_addr), htons(their_addr.sin_port));
			handle(newsock, remote_host, remote_port);
		}
	}

    closesocket(sock);
	WSACleanup();

    return 0;
}