Programming language: Go
License: MIT License
Tags: Networking    
Latest version: v0.3.1

iplib alternatives and similar packages

Based on the "Networking" category.
Alternatively, view iplib alternatives based on common mentions on social networks and blogs.

Do you think we are missing an alternative of iplib or a related project?

Add another 'Networking' Package



Documentation CircleCI Go Report Card Coverage Status

I really enjoy Python's ipaddress library and Ruby's ipaddr, I think you can write a lot of neat software if some of the little problems around manipulating IP addresses and netblocks are taken care of for you, so I set out to write something like them for my language of choice, Go. This is what I've come up with.

IPLib is a hopefully useful, aspirationally full-featured library built around and on top of the address primitives found in the net package, it seeks to make them more accessible and easier to manipulate.

It includes:

net.IP tools

Some simple tools for performing common tasks against IP objects:

  • Compare two addresses
  • Get the delta between two addresses
  • Sort
  • Decrement or increment addresses
  • Print v4 as a hexadecimal string
  • Print v6 in fully expanded form
  • Convert between net.IP, integer and hexadecimal
  • Get the version of a v4 address or force a IPv4-mapped IPv6address to be a v4 address

An enhancement of net.IPNet providing features such as:

  • Retrieve the wildcard mask
  • Get the network, broadcast, first and last usable addresses
  • Increment or decrement an address within the boundaries of a netblock
  • Enumerate all or part of a netblock to []net.IP
  • Allocate subnets and supernets



go get -u github.com/c-robinson/iplib

Using IPLib

There are a series of functions for working with v4 or v6 net.IP objects:

package main

import (


func main() {
    ipa := net.ParseIP("")
    ipb := iplib.IncrementIPBy(ipa, 15)      // ipb is
    ipc := iplib.NextIP(ipa)                 // ipc is

    fmt.Println(iplib.CompareIPs(ipa, ipb))  // -1

    fmt.Println(iplib.DeltaIP(ipa, ipb))     // 15

    fmt.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))      // 3232235777
    fmt.Println(iplib.IPToBinaryString(ipa))  // 11000000.10101000.00000001.00000001
    ipd := iplib.Uint32ToIP4(iplib.IP4ToUint32(ipa)+20) // ipd is
    fmt.Println(iplib.IP4ToARPA(ipa))        //

Addresses that require or return a count default to using uint32, which is sufficient for working with the entire IPv4 space. As a rule these functions are just lowest-common wrappers around IPv4- or IPv6-specific functions. The IPv6-specific variants use big.Int so they can access the entire v6 space:

package main

import (


func main() {
    ipa := net.ParseIP("2001:db8::1")
    ipb := iplib.IncrementIPBy(ipa, 15)      // ipb is 2001:db8::16
    ipc := iplib.NextIP(ipa)                 // ipc is 2001:db8::2

    fmt.Println(iplib.CompareIPs(ipa, ipb))  // -1

    fmt.Println(iplib.DeltaIP6(ipa, ipb))     // 15

    fmt.Println(iplib.ExpandIP6(ipa))        // "2001:0db8:0000:0000:0000:0000:0000:0001"
    fmt.Println(iplib.IPToBigint(ipa))       // 42540766411282592856903984951653826561 
    fmt.Println(iplib.IPToBinaryString(ipa)) // 00100000.00000001.00001101.10111000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000000.00000001

    iplist := []net.IP{ ipb, ipc, ipa }
    sort.Sort(iplib.ByIP(iplist))            // []net.IP{ipa, ipc, ipb}

    m := big.NewInt(int64(iplib.MaxIPv4))    // e.g. 4,294,967,295
    ipd := iplib.IncrementIP6By(ipa, m)      // ipd is 2001:db8::1:0:0

    fmt.Println(iplib.DeltaIP6(ipb, ipd))    // 4294967274
    fmt.Println(iplib.IP6ToARPA(ipa))        //

To work with networks simply create an iplib.IPNet object:

package main

import (


func main() {
    // this calls net.ParseCIDR() under the hood, but returns an iplib.Net object
    _, ipna, err := iplib.ParseCIDR("")
    if err != nil {
        // this will be an error from the net package 

    // NewNet() wants a net.IP and is waaaaaaaaaaaaaaaaay faster
    ipb := net.ParseIP("")
    ipnb := iplib.NewNet(ipb, 22)

    // ...works for IPv6 too
    ipc := net.ParseIP("2001:db8::1")
    ipnc := iplib.NewNet(ipc, 64)

    fmt.Println(ipna.Count())                  // 1022 -- good enough for ipv4, but...

    fmt.Println(ipnc.Count())                  // 4294967295 -- ...sigh
    fmt.Println(ipnc.Count6())                 // 18446744073709551616 -- yay Count6() !

    fmt.Println(iplib.CompareNets(ipna, ipnb)) // -1

    ipnlist := []iplib.Net{ipnb, ipna, ipnc}
    sort.Sort(iplib.ByNet(ipnlist))            // []iplib.Net{ ipna, ipnb, ipnc } 

    elist := ipna.Enumerate(0, 0)
    fmt.Println(len(elist))                    // 1022

    fmt.Println(ipna.ContainsNet(ipnb))        // true

    fmt.Println(ipna.NetworkAddress())         //
    fmt.Println(ipna.FirstAddress())           //
    fmt.Println(ipna.LastAddress())            //
    fmt.Println(ipna.BroadcastAddress())       //

    fmt.Println(ipnc.NetworkAddress())         // 2001:db8::1 -- meaningless in IPv6
    fmt.Println(ipnc.FirstAddress())           // 2001:db8::1
    fmt.Println(ipnc.LastAddress())            // 2001:db8::ffff:ffff:ffff:ffff
    fmt.Println(ipnc.BroadcastAddress())       // 2001:db8::ffff:ffff:ffff:ffff

    ipa1 := net.ParseIP("2001:db8::2")
    ipa1, err = ipna.PreviousIP(ipa1)         //  net.IP{2001:db8::1}, nil
    ipa1, err = ipna.PreviousIP(ipa1)         //  net.IP{}, ErrAddressAtEndOfRange

iplib.IPNet objects can be used to generate subnets and supernets:

package main

import (


func main() {
    _, ipna, _ := iplib.ParseCIDR("")
    fmt.Println(ipna.Subnet(24))   // []iplib.Net{,, 
                                   //    , }
    ipnb, err := ipna.Supernet(21) //

    ipnc := ipna.PreviousNet(21)   //

    ipnd := ipna.NextNet(21)       //