#682342 netcfg DHCP information handling regression between Lenny and Squeeze

#682342#5
Date:
2012-07-21 20:19:00 UTC
From:
To:
I'm using PXE boot with network preseeding to perform automated Debian
installations with Lenny, Squeeze and Wheezy.

With Lenny, netcfg used the DHCP options domain-name,
domain-name-servers, and ntp-servers. With Squeeze and Wheezy, these
options seem to be ignored.

I have the following in my DHCP configuration file, dhcpd.conf:

option domain-name "training.nta-monitor.com";
option domain-name-servers ns0.training.nta-monitor.com;
option ntp-servers ntp0.training.nta-monitor.com;

And I'm using the following boot parameters in the PXE configuration file:

append vga=normal initrd=debian/lenny/i386/initrd.gz
hostname=unassigned domain=unassigned netcfg/no_default_route=true
auto=true url=http://10.0.57.1/debian/d-i/lenny/preseed.cfg
DEBCONF_DEBUG=5

For Lenny, this works fine. In particular the domain name gets set
from the DHCP "domain-name" option, the DNS servers get set from
"domain-name-servers", and the system sets the time from the NTP
server specified by the "ntp-servers" option.

For Squeeze, these boot parameters (appropriately changed to use the
Squeeze preseed URL) result in the domain name getting set to
"unassigned", the installer prompting for the DNS servers, and the
system trying to use the default Debian NTP servers (and failing
because I'm behind a proxy with no direct Internet access).

Wheezy shows the same behaviour as Squeeze.

I can specify these parameters by adding the appropriate additional
parameters to the boot options, but this is not ideal as I'd like to
store the information in the DHCP configuration so it's just in one place.

I think this is a regression in netcfg some time between Lenny and
Squeeze.

I notice the following changelog entry for netcfg 1.48:

* Refactor dhcp configuration code.

Could that be the culprit I wonder?

#682342#10
Date:
2013-05-21 18:28:09 UTC
From:
To:
We recently ran into this problem.  The expedient way to fix it is to replace the netcfg binary in the initrd with one compiled using the following patch.
--- dhcp.c 2013-01-13 08:23:24.000000000 -0500 +++ ../dhcp.c 2013-05-21 14:25:55.613957486 -0400 @@ -591,7 +591,7 @@ preseed_hostname_from_fqdn(client, buf); } - if (netcfg_get_hostname (client, "netcfg/get_hostname", hostname, 1)) { + if (netcfg_get_hostname (client, "netcfg/get_hostname", hostname, !have_domain)) { /* * Going back to POLL wouldn't make much sense. * However, it does make sense to go to the retry
#682342#15
Date:
2013-05-22 05:03:37 UTC
From:
To:
Phil, you've been one of the most active ppl on netcfg. Care to comment?
----- Forwarded message from Sean Noonan <Sean.Noonan@twosigma.com> ----- Date: Tue, 21 May 2013 18:28:09 +0000 From: Sean Noonan <Sean.Noonan@twosigma.com> To: "'682342@bugs.debian.org'" <682342@bugs.debian.org> Subject: Bug#682342: a fix for dhcp search path issues Reply-To: Sean Noonan <Sean.Noonan@twosigma.com>, 682342@bugs.debian.org X-Mailing-List: <debian-boot@lists.debian.org> archive/latest/173316 X-CRM114-Status: Good ( pR: 30.0127 ) We recently ran into this problem. The expedient way to fix it is to replace the netcfg binary in the initrd with one compiled using the following patch.
--- dhcp.c 2013-01-13 08:23:24.000000000 -0500 +++ ../dhcp.c 2013-05-21 14:25:55.613957486 -0400 @@ -591,7 +591,7 @@ preseed_hostname_from_fqdn(client, buf); } - if (netcfg_get_hostname (client, "netcfg/get_hostname", hostname, 1)) { + if (netcfg_get_hostname (client, "netcfg/get_hostname", hostname, !have_domain)) { /* * Going back to POLL wouldn't make much sense. * However, it does make sense to go to the retry
----- End forwarded message -----
#682342#18
Date:
2014-07-26 13:46:46 UTC
From:
To:
I think this patch is incomplete and still needs to strip the domain
off the hostname to preserve behavior if an FQDN is passed in with the
hostname. That way the domain name passed by DHCP will override the
domain part of the hostname.

New possible (untested) patch attached.

Kind regards
Philipp Kern

#682342#21
Date:
2014-07-26 13:46:46 UTC
From:
To:
I think this patch is incomplete and still needs to strip the domain
off the hostname to preserve behavior if an FQDN is passed in with the
hostname. That way the domain name passed by DHCP will override the
domain part of the hostname.

New possible (untested) patch attached.

Kind regards
Philipp Kern

#682342#26
Date:
2019-08-14 16:02:56 UTC
From:
To:
We are able to reproduce this issue at will in Ubuntu Bionic's installer
(not identical to Debian's, but code-wise in this path the same).
While quite a while after the last update from Philipp, we tested the
patch (netcfg_dhcp_domain.patch) after updating it to avoid a
compilation issue, we found it did fix the problem for us.

I am not sure if I can get Debian into our infrastructure to test
explicitly, but I will work on it; at the same time,  the code change
seems straightforward.

Thanks!
-Nish

#682342#31
Date:
2019-08-15 15:08:39 UTC
From:
To:
Hi,

Nishanth Aravamudan <naravamudan@digitalocean.com> (2019-08-14):

Thanks for your feedback. Care to share the fixed version? :)

I'm a little reluctant to blindly merging this patch (originally
labeled “untested”) without a go from its author. Philipp, should
I go ahead?


Cheers,

#682342#36
Date:
2019-08-16 18:34:26 UTC
From:
To:
D'oh! I'm sorry, I thought I did. The patch we tested was:

diff -Naur a/dhcp.c b/dhcp.c
--- a/dhcp.c	2017-10-10 14:01:42.000000000 +0000
+++ b/dhcp.c	2019-08-14 01:04:58.339325357 +0000
@@ -590,7 +590,7 @@
                         preseed_hostname_from_fqdn(client, buf);
                 }

-                if (netcfg_get_hostname (client, "netcfg/get_hostname", hostname, 1)) {
+                if (netcfg_get_hostname (client, "netcfg/get_hostname", hostname, !have_domain)) {
                     /*
                      * Going back to POLL wouldn't make much sense.
                      * However, it does make sense to go to the retry
diff -Naur a/netcfg-common.c b/netcfg-common.c
--- a/netcfg-common.c	2017-10-10 14:04:08.000000000 +0000
+++ b/netcfg-common.c	2019-08-13 20:01:13.606510273 +0000
@@ -1060,14 +1060,24 @@
             continue;
         }

-        if (accept_domain && (s = strchr(hostname, '.'))) {
-            di_info("Detected we have an FQDN; splitting and setting domain");
-            if (s[1] == '\0') { /* "somehostname." <- . should be ignored */
+        if ((s = strchr(hostname, '.'))) {
+            di_info("Detected an FQDN in hostname");
+            if (s[1] == '\0') {
+                /* "somehostname." <- . should be ignored */
                 *s = '\0';
-            } else { /* assume we have a valid domain name given */
-                strncpy(domain, s + 1, MAXHOSTNAMELEN);
-                debconf_set(client, "netcfg/get_domain", domain);
-                have_domain = 1;
+                di_info("Stripped trailing dot from hostname");
+            } else {
+                /* assume that the domain is valid and copy it if
+                 * accept_domain is set; just use the hostname if
+                 * it is unset
+                 */
+                if (accept_domain) {
+                    strncpy(domain, s + 1, MAXHOSTNAMELEN);
+					di_info("Setting domain to %s", domain);
+                    debconf_set(client, "netcfg/get_domain", domain);
+                    have_domain = 1;
+                }
+                /* strip the domain from the hostname */
                 *s = '\0';
             }
         }

Totally understood! I just wanted to make sure to revive this issue, as
I'd also like to get it fixed in Ubuntu! Like I said, I will do my best
to test and reproduce the fix with stock Debian.

#682342#41
Date:
2019-08-22 19:45:26 UTC
From:
To:
This needs indenting fix-up.

I think this should be fine and we're early in the release cycle to find
potential problems if there are any.

Obviously it'd be great to have a test hardness with a DHCP server
sending various bits and us verifying that netcfg did the right thing.
But I'd surprised to find the time for that myself.

Kind regards and thanks
Philipp Kern

#682342#46
Date:
2019-10-09 20:55:17 UTC
From:
To:
Thank you, fixed below, I believe.

diff -Naur a/dhcp.c b/dhcp.c
--- a/dhcp.c	2017-10-10 14:01:42.000000000 +0000
+++ b/dhcp.c	2019-08-14 01:04:58.339325357 +0000
@@ -590,7 +590,7 @@
                         preseed_hostname_from_fqdn(client, buf);
                 }

-                if (netcfg_get_hostname (client, "netcfg/get_hostname", hostname, 1)) {
+                if (netcfg_get_hostname (client, "netcfg/get_hostname", hostname, !have_domain)) {
                     /*
                      * Going back to POLL wouldn't make much sense.
                      * However, it does make sense to go to the retry
diff -Naur a/netcfg-common.c b/netcfg-common.c
--- a/netcfg-common.c	2017-10-10 14:04:08.000000000 +0000
+++ b/netcfg-common.c	2019-08-13 20:01:13.606510273 +0000
@@ -1060,14 +1060,24 @@
             continue;
         }

-        if (accept_domain && (s = strchr(hostname, '.'))) {
-            di_info("Detected we have an FQDN; splitting and setting domain");
-            if (s[1] == '\0') { /* "somehostname." <- . should be ignored */
+        if ((s = strchr(hostname, '.'))) {
+            di_info("Detected an FQDN in hostname");
+            if (s[1] == '\0') {
+                /* "somehostname." <- . should be ignored */
                 *s = '\0';
-            } else { /* assume we have a valid domain name given */
-                strncpy(domain, s + 1, MAXHOSTNAMELEN);
-                debconf_set(client, "netcfg/get_domain", domain);
-                have_domain = 1;
+                di_info("Stripped trailing dot from hostname");
+            } else {
+                /* assume that the domain is valid and copy it if
+                 * accept_domain is set; just use the hostname if
+                 * it is unset
+                 */
+                if (accept_domain) {
+                    strncpy(domain, s + 1, MAXHOSTNAMELEN);
+                    di_info("Setting domain to %s", domain);
+                    debconf_set(client, "netcfg/get_domain", domain);
+                    have_domain = 1;
+                }
+                /* strip the domain from the hostname */
                 *s = '\0';
             }
         }