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