A Clojure library designed to do operations with IP addresses and networks
Add the following in the :deps
section of your deps.edn
file
com.dmo-t/ipaddress {:mvn-version "RELEASE"}
In the NS com.dmo-t.ipaddress.core, 6 main types are defined:
IPv4Address
,IPv4Network
,IPv4Interface
IPv6Address
IPv6Network
IPv6Interface
These types try to mimics the behavior of the corresponding classes in ipaddress
Python library.
All three types implement the following Protocols / Interfaces
So they can be used with the default compare
function. The sort function will work as well without specifying a specific compare
function.
IPv[46]Address
: compare the addresses converted to int.IPv[46]Network
: will compare only the base-address (aka network address). If equality: compare the prefix length.IPv[46]Interface
: Arbitrary choice.
Custom protocol. Defines only the following predicates functions:
loopback?
private?
global?
reserved?
link-local?
multicast?
unspecified?
See the ipaddress
Python Library for the meaning.
Custom protocol. Implement only the next-one
function.
IPv[46]Address
: returns the next IPv[46]Address
. Returns nil
when no more IPv[46]Address.IPv[46]Network
: returns the next IPv[46]Network
with the same IPv[46]Netmask
. Returns nil
when no more network.IPv[46]Interface
: returns the next IPv[46]Interface
in the containing network. Returns nil
when no more address available.Note: (next-one nil)
returns nil.
To create an IPv[46]Address
, always use the constructor make-ipv4address
or make-ipv6address
.
make-ipv4address
: accepts a string or long/int as argument.make-ipv6address
: accepts a string or clojure.lang.BigInt as argument
If the argument is invalid, an exception is raised.clj
Clojure 1.12.2
user=> (use 'com.dmo-t.ipaddress.core)
nil
user=> (def ip1 (make-ipv4address "192.0.2.1"))
#'user/ip1
user=> (to-int ip1)
3221225985
user=> (str ip1)
"192.0.2.1"
user=> (def ip2 (-> (to-int ip1) make-ipv4address))
#'user/ip2
user=> (compare ip1 ip2)
0
user=> (def ip3 (make-ipv4address "172.30.1.2"))
#'user/ip3
user=> (compare ip1 ip3)
1
user=> (private? ip1)
true
user=> (loopback? ip1)
false
user=> (-> (next-one ip1) str )
"192.0.2.2"
user=> (def net (make-ipv4network "192.0.2.0/24"))
#'user/net
user=> (in? ip1 net)
true
user=> (make-ipv4address "192.256.1.2")
Execution error (AssertionError) at com.dmo-t.ipaddress.core/make-ipv4address-from-str (core.clj:98).
Assert failed: (spec/valid? :com.dmo-t.ipaddress.specs/ipv4-address-spec ip)
Always the constructor make-ipv4network
to create an IPv4Network
.
The argument can be address/netmask
or address/mask
.
For IPv6Network
: make-ipv6network
. Only accept a string in address/prefixlen
format.
NB: if the address
part has host bits set, they will be automatically zeroed.
clj
Clojure 1.12.2
user=> (use 'com.dmo-t.ipaddress.core)
nil
user=> (def net1 (make-ipv4network "192.0.2.0/29"))
#'user/net1
user=> (def net2 (make-ipv4network "192.0.2.0/28"))
#'user/net2
user=> (compare net1 net2)
1
user=> (with-prefixlen net1)
"192.0.2.0/29"
user=> (with-netmask net1)
"192.0.2.0/255.255.255.248"
user=> (with-hostmask net1)
"192.0.2.0/0.0.0.7"
user=> (-> (base-address net1) str)
"192.0.2.0"
user=> (-> (broadcast-address net1) str)
"192.0.2.7"
user=> (prefixlen net1)
29
user=> (-> (netmask net1) str)
"255.255.255.248"
user=> (-> (hostmask net1) str)
"0.0.0.7"
user=> (->> (hosts net1) (map #(str %)))
("192.0.2.1" "192.0.2.2" "192.0.2.3" "192.0.2.4" "192.0.2.5" "192.0.2.6")
user=> (subnet-of? net1 net2)
true
user=> (supernet-of? net1 net2)
false
user=> (def ip1 (make-ipv4address "192.0.2.9"))
#'user/ip1
user=> (contains-ip? net1 ip1)
false
user=> (contains-ip? net2 ip1)
true
user=> (def net3 (make-ipv4network "192.0.2.7/32"))
#'user/net3
user=> (overlaps? net1 net3)
true
user=> (def net4 (make-ipv4network "192.0.2.0/27"))
#'user/net4
user=> (subnets net4 29)
user=> (->> (subnets net4 29) (map #(.with-prefixlen %)))
("192.0.2.0/29" "192.0.2.8/29" "192.0.2.16/29" "192.0.2.24/29")
user=> (def net5 (make-ipv4network "192.0.2.72/29"))
#'user/net5
user=> (-> (supernet net5 26) with-prefixlen)
"192.0.2.64/26"
user=> (num-addresses net5)
8
user=> (def net6 (make-ipv4network "192.0.2.64/26"))
#'user/net6
user=> (->> (address-exclude net6 net5) (map #(with-prefixlen %)))
("192.0.2.96/27" "192.0.2.80/28" "192.0.2.64/29")
user=> (-> (next-one net6) with-prefixlen)
"192.0.2.128/26"
user=> (->> (to-seq net6) reverse (take 10) (map #(str % )))
("192.0.2.127" "192.0.2.126" "192.0.2.125" "192.0.2.124" "192.0.2.123" "192.0.2.122" "192.0.2.121" "192.0.2.120" "192.0.2.119" "192.0.2.118")
user=> (def net6-1 (make-ipv6network "2001::/23"))
#'user/net6-1
user=> (def net6-2 (make-ipv6network "2001:3::/32"))
#'user/net6-2
user=> (->> (.address-exclude net6-1 net6-2)
sort
(map #(str %)))
("2001::/31" "2001:2::/32" "2001:4::/30" "2001:8::/29" "2001:10::/28" "2001:20::/27" "2001:40::/26" "2001:80::/25" "2001:100::/24")
IPv4Interface
: Always use the constructor make-ipv4interface
.
Argument: address/prefixlen
or address/netmask
IPv6Interface
: always use the constructor make-ipv6interface
Argument: address/prefixlen
clj
Clojure 1.12.2
user=> (use 'com.dmo-t.ipaddress.core)
nil
(def intf1 (make-ipv4interface "192.0.2.45/29"))
#'user/intf1
user=> (-> (network intf1) with-prefixlen )
"192.0.2.40/29"
user=> (->> (iterate next-one intf1)
(take-while identity)
(map #(with-prefixlen %)))
("192.0.2.45/29" "192.0.2.46/29" "192.0.2.47/29")
user=> (def intf2 (make-ipv4interface "192.0.2.45/29"))
#'user/intf2
user=> (def intf3 (make-ipv4interface "192.0.2.46/28"))
#'user/intf3
user=> (def intf4 (make-ipv4interface "192.0.2.46/29"))
#'user/intf4
user=> (compare intf1 intf2)
0
user=> (compare intf1 intf3)
1
user=> (compare intf1 intf4)
-1
user=> (-> (address intf1) str)
"192.0.2.45"
Copyright © 2025 DMO Technologies
This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0.
This Source Code may also be made available under the following Secondary Licenses when the conditions for such availability set forth in the Eclipse Public License, v. 2.0 are satisfied: GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version, with the GNU Classpath Exception which is available at https://www.gnu.org/software/classpath/license.html.
Can you improve this documentation?Edit on GitLab
cljdoc builds & hosts documentation for Clojure/Script libraries
Ctrl+k | Jump to recent docs |
← | Move to previous article |
→ | Move to next article |
Ctrl+/ | Jump to the search field |