github.imxd.top/hashicorp/consul@v1.4.5/agent/consul/util.go (about) 1 package consul 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "net" 7 "runtime" 8 "strconv" 9 10 "github.com/hashicorp/consul/agent/metadata" 11 "github.com/hashicorp/consul/agent/structs" 12 "github.com/hashicorp/go-version" 13 "github.com/hashicorp/serf/serf" 14 ) 15 16 /* 17 * Contains an entry for each private block: 18 * 10.0.0.0/8 19 * 100.64.0.0/10 20 * 127.0.0.0/8 21 * 169.254.0.0/16 22 * 172.16.0.0/12 23 * 192.168.0.0/16 24 */ 25 var privateBlocks []*net.IPNet 26 27 func init() { 28 // Add each private block 29 privateBlocks = make([]*net.IPNet, 6) 30 31 _, block, err := net.ParseCIDR("10.0.0.0/8") 32 if err != nil { 33 panic(fmt.Sprintf("Bad cidr. Got %v", err)) 34 } 35 privateBlocks[0] = block 36 37 _, block, err = net.ParseCIDR("100.64.0.0/10") 38 if err != nil { 39 panic(fmt.Sprintf("Bad cidr. Got %v", err)) 40 } 41 privateBlocks[1] = block 42 43 _, block, err = net.ParseCIDR("127.0.0.0/8") 44 if err != nil { 45 panic(fmt.Sprintf("Bad cidr. Got %v", err)) 46 } 47 privateBlocks[2] = block 48 49 _, block, err = net.ParseCIDR("169.254.0.0/16") 50 if err != nil { 51 panic(fmt.Sprintf("Bad cidr. Got %v", err)) 52 } 53 privateBlocks[3] = block 54 55 _, block, err = net.ParseCIDR("172.16.0.0/12") 56 if err != nil { 57 panic(fmt.Sprintf("Bad cidr. Got %v", err)) 58 } 59 privateBlocks[4] = block 60 61 _, block, err = net.ParseCIDR("192.168.0.0/16") 62 if err != nil { 63 panic(fmt.Sprintf("Bad cidr. Got %v", err)) 64 } 65 privateBlocks[5] = block 66 } 67 68 // CanServersUnderstandProtocol checks to see if all the servers in the given 69 // list understand the given protocol version. If there are no servers in the 70 // list then this will return false. 71 func CanServersUnderstandProtocol(members []serf.Member, version uint8) (bool, error) { 72 numServers, numWhoGrok := 0, 0 73 for _, m := range members { 74 if m.Tags["role"] != "consul" { 75 continue 76 } 77 numServers++ 78 79 vsnMin, err := strconv.Atoi(m.Tags["vsn_min"]) 80 if err != nil { 81 return false, err 82 } 83 84 vsnMax, err := strconv.Atoi(m.Tags["vsn_max"]) 85 if err != nil { 86 return false, err 87 } 88 89 v := int(version) 90 if (v >= vsnMin) && (v <= vsnMax) { 91 numWhoGrok++ 92 } 93 } 94 return (numServers > 0) && (numWhoGrok == numServers), nil 95 } 96 97 // Returns if a member is a consul node. Returns a bool, 98 // and the datacenter. 99 func isConsulNode(m serf.Member) (bool, string) { 100 if m.Tags["role"] != "node" { 101 return false, "" 102 } 103 return true, m.Tags["dc"] 104 } 105 106 // Returns if the given IP is in a private block 107 func isPrivateIP(ipStr string) bool { 108 ip := net.ParseIP(ipStr) 109 for _, priv := range privateBlocks { 110 if priv.Contains(ip) { 111 return true 112 } 113 } 114 return false 115 } 116 117 // Returns addresses from interfaces that is up 118 func activeInterfaceAddresses() ([]net.Addr, error) { 119 var upAddrs []net.Addr 120 var loAddrs []net.Addr 121 122 interfaces, err := net.Interfaces() 123 if err != nil { 124 return nil, fmt.Errorf("Failed to get interfaces: %v", err) 125 } 126 127 for _, iface := range interfaces { 128 // Require interface to be up 129 if iface.Flags&net.FlagUp == 0 { 130 continue 131 } 132 133 addresses, err := iface.Addrs() 134 if err != nil { 135 return nil, fmt.Errorf("Failed to get interface addresses: %v", err) 136 } 137 138 if iface.Flags&net.FlagLoopback != 0 { 139 loAddrs = append(loAddrs, addresses...) 140 continue 141 } 142 143 upAddrs = append(upAddrs, addresses...) 144 } 145 146 if len(upAddrs) == 0 { 147 return loAddrs, nil 148 } 149 150 return upAddrs, nil 151 } 152 153 // GetPrivateIP is used to return the first private IP address 154 // associated with an interface on the machine 155 func GetPrivateIP() (net.IP, error) { 156 addresses, err := activeInterfaceAddresses() 157 if err != nil { 158 return nil, fmt.Errorf("Failed to get interface addresses: %v", err) 159 } 160 161 return getPrivateIP(addresses) 162 } 163 164 func getPrivateIP(addresses []net.Addr) (net.IP, error) { 165 var candidates []net.IP 166 167 // Find private IPv4 address 168 for _, rawAddr := range addresses { 169 var ip net.IP 170 switch addr := rawAddr.(type) { 171 case *net.IPAddr: 172 ip = addr.IP 173 case *net.IPNet: 174 ip = addr.IP 175 default: 176 continue 177 } 178 179 if ip.To4() == nil { 180 continue 181 } 182 if !isPrivateIP(ip.String()) { 183 continue 184 } 185 candidates = append(candidates, ip) 186 } 187 numIps := len(candidates) 188 switch numIps { 189 case 0: 190 return nil, fmt.Errorf("No private IP address found") 191 case 1: 192 return candidates[0], nil 193 default: 194 return nil, fmt.Errorf("Multiple private IPs found. Please configure one.") 195 } 196 197 } 198 199 // GetPublicIPv6 is used to return the first public IP address 200 // associated with an interface on the machine 201 func GetPublicIPv6() (net.IP, error) { 202 addresses, err := net.InterfaceAddrs() 203 if err != nil { 204 return nil, fmt.Errorf("Failed to get interface addresses: %v", err) 205 } 206 207 return getPublicIPv6(addresses) 208 } 209 210 func isUniqueLocalAddress(ip net.IP) bool { 211 return len(ip) == net.IPv6len && ip[0] == 0xfc && ip[1] == 0x00 212 } 213 214 func getPublicIPv6(addresses []net.Addr) (net.IP, error) { 215 var candidates []net.IP 216 217 // Find public IPv6 address 218 for _, rawAddr := range addresses { 219 var ip net.IP 220 switch addr := rawAddr.(type) { 221 case *net.IPAddr: 222 ip = addr.IP 223 case *net.IPNet: 224 ip = addr.IP 225 default: 226 continue 227 } 228 229 if ip.To4() != nil { 230 continue 231 } 232 233 if ip.IsLinkLocalUnicast() || isUniqueLocalAddress(ip) || ip.IsLoopback() { 234 continue 235 } 236 candidates = append(candidates, ip) 237 } 238 numIps := len(candidates) 239 switch numIps { 240 case 0: 241 return nil, fmt.Errorf("No public IPv6 address found") 242 case 1: 243 return candidates[0], nil 244 default: 245 return nil, fmt.Errorf("Multiple public IPv6 addresses found. Please configure one.") 246 } 247 } 248 249 // Converts bytes to an integer 250 func bytesToUint64(b []byte) uint64 { 251 return binary.BigEndian.Uint64(b) 252 } 253 254 // Converts a uint to a byte slice 255 func uint64ToBytes(u uint64) []byte { 256 buf := make([]byte, 8) 257 binary.BigEndian.PutUint64(buf, u) 258 return buf 259 } 260 261 // runtimeStats is used to return various runtime information 262 func runtimeStats() map[string]string { 263 return map[string]string{ 264 "os": runtime.GOOS, 265 "arch": runtime.GOARCH, 266 "version": runtime.Version(), 267 "max_procs": strconv.FormatInt(int64(runtime.GOMAXPROCS(0)), 10), 268 "goroutines": strconv.FormatInt(int64(runtime.NumGoroutine()), 10), 269 "cpu_count": strconv.FormatInt(int64(runtime.NumCPU()), 10), 270 } 271 } 272 273 // ServersMeetMinimumVersion returns whether the given alive servers are at least on the 274 // given Consul version 275 func ServersMeetMinimumVersion(members []serf.Member, minVersion *version.Version) bool { 276 for _, member := range members { 277 if valid, parts := metadata.IsConsulServer(member); valid && parts.Status == serf.StatusAlive { 278 if parts.Build.LessThan(minVersion) { 279 return false 280 } 281 } 282 } 283 284 return true 285 } 286 287 func ServersGetACLMode(members []serf.Member, leader string, datacenter string) (numServers int, mode structs.ACLMode, leaderMode structs.ACLMode) { 288 numServers = 0 289 mode = structs.ACLModeEnabled 290 leaderMode = structs.ACLModeUnknown 291 for _, member := range members { 292 if valid, parts := metadata.IsConsulServer(member); valid { 293 294 if datacenter != "" && parts.Datacenter != datacenter { 295 continue 296 } 297 298 numServers += 1 299 300 if memberAddr := (&net.TCPAddr{IP: member.Addr, Port: parts.Port}).String(); memberAddr == leader { 301 leaderMode = parts.ACLs 302 } 303 304 switch parts.ACLs { 305 case structs.ACLModeDisabled: 306 // anything disabled means we cant enable ACLs 307 mode = structs.ACLModeDisabled 308 case structs.ACLModeEnabled: 309 // do nothing 310 case structs.ACLModeLegacy: 311 // This covers legacy mode and older server versions that don't advertise ACL support 312 if mode != structs.ACLModeDisabled && mode != structs.ACLModeUnknown { 313 mode = structs.ACLModeLegacy 314 } 315 default: 316 if mode != structs.ACLModeDisabled { 317 mode = structs.ACLModeUnknown 318 } 319 } 320 } 321 } 322 323 return 324 }