Skip to content

Instantly share code, notes, and snippets.

@dougvj
Created April 25, 2022 08:06
Show Gist options
  • Save dougvj/5918a826be845d91bfb8fed79770409d to your computer and use it in GitHub Desktop.
Save dougvj/5918a826be845d91bfb8fed79770409d to your computer and use it in GitHub Desktop.
Getting IPv4 or IPv6 address string from IPv6 sockaddr
// This function returns the string representation of an IP address in an IPv6
// stack. Connections from IPv4 addresses are mapped to IPv6 addresses under
// the ::FFFF prefix. This checks for that mapping and if it exists returns the
// conversion as though the addresss were a native IPv4 Address.
//
// addr is a pointer to a valid sockaddr_in6 struct.
//
// dest must be a buffer of at least size INET6_ADDRSTRLEN
//
// The return is a pointer to dest, otherwise if NULL then errno is set, see
// man inet_ntop(3)
const char* get_addr_string(struct sockaddr_in6* addr, char* dest) {
assert(addr->sin6_family == AF_INET6);
uint32_t *addr_words = (uint32_t *)&(addr->sin6_addr);
// Check for ipv6 mapped ipv4 address. This means that the top 80 bits are
// 0 and the next 16 bits are 1
if (addr_words[0] == 0 && addr_words[1] == 0 &&
ntohl(addr_words[2]) == 0x0000FFFF) {
return inet_ntop(AF_INET, &(addr_words[3]), dest, INET6_ADDRSTRLEN);
}
return inet_ntop(AF_INET6, &(addr->sin6_addr), dest, INET6_ADDRSTRLEN);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment