[PATCH] Patch for bug 11714: Listening for network interface changes doesn't work
Ralph Boehme
rb at sernet.de
Thu Feb 4 17:20:20 UTC 2016
Hi!
<https://bugzilla.samba.org/show_bug.cgi?id=11714>
winbindd is watching for network interface address changes by virtue
of our addrchange_send/recv() API that uses netlink to query the
kernel for this information.
Log:
[2016/02/04 11:43:31.723123, 10, pid=17692, effective(0, 0), real(0,0)] ../source3/lib/addrchange.c:154(addrchange_done)
tdgram_recvfrom_recv returned Operation not supported
[2016/02/04 11:43:31.723176, 10, pid=17692, effective(0, 0), real(0,0), class=winbind] ../source3/winbindd/winbindd.c:1486(winbindd_addr_changed)
addrchange_recv failed: NT_STATUS_NOT_SUPPORTED, stop listening
strace shows a failing ioctl(fd, FIONREAD, ...) returning
EOPNOTSUPP. We use the ioctl to determine the amount of pending data
so we can allocate an appropriate buffer.
This is a regression introduced in 0d161e42d9aeb155eae2b04eccec497b21de8029.
What can we do?
We could use MSG_PEEK, but that's not portable and we'd have to call
recvmsg() twice every time the fd is reported readable.
As a band aid, allocate a laaaarge buffer and watch out for MSG_TRUNC
after receiving.
We could also revert 0d161e42d9aeb155eae2b04eccec497b21de8029 and fix
the issue that change was trying to address differently.
Review&comments welcome.
Thanks!
-Ralph
--
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de,mailto:kontakt@sernet.de
-------------- next part --------------
From bb4c47b7ebc96c81d3091500f6bd0f467b7a7e10 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 4 Feb 2016 15:26:05 +0100
Subject: [PATCH 1/2] lib/tsocket: use recvmsg() instead of recvfrom()
recvmsg() returns msg_flags which will be used in a subsequent commit.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=11714
Signed-off-by: Ralph Boehme <slow at samba.org>
---
lib/tsocket/tsocket_bsd.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/lib/tsocket/tsocket_bsd.c b/lib/tsocket/tsocket_bsd.c
index ac0617d..9b339da 100644
--- a/lib/tsocket/tsocket_bsd.c
+++ b/lib/tsocket/tsocket_bsd.c
@@ -891,6 +891,8 @@ static void tdgram_bsd_recvfrom_handler(void *private_data)
ssize_t ret;
int err;
bool retry;
+ struct iovec iov;
+ struct msghdr msg;
ret = tsocket_bsd_pending(bsds->fd);
if (state->first_try && ret == 0) {
@@ -931,8 +933,19 @@ static void tdgram_bsd_recvfrom_handler(void *private_data)
bsda->u.sa.sa_len = bsda->sa_socklen;
#endif
- ret = recvfrom(bsds->fd, state->buf, state->len, 0,
- &bsda->u.sa, &bsda->sa_socklen);
+ iov = (struct iovec) {
+ .iov_base = state->buf,
+ .iov_len = state->len
+ };
+
+ msg = (struct msghdr) {
+ .msg_name = &bsda->u.sa,
+ .msg_namelen = bsda->sa_socklen,
+ .msg_iov = &iov,
+ .msg_iovlen = 1
+ };
+
+ ret = recvmsg(bsds->fd, &msg, 0);
err = tsocket_bsd_error_from_errno(ret, errno, &retry);
if (retry) {
/* retry later */
@@ -942,6 +955,8 @@ static void tdgram_bsd_recvfrom_handler(void *private_data)
return;
}
+ bsda->sa_socklen = msg.msg_namelen;
+
/*
* Some systems (FreeBSD, see bug #7115) return too much
* bytes in tsocket_bsd_pending()/ioctl(fd, FIONREAD, ...),
--
2.5.0
From 28dfca513b9cc28107438edb1b616ef393b89b45 Mon Sep 17 00:00:00 2001
From: Ralph Boehme <slow at samba.org>
Date: Thu, 4 Feb 2016 15:35:06 +0100
Subject: [PATCH 2/2] lib/tsocket: workaround sockets not supporting FIONREAD
Some sockets, notably netlink sockets, don't support querying pending
bytes with ioctl(fd, FIONREAD, ...) and return EOPNOTSUPP.
What can we do?
We could use MSG_PEEK, but that's not portable and we'd have to call
recvmsg() twice every time the fd is reported readable.
As a band aid, allocate a laaaarge buffer and watch out for MSG_TRUNC
after receiving.
The buffer is reallocated to the actual size at the end anyway and then
passed to the caller.
Bug: https://bugzilla.samba.org/show_bug.cgi?id=11714
Signed-off-by: Ralph Boehme <slow at samba.org>
---
lib/tsocket/tsocket_bsd.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/lib/tsocket/tsocket_bsd.c b/lib/tsocket/tsocket_bsd.c
index 9b339da..146afeb 100644
--- a/lib/tsocket/tsocket_bsd.c
+++ b/lib/tsocket/tsocket_bsd.c
@@ -140,6 +140,16 @@ static ssize_t tsocket_bsd_pending(int fd)
ret = ioctl(fd, FIONREAD, &value);
if (ret == -1) {
+ if (errno == EOPNOTSUPP) {
+ /*
+ * Damn! Some sockets, notably netlink sockets, don't
+ * support this. Allocate a large buffer, hoping for the
+ * best. In case the received messages is truncated,
+ * we'll return an error.
+ */
+ errno = 0;
+ return 64 * 1024;
+ }
return ret;
}
@@ -946,6 +956,18 @@ static void tdgram_bsd_recvfrom_handler(void *private_data)
};
ret = recvmsg(bsds->fd, &msg, 0);
+
+ if (msg.msg_flags & MSG_TRUNC) {
+ /*
+ * It didn't work out to peak at the pending bytes in
+ * tsocket_bsd_pending() and we used some default size that
+ * apperently wasn't big enough. We can't recover from this so
+ * error out.
+ */
+ errno = EINVAL;
+ ret = -1;
+ }
+
err = tsocket_bsd_error_from_errno(ret, errno, &retry);
if (retry) {
/* retry later */
--
2.5.0
More information about the samba-technical
mailing list