Compare commits

...
16 Commits
Author SHA1 Message Date
Simon Kelley ab5ebe9507 Bump Debian version to 2.82 2020-06-26 22:23:15 +01:00
Simon Kelley 837e8f4eb5 Remove runit support when building debs for Ubuntu. 2020-06-26 22:13:27 +01:00
Simon Kelley e2cb655958 Thorough clean-up following 8270648da1. 2020-06-20 22:30:12 +01:00
Frank 8270648da1 Fix memory corruption on EAGAIN return from pipe during TCP requests.
This patch fixes a buffer overflow in TCP requests. Since the read is not
actually being retried, the byte written by the child can be left
in the pipe. When that happens, cache_recv_insert() reads the length of the
name, which is now multiplied by 256 due to the extra 0 byte (8 bit shift)
and results in daemon->namebuff being overflowed.

Namebuff is immediately before the daemon struct in memory so it
ends up corrupting the beginning of the daemon struct.
2020-06-20 15:17:56 +01:00
Simon Kelley 619000a3c5 Suppress logging of listen addresses during startup.
The initial call to enumerate_interfaces() happens before the
logging subsystem in initialised and the startup banner logged.
It's not intended that syslog be written at this point.
2020-04-29 00:09:58 +01:00
Petr Menšík 1c1b925052 Remove duplicate address family from listener
Since address already contain family, remove separate family from
listener. Use now family from address itself.
2020-04-29 00:06:57 +01:00
Petr Menšík 49bdf1ead9 Handle listening on duplicate addresses
Save listening address into listener. Use it to find existing listeners
before creating new one. If it exist, increase just used counter.
Release only listeners not already used.

Duplicates family in listener.
2020-04-29 00:06:31 +01:00
Petr Mensik 60a3ae19c5 Cleanup interfaces no longer available
Clean addresses and interfaces not found after enumerate. Free unused
records to speed up checking active interfaces and reduce used memory.
2020-04-29 00:06:01 +01:00
Petr Mensik 951a22165c Compare address and interface index for allowed interface
If interface is recreated with the same address but different index, it
would not change any other parameter.

Test also address family on incoming TCP queries.
2020-04-29 00:04:29 +01:00
Petr Mensik 51cdd1a227 Explicitly mark address port not used
On many places return value is ignored. Usually it means port is always
the same and not needed to be displayed. Unify warnings.
2020-04-29 00:04:04 +01:00
Petr Mensik 66adee85be Log listening on new interfaces
Log in debug mode listening on interfaces. They can be dynamically
found, include interface number, since it is checked on TCP connections.
Print also addresses found on them.
2020-04-29 00:03:21 +01:00
Simon Kelley 4890bcdea2 Workaround for reported recvmsg() ignoring MSG_PEEK. 2020-04-28 14:02:53 +01:00
Simon Kelley 8baf583a3f Allow IPv6 addresses ofthe form [::ffff:1.2.3.4] in --dhcp-option. 2020-04-23 23:14:45 +01:00
Simon Kelley 913fa15fb1 Convert failure of setsockopt(..., SOL_NETLINK, NETLINK_NO_ENOBUFS, ...) into warning.
We call this, which avoids POLLERR returns from netlink on a loaded system,
if the kernel is new enough to support it. Sadly, qemu-user doesn't support
the socket option, so if it fails despite the kernel being new enough to
support it, we just emit a warning, rather than failing hard.
2020-04-19 23:16:52 +01:00
Simon Kelley 00fe2f49e0 Debian package fix for kFreeBSD. 2020-04-19 21:59:13 +01:00
Simon Kelley ec2067df75 Debian package fixes.
Add runit /etc files to conffiles.
Fix broken copyright file in dnsmasq binary package.
2020-04-12 16:12:50 +01:00
12 changed files with 267 additions and 108 deletions

No files matched your search

+24
View File
@@ -1,3 +1,27 @@
dnsmasq (2.82-1) unstable; urgency=low
* New upstream.
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 26 Jun 2020 22:22:41 +0000
dnsmasq (2.81-4) unstable; urgency=low
* Remove runit support when building for Ubuntu. (closes: #960401)
-- Simon Kelley <simon@thekelleys.org.uk> Fri, 26 Jun 2020 21:52:44 +0000
dnsmasq (2.81-3) unstable; urgency=low
* Fixes to control file for bug 958100
-- Simon Kelley <simon@thekelleys.org.uk> Sun, 19 Apr 2020 21:44:12 +0000
dnsmasq (2.81-2) unstable; urgency=low
* Fix FTBFS on kFreeBSD. (closes: #958100)
-- Simon Kelley <simon@thekelleys.org.uk> Sat, 18 Apr 2020 18:34:15 +0000
dnsmasq (2.81-1) unstable; urgency=low
* New upstream.
+3 -2
View File
@@ -3,8 +3,9 @@ Section: net
Priority: optional
Build-depends: gettext, libnetfilter-conntrack-dev [linux-any],
libidn2-dev, libdbus-1-dev (>=0.61), libgmp-dev,
nettle-dev (>=2.4-3), libbsd-dev [!linux-any],
liblua5.2-dev, dh-runit, debhelper-compat (= 10)
nettle-dev (>=2.4-3), libbsd-dev [kfreebsd-any],
liblua5.2-dev, dh-runit, debhelper-compat (= 10),
pkg-config
Maintainer: Simon Kelley <simon@thekelleys.org.uk>
Homepage: http://www.thekelleys.org.uk/dnsmasq/doc.html
Vcs-Git: http://thekelleys.org.uk/git/dnsmasq.git
+17 -10
View File
@@ -98,9 +98,10 @@ ifeq (,$(filter nodnssec,$(DEB_BUILD_OPTIONS)))
DEB_COPTS += -DHAVE_DNSSEC
endif
ifneq ($(DEB_HOST_ARCH_OS),linux)
ifeq ($(DEB_HOST_ARCH_OS),kfreebsd)
# For strlcpy in FreeBSD
LDFLAGS += -lbsd
LIBS += $(shell ${PKG_CONFIG} --libs libbsd-overlay)
CFLAGS += $(shell ${PKG_CONFIG} --cflags libbsd-overlay)
endif
define build_tree
@@ -169,16 +170,20 @@ binary-indep: checkroot
-d debian/trees/daemon/etc/resolvconf/update.d \
-d debian/trees/daemon/usr/lib/resolvconf/dpkg-event.d \
-d debian/trees/daemon/usr/share/dnsmasq \
-d debian/trees/daemon/usr/share/doc/dnsmasq \
-d debian/trees/daemon/etc/default \
-d debian/trees/daemon/lib/systemd/system \
-d debian/trees/daemon/usr/lib/tmpfiles.d \
-d debian/trees/daemon/etc/insserv.conf.d
install -m 644 debian/conffiles debian/trees/daemon/DEBIAN
install -m 755 debian/postinst debian/postrm debian/prerm debian/trees/daemon/DEBIAN
rm -f debian/dnsmasq.postinst.debhelper debian/dnsmasq.postrm.debhelper
dh_runit -pdnsmasq -Pdebian/trees/daemon
cat debian/dnsmasq.postinst.debhelper >> debian/trees/daemon/DEBIAN/postinst
cat debian/dnsmasq.postrm.debhelper >> debian/trees/daemon/DEBIAN/postrm
if ! dpkg-vendor --derives-from Ubuntu; then \
rm -f debian/dnsmasq.postinst.debhelper debian/dnsmasq.postrm.debhelper; \
dh_runit -pdnsmasq -Pdebian/trees/daemon; \
cat debian/dnsmasq.postinst.debhelper >> debian/trees/daemon/DEBIAN/postinst; \
cat debian/dnsmasq.postrm.debhelper >> debian/trees/daemon/DEBIAN/postrm; \
cd debian/trees/daemon && find etc/sv -type f -printf '/%p\n' >>DEBIAN/conffiles; \
fi
install -m 755 debian/init debian/trees/daemon/etc/init.d/dnsmasq
install -m 755 debian/resolvconf debian/trees/daemon/etc/resolvconf/update.d/dnsmasq
install -m 755 debian/resolvconf-package debian/trees/daemon/usr/lib/resolvconf/dpkg-event.d/dnsmasq
@@ -190,7 +195,9 @@ binary-indep: checkroot
install -m 644 debian/systemd@.service debian/trees/daemon/lib/systemd/system/dnsmasq@.service
install -m 644 debian/tmpfiles.conf debian/trees/daemon/usr/lib/tmpfiles.d/dnsmasq.conf
install -m 644 debian/insserv debian/trees/daemon/etc/insserv.conf.d/dnsmasq
ln -s $(package) debian/trees/daemon/usr/share/doc/dnsmasq
install -m 644 debian/copyright debian/trees/daemon/usr/share/doc/dnsmasq/copyright
install -m 644 debian/changelog debian/trees/daemon/usr/share/doc/dnsmasq/changelog.Debian
gzip -9n debian/trees/daemon/usr/share/doc/dnsmasq/changelog.Debian
cd debian/trees/daemon && find . -type f ! -regex '.*DEBIAN/.*' -printf '%P\0' | LC_ALL=C sort -z | xargs -r0 md5sum > DEBIAN/md5sums
dpkg-gencontrol $(PACKAGE_VERSION) -Tdebian/dnsmasq.substvars -pdnsmasq -Pdebian/trees/daemon
find debian/trees/daemon -depth -newermt '$(BUILD_DATE)' -print0 | xargs -0r touch --no-dereference --date='$(BUILD_DATE)'
@@ -200,7 +207,7 @@ binary-indep: checkroot
binary-arch: checkroot
$(call build_tree,debian/trees/base)
make $(TARGET) BUILDDIR=debian/build/no-lua PREFIX=/usr DESTDIR=`pwd`/debian/trees/base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG)
make $(TARGET) BUILDDIR=debian/build/no-lua PREFIX=/usr DESTDIR=`pwd`/debian/trees/base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG) LIBS="$(LIBS)"
ifeq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS)))
$(call add_docs,debian/trees/base)
else
@@ -219,7 +226,7 @@ endif
dpkg --build debian/trees/base ..
$(call build_tree,debian/trees/lua-base)
make $(TARGET) BUILDDIR=debian/build/lua PREFIX=/usr DESTDIR=`pwd`/debian/trees/lua-base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="-DHAVE_LUASCRIPT $(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG)
make $(TARGET) BUILDDIR=debian/build/lua PREFIX=/usr DESTDIR=`pwd`/debian/trees/lua-base CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="-DHAVE_LUASCRIPT $(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG) LIBS="$(LIBS)"
ifeq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS)))
$(call add_docs,debian/trees/lua-base)
else
@@ -249,7 +256,7 @@ ifeq ($(DEB_HOST_ARCH_OS),linux)
ifeq (,$(findstring nodoc,$(DEB_BUILD_OPTIONS)))
install -m 755 -d debian/trees/utils/usr/share/man/man1
endif
make -C contrib/lease-tools PREFIX=/usr DESTDIR=`pwd`/debian/trees/utils CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG)
make -C contrib/lease-tools PREFIX=/usr DESTDIR=`pwd`/debian/trees/utils CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS)" COPTS="$(DEB_COPTS)" CC=$(CC) PKG_CONFIG=$(PKG_CONFIG) LIBS="$(LIBS)"
install -m 755 contrib/lease-tools/dhcp_release debian/trees/utils/usr/bin/dhcp_release
install -m 755 contrib/lease-tools/dhcp_release6 debian/trees/utils/usr/bin/dhcp_release6
install -m 755 contrib/lease-tools/dhcp_lease_time debian/trees/utils/usr/bin/dhcp_lease_time
+1 -1
View File
@@ -237,7 +237,7 @@ static DBusMessage *dbus_reply_server_loop(DBusMessage *message)
for (serv = daemon->servers; serv; serv = serv->next)
if (serv->flags & SERV_LOOP)
{
prettyprint_addr(&serv->addr, daemon->addrbuff);
(void)prettyprint_addr(&serv->addr, daemon->addrbuff);
dbus_message_iter_append_basic (&args_iter, DBUS_TYPE_STRING, &daemon->addrbuff);
}
+12 -3
View File
@@ -38,7 +38,7 @@ void dhcp_common_init(void)
ssize_t recv_dhcp_packet(int fd, struct msghdr *msg)
{
ssize_t sz;
ssize_t sz, new_sz;
while (1)
{
@@ -65,9 +65,18 @@ ssize_t recv_dhcp_packet(int fd, struct msghdr *msg)
}
}
while ((sz = recvmsg(fd, msg, 0)) == -1 && errno == EINTR);
while ((new_sz = recvmsg(fd, msg, 0)) == -1 && errno == EINTR);
/* Some kernels seem to ignore MSG_PEEK, and dequeue the packet anyway.
If that happens we get EAGAIN here because the socket is non-blocking.
Use the result of the original testing recvmsg as long as the buffer
was big enough. There's a small race here that may lose the odd packet,
but it's UDP anyway. */
return (msg->msg_flags & MSG_TRUNC) ? -1 : sz;
if (new_sz == -1 && (errno == EWOULDBLOCK || errno == EAGAIN))
new_sz = sz;
return (msg->msg_flags & MSG_TRUNC) ? -1 : new_sz;
}
struct dhcp_netid *run_tag_if(struct dhcp_netid *tags)
+34 -28
View File
@@ -58,6 +58,7 @@ int main (int argc, char **argv)
char *bound_device = NULL;
int did_bind = 0;
struct server *serv;
char *netlink_warn;
#endif
#if defined(HAVE_DHCP) || defined(HAVE_DHCP6)
struct dhcp_context *context;
@@ -327,7 +328,7 @@ int main (int argc, char **argv)
#endif
#if defined(HAVE_LINUX_NETWORK)
netlink_init();
netlink_warn = netlink_init();
#elif defined(HAVE_BSD_NETWORK)
route_init();
#endif
@@ -946,6 +947,9 @@ int main (int argc, char **argv)
# ifdef HAVE_LINUX_NETWORK
if (did_bind)
my_syslog(MS_DHCP | LOG_INFO, _("DHCP, sockets bound exclusively to interface %s"), bound_device);
if (netlink_warn)
my_syslog(LOG_WARNING, netlink_warn);
# endif
/* after dhcp_construct_contexts */
@@ -1820,7 +1824,8 @@ static void check_dns_listeners(time_t now)
addr.addr4 = tcp_addr.in.sin_addr;
for (iface = daemon->interfaces; iface; iface = iface->next)
if (iface->index == if_index)
if (iface->index == if_index &&
iface->addr.sa.sa_family == tcp_addr.sa.sa_family)
break;
if (!iface && !loopback_exception(listener->tcpfd, tcp_addr.sa.sa_family, &addr, intr_name))
@@ -1859,31 +1864,30 @@ static void check_dns_listeners(time_t now)
else
{
int i;
#ifdef HAVE_LINUX_NETWORK
/* The child process inherits the netlink socket,
which it never uses, but when the parent (us)
uses it in the future, the answer may go to the
child, resulting in the parent blocking
forever awaiting the result. To avoid this
the child closes the netlink socket, but there's
a nasty race, since the parent may use netlink
before the child has done the close.
To avoid this, the parent blocks here until a
single byte comes back up the pipe, which
is sent by the child after it has closed the
netlink socket. */
unsigned char a;
read_write(pipefd[0], &a, 1, 1);
#endif
for (i = 0; i < MAX_PROCS; i++)
if (daemon->tcp_pids[i] == 0 && daemon->tcp_pipes[i] == -1)
{
char a;
(void)a; /* suppress potential unused warning */
daemon->tcp_pids[i] = p;
daemon->tcp_pipes[i] = pipefd[0];
#ifdef HAVE_LINUX_NETWORK
/* The child process inherits the netlink socket,
which it never uses, but when the parent (us)
uses it in the future, the answer may go to the
child, resulting in the parent blocking
forever awaiting the result. To avoid this
the child closes the netlink socket, but there's
a nasty race, since the parent may use netlink
before the child has done the close.
To avoid this, the parent blocks here until a
single byte comes back up the pipe, which
is sent by the child after it has closed the
netlink socket. */
retry_send(read(pipefd[0], &a, 1));
#endif
break;
}
}
@@ -1915,16 +1919,16 @@ static void check_dns_listeners(time_t now)
terminate the process. */
if (!option_bool(OPT_DEBUG))
{
char a = 0;
(void)a; /* suppress potential unused warning */
#ifdef HAVE_LINUX_NETWORK
/* See comment above re: netlink socket. */
unsigned char a = 0;
close(daemon->netlinkfd);
read_write(pipefd[1], &a, 1, 0);
#endif
alarm(CHILD_LIFETIME);
close(pipefd[0]); /* close read end in child. */
daemon->pipe_to_parent = pipefd[1];
#ifdef HAVE_LINUX_NETWORK
/* See comment above re netlink socket. */
close(daemon->netlinkfd);
retry_send(write(pipefd[1], &a, 1));
#endif
}
/* start with no upstream connections. */
@@ -1951,8 +1955,10 @@ static void check_dns_listeners(time_t now)
shutdown(s->tcpfd, SHUT_RDWR);
close(s->tcpfd);
}
if (!option_bool(OPT_DEBUG))
{
close(daemon->pipe_to_parent);
flush_log();
_exit(0);
}
+3 -2
View File
@@ -572,7 +572,8 @@ struct irec {
};
struct listener {
int fd, tcpfd, tftpfd, family;
int fd, tcpfd, tftpfd, used;
union mysockaddr addr;
struct irec *iface; /* only sometimes valid for non-wildcard */
struct listener *next;
};
@@ -1450,7 +1451,7 @@ void clear_cache_and_reload(time_t now);
/* netlink.c */
#ifdef HAVE_LINUX_NETWORK
void netlink_init(void);
char *netlink_init(void);
void netlink_multicast(void);
#endif
+16 -15
View File
@@ -676,7 +676,7 @@ static size_t process_reply(struct dns_header *header, time_t now, struct server
if (!(header->hb4 & HB4_RA) && rcode == NOERROR &&
server && !(server->flags & SERV_WARNED_RECURSIVE))
{
prettyprint_addr(&server->addr, daemon->namebuff);
(void)prettyprint_addr(&server->addr, daemon->namebuff);
my_syslog(LOG_WARNING, _("nameserver %s refused to do a recursive query"), daemon->namebuff);
if (!option_bool(OPT_LOG))
server->flags |= SERV_WARNED_RECURSIVE;
@@ -960,7 +960,7 @@ void reply_query(int fd, int family, time_t now)
{
forward->sentto->edns_pktsz = SAFE_PKTSZ;
forward->sentto->pktsz_reduced = now;
prettyprint_addr(&forward->sentto->addr, daemon->addrbuff);
(void)prettyprint_addr(&forward->sentto->addr, daemon->addrbuff);
my_syslog(LOG_WARNING, _("reducing DNS packet size for nameserver %s to %d"), daemon->addrbuff, SAFE_PKTSZ);
}
@@ -1284,8 +1284,9 @@ void receive_query(struct listener *listen, time_t now)
CMSG_SPACE(sizeof(struct sockaddr_dl))];
#endif
} control_u;
int family = listen->addr.sa.sa_family;
/* Can always get recvd interface for IPv6 */
int check_dst = !option_bool(OPT_NOWILD) || listen->family == AF_INET6;
int check_dst = !option_bool(OPT_NOWILD) || family == AF_INET6;
/* packet buffer overwritten */
daemon->srv_save = NULL;
@@ -1297,7 +1298,7 @@ void receive_query(struct listener *listen, time_t now)
{
auth_dns = listen->iface->dns_auth;
if (listen->family == AF_INET)
if (family == AF_INET)
{
dst_addr_4 = dst_addr.addr4 = listen->iface->addr.in.sin_addr;
netmask = listen->iface->netmask;
@@ -1327,9 +1328,9 @@ void receive_query(struct listener *listen, time_t now)
information disclosure. */
memset(daemon->packet + n, 0, daemon->edns_pktsz - n);
source_addr.sa.sa_family = listen->family;
source_addr.sa.sa_family = family;
if (listen->family == AF_INET)
if (family == AF_INET)
{
/* Source-port == 0 is an error, we can't send back to that.
http://www.ietf.org/mail-archive/web/dnsop/current/msg11441.html */
@@ -1349,7 +1350,7 @@ void receive_query(struct listener *listen, time_t now)
{
struct addrlist *addr;
if (listen->family == AF_INET6)
if (family == AF_INET6)
{
for (addr = daemon->interface_addrs; addr; addr = addr->next)
if ((addr->flags & ADDRLIST_IPV6) &&
@@ -1387,7 +1388,7 @@ void receive_query(struct listener *listen, time_t now)
return;
#if defined(HAVE_LINUX_NETWORK)
if (listen->family == AF_INET)
if (family == AF_INET)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
{
@@ -1400,7 +1401,7 @@ void receive_query(struct listener *listen, time_t now)
if_index = p.p->ipi_ifindex;
}
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
if (listen->family == AF_INET)
if (family == AF_INET)
{
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
{
@@ -1425,7 +1426,7 @@ void receive_query(struct listener *listen, time_t now)
}
#endif
if (listen->family == AF_INET6)
if (family == AF_INET6)
{
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
@@ -1446,16 +1447,16 @@ void receive_query(struct listener *listen, time_t now)
if (!indextoname(listen->fd, if_index, ifr.ifr_name))
return;
if (!iface_check(listen->family, &dst_addr, ifr.ifr_name, &auth_dns))
if (!iface_check(family, &dst_addr, ifr.ifr_name, &auth_dns))
{
if (!option_bool(OPT_CLEVERBIND))
enumerate_interfaces(0);
if (!loopback_exception(listen->fd, listen->family, &dst_addr, ifr.ifr_name) &&
!label_exception(if_index, listen->family, &dst_addr))
if (!loopback_exception(listen->fd, family, &dst_addr, ifr.ifr_name) &&
!label_exception(if_index, family, &dst_addr))
return;
}
if (listen->family == AF_INET && option_bool(OPT_LOCALISE))
if (family == AF_INET && option_bool(OPT_LOCALISE))
{
struct irec *iface;
@@ -1500,7 +1501,7 @@ void receive_query(struct listener *listen, time_t now)
#endif
char *types = querystr(auth_dns ? "auth" : "query", type);
if (listen->family == AF_INET)
if (family == AF_INET)
log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff,
(union all_addr *)&source_addr.in.sin_addr, types);
else
+8 -3
View File
@@ -49,7 +49,7 @@ static u32 netlink_pid;
static void nl_async(struct nlmsghdr *h);
void netlink_init(void)
char *netlink_init(void)
{
struct sockaddr_nl addr;
socklen_t slen = sizeof(addr);
@@ -82,16 +82,21 @@ void netlink_init(void)
}
if (daemon->netlinkfd == -1 ||
(daemon->kernel_version >= KERNEL_VERSION(2,6,30) &&
setsockopt(daemon->netlinkfd, SOL_NETLINK, NETLINK_NO_ENOBUFS, &opt, sizeof(opt)) == -1) ||
getsockname(daemon->netlinkfd, (struct sockaddr *)&addr, &slen) == -1)
die(_("cannot create netlink socket: %s"), NULL, EC_MISC);
/* save pid assigned by bind() and retrieved by getsockname() */
netlink_pid = addr.nl_pid;
iov.iov_len = 100;
iov.iov_base = safe_malloc(iov.iov_len);
if (daemon->kernel_version >= KERNEL_VERSION(2,6,30) &&
setsockopt(daemon->netlinkfd, SOL_NETLINK, NETLINK_NO_ENOBUFS, &opt, sizeof(opt)) == -1)
return _("warning: failed to set NETLINK_NO_ENOBUFS on netlink socket");
return NULL;
}
static ssize_t netlink_recv(void)
+130 -26
View File
@@ -388,10 +388,11 @@ static int iface_allowed(struct iface_param *param, int if_index, char *label,
/* check whether the interface IP has been added already
we call this routine multiple times. */
for (iface = daemon->interfaces; iface; iface = iface->next)
if (sockaddr_isequal(&iface->addr, addr))
if (sockaddr_isequal(&iface->addr, addr) && iface->index == if_index)
{
iface->dad = !!(iface_flags & IFACE_TENTATIVE);
iface->found = 1; /* for garbage collection */
iface->netmask = netmask;
return 1;
}
@@ -532,7 +533,82 @@ static int iface_allowed_v4(struct in_addr local, int if_index, char *label,
return iface_allowed((struct iface_param *)vparam, if_index, label, &addr, netmask, prefix, 0);
}
/*
* Clean old interfaces no longer found.
*/
static void clean_interfaces()
{
struct irec *iface;
struct irec **up = &daemon->interfaces;
for (iface = *up; iface; iface = *up)
{
if (!iface->found && !iface->done)
{
*up = iface->next;
free(iface->name);
free(iface);
}
else
{
up = &iface->next;
}
}
}
/** Release listener if no other interface needs it.
*
* @return 1 if released, 0 if still required
*/
static int release_listener(struct listener *l)
{
if (l->used > 1)
{
struct irec *iface;
for (iface = daemon->interfaces; iface; iface = iface->next)
if (iface->done && sockaddr_isequal(&l->addr, &iface->addr))
{
if (iface->found)
{
/* update listener to point to active interface instead */
if (!l->iface->found)
l->iface = iface;
}
else
{
l->used--;
iface->done = 0;
}
}
/* Someone is still using this listener, skip its deletion */
if (l->used > 0)
return 0;
}
if (l->iface->done)
{
int port;
port = prettyprint_addr(&l->iface->addr, daemon->addrbuff);
my_syslog(LOG_DEBUG, _("stopped listening on %s(#%d): %s port %d"),
l->iface->name, l->iface->index, daemon->addrbuff, port);
/* In case it ever returns */
l->iface->done = 0;
}
if (l->fd != -1)
close(l->fd);
if (l->tcpfd != -1)
close(l->tcpfd);
if (l->tftpfd != -1)
close(l->tftpfd);
free(l);
return 1;
}
int enumerate_interfaces(int reset)
{
static struct addrlist *spare = NULL;
@@ -630,6 +706,7 @@ int enumerate_interfaces(int reset)
in OPT_CLEVERBIND mode, that at listener will just disappear after
a call to enumerate_interfaces, this is checked OK on all calls. */
struct listener *l, *tmp, **up;
int freed = 0;
for (up = &daemon->listeners, l = daemon->listeners; l; l = tmp)
{
@@ -637,25 +714,17 @@ int enumerate_interfaces(int reset)
if (!l->iface || l->iface->found)
up = &l->next;
else
else if (release_listener(l))
{
*up = l->next;
/* In case it ever returns */
l->iface->done = 0;
if (l->fd != -1)
close(l->fd);
if (l->tcpfd != -1)
close(l->tcpfd);
if (l->tftpfd != -1)
close(l->tftpfd);
free(l);
*up = tmp;
freed = 1;
}
}
if (freed)
clean_interfaces();
}
errno = errsave;
spare = param.spare;
@@ -895,10 +964,11 @@ static struct listener *create_listeners(union mysockaddr *addr, int do_tftp, in
{
l = safe_malloc(sizeof(struct listener));
l->next = NULL;
l->family = addr->sa.sa_family;
l->fd = fd;
l->tcpfd = tcpfd;
l->tftpfd = tftpfd;
l->tftpfd = tftpfd;
l->addr = *addr;
l->used = 1;
l->iface = NULL;
}
@@ -937,20 +1007,48 @@ void create_wildcard_listeners(void)
daemon->listeners = l;
}
static struct listener *find_listener(union mysockaddr *addr)
{
struct listener *l;
for (l = daemon->listeners; l; l = l->next)
if (sockaddr_isequal(&l->addr, addr))
return l;
return NULL;
}
void create_bound_listeners(int dienow)
{
struct listener *new;
struct irec *iface;
struct iname *if_tmp;
struct listener *existing;
for (iface = daemon->interfaces; iface; iface = iface->next)
if (!iface->done && !iface->dad && iface->found &&
(new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
if (!iface->done && !iface->dad && iface->found)
{
new->iface = iface;
new->next = daemon->listeners;
daemon->listeners = new;
iface->done = 1;
existing = find_listener(&iface->addr);
if (existing)
{
iface->done = 1;
existing->used++; /* increase usage counter */
}
else if ((new = create_listeners(&iface->addr, iface->tftp_ok, dienow)))
{
new->iface = iface;
new->next = daemon->listeners;
daemon->listeners = new;
iface->done = 1;
/* Don't log the initial set of listen addresses created
at startup, since this is happening before the logging
system is initialised and the sign-on printed. */
if (!dienow)
{
int port = prettyprint_addr(&iface->addr, daemon->addrbuff);
my_syslog(LOG_DEBUG, _("listening on %s(#%d): %s port %d"),
iface->name, iface->index, daemon->addrbuff, port);
}
}
}
/* Check for --listen-address options that haven't been used because there's
@@ -970,6 +1068,12 @@ void create_bound_listeners(int dienow)
{
new->next = daemon->listeners;
daemon->listeners = new;
if (!dienow)
{
int port = prettyprint_addr(&if_tmp->addr, daemon->addrbuff);
my_syslog(LOG_DEBUG, _("listening on %s port %d"), daemon->addrbuff, port);
}
}
}
@@ -1301,7 +1405,7 @@ void pre_allocate_sfds(void)
errno != 0 &&
option_bool(OPT_NOWILD))
{
prettyprint_addr(&srv->source_addr, daemon->namebuff);
(void)prettyprint_addr(&srv->source_addr, daemon->namebuff);
if (srv->interface[0] != 0)
{
strcat(daemon->namebuff, " ");
+1 -1
View File
@@ -1225,7 +1225,7 @@ static int parse_dhcp_opt(char *errstr, char *arg, int flags)
}
else if (c == '.')
{
is_addr6 = is_dec = is_hex = 0;
is_dec = is_hex = 0;
dots++;
}
else if (c == '-')
+18 -17
View File
@@ -61,8 +61,9 @@ void tftp_request(struct listener *listen, time_t now)
char *prefix = daemon->tftp_prefix;
struct tftp_prefix *pref;
union all_addr addra;
int family = listen->addr.sa.sa_family;
/* Can always get recvd interface for IPv6 */
int check_dest = !option_bool(OPT_NOWILD) || listen->family == AF_INET6;
int check_dest = !option_bool(OPT_NOWILD) || family == AF_INET6;
union {
struct cmsghdr align; /* this ensures alignment */
char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
@@ -121,10 +122,10 @@ void tftp_request(struct listener *listen, time_t now)
if (msg.msg_controllen < sizeof(struct cmsghdr))
return;
addr.sa.sa_family = listen->family;
addr.sa.sa_family = family;
#if defined(HAVE_LINUX_NETWORK)
if (listen->family == AF_INET)
if (family == AF_INET)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
{
@@ -138,7 +139,7 @@ void tftp_request(struct listener *listen, time_t now)
}
#elif defined(HAVE_SOLARIS_NETWORK)
if (listen->family == AF_INET)
if (family == AF_INET)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
{
union {
@@ -154,7 +155,7 @@ void tftp_request(struct listener *listen, time_t now)
}
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
if (listen->family == AF_INET)
if (family == AF_INET)
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
{
union {
@@ -171,7 +172,7 @@ void tftp_request(struct listener *listen, time_t now)
#endif
if (listen->family == AF_INET6)
if (family == AF_INET6)
{
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
@@ -194,7 +195,7 @@ void tftp_request(struct listener *listen, time_t now)
addra.addr4 = addr.in.sin_addr;
if (listen->family == AF_INET6)
if (family == AF_INET6)
addra.addr6 = addr.in6.sin6_addr;
if (daemon->tftp_interfaces)
@@ -210,12 +211,12 @@ void tftp_request(struct listener *listen, time_t now)
else
{
/* Do the same as DHCP */
if (!iface_check(listen->family, &addra, name, NULL))
if (!iface_check(family, &addra, name, NULL))
{
if (!option_bool(OPT_CLEVERBIND))
enumerate_interfaces(0);
if (!loopback_exception(listen->tftpfd, listen->family, &addra, name) &&
!label_exception(if_index, listen->family, &addra))
if (!loopback_exception(listen->tftpfd, family, &addra, name) &&
!label_exception(if_index, family, &addra))
return;
}
@@ -281,7 +282,7 @@ void tftp_request(struct listener *listen, time_t now)
prefix = pref->prefix;
}
if (listen->family == AF_INET)
if (family == AF_INET)
{
addr.in.sin_port = htons(port);
#ifdef HAVE_SOCKADDR_SA_LEN
@@ -304,7 +305,7 @@ void tftp_request(struct listener *listen, time_t now)
if (option_bool(OPT_SINGLE_PORT))
transfer->sockfd = listen->tftpfd;
else if ((transfer->sockfd = socket(listen->family, SOCK_DGRAM, 0)) == -1)
else if ((transfer->sockfd = socket(family, SOCK_DGRAM, 0)) == -1)
{
free(transfer);
return;
@@ -322,7 +323,7 @@ void tftp_request(struct listener *listen, time_t now)
transfer->opt_blocksize = transfer->opt_transize = 0;
transfer->netascii = transfer->carrylf = 0;
prettyprint_addr(&peer, daemon->addrbuff);
(void)prettyprint_addr(&peer, daemon->addrbuff);
/* if we have a nailed-down range, iterate until we find a free one. */
while (!option_bool(OPT_SINGLE_PORT))
@@ -337,7 +338,7 @@ void tftp_request(struct listener *listen, time_t now)
{
if (++port <= daemon->end_tftp_port)
{
if (listen->family == AF_INET)
if (family == AF_INET)
addr.in.sin_port = htons(port);
else
addr.in6.sin6_port = htons(port);
@@ -375,7 +376,7 @@ void tftp_request(struct listener *listen, time_t now)
if ((opt = next(&p, end)) && !option_bool(OPT_TFTP_NOBLOCK))
{
/* 32 bytes for IP, UDP and TFTP headers, 52 bytes for IPv6 */
int overhead = (listen->family == AF_INET) ? 32 : 52;
int overhead = (family == AF_INET) ? 32 : 52;
transfer->blocksize = atoi(opt);
if (transfer->blocksize < 1)
transfer->blocksize = 1;
@@ -624,7 +625,7 @@ void check_tftp_listeners(time_t now)
{
strcpy(daemon->namebuff, transfer->file->filename);
sanitise(daemon->namebuff);
prettyprint_addr(&transfer->peer, daemon->addrbuff);
(void)prettyprint_addr(&transfer->peer, daemon->addrbuff);
my_syslog(MS_TFTP | LOG_INFO, endcon ? _("failed sending %s to %s") : _("sent %s to %s"), daemon->namebuff, daemon->addrbuff);
/* unlink */
*up = tmp;
@@ -667,7 +668,7 @@ static void handle_tftp(time_t now, struct tftp_transfer *transfer, ssize_t len)
char *end = daemon->packet + len;
char *err = next(&p, end);
prettyprint_addr(&transfer->peer, daemon->addrbuff);
(void)prettyprint_addr(&transfer->peer, daemon->addrbuff);
/* Sanitise error message */
if (!err)