LCOV - code coverage report
Current view: top level - source3/lib - util_sock.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 224 480 46.7 %
Date: 2024-06-13 04:01:37 Functions: 16 27 59.3 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Samba utility functions
       4             :    Copyright (C) Andrew Tridgell 1992-1998
       5             :    Copyright (C) Tim Potter      2000-2001
       6             :    Copyright (C) Jeremy Allison  1992-2007
       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 "system/filesys.h"
      24             : #include "../lib/util/memcache.h"
      25             : #include "../lib/async_req/async_sock.h"
      26             : #include "../lib/util/select.h"
      27             : #include "lib/socket/interfaces.h"
      28             : #include "../lib/util/tevent_unix.h"
      29             : #include "../lib/util/tevent_ntstatus.h"
      30             : #include "../lib/tsocket/tsocket.h"
      31             : #include "lib/util/sys_rw.h"
      32             : #include "lib/util/sys_rw_data.h"
      33             : 
      34             : /****************************************************************************
      35             :  Determine if a file descriptor is in fact a socket.
      36             : ****************************************************************************/
      37             : 
      38          38 : bool is_a_socket(int fd)
      39             : {
      40             :         int v;
      41             :         socklen_t l;
      42          38 :         l = sizeof(int);
      43          38 :         return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
      44             : }
      45             : 
      46             : /****************************************************************************
      47             :  Read data from a file descriptor with a timout in msec.
      48             :  mincount = if timeout, minimum to read before returning
      49             :  maxcount = number to be read.
      50             :  time_out = timeout in milliseconds
      51             :  NB. This can be called with a non-socket fd, don't change
      52             :  sys_read() to sys_recv() or other socket call.
      53             : ****************************************************************************/
      54             : 
      55       11527 : NTSTATUS read_fd_with_timeout(int fd, char *buf,
      56             :                                   size_t mincnt, size_t maxcnt,
      57             :                                   unsigned int time_out,
      58             :                                   size_t *size_ret)
      59             : {
      60             :         int pollrtn;
      61             :         ssize_t readret;
      62       11527 :         size_t nread = 0;
      63             : 
      64             :         /* just checking .... */
      65       11527 :         if (maxcnt <= 0)
      66           0 :                 return NT_STATUS_OK;
      67             : 
      68             :         /* Blocking read */
      69       11527 :         if (time_out == 0) {
      70       11527 :                 if (mincnt == 0) {
      71           0 :                         mincnt = maxcnt;
      72             :                 }
      73             : 
      74       30890 :                 while (nread < mincnt) {
      75       11569 :                         readret = sys_read(fd, buf + nread, maxcnt - nread);
      76             : 
      77       11569 :                         if (readret == 0) {
      78          43 :                                 DEBUG(5,("read_fd_with_timeout: "
      79             :                                         "blocking read. EOF from client.\n"));
      80          43 :                                 return NT_STATUS_END_OF_FILE;
      81             :                         }
      82             : 
      83       11526 :                         if (readret == -1) {
      84           0 :                                 return map_nt_error_from_unix(errno);
      85             :                         }
      86       11526 :                         nread += readret;
      87             :                 }
      88       11484 :                 goto done;
      89             :         }
      90             : 
      91             :         /* Most difficult - timeout read */
      92             :         /* If this is ever called on a disk file and
      93             :            mincnt is greater then the filesize then
      94             :            system performance will suffer severely as
      95             :            select always returns true on disk files */
      96             : 
      97           0 :         for (nread=0; nread < mincnt; ) {
      98             :                 int revents;
      99             : 
     100           0 :                 pollrtn = poll_intr_one_fd(fd, POLLIN|POLLHUP, time_out,
     101             :                                            &revents);
     102             : 
     103             :                 /* Check if error */
     104           0 :                 if (pollrtn == -1) {
     105           0 :                         return map_nt_error_from_unix(errno);
     106             :                 }
     107             : 
     108             :                 /* Did we timeout ? */
     109           0 :                 if ((pollrtn == 0) ||
     110           0 :                     ((revents & (POLLIN|POLLHUP|POLLERR)) == 0)) {
     111           0 :                         DEBUG(10,("read_fd_with_timeout: timeout read. "
     112             :                                 "select timed out.\n"));
     113           0 :                         return NT_STATUS_IO_TIMEOUT;
     114             :                 }
     115             : 
     116           0 :                 readret = sys_read(fd, buf+nread, maxcnt-nread);
     117             : 
     118           0 :                 if (readret == 0) {
     119             :                         /* we got EOF on the file descriptor */
     120           0 :                         DEBUG(5,("read_fd_with_timeout: timeout read. "
     121             :                                 "EOF from client.\n"));
     122           0 :                         return NT_STATUS_END_OF_FILE;
     123             :                 }
     124             : 
     125           0 :                 if (readret == -1) {
     126           0 :                         return map_nt_error_from_unix(errno);
     127             :                 }
     128             : 
     129           0 :                 nread += readret;
     130             :         }
     131             : 
     132           0 :  done:
     133             :         /* Return the number we got */
     134       11484 :         if (size_ret) {
     135           0 :                 *size_ret = nread;
     136             :         }
     137       11484 :         return NT_STATUS_OK;
     138             : }
     139             : 
     140             : /****************************************************************************
     141             :  Read data from an fd, reading exactly N bytes.
     142             :  NB. This can be called with a non-socket fd, don't add dependencies
     143             :  on socket calls.
     144             : ****************************************************************************/
     145             : 
     146           0 : NTSTATUS read_data_ntstatus(int fd, char *buffer, size_t N)
     147             : {
     148           0 :         return read_fd_with_timeout(fd, buffer, N, N, 0, NULL);
     149             : }
     150             : 
     151             : /****************************************************************************
     152             :  Read 4 bytes of a smb packet and return the smb length of the packet.
     153             :  Store the result in the buffer.
     154             :  This version of the function will return a length of zero on receiving
     155             :  a keepalive packet.
     156             :  Timeout is in milliseconds.
     157             : ****************************************************************************/
     158             : 
     159        5785 : NTSTATUS read_smb_length_return_keepalive(int fd, char *inbuf,
     160             :                                           unsigned int timeout,
     161             :                                           size_t *len)
     162             : {
     163             :         int msg_type;
     164             :         NTSTATUS status;
     165             : 
     166        5785 :         status = read_fd_with_timeout(fd, inbuf, 4, 4, timeout, NULL);
     167             : 
     168        5785 :         if (!NT_STATUS_IS_OK(status)) {
     169          43 :                 return status;
     170             :         }
     171             : 
     172        5742 :         *len = smb_len(inbuf);
     173        5742 :         msg_type = CVAL(inbuf,0);
     174             : 
     175        5742 :         if (msg_type == NBSSkeepalive) {
     176           0 :                 DEBUG(5,("Got keepalive packet\n"));
     177             :         }
     178             : 
     179        5742 :         DEBUG(10,("got smb length of %lu\n",(unsigned long)(*len)));
     180             : 
     181        5742 :         return NT_STATUS_OK;
     182             : }
     183             : 
     184             : /****************************************************************************
     185             :  Read an smb from a fd.
     186             :  The timeout is in milliseconds.
     187             :  This function will return on receipt of a session keepalive packet.
     188             :  maxlen is the max number of bytes to return, not including the 4 byte
     189             :  length. If zero it means buflen limit.
     190             :  Doesn't check the MAC on signed packets.
     191             : ****************************************************************************/
     192             : 
     193           0 : NTSTATUS receive_smb_raw(int fd, char *buffer, size_t buflen, unsigned int timeout,
     194             :                          size_t maxlen, size_t *p_len)
     195             : {
     196             :         size_t len;
     197             :         NTSTATUS status;
     198             : 
     199           0 :         status = read_smb_length_return_keepalive(fd,buffer,timeout,&len);
     200             : 
     201           0 :         if (!NT_STATUS_IS_OK(status)) {
     202           0 :                 DEBUG(0, ("read_fd_with_timeout failed, read "
     203             :                           "error = %s.\n", nt_errstr(status)));
     204           0 :                 return status;
     205             :         }
     206             : 
     207           0 :         if (len > buflen) {
     208           0 :                 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
     209             :                                         (unsigned long)len));
     210           0 :                 return NT_STATUS_INVALID_PARAMETER;
     211             :         }
     212             : 
     213           0 :         if(len > 0) {
     214           0 :                 if (maxlen) {
     215           0 :                         len = MIN(len,maxlen);
     216             :                 }
     217             : 
     218           0 :                 status = read_fd_with_timeout(
     219             :                         fd, buffer+4, len, len, timeout, &len);
     220             : 
     221           0 :                 if (!NT_STATUS_IS_OK(status)) {
     222           0 :                         DEBUG(0, ("read_fd_with_timeout failed, read error = "
     223             :                                   "%s.\n", nt_errstr(status)));
     224           0 :                         return status;
     225             :                 }
     226             : 
     227             :                 /* not all of samba3 properly checks for packet-termination
     228             :                  * of strings. This ensures that we don't run off into
     229             :                  * empty space. */
     230           0 :                 SSVAL(buffer+4,len, 0);
     231             :         }
     232             : 
     233           0 :         *p_len = len;
     234           0 :         return NT_STATUS_OK;
     235             : }
     236             : 
     237             : /*
     238             :  * Open a socket of the specified type, port, and address for incoming data.
     239             :  *
     240             :  * Return sock or -errno
     241             :  */
     242             : 
     243         551 : int open_socket_in(
     244             :         int type,
     245             :         const struct sockaddr_storage *paddr,
     246             :         uint16_t port,
     247             :         bool rebind)
     248             : {
     249         551 :         struct samba_sockaddr addr = {
     250             :                 .sa_socklen = sizeof(struct sockaddr_storage),
     251             :                 .u.ss = *paddr,
     252             :         };
     253         551 :         int ret, sock = -1;
     254         551 :         int val = rebind ? 1 : 0;
     255             :         bool ok;
     256             : 
     257         551 :         switch (addr.u.sa.sa_family) {
     258         118 :         case AF_INET6:
     259         118 :                 addr.sa_socklen = sizeof(struct sockaddr_in6);
     260         118 :                 break;
     261         433 :         case AF_INET:
     262         433 :                 addr.sa_socklen = sizeof(struct sockaddr_in);
     263         433 :                 break;
     264             :         }
     265             : 
     266         551 :         ok = samba_sockaddr_set_port(&addr, port);
     267         551 :         if (!ok) {
     268           0 :                 ret = -EINVAL;
     269           0 :                 DBG_DEBUG("samba_sockaddr_set_port failed\n");
     270           0 :                 goto fail;
     271             :         }
     272             : 
     273         551 :         sock = socket(addr.u.ss.ss_family, type, 0 );
     274         551 :         if (sock == -1) {
     275           0 :                 ret = -errno;
     276           0 :                 DBG_DEBUG("socket() failed: %s\n", strerror(errno));
     277           0 :                 goto fail;
     278             :         }
     279             : 
     280         551 :         ret = setsockopt(
     281             :                 sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
     282         551 :         if (ret == -1) {
     283           0 :                 ret = -errno;
     284           0 :                 DBG_DEBUG("setsockopt(SO_REUSEADDR) failed: %s\n",
     285             :                           strerror(errno));
     286           0 :                 goto fail;
     287             :         }
     288             : 
     289             : #ifdef SO_REUSEPORT
     290         551 :         ret = setsockopt(
     291             :                 sock, SOL_SOCKET, SO_REUSEPORT, (char *)&val, sizeof(val));
     292         551 :         if (ret == -1) {
     293           0 :                 ret = -errno;
     294           0 :                 DBG_DEBUG("setsockopt(SO_REUSEPORT) failed: %s\n",
     295             :                           strerror(errno));
     296           0 :                 goto fail;
     297             :         }
     298             : #endif /* SO_REUSEPORT */
     299             : 
     300             : #ifdef HAVE_IPV6
     301             :         /*
     302             :          * As IPV6_V6ONLY is the default on some systems,
     303             :          * we better try to be consistent and always use it.
     304             :          *
     305             :          * This also avoids using IPv4 via AF_INET6 sockets
     306             :          * and makes sure %I never resolves to a '::ffff:192.168.0.1'
     307             :          * string.
     308             :          */
     309         551 :         if (addr.u.ss.ss_family == AF_INET6) {
     310             : 
     311         118 :                 val = 1;
     312             : 
     313         118 :                 ret = setsockopt(
     314             :                         sock,
     315             :                         IPPROTO_IPV6,
     316             :                         IPV6_V6ONLY,
     317             :                         (const void *)&val,
     318             :                         sizeof(val));
     319         118 :                 if (ret == -1) {
     320           0 :                         ret = -errno;
     321           0 :                         DBG_DEBUG("setsockopt(IPV6_V6ONLY) failed: %s\n",
     322             :                                   strerror(errno));
     323           0 :                         goto fail;
     324             :                 }
     325             :         }
     326             : #endif
     327             : 
     328             :         /* now we've got a socket - we need to bind it */
     329         551 :         ret = bind(sock, &addr.u.sa, addr.sa_socklen);
     330         551 :         if (ret == -1) {
     331             :                 char addrstr[INET6_ADDRSTRLEN];
     332             : 
     333           0 :                 ret = -errno;
     334             : 
     335           0 :                 print_sockaddr(addrstr, sizeof(addrstr), &addr.u.ss);
     336           0 :                 DBG_DEBUG("bind for %s port %"PRIu16" failed: %s\n",
     337             :                           addrstr,
     338             :                           port,
     339             :                           strerror(-ret));
     340           0 :                 goto fail;
     341             :         }
     342             : 
     343         551 :         DBG_DEBUG("bind succeeded on port %"PRIu16"\n", port);
     344             : 
     345         551 :         return sock;
     346             : 
     347           0 : fail:
     348           0 :         if (sock != -1) {
     349           0 :                 close(sock);
     350           0 :                 sock = -1;
     351             :         }
     352           0 :         return ret;
     353             :  }
     354             : 
     355             : struct open_socket_out_state {
     356             :         int fd;
     357             :         struct tevent_context *ev;
     358             :         struct sockaddr_storage ss;
     359             :         socklen_t salen;
     360             :         uint16_t port;
     361             :         struct tevent_req *connect_subreq;
     362             : };
     363             : 
     364             : static void open_socket_out_connected(struct tevent_req *subreq);
     365             : 
     366        5190 : static void open_socket_out_cleanup(struct tevent_req *req,
     367             :                                     enum tevent_req_state req_state)
     368             : {
     369        3442 :         struct open_socket_out_state *state =
     370        5190 :                 tevent_req_data(req, struct open_socket_out_state);
     371             : 
     372             :         /*
     373             :          * Make sure that the async_connect_send subreq has a chance to reset
     374             :          * fcntl before the socket goes away.
     375             :          */
     376        5190 :         TALLOC_FREE(state->connect_subreq);
     377             : 
     378        5190 :         if (req_state == TEVENT_REQ_DONE) {
     379             :                 /*
     380             :                  * we keep the socket open for the caller to use
     381             :                  */
     382        2595 :                 return;
     383             :         }
     384             : 
     385        2595 :         if (state->fd != -1) {
     386           0 :                 close(state->fd);
     387           0 :                 state->fd = -1;
     388             :         }
     389             : }
     390             : 
     391             : /****************************************************************************
     392             :  Create an outgoing socket. timeout is in milliseconds.
     393             : **************************************************************************/
     394             : 
     395        2595 : struct tevent_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
     396             :                                         struct tevent_context *ev,
     397             :                                         const struct sockaddr_storage *pss,
     398             :                                         uint16_t port,
     399             :                                         int timeout)
     400             : {
     401             :         char addr[INET6_ADDRSTRLEN];
     402             :         struct tevent_req *req;
     403             :         struct open_socket_out_state *state;
     404             :         NTSTATUS status;
     405             : 
     406        2595 :         req = tevent_req_create(mem_ctx, &state,
     407             :                                 struct open_socket_out_state);
     408        2595 :         if (req == NULL) {
     409           0 :                 return NULL;
     410             :         }
     411        2595 :         state->ev = ev;
     412        2595 :         state->ss = *pss;
     413        2595 :         state->port = port;
     414        2595 :         state->salen = -1;
     415             : 
     416        2595 :         state->fd = socket(state->ss.ss_family, SOCK_STREAM, 0);
     417        2595 :         if (state->fd == -1) {
     418           0 :                 status = map_nt_error_from_unix(errno);
     419           0 :                 tevent_req_nterror(req, status);
     420           0 :                 return tevent_req_post(req, ev);
     421             :         }
     422             : 
     423        2595 :         tevent_req_set_cleanup_fn(req, open_socket_out_cleanup);
     424             : 
     425        4316 :         if ((timeout != 0) &&
     426        2595 :             !tevent_req_set_endtime(
     427             :                     req, ev, timeval_current_ofs_msec(timeout))) {
     428           0 :                 tevent_req_oom(req);
     429           0 :                 return tevent_req_post(req, ev);
     430             :         }
     431             : 
     432             : #if defined(HAVE_IPV6)
     433        2595 :         if (pss->ss_family == AF_INET6) {
     434             :                 struct sockaddr_in6 *psa6;
     435          36 :                 psa6 = (struct sockaddr_in6 *)&state->ss;
     436          36 :                 psa6->sin6_port = htons(port);
     437          36 :                 if (psa6->sin6_scope_id == 0
     438          36 :                     && IN6_IS_ADDR_LINKLOCAL(&psa6->sin6_addr)) {
     439           0 :                         setup_linklocal_scope_id(
     440           0 :                                 (struct sockaddr *)&(state->ss));
     441             :                 }
     442          36 :                 state->salen = sizeof(struct sockaddr_in6);
     443             :         }
     444             : #endif
     445        2595 :         if (pss->ss_family == AF_INET) {
     446             :                 struct sockaddr_in *psa;
     447        2559 :                 psa = (struct sockaddr_in *)&state->ss;
     448        2559 :                 psa->sin_port = htons(port);
     449        2559 :                 state->salen = sizeof(struct sockaddr_in);
     450             :         }
     451             : 
     452        2595 :         if (pss->ss_family == AF_UNIX) {
     453           0 :                 state->salen = sizeof(struct sockaddr_un);
     454             :         }
     455             : 
     456        2595 :         print_sockaddr(addr, sizeof(addr), &state->ss);
     457        2595 :         DEBUG(3,("Connecting to %s at port %u\n", addr,       (unsigned int)port));
     458             : 
     459        6911 :         state->connect_subreq = async_connect_send(
     460        4316 :                 state, state->ev, state->fd, (struct sockaddr *)&state->ss,
     461        2595 :                 state->salen, NULL, NULL, NULL);
     462        2595 :         if (tevent_req_nomem(state->connect_subreq, NULL)) {
     463           0 :                 return tevent_req_post(req, ev);
     464             :         }
     465        2595 :         tevent_req_set_callback(state->connect_subreq,
     466             :                                 open_socket_out_connected, req);
     467        2595 :         return req;
     468             : }
     469             : 
     470        2595 : static void open_socket_out_connected(struct tevent_req *subreq)
     471             : {
     472        1721 :         struct tevent_req *req =
     473        2595 :                 tevent_req_callback_data(subreq, struct tevent_req);
     474        1721 :         struct open_socket_out_state *state =
     475        2595 :                 tevent_req_data(req, struct open_socket_out_state);
     476             :         int ret;
     477             :         int sys_errno;
     478             : 
     479        2595 :         ret = async_connect_recv(subreq, &sys_errno);
     480        2595 :         TALLOC_FREE(subreq);
     481        2595 :         state->connect_subreq = NULL;
     482        2595 :         if (ret == 0) {
     483        2595 :                 tevent_req_done(req);
     484        2595 :                 return;
     485             :         }
     486             : 
     487           0 :         tevent_req_nterror(req, map_nt_error_from_unix(sys_errno));
     488             : }
     489             : 
     490        2595 : NTSTATUS open_socket_out_recv(struct tevent_req *req, int *pfd)
     491             : {
     492        1721 :         struct open_socket_out_state *state =
     493        2595 :                 tevent_req_data(req, struct open_socket_out_state);
     494             :         NTSTATUS status;
     495             : 
     496        2595 :         if (tevent_req_is_nterror(req, &status)) {
     497           0 :                 tevent_req_received(req);
     498           0 :                 return status;
     499             :         }
     500        2595 :         *pfd = state->fd;
     501        2595 :         state->fd = -1;
     502        2595 :         tevent_req_received(req);
     503        2595 :         return NT_STATUS_OK;
     504             : }
     505             : 
     506             : /**
     507             : * @brief open a socket
     508             : *
     509             : * @param pss a struct sockaddr_storage defining the address to connect to
     510             : * @param port to connect to
     511             : * @param timeout in MILLISECONDS
     512             : * @param pfd file descriptor returned
     513             : *
     514             : * @return NTSTATUS code
     515             : */
     516          97 : NTSTATUS open_socket_out(const struct sockaddr_storage *pss, uint16_t port,
     517             :                          int timeout, int *pfd)
     518             : {
     519          97 :         TALLOC_CTX *frame = talloc_stackframe();
     520             :         struct tevent_context *ev;
     521             :         struct tevent_req *req;
     522          97 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
     523             : 
     524          97 :         ev = samba_tevent_context_init(frame);
     525          97 :         if (ev == NULL) {
     526           0 :                 goto fail;
     527             :         }
     528             : 
     529          97 :         req = open_socket_out_send(frame, ev, pss, port, timeout);
     530          97 :         if (req == NULL) {
     531           0 :                 goto fail;
     532             :         }
     533          97 :         if (!tevent_req_poll(req, ev)) {
     534           0 :                 status = NT_STATUS_INTERNAL_ERROR;
     535           0 :                 goto fail;
     536             :         }
     537          97 :         status = open_socket_out_recv(req, pfd);
     538          97 :  fail:
     539          97 :         TALLOC_FREE(frame);
     540          97 :         return status;
     541             : }
     542             : 
     543             : struct open_socket_out_defer_state {
     544             :         struct tevent_context *ev;
     545             :         struct sockaddr_storage ss;
     546             :         uint16_t port;
     547             :         int timeout;
     548             :         int fd;
     549             : };
     550             : 
     551             : static void open_socket_out_defer_waited(struct tevent_req *subreq);
     552             : static void open_socket_out_defer_connected(struct tevent_req *subreq);
     553             : 
     554           0 : struct tevent_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx,
     555             :                                               struct tevent_context *ev,
     556             :                                               struct timeval wait_time,
     557             :                                               const struct sockaddr_storage *pss,
     558             :                                               uint16_t port,
     559             :                                               int timeout)
     560             : {
     561             :         struct tevent_req *req, *subreq;
     562             :         struct open_socket_out_defer_state *state;
     563             : 
     564           0 :         req = tevent_req_create(mem_ctx, &state,
     565             :                                 struct open_socket_out_defer_state);
     566           0 :         if (req == NULL) {
     567           0 :                 return NULL;
     568             :         }
     569           0 :         state->ev = ev;
     570           0 :         state->ss = *pss;
     571           0 :         state->port = port;
     572           0 :         state->timeout = timeout;
     573             : 
     574           0 :         subreq = tevent_wakeup_send(
     575             :                 state, ev,
     576           0 :                 timeval_current_ofs(wait_time.tv_sec, wait_time.tv_usec));
     577           0 :         if (subreq == NULL) {
     578           0 :                 goto fail;
     579             :         }
     580           0 :         tevent_req_set_callback(subreq, open_socket_out_defer_waited, req);
     581           0 :         return req;
     582           0 :  fail:
     583           0 :         TALLOC_FREE(req);
     584           0 :         return NULL;
     585             : }
     586             : 
     587           0 : static void open_socket_out_defer_waited(struct tevent_req *subreq)
     588             : {
     589           0 :         struct tevent_req *req = tevent_req_callback_data(
     590             :                 subreq, struct tevent_req);
     591           0 :         struct open_socket_out_defer_state *state = tevent_req_data(
     592             :                 req, struct open_socket_out_defer_state);
     593             :         bool ret;
     594             : 
     595           0 :         ret = tevent_wakeup_recv(subreq);
     596           0 :         TALLOC_FREE(subreq);
     597           0 :         if (!ret) {
     598           0 :                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
     599           0 :                 return;
     600             :         }
     601             : 
     602           0 :         subreq = open_socket_out_send(state, state->ev, &state->ss,
     603           0 :                                       state->port, state->timeout);
     604           0 :         if (tevent_req_nomem(subreq, req)) {
     605           0 :                 return;
     606             :         }
     607           0 :         tevent_req_set_callback(subreq, open_socket_out_defer_connected, req);
     608             : }
     609             : 
     610           0 : static void open_socket_out_defer_connected(struct tevent_req *subreq)
     611             : {
     612           0 :         struct tevent_req *req = tevent_req_callback_data(
     613             :                 subreq, struct tevent_req);
     614           0 :         struct open_socket_out_defer_state *state = tevent_req_data(
     615             :                 req, struct open_socket_out_defer_state);
     616             :         NTSTATUS status;
     617             : 
     618           0 :         status = open_socket_out_recv(subreq, &state->fd);
     619           0 :         TALLOC_FREE(subreq);
     620           0 :         if (!NT_STATUS_IS_OK(status)) {
     621           0 :                 tevent_req_nterror(req, status);
     622           0 :                 return;
     623             :         }
     624           0 :         tevent_req_done(req);
     625             : }
     626             : 
     627           0 : NTSTATUS open_socket_out_defer_recv(struct tevent_req *req, int *pfd)
     628             : {
     629           0 :         struct open_socket_out_defer_state *state = tevent_req_data(
     630             :                 req, struct open_socket_out_defer_state);
     631             :         NTSTATUS status;
     632             : 
     633           0 :         if (tevent_req_is_nterror(req, &status)) {
     634           0 :                 return status;
     635             :         }
     636           0 :         *pfd = state->fd;
     637           0 :         state->fd = -1;
     638           0 :         return NT_STATUS_OK;
     639             : }
     640             : 
     641             : /*******************************************************************
     642             :  Return the IP addr of the remote end of a socket as a string.
     643             :  Optionally return the struct sockaddr_storage.
     644             :  ******************************************************************/
     645             : 
     646           0 : static const char *get_peer_addr_internal(int fd,
     647             :                                 char *addr_buf,
     648             :                                 size_t addr_buf_len,
     649             :                                 struct sockaddr *pss,
     650             :                                 socklen_t *plength)
     651             : {
     652             :         struct sockaddr_storage ss;
     653           0 :         socklen_t length = sizeof(ss);
     654             : 
     655           0 :         strlcpy(addr_buf,"0.0.0.0",addr_buf_len);
     656             : 
     657           0 :         if (fd == -1) {
     658           0 :                 return addr_buf;
     659             :         }
     660             : 
     661           0 :         if (pss == NULL) {
     662           0 :                 pss = (struct sockaddr *)&ss;
     663           0 :                 plength = &length;
     664             :         }
     665             : 
     666           0 :         if (getpeername(fd, (struct sockaddr *)pss, plength) < 0) {
     667           0 :                 int level = (errno == ENOTCONN) ? 2 : 0;
     668           0 :                 DEBUG(level, ("getpeername failed. Error was %s\n",
     669             :                                strerror(errno)));
     670           0 :                 return addr_buf;
     671             :         }
     672             : 
     673           0 :         print_sockaddr_len(addr_buf,
     674             :                         addr_buf_len,
     675             :                         pss,
     676             :                         *plength);
     677           0 :         return addr_buf;
     678             : }
     679             : 
     680             : /*******************************************************************
     681             :  Matchname - determine if host name matches IP address. Used to
     682             :  confirm a hostname lookup to prevent spoof attacks.
     683             : ******************************************************************/
     684             : 
     685           0 : static bool matchname(const char *remotehost,
     686             :                 const struct sockaddr *pss,
     687             :                 socklen_t len)
     688             : {
     689           0 :         struct addrinfo *res = NULL;
     690           0 :         struct addrinfo *ailist = NULL;
     691             :         char addr_buf[INET6_ADDRSTRLEN];
     692           0 :         bool ret = interpret_string_addr_internal(&ailist,
     693             :                         remotehost,
     694             :                         AI_ADDRCONFIG|AI_CANONNAME);
     695             : 
     696           0 :         if (!ret || ailist == NULL) {
     697           0 :                 DEBUG(3,("matchname: getaddrinfo failed for "
     698             :                         "name %s [%s]\n",
     699             :                         remotehost,
     700             :                         gai_strerror(ret) ));
     701           0 :                 return false;
     702             :         }
     703             : 
     704             :         /*
     705             :          * Make sure that getaddrinfo() returns the "correct" host name.
     706             :          */
     707             : 
     708           0 :         if (ailist->ai_canonname == NULL ||
     709           0 :                 (!strequal(remotehost, ailist->ai_canonname) &&
     710           0 :                  !strequal(remotehost, "localhost"))) {
     711           0 :                 DEBUG(0,("matchname: host name/name mismatch: %s != %s\n",
     712             :                          remotehost,
     713             :                          ailist->ai_canonname ?
     714             :                                  ailist->ai_canonname : "(NULL)"));
     715           0 :                 freeaddrinfo(ailist);
     716           0 :                 return false;
     717             :         }
     718             : 
     719             :         /* Look up the host address in the address list we just got. */
     720           0 :         for (res = ailist; res; res = res->ai_next) {
     721           0 :                 if (!res->ai_addr) {
     722           0 :                         continue;
     723             :                 }
     724           0 :                 if (sockaddr_equal((const struct sockaddr *)res->ai_addr,
     725             :                                         (const struct sockaddr *)pss)) {
     726           0 :                         freeaddrinfo(ailist);
     727           0 :                         return true;
     728             :                 }
     729             :         }
     730             : 
     731             :         /*
     732             :          * The host name does not map to the original host address. Perhaps
     733             :          * someone has compromised a name server. More likely someone botched
     734             :          * it, but that could be dangerous, too.
     735             :          */
     736             : 
     737           0 :         DEBUG(0,("matchname: host name/address mismatch: %s != %s\n",
     738             :                 print_sockaddr_len(addr_buf,
     739             :                         sizeof(addr_buf),
     740             :                         pss,
     741             :                         len),
     742             :                  ailist->ai_canonname ? ailist->ai_canonname : "(NULL)"));
     743             : 
     744           0 :         if (ailist) {
     745           0 :                 freeaddrinfo(ailist);
     746             :         }
     747           0 :         return false;
     748             : }
     749             : 
     750             : /*******************************************************************
     751             :  Deal with the singleton cache.
     752             : ******************************************************************/
     753             : 
     754             : struct name_addr_pair {
     755             :         struct sockaddr_storage ss;
     756             :         const char *name;
     757             : };
     758             : 
     759             : /*******************************************************************
     760             :  Lookup a name/addr pair. Returns memory allocated from memcache.
     761             : ******************************************************************/
     762             : 
     763        5320 : static bool lookup_nc(struct name_addr_pair *nc)
     764             : {
     765             :         DATA_BLOB tmp;
     766             : 
     767        5320 :         ZERO_STRUCTP(nc);
     768             : 
     769        5320 :         if (!memcache_lookup(
     770             :                         NULL, SINGLETON_CACHE,
     771             :                         data_blob_string_const_null("get_peer_name"),
     772             :                         &tmp)) {
     773           0 :                 return false;
     774             :         }
     775             : 
     776        5320 :         memcpy(&nc->ss, tmp.data, sizeof(nc->ss));
     777        5320 :         nc->name = (const char *)tmp.data + sizeof(nc->ss);
     778        5320 :         return true;
     779             : }
     780             : 
     781             : /*******************************************************************
     782             :  Save a name/addr pair.
     783             : ******************************************************************/
     784             : 
     785        5320 : static void store_nc(const struct name_addr_pair *nc)
     786             : {
     787             :         DATA_BLOB tmp;
     788        5320 :         size_t namelen = strlen(nc->name);
     789             : 
     790        5320 :         tmp = data_blob(NULL, sizeof(nc->ss) + namelen + 1);
     791        5320 :         if (!tmp.data) {
     792           0 :                 return;
     793             :         }
     794        5320 :         memcpy(tmp.data, &nc->ss, sizeof(nc->ss));
     795        5320 :         memcpy(tmp.data+sizeof(nc->ss), nc->name, namelen+1);
     796             : 
     797        5320 :         memcache_add(NULL, SINGLETON_CACHE,
     798             :                         data_blob_string_const_null("get_peer_name"),
     799             :                         tmp);
     800        5320 :         data_blob_free(&tmp);
     801             : }
     802             : 
     803             : /*******************************************************************
     804             :  Return the IP addr of the remote end of a socket as a string.
     805             :  ******************************************************************/
     806             : 
     807           0 : const char *get_peer_addr(int fd, char *addr, size_t addr_len)
     808             : {
     809           0 :         return get_peer_addr_internal(fd, addr, addr_len, NULL, NULL);
     810             : }
     811             : 
     812        5320 : int get_remote_hostname(const struct tsocket_address *remote_address,
     813             :                         char **name,
     814             :                         TALLOC_CTX *mem_ctx)
     815             : {
     816             :         char name_buf[MAX_DNS_NAME_LENGTH];
     817             :         char tmp_name[MAX_DNS_NAME_LENGTH];
     818             :         struct name_addr_pair nc;
     819             :         struct sockaddr_storage ss;
     820             :         ssize_t len;
     821             :         int rc;
     822             : 
     823        5320 :         if (!lp_hostname_lookups()) {
     824        5320 :                 nc.name = tsocket_address_inet_addr_string(remote_address,
     825             :                                                            mem_ctx);
     826        5320 :                 if (nc.name == NULL) {
     827           0 :                         return -1;
     828             :                 }
     829             : 
     830        5320 :                 len = tsocket_address_bsd_sockaddr(remote_address,
     831             :                                                    (struct sockaddr *) &nc.ss,
     832             :                                                    sizeof(struct sockaddr_storage));
     833        5320 :                 if (len < 0) {
     834           0 :                         return -1;
     835             :                 }
     836             : 
     837        5320 :                 store_nc(&nc);
     838        5320 :                 lookup_nc(&nc);
     839             : 
     840        5320 :                 if (nc.name == NULL) {
     841           0 :                         *name = talloc_strdup(mem_ctx, "UNKNOWN");
     842             :                 } else {
     843        5320 :                         *name = talloc_strdup(mem_ctx, nc.name);
     844             :                 }
     845        5320 :                 return 0;
     846             :         }
     847             : 
     848           0 :         lookup_nc(&nc);
     849             : 
     850           0 :         ZERO_STRUCT(ss);
     851             : 
     852           0 :         len = tsocket_address_bsd_sockaddr(remote_address,
     853             :                                            (struct sockaddr *) &ss,
     854             :                                            sizeof(struct sockaddr_storage));
     855           0 :         if (len < 0) {
     856           0 :                 return -1;
     857             :         }
     858             : 
     859             :         /* it might be the same as the last one - save some DNS work */
     860           0 :         if (sockaddr_equal((struct sockaddr *)&ss, (struct sockaddr *)&nc.ss)) {
     861           0 :                 if (nc.name == NULL) {
     862           0 :                         *name = talloc_strdup(mem_ctx, "UNKNOWN");
     863             :                 } else {
     864           0 :                         *name = talloc_strdup(mem_ctx, nc.name);
     865             :                 }
     866           0 :                 return 0;
     867             :         }
     868             : 
     869             :         /* Look up the remote host name. */
     870           0 :         rc = sys_getnameinfo((struct sockaddr *) &ss,
     871             :                              len,
     872             :                              name_buf,
     873             :                              sizeof(name_buf),
     874             :                              NULL,
     875             :                              0,
     876             :                              0);
     877           0 :         if (rc < 0) {
     878             :                 char *p;
     879             : 
     880           0 :                 p = tsocket_address_inet_addr_string(remote_address, mem_ctx);
     881           0 :                 if (p == NULL) {
     882           0 :                         return -1;
     883             :                 }
     884             : 
     885           0 :                 DEBUG(1,("getnameinfo failed for %s with error %s\n",
     886             :                          p,
     887             :                          gai_strerror(rc)));
     888           0 :                 strlcpy(name_buf, p, sizeof(name_buf));
     889             : 
     890           0 :                 TALLOC_FREE(p);
     891             :         } else {
     892           0 :                 if (!matchname(name_buf, (struct sockaddr *)&ss, len)) {
     893           0 :                         DEBUG(0,("matchname failed on %s\n", name_buf));
     894           0 :                         strlcpy(name_buf, "UNKNOWN", sizeof(name_buf));
     895             :                 }
     896             :         }
     897             : 
     898           0 :         strlcpy(tmp_name, name_buf, sizeof(tmp_name));
     899           0 :         alpha_strcpy(name_buf, tmp_name, "_-.", sizeof(name_buf));
     900           0 :         if (strstr(name_buf,"..")) {
     901           0 :                 strlcpy(name_buf, "UNKNOWN", sizeof(name_buf));
     902             :         }
     903             : 
     904           0 :         nc.name = name_buf;
     905           0 :         nc.ss = ss;
     906             : 
     907           0 :         store_nc(&nc);
     908           0 :         lookup_nc(&nc);
     909             : 
     910           0 :         if (nc.name == NULL) {
     911           0 :                 *name = talloc_strdup(mem_ctx, "UNKNOWN");
     912             :         } else {
     913           0 :                 *name = talloc_strdup(mem_ctx, nc.name);
     914             :         }
     915             : 
     916           0 :         return 0;
     917             : }
     918             : 
     919             : /*******************************************************************
     920             :  Create protected unix domain socket.
     921             : 
     922             :  Some unixes cannot set permissions on a ux-dom-sock, so we
     923             :  have to make sure that the directory contains the protection
     924             :  permissions instead.
     925             :  ******************************************************************/
     926             : 
     927         767 : int create_pipe_sock(const char *socket_dir,
     928             :                      const char *socket_name,
     929             :                      mode_t dir_perms)
     930             : {
     931             : #ifdef HAVE_UNIXSOCKET
     932             :         struct sockaddr_un sunaddr;
     933             :         bool ok;
     934         767 :         int sock = -1;
     935             :         mode_t old_umask;
     936         767 :         char *path = NULL;
     937             :         size_t path_len;
     938             : 
     939         767 :         old_umask = umask(0);
     940             : 
     941         767 :         ok = directory_create_or_exist_strict(socket_dir,
     942             :                                               sec_initial_uid(),
     943             :                                               dir_perms);
     944         767 :         if (!ok) {
     945           0 :                 goto out_close;
     946             :         }
     947             : 
     948             :         /* Create the socket file */
     949         767 :         sock = socket(AF_UNIX, SOCK_STREAM, 0);
     950             : 
     951         767 :         if (sock == -1) {
     952           0 :                 DEBUG(0, ("create_pipe_sock: socket error %s\n",
     953             :                         strerror(errno) ));
     954           0 :                 goto out_close;
     955             :         }
     956             : 
     957         767 :         if (asprintf(&path, "%s/%s", socket_dir, socket_name) == -1) {
     958           0 :                 goto out_close;
     959             :         }
     960             : 
     961         767 :         unlink(path);
     962         767 :         memset(&sunaddr, 0, sizeof(sunaddr));
     963         767 :         sunaddr.sun_family = AF_UNIX;
     964             : 
     965         767 :         path_len = strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path));
     966         767 :         if (path_len > sizeof(sunaddr.sun_path)) {
     967           0 :                 DBG_ERR("Refusing to attempt to create pipe socket "
     968             :                         "%s.  Path is longer than permitted for a "
     969             :                         "unix domain socket.  It would truncate to "
     970             :                         "%s\n",
     971             :                         path,
     972             :                         sunaddr.sun_path);
     973           0 :                 goto out_close;
     974             :         }
     975             : 
     976         767 :         if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) {
     977           0 :                 DEBUG(0, ("bind failed on pipe socket %s: %s\n", path,
     978             :                         strerror(errno)));
     979           0 :                 goto out_close;
     980             :         }
     981             : 
     982         767 :         SAFE_FREE(path);
     983             : 
     984         767 :         umask(old_umask);
     985         767 :         return sock;
     986             : 
     987           0 : out_close:
     988           0 :         SAFE_FREE(path);
     989           0 :         if (sock != -1)
     990           0 :                 close(sock);
     991             : 
     992           0 :         umask(old_umask);
     993           0 :         return -1;
     994             : 
     995             : #else
     996             :         DEBUG(0, ("create_pipe_sock: No Unix sockets on this system\n"));
     997             :         return -1;
     998             : #endif /* HAVE_UNIXSOCKET */
     999             : }
    1000             : 
    1001             : /****************************************************************************
    1002             :  Get my own canonical name, including domain.
    1003             : ****************************************************************************/
    1004             : 
    1005        7740 : const char *get_mydnsfullname(void)
    1006             : {
    1007        7740 :         struct addrinfo *res = NULL;
    1008             :         char my_hostname[HOST_NAME_MAX];
    1009             :         bool ret;
    1010             :         DATA_BLOB tmp;
    1011             : 
    1012        7740 :         if (memcache_lookup(NULL, SINGLETON_CACHE,
    1013             :                         data_blob_string_const_null("get_mydnsfullname"),
    1014             :                         &tmp)) {
    1015         459 :                 SMB_ASSERT(tmp.length > 0);
    1016         459 :                 return (const char *)tmp.data;
    1017             :         }
    1018             : 
    1019             :         /* get my host name */
    1020        7281 :         if (gethostname(my_hostname, sizeof(my_hostname)) == -1) {
    1021           0 :                 DEBUG(0,("get_mydnsfullname: gethostname failed\n"));
    1022           0 :                 return NULL;
    1023             :         }
    1024             : 
    1025             :         /* Ensure null termination. */
    1026        7281 :         my_hostname[sizeof(my_hostname)-1] = '\0';
    1027             : 
    1028        7281 :         ret = interpret_string_addr_internal(&res,
    1029             :                                 my_hostname,
    1030             :                                 AI_ADDRCONFIG|AI_CANONNAME);
    1031             : 
    1032        7281 :         if (!ret || res == NULL) {
    1033        6870 :                 DEBUG(3,("get_mydnsfullname: getaddrinfo failed for "
    1034             :                         "name %s [%s]\n",
    1035             :                         my_hostname,
    1036             :                         gai_strerror(ret) ));
    1037        6870 :                 return NULL;
    1038             :         }
    1039             : 
    1040             :         /*
    1041             :          * Make sure that getaddrinfo() returns the "correct" host name.
    1042             :          */
    1043             : 
    1044         411 :         if (res->ai_canonname == NULL) {
    1045           0 :                 DEBUG(3,("get_mydnsfullname: failed to get "
    1046             :                         "canonical name for %s\n",
    1047             :                         my_hostname));
    1048           0 :                 freeaddrinfo(res);
    1049           0 :                 return NULL;
    1050             :         }
    1051             : 
    1052             :         /* This copies the data, so we must do a lookup
    1053             :          * afterwards to find the value to return.
    1054             :          */
    1055             : 
    1056         411 :         memcache_add(NULL, SINGLETON_CACHE,
    1057             :                         data_blob_string_const_null("get_mydnsfullname"),
    1058         411 :                         data_blob_string_const_null(res->ai_canonname));
    1059             : 
    1060         411 :         if (!memcache_lookup(NULL, SINGLETON_CACHE,
    1061             :                         data_blob_string_const_null("get_mydnsfullname"),
    1062             :                         &tmp)) {
    1063         280 :                 tmp = data_blob_talloc(talloc_tos(), res->ai_canonname,
    1064             :                                 strlen(res->ai_canonname) + 1);
    1065             :         }
    1066             : 
    1067         411 :         freeaddrinfo(res);
    1068             : 
    1069         411 :         return (const char *)tmp.data;
    1070             : }
    1071             : 
    1072             : /************************************************************
    1073             :  Is this my ip address ?
    1074             : ************************************************************/
    1075             : 
    1076         326 : static bool is_my_ipaddr(const char *ipaddr_str)
    1077             : {
    1078             :         struct sockaddr_storage ss;
    1079             :         struct iface_struct *nics;
    1080             :         int i, n;
    1081             : 
    1082         326 :         if (!interpret_string_addr(&ss, ipaddr_str, AI_NUMERICHOST)) {
    1083           0 :                 return false;
    1084             :         }
    1085             : 
    1086         326 :         if (is_zero_addr(&ss)) {
    1087           0 :                 return false;
    1088             :         }
    1089             : 
    1090         650 :         if (ismyaddr((struct sockaddr *)&ss) ||
    1091         324 :                         is_loopback_addr((struct sockaddr *)&ss)) {
    1092           2 :                 return true;
    1093             :         }
    1094             : 
    1095         324 :         n = get_interfaces(talloc_tos(), &nics);
    1096        1620 :         for (i=0; i<n; i++) {
    1097        1296 :                 if (sockaddr_equal((struct sockaddr *)&nics[i].ip, (struct sockaddr *)&ss)) {
    1098           0 :                         TALLOC_FREE(nics);
    1099           0 :                         return true;
    1100             :                 }
    1101             :         }
    1102         324 :         TALLOC_FREE(nics);
    1103         324 :         return false;
    1104             : }
    1105             : 
    1106             : /************************************************************
    1107             :  Is this my name ?
    1108             : ************************************************************/
    1109             : 
    1110         164 : bool is_myname_or_ipaddr(const char *s)
    1111             : {
    1112         164 :         TALLOC_CTX *ctx = talloc_tos();
    1113         164 :         char *name = NULL;
    1114             :         const char *dnsname;
    1115         164 :         char *servername = NULL;
    1116             : 
    1117         164 :         if (!s) {
    1118           0 :                 return false;
    1119             :         }
    1120             : 
    1121             :         /* Sanitize the string from '\\name' */
    1122         164 :         name = talloc_strdup(ctx, s);
    1123         164 :         if (!name) {
    1124           0 :                 return false;
    1125             :         }
    1126             : 
    1127         164 :         servername = strrchr_m(name, '\\' );
    1128         164 :         if (!servername) {
    1129         164 :                 servername = name;
    1130             :         } else {
    1131           0 :                 servername++;
    1132             :         }
    1133             : 
    1134             :         /* Optimize for the common case */
    1135         164 :         if (strequal(servername, lp_netbios_name())) {
    1136           0 :                 return true;
    1137             :         }
    1138             : 
    1139             :         /* Check for an alias */
    1140         164 :         if (is_myname(servername)) {
    1141           0 :                 return true;
    1142             :         }
    1143             : 
    1144             :         /* Check for loopback */
    1145         328 :         if (strequal(servername, "127.0.0.1") ||
    1146         164 :                         strequal(servername, "::1")) {
    1147           0 :                 return true;
    1148             :         }
    1149             : 
    1150         164 :         if (strequal(servername, "localhost")) {
    1151           0 :                 return true;
    1152             :         }
    1153             : 
    1154             :         /* Maybe it's my dns name */
    1155         164 :         dnsname = get_mydnsfullname();
    1156         164 :         if (dnsname && strequal(servername, dnsname)) {
    1157           0 :                 return true;
    1158             :         }
    1159             : 
    1160             :         /* Maybe its an IP address? */
    1161         164 :         if (is_ipaddress(servername)) {
    1162           2 :                 return is_my_ipaddr(servername);
    1163             :         }
    1164             : 
    1165             :         /* Handle possible CNAME records - convert to an IP addr. list. */
    1166             :         {
    1167             :                 /* Use DNS to resolve the name, check all addresses. */
    1168         162 :                 struct addrinfo *p = NULL;
    1169         162 :                 struct addrinfo *res = NULL;
    1170             : 
    1171         162 :                 if (!interpret_string_addr_internal(&res,
    1172             :                                 servername,
    1173             :                                 AI_ADDRCONFIG)) {
    1174           0 :                         return false;
    1175             :                 }
    1176             : 
    1177         486 :                 for (p = res; p; p = p->ai_next) {
    1178             :                         char addr[INET6_ADDRSTRLEN];
    1179             :                         struct sockaddr_storage ss;
    1180             : 
    1181         324 :                         ZERO_STRUCT(ss);
    1182         324 :                         memcpy(&ss, p->ai_addr, p->ai_addrlen);
    1183         324 :                         print_sockaddr(addr,
    1184             :                                         sizeof(addr),
    1185             :                                         &ss);
    1186         324 :                         if (is_my_ipaddr(addr)) {
    1187           0 :                                 freeaddrinfo(res);
    1188           0 :                                 return true;
    1189             :                         }
    1190             :                 }
    1191         162 :                 freeaddrinfo(res);
    1192             :         }
    1193             : 
    1194             :         /* No match */
    1195         162 :         return false;
    1196             : }
    1197             : 
    1198           0 : int poll_one_fd(int fd, int events, int timeout, int *revents)
    1199             : {
    1200             :         struct pollfd pfd;
    1201             :         int ret;
    1202             : 
    1203           0 :         pfd.fd = fd;
    1204           0 :         pfd.events = events;
    1205             : 
    1206           0 :         ret = poll(&pfd, 1, timeout);
    1207             : 
    1208             :         /*
    1209             :          * Assign whatever poll did, even in the ret<=0 case.
    1210             :          */
    1211           0 :         *revents = pfd.revents;
    1212             : 
    1213           0 :         return ret;
    1214             : }
    1215             : 
    1216           0 : int poll_intr_one_fd(int fd, int events, int timeout, int *revents)
    1217             : {
    1218             :         struct pollfd pfd;
    1219             :         int ret;
    1220             : 
    1221           0 :         pfd.fd = fd;
    1222           0 :         pfd.events = events;
    1223             : 
    1224           0 :         ret = sys_poll_intr(&pfd, 1, timeout);
    1225           0 :         if (ret <= 0) {
    1226           0 :                 *revents = 0;
    1227           0 :                 return ret;
    1228             :         }
    1229           0 :         *revents = pfd.revents;
    1230           0 :         return 1;
    1231             : }

Generated by: LCOV version 1.13