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