Skip to content

Net: honor the scope argument - #5105

Merged
gpotter2 merged 1 commit into
secdev:masterfrom
dylanpulver:net-honor-scope-argument
Aug 27, 2026
Merged

Net: honor the scope argument#5105
gpotter2 merged 1 commit into
secdev:masterfrom
dylanpulver:net-honor-scope-argument

Conversation

@dylanpulver

Copy link
Copy Markdown
Contributor

Description

Net.__init__ takes a scope argument and never reads it. The form printed in Net's own docstring returns an unscoped object:

>>> Net("224.0.0.1", scope=conf.iface).scope
None            # expected 'eth0'
>>> Net("224.0.0.1%eth0").scope
'eth0'

__iter__ copies self.scope onto every address it yields, so a Net built with scope= yields plain addresses and packets built from it leave through the default interface rather than the requested one. Net6 inherits __init__, so IPv6 behaves the same way.

The argument arrived with scope support in #4461. That commit wired scope into the signature, into __iter__, into __repr__ and into __hash__, but not into the body of __init__. This patch hands it to ScopedIP, which does the interface resolution and keeps the existing precedence where an inline % overrides the argument.

No test could have caught this. Net.__eq__ does not look at scope, so Net("224.0.0.1", scope=iface) == Net("224.0.0.1%iface") holds whether or not the argument works. The new test asserts on .scope itself for that reason, across the mask form, the start/stop form and the addresses a Net generates.

One related thing I did not touch: __hash__ includes scope but __eq__ does not, so Net("224.0.0.1%eth0") and Net("224.0.0.1") compare equal with different hashes, which makes them distinct keys in a dict. Fixing that shifts comparison semantics, so it seemed worth a separate discussion.

Net.__init__ accepted a scope argument but never read it, so the
documented Net("224.0.0.1", scope=conf.iface) form returned a Net whose
scope was None. Because __iter__ copies self.scope onto the addresses it
yields, such a Net produced unscoped addresses, and packets built from it
left through the default interface rather than the requested one. Net6
inherits __init__ and behaved the same way.

Pass the argument to ScopedIP, which resolves the interface and keeps the
precedence where an inline % overrides it.

The existing tests could not catch this because Net.__eq__ does not look
at scope, so the new test asserts on .scope itself.

AI-Assisted: yes (Claude Opus 5)
@gpotter2
gpotter2 merged commit 5b1612a into secdev:master Aug 27, 2026
1 check passed
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.

2 participants