Handle EMSGSIZE on UNIX domain sockets.
[nivanova/samba-autobuild/.git] / source4 / lib / socket / socket_unix.c
index 4755e796a4a9e99f4ca067c5e8af8ca31086840e..049e5707c87b799c1511f94e9bcd72297e333e56 100644 (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);
+               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);
        }