import of dnsmasq-2.18.tar.gz
diff --git a/src/network.c b/src/network.c
index 71b7342..7815ae6 100644
--- a/src/network.c
+++ b/src/network.c
@@ -14,11 +14,33 @@
#include "dnsmasq.h"
-static struct irec *add_iface(struct daemon *daemon, struct irec *list, char *name, union mysockaddr *addr)
+static struct irec *add_iface(struct daemon *daemon, struct irec *list,
+ char *name, int is_loopback, union mysockaddr *addr)
{
struct irec *iface;
struct iname *tmp;
+ /* If we are restricting the set of interfaces to use, make
+ sure that loopback interfaces are in that set. */
+ if (daemon->if_names && is_loopback)
+ {
+ struct iname *lo;
+ for (lo = daemon->if_names; lo; lo = lo->next)
+ if (lo->name && strcmp(lo->name, name) == 0)
+ {
+ lo->isloop = 1;
+ break;
+ }
+ if (!lo)
+ {
+ lo = safe_malloc(sizeof(struct iname));
+ lo->name = safe_string_alloc(name);
+ lo->isloop = lo->used = 1;
+ lo->next = daemon->if_names;
+ daemon->if_names = lo;
+ }
+ }
+
/* check blacklist */
if (daemon->if_except)
for (tmp = daemon->if_except; tmp; tmp = tmp->next)
@@ -67,6 +89,10 @@
struct irec *enumerate_interfaces(struct daemon *daemon)
{
+#if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6)
+ FILE *f;
+#endif
+ union mysockaddr addr;
struct irec *iface = NULL;
char *buf, *ptr;
struct ifreq *ifr = NULL;
@@ -74,7 +100,7 @@
int lastlen = 0;
int len = 20 * sizeof(struct ifreq);
int fd = socket(PF_INET, SOCK_DGRAM, 0);
-
+
if (fd == -1)
die ("cannot create socket to enumerate interfaces: %s", NULL);
@@ -99,9 +125,8 @@
free(buf);
}
- for (ptr = buf; ptr < buf + len; )
+ for (ptr = buf; ptr < buf + ifc.ifc_len; )
{
- union mysockaddr addr;
#ifdef HAVE_SOCKADDR_SA_LEN
/* subsequent entries may not be aligned, so copy into
an aligned buffer to avoid nasty complaints about
@@ -141,76 +166,47 @@
if (ioctl(fd, SIOCGIFFLAGS, ifr) < 0)
die("ioctl error getting interface flags: %m", NULL);
- /* If we are restricting the set of interfaces to use, make
- sure that loopback interfaces are in that set. */
- if (daemon->if_names && (ifr->ifr_flags & IFF_LOOPBACK))
- {
- struct iname *lo;
- for (lo = daemon->if_names; lo; lo = lo->next)
- if (lo->name && strcmp(lo->name, ifr->ifr_name) == 0)
- {
- lo->isloop = 1;
- break;
- }
- if (!lo)
- {
- lo = safe_malloc(sizeof(struct iname));
- lo->name = safe_string_alloc(ifr->ifr_name);
- lo->isloop = lo->used = 1;
- lo->next = daemon->if_names;
- daemon->if_names = lo;
- }
- }
-
- iface = add_iface(daemon, iface, ifr->ifr_name, &addr);
-
-#if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6)
- /* IPv6 addresses don't seem to work with SIOCGIFCONF. Barf */
- /* This code snarfed from net-tools 1.60 and certainly linux specific, though
- it shouldn't break on other Unices, and their SIOGIFCONF might work. */
- {
- FILE *f = fopen(IP6INTERFACES, "r");
- int found = 0;
- union mysockaddr addr6;
-
- if (f)
- {
- unsigned int plen, scope, flags, if_idx;
- char devname[20], addrstring[32];
-
- while (fscanf(f, "%32s %02x %02x %02x %02x %20s\n",
- addrstring, &if_idx, &plen, &scope, &flags, devname) != EOF)
- {
- if (strcmp(devname, ifr->ifr_name) == 0)
- {
- int i;
- unsigned char *addr6p = (unsigned char *) &addr6.in6.sin6_addr;
- memset(&addr6, 0, sizeof(addr6));
- addr6.sa.sa_family = AF_INET6;
- for (i=0; i<16; i++)
- {
- unsigned int byte;
- sscanf(addrstring+i+i, "%02x", &byte);
- addr6p[i] = byte;
- }
- addr6.in6.sin6_port = htons(daemon->port);
- addr6.in6.sin6_flowinfo = htonl(0);
- addr6.in6.sin6_scope_id = htonl(scope);
-
- found = 1;
- break;
- }
- }
-
- fclose(f);
- }
-
- if (found)
- iface = add_iface(daemon, iface, ifr->ifr_name, &addr6);
- }
-#endif /* LINUX */
+ iface = add_iface(daemon, iface, ifr->ifr_name, ifr->ifr_flags & IFF_LOOPBACK, &addr);
}
-
+
+#if defined(HAVE_LINUX_IPV6_PROC) && defined(HAVE_IPV6)
+ /* IPv6 addresses don't seem to work with SIOCGIFCONF. Barf */
+ /* This code snarfed from net-tools 1.60 and certainly linux specific, though
+ it shouldn't break on other Unices, and their SIOGIFCONF might work. */
+ if ((f = fopen(IP6INTERFACES, "r")))
+ {
+ unsigned int plen, scope, flags, if_idx;
+ char devname[20], addrstring[32];
+
+ while (fscanf(f, "%32s %02x %02x %02x %02x %20s\n",
+ addrstring, &if_idx, &plen, &scope, &flags, devname) != EOF)
+ {
+ int i;
+ struct ifreq sifr;
+ unsigned char *addr6p = (unsigned char *) &addr.in6.sin6_addr;
+ memset(&addr, 0, sizeof(addr));
+ addr.sa.sa_family = AF_INET6;
+ for (i=0; i<16; i++)
+ {
+ unsigned int byte;
+ sscanf(addrstring+i+i, "%02x", &byte);
+ addr6p[i] = byte;
+ }
+ addr.in6.sin6_port = htons(daemon->port);
+ addr.in6.sin6_flowinfo = htonl(0);
+ addr.in6.sin6_scope_id = htonl(scope);
+
+ strncpy(sifr.ifr_name, devname, IF_NAMESIZE);
+ if (ioctl(fd, SIOCGIFFLAGS, &sifr) < 0)
+ die("ioctl error getting interface flags: %m", NULL);
+
+ iface = add_iface(daemon, iface, sifr.ifr_name, sifr.ifr_flags & IFF_LOOPBACK, &addr);
+
+ }
+ fclose(f);
+ }
+#endif /* LINUX */
+
if (buf)
free(buf);
#ifdef HAVE_SOCKADDR_SA_LEN
@@ -361,7 +357,6 @@
struct listener *new = safe_malloc(sizeof(struct listener));
new->family = iface->addr.sa.sa_family;
new->next = listeners;
- listeners = new;
if ((new->tcpfd = socket(iface->addr.sa.sa_family, SOCK_STREAM, 0)) == -1 ||
(new->fd = socket(iface->addr.sa.sa_family, SOCK_DGRAM, 0)) == -1 ||
setsockopt(new->fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 ||
@@ -383,9 +378,25 @@
#endif
if (bind(new->tcpfd, &iface->addr.sa, sa_len(&iface->addr)) == -1 ||
- bind(new->fd, &iface->addr.sa, sa_len(&iface->addr)) == -1 ||
- listen(new->tcpfd, 5) == -1)
- die("failed to bind listening socket: %s", NULL);
+ bind(new->fd, &iface->addr.sa, sa_len(&iface->addr)) == -1)
+ {
+#ifdef HAVE_IPV6
+ if (iface->addr.sa.sa_family == AF_INET6 && errno == ENODEV)
+ {
+ close(new->tcpfd);
+ close(new->fd);
+ free(new);
+ }
+ else
+#endif
+ die("failed to bind listening socket: %s", NULL);
+ }
+ else
+ {
+ listeners = new;
+ if (listen(new->tcpfd, 5) == -1)
+ die("failed to listen on socket: %s", NULL);
+ }
}
return listeners;