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