Blame pcap-tc.c

Packit 209cc3
/*
Packit 209cc3
 * Copyright (c) 2008 CACE Technologies, Davis (California)
Packit 209cc3
 * All rights reserved.
Packit 209cc3
 *
Packit 209cc3
 * Redistribution and use in source and binary forms, with or without
Packit 209cc3
 * modification, are permitted provided that the following conditions
Packit 209cc3
 * are met:
Packit 209cc3
 *
Packit 209cc3
 * 1. Redistributions of source code must retain the above copyright
Packit 209cc3
 * notice, this list of conditions and the following disclaimer.
Packit 209cc3
 * 2. Redistributions in binary form must reproduce the above copyright
Packit 209cc3
 * notice, this list of conditions and the following disclaimer in the
Packit 209cc3
 * documentation and/or other materials provided with the distribution.
Packit 209cc3
 * 3. Neither the name of CACE Technologies nor the names of its
Packit 209cc3
 * contributors may be used to endorse or promote products derived from
Packit 209cc3
 * this software without specific prior written permission.
Packit 209cc3
 *
Packit 209cc3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 209cc3
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 209cc3
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit 209cc3
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit 209cc3
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit 209cc3
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 209cc3
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit 209cc3
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit 209cc3
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 209cc3
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 209cc3
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 209cc3
 *
Packit 209cc3
 */
Packit 209cc3
Packit 209cc3
#ifdef HAVE_CONFIG_H
Packit 209cc3
#include <config.h>
Packit 209cc3
#endif
Packit 209cc3
Packit 209cc3
#include <pcap.h>
Packit 209cc3
#include <pcap-int.h>
Packit 209cc3
Packit 209cc3
#include "pcap-tc.h"
Packit 209cc3
Packit 209cc3
#include <malloc.h>
Packit 209cc3
#include <memory.h>
Packit 209cc3
#include <string.h>
Packit 209cc3
#include <errno.h>
Packit 209cc3
Packit 209cc3
#ifdef _WIN32
Packit 209cc3
#include <tchar.h>
Packit 209cc3
#endif
Packit 209cc3
Packit 209cc3
typedef TC_STATUS	(TC_CALLCONV *TcFcnQueryPortList)			(PTC_PORT *ppPorts, PULONG pLength);
Packit 209cc3
typedef TC_STATUS	(TC_CALLCONV *TcFcnFreePortList)			(TC_PORT *pPorts);
Packit 209cc3
Packit 209cc3
typedef PCHAR		(TC_CALLCONV *TcFcnStatusGetString)			(TC_STATUS status);
Packit 209cc3
Packit 209cc3
typedef PCHAR		(TC_CALLCONV *TcFcnPortGetName)				(TC_PORT port);
Packit 209cc3
typedef PCHAR		(TC_CALLCONV *TcFcnPortGetDescription)		(TC_PORT port);
Packit 209cc3
Packit 209cc3
typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceOpenByName)		(PCHAR name, PTC_INSTANCE pInstance);
Packit 209cc3
typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceClose)			(TC_INSTANCE instance);
Packit 209cc3
typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceSetFeature)		(TC_INSTANCE instance, ULONG feature, ULONG value);
Packit 209cc3
typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceQueryFeature)	(TC_INSTANCE instance, ULONG feature, PULONG pValue);
Packit 209cc3
typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceReceivePackets)	(TC_INSTANCE instance, PTC_PACKETS_BUFFER pBuffer);
Packit 209cc3
typedef HANDLE		(TC_CALLCONV *TcFcnInstanceGetReceiveWaitHandle) (TC_INSTANCE instance);
Packit 209cc3
typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceTransmitPackets)	(TC_INSTANCE instance, TC_PACKETS_BUFFER pBuffer);
Packit 209cc3
typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceQueryStatistics)	(TC_INSTANCE instance, PTC_STATISTICS pStatistics);
Packit 209cc3
Packit 209cc3
typedef TC_STATUS	(TC_CALLCONV *TcFcnPacketsBufferCreate)		(ULONG size, PTC_PACKETS_BUFFER pBuffer);
Packit 209cc3
typedef VOID		(TC_CALLCONV *TcFcnPacketsBufferDestroy)	(TC_PACKETS_BUFFER buffer);
Packit 209cc3
typedef TC_STATUS	(TC_CALLCONV *TcFcnPacketsBufferQueryNextPacket)(TC_PACKETS_BUFFER buffer, PTC_PACKET_HEADER pHeader, PVOID *ppData);
Packit 209cc3
typedef TC_STATUS	(TC_CALLCONV *TcFcnPacketsBufferCommitNextPacket)(TC_PACKETS_BUFFER buffer, PTC_PACKET_HEADER pHeader, PVOID pData);
Packit 209cc3
Packit 209cc3
typedef VOID		(TC_CALLCONV *TcFcnStatisticsDestroy)		(TC_STATISTICS statistics);
Packit 209cc3
typedef TC_STATUS	(TC_CALLCONV *TcFcnStatisticsUpdate)		(TC_STATISTICS statistics);
Packit 209cc3
typedef TC_STATUS	(TC_CALLCONV *TcFcnStatisticsQueryValue)	(TC_STATISTICS statistics, ULONG counterId, PULONGLONG pValue);
Packit 209cc3
Packit 209cc3
typedef enum LONG
Packit 209cc3
{
Packit 209cc3
	TC_API_UNLOADED = 0,
Packit 209cc3
	TC_API_LOADED,
Packit 209cc3
	TC_API_CANNOT_LOAD,
Packit 209cc3
	TC_API_LOADING
Packit 209cc3
}
Packit 209cc3
	TC_API_LOAD_STATUS;
Packit 209cc3
Packit 209cc3
Packit 209cc3
typedef struct _TC_FUNCTIONS
Packit 209cc3
{
Packit 209cc3
	TC_API_LOAD_STATUS			LoadStatus;
Packit 209cc3
#ifdef _WIN32
Packit 209cc3
	HMODULE						hTcApiDllHandle;
Packit 209cc3
#endif
Packit 209cc3
	TcFcnQueryPortList			QueryPortList;
Packit 209cc3
	TcFcnFreePortList			FreePortList;
Packit 209cc3
	TcFcnStatusGetString		StatusGetString;
Packit 209cc3
Packit 209cc3
	TcFcnPortGetName			PortGetName;
Packit 209cc3
	TcFcnPortGetDescription		PortGetDescription;
Packit 209cc3
Packit 209cc3
	TcFcnInstanceOpenByName		InstanceOpenByName;
Packit 209cc3
	TcFcnInstanceClose			InstanceClose;
Packit 209cc3
	TcFcnInstanceSetFeature		InstanceSetFeature;
Packit 209cc3
	TcFcnInstanceQueryFeature	InstanceQueryFeature;
Packit 209cc3
	TcFcnInstanceReceivePackets	InstanceReceivePackets;
Packit 209cc3
#ifdef _WIN32
Packit 209cc3
	TcFcnInstanceGetReceiveWaitHandle InstanceGetReceiveWaitHandle;
Packit 209cc3
#endif
Packit 209cc3
	TcFcnInstanceTransmitPackets InstanceTransmitPackets;
Packit 209cc3
	TcFcnInstanceQueryStatistics InstanceQueryStatistics;
Packit 209cc3
Packit 209cc3
	TcFcnPacketsBufferCreate	PacketsBufferCreate;
Packit 209cc3
	TcFcnPacketsBufferDestroy	PacketsBufferDestroy;
Packit 209cc3
	TcFcnPacketsBufferQueryNextPacket	PacketsBufferQueryNextPacket;
Packit 209cc3
	TcFcnPacketsBufferCommitNextPacket  PacketsBufferCommitNextPacket;
Packit 209cc3
Packit 209cc3
	TcFcnStatisticsDestroy		StatisticsDestroy;
Packit 209cc3
	TcFcnStatisticsUpdate		StatisticsUpdate;
Packit 209cc3
	TcFcnStatisticsQueryValue	StatisticsQueryValue;
Packit 209cc3
}
Packit 209cc3
	TC_FUNCTIONS;
Packit 209cc3
Packit 209cc3
static pcap_if_t* TcCreatePcapIfFromPort(TC_PORT port);
Packit 209cc3
static int TcSetDatalink(pcap_t *p, int dlt);
Packit 209cc3
static int TcGetNonBlock(pcap_t *p);
Packit 209cc3
static int TcSetNonBlock(pcap_t *p, int nonblock);
Packit 209cc3
static void TcCleanup(pcap_t *p);
Packit 209cc3
static int TcInject(pcap_t *p, const void *buf, int size);
Packit 209cc3
static int TcRead(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
Packit 209cc3
static int TcStats(pcap_t *p, struct pcap_stat *ps);
Packit 209cc3
static int TcSetFilter(pcap_t *p, struct bpf_program *fp);
Packit 209cc3
#ifdef _WIN32
Packit 209cc3
static struct pcap_stat *TcStatsEx(pcap_t *p, int *pcap_stat_size);
Packit 209cc3
static int TcSetBuff(pcap_t *p, int dim);
Packit 209cc3
static int TcSetMode(pcap_t *p, int mode);
Packit 209cc3
static int TcSetMinToCopy(pcap_t *p, int size);
Packit 209cc3
static HANDLE TcGetReceiveWaitHandle(pcap_t *p);
Packit 209cc3
static int TcOidGetRequest(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp);
Packit 209cc3
static int TcOidSetRequest(pcap_t *p, bpf_u_int32 oid, const void *data, size_t *lenp);
Packit 209cc3
static u_int TcSendqueueTransmit(pcap_t *p, pcap_send_queue *queue, int sync);
Packit 209cc3
static int TcSetUserBuffer(pcap_t *p, int size);
Packit 209cc3
static int TcLiveDump(pcap_t *p, char *filename, int maxsize, int maxpacks);
Packit 209cc3
static int TcLiveDumpEnded(pcap_t *p, int sync);
Packit 209cc3
static PAirpcapHandle TcGetAirPcapHandle(pcap_t *p);
Packit 209cc3
#endif
Packit 209cc3
Packit 209cc3
#ifdef _WIN32
Packit 209cc3
TC_FUNCTIONS g_TcFunctions =
Packit 209cc3
{
Packit 209cc3
	TC_API_UNLOADED, /* LoadStatus */
Packit 209cc3
	NULL,  /* hTcApiDllHandle */
Packit 209cc3
	NULL,  /* QueryPortList */
Packit 209cc3
	NULL,  /* FreePortList */
Packit 209cc3
	NULL,  /* StatusGetString */
Packit 209cc3
	NULL,  /* PortGetName */
Packit 209cc3
	NULL,  /* PortGetDescription */
Packit 209cc3
	NULL,  /* InstanceOpenByName */
Packit 209cc3
	NULL,  /* InstanceClose */
Packit 209cc3
	NULL,  /* InstanceSetFeature */
Packit 209cc3
	NULL,  /* InstanceQueryFeature */
Packit 209cc3
	NULL,  /* InstanceReceivePackets */
Packit 209cc3
	NULL,  /* InstanceGetReceiveWaitHandle */
Packit 209cc3
	NULL,  /* InstanceTransmitPackets */
Packit 209cc3
	NULL,  /* InstanceQueryStatistics */
Packit 209cc3
	NULL,  /* PacketsBufferCreate */
Packit 209cc3
	NULL,  /* PacketsBufferDestroy */
Packit 209cc3
	NULL,  /* PacketsBufferQueryNextPacket */
Packit 209cc3
	NULL,  /* PacketsBufferCommitNextPacket */
Packit 209cc3
	NULL,  /* StatisticsDestroy */
Packit 209cc3
	NULL,  /* StatisticsUpdate */
Packit 209cc3
	NULL  /* StatisticsQueryValue */
Packit 209cc3
};
Packit 209cc3
#else
Packit 209cc3
TC_FUNCTIONS g_TcFunctions =
Packit 209cc3
{
Packit 209cc3
	TC_API_LOADED, /* LoadStatus */
Packit 209cc3
	TcQueryPortList,
Packit 209cc3
	TcFreePortList,
Packit 209cc3
	TcStatusGetString,
Packit 209cc3
	TcPortGetName,
Packit 209cc3
	TcPortGetDescription,
Packit 209cc3
	TcInstanceOpenByName,
Packit 209cc3
	TcInstanceClose,
Packit 209cc3
	TcInstanceSetFeature,
Packit 209cc3
	TcInstanceQueryFeature,
Packit 209cc3
	TcInstanceReceivePackets,
Packit 209cc3
#ifdef _WIN32
Packit 209cc3
	TcInstanceGetReceiveWaitHandle,
Packit 209cc3
#endif
Packit 209cc3
	TcInstanceTransmitPackets,
Packit 209cc3
	TcInstanceQueryStatistics,
Packit 209cc3
	TcPacketsBufferCreate,
Packit 209cc3
	TcPacketsBufferDestroy,
Packit 209cc3
	TcPacketsBufferQueryNextPacket,
Packit 209cc3
	TcPacketsBufferCommitNextPacket,
Packit 209cc3
	TcStatisticsDestroy,
Packit 209cc3
	TcStatisticsUpdate,
Packit 209cc3
	TcStatisticsQueryValue,
Packit 209cc3
};
Packit 209cc3
#endif
Packit 209cc3
Packit 209cc3
#define MAX_TC_PACKET_SIZE	9500
Packit 209cc3
Packit 209cc3
#pragma pack(push, 1)
Packit 209cc3
Packit 209cc3
#define PPH_PH_FLAG_PADDING	((UCHAR)0x01)
Packit 209cc3
#define PPH_PH_VERSION		((UCHAR)0x00)
Packit 209cc3
Packit 209cc3
typedef struct _PPI_PACKET_HEADER
Packit 209cc3
{
Packit 209cc3
	UCHAR	PphVersion;
Packit 209cc3
	UCHAR	PphFlags;
Packit 209cc3
	USHORT	PphLength;
Packit 209cc3
	ULONG	PphDlt;
Packit 209cc3
}
Packit 209cc3
	PPI_PACKET_HEADER, *PPPI_PACKET_HEADER;
Packit 209cc3
Packit 209cc3
typedef struct _PPI_FIELD_HEADER
Packit 209cc3
{
Packit 209cc3
	USHORT PfhType;
Packit 209cc3
	USHORT PfhLength;
Packit 209cc3
}
Packit 209cc3
	PPI_FIELD_HEADER, *PPPI_FIELD_HEADER;
Packit 209cc3
Packit 209cc3
Packit 209cc3
#define		PPI_FIELD_TYPE_AGGREGATION_EXTENSION	((UCHAR)0x08)
Packit 209cc3
Packit 209cc3
typedef struct _PPI_FIELD_AGGREGATION_EXTENSION
Packit 209cc3
{
Packit 209cc3
	ULONG		InterfaceId;
Packit 209cc3
}
Packit 209cc3
	PPI_FIELD_AGGREGATION_EXTENSION, *PPPI_FIELD_AGGREGATION_EXTENSION;
Packit 209cc3
Packit 209cc3
Packit 209cc3
#define		PPI_FIELD_TYPE_802_3_EXTENSION			((UCHAR)0x09)
Packit 209cc3
Packit 209cc3
#define PPI_FLD_802_3_EXT_FLAG_FCS_PRESENT			((ULONG)0x00000001)
Packit 209cc3
Packit 209cc3
typedef struct _PPI_FIELD_802_3_EXTENSION
Packit 209cc3
{
Packit 209cc3
	ULONG		Flags;
Packit 209cc3
	ULONG		Errors;
Packit 209cc3
}
Packit 209cc3
	PPI_FIELD_802_3_EXTENSION, *PPPI_FIELD_802_3_EXTENSION;
Packit 209cc3
Packit 209cc3
typedef struct _PPI_HEADER
Packit 209cc3
{
Packit 209cc3
	PPI_PACKET_HEADER PacketHeader;
Packit 209cc3
	PPI_FIELD_HEADER  AggregationFieldHeader;
Packit 209cc3
	PPI_FIELD_AGGREGATION_EXTENSION AggregationField;
Packit 209cc3
	PPI_FIELD_HEADER  Dot3FieldHeader;
Packit 209cc3
	PPI_FIELD_802_3_EXTENSION Dot3Field;
Packit 209cc3
}
Packit 209cc3
	PPI_HEADER, *PPPI_HEADER;
Packit 209cc3
#pragma pack(pop)
Packit 209cc3
Packit 209cc3
#ifdef _WIN32
Packit 209cc3
//
Packit 209cc3
// This wrapper around loadlibrary appends the system folder (usually c:\windows\system32)
Packit 209cc3
// to the relative path of the DLL, so that the DLL is always loaded from an absolute path
Packit 209cc3
// (It's no longer possible to load airpcap.dll from the application folder).
Packit 209cc3
// This solves the DLL Hijacking issue discovered in August 2010
Packit 209cc3
// http://blog.metasploit.com/2010/08/exploiting-dll-hijacking-flaws.html
Packit 209cc3
//
Packit 209cc3
HMODULE LoadLibrarySafe(LPCTSTR lpFileName)
Packit 209cc3
{
Packit 209cc3
  TCHAR path[MAX_PATH];
Packit 209cc3
  TCHAR fullFileName[MAX_PATH];
Packit 209cc3
  UINT res;
Packit 209cc3
  HMODULE hModule = NULL;
Packit 209cc3
  do
Packit 209cc3
  {
Packit 209cc3
	res = GetSystemDirectory(path, MAX_PATH);
Packit 209cc3
Packit 209cc3
	if (res == 0)
Packit 209cc3
	{
Packit 209cc3
		//
Packit 209cc3
		// some bad failure occurred;
Packit 209cc3
		//
Packit 209cc3
		break;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	if (res > MAX_PATH)
Packit 209cc3
	{
Packit 209cc3
		//
Packit 209cc3
		// the buffer was not big enough
Packit 209cc3
		//
Packit 209cc3
		SetLastError(ERROR_INSUFFICIENT_BUFFER);
Packit 209cc3
		break;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	if (res + 1 + _tcslen(lpFileName) + 1 < MAX_PATH)
Packit 209cc3
	{
Packit 209cc3
		memcpy(fullFileName, path, res * sizeof(TCHAR));
Packit 209cc3
		fullFileName[res] = _T('\\');
Packit 209cc3
		memcpy(&fullFileName[res + 1], lpFileName, (_tcslen(lpFileName) + 1) * sizeof(TCHAR));
Packit 209cc3
Packit 209cc3
		hModule = LoadLibrary(fullFileName);
Packit 209cc3
	}
Packit 209cc3
	else
Packit 209cc3
	{
Packit 209cc3
		SetLastError(ERROR_INSUFFICIENT_BUFFER);
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
  }while(FALSE);
Packit 209cc3
Packit 209cc3
  return hModule;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
/*
Packit 209cc3
 * NOTE: this function should be called by the pcap functions that can theoretically
Packit 209cc3
 *       deal with the Tc library for the first time, namely listing the adapters and
Packit 209cc3
 *       opening one. All the other ones (close, read, write, set parameters) work
Packit 209cc3
 *       on an open instance of TC, so we do not care to call this function
Packit 209cc3
 */
Packit 209cc3
TC_API_LOAD_STATUS LoadTcFunctions(void)
Packit 209cc3
{
Packit 209cc3
	TC_API_LOAD_STATUS currentStatus;
Packit 209cc3
Packit 209cc3
	do
Packit 209cc3
	{
Packit 209cc3
		currentStatus = InterlockedCompareExchange((LONG*)&g_TcFunctions.LoadStatus, TC_API_LOADING, TC_API_UNLOADED);
Packit 209cc3
Packit 209cc3
		while(currentStatus == TC_API_LOADING)
Packit 209cc3
		{
Packit 209cc3
			currentStatus = InterlockedCompareExchange((LONG*)&g_TcFunctions.LoadStatus, TC_API_LOADING, TC_API_LOADING);
Packit 209cc3
			Sleep(10);
Packit 209cc3
		}
Packit 209cc3
Packit 209cc3
		/*
Packit 209cc3
		 * at this point we are either in the LOADED state, unloaded state (i.e. we are the ones loading everything)
Packit 209cc3
		 * or in cannot load
Packit 209cc3
		 */
Packit 209cc3
		if(currentStatus  == TC_API_LOADED)
Packit 209cc3
		{
Packit 209cc3
			return TC_API_LOADED;
Packit 209cc3
		}
Packit 209cc3
Packit 209cc3
		if (currentStatus == TC_API_CANNOT_LOAD)
Packit 209cc3
		{
Packit 209cc3
			return TC_API_CANNOT_LOAD;
Packit 209cc3
		}
Packit 209cc3
Packit 209cc3
		currentStatus = TC_API_CANNOT_LOAD;
Packit 209cc3
Packit 209cc3
		g_TcFunctions.hTcApiDllHandle = LoadLibrarySafe("TcApi.dll");
Packit 209cc3
		if (g_TcFunctions.hTcApiDllHandle == NULL)	break;
Packit 209cc3
Packit 209cc3
		g_TcFunctions.QueryPortList					= (TcFcnQueryPortList)			GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcQueryPortList");
Packit 209cc3
		g_TcFunctions.FreePortList					= (TcFcnFreePortList)			GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcFreePortList");
Packit 209cc3
Packit 209cc3
		g_TcFunctions.StatusGetString				= (TcFcnStatusGetString)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatusGetString");
Packit 209cc3
Packit 209cc3
		g_TcFunctions.PortGetName					= (TcFcnPortGetName)			GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPortGetName");
Packit 209cc3
		g_TcFunctions.PortGetDescription			= (TcFcnPortGetDescription)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPortGetDescription");
Packit 209cc3
Packit 209cc3
		g_TcFunctions.InstanceOpenByName			= (TcFcnInstanceOpenByName)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceOpenByName");
Packit 209cc3
		g_TcFunctions.InstanceClose					= (TcFcnInstanceClose)			GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceClose");
Packit 209cc3
		g_TcFunctions.InstanceSetFeature			= (TcFcnInstanceSetFeature)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceSetFeature");
Packit 209cc3
		g_TcFunctions.InstanceQueryFeature			= (TcFcnInstanceQueryFeature)	GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceQueryFeature");
Packit 209cc3
		g_TcFunctions.InstanceReceivePackets		= (TcFcnInstanceReceivePackets)	GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceReceivePackets");
Packit 209cc3
		g_TcFunctions.InstanceGetReceiveWaitHandle	= (TcFcnInstanceGetReceiveWaitHandle)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceGetReceiveWaitHandle");
Packit 209cc3
		g_TcFunctions.InstanceTransmitPackets		= (TcFcnInstanceTransmitPackets)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceTransmitPackets");
Packit 209cc3
		g_TcFunctions.InstanceQueryStatistics		= (TcFcnInstanceQueryStatistics)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceQueryStatistics");
Packit 209cc3
Packit 209cc3
		g_TcFunctions.PacketsBufferCreate			= (TcFcnPacketsBufferCreate)	GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferCreate");
Packit 209cc3
		g_TcFunctions.PacketsBufferDestroy			= (TcFcnPacketsBufferDestroy)	GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferDestroy");
Packit 209cc3
		g_TcFunctions.PacketsBufferQueryNextPacket	= (TcFcnPacketsBufferQueryNextPacket)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferQueryNextPacket");
Packit 209cc3
		g_TcFunctions.PacketsBufferCommitNextPacket	= (TcFcnPacketsBufferCommitNextPacket)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferCommitNextPacket");
Packit 209cc3
Packit 209cc3
		g_TcFunctions.StatisticsDestroy				= (TcFcnStatisticsDestroy)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatisticsDestroy");
Packit 209cc3
		g_TcFunctions.StatisticsUpdate				= (TcFcnStatisticsUpdate)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatisticsUpdate");
Packit 209cc3
		g_TcFunctions.StatisticsQueryValue			= (TcFcnStatisticsQueryValue)	GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatisticsQueryValue");
Packit 209cc3
Packit 209cc3
		if (   g_TcFunctions.QueryPortList == NULL
Packit 209cc3
			|| g_TcFunctions.FreePortList == NULL
Packit 209cc3
			|| g_TcFunctions.StatusGetString == NULL
Packit 209cc3
			|| g_TcFunctions.PortGetName == NULL
Packit 209cc3
			|| g_TcFunctions.PortGetDescription == NULL
Packit 209cc3
			|| g_TcFunctions.InstanceOpenByName == NULL
Packit 209cc3
			|| g_TcFunctions.InstanceClose == NULL
Packit 209cc3
			|| g_TcFunctions.InstanceSetFeature	 == NULL
Packit 209cc3
			|| g_TcFunctions.InstanceQueryFeature == NULL
Packit 209cc3
			|| g_TcFunctions.InstanceReceivePackets == NULL
Packit 209cc3
			|| g_TcFunctions.InstanceGetReceiveWaitHandle == NULL
Packit 209cc3
			|| g_TcFunctions.InstanceTransmitPackets == NULL
Packit 209cc3
			|| g_TcFunctions.InstanceQueryStatistics == NULL
Packit 209cc3
			|| g_TcFunctions.PacketsBufferCreate == NULL
Packit 209cc3
			|| g_TcFunctions.PacketsBufferDestroy == NULL
Packit 209cc3
			|| g_TcFunctions.PacketsBufferQueryNextPacket == NULL
Packit 209cc3
			|| g_TcFunctions.PacketsBufferCommitNextPacket == NULL
Packit 209cc3
			|| g_TcFunctions.StatisticsDestroy == NULL
Packit 209cc3
			|| g_TcFunctions.StatisticsUpdate == NULL
Packit 209cc3
			|| g_TcFunctions.StatisticsQueryValue == NULL
Packit 209cc3
		)
Packit 209cc3
		{
Packit 209cc3
			break;
Packit 209cc3
		}
Packit 209cc3
Packit 209cc3
		/*
Packit 209cc3
		 * everything got loaded, yay!!
Packit 209cc3
		 */
Packit 209cc3
		currentStatus = TC_API_LOADED;
Packit 209cc3
	}while(FALSE);
Packit 209cc3
Packit 209cc3
	if (currentStatus != TC_API_LOADED)
Packit 209cc3
	{
Packit 209cc3
		if (g_TcFunctions.hTcApiDllHandle != NULL)
Packit 209cc3
		{
Packit 209cc3
			FreeLibrary(g_TcFunctions.hTcApiDllHandle);
Packit 209cc3
			g_TcFunctions.hTcApiDllHandle = NULL;
Packit 209cc3
		}
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	InterlockedExchange((LONG*)&g_TcFunctions.LoadStatus, currentStatus);
Packit 209cc3
Packit 209cc3
	return currentStatus;
Packit 209cc3
}
Packit 209cc3
#else
Packit 209cc3
// static linking
Packit 209cc3
TC_API_LOAD_STATUS LoadTcFunctions(void)
Packit 209cc3
{
Packit 209cc3
	return TC_API_LOADED;
Packit 209cc3
}
Packit 209cc3
#endif
Packit 209cc3
Packit 209cc3
/*
Packit 209cc3
 * Private data for capturing on TurboCap devices.
Packit 209cc3
 */
Packit 209cc3
struct pcap_tc {
Packit 209cc3
	TC_INSTANCE TcInstance;
Packit 209cc3
	TC_PACKETS_BUFFER TcPacketsBuffer;
Packit 209cc3
	ULONG TcAcceptedCount;
Packit 209cc3
	u_char *PpiPacket;
Packit 209cc3
};
Packit 209cc3
Packit 209cc3
int
Packit 209cc3
TcFindAllDevs(pcap_if_list_t *devlist, char *errbuf)
Packit 209cc3
{
Packit 209cc3
	TC_API_LOAD_STATUS loadStatus;
Packit 209cc3
	ULONG numPorts;
Packit 209cc3
	PTC_PORT pPorts = NULL;
Packit 209cc3
	TC_STATUS status;
Packit 209cc3
	int result = 0;
Packit 209cc3
	pcap_if_t *dev;
Packit 209cc3
	ULONG i;
Packit 209cc3
Packit 209cc3
	do
Packit 209cc3
	{
Packit 209cc3
		loadStatus = LoadTcFunctions();
Packit 209cc3
Packit 209cc3
		if (loadStatus != TC_API_LOADED)
Packit 209cc3
		{
Packit 209cc3
			result = 0;
Packit 209cc3
			break;
Packit 209cc3
		}
Packit 209cc3
Packit 209cc3
		/*
Packit 209cc3
		 * enumerate the ports, and add them to the list
Packit 209cc3
		 */
Packit 209cc3
		status = g_TcFunctions.QueryPortList(&pPorts, &numPorts);
Packit 209cc3
Packit 209cc3
		if (status != TC_SUCCESS)
Packit 209cc3
		{
Packit 209cc3
			result = 0;
Packit 209cc3
			break;
Packit 209cc3
		}
Packit 209cc3
Packit 209cc3
		for (i = 0; i < numPorts; i++)
Packit 209cc3
		{
Packit 209cc3
			/*
Packit 209cc3
			 * transform the port into an entry in the list
Packit 209cc3
			 */
Packit 209cc3
			dev = TcCreatePcapIfFromPort(pPorts[i]);
Packit 209cc3
Packit 209cc3
			if (dev != NULL)
Packit 209cc3
				add_dev(devlist, dev->name, dev->flags, dev->description, errbuf);
Packit 209cc3
		}
Packit 209cc3
Packit 209cc3
		if (numPorts > 0)
Packit 209cc3
		{
Packit 209cc3
			/*
Packit 209cc3
			 * ignore the result here
Packit 209cc3
			 */
Packit 209cc3
			status = g_TcFunctions.FreePortList(pPorts);
Packit 209cc3
		}
Packit 209cc3
Packit 209cc3
	}while(FALSE);
Packit 209cc3
Packit 209cc3
	return result;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
static pcap_if_t* TcCreatePcapIfFromPort(TC_PORT port)
Packit 209cc3
{
Packit 209cc3
	CHAR *name;
Packit 209cc3
	CHAR *description;
Packit 209cc3
	pcap_if_t *newIf = NULL;
Packit 209cc3
Packit 209cc3
	newIf = (pcap_if_t*)malloc(sizeof(*newIf));
Packit 209cc3
	if (newIf == NULL)
Packit 209cc3
	{
Packit 209cc3
		return NULL;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	memset(newIf, 0, sizeof(*newIf));
Packit 209cc3
Packit 209cc3
	name = g_TcFunctions.PortGetName(port);
Packit 209cc3
	description = g_TcFunctions.PortGetDescription(port);
Packit 209cc3
Packit 209cc3
	newIf->name = (char*)malloc(strlen(name) + 1);
Packit 209cc3
	if (newIf->name == NULL)
Packit 209cc3
	{
Packit 209cc3
		free(newIf);
Packit 209cc3
		return NULL;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	newIf->description = (char*)malloc(strlen(description) + 1);
Packit 209cc3
	if (newIf->description == NULL)
Packit 209cc3
	{
Packit 209cc3
		free(newIf->name);
Packit 209cc3
		free(newIf);
Packit 209cc3
		return NULL;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	strcpy(newIf->name, name);
Packit 209cc3
	strcpy(newIf->description, description);
Packit 209cc3
Packit 209cc3
	newIf->addresses = NULL;
Packit 209cc3
	newIf->next = NULL;
Packit 209cc3
	newIf->flags = 0;
Packit 209cc3
Packit 209cc3
	return newIf;
Packit 209cc3
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
static int
Packit 209cc3
TcActivate(pcap_t *p)
Packit 209cc3
{
Packit 209cc3
	struct pcap_tc *pt = p->priv;
Packit 209cc3
	TC_STATUS status;
Packit 209cc3
	ULONG timeout;
Packit 209cc3
	PPPI_HEADER pPpiHeader;
Packit 209cc3
Packit 209cc3
	if (p->opt.rfmon)
Packit 209cc3
	{
Packit 209cc3
		/*
Packit 209cc3
		 * No monitor mode on Tc cards; they're Ethernet
Packit 209cc3
		 * capture adapters.
Packit 209cc3
		 */
Packit 209cc3
		return PCAP_ERROR_RFMON_NOTSUP;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	pt->PpiPacket = malloc(sizeof(PPI_HEADER) + MAX_TC_PACKET_SIZE);
Packit 209cc3
Packit 209cc3
	if (pt->PpiPacket == NULL)
Packit 209cc3
	{
Packit 209cc3
		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error allocating memory");
Packit 209cc3
		return PCAP_ERROR;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	/*
Packit 209cc3
	 * Turn a negative snapshot value (invalid), a snapshot value of
Packit 209cc3
	 * 0 (unspecified), or a value bigger than the normal maximum
Packit 209cc3
	 * value, into the maximum allowed value.
Packit 209cc3
	 *
Packit 209cc3
	 * If some application really *needs* a bigger snapshot
Packit 209cc3
	 * length, we should just increase MAXIMUM_SNAPLEN.
Packit 209cc3
	 */
Packit 209cc3
	if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
Packit 209cc3
		p->snapshot = MAXIMUM_SNAPLEN;
Packit 209cc3
Packit 209cc3
	/*
Packit 209cc3
	 * Initialize the PPI fixed fields
Packit 209cc3
	 */
Packit 209cc3
	pPpiHeader = (PPPI_HEADER)pt->PpiPacket;
Packit 209cc3
	pPpiHeader->PacketHeader.PphDlt = DLT_EN10MB;
Packit 209cc3
	pPpiHeader->PacketHeader.PphLength = sizeof(PPI_HEADER);
Packit 209cc3
	pPpiHeader->PacketHeader.PphFlags = 0;
Packit 209cc3
	pPpiHeader->PacketHeader.PphVersion = 0;
Packit 209cc3
Packit 209cc3
	pPpiHeader->AggregationFieldHeader.PfhLength = sizeof(PPI_FIELD_AGGREGATION_EXTENSION);
Packit 209cc3
	pPpiHeader->AggregationFieldHeader.PfhType = PPI_FIELD_TYPE_AGGREGATION_EXTENSION;
Packit 209cc3
Packit 209cc3
	pPpiHeader->Dot3FieldHeader.PfhLength = sizeof(PPI_FIELD_802_3_EXTENSION);
Packit 209cc3
	pPpiHeader->Dot3FieldHeader.PfhType = PPI_FIELD_TYPE_802_3_EXTENSION;
Packit 209cc3
Packit 209cc3
	status = g_TcFunctions.InstanceOpenByName(p->opt.device, &pt->TcInstance);
Packit 209cc3
Packit 209cc3
	if (status != TC_SUCCESS)
Packit 209cc3
	{
Packit 209cc3
		/* Adapter detected but we are not able to open it. Return failure. */
Packit 209cc3
		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening TurboCap adapter: %s", g_TcFunctions.StatusGetString(status));
Packit 209cc3
		return PCAP_ERROR;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	p->linktype = DLT_EN10MB;
Packit 209cc3
	p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
Packit 209cc3
	/*
Packit 209cc3
	 * If that fails, just leave the list empty.
Packit 209cc3
	 */
Packit 209cc3
	if (p->dlt_list != NULL) {
Packit 209cc3
		p->dlt_list[0] = DLT_EN10MB;
Packit 209cc3
		p->dlt_list[1] = DLT_PPI;
Packit 209cc3
		p->dlt_count = 2;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	/*
Packit 209cc3
	 * ignore promiscuous mode
Packit 209cc3
	 * p->opt.promisc
Packit 209cc3
	 */
Packit 209cc3
Packit 209cc3
Packit 209cc3
	/*
Packit 209cc3
	 * ignore all the buffer sizes
Packit 209cc3
	 */
Packit 209cc3
Packit 209cc3
	/*
Packit 209cc3
	 * enable reception
Packit 209cc3
	 */
Packit 209cc3
	status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_RX_STATUS, 1);
Packit 209cc3
Packit 209cc3
	if (status != TC_SUCCESS)
Packit 209cc3
	{
Packit 209cc3
		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error enabling reception on a TurboCap instance: %s", g_TcFunctions.StatusGetString(status));
Packit 209cc3
		goto bad;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	/*
Packit 209cc3
	 * enable transmission
Packit 209cc3
	 */
Packit 209cc3
	status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_TX_STATUS, 1);
Packit 209cc3
	/*
Packit 209cc3
	 * Ignore the error here.
Packit 209cc3
	 */
Packit 209cc3
Packit 209cc3
	p->inject_op = TcInject;
Packit 209cc3
	/*
Packit 209cc3
	 * if the timeout is -1, it means immediate return, no timeout
Packit 209cc3
	 * if the timeout is 0, it means INFINITE
Packit 209cc3
	 */
Packit 209cc3
Packit 209cc3
	if (p->opt.timeout == 0)
Packit 209cc3
	{
Packit 209cc3
		timeout = 0xFFFFFFFF;
Packit 209cc3
	}
Packit 209cc3
	else
Packit 209cc3
	if (p->opt.timeout < 0)
Packit 209cc3
	{
Packit 209cc3
		/*
Packit 209cc3
		 *  we insert a minimal timeout here
Packit 209cc3
		 */
Packit 209cc3
		timeout = 10;
Packit 209cc3
	}
Packit 209cc3
	else
Packit 209cc3
	{
Packit 209cc3
		timeout = p->opt.timeout;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_READ_TIMEOUT, timeout);
Packit 209cc3
Packit 209cc3
	if (status != TC_SUCCESS)
Packit 209cc3
	{
Packit 209cc3
		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error setting the read timeout a TurboCap instance: %s", g_TcFunctions.StatusGetString(status));
Packit 209cc3
		goto bad;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	p->read_op = TcRead;
Packit 209cc3
	p->setfilter_op = TcSetFilter;
Packit 209cc3
	p->setdirection_op = NULL;	/* Not implemented. */
Packit 209cc3
	p->set_datalink_op = TcSetDatalink;
Packit 209cc3
	p->getnonblock_op = TcGetNonBlock;
Packit 209cc3
	p->setnonblock_op = TcSetNonBlock;
Packit 209cc3
	p->stats_op = TcStats;
Packit 209cc3
#ifdef _WIN32
Packit 209cc3
	p->stats_ex_op = TcStatsEx;
Packit 209cc3
	p->setbuff_op = TcSetBuff;
Packit 209cc3
	p->setmode_op = TcSetMode;
Packit 209cc3
	p->setmintocopy_op = TcSetMinToCopy;
Packit 209cc3
	p->getevent_op = TcGetReceiveWaitHandle;
Packit 209cc3
	p->oid_get_request_op = TcOidGetRequest;
Packit 209cc3
	p->oid_set_request_op = TcOidSetRequest;
Packit 209cc3
	p->sendqueue_transmit_op = TcSendqueueTransmit;
Packit 209cc3
	p->setuserbuffer_op = TcSetUserBuffer;
Packit 209cc3
	p->live_dump_op = TcLiveDump;
Packit 209cc3
	p->live_dump_ended_op = TcLiveDumpEnded;
Packit 209cc3
	p->get_airpcap_handle_op = TcGetAirPcapHandle;
Packit 209cc3
#else
Packit 209cc3
	p->selectable_fd = -1;
Packit 209cc3
#endif
Packit 209cc3
Packit 209cc3
	p->cleanup_op = TcCleanup;
Packit 209cc3
Packit 209cc3
	return 0;
Packit 209cc3
bad:
Packit 209cc3
	TcCleanup(p);
Packit 209cc3
	return PCAP_ERROR;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
pcap_t *
Packit 209cc3
TcCreate(const char *device, char *ebuf, int *is_ours)
Packit 209cc3
{
Packit 209cc3
	ULONG numPorts;
Packit 209cc3
	PTC_PORT pPorts = NULL;
Packit 209cc3
	TC_STATUS status;
Packit 209cc3
	int is_tc;
Packit 209cc3
	ULONG i;
Packit 209cc3
	pcap_t *p;
Packit 209cc3
Packit 209cc3
	if (LoadTcFunctions() != TC_API_LOADED)
Packit 209cc3
	{
Packit 209cc3
		/*
Packit 209cc3
		 * XXX - report this as an error rather than as
Packit 209cc3
		 * "not a TurboCap device"?
Packit 209cc3
		 */
Packit 209cc3
		*is_ours = 0;
Packit 209cc3
		return NULL;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	/*
Packit 209cc3
	 * enumerate the ports, and add them to the list
Packit 209cc3
	 */
Packit 209cc3
	status = g_TcFunctions.QueryPortList(&pPorts, &numPorts);
Packit 209cc3
Packit 209cc3
	if (status != TC_SUCCESS)
Packit 209cc3
	{
Packit 209cc3
		/*
Packit 209cc3
		 * XXX - report this as an error rather than as
Packit 209cc3
		 * "not a TurboCap device"?
Packit 209cc3
		 */
Packit 209cc3
		*is_ours = 0;
Packit 209cc3
		return NULL;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	is_tc = FALSE;
Packit 209cc3
	for (i = 0; i < numPorts; i++)
Packit 209cc3
	{
Packit 209cc3
		if (strcmp(g_TcFunctions.PortGetName(pPorts[i]), device) == 0)
Packit 209cc3
		{
Packit 209cc3
			is_tc = TRUE;
Packit 209cc3
			break;
Packit 209cc3
		}
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	if (numPorts > 0)
Packit 209cc3
	{
Packit 209cc3
		/*
Packit 209cc3
		 * ignore the result here
Packit 209cc3
		 */
Packit 209cc3
		(void)g_TcFunctions.FreePortList(pPorts);
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	if (!is_tc)
Packit 209cc3
	{
Packit 209cc3
		*is_ours = 0;
Packit 209cc3
		return NULL;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	/* OK, it's probably ours. */
Packit 209cc3
	*is_ours = 1;
Packit 209cc3
Packit 209cc3
	p = pcap_create_common(ebuf, sizeof (struct pcap_tc));
Packit 209cc3
	if (p == NULL)
Packit 209cc3
		return NULL;
Packit 209cc3
Packit 209cc3
	p->activate_op = TcActivate;
Packit 209cc3
	/*
Packit 209cc3
	 * Set these up front, so that, even if our client tries
Packit 209cc3
	 * to set non-blocking mode before we're activated, or
Packit 209cc3
	 * query the state of non-blocking mode, they get an error,
Packit 209cc3
	 * rather than having the non-blocking mode option set
Packit 209cc3
	 * for use later.
Packit 209cc3
	 */
Packit 209cc3
	p->getnonblock_op = TcGetNonBlock;
Packit 209cc3
	p->setnonblock_op = TcSetNonBlock;
Packit 209cc3
	return p;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
static int TcSetDatalink(pcap_t *p, int dlt)
Packit 209cc3
{
Packit 209cc3
	/*
Packit 209cc3
	 * We don't have to do any work here; pcap_set_datalink() checks
Packit 209cc3
	 * whether the value is in the list of DLT_ values we
Packit 209cc3
	 * supplied, so we don't have to, and, if it is valid, sets
Packit 209cc3
	 * p->linktype to the new value; we don't have to do anything
Packit 209cc3
	 * in hardware, we just use what's in p->linktype.
Packit 209cc3
	 *
Packit 209cc3
	 * We do have to have a routine, however, so that pcap_set_datalink()
Packit 209cc3
	 * doesn't think we don't support setting the link-layer header
Packit 209cc3
	 * type at all.
Packit 209cc3
	 */
Packit 209cc3
	return 0;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
static int TcGetNonBlock(pcap_t *p)
Packit 209cc3
{
Packit 209cc3
	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
Packit 209cc3
	    "Non-blocking mode isn't supported for TurboCap ports");
Packit 209cc3
	return -1;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
static int TcSetNonBlock(pcap_t *p, int nonblock)
Packit 209cc3
{
Packit 209cc3
	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
Packit 209cc3
	    "Non-blocking mode isn't supported for TurboCap ports");
Packit 209cc3
	return -1;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
static void TcCleanup(pcap_t *p)
Packit 209cc3
{
Packit 209cc3
	struct pcap_tc *pt = p->priv;
Packit 209cc3
Packit 209cc3
	if (pt->TcPacketsBuffer != NULL)
Packit 209cc3
	{
Packit 209cc3
		g_TcFunctions.PacketsBufferDestroy(pt->TcPacketsBuffer);
Packit 209cc3
		pt->TcPacketsBuffer = NULL;
Packit 209cc3
	}
Packit 209cc3
	if (pt->TcInstance != NULL)
Packit 209cc3
	{
Packit 209cc3
		/*
Packit 209cc3
		 * here we do not check for the error values
Packit 209cc3
		 */
Packit 209cc3
		g_TcFunctions.InstanceClose(pt->TcInstance);
Packit 209cc3
		pt->TcInstance = NULL;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	if (pt->PpiPacket != NULL)
Packit 209cc3
	{
Packit 209cc3
		free(pt->PpiPacket);
Packit 209cc3
		pt->PpiPacket = NULL;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	pcap_cleanup_live_common(p);
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
/* Send a packet to the network */
Packit 209cc3
static int TcInject(pcap_t *p, const void *buf, int size)
Packit 209cc3
{
Packit 209cc3
	struct pcap_tc *pt = p->priv;
Packit 209cc3
	TC_STATUS status;
Packit 209cc3
	TC_PACKETS_BUFFER buffer;
Packit 209cc3
	TC_PACKET_HEADER header;
Packit 209cc3
Packit 209cc3
	if (size >= 0xFFFF)
Packit 209cc3
	{
Packit 209cc3
		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: the TurboCap API does not support packets larger than 64k");
Packit 209cc3
		return -1;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	status = g_TcFunctions.PacketsBufferCreate(sizeof(TC_PACKET_HEADER) + TC_ALIGN_USHORT_TO_64BIT((USHORT)size), &buffer);
Packit 209cc3
Packit 209cc3
	if (status != TC_SUCCESS)
Packit 209cc3
	{
Packit 209cc3
		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcPacketsBufferCreate failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
Packit 209cc3
		return -1;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	/*
Packit 209cc3
	 * we assume that the packet is without the checksum, as common with WinPcap
Packit 209cc3
	 */
Packit 209cc3
	memset(&header, 0, sizeof(header));
Packit 209cc3
Packit 209cc3
	header.Length = (USHORT)size;
Packit 209cc3
	header.CapturedLength = header.Length;
Packit 209cc3
Packit 209cc3
	status = g_TcFunctions.PacketsBufferCommitNextPacket(buffer, &header, (PVOID)buf);
Packit 209cc3
Packit 209cc3
	if (status == TC_SUCCESS)
Packit 209cc3
	{
Packit 209cc3
		status = g_TcFunctions.InstanceTransmitPackets(pt->TcInstance, buffer);
Packit 209cc3
Packit 209cc3
		if (status != TC_SUCCESS)
Packit 209cc3
		{
Packit 209cc3
			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcInstanceTransmitPackets failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
Packit 209cc3
		}
Packit 209cc3
	}
Packit 209cc3
	else
Packit 209cc3
	{
Packit 209cc3
		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcPacketsBufferCommitNextPacket failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	g_TcFunctions.PacketsBufferDestroy(buffer);
Packit 209cc3
Packit 209cc3
	if (status != TC_SUCCESS)
Packit 209cc3
	{
Packit 209cc3
		return -1;
Packit 209cc3
	}
Packit 209cc3
	else
Packit 209cc3
	{
Packit 209cc3
		return 0;
Packit 209cc3
	}
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
static int TcRead(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
Packit 209cc3
{
Packit 209cc3
	struct pcap_tc *pt = p->priv;
Packit 209cc3
	TC_STATUS status;
Packit 209cc3
	int n = 0;
Packit 209cc3
Packit 209cc3
	/*
Packit 209cc3
	 * Has "pcap_breakloop()" been called?
Packit 209cc3
	 */
Packit 209cc3
	if (p->break_loop)
Packit 209cc3
	{
Packit 209cc3
		/*
Packit 209cc3
		 * Yes - clear the flag that indicates that it
Packit 209cc3
		 * has, and return -2 to indicate that we were
Packit 209cc3
		 * told to break out of the loop.
Packit 209cc3
		 */
Packit 209cc3
		p->break_loop = 0;
Packit 209cc3
		return -2;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	if (pt->TcPacketsBuffer == NULL)
Packit 209cc3
	{
Packit 209cc3
		status = g_TcFunctions.InstanceReceivePackets(pt->TcInstance, &pt->TcPacketsBuffer);
Packit 209cc3
		if (status != TC_SUCCESS)
Packit 209cc3
		{
Packit 209cc3
			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error, TcInstanceReceivePackets failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
Packit 209cc3
			return -1;
Packit 209cc3
		}
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	while (TRUE)
Packit 209cc3
	{
Packit 209cc3
		struct pcap_pkthdr hdr;
Packit 209cc3
		TC_PACKET_HEADER tcHeader;
Packit 209cc3
		PVOID data;
Packit 209cc3
		ULONG filterResult;
Packit 209cc3
Packit 209cc3
		/*
Packit 209cc3
		 * Has "pcap_breakloop()" been called?
Packit 209cc3
		 * If so, return immediately - if we haven't read any
Packit 209cc3
		 * packets, clear the flag and return -2 to indicate
Packit 209cc3
		 * that we were told to break out of the loop, otherwise
Packit 209cc3
		 * leave the flag set, so that the *next* call will break
Packit 209cc3
		 * out of the loop without having read any packets, and
Packit 209cc3
		 * return the number of packets we've processed so far.
Packit 209cc3
		 */
Packit 209cc3
		if (p->break_loop)
Packit 209cc3
		{
Packit 209cc3
			if (n == 0)
Packit 209cc3
			{
Packit 209cc3
				p->break_loop = 0;
Packit 209cc3
				return -2;
Packit 209cc3
			}
Packit 209cc3
			else
Packit 209cc3
			{
Packit 209cc3
				return n;
Packit 209cc3
			}
Packit 209cc3
		}
Packit 209cc3
Packit 209cc3
		if (pt->TcPacketsBuffer == NULL)
Packit 209cc3
		{
Packit 209cc3
			break;
Packit 209cc3
		}
Packit 209cc3
Packit 209cc3
		status = g_TcFunctions.PacketsBufferQueryNextPacket(pt->TcPacketsBuffer, &tcHeader, &data);
Packit 209cc3
Packit 209cc3
		if (status == TC_ERROR_END_OF_BUFFER)
Packit 209cc3
		{
Packit 209cc3
			g_TcFunctions.PacketsBufferDestroy(pt->TcPacketsBuffer);
Packit 209cc3
			pt->TcPacketsBuffer = NULL;
Packit 209cc3
			break;
Packit 209cc3
		}
Packit 209cc3
Packit 209cc3
		if (status != TC_SUCCESS)
Packit 209cc3
		{
Packit 209cc3
			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error, TcPacketsBufferQueryNextPacket failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
Packit 209cc3
			return -1;
Packit 209cc3
		}
Packit 209cc3
Packit 209cc3
		/* No underlaying filtering system. We need to filter on our own */
Packit 209cc3
		if (p->fcode.bf_insns)
Packit 209cc3
		{
Packit 209cc3
			filterResult = bpf_filter(p->fcode.bf_insns, data, tcHeader.Length, tcHeader.CapturedLength);
Packit 209cc3
Packit 209cc3
			if (filterResult == 0)
Packit 209cc3
			{
Packit 209cc3
				continue;
Packit 209cc3
			}
Packit 209cc3
Packit 209cc3
			if (filterResult > tcHeader.CapturedLength)
Packit 209cc3
			{
Packit 209cc3
				filterResult = tcHeader.CapturedLength;
Packit 209cc3
			}
Packit 209cc3
		}
Packit 209cc3
		else
Packit 209cc3
		{
Packit 209cc3
			filterResult = tcHeader.CapturedLength;
Packit 209cc3
		}
Packit 209cc3
Packit 209cc3
		pt->TcAcceptedCount ++;
Packit 209cc3
Packit 209cc3
		hdr.ts.tv_sec = (bpf_u_int32)(tcHeader.Timestamp / (ULONGLONG)(1000  * 1000 * 1000));
Packit 209cc3
		hdr.ts.tv_usec = (bpf_u_int32)((tcHeader.Timestamp % (ULONGLONG)(1000  * 1000 * 1000)) / 1000);
Packit 209cc3
Packit 209cc3
		if (p->linktype == DLT_EN10MB)
Packit 209cc3
		{
Packit 209cc3
			hdr.caplen = filterResult;
Packit 209cc3
			hdr.len = tcHeader.Length;
Packit 209cc3
			(*callback)(user, &hdr, data);
Packit 209cc3
		}
Packit 209cc3
		else
Packit 209cc3
		{
Packit 209cc3
			PPPI_HEADER pPpiHeader = (PPPI_HEADER)pt->PpiPacket;
Packit 209cc3
			PVOID data2 = pPpiHeader + 1;
Packit 209cc3
Packit 209cc3
			pPpiHeader->AggregationField.InterfaceId = TC_PH_FLAGS_RX_PORT_ID(tcHeader.Flags);
Packit 209cc3
			pPpiHeader->Dot3Field.Errors = tcHeader.Errors;
Packit 209cc3
			if (tcHeader.Flags & TC_PH_FLAGS_CHECKSUM)
Packit 209cc3
			{
Packit 209cc3
				pPpiHeader->Dot3Field.Flags = PPI_FLD_802_3_EXT_FLAG_FCS_PRESENT;
Packit 209cc3
			}
Packit 209cc3
			else
Packit 209cc3
			{
Packit 209cc3
				pPpiHeader->Dot3Field.Flags = 0;
Packit 209cc3
			}
Packit 209cc3
Packit 209cc3
			if (filterResult <= MAX_TC_PACKET_SIZE)
Packit 209cc3
			{
Packit 209cc3
				memcpy(data2, data, filterResult);
Packit 209cc3
				hdr.caplen = sizeof(PPI_HEADER) + filterResult;
Packit 209cc3
				hdr.len = sizeof(PPI_HEADER) + tcHeader.Length;
Packit 209cc3
			}
Packit 209cc3
			else
Packit 209cc3
			{
Packit 209cc3
				memcpy(data2, data, MAX_TC_PACKET_SIZE);
Packit 209cc3
				hdr.caplen = sizeof(PPI_HEADER) + MAX_TC_PACKET_SIZE;
Packit 209cc3
				hdr.len = sizeof(PPI_HEADER) + tcHeader.Length;
Packit 209cc3
			}
Packit 209cc3
Packit 209cc3
			(*callback)(user, &hdr, pt->PpiPacket);
Packit 209cc3
Packit 209cc3
		}
Packit 209cc3
Packit 209cc3
		if (++n >= cnt && cnt > 0)
Packit 209cc3
		{
Packit 209cc3
			return n;
Packit 209cc3
		}
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	return n;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
static int
Packit 209cc3
TcStats(pcap_t *p, struct pcap_stat *ps)
Packit 209cc3
{
Packit 209cc3
	struct pcap_tc *pt = p->priv;
Packit 209cc3
	TC_STATISTICS statistics;
Packit 209cc3
	TC_STATUS status;
Packit 209cc3
	ULONGLONG counter;
Packit 209cc3
	struct pcap_stat s;
Packit 209cc3
Packit 209cc3
	status = g_TcFunctions.InstanceQueryStatistics(pt->TcInstance, &statistics);
Packit 209cc3
Packit 209cc3
	if (status != TC_SUCCESS)
Packit 209cc3
	{
Packit 209cc3
		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcInstanceQueryStatistics: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
Packit 209cc3
		return -1;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	memset(&s, 0, sizeof(s));
Packit 209cc3
Packit 209cc3
	status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_TOTAL_RX_PACKETS, &counter);
Packit 209cc3
	if (status != TC_SUCCESS)
Packit 209cc3
	{
Packit 209cc3
		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
Packit 209cc3
		return -1;
Packit 209cc3
	}
Packit 209cc3
	if (counter <= (ULONGLONG)0xFFFFFFFF)
Packit 209cc3
	{
Packit 209cc3
		s.ps_recv = (ULONG)counter;
Packit 209cc3
	}
Packit 209cc3
	else
Packit 209cc3
	{
Packit 209cc3
		s.ps_recv = 0xFFFFFFFF;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_RX_DROPPED_PACKETS, &counter);
Packit 209cc3
	if (status != TC_SUCCESS)
Packit 209cc3
	{
Packit 209cc3
		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
Packit 209cc3
		return -1;
Packit 209cc3
	}
Packit 209cc3
	if (counter <= (ULONGLONG)0xFFFFFFFF)
Packit 209cc3
	{
Packit 209cc3
		s.ps_ifdrop = (ULONG)counter;
Packit 209cc3
		s.ps_drop = (ULONG)counter;
Packit 209cc3
	}
Packit 209cc3
	else
Packit 209cc3
	{
Packit 209cc3
		s.ps_ifdrop = 0xFFFFFFFF;
Packit 209cc3
		s.ps_drop = 0xFFFFFFFF;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
#if defined(_WIN32) && defined(ENABLE_REMOTE)
Packit 209cc3
	s.ps_capt = pt->TcAcceptedCount;
Packit 209cc3
#endif
Packit 209cc3
	*ps = s;
Packit 209cc3
Packit 209cc3
	return 0;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
Packit 209cc3
/*
Packit 209cc3
 * We filter at user level, since the kernel driver does't process the packets
Packit 209cc3
 */
Packit 209cc3
static int
Packit 209cc3
TcSetFilter(pcap_t *p, struct bpf_program *fp)
Packit 209cc3
{
Packit 209cc3
	if(!fp)
Packit 209cc3
	{
Packit 209cc3
		strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
Packit 209cc3
		return -1;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	/* Install a user level filter */
Packit 209cc3
	if (install_bpf_program(p, fp) < 0)
Packit 209cc3
	{
Packit 209cc3
		return -1;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	return 0;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
#ifdef _WIN32
Packit 209cc3
static struct pcap_stat *
Packit 209cc3
TcStatsEx(pcap_t *p, int *pcap_stat_size)
Packit 209cc3
{
Packit 209cc3
	struct pcap_tc *pt = p->priv;
Packit 209cc3
	TC_STATISTICS statistics;
Packit 209cc3
	TC_STATUS status;
Packit 209cc3
	ULONGLONG counter;
Packit 209cc3
Packit 209cc3
	*pcap_stat_size = sizeof (p->stat);
Packit 209cc3
Packit 209cc3
	status = g_TcFunctions.InstanceQueryStatistics(pt->TcInstance, &statistics);
Packit 209cc3
Packit 209cc3
	if (status != TC_SUCCESS)
Packit 209cc3
	{
Packit 209cc3
		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcInstanceQueryStatistics: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
Packit 209cc3
		return NULL;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	memset(&p->stat, 0, sizeof(p->stat));
Packit 209cc3
Packit 209cc3
	status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_TOTAL_RX_PACKETS, &counter);
Packit 209cc3
	if (status != TC_SUCCESS)
Packit 209cc3
	{
Packit 209cc3
		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
Packit 209cc3
		return NULL;
Packit 209cc3
	}
Packit 209cc3
	if (counter <= (ULONGLONG)0xFFFFFFFF)
Packit 209cc3
	{
Packit 209cc3
		p->stat.ps_recv = (ULONG)counter;
Packit 209cc3
	}
Packit 209cc3
	else
Packit 209cc3
	{
Packit 209cc3
		p->stat.ps_recv = 0xFFFFFFFF;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_RX_DROPPED_PACKETS, &counter);
Packit 209cc3
	if (status != TC_SUCCESS)
Packit 209cc3
	{
Packit 209cc3
		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
Packit 209cc3
		return NULL;
Packit 209cc3
	}
Packit 209cc3
	if (counter <= (ULONGLONG)0xFFFFFFFF)
Packit 209cc3
	{
Packit 209cc3
		p->stat.ps_ifdrop = (ULONG)counter;
Packit 209cc3
		p->stat.ps_drop = (ULONG)counter;
Packit 209cc3
	}
Packit 209cc3
	else
Packit 209cc3
	{
Packit 209cc3
		p->stat.ps_ifdrop = 0xFFFFFFFF;
Packit 209cc3
		p->stat.ps_drop = 0xFFFFFFFF;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
#if defined(_WIN32) && defined(ENABLE_REMOTE)
Packit 209cc3
	p->stat.ps_capt = pt->TcAcceptedCount;
Packit 209cc3
#endif
Packit 209cc3
Packit 209cc3
	return &p->stat;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
/* Set the dimension of the kernel-level capture buffer */
Packit 209cc3
static int
Packit 209cc3
TcSetBuff(pcap_t *p, int dim)
Packit 209cc3
{
Packit 209cc3
	/*
Packit 209cc3
	 * XXX turbocap has an internal way of managing buffers.
Packit 209cc3
	 * And at the moment it's not configurable, so we just
Packit 209cc3
	 * silently ignore the request to set the buffer.
Packit 209cc3
	 */
Packit 209cc3
	return 0;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
static int
Packit 209cc3
TcSetMode(pcap_t *p, int mode)
Packit 209cc3
{
Packit 209cc3
	if (mode != MODE_CAPT)
Packit 209cc3
	{
Packit 209cc3
		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Mode %u not supported by TurboCap devices. TurboCap only supports capture.", mode);
Packit 209cc3
		return -1;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	return 0;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
static int
Packit 209cc3
TcSetMinToCopy(pcap_t *p, int size)
Packit 209cc3
{
Packit 209cc3
	struct pcap_tc *pt = p->priv;
Packit 209cc3
	TC_STATUS status;
Packit 209cc3
Packit 209cc3
	if (size < 0)
Packit 209cc3
	{
Packit 209cc3
		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Mintocopy cannot be less than 0.");
Packit 209cc3
		return -1;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_MINTOCOPY, (ULONG)size);
Packit 209cc3
Packit 209cc3
	if (status != TC_SUCCESS)
Packit 209cc3
	{
Packit 209cc3
		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error setting the mintocopy: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	return 0;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
static HANDLE
Packit 209cc3
TcGetReceiveWaitHandle(pcap_t *p)
Packit 209cc3
{
Packit 209cc3
	struct pcap_tc *pt = p->priv;
Packit 209cc3
Packit 209cc3
	return g_TcFunctions.InstanceGetReceiveWaitHandle(pt->TcInstance);
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
static int
Packit 209cc3
TcOidGetRequest(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_, size_t *lenp _U_)
Packit 209cc3
{
Packit 209cc3
	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
Packit 209cc3
	    "An OID get request cannot be performed on a TurboCap device");
Packit 209cc3
	return PCAP_ERROR;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
static int
Packit 209cc3
TcOidSetRequest(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
Packit 209cc3
    size_t *lenp _U_)
Packit 209cc3
{
Packit 209cc3
	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
Packit 209cc3
	    "An OID set request cannot be performed on a TurboCap device");
Packit 209cc3
	return PCAP_ERROR;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
static u_int
Packit 209cc3
TcSendqueueTransmit(pcap_t *p, pcap_send_queue *queue _U_, int sync _U_)
Packit 209cc3
{
Packit 209cc3
	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
Packit 209cc3
	    "Packets cannot be bulk transmitted on a TurboCap device");
Packit 209cc3
	return 0;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
static int
Packit 209cc3
TcSetUserBuffer(pcap_t *p, int size _U_)
Packit 209cc3
{
Packit 209cc3
	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
Packit 209cc3
	    "The user buffer cannot be set on a TurboCap device");
Packit 209cc3
	return -1;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
static int
Packit 209cc3
TcLiveDump(pcap_t *p, char *filename _U_, int maxsize _U_, int maxpacks _U_)
Packit 209cc3
{
Packit 209cc3
	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
Packit 209cc3
	    "Live packet dumping cannot be performed on a TurboCap device");
Packit 209cc3
	return -1;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
static int
Packit 209cc3
TcLiveDumpEnded(pcap_t *p, int sync _U_)
Packit 209cc3
{
Packit 209cc3
	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
Packit 209cc3
	    "Live packet dumping cannot be performed on a TurboCap device");
Packit 209cc3
	return -1;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
static PAirpcapHandle
Packit 209cc3
TcGetAirPcapHandle(pcap_t *p _U_)
Packit 209cc3
{
Packit 209cc3
	return NULL;
Packit 209cc3
}
Packit 209cc3
#endif