github.com/DataDog/datadog-agent/pkg/security/secl@v0.55.0-devel.0.20240517055856-10c4965fea94/compiler/eval/cidr.go (about) 1 // Unless explicitly stated otherwise all files in this repository are licensed 2 // under the Apache License Version 2.0. 3 // This product includes software developed at Datadog (https://www.datadoghq.com/). 4 // Copyright 2016-present Datadog, Inc. 5 6 // Package eval holds eval related files 7 package eval 8 9 import ( 10 "errors" 11 "net" 12 "strings" 13 ) 14 15 var ( 16 // IPV4Mask32 ipv4 ip address 17 IPV4Mask32 = net.CIDRMask(32, 8*net.IPv4len) 18 // IPV6Mask128 ipv6 ip address 19 IPV6Mask128 = net.CIDRMask(128, 8*net.IPv6len) 20 ) 21 22 // IPNetFromIP returns a IPNET version of the IP 23 func IPNetFromIP(ip net.IP) *net.IPNet { 24 var mask = IPV4Mask32 25 if len(ip) == net.IPv6len { 26 mask = IPV6Mask128 27 } 28 29 return &net.IPNet{ 30 IP: ip, 31 Mask: mask, 32 } 33 } 34 35 // CIDRValues describes a set of CIDRs 36 type CIDRValues struct { 37 ipnets []*net.IPNet 38 39 // caches 40 fieldValues []FieldValue 41 42 exists map[string]bool 43 } 44 45 // AppendCIDR append a CIDR notation 46 func (c *CIDRValues) AppendCIDR(cidr string) error { 47 if c.exists[cidr] { 48 return nil 49 } 50 51 _, ipnet, err := net.ParseCIDR(cidr) 52 if err != nil { 53 return err 54 } 55 56 c.ipnets = append(c.ipnets, ipnet) 57 c.fieldValues = append(c.fieldValues, FieldValue{Type: IPNetValueType, Value: *ipnet}) 58 59 if c.exists == nil { 60 c.exists = make(map[string]bool) 61 } 62 c.exists[cidr] = true 63 64 return nil 65 } 66 67 func isZeros(p net.IP) bool { 68 for i := 0; i < len(p); i++ { 69 if p[i] != 0 { 70 return false 71 } 72 } 73 return true 74 } 75 76 // ParseCIDR converts an IP/CIDR notation to an IPNet object 77 func ParseCIDR(ip string) (*net.IPNet, error) { 78 var ipnet *net.IPNet 79 if !strings.Contains(ip, "/") { 80 if ipnet = IPNetFromIP(net.ParseIP(ip)); isZeros(ipnet.IP) { 81 return nil, errors.New("unknown IP address format") 82 } 83 } else { 84 var err error 85 if _, ipnet, err = net.ParseCIDR(ip); err != nil { 86 return nil, err 87 } 88 } 89 90 return ipnet, nil 91 } 92 93 // AppendIP append ip notation 94 func (c *CIDRValues) AppendIP(ip string) error { 95 if c.exists[ip] { 96 return nil 97 } 98 99 ipnet, err := ParseCIDR(ip) 100 if err != nil { 101 return err 102 } 103 104 c.ipnets = append(c.ipnets, ipnet) 105 c.fieldValues = append(c.fieldValues, FieldValue{Type: IPNetValueType, Value: *ipnet}) 106 107 if c.exists == nil { 108 c.exists = make(map[string]bool) 109 } 110 c.exists[ip] = true 111 112 return nil 113 } 114 115 // Contains returns whether the values match the provided IPNet 116 func (c *CIDRValues) Contains(ipnet *net.IPNet) bool { 117 for _, n := range c.ipnets { 118 if IPNetsMatch(n, ipnet) { 119 return true 120 } 121 } 122 123 return false 124 } 125 126 // Match returns whether the values matches the provided IPNets 127 func (c *CIDRValues) Match(ipnets []net.IPNet) bool { 128 for _, n := range c.ipnets { 129 for _, ipnet := range ipnets { 130 if IPNetsMatch(n, &ipnet) { 131 return true 132 } 133 } 134 } 135 136 return false 137 } 138 139 // MatchAll returns whether the values matches all the provided IPNets 140 func (c *CIDRValues) MatchAll(ipnets []net.IPNet) bool { 141 for _, n := range c.ipnets { 142 for _, ipnet := range ipnets { 143 if !IPNetsMatch(n, &ipnet) { 144 return false 145 } 146 } 147 } 148 149 return true 150 } 151 152 // IPNetsMatch returns whether the IPNets match 153 func IPNetsMatch(i1, i2 *net.IPNet) bool { 154 return i1.Contains(i2.IP) || i2.Contains(i1.IP) 155 }