big_send now forces the Don't-Fragment bit for the whole burst by default, so the largest size that arrives IS the downstream path MTU rather than "fragments got through" — two different measurements the schema already separates. Sizes above our own egress MTU (from the startup self-test) are refused up front and reported as max_df_bytes, because absence caused by our kernel must not be read as a limit of the client's path. Uploads: one JSON file per run under the state dir, with the policy the operator actually cares about — who may upload (off / anonymous / account), how large, how long to keep, and the least anonymization accepted. The profile advertises all of it so the app can present the switch honestly instead of discovering the rules by failing. `account` refuses today rather than falling back to anonymous: picking the strict setting before OIDC lands must not silently mean the loose one. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
62 lines
1.7 KiB
Go
62 lines
1.7 KiB
Go
// SPDX-FileCopyrightText: 2026 Echolot contributors
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
//go:build linux
|
|
|
|
package dataplane
|
|
|
|
import (
|
|
"net"
|
|
"syscall"
|
|
)
|
|
|
|
// PMTUD socket-option values. Go's syscall package exports IP_MTU_DISCOVER and
|
|
// IPV6_MTU_DISCOVER but not the IP_PMTUDISC_* values, so they are spelled out
|
|
// here (include/linux/in.h, in6.h — stable ABI, same reasoning as the client's
|
|
// OsAbi.kt).
|
|
const (
|
|
pmtudiscWant = 0 // per-route default: fragment locally when needed
|
|
pmtudiscDo = 2 // always set DF: oversized sends fail with EMSGSIZE, never fragment
|
|
)
|
|
|
|
// withDF runs fn with the Don't-Fragment bit forced on for conn, then puts the
|
|
// socket back the way it was found.
|
|
//
|
|
// The socket is shared by every session on that address family, so the caller
|
|
// must hold Server.dfMu: a concurrent big_send must not silently ride along
|
|
// with someone else's DF window (or, worse, clear it mid-flight).
|
|
func withDF(conn *net.UDPConn, fn func() error) error {
|
|
raw, err := conn.SyscallConn()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
v4 := conn.LocalAddr().(*net.UDPAddr).IP.To4() != nil
|
|
level, opt := syscall.IPPROTO_IPV6, syscall.IPV6_MTU_DISCOVER
|
|
if v4 {
|
|
level, opt = syscall.IPPROTO_IP, syscall.IP_MTU_DISCOVER
|
|
}
|
|
|
|
var setErr error
|
|
prev := pmtudiscWant
|
|
if err := raw.Control(func(fd uintptr) {
|
|
if p, e := syscall.GetsockoptInt(int(fd), level, opt); e == nil {
|
|
prev = p
|
|
}
|
|
setErr = syscall.SetsockoptInt(int(fd), level, opt, pmtudiscDo)
|
|
}); err != nil {
|
|
return err
|
|
}
|
|
if setErr != nil {
|
|
return setErr
|
|
}
|
|
defer func() {
|
|
_ = raw.Control(func(fd uintptr) {
|
|
_ = syscall.SetsockoptInt(int(fd), level, opt, prev)
|
|
})
|
|
}()
|
|
return fn()
|
|
}
|
|
|
|
// dfSupported reports whether withDF can actually set the DF bit here.
|
|
const dfSupported = true
|