diff options
Diffstat (limited to 'contrib/libpcap/pcap-win32.c')
-rw-r--r-- | contrib/libpcap/pcap-win32.c | 258 |
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); } |