130 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package addr
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"net"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	privateBlocks []*net.IPNet
 | |
| )
 | |
| 
 | |
| func init() {
 | |
| 	for _, b := range []string{"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16", "100.64.0.0/10", "fd00::/8"} {
 | |
| 		if _, block, err := net.ParseCIDR(b); err == nil {
 | |
| 			privateBlocks = append(privateBlocks, block)
 | |
| 		}
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func isPrivateIP(ipAddr string) bool {
 | |
| 	ip := net.ParseIP(ipAddr)
 | |
| 	for _, priv := range privateBlocks {
 | |
| 		if priv.Contains(ip) {
 | |
| 			return true
 | |
| 		}
 | |
| 	}
 | |
| 	return false
 | |
| }
 | |
| 
 | |
| // Extract returns a real ip
 | |
| func Extract(addr string) (string, error) {
 | |
| 	// if addr specified then its returned
 | |
| 	if len(addr) > 0 && (addr != "0.0.0.0" && addr != "[::]" && addr != "::") {
 | |
| 		return addr, nil
 | |
| 	}
 | |
| 
 | |
| 	ifaces, err := net.Interfaces()
 | |
| 	if err != nil {
 | |
| 		return "", fmt.Errorf("Failed to get interfaces! Err: %v", err)
 | |
| 	}
 | |
| 
 | |
| 	var addrs []net.Addr
 | |
| 	for _, iface := range ifaces {
 | |
| 		ifaceAddrs, err := iface.Addrs()
 | |
| 		if err != nil {
 | |
| 			// ignore error, interface can dissapear from system
 | |
| 			continue
 | |
| 		}
 | |
| 		addrs = append(addrs, ifaceAddrs...)
 | |
| 	}
 | |
| 
 | |
| 	var ipAddr []byte
 | |
| 	var publicIP []byte
 | |
| 
 | |
| 	for _, rawAddr := range addrs {
 | |
| 		var ip net.IP
 | |
| 		switch addr := rawAddr.(type) {
 | |
| 		case *net.IPAddr:
 | |
| 			ip = addr.IP
 | |
| 		case *net.IPNet:
 | |
| 			ip = addr.IP
 | |
| 		default:
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		if !isPrivateIP(ip.String()) {
 | |
| 			publicIP = ip
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		ipAddr = ip
 | |
| 		break
 | |
| 	}
 | |
| 
 | |
| 	// return private ip
 | |
| 	if ipAddr != nil {
 | |
| 		return net.IP(ipAddr).String(), nil
 | |
| 	}
 | |
| 
 | |
| 	// return public or virtual ip
 | |
| 	if publicIP != nil {
 | |
| 		return net.IP(publicIP).String(), nil
 | |
| 	}
 | |
| 
 | |
| 	return "", fmt.Errorf("No IP address found, and explicit IP not provided")
 | |
| }
 | |
| 
 | |
| // IPs returns all known ips
 | |
| func IPs() []string {
 | |
| 	ifaces, err := net.Interfaces()
 | |
| 	if err != nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	var ipAddrs []string
 | |
| 
 | |
| 	for _, i := range ifaces {
 | |
| 		addrs, err := i.Addrs()
 | |
| 		if err != nil {
 | |
| 			continue
 | |
| 		}
 | |
| 
 | |
| 		for _, addr := range addrs {
 | |
| 			var ip net.IP
 | |
| 			switch v := addr.(type) {
 | |
| 			case *net.IPNet:
 | |
| 				ip = v.IP
 | |
| 			case *net.IPAddr:
 | |
| 				ip = v.IP
 | |
| 			}
 | |
| 
 | |
| 			if ip == nil {
 | |
| 				continue
 | |
| 			}
 | |
| 
 | |
| 			// dont skip ipv6 addrs
 | |
| 			/*
 | |
| 				ip = ip.To4()
 | |
| 				if ip == nil {
 | |
| 					continue
 | |
| 				}
 | |
| 			*/
 | |
| 
 | |
| 			ipAddrs = append(ipAddrs, ip.String())
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return ipAddrs
 | |
| }
 |