Ejemplo n.º 1
0
        /// <summary>
        /// Open the device
        /// </summary>
        public override void Open(DeviceConfiguration configuration)
        {
            // set the device handle
            var has_open_dead_with_tstamp_precision_support = Pcap.LibpcapVersion >= new Version(1, 5, 1);
            var resolution = configuration.TimestampResolution ?? TimestampResolution.Microsecond;

            if (has_open_dead_with_tstamp_precision_support)
            {
                PcapHandle = LibPcapSafeNativeMethods.pcap_open_dead_with_tstamp_precision((int)configuration.LinkLayerType,
                                                                                           configuration.Snaplen,
                                                                                           (uint)resolution);
            }
            else
            {
                if (resolution != TimestampResolution.Microsecond)
                {
                    configuration.RaiseConfigurationFailed(
                        nameof(configuration.TimestampResolution),
                        (int)PcapError.PlatformNotSupported,
                        "pcap version is < 1.5.1, needs pcap_open_dead_with_tstamp_precision()"
                        );
                }

                PcapHandle = LibPcapSafeNativeMethods.pcap_open_dead((int)configuration.LinkLayerType, configuration.Snaplen);
            }

            m_pcapDumpHandle = LibPcapSafeNativeMethods.pcap_dump_open(PcapHandle, m_pcapFile);
            if (m_pcapDumpHandle == IntPtr.Zero)
            {
                throw new PcapException("Error opening dump file '" + LastError + "'");
            }

            Active = true;
        }
Ejemplo n.º 2
0
 /// <summary>
 /// Most pcap configuration functions have the signature int pcap_set_foo(pcap_t, int)
 /// This is a helper method to use them and detect/report errors
 /// </summary>
 /// <param name="configuration"></param>
 /// <param name="setter"></param>
 /// <param name="property"></param>
 /// <param name="value"></param>
 protected void Configure(
     DeviceConfiguration configuration,
     string property,
     Func <IntPtr, int, int> setter,
     int?value
     )
 {
     if (value.HasValue)
     {
         var retval = setter(PcapHandle, value.Value);
         if (retval != 0)
         {
             configuration.RaiseConfigurationFailed(property, retval);
         }
     }
 }
Ejemplo n.º 3
0
 /// <summary>
 /// Most pcap configuration functions have the signature int pcap_set_foo(pcap_t, int)
 /// those functions also set the error buffer, so we read it
 /// This is a helper method to use them and detect/report errors
 /// </summary>
 /// <param name="configuration"></param>
 /// <param name="setter"></param>
 /// <param name="property"></param>
 /// <param name="value"></param>
 protected void Configure(
     DeviceConfiguration configuration,
     string property,
     Func <PcapHandle, int, PcapError> setter,
     int?value
     )
 {
     if (value.HasValue)
     {
         var retval = setter(Handle, value.Value);
         if (retval != 0)
         {
             configuration.RaiseConfigurationFailed(property, retval, GetLastError(Handle));
         }
     }
 }
Ejemplo n.º 4
0
        /// <summary>
        /// Open the device
        /// </summary>
        public override void Open(DeviceConfiguration configuration)
        {
            // holds errors
            StringBuilder errbuf = new StringBuilder(Pcap.PCAP_ERRBUF_SIZE); //will hold errors

            PcapHandle adapterHandle;

            // Check if we need to open with a defined precision
            var has_offline_with_tstamp_precision_support = Pcap.LibpcapVersion >= new Version(1, 5, 1);
            var resolution = configuration.TimestampResolution ?? TimestampResolution.Microsecond;

            if (has_offline_with_tstamp_precision_support)
            {
                adapterHandle = LibPcapSafeNativeMethods.pcap_open_offline_with_tstamp_precision(m_pcapFile, (uint)resolution, errbuf);
            }
            else
            {
                // notify the user that they asked for a non-standard resolution but their libpcap
                // version lacks the necessary function
                if (resolution != TimestampResolution.Microsecond)
                {
                    configuration.RaiseConfigurationFailed(
                        nameof(configuration.TimestampResolution),
                        (int)PcapError.PlatformNotSupported,
                        "pcap version is < 1.5.1, needs pcap_open_offline_with_tstamp_precision()"
                        );
                }

                adapterHandle = LibPcapSafeNativeMethods.pcap_open_offline(m_pcapFile, errbuf);
            }

            // handle error
            if (adapterHandle.IsInvalid)
            {
                string err = "Unable to open offline adapter: " + errbuf.ToString();
                throw new PcapException(err);
            }

            // set the device handle
            Handle = adapterHandle;

            base.Open(configuration);
        }
Ejemplo n.º 5
0
 protected internal void ConfigureIfCompatible(
     bool compatible,
     DeviceConfiguration configuration,
     string property,
     Func <PcapHandle, int, PcapError> setter,
     int?value
     )
 {
     if (!value.HasValue)
     {
         return;
     }
     if (!compatible)
     {
         configuration.RaiseConfigurationFailed(
             property, PcapError.Generic,
             $"Can not configure {property} with current device and selected modes"
             );
     }
     else
     {
         Configure(configuration, property, setter, value);
     }
 }
Ejemplo n.º 6
0
        /// <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
                );
        }
Ejemplo n.º 7
0
        /// <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
                    );
            }
        }