Add support for SSE-S3 server side encryption with vault (#6192)

Add support for sse-s3 encryption with vault as KMS.

Also refactoring code to make use of headers and functions defined in
crypto package and clean up duplicated code.
This commit is contained in:
poornas
2018-08-17 12:52:14 -07:00
committed by kannappanr
parent 3d197c1449
commit e71ef905f9
236 changed files with 23463 additions and 608 deletions

65
vendor/github.com/hashicorp/go-sockaddr/GNUmakefile generated vendored Normal file
View File

@@ -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

373
vendor/github.com/hashicorp/go-sockaddr/LICENSE generated vendored Normal file
View File

@@ -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.

118
vendor/github.com/hashicorp/go-sockaddr/README.md generated vendored Normal file
View File

@@ -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.

5
vendor/github.com/hashicorp/go-sockaddr/doc.go generated vendored Normal file
View File

@@ -0,0 +1,5 @@
/*
Package sockaddr is a Go implementation of the UNIX socket family data types and
related helper functions.
*/
package sockaddr

254
vendor/github.com/hashicorp/go-sockaddr/ifaddr.go generated vendored Normal file
View File

@@ -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
},
}
}

1281
vendor/github.com/hashicorp/go-sockaddr/ifaddrs.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

65
vendor/github.com/hashicorp/go-sockaddr/ifattr.go generated vendored Normal file
View File

@@ -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)
}

169
vendor/github.com/hashicorp/go-sockaddr/ipaddr.go generated vendored Normal file
View File

@@ -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())
},
}
}

98
vendor/github.com/hashicorp/go-sockaddr/ipaddrs.go generated vendored Normal file
View File

@@ -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()
}

516
vendor/github.com/hashicorp/go-sockaddr/ipv4addr.go generated vendored Normal file
View File

@@ -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))
},
}
}

591
vendor/github.com/hashicorp/go-sockaddr/ipv6addr.go generated vendored Normal file
View File

@@ -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
}

948
vendor/github.com/hashicorp/go-sockaddr/rfc.go generated vendored Normal file
View File

@@ -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)
}
}
}

19
vendor/github.com/hashicorp/go-sockaddr/route_info.go generated vendored Normal file
View File

@@ -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)
}
}

View File

@@ -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
}

View File

@@ -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)")
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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
}

206
vendor/github.com/hashicorp/go-sockaddr/sockaddr.go generated vendored Normal file
View File

@@ -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
}

193
vendor/github.com/hashicorp/go-sockaddr/sockaddrs.go generated vendored Normal file
View File

@@ -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
}

135
vendor/github.com/hashicorp/go-sockaddr/unixsock.go generated vendored Normal file
View File

@@ -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()
},
}
}