LCOV - code coverage report
Current view: top level - source4/lib/socket - socket.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 219 303 72.3 %
Date: 2024-04-21 15:09:00 Functions: 28 30 93.3 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             :    Socket functions
       4             :    Copyright (C) Andrew Tridgell 1992-1998
       5             :    Copyright (C) Tim Potter      2000-2001
       6             :    Copyright (C) Stefan Metzmacher 2004
       7             :    
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             :    
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             :    
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "lib/socket/socket.h"
      24             : #include "system/filesys.h"
      25             : #include "system/network.h"
      26             : #include "param/param.h"
      27             : #include "../lib/tsocket/tsocket.h"
      28             : #include "lib/util/util_net.h"
      29             : 
      30             : /*
      31             :   auto-close sockets on free
      32             : */
      33      419855 : static int socket_destructor(struct socket_context *sock)
      34             : {
      35      419855 :         if (sock->ops->fn_close && 
      36      419855 :             !(sock->flags & SOCKET_FLAG_NOCLOSE)) {
      37      122070 :                 sock->ops->fn_close(sock);
      38             :         }
      39      419855 :         return 0;
      40             : }
      41             : 
      42      210180 : _PUBLIC_ void socket_tevent_fd_close_fn(struct tevent_context *ev,
      43             :                                         struct tevent_fd *fde,
      44             :                                         int fd,
      45             :                                         void *private_data)
      46             : {
      47             :         /* this might be the socket_wrapper swrap_close() */
      48      210180 :         close(fd);
      49      210180 : }
      50             : 
      51      115170 : _PUBLIC_ NTSTATUS socket_create_with_ops(TALLOC_CTX *mem_ctx, const struct socket_ops *ops,
      52             :                                          struct socket_context **new_sock, 
      53             :                                          enum socket_type type, uint32_t flags)
      54             : {
      55        3087 :         NTSTATUS status;
      56             : 
      57      115170 :         (*new_sock) = talloc(mem_ctx, struct socket_context);
      58      115170 :         if (!(*new_sock)) {
      59           0 :                 return NT_STATUS_NO_MEMORY;
      60             :         }
      61             : 
      62      115170 :         (*new_sock)->type = type;
      63      115170 :         (*new_sock)->state = SOCKET_STATE_UNDEFINED;
      64      115170 :         (*new_sock)->flags = flags;
      65             : 
      66      115170 :         (*new_sock)->fd = -1;
      67             : 
      68      115170 :         (*new_sock)->private_data = NULL;
      69      115170 :         (*new_sock)->ops = ops;
      70      115170 :         (*new_sock)->backend_name = NULL;
      71             : 
      72      115170 :         status = (*new_sock)->ops->fn_init((*new_sock));
      73      115170 :         if (!NT_STATUS_IS_OK(status)) {
      74           0 :                 talloc_free(*new_sock);
      75           0 :                 return status;
      76             :         }
      77             : 
      78             :         /* by enabling "testnonblock" mode, all socket receive and
      79             :            send calls on non-blocking sockets will randomly recv/send
      80             :            less data than requested */
      81             : 
      82      198600 :         if (type == SOCKET_TYPE_STREAM &&
      83       83430 :                 getenv("SOCKET_TESTNONBLOCK") != NULL) {
      84         352 :                 (*new_sock)->flags |= SOCKET_FLAG_TESTNONBLOCK;
      85             :         }
      86             : 
      87             :         /* we don't do a connect() on dgram sockets, so need to set
      88             :            non-blocking at socket create time */
      89      115170 :         if (type == SOCKET_TYPE_DGRAM) {
      90       31740 :                 set_blocking(socket_get_fd(*new_sock), false);
      91             :         }
      92             : 
      93      115170 :         talloc_set_destructor(*new_sock, socket_destructor);
      94             : 
      95      115170 :         return NT_STATUS_OK;
      96             : }
      97             : 
      98      115170 : _PUBLIC_ NTSTATUS socket_create(TALLOC_CTX *mem_ctx,
      99             :                                 const char *name, enum socket_type type,
     100             :                                 struct socket_context **new_sock, uint32_t flags)
     101             : {
     102        3087 :         const struct socket_ops *ops;
     103             : 
     104      115170 :         ops = socket_getops_byname(name, type);
     105      115170 :         if (!ops) {
     106           0 :                 return NT_STATUS_INVALID_PARAMETER;
     107             :         }
     108             : 
     109      115170 :         return socket_create_with_ops(mem_ctx, ops, new_sock, type, flags);
     110             : }
     111             : 
     112      102744 : _PUBLIC_ NTSTATUS socket_connect(struct socket_context *sock,
     113             :                                  const struct socket_address *my_address, 
     114             :                                  const struct socket_address *server_address,
     115             :                                  uint32_t flags)
     116             : {
     117      102744 :         if (sock == NULL) {
     118           0 :                 return NT_STATUS_CONNECTION_DISCONNECTED;
     119             :         }
     120      102744 :         if (sock->state != SOCKET_STATE_UNDEFINED) {
     121           0 :                 return NT_STATUS_INVALID_PARAMETER;
     122             :         }
     123             : 
     124      102744 :         if (!sock->ops->fn_connect) {
     125           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
     126             :         }
     127             : 
     128      102744 :         return sock->ops->fn_connect(sock, my_address, server_address, flags);
     129             : }
     130             : 
     131      545445 : _PUBLIC_ NTSTATUS socket_connect_complete(struct socket_context *sock, uint32_t flags)
     132             : {
     133      545445 :         if (!sock->ops->fn_connect_complete) {
     134           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
     135             :         }
     136      545445 :         return sock->ops->fn_connect_complete(sock, flags);
     137             : }
     138             : 
     139        2889 : _PUBLIC_ NTSTATUS socket_listen(struct socket_context *sock, 
     140             :                                 const struct socket_address *my_address, 
     141             :                                 int queue_size, uint32_t flags)
     142             : {
     143        2889 :         if (sock == NULL) {
     144           0 :                 return NT_STATUS_CONNECTION_DISCONNECTED;
     145             :         }
     146        2889 :         if (sock->state != SOCKET_STATE_UNDEFINED) {
     147           0 :                 return NT_STATUS_INVALID_PARAMETER;
     148             :         }
     149             : 
     150        2889 :         if (!sock->ops->fn_listen) {
     151           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
     152             :         }
     153             : 
     154        2889 :         return sock->ops->fn_listen(sock, my_address, queue_size, flags);
     155             : }
     156             : 
     157      159576 : _PUBLIC_ NTSTATUS socket_accept(struct socket_context *sock, struct socket_context **new_sock)
     158             : {
     159        4627 :         NTSTATUS status;
     160             : 
     161      159576 :         if (sock == NULL) {
     162           0 :                 return NT_STATUS_CONNECTION_DISCONNECTED;
     163             :         }
     164      159576 :         if (sock->type != SOCKET_TYPE_STREAM) {
     165           0 :                 return NT_STATUS_INVALID_PARAMETER;
     166             :         }
     167             : 
     168      159576 :         if (sock->state != SOCKET_STATE_SERVER_LISTEN) {
     169           0 :                 return NT_STATUS_INVALID_PARAMETER;
     170             :         }
     171             : 
     172      159576 :         if (!sock->ops->fn_accept) {
     173           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
     174             :         }
     175             : 
     176      159576 :         status = sock->ops->fn_accept(sock, new_sock);
     177             : 
     178      159576 :         if (NT_STATUS_IS_OK(status)) {
     179      129384 :                 talloc_set_destructor(*new_sock, socket_destructor);
     180      129384 :                 (*new_sock)->flags = 0;
     181             :         }
     182             : 
     183      159576 :         return status;
     184             : }
     185             : 
     186     1787775 : _PUBLIC_ NTSTATUS socket_recv(struct socket_context *sock, void *buf, 
     187             :                               size_t wantlen, size_t *nread)
     188             : {
     189     1787775 :         if (sock == NULL) {
     190           0 :                 return NT_STATUS_CONNECTION_DISCONNECTED;
     191             :         }
     192     1787775 :         if (sock->state != SOCKET_STATE_CLIENT_CONNECTED &&
     193     1715959 :             sock->state != SOCKET_STATE_SERVER_CONNECTED &&
     194           0 :             sock->type  != SOCKET_TYPE_DGRAM) {
     195           0 :                 return NT_STATUS_INVALID_PARAMETER;
     196             :         }
     197             : 
     198     1787775 :         if (!sock->ops->fn_recv) {
     199           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
     200             :         }
     201             : 
     202     1787775 :         if ((sock->flags & SOCKET_FLAG_TESTNONBLOCK) 
     203         843 :             && wantlen > 1) {
     204             : 
     205         787 :                 if (random() % 10 == 0) {
     206          88 :                         *nread = 0;
     207          88 :                         return STATUS_MORE_ENTRIES;
     208             :                 }
     209         699 :                 return sock->ops->fn_recv(sock, buf, 1+(random() % wantlen), nread);
     210             :         }
     211     1786988 :         return sock->ops->fn_recv(sock, buf, wantlen, nread);
     212             : }
     213             : 
     214       14752 : _PUBLIC_ NTSTATUS socket_recvfrom(struct socket_context *sock, void *buf, 
     215             :                                   size_t wantlen, size_t *nread, 
     216             :                                   TALLOC_CTX *mem_ctx, struct socket_address **src_addr)
     217             : {
     218       14752 :         if (sock == NULL) {
     219           0 :                 return NT_STATUS_CONNECTION_DISCONNECTED;
     220             :         }
     221       14752 :         if (sock->type != SOCKET_TYPE_DGRAM) {
     222           0 :                 return NT_STATUS_INVALID_PARAMETER;
     223             :         }
     224             : 
     225       14752 :         if (!sock->ops->fn_recvfrom) {
     226           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
     227             :         }
     228             : 
     229       14752 :         return sock->ops->fn_recvfrom(sock, buf, wantlen, nread, 
     230             :                                       mem_ctx, src_addr);
     231             : }
     232             : 
     233    17401654 : _PUBLIC_ NTSTATUS socket_send(struct socket_context *sock, 
     234             :                               const DATA_BLOB *blob, size_t *sendlen)
     235             : {
     236    17401654 :         if (sock == NULL) {
     237           0 :                 return NT_STATUS_CONNECTION_DISCONNECTED;
     238             :         }
     239    17401654 :         if (sock->state != SOCKET_STATE_CLIENT_CONNECTED &&
     240      911052 :             sock->state != SOCKET_STATE_SERVER_CONNECTED) {
     241           0 :                 return NT_STATUS_INVALID_PARAMETER;
     242             :         }
     243             : 
     244    17401654 :         if (!sock->ops->fn_send) {
     245           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
     246             :         }
     247             :         
     248    17401654 :         if ((sock->flags & SOCKET_FLAG_TESTNONBLOCK)
     249         576 :             && blob->length > 1) {
     250         543 :                 DATA_BLOB blob2 = *blob;
     251         543 :                 if (random() % 10 == 0) {
     252          50 :                         *sendlen = 0;
     253          50 :                         return STATUS_MORE_ENTRIES;
     254             :                 }
     255             :                 /* The random size sends are incompatible with TLS and SASL
     256             :                  * sockets, which require re-sends to be consistent */
     257         493 :                 if (!(sock->flags & SOCKET_FLAG_ENCRYPT)) {
     258         493 :                         blob2.length = 1+(random() % blob2.length);
     259             :                 } else {
     260             :                         /* This is particularly stressful on buggy
     261             :                          * LDAP clients, that don't expect on LDAP
     262             :                          * packet in many SASL packets */
     263           0 :                         blob2.length = 1 + blob2.length/2;
     264             :                 }
     265         493 :                 return sock->ops->fn_send(sock, &blob2, sendlen);
     266             :         }
     267    17401111 :         return sock->ops->fn_send(sock, blob, sendlen);
     268             : }
     269             : 
     270             : 
     271       14057 : _PUBLIC_ NTSTATUS socket_sendto(struct socket_context *sock, 
     272             :                                 const DATA_BLOB *blob, size_t *sendlen, 
     273             :                                 const struct socket_address *dest_addr)
     274             : {
     275       14057 :         if (sock == NULL) {
     276           0 :                 return NT_STATUS_CONNECTION_DISCONNECTED;
     277             :         }
     278       14057 :         if (sock->type != SOCKET_TYPE_DGRAM) {
     279           0 :                 return NT_STATUS_INVALID_PARAMETER;
     280             :         }
     281             : 
     282       14057 :         if (sock->state == SOCKET_STATE_CLIENT_CONNECTED ||
     283       13937 :             sock->state == SOCKET_STATE_SERVER_CONNECTED) {
     284           0 :                 return NT_STATUS_INVALID_PARAMETER;
     285             :         }
     286             : 
     287       14057 :         if (!sock->ops->fn_sendto) {
     288           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
     289             :         }
     290             : 
     291       14057 :         return sock->ops->fn_sendto(sock, blob, sendlen, dest_addr);
     292             : }
     293             : 
     294             : 
     295             : /*
     296             :   ask for the number of bytes in a pending incoming packet
     297             : */
     298       62713 : _PUBLIC_ NTSTATUS socket_pending(struct socket_context *sock, size_t *npending)
     299             : {
     300       62713 :         if (sock == NULL) {
     301           0 :                 return NT_STATUS_CONNECTION_DISCONNECTED;
     302             :         }
     303       62713 :         if (!sock->ops->fn_pending) {
     304           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
     305             :         }
     306       62713 :         return sock->ops->fn_pending(sock, npending);
     307             : }
     308             : 
     309             : 
     310       31417 : _PUBLIC_ NTSTATUS socket_set_option(struct socket_context *sock, const char *option, const char *val)
     311             : {
     312       31417 :         if (sock == NULL) {
     313           0 :                 return NT_STATUS_CONNECTION_DISCONNECTED;
     314             :         }
     315       31417 :         if (!sock->ops->fn_set_option) {
     316           0 :                 return NT_STATUS_NOT_IMPLEMENTED;
     317             :         }
     318             : 
     319       31417 :         return sock->ops->fn_set_option(sock, option, val);
     320             : }
     321             : 
     322           0 : _PUBLIC_ char *socket_get_peer_name(struct socket_context *sock, TALLOC_CTX *mem_ctx)
     323             : {
     324           0 :         if (!sock->ops->fn_get_peer_name) {
     325           0 :                 return NULL;
     326             :         }
     327             : 
     328           0 :         return sock->ops->fn_get_peer_name(sock, mem_ctx);
     329             : }
     330             : 
     331      147896 : _PUBLIC_ struct socket_address *socket_get_peer_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
     332             : {
     333      147896 :         if (!sock->ops->fn_get_peer_addr) {
     334           0 :                 return NULL;
     335             :         }
     336             : 
     337      147896 :         return sock->ops->fn_get_peer_addr(sock, mem_ctx);
     338             : }
     339             : 
     340      187503 : _PUBLIC_ struct socket_address *socket_get_my_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
     341             : {
     342      187503 :         if (!sock->ops->fn_get_my_addr) {
     343           0 :                 return NULL;
     344             :         }
     345             : 
     346      187503 :         return sock->ops->fn_get_my_addr(sock, mem_ctx);
     347             : }
     348             : 
     349      289547 : _PUBLIC_ struct tsocket_address *socket_address_to_tsocket_address(TALLOC_CTX *mem_ctx,
     350             :                                                                    const struct socket_address *a)
     351             : {
     352        7006 :         struct tsocket_address *r;
     353        7006 :         int ret;
     354             : 
     355      289547 :         if (!a) {
     356           0 :                 return NULL;
     357             :         }
     358      289547 :         if (a->sockaddr) {
     359      264944 :                 ret = tsocket_address_bsd_from_sockaddr(mem_ctx,
     360             :                                                         a->sockaddr,
     361             :                                                         a->sockaddrlen,
     362             :                                                         &r);
     363             :         } else {
     364       24603 :                 ret = tsocket_address_inet_from_strings(mem_ctx,
     365             :                                                         a->family,
     366             :                                                         a->addr,
     367             :                                                         a->port,
     368             :                                                         &r);
     369             :         }
     370             : 
     371      289547 :         if (ret != 0) {
     372           0 :                 return NULL;
     373             :         }
     374             : 
     375      289547 :         return r;
     376             : }
     377             : 
     378       42377 : _PUBLIC_ void socket_address_set_port(struct socket_address *a,
     379             :                                       uint16_t port)
     380             : {
     381       42377 :         if (a->sockaddr) {
     382           0 :                 set_sockaddr_port(a->sockaddr, port);
     383             :         } else {
     384       42377 :                 a->port = port;
     385             :         }
     386             : 
     387       42377 : }
     388             : 
     389           0 : _PUBLIC_ struct socket_address *tsocket_address_to_socket_address(TALLOC_CTX *mem_ctx,
     390             :                                                                   const struct tsocket_address *a)
     391             : {
     392           0 :         ssize_t ret;
     393           0 :         struct sockaddr_storage ss;
     394           0 :         size_t sslen = sizeof(ss);
     395             : 
     396           0 :         ret = tsocket_address_bsd_sockaddr(a, (struct sockaddr *)(void *)&ss, sslen);
     397           0 :         if (ret < 0) {
     398           0 :                 return NULL;
     399             :         }
     400             : 
     401           0 :         return socket_address_from_sockaddr(mem_ctx, (struct sockaddr *)(void *)&ss, ret);
     402             : }
     403             : 
     404      132472 : _PUBLIC_ struct tsocket_address *socket_get_remote_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
     405             : {
     406        3243 :         struct socket_address *a;
     407        3243 :         struct tsocket_address *r;
     408             : 
     409      132472 :         a = socket_get_peer_addr(sock, mem_ctx);
     410      132472 :         if (a == NULL) {
     411           0 :                 return NULL;
     412             :         }
     413             : 
     414      132472 :         r = socket_address_to_tsocket_address(mem_ctx, a);
     415      132472 :         talloc_free(a);
     416      132472 :         return r;
     417             : }
     418             : 
     419      132472 : _PUBLIC_ struct tsocket_address *socket_get_local_addr(struct socket_context *sock, TALLOC_CTX *mem_ctx)
     420             : {
     421        3243 :         struct socket_address *a;
     422        3243 :         struct tsocket_address *r;
     423             : 
     424      132472 :         a = socket_get_my_addr(sock, mem_ctx);
     425      132472 :         if (a == NULL) {
     426           0 :                 return NULL;
     427             :         }
     428             : 
     429      132472 :         r = socket_address_to_tsocket_address(mem_ctx, a);
     430      132472 :         talloc_free(a);
     431      132472 :         return r;
     432             : }
     433             : 
     434      708213 : _PUBLIC_ int socket_get_fd(struct socket_context *sock)
     435             : {
     436      708213 :         if (!sock->ops->fn_get_fd) {
     437           0 :                 return -1;
     438             :         }
     439             : 
     440      708213 :         return sock->ops->fn_get_fd(sock);
     441             : }
     442             : 
     443             : /*
     444             :   call dup() on a socket, and close the old fd. This is used to change
     445             :   the fd to the lowest available number, to make select() more
     446             :   efficient (select speed depends on the maximum fd number passed to
     447             :   it)
     448             : */
     449       15423 : _PUBLIC_ NTSTATUS socket_dup(struct socket_context *sock)
     450             : {
     451           0 :         int fd;
     452       15423 :         if (sock->fd == -1) {
     453           0 :                 return NT_STATUS_INVALID_HANDLE;
     454             :         }
     455       15423 :         fd = dup(sock->fd);
     456       15423 :         if (fd == -1) {
     457           0 :                 return map_nt_error_from_unix_common(errno);
     458             :         }
     459       15423 :         close(sock->fd);
     460       15423 :         sock->fd = fd;
     461       15423 :         return NT_STATUS_OK;
     462             :         
     463             : }
     464             : 
     465             : /* Create a new socket_address.  The type must match the socket type.
     466             :  * The host parameter may be an IP or a hostname 
     467             :  */
     468             : 
     469      130050 : _PUBLIC_ struct socket_address *socket_address_from_strings(TALLOC_CTX *mem_ctx,
     470             :                                                             const char *family,
     471             :                                                             const char *host,
     472             :                                                             int port)
     473             : {
     474      130050 :         struct socket_address *addr = talloc(mem_ctx, struct socket_address);
     475      130050 :         if (!addr) {
     476           0 :                 return NULL;
     477             :         }
     478             : 
     479      130050 :         if (strcmp(family, "ip") == 0 && is_ipaddress_v6(host)) {
     480             :                 /* leaving as "ip" would force IPv4 */
     481       46559 :                 family = "ipv6";
     482             :         }
     483             : 
     484      130050 :         addr->family = family;
     485      130050 :         addr->addr = talloc_strdup(addr, host);
     486      130050 :         if (!addr->addr) {
     487           0 :                 talloc_free(addr);
     488           0 :                 return NULL;
     489             :         }
     490      130050 :         addr->port = port;
     491      130050 :         addr->sockaddr = NULL;
     492      130050 :         addr->sockaddrlen = 0;
     493             : 
     494      130050 :         return addr;
     495             : }
     496             : 
     497             : /* Create a new socket_address.  Copy the struct sockaddr into the new
     498             :  * structure.  Used for hooks in the kerberos libraries, where they
     499             :  * supply only a struct sockaddr */
     500             : 
     501       47951 : _PUBLIC_ struct socket_address *socket_address_from_sockaddr(TALLOC_CTX *mem_ctx, 
     502             :                                                              struct sockaddr *sockaddr, 
     503             :                                                              size_t sockaddrlen)
     504             : {
     505       47951 :         struct socket_address *addr = talloc(mem_ctx, struct socket_address);
     506       47951 :         if (!addr) {
     507           0 :                 return NULL;
     508             :         }
     509       47951 :         switch (sockaddr->sa_family) {
     510       47951 :         case AF_INET:
     511       47951 :                 addr->family = "ipv4";
     512       47951 :                 break;
     513             : #ifdef HAVE_IPV6
     514           0 :         case AF_INET6:
     515           0 :                 addr->family = "ipv6";
     516           0 :                 break;
     517             : #endif
     518           0 :         case AF_UNIX:
     519           0 :                 addr->family = "unix";
     520           0 :                 break;
     521             :         }
     522       47951 :         addr->addr = NULL;
     523       47951 :         addr->port = 0;
     524       47951 :         addr->sockaddr = (struct sockaddr *)talloc_memdup(addr, sockaddr, sockaddrlen);
     525       47951 :         if (!addr->sockaddr) {
     526           0 :                 talloc_free(addr);
     527           0 :                 return NULL;
     528             :         }
     529       47951 :         addr->sockaddrlen = sockaddrlen;
     530       47951 :         return addr;
     531             : }
     532             : 
     533             : 
     534             : /*
     535             :    Create a new socket_address from sockaddr_storage
     536             :  */
     537        1279 : _PUBLIC_ struct socket_address *socket_address_from_sockaddr_storage(TALLOC_CTX *mem_ctx,
     538             :                                                                      const struct sockaddr_storage *sockaddr,
     539             :         uint16_t port)
     540             : {
     541        1279 :         struct socket_address *addr = talloc_zero(mem_ctx, struct socket_address);
     542          40 :         char addr_str[INET6_ADDRSTRLEN+1];
     543          40 :         const char *str;
     544             : 
     545        1279 :         if (!addr) {
     546           0 :                 return NULL;
     547             :         }
     548        1279 :         addr->port = port;
     549        1279 :         switch (sockaddr->ss_family) {
     550         649 :         case AF_INET:
     551         649 :                 addr->family = "ipv4";
     552         649 :                 break;
     553             : #ifdef HAVE_IPV6
     554         630 :         case AF_INET6:
     555         630 :                 addr->family = "ipv6";
     556         630 :                 break;
     557             : #endif
     558           0 :         default:
     559           0 :                 talloc_free(addr);
     560           0 :                 return NULL;
     561             :         }
     562             : 
     563        1279 :         str = print_sockaddr(addr_str, sizeof(addr_str), sockaddr);
     564        1279 :         if (str == NULL) {
     565           0 :                 talloc_free(addr);
     566           0 :                 return NULL;
     567             :         }
     568        1279 :         addr->addr = talloc_strdup(addr, str);
     569        1279 :         if (addr->addr == NULL) {
     570           0 :                 talloc_free(addr);
     571           0 :                 return NULL;
     572             :         }
     573             : 
     574        1239 :         return addr;
     575             : }
     576             : 
     577             : /* Copy a socket_address structure */
     578       68326 : struct socket_address *socket_address_copy(TALLOC_CTX *mem_ctx,
     579             :                                            const struct socket_address *oaddr)
     580             : {
     581       68326 :         struct socket_address *addr = talloc_zero(mem_ctx, struct socket_address);
     582       68326 :         if (!addr) {
     583           0 :                 return NULL;
     584             :         }
     585       68326 :         addr->family = oaddr->family;
     586       68326 :         if (oaddr->addr) {
     587       68326 :                 addr->addr   = talloc_strdup(addr, oaddr->addr);
     588       68326 :                 if (!addr->addr) {
     589           0 :                         goto nomem;
     590             :                 }
     591             :         }
     592       68326 :         addr->port   = oaddr->port;
     593       68326 :         if (oaddr->sockaddr) {
     594        1678 :                 addr->sockaddr = (struct sockaddr *)talloc_memdup(addr,
     595             :                                                                   oaddr->sockaddr,
     596             :                                                                   oaddr->sockaddrlen);
     597        1678 :                 if (!addr->sockaddr) {
     598           0 :                         goto nomem;
     599             :                 }
     600        1678 :                 addr->sockaddrlen = oaddr->sockaddrlen;
     601             :         }
     602             : 
     603       67022 :         return addr;
     604             : 
     605           0 : nomem:
     606           0 :         talloc_free(addr);
     607           0 :         return NULL;
     608             : }
     609             : 
     610      115170 : _PUBLIC_ const struct socket_ops *socket_getops_byname(const char *family, enum socket_type type)
     611             : {
     612        3087 :         extern const struct socket_ops *socket_ipv4_ops(enum socket_type);
     613        3087 :         extern const struct socket_ops *socket_ipv6_ops(enum socket_type);
     614        3087 :         extern const struct socket_ops *socket_unixdom_ops(enum socket_type);
     615             : 
     616      115170 :         if (strcmp("ip", family) == 0 || 
     617       52089 :             strcmp("ipv4", family) == 0) {
     618      111733 :                 return socket_ipv4_ops(type);
     619             :         }
     620             : 
     621             : #ifdef HAVE_IPV6
     622        3437 :         if (strcmp("ipv6", family) == 0) {
     623         752 :                 return socket_ipv6_ops(type);
     624             :         }
     625             : #endif
     626             : 
     627        2685 :         if (strcmp("unix", family) == 0) {
     628        2685 :                 return socket_unixdom_ops(type);
     629             :         }
     630             : 
     631           0 :         return NULL;
     632             : }
     633             : 
     634             : /*
     635             :   set some flags on a socket 
     636             :  */
     637      137907 : void socket_set_flags(struct socket_context *sock, unsigned flags)
     638             : {
     639      137907 :         sock->flags |= flags;
     640      137907 : }

Generated by: LCOV version 1.14