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 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 as type Block. The input type may be:
string net.IPNet net.IP IP
Example for valid input strings:
"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"
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" "net" "github.com/gaissmai/go-inet/v2/inet" ) func main() { for _, anyOf := range []interface{}{ "fe80::1-fe80::2", // block from string "10.0.0.0-11.255.255.255", // block from string, as range but true CIDR, see output net.IP{192, 168, 0, 0}, // IP from net.IP } { a, _ := inet.ParseBlock(anyOf) fmt.Printf("block: %v\n", a) } }
Output: block: fe80::1-fe80::2 block: 10.0.0.0/7 block: 192.168.0.0/32
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 ParseIP ¶
ParseIP parses and returns the input as type IP. Returns the zero value for IP and error on invalid input.
The input type may be:
string net.IP
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"
func (IP) String ¶
String returns the string form of the IP address. It returns one of 3 forms:
"invalid IP" if ip.IsValid() is false "127.0.0.1" "2001:db8::1"
func (IP) ToStdIP ¶
ToStdIP converts to net.IP. Panics on invalid input.
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("%#v\n", ip1.ToStdIP()) fmt.Printf("%#v\n", ip2.ToStdIP()) }
Output: net.IP{0xc0, 0xa8, 0x2, 0x1} net.IP{0xff, 0xfe, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}