aboutsummaryrefslogtreecommitdiff
path: root/vendor/github.com/hashicorp/go-sockaddr
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/go-sockaddr')
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/GNUmakefile65
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/LICENSE373
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/README.md118
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/doc.go5
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/ifaddr.go254
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/ifaddrs.go1281
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/ifattr.go65
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/ipaddr.go169
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/ipaddrs.go98
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/ipv4addr.go516
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/ipv6addr.go591
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/rfc.go948
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/route_info.go19
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/route_info_bsd.go36
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/route_info_default.go10
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/route_info_linux.go40
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/route_info_solaris.go37
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/route_info_windows.go41
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/sockaddr.go206
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/sockaddrs.go193
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/unixsock.go135
21 files changed, 5200 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/go-sockaddr/GNUmakefile b/vendor/github.com/hashicorp/go-sockaddr/GNUmakefile
new file mode 100644
index 0000000..f3dfd24
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/GNUmakefile
@@ -0,0 +1,65 @@
+TOOLS= golang.org/x/tools/cover
+GOCOVER_TMPFILE?= $(GOCOVER_FILE).tmp
+GOCOVER_FILE?= .cover.out
+GOCOVERHTML?= coverage.html
+FIND=`/usr/bin/which 2> /dev/null gfind find | /usr/bin/grep -v ^no | /usr/bin/head -n 1`
+XARGS=`/usr/bin/which 2> /dev/null gxargs xargs | /usr/bin/grep -v ^no | /usr/bin/head -n 1`
+
+test:: $(GOCOVER_FILE)
+ @$(MAKE) -C cmd/sockaddr test
+
+cover:: coverage_report
+
+$(GOCOVER_FILE)::
+ @${FIND} . -type d ! -path '*cmd*' ! -path '*.git*' -print0 | ${XARGS} -0 -I % sh -ec "cd % && rm -f $(GOCOVER_TMPFILE) && go test -coverprofile=$(GOCOVER_TMPFILE)"
+
+ @echo 'mode: set' > $(GOCOVER_FILE)
+ @${FIND} . -type f ! -path '*cmd*' ! -path '*.git*' -name "$(GOCOVER_TMPFILE)" -print0 | ${XARGS} -0 -n1 cat $(GOCOVER_TMPFILE) | grep -v '^mode: ' >> ${PWD}/$(GOCOVER_FILE)
+
+$(GOCOVERHTML): $(GOCOVER_FILE)
+ go tool cover -html=$(GOCOVER_FILE) -o $(GOCOVERHTML)
+
+coverage_report:: $(GOCOVER_FILE)
+ go tool cover -html=$(GOCOVER_FILE)
+
+audit_tools::
+ @go get -u github.com/golang/lint/golint && echo "Installed golint:"
+ @go get -u github.com/fzipp/gocyclo && echo "Installed gocyclo:"
+ @go get -u github.com/remyoudompheng/go-misc/deadcode && echo "Installed deadcode:"
+ @go get -u github.com/client9/misspell/cmd/misspell && echo "Installed misspell:"
+ @go get -u github.com/gordonklaus/ineffassign && echo "Installed ineffassign:"
+
+audit::
+ deadcode
+ go tool vet -all *.go
+ go tool vet -shadow=true *.go
+ golint *.go
+ ineffassign .
+ gocyclo -over 65 *.go
+ misspell *.go
+
+clean::
+ rm -f $(GOCOVER_FILE) $(GOCOVERHTML)
+
+dev::
+ @go build
+ @$(MAKE) -B -C cmd/sockaddr sockaddr
+
+install::
+ @go install
+ @$(MAKE) -C cmd/sockaddr install
+
+doc::
+ @echo Visit: http://127.0.0.1:6161/pkg/github.com/hashicorp/go-sockaddr/
+ godoc -http=:6161 -goroot $GOROOT
+
+world::
+ @set -e; \
+ for os in solaris darwin freebsd linux windows; do \
+ for arch in amd64; do \
+ printf "Building on %s-%s\n" "$${os}" "$${arch}" ; \
+ env GOOS="$${os}" GOARCH="$${arch}" go build -o /dev/null; \
+ done; \
+ done
+
+ $(MAKE) -C cmd/sockaddr world
diff --git a/vendor/github.com/hashicorp/go-sockaddr/LICENSE b/vendor/github.com/hashicorp/go-sockaddr/LICENSE
new file mode 100644
index 0000000..a612ad9
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/LICENSE
@@ -0,0 +1,373 @@
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
+
+Exhibit B - "Incompatible With Secondary Licenses" Notice
+---------------------------------------------------------
+
+ This Source Code Form is "Incompatible With Secondary Licenses", as
+ defined by the Mozilla Public License, v. 2.0.
diff --git a/vendor/github.com/hashicorp/go-sockaddr/README.md b/vendor/github.com/hashicorp/go-sockaddr/README.md
new file mode 100644
index 0000000..a2e170a
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/README.md
@@ -0,0 +1,118 @@
+# go-sockaddr
+
+## `sockaddr` Library
+
+Socket address convenience functions for Go. `go-sockaddr` is a convenience
+library that makes doing the right thing with IP addresses easy. `go-sockaddr`
+is loosely modeled after the UNIX `sockaddr_t` and creates a union of the family
+of `sockaddr_t` types (see below for an ascii diagram). Library documentation
+is available
+at
+[https://godoc.org/github.com/hashicorp/go-sockaddr](https://godoc.org/github.com/hashicorp/go-sockaddr).
+The primary intent of the library was to make it possible to define heuristics
+for selecting the correct IP addresses when a configuration is evaluated at
+runtime. See
+the
+[docs](https://godoc.org/github.com/hashicorp/go-sockaddr),
+[`template` package](https://godoc.org/github.com/hashicorp/go-sockaddr/template),
+tests,
+and
+[CLI utility](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr)
+for details and hints as to how to use this library.
+
+For example, with this library it is possible to find an IP address that:
+
+* is attached to a default route
+ ([`GetDefaultInterfaces()`](https://godoc.org/github.com/hashicorp/go-sockaddr#GetDefaultInterfaces))
+* is contained within a CIDR block ([`IfByNetwork()`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByNetwork))
+* is an RFC1918 address
+ ([`IfByRFC("1918")`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByRFC))
+* is ordered
+ ([`OrderedIfAddrBy(args)`](https://godoc.org/github.com/hashicorp/go-sockaddr#OrderedIfAddrBy) where
+ `args` includes, but is not limited
+ to,
+ [`AscIfType`](https://godoc.org/github.com/hashicorp/go-sockaddr#AscIfType),
+ [`AscNetworkSize`](https://godoc.org/github.com/hashicorp/go-sockaddr#AscNetworkSize))
+* excludes all IPv6 addresses
+ ([`IfByType("^(IPv4)$")`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByType))
+* is larger than a `/32`
+ ([`IfByMaskSize(32)`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByMaskSize))
+* is not on a `down` interface
+ ([`ExcludeIfs("flags", "down")`](https://godoc.org/github.com/hashicorp/go-sockaddr#ExcludeIfs))
+* preferences an IPv6 address over an IPv4 address
+ ([`SortIfByType()`](https://godoc.org/github.com/hashicorp/go-sockaddr#SortIfByType) +
+ [`ReverseIfAddrs()`](https://godoc.org/github.com/hashicorp/go-sockaddr#ReverseIfAddrs)); and
+* excludes any IP in RFC6890 address
+ ([`IfByRFC("6890")`](https://godoc.org/github.com/hashicorp/go-sockaddr#IfByRFC))
+
+Or any combination or variation therein.
+
+There are also a few simple helper functions such as `GetPublicIP` and
+`GetPrivateIP` which both return strings and select the first public or private
+IP address on the default interface, respectively. Similarly, there is also a
+helper function called `GetInterfaceIP` which returns the first usable IP
+address on the named interface.
+
+## `sockaddr` CLI
+
+Given the possible complexity of the `sockaddr` library, there is a CLI utility
+that accompanies the library, also
+called
+[`sockaddr`](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr).
+The
+[`sockaddr`](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr)
+utility exposes nearly all of the functionality of the library and can be used
+either as an administrative tool or testing tool. To install
+the
+[`sockaddr`](https://github.com/hashicorp/go-sockaddr/tree/master/cmd/sockaddr),
+run:
+
+```text
+$ go get -u github.com/hashicorp/go-sockaddr/cmd/sockaddr
+```
+
+If you're familiar with UNIX's `sockaddr` struct's, the following diagram
+mapping the C `sockaddr` (top) to `go-sockaddr` structs (bottom) and
+interfaces will be helpful:
+
+```
++-------------------------------------------------------+
+| |
+| sockaddr |
+| SockAddr |
+| |
+| +--------------+ +----------------------------------+ |
+| | sockaddr_un | | | |
+| | SockAddrUnix | | sockaddr_in{,6} | |
+| +--------------+ | IPAddr | |
+| | | |
+| | +-------------+ +--------------+ | |
+| | | sockaddr_in | | sockaddr_in6 | | |
+| | | IPv4Addr | | IPv6Addr | | |
+| | +-------------+ +--------------+ | |
+| | | |
+| +----------------------------------+ |
+| |
++-------------------------------------------------------+
+```
+
+## Inspiration and Design
+
+There were many subtle inspirations that led to this design, but the most direct
+inspiration for the filtering syntax was
+OpenBSD's
+[`pf.conf(5)`](https://www.freebsd.org/cgi/man.cgi?query=pf.conf&apropos=0&sektion=0&arch=default&format=html#PARAMETERS) firewall
+syntax that lets you select the first IP address on a given named interface.
+The original problem stemmed from:
+
+* needing to create immutable images using [Packer](https://www.packer.io) that
+ ran the [Consul](https://www.consul.io) process (Consul can only use one IP
+ address at a time);
+* images that may or may not have multiple interfaces or IP addresses at
+ runtime; and
+* we didn't want to rely on configuration management to render out the correct
+ IP address if the VM image was being used in an auto-scaling group.
+
+Instead we needed some way to codify a heuristic that would correctly select the
+right IP address but the input parameters were not known when the image was
+created.
diff --git a/vendor/github.com/hashicorp/go-sockaddr/doc.go b/vendor/github.com/hashicorp/go-sockaddr/doc.go
new file mode 100644
index 0000000..90671de
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/doc.go
@@ -0,0 +1,5 @@
+/*
+Package sockaddr is a Go implementation of the UNIX socket family data types and
+related helper functions.
+*/
+package sockaddr
diff --git a/vendor/github.com/hashicorp/go-sockaddr/ifaddr.go b/vendor/github.com/hashicorp/go-sockaddr/ifaddr.go
new file mode 100644
index 0000000..0811b27
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/ifaddr.go
@@ -0,0 +1,254 @@
+package sockaddr
+
+import "strings"
+
+// ifAddrAttrMap is a map of the IfAddr type-specific attributes.
+var ifAddrAttrMap map[AttrName]func(IfAddr) string
+var ifAddrAttrs []AttrName
+
+func init() {
+ ifAddrAttrInit()
+}
+
+// GetPrivateIP returns a string with a single IP address that is part of RFC
+// 6890 and has a default route. If the system can't determine its IP address
+// or find an RFC 6890 IP address, an empty string will be returned instead.
+// This function is the `eval` equivalent of:
+//
+// ```
+// $ sockaddr eval -r '{{GetPrivateInterfaces | attr "address"}}'
+/// ```
+func GetPrivateIP() (string, error) {
+ privateIfs, err := GetPrivateInterfaces()
+ if err != nil {
+ return "", err
+ }
+ if len(privateIfs) < 1 {
+ return "", nil
+ }
+
+ ifAddr := privateIfs[0]
+ ip := *ToIPAddr(ifAddr.SockAddr)
+ 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.
+// This function is the `eval` equivalent of:
+//
+// ```
+// $ sockaddr eval -r '{{GetPublicInterfaces | attr "address"}}'
+/// ```
+func GetPublicIP() (string, error) {
+ publicIfs, err := GetPublicInterfaces()
+ if err != nil {
+ return "", err
+ } else if len(publicIfs) < 1 {
+ return "", nil
+ }
+
+ ifAddr := publicIfs[0]
+ ip := *ToIPAddr(ifAddr.SockAddr)
+ 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:
+//
+// ```
+// $ sockaddr eval -r '{{GetAllInterfaces | include "name" <<ARG>> | sort "type,size" | include "flag" "forwardable" | attr "address" }}'
+/// ```
+func GetInterfaceIP(namedIfRE string) (string, error) {
+ ifAddrs, err := GetAllInterfaces()
+ if err != nil {
+ return "", err
+ }
+
+ ifAddrs, _, err = IfByName(namedIfRE, ifAddrs)
+ if err != nil {
+ return "", err
+ }
+
+ ifAddrs, _, err = IfByFlag("forwardable", ifAddrs)
+ if err != nil {
+ return "", err
+ }
+
+ ifAddrs, err = SortIfBy("+type,+size", ifAddrs)
+ if err != nil {
+ return "", err
+ }
+
+ if len(ifAddrs) == 0 {
+ return "", err
+ }
+
+ ip := ToIPAddr(ifAddrs[0].SockAddr)
+ if ip == nil {
+ return "", err
+ }
+
+ 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
+}
+
+// IfAddrAttr returns a string representation of an attribute for the given
+// IfAddr.
+func IfAddrAttr(ifAddr IfAddr, attrName AttrName) string {
+ fn, found := ifAddrAttrMap[attrName]
+ if !found {
+ return ""
+ }
+
+ return fn(ifAddr)
+}
+
+// ifAddrAttrInit is called once at init()
+func ifAddrAttrInit() {
+ // Sorted for human readability
+ ifAddrAttrs = []AttrName{
+ "flags",
+ "name",
+ }
+
+ ifAddrAttrMap = map[AttrName]func(ifAddr IfAddr) string{
+ "flags": func(ifAddr IfAddr) string {
+ return ifAddr.Interface.Flags.String()
+ },
+ "name": func(ifAddr IfAddr) string {
+ return ifAddr.Interface.Name
+ },
+ }
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/ifaddrs.go b/vendor/github.com/hashicorp/go-sockaddr/ifaddrs.go
new file mode 100644
index 0000000..2a706c3
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/ifaddrs.go
@@ -0,0 +1,1281 @@
+package sockaddr
+
+import (
+ "encoding/binary"
+ "errors"
+ "fmt"
+ "math/big"
+ "net"
+ "regexp"
+ "sort"
+ "strconv"
+ "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
+
+func (ifs IfAddrs) Len() int { return len(ifs) }
+
+// CmpIfFunc is the function signature that must be met to be used in the
+// OrderedIfAddrBy multiIfAddrSorter
+type CmpIfAddrFunc func(p1, p2 *IfAddr) int
+
+// multiIfAddrSorter implements the Sort interface, sorting the IfAddrs within.
+type multiIfAddrSorter struct {
+ ifAddrs IfAddrs
+ cmp []CmpIfAddrFunc
+}
+
+// Sort sorts the argument slice according to the Cmp functions passed to
+// OrderedIfAddrBy.
+func (ms *multiIfAddrSorter) Sort(ifAddrs IfAddrs) {
+ ms.ifAddrs = ifAddrs
+ sort.Sort(ms)
+}
+
+// OrderedIfAddrBy sorts SockAddr by the list of sort function pointers.
+func OrderedIfAddrBy(cmpFuncs ...CmpIfAddrFunc) *multiIfAddrSorter {
+ return &multiIfAddrSorter{
+ cmp: cmpFuncs,
+ }
+}
+
+// Len is part of sort.Interface.
+func (ms *multiIfAddrSorter) Len() int {
+ return len(ms.ifAddrs)
+}
+
+// Less is part of sort.Interface. It is implemented by looping along the Cmp()
+// functions until it finds a comparison that is either less than or greater
+// than. A return value of 0 defers sorting to the next function in the
+// multisorter (which means the results of sorting may leave the resutls in a
+// non-deterministic order).
+func (ms *multiIfAddrSorter) Less(i, j int) bool {
+ p, q := &ms.ifAddrs[i], &ms.ifAddrs[j]
+ // Try all but the last comparison.
+ var k int
+ for k = 0; k < len(ms.cmp)-1; k++ {
+ cmp := ms.cmp[k]
+ x := cmp(p, q)
+ switch x {
+ case -1:
+ // p < q, so we have a decision.
+ return true
+ case 1:
+ // p > q, so we have a decision.
+ return false
+ }
+ // p == q; try the next comparison.
+ }
+ // All comparisons to here said "equal", so just return whatever the
+ // final comparison reports.
+ switch ms.cmp[k](p, q) {
+ case -1:
+ return true
+ case 1:
+ return false
+ default:
+ // Still a tie! Now what?
+ return false
+ panic("undefined sort order for remaining items in the list")
+ }
+}
+
+// Swap is part of sort.Interface.
+func (ms *multiIfAddrSorter) Swap(i, j int) {
+ ms.ifAddrs[i], ms.ifAddrs[j] = ms.ifAddrs[j], ms.ifAddrs[i]
+}
+
+// AscIfAddress is a sorting function to sort IfAddrs by their respective
+// address type. Non-equal types are deferred in the sort.
+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)
+}
+
+// AscIfNetworkSize is a sorting function to sort IfAddrs by their respective
+// network mask size.
+func AscIfNetworkSize(p1Ptr, p2Ptr *IfAddr) int {
+ return AscNetworkSize(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
+}
+
+// AscIfPort is a sorting function to sort IfAddrs by their respective
+// port type. Non-equal types are deferred in the sort.
+func AscIfPort(p1Ptr, p2Ptr *IfAddr) int {
+ return AscPort(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
+}
+
+// AscIfPrivate is a sorting function to sort IfAddrs by "private" values before
+// "public" values. Both IPv4 and IPv6 are compared against RFC6890 (RFC6890
+// includes, and is not limited to, RFC1918 and RFC6598 for IPv4, and IPv6
+// includes RFC4193).
+func AscIfPrivate(p1Ptr, p2Ptr *IfAddr) int {
+ return AscPrivate(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
+}
+
+// AscIfType is a sorting function to sort IfAddrs by their respective address
+// type. Non-equal types are deferred in the sort.
+func AscIfType(p1Ptr, p2Ptr *IfAddr) int {
+ return AscType(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
+}
+
+// DescIfAddress is identical to AscIfAddress but reverse ordered.
+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)
+}
+
+// DescIfNetworkSize is identical to AscIfNetworkSize but reverse ordered.
+func DescIfNetworkSize(p1Ptr, p2Ptr *IfAddr) int {
+ return -1 * AscNetworkSize(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
+}
+
+// DescIfPort is identical to AscIfPort but reverse ordered.
+func DescIfPort(p1Ptr, p2Ptr *IfAddr) int {
+ return -1 * AscPort(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
+}
+
+// DescIfPrivate is identical to AscIfPrivate but reverse ordered.
+func DescIfPrivate(p1Ptr, p2Ptr *IfAddr) int {
+ return -1 * AscPrivate(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
+}
+
+// DescIfType is identical to AscIfType but reverse ordered.
+func DescIfType(p1Ptr, p2Ptr *IfAddr) int {
+ return -1 * AscType(&p1Ptr.SockAddr, &p2Ptr.SockAddr)
+}
+
+// FilterIfByType filters IfAddrs and returns a list of the matching type
+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
+}
+
+// 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, 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
+ }
+
+ attrName := AttrName(strings.ToLower(selectorName))
+ attrVal, err := ifAddrs[0].Attr(attrName)
+ return attrVal, err
+}
+
+// GetAllInterfaces iterates over all available network interfaces and finds all
+// available IP addresses on each interface and converts them to
+// sockaddr.IPAddrs, and returning the result as an array of IfAddr.
+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
+}
+
+// GetDefaultInterfaces returns IfAddrs of the addresses attached to the default
+// route.
+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
+}
+
+// GetPrivateInterfaces returns an IfAddrs that are part of RFC 6890 and have a
+// default route. If the system can't determine its IP address or find an RFC
+// 6890 IP address, an empty IfAddrs will be returned instead. This function is
+// the `eval` equivalent of:
+//
+// ```
+// $ 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 := 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
+}
+
+// GetPublicInterfaces returns an IfAddrs that are 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 IfAddrs will be returned instead. This
+// function is the `eval` equivalent of:
+//
+// ```
+// $ 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 := 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
+}
+
+// IfByAddress returns a list of matched and non-matched IfAddrs, or an error if
+// the regexp fails to compile.
+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
+}
+
+// IfByName returns a list of matched and non-matched IfAddrs, or an error if
+// the regexp fails to compile.
+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
+}
+
+// IfByPort returns a list of matched and non-matched IfAddrs, or an error if
+// the regexp fails to compile.
+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
+}
+
+// IfByRFC returns a list of matched and non-matched IfAddrs that contain the
+// relevant RFC-specified traits.
+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
+}
+
+// IfByRFCs returns a list of matched and non-matched IfAddrs that contain the
+// relevant RFC-specified traits. Multiple RFCs can be specified and separated
+// by the `|` symbol. No protection is taken to ensure an IfAddr does not end
+// up in both the included and excluded list.
+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
+}
+
+// IfByMaskSize returns a list of matched and non-matched IfAddrs that have the
+// matching mask size.
+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
+}
+
+// IfByType returns a list of matching and non-matching IfAddr that match the
+// specified type. For instance:
+//
+// include "type" "IPv4,IPv6"
+//
+// will include any IfAddrs that is either an IPv4 or IPv6 address. Any
+// addresses on those interfaces that don't match will be included in the
+// remainder results.
+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":
+ // Valid types
+ 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
+}
+
+// IfByFlag returns a list of matching and non-matching IfAddrs that match the
+// specified type. For instance:
+//
+// include "flag" "up,broadcast"
+//
+// will include any IfAddrs that have both the "up" and "broadcast" flags set.
+// Any addresses on those interfaces that don't match will be omitted from the
+// results.
+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
+}
+
+// IfByNetwork returns an IfAddrs that are equal to or included within the
+// network passed in by selector.
+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
+}
+
+// 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
+ var err error
+
+ switch strings.ToLower(selectorName) {
+ case "address":
+ includedIfs, _, err = IfByAddress(selectorParam, inputIfAddrs)
+ case "flag", "flags":
+ includedIfs, _, err = IfByFlag(selectorParam, inputIfAddrs)
+ case "name":
+ includedIfs, _, err = IfByName(selectorParam, inputIfAddrs)
+ case "network":
+ includedIfs, _, err = IfByNetwork(selectorParam, inputIfAddrs)
+ case "port":
+ includedIfs, _, err = IfByPort(selectorParam, inputIfAddrs)
+ case "rfc", "rfcs":
+ includedIfs, _, err = IfByRFCs(selectorParam, inputIfAddrs)
+ case "size":
+ includedIfs, _, err = IfByMaskSize(selectorParam, inputIfAddrs)
+ case "type":
+ includedIfs, _, err = IfByType(selectorParam, inputIfAddrs)
+ default:
+ return IfAddrs{}, fmt.Errorf("invalid include selector %q", selectorName)
+ }
+
+ if err != nil {
+ return IfAddrs{}, err
+ }
+
+ return includedIfs, nil
+}
+
+// ExcludeIfs returns an IfAddrs based on the passed in selector.
+func ExcludeIfs(selectorName, selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) {
+ var excludedIfs IfAddrs
+ var err error
+
+ switch strings.ToLower(selectorName) {
+ case "address":
+ _, excludedIfs, err = IfByAddress(selectorParam, inputIfAddrs)
+ case "flag", "flags":
+ _, excludedIfs, err = IfByFlag(selectorParam, inputIfAddrs)
+ case "name":
+ _, excludedIfs, err = IfByName(selectorParam, inputIfAddrs)
+ case "network":
+ _, excludedIfs, err = IfByNetwork(selectorParam, inputIfAddrs)
+ case "port":
+ _, excludedIfs, err = IfByPort(selectorParam, inputIfAddrs)
+ case "rfc", "rfcs":
+ _, excludedIfs, err = IfByRFCs(selectorParam, inputIfAddrs)
+ case "size":
+ _, excludedIfs, err = IfByMaskSize(selectorParam, inputIfAddrs)
+ case "type":
+ _, excludedIfs, err = IfByType(selectorParam, inputIfAddrs)
+ default:
+ return IfAddrs{}, fmt.Errorf("invalid exclude selector %q", selectorName)
+ }
+
+ if err != nil {
+ return IfAddrs{}, err
+ }
+
+ return excludedIfs, nil
+}
+
+// SortIfBy returns an IfAddrs sorted based on the passed in selector. Multiple
+// sort clauses can be passed in as a comma delimited list without whitespace.
+func SortIfBy(selectorParam string, inputIfAddrs IfAddrs) (IfAddrs, error) {
+ sortedIfs := append(IfAddrs(nil), inputIfAddrs...)
+
+ clauses := strings.Split(selectorParam, ",")
+ sortFuncs := make([]CmpIfAddrFunc, len(clauses))
+
+ for i, clause := range clauses {
+ switch strings.TrimSpace(strings.ToLower(clause)) {
+ case "+address", "address":
+ // The "address" selector returns an array of IfAddrs
+ // ordered by the network address. IfAddrs that are not
+ // comparable will be at the end of the list and in a
+ // non-deterministic order.
+ 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.
+ sortFuncs[i] = AscIfName
+ case "-name":
+ sortFuncs[i] = DescIfName
+ case "+port", "port":
+ // The "port" selector returns an array of IfAddrs
+ // ordered by the port, if included in the IfAddr.
+ // IfAddrs that are not comparable will be at the end of
+ // the list and in a non-deterministic order.
+ sortFuncs[i] = AscIfPort
+ case "-port":
+ sortFuncs[i] = DescIfPort
+ case "+private", "private":
+ // The "private" selector returns an array of IfAddrs
+ // ordered by private addresses first. IfAddrs that are
+ // not comparable will be at the end of the list and in
+ // a non-deterministic order.
+ sortFuncs[i] = AscIfPrivate
+ case "-private":
+ sortFuncs[i] = DescIfPrivate
+ case "+size", "size":
+ // The "size" selector returns an array of IfAddrs
+ // ordered by the size of the network mask, smaller mask
+ // (larger number of hosts per network) to largest
+ // (e.g. a /24 sorts before a /32).
+ sortFuncs[i] = AscIfNetworkSize
+ case "-size":
+ sortFuncs[i] = DescIfNetworkSize
+ case "+type", "type":
+ // The "type" selector returns an array of IfAddrs
+ // ordered by the type of the IfAddr. The sort order is
+ // Unix, IPv4, then IPv6.
+ sortFuncs[i] = AscIfType
+ case "-type":
+ sortFuncs[i] = DescIfType
+ default:
+ // Return an empty list for invalid sort types.
+ return IfAddrs{}, fmt.Errorf("unknown sort type: %q", clause)
+ }
+ }
+
+ OrderedIfAddrBy(sortFuncs...).Sort(sortedIfs)
+
+ return sortedIfs, nil
+}
+
+// UniqueIfAddrsBy creates a unique set of IfAddrs based on the matching
+// selector. UniqueIfAddrsBy assumes the input has already been sorted.
+func UniqueIfAddrsBy(selectorName string, inputIfAddrs IfAddrs) (IfAddrs, error) {
+ attrName := strings.ToLower(selectorName)
+
+ ifs := make(IfAddrs, 0, len(inputIfAddrs))
+ var lastMatch string
+ for _, ifAddr := range inputIfAddrs {
+ var out string
+ switch attrName {
+ case "address":
+ out = ifAddr.SockAddr.String()
+ case "name":
+ out = ifAddr.Name
+ default:
+ return nil, fmt.Errorf("unsupported unique constraint %+q", selectorName)
+ }
+
+ switch {
+ case lastMatch == "", lastMatch != out:
+ lastMatch = out
+ ifs = append(ifs, ifAddr)
+ case lastMatch == out:
+ continue
+ }
+ }
+
+ return ifs, nil
+}
+
+// JoinIfAddrs joins an IfAddrs and returns a string
+func JoinIfAddrs(selectorName string, joinStr string, inputIfAddrs IfAddrs) (string, error) {
+ outputs := make([]string, 0, len(inputIfAddrs))
+ attrName := AttrName(strings.ToLower(selectorName))
+
+ for _, ifAddr := range inputIfAddrs {
+ var attrVal string
+ var err error
+ attrVal, err = ifAddr.Attr(attrName)
+ if err != nil {
+ return "", err
+ }
+ outputs = append(outputs, attrVal)
+ }
+ return strings.Join(outputs, joinStr), nil
+}
+
+// LimitIfAddrs returns a slice of IfAddrs based on the specified limit.
+func LimitIfAddrs(lim uint, in IfAddrs) (IfAddrs, error) {
+ // Clamp the limit to the length of the array
+ if int(lim) > len(in) {
+ lim = uint(len(in))
+ }
+
+ return in[0:lim], nil
+}
+
+// OffsetIfAddrs returns a slice of IfAddrs based on the specified offset.
+func OffsetIfAddrs(off int, in IfAddrs) (IfAddrs, error) {
+ var end bool
+ if off < 0 {
+ end = true
+ off = off * -1
+ }
+
+ if off > len(in) {
+ return IfAddrs{}, fmt.Errorf("unable to seek past the end of the interface array: offset (%d) exceeds the number of interfaces (%d)", off, len(in))
+ }
+
+ if end {
+ return in[len(in)-off:], nil
+ }
+ return in[off:], nil
+}
+
+func (ifAddr IfAddr) String() string {
+ return fmt.Sprintf("%s %v", ifAddr.SockAddr, ifAddr.Interface)
+}
+
+// parseDefaultIfNameFromRoute parses standard route(8)'s output for the *BSDs
+// and Solaris.
+func parseDefaultIfNameFromRoute(routeOut string) (string, error) {
+ lines := strings.Split(routeOut, "\n")
+ for _, line := range lines {
+ kvs := strings.SplitN(line, ":", 2)
+ if len(kvs) != 2 {
+ continue
+ }
+
+ if strings.TrimSpace(kvs[0]) == "interface" {
+ ifName := strings.TrimSpace(kvs[1])
+ return ifName, nil
+ }
+ }
+
+ return "", errors.New("No default interface found")
+}
+
+// parseDefaultIfNameFromIPCmd parses the default interface from ip(8) for
+// Linux.
+func parseDefaultIfNameFromIPCmd(routeOut string) (string, error) {
+ lines := strings.Split(routeOut, "\n")
+ re := whitespaceRE.Copy()
+ for _, line := range lines {
+ kvs := re.Split(line, -1)
+ if len(kvs) < 5 {
+ continue
+ }
+
+ if kvs[0] == "default" &&
+ kvs[1] == "via" &&
+ kvs[3] == "dev" {
+ ifName := strings.TrimSpace(kvs[4])
+ return ifName, nil
+ }
+ }
+
+ return "", errors.New("No default interface found")
+}
+
+// parseDefaultIfNameWindows parses the default interface from `netstat -rn` and
+// `ipconfig` on Windows.
+func parseDefaultIfNameWindows(routeOut, ipconfigOut string) (string, error) {
+ defaultIPAddr, err := parseDefaultIPAddrWindowsRoute(routeOut)
+ if err != nil {
+ return "", err
+ }
+
+ ifName, err := parseDefaultIfNameWindowsIPConfig(defaultIPAddr, ipconfigOut)
+ if err != nil {
+ return "", err
+ }
+
+ return ifName, nil
+}
+
+// parseDefaultIPAddrWindowsRoute parses the IP address on the default interface
+// `netstat -rn`.
+//
+// NOTES(sean): Only IPv4 addresses are parsed at this time. If you have an
+// IPv6 connected host, submit an issue on github.com/hashicorp/go-sockaddr with
+// the output from `netstat -rn`, `ipconfig`, and version of Windows to see IPv6
+// support added.
+func parseDefaultIPAddrWindowsRoute(routeOut string) (string, error) {
+ lines := strings.Split(routeOut, "\n")
+ re := whitespaceRE.Copy()
+ for _, line := range lines {
+ kvs := re.Split(strings.TrimSpace(line), -1)
+ if len(kvs) < 3 {
+ continue
+ }
+
+ if kvs[0] == "0.0.0.0" && kvs[1] == "0.0.0.0" {
+ defaultIPAddr := strings.TrimSpace(kvs[3])
+ return defaultIPAddr, nil
+ }
+ }
+
+ return "", errors.New("No IP on default interface found")
+}
+
+// parseDefaultIfNameWindowsIPConfig parses the output of `ipconfig` to find the
+// interface name forwarding traffic to the default gateway.
+func parseDefaultIfNameWindowsIPConfig(defaultIPAddr, routeOut string) (string, error) {
+ lines := strings.Split(routeOut, "\n")
+ ifNameRe := ifNameRE.Copy()
+ ipAddrRe := ipAddrRE.Copy()
+ var ifName string
+ for _, line := range lines {
+ switch ifNameMatches := ifNameRe.FindStringSubmatch(line); {
+ case len(ifNameMatches) > 1:
+ ifName = ifNameMatches[1]
+ continue
+ }
+
+ switch ipAddrMatches := ipAddrRe.FindStringSubmatch(line); {
+ case len(ipAddrMatches) > 1 && ipAddrMatches[1] == defaultIPAddr:
+ return ifName, nil
+ }
+ }
+
+ return "", errors.New("No default interface found with matching IP")
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/ifattr.go b/vendor/github.com/hashicorp/go-sockaddr/ifattr.go
new file mode 100644
index 0000000..6984cb4
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/ifattr.go
@@ -0,0 +1,65 @@
+package sockaddr
+
+import (
+ "fmt"
+ "net"
+)
+
+// IfAddr is a union of a SockAddr and a net.Interface.
+type IfAddr struct {
+ SockAddr
+ net.Interface
+}
+
+// Attr returns the named attribute as a string
+func (ifAddr IfAddr) Attr(attrName AttrName) (string, error) {
+ val := IfAddrAttr(ifAddr, attrName)
+ if val != "" {
+ return val, nil
+ }
+
+ return Attr(ifAddr.SockAddr, attrName)
+}
+
+// Attr returns the named attribute as a string
+func Attr(sa SockAddr, attrName AttrName) (string, error) {
+ switch sockType := sa.Type(); {
+ case sockType&TypeIP != 0:
+ ip := *ToIPAddr(sa)
+ attrVal := IPAddrAttr(ip, attrName)
+ if attrVal != "" {
+ return attrVal, nil
+ }
+
+ if sockType == TypeIPv4 {
+ ipv4 := *ToIPv4Addr(sa)
+ attrVal := IPv4AddrAttr(ipv4, attrName)
+ if attrVal != "" {
+ return attrVal, nil
+ }
+ } else if sockType == TypeIPv6 {
+ ipv6 := *ToIPv6Addr(sa)
+ attrVal := IPv6AddrAttr(ipv6, attrName)
+ if attrVal != "" {
+ return attrVal, nil
+ }
+ }
+
+ case sockType == TypeUnix:
+ us := *ToUnixSock(sa)
+ attrVal := UnixSockAttr(us, attrName)
+ if attrVal != "" {
+ return attrVal, nil
+ }
+ }
+
+ // Non type-specific attributes
+ switch attrName {
+ case "string":
+ return sa.String(), nil
+ case "type":
+ return sa.Type().String(), nil
+ }
+
+ return "", fmt.Errorf("unsupported attribute name %q", attrName)
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/ipaddr.go b/vendor/github.com/hashicorp/go-sockaddr/ipaddr.go
new file mode 100644
index 0000000..b47d15c
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/ipaddr.go
@@ -0,0 +1,169 @@
+package sockaddr
+
+import (
+ "fmt"
+ "math/big"
+ "net"
+ "strings"
+)
+
+// Constants for the sizes of IPv3, IPv4, and IPv6 address types.
+const (
+ IPv3len = 6
+ IPv4len = 4
+ IPv6len = 16
+)
+
+// IPAddr is a generic IP address interface for IPv4 and IPv6 addresses,
+// networks, and socket endpoints.
+type IPAddr interface {
+ SockAddr
+ AddressBinString() string
+ AddressHexString() string
+ Cmp(SockAddr) int
+ CmpAddress(SockAddr) int
+ CmpPort(SockAddr) int
+ FirstUsable() IPAddr
+ Host() IPAddr
+ IPPort() IPPort
+ LastUsable() IPAddr
+ Maskbits() int
+ NetIP() *net.IP
+ NetIPMask() *net.IPMask
+ NetIPNet() *net.IPNet
+ Network() IPAddr
+ Octets() []int
+}
+
+// IPPort is the type for an IP port number for the TCP and UDP IP transports.
+type IPPort uint16
+
+// IPPrefixLen is a typed integer representing the prefix length for a given
+// IPAddr.
+type IPPrefixLen byte
+
+// ipAddrAttrMap is a map of the IPAddr type-specific attributes.
+var ipAddrAttrMap map[AttrName]func(IPAddr) string
+var ipAddrAttrs []AttrName
+
+func init() {
+ ipAddrInit()
+}
+
+// NewIPAddr creates a new IPAddr from a string. Returns nil if the string is
+// not an IPv4 or an IPv6 address.
+func NewIPAddr(addr string) (IPAddr, error) {
+ ipv4Addr, err := NewIPv4Addr(addr)
+ if err == nil {
+ return ipv4Addr, nil
+ }
+
+ ipv6Addr, err := NewIPv6Addr(addr)
+ if err == nil {
+ return ipv6Addr, nil
+ }
+
+ return nil, fmt.Errorf("invalid IPAddr %v", addr)
+}
+
+// IPAddrAttr returns a string representation of an attribute for the given
+// IPAddr.
+func IPAddrAttr(ip IPAddr, selector AttrName) string {
+ fn, found := ipAddrAttrMap[selector]
+ if !found {
+ return ""
+ }
+
+ return fn(ip)
+}
+
+// IPAttrs returns a list of attributes supported by the IPAddr type
+func IPAttrs() []AttrName {
+ return ipAddrAttrs
+}
+
+// MustIPAddr is a helper method that must return an IPAddr or panic on invalid
+// input.
+func MustIPAddr(addr string) IPAddr {
+ ip, err := NewIPAddr(addr)
+ if err != nil {
+ panic(fmt.Sprintf("Unable to create an IPAddr from %+q: %v", addr, err))
+ }
+ return ip
+}
+
+// ipAddrInit is called once at init()
+func ipAddrInit() {
+ // Sorted for human readability
+ ipAddrAttrs = []AttrName{
+ "host",
+ "address",
+ "port",
+ "netmask",
+ "network",
+ "mask_bits",
+ "binary",
+ "hex",
+ "first_usable",
+ "last_usable",
+ "octets",
+ }
+
+ ipAddrAttrMap = map[AttrName]func(ip IPAddr) string{
+ "address": func(ip IPAddr) string {
+ return ip.NetIP().String()
+ },
+ "binary": func(ip IPAddr) string {
+ return ip.AddressBinString()
+ },
+ "first_usable": func(ip IPAddr) string {
+ return ip.FirstUsable().String()
+ },
+ "hex": func(ip IPAddr) string {
+ return ip.AddressHexString()
+ },
+ "host": func(ip IPAddr) string {
+ return ip.Host().String()
+ },
+ "last_usable": func(ip IPAddr) string {
+ return ip.LastUsable().String()
+ },
+ "mask_bits": func(ip IPAddr) string {
+ return fmt.Sprintf("%d", ip.Maskbits())
+ },
+ "netmask": func(ip IPAddr) string {
+ switch v := ip.(type) {
+ case IPv4Addr:
+ ipv4Mask := IPv4Addr{
+ Address: IPv4Address(v.Mask),
+ Mask: IPv4HostMask,
+ }
+ return ipv4Mask.String()
+ case IPv6Addr:
+ ipv6Mask := new(big.Int)
+ ipv6Mask.Set(v.Mask)
+ ipv6MaskAddr := IPv6Addr{
+ Address: IPv6Address(ipv6Mask),
+ Mask: ipv6HostMask,
+ }
+ return ipv6MaskAddr.String()
+ default:
+ return fmt.Sprintf("<unsupported type: %T>", ip)
+ }
+ },
+ "network": func(ip IPAddr) string {
+ return ip.Network().NetIP().String()
+ },
+ "octets": func(ip IPAddr) string {
+ octets := ip.Octets()
+ octetStrs := make([]string, 0, len(octets))
+ for _, octet := range octets {
+ octetStrs = append(octetStrs, fmt.Sprintf("%d", octet))
+ }
+ return strings.Join(octetStrs, " ")
+ },
+ "port": func(ip IPAddr) string {
+ return fmt.Sprintf("%d", ip.IPPort())
+ },
+ }
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/ipaddrs.go b/vendor/github.com/hashicorp/go-sockaddr/ipaddrs.go
new file mode 100644
index 0000000..6eeb7dd
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/ipaddrs.go
@@ -0,0 +1,98 @@
+package sockaddr
+
+import "bytes"
+
+type IPAddrs []IPAddr
+
+func (s IPAddrs) Len() int { return len(s) }
+func (s IPAddrs) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// // SortIPAddrsByCmp is a type that satisfies sort.Interface and can be used
+// // by the routines in this package. The SortIPAddrsByCmp type is used to
+// // sort IPAddrs by Cmp()
+// type SortIPAddrsByCmp struct{ IPAddrs }
+
+// // Less reports whether the element with index i should sort before the
+// // element with index j.
+// func (s SortIPAddrsByCmp) Less(i, j int) bool {
+// // Sort by Type, then address, then port number.
+// return Less(s.IPAddrs[i], s.IPAddrs[j])
+// }
+
+// SortIPAddrsBySpecificMaskLen is a type that satisfies sort.Interface and
+// can be used by the routines in this package. The
+// SortIPAddrsBySpecificMaskLen type is used to sort IPAddrs by smallest
+// network (most specific to largest network).
+type SortIPAddrsByNetworkSize struct{ IPAddrs }
+
+// Less reports whether the element with index i should sort before the
+// element with index j.
+func (s SortIPAddrsByNetworkSize) Less(i, j int) bool {
+ // Sort masks with a larger binary value (i.e. fewer hosts per network
+ // prefix) after masks with a smaller value (larger number of hosts per
+ // prefix).
+ switch bytes.Compare([]byte(*s.IPAddrs[i].NetIPMask()), []byte(*s.IPAddrs[j].NetIPMask())) {
+ case 0:
+ // Fall through to the second test if the net.IPMasks are the
+ // same.
+ break
+ case 1:
+ return true
+ case -1:
+ return false
+ default:
+ panic("bad, m'kay?")
+ }
+
+ // Sort IPs based on the length (i.e. prefer IPv4 over IPv6).
+ iLen := len(*s.IPAddrs[i].NetIP())
+ jLen := len(*s.IPAddrs[j].NetIP())
+ if iLen != jLen {
+ return iLen > jLen
+ }
+
+ // Sort IPs based on their network address from lowest to highest.
+ switch bytes.Compare(s.IPAddrs[i].NetIPNet().IP, s.IPAddrs[j].NetIPNet().IP) {
+ case 0:
+ break
+ case 1:
+ return false
+ case -1:
+ return true
+ default:
+ panic("lol wut?")
+ }
+
+ // If a host does not have a port set, it always sorts after hosts
+ // that have a port (e.g. a host with a /32 and port number is more
+ // specific and should sort first over a host with a /32 but no port
+ // set).
+ if s.IPAddrs[i].IPPort() == 0 || s.IPAddrs[j].IPPort() == 0 {
+ return false
+ }
+ return s.IPAddrs[i].IPPort() < s.IPAddrs[j].IPPort()
+}
+
+// SortIPAddrsBySpecificMaskLen is a type that satisfies sort.Interface and
+// can be used by the routines in this package. The
+// SortIPAddrsBySpecificMaskLen type is used to sort IPAddrs by smallest
+// network (most specific to largest network).
+type SortIPAddrsBySpecificMaskLen struct{ IPAddrs }
+
+// Less reports whether the element with index i should sort before the
+// element with index j.
+func (s SortIPAddrsBySpecificMaskLen) Less(i, j int) bool {
+ return s.IPAddrs[i].Maskbits() > s.IPAddrs[j].Maskbits()
+}
+
+// SortIPAddrsByBroadMaskLen is a type that satisfies sort.Interface and can
+// be used by the routines in this package. The SortIPAddrsByBroadMaskLen
+// type is used to sort IPAddrs by largest network (i.e. largest subnets
+// first).
+type SortIPAddrsByBroadMaskLen struct{ IPAddrs }
+
+// Less reports whether the element with index i should sort before the
+// element with index j.
+func (s SortIPAddrsByBroadMaskLen) Less(i, j int) bool {
+ return s.IPAddrs[i].Maskbits() < s.IPAddrs[j].Maskbits()
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/ipv4addr.go b/vendor/github.com/hashicorp/go-sockaddr/ipv4addr.go
new file mode 100644
index 0000000..4d395dc
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/ipv4addr.go
@@ -0,0 +1,516 @@
+package sockaddr
+
+import (
+ "encoding/binary"
+ "fmt"
+ "net"
+ "regexp"
+ "strconv"
+ "strings"
+)
+
+type (
+ // IPv4Address is a named type representing an IPv4 address.
+ IPv4Address uint32
+
+ // IPv4Network is a named type representing an IPv4 network.
+ IPv4Network uint32
+
+ // IPv4Mask is a named type representing an IPv4 network mask.
+ IPv4Mask uint32
+)
+
+// IPv4HostMask is a constant represents a /32 IPv4 Address
+// (i.e. 255.255.255.255).
+const IPv4HostMask = IPv4Mask(0xffffffff)
+
+// ipv4AddrAttrMap is a map of the IPv4Addr type-specific attributes.
+var ipv4AddrAttrMap map[AttrName]func(IPv4Addr) string
+var ipv4AddrAttrs []AttrName
+var trailingHexNetmaskRE *regexp.Regexp
+
+// IPv4Addr implements a convenience wrapper around the union of Go's
+// built-in net.IP and net.IPNet types. In UNIX-speak, IPv4Addr implements
+// `sockaddr` when the the address family is set to AF_INET
+// (i.e. `sockaddr_in`).
+type IPv4Addr struct {
+ IPAddr
+ Address IPv4Address
+ Mask IPv4Mask
+ Port IPPort
+}
+
+func init() {
+ ipv4AddrInit()
+ trailingHexNetmaskRE = regexp.MustCompile(`/([0f]{8})$`)
+}
+
+// NewIPv4Addr creates an IPv4Addr from a string. String can be in the form
+// of either an IPv4:port (e.g. `1.2.3.4:80`, in which case the mask is
+// assumed to be a `/32`), an IPv4 address (e.g. `1.2.3.4`, also with a `/32`
+// mask), or an IPv4 CIDR (e.g. `1.2.3.4/24`, which has its IP port
+// initialized to zero). ipv4Str can not be a hostname.
+//
+// NOTE: Many net.*() routines will initialize and return an IPv6 address.
+// To create uint32 values from net.IP, always test to make sure the address
+// returned can be converted to a 4 byte array using To4().
+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.
+ trailingHexNetmaskRe := trailingHexNetmaskRE.Copy()
+ if match := trailingHexNetmaskRe.FindStringIndex(ipv4Str); match != nil {
+ ipv4Str = ipv4Str[:match[0]]
+ }
+
+ // Parse as an IPv4 CIDR
+ ipAddr, network, err := net.ParseCIDR(ipv4Str)
+ if err == nil {
+ ipv4 := ipAddr.To4()
+ if ipv4 == nil {
+ return IPv4Addr{}, fmt.Errorf("Unable to convert %s to an IPv4 address", ipv4Str)
+ }
+
+ // If we see an IPv6 netmask, convert it to an IPv4 mask.
+ netmaskSepPos := strings.LastIndexByte(ipv4Str, '/')
+ if netmaskSepPos != -1 && netmaskSepPos+1 < len(ipv4Str) {
+ netMask, err := strconv.ParseUint(ipv4Str[netmaskSepPos+1:], 10, 8)
+ if err != nil {
+ return IPv4Addr{}, fmt.Errorf("Unable to convert %s to an IPv4 address: unable to parse CIDR netmask: %v", ipv4Str, err)
+ } else if netMask > 128 {
+ return IPv4Addr{}, fmt.Errorf("Unable to convert %s to an IPv4 address: invalid CIDR netmask", ipv4Str)
+ }
+
+ if netMask >= 96 {
+ // Convert the IPv6 netmask to an IPv4 netmask
+ network.Mask = net.CIDRMask(int(netMask-96), IPv4len*8)
+ }
+ }
+ ipv4Addr := IPv4Addr{
+ Address: IPv4Address(binary.BigEndian.Uint32(ipv4)),
+ Mask: IPv4Mask(binary.BigEndian.Uint32(network.Mask)),
+ }
+ return ipv4Addr, nil
+ }
+
+ // Attempt to parse ipv4Str as a /32 host with a port number.
+ tcpAddr, err := net.ResolveTCPAddr("tcp4", ipv4Str)
+ if err == nil {
+ ipv4 := tcpAddr.IP.To4()
+ if ipv4 == nil {
+ return IPv4Addr{}, fmt.Errorf("Unable to resolve %+q as an IPv4 address", ipv4Str)
+ }
+
+ ipv4Uint32 := binary.BigEndian.Uint32(ipv4)
+ ipv4Addr := IPv4Addr{
+ Address: IPv4Address(ipv4Uint32),
+ Mask: IPv4HostMask,
+ Port: IPPort(tcpAddr.Port),
+ }
+
+ return ipv4Addr, nil
+ }
+
+ // Parse as a naked IPv4 address
+ ip := net.ParseIP(ipv4Str)
+ if ip != nil {
+ ipv4 := ip.To4()
+ if ipv4 == nil {
+ return IPv4Addr{}, fmt.Errorf("Unable to string convert %+q to an IPv4 address", ipv4Str)
+ }
+
+ ipv4Uint32 := binary.BigEndian.Uint32(ipv4)
+ ipv4Addr := IPv4Addr{
+ Address: IPv4Address(ipv4Uint32),
+ Mask: IPv4HostMask,
+ }
+ return ipv4Addr, nil
+ }
+
+ return IPv4Addr{}, fmt.Errorf("Unable to parse %+q to an IPv4 address: %v", ipv4Str, err)
+}
+
+// AddressBinString returns a string with the IPv4Addr's Address represented
+// as a sequence of '0' and '1' characters. This method is useful for
+// debugging or by operators who want to inspect an address.
+func (ipv4 IPv4Addr) AddressBinString() string {
+ return fmt.Sprintf("%032s", strconv.FormatUint(uint64(ipv4.Address), 2))
+}
+
+// AddressHexString returns a string with the IPv4Addr address represented as
+// a sequence of hex characters. This method is useful for debugging or by
+// operators who want to inspect an address.
+func (ipv4 IPv4Addr) AddressHexString() string {
+ return fmt.Sprintf("%08s", strconv.FormatUint(uint64(ipv4.Address), 16))
+}
+
+// Broadcast is an IPv4Addr-only method that returns the broadcast address of
+// the network.
+//
+// NOTE: IPv6 only supports multicast, so this method only exists for
+// IPv4Addr.
+func (ipv4 IPv4Addr) Broadcast() IPAddr {
+ // Nothing should listen on a broadcast address.
+ return IPv4Addr{
+ Address: IPv4Address(ipv4.BroadcastAddress()),
+ Mask: IPv4HostMask,
+ }
+}
+
+// BroadcastAddress returns a IPv4Network of the IPv4Addr's broadcast
+// address.
+func (ipv4 IPv4Addr) BroadcastAddress() IPv4Network {
+ return IPv4Network(uint32(ipv4.Address)&uint32(ipv4.Mask) | ^uint32(ipv4.Mask))
+}
+
+// CmpAddress follows the Cmp() standard protocol and returns:
+//
+// - -1 If the receiver should sort first because its address is lower than arg
+// - 0 if the SockAddr arg is equal to the receiving IPv4Addr or the argument is
+// of a different type.
+// - 1 If the argument should sort first.
+func (ipv4 IPv4Addr) CmpAddress(sa SockAddr) int {
+ ipv4b, ok := sa.(IPv4Addr)
+ if !ok {
+ return sortDeferDecision
+ }
+
+ switch {
+ case ipv4.Address == ipv4b.Address:
+ return sortDeferDecision
+ case ipv4.Address < ipv4b.Address:
+ return sortReceiverBeforeArg
+ default:
+ return sortArgBeforeReceiver
+ }
+}
+
+// CmpPort follows the Cmp() standard protocol and returns:
+//
+// - -1 If the receiver should sort first because its port is lower than arg
+// - 0 if the SockAddr arg's port number is equal to the receiving IPv4Addr,
+// regardless of type.
+// - 1 If the argument should sort first.
+func (ipv4 IPv4Addr) CmpPort(sa SockAddr) int {
+ var saPort IPPort
+ switch v := sa.(type) {
+ case IPv4Addr:
+ saPort = v.Port
+ case IPv6Addr:
+ saPort = v.Port
+ default:
+ return sortDeferDecision
+ }
+
+ switch {
+ case ipv4.Port == saPort:
+ return sortDeferDecision
+ case ipv4.Port < saPort:
+ return sortReceiverBeforeArg
+ default:
+ return sortArgBeforeReceiver
+ }
+}
+
+// CmpRFC follows the Cmp() standard protocol and returns:
+//
+// - -1 If the receiver should sort first because it belongs to the RFC and its
+// arg does not
+// - 0 if the receiver and arg both belong to the same RFC or neither do.
+// - 1 If the arg belongs to the RFC but receiver does not.
+func (ipv4 IPv4Addr) CmpRFC(rfcNum uint, sa SockAddr) int {
+ recvInRFC := IsRFC(rfcNum, ipv4)
+ ipv4b, ok := sa.(IPv4Addr)
+ if !ok {
+ // If the receiver is part of the desired RFC and the SockAddr
+ // argument is not, return -1 so that the receiver sorts before
+ // the non-IPv4 SockAddr. Conversely, if the receiver is not
+ // part of the RFC, punt on sorting and leave it for the next
+ // sorter.
+ if recvInRFC {
+ return sortReceiverBeforeArg
+ } else {
+ return sortDeferDecision
+ }
+ }
+
+ argInRFC := IsRFC(rfcNum, ipv4b)
+ switch {
+ case (recvInRFC && argInRFC), (!recvInRFC && !argInRFC):
+ // If a and b both belong to the RFC, or neither belong to
+ // rfcNum, defer sorting to the next sorter.
+ return sortDeferDecision
+ case recvInRFC && !argInRFC:
+ return sortReceiverBeforeArg
+ default:
+ return sortArgBeforeReceiver
+ }
+}
+
+// Contains returns true if the SockAddr is contained within the receiver.
+func (ipv4 IPv4Addr) Contains(sa SockAddr) bool {
+ ipv4b, ok := sa.(IPv4Addr)
+ if !ok {
+ return false
+ }
+
+ return ipv4.ContainsNetwork(ipv4b)
+}
+
+// ContainsAddress returns true if the IPv4Address is contained within the
+// receiver.
+func (ipv4 IPv4Addr) ContainsAddress(x IPv4Address) bool {
+ return IPv4Address(ipv4.NetworkAddress()) <= x &&
+ IPv4Address(ipv4.BroadcastAddress()) >= x
+}
+
+// ContainsNetwork returns true if the network from IPv4Addr is contained
+// within the receiver.
+func (ipv4 IPv4Addr) ContainsNetwork(x IPv4Addr) bool {
+ return ipv4.NetworkAddress() <= x.NetworkAddress() &&
+ ipv4.BroadcastAddress() >= x.BroadcastAddress()
+}
+
+// DialPacketArgs returns the arguments required to be passed to
+// net.DialUDP(). If the Mask of ipv4 is not a /32 or the Port is 0,
+// DialPacketArgs() will fail. See Host() to create an IPv4Addr with its
+// mask set to /32.
+func (ipv4 IPv4Addr) DialPacketArgs() (network, dialArgs string) {
+ if ipv4.Mask != IPv4HostMask || ipv4.Port == 0 {
+ return "udp4", ""
+ }
+ return "udp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port)
+}
+
+// DialStreamArgs returns the arguments required to be passed to
+// net.DialTCP(). If the Mask of ipv4 is not a /32 or the Port is 0,
+// DialStreamArgs() will fail. See Host() to create an IPv4Addr with its
+// mask set to /32.
+func (ipv4 IPv4Addr) DialStreamArgs() (network, dialArgs string) {
+ if ipv4.Mask != IPv4HostMask || ipv4.Port == 0 {
+ return "tcp4", ""
+ }
+ return "tcp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port)
+}
+
+// Equal returns true if a SockAddr is equal to the receiving IPv4Addr.
+func (ipv4 IPv4Addr) Equal(sa SockAddr) bool {
+ ipv4b, ok := sa.(IPv4Addr)
+ if !ok {
+ return false
+ }
+
+ if ipv4.Port != ipv4b.Port {
+ return false
+ }
+
+ if ipv4.Address != ipv4b.Address {
+ return false
+ }
+
+ if ipv4.NetIPNet().String() != ipv4b.NetIPNet().String() {
+ return false
+ }
+
+ return true
+}
+
+// FirstUsable returns an IPv4Addr set to the first address following the
+// network prefix. The first usable address in a network is normally the
+// gateway and should not be used except by devices forwarding packets
+// between two administratively distinct networks (i.e. a router). This
+// function does not discriminate against first usable vs "first address that
+// should be used." For example, FirstUsable() on "192.168.1.10/24" would
+// return the address "192.168.1.1/24".
+func (ipv4 IPv4Addr) FirstUsable() IPAddr {
+ addr := ipv4.NetworkAddress()
+
+ // If /32, return the address itself. If /31 assume a point-to-point
+ // link and return the lower address.
+ if ipv4.Maskbits() < 31 {
+ addr++
+ }
+
+ return IPv4Addr{
+ Address: IPv4Address(addr),
+ Mask: IPv4HostMask,
+ }
+}
+
+// Host returns a copy of ipv4 with its mask set to /32 so that it can be
+// used by DialPacketArgs(), DialStreamArgs(), ListenPacketArgs(), or
+// ListenStreamArgs().
+func (ipv4 IPv4Addr) Host() IPAddr {
+ // Nothing should listen on a broadcast address.
+ return IPv4Addr{
+ Address: ipv4.Address,
+ Mask: IPv4HostMask,
+ Port: ipv4.Port,
+ }
+}
+
+// IPPort returns the Port number attached to the IPv4Addr
+func (ipv4 IPv4Addr) IPPort() IPPort {
+ return ipv4.Port
+}
+
+// LastUsable returns the last address before the broadcast address in a
+// given network.
+func (ipv4 IPv4Addr) LastUsable() IPAddr {
+ addr := ipv4.BroadcastAddress()
+
+ // If /32, return the address itself. If /31 assume a point-to-point
+ // link and return the upper address.
+ if ipv4.Maskbits() < 31 {
+ addr--
+ }
+
+ return IPv4Addr{
+ Address: IPv4Address(addr),
+ Mask: IPv4HostMask,
+ }
+}
+
+// ListenPacketArgs returns the arguments required to be passed to
+// net.ListenUDP(). If the Mask of ipv4 is not a /32, ListenPacketArgs()
+// will fail. See Host() to create an IPv4Addr with its mask set to /32.
+func (ipv4 IPv4Addr) ListenPacketArgs() (network, listenArgs string) {
+ if ipv4.Mask != IPv4HostMask {
+ return "udp4", ""
+ }
+ return "udp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port)
+}
+
+// ListenStreamArgs returns the arguments required to be passed to
+// net.ListenTCP(). If the Mask of ipv4 is not a /32, ListenStreamArgs()
+// will fail. See Host() to create an IPv4Addr with its mask set to /32.
+func (ipv4 IPv4Addr) ListenStreamArgs() (network, listenArgs string) {
+ if ipv4.Mask != IPv4HostMask {
+ return "tcp4", ""
+ }
+ return "tcp4", fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port)
+}
+
+// Maskbits returns the number of network mask bits in a given IPv4Addr. For
+// example, the Maskbits() of "192.168.1.1/24" would return 24.
+func (ipv4 IPv4Addr) Maskbits() int {
+ mask := make(net.IPMask, IPv4len)
+ binary.BigEndian.PutUint32(mask, uint32(ipv4.Mask))
+ maskOnes, _ := mask.Size()
+ return maskOnes
+}
+
+// MustIPv4Addr is a helper method that must return an IPv4Addr or panic on
+// invalid input.
+func MustIPv4Addr(addr string) IPv4Addr {
+ ipv4, err := NewIPv4Addr(addr)
+ if err != nil {
+ panic(fmt.Sprintf("Unable to create an IPv4Addr from %+q: %v", addr, err))
+ }
+ return ipv4
+}
+
+// NetIP returns the address as a net.IP (address is always presized to
+// IPv4).
+func (ipv4 IPv4Addr) NetIP() *net.IP {
+ x := make(net.IP, IPv4len)
+ binary.BigEndian.PutUint32(x, uint32(ipv4.Address))
+ return &x
+}
+
+// NetIPMask create a new net.IPMask from the IPv4Addr.
+func (ipv4 IPv4Addr) NetIPMask() *net.IPMask {
+ ipv4Mask := net.IPMask{}
+ ipv4Mask = make(net.IPMask, IPv4len)
+ binary.BigEndian.PutUint32(ipv4Mask, uint32(ipv4.Mask))
+ return &ipv4Mask
+}
+
+// NetIPNet create a new net.IPNet from the IPv4Addr.
+func (ipv4 IPv4Addr) NetIPNet() *net.IPNet {
+ ipv4net := &net.IPNet{}
+ ipv4net.IP = make(net.IP, IPv4len)
+ binary.BigEndian.PutUint32(ipv4net.IP, uint32(ipv4.NetworkAddress()))
+ ipv4net.Mask = *ipv4.NetIPMask()
+ return ipv4net
+}
+
+// Network returns the network prefix or network address for a given network.
+func (ipv4 IPv4Addr) Network() IPAddr {
+ return IPv4Addr{
+ Address: IPv4Address(ipv4.NetworkAddress()),
+ Mask: ipv4.Mask,
+ }
+}
+
+// NetworkAddress returns an IPv4Network of the IPv4Addr's network address.
+func (ipv4 IPv4Addr) NetworkAddress() IPv4Network {
+ return IPv4Network(uint32(ipv4.Address) & uint32(ipv4.Mask))
+}
+
+// Octets returns a slice of the four octets in an IPv4Addr's Address. The
+// order of the bytes is big endian.
+func (ipv4 IPv4Addr) Octets() []int {
+ return []int{
+ int(ipv4.Address >> 24),
+ int((ipv4.Address >> 16) & 0xff),
+ int((ipv4.Address >> 8) & 0xff),
+ int(ipv4.Address & 0xff),
+ }
+}
+
+// String returns a string representation of the IPv4Addr
+func (ipv4 IPv4Addr) String() string {
+ if ipv4.Port != 0 {
+ return fmt.Sprintf("%s:%d", ipv4.NetIP().String(), ipv4.Port)
+ }
+
+ if ipv4.Maskbits() == 32 {
+ return ipv4.NetIP().String()
+ }
+
+ return fmt.Sprintf("%s/%d", ipv4.NetIP().String(), ipv4.Maskbits())
+}
+
+// Type is used as a type switch and returns TypeIPv4
+func (IPv4Addr) Type() SockAddrType {
+ return TypeIPv4
+}
+
+// IPv4AddrAttr returns a string representation of an attribute for the given
+// IPv4Addr.
+func IPv4AddrAttr(ipv4 IPv4Addr, selector AttrName) string {
+ fn, found := ipv4AddrAttrMap[selector]
+ if !found {
+ return ""
+ }
+
+ return fn(ipv4)
+}
+
+// IPv4Attrs returns a list of attributes supported by the IPv4Addr type
+func IPv4Attrs() []AttrName {
+ return ipv4AddrAttrs
+}
+
+// ipv4AddrInit is called once at init()
+func ipv4AddrInit() {
+ // Sorted for human readability
+ ipv4AddrAttrs = []AttrName{
+ "size", // Same position as in IPv6 for output consistency
+ "broadcast",
+ "uint32",
+ }
+
+ ipv4AddrAttrMap = map[AttrName]func(ipv4 IPv4Addr) string{
+ "broadcast": func(ipv4 IPv4Addr) string {
+ return ipv4.Broadcast().String()
+ },
+ "size": func(ipv4 IPv4Addr) string {
+ return fmt.Sprintf("%d", 1<<uint(IPv4len*8-ipv4.Maskbits()))
+ },
+ "uint32": func(ipv4 IPv4Addr) string {
+ return fmt.Sprintf("%d", uint32(ipv4.Address))
+ },
+ }
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/ipv6addr.go b/vendor/github.com/hashicorp/go-sockaddr/ipv6addr.go
new file mode 100644
index 0000000..d7f4121
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/ipv6addr.go
@@ -0,0 +1,591 @@
+package sockaddr
+
+import (
+ "bytes"
+ "encoding/binary"
+ "fmt"
+ "math/big"
+ "net"
+)
+
+type (
+ // IPv6Address is a named type representing an IPv6 address.
+ IPv6Address *big.Int
+
+ // IPv6Network is a named type representing an IPv6 network.
+ IPv6Network *big.Int
+
+ // IPv6Mask is a named type representing an IPv6 network mask.
+ IPv6Mask *big.Int
+)
+
+// IPv6HostPrefix is a constant represents a /128 IPv6 Prefix.
+const IPv6HostPrefix = IPPrefixLen(128)
+
+// ipv6HostMask is an unexported big.Int representing a /128 IPv6 address.
+// This value must be a constant and always set to all ones.
+var ipv6HostMask IPv6Mask
+
+// ipv6AddrAttrMap is a map of the IPv6Addr type-specific attributes.
+var ipv6AddrAttrMap map[AttrName]func(IPv6Addr) string
+var ipv6AddrAttrs []AttrName
+
+func init() {
+ biMask := new(big.Int)
+ biMask.SetBytes([]byte{
+ 0xff, 0xff,
+ 0xff, 0xff,
+ 0xff, 0xff,
+ 0xff, 0xff,
+ 0xff, 0xff,
+ 0xff, 0xff,
+ 0xff, 0xff,
+ 0xff, 0xff,
+ },
+ )
+ ipv6HostMask = IPv6Mask(biMask)
+
+ ipv6AddrInit()
+}
+
+// IPv6Addr implements a convenience wrapper around the union of Go's
+// built-in net.IP and net.IPNet types. In UNIX-speak, IPv6Addr implements
+// `sockaddr` when the the address family is set to AF_INET6
+// (i.e. `sockaddr_in6`).
+type IPv6Addr struct {
+ IPAddr
+ Address IPv6Address
+ Mask IPv6Mask
+ Port IPPort
+}
+
+// NewIPv6Addr creates an IPv6Addr from a string. String can be in the form of
+// an an IPv6:port (e.g. `[2001:4860:0:2001::68]:80`, in which case the mask is
+// assumed to be a /128), an IPv6 address (e.g. `2001:4860:0:2001::68`, also
+// with a `/128` mask), an IPv6 CIDR (e.g. `2001:4860:0:2001::68/64`, which has
+// its IP port initialized to zero). ipv6Str can not be a hostname.
+//
+// NOTE: Many net.*() routines will initialize and return an IPv4 address.
+// Always test to make sure the address returned cannot be converted to a 4 byte
+// array using To4().
+func NewIPv6Addr(ipv6Str string) (IPv6Addr, error) {
+ v6Addr := false
+LOOP:
+ for i := 0; i < len(ipv6Str); i++ {
+ switch ipv6Str[i] {
+ case '.':
+ break LOOP
+ case ':':
+ v6Addr = true
+ break LOOP
+ }
+ }
+
+ if !v6Addr {
+ return IPv6Addr{}, fmt.Errorf("Unable to resolve %+q as an IPv6 address, appears to be an IPv4 address", ipv6Str)
+ }
+
+ // Attempt to parse ipv6Str as a /128 host with a port number.
+ tcpAddr, err := net.ResolveTCPAddr("tcp6", ipv6Str)
+ if err == nil {
+ ipv6 := tcpAddr.IP.To16()
+ if ipv6 == nil {
+ return IPv6Addr{}, fmt.Errorf("Unable to resolve %+q as a 16byte IPv6 address", ipv6Str)
+ }
+
+ ipv6BigIntAddr := new(big.Int)
+ ipv6BigIntAddr.SetBytes(ipv6)
+
+ ipv6BigIntMask := new(big.Int)
+ ipv6BigIntMask.Set(ipv6HostMask)
+
+ ipv6Addr := IPv6Addr{
+ Address: IPv6Address(ipv6BigIntAddr),
+ Mask: IPv6Mask(ipv6BigIntMask),
+ Port: IPPort(tcpAddr.Port),
+ }
+
+ return ipv6Addr, nil
+ }
+
+ // Parse as a naked IPv6 address. Trim square brackets if present.
+ if len(ipv6Str) > 2 && ipv6Str[0] == '[' && ipv6Str[len(ipv6Str)-1] == ']' {
+ ipv6Str = ipv6Str[1 : len(ipv6Str)-1]
+ }
+ ip := net.ParseIP(ipv6Str)
+ if ip != nil {
+ ipv6 := ip.To16()
+ if ipv6 == nil {
+ return IPv6Addr{}, fmt.Errorf("Unable to string convert %+q to a 16byte IPv6 address", ipv6Str)
+ }
+
+ ipv6BigIntAddr := new(big.Int)
+ ipv6BigIntAddr.SetBytes(ipv6)
+
+ ipv6BigIntMask := new(big.Int)
+ ipv6BigIntMask.Set(ipv6HostMask)
+
+ return IPv6Addr{
+ Address: IPv6Address(ipv6BigIntAddr),
+ Mask: IPv6Mask(ipv6BigIntMask),
+ }, nil
+ }
+
+ // Parse as an IPv6 CIDR
+ ipAddr, network, err := net.ParseCIDR(ipv6Str)
+ if err == nil {
+ ipv6 := ipAddr.To16()
+ if ipv6 == nil {
+ return IPv6Addr{}, fmt.Errorf("Unable to convert %+q to a 16byte IPv6 address", ipv6Str)
+ }
+
+ ipv6BigIntAddr := new(big.Int)
+ ipv6BigIntAddr.SetBytes(ipv6)
+
+ ipv6BigIntMask := new(big.Int)
+ ipv6BigIntMask.SetBytes(network.Mask)
+
+ ipv6Addr := IPv6Addr{
+ Address: IPv6Address(ipv6BigIntAddr),
+ Mask: IPv6Mask(ipv6BigIntMask),
+ }
+ return ipv6Addr, nil
+ }
+
+ return IPv6Addr{}, fmt.Errorf("Unable to parse %+q to an IPv6 address: %v", ipv6Str, err)
+}
+
+// AddressBinString returns a string with the IPv6Addr's Address represented
+// as a sequence of '0' and '1' characters. This method is useful for
+// debugging or by operators who want to inspect an address.
+func (ipv6 IPv6Addr) AddressBinString() string {
+ bi := big.Int(*ipv6.Address)
+ return fmt.Sprintf("%0128s", bi.Text(2))
+}
+
+// AddressHexString returns a string with the IPv6Addr address represented as
+// a sequence of hex characters. This method is useful for debugging or by
+// operators who want to inspect an address.
+func (ipv6 IPv6Addr) AddressHexString() string {
+ bi := big.Int(*ipv6.Address)
+ return fmt.Sprintf("%032s", bi.Text(16))
+}
+
+// CmpAddress follows the Cmp() standard protocol and returns:
+//
+// - -1 If the receiver should sort first because its address is lower than arg
+// - 0 if the SockAddr arg equal to the receiving IPv6Addr or the argument is of a
+// different type.
+// - 1 If the argument should sort first.
+func (ipv6 IPv6Addr) CmpAddress(sa SockAddr) int {
+ ipv6b, ok := sa.(IPv6Addr)
+ if !ok {
+ return sortDeferDecision
+ }
+
+ ipv6aBigInt := new(big.Int)
+ ipv6aBigInt.Set(ipv6.Address)
+ ipv6bBigInt := new(big.Int)
+ ipv6bBigInt.Set(ipv6b.Address)
+
+ return ipv6aBigInt.Cmp(ipv6bBigInt)
+}
+
+// CmpPort follows the Cmp() standard protocol and returns:
+//
+// - -1 If the receiver should sort first because its port is lower than arg
+// - 0 if the SockAddr arg's port number is equal to the receiving IPv6Addr,
+// regardless of type.
+// - 1 If the argument should sort first.
+func (ipv6 IPv6Addr) CmpPort(sa SockAddr) int {
+ var saPort IPPort
+ switch v := sa.(type) {
+ case IPv4Addr:
+ saPort = v.Port
+ case IPv6Addr:
+ saPort = v.Port
+ default:
+ return sortDeferDecision
+ }
+
+ switch {
+ case ipv6.Port == saPort:
+ return sortDeferDecision
+ case ipv6.Port < saPort:
+ return sortReceiverBeforeArg
+ default:
+ return sortArgBeforeReceiver
+ }
+}
+
+// CmpRFC follows the Cmp() standard protocol and returns:
+//
+// - -1 If the receiver should sort first because it belongs to the RFC and its
+// arg does not
+// - 0 if the receiver and arg both belong to the same RFC or neither do.
+// - 1 If the arg belongs to the RFC but receiver does not.
+func (ipv6 IPv6Addr) CmpRFC(rfcNum uint, sa SockAddr) int {
+ recvInRFC := IsRFC(rfcNum, ipv6)
+ ipv6b, ok := sa.(IPv6Addr)
+ if !ok {
+ // If the receiver is part of the desired RFC and the SockAddr
+ // argument is not, sort receiver before the non-IPv6 SockAddr.
+ // Conversely, if the receiver is not part of the RFC, punt on
+ // sorting and leave it for the next sorter.
+ if recvInRFC {
+ return sortReceiverBeforeArg
+ } else {
+ return sortDeferDecision
+ }
+ }
+
+ argInRFC := IsRFC(rfcNum, ipv6b)
+ switch {
+ case (recvInRFC && argInRFC), (!recvInRFC && !argInRFC):
+ // If a and b both belong to the RFC, or neither belong to
+ // rfcNum, defer sorting to the next sorter.
+ return sortDeferDecision
+ case recvInRFC && !argInRFC:
+ return sortReceiverBeforeArg
+ default:
+ return sortArgBeforeReceiver
+ }
+}
+
+// Contains returns true if the SockAddr is contained within the receiver.
+func (ipv6 IPv6Addr) Contains(sa SockAddr) bool {
+ ipv6b, ok := sa.(IPv6Addr)
+ if !ok {
+ return false
+ }
+
+ return ipv6.ContainsNetwork(ipv6b)
+}
+
+// ContainsAddress returns true if the IPv6Address is contained within the
+// receiver.
+func (ipv6 IPv6Addr) ContainsAddress(x IPv6Address) bool {
+ xAddr := IPv6Addr{
+ Address: x,
+ Mask: ipv6HostMask,
+ }
+
+ {
+ xIPv6 := xAddr.FirstUsable().(IPv6Addr)
+ yIPv6 := ipv6.FirstUsable().(IPv6Addr)
+ if xIPv6.CmpAddress(yIPv6) >= 1 {
+ return false
+ }
+ }
+
+ {
+ xIPv6 := xAddr.LastUsable().(IPv6Addr)
+ yIPv6 := ipv6.LastUsable().(IPv6Addr)
+ if xIPv6.CmpAddress(yIPv6) <= -1 {
+ return false
+ }
+ }
+ return true
+}
+
+// ContainsNetwork returns true if the network from IPv6Addr is contained within
+// the receiver.
+func (x IPv6Addr) ContainsNetwork(y IPv6Addr) bool {
+ {
+ xIPv6 := x.FirstUsable().(IPv6Addr)
+ yIPv6 := y.FirstUsable().(IPv6Addr)
+ if ret := xIPv6.CmpAddress(yIPv6); ret >= 1 {
+ return false
+ }
+ }
+
+ {
+ xIPv6 := x.LastUsable().(IPv6Addr)
+ yIPv6 := y.LastUsable().(IPv6Addr)
+ if ret := xIPv6.CmpAddress(yIPv6); ret <= -1 {
+ return false
+ }
+ }
+ return true
+}
+
+// DialPacketArgs returns the arguments required to be passed to
+// net.DialUDP(). If the Mask of ipv6 is not a /128 or the Port is 0,
+// DialPacketArgs() will fail. See Host() to create an IPv6Addr with its
+// mask set to /128.
+func (ipv6 IPv6Addr) DialPacketArgs() (network, dialArgs string) {
+ ipv6Mask := big.Int(*ipv6.Mask)
+ if ipv6Mask.Cmp(ipv6HostMask) != 0 || ipv6.Port == 0 {
+ return "udp6", ""
+ }
+ return "udp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port)
+}
+
+// DialStreamArgs returns the arguments required to be passed to
+// net.DialTCP(). If the Mask of ipv6 is not a /128 or the Port is 0,
+// DialStreamArgs() will fail. See Host() to create an IPv6Addr with its
+// mask set to /128.
+func (ipv6 IPv6Addr) DialStreamArgs() (network, dialArgs string) {
+ ipv6Mask := big.Int(*ipv6.Mask)
+ if ipv6Mask.Cmp(ipv6HostMask) != 0 || ipv6.Port == 0 {
+ return "tcp6", ""
+ }
+ return "tcp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port)
+}
+
+// Equal returns true if a SockAddr is equal to the receiving IPv4Addr.
+func (ipv6a IPv6Addr) Equal(sa SockAddr) bool {
+ ipv6b, ok := sa.(IPv6Addr)
+ if !ok {
+ return false
+ }
+
+ if ipv6a.NetIP().String() != ipv6b.NetIP().String() {
+ return false
+ }
+
+ if ipv6a.NetIPNet().String() != ipv6b.NetIPNet().String() {
+ return false
+ }
+
+ if ipv6a.Port != ipv6b.Port {
+ return false
+ }
+
+ return true
+}
+
+// FirstUsable returns an IPv6Addr set to the first address following the
+// network prefix. The first usable address in a network is normally the
+// gateway and should not be used except by devices forwarding packets
+// between two administratively distinct networks (i.e. a router). This
+// function does not discriminate against first usable vs "first address that
+// should be used." For example, FirstUsable() on "2001:0db8::0003/64" would
+// return "2001:0db8::00011".
+func (ipv6 IPv6Addr) FirstUsable() IPAddr {
+ return IPv6Addr{
+ Address: IPv6Address(ipv6.NetworkAddress()),
+ Mask: ipv6HostMask,
+ }
+}
+
+// Host returns a copy of ipv6 with its mask set to /128 so that it can be
+// used by DialPacketArgs(), DialStreamArgs(), ListenPacketArgs(), or
+// ListenStreamArgs().
+func (ipv6 IPv6Addr) Host() IPAddr {
+ // Nothing should listen on a broadcast address.
+ return IPv6Addr{
+ Address: ipv6.Address,
+ Mask: ipv6HostMask,
+ Port: ipv6.Port,
+ }
+}
+
+// IPPort returns the Port number attached to the IPv6Addr
+func (ipv6 IPv6Addr) IPPort() IPPort {
+ return ipv6.Port
+}
+
+// LastUsable returns the last address in a given network.
+func (ipv6 IPv6Addr) LastUsable() IPAddr {
+ addr := new(big.Int)
+ addr.Set(ipv6.Address)
+
+ mask := new(big.Int)
+ mask.Set(ipv6.Mask)
+
+ negMask := new(big.Int)
+ negMask.Xor(ipv6HostMask, mask)
+
+ lastAddr := new(big.Int)
+ lastAddr.And(addr, mask)
+ lastAddr.Or(lastAddr, negMask)
+
+ return IPv6Addr{
+ Address: IPv6Address(lastAddr),
+ Mask: ipv6HostMask,
+ }
+}
+
+// ListenPacketArgs returns the arguments required to be passed to
+// net.ListenUDP(). If the Mask of ipv6 is not a /128, ListenPacketArgs()
+// will fail. See Host() to create an IPv6Addr with its mask set to /128.
+func (ipv6 IPv6Addr) ListenPacketArgs() (network, listenArgs string) {
+ ipv6Mask := big.Int(*ipv6.Mask)
+ if ipv6Mask.Cmp(ipv6HostMask) != 0 {
+ return "udp6", ""
+ }
+ return "udp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port)
+}
+
+// ListenStreamArgs returns the arguments required to be passed to
+// net.ListenTCP(). If the Mask of ipv6 is not a /128, ListenStreamArgs()
+// will fail. See Host() to create an IPv6Addr with its mask set to /128.
+func (ipv6 IPv6Addr) ListenStreamArgs() (network, listenArgs string) {
+ ipv6Mask := big.Int(*ipv6.Mask)
+ if ipv6Mask.Cmp(ipv6HostMask) != 0 {
+ return "tcp6", ""
+ }
+ return "tcp6", fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port)
+}
+
+// Maskbits returns the number of network mask bits in a given IPv6Addr. For
+// example, the Maskbits() of "2001:0db8::0003/64" would return 64.
+func (ipv6 IPv6Addr) Maskbits() int {
+ maskOnes, _ := ipv6.NetIPNet().Mask.Size()
+
+ return maskOnes
+}
+
+// MustIPv6Addr is a helper method that must return an IPv6Addr or panic on
+// invalid input.
+func MustIPv6Addr(addr string) IPv6Addr {
+ ipv6, err := NewIPv6Addr(addr)
+ if err != nil {
+ panic(fmt.Sprintf("Unable to create an IPv6Addr from %+q: %v", addr, err))
+ }
+ return ipv6
+}
+
+// NetIP returns the address as a net.IP.
+func (ipv6 IPv6Addr) NetIP() *net.IP {
+ return bigIntToNetIPv6(ipv6.Address)
+}
+
+// NetIPMask create a new net.IPMask from the IPv6Addr.
+func (ipv6 IPv6Addr) NetIPMask() *net.IPMask {
+ ipv6Mask := make(net.IPMask, IPv6len)
+ m := big.Int(*ipv6.Mask)
+ copy(ipv6Mask, m.Bytes())
+ return &ipv6Mask
+}
+
+// Network returns a pointer to the net.IPNet within IPv4Addr receiver.
+func (ipv6 IPv6Addr) NetIPNet() *net.IPNet {
+ ipv6net := &net.IPNet{}
+ ipv6net.IP = make(net.IP, IPv6len)
+ copy(ipv6net.IP, *ipv6.NetIP())
+ ipv6net.Mask = *ipv6.NetIPMask()
+ return ipv6net
+}
+
+// Network returns the network prefix or network address for a given network.
+func (ipv6 IPv6Addr) Network() IPAddr {
+ return IPv6Addr{
+ Address: IPv6Address(ipv6.NetworkAddress()),
+ Mask: ipv6.Mask,
+ }
+}
+
+// NetworkAddress returns an IPv6Network of the IPv6Addr's network address.
+func (ipv6 IPv6Addr) NetworkAddress() IPv6Network {
+ addr := new(big.Int)
+ addr.SetBytes((*ipv6.Address).Bytes())
+
+ mask := new(big.Int)
+ mask.SetBytes(*ipv6.NetIPMask())
+
+ netAddr := new(big.Int)
+ netAddr.And(addr, mask)
+
+ return IPv6Network(netAddr)
+}
+
+// Octets returns a slice of the 16 octets in an IPv6Addr's Address. The
+// order of the bytes is big endian.
+func (ipv6 IPv6Addr) Octets() []int {
+ x := make([]int, IPv6len)
+ for i, b := range *bigIntToNetIPv6(ipv6.Address) {
+ x[i] = int(b)
+ }
+
+ return x
+}
+
+// String returns a string representation of the IPv6Addr
+func (ipv6 IPv6Addr) String() string {
+ if ipv6.Port != 0 {
+ return fmt.Sprintf("[%s]:%d", ipv6.NetIP().String(), ipv6.Port)
+ }
+
+ if ipv6.Maskbits() == 128 {
+ return ipv6.NetIP().String()
+ }
+
+ return fmt.Sprintf("%s/%d", ipv6.NetIP().String(), ipv6.Maskbits())
+}
+
+// Type is used as a type switch and returns TypeIPv6
+func (IPv6Addr) Type() SockAddrType {
+ return TypeIPv6
+}
+
+// IPv6Attrs returns a list of attributes supported by the IPv6Addr type
+func IPv6Attrs() []AttrName {
+ return ipv6AddrAttrs
+}
+
+// IPv6AddrAttr returns a string representation of an attribute for the given
+// IPv6Addr.
+func IPv6AddrAttr(ipv6 IPv6Addr, selector AttrName) string {
+ fn, found := ipv6AddrAttrMap[selector]
+ if !found {
+ return ""
+ }
+
+ return fn(ipv6)
+}
+
+// ipv6AddrInit is called once at init()
+func ipv6AddrInit() {
+ // Sorted for human readability
+ ipv6AddrAttrs = []AttrName{
+ "size", // Same position as in IPv6 for output consistency
+ "uint128",
+ }
+
+ ipv6AddrAttrMap = map[AttrName]func(ipv6 IPv6Addr) string{
+ "size": func(ipv6 IPv6Addr) string {
+ netSize := big.NewInt(1)
+ netSize = netSize.Lsh(netSize, uint(IPv6len*8-ipv6.Maskbits()))
+ return netSize.Text(10)
+ },
+ "uint128": func(ipv6 IPv6Addr) string {
+ b := big.Int(*ipv6.Address)
+ return b.Text(10)
+ },
+ }
+}
+
+// bigIntToNetIPv6 is a helper function that correctly returns a net.IP with the
+// correctly padded values.
+func bigIntToNetIPv6(bi *big.Int) *net.IP {
+ x := make(net.IP, IPv6len)
+ ipv6Bytes := bi.Bytes()
+
+ // It's possibe for ipv6Bytes to be less than IPv6len bytes in size. If
+ // they are different sizes we to pad the size of response.
+ if len(ipv6Bytes) < IPv6len {
+ buf := new(bytes.Buffer)
+ buf.Grow(IPv6len)
+
+ for i := len(ipv6Bytes); i < IPv6len; i++ {
+ if err := binary.Write(buf, binary.BigEndian, byte(0)); err != nil {
+ panic(fmt.Sprintf("Unable to pad byte %d of input %v: %v", i, bi, err))
+ }
+ }
+
+ for _, b := range ipv6Bytes {
+ if err := binary.Write(buf, binary.BigEndian, b); err != nil {
+ panic(fmt.Sprintf("Unable to preserve endianness of input %v: %v", bi, err))
+ }
+ }
+
+ ipv6Bytes = buf.Bytes()
+ }
+ i := copy(x, ipv6Bytes)
+ if i != IPv6len {
+ panic("IPv6 wrong size")
+ }
+ return &x
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/rfc.go b/vendor/github.com/hashicorp/go-sockaddr/rfc.go
new file mode 100644
index 0000000..02e188f
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/rfc.go
@@ -0,0 +1,948 @@
+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 {
+ rfcNetMap := KnownRFCs()
+ rfcNets, ok := rfcNetMap[rfcNum]
+ if !ok {
+ return false
+ }
+
+ var contained bool
+ for _, rfcNet := range rfcNets {
+ if rfcNet.Contains(sa) {
+ contained = true
+ break
+ }
+ }
+ return contained
+}
+
+// KnownRFCs returns an initial set of known RFCs.
+//
+// NOTE (sean@): As this list evolves over time, please submit patches to keep
+// this list current. If something isn't right, inquire, as it may just be a
+// bug on my part. Some of the inclusions were based on my judgement as to what
+// would be a useful value (e.g. RFC3330).
+//
+// Useful resources:
+//
+// * https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml
+// * https://www.iana.org/assignments/ipv6-unicast-address-assignments/ipv6-unicast-address-assignments.xhtml
+// * https://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml
+func KnownRFCs() map[uint]SockAddrs {
+ // NOTE(sean@): Multiple SockAddrs per RFC lend themselves well to a
+ // RADIX tree, but `ENOTIME`. Patches welcome.
+ return map[uint]SockAddrs{
+ 919: {
+ // [RFC919] Broadcasting Internet Datagrams
+ MustIPv4Addr("255.255.255.255/32"), // [RFC1122], ยง7 Broadcast IP Addressing - Proposed Standards
+ },
+ 1122: {
+ // [RFC1122] Requirements for Internet Hosts -- Communication Layers
+ MustIPv4Addr("0.0.0.0/8"), // [RFC1122], ยง3.2.1.3
+ MustIPv4Addr("127.0.0.0/8"), // [RFC1122], ยง3.2.1.3
+ },
+ 1112: {
+ // [RFC1112] Host Extensions for IP Multicasting
+ MustIPv4Addr("224.0.0.0/4"), // [RFC1112], ยง4 Host Group Addresses
+ },
+ 1918: {
+ // [RFC1918] Address Allocation for Private Internets
+ MustIPv4Addr("10.0.0.0/8"),
+ MustIPv4Addr("172.16.0.0/12"),
+ MustIPv4Addr("192.168.0.0/16"),
+ },
+ 2544: {
+ // [RFC2544] Benchmarking Methodology for Network
+ // Interconnect Devices
+ MustIPv4Addr("198.18.0.0/15"),
+ },
+ 2765: {
+ // [RFC2765] Stateless IP/ICMP Translation Algorithm
+ // (SIIT) (obsoleted by RFCs 6145, which itself was
+ // later obsoleted by 7915).
+
+ // [RFC2765], ยง2.1 Addresses
+ MustIPv6Addr("0:0:0:0:0:ffff:0:0/96"),
+ },
+ 2928: {
+ // [RFC2928] Initial IPv6 Sub-TLA ID Assignments
+ MustIPv6Addr("2001::/16"), // Superblock
+ //MustIPv6Addr("2001:0000::/23"), // IANA
+ //MustIPv6Addr("2001:0200::/23"), // APNIC
+ //MustIPv6Addr("2001:0400::/23"), // ARIN
+ //MustIPv6Addr("2001:0600::/23"), // RIPE NCC
+ //MustIPv6Addr("2001:0800::/23"), // (future assignment)
+ // ...
+ //MustIPv6Addr("2001:FE00::/23"), // (future assignment)
+ },
+ 3056: { // 6to4 address
+ // [RFC3056] Connection of IPv6 Domains via IPv4 Clouds
+
+ // [RFC3056], ยง2 IPv6 Prefix Allocation
+ MustIPv6Addr("2002::/16"),
+ },
+ 3068: {
+ // [RFC3068] An Anycast Prefix for 6to4 Relay Routers
+ // (obsolete by RFC7526)
+
+ // [RFC3068], ยง 6to4 Relay anycast address
+ MustIPv4Addr("192.88.99.0/24"),
+
+ // [RFC3068], ยง2.5 6to4 IPv6 relay anycast address
+ //
+ // NOTE: /120 == 128-(32-24)
+ MustIPv6Addr("2002:c058:6301::/120"),
+ },
+ 3171: {
+ // [RFC3171] IANA Guidelines for IPv4 Multicast Address Assignments
+ MustIPv4Addr("224.0.0.0/4"),
+ },
+ 3330: {
+ // [RFC3330] Special-Use IPv4 Addresses
+
+ // Addresses in this block refer to source hosts on
+ // "this" network. Address 0.0.0.0/32 may be used as a
+ // source address for this host on this network; other
+ // addresses within 0.0.0.0/8 may be used to refer to
+ // specified hosts on this network [RFC1700, page 4].
+ MustIPv4Addr("0.0.0.0/8"),
+
+ // 10.0.0.0/8 - This block is set aside for use in
+ // private networks. Its intended use is documented in
+ // [RFC1918]. Addresses within this block should not
+ // appear on the public Internet.
+ MustIPv4Addr("10.0.0.0/8"),
+
+ // 14.0.0.0/8 - This block is set aside for assignments
+ // to the international system of Public Data Networks
+ // [RFC1700, page 181]. The registry of assignments
+ // within this block can be accessed from the "Public
+ // Data Network Numbers" link on the web page at
+ // http://www.iana.org/numbers.html. Addresses within
+ // this block are assigned to users and should be
+ // treated as such.
+
+ // 24.0.0.0/8 - This block was allocated in early 1996
+ // for use in provisioning IP service over cable
+ // television systems. Although the IANA initially was
+ // involved in making assignments to cable operators,
+ // this responsibility was transferred to American
+ // Registry for Internet Numbers (ARIN) in May 2001.
+ // Addresses within this block are assigned in the
+ // normal manner and should be treated as such.
+
+ // 39.0.0.0/8 - This block was used in the "Class A
+ // Subnet Experiment" that commenced in May 1995, as
+ // documented in [RFC1797]. The experiment has been
+ // completed and this block has been returned to the
+ // pool of addresses reserved for future allocation or
+ // assignment. This block therefore no longer has a
+ // special use and is subject to allocation to a
+ // Regional Internet Registry for assignment in the
+ // normal manner.
+
+ // 127.0.0.0/8 - This block is assigned for use as the Internet host
+ // loopback address. A datagram sent by a higher level protocol to an
+ // address anywhere within this block should loop back inside the host.
+ // This is ordinarily implemented using only 127.0.0.1/32 for loopback,
+ // but no addresses within this block should ever appear on any network
+ // anywhere [RFC1700, page 5].
+ MustIPv4Addr("127.0.0.0/8"),
+
+ // 128.0.0.0/16 - This block, corresponding to the
+ // numerically lowest of the former Class B addresses,
+ // was initially and is still reserved by the IANA.
+ // Given the present classless nature of the IP address
+ // space, the basis for the reservation no longer
+ // applies and addresses in this block are subject to
+ // future allocation to a Regional Internet Registry for
+ // assignment in the normal manner.
+
+ // 169.254.0.0/16 - This is the "link local" block. It
+ // is allocated for communication between hosts on a
+ // single link. Hosts obtain these addresses by
+ // auto-configuration, such as when a DHCP server may
+ // not be found.
+ MustIPv4Addr("169.254.0.0/16"),
+
+ // 172.16.0.0/12 - This block is set aside for use in
+ // private networks. Its intended use is documented in
+ // [RFC1918]. Addresses within this block should not
+ // appear on the public Internet.
+ MustIPv4Addr("172.16.0.0/12"),
+
+ // 191.255.0.0/16 - This block, corresponding to the numerically highest
+ // to the former Class B addresses, was initially and is still reserved
+ // by the IANA. Given the present classless nature of the IP address
+ // space, the basis for the reservation no longer applies and addresses
+ // in this block are subject to future allocation to a Regional Internet
+ // Registry for assignment in the normal manner.
+
+ // 192.0.0.0/24 - This block, corresponding to the
+ // numerically lowest of the former Class C addresses,
+ // was initially and is still reserved by the IANA.
+ // Given the present classless nature of the IP address
+ // space, the basis for the reservation no longer
+ // applies and addresses in this block are subject to
+ // future allocation to a Regional Internet Registry for
+ // assignment in the normal manner.
+
+ // 192.0.2.0/24 - This block is assigned as "TEST-NET" for use in
+ // documentation and example code. It is often used in conjunction with
+ // domain names example.com or example.net in vendor and protocol
+ // documentation. Addresses within this block should not appear on the
+ // public Internet.
+ MustIPv4Addr("192.0.2.0/24"),
+
+ // 192.88.99.0/24 - This block is allocated for use as 6to4 relay
+ // anycast addresses, according to [RFC3068].
+ MustIPv4Addr("192.88.99.0/24"),
+
+ // 192.168.0.0/16 - This block is set aside for use in private networks.
+ // Its intended use is documented in [RFC1918]. Addresses within this
+ // block should not appear on the public Internet.
+ MustIPv4Addr("192.168.0.0/16"),
+
+ // 198.18.0.0/15 - This block has been allocated for use
+ // in benchmark tests of network interconnect devices.
+ // Its use is documented in [RFC2544].
+ MustIPv4Addr("198.18.0.0/15"),
+
+ // 223.255.255.0/24 - This block, corresponding to the
+ // numerically highest of the former Class C addresses,
+ // was initially and is still reserved by the IANA.
+ // Given the present classless nature of the IP address
+ // space, the basis for the reservation no longer
+ // applies and addresses in this block are subject to
+ // future allocation to a Regional Internet Registry for
+ // assignment in the normal manner.
+
+ // 224.0.0.0/4 - This block, formerly known as the Class
+ // D address space, is allocated for use in IPv4
+ // multicast address assignments. The IANA guidelines
+ // for assignments from this space are described in
+ // [RFC3171].
+ MustIPv4Addr("224.0.0.0/4"),
+
+ // 240.0.0.0/4 - This block, formerly known as the Class E address
+ // space, is reserved. The "limited broadcast" destination address
+ // 255.255.255.255 should never be forwarded outside the (sub-)net of
+ // the source. The remainder of this space is reserved
+ // for future use. [RFC1700, page 4]
+ MustIPv4Addr("240.0.0.0/4"),
+ },
+ 3849: {
+ // [RFC3849] IPv6 Address Prefix Reserved for Documentation
+ MustIPv6Addr("2001:db8::/32"), // [RFC3849], ยง4 IANA Considerations
+ },
+ 3927: {
+ // [RFC3927] Dynamic Configuration of IPv4 Link-Local Addresses
+ MustIPv4Addr("169.254.0.0/16"), // [RFC3927], ยง2.1 Link-Local Address Selection
+ },
+ 4038: {
+ // [RFC4038] Application Aspects of IPv6 Transition
+
+ // [RFC4038], ยง4.2. IPv6 Applications in a Dual-Stack Node
+ MustIPv6Addr("0:0:0:0:0:ffff::/96"),
+ },
+ 4193: {
+ // [RFC4193] Unique Local IPv6 Unicast Addresses
+ MustIPv6Addr("fc00::/7"),
+ },
+ 4291: {
+ // [RFC4291] IP Version 6 Addressing Architecture
+
+ // [RFC4291], ยง2.5.2 The Unspecified Address
+ MustIPv6Addr("::/128"),
+
+ // [RFC4291], ยง2.5.3 The Loopback Address
+ MustIPv6Addr("::1/128"),
+
+ // [RFC4291], ยง2.5.5.1. IPv4-Compatible IPv6 Address
+ MustIPv6Addr("::/96"),
+
+ // [RFC4291], ยง2.5.5.2. IPv4-Mapped IPv6 Address
+ MustIPv6Addr("::ffff:0:0/96"),
+
+ // [RFC4291], ยง2.5.6 Link-Local IPv6 Unicast Addresses
+ MustIPv6Addr("fe80::/10"),
+
+ // [RFC4291], ยง2.5.7 Site-Local IPv6 Unicast Addresses
+ // (depreciated)
+ MustIPv6Addr("fec0::/10"),
+
+ // [RFC4291], ยง2.7 Multicast Addresses
+ MustIPv6Addr("ff00::/8"),
+
+ // IPv6 Multicast Information.
+ //
+ // In the following "table" below, `ff0x` is replaced
+ // with the following values depending on the scope of
+ // the query:
+ //
+ // IPv6 Multicast Scopes:
+ // * ff00/9 // reserved
+ // * ff01/9 // interface-local
+ // * ff02/9 // link-local
+ // * ff03/9 // realm-local
+ // * ff04/9 // admin-local
+ // * ff05/9 // site-local
+ // * ff08/9 // organization-local
+ // * ff0e/9 // global
+ // * ff0f/9 // reserved
+ //
+ // IPv6 Multicast Addresses:
+ // * ff0x::2 // All routers
+ // * ff02::5 // OSPFIGP
+ // * ff02::6 // OSPFIGP Designated Routers
+ // * ff02::9 // RIP Routers
+ // * ff02::a // EIGRP Routers
+ // * ff02::d // All PIM Routers
+ // * ff02::1a // All RPL Routers
+ // * ff0x::fb // mDNSv6
+ // * ff0x::101 // All Network Time Protocol (NTP) servers
+ // * ff02::1:1 // Link Name
+ // * ff02::1:2 // All-dhcp-agents
+ // * ff02::1:3 // Link-local Multicast Name Resolution
+ // * ff05::1:3 // All-dhcp-servers
+ // * ff02::1:ff00:0/104 // Solicited-node multicast address.
+ // * ff02::2:ff00:0/104 // Node Information Queries
+ },
+ 4380: {
+ // [RFC4380] Teredo: Tunneling IPv6 over UDP through
+ // Network Address Translations (NATs)
+
+ // [RFC4380], ยง2.6 Global Teredo IPv6 Service Prefix
+ MustIPv6Addr("2001:0000::/32"),
+ },
+ 4773: {
+ // [RFC4773] Administration of the IANA Special Purpose IPv6 Address Block
+ MustIPv6Addr("2001:0000::/23"), // IANA
+ },
+ 4843: {
+ // [RFC4843] An IPv6 Prefix for Overlay Routable Cryptographic Hash Identifiers (ORCHID)
+ MustIPv6Addr("2001:10::/28"), // [RFC4843], ยง7 IANA Considerations
+ },
+ 5180: {
+ // [RFC5180] IPv6 Benchmarking Methodology for Network Interconnect Devices
+ MustIPv6Addr("2001:0200::/48"), // [RFC5180], ยง8 IANA Considerations
+ },
+ 5735: {
+ // [RFC5735] Special Use IPv4 Addresses
+ MustIPv4Addr("192.0.2.0/24"), // TEST-NET-1
+ MustIPv4Addr("198.51.100.0/24"), // TEST-NET-2
+ MustIPv4Addr("203.0.113.0/24"), // TEST-NET-3
+ MustIPv4Addr("198.18.0.0/15"), // Benchmarks
+ },
+ 5737: {
+ // [RFC5737] IPv4 Address Blocks Reserved for Documentation
+ MustIPv4Addr("192.0.2.0/24"), // TEST-NET-1
+ MustIPv4Addr("198.51.100.0/24"), // TEST-NET-2
+ MustIPv4Addr("203.0.113.0/24"), // TEST-NET-3
+ },
+ 6052: {
+ // [RFC6052] IPv6 Addressing of IPv4/IPv6 Translators
+ MustIPv6Addr("64:ff9b::/96"), // [RFC6052], ยง2.1. Well-Known Prefix
+ },
+ 6333: {
+ // [RFC6333] Dual-Stack Lite Broadband Deployments Following IPv4 Exhaustion
+ MustIPv4Addr("192.0.0.0/29"), // [RFC6333], ยง5.7 Well-Known IPv4 Address
+ },
+ 6598: {
+ // [RFC6598] IANA-Reserved IPv4 Prefix for Shared Address Space
+ MustIPv4Addr("100.64.0.0/10"),
+ },
+ 6666: {
+ // [RFC6666] A Discard Prefix for IPv6
+ MustIPv6Addr("0100::/64"),
+ },
+ 6890: {
+ // [RFC6890] Special-Purpose IP Address Registries
+
+ // From "RFC6890 ยง2.2.1 Information Requirements":
+ /*
+ The IPv4 and IPv6 Special-Purpose Address Registries maintain the
+ following information regarding each entry:
+
+ o Address Block - A block of IPv4 or IPv6 addresses that has been
+ registered for a special purpose.
+
+ o Name - A descriptive name for the special-purpose address block.
+
+ o RFC - The RFC through which the special-purpose address block was
+ requested.
+
+ o Allocation Date - The date upon which the special-purpose address
+ block was allocated.
+
+ o Termination Date - The date upon which the allocation is to be
+ terminated. This field is applicable for limited-use allocations
+ only.
+
+ o Source - A boolean value indicating whether an address from the
+ allocated special-purpose address block is valid when used as the
+ source address of an IP datagram that transits two devices.
+
+ o Destination - A boolean value indicating whether an address from
+ the allocated special-purpose address block is valid when used as
+ the destination address of an IP datagram that transits two
+ devices.
+
+ o Forwardable - A boolean value indicating whether a router may
+ forward an IP datagram whose destination address is drawn from the
+ allocated special-purpose address block between external
+ interfaces.
+
+ o Global - A boolean value indicating whether an IP datagram whose
+ destination address is drawn from the allocated special-purpose
+ address block is forwardable beyond a specified administrative
+ domain.
+
+ o Reserved-by-Protocol - A boolean value indicating whether the
+ special-purpose address block is reserved by IP, itself. This
+ value is "TRUE" if the RFC that created the special-purpose
+ address block requires all compliant IP implementations to behave
+ in a special way when processing packets either to or from
+ addresses contained by the address block.
+
+ If the value of "Destination" is FALSE, the values of "Forwardable"
+ and "Global" must also be false.
+ */
+
+ /*+----------------------+----------------------------+
+ * | Attribute | Value |
+ * +----------------------+----------------------------+
+ * | Address Block | 0.0.0.0/8 |
+ * | Name | "This host on this network"|
+ * | RFC | [RFC1122], Section 3.2.1.3 |
+ * | Allocation Date | September 1981 |
+ * | Termination Date | N/A |
+ * | Source | True |
+ * | Destination | False |
+ * | Forwardable | False |
+ * | Global | False |
+ * | Reserved-by-Protocol | True |
+ * +----------------------+----------------------------+*/
+ MustIPv4Addr("0.0.0.0/8"),
+
+ /*+----------------------+---------------+
+ * | Attribute | Value |
+ * +----------------------+---------------+
+ * | Address Block | 10.0.0.0/8 |
+ * | Name | Private-Use |
+ * | RFC | [RFC1918] |
+ * | Allocation Date | February 1996 |
+ * | Termination Date | N/A |
+ * | Source | True |
+ * | Destination | True |
+ * | Forwardable | True |
+ * | Global | False |
+ * | Reserved-by-Protocol | False |
+ * +----------------------+---------------+ */
+ MustIPv4Addr("10.0.0.0/8"),
+
+ /*+----------------------+----------------------+
+ | Attribute | Value |
+ +----------------------+----------------------+
+ | Address Block | 100.64.0.0/10 |
+ | Name | Shared Address Space |
+ | RFC | [RFC6598] |
+ | Allocation Date | April 2012 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+----------------------+*/
+ MustIPv4Addr("100.64.0.0/10"),
+
+ /*+----------------------+----------------------------+
+ | Attribute | Value |
+ +----------------------+----------------------------+
+ | Address Block | 127.0.0.0/8 |
+ | Name | Loopback |
+ | RFC | [RFC1122], Section 3.2.1.3 |
+ | Allocation Date | September 1981 |
+ | Termination Date | N/A |
+ | Source | False [1] |
+ | Destination | False [1] |
+ | Forwardable | False [1] |
+ | Global | False [1] |
+ | Reserved-by-Protocol | True |
+ +----------------------+----------------------------+*/
+ // [1] Several protocols have been granted exceptions to
+ // this rule. For examples, see [RFC4379] and
+ // [RFC5884].
+ MustIPv4Addr("127.0.0.0/8"),
+
+ /*+----------------------+----------------+
+ | Attribute | Value |
+ +----------------------+----------------+
+ | Address Block | 169.254.0.0/16 |
+ | Name | Link Local |
+ | RFC | [RFC3927] |
+ | Allocation Date | May 2005 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | True |
+ +----------------------+----------------+*/
+ MustIPv4Addr("169.254.0.0/16"),
+
+ /*+----------------------+---------------+
+ | Attribute | Value |
+ +----------------------+---------------+
+ | Address Block | 172.16.0.0/12 |
+ | Name | Private-Use |
+ | RFC | [RFC1918] |
+ | Allocation Date | February 1996 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+---------------+*/
+ MustIPv4Addr("172.16.0.0/12"),
+
+ /*+----------------------+---------------------------------+
+ | Attribute | Value |
+ +----------------------+---------------------------------+
+ | Address Block | 192.0.0.0/24 [2] |
+ | Name | IETF Protocol Assignments |
+ | RFC | Section 2.1 of this document |
+ | Allocation Date | January 2010 |
+ | Termination Date | N/A |
+ | Source | False |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+---------------------------------+*/
+ // [2] Not usable unless by virtue of a more specific
+ // reservation.
+ MustIPv4Addr("192.0.0.0/24"),
+
+ /*+----------------------+--------------------------------+
+ | Attribute | Value |
+ +----------------------+--------------------------------+
+ | Address Block | 192.0.0.0/29 |
+ | Name | IPv4 Service Continuity Prefix |
+ | RFC | [RFC6333], [RFC7335] |
+ | Allocation Date | June 2011 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+--------------------------------+*/
+ MustIPv4Addr("192.0.0.0/29"),
+
+ /*+----------------------+----------------------------+
+ | Attribute | Value |
+ +----------------------+----------------------------+
+ | Address Block | 192.0.2.0/24 |
+ | Name | Documentation (TEST-NET-1) |
+ | RFC | [RFC5737] |
+ | Allocation Date | January 2010 |
+ | Termination Date | N/A |
+ | Source | False |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+----------------------------+*/
+ MustIPv4Addr("192.0.2.0/24"),
+
+ /*+----------------------+--------------------+
+ | Attribute | Value |
+ +----------------------+--------------------+
+ | Address Block | 192.88.99.0/24 |
+ | Name | 6to4 Relay Anycast |
+ | RFC | [RFC3068] |
+ | Allocation Date | June 2001 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | True |
+ | Reserved-by-Protocol | False |
+ +----------------------+--------------------+*/
+ MustIPv4Addr("192.88.99.0/24"),
+
+ /*+----------------------+----------------+
+ | Attribute | Value |
+ +----------------------+----------------+
+ | Address Block | 192.168.0.0/16 |
+ | Name | Private-Use |
+ | RFC | [RFC1918] |
+ | Allocation Date | February 1996 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+----------------+*/
+ MustIPv4Addr("192.168.0.0/16"),
+
+ /*+----------------------+---------------+
+ | Attribute | Value |
+ +----------------------+---------------+
+ | Address Block | 198.18.0.0/15 |
+ | Name | Benchmarking |
+ | RFC | [RFC2544] |
+ | Allocation Date | March 1999 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+---------------+*/
+ MustIPv4Addr("198.18.0.0/15"),
+
+ /*+----------------------+----------------------------+
+ | Attribute | Value |
+ +----------------------+----------------------------+
+ | Address Block | 198.51.100.0/24 |
+ | Name | Documentation (TEST-NET-2) |
+ | RFC | [RFC5737] |
+ | Allocation Date | January 2010 |
+ | Termination Date | N/A |
+ | Source | False |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+----------------------------+*/
+ MustIPv4Addr("198.51.100.0/24"),
+
+ /*+----------------------+----------------------------+
+ | Attribute | Value |
+ +----------------------+----------------------------+
+ | Address Block | 203.0.113.0/24 |
+ | Name | Documentation (TEST-NET-3) |
+ | RFC | [RFC5737] |
+ | Allocation Date | January 2010 |
+ | Termination Date | N/A |
+ | Source | False |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+----------------------------+*/
+ MustIPv4Addr("203.0.113.0/24"),
+
+ /*+----------------------+----------------------+
+ | Attribute | Value |
+ +----------------------+----------------------+
+ | Address Block | 240.0.0.0/4 |
+ | Name | Reserved |
+ | RFC | [RFC1112], Section 4 |
+ | Allocation Date | August 1989 |
+ | Termination Date | N/A |
+ | Source | False |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | True |
+ +----------------------+----------------------+*/
+ MustIPv4Addr("240.0.0.0/4"),
+
+ /*+----------------------+----------------------+
+ | Attribute | Value |
+ +----------------------+----------------------+
+ | Address Block | 255.255.255.255/32 |
+ | Name | Limited Broadcast |
+ | RFC | [RFC0919], Section 7 |
+ | Allocation Date | October 1984 |
+ | Termination Date | N/A |
+ | Source | False |
+ | Destination | True |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+----------------------+*/
+ MustIPv4Addr("255.255.255.255/32"),
+
+ /*+----------------------+------------------+
+ | Attribute | Value |
+ +----------------------+------------------+
+ | Address Block | ::1/128 |
+ | Name | Loopback Address |
+ | RFC | [RFC4291] |
+ | Allocation Date | February 2006 |
+ | Termination Date | N/A |
+ | Source | False |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | True |
+ +----------------------+------------------+*/
+ MustIPv6Addr("::1/128"),
+
+ /*+----------------------+---------------------+
+ | Attribute | Value |
+ +----------------------+---------------------+
+ | Address Block | ::/128 |
+ | Name | Unspecified Address |
+ | RFC | [RFC4291] |
+ | Allocation Date | February 2006 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | True |
+ +----------------------+---------------------+*/
+ MustIPv6Addr("::/128"),
+
+ /*+----------------------+---------------------+
+ | Attribute | Value |
+ +----------------------+---------------------+
+ | Address Block | 64:ff9b::/96 |
+ | Name | IPv4-IPv6 Translat. |
+ | RFC | [RFC6052] |
+ | Allocation Date | October 2010 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | True |
+ | Reserved-by-Protocol | False |
+ +----------------------+---------------------+*/
+ MustIPv6Addr("64:ff9b::/96"),
+
+ /*+----------------------+---------------------+
+ | Attribute | Value |
+ +----------------------+---------------------+
+ | Address Block | ::ffff:0:0/96 |
+ | Name | IPv4-mapped Address |
+ | RFC | [RFC4291] |
+ | Allocation Date | February 2006 |
+ | Termination Date | N/A |
+ | Source | False |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | True |
+ +----------------------+---------------------+*/
+ MustIPv6Addr("::ffff:0:0/96"),
+
+ /*+----------------------+----------------------------+
+ | Attribute | Value |
+ +----------------------+----------------------------+
+ | Address Block | 100::/64 |
+ | Name | Discard-Only Address Block |
+ | RFC | [RFC6666] |
+ | Allocation Date | June 2012 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+----------------------------+*/
+ MustIPv6Addr("100::/64"),
+
+ /*+----------------------+---------------------------+
+ | Attribute | Value |
+ +----------------------+---------------------------+
+ | Address Block | 2001::/23 |
+ | Name | IETF Protocol Assignments |
+ | RFC | [RFC2928] |
+ | Allocation Date | September 2000 |
+ | Termination Date | N/A |
+ | Source | False[1] |
+ | Destination | False[1] |
+ | Forwardable | False[1] |
+ | Global | False[1] |
+ | Reserved-by-Protocol | False |
+ +----------------------+---------------------------+*/
+ // [1] Unless allowed by a more specific allocation.
+ MustIPv6Addr("2001::/16"),
+
+ /*+----------------------+----------------+
+ | Attribute | Value |
+ +----------------------+----------------+
+ | Address Block | 2001::/32 |
+ | Name | TEREDO |
+ | RFC | [RFC4380] |
+ | Allocation Date | January 2006 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+----------------+*/
+ // Covered by previous entry, included for completeness.
+ //
+ // MustIPv6Addr("2001::/16"),
+
+ /*+----------------------+----------------+
+ | Attribute | Value |
+ +----------------------+----------------+
+ | Address Block | 2001:2::/48 |
+ | Name | Benchmarking |
+ | RFC | [RFC5180] |
+ | Allocation Date | April 2008 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+----------------+*/
+ // Covered by previous entry, included for completeness.
+ //
+ // MustIPv6Addr("2001:2::/48"),
+
+ /*+----------------------+---------------+
+ | Attribute | Value |
+ +----------------------+---------------+
+ | Address Block | 2001:db8::/32 |
+ | Name | Documentation |
+ | RFC | [RFC3849] |
+ | Allocation Date | July 2004 |
+ | Termination Date | N/A |
+ | Source | False |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+---------------+*/
+ // Covered by previous entry, included for completeness.
+ //
+ // MustIPv6Addr("2001:db8::/32"),
+
+ /*+----------------------+--------------+
+ | Attribute | Value |
+ +----------------------+--------------+
+ | Address Block | 2001:10::/28 |
+ | Name | ORCHID |
+ | RFC | [RFC4843] |
+ | Allocation Date | March 2007 |
+ | Termination Date | March 2014 |
+ | Source | False |
+ | Destination | False |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+--------------+*/
+ // Covered by previous entry, included for completeness.
+ //
+ // MustIPv6Addr("2001:10::/28"),
+
+ /*+----------------------+---------------+
+ | Attribute | Value |
+ +----------------------+---------------+
+ | Address Block | 2002::/16 [2] |
+ | Name | 6to4 |
+ | RFC | [RFC3056] |
+ | Allocation Date | February 2001 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | N/A [2] |
+ | Reserved-by-Protocol | False |
+ +----------------------+---------------+*/
+ // [2] See [RFC3056] for details.
+ MustIPv6Addr("2002::/16"),
+
+ /*+----------------------+--------------+
+ | Attribute | Value |
+ +----------------------+--------------+
+ | Address Block | fc00::/7 |
+ | Name | Unique-Local |
+ | RFC | [RFC4193] |
+ | Allocation Date | October 2005 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | True |
+ | Global | False |
+ | Reserved-by-Protocol | False |
+ +----------------------+--------------+*/
+ MustIPv6Addr("fc00::/7"),
+
+ /*+----------------------+-----------------------+
+ | Attribute | Value |
+ +----------------------+-----------------------+
+ | Address Block | fe80::/10 |
+ | Name | Linked-Scoped Unicast |
+ | RFC | [RFC4291] |
+ | Allocation Date | February 2006 |
+ | Termination Date | N/A |
+ | Source | True |
+ | Destination | True |
+ | Forwardable | False |
+ | Global | False |
+ | Reserved-by-Protocol | True |
+ +----------------------+-----------------------+*/
+ MustIPv6Addr("fe80::/10"),
+ },
+ 7335: {
+ // [RFC7335] IPv4 Service Continuity Prefix
+ MustIPv4Addr("192.0.0.0/29"), // [RFC7335], ยง6 IANA Considerations
+ },
+ ForwardingBlacklist: { // Pseudo-RFC
+ // Blacklist of non-forwardable IP blocks taken from RFC6890
+ //
+ // TODO: the attributes for forwardable should be
+ // searcahble and embedded in the main list of RFCs
+ // above.
+ MustIPv4Addr("0.0.0.0/8"),
+ MustIPv4Addr("127.0.0.0/8"),
+ MustIPv4Addr("169.254.0.0/16"),
+ MustIPv4Addr("192.0.0.0/24"),
+ MustIPv4Addr("192.0.2.0/24"),
+ MustIPv4Addr("198.51.100.0/24"),
+ MustIPv4Addr("203.0.113.0/24"),
+ MustIPv4Addr("240.0.0.0/4"),
+ MustIPv4Addr("255.255.255.255/32"),
+ MustIPv6Addr("::1/128"),
+ MustIPv6Addr("::/128"),
+ MustIPv6Addr("::ffff:0:0/96"),
+
+ // There is no way of expressing a whitelist per RFC2928
+ // atm without creating a negative mask, which I don't
+ // want to do atm.
+ //MustIPv6Addr("2001::/23"),
+
+ MustIPv6Addr("2001:db8::/32"),
+ MustIPv6Addr("2001:10::/28"),
+ MustIPv6Addr("fe80::/10"),
+ },
+ }
+}
+
+// VisitAllRFCs iterates over all known RFCs and calls the visitor
+func VisitAllRFCs(fn func(rfcNum uint, sockaddrs SockAddrs)) {
+ rfcNetMap := KnownRFCs()
+
+ // Blacklist of faux-RFCs. Don't show the world that we're abusing the
+ // RFC system in this library.
+ rfcBlacklist := map[uint]struct{}{
+ ForwardingBlacklist: {},
+ }
+
+ for rfcNum, sas := range rfcNetMap {
+ if _, found := rfcBlacklist[rfcNum]; !found {
+ fn(rfcNum, sas)
+ }
+ }
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info.go b/vendor/github.com/hashicorp/go-sockaddr/route_info.go
new file mode 100644
index 0000000..2a3ee1d
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/route_info.go
@@ -0,0 +1,19 @@
+package sockaddr
+
+// RouteInterface specifies an interface for obtaining memoized route table and
+// network information from a given OS.
+type RouteInterface interface {
+ // GetDefaultInterfaceName returns the name of the interface that has a
+ // default route or an error and an empty string if a problem was
+ // encountered.
+ GetDefaultInterfaceName() (string, error)
+}
+
+// VisitCommands visits each command used by the platform-specific RouteInfo
+// implementation.
+func (ri routeInfo) VisitCommands(fn func(name string, cmd []string)) {
+ for k, v := range ri.cmds {
+ cmds := append([]string(nil), v...)
+ fn(k, cmds)
+ }
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info_bsd.go b/vendor/github.com/hashicorp/go-sockaddr/route_info_bsd.go
new file mode 100644
index 0000000..705757a
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/route_info_bsd.go
@@ -0,0 +1,36 @@
+// +build darwin dragonfly freebsd netbsd openbsd
+
+package sockaddr
+
+import "os/exec"
+
+var cmds map[string][]string = map[string][]string{
+ "route": {"/sbin/route", "-n", "get", "default"},
+}
+
+type routeInfo struct {
+ cmds map[string][]string
+}
+
+// NewRouteInfo returns a BSD-specific implementation of the RouteInfo
+// interface.
+func NewRouteInfo() (routeInfo, error) {
+ return routeInfo{
+ cmds: cmds,
+ }, 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["route"][0], cmds["route"][1:]...).Output()
+ if err != nil {
+ return "", err
+ }
+
+ var ifName string
+ if ifName, err = parseDefaultIfNameFromRoute(string(out)); err != nil {
+ return "", err
+ }
+ return ifName, nil
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info_default.go b/vendor/github.com/hashicorp/go-sockaddr/route_info_default.go
new file mode 100644
index 0000000..d1b009f
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/route_info_default.go
@@ -0,0 +1,10 @@
+// +build android nacl plan9
+
+package sockaddr
+
+import "errors"
+
+// getDefaultIfName is the default interface function for unsupported platforms.
+func getDefaultIfName() (string, error) {
+ return "", errors.New("No default interface found (unsupported platform)")
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info_linux.go b/vendor/github.com/hashicorp/go-sockaddr/route_info_linux.go
new file mode 100644
index 0000000..c2ec91e
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/route_info_linux.go
@@ -0,0 +1,40 @@
+package sockaddr
+
+import (
+ "errors"
+ "os/exec"
+)
+
+type routeInfo struct {
+ cmds map[string][]string
+}
+
+// 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: 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(ri.cmds["ip"][0], ri.cmds["ip"][1:]...).Output()
+ if err != nil {
+ return "", err
+ }
+
+ var ifName string
+ if ifName, err = parseDefaultIfNameFromIPCmd(string(out)); err != nil {
+ return "", errors.New("No default interface found")
+ }
+ return ifName, nil
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info_solaris.go b/vendor/github.com/hashicorp/go-sockaddr/route_info_solaris.go
new file mode 100644
index 0000000..ee8e798
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/route_info_solaris.go
@@ -0,0 +1,37 @@
+package sockaddr
+
+import (
+ "errors"
+ "os/exec"
+)
+
+var cmds map[string][]string = map[string][]string{
+ "route": {"/usr/sbin/route", "-n", "get", "default"},
+}
+
+type routeInfo struct {
+ cmds map[string][]string
+}
+
+// NewRouteInfo returns a BSD-specific implementation of the RouteInfo
+// interface.
+func NewRouteInfo() (routeInfo, error) {
+ return routeInfo{
+ cmds: cmds,
+ }, 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["route"][0], cmds["route"][1:]...).Output()
+ if err != nil {
+ return "", err
+ }
+
+ var ifName string
+ if ifName, err = parseDefaultIfNameFromRoute(string(out)); err != nil {
+ return "", errors.New("No default interface found")
+ }
+ return ifName, nil
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/route_info_windows.go b/vendor/github.com/hashicorp/go-sockaddr/route_info_windows.go
new file mode 100644
index 0000000..3da9728
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/route_info_windows.go
@@ -0,0 +1,41 @@
+package sockaddr
+
+import "os/exec"
+
+var cmds map[string][]string = map[string][]string{
+ "netstat": {"netstat", "-rn"},
+ "ipconfig": {"ipconfig"},
+}
+
+type routeInfo struct {
+ cmds map[string][]string
+}
+
+// NewRouteInfo returns a BSD-specific implementation of the RouteInfo
+// interface.
+func NewRouteInfo() (routeInfo, error) {
+ return routeInfo{
+ cmds: cmds,
+ }, nil
+}
+
+// GetDefaultInterfaceName returns the interface name attached to the default
+// route on the default interface.
+func (ri routeInfo) GetDefaultInterfaceName() (string, error) {
+ ifNameOut, err := exec.Command(cmds["netstat"][0], cmds["netstat"][1:]...).Output()
+ if err != nil {
+ return "", err
+ }
+
+ ipconfigOut, err := exec.Command(cmds["ipconfig"][0], cmds["ipconfig"][1:]...).Output()
+ if err != nil {
+ return "", err
+ }
+
+ ifName, err := parseDefaultIfNameWindows(string(ifNameOut), string(ipconfigOut))
+ if err != nil {
+ return "", err
+ }
+
+ return ifName, nil
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/sockaddr.go b/vendor/github.com/hashicorp/go-sockaddr/sockaddr.go
new file mode 100644
index 0000000..826c91c
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/sockaddr.go
@@ -0,0 +1,206 @@
+package sockaddr
+
+import (
+ "encoding/json"
+ "fmt"
+ "strings"
+)
+
+type SockAddrType int
+type AttrName string
+
+const (
+ TypeUnknown SockAddrType = 0x0
+ TypeUnix = 0x1
+ TypeIPv4 = 0x2
+ TypeIPv6 = 0x4
+
+ // TypeIP is the union of TypeIPv4 and TypeIPv6
+ TypeIP = 0x6
+)
+
+type SockAddr interface {
+ // CmpRFC returns 0 if SockAddr exactly matches one of the matched RFC
+ // networks, -1 if the receiver is contained within the RFC network, or
+ // 1 if the address is not contained within the RFC.
+ CmpRFC(rfcNum uint, sa SockAddr) int
+
+ // Contains returns true if the SockAddr arg is contained within the
+ // receiver
+ Contains(SockAddr) bool
+
+ // Equal allows for the comparison of two SockAddrs
+ Equal(SockAddr) bool
+
+ DialPacketArgs() (string, string)
+ DialStreamArgs() (string, string)
+ ListenPacketArgs() (string, string)
+ ListenStreamArgs() (string, string)
+
+ // String returns the string representation of SockAddr
+ String() string
+
+ // Type returns the SockAddrType
+ Type() SockAddrType
+}
+
+// sockAddrAttrMap is a map of the SockAddr type-specific attributes.
+var sockAddrAttrMap map[AttrName]func(SockAddr) string
+var sockAddrAttrs []AttrName
+
+func init() {
+ sockAddrInit()
+}
+
+// New creates a new SockAddr from the string. The order in which New()
+// attempts to construct a SockAddr is: IPv4Addr, IPv6Addr, SockAddrUnix.
+//
+// NOTE: New() relies on the heuristic wherein if the path begins with either a
+// '.' or '/' character before creating a new UnixSock. For UNIX sockets that
+// are absolute paths or are nested within a sub-directory, this works as
+// expected, however if the UNIX socket is contained in the current working
+// directory, this will fail unless the path begins with "./"
+// (e.g. "./my-local-socket"). Calls directly to NewUnixSock() do not suffer
+// this limitation. Invalid IP addresses such as "256.0.0.0/-1" will run afoul
+// of this heuristic and be assumed to be a valid UNIX socket path (which they
+// are, but it is probably not what you want and you won't realize it until you
+// stat(2) the file system to discover it doesn't exist).
+func NewSockAddr(s string) (SockAddr, error) {
+ ipv4Addr, err := NewIPv4Addr(s)
+ if err == nil {
+ return ipv4Addr, nil
+ }
+
+ ipv6Addr, err := NewIPv6Addr(s)
+ if err == nil {
+ return ipv6Addr, nil
+ }
+
+ // Check to make sure the string begins with either a '.' or '/', or
+ // contains a '/'.
+ if len(s) > 1 && (strings.IndexAny(s[0:1], "./") != -1 || strings.IndexByte(s, '/') != -1) {
+ unixSock, err := NewUnixSock(s)
+ if err == nil {
+ return unixSock, nil
+ }
+ }
+
+ return nil, fmt.Errorf("Unable to convert %q to an IPv4 or IPv6 address, or a UNIX Socket", s)
+}
+
+// ToIPAddr returns an IPAddr type or nil if the type conversion fails.
+func ToIPAddr(sa SockAddr) *IPAddr {
+ ipa, ok := sa.(IPAddr)
+ if !ok {
+ return nil
+ }
+ return &ipa
+}
+
+// ToIPv4Addr returns an IPv4Addr type or nil if the type conversion fails.
+func ToIPv4Addr(sa SockAddr) *IPv4Addr {
+ switch v := sa.(type) {
+ case IPv4Addr:
+ return &v
+ default:
+ return nil
+ }
+}
+
+// ToIPv6Addr returns an IPv6Addr type or nil if the type conversion fails.
+func ToIPv6Addr(sa SockAddr) *IPv6Addr {
+ switch v := sa.(type) {
+ case IPv6Addr:
+ return &v
+ default:
+ return nil
+ }
+}
+
+// ToUnixSock returns a UnixSock type or nil if the type conversion fails.
+func ToUnixSock(sa SockAddr) *UnixSock {
+ switch v := sa.(type) {
+ case UnixSock:
+ return &v
+ default:
+ return nil
+ }
+}
+
+// SockAddrAttr returns a string representation of an attribute for the given
+// SockAddr.
+func SockAddrAttr(sa SockAddr, selector AttrName) string {
+ fn, found := sockAddrAttrMap[selector]
+ if !found {
+ return ""
+ }
+
+ return fn(sa)
+}
+
+// String() for SockAddrType returns a string representation of the
+// SockAddrType (e.g. "IPv4", "IPv6", "UNIX", "IP", or "unknown").
+func (sat SockAddrType) String() string {
+ switch sat {
+ case TypeIPv4:
+ return "IPv4"
+ case TypeIPv6:
+ return "IPv6"
+ // There is no concrete "IP" type. Leaving here as a reminder.
+ // case TypeIP:
+ // return "IP"
+ case TypeUnix:
+ return "UNIX"
+ default:
+ panic("unsupported type")
+ }
+}
+
+// sockAddrInit is called once at init()
+func sockAddrInit() {
+ sockAddrAttrs = []AttrName{
+ "type", // type should be first
+ "string",
+ }
+
+ sockAddrAttrMap = map[AttrName]func(sa SockAddr) string{
+ "string": func(sa SockAddr) string {
+ return sa.String()
+ },
+ "type": func(sa SockAddr) string {
+ return sa.Type().String()
+ },
+ }
+}
+
+// UnixSockAttrs returns a list of attributes supported by the UnixSock type
+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
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/sockaddrs.go b/vendor/github.com/hashicorp/go-sockaddr/sockaddrs.go
new file mode 100644
index 0000000..75fbffb
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/sockaddrs.go
@@ -0,0 +1,193 @@
+package sockaddr
+
+import (
+ "bytes"
+ "sort"
+)
+
+// SockAddrs is a slice of SockAddrs
+type SockAddrs []SockAddr
+
+func (s SockAddrs) Len() int { return len(s) }
+func (s SockAddrs) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// CmpAddrFunc is the function signature that must be met to be used in the
+// OrderedAddrBy multiAddrSorter
+type CmpAddrFunc func(p1, p2 *SockAddr) int
+
+// multiAddrSorter implements the Sort interface, sorting the SockAddrs within.
+type multiAddrSorter struct {
+ addrs SockAddrs
+ cmp []CmpAddrFunc
+}
+
+// Sort sorts the argument slice according to the Cmp functions passed to
+// OrderedAddrBy.
+func (ms *multiAddrSorter) Sort(sockAddrs SockAddrs) {
+ ms.addrs = sockAddrs
+ sort.Sort(ms)
+}
+
+// OrderedAddrBy sorts SockAddr by the list of sort function pointers.
+func OrderedAddrBy(cmpFuncs ...CmpAddrFunc) *multiAddrSorter {
+ return &multiAddrSorter{
+ cmp: cmpFuncs,
+ }
+}
+
+// Len is part of sort.Interface.
+func (ms *multiAddrSorter) Len() int {
+ return len(ms.addrs)
+}
+
+// Less is part of sort.Interface. It is implemented by looping along the
+// Cmp() functions until it finds a comparison that is either less than,
+// equal to, or greater than.
+func (ms *multiAddrSorter) Less(i, j int) bool {
+ p, q := &ms.addrs[i], &ms.addrs[j]
+ // Try all but the last comparison.
+ var k int
+ for k = 0; k < len(ms.cmp)-1; k++ {
+ cmp := ms.cmp[k]
+ x := cmp(p, q)
+ switch x {
+ case -1:
+ // p < q, so we have a decision.
+ return true
+ case 1:
+ // p > q, so we have a decision.
+ return false
+ }
+ // p == q; try the next comparison.
+ }
+ // All comparisons to here said "equal", so just return whatever the
+ // final comparison reports.
+ switch ms.cmp[k](p, q) {
+ case -1:
+ return true
+ case 1:
+ return false
+ default:
+ // Still a tie! Now what?
+ return false
+ }
+}
+
+// Swap is part of sort.Interface.
+func (ms *multiAddrSorter) Swap(i, j int) {
+ ms.addrs[i], ms.addrs[j] = ms.addrs[j], ms.addrs[i]
+}
+
+const (
+ // NOTE (sean@): These constants are here for code readability only and
+ // are sprucing up the code for readability purposes. Some of the
+ // Cmp*() variants have confusing logic (especially when dealing with
+ // mixed-type comparisons) and this, I think, has made it easier to grok
+ // the code faster.
+ sortReceiverBeforeArg = -1
+ sortDeferDecision = 0
+ sortArgBeforeReceiver = 1
+)
+
+// AscAddress is a sorting function to sort SockAddrs by their respective
+// address type. Non-equal types are deferred in the sort.
+func AscAddress(p1Ptr, p2Ptr *SockAddr) int {
+ p1 := *p1Ptr
+ p2 := *p2Ptr
+
+ switch v := p1.(type) {
+ case IPv4Addr:
+ return v.CmpAddress(p2)
+ case IPv6Addr:
+ return v.CmpAddress(p2)
+ case UnixSock:
+ return v.CmpAddress(p2)
+ default:
+ return sortDeferDecision
+ }
+}
+
+// AscPort is a sorting function to sort SockAddrs by their respective address
+// type. Non-equal types are deferred in the sort.
+func AscPort(p1Ptr, p2Ptr *SockAddr) int {
+ p1 := *p1Ptr
+ p2 := *p2Ptr
+
+ switch v := p1.(type) {
+ case IPv4Addr:
+ return v.CmpPort(p2)
+ case IPv6Addr:
+ return v.CmpPort(p2)
+ default:
+ return sortDeferDecision
+ }
+}
+
+// AscPrivate is a sorting function to sort "more secure" private values before
+// "more public" values. Both IPv4 and IPv6 are compared against RFC6890
+// (RFC6890 includes, and is not limited to, RFC1918 and RFC6598 for IPv4, and
+// IPv6 includes RFC4193).
+func AscPrivate(p1Ptr, p2Ptr *SockAddr) int {
+ p1 := *p1Ptr
+ p2 := *p2Ptr
+
+ switch v := p1.(type) {
+ case IPv4Addr, IPv6Addr:
+ return v.CmpRFC(6890, p2)
+ default:
+ return sortDeferDecision
+ }
+}
+
+// AscNetworkSize is a sorting function to sort SockAddrs based on their network
+// size. Non-equal types are deferred in the sort.
+func AscNetworkSize(p1Ptr, p2Ptr *SockAddr) int {
+ p1 := *p1Ptr
+ p2 := *p2Ptr
+ p1Type := p1.Type()
+ p2Type := p2.Type()
+
+ // Network size operations on non-IP types make no sense
+ if p1Type != p2Type && p1Type != TypeIP {
+ return sortDeferDecision
+ }
+
+ ipA := p1.(IPAddr)
+ ipB := p2.(IPAddr)
+
+ return bytes.Compare([]byte(*ipA.NetIPMask()), []byte(*ipB.NetIPMask()))
+}
+
+// AscType is a sorting function to sort "more secure" types before
+// "less-secure" types.
+func AscType(p1Ptr, p2Ptr *SockAddr) int {
+ p1 := *p1Ptr
+ p2 := *p2Ptr
+ p1Type := p1.Type()
+ p2Type := p2.Type()
+ switch {
+ case p1Type < p2Type:
+ return sortReceiverBeforeArg
+ case p1Type == p2Type:
+ return sortDeferDecision
+ case p1Type > p2Type:
+ return sortArgBeforeReceiver
+ default:
+ return sortDeferDecision
+ }
+}
+
+// FilterByType returns two lists: a list of matched and unmatched SockAddrs
+func (sas SockAddrs) FilterByType(type_ SockAddrType) (matched, excluded SockAddrs) {
+ matched = make(SockAddrs, 0, len(sas))
+ excluded = make(SockAddrs, 0, len(sas))
+
+ for _, sa := range sas {
+ if sa.Type()&type_ != 0 {
+ matched = append(matched, sa)
+ } else {
+ excluded = append(excluded, sa)
+ }
+ }
+ return matched, excluded
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/unixsock.go b/vendor/github.com/hashicorp/go-sockaddr/unixsock.go
new file mode 100644
index 0000000..f3be3f6
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/unixsock.go
@@ -0,0 +1,135 @@
+package sockaddr
+
+import (
+ "fmt"
+ "strings"
+)
+
+type UnixSock struct {
+ SockAddr
+ path string
+}
+type UnixSocks []*UnixSock
+
+// unixAttrMap is a map of the UnixSockAddr type-specific attributes.
+var unixAttrMap map[AttrName]func(UnixSock) string
+var unixAttrs []AttrName
+
+func init() {
+ unixAttrInit()
+}
+
+// NewUnixSock creates an UnixSock from a string path. String can be in the
+// form of either URI-based string (e.g. `file:///etc/passwd`), an absolute
+// path (e.g. `/etc/passwd`), or a relative path (e.g. `./foo`).
+func NewUnixSock(s string) (ret UnixSock, err error) {
+ ret.path = s
+ return ret, nil
+}
+
+// CmpAddress follows the Cmp() standard protocol and returns:
+//
+// - -1 If the receiver should sort first because its name lexically sorts before arg
+// - 0 if the SockAddr arg is not a UnixSock, or is a UnixSock with the same path.
+// - 1 If the argument should sort first.
+func (us UnixSock) CmpAddress(sa SockAddr) int {
+ usb, ok := sa.(UnixSock)
+ if !ok {
+ return sortDeferDecision
+ }
+
+ return strings.Compare(us.Path(), usb.Path())
+}
+
+// DialPacketArgs returns the arguments required to be passed to net.DialUnix()
+// with the `unixgram` network type.
+func (us UnixSock) DialPacketArgs() (network, dialArgs string) {
+ return "unixgram", us.path
+}
+
+// DialStreamArgs returns the arguments required to be passed to net.DialUnix()
+// with the `unix` network type.
+func (us UnixSock) DialStreamArgs() (network, dialArgs string) {
+ return "unix", us.path
+}
+
+// Equal returns true if a SockAddr is equal to the receiving UnixSock.
+func (us UnixSock) Equal(sa SockAddr) bool {
+ usb, ok := sa.(UnixSock)
+ if !ok {
+ return false
+ }
+
+ if us.Path() != usb.Path() {
+ return false
+ }
+
+ return true
+}
+
+// ListenPacketArgs returns the arguments required to be passed to
+// net.ListenUnixgram() with the `unixgram` network type.
+func (us UnixSock) ListenPacketArgs() (network, dialArgs string) {
+ return "unixgram", us.path
+}
+
+// ListenStreamArgs returns the arguments required to be passed to
+// net.ListenUnix() with the `unix` network type.
+func (us UnixSock) ListenStreamArgs() (network, dialArgs string) {
+ return "unix", us.path
+}
+
+// MustUnixSock is a helper method that must return an UnixSock or panic on
+// invalid input.
+func MustUnixSock(addr string) UnixSock {
+ us, err := NewUnixSock(addr)
+ if err != nil {
+ panic(fmt.Sprintf("Unable to create a UnixSock from %+q: %v", addr, err))
+ }
+ return us
+}
+
+// Path returns the given path of the UnixSock
+func (us UnixSock) Path() string {
+ return us.path
+}
+
+// String returns the path of the UnixSock
+func (us UnixSock) String() string {
+ return fmt.Sprintf("%+q", us.path)
+}
+
+// Type is used as a type switch and returns TypeUnix
+func (UnixSock) Type() SockAddrType {
+ return TypeUnix
+}
+
+// UnixSockAttrs returns a list of attributes supported by the UnixSockAddr type
+func UnixSockAttrs() []AttrName {
+ return unixAttrs
+}
+
+// UnixSockAttr returns a string representation of an attribute for the given
+// UnixSock.
+func UnixSockAttr(us UnixSock, attrName AttrName) string {
+ fn, found := unixAttrMap[attrName]
+ if !found {
+ return ""
+ }
+
+ return fn(us)
+}
+
+// unixAttrInit is called once at init()
+func unixAttrInit() {
+ // Sorted for human readability
+ unixAttrs = []AttrName{
+ "path",
+ }
+
+ unixAttrMap = map[AttrName]func(us UnixSock) string{
+ "path": func(us UnixSock) string {
+ return us.Path()
+ },
+ }
+}