mirror of
https://github.com/SagerNet/sing-tun.git
synced 2026-04-22 16:07:19 +08:00
Improve error messages for Linux TUN and redirect operations
This commit is contained in:
+3
-3
@@ -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)
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
+9
-2
@@ -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 {
|
||||
|
||||
+25
-24
@@ -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()
|
||||
}
|
||||
|
||||
+22
-20
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+24
-21
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user