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


MODELS

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.

Examples

metadata(subnet("10.0.0.1/32"))
-> Ok(SubnetMetadata(first: 10.0.0.1, last: 10.0.0.1, count: 1)

metadata(subnet("10.0.0.1/31"))
-> Ok(SubnetMetadata(first: 10.0.0.0, last: 10.0.0.1, count: 2)

metadata(subnet("10.0.0.1/30"))
-> Ok(SubnetMetadata(first: 10.0.0.1, last: 10.0.0.2, count: 2)

metadata(subnet("10.0.0.1/24"))
-> Ok(SubnetMetadata(first: 10.0.0.1, last: 10.0.0.254, count: 254)

metadata(subnet("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF/128"))
-> Ok(SubnetMetadata(first: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF, last: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF, count: 1)

metadata(subnet("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF/127"))
-> Ok(SubnetMetadata(first: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFE, last: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF, count: 2)

metadata(subnet("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF/126"))
-> Ok(SubnetMetadata(first: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFD, last: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFE, count: 2)

metadata(subnet("FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF/112"))
-> Ok(SubnetMetadata(first: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:1, last: FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFF:FFFE, count: 65534)
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. Return the corresponding IPV4 subnet if the parsing succeeds. If parsing an IPV4 subnet fails, then try to parse an IPV6 address and mask. Return the corresponding IPV6 subnet if the parsing succeeds. If both parsing attempts fail, then returns both ParseErrors.

NOTE: this means that in the error case, you’ll get an error for IPV4 **and for IPV6, even though you are only trying to parse one or the other. However, the parsing will fail for both, and so both errors are returned.

pub fn ip_address_to_string(address: IpAddress) -> String

Render an IP Address to a string.

Examples

let assert(ipv4_address) = Ipv4(10, 0, 0, 1)
ip_address_to_string(ipv4_address)
-> "10.0.0.1"

Note: for IPV6, no smart collapsing is done.
pub fn metadata(
  subnet: Subnet,
) -> Result(SubnetMetadata, CidrError)

Retrieve the metadata for a given subnet.

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, so for 10.0.0.0/24, returns 10.0.0.0 through 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 .0 (network) and .255 (broadcast) addresses for a 10.0.0.0/24 network segment.

pub fn relationship(
  subnet: Subnet,
  address: IpAddress,
) -> Result(AddressSubnetRelationship, CidrError)

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

pub fn subnet_from_string(
  s: String,
) -> Result(Subnet, ParseError)

PUBLIC API

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

Examples

subnet("10.0.0.1/24")
-> Ok(IPV4 SUBNET)

subnet(":::::::1/128")
-> Ok(IPV6 SUBNET)
pub fn subnet_to_string(subnet: Subnet) -> String

Render a network subnet to a string.

Search Document