Przeglądaj źródła

Vendor go-sockaddr

diff:
https://github.com/hashicorp/go-sockaddr/compare/acd314c5781ea706c710d9ea70069fd2e110d61d...6d291a969b86c4b633730bfc6b8b9d64c3aafed9

Signed-off-by: Flavio Crisciani <flavio.crisciani@docker.com>
Flavio Crisciani 7 lat temu
rodzic
commit
74d7da907a

+ 1 - 1
libnetwork/vendor.conf

@@ -29,7 +29,7 @@ github.com/hashicorp/go-msgpack 71c2886f5a673a35f909803f38ece5810165097b
 github.com/hashicorp/go-multierror fcdddc395df1ddf4247c69bd436e84cfa0733f7e
 github.com/hashicorp/memberlist 3d8438da9589e7b608a83ffac1ef8211486bcb7c
 github.com/sean-/seed e2103e2c35297fb7e17febb81e49b312087a2372
-github.com/hashicorp/go-sockaddr acd314c5781ea706c710d9ea70069fd2e110d61d
+github.com/hashicorp/go-sockaddr 6d291a969b86c4b633730bfc6b8b9d64c3aafed9
 github.com/hashicorp/serf 598c54895cc5a7b1a24a398d635e8c0ea0959870
 github.com/mattn/go-shellwords v1.0.3
 github.com/miekg/dns 75e6e86cc601825c5dbcd4e0c209eab180997cd7

+ 128 - 0
libnetwork/vendor/github.com/hashicorp/go-sockaddr/ifaddr.go

@@ -1,5 +1,7 @@
 package sockaddr
 
+import "strings"
+
 // ifAddrAttrMap is a map of the IfAddr type-specific attributes.
 var ifAddrAttrMap map[AttrName]func(IfAddr) string
 var ifAddrAttrs []AttrName
@@ -30,6 +32,53 @@ func GetPrivateIP() (string, error) {
 	return ip.NetIP().String(), nil
 }
 
+// GetPrivateIPs returns a string with all IP addresses that are part of RFC
+// 6890 (regardless of whether or not there is a default route, unlike
+// GetPublicIP).  If the system can't find any RFC 6890 IP addresses, an empty
+// string will be returned instead.  This function is the `eval` equivalent of:
+//
+// ```
+// $ sockaddr eval -r '{{GetAllInterfaces | include "RFC" "6890" | join "address" " "}}'
+/// ```
+func GetPrivateIPs() (string, error) {
+	ifAddrs, err := GetAllInterfaces()
+	if err != nil {
+		return "", err
+	} else if len(ifAddrs) < 1 {
+		return "", nil
+	}
+
+	ifAddrs, _ = FilterIfByType(ifAddrs, TypeIP)
+	if len(ifAddrs) == 0 {
+		return "", nil
+	}
+
+	OrderedIfAddrBy(AscIfType, AscIfNetworkSize).Sort(ifAddrs)
+
+	ifAddrs, _, err = IfByRFC("6890", ifAddrs)
+	if err != nil {
+		return "", err
+	} else if len(ifAddrs) == 0 {
+		return "", nil
+	}
+
+	_, ifAddrs, err = IfByRFC(ForwardingBlacklistRFC, ifAddrs)
+	if err != nil {
+		return "", err
+	} else if len(ifAddrs) == 0 {
+		return "", nil
+	}
+
+	ips := make([]string, 0, len(ifAddrs))
+	for _, ifAddr := range ifAddrs {
+		ip := *ToIPAddr(ifAddr.SockAddr)
+		s := ip.NetIP().String()
+		ips = append(ips, s)
+	}
+
+	return strings.Join(ips, " "), nil
+}
+
 // GetPublicIP returns a string with a single IP address that is NOT part of RFC
 // 6890 and has a default route.  If the system can't determine its IP address
 // or find a non RFC 6890 IP address, an empty string will be returned instead.
@@ -51,6 +100,47 @@ func GetPublicIP() (string, error) {
 	return ip.NetIP().String(), nil
 }
 
+// GetPublicIPs returns a string with all IP addresses that are NOT part of RFC
+// 6890 (regardless of whether or not there is a default route, unlike
+// GetPublicIP).  If the system can't find any non RFC 6890 IP addresses, an
+// empty string will be returned instead.  This function is the `eval`
+// equivalent of:
+//
+// ```
+// $ sockaddr eval -r '{{GetAllInterfaces | exclude "RFC" "6890" | join "address" " "}}'
+/// ```
+func GetPublicIPs() (string, error) {
+	ifAddrs, err := GetAllInterfaces()
+	if err != nil {
+		return "", err
+	} else if len(ifAddrs) < 1 {
+		return "", nil
+	}
+
+	ifAddrs, _ = FilterIfByType(ifAddrs, TypeIP)
+	if len(ifAddrs) == 0 {
+		return "", nil
+	}
+
+	OrderedIfAddrBy(AscIfType, AscIfNetworkSize).Sort(ifAddrs)
+
+	_, ifAddrs, err = IfByRFC("6890", ifAddrs)
+	if err != nil {
+		return "", err
+	} else if len(ifAddrs) == 0 {
+		return "", nil
+	}
+
+	ips := make([]string, 0, len(ifAddrs))
+	for _, ifAddr := range ifAddrs {
+		ip := *ToIPAddr(ifAddr.SockAddr)
+		s := ip.NetIP().String()
+		ips = append(ips, s)
+	}
+
+	return strings.Join(ips, " "), nil
+}
+
 // GetInterfaceIP returns a string with a single IP address sorted by the size
 // of the network (i.e. IP addresses with a smaller netmask, larger network
 // size, are sorted first).  This function is the `eval` equivalent of:
@@ -91,6 +181,44 @@ func GetInterfaceIP(namedIfRE string) (string, error) {
 	return IPAddrAttr(*ip, "address"), nil
 }
 
+// GetInterfaceIPs returns a string with all IPs, sorted by the size of the
+// network (i.e. IP addresses with a smaller netmask, larger network size, are
+// sorted first), on a named interface.  This function is the `eval` equivalent
+// of:
+//
+// ```
+// $ sockaddr eval -r '{{GetAllInterfaces | include "name" <<ARG>> | sort "type,size" | join "address" " "}}'
+/// ```
+func GetInterfaceIPs(namedIfRE string) (string, error) {
+	ifAddrs, err := GetAllInterfaces()
+	if err != nil {
+		return "", err
+	}
+
+	ifAddrs, _, err = IfByName(namedIfRE, ifAddrs)
+	if err != nil {
+		return "", err
+	}
+
+	ifAddrs, err = SortIfBy("+type,+size", ifAddrs)
+	if err != nil {
+		return "", err
+	}
+
+	if len(ifAddrs) == 0 {
+		return "", err
+	}
+
+	ips := make([]string, 0, len(ifAddrs))
+	for _, ifAddr := range ifAddrs {
+		ip := *ToIPAddr(ifAddr.SockAddr)
+		s := ip.NetIP().String()
+		ips = append(ips, s)
+	}
+
+	return strings.Join(ips, " "), nil
+}
+
 // IfAddrAttrs returns a list of attributes supported by the IfAddr type
 func IfAddrAttrs() []AttrName {
 	return ifAddrAttrs

+ 327 - 15
libnetwork/vendor/github.com/hashicorp/go-sockaddr/ifaddrs.go

@@ -1,8 +1,10 @@
 package sockaddr
 
 import (
+	"encoding/binary"
 	"errors"
 	"fmt"
+	"math/big"
 	"net"
 	"regexp"
 	"sort"
@@ -10,6 +12,14 @@ import (
 	"strings"
 )
 
+var (
+	// Centralize all regexps and regexp.Copy() where necessary.
+	signRE       *regexp.Regexp = regexp.MustCompile(`^[\s]*[+-]`)
+	whitespaceRE *regexp.Regexp = regexp.MustCompile(`[\s]+`)
+	ifNameRE     *regexp.Regexp = regexp.MustCompile(`^(?:Ethernet|Wireless LAN) adapter ([^:]+):`)
+	ipAddrRE     *regexp.Regexp = regexp.MustCompile(`^   IPv[46] Address\. \. \. \. \. \. \. \. \. \. \. : ([^\s]+)`)
+)
+
 // IfAddrs is a slice of IfAddr
 type IfAddrs []IfAddr
 
@@ -91,6 +101,40 @@ func AscIfAddress(p1Ptr, p2Ptr *IfAddr) int {
 	return AscAddress(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
 }
 
+// AscIfDefault is a sorting function to sort IfAddrs by whether or not they
+// have a default route or not.  Non-equal types are deferred in the sort.
+//
+// FIXME: This is a particularly expensive sorting operation because of the
+// non-memoized calls to NewRouteInfo().  In an ideal world the routeInfo data
+// once at the start of the sort and pass it along as a context or by wrapping
+// the IfAddr type with this information (this would also solve the inability to
+// return errors and the possibility of failing silently).  Fortunately,
+// N*log(N) where N = 3 is only ~6.2 invocations.  Not ideal, but not worth
+// optimizing today.  The common case is this gets called once or twice.
+// Patches welcome.
+func AscIfDefault(p1Ptr, p2Ptr *IfAddr) int {
+	ri, err := NewRouteInfo()
+	if err != nil {
+		return sortDeferDecision
+	}
+
+	defaultIfName, err := ri.GetDefaultInterfaceName()
+	if err != nil {
+		return sortDeferDecision
+	}
+
+	switch {
+	case p1Ptr.Interface.Name == defaultIfName && p2Ptr.Interface.Name == defaultIfName:
+		return sortDeferDecision
+	case p1Ptr.Interface.Name == defaultIfName:
+		return sortReceiverBeforeArg
+	case p2Ptr.Interface.Name == defaultIfName:
+		return sortArgBeforeReceiver
+	default:
+		return sortDeferDecision
+	}
+}
+
 // AscIfName is a sorting function to sort IfAddrs by their interface names.
 func AscIfName(p1Ptr, p2Ptr *IfAddr) int {
 	return strings.Compare(p1Ptr.Name, p2Ptr.Name)
@@ -127,6 +171,11 @@ func DescIfAddress(p1Ptr, p2Ptr *IfAddr) int {
 	return -1 * AscAddress(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
 }
 
+// DescIfDefault is identical to AscIfDefault but reverse ordered.
+func DescIfDefault(p1Ptr, p2Ptr *IfAddr) int {
+	return -1 * AscIfDefault(p1Ptr, p2Ptr)
+}
+
 // DescIfName is identical to AscIfName but reverse ordered.
 func DescIfName(p1Ptr, p2Ptr *IfAddr) int {
 	return -1 * strings.Compare(p1Ptr.Name, p2Ptr.Name)
@@ -169,7 +218,15 @@ func FilterIfByType(ifAddrs IfAddrs, type_ SockAddrType) (matchedIfs, excludedIf
 
 // IfAttr forwards the selector to IfAttr.Attr() for resolution.  If there is
 // more than one IfAddr, only the first IfAddr is used.
-func IfAttr(selectorName string, ifAddrs IfAddrs) (string, error) {
+func IfAttr(selectorName string, ifAddr IfAddr) (string, error) {
+	attrName := AttrName(strings.ToLower(selectorName))
+	attrVal, err := ifAddr.Attr(attrName)
+	return attrVal, err
+}
+
+// IfAttrs forwards the selector to IfAttrs.Attr() for resolution.  If there is
+// more than one IfAddr, only the first IfAddr is used.
+func IfAttrs(selectorName string, ifAddrs IfAddrs) (string, error) {
 	if len(ifAddrs) == 0 {
 		return "", nil
 	}
@@ -243,10 +300,10 @@ func GetDefaultInterfaces() (IfAddrs, error) {
 // the `eval` equivalent of:
 //
 // ```
-// $ sockaddr eval -r '{{GetDefaultInterfaces | include "type" "ip" | include "flags" "forwardable|up" | sort "type,size" | include "RFC" "6890" }}'
+// $ sockaddr eval -r '{{GetAllInterfaces | include "type" "ip" | include "flags" "forwardable" | include "flags" "up" | sort "default,type,size" | include "RFC" "6890" }}'
 /// ```
 func GetPrivateInterfaces() (IfAddrs, error) {
-	privateIfs, err := GetDefaultInterfaces()
+	privateIfs, err := GetAllInterfaces()
 	if err != nil {
 		return IfAddrs{}, err
 	}
@@ -259,15 +316,21 @@ func GetPrivateInterfaces() (IfAddrs, error) {
 		return IfAddrs{}, nil
 	}
 
-	privateIfs, _, err = IfByFlag("forwardable|up", privateIfs)
+	privateIfs, _, err = IfByFlag("forwardable", privateIfs)
+	if err != nil {
+		return IfAddrs{}, err
+	}
+
+	privateIfs, _, err = IfByFlag("up", privateIfs)
 	if err != nil {
 		return IfAddrs{}, err
 	}
+
 	if len(privateIfs) == 0 {
 		return IfAddrs{}, nil
 	}
 
-	OrderedIfAddrBy(AscIfType, AscIfNetworkSize).Sort(privateIfs)
+	OrderedIfAddrBy(AscIfDefault, AscIfType, AscIfNetworkSize).Sort(privateIfs)
 
 	privateIfs, _, err = IfByRFC("6890", privateIfs)
 	if err != nil {
@@ -285,10 +348,10 @@ func GetPrivateInterfaces() (IfAddrs, error) {
 // function is the `eval` equivalent of:
 //
 // ```
-// $ sockaddr eval -r '{{GetDefaultInterfaces | include "type" "ip" | include "flags" "forwardable|up" | sort "type,size" | exclude "RFC" "6890" }}'
+// $ sockaddr eval -r '{{GetAllInterfaces | include "type" "ip" | include "flags" "forwardable" | include "flags" "up" | sort "default,type,size" | exclude "RFC" "6890" }}'
 /// ```
 func GetPublicInterfaces() (IfAddrs, error) {
-	publicIfs, err := GetDefaultInterfaces()
+	publicIfs, err := GetAllInterfaces()
 	if err != nil {
 		return IfAddrs{}, err
 	}
@@ -301,15 +364,21 @@ func GetPublicInterfaces() (IfAddrs, error) {
 		return IfAddrs{}, nil
 	}
 
-	publicIfs, _, err = IfByFlag("forwardable|up", publicIfs)
+	publicIfs, _, err = IfByFlag("forwardable", publicIfs)
 	if err != nil {
 		return IfAddrs{}, err
 	}
+
+	publicIfs, _, err = IfByFlag("up", publicIfs)
+	if err != nil {
+		return IfAddrs{}, err
+	}
+
 	if len(publicIfs) == 0 {
 		return IfAddrs{}, nil
 	}
 
-	OrderedIfAddrBy(AscIfType, AscIfNetworkSize).Sort(publicIfs)
+	OrderedIfAddrBy(AscIfDefault, AscIfType, AscIfNetworkSize).Sort(publicIfs)
 
 	_, publicIfs, err = IfByRFC("6890", publicIfs)
 	if err != nil {
@@ -652,6 +721,245 @@ func IfByNetwork(selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, IfAddrs,
 	return includedIfs, excludedIfs, nil
 }
 
+// IfAddrMath will return a new IfAddr struct with a mutated value.
+func IfAddrMath(operation, value string, inputIfAddr IfAddr) (IfAddr, error) {
+	// Regexp used to enforce the sign being a required part of the grammar for
+	// some values.
+	signRe := signRE.Copy()
+
+	switch strings.ToLower(operation) {
+	case "address":
+		// "address" operates on the IP address and is allowed to overflow or
+		// underflow networks, however it will wrap along the underlying address's
+		// underlying type.
+
+		if !signRe.MatchString(value) {
+			return IfAddr{}, fmt.Errorf("sign (+/-) is required for operation %q", operation)
+		}
+
+		switch sockType := inputIfAddr.SockAddr.Type(); sockType {
+		case TypeIPv4:
+			// 33 == Accept any uint32 value
+			// TODO(seanc@): Add the ability to parse hex
+			i, err := strconv.ParseInt(value, 10, 33)
+			if err != nil {
+				return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
+			}
+
+			ipv4 := *ToIPv4Addr(inputIfAddr.SockAddr)
+			ipv4Uint32 := uint32(ipv4.Address)
+			ipv4Uint32 += uint32(i)
+			return IfAddr{
+				SockAddr: IPv4Addr{
+					Address: IPv4Address(ipv4Uint32),
+					Mask:    ipv4.Mask,
+				},
+				Interface: inputIfAddr.Interface,
+			}, nil
+		case TypeIPv6:
+			// 64 == Accept any int32 value
+			// TODO(seanc@): Add the ability to parse hex.  Also parse a bignum int.
+			i, err := strconv.ParseInt(value, 10, 64)
+			if err != nil {
+				return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
+			}
+
+			ipv6 := *ToIPv6Addr(inputIfAddr.SockAddr)
+			ipv6BigIntA := new(big.Int)
+			ipv6BigIntA.Set(ipv6.Address)
+			ipv6BigIntB := big.NewInt(i)
+
+			ipv6Addr := ipv6BigIntA.Add(ipv6BigIntA, ipv6BigIntB)
+			ipv6Addr.And(ipv6Addr, ipv6HostMask)
+
+			return IfAddr{
+				SockAddr: IPv6Addr{
+					Address: IPv6Address(ipv6Addr),
+					Mask:    ipv6.Mask,
+				},
+				Interface: inputIfAddr.Interface,
+			}, nil
+		default:
+			return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType)
+		}
+	case "network":
+		// "network" operates on the network address.  Positive values start at the
+		// network address and negative values wrap at the network address, which
+		// means a "-1" value on a network will be the broadcast address after
+		// wrapping is applied.
+
+		if !signRe.MatchString(value) {
+			return IfAddr{}, fmt.Errorf("sign (+/-) is required for operation %q", operation)
+		}
+
+		switch sockType := inputIfAddr.SockAddr.Type(); sockType {
+		case TypeIPv4:
+			// 33 == Accept any uint32 value
+			// TODO(seanc@): Add the ability to parse hex
+			i, err := strconv.ParseInt(value, 10, 33)
+			if err != nil {
+				return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
+			}
+
+			ipv4 := *ToIPv4Addr(inputIfAddr.SockAddr)
+			ipv4Uint32 := uint32(ipv4.NetworkAddress())
+
+			// Wrap along network mask boundaries.  EZ-mode wrapping made possible by
+			// use of int64 vs a uint.
+			var wrappedMask int64
+			if i >= 0 {
+				wrappedMask = i
+			} else {
+				wrappedMask = 1 + i + int64(^uint32(ipv4.Mask))
+			}
+
+			ipv4Uint32 = ipv4Uint32 + (uint32(wrappedMask) &^ uint32(ipv4.Mask))
+
+			return IfAddr{
+				SockAddr: IPv4Addr{
+					Address: IPv4Address(ipv4Uint32),
+					Mask:    ipv4.Mask,
+				},
+				Interface: inputIfAddr.Interface,
+			}, nil
+		case TypeIPv6:
+			// 64 == Accept any int32 value
+			// TODO(seanc@): Add the ability to parse hex.  Also parse a bignum int.
+			i, err := strconv.ParseInt(value, 10, 64)
+			if err != nil {
+				return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
+			}
+
+			ipv6 := *ToIPv6Addr(inputIfAddr.SockAddr)
+			ipv6BigInt := new(big.Int)
+			ipv6BigInt.Set(ipv6.NetworkAddress())
+
+			mask := new(big.Int)
+			mask.Set(ipv6.Mask)
+			if i > 0 {
+				wrappedMask := new(big.Int)
+				wrappedMask.SetInt64(i)
+
+				wrappedMask.AndNot(wrappedMask, mask)
+				ipv6BigInt.Add(ipv6BigInt, wrappedMask)
+			} else {
+				// Mask off any bits that exceed the network size.  Subtract the
+				// wrappedMask from the last usable - 1
+				wrappedMask := new(big.Int)
+				wrappedMask.SetInt64(-1 * i)
+				wrappedMask.Sub(wrappedMask, big.NewInt(1))
+
+				wrappedMask.AndNot(wrappedMask, mask)
+
+				lastUsable := new(big.Int)
+				lastUsable.Set(ipv6.LastUsable().(IPv6Addr).Address)
+
+				ipv6BigInt = lastUsable.Sub(lastUsable, wrappedMask)
+			}
+
+			return IfAddr{
+				SockAddr: IPv6Addr{
+					Address: IPv6Address(ipv6BigInt),
+					Mask:    ipv6.Mask,
+				},
+				Interface: inputIfAddr.Interface,
+			}, nil
+		default:
+			return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType)
+		}
+	case "mask":
+		// "mask" operates on the IP address and returns the IP address on
+		// which the given integer mask has been applied. If the applied mask
+		// corresponds to a larger network than the mask of the IP address,
+		// the latter will be replaced by the former.
+		switch sockType := inputIfAddr.SockAddr.Type(); sockType {
+		case TypeIPv4:
+			i, err := strconv.ParseUint(value, 10, 32)
+			if err != nil {
+				return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
+			}
+
+			if i > 32 {
+				return IfAddr{}, fmt.Errorf("parameter for operation %q on ipv4 addresses must be between 0 and 32", operation)
+			}
+
+			ipv4 := *ToIPv4Addr(inputIfAddr.SockAddr)
+
+			ipv4Mask := net.CIDRMask(int(i), 32)
+			ipv4MaskUint32 := binary.BigEndian.Uint32(ipv4Mask)
+
+			maskedIpv4 := ipv4.NetIP().Mask(ipv4Mask)
+			maskedIpv4Uint32 := binary.BigEndian.Uint32(maskedIpv4)
+
+			maskedIpv4MaskUint32 := uint32(ipv4.Mask)
+
+			if ipv4MaskUint32 < maskedIpv4MaskUint32 {
+				maskedIpv4MaskUint32 = ipv4MaskUint32
+			}
+
+			return IfAddr{
+				SockAddr: IPv4Addr{
+					Address: IPv4Address(maskedIpv4Uint32),
+					Mask:    IPv4Mask(maskedIpv4MaskUint32),
+				},
+				Interface: inputIfAddr.Interface,
+			}, nil
+		case TypeIPv6:
+			i, err := strconv.ParseUint(value, 10, 32)
+			if err != nil {
+				return IfAddr{}, fmt.Errorf("unable to convert %q to int for operation %q: %v", value, operation, err)
+			}
+
+			if i > 128 {
+				return IfAddr{}, fmt.Errorf("parameter for operation %q on ipv6 addresses must be between 0 and 64", operation)
+			}
+
+			ipv6 := *ToIPv6Addr(inputIfAddr.SockAddr)
+
+			ipv6Mask := net.CIDRMask(int(i), 128)
+			ipv6MaskBigInt := new(big.Int)
+			ipv6MaskBigInt.SetBytes(ipv6Mask)
+
+			maskedIpv6 := ipv6.NetIP().Mask(ipv6Mask)
+			maskedIpv6BigInt := new(big.Int)
+			maskedIpv6BigInt.SetBytes(maskedIpv6)
+
+			maskedIpv6MaskBigInt := new(big.Int)
+			maskedIpv6MaskBigInt.Set(ipv6.Mask)
+
+			if ipv6MaskBigInt.Cmp(maskedIpv6MaskBigInt) == -1 {
+				maskedIpv6MaskBigInt = ipv6MaskBigInt
+			}
+
+			return IfAddr{
+				SockAddr: IPv6Addr{
+					Address: IPv6Address(maskedIpv6BigInt),
+					Mask:    IPv6Mask(maskedIpv6MaskBigInt),
+				},
+				Interface: inputIfAddr.Interface,
+			}, nil
+		default:
+			return IfAddr{}, fmt.Errorf("unsupported type for operation %q: %T", operation, sockType)
+		}
+	default:
+		return IfAddr{}, fmt.Errorf("unsupported math operation: %q", operation)
+	}
+}
+
+// IfAddrsMath will apply an IfAddrMath operation each IfAddr struct.  Any
+// failure will result in zero results.
+func IfAddrsMath(operation, value string, inputIfAddrs IfAddrs) (IfAddrs, error) {
+	outputAddrs := make(IfAddrs, 0, len(inputIfAddrs))
+	for _, ifAddr := range inputIfAddrs {
+		result, err := IfAddrMath(operation, value, ifAddr)
+		if err != nil {
+			return IfAddrs{}, fmt.Errorf("unable to perform an IPMath operation on %s: %v", ifAddr, err)
+		}
+		outputAddrs = append(outputAddrs, result)
+	}
+	return outputAddrs, nil
+}
+
 // IncludeIfs returns an IfAddrs based on the passed in selector.
 func IncludeIfs(selectorName, selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) {
 	var includedIfs IfAddrs
@@ -736,6 +1044,10 @@ func SortIfBy(selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) {
 			sortFuncs[i] = AscIfAddress
 		case "-address":
 			sortFuncs[i] = DescIfAddress
+		case "+default", "default":
+			sortFuncs[i] = AscIfDefault
+		case "-default":
+			sortFuncs[i] = DescIfDefault
 		case "+name", "name":
 			// The "name" selector returns an array of IfAddrs
 			// ordered by the interface name.
@@ -886,7 +1198,7 @@ func parseDefaultIfNameFromRoute(routeOut string) (string, error) {
 // Linux.
 func parseDefaultIfNameFromIPCmd(routeOut string) (string, error) {
 	lines := strings.Split(routeOut, "\n")
-	re := regexp.MustCompile(`[\s]+`)
+	re := whitespaceRE.Copy()
 	for _, line := range lines {
 		kvs := re.Split(line, -1)
 		if len(kvs) < 5 {
@@ -929,7 +1241,7 @@ func parseDefaultIfNameWindows(routeOut, ipconfigOut string) (string, error) {
 // support added.
 func parseDefaultIPAddrWindowsRoute(routeOut string) (string, error) {
 	lines := strings.Split(routeOut, "\n")
-	re := regexp.MustCompile(`[\s]+`)
+	re := whitespaceRE.Copy()
 	for _, line := range lines {
 		kvs := re.Split(strings.TrimSpace(line), -1)
 		if len(kvs) < 3 {
@@ -949,17 +1261,17 @@ func parseDefaultIPAddrWindowsRoute(routeOut string) (string, error) {
 // interface name forwarding traffic to the default gateway.
 func parseDefaultIfNameWindowsIPConfig(defaultIPAddr, routeOut string) (string, error) {
 	lines := strings.Split(routeOut, "\n")
-	ifNameRE := regexp.MustCompile(`^Ethernet adapter ([^\s:]+):`)
-	ipAddrRE := regexp.MustCompile(`^   IPv[46] Address\. \. \. \. \. \. \. \. \. \. \. : ([^\s]+)`)
+	ifNameRe := ifNameRE.Copy()
+	ipAddrRe := ipAddrRE.Copy()
 	var ifName string
 	for _, line := range lines {
-		switch ifNameMatches := ifNameRE.FindStringSubmatch(line); {
+		switch ifNameMatches := ifNameRe.FindStringSubmatch(line); {
 		case len(ifNameMatches) > 1:
 			ifName = ifNameMatches[1]
 			continue
 		}
 
-		switch ipAddrMatches := ipAddrRE.FindStringSubmatch(line); {
+		switch ipAddrMatches := ipAddrRe.FindStringSubmatch(line); {
 		case len(ipAddrMatches) > 1 && ipAddrMatches[1] == defaultIPAddr:
 			return ifName, nil
 		}

+ 2 - 1
libnetwork/vendor/github.com/hashicorp/go-sockaddr/ipv4addr.go

@@ -58,7 +58,8 @@ func NewIPv4Addr(ipv4Str string) (IPv4Addr, error) {
 	// Strip off any bogus hex-encoded netmasks that will be mis-parsed by Go.  In
 	// particular, clients with the Barracuda VPN client will see something like:
 	// `192.168.3.51/00ffffff` as their IP address.
-	if match := trailingHexNetmaskRE.FindStringIndex(ipv4Str); match != nil {
+	trailingHexNetmaskRe := trailingHexNetmaskRE.Copy()
+	if match := trailingHexNetmaskRe.FindStringIndex(ipv4Str); match != nil {
 		ipv4Str = ipv4Str[:match[0]]
 	}
 

+ 1 - 0
libnetwork/vendor/github.com/hashicorp/go-sockaddr/rfc.go

@@ -3,6 +3,7 @@ package sockaddr
 // ForwardingBlacklist is a faux RFC that includes a list of non-forwardable IP
 // blocks.
 const ForwardingBlacklist = 4294967295
+const ForwardingBlacklistRFC = "4294967295"
 
 // IsRFC tests to see if an SockAddr matches the specified RFC
 func IsRFC(rfcNum uint, sa SockAddr) bool {

+ 9 - 6
libnetwork/vendor/github.com/hashicorp/go-sockaddr/route_info_linux.go

@@ -5,10 +5,6 @@ import (
 	"os/exec"
 )
 
-var cmds map[string][]string = map[string][]string{
-	"ip": {"/sbin/ip", "route"},
-}
-
 type routeInfo struct {
 	cmds map[string][]string
 }
@@ -16,15 +12,22 @@ type routeInfo struct {
 // NewRouteInfo returns a Linux-specific implementation of the RouteInfo
 // interface.
 func NewRouteInfo() (routeInfo, error) {
+	// CoreOS Container Linux moved ip to /usr/bin/ip, so look it up on
+	// $PATH and fallback to /sbin/ip on error.
+	path, _ := exec.LookPath("ip")
+	if path == "" {
+		path = "/sbin/ip"
+	}
+
 	return routeInfo{
-		cmds: cmds,
+		cmds: map[string][]string{"ip": {path, "route"}},
 	}, nil
 }
 
 // GetDefaultInterfaceName returns the interface name attached to the default
 // route on the default interface.
 func (ri routeInfo) GetDefaultInterfaceName() (string, error) {
-	out, err := exec.Command(cmds["ip"][0], cmds["ip"][1:]...).Output()
+	out, err := exec.Command(ri.cmds["ip"][0], ri.cmds["ip"][1:]...).Output()
 	if err != nil {
 		return "", err
 	}

+ 28 - 0
libnetwork/vendor/github.com/hashicorp/go-sockaddr/sockaddr.go

@@ -1,6 +1,7 @@
 package sockaddr
 
 import (
+	"encoding/json"
 	"fmt"
 	"strings"
 )
@@ -176,3 +177,30 @@ func sockAddrInit() {
 func SockAddrAttrs() []AttrName {
 	return sockAddrAttrs
 }
+
+// Although this is pretty trivial to do in a program, having the logic here is
+// useful all around. Note that this marshals into a *string* -- the underlying
+// string representation of the sockaddr. If you then unmarshal into this type
+// in Go, all will work as expected, but externally you can take what comes out
+// and use the string value directly.
+type SockAddrMarshaler struct {
+	SockAddr
+}
+
+func (s *SockAddrMarshaler) MarshalJSON() ([]byte, error) {
+	return json.Marshal(s.SockAddr.String())
+}
+
+func (s *SockAddrMarshaler) UnmarshalJSON(in []byte) error {
+	var str string
+	err := json.Unmarshal(in, &str)
+	if err != nil {
+		return err
+	}
+	sa, err := NewSockAddr(str)
+	if err != nil {
+		return err
+	}
+	s.SockAddr = sa
+	return nil
+}