This vignette demonstrates some typical use cases for the ipaddress package.
Although IPv4 addresses are usually displayed in a human-readable
format (e.g. 192.168.0.1
), they are often saved to disk as
integers to reduce storage requirements. R is unable to store the entire
range of IPv4 addresses in its integer data type, but they can instead
be stored in its numeric data type. More details are found under
help("ip_to_integer")
.
Given this, it’s quite possible that you’ll receive IPv4 addresses
represented as integers, and we’ll want to convert them to the
ip_address()
vector type. Here’s an example of how to do
that:
integer_to_ip(c(0, 3232235521, 4294967295))
#> <ip_address[3]>
#> [1] 0.0.0.0 192.168.0.1 255.255.255.255
There are multiple equivalent ways to represent an IP network:
Although the ip_network()
function can handle the first
3 options, we use the common_network()
function for the
final option.
tibble(
start = ip_address(c("192.168.0.0", "2001:db8::")),
end = ip_address(c("192.168.0.15", "2001:db8::ffff:ffff:ffff"))
%>%
) mutate(network = common_network(start, end))
#> # A tibble: 2 × 3
#> start end network
#> <ip_addr> <ip_addr> <ip_netwk>
#> 1 192.168.0.0 192.168.0.15 192.168.0.0/28
#> 2 2001:db8:: 2001:db8::ffff:ffff:ffff 2001:db8::/80
Note that this approach assumes the two addresses do actually
correspond to the first and last addresses of the network, otherwise an
expanded network will be returned (see
help("common_network")
for details).
A very common task is to check if an address is within a network, so
the ipaddress package provides a couple of different functions to help
with this workflow: is_within()
and
is_within_any()
. We also provide is_subnet()
and is_supernet()
to test if a network is within another
network.
To see how these functions can be used in practice, let’s consider a couple of IP networks:
<- tibble(
my_networks network = ip_network(c("192.168.0.0/16", "2001:db8::/32")),
label = c("Private", "Documentation")
)
my_networks#> # A tibble: 2 × 2
#> network label
#> <ip_netwk> <chr>
#> 1 192.168.0.0/16 Private
#> 2 2001:db8::/32 Documentation
and a handful of addresses:
<- tibble(
my_addresses address = ip_address(c("192.168.100.1", "1.2.3.4", "2001:db8::8a2e:370:7334", "::1"))
)
First, we’ll check if each address is in any of our networks.
%>%
my_addresses mutate(in_network = is_within_any(address, my_networks$network))
#> # A tibble: 4 × 2
#> address in_network
#> <ip_addr> <lgl>
#> 1 192.168.100.1 TRUE
#> 2 1.2.3.4 FALSE
#> 3 2001:db8::8a2e:370:7334 TRUE
#> 4 ::1 FALSE
But what if we need to know which of our networks the
address was found in? We can do that using the excellent fuzzyjoin
package together with the is_within()
function.
%>%
my_addresses ::fuzzy_left_join(my_networks, c("address" = "network"), is_within)
fuzzyjoin#> # A tibble: 4 × 3
#> address network label
#> <ip_addr> <ip_netwk> <chr>
#> 1 192.168.100.1 192.168.0.0/16 Private
#> 2 1.2.3.4 NA <NA>
#> 3 2001:db8::8a2e:370:7334 2001:db8::/32 Documentation
#> 4 ::1 NA <NA>
ipaddress provides functions to sample from a specific network
(sample_network()
) or the entire address space
(sample_ipv4()
and sample_ipv6()
). However, it
can be more difficult to sample from the majority of address space,
while excluding certain networks.
A good example is sampling public IPv4 addresses. The simplest solution is to use an accept-reject algorithm – sampling the entire IPv4 address space and rejecting addresses that are reserved.
<- function(size) {
sample_public <- sample_ipv4(size)
result
<- FALSE
all_public while (!all_public) {
<- is_global(result)
public <- sum(!public)
n_replace
if (n_replace == 0) {
<- TRUE
all_public else {
} !public] <- sample_ipv4(n_replace)
result[
}
}
result }
We now sample 10 addresses and make sure they are all public addresses.
tibble(address = sample_public(10)) %>%
mutate(is_public = is_global(address))
#> # A tibble: 10 × 2
#> address is_public
#> <ip_addr> <lgl>
#> 1 29.110.21.14 TRUE
#> 2 225.204.193.210 TRUE
#> 3 163.202.245.93 TRUE
#> 4 193.227.75.115 TRUE
#> 5 31.26.62.254 TRUE
#> 6 63.240.165.43 TRUE
#> 7 74.61.235.34 TRUE
#> 8 142.115.128.42 TRUE
#> 9 104.246.133.208 TRUE
#> 10 149.97.250.204 TRUE