diff --git a/adapter/inbound/util.go b/adapter/inbound/util.go index 3bcd2808..d67a96db 100644 --- a/adapter/inbound/util.go +++ b/adapter/inbound/util.go @@ -7,7 +7,6 @@ import ( "strconv" "strings" - "github.com/metacubex/mihomo/common/nnip" C "github.com/metacubex/mihomo/constant" "github.com/metacubex/mihomo/transport/socks5" ) @@ -21,13 +20,13 @@ func parseSocksAddr(target socks5.Addr) *C.Metadata { metadata.Host = strings.TrimRight(string(target[2:2+target[1]]), ".") metadata.DstPort = uint16((int(target[2+target[1]]) << 8) | int(target[2+target[1]+1])) case socks5.AtypIPv4: - metadata.DstIP = nnip.IpToAddr(net.IP(target[1 : 1+net.IPv4len])) + metadata.DstIP, _ = netip.AddrFromSlice(target[1 : 1+net.IPv4len]) metadata.DstPort = uint16((int(target[1+net.IPv4len]) << 8) | int(target[1+net.IPv4len+1])) case socks5.AtypIPv6: - ip6, _ := netip.AddrFromSlice(target[1 : 1+net.IPv6len]) - metadata.DstIP = ip6.Unmap() + metadata.DstIP, _ = netip.AddrFromSlice(target[1 : 1+net.IPv6len]) metadata.DstPort = uint16((int(target[1+net.IPv6len]) << 8) | int(target[1+net.IPv6len+1])) } + metadata.DstIP = metadata.DstIP.Unmap() return metadata } diff --git a/common/nnip/netip.go b/common/nnip/netip.go deleted file mode 100644 index b987bb45..00000000 --- a/common/nnip/netip.go +++ /dev/null @@ -1,73 +0,0 @@ -package nnip - -import ( - "encoding/binary" - "net" - "net/netip" -) - -// IpToAddr converts the net.IP to netip.Addr. -// If slice's length is not 4 or 16, IpToAddr returns netip.Addr{} -func IpToAddr(slice net.IP) netip.Addr { - ip := slice - if len(ip) != 4 { - if ip = slice.To4(); ip == nil { - ip = slice - } - } - - if addr, ok := netip.AddrFromSlice(ip); ok { - return addr - } - return netip.Addr{} -} - -// UnMasked returns p's last IP address. -// If p is invalid, UnMasked returns netip.Addr{} -func UnMasked(p netip.Prefix) netip.Addr { - if !p.IsValid() { - return netip.Addr{} - } - - buf := p.Addr().As16() - - hi := binary.BigEndian.Uint64(buf[:8]) - lo := binary.BigEndian.Uint64(buf[8:]) - - bits := p.Bits() - if bits <= 32 { - bits += 96 - } - - hi = hi | ^uint64(0)>>bits - lo = lo | ^(^uint64(0) << (128 - bits)) - - binary.BigEndian.PutUint64(buf[:8], hi) - binary.BigEndian.PutUint64(buf[8:], lo) - - addr := netip.AddrFrom16(buf) - if p.Addr().Is4() { - return addr.Unmap() - } - return addr -} - -// PrefixCompare returns an integer comparing two prefixes. -// The result will be 0 if p == p2, -1 if p < p2, and +1 if p > p2. -// modify from https://github.com/golang/go/issues/61642#issuecomment-1848587909 -func PrefixCompare(p, p2 netip.Prefix) int { - // compare by validity, address family and prefix base address - if c := p.Masked().Addr().Compare(p2.Masked().Addr()); c != 0 { - return c - } - // compare by prefix length - f1, f2 := p.Bits(), p2.Bits() - if f1 < f2 { - return -1 - } - if f1 > f2 { - return 1 - } - // compare by prefix address - return p.Addr().Compare(p2.Addr()) -} diff --git a/component/dhcp/dhcp.go b/component/dhcp/dhcp.go index 04ad2eda..50f91c39 100644 --- a/component/dhcp/dhcp.go +++ b/component/dhcp/dhcp.go @@ -6,7 +6,6 @@ import ( "net" "net/netip" - "github.com/metacubex/mihomo/common/nnip" "github.com/metacubex/mihomo/component/iface" "github.com/insomniacslk/dhcp/dhcpv4" @@ -86,12 +85,14 @@ func receiveOffer(conn net.PacketConn, id dhcpv4.TransactionID, result chan<- [] return } - dnsAddr := make([]netip.Addr, l) - for i := 0; i < l; i++ { - dnsAddr[i] = nnip.IpToAddr(dns[i]) + results := make([]netip.Addr, 0, len(dns)) + for _, ip := range dns { + if addr, ok := netip.AddrFromSlice(ip); ok { + results = append(results, addr.Unmap()) + } } - result <- dnsAddr + result <- results return } diff --git a/component/fakeip/pool.go b/component/fakeip/pool.go index 41b848b3..895fb658 100644 --- a/component/fakeip/pool.go +++ b/component/fakeip/pool.go @@ -6,9 +6,10 @@ import ( "strings" "sync" - "github.com/metacubex/mihomo/common/nnip" "github.com/metacubex/mihomo/component/profile/cachefile" C "github.com/metacubex/mihomo/constant" + + "go4.org/netipx" ) const ( @@ -183,7 +184,7 @@ func New(options Options) (*Pool, error) { hostAddr = options.IPNet.Masked().Addr() gateway = hostAddr.Next() first = gateway.Next().Next().Next() // default start with 198.18.0.4 - last = nnip.UnMasked(options.IPNet) + last = netipx.PrefixLastIP(options.IPNet) ) if !options.IPNet.IsValid() || !first.IsValid() || !first.Less(last) { diff --git a/component/process/process_darwin.go b/component/process/process_darwin.go index c02771ed..93cb90ae 100644 --- a/component/process/process_darwin.go +++ b/component/process/process_darwin.go @@ -87,6 +87,7 @@ func findProcessName(network string, ip netip.Addr, port int) (uint32, string, e default: continue } + srcIP = srcIP.Unmap() if ip == srcIP { // xsocket_n.so_last_pid diff --git a/component/process/process_freebsd_amd64.go b/component/process/process_freebsd_amd64.go index 1884afcc..cb43c5ff 100644 --- a/component/process/process_freebsd_amd64.go +++ b/component/process/process_freebsd_amd64.go @@ -10,7 +10,6 @@ import ( "syscall" "unsafe" - "github.com/metacubex/mihomo/common/nnip" "github.com/metacubex/mihomo/log" ) @@ -136,13 +135,14 @@ func (s *searcher) Search(buf []byte, ip netip.Addr, port uint16, isTCP bool) (u switch { case flag&0x1 > 0 && isIPv4: // ipv4 - srcIP = nnip.IpToAddr(buf[inp+s.ip : inp+s.ip+4]) + srcIP, _ = netip.AddrFromSlice(buf[inp+s.ip : inp+s.ip+4]) case flag&0x2 > 0 && !isIPv4: // ipv6 - srcIP = nnip.IpToAddr(buf[inp+s.ip-12 : inp+s.ip+4]) + srcIP, _ = netip.AddrFromSlice(buf[inp+s.ip-12 : inp+s.ip+4]) default: continue } + srcIP = srcIP.Unmap() if ip != srcIP { continue diff --git a/component/process/process_windows.go b/component/process/process_windows.go index 73ac0255..6ab0fef0 100644 --- a/component/process/process_windows.go +++ b/component/process/process_windows.go @@ -7,7 +7,6 @@ import ( "syscall" "unsafe" - "github.com/metacubex/mihomo/common/nnip" "github.com/metacubex/mihomo/log" "golang.org/x/sys/windows" @@ -137,7 +136,8 @@ func (s *searcher) Search(b []byte, ip netip.Addr, port uint16) (uint32, error) continue } - srcIP := nnip.IpToAddr(row[s.ip : s.ip+s.ipSize]) + srcIP, _ := netip.AddrFromSlice(row[s.ip : s.ip+s.ipSize]) + srcIP = srcIP.Unmap() // windows binds an unbound udp socket to 0.0.0.0/[::] while first sendto if ip != srcIP && (!srcIP.IsUnspecified() || s.tcpState != -1) { continue diff --git a/dns/middleware.go b/dns/middleware.go index b55adc6b..e6461e91 100644 --- a/dns/middleware.go +++ b/dns/middleware.go @@ -6,7 +6,6 @@ import ( "time" "github.com/metacubex/mihomo/common/lru" - "github.com/metacubex/mihomo/common/nnip" "github.com/metacubex/mihomo/component/fakeip" R "github.com/metacubex/mihomo/component/resolver" C "github.com/metacubex/mihomo/constant" @@ -120,14 +119,21 @@ func withMapping(mapping *lru.LruCache[netip.Addr, string]) middleware { switch a := ans.(type) { case *D.A: - ip = nnip.IpToAddr(a.A) + ip, _ = netip.AddrFromSlice(a.A) ttl = a.Hdr.Ttl case *D.AAAA: - ip = nnip.IpToAddr(a.AAAA) + ip, _ = netip.AddrFromSlice(a.AAAA) ttl = a.Hdr.Ttl default: continue } + if !ip.IsValid() { + continue + } + if !ip.IsGlobalUnicast() { + continue + } + ip = ip.Unmap() if ttl < 1 { ttl = 1 diff --git a/dns/util.go b/dns/util.go index 50459cc1..ee04d24e 100644 --- a/dns/util.go +++ b/dns/util.go @@ -10,7 +10,6 @@ import ( "strings" "time" - "github.com/metacubex/mihomo/common/nnip" "github.com/metacubex/mihomo/common/picker" "github.com/metacubex/mihomo/component/dialer" "github.com/metacubex/mihomo/component/resolver" @@ -150,19 +149,24 @@ func handleMsgWithEmptyAnswer(r *D.Msg) *D.Msg { return msg } -func msgToIP(msg *D.Msg) []netip.Addr { - ips := []netip.Addr{} - +func msgToIP(msg *D.Msg) (ips []netip.Addr) { for _, answer := range msg.Answer { + var ip netip.Addr switch ans := answer.(type) { case *D.AAAA: - ips = append(ips, nnip.IpToAddr(ans.AAAA)) + ip, _ = netip.AddrFromSlice(ans.AAAA) case *D.A: - ips = append(ips, nnip.IpToAddr(ans.A)) + ip, _ = netip.AddrFromSlice(ans.A) + default: + continue } + if !ip.IsValid() { + continue + } + ip = ip.Unmap() + ips = append(ips, ip) } - - return ips + return } func msgToDomain(msg *D.Msg) string { diff --git a/listener/config/tun.go b/listener/config/tun.go index 760741cc..4e12056d 100644 --- a/listener/config/tun.go +++ b/listener/config/tun.go @@ -3,9 +3,9 @@ package config import ( "net/netip" - "github.com/metacubex/mihomo/common/nnip" C "github.com/metacubex/mihomo/constant" + "go4.org/netipx" "golang.org/x/exp/slices" ) @@ -70,11 +70,11 @@ type Tun struct { func (t *Tun) Sort() { slices.Sort(t.DNSHijack) - slices.SortFunc(t.Inet4Address, nnip.PrefixCompare) - slices.SortFunc(t.Inet6Address, nnip.PrefixCompare) - slices.SortFunc(t.RouteAddress, nnip.PrefixCompare) + slices.SortFunc(t.Inet4Address, netipx.ComparePrefix) + slices.SortFunc(t.Inet6Address, netipx.ComparePrefix) + slices.SortFunc(t.RouteAddress, netipx.ComparePrefix) slices.Sort(t.RouteAddressSet) - slices.SortFunc(t.RouteExcludeAddress, nnip.PrefixCompare) + slices.SortFunc(t.RouteExcludeAddress, netipx.ComparePrefix) slices.Sort(t.RouteExcludeAddressSet) slices.Sort(t.IncludeInterface) slices.Sort(t.ExcludeInterface) @@ -86,10 +86,10 @@ func (t *Tun) Sort() { slices.Sort(t.IncludePackage) slices.Sort(t.ExcludePackage) - slices.SortFunc(t.Inet4RouteAddress, nnip.PrefixCompare) - slices.SortFunc(t.Inet6RouteAddress, nnip.PrefixCompare) - slices.SortFunc(t.Inet4RouteExcludeAddress, nnip.PrefixCompare) - slices.SortFunc(t.Inet6RouteExcludeAddress, nnip.PrefixCompare) + slices.SortFunc(t.Inet4RouteAddress, netipx.ComparePrefix) + slices.SortFunc(t.Inet6RouteAddress, netipx.ComparePrefix) + slices.SortFunc(t.Inet4RouteExcludeAddress, netipx.ComparePrefix) + slices.SortFunc(t.Inet6RouteExcludeAddress, netipx.ComparePrefix) } func (t *Tun) Equal(other Tun) bool {