func IfByNetwork(selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, IfAddrs, error) {
	var includedIfs, excludedIfs IfAddrs
	for _, netStr := range strings.Split(selectorParam, "|") {
		netAddr, err := NewIPAddr(netStr)
		if err != nil {
			return nil, nil, fmt.Errorf("unable to create an IP address from %+q: %v", netStr, err)
		}
		for _, ifAddr := range inputIfAddrs {
			if netAddr.Contains(ifAddr.SockAddr) {
				includedIfs = append(includedIfs, ifAddr)
			} else {
				excludedIfs = append(excludedIfs, ifAddr)
			}
		}
	}
	return includedIfs, excludedIfs, nil
}
IfByNetwork returns an IfAddrs that are equal to or included within the
network passed in by selector.
package sockaddr
import (
	"encoding/binary"
	"errors"
	"fmt"
	"math/big"
	"net"
	"regexp"
	"sort"
	"strconv"
	"strings"
)
var (
	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]+)`)
)
type IfAddrs []IfAddr
func (ifs IfAddrs) Len() int { return len(ifs) }
type CmpIfAddrFunc func(p1, p2 *IfAddr) int
type multiIfAddrSorter struct {
	ifAddrs IfAddrs
	cmp     []CmpIfAddrFunc
}
func (ms *multiIfAddrSorter) Sort(ifAddrs IfAddrs) {
	ms.ifAddrs = ifAddrs
	sort.Sort(ms)
}
func OrderedIfAddrBy(cmpFuncs ...CmpIfAddrFunc) *multiIfAddrSorter {
	return &multiIfAddrSorter{
		cmp: cmpFuncs,
	}
}
func (ms *multiIfAddrSorter) Len() int {
	return len(ms.ifAddrs)
}
func (ms *multiIfAddrSorter) Less(i, j int) bool {
	p, q := &ms.ifAddrs[i], &ms.ifAddrs[j]
	var k int
	for k = 0; k < len(ms.cmp)-1; k++ {
		cmp := ms.cmp[k]
		x := cmp(p, q)
		switch x {
		case -1:
			return true
		case 1:
			return false
		}
	}
	switch ms.cmp[k](p, q) {
	case -1:
		return true
	case 1:
		return false
	default:
		return false
		panic("undefined sort order for remaining items in the list")
	}
}
func (ms *multiIfAddrSorter) Swap(i, j int) {
	ms.ifAddrs[i], ms.ifAddrs[j] = ms.ifAddrs[j], ms.ifAddrs[i]
}
func AscIfAddress(p1Ptr, p2Ptr *IfAddr) int {
	return AscAddress(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
}
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
	}
}
func AscIfName(p1Ptr, p2Ptr *IfAddr) int {
	return strings.Compare(p1Ptr.Name, p2Ptr.Name)
}
func AscIfNetworkSize(p1Ptr, p2Ptr *IfAddr) int {
	return AscNetworkSize(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
}
func AscIfPort(p1Ptr, p2Ptr *IfAddr) int {
	return AscPort(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
}
func AscIfPrivate(p1Ptr, p2Ptr *IfAddr) int {
	return AscPrivate(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
}
func AscIfType(p1Ptr, p2Ptr *IfAddr) int {
	return AscType(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
}
func DescIfAddress(p1Ptr, p2Ptr *IfAddr) int {
	return -1 * AscAddress(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
}
func DescIfDefault(p1Ptr, p2Ptr *IfAddr) int {
	return -1 * AscIfDefault(p1Ptr, p2Ptr)
}
func DescIfName(p1Ptr, p2Ptr *IfAddr) int {
	return -1 * strings.Compare(p1Ptr.Name, p2Ptr.Name)
}
func DescIfNetworkSize(p1Ptr, p2Ptr *IfAddr) int {
	return -1 * AscNetworkSize(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
}
func DescIfPort(p1Ptr, p2Ptr *IfAddr) int {
	return -1 * AscPort(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
}
func DescIfPrivate(p1Ptr, p2Ptr *IfAddr) int {
	return -1 * AscPrivate(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
}
func DescIfType(p1Ptr, p2Ptr *IfAddr) int {
	return -1 * AscType(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
}
func FilterIfByType(ifAddrs IfAddrs, type_ SockAddrType) (matchedIfs, excludedIfs IfAddrs) {
	excludedIfs = make(IfAddrs, 0, len(ifAddrs))
	matchedIfs = make(IfAddrs, 0, len(ifAddrs))
	for _, ifAddr := range ifAddrs {
		if ifAddr.SockAddr.Type()&type_ != 0 {
			matchedIfs = append(matchedIfs, ifAddr)
		} else {
			excludedIfs = append(excludedIfs, ifAddr)
		}
	}
	return matchedIfs, excludedIfs
}
func IfAttr(selectorName string, ifAddr IfAddr) (string, error) {
	attrName := AttrName(strings.ToLower(selectorName))
	attrVal, err := ifAddr.Attr(attrName)
	return attrVal, err
}
func IfAttrs(selectorName string, ifAddrs IfAddrs) (string, error) {
	if len(ifAddrs) == 0 {
		return "", nil
	}
	attrName := AttrName(strings.ToLower(selectorName))
	attrVal, err := ifAddrs[0].Attr(attrName)
	return attrVal, err
}
func GetAllInterfaces() (IfAddrs, error) {
	ifs, err := net.Interfaces()
	if err != nil {
		return nil, err
	}
	ifAddrs := make(IfAddrs, 0, len(ifs))
	for _, intf := range ifs {
		addrs, err := intf.Addrs()
		if err != nil {
			return nil, err
		}
		for _, addr := range addrs {
			var ipAddr IPAddr
			ipAddr, err = NewIPAddr(addr.String())
			if err != nil {
				return IfAddrs{}, fmt.Errorf("unable to create an IP address from %q", addr.String())
			}
			ifAddr := IfAddr{
				SockAddr:  ipAddr,
				Interface: intf,
			}
			ifAddrs = append(ifAddrs, ifAddr)
		}
	}
	return ifAddrs, nil
}
func GetDefaultInterfaces() (IfAddrs, error) {
	ri, err := NewRouteInfo()
	if err != nil {
		return nil, err
	}
	defaultIfName, err := ri.GetDefaultInterfaceName()
	if err != nil {
		return nil, err
	}
	var defaultIfs, ifAddrs IfAddrs
	ifAddrs, err = GetAllInterfaces()
	for _, ifAddr := range ifAddrs {
		if ifAddr.Name == defaultIfName {
			defaultIfs = append(defaultIfs, ifAddr)
		}
	}
	return defaultIfs, nil
}
func GetPrivateInterfaces() (IfAddrs, error) {
	privateIfs, err := GetAllInterfaces()
	if err != nil {
		return IfAddrs{}, err
	}
	if len(privateIfs) == 0 {
		return IfAddrs{}, nil
	}
	privateIfs, _ = FilterIfByType(privateIfs, TypeIP)
	if len(privateIfs) == 0 {
		return IfAddrs{}, nil
	}
	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(AscIfDefault, AscIfType, AscIfNetworkSize).Sort(privateIfs)
	privateIfs, _, err = IfByRFC("6890", privateIfs)
	if err != nil {
		return IfAddrs{}, err
	} else if len(privateIfs) == 0 {
		return IfAddrs{}, nil
	}
	return privateIfs, nil
}
func GetPublicInterfaces() (IfAddrs, error) {
	publicIfs, err := GetAllInterfaces()
	if err != nil {
		return IfAddrs{}, err
	}
	if len(publicIfs) == 0 {
		return IfAddrs{}, nil
	}
	publicIfs, _ = FilterIfByType(publicIfs, TypeIP)
	if len(publicIfs) == 0 {
		return IfAddrs{}, nil
	}
	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(AscIfDefault, AscIfType, AscIfNetworkSize).Sort(publicIfs)
	_, publicIfs, err = IfByRFC("6890", publicIfs)
	if err != nil {
		return IfAddrs{}, err
	} else if len(publicIfs) == 0 {
		return IfAddrs{}, nil
	}
	return publicIfs, nil
}
func IfByAddress(inputRe string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
	re, err := regexp.Compile(inputRe)
	if err != nil {
		return nil, nil, fmt.Errorf("Unable to compile address regexp %+q: %v", inputRe, err)
	}
	matchedAddrs := make(IfAddrs, 0, len(ifAddrs))
	excludedAddrs := make(IfAddrs, 0, len(ifAddrs))
	for _, addr := range ifAddrs {
		if re.MatchString(addr.SockAddr.String()) {
			matchedAddrs = append(matchedAddrs, addr)
		} else {
			excludedAddrs = append(excludedAddrs, addr)
		}
	}
	return matchedAddrs, excludedAddrs, nil
}
func IfByName(inputRe string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
	re, err := regexp.Compile(inputRe)
	if err != nil {
		return nil, nil, fmt.Errorf("Unable to compile name regexp %+q: %v", inputRe, err)
	}
	matchedAddrs := make(IfAddrs, 0, len(ifAddrs))
	excludedAddrs := make(IfAddrs, 0, len(ifAddrs))
	for _, addr := range ifAddrs {
		if re.MatchString(addr.Name) {
			matchedAddrs = append(matchedAddrs, addr)
		} else {
			excludedAddrs = append(excludedAddrs, addr)
		}
	}
	return matchedAddrs, excludedAddrs, nil
}
func IfByPort(inputRe string, ifAddrs IfAddrs) (matchedIfs, excludedIfs IfAddrs, err error) {
	re, err := regexp.Compile(inputRe)
	if err != nil {
		return nil, nil, fmt.Errorf("Unable to compile port regexp %+q: %v", inputRe, err)
	}
	ipIfs, nonIfs := FilterIfByType(ifAddrs, TypeIP)
	matchedIfs = make(IfAddrs, 0, len(ipIfs))
	excludedIfs = append(IfAddrs(nil), nonIfs...)
	for _, addr := range ipIfs {
		ipAddr := ToIPAddr(addr.SockAddr)
		if ipAddr == nil {
			continue
		}
		port := strconv.FormatInt(int64((*ipAddr).IPPort()), 10)
		if re.MatchString(port) {
			matchedIfs = append(matchedIfs, addr)
		} else {
			excludedIfs = append(excludedIfs, addr)
		}
	}
	return matchedIfs, excludedIfs, nil
}
func IfByRFC(selectorParam string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
	inputRFC, err := strconv.ParseUint(selectorParam, 10, 64)
	if err != nil {
		return IfAddrs{}, IfAddrs{}, fmt.Errorf("unable to parse RFC number %q: %v", selectorParam, err)
	}
	matchedIfAddrs := make(IfAddrs, 0, len(ifAddrs))
	remainingIfAddrs := make(IfAddrs, 0, len(ifAddrs))
	rfcNetMap := KnownRFCs()
	rfcNets, ok := rfcNetMap[uint(inputRFC)]
	if !ok {
		return nil, nil, fmt.Errorf("unsupported RFC %d", inputRFC)
	}
	for _, ifAddr := range ifAddrs {
		var contained bool
		for _, rfcNet := range rfcNets {
			if rfcNet.Contains(ifAddr.SockAddr) {
				matchedIfAddrs = append(matchedIfAddrs, ifAddr)
				contained = true
				break
			}
		}
		if !contained {
			remainingIfAddrs = append(remainingIfAddrs, ifAddr)
		}
	}
	return matchedIfAddrs, remainingIfAddrs, nil
}
func IfByRFCs(selectorParam string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
	var includedIfs, excludedIfs IfAddrs
	for _, rfcStr := range strings.Split(selectorParam, "|") {
		includedRFCIfs, excludedRFCIfs, err := IfByRFC(rfcStr, ifAddrs)
		if err != nil {
			return IfAddrs{}, IfAddrs{}, fmt.Errorf("unable to lookup RFC number %q: %v", rfcStr, err)
		}
		includedIfs = append(includedIfs, includedRFCIfs...)
		excludedIfs = append(excludedIfs, excludedRFCIfs...)
	}
	return includedIfs, excludedIfs, nil
}
func IfByMaskSize(selectorParam string, ifAddrs IfAddrs) (matchedIfs, excludedIfs IfAddrs, err error) {
	maskSize, err := strconv.ParseUint(selectorParam, 10, 64)
	if err != nil {
		return IfAddrs{}, IfAddrs{}, fmt.Errorf("invalid exclude size argument (%q): %v", selectorParam, err)
	}
	ipIfs, nonIfs := FilterIfByType(ifAddrs, TypeIP)
	matchedIfs = make(IfAddrs, 0, len(ipIfs))
	excludedIfs = append(IfAddrs(nil), nonIfs...)
	for _, addr := range ipIfs {
		ipAddr := ToIPAddr(addr.SockAddr)
		if ipAddr == nil {
			return IfAddrs{}, IfAddrs{}, fmt.Errorf("unable to filter mask sizes on non-IP type %s: %v", addr.SockAddr.Type().String(), addr.SockAddr.String())
		}
		switch {
		case (*ipAddr).Type()&TypeIPv4 != 0 && maskSize > 32:
			return IfAddrs{}, IfAddrs{}, fmt.Errorf("mask size out of bounds for IPv4 address: %d", maskSize)
		case (*ipAddr).Type()&TypeIPv6 != 0 && maskSize > 128:
			return IfAddrs{}, IfAddrs{}, fmt.Errorf("mask size out of bounds for IPv6 address: %d", maskSize)
		}
		if (*ipAddr).Maskbits() == int(maskSize) {
			matchedIfs = append(matchedIfs, addr)
		} else {
			excludedIfs = append(excludedIfs, addr)
		}
	}
	return matchedIfs, excludedIfs, nil
}
func IfByType(inputTypes string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
	matchingIfAddrs := make(IfAddrs, 0, len(ifAddrs))
	remainingIfAddrs := make(IfAddrs, 0, len(ifAddrs))
	ifTypes := strings.Split(strings.ToLower(inputTypes), "|")
	for _, ifType := range ifTypes {
		switch ifType {
		case "ip", "ipv4", "ipv6", "unix":
		default:
			return nil, nil, fmt.Errorf("unsupported type %q %q", ifType, inputTypes)
		}
	}
	for _, ifAddr := range ifAddrs {
		for _, ifType := range ifTypes {
			var matched bool
			switch {
			case ifType == "ip" && ifAddr.SockAddr.Type()&TypeIP != 0:
				matched = true
			case ifType == "ipv4" && ifAddr.SockAddr.Type()&TypeIPv4 != 0:
				matched = true
			case ifType == "ipv6" && ifAddr.SockAddr.Type()&TypeIPv6 != 0:
				matched = true
			case ifType == "unix" && ifAddr.SockAddr.Type()&TypeUnix != 0:
				matched = true
			}
			if matched {
				matchingIfAddrs = append(matchingIfAddrs, ifAddr)
			} else {
				remainingIfAddrs = append(remainingIfAddrs, ifAddr)
			}
		}
	}
	return matchingIfAddrs, remainingIfAddrs, nil
}
func IfByFlag(inputFlags string, ifAddrs IfAddrs) (matched, remainder IfAddrs, err error) {
	matchedAddrs := make(IfAddrs, 0, len(ifAddrs))
	excludedAddrs := make(IfAddrs, 0, len(ifAddrs))
	var wantForwardable,
		wantGlobalUnicast,
		wantInterfaceLocalMulticast,
		wantLinkLocalMulticast,
		wantLinkLocalUnicast,
		wantLoopback,
		wantMulticast,
		wantUnspecified bool
	var ifFlags net.Flags
	var checkFlags, checkAttrs bool
	for _, flagName := range strings.Split(strings.ToLower(inputFlags), "|") {
		switch flagName {
		case "broadcast":
			checkFlags = true
			ifFlags = ifFlags | net.FlagBroadcast
		case "down":
			checkFlags = true
			ifFlags = (ifFlags &^ net.FlagUp)
		case "forwardable":
			checkAttrs = true
			wantForwardable = true
		case "global unicast":
			checkAttrs = true
			wantGlobalUnicast = true
		case "interface-local multicast":
			checkAttrs = true
			wantInterfaceLocalMulticast = true
		case "link-local multicast":
			checkAttrs = true
			wantLinkLocalMulticast = true
		case "link-local unicast":
			checkAttrs = true
			wantLinkLocalUnicast = true
		case "loopback":
			checkAttrs = true
			checkFlags = true
			ifFlags = ifFlags | net.FlagLoopback
			wantLoopback = true
		case "multicast":
			checkAttrs = true
			checkFlags = true
			ifFlags = ifFlags | net.FlagMulticast
			wantMulticast = true
		case "point-to-point":
			checkFlags = true
			ifFlags = ifFlags | net.FlagPointToPoint
		case "unspecified":
			checkAttrs = true
			wantUnspecified = true
		case "up":
			checkFlags = true
			ifFlags = ifFlags | net.FlagUp
		default:
			return nil, nil, fmt.Errorf("Unknown interface flag: %+q", flagName)
		}
	}
	for _, ifAddr := range ifAddrs {
		var matched bool
		if checkFlags && ifAddr.Interface.Flags&ifFlags == ifFlags {
			matched = true
		}
		if checkAttrs {
			if ip := ToIPAddr(ifAddr.SockAddr); ip != nil {
				netIP := (*ip).NetIP()
				switch {
				case wantGlobalUnicast && netIP.IsGlobalUnicast():
					matched = true
				case wantInterfaceLocalMulticast && netIP.IsInterfaceLocalMulticast():
					matched = true
				case wantLinkLocalMulticast && netIP.IsLinkLocalMulticast():
					matched = true
				case wantLinkLocalUnicast && netIP.IsLinkLocalUnicast():
					matched = true
				case wantLoopback && netIP.IsLoopback():
					matched = true
				case wantMulticast && netIP.IsMulticast():
					matched = true
				case wantUnspecified && netIP.IsUnspecified():
					matched = true
				case wantForwardable && !IsRFC(ForwardingBlacklist, ifAddr.SockAddr):
					matched = true
				}
			}
		}
		if matched {
			matchedAddrs = append(matchedAddrs, ifAddr)
		} else {
			excludedAddrs = append(excludedAddrs, ifAddr)
		}
	}
	return matchedAddrs, excludedAddrs, nil
}