From: Oliver Kurth Date: Wed, 11 Dec 2019 18:19:09 +0000 (-0800) Subject: nicinfo: report real nameservers used when using systemd-resolved X-Git-Tag: stable-11.0.5~4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e6bc102b12eb346eb0c77feca50ff185994bbcab;p=thirdparty%2Fopen-vm-tools.git nicinfo: report real nameservers used when using systemd-resolved If systemd-resolved is used, report the external DNS server, not the locally installed one. This is detected by checking if /etc/resolv.conf is a link to /run/systemd/resolve/stub-resolv.conf. In that case, /run/systemd/resolve/resolv.conf will hold the actual DNS server. See https://www.freedesktop.org/software/systemd/man/systemd-resolved.service.html --- diff --git a/open-vm-tools/lib/nicInfo/nicInfoPosix.c b/open-vm-tools/lib/nicInfo/nicInfoPosix.c index e661993b3..3363f3ac2 100644 --- a/open-vm-tools/lib/nicInfo/nicInfoPosix.c +++ b/open-vm-tools/lib/nicInfo/nicInfoPosix.c @@ -34,6 +34,7 @@ #include #include #include +#include #if defined(__FreeBSD__) || defined(__APPLE__) # include # include @@ -903,6 +904,63 @@ fail: return FALSE; } +/* + ****************************************************************************** + * RecordResolverNSResolvConf */ /** + * + * @brief Parses file in resolv.conf format, and copies name servers to + * @a dnsConfigInfo. + * + * @param[in] file path of file to read + * @param[out] dnsConfigInfo Destination DnsConfigInfo container + * + ****************************************************************************** + */ + +static void +RecordResolverNSResolvConf(const char *file, DnsConfigInfo *dnsConfigInfo) +{ + FILE *fptr; + + fptr = fopen(file, "rt"); + if (fptr != NULL) { + char line[256]; + while (fgets(line, sizeof(line), fptr)) { + char *tok, *saveptr = NULL; + tok = strtok_r(line, " \t", &saveptr); + if ((tok != NULL) && (strcmp(tok, "nameserver") == 0)) { + char *val; + struct sockaddr_in sa4; + struct sockaddr_in6 sa6; + val = strtok_r(NULL, " \t\r\n", &saveptr); + if (val == NULL) { + g_warning("%s: no value for nameserver in %s\n", + __FUNCTION__, file); + } else if (inet_pton(AF_INET, val, &sa4.sin_addr)) { + sa4.sin_family = AF_INET; + if (0 == AddResolverNSInfo(dnsConfigInfo, + (struct sockaddr *) &sa4)) { + /* Can't add more DNS entries to dnsConfigInfo, break loop */ + break; + } + } else if (inet_pton(AF_INET6, val, &sa6.sin6_addr)) { + sa6.sin6_family = AF_INET6; + if (0 == AddResolverNSInfo(dnsConfigInfo, + (struct sockaddr *) &sa6)) { + /* Can't add more DNS entries to dnsConfigInfo, break loop */ + break; + } + } else { + g_warning("%s: invalid IP address '%s' in %s ignored\n", + __FUNCTION__, val, file); + } + } + } + fclose(fptr); + } else { + g_warning("%s: could not open file '%s': %s\n", __FUNCTION__, file, strerror(errno)); + } +} /* ****************************************************************************** @@ -921,6 +979,28 @@ static void RecordResolverNS(res_state resp, DnsConfigInfo *dnsConfigInfo) // IN { int i; + char resolvConf[PATH_MAX]; + + /* + * If systemd-resolved is used we want to report the external DNS + * server, not the locally installed one. We detect this by checking + * if /etc/resolv.conf is a link to /run/systemd/resolve/stub-resolv.conf. + * In that case, /run/systemd/resolve/resolv.conf will hold the actual + * DNS server. See + * https://www.freedesktop.org/software/systemd/man/systemd-resolved.service.html + */ + if (realpath("/etc/resolv.conf", resolvConf) != NULL) { + if (strcmp(resolvConf, "/run/systemd/resolve/stub-resolv.conf") == 0) { + const char *file = "/run/systemd/resolve/resolv.conf"; + if (access(file, R_OK) != -1) { + RecordResolverNSResolvConf(file, dnsConfigInfo); + return; + } else { + g_debug("%s: could not access %s for reading: %s\n", + __FUNCTION__, file, strerror(errno)); + } + } + } #if defined RESOLVER_IPV6_GETSERVERS {