Home | History | Annotate | Download | only in libpcap
      1 /*
      2  * Copyright (c) 2008 CACE Technologies, Davis (California)
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *
      9  * 1. Redistributions of source code must retain the above copyright
     10  * notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  * notice, this list of conditions and the following disclaimer in the
     13  * documentation and/or other materials provided with the distribution.
     14  * 3. Neither the name of CACE Technologies nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  *
     30  */
     31 
     32 #ifdef HAVE_CONFIG_H
     33 #include <config.h>
     34 #endif
     35 
     36 #include <pcap.h>
     37 #include <pcap-int.h>
     38 
     39 #include "pcap-tc.h"
     40 
     41 #include <malloc.h>
     42 #include <memory.h>
     43 #include <string.h>
     44 #include <errno.h>
     45 
     46 #ifdef _WIN32
     47 #include <tchar.h>
     48 #endif
     49 
     50 typedef TC_STATUS	(TC_CALLCONV *TcFcnQueryPortList)			(PTC_PORT *ppPorts, PULONG pLength);
     51 typedef TC_STATUS	(TC_CALLCONV *TcFcnFreePortList)			(TC_PORT *pPorts);
     52 
     53 typedef PCHAR		(TC_CALLCONV *TcFcnStatusGetString)			(TC_STATUS status);
     54 
     55 typedef PCHAR		(TC_CALLCONV *TcFcnPortGetName)				(TC_PORT port);
     56 typedef PCHAR		(TC_CALLCONV *TcFcnPortGetDescription)		(TC_PORT port);
     57 
     58 typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceOpenByName)		(PCHAR name, PTC_INSTANCE pInstance);
     59 typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceClose)			(TC_INSTANCE instance);
     60 typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceSetFeature)		(TC_INSTANCE instance, ULONG feature, ULONG value);
     61 typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceQueryFeature)	(TC_INSTANCE instance, ULONG feature, PULONG pValue);
     62 typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceReceivePackets)	(TC_INSTANCE instance, PTC_PACKETS_BUFFER pBuffer);
     63 typedef HANDLE		(TC_CALLCONV *TcFcnInstanceGetReceiveWaitHandle) (TC_INSTANCE instance);
     64 typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceTransmitPackets)	(TC_INSTANCE instance, TC_PACKETS_BUFFER pBuffer);
     65 typedef TC_STATUS	(TC_CALLCONV *TcFcnInstanceQueryStatistics)	(TC_INSTANCE instance, PTC_STATISTICS pStatistics);
     66 
     67 typedef TC_STATUS	(TC_CALLCONV *TcFcnPacketsBufferCreate)		(ULONG size, PTC_PACKETS_BUFFER pBuffer);
     68 typedef VOID		(TC_CALLCONV *TcFcnPacketsBufferDestroy)	(TC_PACKETS_BUFFER buffer);
     69 typedef TC_STATUS	(TC_CALLCONV *TcFcnPacketsBufferQueryNextPacket)(TC_PACKETS_BUFFER buffer, PTC_PACKET_HEADER pHeader, PVOID *ppData);
     70 typedef TC_STATUS	(TC_CALLCONV *TcFcnPacketsBufferCommitNextPacket)(TC_PACKETS_BUFFER buffer, PTC_PACKET_HEADER pHeader, PVOID pData);
     71 
     72 typedef VOID		(TC_CALLCONV *TcFcnStatisticsDestroy)		(TC_STATISTICS statistics);
     73 typedef TC_STATUS	(TC_CALLCONV *TcFcnStatisticsUpdate)		(TC_STATISTICS statistics);
     74 typedef TC_STATUS	(TC_CALLCONV *TcFcnStatisticsQueryValue)	(TC_STATISTICS statistics, ULONG counterId, PULONGLONG pValue);
     75 
     76 typedef enum LONG
     77 {
     78 	TC_API_UNLOADED = 0,
     79 	TC_API_LOADED,
     80 	TC_API_CANNOT_LOAD,
     81 	TC_API_LOADING
     82 }
     83 	TC_API_LOAD_STATUS;
     84 
     85 
     86 typedef struct _TC_FUNCTIONS
     87 {
     88 	TC_API_LOAD_STATUS			LoadStatus;
     89 #ifdef _WIN32
     90 	HMODULE						hTcApiDllHandle;
     91 #endif
     92 	TcFcnQueryPortList			QueryPortList;
     93 	TcFcnFreePortList			FreePortList;
     94 	TcFcnStatusGetString		StatusGetString;
     95 
     96 	TcFcnPortGetName			PortGetName;
     97 	TcFcnPortGetDescription		PortGetDescription;
     98 
     99 	TcFcnInstanceOpenByName		InstanceOpenByName;
    100 	TcFcnInstanceClose			InstanceClose;
    101 	TcFcnInstanceSetFeature		InstanceSetFeature;
    102 	TcFcnInstanceQueryFeature	InstanceQueryFeature;
    103 	TcFcnInstanceReceivePackets	InstanceReceivePackets;
    104 #ifdef _WIN32
    105 	TcFcnInstanceGetReceiveWaitHandle InstanceGetReceiveWaitHandle;
    106 #endif
    107 	TcFcnInstanceTransmitPackets InstanceTransmitPackets;
    108 	TcFcnInstanceQueryStatistics InstanceQueryStatistics;
    109 
    110 	TcFcnPacketsBufferCreate	PacketsBufferCreate;
    111 	TcFcnPacketsBufferDestroy	PacketsBufferDestroy;
    112 	TcFcnPacketsBufferQueryNextPacket	PacketsBufferQueryNextPacket;
    113 	TcFcnPacketsBufferCommitNextPacket  PacketsBufferCommitNextPacket;
    114 
    115 	TcFcnStatisticsDestroy		StatisticsDestroy;
    116 	TcFcnStatisticsUpdate		StatisticsUpdate;
    117 	TcFcnStatisticsQueryValue	StatisticsQueryValue;
    118 }
    119 	TC_FUNCTIONS;
    120 
    121 static pcap_if_t* TcCreatePcapIfFromPort(TC_PORT port);
    122 static int TcSetDatalink(pcap_t *p, int dlt);
    123 static int TcGetNonBlock(pcap_t *p);
    124 static int TcSetNonBlock(pcap_t *p, int nonblock);
    125 static void TcCleanup(pcap_t *p);
    126 static int TcInject(pcap_t *p, const void *buf, size_t size);
    127 static int TcRead(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
    128 static int TcStats(pcap_t *p, struct pcap_stat *ps);
    129 static int TcSetFilter(pcap_t *p, struct bpf_program *fp);
    130 #ifdef _WIN32
    131 static struct pcap_stat *TcStatsEx(pcap_t *p, int *pcap_stat_size);
    132 static int TcSetBuff(pcap_t *p, int dim);
    133 static int TcSetMode(pcap_t *p, int mode);
    134 static int TcSetMinToCopy(pcap_t *p, int size);
    135 static HANDLE TcGetReceiveWaitHandle(pcap_t *p);
    136 static int TcOidGetRequest(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp);
    137 static int TcOidSetRequest(pcap_t *p, bpf_u_int32 oid, const void *data, size_t *lenp);
    138 static u_int TcSendqueueTransmit(pcap_t *p, pcap_send_queue *queue, int sync);
    139 static int TcSetUserBuffer(pcap_t *p, int size);
    140 static int TcLiveDump(pcap_t *p, char *filename, int maxsize, int maxpacks);
    141 static int TcLiveDumpEnded(pcap_t *p, int sync);
    142 static PAirpcapHandle TcGetAirPcapHandle(pcap_t *p);
    143 #endif
    144 
    145 #ifdef _WIN32
    146 TC_FUNCTIONS g_TcFunctions =
    147 {
    148 	TC_API_UNLOADED, /* LoadStatus */
    149 	NULL,  /* hTcApiDllHandle */
    150 	NULL,  /* QueryPortList */
    151 	NULL,  /* FreePortList */
    152 	NULL,  /* StatusGetString */
    153 	NULL,  /* PortGetName */
    154 	NULL,  /* PortGetDescription */
    155 	NULL,  /* InstanceOpenByName */
    156 	NULL,  /* InstanceClose */
    157 	NULL,  /* InstanceSetFeature */
    158 	NULL,  /* InstanceQueryFeature */
    159 	NULL,  /* InstanceReceivePackets */
    160 	NULL,  /* InstanceGetReceiveWaitHandle */
    161 	NULL,  /* InstanceTransmitPackets */
    162 	NULL,  /* InstanceQueryStatistics */
    163 	NULL,  /* PacketsBufferCreate */
    164 	NULL,  /* PacketsBufferDestroy */
    165 	NULL,  /* PacketsBufferQueryNextPacket */
    166 	NULL,  /* PacketsBufferCommitNextPacket */
    167 	NULL,  /* StatisticsDestroy */
    168 	NULL,  /* StatisticsUpdate */
    169 	NULL  /* StatisticsQueryValue */
    170 };
    171 #else
    172 TC_FUNCTIONS g_TcFunctions =
    173 {
    174 	TC_API_LOADED, /* LoadStatus */
    175 	TcQueryPortList,
    176 	TcFreePortList,
    177 	TcStatusGetString,
    178 	TcPortGetName,
    179 	TcPortGetDescription,
    180 	TcInstanceOpenByName,
    181 	TcInstanceClose,
    182 	TcInstanceSetFeature,
    183 	TcInstanceQueryFeature,
    184 	TcInstanceReceivePackets,
    185 #ifdef _WIN32
    186 	TcInstanceGetReceiveWaitHandle,
    187 #endif
    188 	TcInstanceTransmitPackets,
    189 	TcInstanceQueryStatistics,
    190 	TcPacketsBufferCreate,
    191 	TcPacketsBufferDestroy,
    192 	TcPacketsBufferQueryNextPacket,
    193 	TcPacketsBufferCommitNextPacket,
    194 	TcStatisticsDestroy,
    195 	TcStatisticsUpdate,
    196 	TcStatisticsQueryValue,
    197 };
    198 #endif
    199 
    200 #define MAX_TC_PACKET_SIZE	9500
    201 
    202 #pragma pack(push, 1)
    203 
    204 #define PPH_PH_FLAG_PADDING	((UCHAR)0x01)
    205 #define PPH_PH_VERSION		((UCHAR)0x00)
    206 
    207 typedef struct _PPI_PACKET_HEADER
    208 {
    209 	UCHAR	PphVersion;
    210 	UCHAR	PphFlags;
    211 	USHORT	PphLength;
    212 	ULONG	PphDlt;
    213 }
    214 	PPI_PACKET_HEADER, *PPPI_PACKET_HEADER;
    215 
    216 typedef struct _PPI_FIELD_HEADER
    217 {
    218 	USHORT PfhType;
    219 	USHORT PfhLength;
    220 }
    221 	PPI_FIELD_HEADER, *PPPI_FIELD_HEADER;
    222 
    223 
    224 #define		PPI_FIELD_TYPE_AGGREGATION_EXTENSION	((UCHAR)0x08)
    225 
    226 typedef struct _PPI_FIELD_AGGREGATION_EXTENSION
    227 {
    228 	ULONG		InterfaceId;
    229 }
    230 	PPI_FIELD_AGGREGATION_EXTENSION, *PPPI_FIELD_AGGREGATION_EXTENSION;
    231 
    232 
    233 #define		PPI_FIELD_TYPE_802_3_EXTENSION			((UCHAR)0x09)
    234 
    235 #define PPI_FLD_802_3_EXT_FLAG_FCS_PRESENT			((ULONG)0x00000001)
    236 
    237 typedef struct _PPI_FIELD_802_3_EXTENSION
    238 {
    239 	ULONG		Flags;
    240 	ULONG		Errors;
    241 }
    242 	PPI_FIELD_802_3_EXTENSION, *PPPI_FIELD_802_3_EXTENSION;
    243 
    244 typedef struct _PPI_HEADER
    245 {
    246 	PPI_PACKET_HEADER PacketHeader;
    247 	PPI_FIELD_HEADER  AggregationFieldHeader;
    248 	PPI_FIELD_AGGREGATION_EXTENSION AggregationField;
    249 	PPI_FIELD_HEADER  Dot3FieldHeader;
    250 	PPI_FIELD_802_3_EXTENSION Dot3Field;
    251 }
    252 	PPI_HEADER, *PPPI_HEADER;
    253 #pragma pack(pop)
    254 
    255 #ifdef _WIN32
    256 //
    257 // This wrapper around loadlibrary appends the system folder (usually c:\windows\system32)
    258 // to the relative path of the DLL, so that the DLL is always loaded from an absolute path
    259 // (It's no longer possible to load airpcap.dll from the application folder).
    260 // This solves the DLL Hijacking issue discovered in August 2010
    261 // http://blog.metasploit.com/2010/08/exploiting-dll-hijacking-flaws.html
    262 //
    263 HMODULE LoadLibrarySafe(LPCTSTR lpFileName)
    264 {
    265   TCHAR path[MAX_PATH];
    266   TCHAR fullFileName[MAX_PATH];
    267   UINT res;
    268   HMODULE hModule = NULL;
    269   do
    270   {
    271 	res = GetSystemDirectory(path, MAX_PATH);
    272 
    273 	if (res == 0)
    274 	{
    275 		//
    276 		// some bad failure occurred;
    277 		//
    278 		break;
    279 	}
    280 
    281 	if (res > MAX_PATH)
    282 	{
    283 		//
    284 		// the buffer was not big enough
    285 		//
    286 		SetLastError(ERROR_INSUFFICIENT_BUFFER);
    287 		break;
    288 	}
    289 
    290 	if (res + 1 + _tcslen(lpFileName) + 1 < MAX_PATH)
    291 	{
    292 		memcpy(fullFileName, path, res * sizeof(TCHAR));
    293 		fullFileName[res] = _T('\\');
    294 		memcpy(&fullFileName[res + 1], lpFileName, (_tcslen(lpFileName) + 1) * sizeof(TCHAR));
    295 
    296 		hModule = LoadLibrary(fullFileName);
    297 	}
    298 	else
    299 	{
    300 		SetLastError(ERROR_INSUFFICIENT_BUFFER);
    301 	}
    302 
    303   }while(FALSE);
    304 
    305   return hModule;
    306 }
    307 
    308 /*
    309  * NOTE: this function should be called by the pcap functions that can theoretically
    310  *       deal with the Tc library for the first time, namely listing the adapters and
    311  *       opening one. All the other ones (close, read, write, set parameters) work
    312  *       on an open instance of TC, so we do not care to call this function
    313  */
    314 TC_API_LOAD_STATUS LoadTcFunctions(void)
    315 {
    316 	TC_API_LOAD_STATUS currentStatus;
    317 
    318 	do
    319 	{
    320 		currentStatus = InterlockedCompareExchange((LONG*)&g_TcFunctions.LoadStatus, TC_API_LOADING, TC_API_UNLOADED);
    321 
    322 		while(currentStatus == TC_API_LOADING)
    323 		{
    324 			currentStatus = InterlockedCompareExchange((LONG*)&g_TcFunctions.LoadStatus, TC_API_LOADING, TC_API_LOADING);
    325 			Sleep(10);
    326 		}
    327 
    328 		/*
    329 		 * at this point we are either in the LOADED state, unloaded state (i.e. we are the ones loading everything)
    330 		 * or in cannot load
    331 		 */
    332 		if(currentStatus  == TC_API_LOADED)
    333 		{
    334 			return TC_API_LOADED;
    335 		}
    336 
    337 		if (currentStatus == TC_API_CANNOT_LOAD)
    338 		{
    339 			return TC_API_CANNOT_LOAD;
    340 		}
    341 
    342 		currentStatus = TC_API_CANNOT_LOAD;
    343 
    344 		g_TcFunctions.hTcApiDllHandle = LoadLibrarySafe("TcApi.dll");
    345 		if (g_TcFunctions.hTcApiDllHandle == NULL)	break;
    346 
    347 		g_TcFunctions.QueryPortList					= (TcFcnQueryPortList)			GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcQueryPortList");
    348 		g_TcFunctions.FreePortList					= (TcFcnFreePortList)			GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcFreePortList");
    349 
    350 		g_TcFunctions.StatusGetString				= (TcFcnStatusGetString)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatusGetString");
    351 
    352 		g_TcFunctions.PortGetName					= (TcFcnPortGetName)			GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPortGetName");
    353 		g_TcFunctions.PortGetDescription			= (TcFcnPortGetDescription)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPortGetDescription");
    354 
    355 		g_TcFunctions.InstanceOpenByName			= (TcFcnInstanceOpenByName)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceOpenByName");
    356 		g_TcFunctions.InstanceClose					= (TcFcnInstanceClose)			GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceClose");
    357 		g_TcFunctions.InstanceSetFeature			= (TcFcnInstanceSetFeature)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceSetFeature");
    358 		g_TcFunctions.InstanceQueryFeature			= (TcFcnInstanceQueryFeature)	GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceQueryFeature");
    359 		g_TcFunctions.InstanceReceivePackets		= (TcFcnInstanceReceivePackets)	GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceReceivePackets");
    360 		g_TcFunctions.InstanceGetReceiveWaitHandle	= (TcFcnInstanceGetReceiveWaitHandle)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceGetReceiveWaitHandle");
    361 		g_TcFunctions.InstanceTransmitPackets		= (TcFcnInstanceTransmitPackets)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceTransmitPackets");
    362 		g_TcFunctions.InstanceQueryStatistics		= (TcFcnInstanceQueryStatistics)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceQueryStatistics");
    363 
    364 		g_TcFunctions.PacketsBufferCreate			= (TcFcnPacketsBufferCreate)	GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferCreate");
    365 		g_TcFunctions.PacketsBufferDestroy			= (TcFcnPacketsBufferDestroy)	GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferDestroy");
    366 		g_TcFunctions.PacketsBufferQueryNextPacket	= (TcFcnPacketsBufferQueryNextPacket)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferQueryNextPacket");
    367 		g_TcFunctions.PacketsBufferCommitNextPacket	= (TcFcnPacketsBufferCommitNextPacket)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferCommitNextPacket");
    368 
    369 		g_TcFunctions.StatisticsDestroy				= (TcFcnStatisticsDestroy)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatisticsDestroy");
    370 		g_TcFunctions.StatisticsUpdate				= (TcFcnStatisticsUpdate)		GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatisticsUpdate");
    371 		g_TcFunctions.StatisticsQueryValue			= (TcFcnStatisticsQueryValue)	GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatisticsQueryValue");
    372 
    373 		if (   g_TcFunctions.QueryPortList == NULL
    374 			|| g_TcFunctions.FreePortList == NULL
    375 			|| g_TcFunctions.StatusGetString == NULL
    376 			|| g_TcFunctions.PortGetName == NULL
    377 			|| g_TcFunctions.PortGetDescription == NULL
    378 			|| g_TcFunctions.InstanceOpenByName == NULL
    379 			|| g_TcFunctions.InstanceClose == NULL
    380 			|| g_TcFunctions.InstanceSetFeature	 == NULL
    381 			|| g_TcFunctions.InstanceQueryFeature == NULL
    382 			|| g_TcFunctions.InstanceReceivePackets == NULL
    383 			|| g_TcFunctions.InstanceGetReceiveWaitHandle == NULL
    384 			|| g_TcFunctions.InstanceTransmitPackets == NULL
    385 			|| g_TcFunctions.InstanceQueryStatistics == NULL
    386 			|| g_TcFunctions.PacketsBufferCreate == NULL
    387 			|| g_TcFunctions.PacketsBufferDestroy == NULL
    388 			|| g_TcFunctions.PacketsBufferQueryNextPacket == NULL
    389 			|| g_TcFunctions.PacketsBufferCommitNextPacket == NULL
    390 			|| g_TcFunctions.StatisticsDestroy == NULL
    391 			|| g_TcFunctions.StatisticsUpdate == NULL
    392 			|| g_TcFunctions.StatisticsQueryValue == NULL
    393 		)
    394 		{
    395 			break;
    396 		}
    397 
    398 		/*
    399 		 * everything got loaded, yay!!
    400 		 */
    401 		currentStatus = TC_API_LOADED;
    402 	}while(FALSE);
    403 
    404 	if (currentStatus != TC_API_LOADED)
    405 	{
    406 		if (g_TcFunctions.hTcApiDllHandle != NULL)
    407 		{
    408 			FreeLibrary(g_TcFunctions.hTcApiDllHandle);
    409 			g_TcFunctions.hTcApiDllHandle = NULL;
    410 		}
    411 	}
    412 
    413 	InterlockedExchange((LONG*)&g_TcFunctions.LoadStatus, currentStatus);
    414 
    415 	return currentStatus;
    416 }
    417 #else
    418 // static linking
    419 TC_API_LOAD_STATUS LoadTcFunctions(void)
    420 {
    421 	return TC_API_LOADED;
    422 }
    423 #endif
    424 
    425 /*
    426  * Private data for capturing on TurboCap devices.
    427  */
    428 struct pcap_tc {
    429 	TC_INSTANCE TcInstance;
    430 	TC_PACKETS_BUFFER TcPacketsBuffer;
    431 	ULONG TcAcceptedCount;
    432 	u_char *PpiPacket;
    433 };
    434 
    435 int
    436 TcFindAllDevs(pcap_if_list_t *devlist, char *errbuf)
    437 {
    438 	TC_API_LOAD_STATUS loadStatus;
    439 	ULONG numPorts;
    440 	PTC_PORT pPorts = NULL;
    441 	TC_STATUS status;
    442 	int result = 0;
    443 	pcap_if_t *dev, *cursor;
    444 	ULONG i;
    445 
    446 	do
    447 	{
    448 		loadStatus = LoadTcFunctions();
    449 
    450 		if (loadStatus != TC_API_LOADED)
    451 		{
    452 			result = 0;
    453 			break;
    454 		}
    455 
    456 		/*
    457 		 * enumerate the ports, and add them to the list
    458 		 */
    459 		status = g_TcFunctions.QueryPortList(&pPorts, &numPorts);
    460 
    461 		if (status != TC_SUCCESS)
    462 		{
    463 			result = 0;
    464 			break;
    465 		}
    466 
    467 		for (i = 0; i < numPorts; i++)
    468 		{
    469 			/*
    470 			 * transform the port into an entry in the list
    471 			 */
    472 			dev = TcCreatePcapIfFromPort(pPorts[i]);
    473 
    474 			if (dev != NULL)
    475 			{
    476 				/*
    477 				 * append it at the end
    478 				 */
    479 				if (devlistp->beginning == NULL)
    480 				{
    481 					devlistp->beginning = dev;
    482 				}
    483 				else
    484 				{
    485 					for (cursor = devlistp->beginning;
    486 					    cursor->next != NULL;
    487 					    cursor = cursor->next);
    488 					cursor->next = dev;
    489 				}
    490 			}
    491 		}
    492 
    493 		if (numPorts > 0)
    494 		{
    495 			/*
    496 			 * ignore the result here
    497 			 */
    498 			status = g_TcFunctions.FreePortList(pPorts);
    499 		}
    500 
    501 	}while(FALSE);
    502 
    503 	return result;
    504 }
    505 
    506 static pcap_if_t* TcCreatePcapIfFromPort(TC_PORT port)
    507 {
    508 	CHAR *name;
    509 	CHAR *description;
    510 	pcap_if_t *newIf = NULL;
    511 
    512 	newIf = (pcap_if_t*)malloc(sizeof(*newIf));
    513 	if (newIf == NULL)
    514 	{
    515 		return NULL;
    516 	}
    517 
    518 	memset(newIf, 0, sizeof(*newIf));
    519 
    520 	name = g_TcFunctions.PortGetName(port);
    521 	description = g_TcFunctions.PortGetDescription(port);
    522 
    523 	newIf->name = (char*)malloc(strlen(name) + 1);
    524 	if (newIf->name == NULL)
    525 	{
    526 		free(newIf);
    527 		return NULL;
    528 	}
    529 
    530 	newIf->description = (char*)malloc(strlen(description) + 1);
    531 	if (newIf->description == NULL)
    532 	{
    533 		free(newIf->name);
    534 		free(newIf);
    535 		return NULL;
    536 	}
    537 
    538 	strcpy(newIf->name, name);
    539 	strcpy(newIf->description, description);
    540 
    541 	newIf->addresses = NULL;
    542 	newIf->next = NULL;
    543 	newIf->flags = 0;
    544 
    545 	return newIf;
    546 
    547 }
    548 
    549 static int
    550 TcActivate(pcap_t *p)
    551 {
    552 	struct pcap_tc *pt = p->priv;
    553 	TC_STATUS status;
    554 	ULONG timeout;
    555 	PPPI_HEADER pPpiHeader;
    556 
    557 	if (p->opt.rfmon)
    558 	{
    559 		/*
    560 		 * No monitor mode on Tc cards; they're Ethernet
    561 		 * capture adapters.
    562 		 */
    563 		return PCAP_ERROR_RFMON_NOTSUP;
    564 	}
    565 
    566 	pt->PpiPacket = malloc(sizeof(PPI_HEADER) + MAX_TC_PACKET_SIZE);
    567 
    568 	if (pt->PpiPacket == NULL)
    569 	{
    570 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error allocating memory");
    571 		return PCAP_ERROR;
    572 	}
    573 
    574 	/*
    575 	 * Turn a negative snapshot value (invalid), a snapshot value of
    576 	 * 0 (unspecified), or a value bigger than the normal maximum
    577 	 * value, into the maximum allowed value.
    578 	 *
    579 	 * If some application really *needs* a bigger snapshot
    580 	 * length, we should just increase MAXIMUM_SNAPLEN.
    581 	 */
    582 	if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
    583 		p->snapshot = MAXIMUM_SNAPLEN;
    584 
    585 	/*
    586 	 * Initialize the PPI fixed fields
    587 	 */
    588 	pPpiHeader = (PPPI_HEADER)pt->PpiPacket;
    589 	pPpiHeader->PacketHeader.PphDlt = DLT_EN10MB;
    590 	pPpiHeader->PacketHeader.PphLength = sizeof(PPI_HEADER);
    591 	pPpiHeader->PacketHeader.PphFlags = 0;
    592 	pPpiHeader->PacketHeader.PphVersion = 0;
    593 
    594 	pPpiHeader->AggregationFieldHeader.PfhLength = sizeof(PPI_FIELD_AGGREGATION_EXTENSION);
    595 	pPpiHeader->AggregationFieldHeader.PfhType = PPI_FIELD_TYPE_AGGREGATION_EXTENSION;
    596 
    597 	pPpiHeader->Dot3FieldHeader.PfhLength = sizeof(PPI_FIELD_802_3_EXTENSION);
    598 	pPpiHeader->Dot3FieldHeader.PfhType = PPI_FIELD_TYPE_802_3_EXTENSION;
    599 
    600 	status = g_TcFunctions.InstanceOpenByName(p->opt.device, &pt->TcInstance);
    601 
    602 	if (status != TC_SUCCESS)
    603 	{
    604 		/* Adapter detected but we are not able to open it. Return failure. */
    605 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening TurboCap adapter: %s", g_TcFunctions.StatusGetString(status));
    606 		return PCAP_ERROR;
    607 	}
    608 
    609 	p->linktype = DLT_EN10MB;
    610 	p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
    611 	/*
    612 	 * If that fails, just leave the list empty.
    613 	 */
    614 	if (p->dlt_list != NULL) {
    615 		p->dlt_list[0] = DLT_EN10MB;
    616 		p->dlt_list[1] = DLT_PPI;
    617 		p->dlt_count = 2;
    618 	}
    619 
    620 	/*
    621 	 * ignore promiscuous mode
    622 	 * p->opt.promisc
    623 	 */
    624 
    625 
    626 	/*
    627 	 * ignore all the buffer sizes
    628 	 */
    629 
    630 	/*
    631 	 * enable reception
    632 	 */
    633 	status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_RX_STATUS, 1);
    634 
    635 	if (status != TC_SUCCESS)
    636 	{
    637 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error enabling reception on a TurboCap instance: %s", g_TcFunctions.StatusGetString(status));
    638 		goto bad;
    639 	}
    640 
    641 	/*
    642 	 * enable transmission
    643 	 */
    644 	status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_TX_STATUS, 1);
    645 	/*
    646 	 * Ignore the error here.
    647 	 */
    648 
    649 	p->inject_op = TcInject;
    650 	/*
    651 	 * if the timeout is -1, it means immediate return, no timeout
    652 	 * if the timeout is 0, it means INFINITE
    653 	 */
    654 
    655 	if (p->opt.timeout == 0)
    656 	{
    657 		timeout = 0xFFFFFFFF;
    658 	}
    659 	else
    660 	if (p->opt.timeout < 0)
    661 	{
    662 		/*
    663 		 *  we insert a minimal timeout here
    664 		 */
    665 		timeout = 10;
    666 	}
    667 	else
    668 	{
    669 		timeout = p->opt.timeout;
    670 	}
    671 
    672 	status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_READ_TIMEOUT, timeout);
    673 
    674 	if (status != TC_SUCCESS)
    675 	{
    676 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error setting the read timeout a TurboCap instance: %s", g_TcFunctions.StatusGetString(status));
    677 		goto bad;
    678 	}
    679 
    680 	p->read_op = TcRead;
    681 	p->setfilter_op = TcSetFilter;
    682 	p->setdirection_op = NULL;	/* Not implemented. */
    683 	p->set_datalink_op = TcSetDatalink;
    684 	p->getnonblock_op = TcGetNonBlock;
    685 	p->setnonblock_op = TcSetNonBlock;
    686 	p->stats_op = TcStats;
    687 #ifdef _WIN32
    688 	p->stats_ex_op = TcStatsEx;
    689 	p->setbuff_op = TcSetBuff;
    690 	p->setmode_op = TcSetMode;
    691 	p->setmintocopy_op = TcSetMinToCopy;
    692 	p->getevent_op = TcGetReceiveWaitHandle;
    693 	p->oid_get_request_op = TcOidGetRequest;
    694 	p->oid_set_request_op = TcOidSetRequest;
    695 	p->sendqueue_transmit_op = TcSendqueueTransmit;
    696 	p->setuserbuffer_op = TcSetUserBuffer;
    697 	p->live_dump_op = TcLiveDump;
    698 	p->live_dump_ended_op = TcLiveDumpEnded;
    699 	p->get_airpcap_handle_op = TcGetAirPcapHandle;
    700 #else
    701 	p->selectable_fd = -1;
    702 #endif
    703 
    704 	p->cleanup_op = TcCleanup;
    705 
    706 	return 0;
    707 bad:
    708 	TcCleanup(p);
    709 	return PCAP_ERROR;
    710 }
    711 
    712 pcap_t *
    713 TcCreate(const char *device, char *ebuf, int *is_ours)
    714 {
    715 	ULONG numPorts;
    716 	PTC_PORT pPorts = NULL;
    717 	TC_STATUS status;
    718 	int is_tc;
    719 	ULONG i;
    720 	pcap_t *p;
    721 
    722 	if (LoadTcFunctions() != TC_API_LOADED)
    723 	{
    724 		/*
    725 		 * XXX - report this as an error rather than as
    726 		 * "not a TurboCap device"?
    727 		 */
    728 		*is_ours = 0;
    729 		return NULL;
    730 	}
    731 
    732 	/*
    733 	 * enumerate the ports, and add them to the list
    734 	 */
    735 	status = g_TcFunctions.QueryPortList(&pPorts, &numPorts);
    736 
    737 	if (status != TC_SUCCESS)
    738 	{
    739 		/*
    740 		 * XXX - report this as an error rather than as
    741 		 * "not a TurboCap device"?
    742 		 */
    743 		*is_ours = 0;
    744 		return NULL;
    745 	}
    746 
    747 	is_tc = FALSE;
    748 	for (i = 0; i < numPorts; i++)
    749 	{
    750 		if (strcmp(g_TcFunctions.PortGetName(pPorts[i]), device) == 0)
    751 		{
    752 			is_tc = TRUE;
    753 			break;
    754 		}
    755 	}
    756 
    757 	if (numPorts > 0)
    758 	{
    759 		/*
    760 		 * ignore the result here
    761 		 */
    762 		(void)g_TcFunctions.FreePortList(pPorts);
    763 	}
    764 
    765 	if (!is_tc)
    766 	{
    767 		*is_ours = 0;
    768 		return NULL;
    769 	}
    770 
    771 	/* OK, it's probably ours. */
    772 	*is_ours = 1;
    773 
    774 	p = pcap_create_common(ebuf, sizeof (struct pcap_tc));
    775 	if (p == NULL)
    776 		return NULL;
    777 
    778 	p->activate_op = TcActivate;
    779 	/*
    780 	 * Set these up front, so that, even if our client tries
    781 	 * to set non-blocking mode before we're activated, or
    782 	 * query the state of non-blocking mode, they get an error,
    783 	 * rather than having the non-blocking mode option set
    784 	 * for use later.
    785 	 */
    786 	p->getnonblock_op = TcGetNonBlock;
    787 	p->setnonblock_op = TcSetNonBlock;
    788 	return p;
    789 }
    790 
    791 static int TcSetDatalink(pcap_t *p, int dlt)
    792 {
    793 	/*
    794 	 * We don't have to do any work here; pcap_set_datalink() checks
    795 	 * whether the value is in the list of DLT_ values we
    796 	 * supplied, so we don't have to, and, if it is valid, sets
    797 	 * p->linktype to the new value; we don't have to do anything
    798 	 * in hardware, we just use what's in p->linktype.
    799 	 *
    800 	 * We do have to have a routine, however, so that pcap_set_datalink()
    801 	 * doesn't think we don't support setting the link-layer header
    802 	 * type at all.
    803 	 */
    804 	return 0;
    805 }
    806 
    807 static int TcGetNonBlock(pcap_t *p)
    808 {
    809 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    810 	    "Non-blocking mode isn't supported for TurboCap ports");
    811 	return -1;
    812 }
    813 
    814 static int TcSetNonBlock(pcap_t *p, int nonblock)
    815 {
    816 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    817 	    "Non-blocking mode isn't supported for TurboCap ports");
    818 	return -1;
    819 }
    820 
    821 static void TcCleanup(pcap_t *p)
    822 {
    823 	struct pcap_tc *pt = p->priv;
    824 
    825 	if (pt->TcPacketsBuffer != NULL)
    826 	{
    827 		g_TcFunctions.PacketsBufferDestroy(pt->TcPacketsBuffer);
    828 		pt->TcPacketsBuffer = NULL;
    829 	}
    830 	if (pt->TcInstance != NULL)
    831 	{
    832 		/*
    833 		 * here we do not check for the error values
    834 		 */
    835 		g_TcFunctions.InstanceClose(pt->TcInstance);
    836 		pt->TcInstance = NULL;
    837 	}
    838 
    839 	if (pt->PpiPacket != NULL)
    840 	{
    841 		free(pt->PpiPacket);
    842 		pt->PpiPacket = NULL;
    843 	}
    844 
    845 	pcap_cleanup_live_common(p);
    846 }
    847 
    848 /* Send a packet to the network */
    849 static int TcInject(pcap_t *p, const void *buf, size_t size)
    850 {
    851 	struct pcap_tc *pt = p->priv;
    852 	TC_STATUS status;
    853 	TC_PACKETS_BUFFER buffer;
    854 	TC_PACKET_HEADER header;
    855 
    856 	if (size >= 0xFFFF)
    857 	{
    858 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: the TurboCap API does not support packets larger than 64k");
    859 		return -1;
    860 	}
    861 
    862 	status = g_TcFunctions.PacketsBufferCreate(sizeof(TC_PACKET_HEADER) + TC_ALIGN_USHORT_TO_64BIT((USHORT)size), &buffer);
    863 
    864 	if (status != TC_SUCCESS)
    865 	{
    866 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcPacketsBufferCreate failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
    867 		return -1;
    868 	}
    869 
    870 	/*
    871 	 * we assume that the packet is without the checksum, as common with WinPcap
    872 	 */
    873 	memset(&header, 0, sizeof(header));
    874 
    875 	header.Length = (USHORT)size;
    876 	header.CapturedLength = header.Length;
    877 
    878 	status = g_TcFunctions.PacketsBufferCommitNextPacket(buffer, &header, (PVOID)buf);
    879 
    880 	if (status == TC_SUCCESS)
    881 	{
    882 		status = g_TcFunctions.InstanceTransmitPackets(pt->TcInstance, buffer);
    883 
    884 		if (status != TC_SUCCESS)
    885 		{
    886 			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcInstanceTransmitPackets failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
    887 		}
    888 	}
    889 	else
    890 	{
    891 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcPacketsBufferCommitNextPacket failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
    892 	}
    893 
    894 	g_TcFunctions.PacketsBufferDestroy(buffer);
    895 
    896 	if (status != TC_SUCCESS)
    897 	{
    898 		return -1;
    899 	}
    900 	else
    901 	{
    902 		return 0;
    903 	}
    904 }
    905 
    906 static int TcRead(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
    907 {
    908 	struct pcap_tc *pt = p->priv;
    909 	TC_STATUS status;
    910 	int n = 0;
    911 
    912 	/*
    913 	 * Has "pcap_breakloop()" been called?
    914 	 */
    915 	if (p->break_loop)
    916 	{
    917 		/*
    918 		 * Yes - clear the flag that indicates that it
    919 		 * has, and return -2 to indicate that we were
    920 		 * told to break out of the loop.
    921 		 */
    922 		p->break_loop = 0;
    923 		return -2;
    924 	}
    925 
    926 	if (pt->TcPacketsBuffer == NULL)
    927 	{
    928 		status = g_TcFunctions.InstanceReceivePackets(pt->TcInstance, &pt->TcPacketsBuffer);
    929 		if (status != TC_SUCCESS)
    930 		{
    931 			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error, TcInstanceReceivePackets failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
    932 			return -1;
    933 		}
    934 	}
    935 
    936 	while (TRUE)
    937 	{
    938 		struct pcap_pkthdr hdr;
    939 		TC_PACKET_HEADER tcHeader;
    940 		PVOID data;
    941 		ULONG filterResult;
    942 
    943 		/*
    944 		 * Has "pcap_breakloop()" been called?
    945 		 * If so, return immediately - if we haven't read any
    946 		 * packets, clear the flag and return -2 to indicate
    947 		 * that we were told to break out of the loop, otherwise
    948 		 * leave the flag set, so that the *next* call will break
    949 		 * out of the loop without having read any packets, and
    950 		 * return the number of packets we've processed so far.
    951 		 */
    952 		if (p->break_loop)
    953 		{
    954 			if (n == 0)
    955 			{
    956 				p->break_loop = 0;
    957 				return -2;
    958 			}
    959 			else
    960 			{
    961 				return n;
    962 			}
    963 		}
    964 
    965 		if (pt->TcPacketsBuffer == NULL)
    966 		{
    967 			break;
    968 		}
    969 
    970 		status = g_TcFunctions.PacketsBufferQueryNextPacket(pt->TcPacketsBuffer, &tcHeader, &data);
    971 
    972 		if (status == TC_ERROR_END_OF_BUFFER)
    973 		{
    974 			g_TcFunctions.PacketsBufferDestroy(pt->TcPacketsBuffer);
    975 			pt->TcPacketsBuffer = NULL;
    976 			break;
    977 		}
    978 
    979 		if (status != TC_SUCCESS)
    980 		{
    981 			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error, TcPacketsBufferQueryNextPacket failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
    982 			return -1;
    983 		}
    984 
    985 		/* No underlaying filtering system. We need to filter on our own */
    986 		if (p->fcode.bf_insns)
    987 		{
    988 			filterResult = bpf_filter(p->fcode.bf_insns, data, tcHeader.Length, tcHeader.CapturedLength);
    989 
    990 			if (filterResult == 0)
    991 			{
    992 				continue;
    993 			}
    994 
    995 			if (filterResult > tcHeader.CapturedLength)
    996 			{
    997 				filterResult = tcHeader.CapturedLength;
    998 			}
    999 		}
   1000 		else
   1001 		{
   1002 			filterResult = tcHeader.CapturedLength;
   1003 		}
   1004 
   1005 		pt->TcAcceptedCount ++;
   1006 
   1007 		hdr.ts.tv_sec = (bpf_u_int32)(tcHeader.Timestamp / (ULONGLONG)(1000  * 1000 * 1000));
   1008 		hdr.ts.tv_usec = (bpf_u_int32)((tcHeader.Timestamp % (ULONGLONG)(1000  * 1000 * 1000)) / 1000);
   1009 
   1010 		if (p->linktype == DLT_EN10MB)
   1011 		{
   1012 			hdr.caplen = filterResult;
   1013 			hdr.len = tcHeader.Length;
   1014 			(*callback)(user, &hdr, data);
   1015 		}
   1016 		else
   1017 		{
   1018 			PPPI_HEADER pPpiHeader = (PPPI_HEADER)pt->PpiPacket;
   1019 			PVOID data2 = pPpiHeader + 1;
   1020 
   1021 			pPpiHeader->AggregationField.InterfaceId = TC_PH_FLAGS_RX_PORT_ID(tcHeader.Flags);
   1022 			pPpiHeader->Dot3Field.Errors = tcHeader.Errors;
   1023 			if (tcHeader.Flags & TC_PH_FLAGS_CHECKSUM)
   1024 			{
   1025 				pPpiHeader->Dot3Field.Flags = PPI_FLD_802_3_EXT_FLAG_FCS_PRESENT;
   1026 			}
   1027 			else
   1028 			{
   1029 				pPpiHeader->Dot3Field.Flags = 0;
   1030 			}
   1031 
   1032 			if (filterResult <= MAX_TC_PACKET_SIZE)
   1033 			{
   1034 				memcpy(data2, data, filterResult);
   1035 				hdr.caplen = sizeof(PPI_HEADER) + filterResult;
   1036 				hdr.len = sizeof(PPI_HEADER) + tcHeader.Length;
   1037 			}
   1038 			else
   1039 			{
   1040 				memcpy(data2, data, MAX_TC_PACKET_SIZE);
   1041 				hdr.caplen = sizeof(PPI_HEADER) + MAX_TC_PACKET_SIZE;
   1042 				hdr.len = sizeof(PPI_HEADER) + tcHeader.Length;
   1043 			}
   1044 
   1045 			(*callback)(user, &hdr, pt->PpiPacket);
   1046 
   1047 		}
   1048 
   1049 		if (++n >= cnt && cnt > 0)
   1050 		{
   1051 			return n;
   1052 		}
   1053 	}
   1054 
   1055 	return n;
   1056 }
   1057 
   1058 static int
   1059 TcStats(pcap_t *p, struct pcap_stat *ps)
   1060 {
   1061 	struct pcap_tc *pt = p->priv;
   1062 	TC_STATISTICS statistics;
   1063 	TC_STATUS status;
   1064 	ULONGLONG counter;
   1065 	struct pcap_stat s;
   1066 
   1067 	status = g_TcFunctions.InstanceQueryStatistics(pt->TcInstance, &statistics);
   1068 
   1069 	if (status != TC_SUCCESS)
   1070 	{
   1071 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcInstanceQueryStatistics: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
   1072 		return -1;
   1073 	}
   1074 
   1075 	memset(&s, 0, sizeof(s));
   1076 
   1077 	status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_TOTAL_RX_PACKETS, &counter);
   1078 	if (status != TC_SUCCESS)
   1079 	{
   1080 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
   1081 		return -1;
   1082 	}
   1083 	if (counter <= (ULONGLONG)0xFFFFFFFF)
   1084 	{
   1085 		s.ps_recv = (ULONG)counter;
   1086 	}
   1087 	else
   1088 	{
   1089 		s.ps_recv = 0xFFFFFFFF;
   1090 	}
   1091 
   1092 	status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_RX_DROPPED_PACKETS, &counter);
   1093 	if (status != TC_SUCCESS)
   1094 	{
   1095 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
   1096 		return -1;
   1097 	}
   1098 	if (counter <= (ULONGLONG)0xFFFFFFFF)
   1099 	{
   1100 		s.ps_ifdrop = (ULONG)counter;
   1101 		s.ps_drop = (ULONG)counter;
   1102 	}
   1103 	else
   1104 	{
   1105 		s.ps_ifdrop = 0xFFFFFFFF;
   1106 		s.ps_drop = 0xFFFFFFFF;
   1107 	}
   1108 
   1109 #if defined(_WIN32) && defined(ENABLE_REMOTE)
   1110 	s.ps_capt = pt->TcAcceptedCount;
   1111 #endif
   1112 	*ps = s;
   1113 
   1114 	return 0;
   1115 }
   1116 
   1117 
   1118 /*
   1119  * We filter at user level, since the kernel driver does't process the packets
   1120  */
   1121 static int
   1122 TcSetFilter(pcap_t *p, struct bpf_program *fp)
   1123 {
   1124 	if(!fp)
   1125 	{
   1126 		strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
   1127 		return -1;
   1128 	}
   1129 
   1130 	/* Install a user level filter */
   1131 	if (install_bpf_program(p, fp) < 0)
   1132 	{
   1133 		return -1;
   1134 	}
   1135 
   1136 	return 0;
   1137 }
   1138 
   1139 #ifdef _WIN32
   1140 static struct pcap_stat *
   1141 TcStatsEx(pcap_t *p, int *pcap_stat_size)
   1142 {
   1143 	struct pcap_tc *pt = p->priv;
   1144 	TC_STATISTICS statistics;
   1145 	TC_STATUS status;
   1146 	ULONGLONG counter;
   1147 
   1148 	*pcap_stat_size = sizeof (p->stat);
   1149 
   1150 	status = g_TcFunctions.InstanceQueryStatistics(pt->TcInstance, &statistics);
   1151 
   1152 	if (status != TC_SUCCESS)
   1153 	{
   1154 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcInstanceQueryStatistics: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
   1155 		return NULL;
   1156 	}
   1157 
   1158 	memset(&p->stat, 0, sizeof(p->stat));
   1159 
   1160 	status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_TOTAL_RX_PACKETS, &counter);
   1161 	if (status != TC_SUCCESS)
   1162 	{
   1163 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
   1164 		return NULL;
   1165 	}
   1166 	if (counter <= (ULONGLONG)0xFFFFFFFF)
   1167 	{
   1168 		p->stat.ps_recv = (ULONG)counter;
   1169 	}
   1170 	else
   1171 	{
   1172 		p->stat.ps_recv = 0xFFFFFFFF;
   1173 	}
   1174 
   1175 	status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_RX_DROPPED_PACKETS, &counter);
   1176 	if (status != TC_SUCCESS)
   1177 	{
   1178 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
   1179 		return NULL;
   1180 	}
   1181 	if (counter <= (ULONGLONG)0xFFFFFFFF)
   1182 	{
   1183 		p->stat.ps_ifdrop = (ULONG)counter;
   1184 		p->stat.ps_drop = (ULONG)counter;
   1185 	}
   1186 	else
   1187 	{
   1188 		p->stat.ps_ifdrop = 0xFFFFFFFF;
   1189 		p->stat.ps_drop = 0xFFFFFFFF;
   1190 	}
   1191 
   1192 #if defined(_WIN32) && defined(ENABLE_REMOTE)
   1193 	p->stat.ps_capt = pt->TcAcceptedCount;
   1194 #endif
   1195 
   1196 	return &p->stat;
   1197 }
   1198 
   1199 /* Set the dimension of the kernel-level capture buffer */
   1200 static int
   1201 TcSetBuff(pcap_t *p, int dim)
   1202 {
   1203 	/*
   1204 	 * XXX turbocap has an internal way of managing buffers.
   1205 	 * And at the moment it's not configurable, so we just
   1206 	 * silently ignore the request to set the buffer.
   1207 	 */
   1208 	return 0;
   1209 }
   1210 
   1211 static int
   1212 TcSetMode(pcap_t *p, int mode)
   1213 {
   1214 	if (mode != MODE_CAPT)
   1215 	{
   1216 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Mode %u not supported by TurboCap devices. TurboCap only supports capture.", mode);
   1217 		return -1;
   1218 	}
   1219 
   1220 	return 0;
   1221 }
   1222 
   1223 static int
   1224 TcSetMinToCopy(pcap_t *p, int size)
   1225 {
   1226 	struct pcap_tc *pt = p->priv;
   1227 	TC_STATUS status;
   1228 
   1229 	if (size < 0)
   1230 	{
   1231 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Mintocopy cannot be less than 0.");
   1232 		return -1;
   1233 	}
   1234 
   1235 	status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_MINTOCOPY, (ULONG)size);
   1236 
   1237 	if (status != TC_SUCCESS)
   1238 	{
   1239 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error setting the mintocopy: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
   1240 	}
   1241 
   1242 	return 0;
   1243 }
   1244 
   1245 static HANDLE
   1246 TcGetReceiveWaitHandle(pcap_t *p)
   1247 {
   1248 	struct pcap_tc *pt = p->priv;
   1249 
   1250 	return g_TcFunctions.InstanceGetReceiveWaitHandle(pt->TcInstance);
   1251 }
   1252 
   1253 static int
   1254 TcOidGetRequest(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_, size_t *lenp _U_)
   1255 {
   1256 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
   1257 	    "An OID get request cannot be performed on a TurboCap device");
   1258 	return PCAP_ERROR;
   1259 }
   1260 
   1261 static int
   1262 TcOidSetRequest(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
   1263     size_t *lenp _U_)
   1264 {
   1265 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
   1266 	    "An OID set request cannot be performed on a TurboCap device");
   1267 	return PCAP_ERROR;
   1268 }
   1269 
   1270 static u_int
   1271 TcSendqueueTransmit(pcap_t *p, pcap_send_queue *queue _U_, int sync _U_)
   1272 {
   1273 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
   1274 	    "Packets cannot be bulk transmitted on a TurboCap device");
   1275 	return 0;
   1276 }
   1277 
   1278 static int
   1279 TcSetUserBuffer(pcap_t *p, int size _U_)
   1280 {
   1281 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
   1282 	    "The user buffer cannot be set on a TurboCap device");
   1283 	return -1;
   1284 }
   1285 
   1286 static int
   1287 TcLiveDump(pcap_t *p, char *filename _U_, int maxsize _U_, int maxpacks _U_)
   1288 {
   1289 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
   1290 	    "Live packet dumping cannot be performed on a TurboCap device");
   1291 	return -1;
   1292 }
   1293 
   1294 static int
   1295 TcLiveDumpEnded(pcap_t *p, int sync _U_)
   1296 {
   1297 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
   1298 	    "Live packet dumping cannot be performed on a TurboCap device");
   1299 	return -1;
   1300 }
   1301 
   1302 static PAirpcapHandle
   1303 TcGetAirPcapHandle(pcap_t *p _U_)
   1304 {
   1305 	return NULL;
   1306 }
   1307 #endif
   1308