/// <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="System.Int32"/> /// </param> /// <param name="monitor_mode"> /// A <see cref="MonitorMode"/> /// </param> /// <param name="kernel_buffer_size"> /// A <see cref="System.UInt32"/> /// </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); PcapHandle = LibPcapSafeNativeMethods.pcap_create( Name, // name of the device 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 (System.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; } }
/// <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="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="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); } } }