From: Vincent Bernat Date: Sat, 14 May 2016 17:46:07 +0000 (+0200) Subject: interfaces: ensure we don't break strict aliasing rule X-Git-Tag: 0.9.3~22 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b562f01fe4fdd24e6819f383e65017b680a159f5;p=thirdparty%2Flldpd.git interfaces: ensure we don't break strict aliasing rule Use an union to manipulate IPv4/IPv6 address. Other occurrences are using memcpy (notably with "struct sockaddr_storage"). This is preventive since gcc seems to rely more on this strict aliasing rule since gcc-6. --- diff --git a/src/daemon/interfaces.c b/src/daemon/interfaces.c index eab78893..bc3e41a5 100644 --- a/src/daemon/interfaces.c +++ b/src/daemon/interfaces.c @@ -376,8 +376,8 @@ interfaces_helper_mgmt_for_af(struct lldpd *cfg, struct lldpd_mgmt *mgmt; char addrstrbuf[INET6_ADDRSTRLEN]; int found = 0; - void *sin_addr_ptr; - size_t sin_addr_size; + union lldpd_address in_addr; + size_t in_addr_size; TAILQ_FOREACH(addr, addrs, next) { if (addr->address.ss_family != lldpd_af(af)) @@ -385,24 +385,26 @@ interfaces_helper_mgmt_for_af(struct lldpd *cfg, switch (af) { case LLDPD_AF_IPV4: - sin_addr_ptr = &((struct sockaddr_in *)&addr->address)->sin_addr; - sin_addr_size = sizeof(struct in_addr); + in_addr_size = sizeof(struct in_addr); + memcpy(&in_addr, &((struct sockaddr_in *)&addr->address)->sin_addr, + in_addr_size); if (global) { - if (!IN_IS_ADDR_GLOBAL((struct in_addr *)sin_addr_ptr)) + if (!IN_IS_ADDR_GLOBAL(&in_addr.inet)) continue; } else { - if (!IN_IS_ADDR_LINKLOCAL((struct in_addr *)sin_addr_ptr)) + if (!IN_IS_ADDR_LINKLOCAL(&in_addr.inet)) continue; } break; case LLDPD_AF_IPV6: - sin_addr_ptr = &((struct sockaddr_in6 *)&addr->address)->sin6_addr; - sin_addr_size = sizeof(struct in6_addr); + in_addr_size = sizeof(struct in6_addr); + memcpy(&in_addr, &((struct sockaddr_in6 *)&addr->address)->sin6_addr, + in_addr_size); if (global) { - if (!IN6_IS_ADDR_GLOBAL((struct in6_addr *)sin_addr_ptr)) + if (!IN6_IS_ADDR_GLOBAL(&in_addr.inet6)) continue; } else { - if (!IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)sin_addr_ptr)) + if (!IN6_IS_ADDR_LINKLOCAL(&in_addr.inet6)) continue; } break; @@ -410,14 +412,14 @@ interfaces_helper_mgmt_for_af(struct lldpd *cfg, assert(0); continue; } - if (inet_ntop(lldpd_af(af), sin_addr_ptr, + if (inet_ntop(lldpd_af(af), &in_addr, addrstrbuf, sizeof(addrstrbuf)) == NULL) { log_warn("interfaces", "unable to convert IP address to a string"); continue; } if (cfg->g_config.c_mgmt_pattern == NULL || pattern_match(addrstrbuf, cfg->g_config.c_mgmt_pattern, allnegative)) { - mgmt = lldpd_alloc_mgmt(af, sin_addr_ptr, sin_addr_size, + mgmt = lldpd_alloc_mgmt(af, &in_addr, in_addr_size, addr->index); if (mgmt == NULL) { assert(errno == ENOMEM); /* anything else is a bug */ diff --git a/src/lldpd-structs.h b/src/lldpd-structs.h index 707b7a22..0260ae7a 100644 --- a/src/lldpd-structs.h +++ b/src/lldpd-structs.h @@ -148,14 +148,15 @@ lldpd_af(int af) } #define LLDPD_MGMT_MAXADDRSIZE 16 /* sizeof(struct in6_addr) */ +union lldpd_address { + struct in_addr inet; + struct in6_addr inet6; + u_int8_t octets[LLDPD_MGMT_MAXADDRSIZE]; /* network byte order! */ +}; struct lldpd_mgmt { TAILQ_ENTRY(lldpd_mgmt) m_entries; - int m_family; - union { - struct in_addr inet; - struct in6_addr inet6; - u_int8_t octets[LLDPD_MGMT_MAXADDRSIZE]; /* network byte order! */ - } m_addr; + int m_family; + union lldpd_address m_addr; size_t m_addrsize; u_int32_t m_iface; };