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.