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