Gisle Vanem on 19 Apr 2004 14:15:02 -0000


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: [tcptra-dev] MingW port


> I did a port of 1.4 and now 1.5-beta5 to gcc/MingW
> (on Win-XP). Is there any interest to make tcptraceroute support 
> the most popular OS ever? If so, a patch + makefile is attached.

A updated patch attached; fixes pcap_setnonblock() and 
meaningful Windows version of pfatal().

--gv

GNU GPL: Free as in herpes.
--- tcptraceroute-1.5beta5/tcptraceroute.c	Thu Jul 03 21:56:41 2003
+++ tcptraceroute.c	Mon Apr 19 12:52:49 2004
@@ -47,26 +47,35 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <unistd.h>
 #include <ctype.h>
 #include <time.h>
 #include <errno.h>
+
+#ifdef WIN32
+  #include <time.h>
+  #include <sys/timeb.h>
+  #define CLOSE_SOCK closesocket
+#else
+  #include <unistd.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <netdb.h>
 #include <sys/ioctl.h>
+  #include <arpa/inet.h>
+  #define CLOSE_SOCK close
+#endif  /* WIN32 */
+
 #include <fcntl.h>

-#ifndef __OpenBSD__
+#if !defined(__OpenBSD__) && !defined(WIN32)
 #include <net/if.h> /* Why doesn't OpenBSD deal with this for us? */
 #endif

-#include <arpa/inet.h>
 #include <libnet.h>
 #include <pcap.h>

-#ifndef SIOCGIFCONF
+#if !defined(SIOCGIFCONF) && !defined(WIN32)
 #include <sys/sockio.h> /* Solaris, maybe others? */
 #endif

@@ -230,8 +239,73 @@

 extern char *optarg;
 extern int optind, opterr, optopt;
-extern char pcap_version[];
-extern int errno;
+
+#ifdef WIN32
+struct timezone {
+       int tz_minuteswest; /* minutes west of Greenwich */
+       int tz_dsttime;     /* type of dst correction */
+     };
+
+static int gettimeofday (struct timeval *tv, struct timezone *tz);
+
+int getuid (void)
+{
+	return (0);
+}
+
+int geteuid (void)
+{
+	return (0);
+}
+
+int setuid (int u)
+{
+	(void)u;
+	return (0);
+}
+
+int seteuid (int u)
+{
+	(void)u;
+	return (0);
+}
+
+char *unicode_to_ascii_device (char* device)
+{
+	DWORD dwVersion;
+	DWORD dwWindowsMajorVersion;
+	char  dev[256] = "";
+
+	dwVersion = GetVersion();
+	dwWindowsMajorVersion =  (DWORD)(LOBYTE(LOWORD(dwVersion)));
+
+	if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4)  /* Windows '95 */
+	{
+		strncpy (dev, device, sizeof(dev)-1);
+		device [sizeof(dev)-1] = '\0';
+	}
+	else
+	{
+		int i, j;
+		for (i = 0, j = 0; i < sizeof(dev)/2; i++)
+		{
+			if (device[i] == '\0' && device[i+1] == '\0')
+				break;
+			if (device[i])
+				dev[j++] = device[i];
+		}
+		dev[j] = '\0';
+	}
+	return strdup (dev);
+}
+
+#define pcap_version pcap_lib_version()
+
+#else   /* WIN32 */
+
+extern char pcap_version[];    /* WinPcap doesn't have this */
+extern int errno;              /* A macro on Windows */
+#endif

 /*
  * fatal() and pfatal() are useful stdarg functions from
@@ -273,9 +347,22 @@

 void pfatal(char *err)
 {
+#ifdef WIN32
+	char buf[1024] = "unknown error";
+	int  error = WSAGetLastError();
+
+	debug("WS-error == %d\n", error);
+	fflush(stdout);
+	if (err)
+	   fprintf(stderr, "%s: ", err);
+	FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, error,
+			LANG_NEUTRAL, buf, sizeof(buf), NULL);
+	fprintf(stderr, "%s\n", buf);
+#else
 	debug("errno == %d\n", errno);
 	fflush(stdout);
 	perror(err);
+#endif
 	exit(1);
 }

@@ -534,6 +621,7 @@

 void getinterfaces(void)
 {
+#ifndef WIN32
 	struct interface_entry *p;
 	struct ifconf ifc;
 	struct ifreq *ifrp, ifr;
@@ -672,6 +760,7 @@

 	free(ifc.ifc_buf);
 	debug("leaving getinterfaces()\n");
+#endif   /* WIN32 */
 }

 /*
@@ -701,7 +790,7 @@
 	if (getsockname(s, (struct sockaddr *)&sinsrc, &size) < 0)
 		pfatal("getsockname");

-	close(s);
+	CLOSE_SOCK(s);
 	debug("Determined source address of %s to reach %s\n",
 		iptos(sinsrc.sin_addr.s_addr), iptos(dest));
 	return sinsrc.sin_addr.s_addr;
@@ -764,7 +853,7 @@
 	if ((getsockname(s, (struct sockaddr *)&in, &insize)) < 0)
 		pfatal("getsockname");

-	close(s);
+	CLOSE_SOCK(s);
 	return ntohs(in.sin_port);
 }

@@ -985,9 +1074,15 @@

 	if (device == NULL)
 	{
+#ifdef WIN32
+		device = pcap_lookupdev(errbuf);
+		if (device)
+			device = unicode_to_ascii_device(device);
+#else
 		/* couldn't find an appropriate interface */
 		warn("Could not determine appropriate device; resorting to pcap_lookupdev()\n");
 		device = pcap_lookupdev(errbuf);
+#endif
 	}

 	if (device == NULL)
@@ -1132,10 +1227,19 @@
 	if (pcap_setfilter(pcap, &fcode) < 0)
 		fatal("pcap_setfilter failed\n");

+	/* setting non-blocking mode on WinPcap is a terrible CPU hog. Hence use
+	 * the read-timeout (10msec) specified in pcap_open_live()
+	 */
+#ifndef WIN32
+#ifdef HAVE_PCAP_SETNONBLOCK
+	if (pcap_setnonblock (pcap, 1, errbuf) < 0)
+		fatal("pcap_setnonblock() failed: %s", errbuf);
+#else
 	pcap_fd = pcap_fileno(pcap);
 	if (fcntl(pcap_fd, F_SETFL, O_NONBLOCK) < 0)
 		pfatal("fcntl(F_SETFL, O_NONBLOCK) failed");
-
+#endif
+#endif /* WIN32 */
 	pcap_freecode(&fcode);
 }

@@ -1392,6 +1496,7 @@

 		if ((packet = (u_char *)pcap_next(pcap, &packet_hdr)) == NULL)
 		{
+			if (!o_noselect)
 			debug("null pointer from pcap_next()\n");
 			continue;
 		}
@@ -1774,7 +1879,8 @@
 	o_nofilter = 0;
 	o_nogetinterfaces = 0;

-#ifdef NOSELECT_DEFAULT
+	/* Win32's select() cannot handle pcap_fd */
+#if defined(NOSELECT_DEFAULT) || defined(WIN32)
 	o_noselect = 1;
 #else
 	o_noselect = 0;
@@ -1825,6 +1931,7 @@
 			continue;
 		}

+#ifndef WIN32
 		/* undocumented, for debugging only */
 		if (CHECKLONG("--select"))
 		{
@@ -1832,7 +1939,7 @@
 			debug("o_noselect disabled\n");
 			continue;
 		}
-
+#endif
 		if (CHECKLONG("--track-id") ||
 			CHECKLONG("--track-ipid"))
 		{
@@ -2009,3 +2116,23 @@
 #endif
 	return exitcode;
 }
+
+#ifdef WIN32
+static int gettimeofday (struct timeval *tv, struct timezone *tz)
+{
+   struct _timeb tb;
+
+   if (!tv)
+      return (-1);
+
+  _ftime (&tb);
+  tv->tv_sec  = tb.time;
+  tv->tv_usec = tb.millitm * 1000 + 500;
+  if (tz)
+  {
+    tz->tz_minuteswest = -60 * _timezone;
+    tz->tz_dsttime = _daylight;
+  }
+  return (0);
+}
+#endif