Skip to content

Derive the DHCP subnet from the FOG address, not the interface (GH-1747) - #1753

Merged
mastacontrola merged 1 commit into
dev-branchfrom
fix/1747-subnet-dev
Sep 10, 2026
Merged

Derive the DHCP subnet from the FOG address, not the interface (GH-1747)#1753
mastacontrola merged 1 commit into
dev-branchfrom
fix/1747-subnet-dev

Conversation

@mastacontrola

Copy link
Copy Markdown
Member

Problem

On an interface with more than one IPv4 address, the installer writes a DHCP subnet that is not a network. #1747 shows a saved mask of 255.255.0.0 on a /24, a Kea subnet of "10.0.45.2/24", a pool starting at .12, and arithmetic syntax error ... /8 during interface selection.

Cause

Each helper reads "the interface" and takes a different address from it:

Where What it took
input.sh every inet address, link-local 169.254.x.x included, so a link-local address listed first became the primary
getCidr() the second global address's prefix (head -n2 | tail -n1), through an unanchored grep, so eth1 also read eth10
configureDHCP, writeKeaSample every global address, unquoted, into mask2network, so a second address became the mask
interface2broadcast() the first brd, whichever address it belonged to

A second address in the same /24 gives exactly the reported config. 10.0.45.2 with 10.0.45.14 gives the network 10.0.45.2. A global 169.254.x.x/16 next to the /24 gives the saved 255.255.0.0. A link-local-only NIC gives the /8 error.

Fix

Everything derives from $ipaddress, the address FOG advertises as next-server.

  • input.sh takes global addresses only, and never 169.254.0.0/16.
  • getCidr IFACE [ADDR] and interface2broadcast IFACE [ADDR] read the named address on that interface only.
  • configureDHCP and writeKeaSample compute the network from $ipaddress.
  • cidr2mask with no prefix returns nothing, instead of printing the arithmetic error.
  • mask2cidr: the 224) case was a string append, so a /27 mask came out as 243. Its error message now goes to stderr instead of into the caller's value.
  • The ifconfig fallback in input.sh is removed. It stored a prefix length in $submask, and ifconfig is not installed before the package step.

Behavior change: with -y, an interface with no usable address now exits. It used to repeat the same answer forever.

Test

tests/installer-subnet-detection.test.sh replays address layouts through the real functions and the real input.sh lines. The fake ip prints real ip -o output.

  • On the old code: 14 passed, 33 failed. It reproduces the report exactly.
  • After the fix: 47 passed, 0 failed.

The same fix for working-1.6 is in a separate PR.

Refs #1747

🤖 Generated with Claude Code

https://claude.ai/code/session_012JsEqysRdWb914YC94Shvo

On an interface with more than one IPv4 address, the installer wrote a
DHCP subnet that was not a network. The report shows a saved mask of
255.255.0.0 on a /24, a Kea subnet of "10.0.45.2/24", a pool starting at
.12, and "arithmetic syntax error ... /8" during interface selection.

Each helper took "the interface" and read a different address from it:

- input.sh took every inet address, link-local 169.254.x.x included.
  Listed first, a link-local address became the primary.
- getCidr() printed the SECOND global address's prefix
  (head -n2 | tail -n1), through an unanchored grep, so eth1 also read
  eth10. A global 169.254.x.x/16 next to a /24 gave 255.255.0.0.
- configureDHCP and writeKeaSample passed every global address, unquoted,
  to mask2network, so a second address became the mask. 10.0.45.2 with
  10.0.45.14 gave the network 10.0.45.2.
- interface2broadcast() took the first brd, whichever address it
  belonged to.

Now everything derives from $ipaddress, the address FOG advertises as
next-server:

- input.sh takes global addresses only, and never 169.254.0.0/16.
- getCidr IFACE [ADDR] prints the prefix of ADDR, or of the first global
  address. It reads only that interface.
- interface2broadcast IFACE [ADDR] prints the brd of ADDR.
- configureDHCP and writeKeaSample use $ipaddress for the network.

Also:

- cidr2mask with no prefix returns nothing instead of printing the /8
  arithmetic error.
- mask2cidr: "224)" had `let` and `nbits+=3` on separate lines, a string
  append, so a /27 mask came out as 243. Its error message went to
  stdout, where every caller takes the value as the prefix; it now goes
  to stderr.
- The ifconfig fallback in input.sh is removed. It stored mask2cidr's
  prefix length in $submask, and ifconfig is not installed before the
  package step. An empty mask is derived again in configureDHCP.
- With -y, an interface with no usable address now exits. It used to
  repeat the same answer forever, and the link-local filter adds a way
  to reach that path.

tests/installer-subnet-detection.test.sh replays address layouts through
the real functions and the real input.sh lines, with a fake `ip` built
from real `ip -o` output. On the old code it fails 33 of 47 checks and
reproduces the report: "10.0.45.2/24", pool "10.0.45.12 - 10.0.45.254",
the saved 255.255.0.0, and the /8 error. It passes all 47 after.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012JsEqysRdWb914YC94Shvo
@mastacontrola
mastacontrola merged commit a7c16bd into dev-branch Sep 10, 2026
8 checks passed
@mastacontrola
mastacontrola deleted the fix/1747-subnet-dev branch September 10, 2026 12:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant