Пример #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
        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;
                    }
                }
            }
        }
Пример #3
0
        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);
        }
Пример #4
0
 static public IReadOnlyList <PcapInterface> GetAllPcapInterfaces(IPEndPoint source, RemoteAuthentication credentials)
 {
     return(GetAllPcapInterfaces("rpcap://" + source, credentials));
 }
Пример #5
0
 internal static pcap_rmtauth CreateAuth(string source, RemoteAuthentication credentials)
 {
     if (credentials == null)
     {
         return(default);
Пример #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
                );
        }
Пример #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
                    );
            }
        }
Пример #8
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);
                }
            }
        }