-
Notifications
You must be signed in to change notification settings - Fork 544
Redo the way interface are enumerated? #169
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Related #61 |
Helpful comment listing the things libpcap gathers per interface: #26 (comment) |
I can add to this that running e.g.
( AFAICS since I modified
which relates to opening the non-existing symlink |
See #169. This still has a lot of flaws, but makes the following important changes: * Eliminates direct Registry queries for IP address info in favor of GAA * Reduces 3 calls to GAA (IsIpv4Enabled, PacketAddIP6Addresses, PacketGetAdaptersIPH) down to 1 in PacketGetAdaptersNPF. * Uses HeapAlloc instead of GlobalAlloc for the buffer used for GAA, as the old method was failing about 50% of the time in my tests. * Stashes the buffer size used for the last successful call to GAA, in order to reduce the chance of failure and realloc. * Uses GAA_FLAG_INCLUDE_ALL_INTERFACES to attempt to open all interfaces, in the hopes that future Npcap improvements may result in non-TCPIP interfaces being supported.
In libpcap,
pcap_findalldevs()
callspcap_platform_finddevs()
to find all the regular interfaces (as well as calling the "find devices" routines for various pcap "modules", if configured in), and the NPF version (in pcap-npf.c) callsPacketGetAdapterNames()
twice - once to get the size of the adapter list so that it can allocate a buffer for the list, and once to read the list into the buffer.PacketGetAdapterNames()
callsPacketPopulateAdaptersInfoList()
.PacketPopulateAdaptersInfoList()
always empties out the current list and then calls, in order:PacketGetAdaptersNPF()
;PacketGetAdaptersIPH()
;PacketAddAdapterNPF()
to add the loopback adapter, if loopback support is configured in.;PacketGetAdaptersAirpcap()
, if the AirPcap DLL is loaded;PacketGetAdaptersDag()
, if the Endace DAG card support is available;to fill in the list.
PacketGetAdaptersNPF()
digs through the Registry to find adapters; for each adapter it finds, it callsPacketAddAdapterNPF()
.PacketAddAdapterNPF()
first iterates over the list to see if it's already been added, and just returns if it has. Otherwise, it attempts to open the adapter, usingPacketOpenAdapterNPF()
and, if that succeeds, adds it. (I've omitted some details such as theINFO_FLAG_DONT_EXPORT
flag.)PacketAddAdapterNPF()
tries to find the IPv4 and IPv6 addresses for the adapter.To find the IPv4 addresses, it calls
PacketGetAddressesFromRegistry()
.PacketGetAddressesFromRegistry()
callsIsIPv4Enabled()
, which calls......
GetAdaptersAddresses()
.To get all the IPv6 addresses for the adapter, it calls
PacketAddIP6Addresses()
.PacketAddIP6Addresses()
gets the adapter's IPv6 addresses by......calling
GetAdaptersAddresses()
, looking for the adapter in the list, and getting the IPv6 addresses from that list.So we end up calling
GetAdaptersAddresses()
in this process. We end up calling it twice per interface in this process.Oh, and then
pcap_platform_finddevs()
() callspacket_add_if_npf()
per interface; that then callsPacketGetNetInfoEx()
, which again callsPacketGetAddressesFromRegistry()
andPacketAddIP6Addresses()
, so there are even more per-adapterGetAdaptersAddresses()
calls.PacketGetAdaptersIPH()
callsGetAdaptersInfo()
, which, as @akontsevoy notes in this comment on issue 26, is probably a wrapper forGetAdaptersAddresses()
since Windows XP. I'm not sure we needPacketGetAdaptersIPH()
andPacketGetAdaptersNPF()
, unless there are Npcap-usable adapters thatPacketGetAdaptersIPH()
would find butPacketGetAdaptersNPF()
wouldn't find and Npcap-usable adapters thatPacketGetAdaptersNPF()
would find butPacketGetAdaptersIPH()
would find.This code needs some work. I have a version of libpcap's pcap-npf.c where
pcap_platform_finddevs()
callsGetAdaptersAddresses()
directly and iterates once through the list it provides. Unfortunately, it currently has to callPacketOpenAdapter()
to check whether the interface is supported by Npcap, and that ends up callingPacketFindAdInfo()
, which ends up callingPacketPopulateAdaptersInfoList()
if the list is empty. That's used to determine whether the device is a regular NPF device, a DAG device, or an AirPcap device.The current master branch of libpcap includes direct support for AirPcap devices (tested on a Windows VM; it works). If we were to remove the AirPcap support from Npcap, and leave that up to libpcap, that would leave only the DAG devices. Endace currently doesn't support Windows, only Linux and FreeBSD, and libpcap already has DAG support, so that might be another case to leave up to libpcap; were Endace to support Windows again, they'll probably either contribute whatever changes are needed to pcap-dag.c or I'd nag them into doing so. :-)
So the first question is whether, were packet.dll not to provide
PacketGetAdapterNames()
at all, the list of adapters would be necessary.If not, it could be removed, and
PacketOpenAdapter()
could just try opening the device through the driver, with the new pcap-npf.c used; that would probably be significantly faster (the profiling I did with a test program that repeatedly calledpcap_findalldevs()
found a lot of the time inpcap_findalldevs()
is spent in repeated calls toGetAdaptersAddresses()
).If it is necessary, perhaps it could just be a list of names, not full interface information.
Alternatively, a
PacketGetAdapterInfo()
routine could be provided, which just hands back a buffer full ofIP_ADAPTER_ADDRESSES
structures fetched from a singleGetAdaptersAddresses()
call. It could allocate a buffer large enough for all the adapters found byGetAdaptersAddresses()
plus an extra entry, added at the beginning, for the loopback device, if present. In addition, it could adjust the "next interface" pointers so that the list in that buffer doesn't include interfaces not supported by Npcap. It would return both a pointer to the raw buffer, for the caller to hand to a packet.dll routine to free, and a pointer to the first interface supported by Npcap. That would let the caller decide what information it wants; some of the information in theIP_ADAPTER_ADDRESSES
structure wouldn't be useful topcap_findalldevs()
, but might be useful to future libpcap APIs that would return more information (e.g., many of the options in a pcapng Interface Description Block).The text was updated successfully, but these errors were encountered: