golang.org/x/net@v0.25.1-0.20240516223405-c87a5b62e243/internal/socket/sys_unix.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris 6 7 package socket 8 9 import ( 10 "net" 11 "unsafe" 12 13 "golang.org/x/sys/unix" 14 ) 15 16 //go:linkname syscall_getsockopt syscall.getsockopt 17 func syscall_getsockopt(s, level, name int, val unsafe.Pointer, vallen *uint32) error 18 19 //go:linkname syscall_setsockopt syscall.setsockopt 20 func syscall_setsockopt(s, level, name int, val unsafe.Pointer, vallen uintptr) error 21 22 func getsockopt(s uintptr, level, name int, b []byte) (int, error) { 23 l := uint32(len(b)) 24 err := syscall_getsockopt(int(s), level, name, unsafe.Pointer(&b[0]), &l) 25 return int(l), err 26 } 27 28 func setsockopt(s uintptr, level, name int, b []byte) error { 29 return syscall_setsockopt(int(s), level, name, unsafe.Pointer(&b[0]), uintptr(len(b))) 30 } 31 32 func recvmsg(s uintptr, buffers [][]byte, oob []byte, flags int, network string) (n, oobn int, recvflags int, from net.Addr, err error) { 33 var unixFrom unix.Sockaddr 34 n, oobn, recvflags, unixFrom, err = unix.RecvmsgBuffers(int(s), buffers, oob, flags) 35 if unixFrom != nil { 36 from = sockaddrToAddr(unixFrom, network) 37 } 38 return 39 } 40 41 func sendmsg(s uintptr, buffers [][]byte, oob []byte, to net.Addr, flags int) (int, error) { 42 var unixTo unix.Sockaddr 43 if to != nil { 44 unixTo = addrToSockaddr(to) 45 } 46 return unix.SendmsgBuffers(int(s), buffers, oob, unixTo, flags) 47 } 48 49 // addrToSockaddr converts a net.Addr to a unix.Sockaddr. 50 func addrToSockaddr(a net.Addr) unix.Sockaddr { 51 var ( 52 ip net.IP 53 port int 54 zone string 55 ) 56 switch a := a.(type) { 57 case *net.TCPAddr: 58 ip = a.IP 59 port = a.Port 60 zone = a.Zone 61 case *net.UDPAddr: 62 ip = a.IP 63 port = a.Port 64 zone = a.Zone 65 case *net.IPAddr: 66 ip = a.IP 67 zone = a.Zone 68 default: 69 return nil 70 } 71 72 if ip4 := ip.To4(); ip4 != nil { 73 sa := unix.SockaddrInet4{Port: port} 74 copy(sa.Addr[:], ip4) 75 return &sa 76 } 77 78 if ip6 := ip.To16(); ip6 != nil && ip.To4() == nil { 79 sa := unix.SockaddrInet6{Port: port} 80 copy(sa.Addr[:], ip6) 81 if zone != "" { 82 sa.ZoneId = uint32(zoneCache.index(zone)) 83 } 84 return &sa 85 } 86 87 return nil 88 } 89 90 // sockaddrToAddr converts a unix.Sockaddr to a net.Addr. 91 func sockaddrToAddr(sa unix.Sockaddr, network string) net.Addr { 92 var ( 93 ip net.IP 94 port int 95 zone string 96 ) 97 switch sa := sa.(type) { 98 case *unix.SockaddrInet4: 99 ip = make(net.IP, net.IPv4len) 100 copy(ip, sa.Addr[:]) 101 port = sa.Port 102 case *unix.SockaddrInet6: 103 ip = make(net.IP, net.IPv6len) 104 copy(ip, sa.Addr[:]) 105 port = sa.Port 106 if sa.ZoneId > 0 { 107 zone = zoneCache.name(int(sa.ZoneId)) 108 } 109 default: 110 return nil 111 } 112 113 switch network { 114 case "tcp", "tcp4", "tcp6": 115 return &net.TCPAddr{IP: ip, Port: port, Zone: zone} 116 case "udp", "udp4", "udp6": 117 return &net.UDPAddr{IP: ip, Port: port, Zone: zone} 118 default: 119 return &net.IPAddr{IP: ip, Zone: zone} 120 } 121 }