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