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