Documentation ¶
Overview ¶
Package inet represents IP-addresses and IP-Blocks as comparable types.
Some missing utility functions in the standard library for IP-addresses and IP-blocks are provided.
This IP representation is comparable and can be sorted very quickly without prior conversions to/from the different IP versions.
The library is mainly intended for fast ACL-lookups and for IP address management (IPAM) in global scope and not for host related systems programming.
So, no IP address zone indices are supported and IPv4-mapped IPv6 addresses are stripped down to plain IPv4 addresses. The information of the prior mapping is discarded.
Blocks are IP-networks or arbitrary IP-ranges, e.g.
192.168.0.1/24 // network ::1/128 // network 10.0.0.3-10.0.17.134 // range 2001:db8::1-2001:db8::f6 // range
Index ¶
- type Block
- func (b Block) Base() IP
- func (b Block) CIDRs() []Block
- func (b Block) Covers(c Block) bool
- func (b Block) Diff(bs []Block) []Block
- func (b Block) Is4() bool
- func (b Block) Is6() bool
- func (b Block) IsCIDR() bool
- func (b Block) IsValid() bool
- func (b Block) Last() IP
- func (b Block) Less(c Block) bool
- func (b Block) String() string
- type IP
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Block ¶
type Block struct {
// contains filtered or unexported fields
}
Block is an IP-network or IP-range, e.g.
192.168.0.1/24 // network, with CIDR mask ::1/128 // network, with CIDR mask 10.0.0.3-10.0.17.134 // range 2001:db8::1-2001:db8::f6 // range
This Block representation is comparable and can be used as key in maps and fast sorted without conversions to/from the different IP versions.
Each Block object only stores two IP addresses, the base and last address of the range or network.
func FromStdIPNet ¶
FromStdIPNet returns an Block from the standard library's IPNet type. If std is invalid, ok is false. If std is invalid, returns Block{} and error.
func Merge ¶
Merge adjacent blocks, remove dups and subsets, returns the remaining blocks sorted.
Example ¶
package main import ( "fmt" "github.com/gaissmai/go-inet/v2/inet" ) func main() { var bs []inet.Block 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", } { b, _ := inet.ParseBlock(s) bs = append(bs, b) } packed := inet.Merge(bs) fmt.Printf("%v\n", packed) }
Output: [10.0.0.0/31 10.0.0.4-10.0.0.99 fe80::/10]
func ParseBlock ¶
ParseBlock parses and returns the input string as type Block.
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
IP addresses as input are converted to /32 or /128 blocks. Returns error and Block{} on invalid input.
The hard part is done by net.ParseIP() and net.ParseCIDR().
Example ¶
package main import ( "fmt" "github.com/gaissmai/go-inet/v2/inet" ) 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 } { a, _ := inet.ParseBlock(s) fmt.Printf("block: %-20s IsValid: %5v, IsCIDR: %5v, Is4: %5v, Is6: %5v\n", a, a.IsValid(), a.IsCIDR(), a.Is4(), a.Is6()) } }
Output: block: fe80::1-fe80::2 IsValid: true, IsCIDR: false, Is4: false, Is6: true block: 10.0.0.0/7 IsValid: true, IsCIDR: true, Is4: true, Is6: false block: invalid Block IsValid: false, IsCIDR: false, Is4: false, Is6: false
func (Block) CIDRs ¶
CIDRs returns a list of CIDRs that span b.
Example ¶
package main import ( "fmt" "github.com/gaissmai/go-inet/v2/inet" ) func main() { b, _ := inet.ParseBlock("10.0.0.6-10.0.0.99") fmt.Printf("%v\n", b.CIDRs()) b, _ = inet.ParseBlock("2001:db8::affe-2001:db8::ffff") fmt.Printf("%v\n", b.CIDRs()) }
Output: [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/127 2001:db8::b000/116 2001:db8::c000/114]
func (Block) Covers ¶
Covers reports whether Block a contains Block b. a and b may NOT coincide. a.Covers(b) returns true when a is a *true* cover of b, a == b must then be false.
a |-----------------| |-----------------| |-----------------| b |------------| |------------| |------------|
func (Block) Diff ¶
Diff the slice of blocks from receiver, returns the remaining blocks.
Example (V4) ¶
package main import ( "fmt" "github.com/gaissmai/go-inet/v2/inet" ) func mustParseBlock(s string) inet.Block { b, err := inet.ParseBlock(s) if err != nil { panic(err) } return b } func main() { outer, _ := inet.ParseBlock("192.168.2.0/24") inner := []inet.Block{ mustParseBlock("192.168.2.0/26"), mustParseBlock("192.168.2.240-192.168.2.249"), } fmt.Printf("%v - %v\ndiff: %v\n", outer, inner, outer.Diff(inner)) }
Output: 192.168.2.0/24 - [192.168.2.0/26 192.168.2.240-192.168.2.249] diff: [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/go-inet/v2/inet" ) func main() { outer, _ := inet.ParseBlock("2001:db8:de00::/40") inner, _ := inet.ParseBlock("2001:db8:dea0::/44") fmt.Printf("%v - %v\ndiff: %v\n", outer, inner, outer.Diff([]inet.Block{inner})) }
Output: 2001:db8:de00::/40 - 2001:db8:dea0::/44 diff: [2001:db8:de00::-2001:db8:de9f:ffff:ffff:ffff:ffff:ffff 2001:db8:deb0::-2001:db8:deff:ffff:ffff:ffff:ffff:ffff]
func (Block) IsValid ¶
IsValid reports whether block is valid and not the zero value of the Block type. The zero value is not a valid Block of any type.
func (Block) Less ¶
Less reports whether the block a should be sorted before b. REMEMBER: sort supersets always to the left of their subsets! If b.Covers(c) is true then b.Less(c) must also be true.
b |---| c |------| b |-------| c |------------| b |-----------------| c |----------| b |-----------------| c |------------|
Example ¶
package main import ( "fmt" "sort" "github.com/gaissmai/go-inet/v2/inet" ) func main() { var buf []inet.Block for _, s := range []string{ "2001:db8:dead:beef::/44", "10.0.0.0/9", "::/0", "10.96.0.2-10.96.1.17", "0.0.0.0/0", "::-::ffff", "2001:db8::/32", } { b, _ := inet.ParseBlock(s) buf = append(buf, b) } sort.Slice(buf, func(i, j int) bool { return buf[i].Less(buf[j]) }) fmt.Printf("%v\n", buf) }
Output: [0.0.0.0/0 10.0.0.0/9 10.96.0.2-10.96.1.17 ::/0 ::/112 2001:db8::/32 2001:db8:dea0::/44]
type IP ¶
type IP struct {
// contains filtered or unexported fields
}
IP represents a single IPv4 or IPv6 address.
func FromStdIP ¶
FromStdIP returns an IP from the standard library's IP type.
If std is <nil>, returns the zero value and error.
func ParseIP ¶
ParseIP parses and returns the input as type IP. Returns the zero value for IP and error on invalid input.
The string form can be in IPv4 dotted decimal ("192.168.2.1"), IPv6 ("2001:db8::affe"), or IPv4-mapped IPv6 ("::ffff:172.16.0.1").
The hard part is done by net.ParseIP().
Example ¶
package main import ( "fmt" "github.com/gaissmai/go-inet/v2/inet" ) func main() { for _, s := range []string{ "2001:db8::", // IPv6 "::ffff:192.168.0.1", // IPv4-mapped IPv6 "10.0.0.1", // IPv4 } { ip, _ := inet.ParseIP(s) fmt.Printf("ip: %v\n", ip) } }
Output: ip: 2001:db8:: ip: 192.168.0.1 ip: 10.0.0.1
func (IP) Expand ¶
Expand IP address into canonical form, useful for grep, aligned output and lexical sort.
Example ¶
package main import ( "fmt" "github.com/gaissmai/go-inet/v2/inet" ) func main() { ip1, _ := inet.ParseIP("192.168.2.1") ip2, _ := inet.ParseIP("fffe:db8::") fmt.Printf("%q\n", ip1.Expand()) fmt.Printf("%q\n", ip2.Expand()) }
Output: "192.168.002.001" "fffe:0db8:0000:0000:0000:0000:0000:0000"
func (IP) Is4 ¶
Is4 reports whether ip is an IPv4 address.
There is no Is4in6. IPv4-mapped IPv6 addresses are stripped down to IPv4 otherwise the sort order would be undefined.
func (IP) Is6 ¶
Is6 reports whether ip is an IPv6 address.
There is no Is4in6. IPv4-mapped IPv6 addresses are stripped down to IPv4 otherwise the sort order would be undefined.
func (IP) IsValid ¶
IsValid reports whether ip is a valid address and not the zero value of the IP type. The zero value is not a valid IP address of any type.
Note that "0.0.0.0" and "::" are not the zero value.
func (IP) Less ¶
Less reports whether the ip should sort before ip2. IPv4 addresses sorts always before IPv6 addresses.
Example ¶
package main import ( "fmt" "sort" "github.com/gaissmai/go-inet/v2/inet" ) func main() { s := []string{ "0.0.0.1", "fe80::1", "0.0.0.0", "127.0.0.1", "::", "::1", "255.255.255.255", } var ips []inet.IP for _, v := range s { ip, _ := inet.ParseIP(v) ips = append(ips, ip) } sort.Slice(ips, func(i, j int) bool { return ips[i].Less(ips[j]) }) for _, ip := range ips { fmt.Println(ip) } }
Output: 0.0.0.0 0.0.0.1 127.0.0.1 255.255.255.255 :: ::1 fe80::1
func (IP) Reverse ¶
Reverse IP address, needed for PTR entries in DNS zone files.
Example ¶
package main import ( "fmt" "github.com/gaissmai/go-inet/v2/inet" ) func main() { ip1, _ := inet.ParseIP("192.168.2.1") ip2, _ := inet.ParseIP("fffe:db8::") fmt.Printf("%q\n", ip1.Reverse()) fmt.Printf("%q\n", ip2.Reverse()) }
Output: "1.2.168.192" "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.e.f.f.f"