From 02397959b3f637f994710fa1640aad96bc473e81 Mon Sep 17 00:00:00 2001 From: fyodor Date: Wed, 10 Aug 2005 04:16:18 +0000 Subject: [PATCH] removed winip lib --- CHANGELOG | 4 + Makefile.in | 2 +- NmapOps.cc | 10 +- docs/nmap.usage.txt | 2 +- idle_scan.cc | 10 +- libdnet-stripped/include/dnet/intf.h | 2 + libdnet-stripped/libdnet-stripped.vcproj | 2 +- libdnet-stripped/src/eth-win32.c | 61 +- libdnet-stripped/src/intf-win32.c | 70 ++ libpcap-possiblymodified/NMAP_MODIFICATIONS | 3 + libpcre/libpcre.vcproj | 4 +- mswin32/nmap.sln | 9 - mswin32/nmap.vcproj | 105 +- mswin32/winclude.h | 4 - mswin32/winfix.cc | 181 ++- mswin32/winfix.h | 25 + mswin32/winip/pcapsend.c | 1201 ------------------- mswin32/winip/snmp95.cpp | 434 ------- mswin32/winip/snmpapi.cpp | 116 -- mswin32/winip/winip.h | 197 --- nmap.cc | 46 +- nmap_winconfig.h | 2 +- osscan.cc | 17 +- scan_engine.cc | 8 +- targets.cc | 10 +- tcpip.cc | 189 ++- tcpip.h | 5 +- 27 files changed, 379 insertions(+), 2340 deletions(-) delete mode 100644 mswin32/winip/pcapsend.c delete mode 100644 mswin32/winip/snmp95.cpp delete mode 100644 mswin32/winip/snmpapi.cpp delete mode 100644 mswin32/winip/winip.h diff --git a/CHANGELOG b/CHANGELOG index 925ba1621..9c5a9ac20 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,10 @@ Nmap 3.83DC13 +o Removed WinIP library (and all Windows raw sockets code) since MS + has gone and broken raw sockets. Maybe packet receipt via raw + sockets will come back at some point. + o Added the ability for Nmap to send and properly route raw ethernet packets cointaining IP datagrams rather than always sending the packets via raw sockets. This is particularly useful for Windows, diff --git a/Makefile.in b/Makefile.in index c66e33a10..804124427 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,4 +1,4 @@ -export NMAP_VERSION = 3.83.DC15 +export NMAP_VERSION = 3.83.DC17 NMAP_NAME= nmap NMAP_URL= http://www.insecure.org/nmap/ NMAP_PLATFORM=@host@ diff --git a/NmapOps.cc b/NmapOps.cc index 1831eb384..d7a978d2b 100644 --- a/NmapOps.cc +++ b/NmapOps.cc @@ -101,6 +101,7 @@ #include "nmap.h" #include "nbase.h" #include "NmapOps.h" +#include "winfix.h" NmapOps o; @@ -185,7 +186,6 @@ void NmapOps::Initialize() { # endif // __amigaos__ #else isr00t = 1; - winip_init(); /* wrapper for all win32 initialization */ #endif debugging = DEBUGGING; verbose = DEBUGGING; @@ -356,7 +356,7 @@ void NmapOps::ValidateOptions() { #ifndef WIN32 fatal("You requested a scan type which requires r00t privileges, and you do not have them.\n"); #else - winip_barf(0); + win_barf(0); #endif } @@ -364,7 +364,7 @@ void NmapOps::ValidateOptions() { #ifndef WIN32 fatal("Sorry, but you've got to be r00t to use decoys, boy!"); #else - winip_barf(0); + win_barf(0); #endif } @@ -372,7 +372,7 @@ void NmapOps::ValidateOptions() { #ifndef WIN32 fatal("Sorry, but fragscan requires r00t privileges\n"); #else - winip_barf(0); + win_barf(0); #endif } @@ -380,7 +380,7 @@ void NmapOps::ValidateOptions() { #ifndef WIN32 fatal("TCP/IP fingerprinting (for OS scan) requires root privileges which you do not appear to possess. Sorry, dude.\n"); #else - winip_barf(0); + win_barf(0); #endif } } diff --git a/docs/nmap.usage.txt b/docs/nmap.usage.txt index 8cb32d3a3..9f81be9ed 100644 --- a/docs/nmap.usage.txt +++ b/docs/nmap.usage.txt @@ -1,4 +1,4 @@ -Nmap 3.83.DC15 Usage: nmap [Scan Type(s)] [Options] +Nmap 3.83.DC16 Usage: nmap [Scan Type(s)] [Options] Some Common Scan Types ('*' options require root privileges) * -sS TCP SYN stealth port scan (default if privileged (root)) -sT TCP connect() port scan (default for unprivileged users) diff --git a/idle_scan.cc b/idle_scan.cc index dbbbd2d72..8873453d1 100644 --- a/idle_scan.cc +++ b/idle_scan.cc @@ -123,11 +123,6 @@ extern NmapOps o; -/* predefined filters -- I need to kill these globals at some point. */ -extern unsigned long flt_dsthost, flt_srchost; -extern unsigned short flt_baseport; - - struct idle_proxy_info { Target host; /* contains name, IP, source IP, timing info, etc. */ int seqclass; /* IPID sequence class (IPID_SEQ_* defined in nmap.h) */ @@ -391,13 +386,10 @@ void initialize_idleproxy(struct idle_proxy_info *proxy, char *proxyName, snprintf(filter, sizeof(filter), "tcp and src host %s and dst host %s and src port %hu", p, q, proxy->probe_port); free(p); free(q); - set_pcap_filter(proxy->host.deviceName(), proxy->pd, flt_icmptcp, filter); + set_pcap_filter(proxy->host.deviceName(), proxy->pd, filter); /* Windows nonsense -- I am not sure why this is needed, but I should get rid of it at sometime */ - flt_srchost = proxy->host.v4source().s_addr; - flt_dsthost = proxy->host.v4host().s_addr; - sequence_base = get_random_u32(); /* Yahoo! It is finally time to send our pr0beZ! */ diff --git a/libdnet-stripped/include/dnet/intf.h b/libdnet-stripped/include/dnet/intf.h index 0ce848dd4..778fed900 100644 --- a/libdnet-stripped/include/dnet/intf.h +++ b/libdnet-stripped/include/dnet/intf.h @@ -60,9 +60,11 @@ intf_t *intf_open(void); int intf_get(intf_t *i, struct intf_entry *entry); int intf_get_src(intf_t *i, struct intf_entry *entry, struct addr *src); int intf_get_dst(intf_t *i, struct intf_entry *entry, struct addr *dst); +int intf_get_pcap_devname(const char *ifname, char *pcapdev, int pcapdevlen); int intf_set(intf_t *i, const struct intf_entry *entry); int intf_loop(intf_t *i, intf_handler callback, void *arg); intf_t *intf_close(intf_t *i); + __END_DECLS #endif /* DNET_INTF_H */ diff --git a/libdnet-stripped/libdnet-stripped.vcproj b/libdnet-stripped/libdnet-stripped.vcproj index 310e4cb21..ae43dca45 100755 --- a/libdnet-stripped/libdnet-stripped.vcproj +++ b/libdnet-stripped/libdnet-stripped.vcproj @@ -23,7 +23,7 @@ PreprocessorDefinitions="WIN32;_DEBUG;_LIB" MinimalRebuild="TRUE" BasicRuntimeChecks="3" - RuntimeLibrary="1" + RuntimeLibrary="5" UsePrecompiledHeader="0" WarningLevel="3" Detect64BitPortabilityProblems="TRUE" diff --git a/libdnet-stripped/src/eth-win32.c b/libdnet-stripped/src/eth-win32.c index e3ebffb40..c33c56fbc 100644 --- a/libdnet-stripped/src/eth-win32.c +++ b/libdnet-stripped/src/eth-win32.c @@ -40,71 +40,14 @@ struct adapter { /* XXX */ extern const char *intf_get_desc(intf_t *intf, const char *device); - eth_t * eth_open(const char *device) { eth_t *eth; - int i; - intf_t *intf; - struct intf_entry ie; - pcap_if_t *pcapdevs; - pcap_if_t *pdev; - char pname[64]; - struct sockaddr_in devip; - pcap_addr_t *pa; - - if ((intf = intf_open()) == NULL) - return (NULL); + char pname[128]; - pname[0] = '\0'; - memset(&ie, 0, sizeof(ie)); - strlcpy(ie.intf_name, device, sizeof(ie.intf_name)); - if (intf_get(intf, &ie) != 0) { - intf_close(intf); + if (intf_get_pcap_devname(device, pname, sizeof(pname)) != 0) return NULL; - } - intf_close(intf); - - /* Find the first IPv4 address for ie */ - if (ie.intf_addr.addr_type == ADDR_TYPE_IP) { - addr_ntos(&ie.intf_addr, (struct sockaddr *) &devip); - } else { - for(i=0; i < (int) ie.intf_alias_num; i++) { - if (ie.intf_alias_addrs[i].addr_type == ADDR_TYPE_IP) { - addr_ntos(&ie.intf_alias_addrs[i], (struct sockaddr *) &devip); - break; - } - if (i == ie.intf_alias_num) - return NULL; // Failed to find IPv4 address, which is currently a requirement - } - } - - /* Next we must find the pcap device name corresponding to the device. - The device description used to be compared with those from PacketGetAdapterNames(), but - that was unrelaible because dnet and pcap sometimes give different descriptions. For example, - dnet gave me "AMD PCNET Family PCI Ethernet Adapter - Packet Scheduler Miniport" for one of my - adapters (in vmware), while pcap described it as "VMware Accelerated AMD PCNet Adapter (Microsoft's - Packet Scheduler)". Plus, Packet* functions aren't really supported for external use by the - WinPcap folks. So I have rewritten this to compare interface addresses (which has its own - problems -- what if you want to listen an an interface with no IP address set?) --Fyodor */ - if (pcap_findalldevs(&pcapdevs, NULL) == -1) - return NULL; - - for(pdev=pcapdevs; pdev && !pname[0]; pdev = pdev->next) { - for (pa=pdev->addresses; pa && !pname[0]; pa = pa->next) { - if (pa->addr->sa_family != AF_INET) - continue; - if (((struct sockaddr_in *)pa->addr)->sin_addr.s_addr == devip.sin_addr.s_addr) { - strlcpy(pname, pdev->name, sizeof(pname)); /* Found it -- Yay! */ - break; - } - } - } - - pcap_freealldevs(pcapdevs); - - if (!pname[0]) return NULL; /* Found no matching interface */ if ((eth = calloc(1, sizeof(*eth))) == NULL) return (NULL); diff --git a/libdnet-stripped/src/intf-win32.c b/libdnet-stripped/src/intf-win32.c index b62d08436..8f9974587 100644 --- a/libdnet-stripped/src/intf-win32.c +++ b/libdnet-stripped/src/intf-win32.c @@ -23,6 +23,7 @@ #include #include +#include "pcap.h" struct ifcombo { DWORD *idx; @@ -258,6 +259,75 @@ intf_get_desc(intf_t *intf, const char *name) return (desc); } +/* Converts a dnet interface name (ifname) to its pcap equivalent, which is stored in +pcapdev (up to a length of pcapdevlen). Returns 0 and fills in pcapdev if successful. */ +int intf_get_pcap_devname(const char *ifname, char *pcapdev, int pcapdevlen) { + int i; + intf_t *intf; + struct intf_entry ie; + pcap_if_t *pcapdevs; + pcap_if_t *pdev; + char pname[128]; + struct sockaddr_in devip; + pcap_addr_t *pa; + + if ((intf = intf_open()) == NULL) + return -1; + + pname[0] = '\0'; + memset(&ie, 0, sizeof(ie)); + strlcpy(ie.intf_name, ifname, sizeof(ie.intf_name)); + if (intf_get(intf, &ie) != 0) { + intf_close(intf); + return -1; + } + intf_close(intf); + + /* Find the first IPv4 address for ie */ + if (ie.intf_addr.addr_type == ADDR_TYPE_IP) { + addr_ntos(&ie.intf_addr, (struct sockaddr *) &devip); + } else { + for(i=0; i < (int) ie.intf_alias_num; i++) { + if (ie.intf_alias_addrs[i].addr_type == ADDR_TYPE_IP) { + addr_ntos(&ie.intf_alias_addrs[i], (struct sockaddr *) &devip); + break; + } + } + if (i == ie.intf_alias_num) + return -1; // Failed to find IPv4 address, which is currently a requirement + } + + /* Next we must find the pcap device name corresponding to the device. + The device description used to be compared with those from PacketGetAdapterNames(), but + that was unrelaible because dnet and pcap sometimes give different descriptions. For example, + dnet gave me "AMD PCNET Family PCI Ethernet Adapter - Packet Scheduler Miniport" for one of my + adapters (in vmware), while pcap described it as "VMware Accelerated AMD PCNet Adapter (Microsoft's + Packet Scheduler)". Plus, Packet* functions aren't really supported for external use by the + WinPcap folks. So I have rewritten this to compare interface addresses (which has its own + problems -- what if you want to listen an an interface with no IP address set?) --Fyodor */ + if (pcap_findalldevs(&pcapdevs, NULL) == -1) + return -1; + + for(pdev=pcapdevs; pdev && !pname[0]; pdev = pdev->next) { + for (pa=pdev->addresses; pa && !pname[0]; pa = pa->next) { + if (pa->addr->sa_family != AF_INET) + continue; + if (((struct sockaddr_in *)pa->addr)->sin_addr.s_addr == devip.sin_addr.s_addr) { + strlcpy(pname, pdev->name, sizeof(pname)); /* Found it -- Yay! */ + break; + } + } + } + + pcap_freealldevs(pcapdevs); + if (pname[0]) { + strlcpy(pcapdev, pname, pcapdevlen); + return 0; + } + return -1; +} + + int intf_get_src(intf_t *intf, struct intf_entry *entry, struct addr *src) { diff --git a/libpcap-possiblymodified/NMAP_MODIFICATIONS b/libpcap-possiblymodified/NMAP_MODIFICATIONS index ad535811c..5c2f95f54 100644 --- a/libpcap-possiblymodified/NMAP_MODIFICATIONS +++ b/libpcap-possiblymodified/NMAP_MODIFICATIONS @@ -10,6 +10,9 @@ o Renamed configure.in to configure.ac, which is the name now recommended by the autoconf project. o Removed the .cvsignore file, all 'CVS' directories, the 'packaging' directory, and the install-sh script. + +o Rewrote Win32 version of eth_open() as the previous verson didn't + work on any of my Windows machines. o Added the gcc debugging flag (-g) to aclocal.m4 if gcc is being used: --- libpcap-0.8.3/aclocal.m4 2003-11-16 01:45:51.000000000 -0800 diff --git a/libpcre/libpcre.vcproj b/libpcre/libpcre.vcproj index aa0df37e4..de82d47ee 100644 --- a/libpcre/libpcre.vcproj +++ b/libpcre/libpcre.vcproj @@ -22,7 +22,7 @@ PreprocessorDefinitions="WIN32;_DEBUG;_LIB" MinimalRebuild="TRUE" BasicRuntimeChecks="3" - RuntimeLibrary="1" + RuntimeLibrary="5" UsePrecompiledHeader="0" WarningLevel="3" Detect64BitPortabilityProblems="FALSE" @@ -61,7 +61,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -403,14 +313,11 @@ - - + RelativePath=".\winfix.h"> #include -#include "nmap_error.h" + +#include "..\nmap.h" +#include "..\tcpip.h" +#include "winfix.h" +#include "..\NmapOps.h" +#include "..\nmap_error.h" + +#ifdef _MSC_VER +# include +#endif + +#ifdef _MSC_VER +#define DLI_ERROR VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND) +#endif + +/* delay-load hooks only for troubleshooting */ +#ifdef _MSC_VER +static int dli_done = 0; +static FARPROC WINAPI winip_dli_fail_hook(unsigned code, PDelayLoadInfo info); +#endif + +extern NmapOps o; + +int pcap_avail = 0; + +/* internal functions */ +static void win_cleanup(void); +static char pcaplist[4096]; + +void win_barf(const char *msg) +{ + if(msg) printf("%s\n\n", msg); + printf("\nYour system doesn't have iphlpapi.dll\n\nIf you have Win95, " + "maybe you could grab it from a Win98 system\n" + "If you have NT4, you need service pack 4 or higher\n" + "If you have NT3.51, try grabbing it from an NT4 system\n" + "Otherwise, your system has problems ;-)\n"); + exit(0); +} + +void win_init() +{ + // variables + DWORD cb = 0; + DWORD nRes; + OSVERSIONINFOEX ver; + PMIB_IPADDRTABLE pIp = 0; + int i; + int numipsleft; + WORD werd; + WSADATA data; + + werd = MAKEWORD( 2, 2 ); + if( (WSAStartup(werd, &data)) !=0 ) + fatal("failed to start winsock.\n"); + + ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); + if(!GetVersionEx((LPOSVERSIONINFO)&ver)) + { + ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + if(!GetVersionEx((LPOSVERSIONINFO)&ver)) + fatal("GetVersionEx failed\n"); + + ver.wServicePackMajor = 0; + ver.wServicePackMinor = 0; + } + + + // Try to initialize winpcap +#ifdef _MSC_VER + __try +#endif + { + ULONG len = sizeof(pcaplist); + + pcap_avail = 1; + if(o.debugging > 2) printf("***WinIP*** trying to initialize winpcap 2.1\n"); + PacketGetAdapterNames(pcaplist, &len); + if(o.debugging) + printf("***WinIP*** winpcap present, dynamic linked to: %s\n", pcap_lib_version()); + } +#ifdef _MSC_VER + __except(GetExceptionCode() == DLI_ERROR) + { + pcap_avail = 0; + printf("WARNING: Failed to locate Winpcap. Nmap may not function properly until this is installed! WinPcap is freely available from http://winpcap.polito.it.\n"); + } +#endif + + // Check for a wpcap.dll (so we don't crash on old winpcap + // But only with VC++.NET, since old versions do not + // provide this functionality :( +#if defined(_MSC_VER) && _MSC_VER >= 1300 + if(pcap_avail) + { + if(FAILED(__HrLoadAllImportsForDll("wpcap.dll"))) + { + error("WARNING: your winpcap is too old to use. Nmap may not function.\n"); + pcap_avail = 0; + } + } +#endif + + o.isr00t = pcap_avail; + atexit(win_cleanup); + + // Mark load as complete so that dli errors are handled +#ifdef _MSC_VER + dli_done = 1; +#endif +} + + +static void win_cleanup(void) +{ + WSACleanup(); +} + +typedef DWORD (__stdcall *PGBI)(IPAddr, PDWORD); + +#ifdef _MSC_VER +static FARPROC WINAPI winip_dli_fail_hook(unsigned code, PDelayLoadInfo info) +{ + if(o.debugging) + { + printf("***WinIP*** delay load error:\n"); + switch(code) + { + case dliFailLoadLib: + printf(" failed to load dll: %s\n", info->szDll); + break; + + case dliFailGetProc: + printf(" failed to load "); + if(info->dlp.fImportByName) + printf("function %s", info->dlp.szProcName + 2); + else printf("ordinal %d", info->dlp.dwOrdinal); + printf(" in dll %s\n", info->szDll); + break; + + default: + printf(" unknown error\n"); + break; + } + } + + if(dli_done) + { + printf("******* Unexpected delay-load failure *******\n"); + + switch(code) + { + case dliFailLoadLib: + printf(" failed to load dll: %s\n", info->szDll); + if(!stricmp(info->szDll, "wpcap.dll")) + printf(" this is most likely because you have" + " winpcap 2.0 (2.1 or later is required)\n" + "Get it from http://netgroup-serv.polito.it/winpcap\n"); + break; + + case dliFailGetProc: + printf(" failed to load "); + if(info->dlp.fImportByName) + printf("function %s", info->dlp.szProcName + 2); + else printf("ordinal %d", info->dlp.dwOrdinal); + printf(" in dll %s\n", info->szDll); + break; + + default: + printf(" unknown error\n"); + break; + } + } + + return 0; +} +#endif // _MSC_VER + + int my_close(int sd) { - if(sd == 501) return 0; return closesocket(sd); } diff --git a/mswin32/winfix.h b/mswin32/winfix.h index 8b1378917..4f6578be7 100644 --- a/mswin32/winfix.h +++ b/mswin32/winfix.h @@ -1 +1,26 @@ +#ifndef WINFIX_H +#define WINFIX_H + +#include +#include +#include +#include + +#ifndef EXTERNC +# ifdef __cplusplus +# define EXTERNC extern "C" +# else +# define EXTERNC extern +# endif +#endif + +// windows-specific options + +#include + +/* (exported) functions */ +EXTERNC void win_init(); +EXTERNC void win_barf(const char *msg); +#endif + diff --git a/mswin32/winip/pcapsend.c b/mswin32/winip/pcapsend.c deleted file mode 100644 index bbbc4ec67..000000000 --- a/mswin32/winip/pcapsend.c +++ /dev/null @@ -1,1201 +0,0 @@ -/* - -pcapsend.c: raw IP sends using winpcap -Copyright (C) 2000 Andy Lutomirski - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License, version 2.1, as published by the Free Software -Foundation, with the exception that if this copy of the library -is distributed under the Lesser GNU Public License (as opposed -to the ordinary GPL), you may ignore section 6b, and that all -copies distributed without exercising section 3 must retain this -paragraph in its entirety. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Implements raw sends using winpcap. -Not as easy as it sounds... - -Note: this was inspired by ryan@eeye.com's attempt to -do the same thing. It no longer bears much (any?) -resemblance to the original. This version uses no -registry calls or undoc'd features, and works on 98, -NT4, W2K, and probably Me. (Ryan's didn't work on -98, or, as far as I can tell, Win2K). - -Routing is done with GetBestRoute, or a homebrew version -for NT4. ARP is in a separate thread to avoid issues -when scanning multiple hosts. There is a slight ARP -latency issue (250ms max). - -Performance when scanning multiple local hosts will go -down the drain if o.maxparallelism > FAILCACHELEN and -there are lots of continuous down hosts. Oh, well. - -Lastly, a question for Fyodor: is WSAEHOSTUNREACH a good -error return for a failed ARP query? (It should convince -nmap not to try the host again, while not confusing nmap.) - -Update 12/08/04: Dana Epp (dana_at_vulscan.com) sdded SendARP stuff -for XP firewall (on by default w/SP2) - -*/ - -#include "..\tcpip.h" -#include "..\..\NmapOps.h" -#include "winip.h" - -#define MAXARPTRIES 3 -#define ARPINTERVAL 200 // should be _less_ than a multiple of POLLINTERVAL -#define POLLINTERVAL 250 -#define FAILCACHELEN 25 // make it high -#define ARPCACHELEN 25 - -void pcapsend_init(); - -#ifdef _DEBUG -//#define THREAD_DEBUG 1 -#endif - -#define REALSEND_WATCH - -static void pcapsend_cleanup(void); - -static int realsend(LPADAPTER pAdap, - const char *packet, int len, - BYTE *to, BYTE *from, int addrlen, - DWORD linktype, DWORD protocol); - -#define ETH_IP 0x0800 -#define ETH_ARP 0x0806 - - -#if defined(THREAD_DEBUG) && THREAD_DEBUG > 1 -#define foo0 printf -#define foo1 printf -#define foo2 printf -#else -#define foo0(x) ((void)0) -#define foo1(x,y) ((void)0) -#define foo2(x,y,z) ((void)0) -#endif - -static int pcapsend_inited = 0; - -static LPADAPTER if2adapter(int ifi, BYTE* phys, int *physlen, DWORD *type); -static void cleanup_if_cache(); - -// -1 on failure -static int ip2route(const struct in_addr *dest, DWORD *nexthop, DWORD *ifi); - -static void releaseadapter(); - -static void send_arp(DWORD ifi, DWORD ip); -static void send_raw_arp(DWORD ifi, DWORD ip); -static int lookupip(DWORD ip, DWORD ifi); - -// ARP cache -static void AddToARPCache(DWORD ip, int ifi, BYTE *phys, int physlen); -static int SearchARP(DWORD ip, int ifi, BYTE *phys, int *physlen); - - -static CRITICAL_SECTION csAdapter, csQueue, csFailCache, csArpCache, csArpTable; -static HANDLE hEvWakeup, hThread, hSemQueue; -static int killthread = 0; - -// For rawsock fallback -extern SOCKET global_raw_socket; -extern int rawsock_avail; -extern int iphlp_avail; - -extern NmapOps o; - -#define SENDQUEUE_LEN 10 // max outstanding ARP's - -struct ethernet_hdr -{ -#ifndef ETHER_ADDR_LEN -#define ETHER_ADDR_LEN 6 -#endif - u_char ether_dhost[ETHER_ADDR_LEN]; /* destination ethernet address */ - u_char ether_shost[ETHER_ADDR_LEN]; /* source ethernet address */ - u_short ether_type; /* packet type ID */ -}; - -struct arp_hdr -{ - u_short ar_hrd; /* format of hardware address */ -#define ARPHRD_ETHER 1 /* ethernet hardware format */ - u_short ar_pro; /* format of protocol address */ - u_char ar_hln; /* length of hardware address */ - u_char ar_pln; /* length of protocol addres */ - u_short ar_op; /* operation type */ -#define ARPOP_REQUEST 1 /* req to resolve address */ -#define ARPOP_REPLY 2 /* resp to previous request */ -#define ARPOP_REVREQUEST 3 /* req protocol address given hardware */ -#define ARPOP_REVREPLY 4 /* resp giving protocol address */ -#define ARPOP_INVREQUEST 8 /* req to identify peer */ -#define ARPOP_INVREPLY 9 /* resp identifying peer */ - - /* - * These should implementation defined but I've hardcoded eth/IP. - */ - u_char ar_sha[6]; /* sender hardware address */ - u_char ar_spa[4]; /* sender protocol address */ - u_char ar_tha[6]; /* target hardware address */ - u_char ar_tpa[4]; /* target protocol address */ -}; - -static int build_ethernet(u_char *dst, u_char *src, u_short type, const u_char *payload, int payload_s, u_char *buf) -{ - struct ethernet_hdr eth_hdr; - - if (!buf) - { - return (-1); - } - - memcpy(eth_hdr.ether_dhost, dst, ETHER_ADDR_LEN); /* destination address */ - memcpy(eth_hdr.ether_shost, src, ETHER_ADDR_LEN); /* source address */ - eth_hdr.ether_type = htons(type); /* packet type */ - - if (payload && payload_s) - { - /* - * Unchecked runtime error for buf + ETH_H payload to be greater than - * the allocated heap memory. - */ - memcpy(buf + 14, payload, payload_s); - } - memcpy(buf, ð_hdr, sizeof(eth_hdr)); - return (1); -} - -// assumes Ethernet -static int realsend(LPADAPTER pAdap, - const char *packet, int len, - BYTE *to, BYTE *from, int addrlen, - DWORD linktype, DWORD protocol) -{ - u_char packetbuf[2048]; - LPPACKET lpPacket; - -#ifdef REALSEND_WATCH - if(o.debugging > 2) - { - int i; - printf("realsend: %d bytes ", len); - for(i = 0; i < addrlen; i++) - printf("%02X", from[i]); - printf(" => "); - for(i = 0; i < addrlen; i++) - printf("%02X", to[i]); - printf(" (link %d, proto %d)\n", linktype, protocol); - } -#endif - - memset(packetbuf,0,2048); - - if(addrlen != 6) - fatal("realsend: non-ethernet address\n"); - - build_ethernet(to, from, protocol, (unsigned char *) packet, len, packetbuf); - - if((lpPacket = PacketAllocatePacket())==NULL) - { - printf("\nError:failed to allocate the LPPACKET structure."); - return (-1); - } - - PacketInitPacket(lpPacket, packetbuf, len+14); - if(!PacketSendPacket(pAdap, lpPacket, TRUE)) - { - if(o.debugging) - printf("realsend: synchronous send failed (%d)\n", GetLastError()); - } - PacketFreePacket(lpPacket); - - return (len); -} - -// The queue -#define Q_PACKET_SIZE(x) (x + sizeof(int) + sizeof(struct _Q_PACKET)) -typedef struct _Q_PACKET { - int len; - struct _Q_PACKET *next; - BYTE data[1]; -} Q_PACKET; - -typedef struct _Q_ROUTE { - DWORD ip; - int numpackets; - int tries, timelasttry, timefirsttry; - Q_PACKET *head, *tail; - int ifi; // -1 for free -} Q_ROUTE; - -typedef struct _Q_FREE { - struct _Q_FREE *next; -} Q_FREE; - -typedef struct _Q_FAIL { - DWORD ip; - int ifi; -} Q_FAIL; - -Q_FAIL failcache[FAILCACHELEN]; -int failfirst = 0; // 0 <= failfirst < FAILCACHELEN - -typedef struct _Q_ARP { - DWORD ip; - int ifi; - BYTE phys[MAXLEN_PHYSADDR]; - int physlen; -} Q_ARP; - -Q_ARP arpcache[ARPCACHELEN]; -int arpfirst = 0; // 0 <= arpfirst < ARPCACHELEN - -PMIB_IPNETTABLE pArpTable; -unsigned long arpalloclen; -int arprefresh = 1; - -// statistics -static int totaltimetofail = 0; -static int numfails = 0; -static int maxfailtime = 0; -static long queuelen = 0; - -// The actual structure -static Q_ROUTE sendqueue[SENDQUEUE_LEN]; -static Q_FREE *nextfree = 0; // protected by the hSemQueue - -// The send thread -static unsigned int WINAPI SendThreadProc(LPVOID unused0) -{ - // this thread manages send ops - -/* the cycle: - - 1. acquire the queue - 2. loop the routes - 2a. is it resolved? then send it - 2b. have 200 ms elapsed since last try? then send an ARP - 2c. have we timed out (3 tries, 600ms)? then kill it - 3. release the queue - 4. wait for 250ms or hEvWakeup - */ - -#ifdef _MSC_VER -__try { -#endif - - while(!killthread) - { - int nRes; - int i; - DWORD time; - - arprefresh = (queuelen ? 1 : 0); - - time = GetTickCount(); // handle the wrap correctly - -// Step 1: acquire the queue - foo0("sendthread: try acquire csQueue\n"); - EnterCriticalSection(&csQueue); - foo0("sendthread: acquired csQueue\n"); - -// Step 2: loop the routes - for(i = 0; i < SENDQUEUE_LEN; i++) - { - BYTE phys[MAXLEN_PHYSADDR]; - int physlen = MAXLEN_PHYSADDR; - if(sendqueue[i].ifi == -1) continue; // free - -// Step 2a: is it resolved? - if(0 == SearchARP(sendqueue[i].ip, sendqueue[i].ifi, - phys, &physlen)) - { - // we got it! - Q_FREE *f; - Q_PACKET *p = sendqueue[i].head; - BYTE myphys[MAXLEN_PHYSADDR]; - int myphyslen = MAXLEN_PHYSADDR; - unsigned long mytype; - LPADAPTER pAdap; - -#ifdef THREAD_DEBUG - printf("sendthread: resolved %s\n", inet_ntoa(*(struct in_addr*)&sendqueue[i].ip)); -#endif - - pAdap = if2adapter(sendqueue[i].ifi, - myphys, &myphyslen, &mytype); - if(!pAdap) fatal("if2adapter failed?!?\n"); - while(p) - { - Q_PACKET *next = p->next; - realsend(pAdap, (char *) p->data, p->len, phys, - myphys, myphyslen, mytype, ETH_IP); - free(p); - p = next; - } - f = (Q_FREE*)&sendqueue[i]; - sendqueue[i].ifi = -1; - f->next = nextfree; - nextfree = f; - releaseadapter(); - - // notify that we have a free - InterlockedDecrement(&queuelen); - ReleaseSemaphore(hSemQueue, 1, 0); - } - -// Step 2b: should we try again? - else if(sendqueue[i].tries < MAXARPTRIES - && sendqueue[i].timelasttry <= time - ARPINTERVAL) - { - // try again - send_arp(sendqueue[i].ifi, sendqueue[i].ip); - sendqueue[i].tries++; - sendqueue[i].timelasttry = time; - } - -// Step 2c: should we kill it? - else if((sendqueue[i].tries >= MAXARPTRIES - && sendqueue[i].timelasttry <= time - ARPINTERVAL)) - { - // kill it - Q_FREE *f; - Q_PACKET *p = sendqueue[i].head; - while(p) - { - Q_PACKET *next = p->next; - free(p); - p = next; - } - - // cache the failure - foo0("sendthread: try acquire csFailCache\n"); - EnterCriticalSection(&csFailCache); - foo0("sendthread: acquired csFailCache\n"); - failcache[failfirst].ifi = sendqueue[i].ifi; - failcache[failfirst].ip = sendqueue[i].ip; - failfirst = (failfirst + 1) % FAILCACHELEN; - LeaveCriticalSection(&csFailCache); - - // gather stats - numfails++; - totaltimetofail += (time - sendqueue[i].timefirsttry); - if((time - sendqueue[i].timefirsttry) > maxfailtime) - maxfailtime = (time - sendqueue[i].timefirsttry); - -#ifdef THREAD_DEBUG - printf("sendthread: %s failed (avg = %lu ms; max = %lu ms)\n", - inet_ntoa(*(struct in_addr*)&sendqueue[i].ip), - totaltimetofail / numfails, maxfailtime); -#endif - - // free it - f = (Q_FREE*)&sendqueue[i]; - sendqueue[i].ifi = -1; - f->next = nextfree; - nextfree = f; - - // and notify that we have a free - InterlockedDecrement(&queuelen); - ReleaseSemaphore(hSemQueue, 1, 0); - } - // else do nothing - } - -// Step 3: release the queue - LeaveCriticalSection(&csQueue); - -// Step 4: wait - // yah yah I know... but i'm too lazy to fix this - WaitForSingleObject(hEvWakeup, POLLINTERVAL); - } - -#ifdef _MSC_VER -} __except(printf("\n\n***** ERROR IN SEND THREAD *****\n\n"), - EXCEPTION_CONTINUE_SEARCH) {} -#endif - - return 0; -} - -// helpers -static void AddPacketToQueue(const void *data, int len, DWORD ip, int ifi) -{ - int i; - Q_ROUTE *r; - Q_PACKET *p; - -begin: - // Is it already there? - EnterCriticalSection(&csQueue); - for(i = 0; i < SENDQUEUE_LEN; i++) - { - if(sendqueue[i].ifi == ifi && sendqueue[i].ip == ip) - { - // We're good to go! - - if(sendqueue[i].numpackets >= 5) - { - // Alas, we need to wait so we don't kill the system - LeaveCriticalSection(&csQueue); - Sleep(500); // give it a chance - goto begin; - } - - p = (Q_PACKET*)malloc(Q_PACKET_SIZE(len)); - memcpy(p->data, data, len); - p->len = len; - p->next = 0; - -#ifdef _DEBUG - { - int foo = 0; - if(sendqueue[i].tail) foo++; - if(sendqueue[i].head) foo++; - if(sendqueue[i].numpackets) foo++; - if(foo != 0 && foo != 3) - fatal("corrupt packet cache\n"); - } -#endif - - if(sendqueue[i].tail) - sendqueue[i].tail->next = p; - else sendqueue[i].head = p; - sendqueue[i].tail = p; - sendqueue[i].numpackets++; - - LeaveCriticalSection(&csQueue); - return; - } - } - - // it's not already there -- leave the CS - LeaveCriticalSection(&csQueue); - - // get a spot in line - while(WAIT_TIMEOUT == WaitForSingleObject(hSemQueue, 10000)) - printf("addpackettoqueue: this is taking WAY too long (%lu/%lu)...\n", - queuelen, SENDQUEUE_LEN); - - // and write it - EnterCriticalSection(&csQueue); - - // we should grab a new route obj - if(!nextfree) fatal("where'd my block go?\n"); - r = (Q_ROUTE*)nextfree; - nextfree = nextfree->next; - r->ifi = ifi; - r->ip = ip; - r->numpackets = 1; - r->tries = 1; - r->timefirsttry = r->timelasttry = GetTickCount(); - send_arp(ifi, ip); // post the first try now - p = (Q_PACKET*)malloc(Q_PACKET_SIZE(len)); - if(!p) fatal("out of memory\n"); - r->head = p; - r->tail = p; - memcpy(p->data, data, len); - p->len = len; - p->next = 0; - InterlockedIncrement(&queuelen); -#ifdef THREAD_DEBUG - printf("addpacket: %s (len = %lu)\n", - inet_ntoa(*(struct in_addr*)&ip), queuelen); -#endif - LeaveCriticalSection(&csQueue); - - return; -} - -// this needs to change for non-Ethernet -static void send_arp(DWORD ifi, DWORD ip) -{ - /* Used to send raw ARP packet on the wire, and then read the result - out of the system cache. Kinda ugly, but anyway ... Windows - Firewall (default-on with XP SP2) started ignoring the responses - because it didn't send them (reasonable), thus breaking the - technique. Now the SendARP iphlpapi function is used. A - downside is that I believe it blocks, so it may cause - local-network ping scans to take much longer on Windows. I - suppose we should send raw and then read results from pcap. But - for now, we have this */ - HRESULT ret; - ULONG uMACAddr[2]; - ULONG uSize = 6; - PBYTE pBuffer; - struct in_addr myip; - - /* For windows95 machines that does not load iphlpapi.dll, send raw - ARP packet */ - if( !iphlp_avail ) - { - send_raw_arp(ifi,ip); - return; - } - - ret = SendARP( ip, 0, uMACAddr, &uSize ); - - if( NO_ERROR == ret ) - { - pBuffer = (PBYTE)uMACAddr; - AddToARPCache( ip, ifi, pBuffer, (int)uSize ); - } -} - -// this to send raw arp packet -static void send_raw_arp(DWORD ifi, DWORD ip) -{ - struct arp_hdr arp_h; - LPADAPTER pAdap; - BYTE mymac[6]; - int len; - unsigned long mytype; - struct in_addr myip; - BYTE bcastmac[6]; // more Ethernet code ! - memset(bcastmac, 0xFF, 6); - - if(0 != ifi2ipaddr(ifi, &myip)) - fatal("sendarp: failed to find my ip ?!?\n"); - - // get the MAC et al - len = 6; - pAdap = if2adapter(ifi, mymac, &len, &mytype); - if(!pAdap) - { - // do nothing for localhost scan - if(myip.s_addr == 0x0100007f) return; - else fatal("send_arp: can't send on this interface\n"); - } - - arp_h.ar_hrd=0x0100; - - arp_h.ar_pro=0x0008; /* format of protocol address */ - arp_h.ar_hln=6; /* length of hardware address */ - arp_h.ar_pln=4; /* length of protocol addres */ - arp_h.ar_op=0x0100 ; - memcpy(arp_h.ar_sha,mymac,6); - memcpy(arp_h.ar_spa,&myip.s_addr,4); - memset(arp_h.ar_tha,0,6); - memcpy(arp_h.ar_tpa,&ip,4); - - realsend(pAdap, (char*)&arp_h, sizeof(arp_h), - bcastmac, mymac, len, mytype, ETH_ARP); - - releaseadapter(); -} - -// resolves an ip addr into a nexthop and index -static int ip2route(const struct in_addr *dest, DWORD *nexthop, DWORD *ifi) -{ - static DWORD last_ip = 0; - static int last_nexthop; - static int last_ifi; - - MIB_IPFORWARDROW route; - - // check the cache - if(last_ip == dest->s_addr) - { - if(nexthop) *nexthop = last_nexthop; - if(ifi) *ifi = last_ifi; - return 0; - } - - if(0 != get_best_route(dest->s_addr, &route)) - return -1; // failure - - last_ip = 0; // if we abort, mark as bad - - // Compute the next hop - switch(route.dwForwardType) - { - case 3: - // local route; the dest is the next hop - last_nexthop = dest->s_addr; - break; - - case 4: - // remote route; use the specified gateway - last_nexthop = route.dwForwardNextHop; - break; - - case 2: - fatal("corrupt route table\n"); - break; - - default: - fatal("unknown route format %d\n", route.dwForwardType); - break; - } - - // save the index - last_ifi = winif2ifi(route.dwForwardIfIndex); - - // mark it valid - last_ip = dest->s_addr; - - // Try to return the answer - if(nexthop) *nexthop = last_nexthop; - if(ifi) *ifi = last_ifi; - - if(o.debugging > 1) - { - printf("%s is routed through ", inet_ntoa(*(struct in_addr*)&last_ip)); - printf("%s\n", inet_ntoa(*(struct in_addr*)&last_nexthop)); - } - - return 0; -} - -// The adapter cache -typedef struct _IFC_ROW { - int ifi; - LPADAPTER pAdapter; - BYTE phys[MAXLEN_PHYSADDR]; - int physlen; - DWORD type; -} IFC_ROW; - -static IFC_ROW last_if = {-1}; - -/* -static int numif = 0; -static IFC_ROW *ifcache = 0; -*/ -static void cleanup_if_cache() -{ - if(last_if.pAdapter) - { - PacketCloseAdapter(last_if.pAdapter); - last_if.pAdapter = 0; - } - - last_if.ifi = -1; -} - -static LPADAPTER if2adapter(int ifi, BYTE* phys, int *physlen, DWORD *type) -{ - const WINIP_IF *ifentry; - char *name; - - EnterCriticalSection(&csAdapter); - - if(last_if.ifi == ifi) - { - if(last_if.physlen == -1) return 0; - if(last_if.pAdapter) - { - if(physlen && (*physlen < last_if.physlen)) return 0; - if(phys) memcpy(phys, last_if.phys, last_if.physlen); - *physlen = last_if.physlen; - if(type) *type = last_if.type; - - // we do not release the CS - return last_if.pAdapter; - } - } - - ifentry = ifi2ifentry(ifi); - if(!ifentry || !ifentry->pcapname) - { - LeaveCriticalSection(&csAdapter); - return 0; // Can't do this one... - } - - cleanup_if_cache(); - - last_if.pAdapter = PacketOpenAdapter(ifentry->pcapname); - - // This is required on Win9x (defaults to 0) - // It's probably a good idea on WinNT/2K - PacketSetNumWrites(last_if.pAdapter, 1); - - if(!last_if.pAdapter) - { - last_if.physlen = -1; - LeaveCriticalSection(&csAdapter); - return 0; - } - - last_if.physlen = ifentry->physlen; - memcpy(last_if.phys, ifentry->physaddr, ifentry->physlen); - last_if.type = ifentry->type; - last_if.ifi = ifi; - - // Try to return the answer - if(physlen && (*physlen < last_if.physlen)) - { - LeaveCriticalSection(&csAdapter); - return 0; - } - if(phys) memcpy(phys, last_if.phys, last_if.physlen); - *physlen = last_if.physlen; - if(type) *type = last_if.type; - - // We do not leave the CS - return last_if.pAdapter; -} - -static void releaseadapter() -{ - LeaveCriticalSection(&csAdapter); -} - -static int fallback_raw_send(const char *packet, int len, - struct sockaddr *to, int tolen) -{ - if(!rawsock_avail) { - fatal("fallback_raw_send: no raw sockets\n" - "This means that you tried to send to an unsupported interface.\n"); - } - - return sendto(global_raw_socket, packet, len, 0, to, tolen); -} - -// The almighty pcapsendraw -// This is the whole point of this file :) -int pcapsendraw(const char *packet, int len, - struct sockaddr *to, int tolen) -{ - struct sockaddr_in *sin = (struct sockaddr_in *) to; - int cb = 0; - int nRes, i; - DWORD nextip; - unsigned long ifi; - LPADAPTER pAdap; - BYTE myphys[MAXLEN_PHYSADDR], tphys[MAXLEN_PHYSADDR]; - int physlen = MAXLEN_PHYSADDR; - DWORD type; - const WINIP_IF *target_ifentry; - - if(!pcapsend_inited) - return fallback_raw_send(packet, len, to, tolen); - - if(-1 == ip2route(&sin->sin_addr, &nextip, &ifi)) - { - WSASetLastError(WSAENETUNREACH); - return -1; // no route to host - } - - target_ifentry = ifi2ifentry(ifi); - if(!target_ifentry || !target_ifentry->pcapname) - return fallback_raw_send(packet, len, to, tolen); - - // check the failcache - EnterCriticalSection(&csFailCache); - for(i = 0; i < FAILCACHELEN; i++) - { - if(failcache[i].ip == nextip && failcache[i].ifi == ifi) - { - // it failed - WSASetLastError(WSAEHOSTUNREACH); -#ifdef THREAD_DEBUG - printf("sendto: autofailed %s\n", inet_ntoa(*(struct in_addr*)&failcache[i].ip)); -#endif - LeaveCriticalSection(&csFailCache); - return -1; - } - } - LeaveCriticalSection(&csFailCache); - - // Read the data - nRes = SearchARP(nextip, ifi, tphys, &physlen); - if(-1 == nRes) - { - // defer the send - AddPacketToQueue(packet, len, nextip, ifi); - return len; // it's in the queue, so it worked... - } - - // otherwise, we have an address - pAdap = if2adapter(ifi, myphys, &physlen, &type); - if(!pAdap) - fatal("can't send to this interface\n"); - realsend(pAdap, packet, len, tphys, myphys, physlen, type, ETH_IP); - releaseadapter(); - return len; -} - -void pcapsend_init() -{ - int i, nRes; - unsigned int id; - - if(pcapsend_inited) return; - pcapsend_inited = 1; - - if(o.debugging > 1) - printf("Initializing winpcap send support..."); - - for(i = 0; i < SENDQUEUE_LEN; i++) - { - Q_FREE *f; - sendqueue[i].ifi = -1; - f = (Q_FREE*)&sendqueue[i]; - f->next = nextfree; - nextfree = f; - } - - InitializeCriticalSection(&csQueue); - InitializeCriticalSection(&csAdapter); - InitializeCriticalSection(&csFailCache); - InitializeCriticalSection(&csArpCache); - InitializeCriticalSection(&csArpTable); - - hEvWakeup = CreateEvent(0, 0, 0, 0); - hSemQueue = CreateSemaphore(0, SENDQUEUE_LEN, SENDQUEUE_LEN, 0); - - // allocate the ARP cache - arpalloclen = 0; - pArpTable = (PMIB_IPNETTABLE)&i; - nRes = GetIpNetTableSafe(pArpTable, &arpalloclen, FALSE); - if(arpalloclen == 0) - { - if(o.debugging && nRes != ERROR_NO_DATA) - printf("ARP table length failure (%lu) during init -- try kludge1 :(\n", nRes); - arpalloclen = 100 * sizeof(MIB_IPNETROW) + 8; - } - - // Read the data - arpalloclen += 3 * sizeof(MIB_IPNETROW); - pArpTable = (PMIB_IPNETTABLE)malloc(arpalloclen); - if(!pArpTable) - { - pcapsend_inited = 0; - fatal("out of memory\n"); - } - nRes = GetIpNetTableSafe(pArpTable, &arpalloclen, TRUE); - - if(nRes != NO_ERROR) - { - if(o.debugging && nRes != ERROR_NO_DATA) - printf("ARP failure (%lu) during init -- trying kludge2\n", nRes); - pArpTable->dwNumEntries = 0; - } - - // Start the send thread - hThread = (HANDLE)_beginthreadex(0, 0, SendThreadProc, 0, 0, &id); - if(!hThread) - { - pcapsend_inited = 0; - fatal("failed to start thread\n"); - } - - atexit(pcapsend_cleanup); - - pcapsend_inited = 1; - - if(o.debugging > 1) - printf(" Done\n"); -} - -// the name cache -typedef struct _IFNAME_ROW { - int ifi; - char name[128]; - DWORD ip; // This is one of the interface's IPs - DWORD type; -} IFNAME_ROW; - -static IFNAME_ROW *names = 0; -static int num_names; - -static void pcapsend_cleanup(void) -{ - if(!pcapsend_inited) - return; - - assert(!killthread); - - killthread = 1; - SetEvent(hEvWakeup); - if(WAIT_TIMEOUT == WaitForSingleObject(hThread, 10000)) - { - error("timed out waiting for thread exit; terminating...\n"); - TerminateThread(hThread, 0); - } - - CloseHandle(hEvWakeup); - CloseHandle(hThread); - CloseHandle(hSemQueue); - DeleteCriticalSection(&csQueue); - DeleteCriticalSection(&csAdapter); - DeleteCriticalSection(&csFailCache); - DeleteCriticalSection(&csArpCache); - DeleteCriticalSection(&csArpTable); - cleanup_if_cache(); - - if(names) free(names); - if(pArpTable) free(pArpTable); -} - -// safe implementation for getbestroute -typedef DWORD (__stdcall *PGBR)(DWORD, DWORD, PMIB_IPFORWARDROW); -int get_best_route(DWORD dest, PMIB_IPFORWARDROW r) -{ - static PGBR GBR = 0; - static int inited = 0; - - int winif = -1, ifi = -1; - - if(!inited) - { - HINSTANCE hInst = GetModuleHandle("iphlpapi.dll"); - inited = 1; - if(hInst && !wo.nt4route) - GBR = (PGBR)GetProcAddress(hInst, "GetBestRoute"); - if(o.debugging > 1 && !GBR) - printf("get_best_route: using NT4-compatible method\n"); - } - - // Find the index - if(*o.device) - { - ifi = name2ifi(o.device); - winif = ifi2winif(ifi); - if(winif == -1) - fatal("get_best_route: nonexistant interface \"%s\"\n", o.device); - } - - // Can we simply redirect? -tryagain: - if(GBR) - { - DWORD source = 0; - DWORD nRes; - - if(ifi != -1) - { - if(-1 == ifi2ipaddr(ifi, (struct in_addr*)&source)) - source = 0; // wtf? - } - - nRes = GBR(dest, source, r); - if(nRes == ERROR_CALL_NOT_IMPLEMENTED) - { - GBR = 0; - goto tryagain; - } - - if(nRes != 0) return nRes; - - // verify we have a good match - if(winif != -1 && r->dwForwardIfIndex != winif) - return -1; - - return 0; - } - - // We need to do this for real - else - { - PMIB_IPFORWARDTABLE pTable = 0; - unsigned long cb = 0; - int bestmatch = -1; - int bestmask, bestmetric; - int nRes, i; - - nRes = GetIpForwardTableSafe(pTable, &cb, FALSE); - if(cb == 0) return (nRes ? nRes : -1); - - cb += sizeof(MIB_IPFORWARDROW); - pTable = (PMIB_IPFORWARDTABLE)_alloca(cb); - nRes = GetIpForwardTableSafe(pTable, &cb, FALSE); - if(nRes != NO_ERROR) return nRes; - - if(pTable->dwNumEntries < 1) return -1; - - for(i = 0; i < pTable->dwNumEntries; i++) - { - // is it a match? - if(pTable->table[i].dwForwardDest != (dest & pTable->table[i].dwForwardMask)) - continue; - - if(winif != -1 && pTable->table[i].dwForwardIfIndex != winif) continue; - -/* if(bestmatch == -1 || (pTable->table[i].dwForwardMask > bestmask) - || (pTable->table[i].dwForwardMask == bestmask - && pTable->table[i].dwForwardMetric1 < bestmetric))*/ - if(bestmatch == -1 || (pTable->table[i].dwForwardMetric1 > bestmetric) - || (pTable->table[i].dwForwardMetric1 == bestmetric - && pTable->table[i].dwForwardMask > bestmask)) - - { - bestmatch = i; - bestmask = pTable->table[i].dwForwardMask; - bestmetric = pTable->table[i].dwForwardMetric1; - } - } - - if(bestmatch == -1) return -1; - - memcpy(r, &pTable->table[bestmatch], sizeof(MIB_IPFORWARDROW)); - - return 0; - } -} - -// ARP cache -static void AddToARPCache(DWORD ip, int ifi, BYTE *phys, int physlen) -{ - if(physlen > MAXLEN_PHYSADDR) - fatal("physical address too long!\n"); - - foo0("addtoarpcache: try acquire csArpCache\n"); - EnterCriticalSection(&csArpCache); - foo0("addtoarpcache: acquired csArpCache\n"); - arpcache[arpfirst].ifi = ifi; - arpcache[arpfirst].ip = ip; - memcpy(arpcache[arpfirst].phys, phys, physlen); - arpcache[arpfirst].physlen = physlen; - arpfirst = (arpfirst + 1) % ARPCACHELEN; - LeaveCriticalSection(&csArpCache); -} - -static int lookupip(DWORD ip, DWORD ifi) -{ - DWORD time = GetTickCount(); - int nRes; - int low, high; - int pass = 0; - DWORD winif = ifi2winif(ifi); - - EnterCriticalSection(&csArpTable); - - goto pass0; - -pass1: - pass = 1; - - if(arprefresh) - { - // refresh - unsigned long len = arpalloclen; - -#ifdef THREAD_DEBUG - printf("lookupip: refreshing ARP table\n"); -#endif - - arprefresh = 0; - -readarp: - nRes = GetIpNetTableSafe(pArpTable, &len, TRUE); - - if(nRes == ERROR_MORE_DATA) - len += 2 * sizeof(MIB_IPNETROW); // give the benefit of the doubt - - if(len == arpalloclen && nRes != NO_ERROR) - { - // Windows bug -- just assume the table is empty - pArpTable->dwNumEntries = 0; - LeaveCriticalSection(&csArpTable); - return -1; - } - - if(len > arpalloclen) - { - // need to try that again - free(pArpTable); - pArpTable = (PMIB_IPNETTABLE)malloc(len); - arpalloclen = len; - if(!pArpTable) fatal("out of memory\n"); - goto readarp; // please don't infinite loop! - } - } - -pass0: - - low = 0; - high = pArpTable->dwNumEntries - 1; - while(low <= high) - { - int i = low + (high - low) / 2; - if(pArpTable->table[i].dwAddr == ip - && pArpTable->table[i].dwType != 2) - { - // we found it - if(pArpTable->table[i].dwIndex != winif) - { - fatal("lookupip: found ip on wrong interface\n" - "e-mail amluto@hotmail.com if you think this should have worked\n"); - } - - LeaveCriticalSection(&csArpTable); - return i; - } - - // Otherwise, we need to narrow search region - if(pArpTable->table[i].dwAddr < ip) - low = i + 1; - else high = i - 1; - } - - if(pass == 0) goto pass1; - - LeaveCriticalSection(&csArpTable); - return -1; -} - -static int SearchARP(DWORD ip, int ifi, BYTE *phys, int *physlen) -{ - int i; - - foo0("searcharp: try acquire csArpCache\n"); - EnterCriticalSection(&csArpCache); - foo0("searcharp: acquired csArpCache\n"); - - // Is it in the ARP cache? - for(i = 0; i < ARPCACHELEN; i++) - { - if(arpcache[i].ip == ip && arpcache[i].ifi == ifi) - { - // we got it! - if(*physlen < arpcache[i].physlen) - fatal("searcharp: can't return the answer\n"); - - memcpy(phys, arpcache[i].phys, arpcache[i].physlen); - *physlen = arpcache[i].physlen; -#ifdef THREAD_DEBUG - printf("searcharp: found %s in cache\n", inet_ntoa(*(struct in_addr*)&ip)); -#endif - LeaveCriticalSection(&csArpCache); - return 0; - } - } - - // else look it up - i = lookupip(ip, ifi); - - LeaveCriticalSection(&csArpCache); - - if(i == -1) return -1; - - if(*physlen < pArpTable->table[i].dwPhysAddrLen) - fatal("insufficient space for physaddr\n"); - - *physlen = pArpTable->table[i].dwPhysAddrLen; - memcpy(phys, pArpTable->table[i].bPhysAddr, - pArpTable->table[i].dwPhysAddrLen); - -#ifdef THREAD_DEBUG - printf("searcharp: found %s in system ARP table\n", inet_ntoa(*(struct in_addr*)&ip)); -#endif - - AddToARPCache(ip, ifi, phys, pArpTable->table[i].dwPhysAddrLen); - - return 0; -} diff --git a/mswin32/winip/snmp95.cpp b/mswin32/winip/snmp95.cpp deleted file mode 100644 index d81b0007e..000000000 --- a/mswin32/winip/snmp95.cpp +++ /dev/null @@ -1,434 +0,0 @@ -/* - -snmp95.c: win95-safe versions of IpHlpApi calls -Copyright (C) 2001 Andy Lutomirski - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License, version 2.1, as published by the Free Software -Foundation, with the exception that if this copy of the library -is distributed under the Lesser GNU Public License (as opposed -to the ordinary GPL), you may ignore section 6b, and that all -copies distributed without exercising section 3 must retain this -paragraph in its entirety. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -These functions are equivalent to the IpHlpApi calls of the same name -except that they work on windows 95. - - -*/ - -// Side note: on GCC, this code is pointless :) - -#include "..\tcpip.h" -#include "winip.h" -#include "iphlpapi.h" -#include "MibAccess.h" - -#ifdef _MSC_VER -#include "delayimp.h" -#endif - -#define MakeAOI(name) {sizeof(name) / sizeof(UINT), name} - - -// This is ridiculous... -#undef errno // safe for now -#undef read // for GCC -#include - -#define DLI_ERROR VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND) - -#ifndef _MSC_VER -// sigh -#define min(x, y) ( (x) < (y) ? (x) : (y) ) -#endif - - -// MIB descriptors - -// ifTable -UINT OID_ifNumber[] = {1, 3, 6, 1, 2, 1, 2, 1, 0}; // includes instance -UINT OID_ifIndex[] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 1}; -UINT OID_ifType[] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 3}; -UINT OID_ifPhysAddress[] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 6}; -UINT OID_ifOperStatus[] = {1, 3, 6, 1, 2, 1, 2, 2, 1, 8}; - -AsnObjectIdentifier AOI_ifNumber = MakeAOI(OID_ifNumber); - -AsnObjectIdentifier ifTable[] = -{ - MakeAOI(OID_ifIndex), // 0 - MakeAOI(OID_ifType), // 1 - MakeAOI(OID_ifPhysAddress), // 2 - MakeAOI(OID_ifOperStatus) // 3 -}; - -// ipAddrTable -UINT OID_ipAdEntAddr[] = {1, 3, 6, 1, 2, 1, 4, 20, 1, 1}; -UINT OID_ipAdEntIfIndex[] = {1, 3, 6, 1, 2, 1, 4, 20, 1, 2}; -UINT OID_ipAdEntNetMask[] = {1, 3, 6, 1, 2, 1, 4, 20, 1, 3}; -UINT OID_ipAdEntBcastAddr[] = {1, 3, 6, 1, 2, 1, 4, 20, 1, 4}; -UINT OID_ipAdEntReasmMaxSize[] = {1, 3, 6, 1, 2, 1, 4, 20, 1, 5}; - -AsnObjectIdentifier ipAddrTable[] = -{ - MakeAOI(OID_ipAdEntAddr), // 0 - MakeAOI(OID_ipAdEntIfIndex), // 1 - MakeAOI(OID_ipAdEntNetMask), // 2 - MakeAOI(OID_ipAdEntBcastAddr), // 3 (int) - MakeAOI(OID_ipAdEntReasmMaxSize) // 4 -}; - -// ipRouteTable -UINT OID_ipRouteDest[] = {1, 3, 6, 1, 2, 1, 4, 21, 1, 1}; -UINT OID_ipRouteIfIndex[] = {1, 3, 6, 1, 2, 1, 4, 21, 1, 2}; -UINT OID_ipRouteMetric1[] = {1, 3, 6, 1, 2, 1, 4, 21, 1, 3}; -UINT OID_ipRouteNextHop[] = {1, 3, 6, 1, 2, 1, 4, 21, 1, 7}; -UINT OID_ipRouteType[] = {1, 3, 6, 1, 2, 1, 4, 21, 1, 8}; -UINT OID_ipRouteMask[] = {1, 3, 6, 1, 2, 1, 4, 21, 1, 11}; - -AsnObjectIdentifier ipRouteTable[] = -{ - MakeAOI(OID_ipRouteDest), // 0 - MakeAOI(OID_ipRouteIfIndex), // 1 - MakeAOI(OID_ipRouteMetric1), // 2 - MakeAOI(OID_ipRouteNextHop), // 3 - MakeAOI(OID_ipRouteType), // 4 - MakeAOI(OID_ipRouteMask) // 5 -}; - -// ipNetTable -UINT OID_ipNetToMediaIfIndex[] = {1, 3, 6, 1, 2, 1, 4, 22, 1, 1}; -UINT OID_ipNetToMediaPhysAddress[] = {1, 3, 6, 1, 2, 1, 4, 22, 1, 2}; -UINT OID_ipNetToMediaNetAddress[] = {1, 3, 6, 1, 2, 1, 4, 22, 1, 3}; -UINT OID_ipNetToMediaType[] = {1, 3, 6, 1, 2, 1, 4, 22, 1, 4}; - -AsnObjectIdentifier ipNetToMediaTable[] = -{ - MakeAOI(OID_ipNetToMediaIfIndex), // 0 - MakeAOI(OID_ipNetToMediaPhysAddress), // 1 - MakeAOI(OID_ipNetToMediaNetAddress), // 2 - MakeAOI(OID_ipNetToMediaType) // 3 -}; - -static std::auto_ptr m; - -static bool populated = false; - -static PMIB_IPADDRTABLE pAddrtable = 0; -static DWORD szAddrtable = 0; - -static PMIB_IPFORWARDTABLE pRoutetable = 0; -static DWORD szRoutetable = 0; - -int iphlp_avail = 1; // Is the iphlpapi dll present? -int net_avail = 1; // Is some method of access present? - -static int __cdecl compip(const void *e1, const void *e2) -{ - return ((const MIB_IPADDRROW*)(e1))->dwAddr - ((const MIB_IPADDRROW*)(e2))->dwAddr; -} - -static bool Populate() -{ -#if defined(_MSC_VER) || defined(__MINGW32__) - if(populated) return szAddrtable != 0; - populated = true; - - if(wo.trace) printf("***WinIP*** initializing inetmib1 tables..."); - - // Allocate - m = std::auto_ptr(new MibII); - MIBTraverser::m = m.get(); - - m->Init(); - if(!m->GetDLLStatus()) - { - if(wo.trace) printf("\n***WinIP*** no inetmib1.dll\n"); - net_avail = 0; - return false; - } - - MIBTraverser mt; - - // Populate the address table - mt.Init(ipAddrTable, sizeof(ipAddrTable) / sizeof(ipAddrTable[0])); - - szAddrtable = sizeof(UINT) + 10 * sizeof(MIB_IPADDRROW); - pAddrtable = (PMIB_IPADDRTABLE)malloc(szAddrtable); - pAddrtable->dwNumEntries = 0; - - while(mt.Next()) - { - if(sizeof(UINT) + (pAddrtable->dwNumEntries + 1) * sizeof(MIB_IPADDRROW) - > szAddrtable) - { - szAddrtable += 10 * sizeof(MIB_IPADDRROW); - pAddrtable = (PMIB_IPADDRTABLE)realloc(pAddrtable, szAddrtable); - } - - MIB_IPADDRROW *r = pAddrtable->table + pAddrtable->dwNumEntries; - pAddrtable->dwNumEntries++; - ZeroMemory(r, sizeof(MIB_IPADDRROW)); - r->dwAddr = ASN_IP(mt[0].value.asnValue); - r->dwIndex = mt[1].value.asnValue.unsigned32; - r->dwMask = ASN_IP(mt[2].value.asnValue); - r->dwBCastAddr = (r->dwAddr & r->dwMask) - | ( (mt[3].value.asnValue.unsigned32 & 1) * ~r->dwMask ); - r->dwReasmSize = mt[4].value.asnValue.unsigned32; - } - - szAddrtable = sizeof(UINT) * pAddrtable->dwNumEntries * sizeof(MIB_IPADDRROW); - - // Populate the route table - mt.Init(ipRouteTable, sizeof(ipRouteTable) / sizeof(ipRouteTable[0])); - - szRoutetable = sizeof(UINT) + 10 * sizeof(MIB_IPFORWARDROW); - pRoutetable = (PMIB_IPFORWARDTABLE)malloc(szRoutetable); - pRoutetable->dwNumEntries = 0; - - while(mt.Next()) - { - if(sizeof(UINT) + (pRoutetable->dwNumEntries + 1) * sizeof(MIB_IPFORWARDROW) - > szRoutetable) - { - szRoutetable += 10 * sizeof(MIB_IPFORWARDROW); - pRoutetable = (PMIB_IPFORWARDTABLE)realloc(pRoutetable, szRoutetable); - } - - MIB_IPFORWARDROW *r = pRoutetable->table + pRoutetable->dwNumEntries; - pRoutetable->dwNumEntries++; - ZeroMemory(r, sizeof(MIB_IPFORWARDROW)); - r->dwForwardIfIndex = mt[1].value.asnValue.unsigned32; - r->dwForwardDest = ASN_IP(mt[0].value.asnValue); - r->dwForwardMetric1 = mt[2].value.asnValue.unsigned32; - r->dwForwardNextHop = ASN_IP(mt[3].value.asnValue); - r->dwForwardType = mt[4].value.asnValue.unsigned32; - r->dwForwardMask = ASN_IP(mt[5].value.asnValue); - } - - szRoutetable = sizeof(UINT) * pRoutetable->dwNumEntries * sizeof(MIB_IPFORWARDROW); - - if(wo.trace) printf(" Done\n"); - - return true; -#else - return false; // won't get here anyway -#endif -} - -// we can ignore the sort option because the table is pre-sorted -extern "C" DWORD GetIfTableSafe(PMIB_IFTABLE pOut, DWORD* size, BOOL bSort) -{ - if(wo.noiphlpapi) iphlp_avail = 0; - - if(iphlp_avail) - { -#ifdef _MSC_VER - __try { -#endif - return GetIfTable(pOut, size, bSort); -#ifdef _MSC_VER - } - __except(GetExceptionCode() == DLI_ERROR) - { - iphlp_avail = 0; - } -#endif - } - - if(!Populate()) return -1; - - MIBTraverser mt; - - // Initialize for single-object read - mt.Init(&AOI_ifNumber, 1); - - if(!mt.Get()) - return 0xFFFFFFFF; - - UINT numnic = mt[0].value.asnValue.unsigned32; - DWORD sz = sizeof(UINT) + numnic * sizeof(MIB_IFROW); - - if(!pOut) - { - *size = sz; - return 0; - } - else - { - if(*size < sz) - { - *size = sz; - return ERROR_INSUFFICIENT_BUFFER; - } - - // Populate the table - mt.Init(ifTable, sizeof(ifTable) / sizeof(ifTable[0])); - pOut->dwNumEntries = 0; - while(mt.Next()) - { - MIB_IFROW *r = &pOut->table[pOut->dwNumEntries]; - pOut->dwNumEntries++; - - ZeroMemory(r, sizeof(MIB_IFROW)); - r->dwIndex = mt[0].value.asnValue.unsigned32; - r->dwType = mt[1].value.asnValue.unsigned32; - r->dwPhysAddrLen = min(MAXLEN_PHYSADDR, - mt[2].value.asnValue.string.length); - memcpy(r->bPhysAddr, mt[2].value.asnValue.string.stream, - r->dwPhysAddrLen); - r->dwOperStatus = mt[3].value.asnValue.unsigned32; - } - - return 0; - } -} - - -extern "C" DWORD GetIpAddrTableSafe(PMIB_IPADDRTABLE pOut, DWORD* size, BOOL bSort) -{ - if(wo.noiphlpapi) iphlp_avail = 0; - - if(iphlp_avail) - { -#ifdef _MSC_VER - __try { -#endif - return GetIpAddrTable(pOut, size, bSort); -#ifdef _MSC_VER - } - __except(GetExceptionCode() == DLI_ERROR) - { - iphlp_avail = 0; - } -#endif - } - - if(!Populate()) return 0xFFFFFFFF; - - if(!pOut) - { - *size = szAddrtable; - return 0; - } - else - { - if(*size < szAddrtable) - { - *size = szAddrtable; - return ERROR_INSUFFICIENT_BUFFER; - } - - memcpy(pOut, pAddrtable, szAddrtable); - return 0; - } -} - - -extern "C" DWORD GetIpNetTableSafe(PMIB_IPNETTABLE pOut, DWORD* size, BOOL bSort) -{ - if(wo.noiphlpapi) iphlp_avail = 0; - - if(iphlp_avail) - { -#ifdef _MSC_VER - __try { -#endif - return GetIpNetTable(pOut, size, bSort); -#ifdef _MSC_VER - } - __except(GetExceptionCode() == DLI_ERROR) - { - iphlp_avail = 0; - } -#endif - } - - if(!Populate()) return -1; - - int sz = sizeof(UINT); // Space used so far - - DWORD temp; - if(*size < 4) pOut = (PMIB_IPNETTABLE)&temp; - pOut->dwNumEntries = 0; - - // Initialize the traverser - MIBTraverser mt; - mt.Init(ipNetToMediaTable, - sizeof(ipNetToMediaTable) / sizeof(ipNetToMediaTable[0])); - - // Begin the traversal - while(mt.Next()) - { - sz += sizeof(MIB_IPNETROW); - if(sz <= *size) - { - // Fill in the row - MIB_IPNETROW *r = pOut->table + pOut->dwNumEntries; - pOut->dwNumEntries++; - r->dwIndex = mt[0].value.asnValue.unsigned32; - r->dwPhysAddrLen = mt[1].value.asnValue.string.length; - memcpy(r->bPhysAddr, mt[1].value.asnValue.string.stream, - r->dwPhysAddrLen); - r->dwAddr = ASN_IP(mt[2].value.asnValue); - r->dwType = mt[3].value.asnValue.unsigned32; - } - } - - if(sz > *size) - { - *size = sz; - return ERROR_INSUFFICIENT_BUFFER; - } - else return 0; -} - -extern "C" DWORD GetIpForwardTableSafe(PMIB_IPFORWARDTABLE pOut, DWORD* size, BOOL bSort) -{ - if(wo.noiphlpapi) iphlp_avail = 0; - - if(iphlp_avail) - { -#ifdef _MSC_VER - __try { -#endif - return GetIpForwardTable(pOut, size, bSort); -#ifdef _MSC_VER - } - __except(GetExceptionCode() == DLI_ERROR) - { - iphlp_avail = 0; - } -#endif - } - - if(!Populate()) return -1; - - if(!pOut) - { - *size = szRoutetable; - return 0; - } - else - { - if(*size < szRoutetable) - { - *size = szRoutetable; - return ERROR_INSUFFICIENT_BUFFER; - } - - memcpy(pOut, pRoutetable, szRoutetable); - return 0; - } -} diff --git a/mswin32/winip/snmpapi.cpp b/mswin32/winip/snmpapi.cpp deleted file mode 100644 index 7bf325f61..000000000 --- a/mswin32/winip/snmpapi.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/****************************************************************** -* -* Copyright (C) Stas Khirman 1998. All rights reserved. -* -* This program is distributed WITHOUT ANY WARRANTY -* -*******************************************************************/ - -/************************************************* -* -* Reproduction of SNMP.LIB and SNMPAPI.LIB base -* functions -* -* Author: Stas Khirman (staskh@rocketmail.com) -* -* -* Free software: no warranty; use anywhere is ok; spread the -* sources; note any modifications; share variations and -* derivatives (including sending to staskh@rocketmail.com). -* -* -*************************************************/ - -// This file is _not_ LGPL -- see above license - -#include "..\tcpip.h" -#include "winip.h" -#include -#include - -SNMPAPI -SNMP_FUNC_TYPE -SnmpUtilOidCpy( - OUT AsnObjectIdentifier *DstObjId, - IN AsnObjectIdentifier *SrcObjId - ) -{ - DstObjId->ids = (UINT *)GlobalAlloc(GMEM_ZEROINIT,SrcObjId->idLength * - sizeof(UINT)); - if(!DstObjId->ids){ - SetLastError(1); - return 0; - } - - memcpy(DstObjId->ids,SrcObjId->ids,SrcObjId->idLength*sizeof(UINT)); - DstObjId->idLength = SrcObjId->idLength; - - return 1; -} - - -VOID -SNMP_FUNC_TYPE -SnmpUtilOidFree( - IN OUT AsnObjectIdentifier *ObjId - ) -{ - GlobalFree(ObjId->ids); - ObjId->ids = 0; - ObjId->idLength = 0; -} - -SNMPAPI -SNMP_FUNC_TYPE -SnmpUtilOidNCmp( - IN AsnObjectIdentifier *ObjIdA, - IN AsnObjectIdentifier *ObjIdB, - IN UINT Len - ) -{ - UINT CmpLen; - UINT i; - int res; - - CmpLen = Len; - if(ObjIdA->idLength < CmpLen) - CmpLen = ObjIdA->idLength; - if(ObjIdB->idLength < CmpLen) - CmpLen = ObjIdB->idLength; - - for(i=0;iids[i] - ObjIdB->ids[i]; - if(res!=0) - return res; - } - return 0; -} - -VOID -SNMP_FUNC_TYPE -SnmpUtilVarBindFree( - IN OUT RFC1157VarBind *VarBind - ) -{ - BYTE asnType; - // free object name - SnmpUtilOidFree(&VarBind->name); - - asnType = VarBind->value.asnType; - - if(asnType==ASN_OBJECTIDENTIFIER){ - SnmpUtilOidFree(&VarBind->value.asnValue.object); - } - else if( - (asnType==ASN_OCTETSTRING) || - (asnType==ASN_RFC1155_IPADDRESS) || - (asnType==ASN_RFC1155_OPAQUE) || - (asnType==ASN_SEQUENCE)){ - if(VarBind->value.asnValue.string.dynamic){ - GlobalFree(VarBind->value.asnValue.string.stream); - } - } - - VarBind->value.asnType = ASN_NULL; - -} diff --git a/mswin32/winip/winip.h b/mswin32/winip/winip.h deleted file mode 100644 index acefbb6fa..000000000 --- a/mswin32/winip/winip.h +++ /dev/null @@ -1,197 +0,0 @@ -#ifndef WINIP_H -#define WINIP_H - -/* - -winip.h: interface definition to the winip library -Copyright (C) 2000 Andy Lutomirski - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License, version 2.1, as published by the Free Software -Foundation, with the exception that if this copy of the library -is distributed under the Lesser GNU Public License (as opposed -to the ordinary GPL), you may ignore section 6b, and that all -copies distributed without exercising section 3 must retain this -paragraph in its entirety. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -/* The ifType spec from RFCs 1156 and 1213 - - -other(1), -- none of the following -regular1822(2), -hdh1822(3), -ddn-x25(4), -rfc877-x25(5), -ethernet-csmacd(6), -iso88023-csmacd(7), -iso88024-tokenBus(8), -iso88025-tokenRing(9), -iso88026-man(10), -starLan(11), -proteon-10MBit(12), -proteon-80MBit(13), -hyperchannel(14), -fddi(15), -lapb(16), -sdlc(17), -t1-carrier(18), -cept(19), -- european equivalent of T-1 -basicIsdn(20), -primaryIsdn(21), -- proprietary serial -propPointToPointSerial(22) -ppp(23) -softwareLoopback(24) -eon(25) -ethernet-3Mbit(26) -nsip(27) -slip(28) -ultra(29) -ds3(30) -sip(31) -frame-relay(32) - - */ - -#include -#include -#include -#include - - -/* -#define IF_other 1 -#define IF_regular1822 2 -#define IF_hdh1822 3 -#define IF_ddn_x25 4 -#define IF_rfc877_x25 5 -#define IF_ethernet_csmacd 6 -#define IF_iso88023_csmacd 7 -#define IF_iso88024_tokenBus 8 -#define IF_iso88025_tokenRing 9 -#define IF_iso88026_man 10 -#define IF_starLan 11 -#define IF_proteon_10MBit 12 -#define IF_proteon_80MBit 13 -#define IF_hyperchannel 14 -#define IF_fddi 15 -#define IF_lapb 16 -#define IF_sdlc 17 -#define IF_t1_carrier 18 -#define IF_cept 19 // european equivalent of T_1 -#define IF_basicIsdn 20 -#define IF_primaryIsdn 21 // proprietary serial -#define IF_propPointToPointSerial 22 -#define IF_ppp 23 -#define IF_softwareLoopback 24 -#define IF_eon 25 -#define IF_ethernet_3Mbit 26 -#define IF_nsip 27 -#define IF_slip 28 -#define IF_ultra 29 -#define IF_ds3 30 -#define IF_sip 31 -#define IF_frame_relay 32 -*/ - -#ifndef EXTERNC -# ifdef __cplusplus -# define EXTERNC extern "C" -# else -# define EXTERNC extern -# endif -#endif - -// windows-specific options - -#include -struct winops { - int norawsock, nopcap, forcerawsock, listinterfaces, nt4route, noiphlpapi, trace; -}; - -/* struct winops wo; - */ - -/* Sets a pcap filter function -- makes SOCK_RAW reads easier */ -typedef int (*PFILTERFN)(const char *packet, unsigned int len); /* 1 to keep */ - -// Makes gcc happy -// One wonders why VC doesn't complain... -class Target; -EXTERNC void set_pcap_filter(const char *device, pcap_t *pd, PFILTERFN filter, char *bpf, ...); - - -typedef struct _IPNODE { - DWORD ip; // net order - struct _IPNODE *next; - DWORD ifi; // amusing hack :) -} IPNODE; - -typedef struct _WINIP_IF { - int winif; // The IpHlpApi index - char name[16]; // The name - DWORD type; - - BYTE physaddr[MAXLEN_PHYSADDR]; - int physlen; - - IPNODE *firstip; - - // pcap support - char *pcapname; // might be pointer to Unicode -} WINIP_IF; - -/* (exported) functions */ -EXTERNC void winip_init(); -EXTERNC void winip_postopt_init(); -EXTERNC void winip_barf(const char *msg); -EXTERNC int winip_corruption_possible(); - -// name translation -EXTERNC int name2ifi(const char *name); -EXTERNC const char *ifi2name(int ifi); -EXTERNC int ifi2winif(int ifi); -EXTERNC int winif2ifi(int winif); -EXTERNC int ifi2ipaddr(int ifi, struct in_addr *addr); -EXTERNC int ipaddr2ifi(DWORD ip); -EXTERNC const WINIP_IF* ifi2ifentry(int ifi); - -//extern int pcap_avail; -//extern int rawsock_avail; - -EXTERNC int get_best_route(DWORD dest, PMIB_IPFORWARDROW r); - - - -// pcapsend interface -void pcapsend_init(); -EXTERNC pcap_t *my_real_pcap_open_live(const char *device, int snaplen, int promisc, int to_ms); -int pcapsendraw(const char *packet, int len, - struct sockaddr *to, int tolen); - -// rawrecv interface -EXTERNC pcap_t *rawrecv_open(const char *dev); -EXTERNC void rawrecv_close(pcap_t *pd); -EXTERNC char *rawrecv_readip(pcap_t *pd, unsigned int *len, long to_usec, struct timeval *rcvdtime); -EXTERNC void rawrecv_setfilter(pcap_t *pd, PFILTERFN filterfn); -EXTERNC char *readip_pcap_real(pcap_t *pd, unsigned int *len, long to_usec); - -// Win95 support -EXTERNC DWORD GetIfTableSafe(PMIB_IFTABLE, DWORD*, BOOL); -EXTERNC DWORD GetIpAddrTableSafe(PMIB_IPADDRTABLE, DWORD*, BOOL); -EXTERNC DWORD GetIpNetTableSafe(PMIB_IPNETTABLE, DWORD*, BOOL); -EXTERNC DWORD GetIpForwardTableSafe(PMIB_IPFORWARDTABLE, DWORD*, BOOL); - -#endif - diff --git a/nmap.cc b/nmap.cc index a4ed71aef..c644dd531 100644 --- a/nmap.cc +++ b/nmap.cc @@ -107,6 +107,7 @@ #include "timing.h" #include "NmapOps.h" #include "MACLookup.h" +#include "winfix.h" using namespace std; @@ -226,9 +227,6 @@ int nmap_main(int argc, char *argv[]) { Target *currenths; vector Targets; char *proberr; -#if WIN32 - bool skip_winip_init = false; -#endif char emptystring[1]; int sourceaddrwarning = 0; /* Have we warned them yet about unguessable source addresses? */ @@ -293,17 +291,6 @@ int nmap_main(int argc, char *argv[]) { {"spoof_mac", required_argument, 0, 0}, {"ttl", required_argument, 0, 0}, /* Time to live */ {"allports", no_argument, 0, 0}, -#ifdef WIN32 - {"win_list_interfaces", no_argument, 0, 0}, - {"win_norawsock", no_argument, 0, 0}, - {"win_forcerawsock", no_argument, 0, 0}, - {"win_nopcap", no_argument, 0, 0}, - {"win_nt4route", no_argument, 0, 0}, - {"win_noiphlpapi", no_argument, 0, 0}, - {"win_help", no_argument, 0, 0}, - {"win_trace", no_argument, 0, 0}, - {"win_skip_winip_init", no_argument, 0, 0}, -#endif {0, 0, 0, 0} }; @@ -380,34 +367,6 @@ int nmap_main(int argc, char *argv[]) { } } else if (strcmp(long_options[option_index].name, "datadir") == 0) { o.datadir = strdup(optarg); -#ifdef WIN32 - } else if (strcmp(long_options[option_index].name, "win_list_interfaces") == 0 ) { - wo.listinterfaces = 1; - } else if (strcmp(long_options[option_index].name, "win_norawsock") == 0 ) { - wo.norawsock = 1; - } else if (strcmp(long_options[option_index].name, "win_forcerawsock") == 0 ) { - wo.forcerawsock = 1; - } else if (strcmp(long_options[option_index].name, "win_nopcap") == 0 ) { - wo.nopcap = 1; - } else if (strcmp(long_options[option_index].name, "win_nt4route") == 0 ) { - wo.nt4route = 1; - } else if (strcmp(long_options[option_index].name, "win_noiphlpapi") == 0 ) { - wo.noiphlpapi = 1; - } else if (strcmp(long_options[option_index].name, "win_trace") == 0 ) { - wo.trace++; - } else if (strcmp(long_options[option_index].name, "win_skip_winip_init") == 0 ) { - skip_winip_init = true; - } else if (strcmp(long_options[option_index].name, "win_help") == 0 ) { - printf("Windows-specific options:\n\n"); - printf(" --win_list_interfaces : list all network interfaces\n"); - printf(" --win_norawsock : disable raw socket support\n"); - printf(" --win_forcerawsock : try raw sockets even on non-W2K systems\n"); - printf(" --win_nopcap : disable winpcap support\n"); - printf(" --win_nt4route : test nt4 route code\n"); - printf(" --win_noiphlpapi : test response to lack of iphlpapi.dll\n"); - printf(" --win_trace : trace through raw IP initialization\n"); - exit(0); -#endif } else if (strcmp(long_options[option_index].name, "append_output") == 0) { o.append_output = 1; } else if (strcmp(long_options[option_index].name, "noninteractive") == 0) { @@ -776,8 +735,7 @@ int nmap_main(int argc, char *argv[]) { } #ifdef WIN32 - if (!skip_winip_init) - winip_postopt_init(); + win_init(); #endif #if HAVE_SIGNAL diff --git a/nmap_winconfig.h b/nmap_winconfig.h index 34c8dc581..515c90375 100644 --- a/nmap_winconfig.h +++ b/nmap_winconfig.h @@ -104,7 +104,7 @@ #ifndef NMAP_WINCONFIG_H #define NMAP_WINCONFIG_H -#define NMAP_VERSION "3.83.DC14" +#define NMAP_VERSION "3.83.DC16" #define NMAP_NAME "nmap" #define NMAP_URL "http://www.insecure.org/nmap" #define NMAP_PLATFORM "i686-pc-windows-windows" diff --git a/osscan.cc b/osscan.cc index 183cdd03c..6f926f153 100644 --- a/osscan.cc +++ b/osscan.cc @@ -117,10 +117,6 @@ #endif extern NmapOps o; -/* predefined filters -- I need to kill these globals at some pont. */ -extern unsigned long flt_dsthost, flt_srchost; -extern unsigned short flt_baseport; - FingerPrint *get_fingerprint(Target *target, struct seq_info *si) { FingerPrint *FP = NULL, *FPtmp = NULL; @@ -209,12 +205,9 @@ oshardtimeout = MAX(500000, 5 * target->to.timeout); if (o.debugging > 1) log_write(LOG_STDOUT, "Wait time is %dms\n", (ossofttimeout +500)/1000); - flt_srchost = target->v4host().s_addr; - flt_dsthost = target->v4source().s_addr; - snprintf(filter, sizeof(filter), "dst host %s and (icmp or (tcp and src host %s))", inet_ntoa(target->v4source()), target->targetipstr()); - set_pcap_filter(target->deviceName(), pd, flt_icmptcp, filter); + set_pcap_filter(target->deviceName(), pd, filter); target->osscan_performed = 1; /* Let Nmap know that we did try an OS scan */ /* Lets find an open port to use */ @@ -1897,10 +1890,6 @@ current_testno++; overwrite our ip_id */ #if !defined(SOLARIS) && !defined(SUNOS) && !defined(IRIX) && !defined(HPUX) -#ifdef WIN32 -if(!winip_corruption_possible()) { -#endif - /* Now lets see how they treated the ID we sent ... */ AVs[current_testno].attribute = "RID"; if (ntohs(ip2->ip_id) == 0) @@ -1911,10 +1900,6 @@ else strcpy(AVs[current_testno].value, "F"); /* They fucked it up */ current_testno++; -#ifdef WIN32 -} -#endif - #endif /* Let us see if the IP checksum we got back computes */ diff --git a/scan_engine.cc b/scan_engine.cc index 7393b9010..94ff91ee6 100644 --- a/scan_engine.cc +++ b/scan_engine.cc @@ -501,9 +501,6 @@ static void init_ultra_timing_vals(ultra_timing_vals *timing, this as a DROPPED PACKET */ void ultrascan_adjust_times(UltraScanInfo *USI, HostScanStats *hss, UltraProbe *probe, struct timeval *rcvdtime); -/* predefined filters -- I need to kill these globals at some pont. */ -extern unsigned long flt_dsthost, flt_srchost; -extern unsigned short flt_baseport; /* Take a buffer, buf, of size bufsz (32 bytes is sufficient) and writes a short description of the probe (arg1) into buf. It also returns @@ -2960,9 +2957,6 @@ static void begin_sniffer(UltraScanInfo *USI, vector &Targets) { filterlen = 0; USI->pd = my_pcap_open_live(Targets[0]->deviceName(), 100, (o.spoofsource)? 1 : 0, 2); - /* Windows nonsense */ - flt_srchost = Targets[0]->v4host().s_addr; - flt_dsthost = Targets[0]->v4source().s_addr; if (USI->tcp_scan || USI->udp_scan) { if (doIndividual) @@ -2999,7 +2993,7 @@ static void begin_sniffer(UltraScanInfo *USI, vector &Targets) { filterlen = len; } else assert(0); /* Other scan types? */ if (o.debugging > 2) printf("Pcap filter: %s\n", pcap_filter); - set_pcap_filter(Targets[0]->deviceName(), USI->pd, flt_all, pcap_filter); + set_pcap_filter(Targets[0]->deviceName(), USI->pd, pcap_filter); /* pcap_setnonblock(USI->pd, 1, NULL); */ return; diff --git a/targets.cc b/targets.cc index 974ae6a79..d03d75310 100644 --- a/targets.cc +++ b/targets.cc @@ -114,11 +114,6 @@ extern NmapOps o; enum pingstyle { pingstyle_unknown, pingstyle_rawtcp, pingstyle_rawudp, pingstyle_connecttcp, pingstyle_icmp }; -/* predefined filters -- I need to kill these globals at some pont. */ -extern unsigned long flt_dsthost, flt_srchost; -extern unsigned short flt_baseport; - - /* Gets the host number (index) of target in the hostbatch array of pointers. Note that the target MUST EXIST in the array or all heck will break loose. */ @@ -622,16 +617,13 @@ if (ptech.rawicmpscan || ptech.rawtcpscan || ptech.rawudpscan) { = 104 byte snaplen */ pd = my_pcap_open_live(hostbatch[0]->deviceName(), 104, o.spoofsource, 20); - flt_dsthost = hostbatch[0]->v4source().s_addr; - flt_baseport = sportbase; - snprintf(filter, sizeof(filter), "(icmp and dst host %s) or ((tcp or udp) and dst host %s and ( dst port %d or dst port %d or dst port %d or dst port %d or dst port %d))", inet_ntoa(hostbatch[0]->v4source()), inet_ntoa(hostbatch[0]->v4source()), sportbase , sportbase + 1, sportbase + 2, sportbase + 3, sportbase + 4); - set_pcap_filter(hostbatch[0]->deviceName(), pd, flt_icmptcp_5port, filter); + set_pcap_filter(hostbatch[0]->deviceName(), pd, filter); } blockinc = (int) (0.9999 + 8.0 / probes_per_host); diff --git a/tcpip.cc b/tcpip.cc index d58227f39..f43731cf3 100644 --- a/tcpip.cc +++ b/tcpip.cc @@ -137,10 +137,6 @@ extern NmapOps o; extern void CloseLibs(void); #endif -/* predefined filters -- I need to kill these globals at some pont. */ -extern unsigned long flt_dsthost, flt_srchost; -extern unsigned short flt_baseport; - #ifdef WIN32 #include "mswin32/winip/winip.h" @@ -155,14 +151,12 @@ int if2nameindex(int ifi); static PacketCounter PktCt; -#ifndef WIN32 /* Already defined in wintcpip.c for now */ void sethdrinclude(int sd) { #ifdef IP_HDRINCL int one = 1; setsockopt(sd, IPPROTO_IP, IP_HDRINCL, (const char *) &one, sizeof(one)); #endif } -#endif /* WIN32 */ // Takes a protocol number like IPPROTO_TCP, IPPROTO_UDP, or // IPPROTO_TCP and returns a ascii representation (or "unknown" if it @@ -650,60 +644,84 @@ char dev[128]; return 0; } -/* Calls pcap_open_live and spits out an error (and quits) if the call - fails. So a valid pcap_t will always be returned. Note that the - Windows/UNIX versions are separate since they differ so much. - Also, the actual my_pcap_open_live() for Windows is in - mswin32/winip/winip.c. It calls the function below if pcap is - being used, otherwise it uses Windows raw sockets. */ #ifdef WIN32 -pcap_t *my_real_pcap_open_live(const char *device, int snaplen, int promisc, int to_ms) -{ - char err0r[PCAP_ERRBUF_SIZE]; - pcap_t *pt; - const WINIP_IF *ifentry; - int ifi = name2ifi(device); +/* Convert a dnet interface name into the long pcap style. This also caches the data +to speed things up. Fills out pcapdev (up to pcapdevlen) and returns true if it finds anything. +Otherwise returns false. This is only necessary on Windows.*/ +bool DnetName2PcapName(const char *dnetdev, char *pcapdev, int pcapdevlen) { + static struct NameCorrelationCache { + char dnetd[64]; + char pcapd[128]; + } *NCC = NULL; + static int NCCsz = 0; + static int NCCcapacity = 0; + int i; + char tmpdev[128]; - if(ifi == -1) - fatal("my_real_pcap_open_live: invalid device %s\n", device); - - if(o.debugging > 1) - printf("Trying to open %s for receive with winpcap.\n", device); - - ifentry = ifi2ifentry(ifi); - - // check for bogus interface - if(!ifentry->pcapname) - { - fatal("my_real_pcap_open_live: called with non-pcap interface %s!\n", - device); + // Init the cache if not done yet + if (!NCC) { + NCCcapacity = 5; + NCC = (struct NameCorrelationCache *) safe_zalloc(NCCcapacity * sizeof(*NCC)); + NCCsz = 0; } - if (!((pt = pcap_open_live(ifentry->pcapname, snaplen, promisc, to_ms, err0r)))) - fatal("pcap_open_live: %s"); + // First check if the name is already in the cache + for(i=0; i < NCCsz; i++) { + if (strcmp(NCC[i].dnetd, dnetdev) == 0) { + Strncpy(pcapdev, NCC[i].pcapd, pcapdevlen); + return true; + } + } - - // This should help - pcap_setmintocopy(pt, 1); + // OK, so it isn't in the cache. Let's ask dnet for it. +/* Converts a dnet interface name (ifname) to its pcap equivalent, which is stored in +pcapdev (up to a length of pcapdevlen). Returns 0 and fills in pcapdev if successful. */ + if (intf_get_pcap_devname(dnetdev, tmpdev, sizeof(tmpdev)) != 0) + return false; - return pt; + // We've got it. Let's add it to the cache + if (NCCsz >= NCCcapacity) { + NCCcapacity <<= 2; + NCC = (struct NameCorrelationCache *) safe_realloc(NCC, NCCcapacity * sizeof(*NCC)); + } + Strncpy(NCC[NCCsz].dnetd, dnetdev, sizeof(NCC[0].dnetd)); + Strncpy(NCC[NCCsz].pcapd, tmpdev, sizeof(NCC[0].pcapd)); + NCCsz++; + Strncpy(pcapdev, tmpdev, pcapdevlen); + return true; } +#endif -#else // !WIN32 pcap_t *my_pcap_open_live(const char *device, int snaplen, int promisc, int to_ms) { char err0r[PCAP_ERRBUF_SIZE]; pcap_t *pt; - if (!((pt = pcap_open_live(device, snaplen, promisc, to_ms, err0r)))) { + char pcapdev[128]; +#ifdef WIN32 +/* Nmap normally uses device names obtained through dnet for interfaces, but Pcap has its own +naming system. So the conversion is done here */ + if (!DnetName2PcapName(device, pcapdev, sizeof(pcapdev))) { + /* Oh crap -- couldn't find the corresponding dev apparently. Let's just go with what we have then ... */ + Strncpy(pcapdev, device, sizeof(pcapdev)); + } +#else + Strncpy(pcapdev, device, sizeof(pcapdev)); +#endif + if (!((pt = pcap_open_live(pcapdev, snaplen, promisc, to_ms, err0r)))) { fatal("pcap_open_live: %s\nThere are several possible reasons for this, depending on your operating system:\n" "LINUX: If you are getting Socket type not supported, try modprobe af_packet or recompile your kernel with SOCK_PACKET enabled.\n" "*BSD: If you are getting device not configured, you need to recompile your kernel with Berkeley Packet Filter support. If you are getting No such file or directory, try creating the device (eg cd /dev; MAKEDEV ; or use mknod).\n" "SOLARIS: If you are trying to scan localhost and getting '/dev/lo0: No such file or directory', complain to Sun. I don't think Solaris can support advanced localhost scans. You can probably use \"-P0 -sT localhost\" though.\n\n", err0r); } + +#ifdef WIN32 + /* We want any responses back ASAP */ + pcap_setmintocopy(pt, 1); +#endif + return pt; } -#endif // WIN32 /* Standard BSD internet checksum routine */ unsigned short in_cksum(u16 *ptr,int nbytes) { @@ -1446,13 +1464,6 @@ static unsigned int alignedbufsz=0; static int warning = 0; if (linknfo) { memset(linknfo, 0, sizeof(*linknfo)); } -#ifdef WIN32 -long to_left; - -// We use WinXP raw packet support when available - if (-2 == (long) pd) return rawrecv_readip(pd, len, to_usec, rcvdtime); -#endif - if (!pd) fatal("NULL packet device passed to readip_pcap"); if (to_usec < 0) { @@ -1539,7 +1550,7 @@ if (!pd) fatal("NULL packet device passed to readip_pcap"); do { #ifdef WIN32 gettimeofday(&tv_end, NULL); - to_left = MAX(1, (to_usec - TIMEVAL_SUBTRACT(tv_end, tv_start)) / 1000); + long to_left = MAX(1, (to_usec - TIMEVAL_SUBTRACT(tv_end, tv_start)) / 1000); // Set the timeout (BUGBUG: this is cheating) PacketSetReadTimeout(pd->adapter, to_left); #endif @@ -1848,7 +1859,7 @@ bool doArp(const char *dev, const u8 *srcmac, /* Start listening */ pd = my_pcap_open_live(dev, 50, 1, 25); - set_pcap_filter(dev, pd, flt_all, "arp and ether dst host %02X:%02X:%02X:%02X:%02X:%02X", srcmac[0], srcmac[1], srcmac[2], srcmac[3], srcmac[4], srcmac[5]); + set_pcap_filter(dev, pd, "arp and ether dst host %02X:%02X:%02X:%02X:%02X:%02X", srcmac[0], srcmac[1], srcmac[2], srcmac[3], srcmac[4], srcmac[5]); /* Prepare probe and sending stuff */ ethsd = eth_open(dev); @@ -1964,11 +1975,9 @@ bool setTargetNextHopMAC(Target *target) { return false; } -#ifndef WIN32 /* Windows version of next few functions is currently - in wintcpip.c. Should be merged at some point. */ /* Set a pcap filter */ void set_pcap_filter(const char *device, - pcap_t *pd, PFILTERFN filter, char *bpf, ...) + pcap_t *pd, char *bpf, ...) { va_list ap; char buf[3072]; @@ -2002,70 +2011,7 @@ void set_pcap_filter(const char *device, fatal("Failed to set the pcap filter: %s\n", pcap_geterr(pd)); } -#endif /* WIN32 */ - -/* This is ugly :(. We need to get rid of these at some point */ -unsigned long flt_dsthost, flt_srchost; /* _net_ order */ -unsigned short flt_baseport; /* _host_ order */ - -/* Just accept everything ... TODO: Need a better approach than this flt_ - stuff */ -int flt_all(const char *packet, unsigned int len) { - return 1; -} - -int flt_icmptcp(const char *packet, unsigned int len) -{ - struct ip* ip = (struct ip*)packet; - if(ip->ip_dst.s_addr != flt_dsthost) return 0; - if(ip->ip_p == IPPROTO_ICMP) return 1; - if(ip->ip_src.s_addr != flt_srchost) return 0; - if(ip->ip_p == IPPROTO_TCP) return 1; - return 0; -} - -int flt_icmptcp_2port(const char *packet, unsigned int len) -{ - unsigned short dport; - struct ip* ip = (struct ip*)packet; - if(ip->ip_dst.s_addr != flt_dsthost) return 0; - if(ip->ip_p == IPPROTO_ICMP) return 1; - if(ip->ip_src.s_addr != flt_srchost) return 0; - if(ip->ip_p == IPPROTO_TCP) - { - struct tcphdr* tcp = (struct tcphdr *) (((char *) ip) + 4 * ip->ip_hl); - if(len < (unsigned) 4 * ip->ip_hl + 4) return 0; - dport = ntohs(tcp->th_dport); - if(dport == flt_baseport || dport == flt_baseport + 1) - return 1; - } - - return 0; -} - -int flt_icmptcp_5port(const char *packet, unsigned int len) -{ - unsigned short dport; - struct ip* ip = (struct ip*)packet; - if(ip->ip_dst.s_addr != flt_dsthost) return 0; - if(ip->ip_p == IPPROTO_ICMP) return 1; - if(ip->ip_p == IPPROTO_TCP) - { - struct tcphdr* tcp = (struct tcphdr *) (((char *) ip) + 4 * ip->ip_hl); - if(len < (unsigned) 4 * ip->ip_hl + 4) return 0; - dport = ntohs(tcp->th_dport); - if(dport >= flt_baseport && dport <= flt_baseport + 4) return 1; - } - - return 0; -} - - -#ifndef WIN32 /* Currently the Windows code for next few functions is - in wintcpip.c -- should probably be merged at some - point. The dev passed in must be at least - 16 bytes long */ - +/* The 'dev' passed in must be at least 32 bytes long */ int ipaddr2devname( char *dev, const struct in_addr *addr ) { struct interface_info *mydevs; int numdevs; @@ -2081,7 +2027,7 @@ for(i=0; i < numdevs; i++) { if (sin->sin_family != AF_INET) continue; if (addr->s_addr == sin->sin_addr.s_addr) { - Strncpy(dev, mydevs[i].devname, 16); + Strncpy(dev, mydevs[i].devname, 32); return 0; } } @@ -2104,7 +2050,7 @@ for(i=0; i < numdevs; i++) { } return -1; } -#endif /* WIN32 */ + struct dnet_collector_route_nfo { struct sys_route *routes; @@ -2766,8 +2712,6 @@ if (echots) *echots = 0; return 0; } -#ifndef WIN32 // An alternative version of this function is defined in - // mswin32/winip/winip.c int Sendto(char *functionname, int sd, const unsigned char *packet, int len, unsigned int flags, struct sockaddr *to, int tolen) { @@ -2783,6 +2727,9 @@ do { error("sendto in %s: sendto(%d, packet, %d, 0, %s, %d) => %s", functionname, sd, len, inet_ntoa(sin->sin_addr), tolen, strerror(err)); +#if WIN32 + return -1; +#else if (retries > 2 || err == EPERM || err == EACCES || err == EADDRNOTAVAIL || err == EINVAL) return -1; @@ -2790,6 +2737,7 @@ do { error("Sleeping %d seconds then retrying", sleeptime); fflush(stderr); sleep(sleeptime); +#endif } retries++; } while( res == -1); @@ -2798,7 +2746,6 @@ do { return res; } -#endif IPProbe::IPProbe() { packetbuflen = 0; diff --git a/tcpip.h b/tcpip.h index 4e5751372..78d2b1a8d 100644 --- a/tcpip.h +++ b/tcpip.h @@ -662,7 +662,8 @@ void readippacket(const u8 *packet, int readdata); of a TCP packet*/ int readtcppacket(const u8 *packet, int readdata); int readudppacket(const u8 *packet, int readdata); -/* Convert an IP address to the device (IE ppp0 eth0) using that address */ +/* Convert an IP address to the device (IE ppp0 eth0) using that address. Dev passed in must be at least + 32 bytes long */ int ipaddr2devname( char *dev, const struct in_addr *addr ); /* And vice versa */ int devname2ipaddr(char *dev, struct in_addr *addr); @@ -796,7 +797,7 @@ int recvtime(int sd, char *buf, int len, int seconds, int *timedout); /* Sets a pcap filter function -- makes SOCK_RAW reads easier */ #ifndef WINIP_H typedef int (*PFILTERFN)(const char *packet, unsigned int len); /* 1 to keep */ -void set_pcap_filter(const char *device, pcap_t *pd, PFILTERFN filter, char *bpf, ...); +void set_pcap_filter(const char *device, pcap_t *pd, char *bpf, ...); #endif /* Just accept everything ... TODO: Need a better approach than this flt_