Network address manipulation library for Scala. Inspired by netaddr library for Python. Examples in this readme are taken from here.
Add the following to your build.sbt:
libraryDependencies += "com.risksense" % "ipaddr_2.12" % "1.0.3"
Before making any contributions, please check the issues section to make sure your concern is not duplicate. If your issue is not already addressed, please create one. Describe the problem/bug/feature that you would like to be solved. If you are ready to contribute, read on...
- Fork this repo!
- Create a new branch with a name that hints about what is added/fixed in the branch.
- Squash your commits. We like having single commit pull requests :)
- Open a pull request and make sure your commit message references the issue number.
This project is licensed under the Apache License. Please see LICENSE file for more details.
- Pankaj Khatkar - initial work
Create IpAddress
from a string notation or a Long value
val ip1: IpAddress = IpAddress("192.168.0.1")
val ip2: IpAddress = IpAddress(3232235521L) // also represents 192.168.0.1
val ip3: IpAddress = IpAddress("192.168.0.2")
Check the equality
ip1.equals(ip2) // true
ip1.equals(ip3) // false
More information about an IpAddress
ip3.width // 32
ip3.wordSize // 8
ip3.wordCount // 4
ip3.maxWord // 255
Numerical representation
val ip: IpAddress = IpAddress(169738753L) // 10.30.2.1
ip.hex // 0a1e0201
ip.words // WrappedArray(10, 30, 2, 1)
ip.bits("-") // 00001010-00011110-00000010-00000001
ip.version // 4
Sorting
val unsortedIpSeq = Seq(IpAddress("192.0.2.130"), IpAddress("10.0.0.1"), IpAddress("192.0.2.128"),
IpAddress("192.0.3.0"), IpAddress("192.0.2.0"))
unsortedIpSeq.sorted // List(10.0.0.1, 192.0.2.0, 192.0.2.128, 192.0.2.130, 192.0.3.0)
Categorization
- Private
IpAddress("192.168.0.1").isPrivate // true
IpAddress("8.8.8.8").isPrivate // false
- LinkLocal
IpAddress("169.254.0.0").isLinkLocal // true
IpAddress("192.168.0.1").isLinkLocal // false
- Loopback
IpAddress("127.0.0.1").isLoopback // true
IpAddress("192.168.0.1").isLoopback // false
- Multicast
IpAddress("239.192.0.1").isMulticast // true
IpAddress("192.168.0.1").isMulticast // false
- Unicast
IpAddress("239.192.0.1").isUnicast // false
IpAddress("192.168.0.1").isUnicast // true
- Reserved
IpAddress("192.0.0.1").isReserved // true
IpAddress("10.1.2.0").isReserved // false
- Is Netmask
IpAddress("255.255.254.0").isNetmask // true
IpAddress("239.192.0.1").isNetmask // false
- Is Hostmast
IpAddress("0.0.1.255").isHostmask // true
IpAddress("10.1.2.0").isHostmask // false
Comparing IpAddress
IpAddress("192.0.2.1") == IpAddress("192.0.2.1") // true
IpAddress("192.0.2.1") < IpAddress("192.0.2.2") // true
IpAddress("192.0.2.2") > IpAddress("192.0.2.1") // true
IpAddress("192.0.2.1") != IpAddress("192.0.2.1") // false
IpAddress("192.0.2.1") >= IpAddress("192.0.2.1") // true
IpAddress("192.0.2.2") >= IpAddress("192.0.2.1") // true
IpAddress("192.0.2.1") <= IpAddress("192.0.2.1") // true
IpAddress("192.0.2.1") <= IpAddress("192.0.2.2") // true
Create an IpNetwork from a CIDR string notation. All of the following calls represent the same network:
val n1 = IpNetwork("192.0.3.112/22")
val n2 = IpNetwork("192.0.3.112", 22)
val n3 = IpNetwork(IpAddress("192.0.3.112"), 22)
val n4 = IpNetwork(3221226352L, 22)
Useful details about a network:
n1.ip // 192.0.3.112
n1.broadcast // 192.0.3.255
n1.netmask // 255.255.252.0
n1.hostmask // 0.0.3.255
n1.size // 1024
n1.first // 3221225472
n1.last // 3221226495
n1.cidr // 192.0.0.0/22, true CIDR address which omits all host bits
val n5 = IpNetwork("192.0.2.1/32") // this creates a network with single host
val n6 = IpNetwork("192.0.2.1") // same as n5
n5.ip // 192.0.2.1
n5.broadcast // 192.0.2.1
n5.netmask // 255.255.255.255
n5.hostmask // 0.0.0.0
n5.size // 1
n5.first // 3221225985
n5.last // 3221225985
Checking if an IpAddress/IpNetwork/IpRange belongs to another IpNetwork:
n1.contains("192.0.3.136") // true
n1.contains(IpNetwork("192.0.3.112/24")) // true
n1.contains(IpRange("192.0.3.112", "192.0.3.115")) // true
Get a list of IpAddresses belonging to an IpNetwork:
IpNetwork("192.0.3.112/30").iter // Vector(192.0.3.112, 192.0.3.113, 192.0.3.114, 192.0.3.115)
Sorting
val unsortedNetworks = Seq(IpNetwork("192.0.2.128/28"), IpNetwork("192.0.3.0/24"),
IpNetwork("192.0.2.0/24"), IpNetwork("172.24/12"))
unsortedNetworks.sorted // List(172.24.0.0/12, 192.0.2.0/24, 192.0.2.128/28, 192.0.3.0/24)
Comparing IpNetworks
IpNetwork compares the subnets (or lower and upper boundaries) rather than their individual IP address values. That's why following example returns true.
IpNetwork("192.0.2.0/24") == IpNetwork("192.0.2.112/24") // true
You can exactly specify which portion of each IpNetwork you’d like to compare.
IpNetwork("192.0.2.0/24").ip == IpNetwork("192.0.2.112/24").ip // false
IpNetwork("192.0.2.0/24").ip < IpNetwork("192.0.2.112/24").ip // true
IpNetwork("192.0.2.0/24").cidr == IpNetwork("192.0.2.112/24").cidr // true
IpNetwork("192.0.2.0/24") == IpNetwork("192.0.3.0/24") // false
IpNetwork("192.0.2.0/24") != IpNetwork("192.0.3.0/24") // true
IpNetwork("192.0.2.0/24") < IpNetwork("192.0.3.0/24") // true
Create an IpRange from dot-delimited IP addresses
val r1 = IpRange("10.1.2.3", "10.1.2.9")
r1.toString // 10.1.2.3-10.1.2.9
More information about an IpRange
r1.first // 167838211
r1.last // 167838217
r1.size // 7
r1.cidrs // Vector(10.1.2.3/32, 10.1.2.4/30, 10.1.2.8/31)
Check if an IpAddress/IpNetwork/IpRange belongs to another IpRange
r1.contains(IpAddress("10.1.2.4")) // true
r1.contains("10.1.2.4") // true
r1.contains("10.1.2.12") // false
r1.contains(IpNetwork("10.1.2.0/31")) // false
Create an IpSet form IpNetwork, IpRange or a sequence of IpNetwork elements
val s1 = IpSet(IpRange("10.1.2.0", "10.1.2.8"))
val s2 = IpSet(IpNetwork("10.1.2.0/28"))
val s3 = IpSet(Seq(IpNetwork("10.1.2.0"), IpNetwork("10.1.2.8")))
val emptySet = IpSet()
s1.head // 10.1.2.0/29
s1.ipRange // 10.1.2.0-10.1.2.8
s2.ipRange // 10.1.2.0-10.1.2.15
s1.isContiguous // true
s1.volume // 9
Adding and removing elements from IpSet
Add/remove an IpAddress, IpNetwork and IpRange from an IpSet.
s1 + IpAddress("10.1.2.10") // IpSet(10.1.2.0/29, 10.1.2.8/32, 10.1.2.10/32)
s1 + IpAddress("10.1.2.0") // IpSet(10.1.2.0/29, 10.1.2.8/32)
s1 - IpAddress("10.1.2.0") // IpSet(10.1.2.1/32, 10.1.2.2/31, 10.1.2.4/30, 10.1.2.8/32)
s1 - IpNetwork("10.1.2.2/31") // IpSet(10.1.2.0/31, 10.1.2.4/30, 10.1.2.8/32)
s1 - IpRange("10.1.2.0", "10.1.2.8") // IpSet()
Comparing IpSets
val largeSet = IpSet(IpRange("10.1.2.0", "10.1.2.8"))
val smallSet = IpSet(IpRange("10.1.2.0", "10.1.2.6"))
smallSet < largeSet // true
smallSet < smallSet // false
smallSet <= largeSet // true. Equivalent to smallSet.subsetOf(largeSet)
smallSet > largeSet // false
smallSet >= largeSet // false. Equivalent to smallSet.supersetOf(largeSet)
IpSet membership
Check if an IpAddress or IpNetwork belongs to an IpSet.
val ipSet = IpSet(IpRange("10.1.2.0", "10.1.2.8"))
ipSet.contains(IpAddress("10.1.2.6")) // true
ipSet.contains(IpAddress("10.1.2.9")) // false
ipSet.contains(IpNetwork("10.1.2.4/30")) // true
Check if an IpSet belongs to another IpSet
val s1 = IpSet(Seq(IpNetwork("10.1.2.6"), IpNetwork("10.1.2.8")))
val s2 = IpSet(Seq(IpNetwork("10.1.2.8"), IpNetwork("10.1.2.10")))
val s3 = IpSet(IpNetwork("10.1.2.9"))
s1.isDisjoint(s2) // false
s1.isDisjoint(s3) // true. Because s3 has nothing in common with s1.
Set operations on IpSet
val s1 = IpSet(Seq(IpNetwork("10.1.2.6"), IpNetwork("10.1.2.8")))
val s2 = IpSet(Seq(IpNetwork("10.1.2.8"), IpNetwork("10.1.2.10")))
s1 & s2 // IpSet(10.1.2.8/32). Equivalent to s1.intersect(s2)
s1 | s2 // IpSet(10.1.2.6/32, 10.1.2.8/32, 10.1.2.10/32). Equivalent to s1.union(s2)
s1 ^ s2 // IpSet(10.1.2.6/32, 10.1.2.10/32). Equivalent to s1.symmetricDiff(s2)
Ipaddr library provides some helper methods to operate on Nmap style address.
Nmap.validNmapRange("192.168.3-5,7.1") // true
Nmap.validNmapRange("10.2-3.4.5-8") // true
Nmap.validNmapRange("172.163.-.12") // true
Nmap.validNmapRange("10.1.2,1-3") // false
Nmap.validNmapRange("1.2.256.2") // false
Nmap.validNmapRange("17.12.12-a.3") // false
Generate an Iterator over Ipaddress contained in an Nmap address.
Nmap.iterNmapRange("192.168.3-5,7.1")
Above code returns an Iterator with IpAddresses 192.168.3.1, 192.168.4.1, 192.168.5.1, 192.168.7.1.