lib: Add iov_buf
[obnox/samba/samba-obnox.git] / source3 / lib / util_sock.c
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 "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
32 const char *client_addr(int fd, char *addr, size_t addrlen)
33 {
34         return get_peer_addr(fd,addr,addrlen);
35 }
36
37 #if 0
38 /* Not currently used. JRA. */
39 int client_socket_port(int fd)
40 {
41         return get_socket_port(fd);
42 }
43 #endif
44
45 /****************************************************************************
46  Determine if a file descriptor is in fact a socket.
47 ****************************************************************************/
48
49 bool is_a_socket(int fd)
50 {
51         int v;
52         socklen_t l;
53         l = sizeof(int);
54         return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
55 }
56
57 /****************************************************************************
58  Read from a socket.
59 ****************************************************************************/
60
61 ssize_t read_udp_v4_socket(int fd,
62                         char *buf,
63                         size_t len,
64                         struct sockaddr_storage *psa)
65 {
66         ssize_t ret;
67         socklen_t socklen = sizeof(*psa);
68         struct sockaddr_in *si = (struct sockaddr_in *)psa;
69
70         memset((char *)psa,'\0',socklen);
71
72         ret = (ssize_t)sys_recvfrom(fd,buf,len,0,
73                         (struct sockaddr *)psa,&socklen);
74         if (ret <= 0) {
75                 /* Don't print a low debug error for a non-blocking socket. */
76                 if (errno == EAGAIN) {
77                         DEBUG(10,("read_udp_v4_socket: returned EAGAIN\n"));
78                 } else {
79                         DEBUG(2,("read_udp_v4_socket: failed. errno=%s\n",
80                                 strerror(errno)));
81                 }
82                 return 0;
83         }
84
85         if (psa->ss_family != AF_INET) {
86                 DEBUG(2,("read_udp_v4_socket: invalid address family %d "
87                         "(not IPv4)\n", (int)psa->ss_family));
88                 return 0;
89         }
90
91         DEBUG(10,("read_udp_v4_socket: ip %s port %d read: %lu\n",
92                         inet_ntoa(si->sin_addr),
93                         si->sin_port,
94                         (unsigned long)ret));
95
96         return ret;
97 }
98
99 /****************************************************************************
100  Read data from a file descriptor with a timout in msec.
101  mincount = if timeout, minimum to read before returning
102  maxcount = number to be read.
103  time_out = timeout in milliseconds
104  NB. This can be called with a non-socket fd, don't change
105  sys_read() to sys_recv() or other socket call.
106 ****************************************************************************/
107
108 NTSTATUS read_fd_with_timeout(int fd, char *buf,
109                                   size_t mincnt, size_t maxcnt,
110                                   unsigned int time_out,
111                                   size_t *size_ret)
112 {
113         int pollrtn;
114         ssize_t readret;
115         size_t nread = 0;
116
117         /* just checking .... */
118         if (maxcnt <= 0)
119                 return NT_STATUS_OK;
120
121         /* Blocking read */
122         if (time_out == 0) {
123                 if (mincnt == 0) {
124                         mincnt = maxcnt;
125                 }
126
127                 while (nread < mincnt) {
128                         readret = sys_read(fd, buf + nread, maxcnt - nread);
129
130                         if (readret == 0) {
131                                 DEBUG(5,("read_fd_with_timeout: "
132                                         "blocking read. EOF from client.\n"));
133                                 return NT_STATUS_END_OF_FILE;
134                         }
135
136                         if (readret == -1) {
137                                 return map_nt_error_from_unix(errno);
138                         }
139                         nread += readret;
140                 }
141                 goto done;
142         }
143
144         /* Most difficult - timeout read */
145         /* If this is ever called on a disk file and
146            mincnt is greater then the filesize then
147            system performance will suffer severely as
148            select always returns true on disk files */
149
150         for (nread=0; nread < mincnt; ) {
151                 int revents;
152
153                 pollrtn = poll_intr_one_fd(fd, POLLIN|POLLHUP, time_out,
154                                            &revents);
155
156                 /* Check if error */
157                 if (pollrtn == -1) {
158                         return map_nt_error_from_unix(errno);
159                 }
160
161                 /* Did we timeout ? */
162                 if ((pollrtn == 0) ||
163                     ((revents & (POLLIN|POLLHUP|POLLERR)) == 0)) {
164                         DEBUG(10,("read_fd_with_timeout: timeout read. "
165                                 "select timed out.\n"));
166                         return NT_STATUS_IO_TIMEOUT;
167                 }
168
169                 readret = sys_read(fd, buf+nread, maxcnt-nread);
170
171                 if (readret == 0) {
172                         /* we got EOF on the file descriptor */
173                         DEBUG(5,("read_fd_with_timeout: timeout read. "
174                                 "EOF from client.\n"));
175                         return NT_STATUS_END_OF_FILE;
176                 }
177
178                 if (readret == -1) {
179                         return map_nt_error_from_unix(errno);
180                 }
181
182                 nread += readret;
183         }
184
185  done:
186         /* Return the number we got */
187         if (size_ret) {
188                 *size_ret = nread;
189         }
190         return NT_STATUS_OK;
191 }
192
193 /****************************************************************************
194  Read data from an fd, reading exactly N bytes.
195  NB. This can be called with a non-socket fd, don't add dependencies
196  on socket calls.
197 ****************************************************************************/
198
199 NTSTATUS read_data(int fd, char *buffer, size_t N)
200 {
201         return read_fd_with_timeout(fd, buffer, N, N, 0, NULL);
202 }
203
204 ssize_t iov_buflen(const struct iovec *iov, int iovcnt)
205 {
206         size_t buflen = 0;
207         int i;
208
209         for (i=0; i<iovcnt; i++) {
210                 size_t thislen = iov[i].iov_len;
211                 size_t tmp = buflen + thislen;
212
213                 if ((tmp < buflen) || (tmp < thislen)) {
214                         /* overflow */
215                         return -1;
216                 }
217                 buflen = tmp;
218         }
219         return buflen;
220 }
221
222 uint8_t *iov_buf(TALLOC_CTX *mem_ctx, const struct iovec *iov, int iovcnt)
223 {
224         int i;
225         ssize_t buflen;
226         uint8_t *buf, *p;
227
228         buflen = iov_buflen(iov, iovcnt);
229         if (buflen == -1) {
230                 return NULL;
231         }
232         buf = talloc_array(mem_ctx, uint8_t, buflen);
233         if (buf == NULL) {
234                 return NULL;
235         }
236
237         p = buf;
238         for (i=0; i<iovcnt; i++) {
239                 size_t len = iov[i].iov_len;
240
241                 memcpy(p, iov[i].iov_base, len);
242                 p += len;
243         }
244         return buf;
245 }
246
247 /****************************************************************************
248  Write all data from an iov array
249  NB. This can be called with a non-socket fd, don't add dependencies
250  on socket calls.
251 ****************************************************************************/
252
253 ssize_t write_data_iov(int fd, const struct iovec *orig_iov, int iovcnt)
254 {
255         ssize_t to_send;
256         ssize_t thistime;
257         size_t sent;
258         struct iovec *iov_copy, *iov;
259
260         to_send = iov_buflen(orig_iov, iovcnt);
261         if (to_send == -1) {
262                 errno = EINVAL;
263                 return -1;
264         }
265
266         thistime = sys_writev(fd, orig_iov, iovcnt);
267         if ((thistime <= 0) || (thistime == to_send)) {
268                 return thistime;
269         }
270         sent = thistime;
271
272         /*
273          * We could not send everything in one call. Make a copy of iov that
274          * we can mess with. We keep a copy of the array start in iov_copy for
275          * the TALLOC_FREE, because we're going to modify iov later on,
276          * discarding elements.
277          */
278
279         iov_copy = (struct iovec *)talloc_memdup(
280                 talloc_tos(), orig_iov, sizeof(struct iovec) * iovcnt);
281
282         if (iov_copy == NULL) {
283                 errno = ENOMEM;
284                 return -1;
285         }
286         iov = iov_copy;
287
288         while (sent < to_send) {
289                 /*
290                  * We have to discard "thistime" bytes from the beginning
291                  * iov array, "thistime" contains the number of bytes sent
292                  * via writev last.
293                  */
294                 while (thistime > 0) {
295                         if (thistime < iov[0].iov_len) {
296                                 char *new_base =
297                                         (char *)iov[0].iov_base + thistime;
298                                 iov[0].iov_base = (void *)new_base;
299                                 iov[0].iov_len -= thistime;
300                                 break;
301                         }
302                         thistime -= iov[0].iov_len;
303                         iov += 1;
304                         iovcnt -= 1;
305                 }
306
307                 thistime = sys_writev(fd, iov, iovcnt);
308                 if (thistime <= 0) {
309                         break;
310                 }
311                 sent += thistime;
312         }
313
314         TALLOC_FREE(iov_copy);
315         return sent;
316 }
317
318 /****************************************************************************
319  Write data to a fd.
320  NB. This can be called with a non-socket fd, don't add dependencies
321  on socket calls.
322 ****************************************************************************/
323
324 ssize_t write_data(int fd, const char *buffer, size_t N)
325 {
326         struct iovec iov;
327
328         iov.iov_base = discard_const_p(void, buffer);
329         iov.iov_len = N;
330         return write_data_iov(fd, &iov, 1);
331 }
332
333 /****************************************************************************
334  Send a keepalive packet (rfc1002).
335 ****************************************************************************/
336
337 bool send_keepalive(int client)
338 {
339         unsigned char buf[4];
340
341         buf[0] = NBSSkeepalive;
342         buf[1] = buf[2] = buf[3] = 0;
343
344         return(write_data(client,(char *)buf,4) == 4);
345 }
346
347 /****************************************************************************
348  Read 4 bytes of a smb packet and return the smb length of the packet.
349  Store the result in the buffer.
350  This version of the function will return a length of zero on receiving
351  a keepalive packet.
352  Timeout is in milliseconds.
353 ****************************************************************************/
354
355 NTSTATUS read_smb_length_return_keepalive(int fd, char *inbuf,
356                                           unsigned int timeout,
357                                           size_t *len)
358 {
359         int msg_type;
360         NTSTATUS status;
361
362         status = read_fd_with_timeout(fd, inbuf, 4, 4, timeout, NULL);
363
364         if (!NT_STATUS_IS_OK(status)) {
365                 return status;
366         }
367
368         *len = smb_len(inbuf);
369         msg_type = CVAL(inbuf,0);
370
371         if (msg_type == NBSSkeepalive) {
372                 DEBUG(5,("Got keepalive packet\n"));
373         }
374
375         DEBUG(10,("got smb length of %lu\n",(unsigned long)(*len)));
376
377         return NT_STATUS_OK;
378 }
379
380 /****************************************************************************
381  Read an smb from a fd.
382  The timeout is in milliseconds.
383  This function will return on receipt of a session keepalive packet.
384  maxlen is the max number of bytes to return, not including the 4 byte
385  length. If zero it means buflen limit.
386  Doesn't check the MAC on signed packets.
387 ****************************************************************************/
388
389 NTSTATUS receive_smb_raw(int fd, char *buffer, size_t buflen, unsigned int timeout,
390                          size_t maxlen, size_t *p_len)
391 {
392         size_t len;
393         NTSTATUS status;
394
395         status = read_smb_length_return_keepalive(fd,buffer,timeout,&len);
396
397         if (!NT_STATUS_IS_OK(status)) {
398                 DEBUG(0, ("read_fd_with_timeout failed, read "
399                           "error = %s.\n", nt_errstr(status)));
400                 return status;
401         }
402
403         if (len > buflen) {
404                 DEBUG(0,("Invalid packet length! (%lu bytes).\n",
405                                         (unsigned long)len));
406                 return NT_STATUS_INVALID_PARAMETER;
407         }
408
409         if(len > 0) {
410                 if (maxlen) {
411                         len = MIN(len,maxlen);
412                 }
413
414                 status = read_fd_with_timeout(
415                         fd, buffer+4, len, len, timeout, &len);
416
417                 if (!NT_STATUS_IS_OK(status)) {
418                         DEBUG(0, ("read_fd_with_timeout failed, read error = "
419                                   "%s.\n", nt_errstr(status)));
420                         return status;
421                 }
422
423                 /* not all of samba3 properly checks for packet-termination
424                  * of strings. This ensures that we don't run off into
425                  * empty space. */
426                 SSVAL(buffer+4,len, 0);
427         }
428
429         *p_len = len;
430         return NT_STATUS_OK;
431 }
432
433 /****************************************************************************
434  Open a socket of the specified type, port, and address for incoming data.
435 ****************************************************************************/
436
437 int open_socket_in(int type,
438                 uint16_t port,
439                 int dlevel,
440                 const struct sockaddr_storage *psock,
441                 bool rebind)
442 {
443         struct sockaddr_storage sock;
444         int res;
445         socklen_t slen = sizeof(struct sockaddr_in);
446
447         sock = *psock;
448
449 #if defined(HAVE_IPV6)
450         if (sock.ss_family == AF_INET6) {
451                 ((struct sockaddr_in6 *)&sock)->sin6_port = htons(port);
452                 slen = sizeof(struct sockaddr_in6);
453         }
454 #endif
455         if (sock.ss_family == AF_INET) {
456                 ((struct sockaddr_in *)&sock)->sin_port = htons(port);
457         }
458
459         res = socket(sock.ss_family, type, 0 );
460         if( res == -1 ) {
461                 if( DEBUGLVL(0) ) {
462                         dbgtext( "open_socket_in(): socket() call failed: " );
463                         dbgtext( "%s\n", strerror( errno ) );
464                 }
465                 return -1;
466         }
467
468         /* This block sets/clears the SO_REUSEADDR and possibly SO_REUSEPORT. */
469         {
470                 int val = rebind ? 1 : 0;
471                 if( setsockopt(res,SOL_SOCKET,SO_REUSEADDR,
472                                         (char *)&val,sizeof(val)) == -1 ) {
473                         if( DEBUGLVL( dlevel ) ) {
474                                 dbgtext( "open_socket_in(): setsockopt: " );
475                                 dbgtext( "SO_REUSEADDR = %s ",
476                                                 val?"true":"false" );
477                                 dbgtext( "on port %d failed ", port );
478                                 dbgtext( "with error = %s\n", strerror(errno) );
479                         }
480                 }
481 #ifdef SO_REUSEPORT
482                 if( setsockopt(res,SOL_SOCKET,SO_REUSEPORT,
483                                         (char *)&val,sizeof(val)) == -1 ) {
484                         if( DEBUGLVL( dlevel ) ) {
485                                 dbgtext( "open_socket_in(): setsockopt: ");
486                                 dbgtext( "SO_REUSEPORT = %s ",
487                                                 val?"true":"false");
488                                 dbgtext( "on port %d failed ", port);
489                                 dbgtext( "with error = %s\n", strerror(errno));
490                         }
491                 }
492 #endif /* SO_REUSEPORT */
493         }
494
495 #ifdef HAVE_IPV6
496         /*
497          * As IPV6_V6ONLY is the default on some systems,
498          * we better try to be consistent and always use it.
499          *
500          * This also avoids using IPv4 via AF_INET6 sockets
501          * and makes sure %I never resolves to a '::ffff:192.168.0.1'
502          * string.
503          */
504         if (sock.ss_family == AF_INET6) {
505                 int val = 1;
506                 int ret;
507
508                 ret = setsockopt(res, IPPROTO_IPV6, IPV6_V6ONLY,
509                                  (const void *)&val, sizeof(val));
510                 if (ret == -1) {
511                         if(DEBUGLVL(0)) {
512                                 dbgtext("open_socket_in(): IPV6_ONLY failed: ");
513                                 dbgtext("%s\n", strerror(errno));
514                         }
515                         close(res);
516                         return -1;
517                 }
518         }
519 #endif
520
521         /* now we've got a socket - we need to bind it */
522         if (bind(res, (struct sockaddr *)&sock, slen) == -1 ) {
523                 if( DEBUGLVL(dlevel) && (port == NMB_PORT ||
524                                          port == NBT_SMB_PORT ||
525                                          port == TCP_SMB_PORT) ) {
526                         char addr[INET6_ADDRSTRLEN];
527                         print_sockaddr(addr, sizeof(addr),
528                                         &sock);
529                         dbgtext( "bind failed on port %d ", port);
530                         dbgtext( "socket_addr = %s.\n", addr);
531                         dbgtext( "Error = %s\n", strerror(errno));
532                 }
533                 close(res);
534                 return -1;
535         }
536
537         DEBUG( 10, ( "bind succeeded on port %d\n", port ) );
538         return( res );
539  }
540
541 struct open_socket_out_state {
542         int fd;
543         struct tevent_context *ev;
544         struct sockaddr_storage ss;
545         socklen_t salen;
546         uint16_t port;
547         int wait_usec;
548 };
549
550 static void open_socket_out_connected(struct tevent_req *subreq);
551
552 static int open_socket_out_state_destructor(struct open_socket_out_state *s)
553 {
554         if (s->fd != -1) {
555                 close(s->fd);
556         }
557         return 0;
558 }
559
560 /****************************************************************************
561  Create an outgoing socket. timeout is in milliseconds.
562 **************************************************************************/
563
564 struct tevent_req *open_socket_out_send(TALLOC_CTX *mem_ctx,
565                                         struct tevent_context *ev,
566                                         const struct sockaddr_storage *pss,
567                                         uint16_t port,
568                                         int timeout)
569 {
570         char addr[INET6_ADDRSTRLEN];
571         struct tevent_req *result, *subreq;
572         struct open_socket_out_state *state;
573         NTSTATUS status;
574
575         result = tevent_req_create(mem_ctx, &state,
576                                    struct open_socket_out_state);
577         if (result == NULL) {
578                 return NULL;
579         }
580         state->ev = ev;
581         state->ss = *pss;
582         state->port = port;
583         state->wait_usec = 10000;
584         state->salen = -1;
585
586         state->fd = socket(state->ss.ss_family, SOCK_STREAM, 0);
587         if (state->fd == -1) {
588                 status = map_nt_error_from_unix(errno);
589                 goto post_status;
590         }
591         talloc_set_destructor(state, open_socket_out_state_destructor);
592
593         if (!tevent_req_set_endtime(
594                     result, ev, timeval_current_ofs_msec(timeout))) {
595                 goto fail;
596         }
597
598 #if defined(HAVE_IPV6)
599         if (pss->ss_family == AF_INET6) {
600                 struct sockaddr_in6 *psa6;
601                 psa6 = (struct sockaddr_in6 *)&state->ss;
602                 psa6->sin6_port = htons(port);
603                 if (psa6->sin6_scope_id == 0
604                     && IN6_IS_ADDR_LINKLOCAL(&psa6->sin6_addr)) {
605                         setup_linklocal_scope_id(
606                                 (struct sockaddr *)&(state->ss));
607                 }
608                 state->salen = sizeof(struct sockaddr_in6);
609         }
610 #endif
611         if (pss->ss_family == AF_INET) {
612                 struct sockaddr_in *psa;
613                 psa = (struct sockaddr_in *)&state->ss;
614                 psa->sin_port = htons(port);
615                 state->salen = sizeof(struct sockaddr_in);
616         }
617
618         if (pss->ss_family == AF_UNIX) {
619                 state->salen = sizeof(struct sockaddr_un);
620         }
621
622         print_sockaddr(addr, sizeof(addr), &state->ss);
623         DEBUG(3,("Connecting to %s at port %u\n", addr, (unsigned int)port));
624
625         subreq = async_connect_send(state, state->ev, state->fd,
626                                     (struct sockaddr *)&state->ss,
627                                     state->salen, NULL, NULL, NULL);
628         if ((subreq == NULL)
629             || !tevent_req_set_endtime(
630                     subreq, state->ev,
631                     timeval_current_ofs(0, state->wait_usec))) {
632                 goto fail;
633         }
634         tevent_req_set_callback(subreq, open_socket_out_connected, result);
635         return result;
636
637  post_status:
638         tevent_req_nterror(result, status);
639         return tevent_req_post(result, ev);
640  fail:
641         TALLOC_FREE(result);
642         return NULL;
643 }
644
645 static void open_socket_out_connected(struct tevent_req *subreq)
646 {
647         struct tevent_req *req =
648                 tevent_req_callback_data(subreq, struct tevent_req);
649         struct open_socket_out_state *state =
650                 tevent_req_data(req, struct open_socket_out_state);
651         int ret;
652         int sys_errno;
653
654         ret = async_connect_recv(subreq, &sys_errno);
655         TALLOC_FREE(subreq);
656         if (ret == 0) {
657                 tevent_req_done(req);
658                 return;
659         }
660
661         if (
662 #ifdef ETIMEDOUT
663                 (sys_errno == ETIMEDOUT) ||
664 #endif
665                 (sys_errno == EINPROGRESS) ||
666                 (sys_errno == EALREADY) ||
667                 (sys_errno == EAGAIN)) {
668
669                 /*
670                  * retry
671                  */
672
673                 if (state->wait_usec < 250000) {
674                         state->wait_usec *= 1.5;
675                 }
676
677                 subreq = async_connect_send(state, state->ev, state->fd,
678                                             (struct sockaddr *)&state->ss,
679                                             state->salen, NULL, NULL, NULL);
680                 if (tevent_req_nomem(subreq, req)) {
681                         return;
682                 }
683                 if (!tevent_req_set_endtime(
684                             subreq, state->ev,
685                             timeval_current_ofs_usec(state->wait_usec))) {
686                         tevent_req_nterror(req, NT_STATUS_NO_MEMORY);
687                         return;
688                 }
689                 tevent_req_set_callback(subreq, open_socket_out_connected, req);
690                 return;
691         }
692
693 #ifdef EISCONN
694         if (sys_errno == EISCONN) {
695                 tevent_req_done(req);
696                 return;
697         }
698 #endif
699
700         /* real error */
701         tevent_req_nterror(req, map_nt_error_from_unix(sys_errno));
702 }
703
704 NTSTATUS open_socket_out_recv(struct tevent_req *req, int *pfd)
705 {
706         struct open_socket_out_state *state =
707                 tevent_req_data(req, struct open_socket_out_state);
708         NTSTATUS status;
709
710         if (tevent_req_is_nterror(req, &status)) {
711                 return status;
712         }
713         *pfd = state->fd;
714         state->fd = -1;
715         return NT_STATUS_OK;
716 }
717
718 /**
719 * @brief open a socket
720 *
721 * @param pss a struct sockaddr_storage defining the address to connect to
722 * @param port to connect to
723 * @param timeout in MILLISECONDS
724 * @param pfd file descriptor returned
725 *
726 * @return NTSTATUS code
727 */
728 NTSTATUS open_socket_out(const struct sockaddr_storage *pss, uint16_t port,
729                          int timeout, int *pfd)
730 {
731         TALLOC_CTX *frame = talloc_stackframe();
732         struct tevent_context *ev;
733         struct tevent_req *req;
734         NTSTATUS status = NT_STATUS_NO_MEMORY;
735
736         ev = samba_tevent_context_init(frame);
737         if (ev == NULL) {
738                 goto fail;
739         }
740
741         req = open_socket_out_send(frame, ev, pss, port, timeout);
742         if (req == NULL) {
743                 goto fail;
744         }
745         if (!tevent_req_poll(req, ev)) {
746                 status = NT_STATUS_INTERNAL_ERROR;
747                 goto fail;
748         }
749         status = open_socket_out_recv(req, pfd);
750  fail:
751         TALLOC_FREE(frame);
752         return status;
753 }
754
755 struct open_socket_out_defer_state {
756         struct tevent_context *ev;
757         struct sockaddr_storage ss;
758         uint16_t port;
759         int timeout;
760         int fd;
761 };
762
763 static void open_socket_out_defer_waited(struct tevent_req *subreq);
764 static void open_socket_out_defer_connected(struct tevent_req *subreq);
765
766 struct tevent_req *open_socket_out_defer_send(TALLOC_CTX *mem_ctx,
767                                               struct tevent_context *ev,
768                                               struct timeval wait_time,
769                                               const struct sockaddr_storage *pss,
770                                               uint16_t port,
771                                               int timeout)
772 {
773         struct tevent_req *req, *subreq;
774         struct open_socket_out_defer_state *state;
775
776         req = tevent_req_create(mem_ctx, &state,
777                                 struct open_socket_out_defer_state);
778         if (req == NULL) {
779                 return NULL;
780         }
781         state->ev = ev;
782         state->ss = *pss;
783         state->port = port;
784         state->timeout = timeout;
785
786         subreq = tevent_wakeup_send(
787                 state, ev,
788                 timeval_current_ofs(wait_time.tv_sec, wait_time.tv_usec));
789         if (subreq == NULL) {
790                 goto fail;
791         }
792         tevent_req_set_callback(subreq, open_socket_out_defer_waited, req);
793         return req;
794  fail:
795         TALLOC_FREE(req);
796         return NULL;
797 }
798
799 static void open_socket_out_defer_waited(struct tevent_req *subreq)
800 {
801         struct tevent_req *req = tevent_req_callback_data(
802                 subreq, struct tevent_req);
803         struct open_socket_out_defer_state *state = tevent_req_data(
804                 req, struct open_socket_out_defer_state);
805         bool ret;
806
807         ret = tevent_wakeup_recv(subreq);
808         TALLOC_FREE(subreq);
809         if (!ret) {
810                 tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
811                 return;
812         }
813
814         subreq = open_socket_out_send(state, state->ev, &state->ss,
815                                       state->port, state->timeout);
816         if (tevent_req_nomem(subreq, req)) {
817                 return;
818         }
819         tevent_req_set_callback(subreq, open_socket_out_defer_connected, req);
820 }
821
822 static void open_socket_out_defer_connected(struct tevent_req *subreq)
823 {
824         struct tevent_req *req = tevent_req_callback_data(
825                 subreq, struct tevent_req);
826         struct open_socket_out_defer_state *state = tevent_req_data(
827                 req, struct open_socket_out_defer_state);
828         NTSTATUS status;
829
830         status = open_socket_out_recv(subreq, &state->fd);
831         TALLOC_FREE(subreq);
832         if (!NT_STATUS_IS_OK(status)) {
833                 tevent_req_nterror(req, status);
834                 return;
835         }
836         tevent_req_done(req);
837 }
838
839 NTSTATUS open_socket_out_defer_recv(struct tevent_req *req, int *pfd)
840 {
841         struct open_socket_out_defer_state *state = tevent_req_data(
842                 req, struct open_socket_out_defer_state);
843         NTSTATUS status;
844
845         if (tevent_req_is_nterror(req, &status)) {
846                 return status;
847         }
848         *pfd = state->fd;
849         state->fd = -1;
850         return NT_STATUS_OK;
851 }
852
853 /****************************************************************************
854  Open a connected UDP socket to host on port
855 **************************************************************************/
856
857 int open_udp_socket(const char *host, int port)
858 {
859         struct sockaddr_storage ss;
860         int res;
861         socklen_t salen;
862
863         if (!interpret_string_addr(&ss, host, 0)) {
864                 DEBUG(10,("open_udp_socket: can't resolve name %s\n",
865                         host));
866                 return -1;
867         }
868
869         res = socket(ss.ss_family, SOCK_DGRAM, 0);
870         if (res == -1) {
871                 return -1;
872         }
873
874 #if defined(HAVE_IPV6)
875         if (ss.ss_family == AF_INET6) {
876                 struct sockaddr_in6 *psa6;
877                 psa6 = (struct sockaddr_in6 *)&ss;
878                 psa6->sin6_port = htons(port);
879                 if (psa6->sin6_scope_id == 0
880                                 && IN6_IS_ADDR_LINKLOCAL(&psa6->sin6_addr)) {
881                         setup_linklocal_scope_id(
882                                 (struct sockaddr *)&ss);
883                 }
884                 salen = sizeof(struct sockaddr_in6);
885         } else 
886 #endif
887         if (ss.ss_family == AF_INET) {
888                 struct sockaddr_in *psa;
889                 psa = (struct sockaddr_in *)&ss;
890                 psa->sin_port = htons(port);
891             salen = sizeof(struct sockaddr_in);
892         } else {
893                 DEBUG(1, ("unknown socket family %d", ss.ss_family));
894                 close(res);
895                 return -1;
896         }
897
898         if (connect(res, (struct sockaddr *)&ss, salen)) {
899                 close(res);
900                 return -1;
901         }
902
903         return res;
904 }
905
906 /*******************************************************************
907  Return the IP addr of the remote end of a socket as a string.
908  Optionally return the struct sockaddr_storage.
909  ******************************************************************/
910
911 static const char *get_peer_addr_internal(int fd,
912                                 char *addr_buf,
913                                 size_t addr_buf_len,
914                                 struct sockaddr *pss,
915                                 socklen_t *plength)
916 {
917         struct sockaddr_storage ss;
918         socklen_t length = sizeof(ss);
919
920         strlcpy(addr_buf,"0.0.0.0",addr_buf_len);
921
922         if (fd == -1) {
923                 return addr_buf;
924         }
925
926         if (pss == NULL) {
927                 pss = (struct sockaddr *)&ss;
928                 plength = &length;
929         }
930
931         if (getpeername(fd, (struct sockaddr *)pss, plength) < 0) {
932                 int level = (errno == ENOTCONN) ? 2 : 0;
933                 DEBUG(level, ("getpeername failed. Error was %s\n",
934                                strerror(errno)));
935                 return addr_buf;
936         }
937
938         print_sockaddr_len(addr_buf,
939                         addr_buf_len,
940                         pss,
941                         *plength);
942         return addr_buf;
943 }
944
945 /*******************************************************************
946  Matchname - determine if host name matches IP address. Used to
947  confirm a hostname lookup to prevent spoof attacks.
948 ******************************************************************/
949
950 static bool matchname(const char *remotehost,
951                 const struct sockaddr *pss,
952                 socklen_t len)
953 {
954         struct addrinfo *res = NULL;
955         struct addrinfo *ailist = NULL;
956         char addr_buf[INET6_ADDRSTRLEN];
957         bool ret = interpret_string_addr_internal(&ailist,
958                         remotehost,
959                         AI_ADDRCONFIG|AI_CANONNAME);
960
961         if (!ret || ailist == NULL) {
962                 DEBUG(3,("matchname: getaddrinfo failed for "
963                         "name %s [%s]\n",
964                         remotehost,
965                         gai_strerror(ret) ));
966                 return false;
967         }
968
969         /*
970          * Make sure that getaddrinfo() returns the "correct" host name.
971          */
972
973         if (ailist->ai_canonname == NULL ||
974                 (!strequal(remotehost, ailist->ai_canonname) &&
975                  !strequal(remotehost, "localhost"))) {
976                 DEBUG(0,("matchname: host name/name mismatch: %s != %s\n",
977                          remotehost,
978                          ailist->ai_canonname ?
979                                  ailist->ai_canonname : "(NULL)"));
980                 freeaddrinfo(ailist);
981                 return false;
982         }
983
984         /* Look up the host address in the address list we just got. */
985         for (res = ailist; res; res = res->ai_next) {
986                 if (!res->ai_addr) {
987                         continue;
988                 }
989                 if (sockaddr_equal((const struct sockaddr *)res->ai_addr,
990                                         (const struct sockaddr *)pss)) {
991                         freeaddrinfo(ailist);
992                         return true;
993                 }
994         }
995
996         /*
997          * The host name does not map to the original host address. Perhaps
998          * someone has compromised a name server. More likely someone botched
999          * it, but that could be dangerous, too.
1000          */
1001
1002         DEBUG(0,("matchname: host name/address mismatch: %s != %s\n",
1003                 print_sockaddr_len(addr_buf,
1004                         sizeof(addr_buf),
1005                         pss,
1006                         len),
1007                  ailist->ai_canonname ? ailist->ai_canonname : "(NULL)"));
1008
1009         if (ailist) {
1010                 freeaddrinfo(ailist);
1011         }
1012         return false;
1013 }
1014
1015 /*******************************************************************
1016  Deal with the singleton cache.
1017 ******************************************************************/
1018
1019 struct name_addr_pair {
1020         struct sockaddr_storage ss;
1021         const char *name;
1022 };
1023
1024 /*******************************************************************
1025  Lookup a name/addr pair. Returns memory allocated from memcache.
1026 ******************************************************************/
1027
1028 static bool lookup_nc(struct name_addr_pair *nc)
1029 {
1030         DATA_BLOB tmp;
1031
1032         ZERO_STRUCTP(nc);
1033
1034         if (!memcache_lookup(
1035                         NULL, SINGLETON_CACHE,
1036                         data_blob_string_const_null("get_peer_name"),
1037                         &tmp)) {
1038                 return false;
1039         }
1040
1041         memcpy(&nc->ss, tmp.data, sizeof(nc->ss));
1042         nc->name = (const char *)tmp.data + sizeof(nc->ss);
1043         return true;
1044 }
1045
1046 /*******************************************************************
1047  Save a name/addr pair.
1048 ******************************************************************/
1049
1050 static void store_nc(const struct name_addr_pair *nc)
1051 {
1052         DATA_BLOB tmp;
1053         size_t namelen = strlen(nc->name);
1054
1055         tmp = data_blob(NULL, sizeof(nc->ss) + namelen + 1);
1056         if (!tmp.data) {
1057                 return;
1058         }
1059         memcpy(tmp.data, &nc->ss, sizeof(nc->ss));
1060         memcpy(tmp.data+sizeof(nc->ss), nc->name, namelen+1);
1061
1062         memcache_add(NULL, SINGLETON_CACHE,
1063                         data_blob_string_const_null("get_peer_name"),
1064                         tmp);
1065         data_blob_free(&tmp);
1066 }
1067
1068 /*******************************************************************
1069  Return the IP addr of the remote end of a socket as a string.
1070  ******************************************************************/
1071
1072 const char *get_peer_addr(int fd, char *addr, size_t addr_len)
1073 {
1074         return get_peer_addr_internal(fd, addr, addr_len, NULL, NULL);
1075 }
1076
1077 int get_remote_hostname(const struct tsocket_address *remote_address,
1078                         char **name,
1079                         TALLOC_CTX *mem_ctx)
1080 {
1081         char name_buf[MAX_DNS_NAME_LENGTH];
1082         char tmp_name[MAX_DNS_NAME_LENGTH];
1083         struct name_addr_pair nc;
1084         struct sockaddr_storage ss;
1085         ssize_t len;
1086         int rc;
1087
1088         if (!lp_hostname_lookups()) {
1089                 nc.name = tsocket_address_inet_addr_string(remote_address,
1090                                                            mem_ctx);
1091                 if (nc.name == NULL) {
1092                         return -1;
1093                 }
1094
1095                 len = tsocket_address_bsd_sockaddr(remote_address,
1096                                                    (struct sockaddr *) &nc.ss,
1097                                                    sizeof(struct sockaddr_storage));
1098                 if (len < 0) {
1099                         return -1;
1100                 }
1101
1102                 store_nc(&nc);
1103                 lookup_nc(&nc);
1104
1105                 if (nc.name == NULL) {
1106                         *name = talloc_strdup(mem_ctx, "UNKNOWN");
1107                 } else {
1108                         *name = talloc_strdup(mem_ctx, nc.name);
1109                 }
1110                 return 0;
1111         }
1112
1113         lookup_nc(&nc);
1114
1115         ZERO_STRUCT(ss);
1116
1117         len = tsocket_address_bsd_sockaddr(remote_address,
1118                                            (struct sockaddr *) &ss,
1119                                            sizeof(struct sockaddr_storage));
1120         if (len < 0) {
1121                 return -1;
1122         }
1123
1124         /* it might be the same as the last one - save some DNS work */
1125         if (sockaddr_equal((struct sockaddr *)&ss, (struct sockaddr *)&nc.ss)) {
1126                 if (nc.name == NULL) {
1127                         *name = talloc_strdup(mem_ctx, "UNKNOWN");
1128                 } else {
1129                         *name = talloc_strdup(mem_ctx, nc.name);
1130                 }
1131                 return 0;
1132         }
1133
1134         /* Look up the remote host name. */
1135         rc = sys_getnameinfo((struct sockaddr *) &ss,
1136                              len,
1137                              name_buf,
1138                              sizeof(name_buf),
1139                              NULL,
1140                              0,
1141                              0);
1142         if (rc < 0) {
1143                 char *p;
1144
1145                 p = tsocket_address_inet_addr_string(remote_address, mem_ctx);
1146                 if (p == NULL) {
1147                         return -1;
1148                 }
1149
1150                 DEBUG(1,("getnameinfo failed for %s with error %s\n",
1151                          p,
1152                          gai_strerror(rc)));
1153                 strlcpy(name_buf, p, sizeof(name_buf));
1154
1155                 TALLOC_FREE(p);
1156         } else {
1157                 if (!matchname(name_buf, (struct sockaddr *)&ss, len)) {
1158                         DEBUG(0,("matchname failed on %s\n", name_buf));
1159                         strlcpy(name_buf, "UNKNOWN", sizeof(name_buf));
1160                 }
1161         }
1162
1163         strlcpy(tmp_name, name_buf, sizeof(tmp_name));
1164         alpha_strcpy(name_buf, tmp_name, "_-.", sizeof(name_buf));
1165         if (strstr(name_buf,"..")) {
1166                 strlcpy(name_buf, "UNKNOWN", sizeof(name_buf));
1167         }
1168
1169         nc.name = name_buf;
1170         nc.ss = ss;
1171
1172         store_nc(&nc);
1173         lookup_nc(&nc);
1174
1175         if (nc.name == NULL) {
1176                 *name = talloc_strdup(mem_ctx, "UNKOWN");
1177         } else {
1178                 *name = talloc_strdup(mem_ctx, nc.name);
1179         }
1180
1181         return 0;
1182 }
1183
1184 /*******************************************************************
1185  Create protected unix domain socket.
1186
1187  Some unixes cannot set permissions on a ux-dom-sock, so we
1188  have to make sure that the directory contains the protection
1189  permissions instead.
1190  ******************************************************************/
1191
1192 int create_pipe_sock(const char *socket_dir,
1193                      const char *socket_name,
1194                      mode_t dir_perms)
1195 {
1196 #ifdef HAVE_UNIXSOCKET
1197         struct sockaddr_un sunaddr;
1198         bool ok;
1199         int sock = -1;
1200         mode_t old_umask;
1201         char *path = NULL;
1202
1203         old_umask = umask(0);
1204
1205         ok = directory_create_or_exist_strict(socket_dir,
1206                                               sec_initial_uid(),
1207                                               dir_perms);
1208         if (!ok) {
1209                 goto out_close;
1210         }
1211
1212         /* Create the socket file */
1213         sock = socket(AF_UNIX, SOCK_STREAM, 0);
1214
1215         if (sock == -1) {
1216                 DEBUG(0, ("create_pipe_sock: socket error %s\n",
1217                         strerror(errno) ));
1218                 goto out_close;
1219         }
1220
1221         if (asprintf(&path, "%s/%s", socket_dir, socket_name) == -1) {
1222                 goto out_close;
1223         }
1224
1225         unlink(path);
1226         memset(&sunaddr, 0, sizeof(sunaddr));
1227         sunaddr.sun_family = AF_UNIX;
1228         strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path));
1229
1230         if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) == -1) {
1231                 DEBUG(0, ("bind failed on pipe socket %s: %s\n", path,
1232                         strerror(errno)));
1233                 goto out_close;
1234         }
1235
1236         SAFE_FREE(path);
1237
1238         umask(old_umask);
1239         return sock;
1240
1241 out_close:
1242         SAFE_FREE(path);
1243         if (sock != -1)
1244                 close(sock);
1245
1246         umask(old_umask);
1247         return -1;
1248
1249 #else
1250         DEBUG(0, ("create_pipe_sock: No Unix sockets on this system\n"));
1251         return -1;
1252 #endif /* HAVE_UNIXSOCKET */
1253 }
1254
1255 /****************************************************************************
1256  Get my own canonical name, including domain.
1257 ****************************************************************************/
1258
1259 const char *get_mydnsfullname(void)
1260 {
1261         struct addrinfo *res = NULL;
1262         char my_hostname[HOST_NAME_MAX];
1263         bool ret;
1264         DATA_BLOB tmp;
1265
1266         if (memcache_lookup(NULL, SINGLETON_CACHE,
1267                         data_blob_string_const_null("get_mydnsfullname"),
1268                         &tmp)) {
1269                 SMB_ASSERT(tmp.length > 0);
1270                 return (const char *)tmp.data;
1271         }
1272
1273         /* get my host name */
1274         if (gethostname(my_hostname, sizeof(my_hostname)) == -1) {
1275                 DEBUG(0,("get_mydnsfullname: gethostname failed\n"));
1276                 return NULL;
1277         }
1278
1279         /* Ensure null termination. */
1280         my_hostname[sizeof(my_hostname)-1] = '\0';
1281
1282         ret = interpret_string_addr_internal(&res,
1283                                 my_hostname,
1284                                 AI_ADDRCONFIG|AI_CANONNAME);
1285
1286         if (!ret || res == NULL) {
1287                 DEBUG(3,("get_mydnsfullname: getaddrinfo failed for "
1288                         "name %s [%s]\n",
1289                         my_hostname,
1290                         gai_strerror(ret) ));
1291                 return NULL;
1292         }
1293
1294         /*
1295          * Make sure that getaddrinfo() returns the "correct" host name.
1296          */
1297
1298         if (res->ai_canonname == NULL) {
1299                 DEBUG(3,("get_mydnsfullname: failed to get "
1300                         "canonical name for %s\n",
1301                         my_hostname));
1302                 freeaddrinfo(res);
1303                 return NULL;
1304         }
1305
1306         /* This copies the data, so we must do a lookup
1307          * afterwards to find the value to return.
1308          */
1309
1310         memcache_add(NULL, SINGLETON_CACHE,
1311                         data_blob_string_const_null("get_mydnsfullname"),
1312                         data_blob_string_const_null(res->ai_canonname));
1313
1314         if (!memcache_lookup(NULL, SINGLETON_CACHE,
1315                         data_blob_string_const_null("get_mydnsfullname"),
1316                         &tmp)) {
1317                 tmp = data_blob_talloc(talloc_tos(), res->ai_canonname,
1318                                 strlen(res->ai_canonname) + 1);
1319         }
1320
1321         freeaddrinfo(res);
1322
1323         return (const char *)tmp.data;
1324 }
1325
1326 /************************************************************
1327  Is this my ip address ?
1328 ************************************************************/
1329
1330 static bool is_my_ipaddr(const char *ipaddr_str)
1331 {
1332         struct sockaddr_storage ss;
1333         struct iface_struct *nics;
1334         int i, n;
1335
1336         if (!interpret_string_addr(&ss, ipaddr_str, AI_NUMERICHOST)) {
1337                 return false;
1338         }
1339
1340         if (is_zero_addr(&ss)) {
1341                 return false;
1342         }
1343
1344         if (ismyaddr((struct sockaddr *)&ss) ||
1345                         is_loopback_addr((struct sockaddr *)&ss)) {
1346                 return true;
1347         }
1348
1349         n = get_interfaces(talloc_tos(), &nics);
1350         for (i=0; i<n; i++) {
1351                 if (sockaddr_equal((struct sockaddr *)&nics[i].ip, (struct sockaddr *)&ss)) {
1352                         TALLOC_FREE(nics);
1353                         return true;
1354                 }
1355         }
1356         TALLOC_FREE(nics);
1357         return false;
1358 }
1359
1360 /************************************************************
1361  Is this my name ?
1362 ************************************************************/
1363
1364 bool is_myname_or_ipaddr(const char *s)
1365 {
1366         TALLOC_CTX *ctx = talloc_tos();
1367         char *name = NULL;
1368         const char *dnsname;
1369         char *servername = NULL;
1370
1371         if (!s) {
1372                 return false;
1373         }
1374
1375         /* Santize the string from '\\name' */
1376         name = talloc_strdup(ctx, s);
1377         if (!name) {
1378                 return false;
1379         }
1380
1381         servername = strrchr_m(name, '\\' );
1382         if (!servername) {
1383                 servername = name;
1384         } else {
1385                 servername++;
1386         }
1387
1388         /* Optimize for the common case */
1389         if (strequal(servername, lp_netbios_name())) {
1390                 return true;
1391         }
1392
1393         /* Check for an alias */
1394         if (is_myname(servername)) {
1395                 return true;
1396         }
1397
1398         /* Check for loopback */
1399         if (strequal(servername, "127.0.0.1") ||
1400                         strequal(servername, "::1")) {
1401                 return true;
1402         }
1403
1404         if (strequal(servername, "localhost")) {
1405                 return true;
1406         }
1407
1408         /* Maybe it's my dns name */
1409         dnsname = get_mydnsfullname();
1410         if (dnsname && strequal(servername, dnsname)) {
1411                 return true;
1412         }
1413
1414         /* Maybe its an IP address? */
1415         if (is_ipaddress(servername)) {
1416                 return is_my_ipaddr(servername);
1417         }
1418
1419         /* Handle possible CNAME records - convert to an IP addr. list. */
1420         {
1421                 /* Use DNS to resolve the name, check all addresses. */
1422                 struct addrinfo *p = NULL;
1423                 struct addrinfo *res = NULL;
1424
1425                 if (!interpret_string_addr_internal(&res,
1426                                 servername,
1427                                 AI_ADDRCONFIG)) {
1428                         return false;
1429                 }
1430
1431                 for (p = res; p; p = p->ai_next) {
1432                         char addr[INET6_ADDRSTRLEN];
1433                         struct sockaddr_storage ss;
1434
1435                         ZERO_STRUCT(ss);
1436                         memcpy(&ss, p->ai_addr, p->ai_addrlen);
1437                         print_sockaddr(addr,
1438                                         sizeof(addr),
1439                                         &ss);
1440                         if (is_my_ipaddr(addr)) {
1441                                 freeaddrinfo(res);
1442                                 return true;
1443                         }
1444                 }
1445                 freeaddrinfo(res);
1446         }
1447
1448         /* No match */
1449         return false;
1450 }
1451
1452 struct getaddrinfo_state {
1453         const char *node;
1454         const char *service;
1455         const struct addrinfo *hints;
1456         struct addrinfo *res;
1457         int ret;
1458 };
1459
1460 static void getaddrinfo_do(void *private_data);
1461 static void getaddrinfo_done(struct tevent_req *subreq);
1462
1463 struct tevent_req *getaddrinfo_send(TALLOC_CTX *mem_ctx,
1464                                     struct tevent_context *ev,
1465                                     struct fncall_context *ctx,
1466                                     const char *node,
1467                                     const char *service,
1468                                     const struct addrinfo *hints)
1469 {
1470         struct tevent_req *req, *subreq;
1471         struct getaddrinfo_state *state;
1472
1473         req = tevent_req_create(mem_ctx, &state, struct getaddrinfo_state);
1474         if (req == NULL) {
1475                 return NULL;
1476         }
1477
1478         state->node = node;
1479         state->service = service;
1480         state->hints = hints;
1481
1482         subreq = fncall_send(state, ev, ctx, getaddrinfo_do, state);
1483         if (tevent_req_nomem(subreq, req)) {
1484                 return tevent_req_post(req, ev);
1485         }
1486         tevent_req_set_callback(subreq, getaddrinfo_done, req);
1487         return req;
1488 }
1489
1490 static void getaddrinfo_do(void *private_data)
1491 {
1492         struct getaddrinfo_state *state =
1493                 (struct getaddrinfo_state *)private_data;
1494
1495         state->ret = getaddrinfo(state->node, state->service, state->hints,
1496                                  &state->res);
1497 }
1498
1499 static void getaddrinfo_done(struct tevent_req *subreq)
1500 {
1501         struct tevent_req *req = tevent_req_callback_data(
1502                 subreq, struct tevent_req);
1503         int ret, err;
1504
1505         ret = fncall_recv(subreq, &err);
1506         TALLOC_FREE(subreq);
1507         if (ret == -1) {
1508                 tevent_req_error(req, err);
1509                 return;
1510         }
1511         tevent_req_done(req);
1512 }
1513
1514 int getaddrinfo_recv(struct tevent_req *req, struct addrinfo **res)
1515 {
1516         struct getaddrinfo_state *state = tevent_req_data(
1517                 req, struct getaddrinfo_state);
1518         int err;
1519
1520         if (tevent_req_is_unix_error(req, &err)) {
1521                 switch(err) {
1522                 case ENOMEM:
1523                         return EAI_MEMORY;
1524                 default:
1525                         return EAI_FAIL;
1526                 }
1527         }
1528         if (state->ret == 0) {
1529                 *res = state->res;
1530         }
1531         return state->ret;
1532 }
1533
1534 int poll_one_fd(int fd, int events, int timeout, int *revents)
1535 {
1536         struct pollfd pfd;
1537         int ret;
1538
1539         pfd.fd = fd;
1540         pfd.events = events;
1541
1542         ret = poll(&pfd, 1, timeout);
1543
1544         /*
1545          * Assign whatever poll did, even in the ret<=0 case.
1546          */
1547         *revents = pfd.revents;
1548
1549         return ret;
1550 }
1551
1552 int poll_intr_one_fd(int fd, int events, int timeout, int *revents)
1553 {
1554         struct pollfd pfd;
1555         int ret;
1556
1557         pfd.fd = fd;
1558         pfd.events = events;
1559
1560         ret = sys_poll_intr(&pfd, 1, timeout);
1561         if (ret <= 0) {
1562                 *revents = 0;
1563                 return ret;
1564         }
1565         *revents = pfd.revents;
1566         return 1;
1567 }