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