Skip to content

Rewrite the README for 1.0, correct the man pages, fix the default config path - #97

Merged
DanielAdolfsson merged 1 commit into
fix/suite-findingsfrom
docs/readme-1.0
Oct 15, 2026
Merged

DanielAdolfsson merged 1 commit into
fix/suite-findingsfrom
docs/readme-1.0

Conversation

@DanielAdolfsson

@DanielAdolfsson DanielAdolfsson commented Oct 15, 2026 •

Copy link
Copy Markdown
Owner

Stacked on #96 — review #95 and #96 first.

README

The rewrite that came with #93 is the base and most of it is kept. This says the things it could not, because it was written for a fork.

Status, and credit where it is due

For six years this project's public answer to "which version should I use" was that the current one was in maintenance, its replacement was not ready for production, and there was no estimate. That is why the reporters in #71 concluded ndppd was abandoned and moved to ndpresponder.

The honest answer now is different, and the README says it: 1.0 is in beta, is running in production, and is being worked on again.

It is being worked on because of @totoCZ. The rewrite sat untouched from June 2020 until they took it into production behind a Juniper switch, worked out everything that was wrong with it, and sent the fixes back — #92 and #93. Several are the kind of bug only a real network finds:

  • a solicited-node multicast MAC wrong by one byte, so every EUI-64 target silently never received a probe;
  • a socket membership dropped by the parent process at fork, leaving the surviving daemon unable to see the packets it exists to answer;
  • an NA correct in every respect except the one flag that would have let a neighbour cache believe it.

That is in the Status section and again under Credits, by name.

What ndppd does not do

A new Limitations section: ndppd does not route, does not enable forwarding, does not send RAs, is not a substitute for the kernel's neighbour table on its own host, is Ethernet-only, is defeated by MLD snooping, and needs its interfaces to exist at startup.

That list is most of the open tracker — #55, #69, #72, #77, #79 — and #60 has been open since June 2020 asking for exactly this. Each item links the issue it corresponds to.

The rest

Man pages

ndppd.conf(5) documented invalid-ttl as defaulting to 5000 when it is 10000, used route eth0 where it meant proxy eth0, and was missing keepalive, router, target and rewrite entirely.

Bounds are now stated for every numeric option, because the parser rejects out-of-range values rather than clamping them, and the error does not say what the range was.

ndppd(8) gained --netns, what the verbosity levels actually are, and a note on promiscuous mode and on log buffering.

The shipped systemd unit could not work

ndppd(8) documents /etc/ndppd.conf as the default configuration path. The compiled-in default was the relative path "../ndppd.conf", and ndppd.service passes no -c at all. systemd runs a service with its working directory at /, so the shipped unit looked for /ndppd.conf:

info  | Loading configuration "../ndppd.conf"...
error | Failed to load configuration: No such file or directory

The default is now built from SYSCONFDIR, so a packager who moves it moves the documentation's claim with it, and 110-config-path.sh asserts the binary and its own man page name the same path — whatever that path is.


Relevance to the open tracker

These issues were all filed against 0.2.x, and the README changes here are on 1.0-devel only. One loose end for master: its README still tells every visitor that 1.0 "is not yet stable enough to be used in production, and I currently have no estimate when it is". That has been the project's public answer since 2020 and is now wrong in the other direction. A paragraph on master would stop the two branches contradicting each other.

Verification

make check: 228 unit + 55 integration assertions, exit 0. Man pages render with asciidoctor -b manpage.

🤖 Generated with Claude Code

…onfig path

**README.** The rewrite that came with #93 is the base; this says the
things it could not, because it was written for a fork.

- A **Status** section that answers the question a visitor actually has.
  For six years this project's public answer was "experimental, no estimate
  for a beta", which is why the reporters in #71 concluded it was abandoned
  and moved to ndpresponder. The honest answer now is that 1.0 is in beta,
  is running in production, and is being worked on again.

- **Credit to totoCZ**, in Status and in a Credits section. The rewrite sat
  untouched from June 2020 until they took it into production behind a
  Juniper switch, found everything wrong with it and sent the fixes back.
  Several are the kind of bug only a real network finds: a multicast MAC
  wrong by one byte, a socket membership dropped by the wrong process at
  fork, an NA correct in every respect except the one flag that would let a
  neighbour cache believe it. That is #93, and it is why this branch is
  worth finishing.

- **A "Limitations" section.** ndppd does not route, does not enable
  forwarding, does not send RAs, is not a substitute for the kernel's
  neighbour table on its own host, is Ethernet-only, is defeated by MLD
  snooping, and needs its interfaces to exist at startup. That list is most
  of the open tracker -- #55, #69, #72, #77, #79 -- and #60 has been open
  since 2020 asking for exactly this.

- **How to choose a rule mode**, which is the decision people most often
  get wrong, including what `static` really commits you to: a static /64
  claims eighteen quintillion addresses on your provider's link.

- `gmake` on BSD, which is #66. The Makefile opens with `ifdef` and the
  base system's make answers "Need an operator".

**Man pages.** ndppd.conf(5) documented `invalid-ttl` as defaulting to
5000 when it is 10000, used `route eth0` where it meant `proxy eth0`, and
was missing `keepalive`, `router`, `target` and `rewrite` entirely. Bounds
are now stated for every numeric option, because the parser rejects
out-of-range values rather than clamping them and the error does not say
what the range was. ndppd(8) gained `--netns`, what the verbosity levels
actually are, and a note about promiscuous mode and log buffering.

**The default configuration path.** ndppd(8) documents /etc/ndppd.conf.
The compiled-in default was the *relative* path "../ndppd.conf", and
ndppd.service passes no -c at all -- systemd runs a service with its
working directory at /, so the shipped unit looked for /ndppd.conf and the
daemon exited. The default is now built from SYSCONFDIR so a packager who
moves it moves it everywhere, and case 110 asserts the binary and its own
man page name the same path, whatever it is.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@DanielAdolfsson
DanielAdolfsson merged commit 085089c into fix/suite-findings Oct 15, 2026
16 checks passed
DanielAdolfsson added a commit that referenced this pull request Oct 15, 2026
Re-lands the content of #96 and #97, which were merged into stacked branches that never reached 1.0-devel after #95 landed as a squash.
DanielAdolfsson added a commit that referenced this pull request Oct 15, 2026
110-config-path.sh arrived with #97 after the other ten had been
converted, so it was the only case left pointing at /bin/bash, where
FreeBSD does not keep it. Nothing else in the case is platform-specific.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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