Gisle Vanem on 19 Apr 2004 14:15:02 -0000 |
> 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
|
|