r15356: Remove unused 'flags' argument from socket_send() and friends.
[bbaumbach/samba-autobuild/.git] / source4 / lib / socket / socket_ipv4.c
index d6b6bf7be4ec90a3dd0378ea273f43e43b047683..38c9f98fdbbfda0777a19d52d45d26907ef0e4bf 100644 (file)
@@ -23,6 +23,8 @@
 
 #include "includes.h"
 #include "system/network.h"
+#include "system/filesys.h"
+#include "lib/socket/socket.h"
 
 static NTSTATUS ipv4_init(struct socket_context *sock)
 {
@@ -44,6 +46,8 @@ static NTSTATUS ipv4_init(struct socket_context *sock)
                return map_nt_error_from_unix(errno);
        }
 
+       sock->backend_name = "ipv4";
+
        return NT_STATUS_OK;
 }
 
@@ -81,46 +85,63 @@ static NTSTATUS ipv4_connect_complete(struct socket_context *sock, uint32_t flag
 
 
 static NTSTATUS ipv4_connect(struct socket_context *sock,
-                                const char *my_address, int my_port,
-                                const char *srv_address, int srv_port,
-                                uint32_t flags)
+                            const struct socket_address *my_address, 
+                            const struct socket_address *srv_address,
+                            uint32_t flags)
 {
        struct sockaddr_in srv_addr;
        struct ipv4_addr my_ip;
        struct ipv4_addr srv_ip;
        int ret;
 
-       my_ip = interpret_addr2(my_address);
-
-       if (my_ip.addr != 0 || my_port != 0) {
-               struct sockaddr_in my_addr;
-               ZERO_STRUCT(my_addr);
-#ifdef HAVE_SOCK_SIN_LEN
-               my_addr.sin_len         = sizeof(my_addr);
-#endif
-               my_addr.sin_addr.s_addr = my_ip.addr;
-               my_addr.sin_port        = htons(my_port);
-               my_addr.sin_family      = PF_INET;
-               
-               ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr));
+       if (my_address && my_address->sockaddr) {
+               ret = bind(sock->fd, my_address->sockaddr, my_address->sockaddrlen);
                if (ret == -1) {
                        return map_nt_error_from_unix(errno);
                }
+       } else if (my_address) {
+               my_ip = interpret_addr2(my_address->addr);
+               
+               if (my_ip.addr != 0 || my_address->port != 0) {
+                       struct sockaddr_in my_addr;
+                       ZERO_STRUCT(my_addr);
+#ifdef HAVE_SOCK_SIN_LEN
+                       my_addr.sin_len         = sizeof(my_addr);
+#endif
+                       my_addr.sin_addr.s_addr = my_ip.addr;
+                       my_addr.sin_port        = htons(my_address->port);
+                       my_addr.sin_family      = PF_INET;
+                       
+                       ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr));
+                       if (ret == -1) {
+                               return map_nt_error_from_unix(errno);
+                       }
+               }
        }
 
-       srv_ip = interpret_addr2(srv_address);
-
-       ZERO_STRUCT(srv_addr);
+       if (srv_address->sockaddr) {
+               ret = connect(sock->fd, srv_address->sockaddr, srv_address->sockaddrlen);
+               if (ret == -1) {
+                       return map_nt_error_from_unix(errno);
+               }
+       } else {
+               srv_ip = interpret_addr2(srv_address->addr);
+               if (!srv_ip.addr) {
+                       return NT_STATUS_BAD_NETWORK_NAME;
+               }
+               
+               ZERO_STRUCT(srv_addr);
 #ifdef HAVE_SOCK_SIN_LEN
-       srv_addr.sin_len        = sizeof(srv_addr);
+               srv_addr.sin_len        = sizeof(srv_addr);
 #endif
-       srv_addr.sin_addr.s_addr= srv_ip.addr;
-       srv_addr.sin_port       = htons(srv_port);
-       srv_addr.sin_family     = PF_INET;
+               srv_addr.sin_addr.s_addr= srv_ip.addr;
+               srv_addr.sin_port       = htons(srv_address->port);
+               srv_addr.sin_family     = PF_INET;
 
-       ret = connect(sock->fd, (const struct sockaddr *)&srv_addr, sizeof(srv_addr));
-       if (ret == -1) {
-               return map_nt_error_from_unix(errno);
+               ret = connect(sock->fd, (const struct sockaddr *)&srv_addr, sizeof(srv_addr));
+               if (ret == -1) {
+                       return map_nt_error_from_unix(errno);
+               }
        }
 
        return ipv4_connect_complete(sock, flags);
@@ -132,24 +153,31 @@ static NTSTATUS ipv4_connect(struct socket_context *sock,
   use for DGRAM sockets, but in reality only a bind() is done
 */
 static NTSTATUS ipv4_listen(struct socket_context *sock,
-                           const char *my_address, int port,
+                           const struct socket_address *my_address, 
                            int queue_size, uint32_t flags)
 {
        struct sockaddr_in my_addr;
        struct ipv4_addr ip_addr;
        int ret;
 
-       ip_addr = interpret_addr2(my_address);
+       socket_set_option(sock, "SO_REUSEADDR=1", NULL);
 
-       ZERO_STRUCT(my_addr);
+       if (my_address->sockaddr) {
+               ret = bind(sock->fd, my_address->sockaddr, my_address->sockaddrlen);
+       } else {
+               ip_addr = interpret_addr2(my_address->addr);
+               
+               ZERO_STRUCT(my_addr);
 #ifdef HAVE_SOCK_SIN_LEN
-       my_addr.sin_len         = sizeof(my_addr);
+               my_addr.sin_len         = sizeof(my_addr);
 #endif
-       my_addr.sin_addr.s_addr = ip_addr.addr;
-       my_addr.sin_port        = htons(port);
-       my_addr.sin_family      = PF_INET;
+               my_addr.sin_addr.s_addr = ip_addr.addr;
+               my_addr.sin_port        = htons(my_address->port);
+               my_addr.sin_family      = PF_INET;
+               
+               ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr));
+       }
 
-       ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr));
        if (ret == -1) {
                return map_nt_error_from_unix(errno);
        }
@@ -202,7 +230,7 @@ static NTSTATUS ipv4_accept(struct socket_context *sock, struct socket_context *
         *       --metze
         */
 
-       (*new_sock) = talloc_p(NULL, struct socket_context);
+       (*new_sock) = talloc(NULL, struct socket_context);
        if (!(*new_sock)) {
                close(new_fd);
                return NT_STATUS_NO_MEMORY;
@@ -217,28 +245,19 @@ static NTSTATUS ipv4_accept(struct socket_context *sock, struct socket_context *
 
        (*new_sock)->private_data       = NULL;
        (*new_sock)->ops                = sock->ops;
+       (*new_sock)->backend_name       = sock->backend_name;
 
        return NT_STATUS_OK;
 }
 
 static NTSTATUS ipv4_recv(struct socket_context *sock, void *buf, 
-                             size_t wantlen, size_t *nread, uint32_t flags)
+                             size_t wantlen, size_t *nread)
 {
        ssize_t gotlen;
-       int flgs = 0;
-
-       /* TODO: we need to map all flags here */
-       if (flags & SOCKET_FLAG_PEEK) {
-               flgs |= MSG_PEEK;
-       }
-
-       if (flags & SOCKET_FLAG_BLOCK) {
-               flgs |= MSG_WAITALL;
-       }
 
        *nread = 0;
 
-       gotlen = recv(sock->fd, buf, wantlen, flgs);
+       gotlen = recv(sock->fd, buf, wantlen, 0);
        if (gotlen == 0) {
                return NT_STATUS_END_OF_FILE;
        } else if (gotlen == -1) {
@@ -252,55 +271,69 @@ static NTSTATUS ipv4_recv(struct socket_context *sock, void *buf,
 
 
 static NTSTATUS ipv4_recvfrom(struct socket_context *sock, void *buf, 
-                             size_t wantlen, size_t *nread, uint32_t flags,
-                             const char **src_addr, int *src_port)
+                             size_t wantlen, size_t *nread, 
+                             TALLOC_CTX *addr_ctx, struct socket_address **_src)
 {
        ssize_t gotlen;
-       int flgs = 0;
-       struct sockaddr_in from_addr;
-       socklen_t from_len = sizeof(from_addr);
+       struct sockaddr_in *from_addr;
+       socklen_t from_len = sizeof(*from_addr);
+       struct socket_address *src;
        const char *addr;
-
-       if (flags & SOCKET_FLAG_PEEK) {
-               flgs |= MSG_PEEK;
+       
+       src = talloc(addr_ctx, struct socket_address);
+       if (!src) {
+               return NT_STATUS_NO_MEMORY;
        }
+       
+       src->family = sock->backend_name;
 
-       if (flags & SOCKET_FLAG_BLOCK) {
-               flgs |= MSG_WAITALL;
+       from_addr = talloc(src, struct sockaddr_in);
+       if (!from_addr) {
+               talloc_free(src);
+               return NT_STATUS_NO_MEMORY;
        }
 
+       src->sockaddr = (struct sockaddr *)from_addr;
+
        *nread = 0;
 
-       gotlen = recvfrom(sock->fd, buf, wantlen, flgs
-                         (struct sockaddr *)&from_addr, &from_len);
+       gotlen = recvfrom(sock->fd, buf, wantlen, 0
+                         src->sockaddr, &from_len);
        if (gotlen == 0) {
+               talloc_free(src);
                return NT_STATUS_END_OF_FILE;
        } else if (gotlen == -1) {
+               talloc_free(src);
                return map_nt_error_from_unix(errno);
        }
 
-       addr = inet_ntoa(from_addr.sin_addr);
+       src->sockaddrlen = from_len;
+
+       addr = inet_ntoa(from_addr->sin_addr);
        if (addr == NULL) {
+               talloc_free(src);
                return NT_STATUS_INTERNAL_ERROR;
        }
-       *src_addr = talloc_strdup(sock, addr);
-       NT_STATUS_HAVE_NO_MEMORY(*src_addr);
-       *src_port = ntohs(from_addr.sin_port);
-
-       *nread = gotlen;
+       src->addr = talloc_strdup(src, addr);
+       if (src->addr == NULL) {
+               talloc_free(src);
+               return NT_STATUS_NO_MEMORY;
+       }
+       src->port = ntohs(from_addr->sin_port);
 
+       *nread  = gotlen;
+       *_src   = src;
        return NT_STATUS_OK;
 }
 
 static NTSTATUS ipv4_send(struct socket_context *sock, 
-                             const DATA_BLOB *blob, size_t *sendlen, uint32_t flags)
+                             const DATA_BLOB *blob, size_t *sendlen)
 {
        ssize_t len;
-       int flgs = 0;
 
        *sendlen = 0;
 
-       len = send(sock->fd, blob->data, blob->length, flgs);
+       len = send(sock->fd, blob->data, blob->length, 0);
        if (len == -1) {
                return map_nt_error_from_unix(errno);
        }       
@@ -311,27 +344,32 @@ static NTSTATUS ipv4_send(struct socket_context *sock,
 }
 
 static NTSTATUS ipv4_sendto(struct socket_context *sock, 
-                           const DATA_BLOB *blob, size_t *sendlen, uint32_t flags,
-                           const char *dest_addr, int dest_port)
+                           const DATA_BLOB *blob, size_t *sendlen, 
+                           const struct socket_address *dest_addr)
 {
        ssize_t len;
-       int flgs = 0;
-       struct sockaddr_in srv_addr;
-       struct ipv4_addr addr;
 
-       ZERO_STRUCT(srv_addr);
+       if (dest_addr->sockaddr) {
+               len = sendto(sock->fd, blob->data, blob->length, 0, 
+                            dest_addr->sockaddr, dest_addr->sockaddrlen);
+       } else {
+               struct sockaddr_in srv_addr;
+               struct ipv4_addr addr;
+               
+               ZERO_STRUCT(srv_addr);
 #ifdef HAVE_SOCK_SIN_LEN
-       srv_addr.sin_len         = sizeof(srv_addr);
+               srv_addr.sin_len         = sizeof(srv_addr);
 #endif
-       addr                     = interpret_addr2(dest_addr);
-       srv_addr.sin_addr.s_addr = addr.addr;
-       srv_addr.sin_port        = htons(dest_port);
-       srv_addr.sin_family      = PF_INET;
-
-       *sendlen = 0;
-
-       len = sendto(sock->fd, blob->data, blob->length, flgs, 
-                  (struct sockaddr *)&srv_addr, sizeof(srv_addr));
+               addr                     = interpret_addr2(dest_addr->addr);
+               srv_addr.sin_addr.s_addr = addr.addr;
+               srv_addr.sin_port        = htons(dest_addr->port);
+               srv_addr.sin_family      = PF_INET;
+               
+               *sendlen = 0;
+               
+               len = sendto(sock->fd, blob->data, blob->length, 0, 
+                            (struct sockaddr *)&srv_addr, sizeof(srv_addr));
+       }
        if (len == -1) {
                return map_nt_error_from_unix(errno);
        }       
@@ -367,67 +405,110 @@ static char *ipv4_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx
        return talloc_strdup(mem_ctx, he->h_name);
 }
 
-static char *ipv4_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
+static struct socket_address *ipv4_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
 {
-       struct sockaddr_in peer_addr;
-       socklen_t len = sizeof(peer_addr);
+       struct sockaddr_in *peer_addr;
+       socklen_t len = sizeof(*peer_addr);
+       const char *addr;
+       struct socket_address *peer;
        int ret;
+       
+       peer = talloc(mem_ctx, struct socket_address);
+       if (!peer) {
+               return NULL;
+       }
+       
+       peer->family = sock->backend_name;
+       peer_addr = talloc(peer, struct sockaddr_in);
+       if (!peer_addr) {
+               talloc_free(peer);
+               return NULL;
+       }
 
-       ret = getpeername(sock->fd, (struct sockaddr *)&peer_addr, &len);
+       peer->sockaddr = (struct sockaddr *)peer_addr;
+
+       ret = getpeername(sock->fd, peer->sockaddr, &len);
        if (ret == -1) {
+               talloc_free(peer);
                return NULL;
        }
 
-       return talloc_strdup(mem_ctx, inet_ntoa(peer_addr.sin_addr));
-}
-
-static int ipv4_get_peer_port(struct socket_context *sock)
-{
-       struct sockaddr_in peer_addr;
-       socklen_t len = sizeof(peer_addr);
-       int ret;
+       peer->sockaddrlen = len;
 
-       ret = getpeername(sock->fd, (struct sockaddr *)&peer_addr, &len);
-       if (ret == -1) {
-               return -1;
+       addr = inet_ntoa(peer_addr->sin_addr);
+       if (addr == NULL) {
+               talloc_free(peer);
+               return NULL;
+       }
+       peer->addr = talloc_strdup(peer, addr);
+       if (!peer->addr) {
+               talloc_free(peer);
+               return NULL;
        }
+       peer->port = ntohs(peer_addr->sin_port);
 
-       return ntohs(peer_addr.sin_port);
+       return peer;
 }
 
-static char *ipv4_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
+static struct socket_address *ipv4_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
 {
-       struct sockaddr_in my_addr;
-       socklen_t len = sizeof(my_addr);
+       struct sockaddr_in *local_addr;
+       socklen_t len = sizeof(*local_addr);
+       const char *addr;
+       struct socket_address *local;
        int ret;
+       
+       local = talloc(mem_ctx, struct socket_address);
+       if (!local) {
+               return NULL;
+       }
+       
+       local->family = sock->backend_name;
+       local_addr = talloc(local, struct sockaddr_in);
+       if (!local_addr) {
+               talloc_free(local);
+               return NULL;
+       }
+
+       local->sockaddr = (struct sockaddr *)local_addr;
 
-       ret = getsockname(sock->fd, (struct sockaddr *)&my_addr, &len);
+       ret = getsockname(sock->fd, local->sockaddr, &len);
        if (ret == -1) {
+               talloc_free(local);
                return NULL;
        }
 
-       return talloc_strdup(mem_ctx, inet_ntoa(my_addr.sin_addr));
-}
-
-static int ipv4_get_my_port(struct socket_context *sock)
-{
-       struct sockaddr_in my_addr;
-       socklen_t len = sizeof(my_addr);
-       int ret;
+       local->sockaddrlen = len;
 
-       ret = getsockname(sock->fd, (struct sockaddr *)&my_addr, &len);
-       if (ret == -1) {
-               return -1;
+       addr = inet_ntoa(local_addr->sin_addr);
+       if (addr == NULL) {
+               talloc_free(local);
+               return NULL;
+       }
+       local->addr = talloc_strdup(local, addr);
+       if (!local->addr) {
+               talloc_free(local);
+               return NULL;
        }
+       local->port = ntohs(local_addr->sin_port);
 
-       return ntohs(my_addr.sin_port);
+       return local;
 }
-
 static int ipv4_get_fd(struct socket_context *sock)
 {
        return sock->fd;
 }
 
+static NTSTATUS ipv4_pending(struct socket_context *sock, size_t *npending)
+{
+       int value = 0;
+       if (ioctl(sock->fd, FIONREAD, &value) == 0) {
+               *npending = value;
+               return NT_STATUS_OK;
+       }
+       return map_nt_error_from_unix(errno);
+}
+
 static const struct socket_ops ipv4_ops = {
        .name                   = "ipv4",
        .fn_init                = ipv4_init,
@@ -439,16 +520,14 @@ static const struct socket_ops ipv4_ops = {
        .fn_recvfrom            = ipv4_recvfrom,
        .fn_send                = ipv4_send,
        .fn_sendto              = ipv4_sendto,
+       .fn_pending             = ipv4_pending,
        .fn_close               = ipv4_close,
 
        .fn_set_option          = ipv4_set_option,
 
        .fn_get_peer_name       = ipv4_get_peer_name,
        .fn_get_peer_addr       = ipv4_get_peer_addr,
-       .fn_get_peer_port       = ipv4_get_peer_port,
        .fn_get_my_addr         = ipv4_get_my_addr,
-       .fn_get_my_port         = ipv4_get_my_port,
-
        .fn_get_fd              = ipv4_get_fd
 };