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  }