Let's look at what your macro is actually doing. Given ...
const struct sockaddr_storage *a;
... the expression (uint64_t *)IP_AS_V6(a, addr).s6_addr)[0]
expands to...
(uint64_t *)((struct sockaddr_in6 *)&(a))->sin6_addr.s6_addr)[0]
In the first place, you've got your levels of indirection messed up, at least if a
in fact points to a struct sockaddr_in6
. &(a)
is a pointer to the struct pointer, which is of no use for your purpose at all. You presumably meant just (a)
, not its address. This is probably the origin of the compiler's complaint.
In the second place, (struct sockaddr_in6 *)(a))->sin6_addr.s6_addr
has type unsigned char[16]
. That is automatically converted to an unsigned char *
which you might safely be able to convert to type uint64_t *
, but then again you might not. If the resulting pointer is not correctly aligned for a uint64_t *
then undefined behavior results, and it's not clear to me that there's anything to ensure that the alignment works out.
In the third place, even if the alignment worked out, accessing parts of an unsigned char[]
via an lvalue of type uint64_t
is a violation of the strict aliasing rule, producing undefined behavior.
The function also casts away const
ness, which is poor form and should elicit a warning, even though it doesn't try to modify either object.
I think I would write the function this way:
static inline int ip_check_equal_v6(const struct sockaddr_storage *a,
const struct sockaddr_storage *b) {
const struct sockaddr_in6 *a6 = (const struct sockaddr_in6 *) a;
const struct sockaddr_in6 *b6 = (const struct sockaddr_in6 *) b;
return !memcmp(a6->sin6_addr.s6_addr, a6->sin6_addr.s6_addr,
sizeof(a6->sin6_addr.s6_addr));
}
That returns 1 if the address bytes in the first address are all the same as those in the second (with both interpreted as IPV6 addresses), and 0 if any of them differ, which appears to be what your version is intended to do. And do note how incredibly much easier than the original it is to read, which makes it much easier to maintain, and even much easier to evaluate by eye. Your compiler might even be able to optimize it better than the original, though I make no promises about that.