github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/common/networkInterface.go (about) 1 /* 2 * Copyright (c) 2015, Psiphon Inc. 3 * All rights reserved. 4 * 5 * This program is free software: you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 * 18 */ 19 20 package common 21 22 import ( 23 "net" 24 25 "github.com/Psiphon-Labs/psiphon-tunnel-core/psiphon/common/errors" 26 ) 27 28 // GetInterfaceIPAddresses takes an interface name, such as "eth0", and 29 // returns the first non-link local IPv4 and IPv6 addresses associated with 30 // it. Either of the IPv4 or IPv6 address may be nil. If neither type of 31 // address is found, an error is returned. 32 func GetInterfaceIPAddresses(interfaceName string) (net.IP, net.IP, error) { 33 34 var IPv4Address, IPv6Address net.IP 35 36 availableInterfaces, err := net.InterfaceByName(interfaceName) 37 if err != nil { 38 return nil, nil, errors.Trace(err) 39 } 40 41 addrs, err := availableInterfaces.Addrs() 42 if err != nil { 43 return nil, nil, errors.Trace(err) 44 } 45 46 for _, addr := range addrs { 47 48 ipNet := addr.(*net.IPNet) 49 if ipNet == nil { 50 continue 51 } 52 53 if ipNet.IP.To4() != nil { 54 if IPv4Address == nil && !ipNet.IP.IsLinkLocalUnicast() { 55 IPv4Address = ipNet.IP 56 } 57 } else { 58 if IPv6Address == nil && !ipNet.IP.IsLinkLocalUnicast() { 59 IPv6Address = ipNet.IP 60 } 61 } 62 63 if IPv4Address != nil && IPv6Address != nil { 64 break 65 } 66 } 67 68 if IPv4Address != nil || IPv6Address != nil { 69 return IPv4Address, IPv6Address, nil 70 } 71 72 return nil, nil, errors.Tracef("could not find any IP address for interface %s", interfaceName) 73 } 74 75 // GetRoutableInterfaceIPAddresses returns GetInterfaceIPAddresses values for 76 // the first non-loopback, non-point-to-point network interface on the host 77 // that has an IP address. 78 func GetRoutableInterfaceIPAddresses() (net.IP, net.IP, error) { 79 80 interfaces, err := net.Interfaces() 81 if err != nil { 82 return nil, nil, errors.Trace(err) 83 } 84 85 for i, in := range interfaces { 86 if (in.Flags&net.FlagUp == 0) || 87 (in.Flags&(net.FlagLoopback|net.FlagPointToPoint)) != 0 { 88 continue 89 } 90 IPv4Address, IPv6Address, err := GetInterfaceIPAddresses(in.Name) 91 if err == nil { 92 return IPv4Address, IPv6Address, nil 93 } else if i == len(interfaces)-1 { 94 return nil, nil, errors.Trace(err) 95 } 96 } 97 return nil, nil, errors.TraceNew("no candidate interfaces found") 98 }