80 lines
1.4 KiB
Go
80 lines
1.4 KiB
Go
|
package common
|
||
|
|
||
|
import (
|
||
|
C "github.com/Dreamacro/clash/constant"
|
||
|
"net/netip"
|
||
|
)
|
||
|
|
||
|
type IPSuffix struct {
|
||
|
*Base
|
||
|
ipBytes []byte
|
||
|
bits int
|
||
|
payload string
|
||
|
adapter string
|
||
|
isSourceIP bool
|
||
|
noResolveIP bool
|
||
|
}
|
||
|
|
||
|
func (is *IPSuffix) RuleType() C.RuleType {
|
||
|
if is.isSourceIP {
|
||
|
return C.SrcIPSuffix
|
||
|
}
|
||
|
return C.IPSuffix
|
||
|
}
|
||
|
|
||
|
func (is *IPSuffix) Match(metadata *C.Metadata) bool {
|
||
|
ip := metadata.DstIP
|
||
|
if is.isSourceIP {
|
||
|
ip = metadata.SrcIP
|
||
|
}
|
||
|
|
||
|
mIPBytes := ip.AsSlice()
|
||
|
if len(is.ipBytes) != len(mIPBytes) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
size := len(mIPBytes)
|
||
|
bits := is.bits
|
||
|
|
||
|
for i := bits / 8; i > 0; i-- {
|
||
|
if is.ipBytes[size-i] != mIPBytes[size-i] {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (is.ipBytes[size-bits/8-1] << (8 - bits%8)) != (mIPBytes[size-bits/8-1] << (8 - bits%8)) {
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
return true
|
||
|
}
|
||
|
|
||
|
func (is *IPSuffix) Adapter() string {
|
||
|
return is.adapter
|
||
|
}
|
||
|
|
||
|
func (is *IPSuffix) Payload() string {
|
||
|
return is.payload
|
||
|
}
|
||
|
|
||
|
func (is *IPSuffix) ShouldResolveIP() bool {
|
||
|
return !is.noResolveIP
|
||
|
}
|
||
|
|
||
|
func NewIPSuffix(payload, adapter string, isSrc, noResolveIP bool) (*IPSuffix, error) {
|
||
|
ipnet, err := netip.ParsePrefix(payload)
|
||
|
if err != nil {
|
||
|
return nil, errPayload
|
||
|
}
|
||
|
|
||
|
return &IPSuffix{
|
||
|
Base: &Base{},
|
||
|
payload: payload,
|
||
|
ipBytes: ipnet.Addr().AsSlice(),
|
||
|
bits: ipnet.Bits(),
|
||
|
adapter: adapter,
|
||
|
isSourceIP: isSrc,
|
||
|
noResolveIP: noResolveIP,
|
||
|
}, nil
|
||
|
}
|