summaryrefslogtreecommitdiffstats
path: root/contrib/libpcap/pcap-win32.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libpcap/pcap-win32.c')
-rw-r--r--contrib/libpcap/pcap-win32.c258
1 files changed, 143 insertions, 115 deletions
diff --git a/contrib/libpcap/pcap-win32.c b/contrib/libpcap/pcap-win32.c
index 435da66..4fea621 100644
--- a/contrib/libpcap/pcap-win32.c
+++ b/contrib/libpcap/pcap-win32.c
@@ -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
*/
-
- p->buffer = (u_char *)malloc(PcapBufSize);
- if (p->buffer == NULL)
+ /*
+ * 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(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
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)
+ p->buffer = (u_char *)malloc(p->bufsize);
+ if (p->buffer == NULL)
{
- snprintf(ebuf, PCAP_ERRBUF_SIZE,"driver error: not enough memory to allocate the kernel buffer\n");
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
goto bad;
}
+ PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
+
/* 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);
}
OpenPOWER on IntegriCloud