From 5186fb7ebd21404e6c3c373d4fb271aa8195e242 Mon Sep 17 00:00:00 2001 From: Rob Gill Date: Thu, 31 Jan 2019 17:12:50 +1000 Subject: [PATCH] Network: Avoid DHCP over-writing user specified DNS settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Adds parser to servers/net/nethost, to check current settings in resolv.conf before updating If user has specified DNS settings manually, DHCP derived settings are appended to resolv.conf, rather than overwriting. (If no user specified data is present, or in the event of a badly damaged resolv.conf, DHCP over-writes file in same manner as prior to this change) Fixes #11565. Change-Id: I43464909009d2416d57f66f7bd14d13c81f803e7 Reviewed-on: https://review.haiku-os.org/c/997 Reviewed-by: Axel Dörfler Reviewed-by: Stephan Aßmus --- .../dnsclient/DNSSettingsView.cpp | 4 +- src/servers/net/NetServer.cpp | 73 +++++++++++++++---- 2 files changed, 61 insertions(+), 16 deletions(-) diff --git a/src/add-ons/network_settings/dnsclient/DNSSettingsView.cpp b/src/add-ons/network_settings/dnsclient/DNSSettingsView.cpp index 131ec34552..0e91851fb4 100644 --- a/src/add-ons/network_settings/dnsclient/DNSSettingsView.cpp +++ b/src/add-ons/network_settings/dnsclient/DNSSettingsView.cpp @@ -233,7 +233,7 @@ DNSSettingsView::_SaveDNSConfiguration() return file.InitCheck(); } - BString content("# Generated by Network preferences\n"); + BString content("# Static DNS entries\n# Generated by Network preferences\n"); for (int i = 0; i < fServerListView->CountItems(); i++) { BString item = ((BStringItem*)fServerListView->ItemAt(i))->Text(); @@ -244,5 +244,7 @@ DNSSettingsView::_SaveDNSConfiguration() if (strlen(fDomain->Text()) > 0) content << "domain\t" << fDomain->Text() << "\n"; + content << "# Dynamic DNS entries\n# may be altered by DHCP\n"; + return file.Write(content.String(), content.Length()); } diff --git a/src/servers/net/NetServer.cpp b/src/servers/net/NetServer.cpp index 75893933b6..90ffe4fe47 100644 --- a/src/servers/net/NetServer.cpp +++ b/src/servers/net/NetServer.cpp @@ -598,30 +598,73 @@ NetServer::_ConfigureInterface(BMessage& message) status_t NetServer::_ConfigureResolver(BMessage& resolverConfiguration) { - // TODO: resolv.conf should be parsed, all information should be - // maintained and it should be distinguished between user entered - // and auto-generated parts of the file, with this method only re-writing - // the auto-generated parts of course. + // Store resolver settings in resolv.conf file, while maintaining any + // user specified settings already present. BPath path; if (find_directory(B_SYSTEM_SETTINGS_DIRECTORY, &path) != B_OK || path.Append("network/resolv.conf") != B_OK) return B_ERROR; - FILE* file = fopen(path.Path(), "w"); - if (file != NULL) { - const char* nameserver; - for (int32 i = 0; resolverConfiguration.FindString("nameserver", i, - &nameserver) == B_OK; i++) { - fprintf(file, "nameserver %s\n", nameserver); + FILE* file = fopen(path.Path(), "r+"); + // open existing resolv.conf if possible + if (file == NULL) { + // no existing resolv.conf, create a new one + file = fopen(path.Path(), "w"); + if (file == NULL) { + fprintf(stderr, "Could not open resolv.conf: %s\n", + strerror(errno)); + return errno; + } + } else { + // An existing resolv.conf was found, parse it for user settings + const char* staticDNS = "# Static DNS Only"; + size_t sizeStaticDNS = strlen(staticDNS); + const char* dynamicDNS = "# Dynamic DNS entries"; + size_t sizeDynamicDNS = strlen(dynamicDNS); + char resolveConfBuffer[80]; + size_t sizeResolveConfBuffer = sizeof(resolveConfBuffer); + + while (fgets(resolveConfBuffer, sizeResolveConfBuffer, file)) { + if (strncmp(resolveConfBuffer, staticDNS, sizeStaticDNS) == 0) { + // If DNS is set to static only, don't modify + fclose(file); + return B_OK; + } else if (strncmp(resolveConfBuffer, dynamicDNS, sizeDynamicDNS) + == 0) { + // Overwrite existing dynamic entries + break; + } } - const char* domain; - if (resolverConfiguration.FindString("domain", &domain) == B_OK) - fprintf(file, "domain %s\n", domain); - - fclose(file); + if (feof(file) != 0) { + // No static entries found, close and re-open as new file + fclose(file); + file = fopen(path.Path(), "w"); + if (file == NULL) { + fprintf(stderr, "Could not open resolv.conf: %s\n", + strerror(errno)); + return errno; + } + } } + + fprintf(file, "# Added automatically by DHCP\n"); + + const char* nameserver; + for (int32 i = 0; resolverConfiguration.FindString("nameserver", i, + &nameserver) == B_OK; i++) { + fprintf(file, "nameserver %s\n", nameserver); + } + + const char* domain; + if (resolverConfiguration.FindString("domain", &domain) == B_OK) + fprintf(file, "domain %s\n", domain); + + fprintf(file, "# End of automatic DHCP additions\n"); + + fclose(file); + return B_OK; }