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, char *errbuf);
    124 static int TcSetNonBlock(pcap_t *p, int nonblock, char *errbuf);
    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_t **alldevsp, 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 (*alldevsp == NULL)
    480 				{
    481 					*alldevsp = dev;
    482 				}
    483 				else
    484 				{
    485 					for(cursor = *alldevsp; cursor->next != NULL; cursor = cursor->next);
    486 					cursor->next = dev;
    487 				}
    488 			}
    489 		}
    490 
    491 		if (numPorts > 0)
    492 		{
    493 			/*
    494 			 * ignore the result here
    495 			 */
    496 			status = g_TcFunctions.FreePortList(pPorts);
    497 		}
    498 
    499 	}while(FALSE);
    500 
    501 	return result;
    502 }
    503 
    504 static pcap_if_t* TcCreatePcapIfFromPort(TC_PORT port)
    505 {
    506 	CHAR *name;
    507 	CHAR *description;
    508 	pcap_if_t *newIf = NULL;
    509 
    510 	newIf = (pcap_if_t*)malloc(sizeof(*newIf));
    511 	if (newIf == NULL)
    512 	{
    513 		return NULL;
    514 	}
    515 
    516 	memset(newIf, 0, sizeof(*newIf));
    517 
    518 	name = g_TcFunctions.PortGetName(port);
    519 	description = g_TcFunctions.PortGetDescription(port);
    520 
    521 	newIf->name = (char*)malloc(strlen(name) + 1);
    522 	if (newIf->name == NULL)
    523 	{
    524 		free(newIf);
    525 		return NULL;
    526 	}
    527 
    528 	newIf->description = (char*)malloc(strlen(description) + 1);
    529 	if (newIf->description == NULL)
    530 	{
    531 		free(newIf->name);
    532 		free(newIf);
    533 		return NULL;
    534 	}
    535 
    536 	strcpy(newIf->name, name);
    537 	strcpy(newIf->description, description);
    538 
    539 	newIf->addresses = NULL;
    540 	newIf->next = NULL;
    541 	newIf->flags = 0;
    542 
    543 	return newIf;
    544 
    545 }
    546 
    547 static int
    548 TcActivate(pcap_t *p)
    549 {
    550 	struct pcap_tc *pt = p->priv;
    551 	TC_STATUS status;
    552 	ULONG timeout;
    553 	PPPI_HEADER pPpiHeader;
    554 
    555 	if (p->opt.rfmon)
    556 	{
    557 		/*
    558 		 * No monitor mode on Tc cards; they're Ethernet
    559 		 * capture adapters.
    560 		 */
    561 		return PCAP_ERROR_RFMON_NOTSUP;
    562 	}
    563 
    564 	pt->PpiPacket = malloc(sizeof(PPI_HEADER) + MAX_TC_PACKET_SIZE);
    565 
    566 	if (pt->PpiPacket == NULL)
    567 	{
    568 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error allocating memory");
    569 		return PCAP_ERROR;
    570 	}
    571 
    572 	/*
    573 	 * Initialize the PPI fixed fields
    574 	 */
    575 	pPpiHeader = (PPPI_HEADER)pt->PpiPacket;
    576 	pPpiHeader->PacketHeader.PphDlt = DLT_EN10MB;
    577 	pPpiHeader->PacketHeader.PphLength = sizeof(PPI_HEADER);
    578 	pPpiHeader->PacketHeader.PphFlags = 0;
    579 	pPpiHeader->PacketHeader.PphVersion = 0;
    580 
    581 	pPpiHeader->AggregationFieldHeader.PfhLength = sizeof(PPI_FIELD_AGGREGATION_EXTENSION);
    582 	pPpiHeader->AggregationFieldHeader.PfhType = PPI_FIELD_TYPE_AGGREGATION_EXTENSION;
    583 
    584 	pPpiHeader->Dot3FieldHeader.PfhLength = sizeof(PPI_FIELD_802_3_EXTENSION);
    585 	pPpiHeader->Dot3FieldHeader.PfhType = PPI_FIELD_TYPE_802_3_EXTENSION;
    586 
    587 	status = g_TcFunctions.InstanceOpenByName(p->opt.device, &pt->TcInstance);
    588 
    589 	if (status != TC_SUCCESS)
    590 	{
    591 		/* Adapter detected but we are not able to open it. Return failure. */
    592 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening TurboCap adapter: %s", g_TcFunctions.StatusGetString(status));
    593 		return PCAP_ERROR;
    594 	}
    595 
    596 	p->linktype = DLT_EN10MB;
    597 	p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
    598 	/*
    599 	 * If that fails, just leave the list empty.
    600 	 */
    601 	if (p->dlt_list != NULL) {
    602 		p->dlt_list[0] = DLT_EN10MB;
    603 		p->dlt_list[1] = DLT_PPI;
    604 		p->dlt_count = 2;
    605 	}
    606 
    607 	/*
    608 	 * ignore promiscuous mode
    609 	 * p->opt.promisc
    610 	 */
    611 
    612 
    613 	/*
    614 	 * ignore all the buffer sizes
    615 	 */
    616 
    617 	/*
    618 	 * enable reception
    619 	 */
    620 	status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_RX_STATUS, 1);
    621 
    622 	if (status != TC_SUCCESS)
    623 	{
    624 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error enabling reception on a TurboCap instance: %s", g_TcFunctions.StatusGetString(status));
    625 		goto bad;
    626 	}
    627 
    628 	/*
    629 	 * enable transmission
    630 	 */
    631 	status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_TX_STATUS, 1);
    632 	/*
    633 	 * Ignore the error here.
    634 	 */
    635 
    636 	p->inject_op = TcInject;
    637 	/*
    638 	 * if the timeout is -1, it means immediate return, no timeout
    639 	 * if the timeout is 0, it means INFINITE
    640 	 */
    641 
    642 	if (p->opt.timeout == 0)
    643 	{
    644 		timeout = 0xFFFFFFFF;
    645 	}
    646 	else
    647 	if (p->opt.timeout < 0)
    648 	{
    649 		/*
    650 		 *  we insert a minimal timeout here
    651 		 */
    652 		timeout = 10;
    653 	}
    654 	else
    655 	{
    656 		timeout = p->opt.timeout;
    657 	}
    658 
    659 	status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_READ_TIMEOUT, timeout);
    660 
    661 	if (status != TC_SUCCESS)
    662 	{
    663 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error setting the read timeout a TurboCap instance: %s", g_TcFunctions.StatusGetString(status));
    664 		goto bad;
    665 	}
    666 
    667 	p->read_op = TcRead;
    668 	p->setfilter_op = TcSetFilter;
    669 	p->setdirection_op = NULL;	/* Not implemented. */
    670 	p->set_datalink_op = TcSetDatalink;
    671 	p->getnonblock_op = TcGetNonBlock;
    672 	p->setnonblock_op = TcSetNonBlock;
    673 	p->stats_op = TcStats;
    674 #ifdef _WIN32
    675 	p->stats_ex_op = TcStatsEx;
    676 	p->setbuff_op = TcSetBuff;
    677 	p->setmode_op = TcSetMode;
    678 	p->setmintocopy_op = TcSetMinToCopy;
    679 	p->getevent_op = TcGetReceiveWaitHandle;
    680 	p->oid_get_request_op = TcOidGetRequest;
    681 	p->oid_set_request_op = TcOidSetRequest;
    682 	p->sendqueue_transmit_op = TcSendqueueTransmit;
    683 	p->setuserbuffer_op = TcSetUserBuffer;
    684 	p->live_dump_op = TcLiveDump;
    685 	p->live_dump_ended_op = TcLiveDumpEnded;
    686 	p->get_airpcap_handle_op = TcGetAirPcapHandle;
    687 #else
    688 	p->selectable_fd = -1;
    689 #endif
    690 
    691 	p->cleanup_op = TcCleanup;
    692 
    693 	return 0;
    694 bad:
    695 	TcCleanup(p);
    696 	return PCAP_ERROR;
    697 }
    698 
    699 pcap_t *
    700 TcCreate(const char *device, char *ebuf, int *is_ours)
    701 {
    702 	ULONG numPorts;
    703 	PTC_PORT pPorts = NULL;
    704 	TC_STATUS status;
    705 	int is_tc;
    706 	ULONG i;
    707 	pcap_t *p;
    708 
    709 	if (LoadTcFunctions() != TC_API_LOADED)
    710 	{
    711 		/*
    712 		 * XXX - report this as an error rather than as
    713 		 * "not a TurboCap device"?
    714 		 */
    715 		*is_ours = 0;
    716 		return NULL;
    717 	}
    718 
    719 	/*
    720 	 * enumerate the ports, and add them to the list
    721 	 */
    722 	status = g_TcFunctions.QueryPortList(&pPorts, &numPorts);
    723 
    724 	if (status != TC_SUCCESS)
    725 	{
    726 		/*
    727 		 * XXX - report this as an error rather than as
    728 		 * "not a TurboCap device"?
    729 		 */
    730 		*is_ours = 0;
    731 		return NULL;
    732 	}
    733 
    734 	is_tc = FALSE;
    735 	for (i = 0; i < numPorts; i++)
    736 	{
    737 		if (strcmp(g_TcFunctions.PortGetName(pPorts[i]), device) == 0)
    738 		{
    739 			is_tc = TRUE;
    740 			break;
    741 		}
    742 	}
    743 
    744 	if (numPorts > 0)
    745 	{
    746 		/*
    747 		 * ignore the result here
    748 		 */
    749 		(void)g_TcFunctions.FreePortList(pPorts);
    750 	}
    751 
    752 	if (!is_tc)
    753 	{
    754 		*is_ours = 0;
    755 		return NULL;
    756 	}
    757 
    758 	/* OK, it's probably ours. */
    759 	*is_ours = 1;
    760 
    761 	p = pcap_create_common(ebuf, sizeof (struct pcap_tc));
    762 	if (p == NULL)
    763 		return NULL;
    764 
    765 	p->activate_op = TcActivate;
    766 	return p;
    767 }
    768 
    769 static int TcSetDatalink(pcap_t *p, int dlt)
    770 {
    771 	/*
    772 	 * always return 0, as the check is done by pcap_set_datalink
    773 	 */
    774 	return 0;
    775 }
    776 
    777 static int TcGetNonBlock(pcap_t *p, char *errbuf)
    778 {
    779 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    780 		    "Getting the non blocking status is not available for TurboCap ports");
    781 	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
    782 		    "Getting the non blocking status is not available for TurboCap ports");
    783 		return -1;
    784 
    785 }
    786 static int TcSetNonBlock(pcap_t *p, int nonblock, char *errbuf)
    787 {
    788 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    789 		    "Setting the non blocking status is not available for TurboCap ports");
    790 	pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
    791 		    "Setting the non blocking status is not available for TurboCap ports");
    792 		return -1;
    793 }
    794 
    795 
    796 static void TcCleanup(pcap_t *p)
    797 {
    798 	struct pcap_tc *pt = p->priv;
    799 
    800 	if (pt->TcPacketsBuffer != NULL)
    801 	{
    802 		g_TcFunctions.PacketsBufferDestroy(pt->TcPacketsBuffer);
    803 		pt->TcPacketsBuffer = NULL;
    804 	}
    805 	if (pt->TcInstance != NULL)
    806 	{
    807 		/*
    808 		 * here we do not check for the error values
    809 		 */
    810 		g_TcFunctions.InstanceClose(pt->TcInstance);
    811 		pt->TcInstance = NULL;
    812 	}
    813 
    814 	if (pt->PpiPacket != NULL)
    815 	{
    816 		free(pt->PpiPacket);
    817 		pt->PpiPacket = NULL;
    818 	}
    819 
    820 	pcap_cleanup_live_common(p);
    821 }
    822 
    823 /* Send a packet to the network */
    824 static int TcInject(pcap_t *p, const void *buf, size_t size)
    825 {
    826 	struct pcap_tc *pt = p->priv;
    827 	TC_STATUS status;
    828 	TC_PACKETS_BUFFER buffer;
    829 	TC_PACKET_HEADER header;
    830 
    831 	if (size >= 0xFFFF)
    832 	{
    833 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: the TurboCap API does not support packets larger than 64k");
    834 		return -1;
    835 	}
    836 
    837 	status = g_TcFunctions.PacketsBufferCreate(sizeof(TC_PACKET_HEADER) + TC_ALIGN_USHORT_TO_64BIT((USHORT)size), &buffer);
    838 
    839 	if (status != TC_SUCCESS)
    840 	{
    841 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcPacketsBufferCreate failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
    842 		return -1;
    843 	}
    844 
    845 	/*
    846 	 * we assume that the packet is without the checksum, as common with WinPcap
    847 	 */
    848 	memset(&header, 0, sizeof(header));
    849 
    850 	header.Length = (USHORT)size;
    851 	header.CapturedLength = header.Length;
    852 
    853 	status = g_TcFunctions.PacketsBufferCommitNextPacket(buffer, &header, (PVOID)buf);
    854 
    855 	if (status == TC_SUCCESS)
    856 	{
    857 		status = g_TcFunctions.InstanceTransmitPackets(pt->TcInstance, buffer);
    858 
    859 		if (status != TC_SUCCESS)
    860 		{
    861 			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcInstanceTransmitPackets failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
    862 		}
    863 	}
    864 	else
    865 	{
    866 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcPacketsBufferCommitNextPacket failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
    867 	}
    868 
    869 	g_TcFunctions.PacketsBufferDestroy(buffer);
    870 
    871 	if (status != TC_SUCCESS)
    872 	{
    873 		return -1;
    874 	}
    875 	else
    876 	{
    877 		return 0;
    878 	}
    879 }
    880 
    881 static int TcRead(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
    882 {
    883 	struct pcap_tc *pt = p->priv;
    884 	TC_STATUS status;
    885 	int n = 0;
    886 
    887 	/*
    888 	 * Has "pcap_breakloop()" been called?
    889 	 */
    890 	if (p->break_loop)
    891 	{
    892 		/*
    893 		 * Yes - clear the flag that indicates that it
    894 		 * has, and return -2 to indicate that we were
    895 		 * told to break out of the loop.
    896 		 */
    897 		p->break_loop = 0;
    898 		return -2;
    899 	}
    900 
    901 	if (pt->TcPacketsBuffer == NULL)
    902 	{
    903 		status = g_TcFunctions.InstanceReceivePackets(pt->TcInstance, &pt->TcPacketsBuffer);
    904 		if (status != TC_SUCCESS)
    905 		{
    906 			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error, TcInstanceReceivePackets failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
    907 			return -1;
    908 		}
    909 	}
    910 
    911 	while (TRUE)
    912 	{
    913 		struct pcap_pkthdr hdr;
    914 		TC_PACKET_HEADER tcHeader;
    915 		PVOID data;
    916 		ULONG filterResult;
    917 
    918 		/*
    919 		 * Has "pcap_breakloop()" been called?
    920 		 * If so, return immediately - if we haven't read any
    921 		 * packets, clear the flag and return -2 to indicate
    922 		 * that we were told to break out of the loop, otherwise
    923 		 * leave the flag set, so that the *next* call will break
    924 		 * out of the loop without having read any packets, and
    925 		 * return the number of packets we've processed so far.
    926 		 */
    927 		if (p->break_loop)
    928 		{
    929 			if (n == 0)
    930 			{
    931 				p->break_loop = 0;
    932 				return -2;
    933 			}
    934 			else
    935 			{
    936 				return n;
    937 			}
    938 		}
    939 
    940 		if (pt->TcPacketsBuffer == NULL)
    941 		{
    942 			break;
    943 		}
    944 
    945 		status = g_TcFunctions.PacketsBufferQueryNextPacket(pt->TcPacketsBuffer, &tcHeader, &data);
    946 
    947 		if (status == TC_ERROR_END_OF_BUFFER)
    948 		{
    949 			g_TcFunctions.PacketsBufferDestroy(pt->TcPacketsBuffer);
    950 			pt->TcPacketsBuffer = NULL;
    951 			break;
    952 		}
    953 
    954 		if (status != TC_SUCCESS)
    955 		{
    956 			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error, TcPacketsBufferQueryNextPacket failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
    957 			return -1;
    958 		}
    959 
    960 		/* No underlaying filtering system. We need to filter on our own */
    961 		if (p->fcode.bf_insns)
    962 		{
    963 			filterResult = bpf_filter(p->fcode.bf_insns, data, tcHeader.Length, tcHeader.CapturedLength);
    964 
    965 			if (filterResult == 0)
    966 			{
    967 				continue;
    968 			}
    969 
    970 			if (filterResult > tcHeader.CapturedLength)
    971 			{
    972 				filterResult = tcHeader.CapturedLength;
    973 			}
    974 		}
    975 		else
    976 		{
    977 			filterResult = tcHeader.CapturedLength;
    978 		}
    979 
    980 		pt->TcAcceptedCount ++;
    981 
    982 		hdr.ts.tv_sec = (bpf_u_int32)(tcHeader.Timestamp / (ULONGLONG)(1000  * 1000 * 1000));
    983 		hdr.ts.tv_usec = (bpf_u_int32)((tcHeader.Timestamp % (ULONGLONG)(1000  * 1000 * 1000)) / 1000);
    984 
    985 		if (p->linktype == DLT_EN10MB)
    986 		{
    987 			hdr.caplen = filterResult;
    988 			hdr.len = tcHeader.Length;
    989 			(*callback)(user, &hdr, data);
    990 		}
    991 		else
    992 		{
    993 			PPPI_HEADER pPpiHeader = (PPPI_HEADER)pt->PpiPacket;
    994 			PVOID data2 = pPpiHeader + 1;
    995 
    996 			pPpiHeader->AggregationField.InterfaceId = TC_PH_FLAGS_RX_PORT_ID(tcHeader.Flags);
    997 			pPpiHeader->Dot3Field.Errors = tcHeader.Errors;
    998 			if (tcHeader.Flags & TC_PH_FLAGS_CHECKSUM)
    999 			{
   1000 				pPpiHeader->Dot3Field.Flags = PPI_FLD_802_3_EXT_FLAG_FCS_PRESENT;
   1001 			}
   1002 			else
   1003 			{
   1004 				pPpiHeader->Dot3Field.Flags = 0;
   1005 			}
   1006 
   1007 			if (filterResult <= MAX_TC_PACKET_SIZE)
   1008 			{
   1009 				memcpy(data2, data, filterResult);
   1010 				hdr.caplen = sizeof(PPI_HEADER) + filterResult;
   1011 				hdr.len = sizeof(PPI_HEADER) + tcHeader.Length;
   1012 			}
   1013 			else
   1014 			{
   1015 				memcpy(data2, data, MAX_TC_PACKET_SIZE);
   1016 				hdr.caplen = sizeof(PPI_HEADER) + MAX_TC_PACKET_SIZE;
   1017 				hdr.len = sizeof(PPI_HEADER) + tcHeader.Length;
   1018 			}
   1019 
   1020 			(*callback)(user, &hdr, pt->PpiPacket);
   1021 
   1022 		}
   1023 
   1024 		if (++n >= cnt && cnt > 0)
   1025 		{
   1026 			return n;
   1027 		}
   1028 	}
   1029 
   1030 	return n;
   1031 }
   1032 
   1033 static int
   1034 TcStats(pcap_t *p, struct pcap_stat *ps)
   1035 {
   1036 	struct pcap_tc *pt = p->priv;
   1037 	TC_STATISTICS statistics;
   1038 	TC_STATUS status;
   1039 	ULONGLONG counter;
   1040 	struct pcap_stat s;
   1041 
   1042 	status = g_TcFunctions.InstanceQueryStatistics(pt->TcInstance, &statistics);
   1043 
   1044 	if (status != TC_SUCCESS)
   1045 	{
   1046 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcInstanceQueryStatistics: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
   1047 		return -1;
   1048 	}
   1049 
   1050 	memset(&s, 0, sizeof(s));
   1051 
   1052 	status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_TOTAL_RX_PACKETS, &counter);
   1053 	if (status != TC_SUCCESS)
   1054 	{
   1055 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
   1056 		return -1;
   1057 	}
   1058 	if (counter <= (ULONGLONG)0xFFFFFFFF)
   1059 	{
   1060 		s.ps_recv = (ULONG)counter;
   1061 	}
   1062 	else
   1063 	{
   1064 		s.ps_recv = 0xFFFFFFFF;
   1065 	}
   1066 
   1067 	status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_RX_DROPPED_PACKETS, &counter);
   1068 	if (status != TC_SUCCESS)
   1069 	{
   1070 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
   1071 		return -1;
   1072 	}
   1073 	if (counter <= (ULONGLONG)0xFFFFFFFF)
   1074 	{
   1075 		s.ps_ifdrop = (ULONG)counter;
   1076 		s.ps_drop = (ULONG)counter;
   1077 	}
   1078 	else
   1079 	{
   1080 		s.ps_ifdrop = 0xFFFFFFFF;
   1081 		s.ps_drop = 0xFFFFFFFF;
   1082 	}
   1083 
   1084 #if defined(_WIN32) && defined(HAVE_REMOTE)
   1085 	s.ps_capt = pt->TcAcceptedCount;
   1086 #endif
   1087 	*ps = s;
   1088 
   1089 	return 0;
   1090 }
   1091 
   1092 
   1093 /*
   1094  * We filter at user level, since the kernel driver does't process the packets
   1095  */
   1096 static int
   1097 TcSetFilter(pcap_t *p, struct bpf_program *fp)
   1098 {
   1099 	if(!fp)
   1100 	{
   1101 		strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
   1102 		return -1;
   1103 	}
   1104 
   1105 	/* Install a user level filter */
   1106 	if (install_bpf_program(p, fp) < 0)
   1107 	{
   1108 		pcap_snprintf(p->errbuf, sizeof(p->errbuf),
   1109 			"setfilter, unable to install the filter: %s", pcap_strerror(errno));
   1110 		return -1;
   1111 	}
   1112 
   1113 	return 0;
   1114 }
   1115 
   1116 #ifdef _WIN32
   1117 static struct pcap_stat *
   1118 TcStatsEx(pcap_t *p, int *pcap_stat_size)
   1119 {
   1120 	struct pcap_tc *pt = p->priv;
   1121 	TC_STATISTICS statistics;
   1122 	TC_STATUS status;
   1123 	ULONGLONG counter;
   1124 
   1125 	*pcap_stat_size = sizeof (p->stat);
   1126 
   1127 	status = g_TcFunctions.InstanceQueryStatistics(pt->TcInstance, &statistics);
   1128 
   1129 	if (status != TC_SUCCESS)
   1130 	{
   1131 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcInstanceQueryStatistics: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
   1132 		return NULL;
   1133 	}
   1134 
   1135 	memset(&p->stat, 0, sizeof(p->stat));
   1136 
   1137 	status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_TOTAL_RX_PACKETS, &counter);
   1138 	if (status != TC_SUCCESS)
   1139 	{
   1140 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
   1141 		return NULL;
   1142 	}
   1143 	if (counter <= (ULONGLONG)0xFFFFFFFF)
   1144 	{
   1145 		p->stat.ps_recv = (ULONG)counter;
   1146 	}
   1147 	else
   1148 	{
   1149 		p->stat.ps_recv = 0xFFFFFFFF;
   1150 	}
   1151 
   1152 	status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_RX_DROPPED_PACKETS, &counter);
   1153 	if (status != TC_SUCCESS)
   1154 	{
   1155 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
   1156 		return NULL;
   1157 	}
   1158 	if (counter <= (ULONGLONG)0xFFFFFFFF)
   1159 	{
   1160 		p->stat.ps_ifdrop = (ULONG)counter;
   1161 		p->stat.ps_drop = (ULONG)counter;
   1162 	}
   1163 	else
   1164 	{
   1165 		p->stat.ps_ifdrop = 0xFFFFFFFF;
   1166 		p->stat.ps_drop = 0xFFFFFFFF;
   1167 	}
   1168 
   1169 #ifdef HAVE_REMOTE
   1170 	p->stat.ps_capt = pt->TcAcceptedCount;
   1171 #endif
   1172 
   1173 	return &p->stat;
   1174 }
   1175 
   1176 /* Set the dimension of the kernel-level capture buffer */
   1177 static int
   1178 TcSetBuff(pcap_t *p, int dim)
   1179 {
   1180 	/*
   1181 	 * XXX turbocap has an internal way of managing buffers.
   1182 	 * And at the moment it's not configurable, so we just
   1183 	 * silently ignore the request to set the buffer.
   1184 	 */
   1185 	return 0;
   1186 }
   1187 
   1188 static int
   1189 TcSetMode(pcap_t *p, int mode)
   1190 {
   1191 	if (mode != MODE_CAPT)
   1192 	{
   1193 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Mode %u not supported by TurboCap devices. TurboCap only supports capture.", mode);
   1194 		return -1;
   1195 	}
   1196 
   1197 	return 0;
   1198 }
   1199 
   1200 static int
   1201 TcSetMinToCopy(pcap_t *p, int size)
   1202 {
   1203 	struct pcap_tc *pt = p->priv;
   1204 	TC_STATUS status;
   1205 
   1206 	if (size < 0)
   1207 	{
   1208 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Mintocopy cannot be less than 0.");
   1209 		return -1;
   1210 	}
   1211 
   1212 	status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_MINTOCOPY, (ULONG)size);
   1213 
   1214 	if (status != TC_SUCCESS)
   1215 	{
   1216 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error setting the mintocopy: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
   1217 	}
   1218 
   1219 	return 0;
   1220 }
   1221 
   1222 static HANDLE
   1223 TcGetReceiveWaitHandle(pcap_t *p)
   1224 {
   1225 	struct pcap_tc *pt = p->priv;
   1226 
   1227 	return g_TcFunctions.InstanceGetReceiveWaitHandle(pt->TcInstance);
   1228 }
   1229 
   1230 static int
   1231 TcOidGetRequest(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_, size_t *lenp _U_)
   1232 {
   1233 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
   1234 	    "An OID get request cannot be performed on a TurboCap device");
   1235 	return PCAP_ERROR;
   1236 }
   1237 
   1238 static int
   1239 TcOidSetRequest(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
   1240     size_t *lenp _U_)
   1241 {
   1242 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
   1243 	    "An OID set request cannot be performed on a TurboCap device");
   1244 	return PCAP_ERROR;
   1245 }
   1246 
   1247 static u_int
   1248 TcSendqueueTransmit(pcap_t *p, pcap_send_queue *queue _U_, int sync _U_)
   1249 {
   1250 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
   1251 	    "Packets cannot be bulk transmitted on a TurboCap device");
   1252 	return 0;
   1253 }
   1254 
   1255 static int
   1256 TcSetUserBuffer(pcap_t *p, int size _U_)
   1257 {
   1258 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
   1259 	    "The user buffer cannot be set on a TurboCap device");
   1260 	return -1;
   1261 }
   1262 
   1263 static int
   1264 TcLiveDump(pcap_t *p, char *filename _U_, int maxsize _U_, int maxpacks _U_)
   1265 {
   1266 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
   1267 	    "Live packet dumping cannot be performed on a TurboCap device");
   1268 	return -1;
   1269 }
   1270 
   1271 static int
   1272 TcLiveDumpEnded(pcap_t *p, int sync _U_)
   1273 {
   1274 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
   1275 	    "Live packet dumping cannot be performed on a TurboCap device");
   1276 	return -1;
   1277 }
   1278 
   1279 static PAirpcapHandle
   1280 TcGetAirPcapHandle(pcap_t *p _U_)
   1281 {
   1282 	return NULL;
   1283 }
   1284 #endif
   1285