v0.3.0
* 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:
parent
860ad5842b
commit
4cbb17bf9e
23
.githooks/pre-commit/01-docgen
Executable file
23
.githooks/pre-commit/01-docgen
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
#docsdir="${PWD}/docs"
|
||||||
|
docsdir="${PWD}"
|
||||||
|
|
||||||
|
if ! command -v asciidoctor &> /dev/null;
|
||||||
|
then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "${docsdir}"
|
||||||
|
|
||||||
|
for f in $(find . -maxdepth 1 -type f -iname "*.adoc"); do
|
||||||
|
filename=$(basename -- "${f}")
|
||||||
|
nosuffix="${filename%.*}"
|
||||||
|
|
||||||
|
asciidoctor \
|
||||||
|
-a allow-uri-read \
|
||||||
|
-o "${docsdir}/${nosuffix}.html" \
|
||||||
|
"${f}"
|
||||||
|
git add "${docsdir}/${nosuffix}.html"
|
||||||
|
done
|
||||||
|
echo "Regenerated docs"
|
||||||
15
.githooks/pre-commit/02-gofmt
Executable file
15
.githooks/pre-commit/02-gofmt
Executable file
@ -0,0 +1,15 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
srcdir="${PWD}/examples"
|
||||||
|
|
||||||
|
if ! command -v gofmt &> /dev/null;
|
||||||
|
then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
for f in $(find ${srcdir} -type f -iname "*.go");
|
||||||
|
do
|
||||||
|
gofmt -w "${f}"
|
||||||
|
git add "${f}"
|
||||||
|
done
|
||||||
|
echo "Reformatted examples"
|
||||||
@ -1,8 +0,0 @@
|
|||||||
The "IPv6 Segment Reference Diagram" output as rendered in the `table`
|
|
||||||
subcommand is from:
|
|
||||||
https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing
|
|
||||||
as fetched on April 07, 2025.
|
|
||||||
It is licensed under Creative Commons "CC BY-SA 4.0";
|
|
||||||
see:
|
|
||||||
https://creativecommons.org/licenses/by-sa/4.0/
|
|
||||||
https://creativecommons.org/licenses/by-sa/4.0/legalcode.en)
|
|
||||||
17
README.adoc
17
README.adoc
@ -56,10 +56,25 @@ A tool to assist in design of segregate/segment/split/subnet networks.
|
|||||||
|
|
||||||
[id="ref"]
|
[id="ref"]
|
||||||
== References
|
== References
|
||||||
|
|
||||||
|
[TIP]
|
||||||
|
====
|
||||||
|
See also the <<ack>> section for specific material used directly.
|
||||||
|
====
|
||||||
|
|
||||||
This program in general draws inspiration from `ipcalc` (http://jodies.de/ipcalc[0^], https://github.com/kjokjo/ipcalc[1^], https://gitlab.com/ipcalc/ipcalc[2^]) and http://www.routemeister.net/projects/sipcalc/[`sipcalc`^].
|
This program in general draws inspiration from `ipcalc` (http://jodies.de/ipcalc[0^], https://github.com/kjokjo/ipcalc[1^], https://gitlab.com/ipcalc/ipcalc[2^]) and http://www.routemeister.net/projects/sipcalc/[`sipcalc`^].
|
||||||
|
|
||||||
The `table` subcommand is inspired by `iptab` from https://metacpan.org/pod/Net::IP[Perl Net-IP^].
|
The `table` subcommand is inspired by `iptab` from https://metacpan.org/pod/Net::IP[Perl Net-IP^].
|
||||||
|
|
||||||
Additional notes for certain contexts are primarily taken from https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing[the Wikipedia article on _Classless Inter-Domain Routing_^] (as of _Jan 28, 2025_).
|
Additional notes for certain contexts are primarily taken from https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing[the Wikipedia article on _Classless Inter-Domain Routing_^] (as of _Jan 28, 2025_).
|
||||||
|
|
||||||
Reservations are pulled/cached directly from the IANA registries (https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml[IPv4^], https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml[IPv6^]).
|
Reservations are pulled/cached directly from the IANA registries (https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml[IPv4^], https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml[IPv6^]).
|
||||||
|
|
||||||
|
[id="ack"]
|
||||||
|
== Acknowledgements
|
||||||
|
|
||||||
|
[id="ack_segrefdiag"]
|
||||||
|
=== IPv6 Segment Reference Diagram
|
||||||
|
The _IPv6 Segment Reference Diagram_ default output as rendered from the `table` subcommand is generally from https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing as fetched on April 07, 2025.
|
||||||
|
|
||||||
|
It is licensed under https://creativecommons.org/licenses/by-sa/4.0/[Creative Commons CC BY-SA 4.0^] (https://creativecommons.org/licenses/by-sa/4.0/legalcode.en[full license^]).
|
||||||
|
|||||||
661
README.html
Normal file
661
README.html
Normal file
@ -0,0 +1,661 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta name="generator" content="Asciidoctor 2.0.26">
|
||||||
|
<meta name="author" content="Brent Saner">
|
||||||
|
<title>Subnetter</title>
|
||||||
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
|
||||||
|
<style>
|
||||||
|
/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */
|
||||||
|
/* Uncomment the following line when using as a custom stylesheet */
|
||||||
|
/* @import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700"; */
|
||||||
|
html{font-family:sans-serif;-webkit-text-size-adjust:100%}
|
||||||
|
a{background:none}
|
||||||
|
a:focus{outline:thin dotted}
|
||||||
|
a:active,a:hover{outline:0}
|
||||||
|
h1{font-size:2em;margin:.67em 0}
|
||||||
|
b,strong{font-weight:bold}
|
||||||
|
abbr{font-size:.9em}
|
||||||
|
abbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}
|
||||||
|
dfn{font-style:italic}
|
||||||
|
hr{height:0}
|
||||||
|
mark{background:#ff0;color:#000}
|
||||||
|
code,kbd,pre,samp{font-family:monospace;font-size:1em}
|
||||||
|
pre{white-space:pre-wrap}
|
||||||
|
q{quotes:"\201C" "\201D" "\2018" "\2019"}
|
||||||
|
small{font-size:80%}
|
||||||
|
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
|
||||||
|
sup{top:-.5em}
|
||||||
|
sub{bottom:-.25em}
|
||||||
|
img{border:0}
|
||||||
|
svg:not(:root){overflow:hidden}
|
||||||
|
figure{margin:0}
|
||||||
|
audio,video{display:inline-block}
|
||||||
|
audio:not([controls]){display:none;height:0}
|
||||||
|
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
|
||||||
|
legend{border:0;padding:0}
|
||||||
|
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
|
||||||
|
button,input{line-height:normal}
|
||||||
|
button,select{text-transform:none}
|
||||||
|
button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}
|
||||||
|
button[disabled],html input[disabled]{cursor:default}
|
||||||
|
input[type=checkbox],input[type=radio]{padding:0}
|
||||||
|
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
|
||||||
|
textarea{overflow:auto;vertical-align:top}
|
||||||
|
table{border-collapse:collapse;border-spacing:0}
|
||||||
|
*,::before,::after{box-sizing:border-box}
|
||||||
|
html,body{font-size:100%}
|
||||||
|
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
|
||||||
|
a:hover{cursor:pointer}
|
||||||
|
img,object,embed{max-width:100%;height:auto}
|
||||||
|
object,embed{height:100%}
|
||||||
|
img{-ms-interpolation-mode:bicubic}
|
||||||
|
.left{float:left!important}
|
||||||
|
.right{float:right!important}
|
||||||
|
.text-left{text-align:left!important}
|
||||||
|
.text-right{text-align:right!important}
|
||||||
|
.text-center{text-align:center!important}
|
||||||
|
.text-justify{text-align:justify!important}
|
||||||
|
.hide{display:none}
|
||||||
|
img,object,svg{display:inline-block;vertical-align:middle}
|
||||||
|
textarea{height:auto;min-height:50px}
|
||||||
|
select{width:100%}
|
||||||
|
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
|
||||||
|
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}
|
||||||
|
a{color:#2156a5;text-decoration:underline;line-height:inherit}
|
||||||
|
a:hover,a:focus{color:#1d4b8f}
|
||||||
|
a img{border:0}
|
||||||
|
p{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
|
||||||
|
p aside{font-size:.875em;line-height:1.35;font-style:italic}
|
||||||
|
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
|
||||||
|
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
|
||||||
|
h1{font-size:2.125em}
|
||||||
|
h2{font-size:1.6875em}
|
||||||
|
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
|
||||||
|
h4,h5{font-size:1.125em}
|
||||||
|
h6{font-size:1em}
|
||||||
|
hr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}
|
||||||
|
em,i{font-style:italic;line-height:inherit}
|
||||||
|
strong,b{font-weight:bold;line-height:inherit}
|
||||||
|
small{font-size:60%;line-height:inherit}
|
||||||
|
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
|
||||||
|
ul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
|
||||||
|
ul,ol{margin-left:1.5em}
|
||||||
|
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}
|
||||||
|
ul.circle{list-style-type:circle}
|
||||||
|
ul.disc{list-style-type:disc}
|
||||||
|
ul.square{list-style-type:square}
|
||||||
|
ul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}
|
||||||
|
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
|
||||||
|
dl dt{margin-bottom:.3125em;font-weight:bold}
|
||||||
|
dl dd{margin-bottom:1.25em}
|
||||||
|
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
|
||||||
|
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
|
||||||
|
@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
|
||||||
|
h1{font-size:2.75em}
|
||||||
|
h2{font-size:2.3125em}
|
||||||
|
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
|
||||||
|
h4{font-size:1.4375em}}
|
||||||
|
table{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}
|
||||||
|
table thead,table tfoot{background:#f7f8f7}
|
||||||
|
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
|
||||||
|
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
|
||||||
|
table tr.even,table tr.alt{background:#f8f8f7}
|
||||||
|
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}
|
||||||
|
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
|
||||||
|
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
|
||||||
|
.center{margin-left:auto;margin-right:auto}
|
||||||
|
.stretch{width:100%}
|
||||||
|
.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
|
||||||
|
.clearfix::after,.float-group::after{clear:both}
|
||||||
|
:not(pre).nobreak{word-wrap:normal}
|
||||||
|
:not(pre).nowrap{white-space:nowrap}
|
||||||
|
:not(pre).pre-wrap{white-space:pre-wrap}
|
||||||
|
:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
|
||||||
|
pre{color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;line-height:1.45;text-rendering:optimizeSpeed}
|
||||||
|
pre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}
|
||||||
|
pre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}
|
||||||
|
em em{font-style:normal}
|
||||||
|
strong strong{font-weight:400}
|
||||||
|
.keyseq{color:rgba(51,51,51,.8)}
|
||||||
|
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
|
||||||
|
.keyseq kbd:first-child{margin-left:0}
|
||||||
|
.keyseq kbd:last-child{margin-right:0}
|
||||||
|
.menuseq,.menuref{color:#000}
|
||||||
|
.menuseq b:not(.caret),.menuref{font-weight:inherit}
|
||||||
|
.menuseq{word-spacing:-.02em}
|
||||||
|
.menuseq b.caret{font-size:1.25em;line-height:.8}
|
||||||
|
.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
|
||||||
|
b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
|
||||||
|
b.button::before{content:"[";padding:0 3px 0 2px}
|
||||||
|
b.button::after{content:"]";padding:0 2px 0 3px}
|
||||||
|
p a>code:hover{color:rgba(0,0,0,.9)}
|
||||||
|
#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
|
||||||
|
#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
|
||||||
|
#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
|
||||||
|
#content{margin-top:1.25em}
|
||||||
|
#content::before{content:none}
|
||||||
|
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
|
||||||
|
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}
|
||||||
|
#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}
|
||||||
|
#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}
|
||||||
|
#header .details span:first-child{margin-left:-.125em}
|
||||||
|
#header .details span.email a{color:rgba(0,0,0,.85)}
|
||||||
|
#header .details br{display:none}
|
||||||
|
#header .details br+span::before{content:"\00a0\2013\00a0"}
|
||||||
|
#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
|
||||||
|
#header .details br+span#revremark::before{content:"\00a0|\00a0"}
|
||||||
|
#header #revnumber{text-transform:capitalize}
|
||||||
|
#header #revnumber::after{content:"\00a0"}
|
||||||
|
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
|
||||||
|
#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}
|
||||||
|
#toc>ul{margin-left:.125em}
|
||||||
|
#toc ul.sectlevel0>li>a{font-style:italic}
|
||||||
|
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
|
||||||
|
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
|
||||||
|
#toc li{line-height:1.3334;margin-top:.3334em}
|
||||||
|
#toc a{text-decoration:none}
|
||||||
|
#toc a:active{text-decoration:underline}
|
||||||
|
#toctitle{color:#7a2518;font-size:1.2em}
|
||||||
|
@media screen and (min-width:768px){#toctitle{font-size:1.375em}
|
||||||
|
body.toc2{padding-left:15em;padding-right:0}
|
||||||
|
body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}
|
||||||
|
#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
|
||||||
|
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
|
||||||
|
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
|
||||||
|
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
|
||||||
|
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
|
||||||
|
body.toc2.toc-right{padding-left:0;padding-right:15em}
|
||||||
|
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}
|
||||||
|
@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
|
||||||
|
#toc.toc2{width:20em}
|
||||||
|
#toc.toc2 #toctitle{font-size:1.375em}
|
||||||
|
#toc.toc2>ul{font-size:.95em}
|
||||||
|
#toc.toc2 ul ul{padding-left:1.25em}
|
||||||
|
body.toc2.toc-right{padding-left:0;padding-right:20em}}
|
||||||
|
#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}
|
||||||
|
#content #toc>:first-child{margin-top:0}
|
||||||
|
#content #toc>:last-child{margin-bottom:0}
|
||||||
|
#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}
|
||||||
|
#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}
|
||||||
|
#content{margin-bottom:.625em}
|
||||||
|
.sect1{padding-bottom:.625em}
|
||||||
|
@media screen and (min-width:768px){#content{margin-bottom:1.25em}
|
||||||
|
.sect1{padding-bottom:1.25em}}
|
||||||
|
.sect1:last-child{padding-bottom:0}
|
||||||
|
.sect1+.sect1{border-top:1px solid #e7e7e9}
|
||||||
|
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
|
||||||
|
#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
|
||||||
|
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
|
||||||
|
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
|
||||||
|
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
|
||||||
|
details,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
|
||||||
|
details{margin-left:1.25rem}
|
||||||
|
details>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}
|
||||||
|
details>summary::-webkit-details-marker{display:none}
|
||||||
|
details>summary::before{content:"";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}
|
||||||
|
details[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}
|
||||||
|
details>summary::after{content:"";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}
|
||||||
|
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
|
||||||
|
table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
|
||||||
|
.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
|
||||||
|
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
|
||||||
|
.admonitionblock>table td.icon{text-align:center;width:80px}
|
||||||
|
.admonitionblock>table td.icon img{max-width:none}
|
||||||
|
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
|
||||||
|
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}
|
||||||
|
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
|
||||||
|
.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}
|
||||||
|
.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}
|
||||||
|
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
|
||||||
|
.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}
|
||||||
|
.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
|
||||||
|
.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}
|
||||||
|
@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}
|
||||||
|
@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}
|
||||||
|
.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^="highlight "]{background:#f7f7f8}
|
||||||
|
.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}
|
||||||
|
.listingblock>.content{position:relative}
|
||||||
|
.listingblock pre>code{display:block}
|
||||||
|
.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}
|
||||||
|
.listingblock:hover code[data-lang]::before{display:block}
|
||||||
|
.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}
|
||||||
|
.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
|
||||||
|
.listingblock pre.highlightjs{padding:0}
|
||||||
|
.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}
|
||||||
|
.listingblock pre.prettyprint{border-width:0}
|
||||||
|
.prettyprint{background:#f7f7f8}
|
||||||
|
pre.prettyprint .linenums{line-height:1.45;margin-left:2em}
|
||||||
|
pre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}
|
||||||
|
pre.prettyprint li code[data-lang]::before{opacity:1}
|
||||||
|
pre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}
|
||||||
|
table.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}
|
||||||
|
table.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}
|
||||||
|
table.linenotable td.code{padding-left:.75em}
|
||||||
|
table.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}
|
||||||
|
pre.pygments span.linenos{display:inline-block;margin-right:.75em}
|
||||||
|
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
|
||||||
|
.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}
|
||||||
|
.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
|
||||||
|
.quoteblock blockquote{margin:0;padding:0;border:0}
|
||||||
|
.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
|
||||||
|
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
|
||||||
|
.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}
|
||||||
|
.verseblock{margin:0 1em 1.25em}
|
||||||
|
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
|
||||||
|
.verseblock pre strong{font-weight:400}
|
||||||
|
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
|
||||||
|
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
|
||||||
|
.quoteblock .attribution br,.verseblock .attribution br{display:none}
|
||||||
|
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
|
||||||
|
.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}
|
||||||
|
.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}
|
||||||
|
.quoteblock.abstract{margin:0 1em 1.25em;display:block}
|
||||||
|
.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
|
||||||
|
.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}
|
||||||
|
.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}
|
||||||
|
.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}
|
||||||
|
.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}
|
||||||
|
p.tableblock:last-child{margin-bottom:0}
|
||||||
|
td.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}
|
||||||
|
td.tableblock>.content>:last-child{margin-bottom:-1.25em}
|
||||||
|
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
|
||||||
|
table.grid-all>*>tr>*{border-width:1px}
|
||||||
|
table.grid-cols>*>tr>*{border-width:0 1px}
|
||||||
|
table.grid-rows>*>tr>*{border-width:1px 0}
|
||||||
|
table.frame-all{border-width:1px}
|
||||||
|
table.frame-ends{border-width:1px 0}
|
||||||
|
table.frame-sides{border-width:0 1px}
|
||||||
|
table.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}
|
||||||
|
table.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}
|
||||||
|
table.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}
|
||||||
|
table.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}
|
||||||
|
table.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}
|
||||||
|
th.halign-left,td.halign-left{text-align:left}
|
||||||
|
th.halign-right,td.halign-right{text-align:right}
|
||||||
|
th.halign-center,td.halign-center{text-align:center}
|
||||||
|
th.valign-top,td.valign-top{vertical-align:top}
|
||||||
|
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
|
||||||
|
th.valign-middle,td.valign-middle{vertical-align:middle}
|
||||||
|
table thead th,table tfoot th{font-weight:bold}
|
||||||
|
tbody tr th{background:#f7f8f7}
|
||||||
|
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
|
||||||
|
p.tableblock>code:only-child{background:none;padding:0}
|
||||||
|
p.tableblock{font-size:1em}
|
||||||
|
ol{margin-left:1.75em}
|
||||||
|
ul li ol{margin-left:1.5em}
|
||||||
|
dl dd{margin-left:1.125em}
|
||||||
|
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
|
||||||
|
li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
|
||||||
|
ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
|
||||||
|
ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
|
||||||
|
ul.unstyled,ol.unstyled{margin-left:0}
|
||||||
|
li>p:empty:only-child::before{content:"";display:inline-block}
|
||||||
|
ul.checklist>li>p:first-child{margin-left:-1em}
|
||||||
|
ul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
|
||||||
|
ul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}
|
||||||
|
ul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
|
||||||
|
ul.inline>li{margin-left:1.25em}
|
||||||
|
.unstyled dl dt{font-weight:400;font-style:normal}
|
||||||
|
ol.arabic{list-style-type:decimal}
|
||||||
|
ol.decimal{list-style-type:decimal-leading-zero}
|
||||||
|
ol.loweralpha{list-style-type:lower-alpha}
|
||||||
|
ol.upperalpha{list-style-type:upper-alpha}
|
||||||
|
ol.lowerroman{list-style-type:lower-roman}
|
||||||
|
ol.upperroman{list-style-type:upper-roman}
|
||||||
|
ol.lowergreek{list-style-type:lower-greek}
|
||||||
|
.hdlist>table,.colist>table{border:0;background:none}
|
||||||
|
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
|
||||||
|
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
|
||||||
|
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
|
||||||
|
td.hdlist2{word-wrap:anywhere}
|
||||||
|
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
|
||||||
|
.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
|
||||||
|
.colist td:not([class]):first-child img{max-width:none}
|
||||||
|
.colist td:not([class]):last-child{padding:.25em 0}
|
||||||
|
.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}
|
||||||
|
.imageblock.left{margin:.25em .625em 1.25em 0}
|
||||||
|
.imageblock.right{margin:.25em 0 1.25em .625em}
|
||||||
|
.imageblock>.title{margin-bottom:0}
|
||||||
|
.imageblock.thumb,.imageblock.th{border-width:6px}
|
||||||
|
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
|
||||||
|
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
|
||||||
|
.image.left{margin-right:.625em}
|
||||||
|
.image.right{margin-left:.625em}
|
||||||
|
a.image{text-decoration:none;display:inline-block}
|
||||||
|
a.image object{pointer-events:none}
|
||||||
|
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
|
||||||
|
sup.footnote a,sup.footnoteref a{text-decoration:none}
|
||||||
|
sup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}
|
||||||
|
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
|
||||||
|
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
|
||||||
|
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
|
||||||
|
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
|
||||||
|
#footnotes .footnote:last-of-type{margin-bottom:0}
|
||||||
|
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
|
||||||
|
div.unbreakable{page-break-inside:avoid}
|
||||||
|
.big{font-size:larger}
|
||||||
|
.small{font-size:smaller}
|
||||||
|
.underline{text-decoration:underline}
|
||||||
|
.overline{text-decoration:overline}
|
||||||
|
.line-through{text-decoration:line-through}
|
||||||
|
.aqua{color:#00bfbf}
|
||||||
|
.aqua-background{background:#00fafa}
|
||||||
|
.black{color:#000}
|
||||||
|
.black-background{background:#000}
|
||||||
|
.blue{color:#0000bf}
|
||||||
|
.blue-background{background:#0000fa}
|
||||||
|
.fuchsia{color:#bf00bf}
|
||||||
|
.fuchsia-background{background:#fa00fa}
|
||||||
|
.gray{color:#606060}
|
||||||
|
.gray-background{background:#7d7d7d}
|
||||||
|
.green{color:#006000}
|
||||||
|
.green-background{background:#007d00}
|
||||||
|
.lime{color:#00bf00}
|
||||||
|
.lime-background{background:#00fa00}
|
||||||
|
.maroon{color:#600000}
|
||||||
|
.maroon-background{background:#7d0000}
|
||||||
|
.navy{color:#000060}
|
||||||
|
.navy-background{background:#00007d}
|
||||||
|
.olive{color:#606000}
|
||||||
|
.olive-background{background:#7d7d00}
|
||||||
|
.purple{color:#600060}
|
||||||
|
.purple-background{background:#7d007d}
|
||||||
|
.red{color:#bf0000}
|
||||||
|
.red-background{background:#fa0000}
|
||||||
|
.silver{color:#909090}
|
||||||
|
.silver-background{background:#bcbcbc}
|
||||||
|
.teal{color:#006060}
|
||||||
|
.teal-background{background:#007d7d}
|
||||||
|
.white{color:#bfbfbf}
|
||||||
|
.white-background{background:#fafafa}
|
||||||
|
.yellow{color:#bfbf00}
|
||||||
|
.yellow-background{background:#fafa00}
|
||||||
|
span.icon>.fa{cursor:default}
|
||||||
|
a span.icon>.fa{cursor:inherit}
|
||||||
|
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
|
||||||
|
.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
|
||||||
|
.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
|
||||||
|
.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
|
||||||
|
.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
|
||||||
|
.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
|
||||||
|
.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
|
||||||
|
.conum[data-value] *{color:#fff!important}
|
||||||
|
.conum[data-value]+b{display:none}
|
||||||
|
.conum[data-value]::after{content:attr(data-value)}
|
||||||
|
pre .conum[data-value]{position:relative;top:-.125em}
|
||||||
|
b.conum *{color:inherit!important}
|
||||||
|
.conum:not([data-value]):empty{display:none}
|
||||||
|
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
|
||||||
|
h1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}
|
||||||
|
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
|
||||||
|
p,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}
|
||||||
|
p{margin-bottom:1.25rem}
|
||||||
|
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
|
||||||
|
.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}
|
||||||
|
.print-only{display:none!important}
|
||||||
|
@page{margin:1.25cm .75cm}
|
||||||
|
@media print{*{box-shadow:none!important;text-shadow:none!important}
|
||||||
|
html{font-size:80%}
|
||||||
|
a{color:inherit!important;text-decoration:underline!important}
|
||||||
|
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
|
||||||
|
a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
|
||||||
|
abbr[title]{border-bottom:1px dotted}
|
||||||
|
abbr[title]::after{content:" (" attr(title) ")"}
|
||||||
|
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
|
||||||
|
thead{display:table-header-group}
|
||||||
|
svg{max-width:100%}
|
||||||
|
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
|
||||||
|
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
|
||||||
|
#header,#content,#footnotes,#footer{max-width:none}
|
||||||
|
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
|
||||||
|
#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}
|
||||||
|
body.book #header{text-align:center}
|
||||||
|
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
|
||||||
|
body.book #header .details{border:0!important;display:block;padding:0!important}
|
||||||
|
body.book #header .details span:first-child{margin-left:0!important}
|
||||||
|
body.book #header .details br{display:block}
|
||||||
|
body.book #header .details br+span::before{content:none!important}
|
||||||
|
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
|
||||||
|
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
|
||||||
|
.listingblock code[data-lang]::before{display:block}
|
||||||
|
#footer{padding:0 .9375em}
|
||||||
|
.hide-on-print{display:none!important}
|
||||||
|
.print-only{display:block!important}
|
||||||
|
.hide-for-print{display:none!important}
|
||||||
|
.show-for-print{display:inherit!important}}
|
||||||
|
@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}
|
||||||
|
.sect1{padding:0!important}
|
||||||
|
.sect1+.sect1{border:0}
|
||||||
|
#footer{background:none}
|
||||||
|
#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
|
||||||
|
@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body class="book toc2 toc-left">
|
||||||
|
<div id="header">
|
||||||
|
<h1>Subnetter</h1>
|
||||||
|
<div class="details">
|
||||||
|
<span id="author" class="author">Brent Saner</span><br>
|
||||||
|
<span id="email" class="email"><a href="mailto:bts@square-r00t.net">bts@square-r00t.net</a></span><br>
|
||||||
|
<span id="revdate">Last rendered 2025-11-08 23:34:42 -0500</span>
|
||||||
|
</div>
|
||||||
|
<div id="toc" class="toc2">
|
||||||
|
<div id="toctitle">Table of Contents</div>
|
||||||
|
<ul class="sectlevel1">
|
||||||
|
<li><a href="#wat">1. What is it?</a></li>
|
||||||
|
<li><a href="#out">2. Output</a></li>
|
||||||
|
<li><a href="#ref">3. References</a></li>
|
||||||
|
<li><a href="#ack">4. Acknowledgements</a>
|
||||||
|
<ul class="sectlevel2">
|
||||||
|
<li><a href="#ack_segrefdiag">4.1. IPv6 Segment Reference Diagram</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="content">
|
||||||
|
<div class="sect1">
|
||||||
|
<h2 id="wat"><a class="link" href="#wat">1. What is it?</a></h2>
|
||||||
|
<div class="sectionbody">
|
||||||
|
<div class="paragraph">
|
||||||
|
<p>A tool to assist in design of segregate/segment/split/subnet networks.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sect1">
|
||||||
|
<h2 id="out"><a class="link" href="#out">2. Output</a></h2>
|
||||||
|
<div class="sectionbody">
|
||||||
|
<div class="ulist">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p><code>PTP</code> refers to "Peer-to-Peer" (e.g. <a href="https://datatracker.ietf.org/doc/html/rfc3021" target="_blank" rel="noopener">RFC 3021</a>).</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p><code>6rd</code> refers to "IPv6 Rapid Deployment", a derivation of 6to4 (<a href="https://datatracker.ietf.org/doc/html/rfc5569" target="_blank" rel="noopener">RFC 5569</a>, <a href="https://datatracker.ietf.org/doc/html/rfc5969" target="_blank" rel="noopener">RFC 5969</a>).</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p><code>LIR</code> refers to "Local Internet Registry" (<a href="https://www.arin.net/participate/policy/nrpm/#2-4-local-internet-registry-lir" target="_blank" rel="noopener">ARIN</a>).</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p><code>RIR</code> refers to "Regional Internet Registry" (<a href="https://www.arin.net/participate/policy/nrpm/#2-2-regional-internet-registry-rir" target="_blank" rel="noopener">ARIN</a>).</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p><code>Unicast</code> refers to "Global Unicast" (<a href="https://datatracker.ietf.org/doc/html/rfc1122" target="_blank" rel="noopener">RFC 1122</a>, <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.5.4" target="_blank" rel="noopener">RFC 4291 § 2.5.4</a>, <a href="https://datatracker.ietf.org/doc/html/rfc4632" target="_blank" rel="noopener">RFC 4632</a>).</p>
|
||||||
|
<div class="ulist">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p>For IPv6 addresses, it will be <code>true</code> for ULA (<em>Unique Local Addresses</em>) (<a href="https://datatracker.ietf.org/doc/html/rfc4193" target="_blank" rel="noopener">RFC 4193</a>) also.</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>For IPv4 addresses, it will be <code>true</code> if the address is routable by external hosts (a unicast address), including private IP addresses (<a href="https://datatracker.ietf.org/doc/html/rfc1918" target="_blank" rel="noopener">RFC 1918</a>).</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p><code>ILM</code> refers to "Interface-Local Multicast" (<a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.7" target="_blank" rel="noopener">RFC 4291 § 2.7</a>, <a href="https://datatracker.ietf.org/doc/html/rfc7346" target="_blank" rel="noopener">RFC 7346</a>).</p>
|
||||||
|
<div class="ulist">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p>It will always be <code>false</code> for IPv4 addresses.</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p><code>LLM</code> refers to "Link-Local Multicast" (<a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.7" target="_blank" rel="noopener">RFC 4291 § 2.7</a>, <a href="https://datatracker.ietf.org/doc/html/rfc7346" target="_blank" rel="noopener">RFC 7346</a>).</p>
|
||||||
|
<div class="ulist">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p>For IPv4 addresses, it will be <code>true</code> if it is in the <code>224.0.0.0/4</code> range (<a href="https://datatracker.ietf.org/doc/html/rfc5735" target="_blank" rel="noopener">RFC 5735</a>).</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p><code>LLU</code> refers to "Link-Local Unicast" (<a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.7" target="_blank" rel="noopener">RFC 4291 § 2.7</a>, <a href="https://datatracker.ietf.org/doc/html/rfc7346" target="_blank" rel="noopener">RFC 7346</a>).</p>
|
||||||
|
<div class="ulist">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p>For IPv4 addresses, it will be <code>true</code> if it is an APIPA (<em>Automatic Private IP Addressing</em>) address (<a href="https://datatracker.ietf.org/doc/html/rfc3927" target="_blank" rel="noopener">RFC 3927</a>) (in the <code>169.254.0.0/16</code> range).</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p><code>First</code> and <code>Last</code> refer to the first and last "usable" ("host"/assignable) addresses in a subnet/network.</p>
|
||||||
|
<div class="ulist">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p>Note that for IPv6, the first address (<code>x::</code>) in a subnet <strong>may</strong> or <strong>may not</strong> be assignable/"usable". If it is assigned to a device, that device <strong>must</strong> be a router for anycast. See <a href="https://datatracker.ietf.org/doc/html/rfc4291#section-2.6.1" target="_blank" rel="noopener">RFC 4291 § 2.6.1</a> for details. In the interest of convenience, <code>subnetter</code> will report this address as <strong>not usable/addressable</strong> in ranges for this reason as it is technically not a "host" address.</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>Note that for IPv6, some subnetting calculators erroneously report the last address as usable. They are reserved in strictly RFC-compliant networks for anycast reasons (per <a href="https://datatracker.ietf.org/doc/html/rfc2526" target="_blank" rel="noopener">RFC 2526</a>). Subnetter follows RFC as closely as possible, and any deviation from RFC is considered a bug — as such, the last address of IPv6 subnets is considered <strong>not usable/addressable</strong>.</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>There are additional restrictions for /64 subnets, but they fall earlier in the range. These are <strong>not explicitly excluded</strong> in the usable host range, nor are they excluded from the total host count.</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>Private networks (<a href="https://datatracker.ietf.org/doc/html/rfc1918" target="_blank" rel="noopener">RFC 1918</a>), ULA prefixes (<a href="https://datatracker.ietf.org/doc/html/rfc4193" target="_blank" rel="noopener">RFC 4193</a>), and documentation prefixes (<a href="https://datatracker.ietf.org/doc/html/rfc3849" target="_blank" rel="noopener">RFC 3849</a>, <a href="https://datatracker.ietf.org/doc/html/rfc5737" target="_blank" rel="noopener">RFC 5737</a>, <a href="https://datatracker.ietf.org/doc/html/rfc9637" target="_blank" rel="noopener">RFC 9637</a>) are treated as "normal" networks (in that it is allowed to subnet them).</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>Various other reserved IPv4 and IPv6 addresses/networks will print warnings with their corresponding RFC(s) (unless <code>-R</code>/<code>--allow-reserved</code> is specified) if they are specified as/included in the initial prefix/network. (<a href="https://datatracker.ietf.org/doc/html/rfc6890" target="_blank" rel="noopener">RFC 6890</a> and its update via <a href="https://datatracker.ietf.org/doc/html/rfc8190" target="_blank" rel="noopener">RFC 8190</a> are useful summaries.) Note that for checking to function, an Internet connection is required as it pulls it directly from IANA live to ensure the data is accurate to standards. This may be cached locally if <code>-c</code>/<code>--cache-reservations</code> is specified, in which case a locally-cached copy will be used if present and populated then used if not.</p>
|
||||||
|
<div class="ulist">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p>The cache directory may be specified by <code>-C</code>/<code>--cache-dir</code> (which can be specifically defaulted via the <code>SBNTR_RSVCACHE_DIR</code> environment variable). If it is not specified, the default (see below) will be used.</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>This directory’s default location determined by the following, and will be created if it doesn’t exist:</p>
|
||||||
|
<div class="ulist">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p>For non-Windows systems (macOS, Linux, etc.)…​</p>
|
||||||
|
<div class="ulist">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p>If <a href="https://specifications.freedesktop.org/basedir-spec/latest/#variables" target="_blank" rel="noopener">the <code>XDG_CACHE_HOME</code> environment variable</a> is present, it will be <code>${XDG_CACHE_HOME}/subnetter/</code>. (If XDG base dirs are enabled, this is usually <code>~/.cache/subnetter/</code> or, explicitly, <code>/home/<username>/.cache/subnetter/</code>)</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>If the <code>XDG_CACHE_HOME</code> environment variable is not present…​</p>
|
||||||
|
<div class="ulist">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p>On macOS, an explicit fallback of <code>~/Library/Caches/subnetter/</code> will be used. (To my knowledge/understanding, this is the standard user cache directory and cannot be changed.) This usually evaluates to <code>/Users/<username>/Library/Caches/subnetter/</code>.</p>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>On all others, an explicit fallback of <code>~/.cache/subnetter</code> will be used.</p>
|
||||||
|
<div class="ulist">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p>On most non-macOS/*NIX-like systems , this is usually <code>/home/<username>/.cache/subetter/</code>, provided normal user homes. On <a href="http://p9f.org/" target="_blank" rel="noopener">Plan9</a> platforms (e.g. <a href="https://9p.io/plan9/index.html" target="_blank" rel="noopener">Plan 9 4th Ed.</a>, <a href="https://9front.org/" target="_blank" rel="noopener">9front</a>, <a href="http://9legacy.org/" target="_blank" rel="noopener">9legacy</a>), the <code>/env/home</code> environment variable (<code>$home</code>) will be used, the <code>./lib/</code> subdirectory under there (which typically/should already exist) will be appended to it, and that appended with <code>./cache/subnetter/</code> (this usually evaluates to <code>/usr/<username>/lib/cache/subnetter/</code>).</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<p>For Windows systems…​</p>
|
||||||
|
<div class="ulist">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<p>If <a href="https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#constants" target="_blank" rel="noopener">the <code>LOCALAPPDATA</code> environment variable</a> is present, it will be <code>%LOCALAPPDATA%\Cache\subnetter\</code> (or <code>${env:LOCALAPPDATA}\Cache\subnetter\</code> in Powershell syntax). This usually evaluates to <code>C:\Users\<username>\AppData\Local\Cache\subnetter\</code>.</p>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sect1">
|
||||||
|
<h2 id="ref"><a class="link" href="#ref">3. References</a></h2>
|
||||||
|
<div class="sectionbody">
|
||||||
|
<div class="admonitionblock tip">
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td class="icon">
|
||||||
|
<div class="title">Tip</div>
|
||||||
|
</td>
|
||||||
|
<td class="content">
|
||||||
|
<div class="paragraph">
|
||||||
|
<p>See also the <a href="#ack">Acknowledgements</a> section for specific material used directly.</p>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="paragraph">
|
||||||
|
<p>This program in general draws inspiration from <code>ipcalc</code> (<a href="http://jodies.de/ipcalc" target="_blank" rel="noopener">0</a>, <a href="https://github.com/kjokjo/ipcalc" target="_blank" rel="noopener">1</a>, <a href="https://gitlab.com/ipcalc/ipcalc" target="_blank" rel="noopener">2</a>) and <a href="http://www.routemeister.net/projects/sipcalc/" target="_blank" rel="noopener"><code>sipcalc</code></a>.</p>
|
||||||
|
</div>
|
||||||
|
<div class="paragraph">
|
||||||
|
<p>The <code>table</code> subcommand is inspired by <code>iptab</code> from <a href="https://metacpan.org/pod/Net::IP" target="_blank" rel="noopener">Perl Net-IP</a>.</p>
|
||||||
|
</div>
|
||||||
|
<div class="paragraph">
|
||||||
|
<p>Additional notes for certain contexts are primarily taken from <a href="https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing" target="_blank" rel="noopener">the Wikipedia article on <em>Classless Inter-Domain Routing</em></a> (as of <em>Jan 28, 2025</em>).</p>
|
||||||
|
</div>
|
||||||
|
<div class="paragraph">
|
||||||
|
<p>Reservations are pulled/cached directly from the IANA registries (<a href="https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml" target="_blank" rel="noopener">IPv4</a>, <a href="https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml" target="_blank" rel="noopener">IPv6</a>).</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="sect1">
|
||||||
|
<h2 id="ack"><a class="link" href="#ack">4. Acknowledgements</a></h2>
|
||||||
|
<div class="sectionbody">
|
||||||
|
<div class="sect2">
|
||||||
|
<h3 id="ack_segrefdiag"><a class="link" href="#ack_segrefdiag">4.1. IPv6 Segment Reference Diagram</a></h3>
|
||||||
|
<div class="paragraph">
|
||||||
|
<p>The <em>IPv6 Segment Reference Diagram</em> default output as rendered from the <code>table</code> subcommand is generally from <a href="https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing" class="bare">https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing</a> as fetched on April 07, 2025.</p>
|
||||||
|
</div>
|
||||||
|
<div class="paragraph">
|
||||||
|
<p>It is licensed under <a href="https://creativecommons.org/licenses/by-sa/4.0/" target="_blank" rel="noopener">Creative Commons CC BY-SA 4.0</a> (<a href="https://creativecommons.org/licenses/by-sa/4.0/legalcode.en" target="_blank" rel="noopener">full license</a>).</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="footer">
|
||||||
|
<div id="footer-text">
|
||||||
|
Last updated 2025-11-08 22:54:28 -0500
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
10
TODO
10
TODO
@ -1,7 +1,13 @@
|
|||||||
- add table rendering for reserved networks?
|
- add table rendering for reserved networks
|
||||||
|
-- note that the IANA doesn't seem to include all? e.g. ff02:: etc.
|
||||||
|
-- ... that's because it's in a different registry:
|
||||||
|
https://www.iana.org/assignments/ipv6-multicast-addresses/ipv6-multicast-addresses.xhtml
|
||||||
|
https://www.iana.org/assignments/multicast-addresses/multicast-addresses.xhtml
|
||||||
|
see https://www.iana.org/numbers "IP Address Allocations" section
|
||||||
|
|
||||||
- when checking/rendering reserved networks, currently the footnotes aren't returned.
|
- when checking/rendering reserved networks, currently the footnotes aren't returned.
|
||||||
-- netsplit.IANARegistryFootnote
|
-- netsplit.IANARegistryFootnote
|
||||||
-- encapsulated in the IANARegistry.Footnotes
|
-- encapsulated in the IANARegistry.Footnotes
|
||||||
|
|
||||||
- add new interface, Getter? different formatting?
|
- add new interface, Getter? different formatting?
|
||||||
|
-- (i forget what this was for. carving a smaller subnet out of a subnet?)
|
||||||
|
|||||||
@ -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)."`
|
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."`
|
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."`
|
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."`
|
AllowReserved bool `short:"R" long:"allow-reserved" description:"If specified, do not warn about reserved IP addresses/networks."`
|
||||||
reservedArgs
|
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."`
|
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."`
|
||||||
|
|||||||
@ -104,6 +104,8 @@ func printMask(label string, pfx netip.Prefix, verb, indent int, indentStr strin
|
|||||||
var mask net.IPMask
|
var mask net.IPMask
|
||||||
var first netip.Addr
|
var first netip.Addr
|
||||||
var last netip.Addr
|
var last netip.Addr
|
||||||
|
var firstUsable netip.Addr
|
||||||
|
var lastUsable netip.Addr
|
||||||
var sb = new(strings.Builder)
|
var sb = new(strings.Builder)
|
||||||
var pre = strings.Repeat(indentStr, indent)
|
var pre = strings.Repeat(indentStr, indent)
|
||||||
var pre2 = strings.Repeat(indentStr, indent+1)
|
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"
|
maskF = "d"
|
||||||
maskSep = "."
|
maskSep = "."
|
||||||
maskEvery = 1
|
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() {
|
switch pfx.Bits() {
|
||||||
case 32: // Host
|
case 32: // Host
|
||||||
first = pfx.Masked().Addr()
|
first = pfx.Masked().Addr()
|
||||||
last = pfx.Masked().Addr()
|
last = pfx.Masked().Addr()
|
||||||
|
firstUsable = first
|
||||||
|
lastUsable = last
|
||||||
case 31: // Point-to-Point
|
case 31: // Point-to-Point
|
||||||
first = pfx.Masked().Addr()
|
first = pfx.Masked().Addr()
|
||||||
last = pfx.Masked().Addr().Next()
|
last = pfx.Masked().Addr().Next()
|
||||||
|
firstUsable = first
|
||||||
|
lastUsable = last
|
||||||
default: // RFC 919, RFC 5735
|
default: // RFC 919, RFC 5735
|
||||||
first = pfx.Masked().Addr().Next()
|
first = pfx.Masked().Addr()
|
||||||
last = netipx.PrefixLastIP(pfx.Masked()).Prev()
|
last = netipx.PrefixLastIP(pfx.Masked())
|
||||||
|
firstUsable = first.Next()
|
||||||
|
lastUsable = last.Prev()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
maskF = "02x"
|
maskF = "02x"
|
||||||
@ -138,16 +146,24 @@ func printMask(label string, pfx netip.Prefix, verb, indent int, indentStr strin
|
|||||||
case 128: // Host/Loopback
|
case 128: // Host/Loopback
|
||||||
first = pfx.Masked().Addr()
|
first = pfx.Masked().Addr()
|
||||||
last = pfx.Masked().Addr()
|
last = pfx.Masked().Addr()
|
||||||
|
firstUsable = first
|
||||||
|
lastUsable = last
|
||||||
case 127: // Point-to-Point
|
case 127: // Point-to-Point
|
||||||
first = pfx.Masked().Addr()
|
first = pfx.Masked().Addr()
|
||||||
last = pfx.Masked().Addr().Next()
|
last = pfx.Masked().Addr().Next()
|
||||||
|
firstUsable = first
|
||||||
|
lastUsable = last
|
||||||
case 64:
|
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.
|
// 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:
|
default:
|
||||||
first = pfx.Masked().Addr()
|
first = pfx.Masked().Addr()
|
||||||
|
firstUsable = first
|
||||||
last = netipx.PrefixLastIP(pfx.Masked())
|
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, "%sBits:\t\t%d\n", pre2, pfx.Bits())
|
||||||
fmt.Fprintf(sb, "%sFirst:\t\t%s\n", pre2, first.String())
|
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, "%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, "%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))
|
fmt.Fprintf(sb, "%sHosts:\t\t%d\n", pre2, netsplit.NumAddrsPfx(pfx.Masked(), false, false))
|
||||||
if verb >= 2 {
|
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) {
|
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 b []byte
|
||||||
|
var resIdx int
|
||||||
var netsLen uint
|
var netsLen uint
|
||||||
var remLen uint
|
var remLen uint
|
||||||
var buf *bytes.Buffer
|
var buf *bytes.Buffer
|
||||||
var masked netip.Prefix
|
var masked netip.Prefix
|
||||||
var remPfxs []*netip.Prefix
|
var remPfxs []*netip.Prefix
|
||||||
var invertedMask net.IPMask
|
var invertedMask net.IPMask
|
||||||
var resIdx int
|
|
||||||
var resPfx netip.Prefix
|
var resPfx netip.Prefix
|
||||||
var resRec *netsplit.IANAAddrNetResRecord
|
var resRec *netsplit.IANAAddrNetResRecord
|
||||||
var reservedList []*netip.Prefix
|
var reservedList []*netip.Prefix
|
||||||
var reserved map[netip.Prefix]*netsplit.IANAAddrNetResRecord
|
var reserved map[netip.Prefix]*netsplit.IANAAddrNetResRecord
|
||||||
var res *netsplit.StructuredResults
|
var res *netsplit.StructuredResults
|
||||||
var verb = -1
|
|
||||||
var fmts []string
|
var fmts []string
|
||||||
var sectSep1 string
|
var sectSep1 string
|
||||||
var sectSep2 string
|
var sectSep2 string
|
||||||
// var sectSep3 string
|
// var sectSep3 string
|
||||||
|
var verb int = 1
|
||||||
|
|
||||||
if orig == nil {
|
if orig == nil {
|
||||||
return
|
return
|
||||||
@ -245,11 +263,14 @@ func printNets(orig *netip.Prefix, origNet *net.IPNet, nets []*netip.Prefix, rem
|
|||||||
sectSep2 = fmts[1]
|
sectSep2 = fmts[1]
|
||||||
// sectSep3 = fmts[2]
|
// sectSep3 = fmts[2]
|
||||||
|
|
||||||
if args.Verbose != nil {
|
if args.Quiet {
|
||||||
verb = 0
|
verb--
|
||||||
for _, i := range args.Verbose {
|
} else {
|
||||||
if i {
|
if args.Verbose != nil {
|
||||||
verb++
|
for _, i := range args.Verbose {
|
||||||
|
if i {
|
||||||
|
verb++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
24
go.mod
24
go.mod
@ -1,29 +1,29 @@
|
|||||||
module r00t2.io/subnetter
|
module r00t2.io/subnetter
|
||||||
|
|
||||||
go 1.24.0
|
go 1.24.5
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/TwiN/go-color v1.4.1
|
github.com/TwiN/go-color v1.4.1
|
||||||
github.com/go-playground/validator/v10 v10.25.0
|
github.com/go-playground/validator/v10 v10.28.0
|
||||||
github.com/go-resty/resty/v2 v2.16.5
|
github.com/go-resty/resty/v2 v2.16.5
|
||||||
github.com/goccy/go-yaml v1.15.23
|
github.com/goccy/go-yaml v1.18.0
|
||||||
github.com/jessevdk/go-flags v1.6.1
|
github.com/jessevdk/go-flags v1.6.1
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba
|
||||||
golang.org/x/mod v0.24.0
|
golang.org/x/mod v0.29.0
|
||||||
r00t2.io/goutils v1.8.1
|
r00t2.io/goutils v1.10.3
|
||||||
r00t2.io/sysutils v1.12.0
|
r00t2.io/sysutils v1.15.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/djherbis/times v1.6.0 // indirect
|
github.com/djherbis/times v1.6.0 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.11 // indirect
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/stretchr/testify v1.9.0 // indirect
|
github.com/stretchr/testify v1.9.0 // indirect
|
||||||
golang.org/x/crypto v0.36.0 // indirect
|
golang.org/x/crypto v0.43.0 // indirect
|
||||||
golang.org/x/net v0.37.0 // indirect
|
golang.org/x/net v0.46.0 // indirect
|
||||||
golang.org/x/sync v0.12.0 // indirect
|
golang.org/x/sync v0.18.0 // indirect
|
||||||
golang.org/x/sys v0.31.0 // indirect
|
golang.org/x/sys v0.38.0 // indirect
|
||||||
golang.org/x/text v0.23.0 // indirect
|
golang.org/x/text v0.30.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
22
go.sum
22
go.sum
@ -7,6 +7,8 @@ github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c=
|
|||||||
github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0=
|
github.com/djherbis/times v1.6.0/go.mod h1:gOHeRAz2h+VJNZ5Gmc/o7iD9k4wW7NMVqieYCY99oc0=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.11 h1:AQvxbp830wPhHTqc1u7nzoLT+ZFxGY7emj5DR5DYFik=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.11/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
@ -15,10 +17,14 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
|
|||||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8=
|
github.com/go-playground/validator/v10 v10.25.0 h1:5Dh7cjvzR7BRZadnsVOzPhWsrwUr0nmsZJxEAnFLNO8=
|
||||||
github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
|
github.com/go-playground/validator/v10 v10.25.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
|
||||||
|
github.com/go-playground/validator/v10 v10.28.0 h1:Q7ibns33JjyW48gHkuFT91qX48KG0ktULL6FgHdG688=
|
||||||
|
github.com/go-playground/validator/v10 v10.28.0/go.mod h1:GoI6I1SjPBh9p7ykNE/yj3fFYbyDOpwMn5KXd+m2hUU=
|
||||||
github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM=
|
github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM=
|
||||||
github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA=
|
github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA=
|
||||||
github.com/goccy/go-yaml v1.15.23 h1:WS0GAX1uNPDLUvLkNU2vXq6oTnsmfVFocjQ/4qA48qo=
|
github.com/goccy/go-yaml v1.15.23 h1:WS0GAX1uNPDLUvLkNU2vXq6oTnsmfVFocjQ/4qA48qo=
|
||||||
github.com/goccy/go-yaml v1.15.23/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
github.com/goccy/go-yaml v1.15.23/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||||
|
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
|
||||||
|
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4=
|
github.com/jessevdk/go-flags v1.6.1 h1:Cvu5U8UGrLay1rZfv/zP7iLpSHGUZ/Ou68T0iX1bBK4=
|
||||||
github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc=
|
github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPGBnNLMooyc=
|
||||||
@ -32,24 +38,40 @@ go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBs
|
|||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||||
|
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04=
|
||||||
|
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0=
|
||||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||||
|
golang.org/x/mod v0.29.0 h1:HV8lRxZC4l2cr3Zq1LvtOsi/ThTgWnUk/y64QSs8GwA=
|
||||||
|
golang.org/x/mod v0.29.0/go.mod h1:NyhrlYXJ2H4eJiRy/WDBO6HMqZQ6q9nk4JzS3NuCK+w=
|
||||||
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
||||||
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||||
|
golang.org/x/net v0.46.0 h1:giFlY12I07fugqwPuWJi68oOnpfqFnJIJzaIIm2JVV4=
|
||||||
|
golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210=
|
||||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
|
golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I=
|
||||||
|
golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
|
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
|
||||||
|
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||||
|
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
|
||||||
|
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
|
||||||
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
|
||||||
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
r00t2.io/goutils v1.8.1 h1:TQcUycPKsYn0QI4uCqb56utmvu/vVSxlblBg98iXStg=
|
r00t2.io/goutils v1.8.1 h1:TQcUycPKsYn0QI4uCqb56utmvu/vVSxlblBg98iXStg=
|
||||||
r00t2.io/goutils v1.8.1/go.mod h1:9ObJI9S71wDLTOahwoOPs19DhZVYrOh4LEHmQ8SW4Lk=
|
r00t2.io/goutils v1.8.1/go.mod h1:9ObJI9S71wDLTOahwoOPs19DhZVYrOh4LEHmQ8SW4Lk=
|
||||||
|
r00t2.io/goutils v1.10.3 h1:GmEtsM/nrrVWooYJllXDRsgInobEinv2dn5ccU4zGAA=
|
||||||
|
r00t2.io/goutils v1.10.3/go.mod h1:76AxpXUeL10uFklxRB11kQsrtj2AKiNm8AwG1bNoBCA=
|
||||||
r00t2.io/sysutils v1.1.1/go.mod h1:Wlfi1rrJpoKBOjWiYM9rw2FaiZqraD6VpXyiHgoDo/o=
|
r00t2.io/sysutils v1.1.1/go.mod h1:Wlfi1rrJpoKBOjWiYM9rw2FaiZqraD6VpXyiHgoDo/o=
|
||||||
r00t2.io/sysutils v1.12.0 h1:Ce3qUOyLixE1ZtFT/+SVwOT5kSkzg5+l1VloGeGugrU=
|
r00t2.io/sysutils v1.12.0 h1:Ce3qUOyLixE1ZtFT/+SVwOT5kSkzg5+l1VloGeGugrU=
|
||||||
r00t2.io/sysutils v1.12.0/go.mod h1:bNTKNBk9MnUhj9coG9JBNicSi5FrtJHEM645um85pyw=
|
r00t2.io/sysutils v1.12.0/go.mod h1:bNTKNBk9MnUhj9coG9JBNicSi5FrtJHEM645um85pyw=
|
||||||
|
r00t2.io/sysutils v1.15.0 h1:FSnREfbXDhBQEO7LMpnRQeKlPshozxk9XHw3YgWRgRg=
|
||||||
|
r00t2.io/sysutils v1.15.0/go.mod h1:28qB0074EIRQ8Sy/ybaA5jC3qA32iW2aYLkMCRhyAFM=
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user