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 1308