diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 7d5cea8..9de14e5 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -16,21 +16,56 @@ on: jobs: build: - name: Build + name: Lint ${{ matrix.goos }}/${{ matrix.goarch }} runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - goos: windows + goarch: amd64 + - goos: windows + goarch: '386' + - goos: windows + goarch: arm64 + - goos: linux + goarch: amd64 + - goos: linux + goarch: arm64 + - goos: linux + goarch: arm + - goos: linux + goarch: '386' + - goos: darwin + goarch: amd64 + - goos: darwin + goarch: arm64 + - goos: android + goarch: arm64 + - goos: freebsd + goarch: amd64 steps: - name: Checkout - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup Go uses: actions/setup-go@v5 with: go-version: ^1.25 + - name: Cache go module + uses: actions/cache@v4 + with: + path: | + ~/go/pkg/mod + key: go-${{ hashFiles('**/go.sum') }} - name: golangci-lint uses: golangci/golangci-lint-action@v8 + env: + GOOS: ${{ matrix.goos }} + GOARCH: ${{ matrix.goarch }} with: version: latest args: --timeout=30m install-mode: binary - verify: false \ No newline at end of file + verify: false diff --git a/.golangci.yml b/.golangci.yml index 7a8a771..0a8a526 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,35 +1,24 @@ version: "2" run: - go: "1.25" + go: "1.24" linters: default: none enable: - - govet - ineffassign - - paralleltest - staticcheck + - modernize settings: staticcheck: checks: - all - - -S1000 - - -S1008 - - -S1017 - - -ST1003 - - -QF1001 - - -QF1003 - - -QF1008 + - -QF1008 # could remove embedded field "" from selector + - -ST1003 # should not use ALL_CAPS in Go names; use CamelCase instead + - -QF1001 # could apply De Morgan's law exclusions: generated: lax presets: - comments - common-false-positives - - legacy - - std-error-handling - paths: - - third_party$ - - builtin$ - - examples$ formatters: enable: - gci @@ -42,8 +31,4 @@ formatters: - default custom-order: true exclusions: - generated: lax - paths: - - third_party$ - - builtin$ - - examples$ + generated: lax \ No newline at end of file diff --git a/Makefile b/Makefile index c752474..ed36c79 100644 --- a/Makefile +++ b/Makefile @@ -18,11 +18,10 @@ fmt_install: go install -v github.com/daixiang0/gci@latest lint: - GOOS=linux golangci-lint run . - GOOS=android golangci-lint run . - GOOS=windows golangci-lint run . - GOOS=darwin golangci-lint run . - GOOS=freebsd golangci-lint run . + GOOS=linux golangci-lint --max-same-issues=0 --max-issues-per-linter=0 run ./... + GOOS=android golangci-lint --max-same-issues=0 --max-issues-per-linter=0 run ./... + GOOS=windows golangci-lint --max-same-issues=0 --max-issues-per-linter=0 run ./... + GOOS=darwin golangci-lint --max-same-issues=0 --max-issues-per-linter=0 run ./... lint_install: go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest diff --git a/internal/checksum_test/sum_bench_test.go b/internal/checksum_test/sum_bench_test.go index 35ee021..a537217 100644 --- a/internal/checksum_test/sum_bench_test.go +++ b/internal/checksum_test/sum_bench_test.go @@ -10,7 +10,7 @@ import ( func BenchmarkTsChecksum(b *testing.B) { packet := make([][]byte, 1000) - for i := 0; i < 1000; i++ { + for i := range 1000 { packet[i] = make([]byte, 1500) rand.Read(packet[i]) } @@ -22,7 +22,7 @@ func BenchmarkTsChecksum(b *testing.B) { func BenchmarkGChecksum(b *testing.B) { packet := make([][]byte, 1000) - for i := 0; i < 1000; i++ { + for i := range 1000 { packet[i] = make([]byte, 1500) rand.Read(packet[i]) } diff --git a/internal/fdbased_darwin/endpoint.go b/internal/fdbased_darwin/endpoint.go index f26bfe3..05371e7 100644 --- a/internal/fdbased_darwin/endpoint.go +++ b/internal/fdbased_darwin/endpoint.go @@ -35,6 +35,9 @@ // only use the first FD to write outbound packets. Once 5 tuple hashes for // all outbound packets are available we will make use of all underlying FD's to // write outbound packets. + +//go:build darwin + package fdbased import ( @@ -46,7 +49,7 @@ import ( "github.com/sagernet/gvisor/pkg/tcpip" "github.com/sagernet/gvisor/pkg/tcpip/header" "github.com/sagernet/gvisor/pkg/tcpip/stack" - "github.com/sagernet/sing-tun/internal/rawfile_darwin" + rawfile "github.com/sagernet/sing-tun/internal/rawfile_darwin" "github.com/sagernet/sing/common" "golang.org/x/sys/unix" diff --git a/internal/fdbased_darwin/endpoint_mutex.go b/internal/fdbased_darwin/endpoint_mutex.go index d05b264..4f2d4b8 100644 --- a/internal/fdbased_darwin/endpoint_mutex.go +++ b/internal/fdbased_darwin/endpoint_mutex.go @@ -1,3 +1,5 @@ +//go:build darwin + package fdbased import ( @@ -92,5 +94,5 @@ func endpointinitLockNames() {} func init() { endpointinitLockNames() - endpointprefixIndex = locking.NewMutexClass(reflect.TypeOf(endpointRWMutex{}), endpointlockNames) + endpointprefixIndex = locking.NewMutexClass(reflect.TypeFor[endpointRWMutex](), endpointlockNames) } diff --git a/internal/fdbased_darwin/errno.go b/internal/fdbased_darwin/errno.go index 074f4e2..8c6f966 100644 --- a/internal/fdbased_darwin/errno.go +++ b/internal/fdbased_darwin/errno.go @@ -1,3 +1,5 @@ +//go:build darwin + package fdbased import ( diff --git a/internal/fdbased_darwin/packet_dispatchers.go b/internal/fdbased_darwin/packet_dispatchers.go index a006d41..c102f6c 100644 --- a/internal/fdbased_darwin/packet_dispatchers.go +++ b/internal/fdbased_darwin/packet_dispatchers.go @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build darwin + package fdbased import ( @@ -19,7 +21,7 @@ import ( "github.com/sagernet/gvisor/pkg/tcpip" "github.com/sagernet/gvisor/pkg/tcpip/stack" "github.com/sagernet/gvisor/pkg/tcpip/stack/gro" - "github.com/sagernet/sing-tun/internal/rawfile_darwin" + rawfile "github.com/sagernet/sing-tun/internal/rawfile_darwin" "github.com/sagernet/sing-tun/internal/stopfd_darwin" "golang.org/x/sys/unix" @@ -177,7 +179,7 @@ func (d *recvMMsgDispatcher) dispatch() (bool, tcpip.Error) { d.gro.Dispatcher = dsp defer d.pkts.Reset() - for k := 0; k < nMsgs; k++ { + for k := range nMsgs { n := int(d.msgHdrs[k].DataLen) payload := d.bufs[k].pullBuffer(n) pkt := stack.NewPacketBuffer(stack.PacketBufferOptions{ diff --git a/internal/fdbased_darwin/processor_mutex.go b/internal/fdbased_darwin/processor_mutex.go index cd297d2..87e1801 100644 --- a/internal/fdbased_darwin/processor_mutex.go +++ b/internal/fdbased_darwin/processor_mutex.go @@ -1,3 +1,5 @@ +//go:build darwin + package fdbased import ( @@ -60,5 +62,5 @@ func processorinitLockNames() {} func init() { processorinitLockNames() - processorprefixIndex = locking.NewMutexClass(reflect.TypeOf(processorMutex{}), processorlockNames) + processorprefixIndex = locking.NewMutexClass(reflect.TypeFor[processorMutex](), processorlockNames) } diff --git a/internal/fdbased_darwin/processors.go b/internal/fdbased_darwin/processors.go index 9df6cfa..1ceca83 100644 --- a/internal/fdbased_darwin/processors.go +++ b/internal/fdbased_darwin/processors.go @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build darwin + package fdbased import ( diff --git a/internal/gtcpip/header/ndp_options.go b/internal/gtcpip/header/ndp_options.go index ba29339..21ed757 100644 --- a/internal/gtcpip/header/ndp_options.go +++ b/internal/gtcpip/header/ndp_options.go @@ -878,7 +878,7 @@ func (o NDPDNSSearchList) iterDomainNames(fn func(string)) error { } // Copy the label and add a trailing period. - for i := 0; i < labelLen; i++ { + for i := range labelLen { b, err := searchList.ReadByte() if err != nil { if err != io.EOF { diff --git a/internal/gtcpip/header/tcp.go b/internal/gtcpip/header/tcp.go index 1b58df8..04c22b5 100644 --- a/internal/gtcpip/header/tcp.go +++ b/internal/gtcpip/header/tcp.go @@ -476,20 +476,14 @@ func ParseSynOptions(opts []byte, isAck bool) TCPSynOptions { if mss == 0 { return synOpts } - synOpts.MSS = mss - if mss < TCPMinimumSendMSS { - synOpts.MSS = TCPMinimumSendMSS - } + synOpts.MSS = max(mss, TCPMinimumSendMSS) i += 4 case TCPOptionWS: if i+3 > limit || opts[i+1] != 3 { return synOpts } - ws := int(opts[i+2]) - if ws > MaxWndScale { - ws = MaxWndScale - } + ws := min(int(opts[i+2]), MaxWndScale) synOpts.WS = ws i += 3 @@ -561,7 +555,7 @@ func ParseTCPOptions(b []byte) TCPOptions { } numBlocks := (sackOptionLen - 2) / 8 opts.SACKBlocks = []SACKBlock{} - for j := 0; j < numBlocks; j++ { + for j := range numBlocks { start := binary.BigEndian.Uint32(b[i+2+j*8:]) end := binary.BigEndian.Uint32(b[i+2+j*8+4:]) opts.SACKBlocks = append(opts.SACKBlocks, SACKBlock{ @@ -646,10 +640,7 @@ func EncodeSACKBlocks(sackBlocks []SACKBlock, b []byte) int { if len(sackBlocks) == 0 { return 0 } - l := len(sackBlocks) - if l > TCPMaxSACKBlocks { - l = TCPMaxSACKBlocks - } + l := min(len(sackBlocks), TCPMaxSACKBlocks) if ll := (len(b) - 2) / 8; ll < l { l = ll } diff --git a/internal/gtcpip/tcpip.go b/internal/gtcpip/tcpip.go index 60d2892..a3dbca8 100644 --- a/internal/gtcpip/tcpip.go +++ b/internal/gtcpip/tcpip.go @@ -245,6 +245,53 @@ func (a Address) Len() int { return a.length } +// String implements the fmt.Stringer interface. +func (a Address) String() string { + switch l := a.Len(); l { + case 4: + return fmt.Sprintf("%d.%d.%d.%d", int(a.addr[0]), int(a.addr[1]), int(a.addr[2]), int(a.addr[3])) + case 16: + // Find the longest subsequence of hexadecimal zeros. + start, end := -1, -1 + for i := 0; i < a.Len(); i += 2 { + j := i + for j < a.Len() && a.addr[j] == 0 && a.addr[j+1] == 0 { + j += 2 + } + if j > i+2 && j-i > end-start { + start, end = i, j + } + } + + var b strings.Builder + for i := 0; i < a.Len(); i += 2 { + if i == start { + b.WriteString("::") + i = end + if end >= a.Len() { + break + } + } else if i > 0 { + b.WriteByte(':') + } + v := uint16(a.addr[i+0])<<8 | uint16(a.addr[i+1]) + if v == 0 { + b.WriteByte('0') + } else { + const digits = "0123456789abcdef" + for i := uint(3); i < 4; i-- { + if v := v >> (i * 4); v != 0 { + b.WriteByte(digits[v&0xf]) + } + } + } + } + return b.String() + default: + return fmt.Sprintf("%x", a.addr[:l]) + } +} + // WithPrefix returns the address with a prefix that represents a point subnet. func (a Address) WithPrefix() AddressWithPrefix { return AddressWithPrefix{ @@ -541,7 +588,7 @@ func (a AddressWithPrefix) Subnet() Subnet { address: a.Address, mask: AddressMask{length: addrLen}, } - for i := 0; i < addrLen; i++ { + for i := range addrLen { sub.mask.mask[i] = 0xff } return sub @@ -550,7 +597,7 @@ func (a AddressWithPrefix) Subnet() Subnet { sa := Address{length: addrLen} sm := AddressMask{length: addrLen} n := uint(a.PrefixLen) - for i := 0; i < addrLen; i++ { + for i := range addrLen { if n >= 8 { sa.addr[i] = a.Address.addr[i] sm.mask[i] = 0xff diff --git a/internal/rawfile_darwin/rawfile.go b/internal/rawfile_darwin/rawfile.go index b73bd82..e3a061b 100644 --- a/internal/rawfile_darwin/rawfile.go +++ b/internal/rawfile_darwin/rawfile.go @@ -1,7 +1,8 @@ +//go:build darwin + package rawfile import ( - "reflect" "unsafe" "golang.org/x/sys/unix" @@ -25,12 +26,8 @@ func IovecFromBytes(bs []byte) unix.Iovec { return iov } -func bytesFromIovec(iov unix.Iovec) (bs []byte) { - sh := (*reflect.SliceHeader)(unsafe.Pointer(&bs)) - sh.Data = uintptr(unsafe.Pointer(iov.Base)) - sh.Len = int(iov.Len) - sh.Cap = int(iov.Len) - return +func bytesFromIovec(iov unix.Iovec) []byte { + return unsafe.Slice(iov.Base, iov.Len) } // AppendIovecFromBytes returns append(iovs, IovecFromBytes(bs)). If len(bs) == @@ -56,6 +53,7 @@ type MsgHdrX struct { } func NonBlockingSendMMsg(fd int, msgHdrs []MsgHdrX) (int, unix.Errno) { + //nolint:staticcheck n, _, e := unix.RawSyscall6(unix.SYS_SENDMSG_X, uintptr(fd), uintptr(unsafe.Pointer(&msgHdrs[0])), uintptr(len(msgHdrs)), unix.MSG_DONTWAIT, 0, 0) return int(n), e } @@ -66,12 +64,14 @@ const SizeofMsgHdrX = unsafe.Sizeof(MsgHdrX{}) // It fails if partial data is written. func NonBlockingWriteIovec(fd int, iovec []unix.Iovec) unix.Errno { iovecLen := uintptr(len(iovec)) + //nolint:staticcheck _, _, e := unix.RawSyscall(unix.SYS_WRITEV, uintptr(fd), uintptr(unsafe.Pointer(&iovec[0])), iovecLen) return e } func BlockingReadvUntilStopped(efd int, fd int, iovecs []unix.Iovec) (int, unix.Errno) { for { + //nolint:staticcheck n, _, e := unix.RawSyscall(unix.SYS_READV, uintptr(fd), uintptr(unsafe.Pointer(&iovecs[0])), uintptr(len(iovecs))) if e == 0 { return int(n), 0 @@ -91,6 +91,7 @@ func BlockingReadvUntilStopped(efd int, fd int, iovecs []unix.Iovec) (int, unix. func BlockingRecvMMsgUntilStopped(efd int, fd int, msgHdrs []MsgHdrX) (int, unix.Errno) { for { + //nolint:staticcheck n, _, e := unix.RawSyscall6(unix.SYS_RECVMSG_X, uintptr(fd), uintptr(unsafe.Pointer(&msgHdrs[0])), uintptr(len(msgHdrs)), unix.MSG_DONTWAIT, 0, 0) if e == 0 { return int(n), e @@ -162,7 +163,7 @@ func BlockingPollUntilStopped(efd int, fd int, events int16) (bool, unix.Errno) var efdHasData bool var errno unix.Errno - for i := 0; i < n; i++ { + for i := range n { ev := &revents[i] if int(ev.Ident) == efd && ev.Filter == unix.EVFILT_READ { diff --git a/internal/stopfd_darwin/stopfd.go b/internal/stopfd_darwin/stopfd.go index fdc3973..0a8f980 100644 --- a/internal/stopfd_darwin/stopfd.go +++ b/internal/stopfd_darwin/stopfd.go @@ -1,3 +1,5 @@ +//go:build darwin + package stopfd import ( diff --git a/internal/winfw/winfw.go b/internal/winfw/winfw.go index f8f17bb..8d5b80f 100644 --- a/internal/winfw/winfw.go +++ b/internal/winfw/winfw.go @@ -98,105 +98,105 @@ func firewallRuleAdd(name, description, group, appPath, serviceName, ports, remo if profile == NET_FW_PROFILE2_CURRENT { currentProfiles, err := oleutil.GetProperty(fwPolicy, "CurrentProfileTypes") if err != nil { - return false, fmt.Errorf("Failed to get CurrentProfiles: %s", err) + return false, fmt.Errorf("failed to get CurrentProfiles: %s", err) } profile = currentProfiles.Value().(int32) } unknownRules, err := oleutil.GetProperty(fwPolicy, "Rules") if err != nil { - return false, fmt.Errorf("Failed to get Rules: %s", err) + return false, fmt.Errorf("failed to get Rules: %s", err) } rules := unknownRules.ToIDispatch() if ok, err := FirewallRuleExistsByName(rules, name); err != nil { - return false, fmt.Errorf("Error while checking rules for duplicate: %s", err) + return false, fmt.Errorf("error while checking rules for duplicate: %s", err) } else if ok { return false, nil } unknown2, err := oleutil.CreateObject("HNetCfg.FWRule") if err != nil { - return false, fmt.Errorf("Error creating Rule object: %s", err) + return false, fmt.Errorf("error creating Rule object: %s", err) } defer unknown2.Release() fwRule, err := unknown2.QueryInterface(ole.IID_IDispatch) if err != nil { - return false, fmt.Errorf("Error creating Rule object (2): %s", err) + return false, fmt.Errorf("error creating Rule object (2): %s", err) } defer fwRule.Release() if _, err := oleutil.PutProperty(fwRule, "Name", name); err != nil { - return false, fmt.Errorf("Error setting property (Name) of Rule: %s", err) + return false, fmt.Errorf("error setting property (Name) of Rule: %s", err) } if _, err := oleutil.PutProperty(fwRule, "Description", description); err != nil { - return false, fmt.Errorf("Error setting property (Description) of Rule: %s", err) + return false, fmt.Errorf("error setting property (Description) of Rule: %s", err) } if appPath != "" { if _, err := oleutil.PutProperty(fwRule, "Applicationname", appPath); err != nil { - return false, fmt.Errorf("Error setting property (Applicationname) of Rule: %s", err) + return false, fmt.Errorf("error setting property (Applicationname) of Rule: %s", err) } } if serviceName != "" { if _, err := oleutil.PutProperty(fwRule, "ServiceName", serviceName); err != nil { - return false, fmt.Errorf("Error setting property (ServiceName) of Rule: %s", err) + return false, fmt.Errorf("error setting property (ServiceName) of Rule: %s", err) } } if protocol != 0 { if _, err := oleutil.PutProperty(fwRule, "Protocol", protocol); err != nil { - return false, fmt.Errorf("Error setting property (Protocol) of Rule: %s", err) + return false, fmt.Errorf("error setting property (Protocol) of Rule: %s", err) } } if icmpTypes != "" { if _, err := oleutil.PutProperty(fwRule, "IcmpTypesAndCodes", icmpTypes); err != nil { - return false, fmt.Errorf("Error setting property (IcmpTypesAndCodes) of Rule: %s", err) + return false, fmt.Errorf("error setting property (IcmpTypesAndCodes) of Rule: %s", err) } } if ports != "" { if _, err := oleutil.PutProperty(fwRule, "LocalPorts", ports); err != nil { - return false, fmt.Errorf("Error setting property (LocalPorts) of Rule: %s", err) + return false, fmt.Errorf("error setting property (LocalPorts) of Rule: %s", err) } } if remotePorts != "" { if _, err := oleutil.PutProperty(fwRule, "RemotePorts", remotePorts); err != nil { - return false, fmt.Errorf("Error setting property (RemotePorts) of Rule: %s", err) + return false, fmt.Errorf("error setting property (RemotePorts) of Rule: %s", err) } } if localAddresses != "" { if _, err := oleutil.PutProperty(fwRule, "LocalAddresses", localAddresses); err != nil { - return false, fmt.Errorf("Error setting property (LocalAddresses) of Rule: %s", err) + return false, fmt.Errorf("error setting property (LocalAddresses) of Rule: %s", err) } } if remoteAddresses != "" { if _, err := oleutil.PutProperty(fwRule, "RemoteAddresses", remoteAddresses); err != nil { - return false, fmt.Errorf("Error setting property (RemoteAddresses) of Rule: %s", err) + return false, fmt.Errorf("error setting property (RemoteAddresses) of Rule: %s", err) } } if direction != 0 { if _, err := oleutil.PutProperty(fwRule, "Direction", direction); err != nil { - return false, fmt.Errorf("Error setting property (Direction) of Rule: %s", err) + return false, fmt.Errorf("error setting property (Direction) of Rule: %s", err) } } if _, err := oleutil.PutProperty(fwRule, "Enabled", enabled); err != nil { - return false, fmt.Errorf("Error setting property (Enabled) of Rule: %s", err) + return false, fmt.Errorf("error setting property (Enabled) of Rule: %s", err) } if _, err := oleutil.PutProperty(fwRule, "Grouping", group); err != nil { - return false, fmt.Errorf("Error setting property (Grouping) of Rule: %s", err) + return false, fmt.Errorf("error setting property (Grouping) of Rule: %s", err) } if _, err := oleutil.PutProperty(fwRule, "Profiles", profile); err != nil { - return false, fmt.Errorf("Error setting property (Profiles) of Rule: %s", err) + return false, fmt.Errorf("error setting property (Profiles) of Rule: %s", err) } if _, err := oleutil.PutProperty(fwRule, "Action", action); err != nil { - return false, fmt.Errorf("Error setting property (Action) of Rule: %s", err) + return false, fmt.Errorf("error setting property (Action) of Rule: %s", err) } if edgeTraversal { if _, err := oleutil.PutProperty(fwRule, "EdgeTraversal", edgeTraversal); err != nil { - return false, fmt.Errorf("Error setting property (EdgeTraversal) of Rule: %s", err) + return false, fmt.Errorf("error setting property (EdgeTraversal) of Rule: %s", err) } } if _, err := oleutil.CallMethod(rules, "Add", fwRule); err != nil { - return false, fmt.Errorf("Error adding Rule: %s", err) + return false, fmt.Errorf("error adding Rule: %s", err) } return true, nil @@ -205,13 +205,13 @@ func firewallRuleAdd(name, description, group, appPath, serviceName, ports, remo func FirewallRuleExistsByName(rules *ole.IDispatch, name string) (bool, error) { enumProperty, err := rules.GetProperty("_NewEnum") if err != nil { - return false, fmt.Errorf("Failed to get enumeration property on Rules: %s", err) + return false, fmt.Errorf("failed to get enumeration property on Rules: %s", err) } defer enumProperty.Clear() enum, err := enumProperty.ToIUnknown().IEnumVARIANT(ole.IID_IEnumVariant) if err != nil { - return false, fmt.Errorf("Failed to cast enum to correct type: %s", err) + return false, fmt.Errorf("failed to cast enum to correct type: %s", err) } if enum == nil { return false, fmt.Errorf("can't get IEnumVARIANT, enum is nil") @@ -219,7 +219,7 @@ func FirewallRuleExistsByName(rules *ole.IDispatch, name string) (bool, error) { for itemRaw, length, err := enum.Next(1); length > 0; itemRaw, length, err = enum.Next(1) { if err != nil { - return false, fmt.Errorf("Failed to seek next Rule item: %s", err) + return false, fmt.Errorf("failed to seek next Rule item: %s", err) } t, err := func() (bool, error) { @@ -227,7 +227,7 @@ func FirewallRuleExistsByName(rules *ole.IDispatch, name string) (bool, error) { defer item.Release() if item, err := oleutil.GetProperty(item, "Name"); err != nil { - return false, fmt.Errorf("Failed to get Property (Name) of Rule") + return false, fmt.Errorf("failed to get Property (Name) of Rule") } else if item.ToString() == name { return true, nil } @@ -251,18 +251,18 @@ func FirewallRuleExistsByName(rules *ole.IDispatch, name string) (bool, error) { func firewallAPIInit() (*ole.IUnknown, *ole.IDispatch, error) { err := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED) if err != nil { - return nil, nil, fmt.Errorf("Failed to initialize COM: %s", err) + return nil, nil, fmt.Errorf("failed to initialize COM: %s", err) } unknown, err := oleutil.CreateObject("HNetCfg.FwPolicy2") if err != nil { - return nil, nil, fmt.Errorf("Failed to create FwPolicy Object: %s", err) + return nil, nil, fmt.Errorf("failed to create FwPolicy Object: %s", err) } fwPolicy, err := unknown.QueryInterface(ole.IID_IDispatch) if err != nil { unknown.Release() - return nil, nil, fmt.Errorf("Failed to create FwPolicy Object (2): %s", err) + return nil, nil, fmt.Errorf("failed to create FwPolicy Object (2): %s", err) } return unknown, fwPolicy, nil diff --git a/internal/winipcfg/interface_change_handler.go b/internal/winipcfg/interface_change_handler.go index af29801..b166940 100644 --- a/internal/winipcfg/interface_change_handler.go +++ b/internal/winipcfg/interface_change_handler.go @@ -1,3 +1,5 @@ +//go:build windows + /* SPDX-License-Identifier: MIT * * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. diff --git a/internal/winipcfg/luid.go b/internal/winipcfg/luid.go index 1f97314..b7159cb 100644 --- a/internal/winipcfg/luid.go +++ b/internal/winipcfg/luid.go @@ -1,3 +1,5 @@ +//go:build windows + /* SPDX-License-Identifier: MIT * * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. diff --git a/internal/winipcfg/mksyscall.go b/internal/winipcfg/mksyscall.go index d62d38d..f07abb3 100644 --- a/internal/winipcfg/mksyscall.go +++ b/internal/winipcfg/mksyscall.go @@ -1,3 +1,5 @@ +//go:build windows + /* SPDX-License-Identifier: MIT * * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. diff --git a/internal/winipcfg/netsh.go b/internal/winipcfg/netsh.go index 2c298cb..5175910 100644 --- a/internal/winipcfg/netsh.go +++ b/internal/winipcfg/netsh.go @@ -1,3 +1,5 @@ +//go:build windows + /* SPDX-License-Identifier: MIT * * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. @@ -60,9 +62,10 @@ const ( func (luid LUID) fallbackSetDNSForFamily(family AddressFamily, dnses []netip.Addr) error { var templateFlush string - if family == windows.AF_INET { + switch family { + case windows.AF_INET: templateFlush = netshCmdTemplateFlush4 - } else if family == windows.AF_INET6 { + case windows.AF_INET6: templateFlush = netshCmdTemplateFlush6 } @@ -72,7 +75,7 @@ func (luid LUID) fallbackSetDNSForFamily(family AddressFamily, dnses []netip.Add return err } cmds = append(cmds, fmt.Sprintf(templateFlush, ipif.InterfaceIndex)) - for i := 0; i < len(dnses); i++ { + for i := range dnses { if dnses[i].Is4() && family == windows.AF_INET { cmds = append(cmds, fmt.Sprintf(netshCmdTemplateAdd4, ipif.InterfaceIndex, dnses[i].String())) } else if dnses[i].Is6() && family == windows.AF_INET6 { @@ -85,23 +88,23 @@ func (luid LUID) fallbackSetDNSForFamily(family AddressFamily, dnses []netip.Add func (luid LUID) fallbackSetDNSDomain(domain string) error { guid, err := luid.GUID() if err != nil { - return fmt.Errorf("Error converting luid to guid: %w", err) + return fmt.Errorf("error converting luid to guid: %w", err) } key, err := registry.OpenKey(registry.LOCAL_MACHINE, fmt.Sprintf("SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Adapters\\%v", guid), registry.QUERY_VALUE) if err != nil { - return fmt.Errorf("Error opening adapter-specific TCP/IP network registry key: %w", err) + return fmt.Errorf("error opening adapter-specific TCP/IP network registry key: %w", err) } paths, _, err := key.GetStringsValue("IpConfig") key.Close() if err != nil { - return fmt.Errorf("Error reading IpConfig registry key: %w", err) + return fmt.Errorf("error reading IpConfig registry key: %w", err) } if len(paths) == 0 { - return errors.New("No TCP/IP interfaces found on adapter") + return errors.New("no TCP/IP interfaces found on adapter") } key, err = registry.OpenKey(registry.LOCAL_MACHINE, fmt.Sprintf("SYSTEM\\CurrentControlSet\\Services\\%s", paths[0]), registry.SET_VALUE) if err != nil { - return fmt.Errorf("Unable to open TCP/IP network registry key: %w", err) + return fmt.Errorf("unable to open TCP/IP network registry key: %w", err) } err = key.SetStringValue("Domain", domain) key.Close() diff --git a/internal/winipcfg/route_change_handler.go b/internal/winipcfg/route_change_handler.go index 4b78331..63e7aa1 100644 --- a/internal/winipcfg/route_change_handler.go +++ b/internal/winipcfg/route_change_handler.go @@ -1,3 +1,5 @@ +//go:build windows + /* SPDX-License-Identifier: MIT * * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. diff --git a/internal/winipcfg/types.go b/internal/winipcfg/types.go index 8e8f4a5..01b5cc0 100644 --- a/internal/winipcfg/types.go +++ b/internal/winipcfg/types.go @@ -1,3 +1,5 @@ +//go:build windows + /* SPDX-License-Identifier: MIT * * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. @@ -62,206 +64,206 @@ type IfType uint32 const ( IfTypeOther IfType = 1 // None of the below - IfTypeRegular1822 = 2 - IfTypeHdh1822 = 3 - IfTypeDdnX25 = 4 - IfTypeRfc877X25 = 5 - IfTypeEthernetCSMACD = 6 - IfTypeISO88023CSMACD = 7 - IfTypeISO88024Tokenbus = 8 - IfTypeISO88025Tokenring = 9 - IfTypeISO88026Man = 10 - IfTypeStarlan = 11 - IfTypeProteon10Mbit = 12 - IfTypeProteon80Mbit = 13 - IfTypeHyperchannel = 14 - IfTypeFddi = 15 - IfTypeLapB = 16 - IfTypeSdlc = 17 - IfTypeDs1 = 18 // DS1-MIB - IfTypeE1 = 19 // Obsolete; see DS1-MIB - IfTypeBasicISDN = 20 - IfTypePrimaryISDN = 21 - IfTypePropPoint2PointSerial = 22 // proprietary serial - IfTypePPP = 23 - IfTypeSoftwareLoopback = 24 - IfTypeEon = 25 // CLNP over IP - IfTypeEthernet3Mbit = 26 - IfTypeNsip = 27 // XNS over IP - IfTypeSlip = 28 // Generic Slip - IfTypeUltra = 29 // ULTRA Technologies - IfTypeDs3 = 30 // DS3-MIB - IfTypeSip = 31 // SMDS, coffee - IfTypeFramerelay = 32 // DTE only - IfTypeRs232 = 33 - IfTypePara = 34 // Parallel port - IfTypeArcnet = 35 - IfTypeArcnetPlus = 36 - IfTypeAtm = 37 // ATM cells - IfTypeMioX25 = 38 - IfTypeSonet = 39 // SONET or SDH - IfTypeX25Ple = 40 - IfTypeIso88022LLC = 41 - IfTypeLocaltalk = 42 - IfTypeSmdsDxi = 43 - IfTypeFramerelayService = 44 // FRNETSERV-MIB - IfTypeV35 = 45 - IfTypeHssi = 46 - IfTypeHippi = 47 - IfTypeModem = 48 // Generic Modem - IfTypeAal5 = 49 // AAL5 over ATM - IfTypeSonetPath = 50 - IfTypeSonetVt = 51 - IfTypeSmdsIcip = 52 // SMDS InterCarrier Interface - IfTypePropVirtual = 53 // Proprietary virtual/internal - IfTypePropMultiplexor = 54 // Proprietary multiplexing - IfTypeIEEE80212 = 55 // 100BaseVG - IfTypeFibrechannel = 56 - IfTypeHippiinterface = 57 - IfTypeFramerelayInterconnect = 58 // Obsolete, use 32 or 44 - IfTypeAflane8023 = 59 // ATM Emulated LAN for 802.3 - IfTypeAflane8025 = 60 // ATM Emulated LAN for 802.5 - IfTypeCctemul = 61 // ATM Emulated circuit - IfTypeFastether = 62 // Fast Ethernet (100BaseT) - IfTypeISDN = 63 // ISDN and X.25 - IfTypeV11 = 64 // CCITT V.11/X.21 - IfTypeV36 = 65 // CCITT V.36 - IfTypeG703_64k = 66 // CCITT G703 at 64Kbps - IfTypeG703_2mb = 67 // Obsolete; see DS1-MIB - IfTypeQllc = 68 // SNA QLLC - IfTypeFastetherFX = 69 // Fast Ethernet (100BaseFX) - IfTypeChannel = 70 - IfTypeIEEE80211 = 71 // Radio spread spectrum - IfTypeIBM370parchan = 72 // IBM System 360/370 OEMI Channel - IfTypeEscon = 73 // IBM Enterprise Systems Connection - IfTypeDlsw = 74 // Data Link Switching - IfTypeISDNS = 75 // ISDN S/T interface - IfTypeISDNU = 76 // ISDN U interface - IfTypeLapD = 77 // Link Access Protocol D - IfTypeIpswitch = 78 // IP Switching Objects - IfTypeRsrb = 79 // Remote Source Route Bridging - IfTypeAtmLogical = 80 // ATM Logical Port - IfTypeDs0 = 81 // Digital Signal Level 0 - IfTypeDs0Bundle = 82 // Group of ds0s on the same ds1 - IfTypeBsc = 83 // Bisynchronous Protocol - IfTypeAsync = 84 // Asynchronous Protocol - IfTypeCnr = 85 // Combat Net Radio - IfTypeIso88025rDtr = 86 // ISO 802.5r DTR - IfTypeEplrs = 87 // Ext Pos Loc Report Sys - IfTypeArap = 88 // Appletalk Remote Access Protocol - IfTypePropCnls = 89 // Proprietary Connectionless Proto - IfTypeHostpad = 90 // CCITT-ITU X.29 PAD Protocol - IfTypeTermpad = 91 // CCITT-ITU X.3 PAD Facility - IfTypeFramerelayMpi = 92 // Multiproto Interconnect over FR - IfTypeX213 = 93 // CCITT-ITU X213 - IfTypeAdsl = 94 // Asymmetric Digital Subscrbr Loop - IfTypeRadsl = 95 // Rate-Adapt Digital Subscrbr Loop - IfTypeSdsl = 96 // Symmetric Digital Subscriber Loop - IfTypeVdsl = 97 // Very H-Speed Digital Subscrb Loop - IfTypeIso88025Crfprint = 98 // ISO 802.5 CRFP - IfTypeMyrinet = 99 // Myricom Myrinet - IfTypeVoiceEm = 100 // Voice recEive and transMit - IfTypeVoiceFxo = 101 // Voice Foreign Exchange Office - IfTypeVoiceFxs = 102 // Voice Foreign Exchange Station - IfTypeVoiceEncap = 103 // Voice encapsulation - IfTypeVoiceOverip = 104 // Voice over IP encapsulation - IfTypeAtmDxi = 105 // ATM DXI - IfTypeAtmFuni = 106 // ATM FUNI - IfTypeAtmIma = 107 // ATM IMA - IfTypePPPmultilinkbundle = 108 // PPP Multilink Bundle - IfTypeIpoverCdlc = 109 // IBM ipOverCdlc - IfTypeIpoverClaw = 110 // IBM Common Link Access to Workstn - IfTypeStacktostack = 111 // IBM stackToStack - IfTypeVirtualipaddress = 112 // IBM VIPA - IfTypeMpc = 113 // IBM multi-proto channel support - IfTypeIpoverAtm = 114 // IBM ipOverAtm - IfTypeIso88025Fiber = 115 // ISO 802.5j Fiber Token Ring - IfTypeTdlc = 116 // IBM twinaxial data link control - IfTypeGigabitethernet = 117 - IfTypeHdlc = 118 - IfTypeLapF = 119 - IfTypeV37 = 120 - IfTypeX25Mlp = 121 // Multi-Link Protocol - IfTypeX25Huntgroup = 122 // X.25 Hunt Group - IfTypeTransphdlc = 123 - IfTypeInterleave = 124 // Interleave channel - IfTypeFast = 125 // Fast channel - IfTypeIP = 126 // IP (for APPN HPR in IP networks) - IfTypeDocscableMaclayer = 127 // CATV Mac Layer - IfTypeDocscableDownstream = 128 // CATV Downstream interface - IfTypeDocscableUpstream = 129 // CATV Upstream interface - IfTypeA12mppswitch = 130 // Avalon Parallel Processor - IfTypeTunnel = 131 // Encapsulation interface - IfTypeCoffee = 132 // Coffee pot - IfTypeCes = 133 // Circuit Emulation Service - IfTypeAtmSubinterface = 134 // ATM Sub Interface - IfTypeL2Vlan = 135 // Layer 2 Virtual LAN using 802.1Q - IfTypeL3Ipvlan = 136 // Layer 3 Virtual LAN using IP - IfTypeL3Ipxvlan = 137 // Layer 3 Virtual LAN using IPX - IfTypeDigitalpowerline = 138 // IP over Power Lines - IfTypeMediamailoverip = 139 // Multimedia Mail over IP - IfTypeDtm = 140 // Dynamic syncronous Transfer Mode - IfTypeDcn = 141 // Data Communications Network - IfTypeIpforward = 142 // IP Forwarding Interface - IfTypeMsdsl = 143 // Multi-rate Symmetric DSL - IfTypeIEEE1394 = 144 // IEEE1394 High Perf Serial Bus - IfTypeIfGsn = 145 - IfTypeDvbrccMaclayer = 146 - IfTypeDvbrccDownstream = 147 - IfTypeDvbrccUpstream = 148 - IfTypeAtmVirtual = 149 - IfTypeMplsTunnel = 150 - IfTypeSrp = 151 - IfTypeVoiceoveratm = 152 - IfTypeVoiceoverframerelay = 153 - IfTypeIdsl = 154 - IfTypeCompositelink = 155 - IfTypeSs7Siglink = 156 - IfTypePropWirelessP2P = 157 - IfTypeFrForward = 158 - IfTypeRfc1483 = 159 - IfTypeUsb = 160 - IfTypeIEEE8023adLag = 161 - IfTypeBgpPolicyAccounting = 162 - IfTypeFrf16MfrBundle = 163 - IfTypeH323Gatekeeper = 164 - IfTypeH323Proxy = 165 - IfTypeMpls = 166 - IfTypeMfSiglink = 167 - IfTypeHdsl2 = 168 - IfTypeShdsl = 169 - IfTypeDs1Fdl = 170 - IfTypePos = 171 - IfTypeDvbAsiIn = 172 - IfTypeDvbAsiOut = 173 - IfTypePlc = 174 - IfTypeNfas = 175 - IfTypeTr008 = 176 - IfTypeGr303Rdt = 177 - IfTypeGr303Idt = 178 - IfTypeIsup = 179 - IfTypePropDocsWirelessMaclayer = 180 - IfTypePropDocsWirelessDownstream = 181 - IfTypePropDocsWirelessUpstream = 182 - IfTypeHiperlan2 = 183 - IfTypePropBwaP2MP = 184 - IfTypeSonetOverheadChannel = 185 - IfTypeDigitalWrapperOverheadChannel = 186 - IfTypeAal2 = 187 - IfTypeRadioMac = 188 - IfTypeAtmRadio = 189 - IfTypeImt = 190 - IfTypeMvl = 191 - IfTypeReachDsl = 192 - IfTypeFrDlciEndpt = 193 - IfTypeAtmVciEndpt = 194 - IfTypeOpticalChannel = 195 - IfTypeOpticalTransport = 196 - IfTypeIEEE80216Wman = 237 - IfTypeWwanpp = 243 // WWAN devices based on GSM technology - IfTypeWwanpp2 = 244 // WWAN devices based on CDMA technology - IfTypeIEEE802154 = 259 // IEEE 802.15.4 WPAN interface - IfTypeXboxWireless = 281 + IfTypeRegular1822 IfType = 2 + IfTypeHdh1822 IfType = 3 + IfTypeDdnX25 IfType = 4 + IfTypeRfc877X25 IfType = 5 + IfTypeEthernetCSMACD IfType = 6 + IfTypeISO88023CSMACD IfType = 7 + IfTypeISO88024Tokenbus IfType = 8 + IfTypeISO88025Tokenring IfType = 9 + IfTypeISO88026Man IfType = 10 + IfTypeStarlan IfType = 11 + IfTypeProteon10Mbit IfType = 12 + IfTypeProteon80Mbit IfType = 13 + IfTypeHyperchannel IfType = 14 + IfTypeFddi IfType = 15 + IfTypeLapB IfType = 16 + IfTypeSdlc IfType = 17 + IfTypeDs1 IfType = 18 // DS1-MIB + IfTypeE1 IfType = 19 // Obsolete; see DS1-MIB + IfTypeBasicISDN IfType = 20 + IfTypePrimaryISDN IfType = 21 + IfTypePropPoint2PointSerial IfType = 22 // proprietary serial + IfTypePPP IfType = 23 + IfTypeSoftwareLoopback IfType = 24 + IfTypeEon IfType = 25 // CLNP over IP + IfTypeEthernet3Mbit IfType = 26 + IfTypeNsip IfType = 27 // XNS over IP + IfTypeSlip IfType = 28 // Generic Slip + IfTypeUltra IfType = 29 // ULTRA Technologies + IfTypeDs3 IfType = 30 // DS3-MIB + IfTypeSip IfType = 31 // SMDS, coffee + IfTypeFramerelay IfType = 32 // DTE only + IfTypeRs232 IfType = 33 + IfTypePara IfType = 34 // Parallel port + IfTypeArcnet IfType = 35 + IfTypeArcnetPlus IfType = 36 + IfTypeAtm IfType = 37 // ATM cells + IfTypeMioX25 IfType = 38 + IfTypeSonet IfType = 39 // SONET or SDH + IfTypeX25Ple IfType = 40 + IfTypeIso88022LLC IfType = 41 + IfTypeLocaltalk IfType = 42 + IfTypeSmdsDxi IfType = 43 + IfTypeFramerelayService IfType = 44 // FRNETSERV-MIB + IfTypeV35 IfType = 45 + IfTypeHssi IfType = 46 + IfTypeHippi IfType = 47 + IfTypeModem IfType = 48 // Generic Modem + IfTypeAal5 IfType = 49 // AAL5 over ATM + IfTypeSonetPath IfType = 50 + IfTypeSonetVt IfType = 51 + IfTypeSmdsIcip IfType = 52 // SMDS InterCarrier Interface + IfTypePropVirtual IfType = 53 // Proprietary virtual/internal + IfTypePropMultiplexor IfType = 54 // Proprietary multiplexing + IfTypeIEEE80212 IfType = 55 // 100BaseVG + IfTypeFibrechannel IfType = 56 + IfTypeHippiinterface IfType = 57 + IfTypeFramerelayInterconnect IfType = 58 // Obsolete, use 32 or 44 + IfTypeAflane8023 IfType = 59 // ATM Emulated LAN for 802.3 + IfTypeAflane8025 IfType = 60 // ATM Emulated LAN for 802.5 + IfTypeCctemul IfType = 61 // ATM Emulated circuit + IfTypeFastether IfType = 62 // Fast Ethernet (100BaseT) + IfTypeISDN IfType = 63 // ISDN and X.25 + IfTypeV11 IfType = 64 // CCITT V.11/X.21 + IfTypeV36 IfType = 65 // CCITT V.36 + IfTypeG703_64k IfType = 66 // CCITT G703 at 64Kbps + IfTypeG703_2mb IfType = 67 // Obsolete; see DS1-MIB + IfTypeQllc IfType = 68 // SNA QLLC + IfTypeFastetherFX IfType = 69 // Fast Ethernet (100BaseFX) + IfTypeChannel IfType = 70 + IfTypeIEEE80211 IfType = 71 // Radio spread spectrum + IfTypeIBM370parchan IfType = 72 // IBM System 360/370 OEMI Channel + IfTypeEscon IfType = 73 // IBM Enterprise Systems Connection + IfTypeDlsw IfType = 74 // Data Link Switching + IfTypeISDNS IfType = 75 // ISDN S/T interface + IfTypeISDNU IfType = 76 // ISDN U interface + IfTypeLapD IfType = 77 // Link Access Protocol D + IfTypeIpswitch IfType = 78 // IP Switching Objects + IfTypeRsrb IfType = 79 // Remote Source Route Bridging + IfTypeAtmLogical IfType = 80 // ATM Logical Port + IfTypeDs0 IfType = 81 // Digital Signal Level 0 + IfTypeDs0Bundle IfType = 82 // Group of ds0s on the same ds1 + IfTypeBsc IfType = 83 // Bisynchronous Protocol + IfTypeAsync IfType = 84 // Asynchronous Protocol + IfTypeCnr IfType = 85 // Combat Net Radio + IfTypeIso88025rDtr IfType = 86 // ISO 802.5r DTR + IfTypeEplrs IfType = 87 // Ext Pos Loc Report Sys + IfTypeArap IfType = 88 // Appletalk Remote Access Protocol + IfTypePropCnls IfType = 89 // Proprietary Connectionless Proto + IfTypeHostpad IfType = 90 // CCITT-ITU X.29 PAD Protocol + IfTypeTermpad IfType = 91 // CCITT-ITU X.3 PAD Facility + IfTypeFramerelayMpi IfType = 92 // Multiproto Interconnect over FR + IfTypeX213 IfType = 93 // CCITT-ITU X213 + IfTypeAdsl IfType = 94 // Asymmetric Digital Subscrbr Loop + IfTypeRadsl IfType = 95 // Rate-Adapt Digital Subscrbr Loop + IfTypeSdsl IfType = 96 // Symmetric Digital Subscriber Loop + IfTypeVdsl IfType = 97 // Very H-Speed Digital Subscrb Loop + IfTypeIso88025Crfprint IfType = 98 // ISO 802.5 CRFP + IfTypeMyrinet IfType = 99 // Myricom Myrinet + IfTypeVoiceEm IfType = 100 // Voice recEive and transMit + IfTypeVoiceFxo IfType = 101 // Voice Foreign Exchange Office + IfTypeVoiceFxs IfType = 102 // Voice Foreign Exchange Station + IfTypeVoiceEncap IfType = 103 // Voice encapsulation + IfTypeVoiceOverip IfType = 104 // Voice over IP encapsulation + IfTypeAtmDxi IfType = 105 // ATM DXI + IfTypeAtmFuni IfType = 106 // ATM FUNI + IfTypeAtmIma IfType = 107 // ATM IMA + IfTypePPPmultilinkbundle IfType = 108 // PPP Multilink Bundle + IfTypeIpoverCdlc IfType = 109 // IBM ipOverCdlc + IfTypeIpoverClaw IfType = 110 // IBM Common Link Access to Workstn + IfTypeStacktostack IfType = 111 // IBM stackToStack + IfTypeVirtualipaddress IfType = 112 // IBM VIPA + IfTypeMpc IfType = 113 // IBM multi-proto channel support + IfTypeIpoverAtm IfType = 114 // IBM ipOverAtm + IfTypeIso88025Fiber IfType = 115 // ISO 802.5j Fiber Token Ring + IfTypeTdlc IfType = 116 // IBM twinaxial data link control + IfTypeGigabitethernet IfType = 117 + IfTypeHdlc IfType = 118 + IfTypeLapF IfType = 119 + IfTypeV37 IfType = 120 + IfTypeX25Mlp IfType = 121 // Multi-Link Protocol + IfTypeX25Huntgroup IfType = 122 // X.25 Hunt Group + IfTypeTransphdlc IfType = 123 + IfTypeInterleave IfType = 124 // Interleave channel + IfTypeFast IfType = 125 // Fast channel + IfTypeIP IfType = 126 // IP (for APPN HPR in IP networks) + IfTypeDocscableMaclayer IfType = 127 // CATV Mac Layer + IfTypeDocscableDownstream IfType = 128 // CATV Downstream interface + IfTypeDocscableUpstream IfType = 129 // CATV Upstream interface + IfTypeA12mppswitch IfType = 130 // Avalon Parallel Processor + IfTypeTunnel IfType = 131 // Encapsulation interface + IfTypeCoffee IfType = 132 // Coffee pot + IfTypeCes IfType = 133 // Circuit Emulation Service + IfTypeAtmSubinterface IfType = 134 // ATM Sub Interface + IfTypeL2Vlan IfType = 135 // Layer 2 Virtual LAN using 802.1Q + IfTypeL3Ipvlan IfType = 136 // Layer 3 Virtual LAN using IP + IfTypeL3Ipxvlan IfType = 137 // Layer 3 Virtual LAN using IPX + IfTypeDigitalpowerline IfType = 138 // IP over Power Lines + IfTypeMediamailoverip IfType = 139 // Multimedia Mail over IP + IfTypeDtm IfType = 140 // Dynamic syncronous Transfer Mode + IfTypeDcn IfType = 141 // Data Communications Network + IfTypeIpforward IfType = 142 // IP Forwarding Interface + IfTypeMsdsl IfType = 143 // Multi-rate Symmetric DSL + IfTypeIEEE1394 IfType = 144 // IEEE1394 High Perf Serial Bus + IfTypeIfGsn IfType = 145 + IfTypeDvbrccMaclayer IfType = 146 + IfTypeDvbrccDownstream IfType = 147 + IfTypeDvbrccUpstream IfType = 148 + IfTypeAtmVirtual IfType = 149 + IfTypeMplsTunnel IfType = 150 + IfTypeSrp IfType = 151 + IfTypeVoiceoveratm IfType = 152 + IfTypeVoiceoverframerelay IfType = 153 + IfTypeIdsl IfType = 154 + IfTypeCompositelink IfType = 155 + IfTypeSs7Siglink IfType = 156 + IfTypePropWirelessP2P IfType = 157 + IfTypeFrForward IfType = 158 + IfTypeRfc1483 IfType = 159 + IfTypeUsb IfType = 160 + IfTypeIEEE8023adLag IfType = 161 + IfTypeBgpPolicyAccounting IfType = 162 + IfTypeFrf16MfrBundle IfType = 163 + IfTypeH323Gatekeeper IfType = 164 + IfTypeH323Proxy IfType = 165 + IfTypeMpls IfType = 166 + IfTypeMfSiglink IfType = 167 + IfTypeHdsl2 IfType = 168 + IfTypeShdsl IfType = 169 + IfTypeDs1Fdl IfType = 170 + IfTypePos IfType = 171 + IfTypeDvbAsiIn IfType = 172 + IfTypeDvbAsiOut IfType = 173 + IfTypePlc IfType = 174 + IfTypeNfas IfType = 175 + IfTypeTr008 IfType = 176 + IfTypeGr303Rdt IfType = 177 + IfTypeGr303Idt IfType = 178 + IfTypeIsup IfType = 179 + IfTypePropDocsWirelessMaclayer IfType = 180 + IfTypePropDocsWirelessDownstream IfType = 181 + IfTypePropDocsWirelessUpstream IfType = 182 + IfTypeHiperlan2 IfType = 183 + IfTypePropBwaP2MP IfType = 184 + IfTypeSonetOverheadChannel IfType = 185 + IfTypeDigitalWrapperOverheadChannel IfType = 186 + IfTypeAal2 IfType = 187 + IfTypeRadioMac IfType = 188 + IfTypeAtmRadio IfType = 189 + IfTypeImt IfType = 190 + IfTypeMvl IfType = 191 + IfTypeReachDsl IfType = 192 + IfTypeFrDlciEndpt IfType = 193 + IfTypeAtmVciEndpt IfType = 194 + IfTypeOpticalChannel IfType = 195 + IfTypeOpticalTransport IfType = 196 + IfTypeIEEE80216Wman IfType = 237 + IfTypeWwanpp IfType = 243 // WWAN devices based on GSM technology + IfTypeWwanpp2 IfType = 244 // WWAN devices based on CDMA technology + IfTypeIEEE802154 IfType = 259 // IEEE 802.15.4 WPAN interface + IfTypeXboxWireless IfType = 281 ) // MibIfEntryLevel enumeration specifies level of interface information to retrieve in GetIfTable2Ex function call. @@ -270,7 +272,7 @@ type MibIfEntryLevel uint32 const ( MibIfEntryNormal MibIfEntryLevel = 0 - MibIfEntryNormalWithoutStatistics = 2 + MibIfEntryNormalWithoutStatistics MibIfEntryLevel = 2 ) // NdisMedium enumeration type identifies the medium types that NDIS drivers support. @@ -522,12 +524,12 @@ type TunnelType uint32 const ( TunnelTypeNone TunnelType = 0 - TunnelTypeOther = 1 - TunnelTypeDirect = 2 - TunnelType6to4 = 11 - TunnelTypeIsatap = 13 - TunnelTypeTeredo = 14 - TunnelTypeIPHTTPS = 15 + TunnelTypeOther TunnelType = 1 + TunnelTypeDirect TunnelType = 2 + TunnelType6to4 TunnelType = 11 + TunnelTypeIsatap TunnelType = 13 + TunnelTypeTeredo TunnelType = 14 + TunnelTypeIPHTTPS TunnelType = 15 ) // InterfaceAndOperStatusFlags enumeration type defines interface and operation flags @@ -574,13 +576,13 @@ type ScopeLevel uint32 const ( ScopeLevelInterface ScopeLevel = 1 - ScopeLevelLink = 2 - ScopeLevelSubnet = 3 - ScopeLevelAdmin = 4 - ScopeLevelSite = 5 - ScopeLevelOrganization = 8 - ScopeLevelGlobal = 14 - ScopeLevelCount = 16 + ScopeLevelLink ScopeLevel = 2 + ScopeLevelSubnet ScopeLevel = 3 + ScopeLevelAdmin ScopeLevel = 4 + ScopeLevelSite ScopeLevel = 5 + ScopeLevelOrganization ScopeLevel = 8 + ScopeLevelGlobal ScopeLevel = 14 + ScopeLevelCount ScopeLevel = 16 ) // RouteData structure describes a route to add @@ -757,7 +759,7 @@ func (addr *RawSockaddrInet) SetAddrPort(addrPort netip.AddrPort) error { addr4.Family = windows.AF_INET addr4.Addr = addrPort.Addr().As4() addr4.Port = htons(addrPort.Port()) - for i := 0; i < 8; i++ { + for i := range 8 { addr4.Zero[i] = 0 } return nil diff --git a/internal/winipcfg/types_32.go b/internal/winipcfg/types_32.go index 1a8d444..bac06ba 100644 --- a/internal/winipcfg/types_32.go +++ b/internal/winipcfg/types_32.go @@ -1,4 +1,4 @@ -//go:build 386 || arm +//go:build windows && (386 || arm) /* SPDX-License-Identifier: MIT * diff --git a/internal/winipcfg/types_64.go b/internal/winipcfg/types_64.go index 3a1fe07..13d3ab9 100644 --- a/internal/winipcfg/types_64.go +++ b/internal/winipcfg/types_64.go @@ -1,4 +1,4 @@ -//go:build amd64 || arm64 +//go:build windows && (amd64 || arm64) /* SPDX-License-Identifier: MIT * diff --git a/internal/winipcfg/types_test.go b/internal/winipcfg/types_test.go index b72d73f..f51c8c9 100644 --- a/internal/winipcfg/types_test.go +++ b/internal/winipcfg/types_test.go @@ -1,3 +1,5 @@ +//go:build windows + /* SPDX-License-Identifier: MIT * * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. diff --git a/internal/winipcfg/types_test_32.go b/internal/winipcfg/types_test_32.go index 9e62bfe..b6e1092 100644 --- a/internal/winipcfg/types_test_32.go +++ b/internal/winipcfg/types_test_32.go @@ -1,4 +1,4 @@ -//go:build 386 || arm +//go:build windows && (386 || arm) /* SPDX-License-Identifier: MIT * diff --git a/internal/winipcfg/types_test_64.go b/internal/winipcfg/types_test_64.go index 8a18157..f94a88d 100644 --- a/internal/winipcfg/types_test_64.go +++ b/internal/winipcfg/types_test_64.go @@ -1,4 +1,4 @@ -//go:build amd64 || arm64 +//go:build windows && (amd64 || arm64) /* SPDX-License-Identifier: MIT * diff --git a/internal/winipcfg/unicast_address_change_handler.go b/internal/winipcfg/unicast_address_change_handler.go index cf4fcb3..0d80f1d 100644 --- a/internal/winipcfg/unicast_address_change_handler.go +++ b/internal/winipcfg/unicast_address_change_handler.go @@ -1,3 +1,5 @@ +//go:build windows + /* SPDX-License-Identifier: MIT * * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. diff --git a/internal/winipcfg/winipcfg.go b/internal/winipcfg/winipcfg.go index e24157b..7a460d7 100644 --- a/internal/winipcfg/winipcfg.go +++ b/internal/winipcfg/winipcfg.go @@ -1,3 +1,5 @@ +//go:build windows + /* SPDX-License-Identifier: MIT * * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. diff --git a/internal/winipcfg/winipcfg_test.go b/internal/winipcfg/winipcfg_test.go index b49daf3..1cba10b 100644 --- a/internal/winipcfg/winipcfg_test.go +++ b/internal/winipcfg/winipcfg_test.go @@ -1,3 +1,5 @@ +//go:build windows + /* SPDX-License-Identifier: MIT * * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved. @@ -104,6 +106,9 @@ func TestAdaptersAddresses(t *testing.T) { } ifcs, err = GetAdaptersAddresses(windows.AF_UNSPEC, GAAFlagDefault) + if err != nil { + t.Errorf("GetAdaptersAddresses() returned error: %v", err) + } for _, i := range ifcs { ifc, err := i.LUID.Interface() @@ -370,7 +375,7 @@ func TestAddDeleteIPAddress(t *testing.T) { return } - addr, err := ifc.LUID.IPAddress(nonexistantIPv4ToAdd.Addr()) + _, err = ifc.LUID.IPAddress(nonexistantIPv4ToAdd.Addr()) if err == nil { t.Errorf("Unicast address %s already exists. Please set nonexistantIPv4ToAdd appropriately.", nonexistantIPv4ToAdd.Addr().String()) return @@ -414,7 +419,7 @@ func TestAddDeleteIPAddress(t *testing.T) { if count != 1 { t.Errorf("After adding there are %d new interface(s).", count) } - addr, err = ifc.LUID.IPAddress(nonexistantIPv4ToAdd.Addr()) + addr, err := ifc.LUID.IPAddress(nonexistantIPv4ToAdd.Addr()) if err != nil { t.Errorf("LUID.IPAddress() returned an error: %w", err) } else if addr == nil { @@ -431,7 +436,7 @@ func TestAddDeleteIPAddress(t *testing.T) { time.Sleep(500 * time.Millisecond) - addr, err = ifc.LUID.IPAddress(nonexistantIPv4ToAdd.Addr()) + _, err = ifc.LUID.IPAddress(nonexistantIPv4ToAdd.Addr()) if err == nil { t.Errorf("Unicast address %s still exists, although it's deleted successfully.", nonexistantIPv4ToAdd.Addr().String()) } else if err != windows.ERROR_NOT_FOUND { diff --git a/internal/wintun/memmod/memmod_windows.go b/internal/wintun/memmod/memmod_windows.go index 985d48a..0b345ba 100644 --- a/internal/wintun/memmod/memmod_windows.go +++ b/internal/wintun/memmod/memmod_windows.go @@ -56,16 +56,16 @@ func (module *Module) copySections(address, size uintptr, oldHeaders *IMAGE_NT_H if sectionSize == 0 { continue } - dest, err := windows.VirtualAlloc(module.codeBase+uintptr(sections[i].VirtualAddress), + _, err := windows.VirtualAlloc(module.codeBase+uintptr(sections[i].VirtualAddress), uintptr(sectionSize), windows.MEM_COMMIT, windows.PAGE_READWRITE) if err != nil { - return fmt.Errorf("Error allocating section: %w", err) + return fmt.Errorf("error allocating section: %w", err) } // Always use position from file to support alignments smaller than page size (allocation above will align to page size). - dest = module.codeBase + uintptr(sections[i].VirtualAddress) + dest := module.codeBase + uintptr(sections[i].VirtualAddress) // NOTE: On 64bit systems we truncate to 32bit here but expand again later when "PhysicalAddress" is used. sections[i].SetPhysicalAddress((uint32)(dest & 0xffffffff)) dst := unsafe.Slice((*byte)(a2p(dest)), sectionSize) @@ -76,7 +76,7 @@ func (module *Module) copySections(address, size uintptr, oldHeaders *IMAGE_NT_H } if size < uintptr(sections[i].PointerToRawData)+uintptr(sections[i].SizeOfRawData) { - return errors.New("Incomplete section") + return errors.New("incomplete section") } // Commit memory block and copy data from dll. @@ -85,7 +85,7 @@ func (module *Module) copySections(address, size uintptr, oldHeaders *IMAGE_NT_H windows.MEM_COMMIT, windows.PAGE_READWRITE) if err != nil { - return fmt.Errorf("Error allocating memory block: %w", err) + return fmt.Errorf("error allocating memory block: %w", err) } // Always use position from file to support alignments smaller than page size (allocation above will align to page size). @@ -158,7 +158,7 @@ func (module *Module) finalizeSection(sectionData *sectionFinalizeData) error { var oldProtect uint32 err := windows.VirtualProtect(sectionData.address, sectionData.size, protect, &oldProtect) if err != nil { - return fmt.Errorf("Error protecting memory page: %w", err) + return fmt.Errorf("error protecting memory page: %w", err) } return nil @@ -204,7 +204,7 @@ func (module *Module) finalizeSections() error { err := module.finalizeSection(§ionData) if err != nil { - return fmt.Errorf("Error finalizing section: %w", err) + return fmt.Errorf("error finalizing section: %w", err) } sectionData.address = sectionAddress sectionData.alignedAddress = alignedAddress @@ -214,7 +214,7 @@ func (module *Module) finalizeSections() error { sectionData.last = true err := module.finalizeSection(§ionData) if err != nil { - return fmt.Errorf("Error finalizing section: %w", err) + return fmt.Errorf("error finalizing section: %w", err) } return nil } @@ -250,10 +250,10 @@ func (module *Module) performBaseRelocation(delta uintptr) (relocated bool, err relocationHdr := (*IMAGE_BASE_RELOCATION)(a2p(relocBase)) for uintptr(unsafe.Pointer(relocationHdr))+unsafe.Sizeof(*relocationHdr) <= relocEnd && relocationHdr.VirtualAddress > 0 { if uintptr(relocationHdr.SizeOfBlock) < unsafe.Sizeof(*relocationHdr) { - return false, errors.New("Invalid relocation block size") + return false, errors.New("invalid relocation block size") } if uintptr(unsafe.Pointer(relocationHdr))+uintptr(relocationHdr.SizeOfBlock) > relocEnd { - return false, errors.New("Relocation block exceeds directory bounds") + return false, errors.New("relocation block exceeds directory bounds") } dest := module.codeBase + uintptr(relocationHdr.VirtualAddress) @@ -272,11 +272,9 @@ func (module *Module) performBaseRelocation(delta uintptr) (relocated bool, err case IMAGE_REL_BASED_LOW: *(*uint16)(a2p(dest + relOffset)) += uint16(delta & 0xffff) - break case IMAGE_REL_BASED_HIGH: *(*uint16)(a2p(dest + relOffset)) += uint16(uint32(delta) >> 16) - break case IMAGE_REL_BASED_HIGHLOW: *(*uint32)(a2p(dest + relOffset)) += uint32(delta) @@ -289,7 +287,7 @@ func (module *Module) performBaseRelocation(delta uintptr) (relocated bool, err imm16 := ((inst << 1) & 0x0800) + ((inst << 12) & 0xf000) + ((inst >> 20) & 0x0700) + ((inst >> 16) & 0x00ff) if (inst & 0x8000fbf0) != 0x0000f240 { - return false, fmt.Errorf("Wrong Thumb2 instruction %08x, expected MOVW", inst) + return false, fmt.Errorf("wrong Thumb2 instruction %08x, expected MOVW", inst) } imm16 += uint32(delta) & 0xffff hiDelta := (uint32(delta&0xffff0000) >> 16) + ((imm16 & 0xffff0000) >> 16) @@ -302,11 +300,11 @@ func (module *Module) performBaseRelocation(delta uintptr) (relocated bool, err imm16 = ((inst << 1) & 0x0800) + ((inst << 12) & 0xf000) + ((inst >> 20) & 0x0700) + ((inst >> 16) & 0x00ff) if (inst & 0x8000fbf0) != 0x0000f2c0 { - return false, fmt.Errorf("Wrong Thumb2 instruction %08x, expected MOVT", inst) + return false, fmt.Errorf("wrong Thumb2 instruction %08x, expected MOVT", inst) } imm16 += hiDelta if imm16 > 0xffff { - return false, fmt.Errorf("Resulting immediate value won't fit: %08x", imm16) + return false, fmt.Errorf("resulting immediate value won't fit: %08x", imm16) } *(*uint32)(a2p(dest + relOffset + 4)) = (inst & 0x8f00fbf0) + ((imm16 >> 1) & 0x0400) + @@ -316,7 +314,7 @@ func (module *Module) performBaseRelocation(delta uintptr) (relocated bool, err } default: - return false, fmt.Errorf("Unsupported relocation: %v", relType) + return false, fmt.Errorf("unsupported relocation: %v", relType) } } @@ -337,7 +335,7 @@ func (module *Module) buildImportTable() error { for importDesc.Name != 0 { handle, err := windows.LoadLibraryEx(windows.BytePtrToString((*byte)(a2p(module.codeBase+uintptr(importDesc.Name)))), 0, windows.LOAD_LIBRARY_SEARCH_SYSTEM32) if err != nil { - return fmt.Errorf("Error loading module: %w", err) + return fmt.Errorf("error loading module: %w", err) } var thunkRef, funcRef *uintptr if importDesc.OriginalFirstThunk() != 0 { @@ -357,7 +355,7 @@ func (module *Module) buildImportTable() error { } if err != nil { windows.FreeLibrary(handle) - return fmt.Errorf("Error getting function address: %w", err) + return fmt.Errorf("error getting function address: %w", err) } thunkRef = (*uintptr)(a2p(uintptr(unsafe.Pointer(thunkRef)) + unsafe.Sizeof(*thunkRef))) funcRef = (*uintptr)(a2p(uintptr(unsafe.Pointer(funcRef)) + unsafe.Sizeof(*funcRef))) @@ -371,14 +369,14 @@ func (module *Module) buildImportTable() error { func (module *Module) buildNameExports() error { directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT) if directory.Size == 0 { - return errors.New("No export table found") + return errors.New("no export table found") } exports := (*IMAGE_EXPORT_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress))) if exports.NumberOfNames == 0 || exports.NumberOfFunctions == 0 { - return errors.New("No functions exported") + return errors.New("no functions exported") } if exports.NumberOfNames == 0 { - return errors.New("No functions exported by name") + return errors.New("no functions exported by name") } nameRefs := unsafe.Slice((*uint32)(a2p(module.codeBase+uintptr(exports.AddressOfNames))), exports.NumberOfNames) ordinals := unsafe.Slice((*uint16)(a2p(module.codeBase+uintptr(exports.AddressOfNameOrdinals))), exports.NumberOfNames) @@ -466,39 +464,39 @@ func hookRtlPcToFileHeader() error { func LoadLibrary(data []byte) (module *Module, err error) { size := uintptr(len(data)) if size < unsafe.Sizeof(IMAGE_DOS_HEADER{}) { - return nil, errors.New("Incomplete IMAGE_DOS_HEADER") + return nil, errors.New("incomplete IMAGE_DOS_HEADER") } addr := uintptr(unsafe.Pointer(&data[0])) dosHeader := (*IMAGE_DOS_HEADER)(a2p(addr)) if dosHeader.E_magic != IMAGE_DOS_SIGNATURE { - return nil, fmt.Errorf("Not an MS-DOS binary (provided: %x, expected: %x)", dosHeader.E_magic, IMAGE_DOS_SIGNATURE) + return nil, fmt.Errorf("not an MS-DOS binary (provided: %x, expected: %x)", dosHeader.E_magic, IMAGE_DOS_SIGNATURE) } if dosHeader.E_lfanew < 0 || (size < uintptr(dosHeader.E_lfanew)+unsafe.Sizeof(IMAGE_NT_HEADERS{})) { - return nil, errors.New("Incomplete IMAGE_NT_HEADERS") + return nil, errors.New("incomplete IMAGE_NT_HEADERS") } oldHeader := (*IMAGE_NT_HEADERS)(a2p(addr + uintptr(dosHeader.E_lfanew))) if oldHeader.Signature != IMAGE_NT_SIGNATURE { - return nil, fmt.Errorf("Not an NT binary (provided: %x, expected: %x)", oldHeader.Signature, IMAGE_NT_SIGNATURE) + return nil, fmt.Errorf("not an NT binary (provided: %x, expected: %x)", oldHeader.Signature, IMAGE_NT_SIGNATURE) } if oldHeader.FileHeader.Machine != imageFileProcess { - return nil, fmt.Errorf("Foreign platform (provided: %x, expected: %x)", oldHeader.FileHeader.Machine, imageFileProcess) + return nil, fmt.Errorf("foreign platform (provided: %x, expected: %x)", oldHeader.FileHeader.Machine, imageFileProcess) } if oldHeader.OptionalHeader.SectionAlignment == 0 || (oldHeader.OptionalHeader.SectionAlignment&(oldHeader.OptionalHeader.SectionAlignment-1)) != 0 { - return nil, errors.New("Unaligned section") + return nil, errors.New("unaligned section") } if oldHeader.FileHeader.NumberOfSections == 0 { - return nil, errors.New("No sections") + return nil, errors.New("no sections") } if uintptr(oldHeader.FileHeader.SizeOfOptionalHeader) < unsafe.Sizeof(oldHeader.OptionalHeader) { - return nil, errors.New("Incomplete optional header") + return nil, errors.New("incomplete optional header") } if oldHeader.OptionalHeader.NumberOfRvaAndSizes < IMAGE_NUMBEROF_DIRECTORY_ENTRIES { - return nil, errors.New("Incomplete data directory") + return nil, errors.New("incomplete data directory") } sectionHeadersEnd := uintptr(dosHeader.E_lfanew) + unsafe.Offsetof(oldHeader.OptionalHeader) + uintptr(oldHeader.FileHeader.SizeOfOptionalHeader) + uintptr(oldHeader.FileHeader.NumberOfSections)*unsafe.Sizeof(IMAGE_SECTION_HEADER{}) if size < sectionHeadersEnd { - return nil, errors.New("Incomplete section headers") + return nil, errors.New("incomplete section headers") } lastSectionEnd := uintptr(0) sections := oldHeader.Sections() @@ -517,7 +515,7 @@ func LoadLibrary(data []byte) (module *Module, err error) { } alignedImageSize := alignUp(uintptr(oldHeader.OptionalHeader.SizeOfImage), uintptr(oldHeader.OptionalHeader.SectionAlignment)) if alignedImageSize != alignUp(lastSectionEnd, uintptr(oldHeader.OptionalHeader.SectionAlignment)) { - return nil, errors.New("Section is not page-aligned") + return nil, errors.New("section is not page-aligned") } module = &Module{isDLL: (oldHeader.FileHeader.Characteristics & IMAGE_FILE_DLL) != 0} @@ -541,18 +539,18 @@ func LoadLibrary(data []byte) (module *Module, err error) { windows.MEM_RESERVE|windows.MEM_COMMIT, windows.PAGE_READWRITE) if err != nil { - err = fmt.Errorf("Error allocating code: %w", err) + err = fmt.Errorf("error allocating code: %w", err) return } } err = module.check4GBBoundaries(alignedImageSize) if err != nil { - err = fmt.Errorf("Error reallocating code: %w", err) + err = fmt.Errorf("error reallocating code: %w", err) return } if size < uintptr(oldHeader.OptionalHeader.SizeOfHeaders) { - err = errors.New("Incomplete headers") + err = errors.New("incomplete headers") return } // Commit memory for headers. @@ -561,7 +559,7 @@ func LoadLibrary(data []byte) (module *Module, err error) { windows.MEM_COMMIT, windows.PAGE_READWRITE) if err != nil { - err = fmt.Errorf("Error allocating headers: %w", err) + err = fmt.Errorf("error allocating headers: %w", err) return } // Copy PE header to code. @@ -574,7 +572,7 @@ func LoadLibrary(data []byte) (module *Module, err error) { // Copy sections from DLL file block to new memory location. err = module.copySections(addr, size, oldHeader) if err != nil { - err = fmt.Errorf("Error copying sections: %w", err) + err = fmt.Errorf("error copying sections: %w", err) return } @@ -583,7 +581,7 @@ func LoadLibrary(data []byte) (module *Module, err error) { if locationDelta != 0 { module.isRelocated, err = module.performBaseRelocation(locationDelta) if err != nil { - err = fmt.Errorf("Error relocating module: %w", err) + err = fmt.Errorf("error relocating module: %w", err) return } if !module.isRelocated { @@ -597,14 +595,14 @@ func LoadLibrary(data []byte) (module *Module, err error) { // Load required dlls and adjust function table of imports. err = module.buildImportTable() if err != nil { - err = fmt.Errorf("Error building import table: %w", err) + err = fmt.Errorf("error building import table: %w", err) return } // Mark memory pages depending on section headers and release sections that are marked as "discardable". err = module.finalizeSections() if err != nil { - err = fmt.Errorf("Error finalizing sections: %w", err) + err = fmt.Errorf("error finalizing sections: %w", err) return } @@ -673,35 +671,35 @@ func (module *Module) Free() { func (module *Module) ProcAddressByName(name string) (uintptr, error) { directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT) if directory.Size == 0 { - return 0, errors.New("No export table found") + return 0, errors.New("no export table found") } exports := (*IMAGE_EXPORT_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress))) if module.nameExports == nil { - return 0, errors.New("No functions exported by name") + return 0, errors.New("no functions exported by name") } if idx, ok := module.nameExports[name]; ok { if uint32(idx) >= exports.NumberOfFunctions { - return 0, errors.New("Ordinal number too high") + return 0, errors.New("ordinal number too high") } // AddressOfFunctions contains the RVAs to the "real" functions. return module.codeBase + uintptr(*(*uint32)(a2p(module.codeBase + uintptr(exports.AddressOfFunctions) + uintptr(idx)*4))), nil } - return 0, errors.New("Function not found by name") + return 0, errors.New("function not found by name") } // ProcAddressByOrdinal returns function address by exported ordinal. func (module *Module) ProcAddressByOrdinal(ordinal uint16) (uintptr, error) { directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT) if directory.Size == 0 { - return 0, errors.New("No export table found") + return 0, errors.New("no export table found") } exports := (*IMAGE_EXPORT_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress))) if uint32(ordinal) < exports.Base { - return 0, errors.New("Ordinal number too low") + return 0, errors.New("ordinal number too low") } idx := ordinal - uint16(exports.Base) if uint32(idx) >= exports.NumberOfFunctions { - return 0, errors.New("Ordinal number too high") + return 0, errors.New("ordinal number too high") } // AddressOfFunctions contains the RVAs to the "real" functions. return module.codeBase + uintptr(*(*uint32)(a2p(module.codeBase + uintptr(exports.AddressOfFunctions) + uintptr(idx)*4))), nil diff --git a/internal/wintun/memmod/memmod_windows_64.go b/internal/wintun/memmod/memmod_windows_64.go index a53851c..b3efca9 100644 --- a/internal/wintun/memmod/memmod_windows_64.go +++ b/internal/wintun/memmod/memmod_windows_64.go @@ -29,7 +29,7 @@ func (module *Module) check4GBBoundaries(alignedImageSize uintptr) (err error) { windows.MEM_RESERVE|windows.MEM_COMMIT, windows.PAGE_READWRITE) if err != nil { - return fmt.Errorf("Error allocating memory block: %w", err) + return fmt.Errorf("error allocating memory block: %w", err) } } return diff --git a/internal/wintun/session_windows.go b/internal/wintun/session_windows.go index f023baf..306f3b1 100644 --- a/internal/wintun/session_windows.go +++ b/internal/wintun/session_windows.go @@ -40,7 +40,7 @@ var ( ) func (wintun *Adapter) StartSession(capacity uint32) (session Session, err error) { - r0, _, e1 := syscall.Syscall(procWintunStartSession.Addr(), 2, uintptr(wintun.handle), uintptr(capacity), 0) + r0, _, e1 := syscall.SyscallN(procWintunStartSession.Addr(), uintptr(wintun.handle), uintptr(capacity)) if r0 == 0 { err = e1 } else { @@ -50,19 +50,18 @@ func (wintun *Adapter) StartSession(capacity uint32) (session Session, err error } func (session Session) End() { - syscall.Syscall(procWintunEndSession.Addr(), 1, session.handle, 0, 0) - session.handle = 0 + syscall.SyscallN(procWintunEndSession.Addr(), session.handle) } func (session Session) ReadWaitEvent() (handle windows.Handle) { - r0, _, _ := syscall.Syscall(procWintunGetReadWaitEvent.Addr(), 1, session.handle, 0, 0) + r0, _, _ := syscall.SyscallN(procWintunGetReadWaitEvent.Addr(), session.handle) handle = windows.Handle(r0) return } func (session Session) ReceivePacket() (packet []byte, err error) { var packetSize uint32 - r0, _, e1 := syscall.Syscall(procWintunReceivePacket.Addr(), 2, session.handle, uintptr(unsafe.Pointer(&packetSize)), 0) + r0, _, e1 := syscall.SyscallN(procWintunReceivePacket.Addr(), session.handle, uintptr(unsafe.Pointer(&packetSize))) if r0 == 0 { err = e1 return @@ -72,11 +71,11 @@ func (session Session) ReceivePacket() (packet []byte, err error) { } func (session Session) ReleaseReceivePacket(packet []byte) { - syscall.Syscall(procWintunReleaseReceivePacket.Addr(), 2, session.handle, uintptr(unsafe.Pointer(&packet[0])), 0) + syscall.SyscallN(procWintunReleaseReceivePacket.Addr(), session.handle, uintptr(unsafe.Pointer(&packet[0]))) } func (session Session) AllocateSendPacket(packetSize int) (packet []byte, err error) { - r0, _, e1 := syscall.Syscall(procWintunAllocateSendPacket.Addr(), 2, session.handle, uintptr(packetSize), 0) + r0, _, e1 := syscall.SyscallN(procWintunAllocateSendPacket.Addr(), session.handle, uintptr(packetSize)) if r0 == 0 { err = e1 return @@ -86,5 +85,5 @@ func (session Session) AllocateSendPacket(packetSize int) (packet []byte, err er } func (session Session) SendPacket(packet []byte) { - syscall.Syscall(procWintunSendPacket.Addr(), 2, session.handle, uintptr(unsafe.Pointer(&packet[0])), 0) + syscall.SyscallN(procWintunSendPacket.Addr(), session.handle, uintptr(unsafe.Pointer(&packet[0]))) } diff --git a/internal/wintun/wintun_windows.go b/internal/wintun/wintun_windows.go index 288d364..8087a1e 100644 --- a/internal/wintun/wintun_windows.go +++ b/internal/wintun/wintun_windows.go @@ -30,7 +30,7 @@ var ( ) func closeAdapter(wintun *Adapter) { - syscall.SyscallN(procWintunCloseAdapter.Addr(), 1, wintun.handle, 0, 0) + syscall.SyscallN(procWintunCloseAdapter.Addr(), wintun.handle) } // CreateAdapter creates a Wintun adapter. name is the cosmetic name of the adapter. @@ -53,7 +53,7 @@ func CreateAdapter(name string, tunnelType string, requestedGUID *windows.GUID) if err != nil { return } - r0, _, e1 := syscall.Syscall(procWintunCreateAdapter.Addr(), 3, uintptr(unsafe.Pointer(name16)), uintptr(unsafe.Pointer(tunnelType16)), uintptr(unsafe.Pointer(requestedGUID))) + r0, _, e1 := syscall.SyscallN(procWintunCreateAdapter.Addr(), uintptr(unsafe.Pointer(name16)), uintptr(unsafe.Pointer(tunnelType16)), uintptr(unsafe.Pointer(requestedGUID))) if r0 == 0 { err = e1 return @@ -70,7 +70,7 @@ func OpenAdapter(name string) (wintun *Adapter, err error) { if err != nil { return } - r0, _, e1 := syscall.Syscall(procWintunOpenAdapter.Addr(), 1, uintptr(unsafe.Pointer(name16)), 0, 0) + r0, _, e1 := syscall.SyscallN(procWintunOpenAdapter.Addr(), uintptr(unsafe.Pointer(name16))) if r0 == 0 { err = e1 return @@ -83,7 +83,7 @@ func OpenAdapter(name string) (wintun *Adapter, err error) { // Close closes a Wintun adapter. func (wintun *Adapter) Close() (err error) { runtime.SetFinalizer(wintun, nil) - r1, _, e1 := syscall.Syscall(procWintunCloseAdapter.Addr(), 1, wintun.handle, 0, 0) + r1, _, e1 := syscall.SyscallN(procWintunCloseAdapter.Addr(), wintun.handle) if r1 == 0 { err = e1 } @@ -92,7 +92,7 @@ func (wintun *Adapter) Close() (err error) { // Uninstall removes the driver from the system if no drivers are currently in use. func Uninstall() (err error) { - r1, _, e1 := syscall.Syscall(procWintunDeleteDriver.Addr(), 0, 0, 0, 0) + r1, _, e1 := syscall.SyscallN(procWintunDeleteDriver.Addr()) if r1 == 0 { err = e1 } @@ -101,7 +101,7 @@ func Uninstall() (err error) { // RunningVersion returns the version of the running Wintun driver. func RunningVersion() (version uint32, err error) { - r0, _, e1 := syscall.Syscall(procWintunGetRunningDriverVersion.Addr(), 0, 0, 0, 0) + r0, _, e1 := syscall.SyscallN(procWintunGetRunningDriverVersion.Addr()) version = uint32(r0) if version == 0 { err = e1 @@ -111,6 +111,6 @@ func RunningVersion() (version uint32, err error) { // LUID returns the LUID of the adapter. func (wintun *Adapter) LUID() (luid uint64) { - syscall.Syscall(procWintunGetAdapterLUID.Addr(), 2, uintptr(wintun.handle), uintptr(unsafe.Pointer(&luid)), 0) + syscall.SyscallN(procWintunGetAdapterLUID.Addr(), uintptr(wintun.handle), uintptr(unsafe.Pointer(&luid))) return } diff --git a/nfqueue_linux.go b/nfqueue_linux.go index baaefb5..ad16dc4 100644 --- a/nfqueue_linux.go +++ b/nfqueue_linux.go @@ -173,7 +173,8 @@ func (h *nfqueueHandler) handlePacket(attr nfqueue.Attribute) int { var tcpOffset int version := payload[0] >> 4 - if version == 4 { + switch version { + case 4: ipv4 := header.IPv4(payload) if !ipv4.IsValid(len(payload)) || ipv4.Protocol() != uint8(unix.IPPROTO_TCP) { h.setVerdict(packetID, nfqueue.NfAccept, 0) @@ -182,7 +183,7 @@ func (h *nfqueueHandler) handlePacket(attr nfqueue.Attribute) int { srcAddr = M.SocksaddrFrom(ipv4.SourceAddr(), 0) dstAddr = M.SocksaddrFrom(ipv4.DestinationAddr(), 0) tcpOffset = int(ipv4.HeaderLength()) - } else if version == 6 { + case 6: transportProto, transportOffset, ok := parseIPv6TransportHeader(payload) if !ok || transportProto != unix.IPPROTO_TCP { h.setVerdict(packetID, nfqueue.NfAccept, 0) @@ -192,7 +193,7 @@ func (h *nfqueueHandler) handlePacket(attr nfqueue.Attribute) int { srcAddr = M.SocksaddrFrom(ipv6.SourceAddr(), 0) dstAddr = M.SocksaddrFrom(ipv6.DestinationAddr(), 0) tcpOffset = transportOffset - } else { + default: h.setVerdict(packetID, nfqueue.NfAccept, 0) return 0 } diff --git a/stack.go b/stack.go index a6f6043..d128feb 100644 --- a/stack.go +++ b/stack.go @@ -68,7 +68,7 @@ func NewStack( func HasNextAddress(prefix netip.Prefix, count int) bool { checkAddr := prefix.Addr() - for i := 0; i < count; i++ { + for range count { checkAddr = checkAddr.Next() } return prefix.Contains(checkAddr) diff --git a/stack_system.go b/stack_system.go index 030eee1..031e87f 100644 --- a/stack_system.go +++ b/stack_system.go @@ -131,7 +131,7 @@ func (s *System) start() error { var tcpListener net.Listener var err error if s.inet4NextAddress.IsValid() { - for i := 0; i < 3; i++ { + for range 3 { tcpListener, err = listener.Listen(s.ctx, "tcp4", net.JoinHostPort(s.inet4Address.String(), "0")) if !retryableListenError(err) { break @@ -146,7 +146,7 @@ func (s *System) start() error { go s.acceptLoop(tcpListener) } if s.inet6NextAddress.IsValid() { - for i := 0; i < 3; i++ { + for range 3 { tcpListener, err = listener.Listen(s.ctx, "tcp6", net.JoinHostPort(s.inet6Address.String(), "0")) if !retryableListenError(err) { break @@ -245,7 +245,7 @@ func (s *System) batchLoopLinux(linuxTUN LinuxTUN, batchSize int) { if n == 0 { continue } - for i := 0; i < n; i++ { + for i := range n { packetSize := packetSizes[i] if packetSize < header.IPv4MinimumSize { continue diff --git a/tun_darwin.go b/tun_darwin.go index 8aa6923..f5f7aff 100644 --- a/tun_darwin.go +++ b/tun_darwin.go @@ -132,7 +132,7 @@ func New(options Options) (Tun, error) { stopFd: common.Must1(stopfd.New()), sendMsgX: options.EXP_SendMsgX, } - for i := 0; i < batchSize; i++ { + for i := range batchSize { nativeTun.iovecs[i] = newIovecBuffer(int(options.MTU)) nativeTun.iovecsOutput[i] = newIovecBuffer(int(options.MTU)) } @@ -352,7 +352,7 @@ func (t *NativeTun) BatchRead() ([]*buf.Buffer, error) { } n, errno := rawfile.BlockingRecvMMsgUntilStopped(t.stopFd.ReadFD, t.tunFd, t.msgHdrs) if errno != 0 { - for k := 0; k < n; k++ { + for k := range n { t.iovecs[k].buffer.Release() t.iovecs[k].buffer = nil } @@ -366,7 +366,7 @@ func (t *NativeTun) BatchRead() ([]*buf.Buffer, error) { return nil, nil } buffers := t.buffers - for k := 0; k < n; k++ { + for k := range n { buffer := t.iovecs[k].buffer t.iovecs[k].buffer = nil buffer.Truncate(int(t.msgHdrs[k].DataLen) - PacketOffset) diff --git a/tun_linux.go b/tun_linux.go index 20fdce2..9cd6300 100644 --- a/tun_linux.go +++ b/tun_linux.go @@ -42,7 +42,6 @@ type NativeTun struct { vnetHdrWriteBuf []byte gsoToWrite []int tcpGROTable *tcpGROTable - udpGroAccess sync.Mutex udpGROTable *udpGROTable gro groDisablementFlags txChecksumOffload bool diff --git a/tun_offload.go b/tun_offload.go index a0eee82..c76aeac 100644 --- a/tun_offload.go +++ b/tun_offload.go @@ -9,11 +9,6 @@ import ( "github.com/sagernet/sing-tun/internal/gtcpip/header" ) -const ( - gsoMaxSize = 65536 - idealBatchSize = 128 -) - // GSOType represents the type of segmentation offload. type GSOType int @@ -167,10 +162,7 @@ func GSOSplit(in []byte, options GSOOptions, outBufs [][]byte, sizes []int, outO if i == len(outBufs) { return i - 1, ErrTooManySegments } - nextSegmentEnd := nextSegmentDataAt + int(options.GSOSize) - if nextSegmentEnd > len(in) { - nextSegmentEnd = len(in) - } + nextSegmentEnd := min(nextSegmentDataAt+int(options.GSOSize), len(in)) segmentDataLen := nextSegmentEnd - nextSegmentDataAt totalLen := int(options.HdrLen) + segmentDataLen sizes[i] = totalLen diff --git a/tun_offload_linux.go b/tun_offload_linux.go index 7733760..0712341 100644 --- a/tun_offload_linux.go +++ b/tun_offload_linux.go @@ -11,6 +11,7 @@ import ( "errors" "fmt" "io" + "slices" "unsafe" "github.com/sagernet/sing-tun/internal/gtcpip" @@ -20,6 +21,11 @@ import ( "golang.org/x/sys/unix" ) +const ( + gsoMaxSize = 65536 + idealBatchSize = 128 +) + // virtioNetHdr is defined in the kernel in include/uapi/linux/virtio_net.h. The // kernel symbol is virtio_net_hdr. type virtioNetHdr struct { @@ -606,7 +612,7 @@ func tcpGRO(bufs [][]byte, offset int, pktI int, table *tcpGROTable, isV6 bool) if !existing { return groResultTableInsert } - for i := len(items) - 1; i >= 0; i-- { + for i, item := range slices.Backward(items) { // In the best case of packets arriving in order iterating in reverse is // more efficient if there are multiple items for a given flow. This // also enables a natural table.deleteAt() in the @@ -615,7 +621,6 @@ func tcpGRO(bufs [][]byte, offset int, pktI int, table *tcpGROTable, isV6 bool) // unordered packets, where pkt may land anywhere in items from a // sequence number perspective, however once an item is inserted into // the table it is never compared across other items later. - item := items[i] can := tcpPacketsCanCoalesce(pkt, uint8(iphLen), uint8(tcphLen), seq, pshSet, gsoSize, item, bufs, offset) if can != coalesceUnavailable { result := coalesceTCPPackets(can, pkt, pktI, gsoSize, seq, pshSet, &item, bufs, offset, isV6) @@ -793,7 +798,8 @@ func packetIsGROCandidate(b []byte, gro groDisablementFlags) groCandidateType { if len(b) < 28 { return notGROCandidate } - if b[0]>>4 == 4 { + switch b[0] >> 4 { + case 4: if b[0]&0x0F != 5 { // IPv4 packets w/IP options do not coalesce return notGROCandidate @@ -804,7 +810,7 @@ func packetIsGROCandidate(b []byte, gro groDisablementFlags) groCandidateType { if b[9] == unix.IPPROTO_UDP && gro.canUDPGRO() { return udp4GROCandidate } - } else if b[0]>>4 == 6 { + case 6: if b[6] == unix.IPPROTO_TCP && len(b) >= 60 && gro.canTCPGRO() { return tcp6GROCandidate }