static public IReadOnlyList <PcapInterface> GetAllPcapInterfaces(string source, ICredentials credentials)
        {
            var devicePtr   = IntPtr.Zero;
            var errorBuffer = new StringBuilder(Pcap.PCAP_ERRBUF_SIZE);
            var auth        = RemotePcap.CreateAuth(source, 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);
        }
        /// <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 = RemotePcap.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;
            }
        }