v1.16.9
ADDED: * netx.IsPub * encodingx/hexx Rest are mostly small corrections and docs
This commit is contained in:
@@ -0,0 +1,295 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/netip"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/olekukonko/tablewriter/tw"
|
||||
)
|
||||
|
||||
const (
|
||||
sectBordChar string = "#"
|
||||
sectBordWdth int = 2
|
||||
sectSpcPad int = 1
|
||||
|
||||
sectSidePad int = sectBordWdth + sectSpcPad
|
||||
sectBothPad int = sectSidePad * 2
|
||||
)
|
||||
|
||||
type (
|
||||
IpInfo struct {
|
||||
// Desc string
|
||||
Index int
|
||||
// IP netip.Addr
|
||||
Is4 bool
|
||||
Is4In6 bool
|
||||
Is6 bool
|
||||
IsGlobalUnicast bool
|
||||
IsLinkLocalUnicast bool
|
||||
IsInterfaceLocalMulticast bool
|
||||
IsLinkLocalMulticast bool
|
||||
IsMulticast bool
|
||||
IsLoopback bool
|
||||
IsPrivate bool
|
||||
IsUnspecified bool
|
||||
IsValid bool
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
datHdrsFunc []string = []string{
|
||||
"-",
|
||||
".Is4", ".Is4In6()", ".Is6()",
|
||||
".IsGlobalUnicast()", ".IsLinkLocalUnicast()",
|
||||
".IsInterfaceLocalMulticast()", ".IsLinkLocalMulticast()", ".IsMulticast()",
|
||||
".IsLoopback()",
|
||||
".IsPrivate()",
|
||||
".IsUnspecified()", ".IsValid()",
|
||||
}
|
||||
|
||||
datHdrsKey []string = []string{
|
||||
"Address Index (See Fig. 3)",
|
||||
"IPv4", "4-in-6", "IPv6",
|
||||
"Global Unicast", "Link-Local Unicast",
|
||||
"Interface Local Multicast", "Link-Local Multicast", "Multicast",
|
||||
"Loopback",
|
||||
"Private/LAN",
|
||||
"\"Unspecified\" Address", "Valid Address",
|
||||
}
|
||||
|
||||
datHdrsShort = []string{
|
||||
"IDX",
|
||||
"4", "6(4)", "6",
|
||||
"GU", "LLU",
|
||||
"ILM", "LLM", "M",
|
||||
"LO",
|
||||
"P",
|
||||
"U", "V",
|
||||
}
|
||||
|
||||
exampleAddrs [][2]string = [][2]string{
|
||||
[2]string{"IPv4", "203.0.113.10"}, // RFC 5737 address (https://datatracker.ietf.org/doc/html/rfc5737)
|
||||
[2]string{"IPv4 Unspecified", "0.0.0.0"}, // Generally used to represent all of IPv4 address space
|
||||
[2]string{"IPv4 Global Unicast", "173.230.132.76"}, // r00t2.io
|
||||
[2]string{"IPv4 Multicast (All) (RFC 1112 § 4)", "224.0.0.1"}, // Should encompass all the multicast below. 224.0.0.0 is reserved.
|
||||
[2]string{"IPv4 Multicast (Reserved) (RFC 1112 § 4)", "224.0.0.0"}, // Reserved per RFC but it should still report multicast.
|
||||
[2]string{"IPv4 Multicast (Link-Local Multicast/Local Network Control Block) (RFC 5771 § 4)", "224.0.0.18"}, // https://datatracker.ietf.org/doc/html/rfc5771#section-4 (VRRP multicast addr)
|
||||
[2]string{"IPv4 Multicast (Internetwork Control Block) (RFC 5771 § 5)", "224.0.1.68"}, // https://datatracker.ietf.org/doc/html/rfc5771#section-5 (mdhcpdiscover, RFC 2730)
|
||||
[2]string{"IPv4 Multicast (AD-HOC I) (RFC 5771 § 6)", "224.0.2.10"}, // https://datatracker.ietf.org/doc/html/rfc5771#section-6
|
||||
[2]string{"IPv4 Multicast (SDP/SAP) (RFC 5771 § 7)", "224.2.0.10"}, // https://datatracker.ietf.org/doc/html/rfc5771#section-7
|
||||
[2]string{"IPv4 Multicast (AD-HOC II) (RFC 5771 § 6)", "224.3.0.10"}, // (above)
|
||||
[2]string{"IPv4 Multicast (Source-Specific) (RFC 5771 § 8)", "232.0.0.10"}, // https://datatracker.ietf.org/doc/html/rfc5771#section-8
|
||||
[2]string{"IPv4 Multicast (GLOP) (RFC 5771 § 9)", "233.0.0.10"}, // https://datatracker.ietf.org/doc/html/rfc5771#section-9
|
||||
[2]string{"IPv4 Multicast (AD-HOC III) (RFC 5771 § 6)", "233.252.0.10"}, // (above)
|
||||
[2]string{"IPv4 Multicast (Administrative) (RFC 5771 § 10)", "239.0.0.10"}, // https://datatracker.ietf.org/doc/html/rfc5771#section-10
|
||||
[2]string{"IPv4 Link-Local Unicast (RFC 3927 § 2.1)", "169.254.1.10"}, // https://datatracker.ietf.org/doc/html/rfc3927#section-2.1
|
||||
[2]string{"IPv4 Loopback", "127.0.1.10"}, // It's actually 127/8. Cannot believe how many people do not know this.
|
||||
[2]string{"IPv4 Private (RFC 1918)", "10.0.0.10"}, // https://datatracker.ietf.org/doc/html/rfc1918
|
||||
[2]string{"4-in-6 (RFC 4291 § 2.5.5.1)", "::203.0.113.10"}, // https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.1
|
||||
[2]string{"4-in-6 (RFC 4291 § 2.5.5.1) (Native)", "::cb00:710a"}, // ""
|
||||
[2]string{"4-in-6 (RFC 4291 § 2.5.5.2)", "::ffff:203.0.113.10"}, // https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.5.2
|
||||
[2]string{"4-in-6 (RFC 4291 § 2.5.5.2) (Native)", "::ffff:cb00:710a"}, // ""
|
||||
[2]string{"IPv6", "2001:db8::cb00:710a"}, // RFC 3849 (https://datatracker.ietf.org/doc/html/rfc3849) / RFC 9637 (https://datatracker.ietf.org/doc/html/rfc9637) address
|
||||
[2]string{"IPv6 Unspecified", "::"}, // Generally used to represent all of IPv6 address space
|
||||
[2]string{"IPv6 Global Unicast", "2600:3c02::f03c:91ff:fe93:c0a7"}, // r00t2.io
|
||||
[2]string{"IPv6 Multicast (RFC 4291 § 2.7.1) (Reserved Net)", "ff00::"}, // https://datatracker.ietf.org/doc/html/rfc4291#section-2.7.1
|
||||
[2]string{"IPv6 Multicast (RFC 4291 § 2.7.1) (Reserved)", "ff00::1"}, // ""
|
||||
[2]string{"IPv6 Multicast (RFC 4291 § 2.7.1) (All Nodes) (Interface-Local)", "ff01::1"}, // ""
|
||||
[2]string{"IPv6 Multicast (RFC 4291 § 2.7.1) (All Nodes) (Link-Local)", "ff02::1"}, // ""
|
||||
[2]string{"IPv6 Multicast (RFC 4291 § 2.7.1) (All Routers) (Interface-Local)", "ff01::2"}, // ""
|
||||
[2]string{"IPv6 Multicast (RFC 4291 § 2.7.1) (All Routers) (Link-Local)", "ff02::2"}, // ""
|
||||
[2]string{"IPv6 Multicast (RFC 4291 § 2.7.1) (All Routers) (Admin-Local)", "ff04::2"}, // ""
|
||||
[2]string{"IPv6 Multicast (RFC 4291 § 2.7.1) (All Routers) (Site-Local)", "ff05::2"}, // ""
|
||||
[2]string{"IPv6 Multicast (RFC 4291 § 2.7.1) (All Routers) (Org-Local)", "ff08::2"}, // ""
|
||||
[2]string{"IPv6 Multicast (RFC 4291 § 2.7.1) (All Routers) (Internet/Global)", "ff0e::2"}, // ""
|
||||
[2]string{"IPv6 Multicast (RFC 4291 § 2.7.1) (Solicited Node)", "ff02::1:ff00:10"}, // ""
|
||||
[2]string{"IPv6 Link-Local Unicast (RFC 4291 § 2.5.6)", "fe80::cb00:710a"}, // https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.6
|
||||
[2]string{"IPv6 Loopback", "::1"}, // It's explicitly always a /128 with the address ::1 per RFC 4291 § 2.5.3.
|
||||
[2]string{"IPv6 Private (Unique-Local Addresses) (RFC 4193) (Reserved)", "fc00::10"}, // https://datatracker.ietf.org/doc/html/rfc4193
|
||||
[2]string{"IPv6 Private (Unique-Local Addresses) (RFC 4193) (Valid)", "fd00::10"}, // ""
|
||||
}
|
||||
|
||||
descs []string = make([]string, len(exampleAddrs))
|
||||
ips []netip.Addr = make([]netip.Addr, len(exampleAddrs))
|
||||
|
||||
sectSep string = "\n" + strings.Repeat("-", 80) + "\n"
|
||||
)
|
||||
|
||||
func genHdr(sectNm string) (s string) {
|
||||
|
||||
// Wish I finished stringsx.Banner at time of writing this...
|
||||
var fillLen int = sectBothPad + len(sectNm)
|
||||
|
||||
s = fmt.Sprintf(
|
||||
"%s\n"+ // top border
|
||||
// begin title line
|
||||
"%-*s"+ // left-justify/right-pad
|
||||
"%s"+ // sectNm text
|
||||
"%[2]*[3]s\n"+ // one-indexed; repeat pad num and pad str from left border as right border
|
||||
// end title line
|
||||
"%[1]s\n", // bottom border
|
||||
strings.Repeat(sectBordChar, fillLen), // top and bottom (bottom uses index)
|
||||
sectSidePad, strings.Repeat(sectBordChar, sectBordWdth), // title left and right borders (right uses index)
|
||||
sectNm, // title text
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
||||
var err error
|
||||
var idx int
|
||||
var s string
|
||||
var desc string
|
||||
var pair [2]string
|
||||
var buf *bytes.Buffer = new(bytes.Buffer)
|
||||
|
||||
var tbl *tablewriter.Table = tablewriter.NewTable(
|
||||
buf,
|
||||
tablewriter.WithConfig(
|
||||
tablewriter.Config{
|
||||
Header: tw.CellConfig{
|
||||
Formatting: tw.CellFormatting{
|
||||
AutoFormat: tw.Off,
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
// requires .Batch(), and the autoheader forces all caps.
|
||||
// https://github.com/olekukonko/tablewriter/issues/143
|
||||
// https://github.com/olekukonko/tablewriter/issues/190
|
||||
/*
|
||||
tablewriter.WithBehavior(
|
||||
tw.Behavior{
|
||||
Structs: tw.Struct{
|
||||
AutoHeader: tw.On,
|
||||
},
|
||||
},
|
||||
),
|
||||
*/
|
||||
tablewriter.WithRendition(
|
||||
tw.Rendition{
|
||||
Settings: tw.Settings{
|
||||
Separators: tw.Separators{BetweenRows: tw.On},
|
||||
},
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
defer func() {
|
||||
var tErr error
|
||||
if tbl != nil {
|
||||
if tErr = tbl.Close(); tErr != nil {
|
||||
log.Printf("Error closing table: %v", tErr)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
buf.WriteString(genHdr("Fig. 1: Address Evaluations"))
|
||||
buf.WriteString("(See Fig. 2 for a key of header symbols to names)\n\n")
|
||||
|
||||
tbl.Header(datHdrsShort)
|
||||
for idx, pair = range exampleAddrs {
|
||||
desc, s = pair[0], pair[1]
|
||||
descs[idx] = desc
|
||||
if ips[idx], err = netip.ParseAddr(s); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
// Currently no way to skip cols etc. https://github.com/olekukonko/tablewriter/issues/317
|
||||
// rows[idx] = IpInfo{
|
||||
if err = tbl.Append(
|
||||
IpInfo{
|
||||
// Desc: desc,
|
||||
Index: idx,
|
||||
// IP: ip,
|
||||
Is4: ips[idx].Is4(),
|
||||
Is4In6: ips[idx].Is4In6(),
|
||||
Is6: ips[idx].Is6(),
|
||||
IsGlobalUnicast: ips[idx].IsGlobalUnicast(),
|
||||
IsLinkLocalUnicast: ips[idx].IsLinkLocalUnicast(),
|
||||
IsInterfaceLocalMulticast: ips[idx].IsInterfaceLocalMulticast(),
|
||||
IsLinkLocalMulticast: ips[idx].IsLinkLocalMulticast(),
|
||||
IsMulticast: ips[idx].IsMulticast(),
|
||||
IsLoopback: ips[idx].IsLoopback(),
|
||||
IsPrivate: ips[idx].IsPrivate(),
|
||||
IsUnspecified: ips[idx].IsUnspecified(),
|
||||
IsValid: ips[idx].IsValid(),
|
||||
},
|
||||
); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
}
|
||||
/*
|
||||
if err = tbl.Bulk(rows); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
*/
|
||||
if err = tbl.Render(); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
buf.WriteString(sectSep)
|
||||
buf.WriteString(genHdr("Fig. 2: Headers Key for Fig. 1"))
|
||||
tbl.Reset()
|
||||
tbl.Header("Symbol", "Description", "net/netip.Addr Method")
|
||||
for idx = range datHdrsKey {
|
||||
if err = tbl.Append(
|
||||
[]string{
|
||||
datHdrsShort[idx],
|
||||
datHdrsKey[idx],
|
||||
datHdrsFunc[idx],
|
||||
},
|
||||
); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
}
|
||||
if err = tbl.Render(); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
buf.WriteString(sectSep)
|
||||
buf.WriteString(genHdr("Fig. 3: Test/Example IP Address Reference/Lookup for Fig. 1"))
|
||||
buf.WriteString("(See Fig. 4 for Descriptions/Detailed Information)\n\n")
|
||||
tbl.Reset()
|
||||
tbl.Header("Index", "Address (Raw)", "Address (Parsed)")
|
||||
for idx = range exampleAddrs {
|
||||
if err = tbl.Append(
|
||||
[]string{
|
||||
strconv.Itoa(idx),
|
||||
exampleAddrs[idx][1],
|
||||
ips[idx].String(),
|
||||
},
|
||||
); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
}
|
||||
if err = tbl.Render(); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
buf.WriteString(sectSep)
|
||||
buf.WriteString(genHdr("Fig. 4: Extended Information for Fig. 3"))
|
||||
tbl.Reset()
|
||||
tbl.Header("Index", "Description")
|
||||
for idx = range exampleAddrs {
|
||||
if err = tbl.Append(
|
||||
[]string{
|
||||
strconv.Itoa(idx),
|
||||
descs[idx],
|
||||
},
|
||||
); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
}
|
||||
if err = tbl.Render(); err != nil {
|
||||
log.Panicln(err)
|
||||
}
|
||||
|
||||
fmt.Println(buf.String())
|
||||
}
|
||||
Reference in New Issue
Block a user