github.com/c12o16h1/go/src@v0.0.0-20200114212001-5a151c0f00ed/net/rawconn_windows_test.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 package net 6 7 import ( 8 "errors" 9 "syscall" 10 "unsafe" 11 ) 12 13 func readRawConn(c syscall.RawConn, b []byte) (int, error) { 14 var operr error 15 var n int 16 err := c.Read(func(s uintptr) bool { 17 var read uint32 18 var flags uint32 19 var buf syscall.WSABuf 20 buf.Buf = &b[0] 21 buf.Len = uint32(len(b)) 22 operr = syscall.WSARecv(syscall.Handle(s), &buf, 1, &read, &flags, nil, nil) 23 n = int(read) 24 return true 25 }) 26 if err != nil { 27 return n, err 28 } 29 if operr != nil { 30 return n, operr 31 } 32 return n, nil 33 } 34 35 func writeRawConn(c syscall.RawConn, b []byte) error { 36 var operr error 37 err := c.Write(func(s uintptr) bool { 38 var written uint32 39 var buf syscall.WSABuf 40 buf.Buf = &b[0] 41 buf.Len = uint32(len(b)) 42 operr = syscall.WSASend(syscall.Handle(s), &buf, 1, &written, 0, nil, nil) 43 return true 44 }) 45 if err != nil { 46 return err 47 } 48 if operr != nil { 49 return operr 50 } 51 return nil 52 } 53 54 func controlRawConn(c syscall.RawConn, addr Addr) error { 55 var operr error 56 fn := func(s uintptr) { 57 var v, l int32 58 l = int32(unsafe.Sizeof(v)) 59 operr = syscall.Getsockopt(syscall.Handle(s), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, (*byte)(unsafe.Pointer(&v)), &l) 60 if operr != nil { 61 return 62 } 63 switch addr := addr.(type) { 64 case *TCPAddr: 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: 71 // 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 75 // IPv6 addresses. 76 // 77 // - When IP.To16() == nil and IP.To4() != nil, 78 // the raw connection consists of an IPv4 79 // socket using only IPv4 addresses. 80 // 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) 89 } 90 } 91 } 92 if err := c.Control(fn); err != nil { 93 return err 94 } 95 if operr != nil { 96 return operr 97 } 98 return nil 99 } 100 101 func controlOnConnSetup(network string, address string, c syscall.RawConn) error { 102 var operr error 103 var fn func(uintptr) 104 switch network { 105 case "tcp", "udp", "ip": 106 return errors.New("ambiguous network: " + network) 107 default: 108 switch network[len(network)-1] { 109 case '4': 110 fn = func(s uintptr) { 111 operr = syscall.SetsockoptInt(syscall.Handle(s), syscall.IPPROTO_IP, syscall.IP_TTL, 1) 112 } 113 case '6': 114 fn = func(s uintptr) { 115 operr = syscall.SetsockoptInt(syscall.Handle(s), syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, 1) 116 } 117 default: 118 return errors.New("unknown network: " + network) 119 } 120 } 121 if err := c.Control(fn); err != nil { 122 return err 123 } 124 if operr != nil { 125 return operr 126 } 127 return nil 128 }