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