xref: /dpdk/drivers/net/pcap/pcap_osdep_windows.c (revision b5674be414638f80bc66b465ece89401ba37512f)
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 *
iface_guid(const char * name)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
osdep_iface_index_get(const char * device_name)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
osdep_iface_mac_get(const char * device_name,struct rte_ether_addr * mac)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