conn.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. // SPDX-License-Identifier: MIT
  2. //
  3. // Copyright (C) 2017-2023 WireGuard LLC. All Rights Reserved.
  4. package conn
  5. import (
  6. "errors"
  7. "fmt"
  8. "net/netip"
  9. "reflect"
  10. "runtime"
  11. "strings"
  12. )
  13. const (
  14. IdealBatchSize = 128 // maximum number of packets handled per read and write
  15. )
  16. // A ReceiveFunc receives at least one packet from the network and writes them
  17. // into packets. On a successful read it returns the number of elements of
  18. // sizes, packets, and endpoints that should be evaluated. Some elements of
  19. // sizes may be zero, and callers should ignore them. Callers must pass a sizes
  20. // and eps slice with a length greater than or equal to the length of packets.
  21. // These lengths must not exceed the length of the associated Bind.BatchSize().
  22. type ReceiveFunc func(packets [][]byte, sizes []int, eps []Endpoint) (n int, err error)
  23. // A Bind listens on a port for both IPv6 and IPv4 UDP traffic.
  24. //
  25. // A Bind interface may also be a PeekLookAtSocketFd or BindSocketToInterface,
  26. // depending on the platform-specific implementation.
  27. type Bind interface {
  28. // Open puts the Bind into a listening state on a given port and reports the actual
  29. // port that it bound to. Passing zero results in a random selection.
  30. // fns is the set of functions that will be called to receive packets.
  31. Open(port uint16) (fns []ReceiveFunc, actualPort uint16, err error)
  32. // Close closes the Bind listener.
  33. // All fns returned by Open must return net.ErrClosed after a call to Close.
  34. Close() error
  35. // SetMark sets the mark for each packet sent through this Bind.
  36. // This mark is passed to the kernel as the socket option SO_MARK.
  37. SetMark(mark uint32) error
  38. // Send writes one or more packets in bufs to address ep. The length of
  39. // bufs must not exceed BatchSize().
  40. Send(bufs [][]byte, ep Endpoint) error
  41. // ParseEndpoint creates a new endpoint from a string.
  42. ParseEndpoint(s string) (Endpoint, error)
  43. // BatchSize is the number of buffers expected to be passed to
  44. // the ReceiveFuncs, and the maximum expected to be passed to SendBatch.
  45. BatchSize() int
  46. }
  47. // BindSocketToInterface is implemented by Bind objects that support being
  48. // tied to a single network interface. Used by wireguard-windows.
  49. type BindSocketToInterface interface {
  50. BindSocketToInterface4(interfaceIndex uint32, blackhole bool) error
  51. BindSocketToInterface6(interfaceIndex uint32, blackhole bool) error
  52. }
  53. // PeekLookAtSocketFd is implemented by Bind objects that support having their
  54. // file descriptor peeked at. Used by wireguard-android.
  55. type PeekLookAtSocketFd interface {
  56. PeekLookAtSocketFd4() (fd int, err error)
  57. PeekLookAtSocketFd6() (fd int, err error)
  58. }
  59. // An Endpoint maintains the source/destination caching for a peer.
  60. //
  61. // dst: the remote address of a peer ("endpoint" in uapi terminology)
  62. // src: the local address from which datagrams originate going to the peer
  63. type Endpoint interface {
  64. ClearSrc() // clears the source address
  65. SrcToString() string // returns the local source address (ip:port)
  66. DstToString() string // returns the destination address (ip:port)
  67. DstToBytes() []byte // used for mac2 cookie calculations
  68. DstIP() netip.Addr
  69. SrcIP() netip.Addr
  70. }
  71. var (
  72. ErrBindAlreadyOpen = errors.New("bind is already open")
  73. ErrWrongEndpointType = errors.New("endpoint type does not correspond with bind type")
  74. )
  75. func (fn ReceiveFunc) PrettyName() string {
  76. name := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name()
  77. // 0. cheese/taco.beansIPv6.func12.func21218-fm
  78. name = strings.TrimSuffix(name, "-fm")
  79. // 1. cheese/taco.beansIPv6.func12.func21218
  80. if idx := strings.LastIndexByte(name, '/'); idx != -1 {
  81. name = name[idx+1:]
  82. // 2. taco.beansIPv6.func12.func21218
  83. }
  84. for {
  85. var idx int
  86. for idx = len(name) - 1; idx >= 0; idx-- {
  87. if name[idx] < '0' || name[idx] > '9' {
  88. break
  89. }
  90. }
  91. if idx == len(name)-1 {
  92. break
  93. }
  94. const dotFunc = ".func"
  95. if !strings.HasSuffix(name[:idx+1], dotFunc) {
  96. break
  97. }
  98. name = name[:idx+1-len(dotFunc)]
  99. // 3. taco.beansIPv6.func12
  100. // 4. taco.beansIPv6
  101. }
  102. if idx := strings.LastIndexByte(name, '.'); idx != -1 {
  103. name = name[idx+1:]
  104. // 5. beansIPv6
  105. }
  106. if name == "" {
  107. return fmt.Sprintf("%p", fn)
  108. }
  109. if strings.HasSuffix(name, "IPv4") {
  110. return "v4"
  111. }
  112. if strings.HasSuffix(name, "IPv6") {
  113. return "v6"
  114. }
  115. return name
  116. }