static public IReadOnlyList <PcapInterface> GetAllPcapInterfaces(string source, RemoteAuthentication credentials) { var devicePtr = IntPtr.Zero; var errorBuffer = new StringBuilder(Pcap.PCAP_ERRBUF_SIZE); var auth = RemoteAuthentication.CreateAuth(credentials); try { var result = LibPcapSafeNativeMethods.pcap_findalldevs_ex(source, ref auth, ref devicePtr, errorBuffer); if (result < 0) { throw new PcapException(errorBuffer.ToString()); } } catch (TypeLoadException ex) { throw new PlatformNotSupportedException( "Operation is not supported on this platform.", ex ); } var pcapInterfaces = GetAllPcapInterfaces(devicePtr, credentials); // Free unmanaged memory allocation LibPcapSafeNativeMethods.pcap_freealldevs(devicePtr); return(pcapInterfaces); }
internal PcapInterface(pcap_if pcapIf, NetworkInterface networkInterface, RemoteAuthentication credentials) { Name = pcapIf.Name; Description = pcapIf.Description; Flags = pcapIf.Flags; Addresses = new List <PcapAddress>(); GatewayAddresses = new List <IPAddress>(); Credentials = credentials; // retrieve addresses var address = pcapIf.Addresses; while (address != IntPtr.Zero) { // Marshal memory pointer into a sockaddr struct var addr = Marshal.PtrToStructure <pcap_addr>(address); PcapAddress newAddress = new PcapAddress(addr); Addresses.Add(newAddress); // is this a hardware address? // if so we should set our MacAddress if (newAddress.Addr?.type == Sockaddr.AddressTypes.HARDWARE) { if (MacAddress == null) { MacAddress = newAddress.Addr.hardwareAddress; } else if (!MacAddress.Equals(newAddress.Addr.hardwareAddress)) { throw new InvalidOperationException("found multiple hardware addresses, existing addr " + MacAddress.ToString() + ", new address " + newAddress.Addr.hardwareAddress.ToString()); } } address = addr.Next; // move to the next address } // attempt to populate the mac address, // friendly name etc of this device if (networkInterface != null) { var ipProperties = networkInterface.GetIPProperties(); int gatewayAddressCount = ipProperties.GatewayAddresses.Count; if (gatewayAddressCount != 0) { foreach (GatewayIPAddressInformation gatewayInfo in ipProperties.GatewayAddresses) { GatewayAddresses.Add(gatewayInfo.Address); } } FriendlyName = networkInterface.Name; PhysicalAddress mac = networkInterface.GetPhysicalAddress(); if (MacAddress == null && mac != null) { PcapAddress pcapAddress = new PcapAddress(); pcapAddress.Addr = new Sockaddr(mac); Addresses.Add(pcapAddress); if (pcapAddress.Addr.hardwareAddress.GetAddressBytes().Length != 0) { MacAddress = pcapAddress.Addr.hardwareAddress; } } } }
static private IReadOnlyList <PcapInterface> GetAllPcapInterfaces(IntPtr devicePtr, RemoteAuthentication credentials) { var list = new List <PcapInterface>(); var nics = NetworkInterface.GetAllNetworkInterfaces(); var nextDevPtr = devicePtr; while (nextDevPtr != IntPtr.Zero) { // Marshal pointer into a struct var pcap_if_unmanaged = Marshal.PtrToStructure <pcap_if>(nextDevPtr); NetworkInterface networkInterface = null; foreach (var nic in nics) { // if the name and id match then we have found the NetworkInterface // that matches the PcapDevice if (pcap_if_unmanaged.Name.EndsWith(nic.Id)) { networkInterface = nic; } } var pcap_if = new PcapInterface(pcap_if_unmanaged, networkInterface, credentials); list.Add(pcap_if); nextDevPtr = pcap_if_unmanaged.Next; } return(list); }
static public IReadOnlyList <PcapInterface> GetAllPcapInterfaces(IPEndPoint source, RemoteAuthentication credentials) { return(GetAllPcapInterfaces("rpcap://" + source, credentials)); }
internal static pcap_rmtauth CreateAuth(string source, RemoteAuthentication credentials) { if (credentials == null) { return(default);
/// <summary> /// Open the device. To start capturing call the 'StartCapture' function /// </summary> /// <param name="configuration"> /// A <see cref="DeviceConfiguration"/> /// </param> public override void Open(DeviceConfiguration configuration) { if (Opened) { return; } var credentials = configuration.Credentials ?? Interface.Credentials; var mode = configuration.Mode; // Check if immediate is supported var immediate_supported = Pcap.LibpcapVersion >= new Version(1, 5, 0); // Check if we can do immediate by setting mintocopy to 0 // See https://www.tcpdump.org/manpages/pcap_set_immediate_mode.3pcap.html var mintocopy_supported = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); var errbuf = new StringBuilder(Pcap.PCAP_ERRBUF_SIZE); //will hold errors // set the StopCaptureTimeout value to twice the read timeout to ensure that // we wait long enough before considering the capture thread to be stuck when stopping // a background capture via StopCapture() // // NOTE: Doesn't affect Mono if unix poll is available, doesn't affect Linux because // Linux devices have no timeout, they always block. Only affects Windows devices. StopCaptureTimeout = new TimeSpan(0, 0, 0, 0, configuration.ReadTimeout * 2); // modes other than OpenFlags.Promiscuous require pcap_open() var otherModes = mode & ~DeviceModes.Promiscuous; if (immediate_supported || mintocopy_supported) { // We can do MaxResponsiveness through Immediate mode otherModes &= ~DeviceModes.MaxResponsiveness; } var immediateMode = configuration.Immediate; if (mode.HasFlag(DeviceModes.MaxResponsiveness)) { immediateMode = true; } // Some configurations can only be used with pcap_create var use_pcap_create = credentials == null && (short)otherModes == 0; if (use_pcap_create) { Handle = LibPcapSafeNativeMethods.pcap_create( Name, // name of the device errbuf); // error buffer // Those are configurations that pcap_open can handle differently Configure( configuration, nameof(configuration.Snaplen), LibPcapSafeNativeMethods.pcap_set_snaplen, configuration.Snaplen ); Configure( configuration, "Promiscuous", LibPcapSafeNativeMethods.pcap_set_promisc, (int)(mode & DeviceModes.Promiscuous) ); Configure( configuration, nameof(configuration.ReadTimeout), LibPcapSafeNativeMethods.pcap_set_timeout, configuration.ReadTimeout ); } else { // We got authentication, so this is an rpcap device var auth = RemoteAuthentication.CreateAuth(credentials); // Immediate and MaxResponsiveness are the same thing if (immediateMode == true) { mode |= DeviceModes.MaxResponsiveness; } // No need to worry about it anymore immediateMode = null; try { Handle = LibPcapSafeNativeMethods.pcap_open( Name, // name of the device configuration.Snaplen, // portion of the packet to capture. (short)mode, // flags (short)configuration.ReadTimeout, // read timeout ref auth, // authentication errbuf); // error buffer } catch (TypeLoadException) { var reason = credentials != null ? "Remote PCAP" : "Requested DeviceModes"; var err = $"Unable to open the adapter '{Name}'. {reason} not supported"; throw new PcapException(err, PcapError.PlatformNotSupported); } } if (Handle.IsInvalid) { var err = $"Unable to open the adapter '{Name}'. {errbuf}"; throw new PcapException(err); } ConfigureIfCompatible(use_pcap_create, configuration, nameof(configuration.TimestampResolution), LibPcapSafeNativeMethods.pcap_set_tstamp_precision, (int?)configuration.TimestampResolution ); ConfigureIfCompatible(use_pcap_create, configuration, nameof(configuration.TimestampType), LibPcapSafeNativeMethods.pcap_set_tstamp_type, (int?)configuration.TimestampType ); ConfigureIfCompatible(use_pcap_create, configuration, nameof(configuration.Monitor), LibPcapSafeNativeMethods.pcap_set_rfmon, (int?)configuration.Monitor ); ConfigureIfCompatible(use_pcap_create, configuration, nameof(configuration.BufferSize), LibPcapSafeNativeMethods.pcap_set_buffer_size, configuration.BufferSize ); if (immediateMode.HasValue) { if (!immediate_supported && !mintocopy_supported) { configuration.RaiseConfigurationFailed( nameof(configuration.Immediate), PcapError.PlatformNotSupported, "Immediate mode not available" ); } else if (immediate_supported) { var immediate = immediateMode.Value ? 1 : 0; Configure( configuration, nameof(configuration.Immediate), LibPcapSafeNativeMethods.pcap_set_immediate_mode, immediate ); } } // pcap_open returns an already activated device if (use_pcap_create) { var activationResult = LibPcapSafeNativeMethods.pcap_activate(Handle); if (activationResult < 0) { string err = "Unable to activate the adapter (" + Name + ")."; throw new PcapException(err, activationResult); } } base.Open(configuration); // retrieve the file descriptor of the adapter for use with poll() if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { FileDescriptor = LibPcapSafeNativeMethods.pcap_get_selectable_fd(Handle); } // Below configurations must be done after the device gets activated Configure( configuration, nameof(configuration.KernelBufferSize), LibPcapSafeNativeMethods.pcap_setbuff, configuration.KernelBufferSize ); if (immediateMode == true && mintocopy_supported && !immediate_supported) { Configure( configuration, nameof(configuration.Immediate), LibPcapSafeNativeMethods.pcap_setmintocopy, 0 ); } Configure( configuration, nameof(configuration.MinToCopy), LibPcapSafeNativeMethods.pcap_setmintocopy, configuration.MinToCopy ); }
/// <summary> /// Open the device. To start capturing call the 'StartCapture' function /// </summary> /// <param name="configuration"> /// A <see cref="DeviceConfiguration"/> /// </param> public override void Open(DeviceConfiguration configuration) { var credentials = configuration.Credentials ?? Interface.Credentials; var mode = configuration.Mode; if (!Opened) { StringBuilder errbuf = new StringBuilder(Pcap.PCAP_ERRBUF_SIZE); //will hold errors // set the StopCaptureTimeout value to twice the read timeout to ensure that // we wait long enough before considering the capture thread to be stuck when stopping // a background capture via StopCapture() // // NOTE: Doesn't affect Mono if unix poll is available, doesn't affect Linux because // Linux devices have no timeout, they always block. Only affects Windows devices. StopCaptureTimeout = new TimeSpan(0, 0, 0, 0, configuration.ReadTimeout * 2); // modes other than OpenFlags.Promiscuous require pcap_open() var otherModes = mode & ~DeviceModes.Promiscuous; if ((credentials == null) || ((short)otherModes != 0) || (configuration.TimestampResolution != null)) { PcapHandle = LibPcapSafeNativeMethods.pcap_create( Name, // name of the device errbuf); // error buffer Configure( configuration, nameof(configuration.Snaplen), LibPcapSafeNativeMethods.pcap_set_snaplen, configuration.Snaplen ); Configure( configuration, "Promiscuous", LibPcapSafeNativeMethods.pcap_set_promisc, (int)(mode & DeviceModes.Promiscuous) ); Configure( configuration, nameof(configuration.ReadTimeout), LibPcapSafeNativeMethods.pcap_set_timeout, configuration.ReadTimeout ); if (configuration.TimestampResolution.HasValue) { Configure( configuration, nameof(configuration.TimestampResolution), LibPcapSafeNativeMethods.pcap_set_tstamp_precision, (int)configuration.TimestampResolution ); } if (configuration.TimestampType.HasValue) { Configure( configuration, nameof(configuration.TimestampType), LibPcapSafeNativeMethods.pcap_set_tstamp_type, (int)configuration.TimestampType ); } } else { // We got authentication, so this is an rpcap device var auth = RemoteAuthentication.CreateAuth(credentials); PcapHandle = LibPcapSafeNativeMethods.pcap_open( Name, // name of the device configuration.Snaplen, // portion of the packet to capture. (short)mode, // flags (short)configuration.ReadTimeout, // read timeout ref auth, // authentication errbuf); // error buffer } if (PcapHandle == IntPtr.Zero) { string err = "Unable to open the adapter (" + Name + "). " + errbuf.ToString(); throw new PcapException(err); } Configure( configuration, nameof(configuration.Monitor), LibPcapSafeNativeMethods.pcap_set_rfmon, (int?)configuration.Monitor ); Configure( configuration, nameof(configuration.BufferSize), LibPcapSafeNativeMethods.pcap_set_buffer_size, configuration.BufferSize ); // Check if immediate is supported var immediate_supported = Pcap.LibpcapVersion >= new Version(1, 5, 0); // Check if we can do immediate by setting mintocopy to 0 // See https://www.tcpdump.org/manpages/pcap_set_immediate_mode.3pcap.html var mintocopy_supported = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); if (configuration.Immediate.HasValue) { if (!immediate_supported && !mintocopy_supported) { configuration.RaiseConfigurationFailed( nameof(configuration.Immediate), (int)PcapError.PlatformNotSupported ); } else if (immediate_supported) { var immediate = configuration.Immediate.Value ? 1 : 0; Configure( configuration, nameof(configuration.Immediate), LibPcapSafeNativeMethods.pcap_set_immediate_mode, immediate ); } } var activationResult = LibPcapSafeNativeMethods.pcap_activate(PcapHandle); if (activationResult < 0) { string err = "Unable to activate the adapter (" + Name + "). Return code: " + activationResult.ToString(); throw new PcapException(err); } Active = true; // retrieve the file descriptor of the adapter for use with poll() if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { FileDescriptor = LibPcapSafeNativeMethods.pcap_get_selectable_fd(PcapHandle); } // Below configurations must be done after the device gets activated Configure( configuration, nameof(configuration.KernelBufferSize), LibPcapSafeNativeMethods.pcap_setbuff, configuration.KernelBufferSize ); if (configuration.Immediate == true && mintocopy_supported && !immediate_supported) { Configure( configuration, nameof(configuration.Immediate), LibPcapSafeNativeMethods.pcap_setmintocopy, 0 ); } Configure( configuration, nameof(configuration.MinToCopy), LibPcapSafeNativeMethods.pcap_setmintocopy, configuration.MinToCopy ); } }
/// <summary> /// Open the device. To start capturing call the 'StartCapture' function /// </summary> /// <param name="mode"> /// A <see cref="DeviceMode"/> /// </param> /// <param name="read_timeout"> /// A <see cref="int"/> /// </param> /// <param name="monitor_mode"> /// A <see cref="MonitorMode"/> /// </param> /// <param name="kernel_buffer_size"> /// A <see cref="uint"/> /// </param> public override void Open(DeviceMode mode, int read_timeout, MonitorMode monitor_mode, uint kernel_buffer_size) { if (!Opened) { StringBuilder errbuf = new StringBuilder(Pcap.PCAP_ERRBUF_SIZE); //will hold errors // set the StopCaptureTimeout value to twice the read timeout to ensure that // we wait long enough before considering the capture thread to be stuck when stopping // a background capture via StopCapture() // // NOTE: Doesn't affect Mono if unix poll is available, doesn't affect Linux because // Linux devices have no timeout, they always block. Only affects Windows devices. StopCaptureTimeout = new TimeSpan(0, 0, 0, 0, read_timeout * 2); if (Interface.Credentials == null) { PcapHandle = LibPcapSafeNativeMethods.pcap_create( Name, // name of the device errbuf); // error buffer } else { // We got authentication, so this is an rpcap device var auth = RemoteAuthentication.CreateAuth(Name, Interface.Credentials); PcapHandle = LibPcapSafeNativeMethods.pcap_open (Name, // name of the device Pcap.MAX_PACKET_SIZE, // portion of the packet to capture. // MAX_PACKET_SIZE (65536) grants that the whole packet will be captured on all the MACs. (short)0, // No flags here (short)read_timeout, // read timeout ref auth, // authentication errbuf); // error buffer } if (PcapHandle == IntPtr.Zero) { string err = "Unable to open the adapter (" + Name + "). " + errbuf.ToString(); throw new PcapException(err); } LibPcapSafeNativeMethods.pcap_set_snaplen(PcapHandle, Pcap.MAX_PACKET_SIZE); if (monitor_mode == MonitorMode.Active) { try { LibPcapSafeNativeMethods.pcap_set_rfmon(PcapHandle, (int)monitor_mode); } catch (EntryPointNotFoundException) { throw new PcapException("This implementation of libpcap does not support monitor mode."); } } LibPcapSafeNativeMethods.pcap_set_promisc(PcapHandle, (int)mode); LibPcapSafeNativeMethods.pcap_set_timeout(PcapHandle, read_timeout); if (kernel_buffer_size != 0) { KernelBufferSize = kernel_buffer_size; } var activationResult = LibPcapSafeNativeMethods.pcap_activate(PcapHandle); if (activationResult < 0) { string err = "Unable to activate the adapter (" + Name + "). Return code: " + activationResult.ToString(); throw new PcapException(err); } Active = true; // retrieve the file descriptor of the adapter for use with poll() if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { FileDescriptor = LibPcapSafeNativeMethods.pcap_get_selectable_fd(PcapHandle); } } }