pcap-tc.c 34 KB

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