Source identity
| Field | Recorded value |
|---|---|
| Source type | GitHub source |
| Original record | Janady13/missionmatch / cmd/corpus-harvest/dial_darwin.go |
| Date | Not specified in source |
| Repository | Janady13/missionmatch |
| Revision | 720d47fae476b0d38477ae4401697d372b1ea2bc |
| Branch | feature/opportunity-to-outcome |
| Path or archive member | cmd/corpus-harvest/dial_darwin.go |
| Original SHA-256 | 6d55ec2f70d26e67bba8d6454cc9e903588ce418c1f89355e4bccb7a3777d76a |
| Git blob SHA | 42794f4586029e74003e6b476e7ea8c26c7825f4 |
| Reading-copy SHA-256 | 6d55ec2f70d26e67bba8d6454cc9e903588ce418c1f89355e4bccb7a3777d76a |
Recovered source transcript
Download complete source text ↓73 lines · 2.9 KB
//go:build darwin
package main
import (
"context"
"fmt"
"net"
"syscall"
)
// BINDING THE SOCKET TO AN INTERFACE, WHICH IS WHY THIS FILE EXISTS.
//
// macOS INTERFACE SCOPES its cloned subnet routes whenever more than one network service carries a
// default route, and every node in this federation does: the wired interface plus Tailscale's tunnel. A
// scoped route is usable only by a socket that has been explicitly bound to that interface, which the BSD
// tools do through the system path. ping, nc and curl therefore reach the database host on the wire while
// Go's dialer, which never sets IP_BOUND_IF, gets EHOSTUNREACH against the same address and port from the
// same process at the same moment. That asymmetry is the whole bug, and it is not fixable by editing the
// routing table: an unscoped host route helped when the node ran alone and stopped helping the moment the
// other node was busy.
//
// So the fix belongs here rather than in the network. The socket says which interface it is for, the
// scoped route matches, and the packet leaves on the wire the way the hardware was cabled to make it.
//
// THE CONSTANTS ARE DARWIN'S, and the standard library does not export them. IP_BOUND_IF is 25 at the
// IPPROTO_IP level and IPV6_BOUND_IF is 125 at IPPROTO_IPV6, both stable in the XNU headers for many
// releases. They are written here with their provenance rather than pulled in behind a new dependency for
// two integers.
const (
darwinIPBoundIf = 25 // netinet/in.h, IP_BOUND_IF
darwinIPv6BoundIf = 125 // netinet6/in6.h, IPV6_BOUND_IF
)
// bindToInterface returns a dial function whose sockets are bound to the named interface.
//
// An empty name returns nil, which every caller reads as "use the default dialer". That is deliberate: the
// binding is a targeted answer to a scoped route and should be switched on where it is needed rather than
// imposed everywhere, because a socket bound to the wrong interface fails in a way that looks exactly like
// the problem it was meant to solve.
func bindToInterface(name string) (func(ctx context.Context, network, addr string) (net.Conn, error), error) {
if name == "" {
return nil, nil
}
ifi, err := net.InterfaceByName(name)
if err != nil {
return nil, fmt.Errorf("bind interface %q: %w", name, err)
}
if ifi.Flags&net.FlagUp == 0 {
return nil, fmt.Errorf("bind interface %q is down", name)
}
idx := ifi.Index
d := &net.Dialer{
Control: func(network, address string, c syscall.RawConn) error {
var setErr error
ctrlErr := c.Control(func(fd uintptr) {
switch network {
case "tcp6", "udp6", "ip6":
setErr = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IPV6, darwinIPv6BoundIf, idx)
default:
setErr = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_IP, darwinIPBoundIf, idx)
}
})
if ctrlErr != nil {
return ctrlErr
}
return setErr
},
}
return d.DialContext, nil
}