rawconn_windows_test.go 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  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. package net
  5. import (
  6. "errors"
  7. "syscall"
  8. "unsafe"
  9. )
  10. func readRawConn(c syscall.RawConn, b []byte) (int, error) {
  11. var operr error
  12. var n int
  13. err := c.Read(func(s uintptr) bool {
  14. var read uint32
  15. var flags uint32
  16. var buf syscall.WSABuf
  17. buf.Buf = &b[0]
  18. buf.Len = uint32(len(b))
  19. operr = syscall.WSARecv(syscall.Handle(s), &buf, 1, &read, &flags, nil, nil)
  20. n = int(read)
  21. return true
  22. })
  23. if err != nil {
  24. return n, err
  25. }
  26. return n, operr
  27. }
  28. func writeRawConn(c syscall.RawConn, b []byte) error {
  29. var operr error
  30. err := c.Write(func(s uintptr) bool {
  31. var written uint32
  32. var buf syscall.WSABuf
  33. buf.Buf = &b[0]
  34. buf.Len = uint32(len(b))
  35. operr = syscall.WSASend(syscall.Handle(s), &buf, 1, &written, 0, nil, nil)
  36. return true
  37. })
  38. if err != nil {
  39. return err
  40. }
  41. return operr
  42. }
  43. func controlRawConn(c syscall.RawConn, addr Addr) error {
  44. var operr error
  45. fn := func(s uintptr) {
  46. var v, l int32
  47. l = int32(unsafe.Sizeof(v))
  48. operr = syscall.Getsockopt(syscall.Handle(s), syscall.SOL_SOCKET, syscall.SO_REUSEADDR, (*byte)(unsafe.Pointer(&v)), &l)
  49. if operr != nil {
  50. return
  51. }
  52. switch addr := addr.(type) {
  53. case *TCPAddr:
  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:
  60. //
  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
  64. // IPv6 addresses.
  65. //
  66. // - When IP.To16() == nil and IP.To4() != nil,
  67. // the raw connection consists of an IPv4
  68. // socket using only IPv4 addresses.
  69. //
  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(syscall.Handle(s), syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, 1)
  76. } else if addr.IP.To16() == nil && addr.IP.To4() != nil {
  77. operr = syscall.SetsockoptInt(syscall.Handle(s), syscall.IPPROTO_IP, syscall.IP_TTL, 1)
  78. }
  79. }
  80. }
  81. if err := c.Control(fn); err != nil {
  82. return err
  83. }
  84. return operr
  85. }
  86. func controlOnConnSetup(network string, address string, c syscall.RawConn) error {
  87. var operr error
  88. var fn func(uintptr)
  89. switch network {
  90. case "tcp", "udp", "ip":
  91. return errors.New("ambiguous network: " + network)
  92. default:
  93. switch network[len(network)-1] {
  94. case '4':
  95. fn = func(s uintptr) {
  96. operr = syscall.SetsockoptInt(syscall.Handle(s), syscall.IPPROTO_IP, syscall.IP_TTL, 1)
  97. }
  98. case '6':
  99. fn = func(s uintptr) {
  100. operr = syscall.SetsockoptInt(syscall.Handle(s), syscall.IPPROTO_IPV6, syscall.IPV6_UNICAST_HOPS, 1)
  101. }
  102. default:
  103. return errors.New("unknown network: " + network)
  104. }
  105. }
  106. if err := c.Control(fn); err != nil {
  107. return err
  108. }
  109. return operr
  110. }