123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- package net2
- import (
- "fmt"
- "log"
- "net"
- "os"
- "strings"
- "sync"
- )
- var myHostname string
- var myHostnameOnce sync.Once
- // Like os.Hostname but caches first successful result, making it cheap to call it
- // over and over.
- // It will also crash whole process if fetching Hostname fails!
- func MyHostname() string {
- myHostnameOnce.Do(func() {
- var err error
- myHostname, err = os.Hostname()
- if err != nil {
- log.Fatal(err)
- }
- })
- return myHostname
- }
- var myIp4 *net.IPAddr
- var myIp4Once sync.Once
- // Resolves `MyHostname()` to an Ip4 address. Caches first successful result, making it
- // cheap to call it over and over.
- // It will also crash whole process if resolving the IP fails!
- func MyIp4() *net.IPAddr {
- myIp4Once.Do(func() {
- var err error
- myIp4, err = net.ResolveIPAddr("ip4", MyHostname())
- if err != nil {
- log.Fatal(err)
- }
- })
- return myIp4
- }
- var myIp6 *net.IPAddr
- var myIp6Once sync.Once
- // Resolves `MyHostname()` to an Ip6 address. Caches first successful result, making it
- // cheap to call it over and over.
- // It will also crash whole process if resolving the IP fails!
- func MyIp6() *net.IPAddr {
- myIp6Once.Do(func() {
- var err error
- myIp6, err = net.ResolveIPAddr("ip6", MyHostname())
- if err != nil {
- log.Fatal(err)
- }
- })
- return myIp6
- }
- // This returns the list of local ip addresses which other hosts can connect
- // to (NOTE: Loopback ip is ignored).
- // Also resolves Hostname to an address and adds it to the list too, so
- // IPs from /etc/hosts can work too.
- func GetLocalIPs() ([]*net.IP, error) {
- hostname, err := os.Hostname()
- if err != nil {
- return nil, fmt.Errorf("Failed to lookup hostname: %v", err)
- }
- // Resolves IP Address from Hostname, this way overrides in /etc/hosts
- // can work too for IP resolution.
- ipInfo, err := net.ResolveIPAddr("ip4", hostname)
- if err != nil {
- return nil, fmt.Errorf("Failed to resolve ip: %v", err)
- }
- ips := []*net.IP{&ipInfo.IP}
- // TODO(zviad): Is rest of the code really necessary?
- addrs, err := net.InterfaceAddrs()
- if err != nil {
- return nil, fmt.Errorf("Failed to get interface addresses: %v", err)
- }
- for _, addr := range addrs {
- ipnet, ok := addr.(*net.IPNet)
- if !ok {
- continue
- }
- if ipnet.IP.IsLoopback() {
- continue
- }
- ips = append(ips, &ipnet.IP)
- }
- return ips, nil
- }
- var localhostIPNets []*net.IPNet
- func init() {
- for _, mask := range []string{"127.0.0.1/8", "::1/128"} {
- _, ipnet, err := net.ParseCIDR(mask)
- if err != nil {
- panic(err)
- }
- localhostIPNets = append(localhostIPNets, ipnet)
- }
- }
- func IsLocalhostIp(ipStr string) bool {
- ip := net.ParseIP(ipStr)
- if ip == nil {
- return false
- }
- for _, ipnet := range localhostIPNets {
- if ipnet.Contains(ip) {
- return true
- }
- }
- return false
- }
- // Given a host string, return true if the host is an ip (v4/v6) localhost.
- func IsLocalhost(host string) bool {
- return IsLocalhostIp(host) ||
- host == "localhost" ||
- host == "ip6-localhost" ||
- host == "ipv6-localhost"
- }
- // Resolves hostnames in addresses to actual IP4 addresses. Skips all invalid addresses
- // and all addresses that can't be resolved.
- // `addrs` are assumed to be of form: ["<hostname>:<port>", ...]
- // Returns an error in addition to resolved addresses if not all resolutions succeed.
- func ResolveIP4s(addrs []string) ([]string, error) {
- resolvedAddrs := make([]string, 0, len(addrs))
- var lastErr error
- for _, server := range addrs {
- hostPort := strings.Split(server, ":")
- if len(hostPort) != 2 {
- lastErr = fmt.Errorf("Skipping invalid address: %s", server)
- continue
- }
- ip, err := net.ResolveIPAddr("ip4", hostPort[0])
- if err != nil {
- lastErr = err
- continue
- }
- resolvedAddrs = append(resolvedAddrs, ip.IP.String()+":"+hostPort[1])
- }
- return resolvedAddrs, lastErr
- }
- func LookupValidAddrs() (map[string]bool, error) {
- hostName, err := os.Hostname()
- if err != nil {
- return nil, err
- }
- addrs, err := net.LookupHost(hostName)
- if err != nil {
- return nil, err
- }
- validAddrs := make(map[string]bool)
- validAddrs[hostName] = true
- for _, addr := range addrs {
- validAddrs[addr] = true
- }
- // Special case localhost/127.0.0.1 so that this works on devVMs. It should
- // have no affect in production.
- validAddrs["127.0.0.1"] = true
- validAddrs["localhost"] = true
- return validAddrs, nil
- }
|