Skip to content

Instantly share code, notes, and snippets.

@derekkraan
Created September 3, 2025 07:45
Show Gist options
  • Select an option

  • Save derekkraan/775caa9a30c0e81ff9879f3edb9c2f41 to your computer and use it in GitHub Desktop.

Select an option

Save derekkraan/775caa9a30c0e81ff9879f3edb9c2f41 to your computer and use it in GitHub Desktop.
CIDR Range checking (IPV4/IPV6)
defmodule CIDRRange do
import Bitwise
@type cidr :: {integer(), integer()}
@spec contains?(cidr(), binary()) :: boolean()
def contains?(cidr, ip) when is_binary(ip) do
contains?(cidr, parse_ip(ip))
end
def contains?(cidr, ip) when is_binary(cidr) do
contains?(parse_cidr(cidr), ip)
end
def contains?(mask, {ip_int, _ip_size}) when is_integer(ip_int) do
{mask_ip, mask_bitmask} = mask
band(ip_int, mask_bitmask) == band(mask_ip, mask_bitmask)
end
@spec parse_cidr(binary()) :: cidr()
def parse_cidr(cidr) do
[ip, mask_bits] = String.split(cidr, "/")
{ip_int, bin_size} = parse_ip(ip)
mask_int = mask(bin_size, mask_bits)
{ip_int, mask_int}
end
def parse_ip(ip) do
case :inet.parse_address(~c(#{ip})) do
{:ok, {a, b, c, d, e, f, g, h}} ->
<<ip::128>> = <<a::16, b::16, c::16, d::16, e::16, f::16, g::16, h::16>>
{ip, 128}
{:ok, {a, b, c, d}} ->
<<ip::32>> = <<a, b, c, d>>
{ip, 32}
end
end
defp mask(total_size, mask_bits_str) do
bits_off = total_size - String.to_integer(mask_bits_str)
ones = floor(:math.pow(2, total_size) - 1)
floor(:math.pow(2, bits_off) - 1)
|> bxor(ones)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment