code/include/swoc/swoc_ip_util.h (94 lines of code) (raw):
// SPDX-License-Identifier: Apache-2.0
// Copyright Network Geographics 2014
/** @file
Shared utilities for IP address classes.
*/
#pragma once
#include <netinet/in.h>
#include "swoc/swoc_version.h"
// These have to be global namespace, unfortunately.
inline bool
operator==(in6_addr const& lhs, in6_addr const& rhs) {
return 0 == memcmp(&lhs, &rhs, sizeof(in6_addr));
}
inline bool
operator!=(in6_addr const& lhs, in6_addr const& rhs) {
return 0 != memcmp(&lhs, &rhs, sizeof(in6_addr));
}
namespace swoc { inline namespace SWOC_VERSION_NS {
/// Internal IP address utilities.
namespace ip {
inline bool is_loopback_host_order(in_addr_t addr) {
return (addr & 0xFF000000) == 0x7F000000;
}
inline bool is_link_local_host_order(in_addr_t addr) {
return (addr & 0xFFFF0000) == 0xA9FE0000; // 169.254.0.0/16
}
inline bool is_multicast_host_order(in_addr_t addr) {
return IN_MULTICAST(addr);
}
inline bool is_private_host_order(in_addr_t addr) {
return (((addr & 0xFF000000) == 0x0A000000) || // 10.0.0.0/8
((addr & 0xFFC00000) == 0x64400000) || // 100.64.0.0/10
((addr & 0xFFF00000) == 0xAC100000) || // 172.16.0.0/12
((addr & 0xFFFF0000) == 0xC0A80000) // 192.168.0.0/16
);
}
// There really is no "host order" for IPv6, so only the network order utilities are defined.
// @c IP6Addr uses an idiosyncratic ordering for performance, not really useful to expose to
// clients.
inline bool is_loopback_network_order(in6_addr const& addr) {
return addr == in6addr_loopback;
}
inline bool is_multicast_network_order(in6_addr const& addr) {
return addr.s6_addr[0] == 0xFF;
}
inline bool is_link_local_network_order(in6_addr const& addr) {
return addr.s6_addr[0] == 0xFE && (addr.s6_addr[1] & 0xC0) == 0x80; // fe80::/10
}
inline bool is_private_network_order(in6_addr const& addr) {
return (addr.s6_addr[0] & 0xFE) == 0xFC; // fc00::/7
}
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
inline bool is_loopback_network_order(in_addr_t addr) {
return (addr & 0xFF) == 0x7F;
}
inline bool is_private_network_order(in_addr_t addr) {
return (((addr & 0xFF) == 0x0A) || // 10.0.0.0/8
((addr & 0xC0FF) == 0x4064) || // 100.64.0.0/10
((addr & 0xF0FF) == 0x10AC) || // 172.16.0.0/12
((addr & 0xFFFF) == 0xA8C0) // 192.168.0.0/16
);
}
inline bool is_link_local_network_order(in_addr_t addr) {
return (addr & 0xFFFF) == 0xFEA9; // 169.254.0.0/16
}
inline bool is_multicast_network_order(in_addr_t addr) {
return (addr & 0xF0) == 0xE0;
}
#else
inline bool is_loopback_network_order(in_addr_t addr) {
return is_loopback_host_order(addr);
}
inline bool is_link_local_network_order(inaddr_t addr) {
return is_link_local_host_order(addr);
}
inline bool is_private_network_order(in_addr_t addr) {
return is_link_local_host_order(addr);
}
inline bool is_multicast_network_order(in_addr_t addr) {
return is_multicast_host_order(addr);
}
#endif
/** Check if the address in a socket address is a loopback address..
* @return @c true if so, @c false if not.
*/
inline bool is_loopback(sockaddr const * sa) {
return ( sa->sa_family == AF_INET && is_loopback_network_order(reinterpret_cast<sockaddr_in const *>(sa)->sin_addr.s_addr)) ||
( sa->sa_family == AF_INET6 && is_loopback_network_order(reinterpret_cast<sockaddr_in6 const *>(sa)->sin6_addr))
;
}
/** Check if the address in a socket address is multicast.
* @return @c true if so, @c false if not.
*/
inline bool is_multicast(sockaddr const * sa) {
return ( sa->sa_family == AF_INET && is_multicast_network_order(reinterpret_cast<sockaddr_in const *>(sa)->sin_addr.s_addr)) ||
( sa->sa_family == AF_INET6 && is_multicast_network_order(reinterpret_cast<sockaddr_in6 const *>(sa)->sin6_addr))
;
}
/** Check if the IP address in a socket address is link local.
* @return @c true if link local, @c false if not.
*/
inline bool is_link_local(sockaddr const* sa) {
return ( sa->sa_family == AF_INET && is_link_local_network_order(reinterpret_cast<sockaddr_in const *>(sa)->sin_addr.s_addr)) ||
( sa->sa_family == AF_INET6 && is_link_local_network_order(reinterpret_cast<sockaddr_in6 const *>(sa)->sin6_addr))
;
}
/** Check if the IP address in a socket address is private (non-routable)
* @return @c true if private, @c false if not.
*/
inline bool is_private(sockaddr const* sa) {
return ( sa->sa_family == AF_INET && is_private_network_order(reinterpret_cast<sockaddr_in const *>(sa)->sin_addr.s_addr)) ||
( sa->sa_family == AF_INET6 && is_private_network_order(reinterpret_cast<sockaddr_in6 const *>(sa)->sin6_addr))
;
}
} // hnamespace ip
}} // namespace swoc::SWOC_VERSION_NS