예제 #1
0
        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);
        }
예제 #2
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
                    );
            }
        }
예제 #3
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
                );
        }
예제 #4
0
        /// <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);
                }
            }
        }