/* SPDX-License-Identifier: AGPL-3.0-or-later * Copyright Red Hat * Author: David Gibson * * inany.h - Types and helpers for handling addresses which could be * IPv6 or IPv4 (encoded as IPv4-mapped IPv6 addresses) */ #include /** union inany_addr - Represents either an IPv4 or IPv6 address * @a6: Address as an IPv6 address, may be IPv4-mapped * @_v4._zero: All zero-bits for an IPv4 address * @_v4._one: All one-bits for an IPv4 address * @_v4.a4: If @a6 is an IPv4 mapped address, this is the raw IPv4 address * * Fields starting with _ shouldn't be accessed except via helpers. */ union inany_addr { struct in6_addr a6; struct { uint8_t _zero[10]; uint8_t _one[2]; struct in_addr a4; } _v4mapped; }; /** inany_v4 - Extract IPv4 address, if present, from IPv[46] address * @addr: IPv4 or IPv6 address * * Return: IPv4 address if @addr is IPv4, NULL otherwise */ static inline const struct in_addr *inany_v4(const union inany_addr *addr) { if (!IN6_IS_ADDR_V4MAPPED(&addr->a6)) return NULL; return &addr->_v4mapped.a4; } /** inany_equals - Compare two IPv[46] addresses * @a, @b: IPv[46] addresses * * Return: true if @a and @b are the same address */ static inline bool inany_equals(const union inany_addr *a, const union inany_addr *b) { return IN6_ARE_ADDR_EQUAL(&a->a6, &b->a6); } /** inany_from_af - Set IPv[46] address from IPv4 or IPv6 address * @aa: Pointer to store IPv[46] address * @af: Address family of @addr * @addr: struct in_addr (IPv4) or struct in6_addr (IPv6) */ static inline void inany_from_af(union inany_addr *aa, int af, const void *addr) { if (af == AF_INET6) { aa->a6 = *((struct in6_addr *)addr); } else if (af == AF_INET) { memset(&aa->_v4mapped._zero, 0, sizeof(aa->_v4mapped._zero)); memset(&aa->_v4mapped._one, 0xff, sizeof(aa->_v4mapped._one)); aa->_v4mapped.a4 = *((struct in_addr *)addr); } else { /* Not valid to call with other address families */ assert(0); } }