#define PCAP_DONT_INCLUDE_PCAP_BPF_H
#include <Packet32.h>
#include <pcap-int.h>
#include <pcap/dlt.h>
#ifdef __MINGW32__
#ifdef __MINGW64__
#include <ntddndis.h>
#else
#include <ddk/ntddndis.h>
#include <ddk/ndis.h>
#endif
#else
#include <ntddndis.h>
#endif
#ifdef HAVE_DAG_API
#include <dagnew.h>
#include <dagapi.h>
#endif
#ifdef __MINGW32__
int* _errno();
#define errno (*_errno())
#endif
#ifdef HAVE_REMOTE
#include "pcap-rpcap.h"
#endif
static int pcap_setfilter_win32_npf(pcap_t *, struct bpf_program *);
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 WIN32_DEFAULT_USER_BUFFER_SIZE 256000
#define WIN32_DEFAULT_KERNEL_BUFFER_SIZE 1000000
#define SWAPS(_X) ((_X & 0xff) << 8) | (_X >> 8)
struct pcap_win {
int nonblock;
int rfmon_selfstart;
int filtering_in_kernel;
#ifdef HAVE_DAG_API
int dag_fcs_bits;
#endif
};
BOOL WINAPI DllMain(
HANDLE hinstDLL,
DWORD dwReason,
LPVOID lpvReserved
)
{
return (TRUE);
}
#ifndef HAVE_NPCAP_PACKET_API
static int
PacketIsMonitorModeSupported(PCHAR AdapterName _U_)
{
return (0);
}
static int
PacketSetMonitorMode(PCHAR AdapterName _U_, int mode _U_)
{
return (0);
}
static int
PacketGetMonitorMode(PCHAR AdapterName _U_)
{
return (-1);
}
#endif
int
wsockinit(void)
{
WORD wVersionRequested;
WSADATA wsaData;
static int err = -1;
static int done = 0;
if (done)
return (err);
wVersionRequested = MAKEWORD( 1, 1);
err = WSAStartup( wVersionRequested, &wsaData );
atexit ((void(*)(void))WSACleanup);
done = 1;
if ( err != 0 )
err = -1;
return (err);
}
int
pcap_wsockinit(void)
{
return (wsockinit());
}
static int
pcap_stats_win32(pcap_t *p, struct pcap_stat *ps)
{
struct bpf_stat bstats;
char errbuf[PCAP_ERRBUF_SIZE+1];
if (!PacketGetStats(p->adapter, &bstats)) {
pcap_win32_err_to_str(GetLastError(), errbuf);
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"PacketGetStats error: %s", errbuf);
return (-1);
}
ps->ps_recv = bstats.bs_recv;
ps->ps_drop = bstats.bs_drop;
#if 0
ps->ps_ifdrop = bstats.ps_ifdrop;
#else
ps->ps_ifdrop = 0;
#endif
return (0);
}
struct pcap_stat *
pcap_stats_ex_win32(pcap_t *p, int *pcap_stat_size)
{
struct bpf_stat bstats;
char errbuf[PCAP_ERRBUF_SIZE+1];
*pcap_stat_size = sizeof (p->stat);
if (!PacketGetStatsEx(p->adapter, &bstats)) {
pcap_win32_err_to_str(GetLastError(), errbuf);
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"PacketGetStatsEx error: %s", errbuf);
return (NULL);
}
p->stat.ps_recv = bstats.bs_recv;
p->stat.ps_drop = bstats.bs_drop;
p->stat.ps_ifdrop = bstats.ps_ifdrop;
#ifdef HAVE_REMOTE
p->stat.ps_capt = bstats.bs_capt;
#endif
return (&p->stat);
}
static int
pcap_setbuff_win32(pcap_t *p, int dim)
{
if(PacketSetBuff(p->adapter,dim)==FALSE)
{
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
return (-1);
}
return (0);
}
static int
pcap_setmode_win32(pcap_t *p, int mode)
{
if(PacketSetMode(p->adapter,mode)==FALSE)
{
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
return (-1);
}
return (0);
}
static int
pcap_setmintocopy_win32(pcap_t *p, int size)
{
if(PacketSetMinToCopy(p->adapter, size)==FALSE)
{
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
return (-1);
}
return (0);
}
static HANDLE
pcap_getevent_win32(pcap_t *p)
{
return (PacketGetReadEvent(p->adapter));
}
static int
pcap_oid_get_request_win32(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp)
{
PACKET_OID_DATA *oid_data_arg;
char errbuf[PCAP_ERRBUF_SIZE+1];
oid_data_arg = malloc(sizeof (PACKET_OID_DATA) + *lenp);
if (oid_data_arg == NULL) {
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Couldn't allocate argument buffer for PacketRequest");
return (PCAP_ERROR);
}
oid_data_arg->Oid = oid;
oid_data_arg->Length = (ULONG)(*lenp);
if (!PacketRequest(p->adapter, FALSE, oid_data_arg)) {
pcap_win32_err_to_str(GetLastError(), errbuf);
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Error calling PacketRequest: %s", errbuf);
free(oid_data_arg);
return (PCAP_ERROR);
}
*lenp = oid_data_arg->Length;
memcpy(data, oid_data_arg->Data, *lenp);
free(oid_data_arg);
return (0);
}
static int
pcap_oid_set_request_win32(pcap_t *p, bpf_u_int32 oid, const void *data,
size_t *lenp)
{
PACKET_OID_DATA *oid_data_arg;
char errbuf[PCAP_ERRBUF_SIZE+1];
oid_data_arg = malloc(sizeof (PACKET_OID_DATA) + *lenp);
if (oid_data_arg == NULL) {
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Couldn't allocate argument buffer for PacketRequest");
return (PCAP_ERROR);
}
oid_data_arg->Oid = oid;
oid_data_arg->Length = (ULONG)(*lenp);
memcpy(oid_data_arg->Data, data, *lenp);
if (!PacketRequest(p->adapter, TRUE, oid_data_arg)) {
pcap_win32_err_to_str(GetLastError(), errbuf);
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Error calling PacketRequest: %s", errbuf);
free(oid_data_arg);
return (PCAP_ERROR);
}
*lenp = oid_data_arg->Length;
free(oid_data_arg);
return (0);
}
static u_int
pcap_sendqueue_transmit_win32(pcap_t *p, pcap_send_queue *queue, int sync)
{
u_int res;
char errbuf[PCAP_ERRBUF_SIZE+1];
if (p->adapter==NULL) {
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Cannot transmit a queue to an offline capture or to a TurboCap port");
return (0);
}
res = PacketSendPackets(p->adapter,
queue->buffer,
queue->len,
(BOOLEAN)sync);
if(res != queue->len){
pcap_win32_err_to_str(GetLastError(), errbuf);
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Error opening adapter: %s", errbuf);
}
return (res);
}
static int
pcap_setuserbuffer_win32(pcap_t *p, int size)
{
unsigned char *new_buff;
if (size<=0) {
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Error: invalid size %d",size);
return (-1);
}
new_buff=(unsigned char*)malloc(sizeof(char)*size);
if (!new_buff) {
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Error: not enough memory");
return (-1);
}
free(p->buffer);
p->buffer=new_buff;
p->bufsize=size;
return (0);
}
static int
pcap_live_dump_win32(pcap_t *p, char *filename, int maxsize, int maxpacks)
{
BOOLEAN res;
res = PacketSetMode(p->adapter, PACKET_MODE_DUMP);
if(res == FALSE){
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Error setting dump mode");
return (-1);
}
res = PacketSetDumpName(p->adapter, filename, (int)strlen(filename));
if(res == FALSE){
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Error setting kernel dump file name");
return (-1);
}
res = PacketSetDumpLimits(p->adapter, maxsize, maxpacks);
return (0);
}
static int
pcap_live_dump_ended_win32(pcap_t *p, int sync)
{
return (PacketIsDumpEnded(p->adapter, (BOOLEAN)sync));
}
static PAirpcapHandle
pcap_get_airpcap_handle_win32(pcap_t *p)
{
#ifdef HAVE_AIRPCAP_API
return (PacketGetAirPcapHandle(p->adapter));
#else
return (NULL);
#endif
}
static int
pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
PACKET Packet;
int cc;
int n = 0;
register u_char *bp, *ep;
u_char *datap;
struct pcap_win *pw = p->priv;
cc = p->cc;
if (p->cc == 0) {
if (p->break_loop) {
p->break_loop = 0;
return (PCAP_ERROR_BREAK);
}
PacketInitPacket(&Packet, (BYTE *)p->buffer, p->bufsize);
if (!PacketReceivePacket(p->adapter, &Packet, TRUE)) {
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
return (PCAP_ERROR);
}
cc = Packet.ulBytesReceived;
bp = p->buffer;
}
else
bp = p->bp;
#define bhp ((struct bpf_hdr *)bp)
ep = bp + cc;
while (1) {
register int caplen, hdrlen;
if (p->break_loop) {
if (n == 0) {
p->break_loop = 0;
return (PCAP_ERROR_BREAK);
} else {
p->bp = bp;
p->cc = (int) (ep - bp);
return (n);
}
}
if (bp >= ep)
break;
caplen = bhp->bh_caplen;
hdrlen = bhp->bh_hdrlen;
datap = bp + hdrlen;
if (pw->filtering_in_kernel ||
p->fcode.bf_insns == NULL ||
bpf_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) {
(*callback)(user, (struct pcap_pkthdr*)bp, datap);
bp += Packet_WORDALIGN(caplen + hdrlen);
if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
p->bp = bp;
p->cc = (int) (ep - bp);
return (n);
}
} else {
bp += Packet_WORDALIGN(caplen + hdrlen);
}
}
#undef bhp
p->cc = 0;
return (n);
}
#ifdef HAVE_DAG_API
static int
pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
{
struct pcap_win *pw = p->priv;
PACKET Packet;
u_char *dp = NULL;
int packet_len = 0, caplen = 0;
struct pcap_pkthdr pcap_header;
u_char *endofbuf;
int n = 0;
dag_record_t *header;
unsigned erf_record_len;
ULONGLONG ts;
int cc;
unsigned swt;
unsigned dfp = p->adapter->DagFastProcess;
cc = p->cc;
if (cc == 0)
{
PacketInitPacket(&Packet, (BYTE *)p->buffer, p->bufsize);
if (!PacketReceivePacket(p->adapter, &Packet, TRUE)) {
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
return (-1);
}
cc = Packet.ulBytesReceived;
if(cc == 0)
return (0);
header = (dag_record_t*)p->adapter->DagBuffer;
}
else
header = (dag_record_t*)p->bp;
endofbuf = (char*)header + cc;
do
{
erf_record_len = SWAPS(header->rlen);
if((char*)header + erf_record_len > endofbuf)
break;
p->stat.ps_recv++;
dp = ((u_char *)header) + dag_record_size;
switch(header->type)
{
case TYPE_ATM:
packet_len = ATM_SNAPLEN;
caplen = ATM_SNAPLEN;
dp += 4;
break;
case TYPE_ETH:
swt = SWAPS(header->wlen);
packet_len = swt - (pw->dag_fcs_bits);
caplen = erf_record_len - dag_record_size - 2;
if (caplen > packet_len)
{
caplen = packet_len;
}
dp += 2;
break;
case TYPE_HDLC_POS:
swt = SWAPS(header->wlen);
packet_len = swt - (pw->dag_fcs_bits);
caplen = erf_record_len - dag_record_size;
if (caplen > packet_len)
{
caplen = packet_len;
}
break;
}
if(caplen > p->snapshot)
caplen = p->snapshot;
if (p->break_loop)
{
if (n == 0)
{
p->break_loop = 0;
return (-2);
}
else
{
p->bp = (char*)header;
p->cc = endofbuf - (char*)header;
return (n);
}
}
if(!dfp)
{
ts = header->ts;
pcap_header.ts.tv_sec = (int)(ts >> 32);
ts = (ts & 0xffffffffi64) * 1000000;
ts += 0x80000000;
pcap_header.ts.tv_usec = (int)(ts >> 32);
if (pcap_header.ts.tv_usec >= 1000000) {
pcap_header.ts.tv_usec -= 1000000;
pcap_header.ts.tv_sec++;
}
}
if (p->fcode.bf_insns)
{
if (bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen) == 0)
{
header = (dag_record_t*)((char*)header + erf_record_len);
continue;
}
}
pcap_header.caplen = caplen;
pcap_header.len = packet_len;
(*callback)(user, &pcap_header, dp);
header = (dag_record_t*)((char*)header + erf_record_len);
if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt))
{
p->bp = (char*)header;
p->cc = endofbuf - (char*)header;
return (n);
}
}
while((u_char*)header < endofbuf);
return (1);
}
#endif
static int
pcap_inject_win32(pcap_t *p, const void *buf, size_t size){
LPPACKET PacketToSend;
PacketToSend=PacketAllocatePacket();
if (PacketToSend == NULL)
{
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketAllocatePacket failed");
return (-1);
}
PacketInitPacket(PacketToSend, (PVOID)buf, (UINT)size);
if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed");
PacketFreePacket(PacketToSend);
return (-1);
}
PacketFreePacket(PacketToSend);
return ((int)size);
}
static void
pcap_cleanup_win32(pcap_t *p)
{
struct pcap_win *pw = p->priv;
if (p->adapter != NULL) {
PacketCloseAdapter(p->adapter);
p->adapter = NULL;
}
if (pw->rfmon_selfstart)
{
PacketSetMonitorMode(p->opt.device, 0);
}
pcap_cleanup_live_common(p);
}
static int
pcap_activate_win32(pcap_t *p)
{
struct pcap_win *pw = p->priv;
NetType type;
int res;
char errbuf[PCAP_ERRBUF_SIZE+1];
#ifdef HAVE_REMOTE
char host[PCAP_BUF_SIZE + 1];
char port[PCAP_BUF_SIZE + 1];
char name[PCAP_BUF_SIZE + 1];
int srctype;
int opensource_remote_result;
struct pcap_md *md;
md = (struct pcap_md *) ((u_char*)p->priv + sizeof(struct pcap_win));
if (pcap_parsesrcstr(p->opt.device, &srctype, host, port, name, p->errbuf))
return PCAP_ERROR;
if (srctype == PCAP_SRC_IFREMOTE)
{
opensource_remote_result = pcap_opensource_remote(p, NULL);
if (opensource_remote_result != 0)
return opensource_remote_result;
md->rmt_flags = (p->opt.promisc) ? PCAP_OPENFLAG_PROMISCUOUS : 0;
return 0;
}
if (srctype == PCAP_SRC_IFLOCAL)
{
if (strncmp(p->opt.device, PCAP_SRC_IF_STRING, strlen(PCAP_SRC_IF_STRING)) == 0)
{
size_t len = strlen(p->opt.device) - strlen(PCAP_SRC_IF_STRING) + 1;
char *new_string;
if (len > 0)
{
new_string = (char*)malloc(len);
if (new_string != NULL)
{
char *tmp;
strcpy_s(new_string, len, p->opt.device + strlen(PCAP_SRC_IF_STRING));
tmp = p->opt.device;
p->opt.device = new_string;
free(tmp);
}
}
}
}
#endif
if (p->opt.rfmon) {
if (PacketGetMonitorMode(p->opt.device) == 1)
{
pw->rfmon_selfstart = 0;
}
else
{
if ((res = PacketSetMonitorMode(p->opt.device, 1)) != 1)
{
pw->rfmon_selfstart = 0;
if (res == 0)
{
return PCAP_ERROR_RFMON_NOTSUP;
}
else
{
return PCAP_ERROR;
}
}
else
{
pw->rfmon_selfstart = 1;
}
}
}
wsockinit();
p->adapter = PacketOpenAdapter(p->opt.device);
if (p->adapter == NULL)
{
pcap_win32_err_to_str(GetLastError(), errbuf);
if (pw->rfmon_selfstart)
{
PacketSetMonitorMode(p->opt.device, 0);
}
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Error opening adapter: %s", errbuf);
return (PCAP_ERROR);
}
if(PacketGetNetType (p->adapter,&type) == FALSE)
{
pcap_win32_err_to_str(GetLastError(), errbuf);
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Cannot determine the network type: %s", errbuf);
goto bad;
}
switch (type.LinkType)
{
case NdisMediumWan:
p->linktype = DLT_EN10MB;
break;
case NdisMedium802_3:
p->linktype = DLT_EN10MB;
p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
if (p->dlt_list != NULL) {
p->dlt_list[0] = DLT_EN10MB;
p->dlt_list[1] = DLT_DOCSIS;
p->dlt_count = 2;
}
break;
case NdisMediumFddi:
p->linktype = DLT_FDDI;
break;
case NdisMedium802_5:
p->linktype = DLT_IEEE802;
break;
case NdisMediumArcnetRaw:
p->linktype = DLT_ARCNET;
break;
case NdisMediumArcnet878_2:
p->linktype = DLT_ARCNET;
break;
case NdisMediumAtm:
p->linktype = DLT_ATM_RFC1483;
break;
case NdisMediumCHDLC:
p->linktype = DLT_CHDLC;
break;
case NdisMediumPPPSerial:
p->linktype = DLT_PPP_SERIAL;
break;
case NdisMediumNull:
p->linktype = DLT_NULL;
break;
case NdisMediumBare80211:
p->linktype = DLT_IEEE802_11;
break;
case NdisMediumRadio80211:
p->linktype = DLT_IEEE802_11_RADIO;
break;
case NdisMediumPpi:
p->linktype = DLT_PPI;
break;
default:
p->linktype = DLT_EN10MB;
break;
}
if (p->opt.promisc)
{
if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE)
{
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode");
goto bad;
}
}
else
{
if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL) == FALSE)
{
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode");
goto bad;
}
}
p->bufsize = WIN32_DEFAULT_USER_BUFFER_SIZE;
if(!(p->adapter->Flags & INFO_FLAG_DAG_CARD))
{
if (p->opt.buffer_size == 0)
p->opt.buffer_size = WIN32_DEFAULT_KERNEL_BUFFER_SIZE;
if(PacketSetBuff(p->adapter,p->opt.buffer_size)==FALSE)
{
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
goto bad;
}
p->buffer = malloc(p->bufsize);
if (p->buffer == NULL)
{
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
goto bad;
}
if (p->opt.immediate)
{
if(PacketSetMinToCopy(p->adapter,0)==FALSE)
{
pcap_win32_err_to_str(GetLastError(), errbuf);
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Error calling PacketSetMinToCopy: %s",
errbuf);
goto bad;
}
}
else
{
if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
{
pcap_win32_err_to_str(GetLastError(), errbuf);
pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
"Error calling PacketSetMinToCopy: %s",
errbuf);
goto bad;
}
}
}
else
#ifdef HAVE_DAG_API
{
LONG status;
HKEY dagkey;
DWORD lptype;
DWORD lpcbdata;
int postype = 0;
char keyname[512];
pcap_snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s",
"SYSTEM\\CurrentControlSet\\Services\\DAG",
strstr(_strlwr(p->opt.device), "dag"));
do
{
status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &dagkey);
if(status != ERROR_SUCCESS)
break;
status = RegQueryValueEx(dagkey,
"PosType",
NULL,
&lptype,
(char*)&postype,
&lpcbdata);
if(status != ERROR_SUCCESS)
{
postype = 0;
}
RegCloseKey(dagkey);
}
while(FALSE);
p->snapshot = PacketSetSnapLen(p->adapter, snaplen);
pw->dag_fcs_bits = p->adapter->DagFcsLen;
}
#else
goto bad;
#endif
PacketSetReadTimeout(p->adapter, p->opt.timeout);
#ifdef HAVE_DAG_API
if(p->adapter->Flags & INFO_FLAG_DAG_CARD)
{
p->read_op = pcap_read_win32_dag;
p->setfilter_op = pcap_setfilter_win32_dag;
}
else
{
#endif
p->read_op = pcap_read_win32_npf;
p->setfilter_op = pcap_setfilter_win32_npf;
#ifdef HAVE_DAG_API
}
#endif
p->setdirection_op = NULL;
p->inject_op = pcap_inject_win32;
p->set_datalink_op = NULL;
p->getnonblock_op = pcap_getnonblock_win32;
p->setnonblock_op = pcap_setnonblock_win32;
p->stats_op = pcap_stats_win32;
p->stats_ex_op = pcap_stats_ex_win32;
p->setbuff_op = pcap_setbuff_win32;
p->setmode_op = pcap_setmode_win32;
p->setmintocopy_op = pcap_setmintocopy_win32;
p->getevent_op = pcap_getevent_win32;
p->oid_get_request_op = pcap_oid_get_request_win32;
p->oid_set_request_op = pcap_oid_set_request_win32;
p->sendqueue_transmit_op = pcap_sendqueue_transmit_win32;
p->setuserbuffer_op = pcap_setuserbuffer_win32;
p->live_dump_op = pcap_live_dump_win32;
p->live_dump_ended_op = pcap_live_dump_ended_win32;
p->get_airpcap_handle_op = pcap_get_airpcap_handle_win32;
p->cleanup_op = pcap_cleanup_win32;
return (0);
bad:
pcap_cleanup_win32(p);
return (PCAP_ERROR);
}
static int
pcap_can_set_rfmon_win32(pcap_t *p)
{
return (PacketIsMonitorModeSupported(p->opt.device) == 1);
}
pcap_t *
pcap_create_interface(const char *device _U_, char *ebuf)
{
pcap_t *p;
#ifdef HAVE_REMOTE
p = pcap_create_common(ebuf, sizeof(struct pcap_win) + sizeof(struct pcap_md));
#else
p = pcap_create_common(ebuf, sizeof(struct pcap_win));
#endif
if (p == NULL)
return (NULL);
p->activate_op = pcap_activate_win32;
p->can_set_rfmon_op = pcap_can_set_rfmon_win32;
return (p);
}
static int
pcap_setfilter_win32_npf(pcap_t *p, struct bpf_program *fp)
{
struct pcap_win *pw = p->priv;
if(PacketSetBpf(p->adapter,fp)==FALSE){
if (install_bpf_program(p, fp) < 0)
return (-1);
pw->filtering_in_kernel = 0;
return (0);
}
pw->filtering_in_kernel = 1;
p->cc = 0;
return (0);
}
static int
pcap_setfilter_win32_dag(pcap_t *p, struct bpf_program *fp) {
if(!fp)
{
strlcpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
return (-1);
}
if (install_bpf_program(p, fp) < 0)
{
pcap_snprintf(p->errbuf, sizeof(p->errbuf),
"setfilter, unable to install the filter: %s", pcap_strerror(errno));
return (-1);
}
return (0);
}
static int
pcap_getnonblock_win32(pcap_t *p, char *errbuf)
{
struct pcap_win *pw = p->priv;
return (pw->nonblock);
}
static int
pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
{
struct pcap_win *pw = p->priv;
int newtimeout;
char win_errbuf[PCAP_ERRBUF_SIZE+1];
if (nonblock) {
newtimeout = -1;
} else {
newtimeout = p->opt.timeout;
}
if (!PacketSetReadTimeout(p->adapter, newtimeout)) {
pcap_win32_err_to_str(GetLastError(), win_errbuf);
pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"PacketSetReadTimeout: %s", win_errbuf);
return (-1);
}
pw->nonblock = (newtimeout == -1);
return (0);
}
static int
pcap_add_if_win32(pcap_if_t **devlist, char *name, bpf_u_int32 flags,
const char *description, char *errbuf)
{
pcap_if_t *curdev;
npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
LONG if_addr_size;
int res = 0;
if_addr_size = MAX_NETWORK_ADDRESSES;
if (add_or_find_if(&curdev, devlist, name, flags, description,
errbuf) == -1) {
return (-1);
}
if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) {
return (0);
}
while (if_addr_size-- > 0) {
if(curdev == NULL)
break;
res = add_addr_to_dev(curdev,
(struct sockaddr *)&if_addrs[if_addr_size].IPAddress,
sizeof (struct sockaddr_storage),
(struct sockaddr *)&if_addrs[if_addr_size].SubnetMask,
sizeof (struct sockaddr_storage),
(struct sockaddr *)&if_addrs[if_addr_size].Broadcast,
sizeof (struct sockaddr_storage),
NULL,
0,
errbuf);
if (res == -1) {
break;
}
}
return (res);
}
int
pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
{
pcap_if_t *devlist = NULL;
int ret = 0;
const char *desc;
char *AdaptersName;
ULONG NameLength;
char *name;
char our_errbuf[PCAP_ERRBUF_SIZE+1];
NameLength = 0;
if (!PacketGetAdapterNames(NULL, &NameLength))
{
DWORD last_error = GetLastError();
if (last_error != ERROR_INSUFFICIENT_BUFFER)
{
pcap_win32_err_to_str(last_error, our_errbuf);
pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
"PacketGetAdapterNames: %s", our_errbuf);
return (-1);
}
}
if (NameLength > 0)
AdaptersName = (char*) malloc(NameLength);
else
{
*alldevsp = NULL;
return 0;
}
if (AdaptersName == NULL)
{
pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters.");
return (-1);
}
if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
pcap_win32_err_to_str(GetLastError(), our_errbuf);
pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "PacketGetAdapterNames: %s",
our_errbuf);
free(AdaptersName);
return (-1);
}
desc = &AdaptersName[0];
while (*desc != '\0' || *(desc + 1) != '\0')
desc++;
desc += 2;
name = &AdaptersName[0];
while (*name != '\0') {
bpf_u_int32 flags = 0;
#ifdef HAVE_PACKET_IS_LOOPBACK_ADAPTER
if (PacketIsLoopbackAdapter(name)) {
flags |= PCAP_IF_LOOPBACK;
}
#endif
if (pcap_add_if_win32(&devlist, name, flags, desc,
errbuf) == -1) {
ret = -1;
break;
}
name += strlen(name) + 1;
desc += strlen(desc) + 1;
}
if (ret == -1) {
if (devlist != NULL) {
pcap_freealldevs(devlist);
devlist = NULL;
}
}
*alldevsp = devlist;
free(AdaptersName);
return (ret);
}