| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #include "windows_api.h" |
| 4 | |
| 5 | #include <winsock2.h> |
| 6 | #include <ws2tcpip.h> |
| 7 | #include <iphlpapi.h> |
| 8 | #include <stdlib.h> |
| 9 | #include <string.h> |
| 10 | #include <stdbool.h> |
| 11 | |
| 12 | |
| 13 | struct netdata_windows_ip_labels { |
| 14 | char *local_iface; |
| 15 | char *ipaddr; |
| 16 | bool initialized; |
| 17 | } default_ip = { |
| 18 | .local_iface = NULL, |
| 19 | .ipaddr = NULL, |
| 20 | .initialized = false |
| 21 | }; |
| 22 | |
| 23 | int netdata_fill_default_ip() |
| 24 | { |
| 25 | if (default_ip.initialized) |
| 26 | return 0; |
| 27 | |
| 28 | default_ip.initialized = true; |
| 29 | |
| 30 | MIB_IPFORWARDROW route; |
| 31 | DWORD dest = 0; |
| 32 | if (GetBestRoute(dest, 0, &route) != NO_ERROR) { |
| 33 | return -1; |
| 34 | } |
| 35 | |
| 36 | DWORD ifIndex = route.dwForwardIfIndex; |
| 37 | |
| 38 | ULONG bufLen = 15000; |
| 39 | PIP_ADAPTER_ADDRESSES adapters = (PIP_ADAPTER_ADDRESSES)malloc(bufLen); |
| 40 | if (!adapters) { |
| 41 | return 1; |
| 42 | } |
| 43 | |
| 44 | int ret = GetAdaptersAddresses(AF_INET, GAA_FLAG_INCLUDE_PREFIX, NULL, adapters, &bufLen); |
| 45 | if (ret != NO_ERROR) { |
| 46 | goto end_ip_detection; |
| 47 | } |
| 48 | |
| 49 | PIP_ADAPTER_ADDRESSES aa = adapters; |
| 50 | while (aa) { |
| 51 | if (aa->IfIndex == ifIndex) { |
| 52 | char iface[1024]; |
| 53 | size_t required_size = wcstombs(NULL , aa->FriendlyName, 0) + 1; |
| 54 | wcstombs(iface, aa->FriendlyName, required_size); |
| 55 | default_ip.local_iface = strdup(iface); |
| 56 | |
| 57 | PIP_ADAPTER_UNICAST_ADDRESS ua = aa->FirstUnicastAddress; |
| 58 | while (ua) { |
| 59 | if (ua->Address.lpSockaddr->sa_family == AF_INET) { |
| 60 | char ipstr[INET_ADDRSTRLEN]; |
| 61 | struct sockaddr_in *sa_in = (struct sockaddr_in *)ua->Address.lpSockaddr; |
| 62 | inet_ntop(AF_INET, &(sa_in->sin_addr), ipstr, sizeof(ipstr)); |
| 63 | default_ip.ipaddr = strdup(ipstr); |
| 64 | goto end_ip_detection; |
| 65 | } |
| 66 | ua = ua->Next; |
| 67 | } |
| 68 | break; |
| 69 | } |
| 70 | aa = aa->Next; |
| 71 | } |
| 72 | |
| 73 | ret = NO_ERROR; |
| 74 | end_ip_detection: |
| 75 | free(adapters); |
| 76 | return ret; |
| 77 | } |
| 78 | |
| 79 | char *netdata_win_local_interface() |
| 80 | { |
| 81 | if (!default_ip.initialized) |
| 82 | netdata_fill_default_ip(); |
| 83 | |
| 84 | return default_ip.local_iface; |
| 85 | } |
| 86 | |
| 87 | char *netdata_win_local_ip() |
| 88 | { |
| 89 | if (!default_ip.initialized) |
| 90 | netdata_fill_default_ip(); |
| 91 | |
| 92 | return default_ip.ipaddr; |
| 93 | } |