- Notifications
You must be signed in to change notification settings - Fork22
A library for working with IP addresses and networks in Go
License
c-robinson/iplib
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
ATTENTION version 2.0.0 is a breaking change from previous versions forhandling IPv6 addresses (functions for IPv4 are unchanged). Calls that resultin arithmatic operations against IPv6 now useuint128.Uint128instead of*big.Int
. Until now this library restricted itself to using thestandard library, butmath/big
is sloooooooooow and the performance gainsfrom switching were too large to ignore:
Benchmark | *big.Int | uint128.Uint128 |
---|---|---|
Benchmark_DeltaIP6 | 79.27 ns/op | 2.809 ns/op |
BenchmarkDecrementIP6By | 50.54 ns/op | 13.88 ns/op |
BenchmarkIncrementIP6By | 50.48 ns/op | 13.92 ns/op |
BenchmarkNet_Count6 | 122.2 ns/op | 11.26 ns/op |
It would be fantastic to remove this external dependency in some future v3that switched to a nativeuint128
but for that to happenthis proposal(or something similar) would need to be adopted.
Okay you can stop paying attention now
I really enjoy Python'sipaddresslibrary and Ruby'sipaddr,I think you can write a lot of neat software if some of the little problemsaround manipulating IP addresses and netblocks are taken care of for you, so Iset out to write something like them for my language of choice, Go. This iswhat I've come up with.
IPLib is a hopefully useful,aspirationally full-featured library built around and on top of the addressprimitives found in thenet package, it seeksto make them more accessible and easier to manipulate.
It includes:
Some simple tools for performing common tasks against IP objects:
- compare two addresses
- make a copy of a net.IP address
- get the delta between two addresses
- sort
- decrement or increment addresses
- print addresses as binary or hexadecimal strings, or print their addr.ARPADNS name
- print v6 in fully expanded form
- convert between net.IP and integer values
- get the version of a v4 address or force a IPv4-mapped IPv6address to be av4 address
An enhancement ofnet.IPNet
,iplib.Net
is an interface with two, version-specific implementations providing features such as:
- retrieve the first and last usable address
- retrieve the wildcard mask
- enumerate all or part of a netblock to
[]net.IP
- decrement or increment addresses within the boundaries of the netblock
- return the supernet of a netblock
- allocate subnets within the netblock
- return next- or previous-adjacent netblocks
The two address versions behave differently in both large and subtle ways,and the version-specific implementations seek to account for this. For examplethe Net4 implementation omits the network and broadcast addresses fromconsideration during enumeration; while the Net6 implementation introduces theconcept of a HostMask, which blocks usable addresses off from the right in thesame way that a netmask constrains them from the left
Additional version-specific considerations described in theNet4andNet6 sections below.
- iana - a module for referencingIP netblocks against theInternet Assigned Numbers Authority'sSpecial IP Address Registry
- iid - a module forgenerating and validating IPv6 Interface Identifiers, includingRFC4291modified EUI64 andRFC7217Semantically Opaque addresses
go get -u github.com/c-robinson/iplib/v2
There are a series of functions for working with v4 or v6net.IP
objects:
package mainimport ("fmt""net""sort""github.com/c-robinson/iplib/v2")funcmain() {ipa:=net.ParseIP("192.168.1.1")ipb:=iplib.IncrementIPBy(ipa,15)// ipb is 192.168.1.16ipc:=iplib.NextIP(ipa)// ipc is 192.168.1.2fmt.Println(iplib.CompareIPs(ipa,ipb))// -1fmt.Println(iplib.DeltaIP(ipa,ipb))// 15fmt.Println(iplib.IPToHexString(ipc))// "c0a80102"iplist:= []net.IP{ipb,ipc,ipa }sort.Sort(iplib.ByIP(iplist))// []net.IP{ipa, ipc, ipb}fmt.Println(iplib.IP4ToUint32(ipa))// 3232235777fmt.Println(iplib.IPToBinaryString(ipa))// 11000000.10101000.00000001.00000001fmt.Println(iplib.IP4ToARPA(ipa))// 1.1.168.192.in-addr.arpa}
Addresses that require or return a count default to usinguint32
, which issufficient for working with the entire IPv4 space. As a rule these functionsare just lowest-common wrappers around IPv4- or IPv6-specific functions. TheIPv6-specific variants useuint128.Uint128
so they can access the entire v6space.
Net
describes aniplib.Net
object, the exposed functions are those thatare required for comparison, sorting, generic initialization and for ancillaryfunctions such as those found in this package's submodules.
Net4
represents an IPv4 network. Since the first and last addresses of a v4network are typically not allocated for use these will be omitted byEnumerate()
,NextIP()
andPreviousIP()
; they wont show up inCount()
;andFirstAddress()
andLastAddress()
show the 2nd and 2nd-to-the-lastaddresses respectively. The v4-specific methodNetworkAddress()
returns thefirst address, whileBroadcastAddress()
returns the last. There is anexception made forNet4
networks defined with a 31-bit netmask, since theseare assumed to be forRFC3021point-to-point links.
AdditionallyNet4
contains aWildcard()
method which will return thenetwork'swildcard address.
n:=iplib.NewNet4(net.ParseIP("192.168.0.0"),16)fmt.Println(n.Count())// 65534 (note: not 65536)fmt.Println(n.Enumerate(2,1024))// [192.168.4.1 192.168.4.2]fmt.Println(n.IP())// 192.168.0.0fmt.Println(n.FirstAddress())// 192.168.0.1fmt.Println(n.LastAddress())// 192.168.255.254fmt.Println(n.BroadcastAddress())// 192.168.255.255fmt.Println(n.Wildcard())// 0000fffffmt.Println(n.Subnet(0))// [192.168.0.0/17 192.168.128.0/17] <nil>fmt.Println(n.Supernet(0))// 192.168.0.0/15 <nil>
Net6
represents an IPv6 network. In some ways v6 is simpler than v4, asit does away with the special behavior of addresses at the front and back ofthe netblock. For IPv6 the primary problem is the sheer size of the thing:there are 2^128th addresses in IPv6, which translates to 340 undecillion!
n:=iplib.NewNet6(net.ParseIP("2001:db8::"),56,0)fmt.Println(n.Count())// 4722366482869645213696fmt.Println(n.Enumerate(2,1024))// [2001:db8::400 2001:db8::401]fmt.Println(n.FirstAddress())// 2001:db8::fmt.Println(n.NextIP(n.FirstAddress()))// 2001:db8::1 <nil>fmt.Println(n.LastAddress())// 2001:db8:0:ff:ffff:ffff:ffff:fffffmt.Println(n.Subnet(0,0))// [2001:db8::/57 2001:db8:0:80::/57] <nil>fmt.Println(n.Supernet(0,0))// 2001:db8::/55 <nil>
To manage the address space,Net6
introducesHostMask
. This optionalconstraint can be used to block addresses on the right-side of a netblocksomewhat like Netmasks do on the left.Hostmask
must be specified atinitialization time and, if set, will affect the behavior ofCount()
,Enumerate()
,LastAddress()
,NextIP()
andPreviousIP()
.Subnet()
andSupernet()
generate objects that inherit the hostmask of their parent, whilea hostmask must be specified forNextNet()
andPreviousNet()
.
// this is the same as the previous example, except with a hostmask setn:=NewNet6(net.ParseIP("2001:db8::"),56,60)fmt.Println(n.Count())// 4096fmt.Println(n.Enumerate(2,1024))// [2001:db8:0:40:: 2001:db8:0:40:100::]fmt.Println(n.FirstAddress())// 2001:db8::fmt.Println(n.NextIP(n.FirstAddress()))// 2001:db8:0:0:100:: <nil>fmt.Println(n.LastAddress())// 2001:db8:0:ff:f00::fmt.Println(n.Mask().String())// ffffffffffffff000000000000000000fmt.Println(n.Hostmask.String())// 0000000000000000f0fffffffffffffffmt.Println(n.Subnet(0,60))// [2001:db8::/57 2001:db8:0:80::/57] <nil>fmt.Println(n.Supernet(0,60))// 2001:db8::/55 <nil>
IPfool is a simple command-line tool that Iwrote to test many of the features within this library and might be useful inevaluating it.
About
A library for working with IP addresses and networks in Go