* Default is now previous single-verbosity level; it was too annoying to
  add the -v every time.
** -q/--quiet has been added to return to the previous default output
This commit is contained in:
brent saner
2025-11-08 23:33:21 -05:00
parent 860ad5842b
commit 4cbb17bf9e
11 changed files with 792 additions and 36 deletions

View File

@@ -25,7 +25,8 @@ type commonBase struct {
Plain bool `short:"p" long:"plain" description:"Show plain output instead of unicode (only used if -f/--format=pretty)."`
Separator string `short:"S" long:"separator" default:"\n" description:"Separator between addresses; only used for -f/--format=pretty with no verbosity."`
Fmt string `short:"f" long:"format" choice:"json" choice:"pretty" choice:"yml" choice:"xml" default:"pretty" description:"Output format. 'pretty' is not intended to be parseable, either by subnetter or by external tooling."`
Verbose []bool `short:"v" long:"verbose" description:"Show verbose information if -f/--format=pretty. May be specified multiple times to increase verbosity (up to 3 levels)."`
Verbose []bool `short:"v" long:"verbose" description:"Show verbose (even more) information if -f/--format=pretty. May be specified multiple times to increase verbosity (up to 2 levels)."`
Quiet bool `short:"q" long:"quiet" description:"The opposite of -v/--verbose (if -f/--format=pretty). Overrides any/all verbosity and instead produces a much more simple newline-separated output that may be easier for e.g. shell script to parse."`
AllowReserved bool `short:"R" long:"allow-reserved" description:"If specified, do not warn about reserved IP addresses/networks."`
reservedArgs
AllowHostNet bool `short:"H" long:"allow-host" description:"If specified, do not warn about host bits. Host bits are always removed for subnetting (as otherwise there would be errors); this is only used only for output."`

View File

@@ -104,6 +104,8 @@ func printMask(label string, pfx netip.Prefix, verb, indent int, indentStr strin
var mask net.IPMask
var first netip.Addr
var last netip.Addr
var firstUsable netip.Addr
var lastUsable netip.Addr
var sb = new(strings.Builder)
var pre = strings.Repeat(indentStr, indent)
var pre2 = strings.Repeat(indentStr, indent+1)
@@ -118,17 +120,23 @@ func printMask(label string, pfx netip.Prefix, verb, indent int, indentStr strin
maskF = "d"
maskSep = "."
maskEvery = 1
// IPv4 *always* reserves last addr for broadcast UNLESS it's a /31 (or /32). RFC 919, RFC 1770, RFC 5735.
// IPv4 *always* reserves lastUsable addr for broadcast UNLESS it's a /31 (or /32). RFC 919, RFC 1770, RFC 5735.
switch pfx.Bits() {
case 32: // Host
first = pfx.Masked().Addr()
last = pfx.Masked().Addr()
firstUsable = first
lastUsable = last
case 31: // Point-to-Point
first = pfx.Masked().Addr()
last = pfx.Masked().Addr().Next()
firstUsable = first
lastUsable = last
default: // RFC 919, RFC 5735
first = pfx.Masked().Addr().Next()
last = netipx.PrefixLastIP(pfx.Masked()).Prev()
first = pfx.Masked().Addr()
last = netipx.PrefixLastIP(pfx.Masked())
firstUsable = first.Next()
lastUsable = last.Prev()
}
} else {
maskF = "02x"
@@ -138,16 +146,24 @@ func printMask(label string, pfx netip.Prefix, verb, indent int, indentStr strin
case 128: // Host/Loopback
first = pfx.Masked().Addr()
last = pfx.Masked().Addr()
firstUsable = first
lastUsable = last
case 127: // Point-to-Point
first = pfx.Masked().Addr()
last = pfx.Masked().Addr().Next()
firstUsable = first
lastUsable = last
case 64:
first = pfx.Masked().Addr().Next()
first = pfx.Masked().Addr()
firstUsable = first.Next()
// IPv6 only reserves the last address (for EUI-64 reasons) for /64's.
last = netipx.PrefixLastIP(pfx.Masked()).Prev()
last = netipx.PrefixLastIP(pfx.Masked())
lastUsable = last.Prev()
default:
first = pfx.Masked().Addr()
firstUsable = first
last = netipx.PrefixLastIP(pfx.Masked())
lastUsable = last
}
}
@@ -158,6 +174,8 @@ func printMask(label string, pfx netip.Prefix, verb, indent int, indentStr strin
fmt.Fprintf(sb, "%sBits:\t\t%d\n", pre2, pfx.Bits())
fmt.Fprintf(sb, "%sFirst:\t\t%s\n", pre2, first.String())
fmt.Fprintf(sb, "%sLast:\t\t%s\n", pre2, last.String())
fmt.Fprintf(sb, "%sFirst Usable:\t%s\n", pre2, firstUsable.String())
fmt.Fprintf(sb, "%sLast Usable:\t%s\n", pre2, lastUsable.String())
fmt.Fprintf(sb, "%sAddresses:\t%d\n", pre2, netsplit.NumAddrsPfx(pfx.Masked(), true, true))
fmt.Fprintf(sb, "%sHosts:\t\t%d\n", pre2, netsplit.NumAddrsPfx(pfx.Masked(), false, false))
if verb >= 2 {
@@ -211,23 +229,23 @@ func printMask(label string, pfx netip.Prefix, verb, indent int, indentStr strin
func printNets(orig *netip.Prefix, origNet *net.IPNet, nets []*netip.Prefix, remaining *netipx.IPSet, args *common, splitter netsplit.NetSplitter) (err error) {
var b []byte
var resIdx int
var netsLen uint
var remLen uint
var buf *bytes.Buffer
var masked netip.Prefix
var remPfxs []*netip.Prefix
var invertedMask net.IPMask
var resIdx int
var resPfx netip.Prefix
var resRec *netsplit.IANAAddrNetResRecord
var reservedList []*netip.Prefix
var reserved map[netip.Prefix]*netsplit.IANAAddrNetResRecord
var res *netsplit.StructuredResults
var verb = -1
var fmts []string
var sectSep1 string
var sectSep2 string
// var sectSep3 string
var verb int = 1
if orig == nil {
return
@@ -245,11 +263,14 @@ func printNets(orig *netip.Prefix, origNet *net.IPNet, nets []*netip.Prefix, rem
sectSep2 = fmts[1]
// sectSep3 = fmts[2]
if args.Verbose != nil {
verb = 0
for _, i := range args.Verbose {
if i {
verb++
if args.Quiet {
verb--
} else {
if args.Verbose != nil {
for _, i := range args.Verbose {
if i {
verb++
}
}
}
}