glm_cidr/cidr

Types

The relationship between an IP Address, and an Subnet

pub type AddressSubnetRelationship {
  AddressIsInsideSubnet
  AddressIsOutsideSubnet
}

Constructors

  • AddressIsInsideSubnet

    The IP Address lies inside the Subnet

  • AddressIsOutsideSubnet

    The IP Address lies outside the Subnet

pub type CidrError {
  SubnetSliceError(
    subnet: Subnet,
    bitarray: BitArray,
    bitarray_length: Int,
  )
  UnrelatedNetworkTypesIpv6Ipv4(Subnet, IpAddress)
  UnrelatedNetworkTypesIpv4Ipv6(Subnet, IpAddress)
  IncrementIpAddressError
  MalformedBitArray
  NetworkSizeParseError(Nil)
  UnableToFindNextAddress(
    Subnet,
    IpAddress,
    AddressSubnetRelationship,
    String,
  )
  AddressSliceError(address: BitArray, count: Int)
  AddressIsOutsideUsableRange(IpAddress, Subnet, order.Order)
  UnableToFindNextUsableAddress(IpAddress, Subnet, CidrError)
}

Constructors

IP Address

pub type IpAddress {
  Ipv4(a: Int, b: Int, c: Int, d: Int)
  Ipv6(
    a: Int,
    b: Int,
    c: Int,
    d: Int,
    e: Int,
    f: Int,
    g: Int,
    h: Int,
  )
}

Constructors

  • Ipv4(a: Int, b: Int, c: Int, d: Int)

    The IPV4 representation of an IP Address (4 8 bit integers)

  • Ipv6(
      a: Int,
      b: Int,
      c: Int,
      d: Int,
      e: Int,
      f: Int,
      g: Int,
      h: Int,
    )

    The IPV6 representation of an IP Address (8 16 bit integers)

The number of bits in a network mask.

pub type NetworkMask {
  NetworkMask(count: Int)
}

Constructors

  • NetworkMask(count: Int)

    For IPV4, valid values are from 0 to 32 For IPV6, valid values are from 0 to 128

Parse errors are any error encontered while trying to parse user input into a subnet.

pub type ParseError {
  UnknownParseError
  ParseErrors(errors: List(ParseError))
  SplitAddressFromMaskParseError
  MaskParseError(Nil)
  MaskTooLargeParseError(value: Int)
  MaskTooSmallParseError(value: Int)
  AddressTooManyComponentsParseError(count: Int)
  AddressTooFewComponentsParseError(count: Int)
  AddressComponentStringToIntParseError(s: String)
  AddressComponentValueTooLargeParseError(value: Int)
}

Constructors

  • UnknownParseError

    Unknown (default) Parse Error when we don’t know what happened

  • ParseErrors(errors: List(ParseError))

    Parse failed and fallback(s) also failed

  • SplitAddressFromMaskParseError

    Failed to split the address from the mask, probably missing the “/” separator

  • MaskParseError(Nil)

    The net mask is probably not parsing to an integer

  • MaskTooLargeParseError(value: Int)

    The net mask can be <= 128 for ipv6, and <= 32 for ipv4

  • MaskTooSmallParseError(value: Int)

    The mask must be > 0

  • AddressTooManyComponentsParseError(count: Int)

    After splitting the address on “:” for ipv6 or “.” for ipv4, there are too many strings

  • AddressTooFewComponentsParseError(count: Int)

    After splitting the address on “:” for ipv6 or “.” for ipv4, there are too few strings

  • AddressComponentStringToIntParseError(s: String)

    Parsing the hex string failed, max length 4 characters

  • AddressComponentValueTooLargeParseError(value: Int)

    Addresses must be between 0 and 216 for ipv6 or 0 and 28 for ipv4

A subnet defines a network using an IP Address and a NetMask

pub type Subnet {
  Subnet(address: IpAddress, netmask: NetworkMask)
}

Constructors

  • Subnet(address: IpAddress, netmask: NetworkMask)

    An IPV4 Subnet has 32 bits for the network and host address An IPV6 Subnet has 128 bits for the network and host address

SubnetMetadata

SubnetMetadata about the usable addresses. By usable addresses, we mean the addresses that are not already allocated by the networking system, e.g. the network address and the broadcast address.

Special cases:

Note that for both IPV4 and IPV6, this function follows the following convention:

IPV4 /32 -> single host -> 1 address IPV4 /31 -> point-to-point link -> 2 addresses IPV4 /30 -> traditional point-to-point link -> 2 addresses

Single Host Route (/32 | /128)

If the entire range is masked off, e.g. /32 or /128, then this is deemed to be a single host with no subnet, and the function returns one usable address for both the first and last addresses.

Point-To-Point Links (/31 /127)

With all but one bit masked off, e.g. /32 or /127, then 2 hosts are returned. This is commonly used for the creation of a point-to-point network with two usable addresses.

Traditional Point-To-Point Links (/30 /126)

With all but two bits masked off, e.g. /30 or /126, this defines a traditional point-to-point link. The first and last addresses are allocated as network and broadcast addresses. This method returns the two remaining addresses as first and last.

Standard Subnet (/29 /64)

With three or more bits available (IPV4) or 64 bits (IPV6), the first and last addresses are and last addresses are allocated as network and broadcast addresses. This method returns the two remaining addresses as first and last. The count for IPV4 returns the count of usable addresses, .e.g 2**(32-3) for a /29 IPV4 network and 2**(128-64) for a /64 IPV4 network.

Summary

To keep things consistent, the behaviour of these special cases follows the same convention for both IPV4 and IPV6. Even though IPV6 does not have a broadcast address, we are treating it as if it did.

pub type SubnetMetadata {
  SubnetMetadata(
    network: IpAddress,
    broadcast: IpAddress,
    first_host: IpAddress,
    last_host: IpAddress,
    usable_hosts: Int,
    prefix: Int,
    hex_netmask: String,
  )
}

Constructors

  • SubnetMetadata(
      network: IpAddress,
      broadcast: IpAddress,
      first_host: IpAddress,
      last_host: IpAddress,
      usable_hosts: Int,
      prefix: Int,
      hex_netmask: String,
    )

    Arguments

    network

    network address

    broadcast

    broadcast address

    first_host

    The first usable host address in the subnet. The first host is often the gateway or default router address, with hosts using the subsequent addresses up to and including the last usable host.

    last_host

    The last usable host address in the subnet.

    usable_hosts

    The count of the usable host addresses in the subnet.

    prefix

    The subnet network prefix as an int, e.g. /24.

    hex_netmask

    The subnet network prefix as a hex string, e.g. 0xFFFFFF00

Values

pub fn ip_address_from_string(
  address: String,
) -> Result(IpAddress, ParseError)

Parse an ip address from a string.

Examples

use a1 <- result.try(cidr.ip_address_from_string("10.0.0.1"))
a1
|> string.inspect
-> Ipv4(10, 0, 0, 1)

use a2 <- result.try(cidr.ip_address_from_string(":::::::1"))
a2
|> string.inspect
-> Ipv6(0, 0, 0, 0, 0, 0, 0, 1)
pub fn ip_address_to_string(address: IpAddress) -> String

Render an IP Address to a string.

Examples

let a1 = cidr.Ipv4(10, 0, 0, 1)
a1 |> ip_address_to_string
-> "10.0.0.1"

// Note that this library does not smart collapse zeros
// in Ipv6 addresses.
let a2 = cidr.Ipv6(10, 0, 0, 0, 0, 0, 0, 1)
a2 |> ip_address_to_string
-> "A:0:0:0:0:0:0:1"
pub fn metadata(
  subnet: Subnet,
) -> Result(SubnetMetadata, CidrError)

Retrieve the metadata for a given subnet.

Examples

let s1 = cidr.Subnet(
    address: cidr.Ipv4(10, 0, 0, 0), netmask: cidr.NetworkMask(24))
cidr.metadata(s1)
-> SubnetMetadata(Ipv4(10, 0, 0, 0), Ipv4(10, 0, 0, 255), Ipv4(10, 0, 0, 1), Ipv4(10, 0, 0, 254), 254, 24, "0xFFFFFF00")

//    cidr.SubnetMetadata(
//      network: cidr.Ipv4(10, 0, 0, 0),
//      broadcast: cidr.Ipv4(10, 0, 0, 255),
//      first_host: cidr.Ipv4(10, 0, 0, 1),
//      last_host: cidr.Ipv4(10, 0, 0, 254),
//      usable_hosts: 254,
//      prefix: 24,
//      hex_netmask: "0xFFFFFF00",
//    ),
pub fn next(
  subnet: Subnet,
  address: IpAddress,
) -> Result(IpAddress, CidrError)

Return the next address in the subnet, after the given address. Returns an error if the given address is not in the subnet, or if there are no more addresses left in the subnet. Returns the full set of addresses, after the passed in address.

Examples:

let s1 =
  Subnet(address: Ipv4(10, 0, 0, 0), netmask: NetworkMask(24))
let a1 = Ipv4(10, 0, 0, 0)
next(s1, a1)
-> Ipv4(10, 0, 0, 1)

let a2 = Ipv4(10, 0, 0, 254)
next(s1, a2)
-> Ipv4(10, 0, 0, 255)
pub fn next_usable(
  subnet: Subnet,
  address: IpAddress,
) -> Result(IpAddress, CidrError)

Return the next usable address. Differs from usable() in that it omits the .255 (broadcast) address for a 10.0.0.0/24 network segment.

Examples

let s1 =
  Subnet(address: Ipv4(10, 0, 0, 0), netmask: NetworkMask(24))
let a1 = Ipv4(10, 0, 0, 0)
next_usable(s1, a1)
-> Ipv4(10, 0, 0, 1)

let a2 = Ipv4(10, 0, 0, 254)
next_usable(s1, a2)
-> Error(AddressIsOutsideUsableRange(Ipv4(10, 0, 0, 255), Subnet(Ipv4(10, 0, 0, 0), NetworkMask(24)), Gt))
pub fn relationship(
  subnet: Subnet,
  address: IpAddress,
) -> Result(AddressSubnetRelationship, CidrError)

Given a subnet and an internet address, determine the relationship between the two.

Examples

let s1 =
  Subnet(address: Ipv4(10, 0, 0, 0), netmask: NetworkMask(24))
relationship(s1, Ipv4(10, 0, 0, 0))
-> Ok(AddressIsInsideSubnet)
relationship(s1, Ipv4(10, 0, 0, 255))
-> Ok(AddressIsInsideSubnet)
relationship(s1, Ipv4(11, 0, 0, 255))
-> Ok(AddressIsOutsideSubnet)
pub fn subnet_from_string(
  s: String,
) -> Result(Subnet, ParseError)

Parse a string with an internet address and network mask delimited with a slash “/”, return a subnet.

Examples

subnet_from_string("10.0.0.0/24")
>> Ok(Subnet(Ipv4(10, 0, 0, 0), NetworkMask(24)))

echo subnet(":::::::0/128")
>> Ok(Subnet(Ipv6(0, 0, 0, 0, 0, 0, 0, 0), NetworkMask(128)))
pub fn subnet_to_string(subnet: Subnet) -> String

Render a network subnet to a string.

Examples

use s1 <- result.try(subnet_from_string("10.0.0.0/24"))
s1 |> subnet_to_string
-> "10.0.0.0/24"

// Note that this library does not smart collapse zeros
// in Ipv6 addresses.
use s2 <- result.try(subnet(":::::::/128"))
->"0:0:0:0:0:0:0:0/128"
Search Document