github.com/openziti/transport@v0.1.5/address.go (about) 1 /* 2 Copyright NetFoundry, Inc. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 https://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package transport 18 19 import ( 20 "errors" 21 "fmt" 22 "github.com/openziti/foundation/identity/identity" 23 log "github.com/sirupsen/logrus" 24 "io" 25 "net" 26 "time" 27 ) 28 29 type Configuration map[interface{}]interface{} 30 31 // Address implements the functionality provided by a generic "address". 32 // 33 type Address interface { 34 Dial(name string, i *identity.TokenId, timeout time.Duration, tcfg Configuration) (Connection, error) 35 DialWithLocalBinding(name string, binding string, i *identity.TokenId, timeout time.Duration, tcfg Configuration) (Connection, error) 36 Listen(name string, i *identity.TokenId, incoming chan Connection, tcfg Configuration) (io.Closer, error) 37 MustListen(name string, i *identity.TokenId, incoming chan Connection, tcfg Configuration) io.Closer 38 String() string 39 Type() string 40 } 41 42 // AddressParser implements the functionality provided by an "address parser". 43 // 44 type AddressParser interface { 45 Parse(addressString string) (Address, error) 46 } 47 48 // AddAddressParser adds an AddressParser to the globally-configured address parsers. 49 // 50 func AddAddressParser(addressParser AddressParser) { 51 for _, e := range addressParsers { 52 if addressParser == e { 53 return 54 } 55 } 56 addressParsers = append(addressParsers, addressParser) 57 } 58 59 // ParseAddress uses the globally-configured AddressParser instances to parse an address. 60 // 61 func ParseAddress(addressString string) (Address, error) { 62 if addressParsers == nil || len(addressParsers) < 1 { 63 return nil, errors.New("no configured address parsers") 64 } 65 for _, addressParser := range addressParsers { 66 address, err := addressParser.Parse(addressString) 67 if err == nil { 68 return address, nil 69 } 70 } 71 return nil, fmt.Errorf("address (%v) not parsed", addressString) 72 } 73 74 // The globally-configured address parsers. 75 // 76 var addressParsers = make([]AddressParser, 0) 77 78 // Resolve a network interface by name or IP address 79 func ResolveInterface(toResolve string) (*net.Interface, error) { 80 // Easy check first - see if the interface is specified by name 81 ief, err := net.InterfaceByName(toResolve) 82 83 if err == nil { 84 return ief, nil 85 } 86 87 // Nope! Scan all network interfaces to if there is an IP match 88 ifaces, err := net.Interfaces() 89 if err != nil { 90 return nil, err 91 } 92 93 for _, iface := range ifaces { 94 if (iface.Flags & net.FlagUp) == 0 { 95 log.Debugf("Interface %s is down, ignoring it for address resolution", iface.Name) 96 continue 97 } 98 99 addrs, err := iface.Addrs() 100 if err != nil { 101 log.Warnf("Could not check interface %s (%s)", iface.Name, err) 102 continue 103 } 104 105 for _, addr := range addrs { 106 log.Tracef("Checking interface %s (%s) against %s", iface.Name, addr.String(), toResolve) 107 108 var ip net.IP 109 110 switch addr := addr.(type) { 111 case *net.IPAddr: 112 ip = addr.IP 113 case *net.IPNet: 114 ip = addr.IP 115 default: 116 continue 117 } 118 119 if ip.To4() != nil && ip.To4().String() == toResolve { 120 log.Debugf("Resolved %s to interface %s", toResolve, iface.Name) 121 return &iface, nil 122 } 123 } 124 } 125 126 // Not an IP either, not sure how to resolve this interface 127 return nil, errors.New(fmt.Sprintf("no network interface found for %s", toResolve)) 128 }