1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) 2021 Dmitry Kozlyuk 3 */ 4 5 #include <winsock2.h> 6 #include <iphlpapi.h> 7 #include <strsafe.h> 8 9 #include "pcap_osdep.h" 10 11 /* 12 * Given a device name like "\Device\NPF_{GUID}" extract the "{GUID}" part. 13 * Return NULL if "{GUID}" part is not found. 14 */ 15 static const char * 16 iface_guid(const char *name) 17 { 18 static const size_t GUID_LENGTH = 32 + 4; /* 16 hex bytes + 4 dashes */ 19 20 const char *ob, *cb; 21 22 ob = strchr(name, '{'); 23 if (ob == NULL) 24 return NULL; 25 26 cb = strchr(ob, '}'); 27 if (cb == NULL || cb - ob != GUID_LENGTH + 1) /* + 1 opening '{' */ 28 return NULL; 29 30 return ob; 31 } 32 33 /* 34 * libpcap takes device names like "\Device\NPF_{GUID}", 35 * GetAdapterIndex() takes interface names like "\DEVICE\TCPIP_{GUID}". 36 * Try to convert, fall back to original device name. 37 */ 38 int 39 osdep_iface_index_get(const char *device_name) 40 { 41 WCHAR adapter_name[MAX_ADAPTER_NAME_LENGTH]; 42 const char *guid; 43 ULONG index; 44 DWORD ret; 45 46 guid = iface_guid(device_name); 47 if (guid != NULL) 48 StringCbPrintfW(adapter_name, sizeof(adapter_name), 49 L"\\DEVICE\\TCPIP_%S", guid); 50 else 51 StringCbPrintfW(adapter_name, sizeof(adapter_name), 52 L"%S", device_name); 53 54 ret = GetAdapterIndex(adapter_name, &index); 55 if (ret != NO_ERROR) { 56 PMD_LOG(ERR, "GetAdapterIndex(%S) = %lu\n", adapter_name, ret); 57 return -1; 58 } 59 60 return index; 61 } 62 63 /* 64 * libpcap takes device names like "\Device\NPF_{GUID}", 65 * GetAdaptersAddresses() returns names in "{GUID}" form. 66 * Try to extract GUID from device name, fall back to original device name. 67 */ 68 int 69 osdep_iface_mac_get(const char *device_name, struct rte_ether_addr *mac) 70 { 71 IP_ADAPTER_ADDRESSES *info = NULL, *cur = NULL; 72 ULONG size, sys_ret; 73 const char *adapter_name; 74 int ret = -1; 75 76 sys_ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &size); 77 if (sys_ret != ERROR_BUFFER_OVERFLOW) { 78 PMD_LOG(ERR, "GetAdapterAddresses() = %lu, expected %lu\n", 79 sys_ret, ERROR_BUFFER_OVERFLOW); 80 return -1; 81 } 82 83 info = (IP_ADAPTER_ADDRESSES *)malloc(size); 84 if (info == NULL) { 85 PMD_LOG(ERR, "Cannot allocate adapter address info\n"); 86 return -1; 87 } 88 89 sys_ret = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, info, &size); 90 if (sys_ret != ERROR_SUCCESS) { 91 PMD_LOG(ERR, "GetAdapterAddresses() = %lu\n", sys_ret); 92 free(info); 93 return -1; 94 } 95 96 adapter_name = iface_guid(device_name); 97 if (adapter_name == NULL) 98 adapter_name = device_name; 99 100 for (cur = info; cur != NULL; cur = cur->Next) { 101 if (strcmp(cur->AdapterName, adapter_name) == 0) { 102 if (cur->PhysicalAddressLength != RTE_ETHER_ADDR_LEN) { 103 PMD_LOG(ERR, "Physical address length: want %u, got %lu", 104 RTE_ETHER_ADDR_LEN, 105 cur->PhysicalAddressLength); 106 break; 107 } 108 109 memcpy(mac->addr_bytes, cur->PhysicalAddress, 110 RTE_ETHER_ADDR_LEN); 111 ret = 0; 112 break; 113 } 114 } 115 116 free(info); 117 return ret; 118 } 119