1
0
mirror of https://github.com/samba-team/samba.git synced 2025-07-30 19:42:05 +03:00

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
This commit is contained in:
Landon Fuller
2013-03-02 14:08:47 -05:00
committed by Andrew Bartlett
parent 606f5d6cc6
commit c692bb02b0

View File

@ -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);
len = sendto(sock->fd, blob->data, blob->length, 0,
(struct sockaddr *)&srv_addr, sizeof(srv_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);
/* 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);
}