diff options
author | Rich Felker <dalias@aerifal.cx> | 2025-07-30 09:32:02 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2025-07-30 09:32:02 -0400 |
commit | a6244de1c94588cd8cc965c15619d2649418f7a3 (patch) | |
tree | 8b2aad3e37d47ca1f9d90d2d2be6bc0e383d387f | |
parent | 8fd5d031876345e42ae3d11cc07b962f8625bc3b (diff) | |
download | musl-a6244de1c94588cd8cc965c15619d2649418f7a3.tar.gz |
fix erroneous definition of IN6_IS_ADDR_V4COMPAT
v4-compatible addresses in ipv6 are a deprecated feature where the
high 96 bits are all zero and an ipv4 address is stored in the low
32 bits. however, since :: and ::1 are the unspecified and loopback
addresses, these two particular values are excluded from the
definition of the v4-compat class.
our version of the macro incorrectly assessed this condition by
checking only the high 96 and low 8 bits. this incorrectly excluded
the v4compat version of any ipv4 address ending in .1, not just ::1.
rather than writing out non-obvious or error-prone conditions on the
individual address bytes, just express the "not :: or ::1" condition
naturally using the existing IN6_IS_ADDR_UNSPECIFIED and
IN6_IS_ADDR_LOOPBACK macros, after checking that the high 96 bits are
all zero. any vaguely reasonable compiler will collapse out the
redundant tests of the upper bits as part of CSE.
-rw-r--r-- | include/netinet/in.h | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/include/netinet/in.h b/include/netinet/in.h index fb628b61..60bbaa75 100644 --- a/include/netinet/in.h +++ b/include/netinet/in.h @@ -132,7 +132,8 @@ uint16_t ntohs(uint16_t); #define IN6_IS_ADDR_V4COMPAT(a) \ (((uint32_t *) (a))[0] == 0 && ((uint32_t *) (a))[1] == 0 && \ - ((uint32_t *) (a))[2] == 0 && ((uint8_t *) (a))[15] > 1) + ((uint32_t *) (a))[2] == 0 && \ + !IN6_IS_ADDR_UNSPECIFIED(a) && !IN6_IS_ADDR_LOOPBACK(a)) #define IN6_IS_ADDR_MC_NODELOCAL(a) \ (IN6_IS_ADDR_MULTICAST(a) && ((((uint8_t *) (a))[1] & 0xf) == 0x1)) |