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