summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command')
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/autohelp.go121
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/dump.go274
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/eval.go158
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/multi_arg.go17
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/rfc.go121
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/rfc_list.go94
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/tech_support.go216
-rw-r--r--vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/version.go27
8 files changed, 1028 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/autohelp.go b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/autohelp.go
new file mode 100644
index 000000000..082c53e27
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/autohelp.go
@@ -0,0 +1,121 @@
+package command
+
+import (
+ "flag"
+ "fmt"
+ "sort"
+ "strings"
+
+ wordwrap "github.com/mitchellh/go-wordwrap"
+ "github.com/ryanuber/columnize"
+)
+
+// AutoHelp specifies the necessary methods required to have their help
+// completely generated for them.
+type AutoHelp interface {
+ Usage() string
+ Description() string
+ InitOpts()
+ VisitAllFlags(func(f *flag.Flag))
+}
+
+// MakeHelp generates a help string based on the capabilities of the Command
+func MakeHelp(c AutoHelp) string {
+ usageText := c.Usage()
+
+ // If the length of Usage() is zero, then assume this is a hidden
+ // command.
+ if len(usageText) == 0 {
+ return ""
+ }
+
+ descriptionText := wordwrap.WrapString(c.Description(), 60)
+ descrLines := strings.Split(descriptionText, "\n")
+ prefixedLines := make([]string, len(descrLines))
+ for i := range descrLines {
+ prefixedLines[i] = " " + descrLines[i]
+ }
+ descriptionText = strings.Join(prefixedLines, "\n")
+
+ c.InitOpts()
+ flags := []*flag.Flag{}
+ c.VisitAllFlags(func(f *flag.Flag) {
+ flags = append(flags, f)
+ })
+ optionsText := OptionsHelpOutput(flags)
+
+ var helpOutput string
+ switch {
+ case len(optionsText) == 0 && len(descriptionText) == 0:
+ helpOutput = usageText
+ case len(optionsText) == 0:
+ helpOutput = fmt.Sprintf(`Usage: %s
+
+%s`,
+ usageText, descriptionText)
+ case len(descriptionText) == 0 && len(optionsText) > 0:
+ helpOutput = fmt.Sprintf(`Usage: %s
+
+Options:
+
+%s`,
+ usageText, optionsText)
+ default:
+ helpOutput = fmt.Sprintf(`Usage: %s
+
+%s
+
+Options:
+
+%s`,
+ usageText, descriptionText, optionsText)
+ }
+
+ return strings.TrimSpace(helpOutput)
+}
+
+// ByOptName implements sort.Interface for flag.Flag based on the Name field.
+type ByName []*flag.Flag
+
+func (a ByName) Len() int { return len(a) }
+func (a ByName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+func (a ByName) Less(i, j int) bool {
+ // Bubble up single-char args to the top of the list
+ switch {
+ case len(a[i].Name) == 1 && len(a[j].Name) != 1:
+ return true
+ case len(a[i].Name) != 1 && len(a[j].Name) == 1:
+ return false
+ default:
+ // Case-insensitive sort. Use case as a tie breaker, however.
+ a1 := strings.ToLower(a[i].Name)
+ a2 := strings.ToLower(a[j].Name)
+ if a1 == a2 {
+ return a[i].Name < a[j].Name
+ } else {
+ return a1 < a2
+ }
+ }
+}
+
+// OptionsHelpOutput returns a string of formatted options
+func OptionsHelpOutput(flags []*flag.Flag) string {
+ sort.Sort(ByName(flags))
+
+ var output []string
+ for _, f := range flags {
+ if len(f.Usage) == 0 {
+ continue
+ }
+
+ output = append(output, fmt.Sprintf("-%s | %s", f.Name, f.Usage))
+ }
+
+ optionsOutput := columnize.Format(output, &columnize.Config{
+ Delim: "|",
+ Glue: " ",
+ Prefix: " ",
+ Empty: "",
+ })
+ return optionsOutput
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/dump.go b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/dump.go
new file mode 100644
index 000000000..a5618b357
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/dump.go
@@ -0,0 +1,274 @@
+package command
+
+import (
+ "flag"
+ "fmt"
+
+ "github.com/hashicorp/errwrap"
+ sockaddr "github.com/hashicorp/go-sockaddr"
+ "github.com/mitchellh/cli"
+ "github.com/ryanuber/columnize"
+)
+
+type DumpCommand struct {
+ Ui cli.Ui
+
+ // attrNames is a list of attribute names to include in the output
+ attrNames []string
+
+ // flags is a list of options belonging to this command
+ flags *flag.FlagSet
+
+ // machineMode changes the output format to be machine friendly
+ // (i.e. tab-separated values).
+ machineMode bool
+
+ // valueOnly changes the output format to include only values
+ valueOnly bool
+
+ // ifOnly parses the input as an interface name
+ ifOnly bool
+
+ // ipOnly parses the input as an IP address (either IPv4 or IPv6)
+ ipOnly bool
+
+ // v4Only parses the input exclusively as an IPv4 address
+ v4Only bool
+
+ // v6Only parses the input exclusively as an IPv6 address
+ v6Only bool
+
+ // unixOnly parses the input exclusively as a UNIX Socket
+ unixOnly bool
+}
+
+// Description is the long-form command help.
+func (c *DumpCommand) Description() string {
+ return `Parse address(es) or interface and dumps various output.`
+}
+
+// Help returns the full help output expected by `sockaddr -h cmd`
+func (c *DumpCommand) Help() string {
+ return MakeHelp(c)
+}
+
+// InitOpts is responsible for setup of this command's configuration via the
+// command line. InitOpts() does not parse the arguments (see parseOpts()).
+func (c *DumpCommand) InitOpts() {
+ c.flags = flag.NewFlagSet("dump", flag.ContinueOnError)
+ c.flags.Usage = func() { c.Ui.Output(c.Help()) }
+ c.flags.BoolVar(&c.machineMode, "H", false, "Machine readable output")
+ c.flags.BoolVar(&c.valueOnly, "n", false, "Show only the value")
+ c.flags.BoolVar(&c.v4Only, "4", false, "Parse the input as IPv4 only")
+ c.flags.BoolVar(&c.v6Only, "6", false, "Parse the input as IPv6 only")
+ c.flags.BoolVar(&c.ifOnly, "I", false, "Parse the argument as an interface name")
+ c.flags.BoolVar(&c.ipOnly, "i", false, "Parse the input as IP address (either IPv4 or IPv6)")
+ c.flags.BoolVar(&c.unixOnly, "u", false, "Parse the input as a UNIX Socket only")
+ c.flags.Var((*MultiArg)(&c.attrNames), "o", "Name of an attribute to pass through")
+}
+
+// Run executes this command.
+func (c *DumpCommand) Run(args []string) int {
+ if len(args) == 0 {
+ c.Ui.Error(c.Help())
+ return 1
+ }
+
+ c.InitOpts()
+ addrs, err := c.parseOpts(args)
+ if err != nil {
+ if errwrap.Contains(err, "flag: help requested") {
+ return 0
+ }
+ return 1
+ }
+ for _, addr := range addrs {
+ var sa sockaddr.SockAddr
+ var ifAddrs sockaddr.IfAddrs
+ var err error
+ switch {
+ case c.v4Only:
+ sa, err = sockaddr.NewIPv4Addr(addr)
+ case c.v6Only:
+ sa, err = sockaddr.NewIPv6Addr(addr)
+ case c.unixOnly:
+ sa, err = sockaddr.NewUnixSock(addr)
+ case c.ipOnly:
+ sa, err = sockaddr.NewIPAddr(addr)
+ case c.ifOnly:
+ ifAddrs, err = sockaddr.GetAllInterfaces()
+ if err != nil {
+ break
+ }
+
+ ifAddrs, _, err = sockaddr.IfByName(addr, ifAddrs)
+ default:
+ sa, err = sockaddr.NewSockAddr(addr)
+ }
+ if err != nil {
+ c.Ui.Error(fmt.Sprintf("Unable to parse %+q: %v", addr, err))
+ return 1
+ }
+ if sa != nil {
+ c.dumpSockAddr(sa)
+ } else if ifAddrs != nil {
+ c.dumpIfAddrs(ifAddrs)
+ } else {
+ panic("bad")
+ }
+ }
+ return 0
+}
+
+// Synopsis returns a terse description used when listing sub-commands.
+func (c *DumpCommand) Synopsis() string {
+ return `Parses input as an IP or interface name(s) and dumps various information`
+}
+
+// Usage is the one-line usage description
+func (c *DumpCommand) Usage() string {
+ return `sockaddr dump [options] input [...]`
+}
+
+// VisitAllFlags forwards the visitor function to the FlagSet
+func (c *DumpCommand) VisitAllFlags(fn func(*flag.Flag)) {
+ c.flags.VisitAll(fn)
+}
+
+func (c *DumpCommand) dumpIfAddrs(ifAddrs sockaddr.IfAddrs) {
+ for _, ifAddr := range ifAddrs {
+ c.dumpSockAddr(ifAddr.SockAddr)
+ }
+}
+
+func (c *DumpCommand) dumpSockAddr(sa sockaddr.SockAddr) {
+ reservedAttrs := []sockaddr.AttrName{"Attribute"}
+ const maxNumAttrs = 32
+
+ output := make([]string, 0, maxNumAttrs+len(reservedAttrs))
+ allowedAttrs := make(map[sockaddr.AttrName]struct{}, len(c.attrNames)+len(reservedAttrs))
+ for _, attr := range reservedAttrs {
+ allowedAttrs[attr] = struct{}{}
+ }
+ for _, attr := range c.attrNames {
+ allowedAttrs[sockaddr.AttrName(attr)] = struct{}{}
+ }
+
+ // allowedAttr returns true if the attribute is allowed to be appended
+ // to the output.
+ allowedAttr := func(k sockaddr.AttrName) bool {
+ if len(allowedAttrs) == len(reservedAttrs) {
+ return true
+ }
+
+ _, found := allowedAttrs[k]
+ return found
+ }
+
+ // outFmt is a small helper function to reduce the tedium below. outFmt
+ // returns a new slice and expects the value to already be a string.
+ outFmt := func(o []string, k sockaddr.AttrName, v interface{}) []string {
+ if !allowedAttr(k) {
+ return o
+ }
+ switch {
+ case c.valueOnly:
+ return append(o, fmt.Sprintf("%s", v))
+ case !c.valueOnly && c.machineMode:
+ return append(o, fmt.Sprintf("%s\t%s", k, v))
+ case !c.valueOnly && !c.machineMode:
+ fallthrough
+ default:
+ return append(o, fmt.Sprintf("%s | %s", k, v))
+ }
+ }
+
+ if !c.machineMode {
+ output = outFmt(output, "Attribute", "Value")
+ }
+
+ // Attributes for all SockAddr types
+ for _, attr := range sockaddr.SockAddrAttrs() {
+ output = outFmt(output, attr, sockaddr.SockAddrAttr(sa, attr))
+ }
+
+ // Attributes for all IP types (both IPv4 and IPv6)
+ if sa.Type()&sockaddr.TypeIP != 0 {
+ ip := *sockaddr.ToIPAddr(sa)
+ for _, attr := range sockaddr.IPAttrs() {
+ output = outFmt(output, attr, sockaddr.IPAddrAttr(ip, attr))
+ }
+ }
+
+ if sa.Type() == sockaddr.TypeIPv4 {
+ ipv4 := *sockaddr.ToIPv4Addr(sa)
+ for _, attr := range sockaddr.IPv4Attrs() {
+ output = outFmt(output, attr, sockaddr.IPv4AddrAttr(ipv4, attr))
+ }
+ }
+
+ if sa.Type() == sockaddr.TypeIPv6 {
+ ipv6 := *sockaddr.ToIPv6Addr(sa)
+ for _, attr := range sockaddr.IPv6Attrs() {
+ output = outFmt(output, attr, sockaddr.IPv6AddrAttr(ipv6, attr))
+ }
+ }
+
+ if sa.Type() == sockaddr.TypeUnix {
+ us := *sockaddr.ToUnixSock(sa)
+ for _, attr := range sockaddr.UnixSockAttrs() {
+ output = outFmt(output, attr, sockaddr.UnixSockAttr(us, attr))
+ }
+ }
+
+ // Developer-focused arguments
+ {
+ arg1, arg2 := sa.DialPacketArgs()
+ output = outFmt(output, "DialPacket", fmt.Sprintf("%+q %+q", arg1, arg2))
+ }
+ {
+ arg1, arg2 := sa.DialStreamArgs()
+ output = outFmt(output, "DialStream", fmt.Sprintf("%+q %+q", arg1, arg2))
+ }
+ {
+ arg1, arg2 := sa.ListenPacketArgs()
+ output = outFmt(output, "ListenPacket", fmt.Sprintf("%+q %+q", arg1, arg2))
+ }
+ {
+ arg1, arg2 := sa.ListenStreamArgs()
+ output = outFmt(output, "ListenStream", fmt.Sprintf("%+q %+q", arg1, arg2))
+ }
+
+ result := columnize.SimpleFormat(output)
+ c.Ui.Output(result)
+}
+
+// parseOpts is responsible for parsing the options set in InitOpts(). Returns
+// a list of non-parsed flags.
+func (c *DumpCommand) parseOpts(args []string) ([]string, error) {
+ if err := c.flags.Parse(args); err != nil {
+ return nil, err
+ }
+
+ conflictingOptsCount := 0
+ if c.v4Only {
+ conflictingOptsCount++
+ }
+ if c.v6Only {
+ conflictingOptsCount++
+ }
+ if c.unixOnly {
+ conflictingOptsCount++
+ }
+ if c.ifOnly {
+ conflictingOptsCount++
+ }
+ if c.ipOnly {
+ conflictingOptsCount++
+ }
+ if conflictingOptsCount > 1 {
+ return nil, fmt.Errorf("Conflicting options specified, only one parsing mode may be specified at a time")
+ }
+
+ return c.flags.Args(), nil
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/eval.go b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/eval.go
new file mode 100644
index 000000000..0554cda4f
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/eval.go
@@ -0,0 +1,158 @@
+package command
+
+import (
+ "bytes"
+ "flag"
+ "fmt"
+ "io"
+ "os"
+ "strings"
+
+ "github.com/hashicorp/errwrap"
+ "github.com/hashicorp/go-sockaddr/template"
+ "github.com/mitchellh/cli"
+)
+
+type EvalCommand struct {
+ Ui cli.Ui
+
+ // debugOutput emits framed output vs raw output.
+ debugOutput bool
+
+ // flags is a list of options belonging to this command
+ flags *flag.FlagSet
+
+ // rawInput disables wrapping the string in the text/template {{ }}
+ // handlebars.
+ rawInput bool
+
+ // suppressNewline changes whether or not there's a newline between each
+ // arg passed to the eval subcommand.
+ suppressNewline bool
+}
+
+// Description is the long-form command help.
+func (c *EvalCommand) Description() string {
+ return `Parse the sockaddr template and evaluates the output.
+
+` + "The `sockaddr` library has the potential to be very complex, which is why the " +
+ "`sockaddr` command supports an `eval` subcommand in order to test configurations " +
+ "from the command line. The `eval` subcommand automatically wraps its input with " +
+ "the `{{` and `}}` template delimiters unless the `-r` command is specified, in " +
+ "which case `eval` parses the raw input. If the `template` argument passed to " +
+ "`eval` is a dash (`-`), then `sockaddr eval` will read from stdin and " +
+ "automatically sets the `-r` flag."
+
+}
+
+// Help returns the full help output expected by `sockaddr -h cmd`
+func (c *EvalCommand) Help() string {
+ return MakeHelp(c)
+}
+
+// InitOpts is responsible for setup of this command's configuration via the
+// command line. InitOpts() does not parse the arguments (see parseOpts()).
+func (c *EvalCommand) InitOpts() {
+ c.flags = flag.NewFlagSet("eval", flag.ContinueOnError)
+ c.flags.Usage = func() { c.Ui.Output(c.Help()) }
+ c.flags.BoolVar(&c.debugOutput, "d", false, "Debug output")
+ c.flags.BoolVar(&c.suppressNewline, "n", false, "Suppress newlines between args")
+ c.flags.BoolVar(&c.rawInput, "r", false, "Suppress wrapping the input with {{ }} delimiters")
+}
+
+// Run executes this command.
+func (c *EvalCommand) Run(args []string) int {
+ if len(args) == 0 {
+ c.Ui.Error(c.Help())
+ return 1
+ }
+
+ c.InitOpts()
+ tmpls, err := c.parseOpts(args)
+ if err != nil {
+ if errwrap.Contains(err, "flag: help requested") {
+ return 0
+ }
+ return 1
+ }
+ inputs, outputs := make([]string, len(tmpls)), make([]string, len(tmpls))
+ var rawInput, readStdin bool
+ for i, in := range tmpls {
+ if readStdin {
+ break
+ }
+
+ rawInput = c.rawInput
+ if in == "-" {
+ rawInput = true
+ var f io.Reader = os.Stdin
+ var buf bytes.Buffer
+ if _, err := io.Copy(&buf, f); err != nil {
+ c.Ui.Error(fmt.Sprintf("[ERROR]: Error reading from stdin: %v", err))
+ return 1
+ }
+ in = buf.String()
+ if len(in) == 0 {
+ return 0
+ }
+ readStdin = true
+ }
+ inputs[i] = in
+
+ if !rawInput {
+ in = `{{` + in + `}}`
+ inputs[i] = in
+ }
+
+ out, err := template.Parse(in)
+ if err != nil {
+ c.Ui.Error(fmt.Sprintf("ERROR[%d] in: %q\n[%d] msg: %v\n", i, in, i, err))
+ return 1
+ }
+ outputs[i] = out
+ }
+
+ if c.debugOutput {
+ for i, out := range outputs {
+ c.Ui.Output(fmt.Sprintf("[%d] in: %q\n[%d] out: %q\n", i, inputs[i], i, out))
+ if i != len(outputs)-1 {
+ if c.debugOutput {
+ c.Ui.Output(fmt.Sprintf("---\n"))
+ }
+ }
+ }
+ } else {
+ sep := "\n"
+ if c.suppressNewline {
+ sep = ""
+ }
+ c.Ui.Output(strings.Join(outputs, sep))
+ }
+
+ return 0
+}
+
+// Synopsis returns a terse description used when listing sub-commands.
+func (c *EvalCommand) Synopsis() string {
+ return `Evaluates a sockaddr template`
+}
+
+// Usage is the one-line usage description
+func (c *EvalCommand) Usage() string {
+ return `sockaddr eval [options] [template ...]`
+}
+
+// VisitAllFlags forwards the visitor function to the FlagSet
+func (c *EvalCommand) VisitAllFlags(fn func(*flag.Flag)) {
+ c.flags.VisitAll(fn)
+}
+
+// parseOpts is responsible for parsing the options set in InitOpts(). Returns
+// a list of non-parsed flags.
+func (c *EvalCommand) parseOpts(args []string) ([]string, error) {
+ if err := c.flags.Parse(args); err != nil {
+ return nil, err
+ }
+
+ return c.flags.Args(), nil
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/multi_arg.go b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/multi_arg.go
new file mode 100644
index 000000000..c626dab0f
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/multi_arg.go
@@ -0,0 +1,17 @@
+package command
+
+import "regexp"
+
+type MultiArg []string
+
+func (v *MultiArg) String() string {
+ return ""
+}
+
+func (v *MultiArg) Set(raw string) error {
+ parts := regexp.MustCompile(`[\s]*,[\s]*`).Split(raw, -1)
+ for _, part := range parts {
+ *v = append(*v, part)
+ }
+ return nil
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/rfc.go b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/rfc.go
new file mode 100644
index 000000000..4c66b8517
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/rfc.go
@@ -0,0 +1,121 @@
+package command
+
+import (
+ "flag"
+ "fmt"
+ "strconv"
+
+ "github.com/hashicorp/errwrap"
+ sockaddr "github.com/hashicorp/go-sockaddr"
+ "github.com/mitchellh/cli"
+)
+
+type RFCCommand struct {
+ Ui cli.Ui
+
+ // flags is a list of options belonging to this command
+ flags *flag.FlagSet
+
+ // silentMode prevents any output and only returns exit code 1 when the
+ // IP address is NOT a member of the known RFC. Unknown RFCs return a
+ // status code of 2.
+ silentMode bool
+}
+
+// Description is the long-form command help.
+func (c *RFCCommand) Description() string {
+ return `Tests a given IP address to see if it is part of a known RFC. If the IP address belongs to a known RFC, return exit code 0 and print the status. If the IP does not belong to an RFC, return 1. If the RFC is not known, return 2.`
+}
+
+// Help returns the full help output expected by `sockaddr -h cmd`
+func (c *RFCCommand) Help() string {
+ return MakeHelp(c)
+}
+
+// InitOpts is responsible for setup of this command's configuration via the
+// command line. InitOpts() does not parse the arguments (see parseOpts()).
+func (c *RFCCommand) InitOpts() {
+ c.flags = flag.NewFlagSet("rfc", flag.ContinueOnError)
+ c.flags.Usage = func() { c.Ui.Output(c.Help()) }
+ c.flags.BoolVar(&c.silentMode, "s", false, "Silent, only return different exit codes")
+}
+
+// Run executes this command.
+func (c *RFCCommand) Run(args []string) int {
+ if len(args) == 0 {
+ c.Ui.Error(c.Help())
+ return 1
+ }
+
+ c.InitOpts()
+ unprocessedArgs, err := c.parseOpts(args)
+ if err != nil {
+ if errwrap.Contains(err, "flag: help requested") {
+ return 0
+ }
+ return 1
+ }
+
+ switch numArgs := len(unprocessedArgs); {
+ case numArgs != 2 && numArgs != 0:
+ c.Ui.Error(`ERROR: Need an RFC Number and an IP address to test.`)
+ c.Ui.Error(c.Help())
+ fallthrough
+ case numArgs == 0:
+ return 1
+ }
+
+ // Parse the RFC Number
+ rfcNum, err := strconv.ParseUint(unprocessedArgs[0], 10, 32)
+ if err != nil {
+ c.Ui.Error(fmt.Sprintf("ERROR: Invalid RFC Number %+q: %v", unprocessedArgs[0], err))
+ return 2
+ }
+
+ // Parse the IP address
+ ipAddr, err := sockaddr.NewIPAddr(unprocessedArgs[1])
+ if err != nil {
+ c.Ui.Error(fmt.Sprintf("ERROR: Invalid IP address %+q: %v", unprocessedArgs[1], err))
+ return 3
+ }
+
+ switch inRFC := sockaddr.IsRFC(uint(rfcNum), ipAddr); {
+ case inRFC && !c.silentMode:
+ c.Ui.Output(fmt.Sprintf("%s is part of RFC %d", ipAddr, rfcNum))
+ fallthrough
+ case inRFC:
+ return 0
+ case !inRFC && !c.silentMode:
+ c.Ui.Output(fmt.Sprintf("%s is not part of RFC %d", ipAddr, rfcNum))
+ fallthrough
+ case !inRFC:
+ return 1
+ default:
+ panic("bad")
+ }
+}
+
+// Synopsis returns a terse description used when listing sub-commands.
+func (c *RFCCommand) Synopsis() string {
+ return `Test to see if an IP is part of a known RFC`
+}
+
+// Usage is the one-line usage description
+func (c *RFCCommand) Usage() string {
+ return `sockaddr rfc [RFC Number] [IP Address]`
+}
+
+// VisitAllFlags forwards the visitor function to the FlagSet
+func (c *RFCCommand) VisitAllFlags(fn func(*flag.Flag)) {
+ c.flags.VisitAll(fn)
+}
+
+// parseOpts is responsible for parsing the options set in InitOpts(). Returns
+// a list of non-parsed flags.
+func (c *RFCCommand) parseOpts(args []string) ([]string, error) {
+ if err := c.flags.Parse(args); err != nil {
+ return nil, err
+ }
+
+ return c.flags.Args(), nil
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/rfc_list.go b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/rfc_list.go
new file mode 100644
index 000000000..11c1ac365
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/rfc_list.go
@@ -0,0 +1,94 @@
+package command
+
+import (
+ "flag"
+ "fmt"
+ "sort"
+
+ "github.com/hashicorp/errwrap"
+ sockaddr "github.com/hashicorp/go-sockaddr"
+ "github.com/mitchellh/cli"
+)
+
+type RFCListCommand struct {
+ Ui cli.Ui
+
+ // flags is a list of options belonging to this command
+ flags *flag.FlagSet
+}
+
+// Description is the long-form command help.
+func (c *RFCListCommand) Description() string {
+ return `Lists all known RFCs.`
+}
+
+// Help returns the full help output expected by `sockaddr -h cmd`
+func (c *RFCListCommand) Help() string {
+ return MakeHelp(c)
+}
+
+// InitOpts is responsible for setup of this command's configuration via the
+// command line. InitOpts() does not parse the arguments (see parseOpts()).
+func (c *RFCListCommand) InitOpts() {
+ c.flags = flag.NewFlagSet("list", flag.ContinueOnError)
+ c.flags.Usage = func() { c.Ui.Output(c.Help()) }
+}
+
+type rfcNums []uint
+
+func (s rfcNums) Len() int { return len(s) }
+func (s rfcNums) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+func (s rfcNums) Less(i, j int) bool { return s[i] < s[j] }
+
+// Run executes this command.
+func (c *RFCListCommand) Run(args []string) int {
+ if len(args) != 0 {
+ c.Ui.Error(c.Help())
+ return 1
+ }
+
+ c.InitOpts()
+ _, err := c.parseOpts(args)
+ if err != nil {
+ if errwrap.Contains(err, "flag: help requested") {
+ return 0
+ }
+ return 1
+ }
+
+ var rfcs rfcNums
+ sockaddr.VisitAllRFCs(func(rfcNum uint, sas sockaddr.SockAddrs) {
+ rfcs = append(rfcs, rfcNum)
+ })
+
+ sort.Sort(rfcs)
+
+ for _, rfcNum := range rfcs {
+ c.Ui.Output(fmt.Sprintf("%d", rfcNum))
+ }
+
+ return 0
+}
+
+// Synopsis returns a terse description used when listing sub-commands.
+func (c *RFCListCommand) Synopsis() string {
+ return `Lists all known RFCs`
+}
+
+// Usage is the one-line usage description
+func (c *RFCListCommand) Usage() string {
+ return `sockaddr rfc list`
+}
+
+// VisitAllFlags forwards the visitor function to the FlagSet
+func (c *RFCListCommand) VisitAllFlags(fn func(*flag.Flag)) {
+ c.flags.VisitAll(fn)
+}
+
+func (c *RFCListCommand) parseOpts(args []string) ([]string, error) {
+ if err := c.flags.Parse(args); err != nil {
+ return nil, err
+ }
+
+ return c.flags.Args(), nil
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/tech_support.go b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/tech_support.go
new file mode 100644
index 000000000..fd706009d
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/tech_support.go
@@ -0,0 +1,216 @@
+package command
+
+import (
+ "flag"
+ "fmt"
+ "net"
+ "os/exec"
+ "runtime"
+
+ "github.com/hashicorp/errwrap"
+ sockaddr "github.com/hashicorp/go-sockaddr"
+ "github.com/mitchellh/cli"
+)
+
+type TechSupportCommand struct {
+ Ui cli.Ui
+
+ // outputMode controls the type of output encoding.
+ outputMode string
+
+ // flags is a list of options belonging to this command
+ flags *flag.FlagSet
+}
+
+// Description is the long-form command help.
+func (c *TechSupportCommand) Description() string {
+ return `Print out network diagnostic information that can be used by support.
+
+` + "The `sockaddr` library relies on OS-specific commands and output which can potentially be " +
+ "brittle. The `tech-support` subcommand emits all of the platform-specific " +
+ "network details required to debug why a given `sockaddr` API call is behaving " +
+ "differently than expected. The `-output` flag controls the output format. " +
+ "The default output mode is Markdown (`md`) however a raw mode (`raw`) is " +
+ "available to obtain the original output."
+}
+
+// Help returns the full help output expected by `sockaddr -h cmd`
+func (c *TechSupportCommand) Help() string {
+ return MakeHelp(c)
+}
+
+// InitOpts is responsible for setup of this command's configuration via the
+// command line. InitOpts() does not parse the arguments (see parseOpts()).
+func (c *TechSupportCommand) InitOpts() {
+ c.flags = flag.NewFlagSet("tech-support", flag.ContinueOnError)
+ c.flags.Usage = func() { c.Ui.Output(c.Help()) }
+ c.flags.StringVar(&c.outputMode, "output", "md", `Encode the output using one of Markdown ("md") or Raw ("raw")`)
+}
+
+// Run executes this command.
+func (c *TechSupportCommand) Run(args []string) int {
+ c.InitOpts()
+ rest, err := c.parseOpts(args)
+ if err != nil {
+ if errwrap.Contains(err, "flag: help requested") {
+ return 0
+ }
+ return 1
+ }
+ if len(rest) != 0 {
+ c.Ui.Error(c.Help())
+ return 1
+ }
+
+ ri, err := sockaddr.NewRouteInfo()
+ if err != nil {
+ c.Ui.Error(fmt.Sprintf("error loading route information: %v", err))
+ return 1
+ }
+
+ const initNumCmds = 4
+ type cmdResult struct {
+ cmd []string
+ out string
+ }
+ output := make(map[string]cmdResult, initNumCmds)
+ ri.VisitCommands(func(name string, cmd []string) {
+ out, err := exec.Command(cmd[0], cmd[1:]...).Output()
+ if err != nil {
+ out = []byte(fmt.Sprintf("ERROR: command %q failed: %v", name, err))
+ }
+
+ output[name] = cmdResult{
+ cmd: cmd,
+ out: string(out),
+ }
+ })
+
+ out := c.rowWriterOutputFactory()
+
+ for cmdName, result := range output {
+ switch c.outputMode {
+ case "md":
+ c.Ui.Output(fmt.Sprintf("## cmd: `%s`", cmdName))
+ c.Ui.Output("")
+ c.Ui.Output(fmt.Sprintf("Command: `%#v`", result.cmd))
+ c.Ui.Output("```")
+ c.Ui.Output(result.out)
+ c.Ui.Output("```")
+ c.Ui.Output("")
+ case "raw":
+ c.Ui.Output(fmt.Sprintf("cmd: %q: %#v", cmdName, result.cmd))
+ c.Ui.Output("")
+ c.Ui.Output(result.out)
+ c.Ui.Output("")
+ default:
+ c.Ui.Error(fmt.Sprintf("Unsupported output type: %q", c.outputMode))
+ return 1
+ }
+
+ out("s", "GOOS", runtime.GOOS)
+ out("s", "GOARCH", runtime.GOARCH)
+ out("s", "Compiler", runtime.Compiler)
+ out("s", "Version", runtime.Version())
+ ifs, err := net.Interfaces()
+ if err != nil {
+ out("v", "net.Interfaces", err)
+ } else {
+ for i, intf := range ifs {
+ out("s", fmt.Sprintf("net.Interfaces[%d].Name", i), intf.Name)
+ out("s", fmt.Sprintf("net.Interfaces[%d].Flags", i), intf.Flags)
+ out("+v", fmt.Sprintf("net.Interfaces[%d].Raw", i), intf)
+ addrs, err := intf.Addrs()
+ if err != nil {
+ out("v", fmt.Sprintf("net.Interfaces[%d].Addrs", i), err)
+ } else {
+ for j, addr := range addrs {
+ out("s", fmt.Sprintf("net.Interfaces[%d].Addrs[%d]", i, j), addr)
+ }
+ }
+ }
+ }
+ }
+
+ return 0
+}
+
+// Synopsis returns a terse description used when listing sub-commands.
+func (c *TechSupportCommand) Synopsis() string {
+ return `Dumps diagnostic information about a platform's network`
+}
+
+// Usage is the one-line usage description
+func (c *TechSupportCommand) Usage() string {
+ return `sockaddr tech-support [options]`
+}
+
+// VisitAllFlags forwards the visitor function to the FlagSet
+func (c *TechSupportCommand) VisitAllFlags(fn func(*flag.Flag)) {
+ c.flags.VisitAll(fn)
+}
+
+// parseOpts is responsible for parsing the options set in InitOpts(). Returns
+// a list of non-parsed flags.
+func (c *TechSupportCommand) parseOpts(args []string) ([]string, error) {
+ if err := c.flags.Parse(args); err != nil {
+ return nil, err
+ }
+
+ switch c.outputMode {
+ case "md", "markdown":
+ c.outputMode = "md"
+ case "raw":
+ default:
+ return nil, fmt.Errorf(`Invalid output mode %q, supported output types are "md" (default) and "raw"`, c.outputMode)
+ }
+ return c.flags.Args(), nil
+}
+
+func (c *TechSupportCommand) rowWriterOutputFactory() func(valueVerb, key string, val interface{}) {
+ type _Fmt string
+ type _Verb string
+ var lineNoFmt string
+ var keyVerb _Verb
+ var fmtMap map[_Verb]_Fmt
+ switch c.outputMode {
+ case "md":
+ lineNoFmt = "%02d."
+ keyVerb = "s"
+ fmtMap = map[_Verb]_Fmt{
+ "s": "`%s`",
+ "-s": "%s",
+ "v": "`%v`",
+ "+v": "`%#v`",
+ }
+ case "raw":
+ lineNoFmt = "%02d:"
+ keyVerb = "-s"
+ fmtMap = map[_Verb]_Fmt{
+ "s": "%q",
+ "-s": "%s",
+ "v": "%v",
+ "+v": "%#v",
+ }
+ default:
+ panic(fmt.Sprintf("Unsupported output type: %q", c.outputMode))
+ }
+
+ var count int
+ return func(valueVerb, key string, val interface{}) {
+ count++
+
+ keyFmt, ok := fmtMap[keyVerb]
+ if !ok {
+ panic(fmt.Sprintf("Invalid key verb: %q", keyVerb))
+ }
+
+ valFmt, ok := fmtMap[_Verb(valueVerb)]
+ if !ok {
+ panic(fmt.Sprintf("Invalid value verb: %q", valueVerb))
+ }
+
+ outputModeFmt := fmt.Sprintf("%s %s:\t%s", lineNoFmt, keyFmt, valFmt)
+ c.Ui.Output(fmt.Sprintf(outputModeFmt, count, key, val))
+ }
+}
diff --git a/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/version.go b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/version.go
new file mode 100644
index 000000000..add3d1cc6
--- /dev/null
+++ b/vendor/github.com/hashicorp/go-sockaddr/cmd/sockaddr/command/version.go
@@ -0,0 +1,27 @@
+package command
+
+import (
+ "fmt"
+
+ "github.com/mitchellh/cli"
+)
+
+// VersionCommand is a Command implementation prints the version.
+type VersionCommand struct {
+ HumanVersion string
+ Ui cli.Ui
+}
+
+func (c *VersionCommand) Help() string {
+ return ""
+}
+
+func (c *VersionCommand) Run(_ []string) int {
+ c.Ui.Output(fmt.Sprintf("sockaddr %s", c.HumanVersion))
+
+ return 0
+}
+
+func (c *VersionCommand) Synopsis() string {
+ return "Prints the sockaddr version"
+}