Skip to content

Revert "feat(netwatch): allow setting SO_MARK on UdpSocket" - #185

Merged
flub merged 2 commits into
mainfrom
revert-179-feat/socket-mark
Jul 17, 2026
Merged

flub merged 2 commits into
mainfrom
revert-179-feat/socket-mark

Conversation

@flub

@flub flub commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Reverts #179

See #182: this needs more design.

@flub
flub requested a review from matheus23 July 16, 2026 16:26
@github-actions

github-actions Bot commented Jul 16, 2026 •

Copy link
Copy Markdown

Documentation for this PR has been generated and is available at: https://n0-computer.github.io/net-tools/pr/185/docs/net_tools/

Last updated: 2026-07-17T09:16:27Z

@matheus23

Copy link
Copy Markdown
Member

@ifdario please don't worry - our goal is just that we don't publish something next week that we'll want to deprecate the week after.

@n0bot n0bot Bot added this to iroh Jul 16, 2026
@github-project-automation github-project-automation Bot moved this to 🚑 Needs Triage in iroh Jul 16, 2026
@ifdario

ifdario commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

@ifdario please don't worry - our goal is just that we don't publish something next week that we'll want to deprecate the week after.

No problem. I understand and it is partially my responsability

@flub
flub added this pull request to the merge queue Jul 17, 2026
Merged via the queue into main with commit 425a0ea Jul 17, 2026
29 of 30 checks passed
@github-project-automation github-project-automation Bot moved this from 🚑 Needs Triage to ✅ Done in iroh Jul 17, 2026
@flub
flub deleted the revert-179-feat/socket-mark branch July 17, 2026 09:48
Kiesen pushed a commit to mira-mobility/net-tools that referenced this pull request Sep 10, 2026
…er#182)

Follow-up to n0-computer#179, which was reverted in n0-computer#185 pending a more general
design. Merged with current `main`.

## What

`BindOptions` comes back carrying only the general form: a hook that
runs on every socket right after creation and before `bind()`, and again
on every internal rebind.

```rust
let opts = BindOptions::new().configure_socket(|socket, _family| {
    socket2::SockRef::from(&socket).set_mark(0x80)
});
let socket = UdpSocket::bind_with(addr, opts)?;
```

- `UdpSocket::bind_with(addr, BindOptions)` replaces the private
`bind_raw`; the other `bind_*` constructors all go through it.
- The hook is stored in both `SocketState` variants, so it reruns on
every rebind. That is the point of it: on macOS the equivalent of
`SO_MARK` is binding to the physical default-route interface
(`IP_BOUND_IF`), and the right interface changes when the default route
moves (wifi to ethernet, say), so it has to be re-resolved per bind. A
one-shot option cannot express that.
- An error from the hook fails the bind (fail closed): for
loop-prevention users a socket that silently missed its configuration
would leak traffic into the tunnel it is carrying.
- No `socket2` in the public API. The hook gets a `SocketRef`, a
borrowed handle that implements `AsFd` on unix and `AsSocket` on
Windows, plus netwatch's own `IpFamily` (the family cannot be read back
off the socket portably, `SO_DOMAIN` is Linux-only). Callers reach for
whatever socket crate they like, `socket2::SockRef::from(&socket)` or
plain `libc::setsockopt` on the raw fd, without having to match
netwatch's socket2 version. This is also what keeps `cargo
check-external-types` green; the earlier `SockRef`/`Domain` signature
failed that job.
- No new public trait either. The hook is a plain closure, stored as
`Arc<dyn Fn(SocketRef<'_>, IpFamily) -> io::Result<()> + Send + Sync>`.
So the added API surface is `BindOptions`, `BindOptions::{new,
configure_socket}`, `SocketRef` and `UdpSocket::bind_with`, and nothing
else to keep compatible later.
- `BindOptions` keeps `Debug` (the field is `#[debug(skip)]`ed via
derive_more, already a dependency), `Default` and `Clone`. It is not
`Copy`/`PartialEq`/`Eq`.
- Purely additive against `main`, so no semver break.

Tests cover the hook running on bind and on rebind, and the fail-closed
path.

Also drops the `semicolon_in_expressions_from_macros` allow in
`build.rs`, per @matheus23: `cfg_aliases` 0.2.2 no longer trips the
lint.

## Why

Same client as n0-computer#179: full tunnel over iroh, WireGuard/Tailscale-style
loop prevention. `SO_MARK` covers Linux, macOS needs `IP_BOUND_IF`
re-applied on every bind, and other platforms need yet other
setsockopts. One hook covers all of them, and whatever else a caller
needs, without growing `BindOptions` per platform.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

3 participants