├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── device ├── device_linux.go ├── device_windows.go ├── dll_windows_386.go ├── dll_windows_amd64.go ├── dll_windows_arm.go ├── dll_windows_arm64.go └── wintun │ ├── LICENSE.txt │ ├── README.md │ ├── bin │ ├── amd64 │ │ └── wintun.dll │ ├── arm │ │ └── wintun.dll │ ├── arm64 │ │ └── wintun.dll │ └── x86 │ │ └── wintun.dll │ └── include │ └── wintun.h ├── go.mod ├── go.sum ├── tcp.go ├── test ├── main_windows.go ├── test.exe ├── test.go ├── test_linux.go ├── test_windows.go ├── tunat_linux_test.go └── wintun.dll ├── tunat.go ├── tunat_linux.go └── udp.go /.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FH0/tunat/efc19127d257534612fc68f435c2e73c6feda667/.gitignore -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 FH0 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: fmt golangci-lint 2 | 3 | all: fmt golangci-lint test-linux 4 | 5 | fmt: 6 | gofumpt -l -w . 7 | 8 | golangci-lint: 9 | golangci-lint run 10 | 11 | test-linux: 12 | go test -race -cover ./... 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # tunat 2 | golang tun nat 3 | -------------------------------------------------------------------------------- /device/device_linux.go: -------------------------------------------------------------------------------- 1 | package device 2 | 3 | import ( 4 | "errors" 5 | "net" 6 | "os" 7 | "syscall" 8 | "unsafe" 9 | 10 | "golang.org/x/sys/unix" 11 | ) 12 | 13 | type ifreq struct { 14 | ifrName [syscall.IFNAMSIZ]byte 15 | ifrFlags uint16 16 | } 17 | 18 | // New an issue https://github.com/golang/go/issues/30426#issuecomment-470335255 19 | func New(name string) (file *os.File, err error) { 20 | var tunPath string 21 | if _, err = os.Stat("/dev/net/tun"); err == nil { 22 | tunPath = "/dev/net/tun" 23 | } else if _, err = os.Stat("/dev/tun"); err == nil { 24 | tunPath = "/dev/tun" 25 | } else { 26 | return 27 | } 28 | 29 | fd, err := syscall.Open(tunPath, os.O_RDWR|syscall.O_NONBLOCK, 0) 30 | if err != nil { 31 | return 32 | } 33 | 34 | var req ifreq 35 | copy(req.ifrName[:], []byte(name)) 36 | req.ifrFlags = syscall.IFF_TUN | syscall.IFF_NO_PI 37 | 38 | _, _, errno := unix.Syscall( 39 | syscall.SYS_IOCTL, 40 | uintptr(fd), 41 | syscall.TUNSETIFF, 42 | uintptr(unsafe.Pointer(&req)), 43 | ) 44 | if errno != 0 { 45 | return nil, errno 46 | } 47 | 48 | file = os.NewFile(uintptr(fd), tunPath) 49 | return 50 | } 51 | 52 | // NewFromUnixSocket basically for Android 53 | func NewFromUnixSocket(path string) (_ *os.File, err error) { 54 | unixListener, err := net.ListenUnix("unix", &net.UnixAddr{ 55 | Name: path, 56 | Net: "unix", 57 | }) 58 | if err != nil { 59 | return 60 | } 61 | 62 | unixConn, err := unixListener.AcceptUnix() 63 | if err != nil { 64 | return 65 | } 66 | 67 | name := make([]byte, 256) 68 | oob := make([]byte, syscall.CmsgSpace(4)) // fd length is 4 69 | nameLen, oobLen, _, _, err := unixConn.ReadMsgUnix(name, oob) 70 | if err != nil { 71 | return 72 | } 73 | 74 | // parse msg 75 | cmsgs, err := syscall.ParseSocketControlMessage(oob[:oobLen]) 76 | if err != nil { 77 | return 78 | } 79 | if len(cmsgs) != 1 { 80 | return nil, errors.New("the number of cmsgs is not 1") 81 | } 82 | 83 | // get fd from msg 84 | fds, err := syscall.ParseUnixRights(&cmsgs[0]) 85 | if err != nil { 86 | return 87 | } 88 | if len(fds) != 1 { 89 | return nil, errors.New("the number of fds is not 1") 90 | } 91 | 92 | err = syscall.Unlink(path) 93 | if err != nil { 94 | return 95 | } 96 | 97 | file := os.NewFile(uintptr(fds[0]), string(name[:nameLen])) 98 | return file, nil 99 | } 100 | -------------------------------------------------------------------------------- /device/device_windows.go: -------------------------------------------------------------------------------- 1 | package device 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | "os" 8 | "sync" 9 | 10 | "golang.org/x/sys/windows" 11 | "golang.zx2c4.com/wintun" 12 | ) 13 | 14 | type device struct { 15 | adapter *wintun.Adapter 16 | session wintun.Session 17 | readWaitEvent windows.Handle 18 | closeOnce sync.Once 19 | } 20 | 21 | func (d *device) Read(buf []byte) (int, error) { 22 | for { 23 | packet, err := d.session.ReceivePacket() 24 | switch err { 25 | case nil: 26 | nread := copy(buf, packet) 27 | d.session.ReleaseReceivePacket(packet) 28 | return nread, err 29 | case windows.ERROR_NO_MORE_ITEMS: 30 | event, err := windows.WaitForSingleObject(d.readWaitEvent, windows.INFINITE) 31 | if err != nil { 32 | return 0, err 33 | } 34 | if event != windows.WAIT_OBJECT_0 { 35 | return 0, errors.New("event != windows.WAIT_OBJECT_0") 36 | } 37 | case windows.ERROR_HANDLE_EOF: 38 | return 0, os.ErrClosed 39 | case windows.ERROR_INVALID_DATA: 40 | return 0, errors.New("Send ring corrupt") 41 | default: 42 | return 0, fmt.Errorf("Read failed: %w", err) 43 | } 44 | } 45 | } 46 | 47 | func (d *device) Write(buf []byte) (int, error) { 48 | packet, err := d.session.AllocateSendPacket(len(buf)) 49 | if err == nil { 50 | nwrite := copy(packet, buf) 51 | d.session.SendPacket(packet) 52 | return nwrite, nil 53 | } 54 | switch err { 55 | case windows.ERROR_HANDLE_EOF: 56 | return 0, os.ErrClosed 57 | case windows.ERROR_BUFFER_OVERFLOW: 58 | return 0, nil // Dropping when ring is full. 59 | } 60 | return 0, fmt.Errorf("Write failed: %w", err) 61 | } 62 | 63 | func (d *device) Close() (err error) { 64 | d.closeOnce.Do(func() { 65 | d.session.End() 66 | if d.adapter != nil { 67 | err = d.adapter.Close() 68 | } 69 | }) 70 | return 71 | } 72 | 73 | // New create tun device 74 | func New(name string) (file io.ReadWriteCloser, err error) { 75 | if _, err = os.Stat("wintun.dll"); err != nil { 76 | err = os.WriteFile("wintun.dll", wintunDLL, 0o777) 77 | if err != nil { 78 | return 79 | } 80 | } 81 | 82 | device := &device{} 83 | device.adapter, err = wintun.CreateAdapter(name, "WireGuard", nil) 84 | if err != nil { 85 | return nil, fmt.Errorf("Error creating interface: %w", err) 86 | } 87 | device.session, err = device.adapter.StartSession(0x800000) 88 | if err != nil { 89 | device.adapter.Close() 90 | return 91 | } 92 | device.readWaitEvent = device.session.ReadWaitEvent() 93 | return device, nil 94 | } 95 | -------------------------------------------------------------------------------- /device/dll_windows_386.go: -------------------------------------------------------------------------------- 1 | package device 2 | 3 | import ( 4 | _ "embed" 5 | ) 6 | 7 | //go:embed wintun/bin/x86/wintun.dll 8 | var wintunDLL []byte 9 | -------------------------------------------------------------------------------- /device/dll_windows_amd64.go: -------------------------------------------------------------------------------- 1 | package device 2 | 3 | import ( 4 | _ "embed" 5 | ) 6 | 7 | //go:embed wintun/bin/amd64/wintun.dll 8 | var wintunDLL []byte 9 | -------------------------------------------------------------------------------- /device/dll_windows_arm.go: -------------------------------------------------------------------------------- 1 | package device 2 | 3 | import ( 4 | _ "embed" 5 | ) 6 | 7 | //go:embed wintun/bin/arm/wintun.dll 8 | var wintunDLL []byte 9 | -------------------------------------------------------------------------------- /device/dll_windows_arm64.go: -------------------------------------------------------------------------------- 1 | package device 2 | 3 | import ( 4 | _ "embed" 5 | ) 6 | 7 | //go:embed wintun/bin/arm64/wintun.dll 8 | var wintunDLL []byte 9 | -------------------------------------------------------------------------------- /device/wintun/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Prebuilt Binaries License 2 | ------------------------- 3 | 4 | 1. DEFINITIONS. "Software" means the precise contents of the "wintun.dll" 5 | files that are included in the .zip file that contains this document as 6 | downloaded from wintun.net/builds. 7 | 8 | 2. LICENSE GRANT. WireGuard LLC grants to you a non-exclusive and 9 | non-transferable right to use Software for lawful purposes under certain 10 | obligations and limited rights as set forth in this agreement. 11 | 12 | 3. RESTRICTIONS. Software is owned and copyrighted by WireGuard LLC. It is 13 | licensed, not sold. Title to Software and all associated intellectual 14 | property rights are retained by WireGuard. You must not: 15 | a. reverse engineer, decompile, disassemble, extract from, or otherwise 16 | modify the Software; 17 | b. modify or create derivative work based upon Software in whole or in 18 | parts, except insofar as only the API interfaces of the "wintun.h" file 19 | distributed alongside the Software (the "Permitted API") are used; 20 | c. remove any proprietary notices, labels, or copyrights from the Software; 21 | d. resell, redistribute, lease, rent, transfer, sublicense, or otherwise 22 | transfer rights of the Software without the prior written consent of 23 | WireGuard LLC, except insofar as the Software is distributed alongside 24 | other software that uses the Software only via the Permitted API; 25 | e. use the name of WireGuard LLC, the WireGuard project, the Wintun 26 | project, or the names of its contributors to endorse or promote products 27 | derived from the Software without specific prior written consent. 28 | 29 | 4. LIMITED WARRANTY. THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF 30 | ANY KIND. WIREGUARD LLC HEREBY EXCLUDES AND DISCLAIMS ALL IMPLIED OR 31 | STATUTORY WARRANTIES, INCLUDING ANY WARRANTIES OF MERCHANTABILITY, FITNESS 32 | FOR A PARTICULAR PURPOSE, QUALITY, NON-INFRINGEMENT, TITLE, RESULTS, 33 | EFFORTS, OR QUIET ENJOYMENT. THERE IS NO WARRANTY THAT THE PRODUCT WILL BE 34 | ERROR-FREE OR WILL FUNCTION WITHOUT INTERRUPTION. YOU ASSUME THE ENTIRE 35 | RISK FOR THE RESULTS OBTAINED USING THE PRODUCT. TO THE EXTENT THAT 36 | WIREGUARD LLC MAY NOT DISCLAIM ANY WARRANTY AS A MATTER OF APPLICABLE LAW, 37 | THE SCOPE AND DURATION OF SUCH WARRANTY WILL BE THE MINIMUM PERMITTED UNDER 38 | SUCH LAW. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND 39 | WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR 40 | A PARTICULAR PURPOSE OR NON-INFRINGEMENT ARE DISCLAIMED, EXCEPT TO THE 41 | EXTENT THAT THESE DISCLAIMERS ARE HELD TO BE LEGALLY INVALID. 42 | 43 | 5. LIMITATION OF LIABILITY. To the extent not prohibited by law, in no event 44 | WireGuard LLC or any third-party-developer will be liable for any lost 45 | revenue, profit or data or for special, indirect, consequential, incidental 46 | or punitive damages, however caused regardless of the theory of liability, 47 | arising out of or related to the use of or inability to use Software, even 48 | if WireGuard LLC has been advised of the possibility of such damages. 49 | Solely you are responsible for determining the appropriateness of using 50 | Software and accept full responsibility for all risks associated with its 51 | exercise of rights under this agreement, including but not limited to the 52 | risks and costs of program errors, compliance with applicable laws, damage 53 | to or loss of data, programs or equipment, and unavailability or 54 | interruption of operations. The foregoing limitations will apply even if 55 | the above stated warranty fails of its essential purpose. You acknowledge, 56 | that it is in the nature of software that software is complex and not 57 | completely free of errors. In no event shall WireGuard LLC or any 58 | third-party-developer be liable to you under any theory for any damages 59 | suffered by you or any user of Software or for any special, incidental, 60 | indirect, consequential or similar damages (including without limitation 61 | damages for loss of business profits, business interruption, loss of 62 | business information or any other pecuniary loss) arising out of the use or 63 | inability to use Software, even if WireGuard LLC has been advised of the 64 | possibility of such damages and regardless of the legal or quitable theory 65 | (contract, tort, or otherwise) upon which the claim is based. 66 | 67 | 6. TERMINATION. This agreement is affected until terminated. You may 68 | terminate this agreement at any time. This agreement will terminate 69 | immediately without notice from WireGuard LLC if you fail to comply with 70 | the terms and conditions of this agreement. Upon termination, you must 71 | delete Software and all copies of Software and cease all forms of 72 | distribution of Software. 73 | 74 | 7. SEVERABILITY. If any provision of this agreement is held to be 75 | unenforceable, this agreement will remain in effect with the provision 76 | omitted, unless omission would frustrate the intent of the parties, in 77 | which case this agreement will immediately terminate. 78 | 79 | 8. RESERVATION OF RIGHTS. All rights not expressly granted in this agreement 80 | are reserved by WireGuard LLC. For example, WireGuard LLC reserves the 81 | right at any time to cease development of Software, to alter distribution 82 | details, features, specifications, capabilities, functions, licensing 83 | terms, release dates, APIs, ABIs, general availability, or other 84 | characteristics of the Software. 85 | -------------------------------------------------------------------------------- /device/wintun/README.md: -------------------------------------------------------------------------------- 1 | # [Wintun Network Adapter](https://www.wintun.net/) 2 | ### TUN Device Driver for Windows 3 | 4 | This is a layer 3 TUN driver for Windows 7, 8, 8.1, and 10. Originally created for [WireGuard](https://www.wireguard.com/), it is intended to be useful to a wide variety of projects that require layer 3 tunneling devices with implementations primarily in userspace. 5 | 6 | ## Installation 7 | 8 | Wintun is deployed as a platform-specific `wintun.dll` file. Install the `wintun.dll` file side-by-side with your application. Download the dll from [wintun.net](https://www.wintun.net/), alongside the header file for your application described below. 9 | 10 | ## Usage 11 | 12 | Include the [`wintun.h` file](https://git.zx2c4.com/wintun/tree/api/wintun.h) in your project simply by copying it there and dynamically load the `wintun.dll` using [`LoadLibraryEx()`](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexa) and [`GetProcAddress()`](https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-getprocaddress) to resolve each function, using the typedefs provided in the header file. The [`InitializeWintun` function in the example.c code](https://git.zx2c4.com/wintun/tree/example/example.c) provides this in a function that you can simply copy and paste. 13 | 14 | With the library setup, Wintun can then be used by first creating an adapter, configuring it, and then setting its status to "up". Adapters have names (e.g. "OfficeNet") and types (e.g. "Wintun"). 15 | 16 | ```C 17 | WINTUN_ADAPTER_HANDLE Adapter1 = WintunCreateAdapter(L"OfficeNet", L"Wintun", &SomeFixedGUID1); 18 | WINTUN_ADAPTER_HANDLE Adapter2 = WintunCreateAdapter(L"HomeNet", L"Wintun", &SomeFixedGUID2); 19 | WINTUN_ADAPTER_HANDLE Adapter3 = WintunCreateAdapter(L"Data Center", L"Wintun", &SomeFixedGUID3); 20 | ``` 21 | 22 | After creating an adapter, we can use it by starting a session: 23 | 24 | ```C 25 | WINTUN_SESSION_HANDLE Session = WintunStartSession(Adapter2, 0x400000); 26 | ``` 27 | 28 | Then, the `WintunAllocateSendPacket` and `WintunSendPacket` functions can be used for sending packets ([used by `SendPackets` in the example.c code](https://git.zx2c4.com/wintun/tree/example/example.c)): 29 | 30 | ```C 31 | BYTE *OutgoingPacket = WintunAllocateSendPacket(Session, PacketDataSize); 32 | if (OutgoingPacket) 33 | { 34 | memcpy(OutgoingPacket, PacketData, PacketDataSize); 35 | WintunSendPacket(Session, OutgoingPacket); 36 | } 37 | else if (GetLastError() != ERROR_BUFFER_OVERFLOW) // Silently drop packets if the ring is full 38 | Log(L"Packet write failed"); 39 | ``` 40 | 41 | And the `WintunReceivePacket` and `WintunReleaseReceivePacket` functions can be used for receiving packets ([used by `ReceivePackets` in the example.c code](https://git.zx2c4.com/wintun/tree/example/example.c)): 42 | 43 | ```C 44 | for (;;) 45 | { 46 | DWORD IncomingPacketSize; 47 | BYTE *IncomingPacket = WintunReceivePacket(Session, &IncomingPacketSize); 48 | if (IncomingPacket) 49 | { 50 | DoSomethingWithPacket(IncomingPacket, IncomingPacketSize); 51 | WintunReleaseReceivePacket(Session, IncomingPacket); 52 | } 53 | else if (GetLastError() == ERROR_NO_MORE_ITEMS) 54 | WaitForSingleObject(WintunGetReadWaitEvent(Session), INFINITE); 55 | else 56 | { 57 | Log(L"Packet read failed"); 58 | break; 59 | } 60 | } 61 | ``` 62 | 63 | Some high performance use cases may want to spin on `WintunReceivePackets` for a number of cycles before falling back to waiting on the read-wait event. 64 | 65 | You are **highly encouraged** to read the [**example.c short example**](https://git.zx2c4.com/wintun/tree/example/example.c) to see how to put together a simple userspace network tunnel. 66 | 67 | The various functions and definitions are [documented in the reference below](#Reference). 68 | 69 | ## Reference 70 | 71 | ### Macro Definitions 72 | 73 | #### WINTUN\_MAX\_POOL 74 | 75 | `#define WINTUN_MAX_POOL 256` 76 | 77 | Maximum pool name length including zero terminator 78 | 79 | #### WINTUN\_MIN\_RING\_CAPACITY 80 | 81 | `#define WINTUN_MIN_RING_CAPACITY 0x20000 /* 128kiB */` 82 | 83 | Minimum ring capacity. 84 | 85 | #### WINTUN\_MAX\_RING\_CAPACITY 86 | 87 | `#define WINTUN_MAX_RING_CAPACITY 0x4000000 /* 64MiB */` 88 | 89 | Maximum ring capacity. 90 | 91 | #### WINTUN\_MAX\_IP\_PACKET\_SIZE 92 | 93 | `#define WINTUN_MAX_IP_PACKET_SIZE 0xFFFF` 94 | 95 | Maximum IP packet size 96 | 97 | ### Typedefs 98 | 99 | #### WINTUN\_ADAPTER\_HANDLE 100 | 101 | `typedef void* WINTUN_ADAPTER_HANDLE` 102 | 103 | A handle representing Wintun adapter 104 | 105 | #### WINTUN\_ENUM\_CALLBACK 106 | 107 | `typedef BOOL(* WINTUN_ENUM_CALLBACK) (WINTUN_ADAPTER_HANDLE Adapter, LPARAM Param)` 108 | 109 | Called by WintunEnumAdapters for each adapter in the pool. 110 | 111 | **Parameters** 112 | 113 | - *Adapter*: Adapter handle, which will be freed when this function returns. 114 | - *Param*: An application-defined value passed to the WintunEnumAdapters. 115 | 116 | **Returns** 117 | 118 | Non-zero to continue iterating adapters; zero to stop. 119 | 120 | #### WINTUN\_LOGGER\_CALLBACK 121 | 122 | `typedef void(* WINTUN_LOGGER_CALLBACK) (WINTUN_LOGGER_LEVEL Level, DWORD64 Timestamp, const WCHAR *Message)` 123 | 124 | Called by internal logger to report diagnostic messages 125 | 126 | **Parameters** 127 | 128 | - *Level*: Message level. 129 | - *Timestamp*: Message timestamp in in 100ns intervals since 1601-01-01 UTC. 130 | - *Message*: Message text. 131 | 132 | #### WINTUN\_SESSION\_HANDLE 133 | 134 | `typedef void* WINTUN_SESSION_HANDLE` 135 | 136 | A handle representing Wintun session 137 | 138 | ### Enumeration Types 139 | 140 | #### WINTUN\_LOGGER\_LEVEL 141 | 142 | `enum WINTUN_LOGGER_LEVEL` 143 | 144 | Determines the level of logging, passed to WINTUN\_LOGGER\_CALLBACK. 145 | 146 | - *WINTUN\_LOG\_INFO*: Informational 147 | - *WINTUN\_LOG\_WARN*: Warning 148 | - *WINTUN\_LOG\_ERR*: Error 149 | 150 | Enumerator 151 | 152 | ### Functions 153 | 154 | #### WintunCreateAdapter() 155 | 156 | `WINTUN_ADAPTER_HANDLE WintunCreateAdapter (const WCHAR * Name, const WCHAR * TunnelType, const GUID * RequestedGUID)` 157 | 158 | Creates a new Wintun adapter. 159 | 160 | **Parameters** 161 | 162 | - *Name*: The requested name of the adapter. Zero-terminated string of up to MAX\_ADAPTER\_NAME-1 characters. 163 | - *Name*: Name of the adapter tunnel type. Zero-terminated string of up to MAX\_ADAPTER\_NAME-1 characters. 164 | - *RequestedGUID*: The GUID of the created network adapter, which then influences NLA generation deterministically. If it is set to NULL, the GUID is chosen by the system at random, and hence a new NLA entry is created for each new adapter. It is called "requested" GUID because the API it uses is completely undocumented, and so there could be minor interesting complications with its usage. 165 | 166 | **Returns** 167 | 168 | If the function succeeds, the return value is the adapter handle. Must be released with WintunCloseAdapter. If the function fails, the return value is NULL. To get extended error information, call GetLastError. 169 | 170 | #### WintunOpenAdapter() 171 | 172 | `WINTUN_ADAPTER_HANDLE WintunOpenAdapter (const WCHAR * Name)` 173 | 174 | Opens an existing Wintun adapter. 175 | 176 | **Parameters** 177 | 178 | - *Name*: The requested name of the adapter. Zero-terminated string of up to MAX\_ADAPTER\_NAME-1 characters. 179 | 180 | **Returns** 181 | 182 | If the function succeeds, the return value is adapter handle. Must be released with WintunCloseAdapter. If the function fails, the return value is NULL. To get extended error information, call GetLastError. 183 | 184 | #### WintunCloseAdapter() 185 | 186 | `void WintunCloseAdapter (WINTUN_ADAPTER_HANDLE Adapter)` 187 | 188 | Releases Wintun adapter resources and, if adapter was created with WintunCreateAdapter, removes adapter. 189 | 190 | **Parameters** 191 | 192 | - *Adapter*: Adapter handle obtained with WintunCreateAdapter or WintunOpenAdapter. 193 | 194 | #### WintunDeleteDriver() 195 | 196 | `BOOL WintunDeleteDriver ()` 197 | 198 | Deletes the Wintun driver if there are no more adapters in use. 199 | 200 | **Returns** 201 | 202 | If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To get extended error information, call GetLastError. 203 | 204 | #### WintunGetAdapterLuid() 205 | 206 | `void WintunGetAdapterLuid (WINTUN_ADAPTER_HANDLE Adapter, NET_LUID * Luid)` 207 | 208 | Returns the LUID of the adapter. 209 | 210 | **Parameters** 211 | 212 | - *Adapter*: Adapter handle obtained with WintunOpenAdapter or WintunCreateAdapter 213 | - *Luid*: Pointer to LUID to receive adapter LUID. 214 | 215 | #### WintunGetRunningDriverVersion() 216 | 217 | `DWORD WintunGetRunningDriverVersion (void )` 218 | 219 | Determines the version of the Wintun driver currently loaded. 220 | 221 | **Returns** 222 | 223 | If the function succeeds, the return value is the version number. If the function fails, the return value is zero. To get extended error information, call GetLastError. Possible errors include the following: ERROR\_FILE\_NOT\_FOUND Wintun not loaded 224 | 225 | #### WintunSetLogger() 226 | 227 | `void WintunSetLogger (WINTUN_LOGGER_CALLBACK NewLogger)` 228 | 229 | Sets logger callback function. 230 | 231 | **Parameters** 232 | 233 | - *NewLogger*: Pointer to callback function to use as a new global logger. NewLogger may be called from various threads concurrently. Should the logging require serialization, you must handle serialization in NewLogger. Set to NULL to disable. 234 | 235 | #### WintunStartSession() 236 | 237 | `WINTUN_SESSION_HANDLE WintunStartSession (WINTUN_ADAPTER_HANDLE Adapter, DWORD Capacity)` 238 | 239 | Starts Wintun session. 240 | 241 | **Parameters** 242 | 243 | - *Adapter*: Adapter handle obtained with WintunOpenAdapter or WintunCreateAdapter 244 | - *Capacity*: Rings capacity. Must be between WINTUN\_MIN\_RING\_CAPACITY and WINTUN\_MAX\_RING\_CAPACITY (incl.) Must be a power of two. 245 | 246 | **Returns** 247 | 248 | Wintun session handle. Must be released with WintunEndSession. If the function fails, the return value is NULL. To get extended error information, call GetLastError. 249 | 250 | #### WintunEndSession() 251 | 252 | `void WintunEndSession (WINTUN_SESSION_HANDLE Session)` 253 | 254 | Ends Wintun session. 255 | 256 | **Parameters** 257 | 258 | - *Session*: Wintun session handle obtained with WintunStartSession 259 | 260 | #### WintunGetReadWaitEvent() 261 | 262 | `HANDLE WintunGetReadWaitEvent (WINTUN_SESSION_HANDLE Session)` 263 | 264 | Gets Wintun session's read-wait event handle. 265 | 266 | **Parameters** 267 | 268 | - *Session*: Wintun session handle obtained with WintunStartSession 269 | 270 | **Returns** 271 | 272 | Pointer to receive event handle to wait for available data when reading. Should WintunReceivePackets return ERROR\_NO\_MORE\_ITEMS (after spinning on it for a while under heavy load), wait for this event to become signaled before retrying WintunReceivePackets. Do not call CloseHandle on this event - it is managed by the session. 273 | 274 | #### WintunReceivePacket() 275 | 276 | `BYTE* WintunReceivePacket (WINTUN_SESSION_HANDLE Session, DWORD * PacketSize)` 277 | 278 | Retrieves one or packet. After the packet content is consumed, call WintunReleaseReceivePacket with Packet returned from this function to release internal buffer. This function is thread-safe. 279 | 280 | **Parameters** 281 | 282 | - *Session*: Wintun session handle obtained with WintunStartSession 283 | - *PacketSize*: Pointer to receive packet size. 284 | 285 | **Returns** 286 | 287 | Pointer to layer 3 IPv4 or IPv6 packet. Client may modify its content at will. If the function fails, the return value is NULL. To get extended error information, call GetLastError. Possible errors include the following: ERROR\_HANDLE\_EOF Wintun adapter is terminating; ERROR\_NO\_MORE\_ITEMS Wintun buffer is exhausted; ERROR\_INVALID\_DATA Wintun buffer is corrupt 288 | 289 | #### WintunReleaseReceivePacket() 290 | 291 | `void WintunReleaseReceivePacket (WINTUN_SESSION_HANDLE Session, const BYTE * Packet)` 292 | 293 | Releases internal buffer after the received packet has been processed by the client. This function is thread-safe. 294 | 295 | **Parameters** 296 | 297 | - *Session*: Wintun session handle obtained with WintunStartSession 298 | - *Packet*: Packet obtained with WintunReceivePacket 299 | 300 | #### WintunAllocateSendPacket() 301 | 302 | `BYTE* WintunAllocateSendPacket (WINTUN_SESSION_HANDLE Session, DWORD PacketSize)` 303 | 304 | Allocates memory for a packet to send. After the memory is filled with packet data, call WintunSendPacket to send and release internal buffer. WintunAllocateSendPacket is thread-safe and the WintunAllocateSendPacket order of calls define the packet sending order. 305 | 306 | **Parameters** 307 | 308 | - *Session*: Wintun session handle obtained with WintunStartSession 309 | - *PacketSize*: Exact packet size. Must be less or equal to WINTUN\_MAX\_IP\_PACKET\_SIZE. 310 | 311 | **Returns** 312 | 313 | Returns pointer to memory where to prepare layer 3 IPv4 or IPv6 packet for sending. If the function fails, the return value is NULL. To get extended error information, call GetLastError. Possible errors include the following: ERROR\_HANDLE\_EOF Wintun adapter is terminating; ERROR\_BUFFER\_OVERFLOW Wintun buffer is full; 314 | 315 | #### WintunSendPacket() 316 | 317 | `void WintunSendPacket (WINTUN_SESSION_HANDLE Session, const BYTE * Packet)` 318 | 319 | Sends the packet and releases internal buffer. WintunSendPacket is thread-safe, but the WintunAllocateSendPacket order of calls define the packet sending order. This means the packet is not guaranteed to be sent in the WintunSendPacket yet. 320 | 321 | **Parameters** 322 | 323 | - *Session*: Wintun session handle obtained with WintunStartSession 324 | - *Packet*: Packet obtained with WintunAllocateSendPacket 325 | 326 | ## Building 327 | 328 | **Do not distribute drivers or files named "Wintun", as they will most certainly clash with official deployments. Instead distribute [`wintun.dll` as downloaded from wintun.net](https://www.wintun.net).** 329 | 330 | General requirements: 331 | 332 | - [Visual Studio 2019](https://visualstudio.microsoft.com/downloads/) with Windows SDK 333 | - [Windows Driver Kit](https://docs.microsoft.com/en-us/windows-hardware/drivers/download-the-wdk) 334 | 335 | `wintun.sln` may be opened in Visual Studio for development and building. Be sure to run `bcdedit /set testsigning on` and then reboot before to enable unsigned driver loading. The default run sequence (F5) in Visual Studio will build the example project and its dependencies. 336 | 337 | ## License 338 | 339 | The entire contents of [the repository](https://git.zx2c4.com/wintun/), including all documentation and example code, is "Copyright © 2018-2021 WireGuard LLC. All Rights Reserved." Source code is licensed under the [GPLv2](COPYING). Prebuilt binaries from [wintun.net](https://www.wintun.net/) are released under a more permissive license suitable for more forms of software contained inside of the .zip files distributed there. 340 | -------------------------------------------------------------------------------- /device/wintun/bin/amd64/wintun.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FH0/tunat/efc19127d257534612fc68f435c2e73c6feda667/device/wintun/bin/amd64/wintun.dll -------------------------------------------------------------------------------- /device/wintun/bin/arm/wintun.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FH0/tunat/efc19127d257534612fc68f435c2e73c6feda667/device/wintun/bin/arm/wintun.dll -------------------------------------------------------------------------------- /device/wintun/bin/arm64/wintun.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FH0/tunat/efc19127d257534612fc68f435c2e73c6feda667/device/wintun/bin/arm64/wintun.dll -------------------------------------------------------------------------------- /device/wintun/bin/x86/wintun.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FH0/tunat/efc19127d257534612fc68f435c2e73c6feda667/device/wintun/bin/x86/wintun.dll -------------------------------------------------------------------------------- /device/wintun/include/wintun.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0 OR MIT 2 | * 3 | * Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved. 4 | */ 5 | 6 | #pragma once 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #ifdef __cplusplus 15 | extern "C" { 16 | #endif 17 | 18 | #ifndef ALIGNED 19 | # if defined(_MSC_VER) 20 | # define ALIGNED(n) __declspec(align(n)) 21 | # elif defined(__GNUC__) 22 | # define ALIGNED(n) __attribute__((aligned(n))) 23 | # else 24 | # error "Unable to define ALIGNED" 25 | # endif 26 | #endif 27 | 28 | /* MinGW is missing this one, unfortunately. */ 29 | #ifndef _Post_maybenull_ 30 | # define _Post_maybenull_ 31 | #endif 32 | 33 | #pragma warning(push) 34 | #pragma warning(disable : 4324) /* structure was padded due to alignment specifier */ 35 | 36 | /** 37 | * A handle representing Wintun adapter 38 | */ 39 | typedef struct _WINTUN_ADAPTER *WINTUN_ADAPTER_HANDLE; 40 | 41 | /** 42 | * Creates a new Wintun adapter. 43 | * 44 | * @param Name The requested name of the adapter. Zero-terminated string of up to MAX_ADAPTER_NAME-1 45 | * characters. 46 | * 47 | * @param TunnelType Name of the adapter tunnel type. Zero-terminated string of up to MAX_ADAPTER_NAME-1 48 | * characters. 49 | * 50 | * @param RequestedGUID The GUID of the created network adapter, which then influences NLA generation deterministically. 51 | * If it is set to NULL, the GUID is chosen by the system at random, and hence a new NLA entry is 52 | * created for each new adapter. It is called "requested" GUID because the API it uses is 53 | * completely undocumented, and so there could be minor interesting complications with its usage. 54 | * 55 | * @return If the function succeeds, the return value is the adapter handle. Must be released with 56 | * WintunCloseAdapter. If the function fails, the return value is NULL. To get extended error information, call 57 | * GetLastError. 58 | */ 59 | typedef _Must_inspect_result_ 60 | _Return_type_success_(return != NULL) 61 | _Post_maybenull_ 62 | WINTUN_ADAPTER_HANDLE(WINAPI WINTUN_CREATE_ADAPTER_FUNC) 63 | (_In_z_ LPCWSTR Name, _In_z_ LPCWSTR TunnelType, _In_opt_ const GUID *RequestedGUID); 64 | 65 | /** 66 | * Opens an existing Wintun adapter. 67 | * 68 | * @param Name The requested name of the adapter. Zero-terminated string of up to MAX_ADAPTER_NAME-1 69 | * characters. 70 | * 71 | * @return If the function succeeds, the return value is the adapter handle. Must be released with 72 | * WintunCloseAdapter. If the function fails, the return value is NULL. To get extended error information, call 73 | * GetLastError. 74 | */ 75 | typedef _Must_inspect_result_ 76 | _Return_type_success_(return != NULL) 77 | _Post_maybenull_ 78 | WINTUN_ADAPTER_HANDLE(WINAPI WINTUN_OPEN_ADAPTER_FUNC)(_In_z_ LPCWSTR Name); 79 | 80 | /** 81 | * Releases Wintun adapter resources and, if adapter was created with WintunCreateAdapter, removes adapter. 82 | * 83 | * @param Adapter Adapter handle obtained with WintunCreateAdapter or WintunOpenAdapter. 84 | */ 85 | typedef VOID(WINAPI WINTUN_CLOSE_ADAPTER_FUNC)(_In_opt_ WINTUN_ADAPTER_HANDLE Adapter); 86 | 87 | /** 88 | * Deletes the Wintun driver if there are no more adapters in use. 89 | * 90 | * @return If the function succeeds, the return value is nonzero. If the function fails, the return value is zero. To 91 | * get extended error information, call GetLastError. 92 | */ 93 | typedef _Return_type_success_(return != FALSE) 94 | BOOL(WINAPI WINTUN_DELETE_DRIVER_FUNC)(VOID); 95 | 96 | /** 97 | * Returns the LUID of the adapter. 98 | * 99 | * @param Adapter Adapter handle obtained with WintunCreateAdapter or WintunOpenAdapter 100 | * 101 | * @param Luid Pointer to LUID to receive adapter LUID. 102 | */ 103 | typedef VOID(WINAPI WINTUN_GET_ADAPTER_LUID_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _Out_ NET_LUID *Luid); 104 | 105 | /** 106 | * Determines the version of the Wintun driver currently loaded. 107 | * 108 | * @return If the function succeeds, the return value is the version number. If the function fails, the return value is 109 | * zero. To get extended error information, call GetLastError. Possible errors include the following: 110 | * ERROR_FILE_NOT_FOUND Wintun not loaded 111 | */ 112 | typedef _Return_type_success_(return != 0) 113 | DWORD(WINAPI WINTUN_GET_RUNNING_DRIVER_VERSION_FUNC)(VOID); 114 | 115 | /** 116 | * Determines the level of logging, passed to WINTUN_LOGGER_CALLBACK. 117 | */ 118 | typedef enum 119 | { 120 | WINTUN_LOG_INFO, /**< Informational */ 121 | WINTUN_LOG_WARN, /**< Warning */ 122 | WINTUN_LOG_ERR /**< Error */ 123 | } WINTUN_LOGGER_LEVEL; 124 | 125 | /** 126 | * Called by internal logger to report diagnostic messages 127 | * 128 | * @param Level Message level. 129 | * 130 | * @param Timestamp Message timestamp in in 100ns intervals since 1601-01-01 UTC. 131 | * 132 | * @param Message Message text. 133 | */ 134 | typedef VOID(CALLBACK *WINTUN_LOGGER_CALLBACK)( 135 | _In_ WINTUN_LOGGER_LEVEL Level, 136 | _In_ DWORD64 Timestamp, 137 | _In_z_ LPCWSTR Message); 138 | 139 | /** 140 | * Sets logger callback function. 141 | * 142 | * @param NewLogger Pointer to callback function to use as a new global logger. NewLogger may be called from various 143 | * threads concurrently. Should the logging require serialization, you must handle serialization in 144 | * NewLogger. Set to NULL to disable. 145 | */ 146 | typedef VOID(WINAPI WINTUN_SET_LOGGER_FUNC)(_In_ WINTUN_LOGGER_CALLBACK NewLogger); 147 | 148 | /** 149 | * Minimum ring capacity. 150 | */ 151 | #define WINTUN_MIN_RING_CAPACITY 0x20000 /* 128kiB */ 152 | 153 | /** 154 | * Maximum ring capacity. 155 | */ 156 | #define WINTUN_MAX_RING_CAPACITY 0x4000000 /* 64MiB */ 157 | 158 | /** 159 | * A handle representing Wintun session 160 | */ 161 | typedef struct _TUN_SESSION *WINTUN_SESSION_HANDLE; 162 | 163 | /** 164 | * Starts Wintun session. 165 | * 166 | * @param Adapter Adapter handle obtained with WintunOpenAdapter or WintunCreateAdapter 167 | * 168 | * @param Capacity Rings capacity. Must be between WINTUN_MIN_RING_CAPACITY and WINTUN_MAX_RING_CAPACITY (incl.) 169 | * Must be a power of two. 170 | * 171 | * @return Wintun session handle. Must be released with WintunEndSession. If the function fails, the return value is 172 | * NULL. To get extended error information, call GetLastError. 173 | */ 174 | typedef _Must_inspect_result_ 175 | _Return_type_success_(return != NULL) 176 | _Post_maybenull_ 177 | WINTUN_SESSION_HANDLE(WINAPI WINTUN_START_SESSION_FUNC)(_In_ WINTUN_ADAPTER_HANDLE Adapter, _In_ DWORD Capacity); 178 | 179 | /** 180 | * Ends Wintun session. 181 | * 182 | * @param Session Wintun session handle obtained with WintunStartSession 183 | */ 184 | typedef VOID(WINAPI WINTUN_END_SESSION_FUNC)(_In_ WINTUN_SESSION_HANDLE Session); 185 | 186 | /** 187 | * Gets Wintun session's read-wait event handle. 188 | * 189 | * @param Session Wintun session handle obtained with WintunStartSession 190 | * 191 | * @return Pointer to receive event handle to wait for available data when reading. Should 192 | * WintunReceivePackets return ERROR_NO_MORE_ITEMS (after spinning on it for a while under heavy 193 | * load), wait for this event to become signaled before retrying WintunReceivePackets. Do not call 194 | * CloseHandle on this event - it is managed by the session. 195 | */ 196 | typedef HANDLE(WINAPI WINTUN_GET_READ_WAIT_EVENT_FUNC)(_In_ WINTUN_SESSION_HANDLE Session); 197 | 198 | /** 199 | * Maximum IP packet size 200 | */ 201 | #define WINTUN_MAX_IP_PACKET_SIZE 0xFFFF 202 | 203 | /** 204 | * Retrieves one or packet. After the packet content is consumed, call WintunReleaseReceivePacket with Packet returned 205 | * from this function to release internal buffer. This function is thread-safe. 206 | * 207 | * @param Session Wintun session handle obtained with WintunStartSession 208 | * 209 | * @param PacketSize Pointer to receive packet size. 210 | * 211 | * @return Pointer to layer 3 IPv4 or IPv6 packet. Client may modify its content at will. If the function fails, the 212 | * return value is NULL. To get extended error information, call GetLastError. Possible errors include the 213 | * following: 214 | * ERROR_HANDLE_EOF Wintun adapter is terminating; 215 | * ERROR_NO_MORE_ITEMS Wintun buffer is exhausted; 216 | * ERROR_INVALID_DATA Wintun buffer is corrupt 217 | */ 218 | typedef _Must_inspect_result_ 219 | _Return_type_success_(return != NULL) 220 | _Post_maybenull_ 221 | _Post_writable_byte_size_(*PacketSize) 222 | BYTE *(WINAPI WINTUN_RECEIVE_PACKET_FUNC)(_In_ WINTUN_SESSION_HANDLE Session, _Out_ DWORD *PacketSize); 223 | 224 | /** 225 | * Releases internal buffer after the received packet has been processed by the client. This function is thread-safe. 226 | * 227 | * @param Session Wintun session handle obtained with WintunStartSession 228 | * 229 | * @param Packet Packet obtained with WintunReceivePacket 230 | */ 231 | typedef VOID( 232 | WINAPI WINTUN_RELEASE_RECEIVE_PACKET_FUNC)(_In_ WINTUN_SESSION_HANDLE Session, _In_ const BYTE *Packet); 233 | 234 | /** 235 | * Allocates memory for a packet to send. After the memory is filled with packet data, call WintunSendPacket to send 236 | * and release internal buffer. WintunAllocateSendPacket is thread-safe and the WintunAllocateSendPacket order of 237 | * calls define the packet sending order. 238 | * 239 | * @param Session Wintun session handle obtained with WintunStartSession 240 | * 241 | * @param PacketSize Exact packet size. Must be less or equal to WINTUN_MAX_IP_PACKET_SIZE. 242 | * 243 | * @return Returns pointer to memory where to prepare layer 3 IPv4 or IPv6 packet for sending. If the function fails, 244 | * the return value is NULL. To get extended error information, call GetLastError. Possible errors include the 245 | * following: 246 | * ERROR_HANDLE_EOF Wintun adapter is terminating; 247 | * ERROR_BUFFER_OVERFLOW Wintun buffer is full; 248 | */ 249 | typedef _Must_inspect_result_ 250 | _Return_type_success_(return != NULL) 251 | _Post_maybenull_ 252 | _Post_writable_byte_size_(PacketSize) 253 | BYTE *(WINAPI WINTUN_ALLOCATE_SEND_PACKET_FUNC)(_In_ WINTUN_SESSION_HANDLE Session, _In_ DWORD PacketSize); 254 | 255 | /** 256 | * Sends the packet and releases internal buffer. WintunSendPacket is thread-safe, but the WintunAllocateSendPacket 257 | * order of calls define the packet sending order. This means the packet is not guaranteed to be sent in the 258 | * WintunSendPacket yet. 259 | * 260 | * @param Session Wintun session handle obtained with WintunStartSession 261 | * 262 | * @param Packet Packet obtained with WintunAllocateSendPacket 263 | */ 264 | typedef VOID(WINAPI WINTUN_SEND_PACKET_FUNC)(_In_ WINTUN_SESSION_HANDLE Session, _In_ const BYTE *Packet); 265 | 266 | #pragma warning(pop) 267 | 268 | #ifdef __cplusplus 269 | } 270 | #endif 271 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/FH0/tunat 2 | 3 | go 1.17 4 | 5 | require ( 6 | golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 7 | golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 8 | gvisor.dev/gvisor v0.0.0-20220720011844-c2fcd7b14d4b 9 | ) 10 | 11 | require ( 12 | github.com/google/btree v1.1.2 // indirect 13 | golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect 14 | ) 15 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= 2 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 3 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 4 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= 5 | cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= 6 | cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= 7 | cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= 8 | cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= 9 | cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= 10 | cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= 11 | cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= 12 | cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= 13 | cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= 14 | cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= 15 | cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= 16 | cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= 17 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= 18 | cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= 19 | cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= 20 | cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= 21 | cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= 22 | cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= 23 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= 24 | cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= 25 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= 26 | cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= 27 | cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= 28 | cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= 29 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= 30 | cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= 31 | cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= 32 | cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= 33 | cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= 34 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= 35 | github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= 36 | github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= 37 | github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= 38 | github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= 39 | github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= 40 | github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= 41 | github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= 42 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 43 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= 44 | github.com/Microsoft/go-winio v0.4.16-0.20201130162521-d1ffc52c7331/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= 45 | github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= 46 | github.com/Microsoft/hcsshim v0.8.14/go.mod h1:NtVKoYxQuTLx6gEq0L96c9Ju4JbRJ4nY2ow3VK6a9Lg= 47 | github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= 48 | github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= 49 | github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= 50 | github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= 51 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 52 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 53 | github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= 54 | github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= 55 | github.com/bazelbuild/rules_go v0.30.0/go.mod h1:MC23Dc/wkXEyk3Wpq6lCqz0ZAYOZDw2DR5y3N1q2i7M= 56 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 57 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 58 | github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= 59 | github.com/cenkalti/backoff v1.1.1-0.20190506075156-2146c9339422/go.mod h1:b6Nc7NRH5C4aCISLry0tLnTjcuTEvoiqcWDdsU0sOGM= 60 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 61 | github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= 62 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 63 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 64 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 65 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 66 | github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg= 67 | github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= 68 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 69 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 70 | github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 71 | github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= 72 | github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 73 | github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 74 | github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 75 | github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 76 | github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= 77 | github.com/containerd/cgroups v1.0.1/go.mod h1:0SJrPIenamHDcZhEcJMNBB85rHcUsw4f25ZfBiPYRkU= 78 | github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= 79 | github.com/containerd/console v1.0.1/go.mod h1:XUsP6YE/mKtz6bxc+I8UiKKTP04qjQL4qcS3XoQ5xkw= 80 | github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= 81 | github.com/containerd/containerd v1.4.12/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= 82 | github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= 83 | github.com/containerd/continuity v0.2.1/go.mod h1:wCYX+dRqZdImhGucXOqTQn05AhX6EUDaGEMUzTFFpLg= 84 | github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= 85 | github.com/containerd/fifo v1.0.0/go.mod h1:ocF/ME1SX5b1AOlWi9r677YJmCPSwwWnQ9O123vzpE4= 86 | github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= 87 | github.com/containerd/go-runc v1.0.0/go.mod h1:cNU0ZbCgCQVZK4lgG3P+9tn9/PaJNmoDXPpoJhDR+Ok= 88 | github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= 89 | github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8httJEt98Y= 90 | github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc= 91 | github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s= 92 | github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= 93 | github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= 94 | github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= 95 | github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= 96 | github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= 97 | github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= 98 | github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 99 | github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= 100 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 101 | github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= 102 | github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 103 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 104 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 105 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 106 | github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= 107 | github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= 108 | github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= 109 | github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= 110 | github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 111 | github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= 112 | github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= 113 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 114 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 115 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 116 | github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 117 | github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= 118 | github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= 119 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 120 | github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= 121 | github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= 122 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 123 | github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 124 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 125 | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= 126 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 127 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= 128 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 129 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 130 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 131 | github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= 132 | github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= 133 | github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= 134 | github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= 135 | github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= 136 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 137 | github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= 138 | github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= 139 | github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= 140 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 141 | github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= 142 | github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 143 | github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= 144 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 145 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 146 | github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 147 | github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 148 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 149 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 150 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 151 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 152 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 153 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= 154 | github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 155 | github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 156 | github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= 157 | github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= 158 | github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 159 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 160 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 161 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 162 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 163 | github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 164 | github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= 165 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 166 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 167 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 168 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 169 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 170 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 171 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 172 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 173 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 174 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 175 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 176 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= 177 | github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= 178 | github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= 179 | github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= 180 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 181 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 182 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 183 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 184 | github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 185 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 186 | github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 187 | github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 188 | github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 189 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 190 | github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 191 | github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= 192 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 193 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= 194 | github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= 195 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 196 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= 197 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 198 | github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 199 | github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 200 | github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 201 | github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= 202 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 203 | github.com/google/subcommands v1.0.2-0.20190508160503-636abe8753b8/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= 204 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 205 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 206 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= 207 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= 208 | github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= 209 | github.com/googleapis/gnostic v0.4.0/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= 210 | github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= 211 | github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= 212 | github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= 213 | github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= 214 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= 215 | github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= 216 | github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= 217 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 218 | github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= 219 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 220 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= 221 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 222 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 223 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= 224 | github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= 225 | github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= 226 | github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= 227 | github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 228 | github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 229 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= 230 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= 231 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 232 | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= 233 | github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= 234 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 235 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 236 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 237 | github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 238 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 239 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 240 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 241 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 242 | github.com/kr/pty v1.1.4-0.20190131011033-7dc38fb350b1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 243 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 244 | github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= 245 | github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= 246 | github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a/go.mod h1:M1qoD/MqPgTZIk0EWKB38wE28ACRfVcn+cU08jyArI0= 247 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 248 | github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= 249 | github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= 250 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 251 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 252 | github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 253 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 254 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 255 | github.com/mohae/deepcopy v0.0.0-20170308212314-bb9b5e7adda9/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= 256 | github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 257 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 258 | github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= 259 | github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= 260 | github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 261 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 262 | github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 263 | github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= 264 | github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 265 | github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= 266 | github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= 267 | github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= 268 | github.com/opencontainers/runc v1.0.0-rc90/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= 269 | github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= 270 | github.com/opencontainers/runtime-spec v1.0.3-0.20211123151946-c2389c3cb60a/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= 271 | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= 272 | github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= 273 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 274 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 275 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 276 | github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 277 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 278 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 279 | github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= 280 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 281 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 282 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 283 | github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= 284 | github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 285 | github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 286 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 287 | github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 288 | github.com/prometheus/procfs v0.0.0-20190522114515-bc1a522cf7b1/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 289 | github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= 290 | github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= 291 | github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= 292 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 293 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 294 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 295 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 296 | github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= 297 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 298 | github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 299 | github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= 300 | github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= 301 | github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= 302 | github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= 303 | github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= 304 | github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 305 | github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= 306 | github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= 307 | github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 308 | github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= 309 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 310 | github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= 311 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 312 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 313 | github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 314 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 315 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 316 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 317 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 318 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 319 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 320 | github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= 321 | github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= 322 | github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= 323 | github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= 324 | github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= 325 | github.com/vishvananda/netlink v1.0.1-0.20190930145447-2ec5bdc52b86/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= 326 | github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= 327 | github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= 328 | github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= 329 | github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 330 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 331 | github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 332 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 333 | github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 334 | github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 335 | go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= 336 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= 337 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= 338 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 339 | go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 340 | go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= 341 | go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= 342 | go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= 343 | go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 344 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 345 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 346 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 347 | golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 348 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 349 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 350 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 351 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 352 | golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 353 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 354 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 355 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 356 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= 357 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= 358 | golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= 359 | golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 360 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 361 | golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= 362 | golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= 363 | golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= 364 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= 365 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= 366 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 367 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 368 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 369 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 370 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 371 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 372 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 373 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= 374 | golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 375 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 376 | golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= 377 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= 378 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= 379 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 380 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= 381 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 382 | golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 383 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 384 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 385 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 386 | golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= 387 | golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 388 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 389 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 390 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 391 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 392 | golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 393 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 394 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 395 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 396 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 397 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 398 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 399 | golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 400 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 401 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 402 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 403 | golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 404 | golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 405 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 406 | golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 407 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 408 | golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 409 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 410 | golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 411 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 412 | golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 413 | golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 414 | golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 415 | golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 416 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 417 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 418 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 419 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 420 | golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 421 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 422 | golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= 423 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 424 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 425 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 426 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 427 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 428 | golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= 429 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 430 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 431 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 432 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 433 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 434 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 435 | golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 436 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 437 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 438 | golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 439 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 440 | golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 441 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 442 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 443 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 444 | golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 445 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 446 | golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 447 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 448 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 449 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 450 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 451 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 452 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 453 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 454 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 455 | golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 456 | golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 457 | golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 458 | golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 459 | golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 460 | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 461 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 462 | golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 463 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 464 | golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 465 | golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 466 | golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 467 | golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 468 | golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 469 | golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 470 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 471 | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 472 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 473 | golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 474 | golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 475 | golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 476 | golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 477 | golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 478 | golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 479 | golang.org/x/sys v0.0.0-20200916030750-2334cc1a136f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 480 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 481 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 482 | golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 483 | golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 484 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 485 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 486 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 487 | golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 488 | golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 489 | golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= 490 | golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 491 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 492 | golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 493 | golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 494 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 495 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 496 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 497 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 498 | golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 499 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 500 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 501 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 502 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 503 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 504 | golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U= 505 | golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 506 | golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 507 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 508 | golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 509 | golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 510 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 511 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 512 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 513 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 514 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 515 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 516 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 517 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 518 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 519 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 520 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 521 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 522 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 523 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 524 | golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 525 | golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 526 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 527 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 528 | golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 529 | golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 530 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 531 | golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 532 | golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 533 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 534 | golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 535 | golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 536 | golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 537 | golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 538 | golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 539 | golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 540 | golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= 541 | golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= 542 | golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 543 | golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 544 | golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 545 | golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 546 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 547 | golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 548 | golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 549 | golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= 550 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 551 | golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 552 | golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= 553 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 554 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 555 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 556 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 557 | golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY= 558 | golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= 559 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= 560 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= 561 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 562 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= 563 | google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 564 | google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 565 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= 566 | google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 567 | google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 568 | google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 569 | google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 570 | google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= 571 | google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 572 | google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= 573 | google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= 574 | google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= 575 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 576 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 577 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 578 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= 579 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 580 | google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 581 | google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 582 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 583 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 584 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 585 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 586 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= 587 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 588 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 589 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= 590 | google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 591 | google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 592 | google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 593 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 594 | google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 595 | google.golang.org/genproto v0.0.0-20200117163144-32f20d992d24/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 596 | google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= 597 | google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= 598 | google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 599 | google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 600 | google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 601 | google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 602 | google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 603 | google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 604 | google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 605 | google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 606 | google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 607 | google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= 608 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 609 | google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= 610 | google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 611 | google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 612 | google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= 613 | google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= 614 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 615 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= 616 | google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 617 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= 618 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 619 | google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 620 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 621 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 622 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 623 | google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 624 | google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= 625 | google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= 626 | google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 627 | google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= 628 | google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= 629 | google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= 630 | google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 631 | google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= 632 | google.golang.org/grpc v1.42.0-dev.0.20211020220737-f00baa6c3c84/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= 633 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 634 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 635 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 636 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 637 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 638 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 639 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 640 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 641 | google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= 642 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 643 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 644 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 645 | google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 646 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 647 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 648 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 649 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 650 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 651 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 652 | gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= 653 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 654 | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= 655 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 656 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 657 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 658 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 659 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 660 | gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= 661 | gvisor.dev/gvisor v0.0.0-20220720011844-c2fcd7b14d4b h1:/qX0vWRZvBl42V63X/upnp73WTF2pxFbopWl/o2I418= 662 | gvisor.dev/gvisor v0.0.0-20220720011844-c2fcd7b14d4b/go.mod h1:TIvkJD0sxe8pIob3p6T8IzxXunlp6yfgktvTNp+DGNM= 663 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 664 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 665 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 666 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 667 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 668 | honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 669 | honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= 670 | k8s.io/api v0.16.13/go.mod h1:QWu8UWSTiuQZMMeYjwLs6ILu5O74qKSJ0c+4vrchDxs= 671 | k8s.io/apimachinery v0.16.13/go.mod h1:4HMHS3mDHtVttspuuhrJ1GGr/0S9B6iWYWZ57KnnZqQ= 672 | k8s.io/apimachinery v0.16.14-rc.0/go.mod h1:4HMHS3mDHtVttspuuhrJ1GGr/0S9B6iWYWZ57KnnZqQ= 673 | k8s.io/client-go v0.16.13/go.mod h1:UKvVT4cajC2iN7DCjLgT0KVY/cbY6DGdUCyRiIfws5M= 674 | k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= 675 | k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= 676 | k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= 677 | k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= 678 | k8s.io/kube-openapi v0.0.0-20200410163147-594e756bea31/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= 679 | k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= 680 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= 681 | rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= 682 | rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= 683 | sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= 684 | sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= 685 | -------------------------------------------------------------------------------- /tcp.go: -------------------------------------------------------------------------------- 1 | package tunat 2 | 3 | import ( 4 | "errors" 5 | "net" 6 | "net/netip" 7 | 8 | "gvisor.dev/gvisor/pkg/tcpip" 9 | "gvisor.dev/gvisor/pkg/tcpip/header" 10 | ) 11 | 12 | type tcpMapValue struct { 13 | natAddr netip.AddrPort // fakeSAddr or originSAddr 14 | daddr netip.AddrPort 15 | } 16 | 17 | type tcpConn struct { 18 | net.Conn 19 | tunat *Tunat 20 | saddr netip.AddrPort 21 | daddr netip.AddrPort 22 | saddrInterface net.Addr 23 | daddrInterface net.Addr 24 | } 25 | 26 | // Close delete nat map at the same time 27 | func (tc *tcpConn) Close() error { 28 | if value, ok := tc.tunat.tcpMap.Load(tc.saddr); ok { 29 | tc.tunat.tcpMap.Delete(value.(*tcpMapValue).natAddr) 30 | tc.tunat.tcpMap.Delete(tc.saddr) 31 | } 32 | 33 | return tc.Conn.Close() 34 | } 35 | 36 | // LocalAddr original destination address 37 | func (tc *tcpConn) LocalAddr() net.Addr { 38 | return tc.daddrInterface 39 | } 40 | 41 | // RemoteAddr original source address 42 | func (tc *tcpConn) RemoteAddr() net.Addr { 43 | return tc.saddrInterface 44 | } 45 | 46 | // Accept like net package 47 | func (t *Tunat) Accept() (conn net.Conn, err error) { 48 | acceptConn, err := t.tcpListener.Accept() 49 | if err != nil { 50 | return 51 | } 52 | 53 | connRemoteAddr := acceptConn.RemoteAddr().(*net.TCPAddr).AddrPort() 54 | if connRemoteAddr.Addr().Is4In6() { 55 | connRemoteAddr = netip.AddrPortFrom(connRemoteAddr.Addr().Unmap(), connRemoteAddr.Port()) 56 | } 57 | value, ok := t.tcpMap.Load(connRemoteAddr) 58 | if !ok { 59 | return nil, errors.New("tcp nat map not exist") 60 | } 61 | saddr := value.(*tcpMapValue).natAddr 62 | daddr := value.(*tcpMapValue).daddr 63 | conn = &tcpConn{ 64 | Conn: acceptConn, 65 | tunat: t, 66 | saddr: saddr, 67 | daddr: daddr, 68 | saddrInterface: net.TCPAddrFromAddrPort(saddr), 69 | daddrInterface: net.TCPAddrFromAddrPort(daddr), 70 | } 71 | return 72 | } 73 | 74 | func (t *Tunat) handleIPv4TCP(ipHeader header.IPv4, tcpHeader header.TCP) { 75 | /* 76 | tcpListener 10.0.0.1:100 77 | raw 10.0.0.1:1234 -> 1.2.3.4:4321 SYN 78 | modified 10.0.0.2:1234 -> 10.0.0.1:100 SYN 79 | raw 10.0.0.1:100 -> 10.0.0.2:1234 ACK SYN 80 | modified 1.2.3.4:4321 -> 10.0.0.1:1234 ACK SYN 81 | raw 10.0.0.1:1234 -> 1.2.3.4:4321 ACK 82 | modified 10.0.0.2:1234 -> 10.0.0.1:100 ACK 83 | */ 84 | ip, ok := netip.AddrFromSlice([]byte(ipHeader.SourceAddress())) 85 | if !ok { 86 | return 87 | } 88 | saddr := netip.AddrPortFrom(ip, tcpHeader.SourcePort()) 89 | ip, ok = netip.AddrFromSlice([]byte(ipHeader.DestinationAddress())) 90 | if !ok { 91 | return 92 | } 93 | daddr := netip.AddrPortFrom(ip, tcpHeader.DestinationPort()) 94 | 95 | if tcpHeader.Flags()&header.TCPFlagSyn == 0 || tcpHeader.Flags()&header.TCPFlagAck != 0 { 96 | goto next 97 | } 98 | if _, ok := t.tcpMap.Load(saddr); ok { 99 | goto next 100 | } 101 | for port, endPort := tcpHeader.SourcePort(), tcpHeader.SourcePort()-1; port != endPort; port++ { 102 | if port == 0 { 103 | continue 104 | } 105 | fakeAddr := netip.AddrPortFrom(t.fakeIPv4Addr, port) 106 | if _, ok := t.tcpMap.Load(fakeAddr); !ok { 107 | t.tcpMap.Store(fakeAddr, &tcpMapValue{natAddr: saddr, daddr: daddr}) 108 | t.tcpMap.Store(saddr, &tcpMapValue{natAddr: fakeAddr, daddr: daddr}) 109 | goto next 110 | } 111 | } 112 | return 113 | 114 | next: 115 | if value, ok := t.tcpMap.Load(saddr); ok { 116 | ipHeader.SetSourceAddress(tcpip.Address(value.(*tcpMapValue).natAddr.Addr().AsSlice())) 117 | ipHeader.SetDestinationAddress(tcpip.Address(t.ipv4TCPListenerAddrPort.Addr().AsSlice())) 118 | tcpHeader.SetSourcePort(uint16(value.(*tcpMapValue).natAddr.Port())) 119 | tcpHeader.SetDestinationPort(uint16(t.ipv4TCPListenerAddrPort.Port())) 120 | } else if value, ok := t.tcpMap.Load(daddr); ok { 121 | ipHeader.SetSourceAddress(tcpip.Address(value.(*tcpMapValue).daddr.Addr().AsSlice())) 122 | ipHeader.SetDestinationAddress(tcpip.Address(value.(*tcpMapValue).natAddr.Addr().AsSlice())) 123 | tcpHeader.SetSourcePort(uint16(value.(*tcpMapValue).daddr.Port())) 124 | tcpHeader.SetDestinationPort(uint16(value.(*tcpMapValue).natAddr.Port())) 125 | } else { 126 | return 127 | } 128 | 129 | ipHeader.SetChecksum(0) 130 | ipHeader.SetChecksum(^ipHeader.CalculateChecksum()) 131 | tcpHeader.SetChecksum(0) 132 | tcpHeader.SetChecksum( 133 | ^tcpHeader.CalculateChecksum( 134 | header.Checksum( 135 | tcpHeader.Payload(), 136 | header.PseudoHeaderChecksum( 137 | header.TCPProtocolNumber, 138 | ipHeader.SourceAddress(), 139 | ipHeader.DestinationAddress(), 140 | uint16(len(tcpHeader)), 141 | ), 142 | ), 143 | ), 144 | ) 145 | 146 | _, _ = t.file.Write(ipHeader) 147 | } 148 | 149 | func (t *Tunat) handleIPv6TCP(ipHeader header.IPv6, tcpHeader header.TCP) { 150 | ip, ok := netip.AddrFromSlice([]byte(ipHeader.SourceAddress())) 151 | if !ok { 152 | return 153 | } 154 | saddr := netip.AddrPortFrom(ip, tcpHeader.SourcePort()) 155 | ip, ok = netip.AddrFromSlice([]byte(ipHeader.DestinationAddress())) 156 | if !ok { 157 | return 158 | } 159 | daddr := netip.AddrPortFrom(ip, tcpHeader.DestinationPort()) 160 | 161 | if tcpHeader.Flags()&header.TCPFlagSyn == 0 || tcpHeader.Flags()&header.TCPFlagAck != 0 { 162 | goto next 163 | } 164 | if _, ok := t.tcpMap.Load(saddr); ok { 165 | goto next 166 | } 167 | for port, endPort := tcpHeader.SourcePort(), tcpHeader.SourcePort()-1; port != endPort; port++ { 168 | if port == 0 { 169 | continue 170 | } 171 | fakeAddr := netip.AddrPortFrom(t.fakeIPv6Addr, port) 172 | if _, ok := t.tcpMap.Load(fakeAddr); !ok { 173 | t.tcpMap.Store(fakeAddr, &tcpMapValue{natAddr: saddr, daddr: daddr}) 174 | t.tcpMap.Store(saddr, &tcpMapValue{natAddr: fakeAddr, daddr: daddr}) 175 | goto next 176 | } 177 | } 178 | return 179 | 180 | next: 181 | if value, ok := t.tcpMap.Load(saddr); ok { 182 | ipHeader.SetSourceAddress(tcpip.Address(value.(*tcpMapValue).natAddr.Addr().AsSlice())) 183 | ipHeader.SetDestinationAddress(tcpip.Address(t.ipv6TCPListenerAddrPort.Addr().AsSlice())) 184 | tcpHeader.SetSourcePort(uint16(value.(*tcpMapValue).natAddr.Port())) 185 | tcpHeader.SetDestinationPort(uint16(t.ipv6TCPListenerAddrPort.Port())) 186 | } else if value, ok := t.tcpMap.Load(daddr); ok { 187 | ipHeader.SetSourceAddress(tcpip.Address(value.(*tcpMapValue).daddr.Addr().AsSlice())) 188 | ipHeader.SetDestinationAddress(tcpip.Address(value.(*tcpMapValue).natAddr.Addr().AsSlice())) 189 | tcpHeader.SetSourcePort(uint16(value.(*tcpMapValue).daddr.Port())) 190 | tcpHeader.SetDestinationPort(uint16(value.(*tcpMapValue).natAddr.Port())) 191 | } else { 192 | return 193 | } 194 | 195 | tcpHeader.SetChecksum(0) 196 | tcpHeader.SetChecksum( 197 | ^tcpHeader.CalculateChecksum( 198 | header.Checksum( 199 | tcpHeader.Payload(), 200 | header.PseudoHeaderChecksum( 201 | header.TCPProtocolNumber, 202 | ipHeader.SourceAddress(), 203 | ipHeader.DestinationAddress(), 204 | uint16(len(tcpHeader)), 205 | ), 206 | ), 207 | ), 208 | ) 209 | 210 | _, _ = t.file.Write(ipHeader) 211 | } 212 | -------------------------------------------------------------------------------- /test/main_windows.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | func main() { 6 | var b byte 7 | fmt.Println("press any key to continue") 8 | _, _ = fmt.Scan(&b) 9 | 10 | testUDP() 11 | testTCP() 12 | } 13 | -------------------------------------------------------------------------------- /test/test.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FH0/tunat/efc19127d257534612fc68f435c2e73c6feda667/test/test.exe -------------------------------------------------------------------------------- /test/test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net" 6 | "net/netip" 7 | "time" 8 | ) 9 | 10 | type udpData struct { 11 | payload []byte 12 | saddr netip.AddrPort 13 | daddr netip.AddrPort 14 | } 15 | 16 | func testUDP() { 17 | udpListener, _ := net.ListenUDP("udp", net.UDPAddrFromAddrPort(netip.MustParseAddrPort("[::]:100"))) 18 | defer udpListener.Close() 19 | buf := make([]byte, 100) 20 | 21 | // tunat write 22 | _, err := tn.WriteToUDPAddrPort( 23 | []byte("abcd"), 24 | netip.MustParseAddrPort("10.0.0.3:100"), 25 | netip.MustParseAddrPort("10.0.0.1:100"), 26 | ) 27 | if err != nil { 28 | panic(err) 29 | } 30 | _, err = tn.WriteToUDPAddrPort( 31 | []byte("abcd"), 32 | netip.MustParseAddrPort("[fd::3]:100"), 33 | netip.MustParseAddrPort("[fd::1]:100"), 34 | ) 35 | if err != nil { 36 | panic(err) 37 | } 38 | 39 | // udpListener write 40 | _, err = udpListener.WriteToUDPAddrPort([]byte("abcd"), netip.MustParseAddrPort("[::FFFF:10.0.0.3]:100")) 41 | if err != nil { 42 | panic(err) 43 | } 44 | _, err = udpListener.WriteToUDPAddrPort([]byte("abcd"), netip.MustParseAddrPort("[fd::3]:100")) 45 | if err != nil { 46 | panic(err) 47 | } 48 | 49 | // tunat read contains 50 | ch := make(chan udpData) 51 | go func() { 52 | for { 53 | nread, saddr, daddr, err := tn.ReadFromUDPAddrPort(buf) 54 | if err != nil { 55 | panic(err) 56 | } 57 | ch <- udpData{ 58 | payload: append([]byte(nil), buf[:nread]...), 59 | saddr: saddr, 60 | daddr: daddr, 61 | } 62 | } 63 | }() 64 | var ( 65 | tunatIPv4OK bool 66 | tunatIPv6OK bool 67 | ) 68 | for !tunatIPv4OK || !tunatIPv6OK { 69 | select { 70 | case <-time.After(1 * time.Second): 71 | panic("timeout") 72 | case udpData := <-ch: 73 | if udpData.saddr.String() == "10.0.0.1:100" && 74 | udpData.daddr.String() == "10.0.0.3:100" && 75 | string(udpData.payload) == "abcd" { 76 | tunatIPv4OK = true 77 | } 78 | if udpData.saddr.String() == "[fd::1]:100" && 79 | udpData.daddr.String() == "[fd::3]:100" && 80 | string(udpData.payload) == "abcd" { 81 | tunatIPv6OK = true 82 | } 83 | } 84 | } 85 | 86 | // udpListener read 87 | nread, saddr, err := udpListener.ReadFromUDPAddrPort(buf) 88 | if err != nil { 89 | panic(err) 90 | } 91 | if (saddr.String() != "[::ffff:10.0.0.3]:100" && saddr.String() != "[fd::3]:100") || 92 | string(buf[:nread]) != "abcd" { 93 | panic(fmt.Sprintf("%v %v", saddr, string(buf[:nread]))) 94 | } 95 | nread, saddr, err = udpListener.ReadFromUDPAddrPort(buf) 96 | if err != nil { 97 | panic(err) 98 | } 99 | if (saddr.String() != "[::ffff:10.0.0.3]:100" && saddr.String() != "[fd::3]:100") || 100 | string(buf[:nread]) != "abcd" { 101 | panic(fmt.Sprintf("%v %v", saddr, string(buf[:nread]))) 102 | } 103 | } 104 | 105 | func testTCP() { 106 | buf := make([]byte, 100) 107 | 108 | // ipv4 109 | conn1, err := net.Dial("tcp", "10.0.0.3:100") 110 | if err != nil { 111 | panic(err) 112 | } 113 | conn2, err := tn.Accept() 114 | if err != nil { 115 | panic(err) 116 | } 117 | _, err = conn1.Write([]byte("abcd")) 118 | if err != nil { 119 | panic(err) 120 | } 121 | nread, err := conn2.Read(buf) 122 | if err != nil { 123 | panic(err) 124 | } 125 | if conn2.LocalAddr().String() != "10.0.0.3:100" || string(buf[:nread]) != "abcd" { 126 | panic(fmt.Sprintf("%v %v", conn1.LocalAddr(), string(buf[:nread]))) 127 | } 128 | 129 | // ipv6 130 | conn1, err = net.Dial("tcp", "[fd::3]:100") 131 | if err != nil { 132 | panic(err) 133 | } 134 | conn2, err = tn.Accept() 135 | if err != nil { 136 | panic(err) 137 | } 138 | _, err = conn1.Write([]byte("abcd")) 139 | if err != nil { 140 | panic(err) 141 | } 142 | nread, err = conn2.Read(buf) 143 | if err != nil { 144 | panic(err) 145 | } 146 | if conn2.LocalAddr().String() != "[fd::3]:100" || string(buf[:nread]) != "abcd" { 147 | panic(fmt.Sprintf("%v %v", conn1.LocalAddr(), string(buf[:nread]))) 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /test/test_linux.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/netip" 5 | 6 | "github.com/FH0/tunat" 7 | ) 8 | 9 | var tn *tunat.Tunat 10 | 11 | func init() { 12 | var err error 13 | tn, err = tunat.New( 14 | "tun1", 15 | netip.MustParsePrefix("10.0.0.1/24"), 16 | netip.MustParsePrefix("fd::1/120"), 17 | 1500, 18 | []string{ 19 | "ip tuntap add mode tun tun1 || true", 20 | }, 21 | []string{ 22 | "ip link set tun1 up", 23 | "ip addr replace 10.0.0.1/24 dev tun1", 24 | "ip addr replace fd::1/120 dev tun1", 25 | }, 26 | ) 27 | if err != nil { 28 | panic(err) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /test/test_windows.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/netip" 5 | 6 | "github.com/FH0/tunat" 7 | ) 8 | 9 | var tn *tunat.Tunat 10 | 11 | func init() { 12 | var err error 13 | tn, err = tunat.New( 14 | "tun1", 15 | netip.MustParsePrefix("10.0.0.1/24"), 16 | netip.MustParsePrefix("fd::1/120"), 17 | 1500, 18 | []string{}, 19 | []string{ 20 | "netsh interface ip set address tun1 static 10.0.0.1 255.255.255.0", 21 | "netsh interface ipv6 set address tun1 fd::1/120", 22 | }, 23 | ) 24 | if err != nil { 25 | panic(err) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /test/tunat_linux_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/hex" 5 | "fmt" 6 | "net" 7 | "net/netip" 8 | "syscall" 9 | "testing" 10 | "time" 11 | 12 | "github.com/FH0/tunat/device" 13 | ) 14 | 15 | func TestUDP(t *testing.T) { 16 | testUDP() 17 | } 18 | 19 | func TestTCP(t *testing.T) { 20 | testTCP() 21 | } 22 | 23 | func TestUnixSocket(t *testing.T) { 24 | tn.Close() 25 | 26 | unixSocket := "/tmp/tunUnixSocket" 27 | 28 | // send fd background 29 | go func() { 30 | file, err := device.New("tun1") 31 | if err != nil { 32 | panic(err) 33 | } 34 | 35 | time.Sleep(10 * time.Millisecond) 36 | 37 | unixConn, err := net.DialUnix("unix", nil, &net.UnixAddr{ 38 | Name: unixSocket, 39 | Net: "unix", 40 | }) 41 | if err != nil { 42 | panic(err) 43 | } 44 | 45 | oob := syscall.UnixRights(int(file.Fd())) 46 | _, _, err = unixConn.WriteMsgUnix([]byte("/dev/net/tun"), oob, nil) 47 | if err != nil { 48 | panic(err) 49 | } 50 | }() 51 | 52 | // recv fd 53 | file, err := device.NewFromUnixSocket(unixSocket) 54 | if err != nil { 55 | panic(err) 56 | } 57 | 58 | // send packet to tun background 59 | go func() { 60 | conn, err := net.ListenUDP("udp", &net.UDPAddr{IP: net.ParseIP("[::]"), Port: 100}) 61 | if err != nil { 62 | panic(err) 63 | } 64 | 65 | _, err = conn.WriteToUDPAddrPort([]byte("abcd"), netip.MustParseAddrPort("[::FFFF:10.0.0.3]:100")) 66 | if err != nil { 67 | panic(err) 68 | } 69 | }() 70 | 71 | // read tun 72 | buf := make([]byte, 65535) 73 | nread, err := file.Read(buf) 74 | if err != nil { 75 | panic(err) 76 | } 77 | fmt.Println(hex.EncodeToString(buf[:nread])) 78 | } 79 | -------------------------------------------------------------------------------- /test/wintun.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FH0/tunat/efc19127d257534612fc68f435c2e73c6feda667/test/wintun.dll -------------------------------------------------------------------------------- /tunat.go: -------------------------------------------------------------------------------- 1 | package tunat 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "io" 7 | "net" 8 | "net/netip" 9 | "os/exec" 10 | "sync" 11 | 12 | "github.com/FH0/tunat/device" 13 | "gvisor.dev/gvisor/pkg/tcpip/header" 14 | ) 15 | 16 | // Tunat main struct 17 | type Tunat struct { 18 | file io.ReadWriteCloser 19 | tcpListener net.Listener 20 | ipv4TCPListenerAddrPort netip.AddrPort 21 | ipv6TCPListenerAddrPort netip.AddrPort 22 | fakeIPv4Addr netip.Addr 23 | fakeIPv6Addr netip.Addr 24 | udpChan chan udpData 25 | bufLen int 26 | tcpMap sync.Map 27 | } 28 | 29 | // New new a Tunat 30 | func New(name string, 31 | ipv4Prefix, 32 | ipv6Prefix netip.Prefix, 33 | bufLen int, 34 | preCommands []string, 35 | postCommands []string, 36 | ) (tunat *Tunat, err error) { 37 | tunat = &Tunat{ 38 | udpChan: make(chan udpData, 100), 39 | bufLen: bufLen, 40 | } 41 | 42 | err = excuteCommands(preCommands) 43 | if err != nil { 44 | return 45 | } 46 | tunat.file, err = device.New(name) 47 | if err != nil { 48 | return 49 | } 50 | err = excuteCommands(postCommands) 51 | if err != nil { 52 | return 53 | } 54 | tunat.tcpListener, err = net.Listen("tcp", "[::]:0") 55 | if err != nil { 56 | return 57 | } 58 | if ipv4Prefix.IsValid() { 59 | tunat.ipv4TCPListenerAddrPort = netip.AddrPortFrom( 60 | ipv4Prefix.Addr(), 61 | uint16(tunat.tcpListener.Addr().(*net.TCPAddr).Port), 62 | ) 63 | tunat.fakeIPv4Addr = ipv4Prefix.Addr().Next() 64 | if !ipv4Prefix.Contains(tunat.fakeIPv4Addr) { 65 | err = errors.New("ipv4 next address is out of CIDR") 66 | return 67 | } 68 | } 69 | if ipv6Prefix.IsValid() { 70 | tunat.ipv6TCPListenerAddrPort = netip.AddrPortFrom( 71 | ipv6Prefix.Addr(), 72 | uint16(tunat.tcpListener.Addr().(*net.TCPAddr).Port), 73 | ) 74 | tunat.fakeIPv6Addr = ipv6Prefix.Addr().Next() 75 | if !ipv6Prefix.Contains(tunat.fakeIPv6Addr) { 76 | err = errors.New("ipv6 next address is out of CIDR") 77 | return 78 | } 79 | } 80 | 81 | go tunat.start() 82 | return 83 | } 84 | 85 | // Close close tun device 86 | func (t *Tunat) Close() (err error) { 87 | return t.file.Close() 88 | } 89 | 90 | func (t *Tunat) start() { 91 | buf := make([]byte, t.bufLen) 92 | for { 93 | nread, err := t.file.Read(buf) 94 | if err != nil { 95 | fmt.Printf("tunat read error: %v\n", err) 96 | return 97 | } 98 | packet := buf[:nread] 99 | 100 | switch header.IPVersion(packet) { 101 | case header.IPv4Version: 102 | ipHeader := header.IPv4(packet) 103 | switch ipHeader.TransportProtocol() { 104 | case header.TCPProtocolNumber: 105 | t.handleIPv4TCP(ipHeader, ipHeader.Payload()) 106 | case header.UDPProtocolNumber: 107 | t.handleIPv4UDP(ipHeader, ipHeader.Payload()) 108 | } 109 | case header.IPv6Version: 110 | ipHeader := header.IPv6(packet) 111 | switch ipHeader.TransportProtocol() { 112 | case header.TCPProtocolNumber: 113 | t.handleIPv6TCP(ipHeader, ipHeader.Payload()) 114 | case header.UDPProtocolNumber: 115 | t.handleIPv6UDP(ipHeader, ipHeader.Payload()) 116 | } 117 | } 118 | } 119 | } 120 | 121 | func excuteCommands(commands []string) (err error) { 122 | for _, cmd := range commands { 123 | err = exec.Command("bash", "-c", cmd).Run() 124 | if err != nil { 125 | return 126 | } 127 | } 128 | return 129 | } 130 | -------------------------------------------------------------------------------- /tunat_linux.go: -------------------------------------------------------------------------------- 1 | package tunat 2 | 3 | import ( 4 | "errors" 5 | "net" 6 | "net/netip" 7 | 8 | "github.com/FH0/tunat/device" 9 | ) 10 | 11 | // NewFromUnixSocket new a Tunat from unix 12 | func NewFromUnixSocket(path string, 13 | ipv4Prefix, 14 | ipv6Prefix netip.Prefix, 15 | bufLen int, 16 | preCommands []string, 17 | postCommands []string, 18 | ) (tunat *Tunat, err error) { 19 | tunat = &Tunat{ 20 | udpChan: make(chan udpData, 100), 21 | bufLen: bufLen, 22 | } 23 | 24 | err = excuteCommands(preCommands) 25 | if err != nil { 26 | return 27 | } 28 | tunat.file, err = device.NewFromUnixSocket(path) 29 | if err != nil { 30 | return 31 | } 32 | err = excuteCommands(postCommands) 33 | if err != nil { 34 | return 35 | } 36 | tunat.tcpListener, err = net.Listen("tcp", "[::]:0") 37 | if err != nil { 38 | return 39 | } 40 | if ipv4Prefix.IsValid() { 41 | tunat.ipv4TCPListenerAddrPort = netip.AddrPortFrom( 42 | ipv4Prefix.Addr(), 43 | uint16(tunat.tcpListener.Addr().(*net.TCPAddr).Port), 44 | ) 45 | tunat.fakeIPv4Addr = ipv4Prefix.Addr().Next() 46 | if !ipv4Prefix.Contains(tunat.fakeIPv4Addr) { 47 | err = errors.New("ipv4 next address is out of CIDR") 48 | return 49 | } 50 | } 51 | if ipv6Prefix.IsValid() { 52 | tunat.ipv6TCPListenerAddrPort = netip.AddrPortFrom( 53 | ipv6Prefix.Addr(), 54 | uint16(tunat.tcpListener.Addr().(*net.TCPAddr).Port), 55 | ) 56 | tunat.fakeIPv6Addr = ipv6Prefix.Addr().Next() 57 | if !ipv6Prefix.Contains(tunat.fakeIPv6Addr) { 58 | err = errors.New("ipv6 next address is out of CIDR") 59 | return 60 | } 61 | } 62 | 63 | go tunat.start() 64 | return 65 | } 66 | -------------------------------------------------------------------------------- /udp.go: -------------------------------------------------------------------------------- 1 | package tunat 2 | 3 | import ( 4 | "net/netip" 5 | 6 | "gvisor.dev/gvisor/pkg/tcpip" 7 | "gvisor.dev/gvisor/pkg/tcpip/header" 8 | ) 9 | 10 | type udpData struct { 11 | payload []byte 12 | saddr netip.AddrPort 13 | daddr netip.AddrPort 14 | } 15 | 16 | // ReadFromUDPAddrPort like net package 17 | func (t *Tunat) ReadFromUDPAddrPort(payload []byte) (nread int, saddr, daddr netip.AddrPort, err error) { 18 | udpData := <-t.udpChan 19 | nread = copy(payload, udpData.payload) 20 | return nread, udpData.saddr, udpData.daddr, nil 21 | } 22 | 23 | // WriteToUDPAddrPort like net package 24 | func (t *Tunat) WriteToUDPAddrPort(payload []byte, saddr, daddr netip.AddrPort) (nwrite int, err error) { 25 | if saddr.Addr().Is4() { 26 | return t.ipv4WriteTo(payload, saddr, daddr) 27 | } 28 | return t.ipv6WriteTo(payload, saddr, daddr) 29 | } 30 | 31 | func (t *Tunat) ipv4WriteTo(payload []byte, saddr, daddr netip.AddrPort) (nwrite int, err error) { 32 | totalLen := header.IPv4MinimumSize + header.UDPMinimumSize + len(payload) 33 | ipHeader := header.IPv4( 34 | append( 35 | make([]byte, totalLen-len(payload)), 36 | payload..., 37 | ), 38 | ) 39 | ipHeader.Encode(&header.IPv4Fields{ 40 | TotalLength: uint16(totalLen), 41 | TTL: 64, 42 | Protocol: uint8(header.UDPProtocolNumber), 43 | SrcAddr: tcpip.Address(saddr.Addr().AsSlice()), 44 | DstAddr: tcpip.Address(daddr.Addr().AsSlice()), 45 | }) 46 | ipHeader.SetChecksum(0) 47 | ipHeader.SetChecksum(^ipHeader.CalculateChecksum()) 48 | 49 | udpHeader := header.UDP(ipHeader.Payload()) 50 | udpHeader.Encode(&header.UDPFields{ 51 | SrcPort: uint16(saddr.Port()), 52 | DstPort: uint16(daddr.Port()), 53 | Length: uint16(header.UDPMinimumSize + len(payload)), 54 | }) 55 | udpHeader.SetChecksum(0) 56 | udpHeader.SetChecksum( 57 | ^udpHeader.CalculateChecksum( 58 | header.Checksum( 59 | udpHeader.Payload(), 60 | header.PseudoHeaderChecksum( 61 | header.UDPProtocolNumber, 62 | ipHeader.SourceAddress(), 63 | ipHeader.DestinationAddress(), 64 | udpHeader.Length(), 65 | ), 66 | ), 67 | ), 68 | ) 69 | 70 | return t.file.Write(ipHeader) 71 | } 72 | 73 | func (t *Tunat) ipv6WriteTo(payload []byte, saddr, daddr netip.AddrPort) (nwrite int, err error) { 74 | totalLen := header.IPv6MinimumSize + header.UDPMinimumSize + len(payload) 75 | ipHeader := header.IPv6( 76 | append( 77 | make([]byte, totalLen-len(payload)), 78 | payload..., 79 | ), 80 | ) 81 | ipHeader.Encode(&header.IPv6Fields{ 82 | PayloadLength: uint16(header.UDPMinimumSize + len(payload)), 83 | TransportProtocol: header.UDPProtocolNumber, 84 | HopLimit: 64, 85 | SrcAddr: tcpip.Address(saddr.Addr().AsSlice()), 86 | DstAddr: tcpip.Address(daddr.Addr().AsSlice()), 87 | }) 88 | 89 | udpHeader := header.UDP(ipHeader.Payload()) 90 | udpHeader.Encode(&header.UDPFields{ 91 | SrcPort: uint16(saddr.Port()), 92 | DstPort: uint16(daddr.Port()), 93 | Length: uint16(header.UDPMinimumSize + len(payload)), 94 | }) 95 | udpHeader.SetChecksum(0) 96 | udpHeader.SetChecksum( 97 | ^udpHeader.CalculateChecksum( 98 | header.Checksum( 99 | udpHeader.Payload(), 100 | header.PseudoHeaderChecksum( 101 | header.UDPProtocolNumber, 102 | ipHeader.SourceAddress(), 103 | ipHeader.DestinationAddress(), 104 | udpHeader.Length(), 105 | ), 106 | ), 107 | ), 108 | ) 109 | 110 | return t.file.Write(ipHeader) 111 | } 112 | 113 | func (t *Tunat) handleIPv4UDP(ipHeader header.IPv4, udpHeader header.UDP) { 114 | ip, ok := netip.AddrFromSlice([]byte(ipHeader.SourceAddress())) 115 | if !ok { 116 | return 117 | } 118 | saddr := netip.AddrPortFrom(ip, udpHeader.SourcePort()) 119 | ip, ok = netip.AddrFromSlice([]byte(ipHeader.DestinationAddress())) 120 | if !ok { 121 | return 122 | } 123 | daddr := netip.AddrPortFrom(ip, udpHeader.DestinationPort()) 124 | 125 | t.udpChan <- udpData{ 126 | payload: append([]byte(nil), udpHeader.Payload()...), 127 | saddr: saddr, 128 | daddr: daddr, 129 | } 130 | } 131 | 132 | func (t *Tunat) handleIPv6UDP(ipHeader header.IPv6, udpHeader header.UDP) { 133 | ip, ok := netip.AddrFromSlice([]byte(ipHeader.SourceAddress())) 134 | if !ok { 135 | return 136 | } 137 | saddr := netip.AddrPortFrom(ip, udpHeader.SourcePort()) 138 | ip, ok = netip.AddrFromSlice([]byte(ipHeader.DestinationAddress())) 139 | if !ok { 140 | return 141 | } 142 | daddr := netip.AddrPortFrom(ip, udpHeader.DestinationPort()) 143 | 144 | t.udpChan <- udpData{ 145 | payload: append([]byte(nil), udpHeader.Payload()...), 146 | saddr: saddr, 147 | daddr: daddr, 148 | } 149 | } 150 | --------------------------------------------------------------------------------