summaryrefslogtreecommitdiff
path: root/source4/lib/socket
diff options
context:
space:
mode:
authorLandon Fuller <landonf@bikemonkey.org>2013-03-02 14:08:47 -0500
committerAndrew Bartlett <abartlet@samba.org>2013-03-02 23:34:03 +0100
commitc692bb02b039ae8fef6ba968fd13b36ad7d62a72 (patch)
treeef0ecae7596c009ad93132a8da797a81d76af291 /source4/lib/socket
parent606f5d6cc6b018259ba0306fe3b55e21b4b70fdb (diff)
downloadsamba-c692bb02b039ae8fef6ba968fd13b36ad7d62a72.tar.gz
samba-c692bb02b039ae8fef6ba968fd13b36ad7d62a72.tar.bz2
samba-c692bb02b039ae8fef6ba968fd13b36ad7d62a72.zip
Handle EMSGSIZE on UNIX domain sockets.
On some systems (eg, FreeBSD) the default SO_SNDBUF for UNIX domain sockets is to small, and EMSGSIZE is returned. Other systems provide a larger default send buffer, but there is still no guarantee that the buffer will be sized appropriately. This patch modifies the sendto() path to attempt to resize the SO_SNDBUF dynamically upon an EMSGSIZE failure, and then retry the send. This fixes local DCE/RPC errors on FreeBSD, eg: https://lists.samba.org/archive/samba-technical/2013-January/089881.html Signed-Off-By: Landon Fuller <landonf@bikemonkey.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org> Autobuild-User(master): Andrew Bartlett <abartlet@samba.org> Autobuild-Date(master): Sat Mar 2 23:34:03 CET 2013 on sn-devel-104
Diffstat (limited to 'source4/lib/socket')
-rw-r--r--source4/lib/socket/socket_unix.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/source4/lib/socket/socket_unix.c b/source4/lib/socket/socket_unix.c
index 4755e796a4..049e5707c8 100644
--- a/source4/lib/socket/socket_unix.c
+++ b/source4/lib/socket/socket_unix.c
@@ -263,26 +263,43 @@ static NTSTATUS unixdom_sendto(struct socket_context *sock,
const DATA_BLOB *blob, size_t *sendlen,
const struct socket_address *dest)
{
+ struct sockaddr_un srv_addr;
+ const struct sockaddr *sa;
+ socklen_t sa_len;
ssize_t len;
+
*sendlen = 0;
-
+
if (dest->sockaddr) {
- len = sendto(sock->fd, blob->data, blob->length, 0,
- dest->sockaddr, dest->sockaddrlen);
+ sa = dest->sockaddr;
+ sa_len = dest->sockaddrlen;
} else {
- struct sockaddr_un srv_addr;
-
if (strlen(dest->addr)+1 > sizeof(srv_addr.sun_path)) {
return NT_STATUS_OBJECT_PATH_INVALID;
}
-
+
ZERO_STRUCT(srv_addr);
srv_addr.sun_family = AF_UNIX;
- snprintf(srv_addr.sun_path, sizeof(srv_addr.sun_path), "%s", dest->addr);
+ snprintf(srv_addr.sun_path, sizeof(srv_addr.sun_path), "%s",
+ dest->addr);
+ sa = (struct sockaddr *) &srv_addr;
+ sa_len = sizeof(srv_addr);
+ }
+
+ len = sendto(sock->fd, blob->data, blob->length, 0, sa, sa_len);
- len = sendto(sock->fd, blob->data, blob->length, 0,
- (struct sockaddr *)&srv_addr, sizeof(srv_addr));
+ /* retry once */
+ if (len == -1 && errno == EMSGSIZE) {
+ /* round up in 1K increments */
+ int bufsize = ((blob->length + 1023) & (~1023));
+ if (setsockopt(sock->fd, SOL_SOCKET, SO_SNDBUF, &bufsize,
+ sizeof(bufsize)) == -1)
+ {
+ return map_nt_error_from_unix_common(errno);
+ }
+ len = sendto(sock->fd, blob->data, blob->length, 0, sa, sa_len);
}
+
if (len == -1) {
return map_nt_error_from_unix_common(errno);
}