samldb: Allow automatic generation of mAPIIDs
[sfrench/samba-autobuild/.git] / source4 / lib / socket / socket_unix.c
index 7686fea1d81947745ee2c7675ab2ae838265c3ad..6876e395ed632d1e706b865b33449b45460899e1 100644 (file)
@@ -25,6 +25,7 @@
 #include "system/network.h"
 #include "system/filesys.h"
 
+_PUBLIC_ const struct socket_ops *socket_unixdom_ops(enum socket_type type);
 
 
 /*
@@ -32,7 +33,7 @@
 */
 static NTSTATUS unixdom_error(int ernum)
 {
-       return map_nt_error_from_unix(ernum);
+       return map_nt_error_from_unix_common(ernum);
 }
 
 static NTSTATUS unixdom_init(struct socket_context *sock)
@@ -52,12 +53,14 @@ static NTSTATUS unixdom_init(struct socket_context *sock)
 
        sock->fd = socket(PF_UNIX, type, 0);
        if (sock->fd == -1) {
-               return map_nt_error_from_unix(errno);
+               return map_nt_error_from_unix_common(errno);
        }
        sock->private_data = NULL;
 
        sock->backend_name = "unix";
 
+       smb_set_close_on_exec(sock->fd);
+
        return NT_STATUS_OK;
 }
 
@@ -75,16 +78,16 @@ static NTSTATUS unixdom_connect_complete(struct socket_context *sock, uint32_t f
           for non-blocking connect */
        ret = getsockopt(sock->fd, SOL_SOCKET, SO_ERROR, &error, &len);
        if (ret == -1) {
-               return map_nt_error_from_unix(errno);
+               return map_nt_error_from_unix_common(errno);
        }
        if (error != 0) {
-               return map_nt_error_from_unix(error);
+               return map_nt_error_from_unix_common(error);
        }
 
        if (!(flags & SOCKET_FLAG_BLOCK)) {
-               ret = set_blocking(sock->fd, False);
+               ret = set_blocking(sock->fd, false);
                if (ret == -1) {
-                       return map_nt_error_from_unix(errno);
+                       return map_nt_error_from_unix_common(errno);
                }
        }
 
@@ -110,7 +113,7 @@ static NTSTATUS unixdom_connect(struct socket_context *sock,
                
                ZERO_STRUCT(srv_addr);
                srv_addr.sun_family = AF_UNIX;
-               strncpy(srv_addr.sun_path, srv_address->addr, sizeof(srv_addr.sun_path));
+               snprintf(srv_addr.sun_path, sizeof(srv_addr.sun_path), "%s", srv_address->addr);
 
                ret = connect(sock->fd, (const struct sockaddr *)&srv_addr, sizeof(srv_addr));
        }
@@ -145,8 +148,8 @@ static NTSTATUS unixdom_listen(struct socket_context *sock,
                
                ZERO_STRUCT(my_addr);
                my_addr.sun_family = AF_UNIX;
-               strncpy(my_addr.sun_path, my_address->addr, sizeof(my_addr.sun_path));
-               
+               snprintf(my_addr.sun_path, sizeof(my_addr.sun_path), "%s", my_address->addr);
+
                ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr));
        }
        if (ret == -1) {
@@ -161,7 +164,7 @@ static NTSTATUS unixdom_listen(struct socket_context *sock,
        }
 
        if (!(flags & SOCKET_FLAG_BLOCK)) {
-               ret = set_blocking(sock->fd, False);
+               ret = set_blocking(sock->fd, false);
                if (ret == -1) {
                        return unixdom_error(errno);
                }
@@ -190,13 +193,15 @@ static NTSTATUS unixdom_accept(struct socket_context *sock,
        }
 
        if (!(sock->flags & SOCKET_FLAG_BLOCK)) {
-               int ret = set_blocking(new_fd, False);
+               int ret = set_blocking(new_fd, false);
                if (ret == -1) {
                        close(new_fd);
-                       return map_nt_error_from_unix(errno);
+                       return map_nt_error_from_unix_common(errno);
                }
        }
 
+       smb_set_close_on_exec(new_fd);
+
        (*new_sock) = talloc(NULL, struct socket_context);
        if (!(*new_sock)) {
                close(new_fd);
@@ -258,28 +263,45 @@ 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;
-               strncpy(srv_addr.sun_path, dest->addr, sizeof(srv_addr.sun_path));
-               
-               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(EMSGSIZE);
+               }
+               len = sendto(sock->fd, blob->data, blob->length, 0, sa, sa_len);
        }
+
        if (len == -1) {
-               return map_nt_error_from_unix(errno);
+               return map_nt_error_from_unix_common(errno);
        }       
 
        *sendlen = len;
@@ -301,7 +323,7 @@ static char *unixdom_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_
 
 static struct socket_address *unixdom_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
 {
-       struct sockaddr_in *peer_addr;
+       struct sockaddr_un *peer_addr;
        socklen_t len = sizeof(*peer_addr);
        struct socket_address *peer;
        int ret;
@@ -312,7 +334,7 @@ static struct socket_address *unixdom_get_peer_addr(struct socket_context *sock,
        }
        
        peer->family = sock->backend_name;
-       peer_addr = talloc(peer, struct sockaddr_in);
+       peer_addr = talloc(peer, struct sockaddr_un);
        if (!peer_addr) {
                talloc_free(peer);
                return NULL;
@@ -340,7 +362,7 @@ static struct socket_address *unixdom_get_peer_addr(struct socket_context *sock,
 
 static struct socket_address *unixdom_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
 {
-       struct sockaddr_in *local_addr;
+       struct sockaddr_un *local_addr;
        socklen_t len = sizeof(*local_addr);
        struct socket_address *local;
        int ret;
@@ -351,7 +373,7 @@ static struct socket_address *unixdom_get_my_addr(struct socket_context *sock, T
        }
        
        local->family = sock->backend_name;
-       local_addr = talloc(local, struct sockaddr_in);
+       local_addr = talloc(local, struct sockaddr_un);
        if (!local_addr) {
                talloc_free(local);
                return NULL;
@@ -389,7 +411,7 @@ static NTSTATUS unixdom_pending(struct socket_context *sock, size_t *npending)
                *npending = value;
                return NT_STATUS_OK;
        }
-       return map_nt_error_from_unix(errno);
+       return map_nt_error_from_unix_common(errno);
 }
 
 static const struct socket_ops unixdom_ops = {
@@ -414,7 +436,7 @@ static const struct socket_ops unixdom_ops = {
        .fn_get_fd              = unixdom_get_fd
 };
 
-const struct socket_ops *socket_unixdom_ops(enum socket_type type)
+_PUBLIC_ const struct socket_ops *socket_unixdom_ops(enum socket_type type)
 {
        return &unixdom_ops;
 }