"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/network.c" between
dnsmasq-2.80.tar.gz and dnsmasq-2.81.tar.xz

About: Dnsmasq is a lightweight caching DNS forwarder and DHCP server.

network.c  (dnsmasq-2.80):network.c  (dnsmasq-2.81.tar.xz)
/* dnsmasq is Copyright (c) 2000-2018 Simon Kelley /* dnsmasq is Copyright (c) 2000-2020 Simon Kelley
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 dated June, 1991, or the Free Software Foundation; version 2 dated June, 1991, or
(at your option) version 3 dated 29 June, 2007. (at your option) version 3 dated 29 June, 2007.
This program is distributed in the hope that it will be useful, This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
skipping to change at line 110 skipping to change at line 110
(void)fd; (void)fd;
if (index == 0 || !if_indextoname(index, name)) if (index == 0 || !if_indextoname(index, name))
return 0; return 0;
return 1; return 1;
} }
#endif #endif
int iface_check(int family, struct all_addr *addr, char *name, int *auth) int iface_check(int family, union all_addr *addr, char *name, int *auth)
{ {
struct iname *tmp; struct iname *tmp;
int ret = 1, match_addr = 0; int ret = 1, match_addr = 0;
/* Note: have to check all and not bail out early, so that we set the /* Note: have to check all and not bail out early, so that we set the
"used" flags. "used" flags.
May be called with family == AF_LOCALto check interface by name only. */ May be called with family == AF_LOCALto check interface by name only. */
if (auth) if (auth)
skipping to change at line 136 skipping to change at line 136
for (tmp = daemon->if_names; tmp; tmp = tmp->next) for (tmp = daemon->if_names; tmp; tmp = tmp->next)
if (tmp->name && wildcard_match(tmp->name, name)) if (tmp->name && wildcard_match(tmp->name, name))
ret = tmp->used = 1; ret = tmp->used = 1;
if (addr) if (addr)
for (tmp = daemon->if_addrs; tmp; tmp = tmp->next) for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
if (tmp->addr.sa.sa_family == family) if (tmp->addr.sa.sa_family == family)
{ {
if (family == AF_INET && if (family == AF_INET &&
tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr) tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
ret = match_addr = tmp->used = 1; ret = match_addr = tmp->used = 1;
#ifdef HAVE_IPV6
else if (family == AF_INET6 && else if (family == AF_INET6 &&
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr,
&addr->addr.addr6)) &addr->addr6))
ret = match_addr = tmp->used = 1; ret = match_addr = tmp->used = 1;
#endif
} }
} }
if (!match_addr) if (!match_addr)
for (tmp = daemon->if_except; tmp; tmp = tmp->next) for (tmp = daemon->if_except; tmp; tmp = tmp->next)
if (tmp->name && wildcard_match(tmp->name, name)) if (tmp->name && wildcard_match(tmp->name, name))
ret = 0; ret = 0;
for (tmp = daemon->authinterface; tmp; tmp = tmp->next) for (tmp = daemon->authinterface; tmp; tmp = tmp->next)
if (tmp->name) if (tmp->name)
{ {
if (strcmp(tmp->name, name) == 0 && if (strcmp(tmp->name, name) == 0 &&
(tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family)) (tmp->addr.sa.sa_family == 0 || tmp->addr.sa.sa_family == family))
break; break;
} }
else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET && else if (addr && tmp->addr.sa.sa_family == AF_INET && family == AF_INET &&
tmp->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr) tmp->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
break; break;
#ifdef HAVE_IPV6
else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 && else if (addr && tmp->addr.sa.sa_family == AF_INET6 && family == AF_INET6 &&
IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr.addr6)) IN6_ARE_ADDR_EQUAL(&tmp->addr.in6.sin6_addr, &addr->addr6))
break; break;
#endif
if (tmp && auth) if (tmp && auth)
{ {
*auth = 1; *auth = 1;
ret = 1; ret = 1;
} }
return ret; return ret;
} }
/* Fix for problem that the kernel sometimes reports the loopback interface as t he /* Fix for problem that the kernel sometimes reports the loopback interface as t he
arrival interface when a packet originates locally, even when sent to address of arrival interface when a packet originates locally, even when sent to address of
an interface other than the loopback. Accept packet if it arrived via a loopb ack an interface other than the loopback. Accept packet if it arrived via a loopb ack
interface, even when we're not accepting packets that way, as long as the des tination interface, even when we're not accepting packets that way, as long as the des tination
address is one we're believing. Interface list must be up-to-date before call ing. */ address is one we're believing. Interface list must be up-to-date before call ing. */
int loopback_exception(int fd, int family, struct all_addr *addr, char *name) int loopback_exception(int fd, int family, union all_addr *addr, char *name)
{ {
struct ifreq ifr; struct ifreq ifr;
struct irec *iface; struct irec *iface;
safe_strncpy(ifr.ifr_name, name, IF_NAMESIZE); safe_strncpy(ifr.ifr_name, name, IF_NAMESIZE);
if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 && if (ioctl(fd, SIOCGIFFLAGS, &ifr) != -1 &&
ifr.ifr_flags & IFF_LOOPBACK) ifr.ifr_flags & IFF_LOOPBACK)
{ {
for (iface = daemon->interfaces; iface; iface = iface->next) for (iface = daemon->interfaces; iface; iface = iface->next)
if (iface->addr.sa.sa_family == family) if (iface->addr.sa.sa_family == family)
{ {
if (family == AF_INET) if (family == AF_INET)
{ {
if (iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr) if (iface->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
return 1; return 1;
} }
#ifdef HAVE_IPV6 else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr6)
else if (IN6_ARE_ADDR_EQUAL(&iface->addr.in6.sin6_addr, &addr->addr.a )
ddr6))
return 1; return 1;
#endif
} }
} }
return 0; return 0;
} }
/* If we're configured with something like --interface=eth0:0 then we'll listen correctly /* If we're configured with something like --interface=eth0:0 then we'll listen correctly
on the relevant address, but the name of the arrival interface, derived from the on the relevant address, but the name of the arrival interface, derived from the
index won't match the config. Check that we found an interface address for th e arrival index won't match the config. Check that we found an interface address for th e arrival
interface: daemon->interfaces must be up-to-date. */ interface: daemon->interfaces must be up-to-date. */
int label_exception(int index, int family, struct all_addr *addr) int label_exception(int index, int family, union all_addr *addr)
{ {
struct irec *iface; struct irec *iface;
/* labels only supported on IPv4 addresses. */ /* labels only supported on IPv4 addresses. */
if (family != AF_INET) if (family != AF_INET)
return 0; return 0;
for (iface = daemon->interfaces; iface; iface = iface->next) for (iface = daemon->interfaces; iface; iface = iface->next)
if (iface->index == index && iface->addr.sa.sa_family == AF_INET && if (iface->index == index && iface->addr.sa.sa_family == AF_INET &&
iface->addr.in.sin_addr.s_addr == addr->addr.addr4.s_addr) iface->addr.in.sin_addr.s_addr == addr->addr4.s_addr)
return 1; return 1;
return 0; return 0;
} }
struct iface_param { struct iface_param {
struct addrlist *spare; struct addrlist *spare;
int fd; int fd;
}; };
skipping to change at line 288 skipping to change at line 281
al = whine_malloc(sizeof(struct addrlist)); al = whine_malloc(sizeof(struct addrlist));
if (al) if (al)
{ {
al->next = daemon->interface_addrs; al->next = daemon->interface_addrs;
daemon->interface_addrs = al; daemon->interface_addrs = al;
al->prefixlen = prefixlen; al->prefixlen = prefixlen;
if (addr->sa.sa_family == AF_INET) if (addr->sa.sa_family == AF_INET)
{ {
al->addr.addr.addr4 = addr->in.sin_addr; al->addr.addr4 = addr->in.sin_addr;
al->flags = 0; al->flags = 0;
} }
#ifdef HAVE_IPV6
else else
{ {
al->addr.addr.addr6 = addr->in6.sin6_addr; al->addr.addr6 = addr->in6.sin6_addr;
al->flags = ADDRLIST_IPV6; al->flags = ADDRLIST_IPV6;
} }
#endif
} }
} }
#ifdef HAVE_IPV6
if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_a ddr)) if (addr->sa.sa_family != AF_INET6 || !IN6_IS_ADDR_LINKLOCAL(&addr->in6.sin6_a ddr))
#endif
{ {
struct interface_name *int_name; struct interface_name *int_name;
struct addrlist *al; struct addrlist *al;
#ifdef HAVE_AUTH #ifdef HAVE_AUTH
struct auth_zone *zone; struct auth_zone *zone;
struct auth_name_list *name; struct auth_name_list *name;
/* Find subnets in auth_zones */ /* Find subnets in auth_zones */
for (zone = daemon->auth_zones; zone; zone = zone->next) for (zone = daemon->auth_zones; zone; zone = zone->next)
for (name = zone->interface_names; name; name = name->next) for (name = zone->interface_names; name; name = name->next)
skipping to change at line 331 skipping to change at line 320
param->spare = al->next; param->spare = al->next;
} }
else else
al = whine_malloc(sizeof(struct addrlist)); al = whine_malloc(sizeof(struct addrlist));
if (al) if (al)
{ {
al->next = zone->subnet; al->next = zone->subnet;
zone->subnet = al; zone->subnet = al;
al->prefixlen = prefixlen; al->prefixlen = prefixlen;
al->addr.addr.addr4 = addr->in.sin_addr; al->addr.addr4 = addr->in.sin_addr;
al->flags = 0; al->flags = 0;
} }
} }
#ifdef HAVE_IPV6
if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6)) if (addr->sa.sa_family == AF_INET6 && (name->flags & AUTH6))
{ {
if (param->spare) if (param->spare)
{ {
al = param->spare; al = param->spare;
param->spare = al->next; param->spare = al->next;
} }
else else
al = whine_malloc(sizeof(struct addrlist)); al = whine_malloc(sizeof(struct addrlist));
if (al) if (al)
{ {
al->next = zone->subnet; al->next = zone->subnet;
zone->subnet = al; zone->subnet = al;
al->prefixlen = prefixlen; al->prefixlen = prefixlen;
al->addr.addr.addr6 = addr->in6.sin6_addr; al->addr.addr6 = addr->in6.sin6_addr;
al->flags = ADDRLIST_IPV6; al->flags = ADDRLIST_IPV6;
} }
} }
#endif
} }
#endif #endif
/* Update addresses from interface_names. These are a set independent /* Update addresses from interface_names. These are a set independent
of the set we're listening on. */ of the set we're listening on. */
for (int_name = daemon->int_names; int_name; int_name = int_name->next) for (int_name = daemon->int_names; int_name; int_name = int_name->next)
if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0 && if (strncmp(label, int_name->intr, IF_NAMESIZE) == 0 &&
(addr->sa.sa_family == int_name->family || int_name->family == 0)) (addr->sa.sa_family == int_name->family || int_name->family == 0))
{ {
if (param->spare) if (param->spare)
skipping to change at line 382 skipping to change at line 368
else else
al = whine_malloc(sizeof(struct addrlist)); al = whine_malloc(sizeof(struct addrlist));
if (al) if (al)
{ {
al->next = int_name->addr; al->next = int_name->addr;
int_name->addr = al; int_name->addr = al;
if (addr->sa.sa_family == AF_INET) if (addr->sa.sa_family == AF_INET)
{ {
al->addr.addr.addr4 = addr->in.sin_addr; al->addr.addr4 = addr->in.sin_addr;
al->flags = 0; al->flags = 0;
} }
#ifdef HAVE_IPV6
else else
{ {
al->addr.addr.addr6 = addr->in6.sin6_addr; al->addr.addr6 = addr->in6.sin6_addr;
al->flags = ADDRLIST_IPV6; al->flags = ADDRLIST_IPV6;
/* Privacy addresses and addresses still undergoing DAD and d eprecated addresses /* Privacy addresses and addresses still undergoing DAD and d eprecated addresses
don't appear in forward queries, but will in reverse ones. */ don't appear in forward queries, but will in reverse ones. */
if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE _DEPRECATED | IFACE_TENTATIVE))) if (!(iface_flags & IFACE_PERMANENT) || (iface_flags & (IFACE _DEPRECATED | IFACE_TENTATIVE)))
al->flags |= ADDRLIST_REVONLY; al->flags |= ADDRLIST_REVONLY;
} }
#endif
} }
} }
} }
/* check whether the interface IP has been added already /* check whether the interface IP has been added already
we call this routine multiple times. */ we call this routine multiple times. */
for (iface = daemon->interfaces; iface; iface = iface->next) for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, addr)) if (sockaddr_isequal(&iface->addr, addr))
{ {
iface->dad = !!(iface_flags & IFACE_TENTATIVE); iface->dad = !!(iface_flags & IFACE_TENTATIVE);
skipping to change at line 434 skipping to change at line 418
lo->used = 1; lo->used = 1;
lo->next = daemon->if_names; lo->next = daemon->if_names;
daemon->if_names = lo; daemon->if_names = lo;
} }
else else
free(lo); free(lo);
} }
} }
if (addr->sa.sa_family == AF_INET && if (addr->sa.sa_family == AF_INET &&
!iface_check(AF_INET, (struct all_addr *)&addr->in.sin_addr, label, &auth_ dns)) !iface_check(AF_INET, (union all_addr *)&addr->in.sin_addr, label, &auth_d ns))
return 1; return 1;
#ifdef HAVE_IPV6
if (addr->sa.sa_family == AF_INET6 && if (addr->sa.sa_family == AF_INET6 &&
!iface_check(AF_INET6, (struct all_addr *)&addr->in6.sin6_addr, label, &au th_dns)) !iface_check(AF_INET6, (union all_addr *)&addr->in6.sin6_addr, label, &aut h_dns))
return 1; return 1;
#endif
#ifdef HAVE_DHCP #ifdef HAVE_DHCP
/* No DHCP where we're doing auth DNS. */ /* No DHCP where we're doing auth DNS. */
if (auth_dns) if (auth_dns)
{ {
tftp_ok = 0; tftp_ok = 0;
dhcp_ok = 0; dhcp_ok = 0;
} }
else else
for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
skipping to change at line 499 skipping to change at line 481
return 1; return 1;
} }
free(iface); free(iface);
} }
errno = ENOMEM; errno = ENOMEM;
return 0; return 0;
} }
#ifdef HAVE_IPV6
static int iface_allowed_v6(struct in6_addr *local, int prefix, static int iface_allowed_v6(struct in6_addr *local, int prefix,
int scope, int if_index, int flags, int scope, int if_index, int flags,
int preferred, int valid, void *vparam) int preferred, int valid, void *vparam)
{ {
union mysockaddr addr; union mysockaddr addr;
struct in_addr netmask; /* dummy */ struct in_addr netmask; /* dummy */
netmask.s_addr = 0; netmask.s_addr = 0;
(void)scope; /* warning */ (void)scope; /* warning */
(void)preferred; (void)preferred;
skipping to change at line 527 skipping to change at line 508
addr.in6.sin6_addr = *local; addr.in6.sin6_addr = *local;
addr.in6.sin6_port = htons(daemon->port); addr.in6.sin6_port = htons(daemon->port);
/* FreeBSD insists this is zero for non-linklocal addresses */ /* FreeBSD insists this is zero for non-linklocal addresses */
if (IN6_IS_ADDR_LINKLOCAL(local)) if (IN6_IS_ADDR_LINKLOCAL(local))
addr.in6.sin6_scope_id = if_index; addr.in6.sin6_scope_id = if_index;
else else
addr.in6.sin6_scope_id = 0; addr.in6.sin6_scope_id = 0;
return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netm ask, prefix, flags); return iface_allowed((struct iface_param *)vparam, if_index, NULL, &addr, netm ask, prefix, flags);
} }
#endif
static int iface_allowed_v4(struct in_addr local, int if_index, char *label, static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
struct in_addr netmask, struct in_addr broadcast, voi d *vparam) struct in_addr netmask, struct in_addr broadcast, voi d *vparam)
{ {
union mysockaddr addr; union mysockaddr addr;
int prefix, bit; int prefix, bit;
(void)broadcast; /* warning */ (void)broadcast; /* warning */
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
skipping to change at line 631 skipping to change at line 611
*up = addr->next; *up = addr->next;
addr->next = spare; addr->next = spare;
spare = addr; spare = addr;
} }
} }
} }
#endif #endif
param.spare = spare; param.spare = spare;
#ifdef HAVE_IPV6
ret = iface_enumerate(AF_INET6, &param, iface_allowed_v6); ret = iface_enumerate(AF_INET6, &param, iface_allowed_v6);
#endif
if (ret) if (ret)
ret = iface_enumerate(AF_INET, &param, iface_allowed_v4); ret = iface_enumerate(AF_INET, &param, iface_allowed_v4);
errsave = errno; errsave = errno;
close(param.fd); close(param.fd);
if (option_bool(OPT_CLEVERBIND)) if (option_bool(OPT_CLEVERBIND))
{ {
/* Garbage-collect listeners listening on addresses that no longer exist. /* Garbage-collect listeners listening on addresses that no longer exist.
skipping to change at line 738 skipping to change at line 716
} }
else else
my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno)); my_syslog(LOG_WARNING, s, daemon->addrbuff, strerror(errno));
return -1; return -1;
} }
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_ fd(fd)) if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) == -1 || !fix_ fd(fd))
goto err; goto err;
#ifdef HAVE_IPV6
if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, size of(opt)) == -1) if (family == AF_INET6 && setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, size of(opt)) == -1)
goto err; goto err;
#endif
if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1) if ((rc = bind(fd, (struct sockaddr *)addr, sa_len(addr))) == -1)
goto err; goto err;
if (type == SOCK_STREAM) if (type == SOCK_STREAM)
{ {
#ifdef TCP_FASTOPEN
int qlen = 5;
setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen));
#endif
if (listen(fd, TCP_BACKLOG) == -1) if (listen(fd, TCP_BACKLOG) == -1)
goto err; goto err;
} }
else if (family == AF_INET) else if (family == AF_INET)
{ {
if (!option_bool(OPT_NOWILD)) if (!option_bool(OPT_NOWILD))
{ {
#if defined(HAVE_LINUX_NETWORK) #if defined(HAVE_LINUX_NETWORK)
if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1) if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)) == -1)
goto err; goto err;
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF) #elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 || if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt)) == -1 ||
setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1) setsockopt(fd, IPPROTO_IP, IP_RECVIF, &opt, sizeof(opt)) == -1)
goto err; goto err;
#endif #endif
} }
} }
#ifdef HAVE_IPV6
else if (!set_ipv6pktinfo(fd)) else if (!set_ipv6pktinfo(fd))
goto err; goto err;
#endif
return fd; return fd;
} }
#ifdef HAVE_IPV6
int set_ipv6pktinfo(int fd) int set_ipv6pktinfo(int fd)
{ {
int opt = 1; int opt = 1;
/* The API changed around Linux 2.6.14 but the old ABI is still supported: /* The API changed around Linux 2.6.14 but the old ABI is still supported:
handle all combinations of headers and kernel. handle all combinations of headers and kernel.
OpenWrt note that this fixes the problem addressed by your very broken patc h. */ OpenWrt note that this fixes the problem addressed by your very broken patc h. */
daemon->v6pktinfo = IPV6_PKTINFO; daemon->v6pktinfo = IPV6_PKTINFO;
#ifdef IPV6_RECVPKTINFO #ifdef IPV6_RECVPKTINFO
skipping to change at line 800 skipping to change at line 778
return 1; return 1;
} }
# endif # endif
#else #else
if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &opt, sizeof(opt)) != -1) if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &opt, sizeof(opt)) != -1)
return 1; return 1;
#endif #endif
return 0; return 0;
} }
#endif
/* Find the interface on which a TCP connection arrived, if possible, or zero ot herwise. */ /* Find the interface on which a TCP connection arrived, if possible, or zero ot herwise. */
int tcp_interface(int fd, int af) int tcp_interface(int fd, int af)
{ {
(void)fd; /* suppress potential unused warning */
(void)af; /* suppress potential unused warning */
int if_index = 0; int if_index = 0;
#ifdef HAVE_LINUX_NETWORK #ifdef HAVE_LINUX_NETWORK
int opt = 1; int opt = 1;
struct cmsghdr *cmptr; struct cmsghdr *cmptr;
struct msghdr msg; struct msghdr msg;
socklen_t len; socklen_t len;
/* use mshdr so that the CMSDG_* macros are available */ /* use mshdr so that the CMSDG_* macros are available */
msg.msg_control = daemon->packet; msg.msg_control = daemon->packet;
skipping to change at line 839 skipping to change at line 818
union { union {
unsigned char *c; unsigned char *c;
struct in_pktinfo *p; struct in_pktinfo *p;
} p; } p;
p.c = CMSG_DATA(cmptr); p.c = CMSG_DATA(cmptr);
if_index = p.p->ipi_ifindex; if_index = p.p->ipi_ifindex;
} }
} }
} }
#ifdef HAVE_IPV6
else else
{ {
/* Only the RFC-2292 API has the ability to find the interface for TCP con nections, /* Only the RFC-2292 API has the ability to find the interface for TCP con nections,
it was removed in RFC-3542 !!!! it was removed in RFC-3542 !!!!
Fortunately, Linux kept the 2292 ABI when it moved to 3542. The followin g code always Fortunately, Linux kept the 2292 ABI when it moved to 3542. The followin g code always
uses the old ABI, and should work with pre- and post-3542 kernel headers */ uses the old ABI, and should work with pre- and post-3542 kernel headers */
#ifdef IPV6_2292PKTOPTIONS #ifdef IPV6_2292PKTOPTIONS
# define PKTOPTIONS IPV6_2292PKTOPTIONS # define PKTOPTIONS IPV6_2292PKTOPTIONS
skipping to change at line 871 skipping to change at line 849
union { union {
unsigned char *c; unsigned char *c;
struct in6_pktinfo *p; struct in6_pktinfo *p;
} p; } p;
p.c = CMSG_DATA(cmptr); p.c = CMSG_DATA(cmptr);
if_index = p.p->ipi6_ifindex; if_index = p.p->ipi6_ifindex;
} }
} }
} }
#endif /* IPV6 */
#endif /* Linux */ #endif /* Linux */
return if_index; return if_index;
} }
static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, in t dienow) static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, in t dienow)
{ {
struct listener *l = NULL; struct listener *l = NULL;
int fd = -1, tcpfd = -1, tftpfd = -1; int fd = -1, tcpfd = -1, tftpfd = -1;
skipping to change at line 901 skipping to change at line 878
if (do_tftp) if (do_tftp)
{ {
if (addr->sa.sa_family == AF_INET) if (addr->sa.sa_family == AF_INET)
{ {
/* port must be restored to DNS port for TCP code */ /* port must be restored to DNS port for TCP code */
short save = addr->in.sin_port; short save = addr->in.sin_port;
addr->in.sin_port = htons(TFTP_PORT); addr->in.sin_port = htons(TFTP_PORT);
tftpfd = make_sock(addr, SOCK_DGRAM, dienow); tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
addr->in.sin_port = save; addr->in.sin_port = save;
} }
# ifdef HAVE_IPV6
else else
{ {
short save = addr->in6.sin6_port; short save = addr->in6.sin6_port;
addr->in6.sin6_port = htons(TFTP_PORT); addr->in6.sin6_port = htons(TFTP_PORT);
tftpfd = make_sock(addr, SOCK_DGRAM, dienow); tftpfd = make_sock(addr, SOCK_DGRAM, dienow);
addr->in6.sin6_port = save; addr->in6.sin6_port = save;
} }
# endif
} }
#endif #endif
if (fd != -1 || tcpfd != -1 || tftpfd != -1) if (fd != -1 || tcpfd != -1 || tftpfd != -1)
{ {
l = safe_malloc(sizeof(struct listener)); l = safe_malloc(sizeof(struct listener));
l->next = NULL; l->next = NULL;
l->family = addr->sa.sa_family; l->family = addr->sa.sa_family;
l->fd = fd; l->fd = fd;
l->tcpfd = tcpfd; l->tcpfd = tcpfd;
skipping to change at line 942 skipping to change at line 917
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
addr.in.sin_len = sizeof(addr.in); addr.in.sin_len = sizeof(addr.in);
#endif #endif
addr.in.sin_family = AF_INET; addr.in.sin_family = AF_INET;
addr.in.sin_addr.s_addr = INADDR_ANY; addr.in.sin_addr.s_addr = INADDR_ANY;
addr.in.sin_port = htons(daemon->port); addr.in.sin_port = htons(daemon->port);
l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1); l = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
#ifdef HAVE_IPV6
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
# ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
addr.in6.sin6_len = sizeof(addr.in6); addr.in6.sin6_len = sizeof(addr.in6);
# endif #endif
addr.in6.sin6_family = AF_INET6; addr.in6.sin6_family = AF_INET6;
addr.in6.sin6_addr = in6addr_any; addr.in6.sin6_addr = in6addr_any;
addr.in6.sin6_port = htons(daemon->port); addr.in6.sin6_port = htons(daemon->port);
l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1); l6 = create_listeners(&addr, !!option_bool(OPT_TFTP), 1);
if (l) if (l)
l->next = l6; l->next = l6;
else else
l = l6; l = l6;
#endif
daemon->listeners = l; daemon->listeners = l;
} }
void create_bound_listeners(int dienow) void create_bound_listeners(int dienow)
{ {
struct listener *new; struct listener *new;
struct irec *iface; struct irec *iface;
struct iname *if_tmp; struct iname *if_tmp;
skipping to change at line 1156 skipping to change at line 1129
unsigned short port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail))); unsigned short port = htons(daemon->min_port + (rand16() % ((unsigned short)ports_avail)));
if (family == AF_INET) if (family == AF_INET)
{ {
addr.in.sin_addr.s_addr = INADDR_ANY; addr.in.sin_addr.s_addr = INADDR_ANY;
addr.in.sin_port = port; addr.in.sin_port = port;
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
addr.in.sin_len = sizeof(struct sockaddr_in); addr.in.sin_len = sizeof(struct sockaddr_in);
#endif #endif
} }
#ifdef HAVE_IPV6
else else
{ {
addr.in6.sin6_addr = in6addr_any; addr.in6.sin6_addr = in6addr_any;
addr.in6.sin6_port = port; addr.in6.sin6_port = port;
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
addr.in6.sin6_len = sizeof(struct sockaddr_in6); addr.in6.sin6_len = sizeof(struct sockaddr_in6);
#endif #endif
} }
#endif
if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0) if (bind(fd, (struct sockaddr *)&addr, sa_len(&addr)) == 0)
return fd; return fd;
if (errno != EADDRINUSE && errno != EACCES) if (errno != EADDRINUSE && errno != EACCES)
break; break;
} }
close(fd); close(fd);
} }
skipping to change at line 1189 skipping to change at line 1160
int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifind ex, int is_tcp) int local_bind(int fd, union mysockaddr *addr, char *intname, unsigned int ifind ex, int is_tcp)
{ {
union mysockaddr addr_copy = *addr; union mysockaddr addr_copy = *addr;
/* cannot set source _port_ for TCP connections. */ /* cannot set source _port_ for TCP connections. */
if (is_tcp) if (is_tcp)
{ {
if (addr_copy.sa.sa_family == AF_INET) if (addr_copy.sa.sa_family == AF_INET)
addr_copy.in.sin_port = 0; addr_copy.in.sin_port = 0;
#ifdef HAVE_IPV6
else else
addr_copy.in6.sin6_port = 0; addr_copy.in6.sin6_port = 0;
#endif
} }
if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1) if (bind(fd, (struct sockaddr *)&addr_copy, sa_len(&addr_copy)) == -1)
return 0; return 0;
if (!is_tcp && ifindex > 0) if (!is_tcp && ifindex > 0)
{ {
#if defined(IP_UNICAST_IF) #if defined(IP_UNICAST_IF)
if (addr_copy.sa.sa_family == AF_INET) if (addr_copy.sa.sa_family == AF_INET)
{ {
uint32_t ifindex_opt = htonl(ifindex); uint32_t ifindex_opt = htonl(ifindex);
return setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_opt, sizeof( ifindex_opt)) == 0; return setsockopt(fd, IPPROTO_IP, IP_UNICAST_IF, &ifindex_opt, sizeof( ifindex_opt)) == 0;
} }
#endif #endif
#if defined(HAVE_IPV6) && defined (IPV6_UNICAST_IF) #if defined (IPV6_UNICAST_IF)
if (addr_copy.sa.sa_family == AF_INET6) if (addr_copy.sa.sa_family == AF_INET6)
{ {
uint32_t ifindex_opt = htonl(ifindex); uint32_t ifindex_opt = htonl(ifindex);
return setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_opt, siz eof(ifindex_opt)) == 0; return setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_IF, &ifindex_opt, siz eof(ifindex_opt)) == 0;
} }
#endif #endif
} }
(void)intname; /* suppress potential unused warning */
#if defined(SO_BINDTODEVICE) #if defined(SO_BINDTODEVICE)
if (intname[0] != 0 && if (intname[0] != 0 &&
setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1) setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, intname, IF_NAMESIZE) == -1)
return 0; return 0;
#endif #endif
return 1; return 1;
} }
static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname) static struct serverfd *allocate_sfd(union mysockaddr *addr, char *intname)
skipping to change at line 1243 skipping to change at line 1213
the INADDR_ANY/port0 socket have sfd set to NULL */ the INADDR_ANY/port0 socket have sfd set to NULL */
if (!daemon->osport && intname[0] == 0) if (!daemon->osport && intname[0] == 0)
{ {
errno = 0; errno = 0;
if (addr->sa.sa_family == AF_INET && if (addr->sa.sa_family == AF_INET &&
addr->in.sin_addr.s_addr == INADDR_ANY && addr->in.sin_addr.s_addr == INADDR_ANY &&
addr->in.sin_port == htons(0)) addr->in.sin_port == htons(0))
return NULL; return NULL;
#ifdef HAVE_IPV6
if (addr->sa.sa_family == AF_INET6 && if (addr->sa.sa_family == AF_INET6 &&
memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 && memcmp(&addr->in6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0 &&
addr->in6.sin6_port == htons(0)) addr->in6.sin6_port == htons(0))
return NULL; return NULL;
#endif
} }
if (intname && strlen(intname) != 0) if (intname && strlen(intname) != 0)
ifindex = if_nametoindex(intname); /* index == 0 when not binding to an inte rface */ ifindex = if_nametoindex(intname); /* index == 0 when not binding to an inte rface */
/* may have a suitable one already */ /* may have a suitable one already */
for (sfd = daemon->sfds; sfd; sfd = sfd->next ) for (sfd = daemon->sfds; sfd; sfd = sfd->next )
if (sockaddr_isequal(&sfd->source_addr, addr) && if (sockaddr_isequal(&sfd->source_addr, addr) &&
strcmp(intname, sfd->interface) == 0 && strcmp(intname, sfd->interface) == 0 &&
ifindex == sfd->ifindex) ifindex == sfd->ifindex)
skipping to change at line 1311 skipping to change at line 1279
union mysockaddr addr; union mysockaddr addr;
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.in.sin_family = AF_INET; addr.in.sin_family = AF_INET;
addr.in.sin_addr.s_addr = INADDR_ANY; addr.in.sin_addr.s_addr = INADDR_ANY;
addr.in.sin_port = htons(daemon->query_port); addr.in.sin_port = htons(daemon->query_port);
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
addr.in.sin_len = sizeof(struct sockaddr_in); addr.in.sin_len = sizeof(struct sockaddr_in);
#endif #endif
if ((sfd = allocate_sfd(&addr, ""))) if ((sfd = allocate_sfd(&addr, "")))
sfd->preallocated = 1; sfd->preallocated = 1;
#ifdef HAVE_IPV6
memset(&addr, 0, sizeof(addr)); memset(&addr, 0, sizeof(addr));
addr.in6.sin6_family = AF_INET6; addr.in6.sin6_family = AF_INET6;
addr.in6.sin6_addr = in6addr_any; addr.in6.sin6_addr = in6addr_any;
addr.in6.sin6_port = htons(daemon->query_port); addr.in6.sin6_port = htons(daemon->query_port);
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
addr.in6.sin6_len = sizeof(struct sockaddr_in6); addr.in6.sin6_len = sizeof(struct sockaddr_in6);
#endif #endif
if ((sfd = allocate_sfd(&addr, ""))) if ((sfd = allocate_sfd(&addr, "")))
sfd->preallocated = 1; sfd->preallocated = 1;
#endif
} }
for (srv = daemon->servers; srv; srv = srv->next) for (srv = daemon->servers; srv; srv = srv->next)
if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) && if (!(srv->flags & (SERV_LITERAL_ADDRESS | SERV_NO_ADDR | SERV_USE_RESOLV | SERV_NO_REBIND)) &&
!allocate_sfd(&srv->source_addr, srv->interface) && !allocate_sfd(&srv->source_addr, srv->interface) &&
errno != 0 && errno != 0 &&
option_bool(OPT_NOWILD)) option_bool(OPT_NOWILD))
{ {
prettyprint_addr(&srv->source_addr, daemon->namebuff); prettyprint_addr(&srv->source_addr, daemon->namebuff);
if (srv->interface[0] != 0) if (srv->interface[0] != 0)
skipping to change at line 1572 skipping to change at line 1539
s1 = _("unqualified"), s2 = _("names"); s1 = _("unqualified"), s2 = _("names");
else if (strlen(serv->domain) == 0) else if (strlen(serv->domain) == 0)
s1 = _("default"), s2 = ""; s1 = _("default"), s2 = "";
else else
s1 = _("domain"), s2 = serv->domain; s1 = _("domain"), s2 = serv->domain;
if (serv->flags & SERV_NO_ADDR) if (serv->flags & SERV_NO_ADDR)
{ {
count--; count--;
if (++locals <= LOCALS_LOGGED) if (++locals <= LOCALS_LOGGED)
my_syslog(LOG_INFO, _("using local addresses only for %s %s"), s1, s2); my_syslog(LOG_INFO, _("using only locally-known addresses for %s %s"), s1, s2);
} }
else if (serv->flags & SERV_USE_RESOLV) else if (serv->flags & SERV_USE_RESOLV)
my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1 , s2); my_syslog(LOG_INFO, _("using standard nameservers for %s %s"), s1 , s2);
else else
my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s %s"), dae mon->namebuff, port, s1, s2, s3); my_syslog(LOG_INFO, _("using nameserver %s#%d for %s %s %s"), dae mon->namebuff, port, s1, s2, s3);
} }
#ifdef HAVE_LOOP #ifdef HAVE_LOOP
else if (serv->flags & SERV_LOOP) else if (serv->flags & SERV_LOOP)
my_syslog(LOG_INFO, _("NOT using nameserver %s#%d - query loop detect ed"), daemon->namebuff, port); my_syslog(LOG_INFO, _("NOT using nameserver %s#%d - query loop detect ed"), daemon->namebuff, port);
#endif #endif
skipping to change at line 1654 skipping to change at line 1621
if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1) if ((addr.in.sin_addr.s_addr = inet_addr(token)) != (in_addr_t) -1)
{ {
#ifdef HAVE_SOCKADDR_SA_LEN #ifdef HAVE_SOCKADDR_SA_LEN
source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in); source_addr.in.sin_len = addr.in.sin_len = sizeof(source_addr.in);
#endif #endif
source_addr.in.sin_family = addr.in.sin_family = AF_INET; source_addr.in.sin_family = addr.in.sin_family = AF_INET;
addr.in.sin_port = htons(NAMESERVER_PORT); addr.in.sin_port = htons(NAMESERVER_PORT);
source_addr.in.sin_addr.s_addr = INADDR_ANY; source_addr.in.sin_addr.s_addr = INADDR_ANY;
source_addr.in.sin_port = htons(daemon->query_port); source_addr.in.sin_port = htons(daemon->query_port);
} }
#ifdef HAVE_IPV6
else else
{ {
int scope_index = 0; int scope_index = 0;
char *scope_id = strchr(token, '%'); char *scope_id = strchr(token, '%');
if (scope_id) if (scope_id)
{ {
*(scope_id++) = 0; *(scope_id++) = 0;
scope_index = if_nametoindex(scope_id); scope_index = if_nametoindex(scope_id);
} }
skipping to change at line 1682 skipping to change at line 1648
source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0; source_addr.in6.sin6_flowinfo = addr.in6.sin6_flowinfo = 0;
addr.in6.sin6_port = htons(NAMESERVER_PORT); addr.in6.sin6_port = htons(NAMESERVER_PORT);
addr.in6.sin6_scope_id = scope_index; addr.in6.sin6_scope_id = scope_index;
source_addr.in6.sin6_addr = in6addr_any; source_addr.in6.sin6_addr = in6addr_any;
source_addr.in6.sin6_port = htons(daemon->query_port); source_addr.in6.sin6_port = htons(daemon->query_port);
source_addr.in6.sin6_scope_id = 0; source_addr.in6.sin6_scope_id = 0;
} }
else else
continue; continue;
} }
#else /* IPV6 */
else
continue;
#endif
add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL); add_update_server(SERV_FROM_RESOLV, &addr, &source_addr, NULL, NULL);
gotone = 1; gotone = 1;
} }
fclose(f); fclose(f);
cleanup_servers(); cleanup_servers();
return gotone; return gotone;
} }
 End of changes. 67 change blocks. 
71 lines changed or deleted 33 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)