216 lines
7.2 KiB
Diff
216 lines
7.2 KiB
Diff
|
|
From 535be2f5d355d61332043c7fdc06e095e52a3937 Mon Sep 17 00:00:00 2001
|
||
|
|
From: Simon Kelley <simon@thekelleys.org.uk>
|
||
|
|
Date: Sat, 8 Feb 2025 22:58:42 +0000
|
||
|
|
Subject: [PATCH] Fix possible SIGSEGV in bpf.c
|
||
|
|
|
||
|
|
Conflict:Context adaptation
|
||
|
|
Reference:https://thekelleys.org.uk/gitweb/?p=dnsmasq.git;a=patch;h=535be2f5d355d61332043c7fdc06e095e52a3937
|
||
|
|
|
||
|
|
---
|
||
|
|
src/bpf.c | 170 ++++++++++++++++++++++++++----------------------------
|
||
|
|
1 file changed, 83 insertions(+), 87 deletions(-)
|
||
|
|
|
||
|
|
diff --git a/src/bpf.c b/src/bpf.c
|
||
|
|
index 15c42fc..4620b3f 100644
|
||
|
|
--- a/src/bpf.c
|
||
|
|
+++ b/src/bpf.c
|
||
|
|
@@ -126,112 +126,108 @@ int iface_enumerate(int family, void *parm, int (*callback)())
|
||
|
|
|
||
|
|
for (addrs = head; addrs; addrs = addrs->ifa_next)
|
||
|
|
{
|
||
|
|
- if (addrs->ifa_addr->sa_family == family)
|
||
|
|
- {
|
||
|
|
- int iface_index = if_nametoindex(addrs->ifa_name);
|
||
|
|
-
|
||
|
|
- if (iface_index == 0 || !addrs->ifa_addr ||
|
||
|
|
- (!addrs->ifa_netmask && family != AF_LINK))
|
||
|
|
- continue;
|
||
|
|
+ int iface_index = if_nametoindex(addrs->ifa_name);
|
||
|
|
|
||
|
|
- if (family == AF_INET)
|
||
|
|
- {
|
||
|
|
- struct in_addr addr, netmask, broadcast;
|
||
|
|
- addr = ((struct sockaddr_in *) addrs->ifa_addr)->sin_addr;
|
||
|
|
+ if (iface_index == 0 || !addrs->ifa_addr ||
|
||
|
|
+ addrs->ifa_addr->sa_family != family ||
|
||
|
|
+ (!addrs->ifa_netmask && family != AF_LINK))
|
||
|
|
+ continue;
|
||
|
|
+ if (family == AF_INET)
|
||
|
|
+ {
|
||
|
|
+ struct in_addr addr, netmask, broadcast;
|
||
|
|
+ addr = ((struct sockaddr_in *) addrs->ifa_addr)->sin_addr;
|
||
|
|
#ifdef HAVE_BSD_NETWORK
|
||
|
|
- if (del_family == AF_INET && del_addr.addr4.s_addr == addr.s_addr)
|
||
|
|
- continue;
|
||
|
|
+ if (del_family == AF_INET && del_addr.addr4.s_addr == addr.s_addr)
|
||
|
|
+ continue;
|
||
|
|
#endif
|
||
|
|
- netmask = ((struct sockaddr_in *) addrs->ifa_netmask)->sin_addr;
|
||
|
|
- if (addrs->ifa_broadaddr)
|
||
|
|
- broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr;
|
||
|
|
- else
|
||
|
|
- broadcast.s_addr = 0;
|
||
|
|
- if (!((*callback)(addr, iface_index, NULL, netmask, broadcast, parm)))
|
||
|
|
- goto err;
|
||
|
|
- }
|
||
|
|
- else if (family == AF_INET6)
|
||
|
|
- {
|
||
|
|
- struct in6_addr *addr = &((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_addr;
|
||
|
|
- unsigned char *netmask = (unsigned char *) &((struct sockaddr_in6 *) addrs->ifa_netmask)->sin6_addr;
|
||
|
|
- int scope_id = ((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_scope_id;
|
||
|
|
- int i, j, prefix = 0;
|
||
|
|
- u32 valid = 0xffffffff, preferred = 0xffffffff;
|
||
|
|
- int flags = 0;
|
||
|
|
+ netmask = ((struct sockaddr_in *) addrs->ifa_netmask)->sin_addr;
|
||
|
|
+ if (addrs->ifa_broadaddr)
|
||
|
|
+ broadcast = ((struct sockaddr_in *) addrs->ifa_broadaddr)->sin_addr;
|
||
|
|
+ else
|
||
|
|
+ broadcast.s_addr = 0;
|
||
|
|
+ if (!callback.af_inet(addr, iface_index, NULL, netmask, broadcast, parm))
|
||
|
|
+ goto err;
|
||
|
|
+ }
|
||
|
|
+ else if (family == AF_INET6)
|
||
|
|
+ {
|
||
|
|
+ struct in6_addr *addr = &((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_addr;
|
||
|
|
+ unsigned char *netmask = (unsigned char *) &((struct sockaddr_in6 *) addrs->ifa_netmask)->sin6_addr;
|
||
|
|
+ int scope_id = ((struct sockaddr_in6 *) addrs->ifa_addr)->sin6_scope_id;
|
||
|
|
+ int i, j, prefix = 0;
|
||
|
|
+ u32 valid = 0xffffffff, preferred = 0xffffffff;
|
||
|
|
+ int flags = 0;
|
||
|
|
#ifdef HAVE_BSD_NETWORK
|
||
|
|
- if (del_family == AF_INET6 && IN6_ARE_ADDR_EQUAL(&del_addr.addr6, addr))
|
||
|
|
- continue;
|
||
|
|
+ if (del_family == AF_INET6 && IN6_ARE_ADDR_EQUAL(&del_addr.addr6, addr))
|
||
|
|
+ continue;
|
||
|
|
#endif
|
||
|
|
#if defined(HAVE_BSD_NETWORK) && !defined(__APPLE__)
|
||
|
|
- struct in6_ifreq ifr6;
|
||
|
|
-
|
||
|
|
- memset(&ifr6, 0, sizeof(ifr6));
|
||
|
|
- safe_strncpy(ifr6.ifr_name, addrs->ifa_name, sizeof(ifr6.ifr_name));
|
||
|
|
+ struct in6_ifreq ifr6;
|
||
|
|
+
|
||
|
|
+ memset(&ifr6, 0, sizeof(ifr6));
|
||
|
|
+ safe_strncpy(ifr6.ifr_name, addrs->ifa_name, sizeof(ifr6.ifr_name));
|
||
|
|
+
|
||
|
|
+ ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
|
||
|
|
+ if (fd != -1 && ioctl(fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
|
||
|
|
+ {
|
||
|
|
+ if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE)
|
||
|
|
+ flags |= IFACE_TENTATIVE;
|
||
|
|
|
||
|
|
- ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
|
||
|
|
- if (fd != -1 && ioctl(fd, SIOCGIFAFLAG_IN6, &ifr6) != -1)
|
||
|
|
- {
|
||
|
|
- if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_TENTATIVE)
|
||
|
|
- flags |= IFACE_TENTATIVE;
|
||
|
|
-
|
||
|
|
- if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED)
|
||
|
|
- flags |= IFACE_DEPRECATED;
|
||
|
|
+ if (ifr6.ifr_ifru.ifru_flags6 & IN6_IFF_DEPRECATED)
|
||
|
|
+ flags |= IFACE_DEPRECATED;
|
||
|
|
|
||
|
|
#ifdef IN6_IFF_TEMPORARY
|
||
|
|
- if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_TEMPORARY)))
|
||
|
|
- flags |= IFACE_PERMANENT;
|
||
|
|
+ if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_TEMPORARY)))
|
||
|
|
+ flags |= IFACE_PERMANENT;
|
||
|
|
#endif
|
||
|
|
|
||
|
|
#ifdef IN6_IFF_PRIVACY
|
||
|
|
- if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_PRIVACY)))
|
||
|
|
- flags |= IFACE_PERMANENT;
|
||
|
|
-#endif
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
|
||
|
|
- if (fd != -1 && ioctl(fd, SIOCGIFALIFETIME_IN6, &ifr6) != -1)
|
||
|
|
- {
|
||
|
|
- valid = ifr6.ifr_ifru.ifru_lifetime.ia6t_vltime;
|
||
|
|
- preferred = ifr6.ifr_ifru.ifru_lifetime.ia6t_pltime;
|
||
|
|
- }
|
||
|
|
+ if (!(ifr6.ifr_ifru.ifru_flags6 & (IN6_IFF_AUTOCONF | IN6_IFF_PRIVACY)))
|
||
|
|
+ flags |= IFACE_PERMANENT;
|
||
|
|
#endif
|
||
|
|
-
|
||
|
|
- for (i = 0; i < IN6ADDRSZ; i++, prefix += 8)
|
||
|
|
- if (netmask[i] != 0xff)
|
||
|
|
- break;
|
||
|
|
-
|
||
|
|
- if (i != IN6ADDRSZ && netmask[i])
|
||
|
|
- for (j = 7; j > 0; j--, prefix++)
|
||
|
|
- if ((netmask[i] & (1 << j)) == 0)
|
||
|
|
- break;
|
||
|
|
-
|
||
|
|
- /* voodoo to clear interface field in address */
|
||
|
|
- if (!option_bool(OPT_NOWILD) && IN6_IS_ADDR_LINKLOCAL(addr))
|
||
|
|
- {
|
||
|
|
- addr->s6_addr[2] = 0;
|
||
|
|
- addr->s6_addr[3] = 0;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
- if (!((*callback)(addr, prefix, scope_id, iface_index, flags,
|
||
|
|
- (int) preferred, (int)valid, parm)))
|
||
|
|
- goto err;
|
||
|
|
- }
|
||
|
|
|
||
|
|
-#ifdef HAVE_DHCP6
|
||
|
|
- else if (family == AF_LINK)
|
||
|
|
- {
|
||
|
|
- /* Assume ethernet again here */
|
||
|
|
- struct sockaddr_dl *sdl = (struct sockaddr_dl *) addrs->ifa_addr;
|
||
|
|
- if (sdl->sdl_alen != 0 &&
|
||
|
|
- !((*callback)(iface_index, ARPHRD_ETHER, LLADDR(sdl), sdl->sdl_alen, parm)))
|
||
|
|
- goto err;
|
||
|
|
+ ifr6.ifr_addr = *((struct sockaddr_in6 *) addrs->ifa_addr);
|
||
|
|
+ if (fd != -1 && ioctl(fd, SIOCGIFALIFETIME_IN6, &ifr6) != -1)
|
||
|
|
+ {
|
||
|
|
+ valid = ifr6.ifr_ifru.ifru_lifetime.ia6t_vltime;
|
||
|
|
+ preferred = ifr6.ifr_ifru.ifru_lifetime.ia6t_pltime;
|
||
|
|
}
|
||
|
|
-#endif
|
||
|
|
+#endif
|
||
|
|
+
|
||
|
|
+ for (i = 0; i < IN6ADDRSZ; i++, prefix += 8)
|
||
|
|
+ if (netmask[i] != 0xff)
|
||
|
|
+ break;
|
||
|
|
+
|
||
|
|
+ if (i != IN6ADDRSZ && netmask[i])
|
||
|
|
+ for (j = 7; j > 0; j--, prefix++)
|
||
|
|
+ if ((netmask[i] & (1 << j)) == 0)
|
||
|
|
+ break;
|
||
|
|
+
|
||
|
|
+ /* voodoo to clear interface field in address */
|
||
|
|
+ if (!option_bool(OPT_NOWILD) && IN6_IS_ADDR_LINKLOCAL(addr))
|
||
|
|
+ {
|
||
|
|
+ addr->s6_addr[2] = 0;
|
||
|
|
+ addr->s6_addr[3] = 0;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ if (!callback.af_inet6(addr, prefix, scope_id, iface_index, flags,
|
||
|
|
+ (unsigned int) preferred, (unsigned int)valid, parm))
|
||
|
|
+ goto err;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+#ifdef HAVE_DHCP6
|
||
|
|
+ else if (family == AF_LINK)
|
||
|
|
+ {
|
||
|
|
+ /* Assume ethernet again here */
|
||
|
|
+ struct sockaddr_dl *sdl = (struct sockaddr_dl *) addrs->ifa_addr;
|
||
|
|
+ if (sdl->sdl_alen != 0 &&
|
||
|
|
+ !callback.af_local(iface_index, ARPHRD_ETHER, LLADDR(sdl), sdl->sdl_alen, parm))
|
||
|
|
+ goto err;
|
||
|
|
}
|
||
|
|
+#endif
|
||
|
|
}
|
||
|
|
|
||
|
|
ret = 1;
|
||
|
|
-
|
||
|
|
+
|
||
|
|
err:
|
||
|
|
errsave = errno;
|
||
|
|
freeifaddrs(head);
|
||
|
|
--
|
||
|
|
2.33.0
|
||
|
|
|