From 1ab008e1e61589e828429cc0a7a39877eb59d1de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=96=E7=95=8C?= Date: Sun, 15 Mar 2026 14:43:38 +0800 Subject: [PATCH] Improve error messages for Linux TUN and redirect operations --- monitor_android.go | 6 ++--- monitor_linux.go | 4 ++-- monitor_linux_default.go | 4 ++-- redirect_iptables.go | 4 ++-- redirect_linux.go | 11 +++++++-- redirect_nftables.go | 49 +++++++++++++++++++------------------- redirect_nftables_rules.go | 42 ++++++++++++++++---------------- redirect_route_linux.go | 17 ++++++------- tun_linux.go | 45 ++++++++++++++++++---------------- 9 files changed, 98 insertions(+), 84 deletions(-) diff --git a/monitor_android.go b/monitor_android.go index 1c7e711..c83440d 100644 --- a/monitor_android.go +++ b/monitor_android.go @@ -8,7 +8,7 @@ import ( func (m *defaultInterfaceMonitor) checkUpdate() error { ruleList, err := netlink.RuleList(netlink.FAMILY_ALL) if err != nil { - return err + return E.Cause(err, "list rules") } oldVPNEnabled := m.androidVPNEnabled @@ -38,7 +38,7 @@ func (m *defaultInterfaceMonitor) checkUpdate() error { routes, err := netlink.RouteListFiltered(netlink.FAMILY_ALL, &netlink.Route{Table: defaultTableIndex}, netlink.RT_FILTER_TABLE) if err != nil { - return err + return E.Cause(err, "list routes") } if len(routes) == 0 { @@ -48,7 +48,7 @@ func (m *defaultInterfaceMonitor) checkUpdate() error { var link netlink.Link link, err = netlink.LinkByIndex(routes[0].LinkIndex) if err != nil { - return err + return E.Cause(err, "find link by index") } newInterface, err := m.interfaceFinder.ByIndex(link.Attrs().Index) diff --git a/monitor_linux.go b/monitor_linux.go index 86dd28b..4725c16 100644 --- a/monitor_linux.go +++ b/monitor_linux.go @@ -57,11 +57,11 @@ func NewNetworkUpdateMonitor(logger logger.Logger) (NetworkUpdateMonitor, error) func (m *networkUpdateMonitor) Start() error { err := netlink.RouteSubscribe(m.routeUpdate, m.close) if err != nil { - return err + return E.Cause(err, "subscribe route updates") } err = netlink.LinkSubscribe(m.linkUpdate, m.close) if err != nil { - return err + return E.Cause(err, "subscribe link updates") } go m.loopUpdate() return nil diff --git a/monitor_linux_default.go b/monitor_linux_default.go index 72ba1be..ce6b36d 100644 --- a/monitor_linux_default.go +++ b/monitor_linux_default.go @@ -12,7 +12,7 @@ import ( func (m *defaultInterfaceMonitor) checkUpdate() error { routes, err := netlink.RouteListFiltered(netlink.FAMILY_ALL, &netlink.Route{Table: unix.RT_TABLE_MAIN}, netlink.RT_FILTER_TABLE) if err != nil { - return err + return E.Cause(err, "list routes") } for _, route := range routes { if route.Dst != nil { @@ -22,7 +22,7 @@ func (m *defaultInterfaceMonitor) checkUpdate() error { var link netlink.Link link, err = netlink.LinkByIndex(route.LinkIndex) if err != nil { - return err + return E.Cause(err, "find link by index") } newInterface, err := m.interfaceFinder.ByIndex(link.Attrs().Index) diff --git a/redirect_iptables.go b/redirect_iptables.go index 2c6e2e2..d918363 100644 --- a/redirect_iptables.go +++ b/redirect_iptables.go @@ -14,13 +14,13 @@ func (r *autoRedirect) setupIPTables() error { if r.enableIPv4 { err := r.setupIPTablesForFamily(r.iptablesPath) if err != nil { - return err + return E.Cause(err, "setup iptables") } } if r.enableIPv6 { err := r.setupIPTablesForFamily(r.ip6tablesPath) if err != nil { - return err + return E.Cause(err, "setup ip6tables") } } return nil diff --git a/redirect_linux.go b/redirect_linux.go index 237b02a..e9c892c 100644 --- a/redirect_linux.go +++ b/redirect_linux.go @@ -154,17 +154,24 @@ func (r *autoRedirect) Start() error { } r.cleanupNFTables() err = r.setupNFTables() - if err == nil && r.tunOptions.AutoRedirectMarkMode { + if err != nil { + return E.Cause(err, "setup nftables") + } + if r.tunOptions.AutoRedirectMarkMode { err = r.setupRedirectRoutes() if err != nil { r.cleanupNFTables() + return E.Cause(err, "setup redirect routes") } } } else { r.cleanupIPTables() err = r.setupIPTables() + if err != nil { + return E.Cause(err, "setup iptables") + } } - return err + return nil } func (r *autoRedirect) Close() error { diff --git a/redirect_nftables.go b/redirect_nftables.go index 3da8576..f45f5df 100644 --- a/redirect_nftables.go +++ b/redirect_nftables.go @@ -11,6 +11,7 @@ import ( "github.com/sagernet/nftables/expr" "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/control" + E "github.com/sagernet/sing/common/exceptions" "golang.org/x/exp/slices" "golang.org/x/sys/unix" @@ -19,7 +20,7 @@ import ( func (r *autoRedirect) setupNFTables() error { nft, err := nftables.New() if err != nil { - return err + return E.Cause(err, "create nftables connection") } defer nft.CloseLasting() @@ -30,12 +31,12 @@ func (r *autoRedirect) setupNFTables() error { err = r.nftablesCreateAddressSets(nft, table, false) if err != nil { - return err + return E.Cause(err, "create address sets") } err = r.interfaceFinder.Update() if err != nil { - return err + return E.Cause(err, "update interfaces") } r.localAddresses = common.FlatMap(r.interfaceFinder.Interfaces(), func(it control.Interface) []netip.Prefix { return common.Filter(it.Addresses, func(prefix netip.Prefix) bool { @@ -44,18 +45,18 @@ func (r *autoRedirect) setupNFTables() error { }) err = r.nftablesCreateLocalAddressSets(nft, table, r.localAddresses, nil) if err != nil { - return err + return E.Cause(err, "create local address sets") } err = r.nftablesCreateLoopbackAddressSets(nft, table) if err != nil { - return err + return E.Cause(err, "create loopback address sets") } if r.nfqueueEnabled { err = r.nftablesCreatePreMatchChains(nft, table) if err != nil { - return err + return E.Cause(err, "create pre-match chains") } } @@ -74,12 +75,12 @@ func (r *autoRedirect) setupNFTables() error { if r.tunOptions.AutoRedirectMarkMode { err = r.nftablesCreateExcludeRules(nft, table, chainOutput) if err != nil { - return err + return E.Cause(err, "create output exclude rules") } r.nftablesCreateUnreachable(nft, table, chainOutput) err = r.nftablesCreateRedirect(nft, table, chainOutput) if err != nil { - return err + return E.Cause(err, "create output redirect") } if len(r.tunOptions.Inet4LoopbackAddress) > 0 || len(r.tunOptions.Inet6LoopbackAddress) > 0 { chainOutputRoute := nft.AddChain(&nftables.Chain{ @@ -91,7 +92,7 @@ func (r *autoRedirect) setupNFTables() error { }) err = r.nftablesCreateLoopbackReroute(nft, table, chainOutputRoute) if err != nil { - return err + return E.Cause(err, "create output loopback reroute") } } chainOutputUDP := nft.AddChain(&nftables.Chain{ @@ -103,7 +104,7 @@ func (r *autoRedirect) setupNFTables() error { }) err = r.nftablesCreateExcludeRules(nft, table, chainOutputUDP) if err != nil { - return err + return E.Cause(err, "create output udp exclude rules") } r.nftablesCreateUnreachable(nft, table, chainOutputUDP) r.nftablesCreateMark(nft, table, chainOutputUDP) @@ -117,7 +118,7 @@ func (r *autoRedirect) setupNFTables() error { Data: nftablesIfname(r.tunOptions.Name), }) if err != nil { - return err + return E.Cause(err, "create output redirect") } } } @@ -131,12 +132,12 @@ func (r *autoRedirect) setupNFTables() error { }) err = r.nftablesCreateExcludeRules(nft, table, chainPreRouting) if err != nil { - return err + return E.Cause(err, "create prerouting exclude rules") } r.nftablesCreateUnreachable(nft, table, chainPreRouting) err = r.nftablesCreateRedirect(nft, table, chainPreRouting) if err != nil { - return err + return E.Cause(err, "create prerouting redirect") } if r.tunOptions.AutoRedirectMarkMode { r.nftablesCreateMark(nft, table, chainPreRouting) @@ -150,7 +151,7 @@ func (r *autoRedirect) setupNFTables() error { }) err = r.nftablesCreateLoopbackReroute(nft, table, chainPreRoutingFilter) if err != nil { - return err + return E.Cause(err, "create prerouting loopback reroute") } } chainPreRoutingUDP := nft.AddChain(&nftables.Chain{ @@ -172,7 +173,7 @@ func (r *autoRedirect) setupNFTables() error { {Key: []byte{unix.IPPROTO_ICMPV6}}, }) if err != nil { - return err + return E.Cause(err, "add ip protocol set") } nft.AddRule(&nftables.Rule{ Table: table, @@ -280,12 +281,12 @@ func (r *autoRedirect) setupNFTables() error { err = r.configureOpenWRTFirewall4(nft, false) if err != nil { - return err + return E.Cause(err, "configure openwrt firewall4") } err = nft.Flush() if err != nil { - return err + return E.Cause(err, "flush nftables") } r.networkListener = r.networkMonitor.RegisterCallback(func() { @@ -307,7 +308,7 @@ func (r *autoRedirect) setupNFTables() error { func (r *autoRedirect) nftablesUpdateLocalAddressSet() error { err := r.interfaceFinder.Update() if err != nil { - return err + return E.Cause(err, "update interfaces") } newLocalAddresses := common.FlatMap(r.interfaceFinder.Interfaces(), func(it control.Interface) []netip.Prefix { return common.Filter(it.Addresses, func(prefix netip.Prefix) bool { @@ -324,16 +325,16 @@ func (r *autoRedirect) nftablesUpdateLocalAddressSet() error { } nft, err := nftables.New() if err != nil { - return err + return E.Cause(err, "create nftables connection") } defer nft.CloseLasting() table, err := nft.ListTableOfFamily(r.tableName, nftables.TableFamilyINet) if err != nil { - return err + return E.Cause(err, "list nftables table") } err = r.nftablesCreateLocalAddressSets(nft, table, newLocalAddresses, r.localAddresses) if err != nil { - return err + return E.Cause(err, "create local address sets") } r.localAddresses = newLocalAddresses return nft.Flush() @@ -342,16 +343,16 @@ func (r *autoRedirect) nftablesUpdateLocalAddressSet() error { func (r *autoRedirect) nftablesUpdateRouteAddressSet() error { nft, err := nftables.New() if err != nil { - return err + return E.Cause(err, "create nftables connection") } defer nft.CloseLasting() table, err := nft.ListTableOfFamily(r.tableName, nftables.TableFamilyINet) if err != nil { - return err + return E.Cause(err, "list nftables table") } err = r.nftablesCreateAddressSets(nft, table, true) if err != nil { - return err + return E.Cause(err, "create address sets") } return nft.Flush() } diff --git a/redirect_nftables_rules.go b/redirect_nftables_rules.go index 968a27d..9f950a3 100644 --- a/redirect_nftables_rules.go +++ b/redirect_nftables_rules.go @@ -13,6 +13,8 @@ import ( "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/ranges" + E "github.com/sagernet/sing/common/exceptions" + "golang.org/x/exp/slices" "golang.org/x/sys/unix" ) @@ -38,13 +40,13 @@ func (r *autoRedirect) nftablesCreateAddressSets( if r.enableIPv4 { _, err := nftablesCreateIPSet(nft, table, 1, "inet4_route_address_set", nftables.TableFamilyIPv4, routeAddressSet, nil, true, update) if err != nil { - return err + return E.Cause(err, "create ipv4 route address set") } } if r.enableIPv6 { _, err := nftablesCreateIPSet(nft, table, 2, "inet6_route_address_set", nftables.TableFamilyIPv6, routeAddressSet, nil, true, update) if err != nil { - return err + return E.Cause(err, "create ipv6 route address set") } } } @@ -53,13 +55,13 @@ func (r *autoRedirect) nftablesCreateAddressSets( if r.enableIPv4 { _, err := nftablesCreateIPSet(nft, table, 3, "inet4_route_exclude_address_set", nftables.TableFamilyIPv4, routeExcludeAddressSet, nil, false, update) if err != nil { - return err + return E.Cause(err, "create ipv4 route exclude address set") } } if r.enableIPv6 { _, err := nftablesCreateIPSet(nft, table, 4, "inet6_route_exclude_address_set", nftables.TableFamilyIPv6, routeExcludeAddressSet, nil, false, update) if err != nil { - return err + return E.Cause(err, "create ipv6 route exclude address set") } } } @@ -85,7 +87,7 @@ func (r *autoRedirect) nftablesCreateLocalAddressSets( if len(lastAddresses) == 0 || update { _, err := nftablesCreateIPSet(nft, table, 5, "inet4_local_address_set", nftables.TableFamilyIPv4, nil, localAddresses4, false, update) if err != nil { - return err + return E.Cause(err, "create ipv4 local address set") } } } @@ -104,7 +106,7 @@ func (r *autoRedirect) nftablesCreateLocalAddressSets( if len(lastAddresses) == 0 || update { _, err := nftablesCreateIPSet(nft, table, 6, "inet6_local_address_set", nftables.TableFamilyIPv6, nil, localAddresses6, false, update) if err != nil { - return err + return E.Cause(err, "create ipv6 local address set") } } } @@ -117,13 +119,13 @@ func (r *autoRedirect) nftablesCreateLoopbackAddressSets( if r.enableIPv4 && len(r.tunOptions.Inet4LoopbackAddress) > 0 { _, err := nftablesCreateIPConst(nft, table, 7, "inet4_local_redirect_address_set", nftables.TableFamilyIPv4, r.tunOptions.Inet4LoopbackAddress) if err != nil { - return err + return E.Cause(err, "create ipv4 loopback address set") } } if r.enableIPv6 && len(r.tunOptions.Inet6LoopbackAddress) > 0 { _, err := nftablesCreateIPConst(nft, table, 8, "inet6_local_redirect_address_set", nftables.TableFamilyIPv6, r.tunOptions.Inet6LoopbackAddress) if err != nil { - return err + return E.Cause(err, "create ipv6 loopback address set") } } return nil @@ -144,7 +146,7 @@ func (r *autoRedirect) nftablesCreateExcludeRules(nft *nftables.Conn, table *nft {Key: []byte{unix.IPPROTO_ICMPV6}}, }) if err != nil { - return err + return E.Cause(err, "add ip protocol set") } nft.AddRule(&nftables.Rule{ Table: table, @@ -283,7 +285,7 @@ func (r *autoRedirect) nftablesCreateExcludeRules(nft *nftables.Conn, table *nft } })) if err != nil { - return err + return E.Cause(err, "add include interface set") } nft.AddRule(&nftables.Rule{ Table: table, @@ -336,7 +338,7 @@ func (r *autoRedirect) nftablesCreateExcludeRules(nft *nftables.Conn, table *nft } })) if err != nil { - return err + return E.Cause(err, "add exclude interface set") } nft.AddRule(&nftables.Rule{ Table: table, @@ -395,7 +397,7 @@ func (r *autoRedirect) nftablesCreateExcludeRules(nft *nftables.Conn, table *nft } })) if err != nil { - return err + return E.Cause(err, "add include uid set") } nft.AddRule(&nftables.Rule{ Table: table, @@ -456,7 +458,7 @@ func (r *autoRedirect) nftablesCreateExcludeRules(nft *nftables.Conn, table *nft } })) if err != nil { - return err + return E.Cause(err, "add exclude uid set") } nft.AddRule(&nftables.Rule{ Table: table, @@ -499,7 +501,7 @@ func (r *autoRedirect) nftablesCreateExcludeRules(nft *nftables.Conn, table *nft if len(r.tunOptions.Inet4RouteAddress) > 0 { inet4RouteAddress, err := nftablesCreateIPSet(nft, table, 0, "", nftables.TableFamilyIPv4, nil, r.tunOptions.Inet4RouteAddress, false, false) if err != nil { - return err + return E.Cause(err, "create ipv4 route address set") } nftablesCreateExcludeDestinationIPSet(nft, table, chain, inet4RouteAddress.ID, inet4RouteAddress.Name, nftables.TableFamilyIPv4, true) } @@ -507,7 +509,7 @@ func (r *autoRedirect) nftablesCreateExcludeRules(nft *nftables.Conn, table *nft if len(r.tunOptions.Inet6RouteAddress) > 0 { inet6RouteAddress, err := nftablesCreateIPSet(nft, table, 0, "", nftables.TableFamilyIPv6, nil, r.tunOptions.Inet6RouteAddress, false, false) if err != nil { - return err + return E.Cause(err, "create ipv6 route address set") } nftablesCreateExcludeDestinationIPSet(nft, table, chain, inet6RouteAddress.ID, inet6RouteAddress.Name, nftables.TableFamilyIPv6, true) } @@ -515,7 +517,7 @@ func (r *autoRedirect) nftablesCreateExcludeRules(nft *nftables.Conn, table *nft if len(r.tunOptions.Inet4RouteExcludeAddress) > 0 { inet4RouteExcludeAddress, err := nftablesCreateIPSet(nft, table, 0, "", nftables.TableFamilyIPv4, nil, r.tunOptions.Inet4RouteExcludeAddress, false, false) if err != nil { - return err + return E.Cause(err, "create ipv4 route exclude address set") } nftablesCreateExcludeDestinationIPSet(nft, table, chain, inet4RouteExcludeAddress.ID, inet4RouteExcludeAddress.Name, nftables.TableFamilyIPv4, false) } @@ -523,7 +525,7 @@ func (r *autoRedirect) nftablesCreateExcludeRules(nft *nftables.Conn, table *nft if len(r.tunOptions.Inet6RouteExcludeAddress) > 0 { inet6RouteExcludeAddress, err := nftablesCreateIPSet(nft, table, 0, "", nftables.TableFamilyIPv6, nil, r.tunOptions.Inet6RouteExcludeAddress, false, false) if err != nil { - return err + return E.Cause(err, "create ipv6 route exclude address set") } nftablesCreateExcludeDestinationIPSet(nft, table, chain, inet6RouteExcludeAddress.ID, inet6RouteExcludeAddress.Name, nftables.TableFamilyIPv6, false) } @@ -533,13 +535,13 @@ func (r *autoRedirect) nftablesCreateExcludeRules(nft *nftables.Conn, table *nft if r.enableIPv4 { err := r.nftablesCreateDNSHijackRulesForFamily(nft, table, chain, nftables.TableFamilyIPv4, 5, "inet4_local_address_set") if err != nil { - return err + return E.Cause(err, "create ipv4 dns hijack rules") } } if r.enableIPv6 { err := r.nftablesCreateDNSHijackRulesForFamily(nft, table, chain, nftables.TableFamilyIPv6, 6, "inet6_local_address_set") if err != nil { - return err + return E.Cause(err, "create ipv6 dns hijack rules") } } } @@ -848,7 +850,7 @@ func (r *autoRedirect) nftablesCreateDNSHijackRulesForFamily( {Key: []byte{unix.IPPROTO_UDP}}, }) if err != nil { - return err + return E.Cause(err, "add dns protocol set") } dnsServer := common.Find(r.tunOptions.DNSServers, func(it netip.Addr) bool { return it.Is4() == (family == nftables.TableFamilyIPv4) diff --git a/redirect_route_linux.go b/redirect_route_linux.go index 6b86da1..db79cac 100644 --- a/redirect_route_linux.go +++ b/redirect_route_linux.go @@ -8,6 +8,7 @@ import ( "net/netip" "github.com/sagernet/netlink" + E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing/common" "github.com/sagernet/sing/common/control" @@ -31,7 +32,7 @@ func (r *autoRedirect) setupRedirectRoutes() error { } err := r.interfaceFinder.Update() if err != nil { - return err + return E.Cause(err, "update interfaces") } tunName := r.tunOptions.Name r.redirectInterfaces = common.Filter(r.interfaceFinder.Interfaces(), func(it control.Interface) bool { @@ -41,7 +42,7 @@ func (r *autoRedirect) setupRedirectRoutes() error { for _, iface := range r.redirectInterfaces { err = r.addRedirectRoutes(iface) if err != nil { - return err + return E.Cause(err, "add redirect routes for ", iface.Name) } } if r.enableIPv4 { @@ -51,7 +52,7 @@ func (r *autoRedirect) setupRedirectRoutes() error { rule.Family = unix.AF_INET err = netlink.RuleAdd(rule) if err != nil { - return err + return E.Cause(err, "add ipv4 redirect rule") } } if r.enableIPv6 { @@ -61,7 +62,7 @@ func (r *autoRedirect) setupRedirectRoutes() error { rule.Family = unix.AF_INET6 err = netlink.RuleAdd(rule) if err != nil { - return err + return E.Cause(err, "add ipv6 redirect rule") } } return nil @@ -79,7 +80,7 @@ func (r *autoRedirect) addRedirectRoutes(iface control.Interface) error { Scope: netlink.SCOPE_HOST, }) if err != nil { - return err + return E.Cause(err, "append ipv4 loopback route") } } if r.enableIPv6 && common.Any(iface.Addresses, func(it netip.Prefix) bool { @@ -93,7 +94,7 @@ func (r *autoRedirect) addRedirectRoutes(iface control.Interface) error { Scope: netlink.SCOPE_HOST, }) if err != nil { - return err + return E.Cause(err, "append ipv6 loopback route") } } return nil @@ -121,7 +122,7 @@ func (r *autoRedirect) removeRedirectRoutes(linkIndex int) { func (r *autoRedirect) updateRedirectRoutes() error { err := r.interfaceFinder.Update() if err != nil { - return err + return E.Cause(err, "update interfaces") } tunName := r.tunOptions.Name newInterfaces := common.Filter(r.interfaceFinder.Interfaces(), func(it control.Interface) bool { @@ -139,7 +140,7 @@ func (r *autoRedirect) updateRedirectRoutes() error { if !oldMap[iface.Index] { err = r.addRedirectRoutes(iface) if err != nil { - return err + return E.Cause(err, "add redirect routes for ", iface.Name) } } } diff --git a/tun_linux.go b/tun_linux.go index 5d7b9c6..20fdce2 100644 --- a/tun_linux.go +++ b/tun_linux.go @@ -53,7 +53,7 @@ func New(options Options) (Tun, error) { if options.FileDescriptor == 0 { tunFd, err := open(options.Name, options.GSO) if err != nil { - return nil, err + return nil, E.Cause(err, "open tun") } tunLink, err := netlink.LinkByName(options.Name) if err != nil { @@ -93,12 +93,12 @@ func init() { func open(name string, vnetHdr bool) (int, error) { fd, err := unix.Open(controlPath, unix.O_RDWR, 0) if err != nil { - return -1, err + return -1, E.Cause(err, "open ", controlPath) } ifr, err := unix.NewIfreq(name) if err != nil { unix.Close(fd) - return 0, err + return 0, E.Cause(err, "create ifreq") } flags := unix.IFF_TUN | unix.IFF_NO_PI if vnetHdr { @@ -108,12 +108,12 @@ func open(name string, vnetHdr bool) (int, error) { err = unix.IoctlIfreq(fd, unix.TUNSETIFF, ifr) if err != nil { unix.Close(fd) - return 0, err + return 0, E.Cause(err, "TUNSETIFF") } err = unix.SetNonblock(fd, true) if err != nil { unix.Close(fd) - return 0, err + return 0, E.Cause(err, "set nonblock") } return fd, nil } @@ -123,7 +123,7 @@ func (t *NativeTun) configure(tunLink netlink.Link) error { if errors.Is(err, unix.EPERM) { return nil } else if err != nil { - return err + return E.Cause(err, "set mtu") } if !t.options.EXP_ExternalConfiguration { if len(t.options.Inet4Address) > 0 { @@ -131,7 +131,7 @@ func (t *NativeTun) configure(tunLink netlink.Link) error { addr4, _ := netlink.ParseAddr(address.String()) err = netlink.AddrAdd(tunLink, addr4) if err != nil && !errors.Is(err, unix.EEXIST) { - return err + return E.Cause(err, "add address ", address) } } } @@ -140,7 +140,7 @@ func (t *NativeTun) configure(tunLink netlink.Link) error { addr6, _ := netlink.ParseAddr(address.String()) err = netlink.AddrAdd(tunLink, addr6) if err != nil && !errors.Is(err, unix.EEXIST) { - return err + return E.Cause(err, "add address ", address) } } } @@ -165,12 +165,12 @@ func (t *NativeTun) configure(tunLink netlink.Link) error { var txChecksumOffload bool txChecksumOffload, err = checkChecksumOffload(t.options.Name, unix.ETHTOOL_GTXCSUM) if err != nil { - return err + return E.Cause(err, "check tx checksum offload") } if !txChecksumOffload { err = setChecksumOffload(t.options.Name, unix.ETHTOOL_STXCSUM) if err != nil { - return err + return E.Cause(err, "set tx checksum offload") } } t.txChecksumOffload = true @@ -239,7 +239,10 @@ func (t *NativeTun) probeTCPGRO() error { tcpH.SetChecksum(^tcpH.CalculateChecksum(pseudoCsum)) } _, err := t.BatchWrite(bufs, virtioNetHdrLen) - return err + if err != nil { + return E.Cause(err, "batch write") + } + return nil } func (t *NativeTun) Name() (string, error) { @@ -265,12 +268,12 @@ func (t *NativeTun) Start() error { } tunLink, err := netlink.LinkByName(t.options.Name) if err != nil { - return err + return E.Cause(err, "find tun interface") } err = netlink.LinkSetUp(tunLink) if err != nil { - return err + return E.Cause(err, "set tun up") } if t.vnetHdr && len(t.options.Inet4Address) > 0 { @@ -301,7 +304,7 @@ func (t *NativeTun) Start() error { err = t.setRoute(tunLink) if err != nil { _ = t.unsetRoute0(tunLink) - return err + return E.Cause(err, "set routes") } err = t.unsetRules() @@ -311,7 +314,7 @@ func (t *NativeTun) Start() error { err = t.setRules() if err != nil { _ = t.unsetRules() - return err + return E.Cause(err, "set rules") } t.setSearchDomainForSystemdResolved() @@ -498,11 +501,11 @@ func (t *NativeTun) UpdateRouteOptions(tunOptions Options) error { } tunLink, err := netlink.LinkByName(t.options.Name) if err != nil { - return err + return E.Cause(err, "find tun interface") } err = t.unsetRoute0(tunLink) if err != nil { - return err + return E.Cause(err, "unset old routes") } t.options = tunOptions return t.setRoute(tunLink) @@ -511,7 +514,7 @@ func (t *NativeTun) UpdateRouteOptions(tunOptions Options) error { func (t *NativeTun) routes(tunLink netlink.Link) ([]netlink.Route, error) { routeRanges, err := t.options.BuildAutoRouteRanges(false) if err != nil { - return nil, err + return nil, E.Cause(err, "build auto route ranges") } // Do not create gateway on linux by default gateway4, gateway6 := t.options.Inet4GatewayAddr(), t.options.Inet6GatewayAddr() @@ -956,7 +959,7 @@ func (t *NativeTun) rules() []*netlink.Rule { func (t *NativeTun) setRoute(tunLink netlink.Link) error { routes, err := t.routes(tunLink) if err != nil { - return err + return E.Cause(err, "build routes") } for i, route := range routes { err := netlink.RouteAdd(&route) @@ -983,7 +986,7 @@ func (t *NativeTun) unsetRoute() error { } tunLink, err := netlink.LinkByName(t.options.Name) if err != nil { - return err + return E.Cause(err, "find tun interface") } return t.unsetRoute0(tunLink) } @@ -1016,7 +1019,7 @@ func (t *NativeTun) unsetRules() error { if t.options.AutoRoute { ruleList, err := netlink.RuleList(netlink.FAMILY_ALL) if err != nil { - return err + return E.Cause(err, "list rules") } for _, rule := range ruleList { ruleStart := t.options.IPRoute2RuleIndex