Skip to content

netaddr: add new netaddr module with scope/property API - #467

Merged
jow- merged 1 commit into
masterfrom
feat/lib-netaddr
Oct 5, 2026
Merged

jow- merged 1 commit into
masterfrom
feat/lib-netaddr

Conversation

@jow-

@jow- jow- commented Oct 5, 2026

Copy link
Copy Markdown
Collaborator

Adds a new netaddr module ported from LuCI's luci-lib-ip, providing IP address/network manipulation utilities.

Also updates the socket and resolv modules to accept netaddr.range values (and any stringifiable value) for addresses.

Commits:

  • cb53b56 netaddr: add new netaddr module ported from LuCI's luci-lib-ip
  • b4e0fa9 socket, resolv: accept netaddr.range (and any stringifiable value) for addresses

@jow-
jow- force-pushed the feat/lib-netaddr branch from b4e0fa9 to e3deda1 Compare October 5, 2026 19:58
@jow- jow- changed the title netaddr: add new netaddr module ported from LuCI's luci-lib-ip netaddr: add new netaddr module with scope/property API Oct 5, 2026
@jow-
jow- force-pushed the feat/lib-netaddr branch from e3deda1 to ac38985 Compare October 5, 2026 20:50
Add a new netaddr module providing network address handling (IPv4,
IPv6 and MAC) as a port of the LuCI luci-lib-ip library, reduced to
its pure address calculation functionality (no netlink/rtnl parts,
which are covered by the rtnl module).

Addresses are represented by netaddr.range resource instances which
carry the address, its family and a prefix size. Instances are created
with the new(), v4(), v6() or mac() constructors, which accept address
strings (optionally with prefix/netmask), unsigned numbers, byte
arrays (length 4 = IPv4, 6 = MAC, 16 = IPv6) or sockaddr-like objects
({ address, family, interface }) and raise a runtime exception on
invalid input.

The checkv4(), checkv6() and checkmac() functions provide
non-throwing validation, returning the canonical string representation
of the given address or null.

Instances support byte-level access, prefix/netmask manipulation,
range queries (network, mask, broadcast, minhost, maxhost, size),
family predicates (is4, is4rfc1918, is4linklocal, is6, is6linklocal,
is6mapped4, ismac, ismaclocal, ismacmcast), conversions (mapped4,
unscoped, tomac, tolinklocal), arithmetic (add, sub), comparisons
(lower, higher, equal, contains) and string formatting (string,
tostring).

minhost() and maxhost() treat IPv4 /31 point-to-point ranges (RFC
3021) as having both addresses usable, deviating from the LuCI
reference implementation which inverts the host range for /31.

The scalar range fields (bits, family, netmask, host, mapped4,
unscopename, size) are exposed as virtual properties accessed via the
__get__()/__set__() metamethods, following the pattern established by
the meta-field support in the interpreter, replacing dedicated getter
methods while remaining fully backward compatible with existing
positional byte access. All properties are documented via @Property
JSDoc annotations on the @Class module:netaddr.range block,
indicating read-only vs read/write status.

The v6() constructor accepts a third optional 'scope' argument,
accepting an interface name or numeric index for link-local addresses
(fe80::/10). A shared parse_scope() helper is used by the constructor,
the sockaddr-like object form, and the scopeid property setter. The
scope handling extends to MAC address instances (the scope carries the
interface the MAC is bound to) and the range type provides:

- scoped(): derive a copy of the address carrying its scope (IPv6/MAC)
- unscopename(): return the interface name of the address scope
- scopeid property: get/set the scope by interface name or index

Return from the module functions immediately after raising a runtime
exception, as uc_vm_raise_exception() only records the exception on
the vm and returns, matching the convention of the other lib modules.

The socket and resolv modules accept values with a tostring()
metamethod (e.g. netaddr.range instances) wherever an address string
is expected; the socket string parsing path is guarded on the
resolved string pointer rather than re-testing the value type.

Replace the netinet/ether.h dependency with a plain uint8_t mac[6]
field so the module builds on macOS (which lacks that header), and
define AF_PACKET when not provided by the platform.

Add a valgrind suppression for a glibc 2.43 inet_pton6() false
positive (fortified memmove compiled to memcpy_chk with overlapping
source/destination inside glibc's own buffer).

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
@jow-
jow- force-pushed the feat/lib-netaddr branch from ac38985 to 959206e Compare October 5, 2026 22:28
@jow-
jow- merged commit 4b493d8 into master Oct 5, 2026
3 checks passed
@jow-
jow- deleted the feat/lib-netaddr branch October 5, 2026 23:09
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