Documentation
¶
Overview ¶
Package iprange is an extension to net/netip.
An additional type IPRange is defined and the most useful methods for it.
For more advanced functionality IPRange implements the interval.Interface for fast lookups.
see also: https://github.com/gaissmai/interval
Index ¶
- func Compare(a, b IPRange) (ll int, rr int, lr int, rl int)
- type IPRange
- func (r IPRange) Addrs() (first, last netip.Addr)
- func (r IPRange) CompareLower(r2 IPRange) intdeprecated
- func (r IPRange) CompareUpper(r2 IPRange) intdeprecated
- func (r IPRange) IsValid() bool
- func (r IPRange) MarshalBinary() ([]byte, error)
- func (r IPRange) MarshalText() ([]byte, error)
- func (r IPRange) Prefix() (prefix netip.Prefix, ok bool)
- func (r IPRange) Prefixes() []netip.Prefix
- func (r IPRange) PrefixesAppend(dst []netip.Prefix) []netip.Prefix
- func (r IPRange) Remove(in []IPRange) (out []IPRange)
- func (r IPRange) String() string
- func (r *IPRange) UnmarshalBinary(data []byte) error
- func (r *IPRange) UnmarshalText(text []byte) error
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type IPRange ¶
type IPRange struct {
// contains filtered or unexported fields
}
IPRange represents an inclusive range of IP addresses from the same address family.
10.0.0.3-10.0.17.134 // range 2001:db8::1-2001:db8::f6 // range 192.168.0.1/24 // Prefix aka CIDR ::1/128 // Prefix aka CIDR
Not all IP address ranges in the wild are CIDRs, very often you have to deal with ranges not representable as a prefix.
This library handels IP ranges and CIDRs transparently.
func FromAddrs ¶ added in v0.5.0
FromAddrs returns an IPRange from the provided IP addresses.
IP addresses with zones are not allowed.
func FromPrefix ¶ added in v0.5.0
FromPrefix returns an IPRange from the standard library's netip.Prefix type.
func FromString ¶ added in v0.4.0
FromString parses the input string and returns an IPRange.
Returns an error on invalid input.
Valid strings are of the form:
192.168.2.3-192.168.7.255 2001:db8::1-2001:db8::ff00:35 2001:db8:dead::/38 10.0.0.0/8 4.4.4.4 ::0
Single IP addresses as input are converted to /32 or /128 ranges.
The hard part is done by netip.ParseAddr and netip.ParsePrefix from the stdlib.
Example ¶
package main
import (
"fmt"
"github.com/gaissmai/iprange"
)
func isPrefix(p iprange.IPRange) bool {
_, ok := p.Prefix()
return ok
}
func main() {
for _, s := range []string{
"fe80::1-fe80::2", // as range
"10.0.0.0-11.255.255.255", // as range but true CIDR, see output
"", // invalid
} {
r, _ := iprange.FromString(s)
fmt.Printf("%-20s isPrefix: %5v\n", r, isPrefix(r))
}
}
Output: fe80::1-fe80::2 isPrefix: false 10.0.0.0/7 isPrefix: true invalid IPRange isPrefix: false
func Merge ¶
Merge adjacent and overlapping IPRanges.
Skip dups and subsets and invalid ranges, returns the remaining IPRanges sorted.
Example ¶
package main
import (
"fmt"
"github.com/gaissmai/iprange"
)
func main() {
var rs []iprange.IPRange
for _, s := range []string{
"10.0.0.0/32",
"10.0.0.1/32",
"10.0.0.4/30",
"10.0.0.6-10.0.0.99",
"fe80::/12",
"fe80:0000:0000:0000:fe2d:5eff:fef0:fc64/128",
"fe80::/10",
} {
r, _ := iprange.FromString(s)
rs = append(rs, r)
}
merged := iprange.Merge(rs)
fmt.Printf("%v\n", merged)
}
Output: [10.0.0.0/31 10.0.0.4-10.0.0.99 fe80::/10]
func (IPRange) Addrs ¶
Addrs returns the first and last IP address of the IPRange.
Example ¶
package main
import (
"fmt"
"github.com/gaissmai/iprange"
)
func mustParse(s string) iprange.IPRange {
r, err := iprange.FromString(s)
if err != nil {
panic(err)
}
return r
}
func main() {
first, last := mustParse("fe80::/10").Addrs()
fmt.Printf("Addrs() fe80::/10\n")
fmt.Printf("first: %s\n", first)
fmt.Printf("last: %s\n", last)
}
Output: Addrs() fe80::/10 first: fe80:: last: febf:ffff:ffff:ffff:ffff:ffff:ffff:ffff
func (IPRange) CompareLower
deprecated
func (IPRange) CompareUpper
deprecated
func (IPRange) MarshalBinary ¶
MarshalBinary implements the encoding.BinaryMarshaler interface.
func (IPRange) MarshalText ¶
MarshalText implements the encoding.TextMarshaler interface, The encoding is the same as returned by String, with one exception: If r is the zero IPRange, the encoding is the empty string.
func (IPRange) Prefix ¶
Prefix returns r as a netip.Prefix, if it can be presented exactly as such. If r is not valid or is not exactly equal to one prefix, ok is false.
func (IPRange) Prefixes ¶
Prefixes returns the slice of netip.Prefix entries that covers r.
If r is invalid Prefixes returns nil.
Prefixes necessarily allocates. See PrefixesAppend for a version that uses memory you provide.
Example ¶
package main
import (
"fmt"
"github.com/gaissmai/iprange"
)
func main() {
r, _ := iprange.FromString("10.0.0.6-10.0.0.99")
fmt.Printf("%s -> Prefixes:\n", r)
for _, p := range r.Prefixes() {
fmt.Println(p)
}
fmt.Println()
r, _ = iprange.FromString("2001:db8::affe-2001:db8::ffff")
fmt.Printf("%s -> Prefixes:\n", r)
for _, p := range r.Prefixes() {
fmt.Println(p)
}
}
Output: 10.0.0.6-10.0.0.99 -> Prefixes: 10.0.0.6/31 10.0.0.8/29 10.0.0.16/28 10.0.0.32/27 10.0.0.64/27 10.0.0.96/30 2001:db8::affe-2001:db8::ffff -> Prefixes: 2001:db8::affe/127 2001:db8::b000/116 2001:db8::c000/114
func (IPRange) PrefixesAppend ¶
PrefixesAppend is the append version of Prefixes.
It appends to dst the netip.Prefix entries that covers r.
func (IPRange) Remove ¶
Remove the slice of IPRanges from r, returns the remaining IPRanges.
Example (V4) ¶
package main
import (
"fmt"
"github.com/gaissmai/iprange"
)
func mustParse(s string) iprange.IPRange {
r, err := iprange.FromString(s)
if err != nil {
panic(err)
}
return r
}
func main() {
outer, _ := iprange.FromString("192.168.2.0/24")
inner := []iprange.IPRange{
mustParse("192.168.2.0/26"),
mustParse("192.168.2.240-192.168.2.249"),
}
fmt.Printf("outer: %v\n", outer)
fmt.Printf("inner: %v\n", inner)
fmt.Println("Result:")
for _, r := range outer.Remove(inner) {
fmt.Println(r)
}
}
Output: outer: 192.168.2.0/24 inner: [192.168.2.0/26 192.168.2.240-192.168.2.249] Result: 192.168.2.64-192.168.2.239 192.168.2.250-192.168.2.255
Example (V6) ¶
package main
import (
"fmt"
"github.com/gaissmai/iprange"
)
func mustParse(s string) iprange.IPRange {
r, err := iprange.FromString(s)
if err != nil {
panic(err)
}
return r
}
func main() {
outer, _ := iprange.FromString("2001:db8:de00::/40")
inner := []iprange.IPRange{mustParse("2001:db8:dea0::/44")}
fmt.Printf("outer: %v\n", outer)
fmt.Printf("inner: %v\n", inner)
fmt.Println("Result:")
for _, r := range outer.Remove(inner) {
fmt.Println(r)
}
}
Output: outer: 2001:db8:de00::/40 inner: [2001:db8:dea0::/44] Result: 2001:db8:de00::-2001:db8:de9f:ffff:ffff:ffff:ffff:ffff 2001:db8:deb0::-2001:db8:deff:ffff:ffff:ffff:ffff:ffff
func (IPRange) String ¶
String returns the string form of the IPRange.
"127.0.0.1-127.0.0.19" "2001:db8::/32"
func (*IPRange) UnmarshalBinary ¶
UnmarshalBinary implements the encoding.BinaryUnmarshaler interface. It expects data in the form generated by MarshalBinary.
func (*IPRange) UnmarshalText ¶
UnmarshalText implements the encoding.TextUnmarshaler interface. The IPRange is expected in a form accepted by FromString.
If text is empty, UnmarshalText sets *r to the zero IPRange and returns no error.