Repository: go
Issue: x/sys: cannot create AF_UNSPEC sockaddr
Labels: NeedsInvestigation

### What version of Go are you using (`go version`)?

<pre>
$ go version
go version go1.21.3 darwin/arm64
</pre>

### Does this issue reproduce with the latest release?

Yes

### What operating system and processor architecture are you using (`go env`)?

<details><summary><code>go env</code> Output</summary><br><pre>
$ go env
GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/msteinert/Library/Caches/go-build'
GOENV='/Users/msteinert/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/msteinert/go/pkg/mod'
GONOPROXY='git.drwholdings.com'
GONOSUMDB='git.drwholdings.com'
GOOS='darwin'
GOPATH='/Users/msteinert/go'
GOPRIVATE='git.drwholdings.com'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.21.3/libexec'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.21.3/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.21.3'
GCCGO='gccgo'
AR='ar'
CC='cc'
CXX='c++'
CGO_ENABLED='1'
GOMOD='/Users/msteinert/src/git/monstack/jimi/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/fold
ers/m5/f15ps3xd7lz2gbn361wzn07r0000gp/T/go-build3450338831=/tmp/go-build -gno-record-gcc-switches -fno-common'
</pre></details>

### What did you do?

I would like to reset/disconnect a socket connection. The specification for [connect][] says:

> If the sa_family member of address is AF_UNSPEC, the socket's peer address shall be reset.

[connect]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/connect.html

### What did you expect to see?

A way to call `unix.Connect` with a socket address that has the family set to `AF_UNSPEC`.

For example, a `SockaddrUnspec` type:

```diff
diff --git a/unix/syscall_unix.go b/unix/syscall_unix.go
index 77081de..548855f 100644
--- a/unix/syscall_unix.go
+++ b/unix/syscall_unix.go
@@ -232,6 +232,17 @@ type SockaddrUnix struct {
        raw  RawSockaddrUnix
 }

+// SockaddrUnspec implements the Sockaddr interface for AF_UNSPEC type sockets.
+type SockaddrUnspec struct {
+ raw RawSockaddr
+}
+
+func (sa *SockaddrUnspec) sockaddr() (unsafe.Pointer, _Socklen, error) {
+ sa.raw.Len = 16
+ sa.raw.Family = AF_UNSPEC
+ return unsafe.Pointer(&sa.raw), _Socklen(sa.raw.Len), nil
+}
+
 func Bind(fd int, sa Sockaddr) (err error) {
        ptr, n, err := sa.sockaddr()
        if err != nil {
```

I tested the above patch with the following function:

```go
func Disconnect(fd int) error {
        sa := unix.SockaddrUnspec{}
        var err error = unix.EINTR
        for err == unix.EINTR {
                err = unix.Connect(fd, &sa)
        }
        if err != nil {
                if err != unix.EAFNOSUPPORT && err != unix.EINVAL {
                        return err
                }
        }
        return nil
}
```

The connect manpage on MacOS also mentions that passing a `NULL` address achieves the same effect. When I passed a `nil` address to `unix.Connect` I got a segmentation fault.

I realize this patch is probably not formatted correctly. It looks like the struct size and the `sockaddr()` interface function should be generated per-platform basis. I submitted a bug/question here to see if there is another way to do it or if something like the above patch might be accepted (if I figure out how to do it correctly).

### What did you see instead?

No way to pass an `AF_UNSPEC` address to `unix.Connect`.