Skip to content

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

Merged
mastacontrola merged 1 commit into
working-1.6from
fix/1747-subnet
Sep 10, 2026
Merged

Derive the DHCP subnet from the FOG address, not the interface (GH-1747)#1754
mastacontrola merged 1 commit into
working-1.6from
fix/1747-subnet

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.

This is the working-1.6 side of #1753, which fixed dev-branch.

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
writeKeaSample every global address, unquoted, into mask2network, so a second address became the mask
configureDHCP the first global address, which is not always ${NET_fog_server_ip}
interface2broadcast() the first brd, whichever address it belonged to

A second address in the same /24 gives exactly the reported config. 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 ${NET_fog_server_ip}, 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. Both stay awk, so they work with busybox (Installer support for Alpine Linux as host OS #863).
  • configureDHCP and writeKeaSample compute the network from ${NET_fog_server_ip}.
  • cidr2mask with no prefix returns nothing, instead of printing the arithmetic error.
  • mask2cidr sends its error message to stderr instead of into the caller's value.
  • The ifconfig fallbacks in input.sh and configureDHCP are removed. ifconfig is not installed before the package step, and the input.sh one stored a prefix length as the mask.

Behavior changes

  • With -y, an interface with no usable address now exits. It used to repeat the same answer forever.
  • Default storage group trust. storageDefaultCidr now takes the prefix of ${NET_fog_server_ip}. On a multi-address interface it used to take the second address's prefix and apply it to the FOG address. On an interface with one address, nothing changes. This is the trusted CIDR for node-to-node status calls, so this PR is a draft until that change is approved.

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: 21 passed, 37 failed. It reproduces the report exactly.
  • After the fix: 58 passed, 0 failed.
  • Alpine: the helpers ran against busybox ip and awk on a dummy interface with the same addresses, with the same results.

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.
- 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.
- configureDHCP took the first global address, which is not always
  ${NET_fog_server_ip}.
- interface2broadcast() took the first brd, whichever address it
  belonged to.

Now everything derives from ${NET_fog_server_ip}, 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. It keeps awk:
  busybox grep has no -P (#863).
- configureDHCP and writeKeaSample use ${NET_fog_server_ip}.
- The default storage group's trusted CIDR takes the prefix of
  ${NET_fog_server_ip}. On a multi-address interface it used to take
  the second address's prefix and apply it to the FOG address.

Also:

- cidr2mask with no prefix returns nothing instead of printing the /8
  arithmetic error.
- mask2cidr's error message went to stdout, where every caller takes the
  value as the prefix. It now goes to stderr.
- The ifconfig fallbacks in input.sh and configureDHCP are removed. The
  input.sh one stored mask2cidr's prefix length in ${NET_subnet_mask},
  and ifconfig is not installed before the package step.
- 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 37 of 58 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 58 after.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012JsEqysRdWb914YC94Shvo
@mastacontrola
mastacontrola marked this pull request as ready for review September 10, 2026 12:43
@mastacontrola
mastacontrola added this pull request to the merge queue Sep 10, 2026
Merged via the queue into working-1.6 with commit 663dd20 Sep 10, 2026
12 checks passed
@mastacontrola
mastacontrola deleted the fix/1747-subnet branch September 10, 2026 12:50
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