mirror of
https://github.com/nmap/nmap.git
synced 2025-12-24 16:39:03 +00:00
Upgrade libpcap to version 1.0.0.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
|
||||
* Copyright (c) 2005 - 2007 CACE Technologies, Davis (California)
|
||||
* Copyright (c) 2005 - 2008 CACE Technologies, Davis (California)
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -33,12 +33,16 @@
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] _U_ =
|
||||
"@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.25.2.7 2007/06/14 22:07:14 gianluca Exp $ (LBL)";
|
||||
"@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.34.2.8 2008-05-21 22:11:26 gianluca Exp $ (LBL)";
|
||||
#endif
|
||||
|
||||
#include <pcap-int.h>
|
||||
#include <Packet32.h>
|
||||
#include <Ntddndis.h>
|
||||
#ifdef __MINGW32__
|
||||
#include <ddk/ndis.h>
|
||||
#else /*__MINGW32__*/
|
||||
#include <ntddndis.h>
|
||||
#endif /*__MINGW32__*/
|
||||
#ifdef HAVE_DAG_API
|
||||
#include <dagnew.h>
|
||||
#include <dagapi.h>
|
||||
@@ -53,8 +57,11 @@ static int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *);
|
||||
static int pcap_getnonblock_win32(pcap_t *, char *);
|
||||
static int pcap_setnonblock_win32(pcap_t *, int, char *);
|
||||
|
||||
#define PcapBufSize 256000 /*dimension of the buffer in the pcap_t structure*/
|
||||
#define SIZE_BUF 1000000
|
||||
/*dimension of the buffer in the pcap_t structure*/
|
||||
#define WIN32_DEFAULT_USER_BUFFER_SIZE 256000
|
||||
|
||||
/*dimension of the buffer in the kernel driver NPF */
|
||||
#define WIN32_DEFAULT_KERNEL_BUFFER_SIZE 1000000
|
||||
|
||||
/* Equivalent to ntohs(), but a lot faster under Windows */
|
||||
#define SWAPS(_X) ((_X & 0xff) << 8) | (_X >> 8)
|
||||
@@ -100,6 +107,43 @@ pcap_stats_win32(pcap_t *p, struct pcap_stat *ps)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the dimension of the kernel-level capture buffer */
|
||||
static int
|
||||
pcap_setbuff_win32(pcap_t *p, int dim)
|
||||
{
|
||||
if(PacketSetBuff(p->adapter,dim)==FALSE)
|
||||
{
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the driver working mode */
|
||||
static int
|
||||
pcap_setmode_win32(pcap_t *p, int mode)
|
||||
{
|
||||
if(PacketSetMode(p->adapter,mode)==FALSE)
|
||||
{
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*set the minimum amount of data that will release a read call*/
|
||||
static int
|
||||
pcap_setmintocopy_win32(pcap_t *p, int size)
|
||||
{
|
||||
if(PacketSetMinToCopy(p->adapter, size)==FALSE)
|
||||
{
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
|
||||
{
|
||||
@@ -376,9 +420,8 @@ pcap_inject_win32(pcap_t *p, const void *buf, size_t size){
|
||||
}
|
||||
|
||||
static void
|
||||
pcap_close_win32(pcap_t *p)
|
||||
pcap_cleanup_win32(pcap_t *p)
|
||||
{
|
||||
pcap_close_common(p);
|
||||
if (p->adapter != NULL) {
|
||||
PacketCloseAdapter(p->adapter);
|
||||
p->adapter = NULL;
|
||||
@@ -387,41 +430,39 @@ pcap_close_win32(pcap_t *p)
|
||||
PacketFreePacket(p->Packet);
|
||||
p->Packet = NULL;
|
||||
}
|
||||
pcap_cleanup_live_common(p);
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
|
||||
char *ebuf)
|
||||
static int
|
||||
pcap_activate_win32(pcap_t *p)
|
||||
{
|
||||
register pcap_t *p;
|
||||
NetType type;
|
||||
|
||||
if (p->opt.rfmon) {
|
||||
/*
|
||||
* No monitor mode on Windows. It could be done on
|
||||
* Vista with drivers that support the native 802.11
|
||||
* mechanism and monitor mode.
|
||||
*/
|
||||
return (PCAP_ERROR_RFMON_NOTSUP);
|
||||
}
|
||||
|
||||
/* Init WinSock */
|
||||
wsockinit();
|
||||
|
||||
p = (pcap_t *)malloc(sizeof(*p));
|
||||
if (p == NULL)
|
||||
{
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
|
||||
return (NULL);
|
||||
}
|
||||
memset(p, 0, sizeof(*p));
|
||||
p->adapter=NULL;
|
||||
|
||||
p->adapter = PacketOpenAdapter((char*)device);
|
||||
p->adapter = PacketOpenAdapter(p->opt.source);
|
||||
|
||||
if (p->adapter == NULL)
|
||||
{
|
||||
free(p);
|
||||
/* Adapter detected but we are not able to open it. Return failure. */
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror());
|
||||
return NULL;
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror());
|
||||
return PCAP_ERROR;
|
||||
}
|
||||
|
||||
/*get network type*/
|
||||
if(PacketGetNetType (p->adapter,&type) == FALSE)
|
||||
{
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror());
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror());
|
||||
goto bad;
|
||||
}
|
||||
|
||||
@@ -505,12 +546,12 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
|
||||
}
|
||||
|
||||
/* Set promiscuous mode */
|
||||
if (promisc)
|
||||
if (p->opt.promisc)
|
||||
{
|
||||
|
||||
if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE)
|
||||
{
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode");
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode");
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
@@ -518,21 +559,18 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
|
||||
{
|
||||
if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL) == FALSE)
|
||||
{
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode");
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode");
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the buffer size */
|
||||
p->bufsize = PcapBufSize;
|
||||
|
||||
/* Store the timeout. Used by pcap_setnonblock() */
|
||||
p->timeout= to_ms;
|
||||
p->bufsize = WIN32_DEFAULT_USER_BUFFER_SIZE;
|
||||
|
||||
/* allocate Packet structure used during the capture */
|
||||
if((p->Packet = PacketAllocatePacket())==NULL)
|
||||
{
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure");
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
@@ -541,29 +579,32 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
|
||||
/*
|
||||
* Traditional Adapter
|
||||
*/
|
||||
/*
|
||||
* If the buffer size wasn't explicitly set, default to
|
||||
* WIN32_DEFAULT_USER_BUFFER_SIZE.
|
||||
*/
|
||||
if (p->opt.buffer_size == 0)
|
||||
p->opt.buffer_size = WIN32_DEFAULT_KERNEL_BUFFER_SIZE;
|
||||
|
||||
if(PacketSetBuff(p->adapter,p->opt.buffer_size)==FALSE)
|
||||
{
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
p->buffer = (u_char *)malloc(PcapBufSize);
|
||||
p->buffer = (u_char *)malloc(p->bufsize);
|
||||
if (p->buffer == NULL)
|
||||
{
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
|
||||
|
||||
p->snapshot = snaplen;
|
||||
|
||||
/* allocate the standard buffer in the driver */
|
||||
if(PacketSetBuff( p->adapter, SIZE_BUF)==FALSE)
|
||||
{
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE,"driver error: not enough memory to allocate the kernel buffer\n");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* tell the driver to copy the buffer only if it contains at least 16K */
|
||||
if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
|
||||
{
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s\n", pcap_win32strerror());
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror());
|
||||
goto bad;
|
||||
}
|
||||
}
|
||||
@@ -582,7 +623,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
|
||||
|
||||
snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s",
|
||||
"SYSTEM\\CurrentControlSet\\Services\\DAG",
|
||||
strstr(_strlwr((char*)device), "dag"));
|
||||
strstr(_strlwr(p->opt.source), "dag"));
|
||||
do
|
||||
{
|
||||
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &dagkey);
|
||||
@@ -616,7 +657,7 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
|
||||
goto bad;
|
||||
#endif /* HAVE_DAG_API */
|
||||
|
||||
PacketSetReadTimeout(p->adapter, to_ms);
|
||||
PacketSetReadTimeout(p->adapter, p->md.timeout);
|
||||
|
||||
#ifdef HAVE_DAG_API
|
||||
if(p->adapter->Flags & INFO_FLAG_DAG_CARD)
|
||||
@@ -641,25 +682,60 @@ pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
|
||||
p->getnonblock_op = pcap_getnonblock_win32;
|
||||
p->setnonblock_op = pcap_setnonblock_win32;
|
||||
p->stats_op = pcap_stats_win32;
|
||||
p->close_op = pcap_close_win32;
|
||||
p->setbuff_op = pcap_setbuff_win32;
|
||||
p->setmode_op = pcap_setmode_win32;
|
||||
p->setmintocopy_op = pcap_setmintocopy_win32;
|
||||
p->cleanup_op = pcap_cleanup_win32;
|
||||
|
||||
return (p);
|
||||
return (0);
|
||||
bad:
|
||||
if (p->adapter)
|
||||
PacketCloseAdapter(p->adapter);
|
||||
if (p->buffer != NULL)
|
||||
free(p->buffer);
|
||||
if(p->Packet)
|
||||
PacketFreePacket(p->Packet);
|
||||
/*
|
||||
* Get rid of any link-layer type list we allocated.
|
||||
*/
|
||||
if (p->dlt_list != NULL)
|
||||
free(p->dlt_list);
|
||||
free(p);
|
||||
return (NULL);
|
||||
pcap_cleanup_win32(p);
|
||||
return (PCAP_ERROR);
|
||||
}
|
||||
|
||||
pcap_t *
|
||||
pcap_create(const char *device, char *ebuf)
|
||||
{
|
||||
pcap_t *p;
|
||||
|
||||
if (strlen(device) == 1)
|
||||
{
|
||||
/*
|
||||
* It's probably a unicode string
|
||||
* Convert to ascii and pass it to pcap_create_common
|
||||
*
|
||||
* This wonderful hack is needed because pcap_lookupdev still returns
|
||||
* unicode strings, and it's used by windump when no device is specified
|
||||
* in the command line
|
||||
*/
|
||||
size_t length;
|
||||
char* deviceAscii;
|
||||
|
||||
length = wcslen((wchar_t*)device);
|
||||
|
||||
deviceAscii = (char*)malloc(length + 1);
|
||||
|
||||
if (deviceAscii == NULL)
|
||||
{
|
||||
snprintf(ebuf, PCAP_ERRBUF_SIZE, "Malloc failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snprintf(deviceAscii, length + 1, "%ws", (wchar_t*)device);
|
||||
p = pcap_create_common(deviceAscii, ebuf);
|
||||
free(deviceAscii);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = pcap_create_common(device, ebuf);
|
||||
}
|
||||
|
||||
if (p == NULL)
|
||||
return (NULL);
|
||||
|
||||
p->activate_op = pcap_activate_win32;
|
||||
return (p);
|
||||
}
|
||||
|
||||
static int
|
||||
pcap_setfilter_win32_npf(pcap_t *p, struct bpf_program *fp)
|
||||
@@ -736,7 +812,7 @@ pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
|
||||
* (Note that this may be -1, in which case we're not
|
||||
* really leaving non-blocking mode.)
|
||||
*/
|
||||
newtimeout = p->timeout;
|
||||
newtimeout = p->md.timeout;
|
||||
}
|
||||
if (!PacketSetReadTimeout(p->adapter, newtimeout)) {
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
|
||||
@@ -747,57 +823,9 @@ pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Set the driver working mode */
|
||||
int
|
||||
pcap_setmode(pcap_t *p, int mode){
|
||||
|
||||
if (p->adapter==NULL)
|
||||
{
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "impossible to set mode while reading from a file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(PacketSetMode(p->adapter,mode)==FALSE)
|
||||
{
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set the dimension of the kernel-level capture buffer */
|
||||
int
|
||||
pcap_setbuff(pcap_t *p, int dim)
|
||||
/*platform-dependent routine to add devices other than NDIS interfaces*/
|
||||
int
|
||||
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
|
||||
{
|
||||
if (p->adapter==NULL)
|
||||
{
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The kernel buffer size cannot be set while reading from a file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(PacketSetBuff(p->adapter,dim)==FALSE)
|
||||
{
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*set the minimum amount of data that will release a read call*/
|
||||
int
|
||||
pcap_setmintocopy(pcap_t *p, int size)
|
||||
{
|
||||
if (p->adapter==NULL)
|
||||
{
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Impossible to set the mintocopy parameter on an offline capture");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(PacketSetMinToCopy(p->adapter, size)==FALSE)
|
||||
{
|
||||
snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user