Skip to content

Commit

Permalink
fix: secrule support ipv6
Browse files Browse the repository at this point in the history
  • Loading branch information
Qiu Jian committed Jan 24, 2024
1 parent 0486a12 commit 21d0e17
Show file tree
Hide file tree
Showing 11 changed files with 1,297 additions and 187 deletions.
204 changes: 200 additions & 4 deletions util/netutils/ipv6.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ import (
"fmt"
"math/rand"
"net"
"sort"
"strconv"
"strings"

"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/sortutils"
)

type IPV6Addr [8]uint16
Expand Down Expand Up @@ -461,21 +463,21 @@ func (ar IPV6AddrRange) EndIp() IPV6Addr {
return ar.end
}

func (ar IPV6AddrRange) Merge(ar2 IPV6AddrRange) (*IPV6AddrRange, bool) {
func (ar IPV6AddrRange) Merge(ar2 IPV6AddrRange) (IPV6AddrRange, bool) {
if ar.IsOverlap(ar2) || ar.end.StepUp().Equals(ar2.start) || ar2.end.StepUp().Equals(ar.start) {
if ar2.start.Lt(ar.start) {
ar.start = ar2.start
}
if ar2.end.Gt(ar.end) {
ar.end = ar2.end
}
return &ar, true
return ar, true
}
return nil, false
return ar, false
}

func (ar IPV6AddrRange) IsOverlap(ar2 IPV6AddrRange) bool {
if ar.start.Ge(ar2.end) || ar.end.Le(ar2.start) {
if ar.start.Gt(ar2.end) || ar.end.Lt(ar2.start) {
return false
} else {
return true
Expand Down Expand Up @@ -544,6 +546,15 @@ func NewIPV6Prefix(prefix string) (IPV6Prefix, error) {
return pref, nil
}

func NewIPV6PrefixFromAddr(addr IPV6Addr, masklen uint8) IPV6Prefix {
pref := IPV6Prefix{
Address: addr.NetAddr(masklen),
MaskLen: masklen,
}
pref.ipRange = pref.ToIPRange()
return pref
}

func (prefix IPV6Prefix) ToIPRange() IPV6AddrRange {
start := prefix.Address.NetAddr(prefix.MaskLen)
end := prefix.Address.BroadcastAddr(prefix.MaskLen)
Expand Down Expand Up @@ -581,3 +592,188 @@ func DeriveIPv6AddrFromIPv4AddrMac(ipAddr string, macAddr string, startIp6, endI
}
return ""
}

func (ar IPV6AddrRange) Substract(ar2 IPV6AddrRange) ([]IPV6AddrRange, *IPV6AddrRange) {
lefts, overlap, sub := ar.Substract2(ar2)
var subp *IPV6AddrRange
if overlap {
subp = &sub
}
return lefts, subp
}

func (ar IPV6AddrRange) Substract2(ar2 IPV6AddrRange) ([]IPV6AddrRange, bool, IPV6AddrRange) {
lefts := []IPV6AddrRange{}
// no intersection, no substract
if ar.end.Lt(ar2.start) || ar.start.Gt(ar2.end) {
lefts = append(lefts, ar)
return lefts, false, IPV6AddrRange{}
}

// ar contains ar2
if ar.ContainsRange(ar2) {
if ar.start.Equals(ar2.start) && ar.end.Equals(ar2.end) {
// lefts empty
} else if ar.start.Lt(ar2.start) && ar.end.Equals(ar2.end) {
lefts = append(lefts,
NewIPV6AddrRange(ar.start, ar2.start.StepDown()),
)
} else if ar.start.Equals(ar2.start) && ar.end.Gt(ar2.end) {
lefts = append(lefts,
NewIPV6AddrRange(ar2.end.StepUp(), ar.end),
)
} else {
lefts = append(lefts,
NewIPV6AddrRange(ar.start, ar2.start.StepDown()),
NewIPV6AddrRange(ar2.end.StepUp(), ar.end),
)
}
return lefts, true, ar2
}

// ar contained by ar2
if ar2.ContainsRange(ar) {
return lefts, true, ar
}

// intersect, ar on the left
if ar.start.Lt(ar2.start) && ar.end.Ge(ar2.start) {
lefts = append(lefts, NewIPV6AddrRange(ar.start, ar2.start.StepDown()))
sub_ := NewIPV6AddrRange(ar2.start, ar.end)
return lefts, true, sub_
}

// intersect, ar on the right
if ar.start.Le(ar2.end) && ar.end.Gt(ar2.end) {
lefts = append(lefts, NewIPV6AddrRange(ar2.end.StepUp(), ar.end))
sub_ := NewIPV6AddrRange(ar.start, ar2.end)
return lefts, true, sub_
}

// no intersection
return lefts, false, IPV6AddrRange{}
}

func (addr IPV6Addr) ToBytes() []byte {
ret := make([]byte, 16)
for i := 0; i < len(addr); i++ {
binary.BigEndian.PutUint16(ret[2*i:], addr[i])
}
return ret
}

func (addr IPV6Addr) ToIP() net.IP {
return net.IP(addr.ToBytes())
}

func (pref IPV6Prefix) ToIPNet() *net.IPNet {
return &net.IPNet{
IP: pref.Address.ToIP(),
Mask: net.CIDRMask(int(pref.MaskLen), 128),
}
}

func (ar IPV6AddrRange) ToIPNets() []*net.IPNet {
r := []*net.IPNet{}
mms := ar.ToPrefixes()
for _, mm := range mms {
r = append(r, mm.ToIPNet())
}
return r
}

func (ar IPV6AddrRange) ToPrefixes() []IPV6Prefix {
prefixes := make([]IPV6Prefix, 0)
sp := ar.StartIp()
ep := ar.EndIp()
for sp.Le(ep) {
masklen := uint8(128)
for sp.NetAddr(masklen-1).Equals(sp) && sp.BroadcastAddr(masklen-1).Le(ep) && masklen > 0 {
masklen--
}
if masklen == 0 {
prefixes = append(prefixes, NewIPV6PrefixFromAddr(sp, 0))
break
}
prefixes = append(prefixes, NewIPV6PrefixFromAddr(sp, masklen))
sp = sp.BroadcastAddr(masklen).StepUp()
}
return prefixes
}

type IPV6AddrRangeList []IPV6AddrRange

func (rl IPV6AddrRangeList) Len() int {
return len(rl)
}

func (rl IPV6AddrRangeList) Swap(i, j int) {
rl[i], rl[j] = rl[j], rl[i]
}

func (rl IPV6AddrRangeList) Less(i, j int) bool {
return rl[i].Compare(rl[j]) == sortutils.Less
}

func (v6range IPV6AddrRange) Compare(r2 IPV6AddrRange) sortutils.CompareResult {
if v6range.start.Lt(r2.start) {
return sortutils.Less
} else if v6range.start.Gt(r2.start) {
return sortutils.More
} else {
// start equals, compare ends
if v6range.end.Gt(r2.end) {
return sortutils.Less
} else if v6range.end.Lt(r2.end) {
return sortutils.More
} else {
return sortutils.Equal
}
}
}

func (rl IPV6AddrRangeList) Merge() []IPV6AddrRange {
sort.Sort(rl)
ret := make([]IPV6AddrRange, 0, len(rl))
for i := range rl {
if i == 0 {
ret = append(ret, rl[i])
} else {
result, isMerged := ret[len(ret)-1].Merge(rl[i])
if isMerged {
ret[len(ret)-1] = result
} else {
ret = append(ret, rl[i])
}
}
}
return ret
}

func (rl IPV6AddrRangeList) String() string {
ret := make([]string, len(rl))
for i := range rl {
ret[i] = rl[i].String()
}
return strings.Join(ret, ",")
}

var IPV6Zero = IPV6Addr([8]uint16{0, 0, 0, 0, 0, 0, 0, 0})
var IPV6Ones = IPV6Addr([8]uint16{0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff})
var AllIPV6AddrRange = IPV6AddrRange{
start: IPV6Zero,
end: IPV6Ones,
}

func (r IPV6AddrRange) IsAll() bool {
return r.start.Equals(IPV6Zero) && r.end.Equals(IPV6Ones)
}

func (rl IPV6AddrRangeList) Substract(addrRange IPV6AddrRange) []IPV6AddrRange {
ret := make([]IPV6AddrRange, 0)
for i := range rl {
lefts, _ := rl[i].Substract(addrRange)
ret = append(ret, lefts...)
}
return ret
}
Loading

0 comments on commit 21d0e17

Please # to comment.