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