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