summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2025-07-30 09:32:02 -0400
committerRich Felker <dalias@aerifal.cx>2025-07-30 09:32:02 -0400
commita6244de1c94588cd8cc965c15619d2649418f7a3 (patch)
tree8b2aad3e37d47ca1f9d90d2d2be6bc0e383d387f
parent8fd5d031876345e42ae3d11cc07b962f8625bc3b (diff)
downloadmusl-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.h3
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))