Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c05f9c4d47
|
||
|
|
4ab83c9069
|
8
ACKNOWLEDGEMENTS
Normal file
8
ACKNOWLEDGEMENTS
Normal file
@@ -0,0 +1,8 @@
|
||||
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)
|
||||
@@ -5,7 +5,7 @@
|
||||
{{- if $opts.Plain }}
|
||||
IPV4:
|
||||
{{- else }}
|
||||
{{- bold "IPv4:"}}
|
||||
{{- bold "IPv4:" }}
|
||||
{{- end }}
|
||||
{{- if $opts.Legacy }}
|
||||
{{- if $opts.Plain }}
|
||||
@@ -47,13 +47,268 @@ IPV4:
|
||||
{{- end }}
|
||||
|
||||
{{- if not $opts.NoIpv6 }}
|
||||
|
||||
{{- if $opts.Plain }}
|
||||
IPV6:
|
||||
{{- else }}
|
||||
{{ bold "IPv6:"}}
|
||||
{{- end }}
|
||||
{{- if $opts.Plain }}
|
||||
IPV6:
|
||||
{{- else }}
|
||||
{{ bold "IPv6:"}}
|
||||
{{- end }}
|
||||
{{- if not $opts.NoIpv6Seg }}
|
||||
{{- if $opts.Plain }}
|
||||
IPv6 Segment Reference Diagram:
|
||||
{{- if $opts.VertSeg }}
|
||||
|
||||
Example: 2001:0db8:0123:4567:89ab:cdef:1234:5678
|
||||
{{- if not $opts.VertInvert }}
|
||||
2 4
|
||||
0 8
|
||||
0 12
|
||||
1 16
|
||||
:
|
||||
0 20
|
||||
d 24
|
||||
b 28
|
||||
8 32
|
||||
:
|
||||
0 36
|
||||
1 40
|
||||
2 44
|
||||
3 48
|
||||
:
|
||||
4 52
|
||||
5 56
|
||||
6 60
|
||||
7 64
|
||||
:
|
||||
8 68
|
||||
9 72
|
||||
a 76
|
||||
b 80
|
||||
:
|
||||
c 84
|
||||
d 88
|
||||
e 92
|
||||
f 96
|
||||
:
|
||||
1 100
|
||||
2 104
|
||||
3 108
|
||||
4 112
|
||||
:
|
||||
5 116
|
||||
6 120
|
||||
7 124
|
||||
8 127 or 128
|
||||
{{- else }}
|
||||
4 ____ 2
|
||||
8 ____ 0
|
||||
12 ___ 0
|
||||
16 ___ 1
|
||||
___ :
|
||||
20 _____ 0
|
||||
24 _____ d
|
||||
28 _____ b
|
||||
32 _____ 8
|
||||
_____ :
|
||||
36 _______ 0
|
||||
40 _______ 1
|
||||
44 _______ 2
|
||||
48 _______ 3
|
||||
_______ :
|
||||
52 _________ 4
|
||||
56 _________ 5
|
||||
60 _________ 6
|
||||
64 _________ 7
|
||||
_________ :
|
||||
68 ___________ 8
|
||||
72 ___________ 9
|
||||
76 ___________ a
|
||||
80 ___________ b
|
||||
___________ :
|
||||
84 _____________ c
|
||||
88 _____________ d
|
||||
92 _____________ e
|
||||
96 _____________ f
|
||||
_____________ :
|
||||
100 ______________ 1
|
||||
104 ______________ 2
|
||||
108 ______________ 3
|
||||
112 ______________ 4
|
||||
______________ :
|
||||
116 ________________ 5
|
||||
120 ________________ 6
|
||||
124 ________________ 7
|
||||
127 ________________ (8)
|
||||
128 ________________ (8)
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
|
||||
2001:0db8:0123:4567:89ab:cdef:1234:5678
|
||||
|||| |||| |||| |||| |||| |||| |||| ||||
|
||||
|||| |||| |||| |||| |||| |||| |||| |||128
|
||||
|||| |||| |||| |||| |||| |||| |||| |||127
|
||||
|||| |||| |||| |||| |||| |||| |||| ||124
|
||||
|||| |||| |||| |||| |||| |||| |||| |120
|
||||
|||| |||| |||| |||| |||| |||| |||| 116
|
||||
|||| |||| |||| |||| |||| |||| |||112
|
||||
|||| |||| |||| |||| |||| |||| ||108
|
||||
|||| |||| |||| |||| |||| |||| |104
|
||||
|||| |||| |||| |||| |||| |||| 100
|
||||
|||| |||| |||| |||| |||| |||96
|
||||
|||| |||| |||| |||| |||| ||92
|
||||
|||| |||| |||| |||| |||| |88
|
||||
|||| |||| |||| |||| |||| 84
|
||||
|||| |||| |||| |||| |||80
|
||||
|||| |||| |||| |||| ||76
|
||||
|||| |||| |||| |||| |72
|
||||
|||| |||| |||| |||| 68
|
||||
|||| |||| |||| |||64
|
||||
|||| |||| |||| ||60
|
||||
|||| |||| |||| |56
|
||||
|||| |||| |||| 52
|
||||
|||| |||| |||48
|
||||
|||| |||| ||44
|
||||
|||| |||| |40
|
||||
|||| |||| 36
|
||||
|||| |||32
|
||||
|||| ||28
|
||||
|||| |24
|
||||
|||| 20
|
||||
|||16
|
||||
||12
|
||||
|8
|
||||
4
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{ bold "IPv6 Segment Reference Diagram:" }}
|
||||
{{- if $opts.VertSeg }}
|
||||
|
||||
{{ bold "Example:"}} 2001:0db8:0123:4567:89ab:cdef:1234:5678
|
||||
{{- if not $opts.VertInvert }}
|
||||
2 4
|
||||
0 8
|
||||
0 12
|
||||
1 16
|
||||
:
|
||||
0 20
|
||||
d 24
|
||||
b 28
|
||||
8 32
|
||||
:
|
||||
0 36
|
||||
1 40
|
||||
2 44
|
||||
3 48
|
||||
:
|
||||
4 52
|
||||
5 56
|
||||
6 60
|
||||
7 64
|
||||
:
|
||||
8 68
|
||||
9 72
|
||||
a 76
|
||||
b 80
|
||||
:
|
||||
c 84
|
||||
d 88
|
||||
e 92
|
||||
f 96
|
||||
:
|
||||
1 100
|
||||
2 104
|
||||
3 108
|
||||
4 112
|
||||
:
|
||||
5 116
|
||||
6 120
|
||||
7 124
|
||||
8 127 or 128
|
||||
{{- else }}
|
||||
4 ━━━━ 2
|
||||
8 ━━━━ 0
|
||||
12 ━━━ 0
|
||||
16 ━━━ 1
|
||||
━━━ :
|
||||
20 ━━━━━ 0
|
||||
24 ━━━━━ d
|
||||
28 ━━━━━ b
|
||||
32 ━━━━━ 8
|
||||
━━━━━ :
|
||||
36 ━━━━━━━ 0
|
||||
40 ━━━━━━━ 1
|
||||
44 ━━━━━━━ 2
|
||||
48 ━━━━━━━ 3
|
||||
━━━━━━━ :
|
||||
52 ━━━━━━━━━ 4
|
||||
56 ━━━━━━━━━ 5
|
||||
60 ━━━━━━━━━ 6
|
||||
64 ━━━━━━━━━ 7
|
||||
━━━━━━━━━ :
|
||||
68 ━━━━━━━━━━━ 8
|
||||
72 ━━━━━━━━━━━ 9
|
||||
76 ━━━━━━━━━━━ a
|
||||
80 ━━━━━━━━━━━ b
|
||||
━━━━━━━━━━━ :
|
||||
84 ━━━━━━━━━━━━━ c
|
||||
88 ━━━━━━━━━━━━━ d
|
||||
92 ━━━━━━━━━━━━━ e
|
||||
96 ━━━━━━━━━━━━━ f
|
||||
━━━━━━━━━━━━━ :
|
||||
100 ━━━━━━━━━━━━━━ 1
|
||||
104 ━━━━━━━━━━━━━━ 2
|
||||
108 ━━━━━━━━━━━━━━ 3
|
||||
112 ━━━━━━━━━━━━━━ 4
|
||||
━━━━━━━━━━━━━━ :
|
||||
116 ━━━━━━━━━━━━━━━━ 5
|
||||
120 ━━━━━━━━━━━━━━━━ 6
|
||||
124 ━━━━━━━━━━━━━━━━ 7
|
||||
127 ━━━━━━━━━━━━━━━━ (8)
|
||||
128 ━━━━━━━━━━━━━━━━ (8)
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
|
||||
{{ bold "2001:0db8:0123:4567:89ab:cdef:1234:5678" }}
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃128
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃127
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃124
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃120
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ 116
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃112
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃108
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃104
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ 100
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃96
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃92
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃88
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ 84
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃80
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃76
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃72
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃┃ 68
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃┃64
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃┃60
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ ┃56
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃┃ 52
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃┃48
|
||||
┃┃┃┃ ┃┃┃┃ ┃┃44
|
||||
┃┃┃┃ ┃┃┃┃ ┃40
|
||||
┃┃┃┃ ┃┃┃┃ 36
|
||||
┃┃┃┃ ┃┃┃32
|
||||
┃┃┃┃ ┃┃28
|
||||
┃┃┃┃ ┃24
|
||||
┃┃┃┃ 20
|
||||
┃┃┃16
|
||||
┃┃12
|
||||
┃8
|
||||
4
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
|
||||
{{- if $opts.Plain }}
|
||||
|
||||
CIDR:
|
||||
{{- else }}
|
||||
{{ bold "CIDR:" }}
|
||||
|
||||
@@ -77,18 +77,21 @@ type SplitHostArgs struct {
|
||||
}
|
||||
|
||||
type SplitSubnetArgs struct {
|
||||
Strict bool `short:"t" long:"strict" description:"If specified, an error will occur if the number of possible equally-sized subnets is not exactly -n/--num-nets."`
|
||||
Strict bool `short:"t" long:"strict" description:"If specified, an error will occur if the number of subnets is not exactly -n/--num-nets."`
|
||||
NumNets uint `short:"n" long:"num-nets" required:"true" description:"Number of networks." validate:"required"`
|
||||
splitArgs
|
||||
}
|
||||
|
||||
type TableArgs struct {
|
||||
Notes bool `short:"n" long:"notes" description:"Include notes about prefixes (as a separate table)."`
|
||||
Legacy bool `short:"l" long:"legacy" description:"Include legacy/obsolete/deprecated information (as separate table(s))."`
|
||||
Plain bool `short:"p" long:"plain" description:"Show plain table output instead of unicode."`
|
||||
NoV4Mask bool `short:"M" long:"no-mask" description:"Do not include netmasks for IPv4."`
|
||||
NoIpv6 bool `short:"4" long:"ipv4" description:"Only show IPv4 table(s)."`
|
||||
NoIpv4 bool `short:"6" long:"ipv6" description:"Only show IPv6 table(s)."`
|
||||
Notes bool `short:"n" long:"notes" description:"Include notes about prefixes (as a separate table)."`
|
||||
Legacy bool `short:"l" long:"legacy" description:"Include legacy/obsolete/deprecated information (as separate table(s))."`
|
||||
Plain bool `short:"p" long:"plain" description:"Show plain table output instead of unicode."`
|
||||
NoV4Mask bool `short:"M" long:"no-mask" description:"Do not include netmasks for IPv4."`
|
||||
NoIpv6 bool `short:"4" long:"ipv4" description:"Only show IPv4 table(s)."`
|
||||
NoIpv4 bool `short:"6" long:"ipv6" description:"Only show IPv6 table(s)."`
|
||||
NoIpv6Seg bool `short:"D" long:"no-ipv6-seg" description:"Do not show the IPv6 Segment Reference Diagram (ignored if -4/--ipv4 is specified)."`
|
||||
VertSeg bool `short:"V" long:"vert-ipv6-seg" description:"If specified, display the IPv6 Segment Reference Diagram vertically-aligned instead of horizontally."`
|
||||
VertInvert bool `short:"I" long:"vert-invert" description:"When printing a vertical-aligned IPv6 Segment Reference Diagram, flip so the prefix length is on the left. This takes up less width and is recommended for smaller terminals, and may be easier to read in general."`
|
||||
}
|
||||
|
||||
type CheckArgs struct {
|
||||
|
||||
@@ -5,6 +5,7 @@ import "errors"
|
||||
var (
|
||||
ErrBadBoundary error = errors.New("subnet does not align on bit boundary")
|
||||
ErrBadNumHosts error = errors.New("bad number of hosts; cannot split into prefix exactly")
|
||||
ErrBadNumNets error = errors.New("bad number of nets; cannot split into prefix exactly")
|
||||
ErrBadPrefix error = errors.New("prefix is invalid")
|
||||
ErrBadPrefixLen error = errors.New("prefix length exceeds maximum possible for prefix's inet family")
|
||||
ErrBadSplitter error = errors.New("invalid or unknown splitter when containing")
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
package netsplit
|
||||
|
||||
import (
|
||||
`net`
|
||||
`math`
|
||||
"net/netip"
|
||||
|
||||
`github.com/projectdiscovery/mapcidr`
|
||||
"go4.org/netipx"
|
||||
)
|
||||
|
||||
@@ -22,10 +21,7 @@ func (s *SubnetSplitter) Split() (nets []*netip.Prefix, remaining *netipx.IPSet,
|
||||
var ok bool
|
||||
var pfxLen int
|
||||
var base netip.Prefix
|
||||
var sub netip.Prefix
|
||||
var subPtr *netip.Prefix
|
||||
var split []*net.IPNet
|
||||
var ipsb *netipx.IPSetBuilder = new(netipx.IPSetBuilder)
|
||||
var vlsm *VLSMSplitter
|
||||
|
||||
if s == nil || s.BaseSplitter == nil || s.network == nil || s.NumberSubnets == 0 {
|
||||
return
|
||||
@@ -40,65 +36,48 @@ func (s *SubnetSplitter) Split() (nets []*netip.Prefix, remaining *netipx.IPSet,
|
||||
return
|
||||
}
|
||||
|
||||
if split, err = mapcidr.SplitIPNetIntoN(s.network, int(s.NumberSubnets)); err != nil {
|
||||
// Previously, this used (github.com/projectdiscovery/mapcidr).SplitIPNetIntoN.
|
||||
// It no longer does: https://github.com/projectdiscovery/mapcidr/issues/628
|
||||
// I am Noticing.
|
||||
|
||||
// First the number of bits needed is calculated.
|
||||
pfxLen = int(math.Ceil(math.Log2(float64(s.NumberSubnets))))
|
||||
// And this is then added to the original prefix length to get the new prefix size.
|
||||
pfxLen = pfxLen + base.Bits()
|
||||
// I don't know how this would happen, but it'd be bad if it did.
|
||||
if pfxLen < base.Bits() {
|
||||
err = ErrBigPrefix
|
||||
return
|
||||
}
|
||||
// Likewise.
|
||||
if base.Addr().Is6() {
|
||||
ok = pfxLen <= int(maxBitsv6)
|
||||
} else {
|
||||
ok = pfxLen <= int(maxBitsv4)
|
||||
}
|
||||
if !ok {
|
||||
err = ErrBadPrefix
|
||||
return
|
||||
}
|
||||
|
||||
for _, n := range split {
|
||||
if sub, ok = netipx.FromStdIPNet(n); !ok {
|
||||
// We bail early on this error.
|
||||
err = &SplitErr{
|
||||
Wrapped: ErrBadBoundary,
|
||||
Nets: nets,
|
||||
Remaining: remaining,
|
||||
LastSubnet: subPtr,
|
||||
RequestedPrefixLen: 0,
|
||||
}
|
||||
err = ErrBadBoundary
|
||||
return
|
||||
}
|
||||
if sub.String() == base.String() {
|
||||
continue
|
||||
}
|
||||
if pfxLen == 0 {
|
||||
pfxLen = sub.Bits()
|
||||
if nets == nil {
|
||||
nets = make([]*netip.Prefix, 0)
|
||||
}
|
||||
subPtr = new(netip.Prefix)
|
||||
*subPtr = sub
|
||||
nets = append(nets, subPtr)
|
||||
} else {
|
||||
if sub.Bits() != pfxLen {
|
||||
if err == nil {
|
||||
// Return this err but don't return early; wait for the populate.
|
||||
err = &SplitErr{
|
||||
Wrapped: ErrNoNetSpace,
|
||||
Nets: nets,
|
||||
Remaining: remaining,
|
||||
LastSubnet: subPtr,
|
||||
RequestedPrefixLen: uint8(pfxLen),
|
||||
}
|
||||
}
|
||||
ipsb.AddPrefix(sub)
|
||||
} else {
|
||||
subPtr = new(netip.Prefix)
|
||||
*subPtr = sub
|
||||
nets = append(nets, subPtr)
|
||||
}
|
||||
}
|
||||
// We can now VLSM.
|
||||
vlsm = &VLSMSplitter{
|
||||
// Ascenting and Explicit are pointless to set as all defined sizes are the same.
|
||||
Ascending: false,
|
||||
Explicit: false,
|
||||
PrefixLengths: make([]uint8, s.NumberSubnets),
|
||||
BaseSplitter: s.BaseSplitter,
|
||||
}
|
||||
for i := 0; i < int(s.NumberSubnets); i++ {
|
||||
vlsm.PrefixLengths[i] = uint8(pfxLen)
|
||||
}
|
||||
|
||||
if remaining, err = ipsb.IPSet(); err != nil {
|
||||
if nets, remaining, err = vlsm.Split(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if len(nets) < int(s.NumberSubnets) {
|
||||
err = &SplitErr{
|
||||
Wrapped: ErrNoNetSpace,
|
||||
Nets: nets,
|
||||
Remaining: remaining,
|
||||
}
|
||||
if s.Strict && remaining != nil && remaining.Prefixes() != nil && len(remaining.Prefixes()) > 0 {
|
||||
err = ErrBadNumNets
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user