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