diff --git a/libdnet-stripped/include/dnet/intf.h b/libdnet-stripped/include/dnet/intf.h index 68d6d2f6a..3d1939f12 100644 --- a/libdnet-stripped/include/dnet/intf.h +++ b/libdnet-stripped/include/dnet/intf.h @@ -60,6 +60,7 @@ intf_t *intf_open(void); int intf_get(intf_t *i, struct intf_entry *entry); int intf_get_src(intf_t *i, struct intf_entry *entry, struct addr *src); int intf_get_dst(intf_t *i, struct intf_entry *entry, struct addr *dst); +int intf_get_pcap_devname(const char *intf_name, char *pcapdev, int pcapdevlen); int intf_set(intf_t *i, const struct intf_entry *entry); int intf_loop(intf_t *i, intf_handler callback, void *arg); intf_t *intf_close(intf_t *i); diff --git a/libdnet-stripped/src/eth-win32.c b/libdnet-stripped/src/eth-win32.c index a767a8e6d..9cbb3f9f4 100644 --- a/libdnet-stripped/src/eth-win32.c +++ b/libdnet-stripped/src/eth-win32.c @@ -34,56 +34,25 @@ eth_t * eth_open(const char *device) { eth_t *eth; - intf_t *intf; - struct intf_entry ifent; - eth_addr_t ea; - char *p, *buf; - ULONG len; + char pcapdev[128]; - /* Get interface entry. */ - memset(&ifent, 0, sizeof(ifent)); - if ((intf = intf_open()) != NULL) { - strlcpy(ifent.intf_name, device, sizeof(ifent.intf_name)); - intf_get(intf, &ifent); - intf_close(intf); - } - if (ifent.intf_link_addr.addr_type != ADDR_TYPE_ETH) + if (eth_get_pcap_devname(device, pcapdev, sizeof(pcapdev)) != 0) return (NULL); - /* Get Packet driver adapter name/desc lists. */ - buf = NULL; - PacketGetAdapterNames(buf, &len); - if (len > 0 && (buf = malloc(len)) != NULL) { - if (!PacketGetAdapterNames(buf, &len)) { - free(buf); - buf = NULL; - } - } - if (buf == NULL) + if ((eth = calloc(1, sizeof(*eth))) == NULL) return (NULL); - - /* XXX - find adapter with matching interface MAC address. */ - if ((eth = calloc(1, sizeof(*eth))) == NULL) { - free(buf); + eth->lpa = PacketOpenAdapter(pcapdev); + if (eth->lpa == NULL) { + eth_close(eth); return (NULL); } - for (p = buf; *p != '\0'; p += strlen(p) + 1) { - if ((eth->lpa = PacketOpenAdapter(p)) != NULL) { - if (eth->lpa->hFile != INVALID_HANDLE_VALUE && - eth_get(eth, &ea) == 0 && - memcmp(&ea, &ifent.intf_link_addr.addr_eth, - ETH_ADDR_LEN) == 0) { - PacketSetBuff(eth->lpa, 512000); - eth->pkt = PacketAllocatePacket(); - break; - } - PacketCloseAdapter(eth->lpa); - } + PacketSetBuff(eth->lpa, 512000); + eth->pkt = PacketAllocatePacket(); + if (eth->pkt == NULL) { + eth_close(eth); + return NULL; } - free(buf); - if (eth->pkt == NULL) - eth = eth_close(eth); - + return (eth); } @@ -142,61 +111,8 @@ eth_set(eth_t *eth, const eth_addr_t *ea) return (-1); } - -/* Converts a dnet interface name (ifname) to its pcap equivalent, which is stored in -pcapdev (up to a length of pcapdevlen). Returns 0 and fills in pcapdev if successful. */ -int eth_get_pcap_devname(const char *ifname, char *pcapdev, int pcapdevlen) { - intf_t *intf; - struct intf_entry ie; - pcap_if_t *pcapdevs; - pcap_if_t *pdev; - char pname[128]; - - if ((intf = intf_open()) == NULL) - return -1; - - pname[0] = '\0'; - memset(&ie, 0, sizeof(ie)); - strlcpy(ie.intf_name, ifname, sizeof(ie.intf_name)); - if (intf_get(intf, &ie) != 0) { - intf_close(intf); - return -1; - } - intf_close(intf); - - /* Next we must find the pcap device name corresponding to the device. - The device description used to be compared with those from PacketGetAdapterNames(), but - that was unrelaible because dnet and pcap sometimes give different descriptions. For example, - dnet gave me "AMD PCNET Family PCI Ethernet Adapter - Packet Scheduler Miniport" for one of my - adapters (in vmware), while pcap described it as "VMware Accelerated AMD PCNet Adapter (Microsoft's - Packet Scheduler)". Then IP addresses used to be compared, but that proved to be unreliable - as well. Now we compare hardware addresses much like eth_open() does */ - if (pcap_findalldevs(&pcapdevs, NULL) == -1) - return -1; - - if (pname[0] == '\0' && ie.intf_link_addr.addr_type == ADDR_TYPE_ETH) { - for(pdev=pcapdevs; pdev && !pname[0]; pdev = pdev->next) { - eth_t eth; - eth_addr_t ea; - - eth.lpa = PacketOpenAdapter(pdev->name); - if (eth.lpa == NULL) - continue; - if (eth.lpa->hFile != INVALID_HANDLE_VALUE && - eth_get(ð, &ea) == 0 && - memcmp(&ea, &ie.intf_link_addr.addr_eth, - ETH_ADDR_LEN) == 0) { - /* Found it -- Yay! */ - strlcpy(pname, pdev->name, sizeof(pname)); - } - PacketCloseAdapter(eth.lpa); - } - } - - pcap_freealldevs(pcapdevs); - if (pname[0]) { - strlcpy(pcapdev, pname, pcapdevlen); - return 0; - } - return -1; +int +eth_get_pcap_devname(const char *intf_name, char *pcapdev, int pcapdevlen) +{ + return intf_get_pcap_devname(intf_name, pcapdev, pcapdevlen); } diff --git a/libdnet-stripped/src/intf-win32.c b/libdnet-stripped/src/intf-win32.c index c19edcb1c..d81fbf4cb 100644 --- a/libdnet-stripped/src/intf-win32.c +++ b/libdnet-stripped/src/intf-win32.c @@ -21,6 +21,9 @@ #include #include "dnet.h" +#include "pcap.h" +#include +#include struct ifcombo { DWORD *idx; @@ -384,3 +387,89 @@ intf_close(intf_t *intf) } return (NULL); } + +/* Converts a libdnet interface name to its pcap equivalent. The pcap name is + stored in pcapdev up to a length of pcapdevlen, including the terminating + '\0'. Returns -1 on error. */ +int +intf_get_pcap_devname(const char *intf_name, char *pcapdev, int pcapdevlen) +{ + wchar_t descr_wc[512]; + pcap_if_t *pcapdevs; + pcap_if_t *pdev; + intf_t *intf; + MIB_IFROW ifrow; + + if ((intf = intf_open()) == NULL) + return (-1); + if (_refresh_tables(intf) < 0) { + intf_close(intf); + return (-1); + } + ifrow.dwIndex = _find_ifindex(intf, intf_name); + intf_close(intf); + + if (GetIfEntry(&ifrow) != NO_ERROR) + return (-1); + + /* OID_GEN_FRIENDLY_NAME returns a wide-character string, so convert + the description to wide characters for string comparison. */ + mbstowcs(descr_wc, ifrow.bDescr, sizeof(descr_wc) / sizeof(descr_wc[0]) - 1); + descr_wc[sizeof(descr_wc) / sizeof(descr_wc[0]) - 1] = L'\0'; + + if (pcap_findalldevs(&pcapdevs, NULL) == -1) + return (-1); + + /* Loop through all the pcap devices until we find a match. pcap gets + its interface list from the registry; dnet gets it from GetIfList. + We must match them up using values common to both data sets. We do + it by comparing hardware addresses and interface descriptions. */ + for (pdev = pcapdevs; pdev != NULL; pdev = pdev->next) { + PACKET_OID_DATA *data; + u_char buf[512]; + LPADAPTER lpa; + + lpa = PacketOpenAdapter(pdev->name); + if (lpa == NULL) + continue; + if (lpa->hFile == INVALID_HANDLE_VALUE) + goto close_adapter; + + data = (PACKET_OID_DATA *) buf; + + /* Check the MAC address if available. */ + data->Oid = OID_802_3_CURRENT_ADDRESS; + data->Length = sizeof(buf) - sizeof(*data); + if (PacketRequest(lpa, FALSE, data) == TRUE) { + if (data->Length != ifrow.dwPhysAddrLen) + goto close_adapter; + if (memcmp(ifrow.bPhysAddr, data->Data, data->Length) != 0) + goto close_adapter; + } + + /* Distinct interfaces can have the same MAC address in the + case of "teamed" interfaces. Additionally check the + description string. */ + data->Oid = OID_GEN_FRIENDLY_NAME; + data->Length = sizeof(buf) - sizeof(*data); + if (PacketRequest(lpa, FALSE, data) != TRUE) + goto close_adapter; + if (wcscmp(descr_wc, (wchar_t *) data->Data) != 0) + goto close_adapter; + + /* Found it. */ + PacketCloseAdapter(lpa); + break; + +close_adapter: + PacketCloseAdapter(lpa); + } + + if (pdev != NULL) + strlcpy(pcapdev, pdev->name, pcapdevlen); + pcap_freealldevs(pcapdevs); + if (pdev == NULL) + return -1; + else + return 0; +}