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.
13 func readRawConn(c syscall
.RawConn
, b
[]byte) (int, error
) {
16 err
:= c
.Read(func(s
uintptr) bool {
19 var buf syscall
.WSABuf
21 buf
.Len
= uint32(len(b
))
22 operr
= syscall
.WSARecv(syscall
.Handle(s
), &buf
, 1, &read
, &flags
, nil, nil)
35 func writeRawConn(c syscall
.RawConn
, b
[]byte) error
{
37 err
:= c
.Write(func(s
uintptr) bool {
39 var buf syscall
.WSABuf
41 buf
.Len
= uint32(len(b
))
42 operr
= syscall
.WSASend(syscall
.Handle(s
), &buf
, 1, &written
, 0, nil, nil)
54 func controlRawConn(c syscall
.RawConn
, addr Addr
) error
{
56 fn
:= func(s
uintptr) {
58 l
= int32(unsafe
.Sizeof(v
))
59 operr
= syscall
.Getsockopt(syscall
.Handle(s
), syscall
.SOL_SOCKET
, syscall
.SO_REUSEADDR
, (*byte)(unsafe
.Pointer(&v
)), &l
)
63 switch addr
:= addr
.(type) {
65 // There's no guarantee that IP-level socket
66 // options work well with dual stack sockets.
67 // A simple solution would be to take a look
68 // at the bound address to the raw connection
69 // and to classify the address family of the
70 // underlying socket by the bound address:
72 // - When IP.To16() != nil and IP.To4() == nil,
73 // we can assume that the raw connection
74 // consists of an IPv6 socket using only
77 // - When IP.To16() == nil and IP.To4() != nil,
78 // the raw connection consists of an IPv4
79 // socket using only IPv4 addresses.
81 // - Otherwise, the raw connection is a dual
82 // stack socket, an IPv6 socket using IPv6
83 // addresses including IPv4-mapped or
84 // IPv4-embedded IPv6 addresses.
85 if addr
.IP
.To16() != nil && addr
.IP
.To4() == nil {
86 operr
= syscall
.SetsockoptInt(syscall
.Handle(s
), syscall
.IPPROTO_IPV6
, syscall
.IPV6_UNICAST_HOPS
, 1)
87 } else if addr
.IP
.To16() == nil && addr
.IP
.To4() != nil {
88 operr
= syscall
.SetsockoptInt(syscall
.Handle(s
), syscall
.IPPROTO_IP
, syscall
.IP_TTL
, 1)
92 if err
:= c
.Control(fn
); err
!= nil {
101 func controlOnConnSetup(network
string, address
string, c syscall
.RawConn
) error
{
105 case "tcp", "udp", "ip":
106 return errors
.New("ambiguous network: " + network
)
108 switch network
[len(network
)-1] {
110 fn
= func(s
uintptr) {
111 operr
= syscall
.SetsockoptInt(syscall
.Handle(s
), syscall
.IPPROTO_IP
, syscall
.IP_TTL
, 1)
114 fn
= func(s
uintptr) {
115 operr
= syscall
.SetsockoptInt(syscall
.Handle(s
), syscall
.IPPROTO_IPV6
, syscall
.IPV6_UNICAST_HOPS
, 1)
118 return errors
.New("unknown network: " + network
)
121 if err
:= c
.Control(fn
); err
!= nil {