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.
5 //go:build aix || darwin || dragonfly || freebsd || hurd || linux || netbsd || openbsd || solaris
14 func readRawConn(c syscall
.RawConn
, b
[]byte) (int, error
) {
17 err
:= c
.Read(func(s
uintptr) bool {
18 n
, operr
= syscall
.Read(int(s
), b
)
19 if operr
== syscall
.EAGAIN
{
30 func writeRawConn(c syscall
.RawConn
, b
[]byte) error
{
32 err
:= c
.Write(func(s
uintptr) bool {
33 _
, operr
= syscall
.Write(int(s
), b
)
34 if operr
== syscall
.EAGAIN
{
45 func controlRawConn(c syscall
.RawConn
, addr Addr
) error
{
47 fn
:= func(s
uintptr) {
48 _
, operr
= syscall
.GetsockoptInt(int(s
), syscall
.SOL_SOCKET
, syscall
.SO_REUSEADDR
)
52 switch addr
:= addr
.(type) {
54 // There's no guarantee that IP-level socket
55 // options work well with dual stack sockets.
56 // A simple solution would be to take a look
57 // at the bound address to the raw connection
58 // and to classify the address family of the
59 // underlying socket by the bound address:
61 // - When IP.To16() != nil and IP.To4() == nil,
62 // we can assume that the raw connection
63 // consists of an IPv6 socket using only
66 // - When IP.To16() == nil and IP.To4() != nil,
67 // the raw connection consists of an IPv4
68 // socket using only IPv4 addresses.
70 // - Otherwise, the raw connection is a dual
71 // stack socket, an IPv6 socket using IPv6
72 // addresses including IPv4-mapped or
73 // IPv4-embedded IPv6 addresses.
74 if addr
.IP
.To16() != nil && addr
.IP
.To4() == nil {
75 operr
= syscall
.SetsockoptInt(int(s
), syscall
.IPPROTO_IPV6
, syscall
.IPV6_UNICAST_HOPS
, 1)
76 } else if addr
.IP
.To16() == nil && addr
.IP
.To4() != nil {
77 operr
= syscall
.SetsockoptInt(int(s
), syscall
.IPPROTO_IP
, syscall
.IP_TTL
, 1)
81 if err
:= c
.Control(fn
); err
!= nil {
87 func controlOnConnSetup(network
string, address
string, c syscall
.RawConn
) error
{
91 case "tcp", "udp", "ip":
92 return errors
.New("ambiguous network: " + network
)
93 case "unix", "unixpacket", "unixgram":
94 fn
= func(s
uintptr) {
95 _
, operr
= syscall
.GetsockoptInt(int(s
), syscall
.SOL_SOCKET
, syscall
.SO_ERROR
)
98 switch network
[len(network
)-1] {
100 fn
= func(s
uintptr) {
101 operr
= syscall
.SetsockoptInt(int(s
), syscall
.IPPROTO_IP
, syscall
.IP_TTL
, 1)
104 fn
= func(s
uintptr) {
105 operr
= syscall
.SetsockoptInt(int(s
), syscall
.IPPROTO_IPV6
, syscall
.IPV6_UNICAST_HOPS
, 1)
108 return errors
.New("unknown network: " + network
)
111 if err
:= c
.Control(fn
); err
!= nil {