Network addresses

#include <libcork/core.h>

IP addresses

libcork provides C types for storing IPv4 and IPv6 addresses, as well as a union type for storing a generic IP address, regardless of whether it’s IPv4 or IPv6. (This lets you distinguish between an IPv4 address and the equivalent ::ffff:0:0/96 IPv4-mapped IPv6 address.)

struct cork_ipv4
struct cork_ipv6

An IPv4 or IPv6 address. The address is stored in memory exactly as it would be if sent over a network connection — i.e., in network-endian order, regardless of the endianness of the current host. The types are also guaranteed to be exactly the size of an actual IPv4 or IPv6 address (without additional padding), so they can be embedded directly into struct types that represent binary disk/wire formats.

The contents of these types should be considered opaque. You should use the accessor functions defined below to interact with the IP address.

struct cork_ip

A single union type that can contain either an IPv4 or IPv6 address. This type contains a discriminator field, so you can’t use it directly in a binary disk/wire format type.

unsigned int version

Either 4 or 6, indicating whether the current IP address is an IPv4 address or an IPv6 address.

struct cork_ipv4 ip.v4
struct cork_ipv6 ip.v6

Gives you access to the underlying cork_ipv4 or cork_ipv6 instance for the current address. It’s your responsibility to check the cork_ip.version field and only access the union branch that corresponds to the current IP version.

void cork_ipv4_copy(struct cork_ipv4 *addr, const void *src)
void cork_ipv6_copy(struct cork_ipv6 *addr, const void *src)
void cork_ip_from_ipv4(struct cork_ip *addr, const void *src)
void cork_ip_from_ipv6(struct cork_ip *addr, const void *src)

Initializes a cork_ipv4, cork_ipv6, or cork_ip instance from an existing IP address somewhere in memory. The existing address doesn’t have to be an instance of the cork_ipv4 or cork_ipv6 types, but it does have to be a well-formed address. (For IPv4, it must be 4 bytes long; for IPv6, 16 bytes long. And in both cases, the address must already be in network-endian order, regardless of the host’s endianness.)

int cork_ipv4_init(struct cork_ipv4 *addr, const char *str)
int cork_ipv6_init(struct cork_ipv6 *addr, const char *str)
int cork_ip_init(struct cork_ip *addr, const char *str)

Initializes a cork_ipv4, cork_ipv6, or cork_ip instance from the string representation of an IP address. str must point to a string containing a well-formed IP address. (Dotted-quad for an IPv4, and colon-hex for IPv6.) Moreover, the version of the IP address in str must be compatible with the function that you call: it can’t be an IPv6 address if you call cork_ipv4_init, and it can’t be an IPv4 address if you call cork_ipv6_init.

If str doesn’t represent a valid address (of a compatible IP version), then we leave addr unchanged, fill in the current error condition with a CORK_NET_ADDRESS_PARSE_ERROR error, and return -1.

bool cork_ipv4_equal(const struct cork_ipv4 *addr1, const struct cork_ipv4 *addr2)
bool cork_ipv6_equal(const struct cork_ipv6 *addr1, const struct cork_ipv6 *addr2)
bool cork_ip_equal(const struct cork_ip *addr1, const struct cork_ip *addr2)

Checks two IP addresses for equality.


The maximum length of the string representation of an IPv4, IPv6, or generic IP address, including a NUL terminator.

void cork_ipv4_to_raw_string(const struct cork_ipv4 *addr, char *dest)
void cork_ipv6_to_raw_string(const struct cork_ipv6 *addr, char *dest)
void cork_ip_to_raw_string(const struct cork_ip *addr, char *dest)

Fills in dest with the string representation of an IPv4, IPv6, or generic IP address. You are responsible for ensuring that dest is large enough to hold the string representation of any valid IP address of the given version. The CORK_IPV4_STRING_LENGTH, CORK_IPV6_STRING_LENGTH, and CORK_IP_STRING_LENGTH macros can be helpful for this:

struct cork_ipv4  addr;
cork_ipv4_to_raw_string(&addr, buf);
bool cork_ipv4_is_valid_network(const struct cork_ipv4 *addr, unsigned int cidr_prefix)
bool cork_ipv6_is_valid_network(const struct cork_ipv6 *addr, unsigned int cidr_prefix)
bool cork_ip_is_valid_network(const struct cork_ipv6 *addr, unsigned int cidr_prefix)

Checks an IP address for alignment with a CIDR block prefix. For example, is invalid, but is valid.


The error class and codes used for the error conditions described in this section.

Table Of Contents

Previous topic

128-bit integers

Next topic

High-precision timestamps

This Page