From 931e8f2a3d2e3714ceed7f071de24805b8a3e535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Klaus=20N=C3=B6ske?= <40196862+klaus0x7c4@users.noreply.github.com> Date: Sat, 28 Dec 2024 12:46:15 +0100 Subject: [PATCH] Improve/fix error buffer handling for native pcap methods Credit to @trivalik See: https://github.com/klaus0x7c4/Pcap.Net/pull/2 and: https://github.com/dotpcap/sharppcap/pull/533 --- .../src/PcapDotNet.Core/Native/IPcapPal.cs | 41 +++++----- .../src/PcapDotNet.Core/Native/PcapUnixPal.cs | 78 ++++++++++-------- .../Native/PcapUnmanagedStructures.cs | 27 +++++- .../PcapDotNet.Core/Native/PcapWindowsPal.cs | 82 +++++++++++-------- .../LivePacketCommunicator.cs | 5 +- .../OfflinePacketCommunicator.cs | 3 +- .../PacketCommunicator/PacketCommunicator.cs | 8 +- PcapDotNet/src/PcapDotNet.Core/Pcap.cs | 7 -- 8 files changed, 142 insertions(+), 109 deletions(-) diff --git a/PcapDotNet/src/PcapDotNet.Core/Native/IPcapPal.cs b/PcapDotNet/src/PcapDotNet.Core/Native/IPcapPal.cs index 0b098463..b07ecd6b 100644 --- a/PcapDotNet/src/PcapDotNet.Core/Native/IPcapPal.cs +++ b/PcapDotNet/src/PcapDotNet.Core/Native/IPcapPal.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.InteropServices; using System.Text; using PcapDotNet.Packets; using static PcapDotNet.Core.Native.PcapUnmanagedStructures; @@ -18,7 +19,7 @@ internal interface IPcapPal /// /// Creates a platform depend pcap packet header.handle /// - /// MUST be freed with Marshal.FreeHCGlobal! + /// MUST be freed with ! /// Pointer to the header structure IntPtr CreatePcapPacketHeaderHandle(Packet packet); @@ -34,7 +35,7 @@ internal interface IPcapPal PacketTotalStatistics GetTotalStatistics(PcapHandle pcapDescriptor); - int pcap_findalldevs(ref PcapInterfaceHandle /* pcap_if_t** */ alldevs, StringBuilder /* char* */ errbuf); + int pcap_findalldevs(ref PcapInterfaceHandle /* pcap_if_t** */ alldevs, out string /* char* */ errbuf); void pcap_freealldevs(IntPtr /* pcap_if_t * */ alldevs); @@ -49,11 +50,11 @@ internal interface IPcapPal int flags, int read_timeout, ref pcap_rmtauth rmtauth, - StringBuilder errbuf); + out string errbuf); - PcapHandle /* pcap_t* */ pcap_create(string dev, StringBuilder errbuf); + PcapHandle /* pcap_t* */ pcap_create(string dev, out string errbuf); - PcapHandle /* pcap_t* */ pcap_open_offline(string/*const char* */ fname, StringBuilder/* char* */ errbuf); + PcapHandle /* pcap_t* */ pcap_open_offline(string/*const char* */ fname, out string /* char* */ errbuf); /// @@ -154,54 +155,54 @@ internal interface IPcapPal /// /// Is used to get a list of the supported link-layer header types of the interface associated with the pcap descriptor. pcap_list_datalinks() allocates an array to hold the list and sets *dataLinkList to point to that array. /// The caller is responsible for freeing the array with pcap_free_datalinks(), which frees the list of link-layer header types pointed to by dataLinkList. - /// It must not be called on a pcap descriptor created by pcap_create(3PCAP) that has not yet been activated by pcap_activate(3PCAP). + /// It must not be called on a pcap descriptor created by pcap_create(3PCAP) that has not yet been activated by pcap_activate(3PCAP). /// /// list of link-layer header types supported by a capture device /// The number of link-layer header types in the array on success, PCAP_ERROR_NOT_ACTIVATED if called on a capture handle that has been created but not activated, and PCAP_ERROR on other errors. If PCAP_ERROR is returned, pcap_geterr(3PCAP) or pcap_perror(3PCAP) may be called with p as an argument to fetch or display the error text. int pcap_list_datalinks(PcapHandle /* pcap_t* */ adaptHandle, ref IntPtr /* int** */ dataLinkList); /// - /// Frees the list of link-layer header types pointed to by dataLinkList. + /// Frees the list of link-layer header types pointed to by dataLinkList. /// void pcap_free_datalinks(IntPtr /* int* */ dataLinkList); /// /// Get the link-layer header type value corresponding to a header type name. - /// Translates a link-layer header type name, which is a DLT_ name with the DLT_ removed, + /// Translates a link-layer header type name, which is a DLT_ name with the DLT_ removed, /// to the corresponding link-layer header type value.The translation is case-insensitive. /// /// Returns the type value on success and PCAP_ERROR if the name is not a known type name. int pcap_datalink_name_to_val(string /*const char* */ name); /// - /// Translates a link-layer header type value to the corresponding link-layer header type name, - /// which is the DLT_ name for the link-layer header type value with the DLT_ removed. - /// NULL is returned if the type value does not correspond to a known DLT_ value. + /// Translates a link-layer header type value to the corresponding link-layer header type name, + /// which is the DLT_ name for the link-layer header type value with the DLT_ removed. + /// NULL is returned if the type value does not correspond to a known DLT_ value. /// string /* const char* */ pcap_datalink_val_to_name(int dlt); /// - /// Translates a link-layer header type value to a short description of that link-layer header type. - /// NULL is returned if the type value does not correspond to a known DLT_ value. + /// Translates a link-layer header type value to a short description of that link-layer header type. + /// NULL is returned if the type value does not correspond to a known DLT_ value. /// string /* const char* */ pcap_datalink_val_to_description(int dlt); /// /// Translates a link-layer header type value to a short description of that link-layer header type - /// just like pcap_datalink_val_to_description. If the type value does not correspond to a known DLT_ value, - /// the string "DLT n" is returned, where n is the value of the dlt argument. + /// just like pcap_datalink_val_to_description. If the type value does not correspond to a known DLT_ value, + /// the string "DLT n" is returned, where n is the value of the dlt argument. /// string /* const char* */ pcap_datalink_val_to_description_or_dlt(int dlt); /// /// Set nonblocking mode. pcap_loop() and pcap_next() doesnt work in nonblocking mode! /// - int pcap_setnonblock(PcapHandle /* pcap_t* */ adaptHandle, int nonblock, StringBuilder /* char* */ errbuf); + int pcap_setnonblock(PcapHandle /* pcap_t* */ adaptHandle, int nonblock, out string /* char* */ errbuf); /// /// Get nonblocking mode, returns allways 0 for savefiles. /// - int pcap_getnonblock(PcapHandle /* pcap_t* */ adaptHandle, StringBuilder /* char* */ errbuf); + int pcap_getnonblock(PcapHandle /* pcap_t* */ adaptHandle, out string /* char* */ errbuf); /// /// Read packets until cnt packets are processed or an error occurs. @@ -237,7 +238,7 @@ internal interface IPcapPal int pcap_snapshot(PcapHandle /* pcap_t* */ adapter); /// - /// find out whether a 'savefile' has the native byte order + /// find out whether a 'savefile' has the native byte order /// /// /// returns true (1) if p refers to a 'savefile' that uses a different byte order than the current system. For a live capture, it always returns false (0). Returns PCAP_ERROR_NOT_ACTIVATED if called on a capture handle that has been created but not activated. @@ -245,7 +246,7 @@ internal interface IPcapPal int pcap_is_swapped(PcapHandle /* pcap_t* */ adapter); /// - /// The version number of a 'savefile' + /// The version number of a 'savefile' /// /// The major number of the file format of the 'savefile' /// @@ -255,7 +256,7 @@ internal interface IPcapPal int pcap_major_version(PcapHandle /* pcap_t* */ adapter); /// - /// The version number of a 'savefile' + /// The version number of a 'savefile' /// /// The minor number of the file format of the 'savefile' /// diff --git a/PcapDotNet/src/PcapDotNet.Core/Native/PcapUnixPal.cs b/PcapDotNet/src/PcapDotNet.Core/Native/PcapUnixPal.cs index 4d8a5170..c7f6d376 100644 --- a/PcapDotNet/src/PcapDotNet.Core/Native/PcapUnixPal.cs +++ b/PcapDotNet/src/PcapDotNet.Core/Native/PcapUnixPal.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Runtime.InteropServices; using System.Security; using System.Text; @@ -45,12 +45,10 @@ public virtual unsafe PcapPacketHeader CreatePcapPacketHeader(IntPtr /* pcap_pkt public PcapInterfaceHandle GetAllLocalMachine() { var handle = new PcapInterfaceHandle(); - var errorBuffer = Pcap.CreateErrorBuffer(); - - var result = pcap_findalldevs(ref handle, errorBuffer); + var result = pcap_findalldevs(ref handle, out var errorBuffer); if (result < 0) { - PcapError.ThrowInvalidOperation("Failed getting devices. Error: " + errorBuffer.ToString(), null); + PcapError.ThrowInvalidOperation($"Failed getting devices. Error: {errorBuffer}", null); } return handle; } @@ -95,9 +93,11 @@ public int pcap_compile(PcapHandle adaptHandle, IntPtr fp, string str, int optim return SafeNativeMethods.pcap_compile(adaptHandle, fp, str, optimize, netmask); } - public PcapHandle pcap_create(string dev, StringBuilder errbuf) + public PcapHandle pcap_create(string dev, out string errbuf) { - return SafeNativeMethods.pcap_create(dev, errbuf); + var result = SafeNativeMethods.pcap_create(dev, out var errorBuffer); + errbuf = errorBuffer.ToString(); + return result; } public int pcap_datalink(PcapHandle adaptHandle) @@ -165,9 +165,11 @@ public int pcap_fileno(PcapHandle adapter) return SafeNativeMethods.pcap_fileno(adapter); } - public int pcap_findalldevs(ref PcapInterfaceHandle alldevs, StringBuilder errbuf) + public int pcap_findalldevs(ref PcapInterfaceHandle alldevs, out string errbuf) { - return SafeNativeMethods.pcap_findalldevs(ref alldevs, errbuf); + var result = SafeNativeMethods.pcap_findalldevs(ref alldevs, out var errorBuffer); + errbuf = errorBuffer.ToString(); + return result; } public void pcap_freealldevs(IntPtr alldevs) @@ -185,9 +187,11 @@ public string pcap_geterr(PcapHandle adaptHandle) return SafeNativeMethods.pcap_geterr(adaptHandle); } - public int pcap_getnonblock(PcapHandle adaptHandle, StringBuilder errbuf) + public int pcap_getnonblock(PcapHandle adaptHandle, out string errbuf) { - return SafeNativeMethods.pcap_getnonblock(adaptHandle, errbuf); + var result = SafeNativeMethods.pcap_getnonblock(adaptHandle, out var errorBuffer); + errbuf = errorBuffer.ToString(); + return result; } public int pcap_get_selectable_fd(PcapHandle adaptHandle) @@ -210,9 +214,11 @@ public int pcap_offline_filter(IntPtr prog, IntPtr header, IntPtr pkt_data) return SafeNativeMethods.pcap_offline_filter(prog, header, pkt_data); } - public PcapHandle pcap_open(string dev, int packetLen, int flags, int read_timeout, ref pcap_rmtauth rmtauth, StringBuilder errbuf) + public PcapHandle pcap_open(string dev, int packetLen, int flags, int read_timeout, ref pcap_rmtauth rmtauth, out string errbuf) { - return SafeNativeMethods.pcap_open(dev, packetLen, flags, read_timeout, ref rmtauth, errbuf); + var result = SafeNativeMethods.pcap_open(dev, packetLen, flags, read_timeout, ref rmtauth, out var errorBuffer); + errbuf = errorBuffer.ToString(); + return result; } public PcapHandle pcap_open_dead(int linktype, int snaplen) @@ -220,9 +226,11 @@ public PcapHandle pcap_open_dead(int linktype, int snaplen) return SafeNativeMethods.pcap_open_dead(linktype, snaplen); } - public PcapHandle pcap_open_offline(string fname, StringBuilder errbuf) + public PcapHandle pcap_open_offline(string fname, out string errbuf) { - return SafeNativeMethods.pcap_open_offline(fname, errbuf); + var result = SafeNativeMethods.pcap_open_offline(fname, out var errorBuffer); + errbuf = errorBuffer.ToString(); + return result; } public int pcap_sendpacket(PcapHandle adaptHandle, IntPtr data, int size) @@ -235,9 +243,11 @@ public int pcap_setfilter(PcapHandle adaptHandle, IntPtr fp) return SafeNativeMethods.pcap_setfilter(adaptHandle, fp); } - public int pcap_setnonblock(PcapHandle adaptHandle, int nonblock, StringBuilder errbuf) + public int pcap_setnonblock(PcapHandle adaptHandle, int nonblock, out string errbuf) { - return SafeNativeMethods.pcap_setnonblock(adaptHandle, nonblock, errbuf); + var result = SafeNativeMethods.pcap_setnonblock(adaptHandle, nonblock, out var errorBuffer); + errbuf = errorBuffer.ToString(); + return result; } public int pcap_set_buffer_size(PcapHandle adapter, int bufferSizeInBytes) @@ -351,7 +361,7 @@ private static class SafeNativeMethods [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static int pcap_findalldevs( ref PcapInterfaceHandle /* pcap_if_t** */ alldevs, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] StringBuilder /* char* */ errbuf); + out PcapErrorBuffer /* char* */ errbuf); [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static void pcap_freealldevs(IntPtr /* pcap_if_t* */ alldevs); @@ -363,17 +373,17 @@ internal extern static int pcap_findalldevs( int flags, int read_timeout, ref pcap_rmtauth rmtauth, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] StringBuilder errbuf); + out PcapErrorBuffer /* char* */ errbuf); [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static PcapHandle /* pcap_t* */ pcap_create( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] string dev, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] StringBuilder errbuf); + out PcapErrorBuffer /* char* */ errbuf); [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static PcapHandle /* pcap_t* */ pcap_open_offline( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] string/*const char* */ fname, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] StringBuilder/* char* */ errbuf); + out PcapErrorBuffer /* char* */ errbuf); [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static PcapHandle /* pcap_t* */ pcap_open_dead(int linktype, int snaplen); @@ -388,7 +398,7 @@ internal extern static int pcap_findalldevs( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] string /*const char * */fname); /// - /// Save a packet to disk. + /// Save a packet to disk. /// [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static void pcap_dump(IntPtr /*u_char * */user, IntPtr /*const struct pcap_pkthdr * */h, IntPtr /*const u_char * */sp); @@ -405,7 +415,7 @@ internal extern static int pcap_findalldevs( /// /// Send a raw packet.
- /// This function allows to send a raw packet to the network. + /// This function allows to send a raw packet to the network. /// The MAC CRC doesn't need to be included, because it is transparently calculated /// and added by the network interface driver. ///
@@ -417,7 +427,7 @@ internal extern static int pcap_findalldevs( internal extern static int pcap_sendpacket(PcapHandle /* pcap_t* */ adaptHandle, IntPtr data, int size); /// - /// Compile a packet filter, converting an high level filtering expression (see Filtering expression syntax) in a program that can be interpreted by the kernel-level filtering engine. + /// Compile a packet filter, converting an high level filtering expression (see Filtering expression syntax) in a program that can be interpreted by the kernel-level filtering engine. /// [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static int pcap_compile( @@ -431,7 +441,7 @@ internal extern static int pcap_compile( internal extern static int pcap_setfilter(PcapHandle /* pcap_t* */ adaptHandle, IntPtr /*bpf_program **/fp); /// - /// Returns if a given filter applies to an offline packet. + /// Returns if a given filter applies to an offline packet. /// /// [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] @@ -459,8 +469,8 @@ internal extern static int pcap_compile( [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static IntPtr /*FILE **/ pcap_dump_file(IntPtr /*pcap_dumper_t **/p); - /// Flushes the output buffer to the 'savefile', so that any packets - /// written with pcap_dump() but not yet written to the 'savefile' will be written. + /// Flushes the output buffer to the 'savefile', so that any packets + /// written with pcap_dump() but not yet written to the 'savefile' will be written. /// -1 is returned on error, 0 on success. [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static int pcap_dump_flush(IntPtr /*pcap_dumper_t **/p); @@ -499,7 +509,7 @@ internal extern static int pcap_datalink_name_to_val( internal extern static int pcap_setnonblock( PcapHandle /* pcap_if_t** */ adaptHandle, int nonblock, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] StringBuilder /* char* */ errbuf); + out PcapErrorBuffer /* char* */ errbuf); /// /// Get nonblocking mode, returns allways 0 for savefiles. @@ -507,7 +517,7 @@ internal extern static int pcap_setnonblock( [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static int pcap_getnonblock( PcapHandle /* pcap_if_t** */ adaptHandle, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] StringBuilder /* char* */ errbuf); + out PcapErrorBuffer /* char* */ errbuf); /// /// Read packets until cnt packets are processed or an error occurs. @@ -536,22 +546,22 @@ internal extern static int pcap_getnonblock( /// /// pcap_set_rfmon() sets whether monitor mode should be set on a capture handle when the handle is activated. - /// If rfmon is non-zero, monitor mode will be set, otherwise it will not be set. + /// If rfmon is non-zero, monitor mode will be set, otherwise it will not be set. /// /// Returns 0 on success or PCAP_ERROR_ACTIVATED if called on a capture handle that has been activated. [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static int pcap_set_rfmon(PcapHandle /* pcap_t* */ p, int rfmon); /// - /// pcap_set_snaplen() sets the snapshot length to be used on a capture handle when the handle is activated to snaplen. + /// pcap_set_snaplen() sets the snapshot length to be used on a capture handle when the handle is activated to snaplen. /// /// Returns 0 on success or PCAP_ERROR_ACTIVATED if called on a capture handle that has been activated. [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static int pcap_set_snaplen(PcapHandle /* pcap_t* */ p, int snaplen); /// - /// pcap_set_promisc() sets whether promiscuous mode should be set on a capture handle when the handle is activated. - /// If promisc is non-zero, promiscuous mode will be set, otherwise it will not be set. + /// pcap_set_promisc() sets whether promiscuous mode should be set on a capture handle when the handle is activated. + /// If promisc is non-zero, promiscuous mode will be set, otherwise it will not be set. /// /// Returns 0 on success or PCAP_ERROR_ACTIVATED if called on a capture handle that has been activated. [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] @@ -591,4 +601,4 @@ internal extern static int pcap_getnonblock( #endregion } } -} \ No newline at end of file +} diff --git a/PcapDotNet/src/PcapDotNet.Core/Native/PcapUnmanagedStructures.cs b/PcapDotNet/src/PcapDotNet.Core/Native/PcapUnmanagedStructures.cs index 23053627..9dcda87f 100644 --- a/PcapDotNet/src/PcapDotNet.Core/Native/PcapUnmanagedStructures.cs +++ b/PcapDotNet/src/PcapDotNet.Core/Native/PcapUnmanagedStructures.cs @@ -1,4 +1,4 @@ -/* +/* This file is part of SharpPcap. SharpPcap is free software: you can redistribute it and/or modify @@ -21,6 +21,7 @@ You should have received a copy of the GNU Lesser General Public License using System; using System.Runtime.InteropServices; +using System.Text; namespace PcapDotNet.Core.Native { @@ -375,8 +376,30 @@ public struct pcap_samp /// public int value; }; + + [StructLayout(LayoutKind.Sequential)] + internal struct PcapErrorBuffer + { + [MarshalAs(UnmanagedType.ByValArray, SizeConst = Pcap.PCAP_ERRBUF_SIZE)] + internal byte[] Data; + + public override string ToString() + { + return ToString(Interop.Pcap.StringEncoding); + } + + public string ToString(Encoding encoding) + { + var nbBytes = 0; + while (Data[nbBytes] != 0) + { + nbBytes++; + } + return encoding.GetString(Data, 0, nbBytes); + } + } #endregion Unmanaged Structs Implementation } #pragma warning restore IDE1006 // Naming Styles -} \ No newline at end of file +} diff --git a/PcapDotNet/src/PcapDotNet.Core/Native/PcapWindowsPal.cs b/PcapDotNet/src/PcapDotNet.Core/Native/PcapWindowsPal.cs index 3efeb79b..5d4ef3d9 100644 --- a/PcapDotNet/src/PcapDotNet.Core/Native/PcapWindowsPal.cs +++ b/PcapDotNet/src/PcapDotNet.Core/Native/PcapWindowsPal.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Runtime.InteropServices; using System.Security; @@ -21,14 +21,15 @@ private static Encoding ConfigureStringEncoding() try { // Try to change Libpcap to UTF-8 mode - var errorBuffer = Pcap.CreateErrorBuffer(); const uint PCAP_CHAR_ENC_UTF_8 = 1; - var res = SafeNativeMethods.pcap_init(PCAP_CHAR_ENC_UTF_8, errorBuffer); + var res = SafeNativeMethods.pcap_init(PCAP_CHAR_ENC_UTF_8, out var errorBuffer); if (res == 0) { // We made it return Encoding.UTF8; } + + throw new InvalidOperationException($"Failed to set pcap_init to UTF-8. Error: {errorBuffer.ToString(Encoding.Default)} ({res})"); } catch (TypeLoadException) { @@ -71,13 +72,12 @@ public unsafe PcapPacketHeader CreatePcapPacketHeader(IntPtr /* pcap_pkthdr* */ public PcapInterfaceHandle GetAllLocalMachine() { var handle = new PcapInterfaceHandle(); - var errorBuffer = Pcap.CreateErrorBuffer(); var auth = default(pcap_rmtauth); //auth is not needed - var result = pcap_findalldevs_ex(Pcap.PCAP_SRC_IF_STRING, ref auth, ref handle, errorBuffer); + var result = pcap_findalldevs_ex(Pcap.PCAP_SRC_IF_STRING, ref auth, ref handle, out var errbuf); if (result < 0) { - PcapError.ThrowInvalidOperation("Failed getting devices. Error: " + errorBuffer.ToString(), null); + PcapError.ThrowInvalidOperation($"Failed getting devices. Error: {errbuf}", null); } return handle; } @@ -112,9 +112,11 @@ public int pcap_compile(PcapHandle adaptHandle, IntPtr fp, string str, int optim return SafeNativeMethods.pcap_compile(adaptHandle, fp, str, optimize, netmask); } - public PcapHandle pcap_create(string dev, StringBuilder errbuf) + public PcapHandle pcap_create(string dev, out string errbuf) { - return SafeNativeMethods.pcap_create(dev, errbuf); + var result = SafeNativeMethods.pcap_create(dev, out var errorBuffer); + errbuf = errorBuffer.ToString(); + return result; } public int pcap_datalink(PcapHandle adaptHandle) @@ -182,14 +184,18 @@ public int pcap_fileno(PcapHandle adapter) return SafeNativeMethods.pcap_fileno(adapter); } - public int pcap_findalldevs(ref PcapInterfaceHandle alldevs, StringBuilder errbuf) + public int pcap_findalldevs(ref PcapInterfaceHandle alldevs, out string errbuf) { - return SafeNativeMethods.pcap_findalldevs(ref alldevs, errbuf); + var result = SafeNativeMethods.pcap_findalldevs(ref alldevs, out var errorBuffer); + errbuf = errorBuffer.ToString(); + return result; } - public int pcap_findalldevs_ex(string source, ref pcap_rmtauth auth, ref PcapInterfaceHandle alldevs, StringBuilder errbuf) + public int pcap_findalldevs_ex(string source, ref pcap_rmtauth auth, ref PcapInterfaceHandle alldevs, out string errbuf) { - return SafeNativeMethods.pcap_findalldevs_ex(source, ref auth, ref alldevs, errbuf); + var result = SafeNativeMethods.pcap_findalldevs_ex(source, ref auth, ref alldevs, out var errorBuffer); + errbuf = errorBuffer.ToString(); + return result; } public void pcap_freealldevs(IntPtr alldevs) @@ -207,9 +213,11 @@ public string pcap_geterr(PcapHandle adaptHandle) return SafeNativeMethods.pcap_geterr(adaptHandle); } - public int pcap_getnonblock(PcapHandle adaptHandle, StringBuilder errbuf) + public int pcap_getnonblock(PcapHandle adaptHandle, out string errbuf) { - return SafeNativeMethods.pcap_getnonblock(adaptHandle, errbuf); + var result = SafeNativeMethods.pcap_getnonblock(adaptHandle, out var errorBuffer); + errbuf = errorBuffer.ToString(); + return result; } public int pcap_get_selectable_fd(PcapHandle adaptHandle) @@ -232,9 +240,11 @@ public int pcap_offline_filter(IntPtr prog, IntPtr header, IntPtr pkt_data) return SafeNativeMethods.pcap_offline_filter(prog, header, pkt_data); } - public PcapHandle pcap_open(string dev, int packetLen, int flags, int read_timeout, ref pcap_rmtauth rmtauth, StringBuilder errbuf) + public PcapHandle pcap_open(string dev, int packetLen, int flags, int read_timeout, ref pcap_rmtauth rmtauth, out string errbuf) { - return SafeNativeMethods.pcap_open(dev, packetLen, flags, read_timeout, ref rmtauth, errbuf); + var handle = SafeNativeMethods.pcap_open(dev, packetLen, flags, read_timeout, ref rmtauth, out var errorBuffer); + errbuf = errorBuffer.ToString(); + return handle; } public PcapHandle pcap_open_dead(int linktype, int snaplen) @@ -242,9 +252,11 @@ public PcapHandle pcap_open_dead(int linktype, int snaplen) return SafeNativeMethods.pcap_open_dead(linktype, snaplen); } - public PcapHandle pcap_open_offline(string fname, StringBuilder errbuf) + public PcapHandle pcap_open_offline(string fname, out string errbuf) { - return SafeNativeMethods.pcap_open_offline(fname, errbuf); + var result = SafeNativeMethods.pcap_open_offline(fname, out var errorBuffer); + errbuf = errorBuffer.ToString(); + return result; } public int pcap_sendpacket(PcapHandle adaptHandle, IntPtr data, int size) @@ -257,9 +269,11 @@ public int pcap_setfilter(PcapHandle adaptHandle, IntPtr fp) return SafeNativeMethods.pcap_setfilter(adaptHandle, fp); } - public int pcap_setnonblock(PcapHandle adaptHandle, int nonblock, StringBuilder errbuf) + public int pcap_setnonblock(PcapHandle adaptHandle, int nonblock, out string errbuf) { - return SafeNativeMethods.pcap_setnonblock(adaptHandle, nonblock, errbuf); + var result = SafeNativeMethods.pcap_setnonblock(adaptHandle, nonblock, out var errorBuffer); + errbuf = errorBuffer.ToString(); + return result; } public int pcap_set_buffer_size(PcapHandle adapter, int bufferSizeInBytes) @@ -358,7 +372,7 @@ public int pcap_sendqueue_transmit(PcapHandle p, ref pcap_send_queue queue, int } /// - /// Per http://msdn.microsoft.com/en-us/ms182161.aspx + /// Per http://msdn.microsoft.com/en-us/ms182161.aspx /// [SuppressUnmanagedCodeSecurity] private static class SafeNativeMethods @@ -375,21 +389,17 @@ static SafeNativeMethods() } [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] - internal extern static int pcap_init( - uint opts, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] StringBuilder /* char* */ errbuf); + internal static extern int pcap_init(uint opts, out PcapErrorBuffer /* char* */ errbuf); [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] - internal extern static int pcap_findalldevs( - ref PcapInterfaceHandle /* pcap_if_t** */ alldevs, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] StringBuilder /* char* */ errbuf); + internal extern static int pcap_findalldevs(ref PcapInterfaceHandle /* pcap_if_t** */ alldevs, out PcapErrorBuffer /* char* */ errbuf); [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static int pcap_findalldevs_ex( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] string /* char* */source, ref pcap_rmtauth /* pcap_rmtauth* */auth, ref PcapInterfaceHandle /* pcap_if_t** */alldevs, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] StringBuilder /* char* */errbuf); + out PcapErrorBuffer /* char* */ errbuf); [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static void pcap_freealldevs(IntPtr /* pcap_if_t* */ alldevs); @@ -397,7 +407,7 @@ internal extern static int pcap_findalldevs_ex( [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static PcapHandle /* pcap_t* */ pcap_create( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] string dev, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] StringBuilder errbuf); + out PcapErrorBuffer /* char* */ errbuf); [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static PcapHandle /* pcap_t* */ pcap_open( @@ -406,12 +416,12 @@ internal extern static int pcap_findalldevs_ex( int flags, int read_timeout, ref pcap_rmtauth rmtauth, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] StringBuilder errbuf); + out PcapErrorBuffer /* char* */ errbuf); [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static PcapHandle /* pcap_t* */ pcap_open_offline( [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] string/* const char* */ fname, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] StringBuilder/* char* */ errbuf); + out PcapErrorBuffer /* char* */ errbuf); [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static PcapHandle /* pcap_t* */ pcap_open_dead(int linktype, int snaplen); @@ -535,17 +545,17 @@ internal extern static int pcap_datalink_name_to_val( /// [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static int pcap_setnonblock( - PcapHandle /* pcap_if_t** */ adaptHandle, + PcapHandle /* pcap_t* */ adaptHandle, int nonblock, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] StringBuilder /* char* */ errbuf); + out PcapErrorBuffer /* char* */ errbuf); /// /// Get nonblocking mode, returns allways 0 for savefiles. /// [DllImport(PCAP_DLL, CallingConvention = CallingConvention.Cdecl)] internal extern static int pcap_getnonblock( - PcapHandle /* pcap_if_t** */ adaptHandle, - [MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(PcapStringMarshaler))] StringBuilder /* char* */ errbuf); + PcapHandle /* pcap_t* */ adaptHandle, + out PcapErrorBuffer /* char* */ errbuf); /// /// Read packets until cnt packets are processed or an error occurs. @@ -693,4 +703,4 @@ internal extern static int pcap_getnonblock( #endregion } } -} \ No newline at end of file +} diff --git a/PcapDotNet/src/PcapDotNet.Core/PacketCommunicator/LivePacketCommunicator.cs b/PcapDotNet/src/PcapDotNet.Core/PacketCommunicator/LivePacketCommunicator.cs index 34b49e10..e68ed445 100644 --- a/PcapDotNet/src/PcapDotNet.Core/PacketCommunicator/LivePacketCommunicator.cs +++ b/PcapDotNet/src/PcapDotNet.Core/PacketCommunicator/LivePacketCommunicator.cs @@ -1,4 +1,4 @@ -using PcapDotNet.Core.Native; +using PcapDotNet.Core.Native; using System; namespace PcapDotNet.Core @@ -55,7 +55,6 @@ public override void Transmit(PacketSendBuffer sendBuffer, bool isSync) private static PcapHandle PcapOpen(string source, int snapshotLength, PacketDeviceOpenAttributes attributes, int readTimeout, PcapUnmanagedStructures.pcap_rmtauth auth) { - var errorBuffer = Pcap.CreateErrorBuffer(); var handle = Interop.Pcap.pcap_open( source, // name of the device snapshotLength, // portion of the packet to capture @@ -63,7 +62,7 @@ private static PcapHandle PcapOpen(string source, int snapshotLength, PacketDevi (int)attributes, readTimeout, ref auth, // authentication on the remote machine - errorBuffer); + out var errorBuffer); if (handle.IsInvalid) { diff --git a/PcapDotNet/src/PcapDotNet.Core/PacketCommunicator/OfflinePacketCommunicator.cs b/PcapDotNet/src/PcapDotNet.Core/PacketCommunicator/OfflinePacketCommunicator.cs index 2a0d9fc9..48b5f79e 100644 --- a/PcapDotNet/src/PcapDotNet.Core/PacketCommunicator/OfflinePacketCommunicator.cs +++ b/PcapDotNet/src/PcapDotNet.Core/PacketCommunicator/OfflinePacketCommunicator.cs @@ -40,8 +40,7 @@ private static PcapHandle OpenFile(string fileName) // ToDo: This is currently still very simplified // compared to the original native version. Still needs to be revised. - var errorBuffer = Pcap.CreateErrorBuffer(); - var handle = Interop.Pcap.pcap_open_offline(fileName, errorBuffer); + var handle = Interop.Pcap.pcap_open_offline(fileName, out var errorBuffer); if(handle.IsInvalid) { PcapError.ThrowInvalidOperation($"Failed opening file {fileName}. Error: {errorBuffer}.", null); diff --git a/PcapDotNet/src/PcapDotNet.Core/PacketCommunicator/PacketCommunicator.cs b/PcapDotNet/src/PcapDotNet.Core/PacketCommunicator/PacketCommunicator.cs index d54ae8fc..9073daa1 100644 --- a/PcapDotNet/src/PcapDotNet.Core/PacketCommunicator/PacketCommunicator.cs +++ b/PcapDotNet/src/PcapDotNet.Core/PacketCommunicator/PacketCommunicator.cs @@ -172,18 +172,16 @@ public bool NonBlocking { get { - var errorBuffer = Pcap.CreateErrorBuffer(); - var nonBlockValue = Interop.Pcap.pcap_getnonblock(PcapDescriptor, errorBuffer); + var nonBlockValue = Interop.Pcap.pcap_getnonblock(PcapDescriptor, out var errorBuffer); if (nonBlockValue < 0) { - ThrowInvalidOperation("Error getting NonBlocking value: " + errorBuffer.ToString()); + ThrowInvalidOperation("Error getting NonBlocking value: " + errorBuffer); } return nonBlockValue != 0; } set { - var errorBuffer = Pcap.CreateErrorBuffer(); - if (Interop.Pcap.pcap_setnonblock(PcapDescriptor, value ? 1 : 0, errorBuffer) < 0) + if (Interop.Pcap.pcap_setnonblock(PcapDescriptor, value ? 1 : 0, out var errorBuffer) < 0) { ThrowInvalidOperation($"Error setting NonBlocking to {value}: {errorBuffer}"); } diff --git a/PcapDotNet/src/PcapDotNet.Core/Pcap.cs b/PcapDotNet/src/PcapDotNet.Core/Pcap.cs index 16b3f131..232ca9fd 100644 --- a/PcapDotNet/src/PcapDotNet.Core/Pcap.cs +++ b/PcapDotNet/src/PcapDotNet.Core/Pcap.cs @@ -1,5 +1,3 @@ -using System.Text; - namespace PcapDotNet.Core { /// @@ -45,10 +43,5 @@ public class Pcap /// interface isn't up internal const int PCAP_ERROR_IFACE_NOT_UP = -9; #endregion - - internal static StringBuilder CreateErrorBuffer() - { - return new StringBuilder(PCAP_ERRBUF_SIZE); - } } }