github.com/fafucoder/cilium@v1.6.11/common/addressing/ip.go (about) 1 // Copyright 2016-2017 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package addressing 16 17 import ( 18 "encoding/json" 19 "fmt" 20 "net" 21 ) 22 23 type CiliumIP interface { 24 IPNet(ones int) *net.IPNet 25 EndpointPrefix() *net.IPNet 26 IP() net.IP 27 String() string 28 IsIPv6() bool 29 GetFamilyString() string 30 IsSet() bool 31 } 32 33 type CiliumIPv6 []byte 34 35 // NewCiliumIPv6 returns a IPv6 if the given `address` is: 36 // - An IPv6 address. 37 // - Node ID, bits from 112 to 120, must be different than 0 38 // - Endpoint ID, bits from 120 to 128, must be equal to 0 39 func NewCiliumIPv6(address string) (CiliumIPv6, error) { 40 ip, _, err := net.ParseCIDR(address) 41 if err != nil { 42 ip = net.ParseIP(address) 43 if ip == nil { 44 return nil, fmt.Errorf("Invalid IPv6 address: %s", address) 45 } 46 } 47 48 // As result of ParseIP, ip is either a valid IPv6 or IPv4 address. net.IP 49 // represents both versions on 16 bytes, so a more reliable way to tell 50 // IPv4 and IPv6 apart is to see if it fits 4 bytes 51 ip4 := ip.To4() 52 if ip4 != nil { 53 return nil, fmt.Errorf("Not an IPv6 address: %s", address) 54 } 55 return DeriveCiliumIPv6(ip.To16()), nil 56 } 57 58 func DeriveCiliumIPv6(src net.IP) CiliumIPv6 { 59 ip := make(CiliumIPv6, 16) 60 copy(ip, src.To16()) 61 return ip 62 } 63 64 // IsSet returns true if the IP is set 65 func (ip CiliumIPv6) IsSet() bool { 66 return ip.String() != "" 67 } 68 69 func (ip CiliumIPv6) IsIPv6() bool { 70 return true 71 } 72 73 func (ip CiliumIPv6) IPNet(ones int) *net.IPNet { 74 return &net.IPNet{ 75 IP: ip.IP(), 76 Mask: net.CIDRMask(ones, 128), 77 } 78 } 79 80 func (ip CiliumIPv6) EndpointPrefix() *net.IPNet { 81 return ip.IPNet(128) 82 } 83 84 func (ip CiliumIPv6) IP() net.IP { 85 return net.IP(ip) 86 } 87 88 func (ip CiliumIPv6) String() string { 89 if ip == nil { 90 return "" 91 } 92 93 return net.IP(ip).String() 94 } 95 96 func (ip CiliumIPv6) MarshalJSON() ([]byte, error) { 97 return json.Marshal(net.IP(ip)) 98 } 99 100 func (ip *CiliumIPv6) UnmarshalJSON(b []byte) error { 101 if len(b) < len(`""`) { 102 return fmt.Errorf("Invalid CiliumIPv6 '%s'", string(b)) 103 } 104 105 str := string(b[1 : len(b)-1]) 106 if str == "" { 107 return nil 108 } 109 110 c, err := NewCiliumIPv6(str) 111 if err != nil { 112 return fmt.Errorf("Invalid CiliumIPv6 '%s': %s", str, err) 113 } 114 115 *ip = c 116 return nil 117 } 118 119 type CiliumIPv4 []byte 120 121 func NewCiliumIPv4(address string) (CiliumIPv4, error) { 122 ip, _, err := net.ParseCIDR(address) 123 if err != nil { 124 ip = net.ParseIP(address) 125 if ip == nil { 126 return nil, fmt.Errorf("Invalid IPv4 address: %s", address) 127 } 128 } 129 130 ip4 := ip.To4() 131 if ip4 == nil { 132 return nil, fmt.Errorf("Not an IPv4 address") 133 } 134 return DeriveCiliumIPv4(ip4), nil 135 } 136 137 func DeriveCiliumIPv4(src net.IP) CiliumIPv4 { 138 ip := make(CiliumIPv4, 4) 139 copy(ip, src.To4()) 140 return ip 141 } 142 143 // IsSet returns true if the IP is set 144 func (ip CiliumIPv4) IsSet() bool { 145 return ip.String() != "" 146 } 147 148 func (ip CiliumIPv4) IsIPv6() bool { 149 return false 150 } 151 152 func (ip CiliumIPv4) IPNet(ones int) *net.IPNet { 153 return &net.IPNet{ 154 IP: net.IP(ip), 155 Mask: net.CIDRMask(ones, 32), 156 } 157 } 158 159 func (ip CiliumIPv4) EndpointPrefix() *net.IPNet { 160 return ip.IPNet(32) 161 } 162 163 func (ip CiliumIPv4) IP() net.IP { 164 return net.IP(ip) 165 } 166 167 func (ip CiliumIPv4) String() string { 168 if ip == nil { 169 return "" 170 } 171 172 return net.IP(ip).String() 173 } 174 175 func (ip CiliumIPv4) MarshalJSON() ([]byte, error) { 176 return json.Marshal(net.IP(ip)) 177 } 178 179 func (ip *CiliumIPv4) UnmarshalJSON(b []byte) error { 180 if len(b) < len(`""`) { 181 return fmt.Errorf("Invalid CiliumIPv4 '%s'", string(b)) 182 } 183 184 str := string(b[1 : len(b)-1]) 185 if str == "" { 186 return nil 187 } 188 189 c, err := NewCiliumIPv4(str) 190 if err != nil { 191 return fmt.Errorf("Invalid CiliumIPv4 '%s': %s", str, err) 192 } 193 194 *ip = c 195 return nil 196 } 197 198 // GetFamilyString returns the address family of ip as a string. 199 func (ip CiliumIPv4) GetFamilyString() string { 200 return "IPv4" 201 } 202 203 // GetFamilyString returns the address family of ip as a string. 204 func (ip CiliumIPv6) GetFamilyString() string { 205 return "IPv6" 206 }