github.com/prysmaticlabs/prysm@v1.4.4/shared/iputils/external_ip.go (about) 1 // Package iputils contains useful functions for ip address formatting. 2 package iputils 3 4 import ( 5 "net" 6 "sort" 7 ) 8 9 // ExternalIPv4 returns the first IPv4 available. 10 func ExternalIPv4() (string, error) { 11 ips, err := ipAddrs() 12 if err != nil { 13 return "", err 14 } 15 if len(ips) == 0 { 16 return "127.0.0.1", nil 17 } 18 for _, ip := range ips { 19 ip = ip.To4() 20 if ip == nil { 21 continue // not an ipv4 address 22 } 23 return ip.String(), nil 24 } 25 return "127.0.0.1", nil 26 } 27 28 // ExternalIP returns the first IPv4/IPv6 available. 29 func ExternalIP() (string, error) { 30 ips, err := ipAddrs() 31 if err != nil { 32 return "", err 33 } 34 if len(ips) == 0 { 35 return "127.0.0.1", nil 36 } 37 return ips[0].String(), nil 38 } 39 40 // ipAddrs returns all the valid IPs available. 41 func ipAddrs() ([]net.IP, error) { 42 ifaces, err := net.Interfaces() 43 if err != nil { 44 return nil, err 45 } 46 var ipAddrs []net.IP 47 for _, iface := range ifaces { 48 if iface.Flags&net.FlagUp == 0 { 49 continue // interface down 50 } 51 if iface.Flags&net.FlagLoopback != 0 { 52 continue // loopback interface 53 } 54 addrs, err := iface.Addrs() 55 if err != nil { 56 return nil, err 57 } 58 for _, addr := range addrs { 59 var ip net.IP 60 switch v := addr.(type) { 61 case *net.IPNet: 62 ip = v.IP 63 case *net.IPAddr: 64 ip = v.IP 65 } 66 if ip == nil || ip.IsLoopback() || ip.IsLinkLocalUnicast() { 67 continue 68 } 69 ipAddrs = append(ipAddrs, ip) 70 } 71 } 72 return SortAddresses(ipAddrs), nil 73 } 74 75 // SortAddresses sorts a set of addresses in the order of 76 // ipv4 -> ipv6. 77 func SortAddresses(ipAddrs []net.IP) []net.IP { 78 sort.Slice(ipAddrs, func(i, j int) bool { 79 return ipAddrs[i].To4() != nil && ipAddrs[j].To4() == nil 80 }) 81 return ipAddrs 82 }