From 2442c62cccc97d88ca1635d2b231dec7261ca17f Mon Sep 17 00:00:00 2001
From: Ludovic Pouzenc <ludovic@pouzenc.fr>
Date: Mon, 22 Oct 2012 21:56:07 +0000
Subject: Version compilable sous Windows avec Visual Studio 8 et ses outils de
 compilations... Vive les #ifdef partout.

git-svn-id: file:///var/svn/2012-tzsp/trunk@13 147d2d3d-d0bd-48ea-923a-d90ac20f5906
---
 pcap2tzsp.c | 124 ++++++++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 100 insertions(+), 24 deletions(-)

diff --git a/pcap2tzsp.c b/pcap2tzsp.c
index 5d8d05f..bf175ea 100644
--- a/pcap2tzsp.c
+++ b/pcap2tzsp.c
@@ -25,26 +25,68 @@
 /* Basics */
 #include <stdio.h>
 #include <stdlib.h>
-#include <string.h>
+#include <stdint.h> /* Consider using msinttypes for Visual Studio */
 #include <signal.h>
+#include <string.h>
+
+#ifdef WIN32 /* snprintf compatiblity */
+#define my_snprintf sprintf_s
+#else
+#define my_snprintf snprintf
+#endif
 
-/* Args parsing and basename() for usage */
-#include <getopt.h>
-#include <libgen.h>
+
+/* Packet capture stuff */
+#include <pcap.h>
 
 /* UDP stuff */
+#ifdef WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <unistd.h>
 #include <netdb.h> /* Name resolution */
-
-/* Packet capture stuff */
-#include <pcap.h>
-#include <sys/time.h>
+#define SOCKET int
+#define INVALID_SOCKET -1
+#endif
 
 /* Time management (for bwlimit) */
 #include <time.h>
 
+/* Args parsing and basename() for usage */
+#ifdef WIN32
+#undef _UNICODE
+#include <getopt.h> /* Consider using getopt4win for WIN32 */
+
+	/* Poor's men hand-written basename. 
+	With calloc() and this is diffent from POSIX basename() */
+	char * basename(const char *path) {
+		errno_t e;
+		size_t len1, len2;
+		char filename[256], ext[8];
+		char *res=NULL;
+
+		e=_splitpath_s(path, NULL, 0, NULL, 0, filename, 256, ext, 8);
+		if (e != 0) {
+			res=strdup("");
+		} else {
+			len1=strlen(filename);
+			len2=strlen(ext);
+			res=calloc(len1+len2 + 1, sizeof(char));
+			if ( res != NULL ) {
+				strcpy_s(res, len1+1, filename);
+				strcpy_s(res+len1, len2+1, ext);
+			}
+		}
+		return res;
+	}
+#else
+#include <getopt.h>
+#include <libgen.h>
+#endif
+
 /* Option default values (as strings) */
 #define DEFAULT_FILTER "not ( icmp[icmptype]=icmp-unreach or (udp and dst %s and port %s) )"
 #define DEFAULT_HOST "localhost"
@@ -67,7 +109,6 @@
 
 /*
 TODO List
-  * Version qui compile sous Windows
   * Implémenter une bwlimit en sortie (ptks/s et/ou bytes/s)
   * Calcul dynamique de MAX_TZSP_PAYLOAD
 */
@@ -82,7 +123,7 @@ typedef struct _process_packet_args {
 	/* Types like in libpcap because I don't want to mess around hours */
 	u_int captured_pkt_count;
 	u_int sent_pkt_count;
-	int socket;
+	SOCKET socket;
 } process_packet_args_t;
 
 
@@ -105,6 +146,7 @@ void usage(char progname[]) {
 	exit(1);
 }
 
+
 void sig_handler(int signo) {
 	static int pcap_break=0;
 
@@ -123,8 +165,15 @@ void sig_handler(int signo) {
 
 int main(int argc, char *argv[]) {
 
+#ifdef WIN32
+	// Winsock2 mystic stuff
+	WSADATA wsaData = {0};
+	int iResult;
+#endif
+
 	/* Command line args parsing */
-	int c,i,j,pcap_filter_len;
+	int c,i,j;
+	size_t pcap_filter_len; /* size_t is "mandatory" for WIN32 */
 	char *pcap_filter=NULL;
 
 	while (1) {
@@ -196,17 +245,30 @@ int main(int argc, char *argv[]) {
 
 		for (i=optind, j=0; i<argc; i++) {
 			if (i<argc-1) {
-				 j+=sprintf(pcap_filter+j, "%s ", argv[i]);
+				 j+=my_snprintf(pcap_filter+j,pcap_filter_len-j, "%s ", argv[i]);
 			} else {
-				j+=sprintf(pcap_filter+j, "%s", argv[i]);
+				j+=my_snprintf(pcap_filter+j,pcap_filter_len-j, "%s", argv[i]);
 			}
 		}
 	}
 
+
+#ifdef WIN32
+	// Initialize Winsock
+	iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
+    if (iResult != 0) {
+        fprintf(stderr, "WSAStartup failed: %d\n", iResult);
+        return -10;
+    }
+#endif
+
 	signal(SIGINT, sig_handler);
 	/* Run the capture loop */
 	start_capture_loop(pcap_filter);
 
+#ifdef WIN32
+	WSACleanup();
+#endif
 	free(opt_host);
 	free(opt_port);
 	free(opt_snaplen);
@@ -218,12 +280,15 @@ int main(int argc, char *argv[]) {
 
 int make_dgram_socket(char host[], char service[], int hint_flags, char **resolved_address) {
 
-	/* Code taken from Client program example of getaddrinfo(3) manpage */
+	/* Code taken from Client program example of getaddrinfo(3) manpage
+	   Tweaks added for WIN32 "compatibility"
+	*/
 
 	struct addrinfo hints;
 	struct addrinfo *result, *rp;
 	char hbuf[NI_MAXHOST_NUMERIC];
-	int sfd, s;
+	int s;
+	SOCKET sfd = INVALID_SOCKET;
 
 	/* Obtain address(es) matching host/port */
 
@@ -236,7 +301,7 @@ int make_dgram_socket(char host[], char service[], int hint_flags, char **resolv
 	s = getaddrinfo(host, service, &hints, &result);
 	if (s != 0) {
 		fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
-		exit(EXIT_FAILURE);
+		return -2;
 	}
 
 	/* getaddrinfo() returns a list of address structures.
@@ -245,15 +310,17 @@ int make_dgram_socket(char host[], char service[], int hint_flags, char **resolv
 	   and) try the next address. */
 
 	for (rp = result; rp != NULL; rp = rp->ai_next) {
-		sfd = socket(rp->ai_family, rp->ai_socktype,
-				rp->ai_protocol);
-		if (sfd == -1)
+		sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+		if (sfd == INVALID_SOCKET)
 			continue;
 
 		if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1)
 			break;		/* Success */
-
+#ifdef WIN32
+		closesocket(sfd);
+#else
 		close(sfd);
+#endif
 	}
 
 	if (rp == NULL) {		/* No address succeeded */
@@ -285,7 +352,8 @@ void start_capture_loop(char *pcap_filter) {
 	struct bpf_program pcap_filter_prog;
 	struct pcap_stat stat;
 	process_packet_args_t process_packet_args;
-	int snaplen, hints_flags, pcap_filter_len, pcap_filter_synthetised=0;
+	int snaplen, hints_flags, pcap_filter_synthetised=0;
+	size_t pcap_filter_len; /* size_t is "mandatory" for WIN32 */
 
 	memset(pcap_errbuf,0,PCAP_ERRBUF_SIZE); 
 	memset(&process_packet_args,0,sizeof(process_packet_args_t)); 
@@ -310,7 +378,7 @@ void start_capture_loop(char *pcap_filter) {
 	/* UDP socket creation */
 	hints_flags=AI_NUMERICSERV | AI_ADDRCONFIG | AI_V4MAPPED;
 	if (opt_verbose) printf("Opening socket for sending TZSP to %s:%s\n", opt_host, opt_port);
-	if ( ( process_packet_args.socket = make_dgram_socket(opt_host, opt_port, hints_flags, &resolved_address) ) == -1 ) {
+	if ( ( process_packet_args.socket = make_dgram_socket(opt_host, opt_port, hints_flags, &resolved_address) ) < 0 ) {
 		fprintf(stderr, "ERROR : Couldn't make a socket to %s:%s\n", opt_host, opt_port);
 		exit(10);
 	}
@@ -331,13 +399,13 @@ void start_capture_loop(char *pcap_filter) {
 		pcap_filter_len = strlen(DEFAULT_FILTER) -4 + strlen(resolved_address) + strlen(opt_port) + 1;
 		pcap_filter=calloc(pcap_filter_len, sizeof(char));
 		//XXX pos=snprintf(pcap_filter, pcap_filter_len, DEFAULT_FILTER, resolved_address, opt_port);
-		/*res=*/ (void)sprintf(pcap_filter, DEFAULT_FILTER, resolved_address, opt_port);
+		/*res=*/ (void)my_snprintf(pcap_filter, pcap_filter_len, DEFAULT_FILTER, resolved_address, opt_port);
 		//printf ("DEBUG : Capture filter will be : '%s' (pcap_filter_len-res==%i)\n", pcap_filter, pcap_filter_len-res);
 	}
 	free(resolved_address);
 
 	if (opt_verbose) printf("Compiling the following capture filter : '%s'\n", pcap_filter);
-	if ( pcap_compile(pcap_handle,&pcap_filter_prog,pcap_filter,1,PCAP_NETMASK_UNKNOWN) == -1 ) {
+	if ( pcap_compile(pcap_handle,&pcap_filter_prog,pcap_filter,1,0/*FIXME PCAP_NETMASK_UNKNOWN*/) == -1 ) {
 		fprintf(stderr,"ERROR : %s\n", pcap_geterr(pcap_handle) );
 		exit(22);
 	}
@@ -368,7 +436,11 @@ void start_capture_loop(char *pcap_filter) {
 		stat.ps_recv, stat.ps_drop);
 
 	pcap_close(pcap_handle);
+#ifdef WIN32
+	closesocket(process_packet_args.socket);
+#else
 	close(process_packet_args.socket);
+#endif
 }
 
 
@@ -443,7 +515,11 @@ void process_packet(u_char *void_args, const struct pcap_pkthdr* pkthdr, const u
 
 	/* TZSP packet sending (over the UDP socket) */
 	tzsp_len=16+pkthdr->caplen;
+#ifdef WIN32
+	res=send(args->socket, buf, tzsp_len,0);
+#else
 	res=write(args->socket, buf, tzsp_len);
+#endif
 	if (res != tzsp_len) {
 		fprintf(stderr, "write() on UDP socket error (written %i of %i bytes)\n", res, tzsp_len);
 	} else {
-- 
cgit v1.2.3