import of dnsmasq-2.41.tar.gz
diff --git a/src/bpf.c b/src/bpf.c
index 2dbc4f1..1b71f3c 100644
--- a/src/bpf.c
+++ b/src/bpf.c
@@ -1,20 +1,22 @@
-/* dnsmasq is Copyright (c) 2000-2006 Simon Kelley
+/* dnsmasq is Copyright (c) 2000-2007 Simon Kelley
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; version 2 dated June, 1991.
-
+ the Free Software Foundation; version 2 dated June, 1991, or
+ (at your option) version 3 dated 29 June, 2007.
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "dnsmasq.h"
-#ifndef HAVE_LINUX_NETWORK
-
-#include <net/bpf.h>
+#if defined(HAVE_BSD_NETWORK) || defined(HAVE_SOLARIS_NETWORK)
static struct iovec ifconf = {
.iov_base = NULL,
@@ -26,6 +28,107 @@
.iov_len = 0
};
+int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)())
+{
+ char *ptr;
+ struct ifreq *ifr;
+ struct ifconf ifc;
+ int fd, errsav, ret = 0;
+ int lastlen = 0;
+ size_t len = 0;
+
+ if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
+ return 0;
+
+ while(1)
+ {
+ len += 10*sizeof(struct ifreq);
+
+ if (!expand_buf(&ifconf, len))
+ goto err;
+
+ ifc.ifc_len = len;
+ ifc.ifc_buf = ifconf.iov_base;
+
+ if (ioctl(fd, SIOCGIFCONF, &ifc) == -1)
+ {
+ if (errno != EINVAL || lastlen != 0)
+ goto err;
+ }
+ else
+ {
+ if (ifc.ifc_len == lastlen)
+ break; /* got a big enough buffer now */
+ lastlen = ifc.ifc_len;
+ }
+ }
+
+ for (ptr = ifc.ifc_buf; ptr < ifc.ifc_buf + ifc.ifc_len; ptr += len )
+ {
+ /* subsequent entries may not be aligned, so copy into
+ an aligned buffer to avoid nasty complaints about
+ unaligned accesses. */
+#ifdef HAVE_SOCKADDR_SA_LEN
+ len = ((struct ifreq *)ptr)->ifr_addr.sa_len + IF_NAMESIZE;
+#else
+ len = sizeof(struct ifreq);
+#endif
+ if (!expand_buf(&ifreq, len))
+ goto err;
+
+ ifr = (struct ifreq *)ifreq.iov_base;
+ memcpy(ifr, ptr, len);
+
+ if (ifr->ifr_addr.sa_family == AF_INET && ipv4_callback)
+ {
+ struct in_addr addr, netmask, broadcast;
+ broadcast.s_addr = 0;
+ addr = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr;
+ if (ioctl(fd, SIOCGIFNETMASK, ifr) == -1)
+ continue;
+ netmask = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr;
+ if (ioctl(fd, SIOCGIFBRDADDR, ifr) != -1)
+ broadcast = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr;
+ if (!((*ipv4_callback)(addr,
+ (int)if_nametoindex(ifr->ifr_name),
+ netmask, broadcast,
+ parm)))
+ goto err;
+ }
+#ifdef HAVE_IPV6
+ else if (ifr->ifr_addr.sa_family == AF_INET6 && ipv6_callback)
+ {
+ struct in6_addr *addr = &((struct sockaddr_in6 *)&ifr->ifr_addr)->sin6_addr;
+ /* voodoo to clear interface field in address */
+ if (!(daemon->options & OPT_NOWILD) && IN6_IS_ADDR_LINKLOCAL(addr))
+ {
+ addr->s6_addr[2] = 0;
+ addr->s6_addr[3] = 0;
+ }
+ if (!((*ipv6_callback)(addr,
+ (int)((struct sockaddr_in6 *)&ifr->ifr_addr)->sin6_scope_id,
+ (int)if_nametoindex(ifr->ifr_name),
+ parm)))
+ goto err;
+ }
+#endif
+ }
+
+ ret = 1;
+
+ err:
+ errsav = errno;
+ close(fd);
+ errno = errsav;
+
+ return ret;
+}
+#endif
+
+
+#if defined(HAVE_BSD_NETWORK)
+#include <net/bpf.h>
+
void init_bpf(void)
{
int i = 0;
@@ -116,8 +219,10 @@
udp.uh_sum = 0;
udp.uh_ulen = sum = htons(sizeof(struct udphdr) + len);
sum += htons(IPPROTO_UDP);
- for (i = 0; i < 4; i++)
- sum += ((u16 *)&ip.ip_src)[i];
+ sum += ip.ip_src.s_addr & 0xffff;
+ sum += (ip.ip_src.s_addr >> 16) & 0xffff;
+ sum += ip.ip_dst.s_addr & 0xffff;
+ sum += (ip.ip_dst.s_addr >> 16) & 0xffff;
for (i = 0; i < sizeof(struct udphdr)/2; i++)
sum += ((u16 *)&udp)[i];
for (i = 0; i < (len + 1) / 2; i++)
@@ -140,100 +245,6 @@
while (writev(daemon->dhcp_raw_fd, iov, 4) == -1 && retry_send());
}
-int iface_enumerate(void *parm, int (*ipv4_callback)(), int (*ipv6_callback)())
-{
- char *ptr;
- struct ifreq *ifr;
- struct ifconf ifc;
- int fd, errsav, ret = 0;
- int lastlen = 0;
- size_t len = 0;
-
- if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) == -1)
- return 0;
-
- while(1)
- {
- len += 10*sizeof(struct ifreq);
-
- if (!expand_buf(&ifconf, len))
- goto err;
-
- ifc.ifc_len = len;
- ifc.ifc_buf = ifconf.iov_base;
-
- if (ioctl(fd, SIOCGIFCONF, &ifc) == -1)
- {
- if (errno != EINVAL || lastlen != 0)
- goto err;
- }
- else
- {
- if (ifc.ifc_len == lastlen)
- break; /* got a big enough buffer now */
- lastlen = ifc.ifc_len;
- }
- }
-
- for (ptr = ifc.ifc_buf; ptr < ifc.ifc_buf + ifc.ifc_len; ptr += len )
- {
- /* subsequent entries may not be aligned, so copy into
- an aligned buffer to avoid nasty complaints about
- unaligned accesses. */
-#ifdef HAVE_SOCKADDR_SA_LEN
- len = ((struct ifreq *)ptr)->ifr_addr.sa_len + IF_NAMESIZE;
-#else
- len = sizeof(struct ifreq);
#endif
- if (!expand_buf(&ifreq, len))
- goto err;
- ifr = ifreq.iov_base;
- memcpy(ifr, ptr, len);
-
- if (ifr->ifr_addr.sa_family == AF_INET && ipv4_callback)
- {
- struct in_addr addr, netmask, broadcast;
- broadcast.s_addr = 0;
- addr = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr;
- if (ioctl(fd, SIOCGIFNETMASK, ifr) == -1)
- continue;
- netmask = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr;
- if (ioctl(fd, SIOCGIFBRDADDR, ifr) != -1)
- broadcast = ((struct sockaddr_in *) &ifr->ifr_addr)->sin_addr;
- if (!((*ipv4_callback)(addr,
- (int)if_nametoindex(ifr->ifr_name),
- netmask, broadcast,
- parm)))
- goto err;
- }
-#ifdef HAVE_IPV6
- else if (ifr->ifr_addr.sa_family == AF_INET6 && ipv6_callback)
- {
- struct in6_addr *addr = &((struct sockaddr_in6 *)&ifr->ifr_addr)->sin6_addr;
- /* voodoo to clear interface field in address */
- if (!(daemon->options & OPT_NOWILD) && IN6_IS_ADDR_LINKLOCAL(addr))
- {
- addr->s6_addr[2] = 0;
- addr->s6_addr[3] = 0;
- }
- if (!((*ipv6_callback)(addr,
- (int)((struct sockaddr_in6 *)&ifr->ifr_addr)->sin6_scope_id,
- (int)if_nametoindex(ifr->ifr_name),
- parm)))
- goto err;
- }
-#endif
- }
-
- ret = 1;
- err:
- errsav = errno;
- close(fd);
- errno = errsav;
-
- return ret;
-}
-
-#endif