2 * ircd-ratbox: A slightly useful ircd.
3 * commio.c: Network/file related functions
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
24 * $Id: commio.c 26254 2008-12-10 04:04:38Z androsyn $
26 #include <libratbox_config.h>
27 #include <ratbox_lib.h>
28 #include <commio-int.h>
29 #include <commio-ssl.h>
30 #include <event-int.h>
37 #define MSG_NOSIGNAL 0
50 rb_dlink_list
*rb_fd_table
;
51 static rb_bh
*fd_heap
;
53 static rb_dlink_list timeout_list
;
54 static rb_dlink_list closed_list
;
56 static struct ev_entry
*rb_timeout_ev
;
59 static const char *rb_err_str
[] = { "Comm OK", "Error during bind()",
60 "Error during DNS lookup", "connect timeout",
61 "Error during connect()",
66 /* Highest FD and number of open FDs .. */
67 static int number_fd
= 0;
68 int rb_maxconnections
= 0;
70 static PF rb_connect_timeout
;
71 static PF rb_connect_tryconnect
;
73 static void mangle_mapped_sockaddr(struct sockaddr
*in
);
76 #ifndef HAVE_SOCKETPAIR
77 static int rb_inet_socketpair(int d
, int type
, int protocol
, int sv
[2]);
78 static int rb_inet_socketpair_udp(rb_fde_t
**newF1
, rb_fde_t
**newF2
);
81 static inline rb_fde_t
*
84 rb_fde_t
*F
= rb_find_fd(fd
);
86 /* look up to see if we have it already */
90 F
= rb_bh_alloc(fd_heap
);
92 rb_dlinkAdd(F
, &F
->node
, &rb_fd_table
[rb_hash_fd(fd
)]);
97 remove_fd(rb_fde_t
*F
)
99 if(F
== NULL
|| !IsFDOpen(F
))
102 rb_dlinkMoveNode(&F
->node
, &rb_fd_table
[rb_hash_fd(F
->fd
)], &closed_list
);
109 rb_dlink_node
*ptr
, *next
;
110 RB_DLINK_FOREACH_SAFE(ptr
, next
, closed_list
.head
)
113 rb_dlinkDelete(ptr
, &closed_list
);
114 rb_bh_free(fd_heap
, F
);
118 /* 32bit solaris is kinda slow and stdio only supports fds < 256
119 * so we got to do this crap below.
120 * (BTW Fuck you Sun, I hate your guts and I hope you go bankrupt soon)
123 #if defined (__SVR4) && defined (__sun)
128 if(*fd
> 256 || *fd
< 0)
130 if((newfd
= fcntl(*fd
, F_DUPFD
, 256)) != -1)
138 #define rb_fd_hack(fd)
142 /* close_all_connections() can be used *before* the system come up! */
150 /* XXX someone tell me why we care about 4 fd's ? */
151 /* XXX btw, fd 3 is used for profiler ! */
152 for(i
= 3; i
< rb_maxconnections
; ++i
)
160 * get_sockerr - get the error value from the socket or the current errno
162 * Get the *real* error from the socket (well try to anyway..).
163 * This may only work when SO_DEBUG is enabled but its worth the
167 rb_get_sockerr(rb_fde_t
*F
)
171 rb_socklen_t len
= sizeof(err
);
173 if(!(F
->type
& RB_FD_SOCKET
))
181 && !getsockopt(rb_get_fd(F
), SOL_SOCKET
, SO_ERROR
, (char *)&err
, (rb_socklen_t
*) & len
))
192 * rb_getmaxconnect - return the max number of connections allowed
195 rb_getmaxconnect(void)
197 return (rb_maxconnections
);
201 * set_sock_buffers - set send and receive buffers for socket
203 * inputs - fd file descriptor
205 * output - returns true (1) if successful, false (0) otherwise
209 rb_set_buffers(rb_fde_t
*F
, int size
)
214 (F
->fd
, SOL_SOCKET
, SO_RCVBUF
, (char *)&size
, sizeof(size
))
215 || setsockopt(F
->fd
, SOL_SOCKET
, SO_SNDBUF
, (char *)&size
, sizeof(size
)))
221 * set_non_blocking - Set the client connection into non-blocking mode.
223 * inputs - fd to set into non blocking mode
224 * output - 1 if successful 0 if not
225 * side effects - use POSIX compliant non blocking and
229 rb_set_nb(rb_fde_t
*F
)
238 if((res
= rb_setup_fd(F
)))
242 res
= fcntl(fd
, F_GETFL
, 0);
243 if(-1 == res
|| fcntl(fd
, F_SETFL
, res
| nonb
) == -1)
248 if(ioctl(fd
, FIONBIO
, (char *)&nonb
) == -1)
256 * rb_settimeout() - set the socket timeout
258 * Set the timeout for the fd
261 rb_settimeout(rb_fde_t
*F
, time_t timeout
, PF
* callback
, void *cbdata
)
263 struct timeout_data
*td
;
268 lrb_assert(IsFDOpen(F
));
270 if(callback
== NULL
) /* user wants to remove */
274 rb_dlinkDelete(&td
->node
, &timeout_list
);
277 if(rb_dlink_list_length(&timeout_list
) == 0)
279 rb_event_delete(rb_timeout_ev
);
280 rb_timeout_ev
= NULL
;
285 if(F
->timeout
== NULL
)
286 td
= F
->timeout
= rb_malloc(sizeof(struct timeout_data
));
289 td
->timeout
= rb_current_time() + timeout
;
290 td
->timeout_handler
= callback
;
291 td
->timeout_data
= cbdata
;
292 rb_dlinkAdd(td
, &td
->node
, &timeout_list
);
293 if(rb_timeout_ev
== NULL
)
295 rb_timeout_ev
= rb_event_add("rb_checktimeouts", rb_checktimeouts
, NULL
, 5);
300 * rb_checktimeouts() - check the socket timeouts
302 * All this routine does is call the given callback/cbdata, without closing
303 * down the file descriptor. When close handlers have been implemented,
307 rb_checktimeouts(void *notused
)
309 rb_dlink_node
*ptr
, *next
;
310 struct timeout_data
*td
;
315 RB_DLINK_FOREACH_SAFE(ptr
, next
, timeout_list
.head
)
319 if(F
== NULL
|| !IsFDOpen(F
))
322 if(td
->timeout
< rb_current_time())
324 hdl
= td
->timeout_handler
;
325 data
= td
->timeout_data
;
326 rb_dlinkDelete(&td
->node
, &timeout_list
);
335 rb_accept_tryaccept(rb_fde_t
*F
, void *data
)
337 struct rb_sockaddr_storage st
;
339 rb_socklen_t addrlen
= sizeof(st
);
344 new_fd
= accept(F
->fd
, (struct sockaddr
*)&st
, &addrlen
);
348 rb_setselect(F
, RB_SELECT_ACCEPT
, rb_accept_tryaccept
, NULL
);
354 new_F
= rb_open(new_fd
, RB_FD_SOCKET
, "Incoming Connection");
359 ("rb_accept: new_F == NULL on incoming connection. Closing new_fd == %d\n",
365 if(rb_unlikely(!rb_set_nb(new_F
)))
368 rb_lib_log("rb_accept: Couldn't set FD %d non blocking!", new_F
->fd
);
373 mangle_mapped_sockaddr((struct sockaddr
*)&st
);
376 if(F
->accept
->precb
!= NULL
)
378 if(!F
->accept
->precb(new_F
, (struct sockaddr
*)&st
, addrlen
, F
->accept
->data
)) /* pre-callback decided to drop it */
382 if(F
->type
& RB_FD_SSL
)
384 rb_ssl_accept_setup(F
, new_F
, (struct sockaddr
*)&st
, addrlen
);
387 #endif /* HAVE_SSL */
389 F
->accept
->callback(new_F
, RB_OK
, (struct sockaddr
*)&st
, addrlen
,
396 /* try to accept a TCP connection */
398 rb_accept_tcp(rb_fde_t
*F
, ACPRE
* precb
, ACCB
* callback
, void *data
)
402 lrb_assert(callback
);
404 F
->accept
= rb_malloc(sizeof(struct acceptdata
));
405 F
->accept
->callback
= callback
;
406 F
->accept
->data
= data
;
407 F
->accept
->precb
= precb
;
408 rb_accept_tryaccept(F
, NULL
);
412 * void rb_connect_tcp(int fd, struct sockaddr *dest,
413 * struct sockaddr *clocal, int socklen,
414 * CNCB *callback, void *data, int timeout)
415 * Input: An fd to connect with, a host and port to connect to,
416 * a local sockaddr to connect from + length(or NULL to use the
417 * default), a callback, the data to pass into the callback, the
420 * Side-effects: A non-blocking connection to the host is started, and
421 * if necessary, set up for selection. The callback given
422 * may be called now, or it may be called later.
425 rb_connect_tcp(rb_fde_t
*F
, struct sockaddr
*dest
,
426 struct sockaddr
*clocal
, int socklen
, CNCB
* callback
, void *data
, int timeout
)
431 lrb_assert(callback
);
432 F
->connect
= rb_malloc(sizeof(struct conndata
));
433 F
->connect
->callback
= callback
;
434 F
->connect
->data
= data
;
436 memcpy(&F
->connect
->hostaddr
, dest
, sizeof(F
->connect
->hostaddr
));
438 /* Note that we're using a passed sockaddr here. This is because
439 * generally you'll be bind()ing to a sockaddr grabbed from
440 * getsockname(), so this makes things easier.
441 * XXX If NULL is passed as local, we should later on bind() to the
442 * virtual host IP, for completeness.
445 if((clocal
!= NULL
) && (bind(F
->fd
, clocal
, socklen
) < 0))
447 /* Failure, call the callback with RB_ERR_BIND */
448 rb_connect_callback(F
, RB_ERR_BIND
);
453 /* We have a valid IP, so we just call tryconnect */
454 /* Make sure we actually set the timeout here .. */
455 rb_settimeout(F
, timeout
, rb_connect_timeout
, NULL
);
456 rb_connect_tryconnect(F
, NULL
);
461 * rb_connect_callback() - call the callback, and continue with life
464 rb_connect_callback(rb_fde_t
*F
, int status
)
468 int errtmp
= errno
; /* save errno as rb_settimeout clobbers it sometimes */
470 /* This check is gross..but probably necessary */
471 if(F
== NULL
|| F
->connect
== NULL
|| F
->connect
->callback
== NULL
)
473 /* Clear the connect flag + handler */
474 hdl
= F
->connect
->callback
;
475 data
= F
->connect
->data
;
476 F
->connect
->callback
= NULL
;
479 /* Clear the timeout handler */
480 rb_settimeout(F
, 0, NULL
, NULL
);
482 /* Call the handler */
483 hdl(F
, status
, data
);
488 * rb_connect_timeout() - this gets called when the socket connection
489 * times out. This *only* can be called once connect() is initially
493 rb_connect_timeout(rb_fde_t
*F
, void *notused
)
496 rb_connect_callback(F
, RB_ERR_TIMEOUT
);
499 /* static void rb_connect_tryconnect(int fd, void *notused)
500 * Input: The fd, the handler data(unused).
502 * Side-effects: Try and connect with pending connect data for the FD. If
503 * we succeed or get a fatal error, call the callback.
504 * Otherwise, it is still blocking or something, so register
505 * to select for a write event on this FD.
508 rb_connect_tryconnect(rb_fde_t
*F
, void *notused
)
512 if(F
== NULL
|| F
->connect
== NULL
|| F
->connect
->callback
== NULL
)
514 /* Try the connect() */
515 retval
= connect(F
->fd
,
516 (struct sockaddr
*)&F
->connect
->hostaddr
,
517 GET_SS_LEN(&F
->connect
->hostaddr
));
522 * If we get EISCONN, then we've already connect()ed the socket,
523 * which is a good thing.
528 rb_connect_callback(F
, RB_OK
);
529 else if(rb_ignore_errno(errno
))
530 /* Ignore error? Reschedule */
531 rb_setselect(F
, RB_SELECT_CONNECT
, rb_connect_tryconnect
, NULL
);
533 /* Error? Fail with RB_ERR_CONNECT */
534 rb_connect_callback(F
, RB_ERR_CONNECT
);
537 /* If we get here, we've suceeded, so call with RB_OK */
538 rb_connect_callback(F
, RB_OK
);
543 rb_connect_sockaddr(rb_fde_t
*F
, struct sockaddr
*addr
, int len
)
548 memcpy(addr
, &F
->connect
->hostaddr
, len
);
553 * rb_error_str() - return an error string for the given error condition
558 if(error
< 0 || error
>= RB_ERR_MAX
)
559 return "Invalid error number!";
560 return rb_err_str
[error
];
565 rb_socketpair(int family
, int sock_type
, int proto
, rb_fde_t
**F1
, rb_fde_t
**F2
, const char *note
)
568 if(number_fd
>= rb_maxconnections
)
574 #ifdef HAVE_SOCKETPAIR
575 if(socketpair(family
, sock_type
, proto
, nfd
))
577 if(sock_type
== SOCK_DGRAM
)
579 return rb_inet_socketpair_udp(F1
, F2
);
582 if(rb_inet_socketpair(AF_INET
, sock_type
, proto
, nfd
))
589 *F1
= rb_open(nfd
[0], RB_FD_SOCKET
, note
);
590 *F2
= rb_open(nfd
[1], RB_FD_SOCKET
, note
);
605 /* Set the socket non-blocking, and other wonderful bits */
606 if(rb_unlikely(!rb_set_nb(*F1
)))
608 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd
[0], strerror(errno
));
614 if(rb_unlikely(!rb_set_nb(*F2
)))
616 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd
[1], strerror(errno
));
627 rb_pipe(rb_fde_t
**F1
, rb_fde_t
**F2
, const char *desc
)
631 if(number_fd
>= rb_maxconnections
)
640 *F1
= rb_open(fd
[0], RB_FD_PIPE
, desc
);
641 *F2
= rb_open(fd
[1], RB_FD_PIPE
, desc
);
643 if(rb_unlikely(!rb_set_nb(*F1
)))
645 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
[0], strerror(errno
));
651 if(rb_unlikely(!rb_set_nb(*F2
)))
653 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
[1], strerror(errno
));
662 /* Its not a pipe..but its selectable. I'll take dirty hacks
665 return rb_socketpair(AF_INET
, SOCK_STREAM
, 0, F1
, F2
, desc
);
670 * rb_socket() - open a socket
672 * This is a highly highly cut down version of squid's rb_open() which
673 * for the most part emulates socket(), *EXCEPT* it fails if we're about
674 * to run out of file descriptors.
677 rb_socket(int family
, int sock_type
, int proto
, const char *note
)
681 /* First, make sure we aren't going to run out of file descriptors */
682 if(rb_unlikely(number_fd
>= rb_maxconnections
))
689 * Next, we try to open the socket. We *should* drop the reserved FD
690 * limit if/when we get an error, but we can deal with that later.
693 fd
= socket(family
, sock_type
, proto
);
695 if(rb_unlikely(fd
< 0))
696 return NULL
; /* errno will be passed through, yay.. */
698 #if defined(RB_IPV6) && defined(IPV6_V6ONLY)
700 * Make sure we can take both IPv4 and IPv6 connections
701 * on an AF_INET6 socket
703 if(family
== AF_INET6
)
706 if(setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &off
, sizeof(off
)) == -1)
708 rb_lib_log("rb_socket: Could not set IPV6_V6ONLY option to 1 on FD %d: %s",
709 fd
, strerror(errno
));
716 F
= rb_open(fd
, RB_FD_SOCKET
, note
);
719 rb_lib_log("rb_socket: rb_open returns NULL on FD %d: %s, closing fd", fd
,
724 /* Set the socket non-blocking, and other wonderful bits */
725 if(rb_unlikely(!rb_set_nb(F
)))
727 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
, strerror(errno
));
736 * If a sockaddr_storage is AF_INET6 but is a mapped IPv4
737 * socket manged the sockaddr.
741 mangle_mapped_sockaddr(struct sockaddr
*in
)
743 struct sockaddr_in6
*in6
= (struct sockaddr_in6
*)in
;
745 if(in
->sa_family
== AF_INET
)
748 if(in
->sa_family
== AF_INET6
&& IN6_IS_ADDR_V4MAPPED(&in6
->sin6_addr
))
750 struct sockaddr_in in4
;
751 memset(&in4
, 0, sizeof(struct sockaddr_in
));
752 in4
.sin_family
= AF_INET
;
753 in4
.sin_port
= in6
->sin6_port
;
754 in4
.sin_addr
.s_addr
= ((uint32_t *)&in6
->sin6_addr
)[3];
755 memcpy(in
, &in4
, sizeof(struct sockaddr_in
));
762 * rb_listen() - listen on a port
765 rb_listen(rb_fde_t
*F
, int backlog
, int defer_accept
)
769 F
->type
= RB_FD_SOCKET
| RB_FD_LISTEN
;
770 result
= listen(F
->fd
, backlog
);
772 #ifdef TCP_DEFER_ACCEPT
773 if (defer_accept
&& !result
)
775 setsockopt(F
->fd
, IPPROTO_TCP
, TCP_DEFER_ACCEPT
, &backlog
, sizeof(int));
778 #ifdef SO_ACCEPTFILTER
779 if (defer_accept
&& !result
)
781 struct accept_filter_arg afa
;
783 memset(&afa
, '\0', sizeof afa
);
784 rb_strlcpy(afa
.af_name
, "dataready", sizeof afa
.af_name
);
785 (void)setsockopt(F
->fd
, SOL_SOCKET
, SO_ACCEPTFILTER
, &afa
,
794 rb_fdlist_init(int closeall
, int maxfds
, size_t heapsize
)
796 static int initialized
= 0;
800 int vers
= MAKEWORD(2, 0);
802 err
= WSAStartup(vers
, &wsaData
);
805 rb_lib_die("WSAStartup failed");
811 rb_maxconnections
= maxfds
;
814 /* Since we're doing this once .. */
817 fd_heap
= rb_bh_create(sizeof(rb_fde_t
), heapsize
, "librb_fd_heap");
822 /* Called to open a given filedescriptor */
824 rb_open(int fd
, uint8_t type
, const char *desc
)
831 lrb_assert(!IsFDOpen(F
));
832 if(rb_unlikely(IsFDOpen(F
)))
835 if(F
!= NULL
&& F
->desc
!= NULL
)
839 rb_lib_log("Trying to rb_open an already open FD: %d desc: %s", fd
, fdesc
);
847 F
->desc
= rb_strndup(desc
, FD_DESC_SZ
);
853 /* Called to close a given filedescriptor */
855 rb_close(rb_fde_t
*F
)
864 lrb_assert(IsFDOpen(F
));
866 lrb_assert(!(type
& RB_FD_FILE
));
867 if(rb_unlikely(type
& RB_FD_FILE
))
869 lrb_assert(F
->read_handler
== NULL
);
870 lrb_assert(F
->write_handler
== NULL
);
872 rb_setselect(F
, RB_SELECT_WRITE
| RB_SELECT_READ
, NULL
, NULL
);
873 rb_settimeout(F
, 0, NULL
, NULL
);
882 #endif /* HAVE_SSL */
892 if(type
& (RB_FD_SOCKET
| RB_FD_PIPE
))
904 * rb_dump_fd() - dump the list of active filedescriptors
907 rb_dump_fd(DUMPCB
* cb
, void *data
)
909 static const char *empty
= "";
911 rb_dlink_list
*bucket
;
915 for(i
= 0; i
< RB_FD_HASH_SIZE
; i
++)
917 bucket
= &rb_fd_table
[i
];
919 if(rb_dlink_list_length(bucket
) <= 0)
922 RB_DLINK_FOREACH(ptr
, bucket
->head
)
925 if(F
== NULL
|| !IsFDOpen(F
))
928 cb(F
->fd
, F
->desc
? F
->desc
: empty
, data
);
934 * rb_note() - set the fd note
936 * Note: must be careful not to overflow rb_fd_table[fd].desc when
940 rb_note(rb_fde_t
*F
, const char *string
)
946 F
->desc
= rb_strndup(string
, FD_DESC_SZ
);
950 rb_set_type(rb_fde_t
*F
, uint8_t type
)
952 /* if the caller is calling this, lets assume they have a clue */
958 rb_get_type(rb_fde_t
*F
)
964 rb_fd_ssl(rb_fde_t
*F
)
968 if(F
->type
& RB_FD_SSL
)
974 rb_get_fd(rb_fde_t
*F
)
984 return rb_find_fd(fd
);
988 rb_read(rb_fde_t
*F
, void *buf
, int count
)
994 /* This needs to be *before* RB_FD_SOCKET otherwise you'll process
995 * an SSL socket as a regular socket
998 if(F
->type
& RB_FD_SSL
)
1000 return rb_ssl_read(F
, buf
, count
);
1003 if(F
->type
& RB_FD_SOCKET
)
1005 ret
= recv(F
->fd
, buf
, count
, 0);
1015 return read(F
->fd
, buf
, count
);
1020 rb_write(rb_fde_t
*F
, const void *buf
, int count
)
1027 if(F
->type
& RB_FD_SSL
)
1029 return rb_ssl_write(F
, buf
, count
);
1032 if(F
->type
& RB_FD_SOCKET
)
1034 ret
= send(F
->fd
, buf
, count
, MSG_NOSIGNAL
);
1042 return write(F
->fd
, buf
, count
);
1045 #if defined(HAVE_SSL) || defined(WIN32) || !defined(HAVE_WRITEV)
1047 rb_fake_writev(rb_fde_t
*F
, const struct rb_iovec
*vp
, size_t vpcount
)
1051 while(vpcount
-- > 0)
1053 ssize_t written
= rb_write(F
, vp
->iov_base
, vp
->iov_len
);
1069 #if defined(WIN32) || !defined(HAVE_WRITEV)
1071 rb_writev(rb_fde_t
*F
, struct rb_iovec
* vecount
, int count
)
1073 return rb_fake_writev(F
, vecount
, count
);
1078 rb_writev(rb_fde_t
*F
, struct rb_iovec
* vector
, int count
)
1086 if(F
->type
& RB_FD_SSL
)
1088 return rb_fake_writev(F
, vector
, count
);
1090 #endif /* HAVE_SSL */
1092 if(F
->type
& RB_FD_SOCKET
)
1095 memset(&msg
, 0, sizeof(msg
));
1096 msg
.msg_iov
= (struct iovec
*)vector
;
1097 msg
.msg_iovlen
= count
;
1098 return sendmsg(F
->fd
, &msg
, MSG_NOSIGNAL
);
1100 #endif /* HAVE_SENDMSG */
1101 return writev(F
->fd
, (struct iovec
*)vector
, count
);
1108 * From: Thomas Helvey <tomh@inxpress.net>
1110 static const char *IpQuadTab
[] = {
1111 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
1112 "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
1113 "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
1114 "30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
1115 "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
1116 "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
1117 "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
1118 "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
1119 "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
1120 "90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
1121 "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
1122 "110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
1123 "120", "121", "122", "123", "124", "125", "126", "127", "128", "129",
1124 "130", "131", "132", "133", "134", "135", "136", "137", "138", "139",
1125 "140", "141", "142", "143", "144", "145", "146", "147", "148", "149",
1126 "150", "151", "152", "153", "154", "155", "156", "157", "158", "159",
1127 "160", "161", "162", "163", "164", "165", "166", "167", "168", "169",
1128 "170", "171", "172", "173", "174", "175", "176", "177", "178", "179",
1129 "180", "181", "182", "183", "184", "185", "186", "187", "188", "189",
1130 "190", "191", "192", "193", "194", "195", "196", "197", "198", "199",
1131 "200", "201", "202", "203", "204", "205", "206", "207", "208", "209",
1132 "210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
1133 "220", "221", "222", "223", "224", "225", "226", "227", "228", "229",
1134 "230", "231", "232", "233", "234", "235", "236", "237", "238", "239",
1135 "240", "241", "242", "243", "244", "245", "246", "247", "248", "249",
1136 "250", "251", "252", "253", "254", "255"
1140 * inetntoa - in_addr to string
1141 * changed name to remove collision possibility and
1142 * so behaviour is guaranteed to take a pointer arg.
1144 * inet_ntoa -- returned the dotted notation of a given
1147 * inet_ntoa -- its broken on some Ultrix/Dynix too. -avalon
1151 inetntoa(const char *in
)
1153 static char buf
[16];
1155 const unsigned char *a
= (const unsigned char *)in
;
1158 n
= IpQuadTab
[*a
++];
1162 n
= IpQuadTab
[*a
++];
1166 n
= IpQuadTab
[*a
++];
1179 * Copyright (c) 1996-1999 by Internet Software Consortium.
1181 * Permission to use, copy, modify, and distribute this software for any
1182 * purpose with or without fee is hereby granted, provided that the above
1183 * copyright notice and this permission notice appear in all copies.
1185 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
1186 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
1187 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
1188 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
1189 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
1190 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
1191 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
1195 #define SPRINTF(x) ((size_t)rb_sprintf x)
1198 * WARNING: Don't even consider trying to compile this on a system where
1199 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
1202 static const char *inet_ntop4(const unsigned char *src
, char *dst
, unsigned int size
);
1204 static const char *inet_ntop6(const unsigned char *src
, char *dst
, unsigned int size
);
1208 * inet_ntop4(src, dst, size)
1209 * format an IPv4 address
1211 * `dst' (as a const)
1213 * (1) uses no statics
1214 * (2) takes a unsigned char* not an in_addr as input
1219 inet_ntop4(const unsigned char *src
, char *dst
, unsigned int size
)
1223 return strcpy(dst
, inetntoa((const char *)src
));
1227 * inet_ntop6(src, dst, size)
1228 * convert IPv6 binary address into presentation (printable) format
1234 inet_ntop6(const unsigned char *src
, char *dst
, unsigned int size
)
1237 * Note that int32_t and int16_t need only be "at least" large enough
1238 * to contain a value of the specified size. On some systems, like
1239 * Crays, there is no such thing as an integer variable with 16 bits.
1240 * Keep this in mind if you think this function should have been coded
1241 * to use pointer overlays. All the world's not a VAX.
1243 char tmp
[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp
;
1249 unsigned int words
[IN6ADDRSZ
/ INT16SZ
];
1254 * Copy the input (bytewise) array into a wordwise array.
1255 * Find the longest run of 0x00's in src[] for :: shorthanding.
1257 memset(words
, '\0', sizeof words
);
1258 for(i
= 0; i
< IN6ADDRSZ
; i
+= 2)
1259 words
[i
/ 2] = (src
[i
] << 8) | src
[i
+ 1];
1264 for(i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++)
1269 cur
.base
= i
, cur
.len
= 1;
1277 if(best
.base
== -1 || cur
.len
> best
.len
)
1285 if(best
.base
== -1 || cur
.len
> best
.len
)
1288 if(best
.base
!= -1 && best
.len
< 2)
1292 * Format the result.
1295 for(i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++)
1297 /* Are we inside the best run of 0x00's? */
1298 if(best
.base
!= -1 && i
>= best
.base
&& i
< (best
.base
+ best
.len
))
1308 /* Are we following an initial run of 0x00s or any real hex? */
1311 /* Is this address an encapsulated IPv4? */
1312 if(i
== 6 && best
.base
== 0 &&
1313 (best
.len
== 6 || (best
.len
== 5 && words
[5] == 0xffff)))
1315 if(!inet_ntop4(src
+ 12, tp
, sizeof tmp
- (tp
- tmp
)))
1320 tp
+= SPRINTF((tp
, "%x", words
[i
]));
1322 /* Was it a trailing run of 0x00's? */
1323 if(best
.base
!= -1 && (best
.base
+ best
.len
) == (IN6ADDRSZ
/ INT16SZ
))
1328 * Check for overflow, copy, and we're done.
1331 if((unsigned int)(tp
- tmp
) > size
)
1335 return memcpy(dst
, tmp
, tp
- tmp
);
1340 rb_inet_pton_sock(const char *src
, struct sockaddr
*dst
)
1342 if(rb_inet_pton(AF_INET
, src
, &((struct sockaddr_in
*)dst
)->sin_addr
))
1344 ((struct sockaddr_in
*)dst
)->sin_port
= 0;
1345 ((struct sockaddr_in
*)dst
)->sin_family
= AF_INET
;
1346 SET_SS_LEN(dst
, sizeof(struct sockaddr_in
));
1350 else if(rb_inet_pton(AF_INET6
, src
, &((struct sockaddr_in6
*)dst
)->sin6_addr
))
1352 ((struct sockaddr_in6
*)dst
)->sin6_port
= 0;
1353 ((struct sockaddr_in6
*)dst
)->sin6_family
= AF_INET6
;
1354 SET_SS_LEN(dst
, sizeof(struct sockaddr_in6
));
1362 rb_inet_ntop_sock(struct sockaddr
*src
, char *dst
, unsigned int size
)
1364 switch (src
->sa_family
)
1367 return (rb_inet_ntop(AF_INET
, &((struct sockaddr_in
*)src
)->sin_addr
, dst
, size
));
1371 return (rb_inet_ntop
1372 (AF_INET6
, &((struct sockaddr_in6
*)src
)->sin6_addr
, dst
, size
));
1382 * rb_inet_ntop(af, src, dst, size)
1383 * convert a network format address to presentation format.
1385 * pointer to presentation format address (`dst'), or NULL (see errno).
1390 rb_inet_ntop(int af
, const void *src
, char *dst
, unsigned int size
)
1395 return (inet_ntop4(src
, dst
, size
));
1398 if(IN6_IS_ADDR_V4MAPPED((const struct in6_addr
*)src
) ||
1399 IN6_IS_ADDR_V4COMPAT((const struct in6_addr
*)src
))
1401 ((const unsigned char *)&((const struct in6_addr
*)src
)->
1402 s6_addr
[12], dst
, size
));
1404 return (inet_ntop6(src
, dst
, size
));
1415 * WARNING: Don't even consider trying to compile this on a system where
1416 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
1420 * rb_inet_pton(af, src, dst)
1421 * convert from presentation format (which usually means ASCII printable)
1422 * to network format (which is usually some kind of binary format).
1424 * 1 if the address was valid for the specified address family
1425 * 0 if the address wasn't valid (`dst' is untouched in this case)
1426 * -1 if some other error occurred (`dst' is untouched in this case, too)
1432 * inet_pton4(src, dst)
1433 * like inet_aton() but without all the hexadecimal and shorthand.
1435 * 1 if `src' is a valid dotted quad, else 0.
1437 * does not touch `dst' unless it's returning 1.
1442 inet_pton4(const char *src
, unsigned char *dst
)
1444 int saw_digit
, octets
, ch
;
1445 unsigned char tmp
[INADDRSZ
], *tp
;
1450 while((ch
= *src
++) != '\0')
1453 if(ch
>= '0' && ch
<= '9')
1455 unsigned int new = *tp
* 10 + (ch
- '0');
1467 else if(ch
== '.' && saw_digit
)
1479 memcpy(dst
, tmp
, INADDRSZ
);
1485 * inet_pton6(src, dst)
1486 * convert presentation level address to network order binary form.
1488 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
1490 * (1) does not touch `dst' unless it's returning 1.
1491 * (2) :: in a full address is silently ignored.
1493 * inspired by Mark Andrews.
1499 inet_pton6(const char *src
, unsigned char *dst
)
1501 static const char xdigits
[] = "0123456789abcdef";
1502 unsigned char tmp
[IN6ADDRSZ
], *tp
, *endp
, *colonp
;
1507 tp
= memset(tmp
, '\0', IN6ADDRSZ
);
1508 endp
= tp
+ IN6ADDRSZ
;
1510 /* Leading :: requires some special handling. */
1517 while((ch
= tolower(*src
++)) != '\0')
1521 pch
= strchr(xdigits
, ch
);
1525 val
|= (pch
- xdigits
);
1541 else if(*src
== '\0')
1545 if(tp
+ INT16SZ
> endp
)
1547 *tp
++ = (unsigned char)(val
>> 8) & 0xff;
1548 *tp
++ = (unsigned char)val
& 0xff;
1553 if(*src
!= '\0' && ch
== '.')
1555 if(((tp
+ INADDRSZ
) <= endp
) && inet_pton4(curtok
, tp
) > 0)
1559 break; /* '\0' was seen by inet_pton4(). */
1568 if(tp
+ INT16SZ
> endp
)
1570 *tp
++ = (unsigned char)(val
>> 8) & 0xff;
1571 *tp
++ = (unsigned char)val
& 0xff;
1576 * Since some memmove()'s erroneously fail to handle
1577 * overlapping regions, we'll do the shift by hand.
1579 const int n
= tp
- colonp
;
1584 for(i
= 1; i
<= n
; i
++)
1586 endp
[-i
] = colonp
[n
- i
];
1593 memcpy(dst
, tmp
, IN6ADDRSZ
);
1598 rb_inet_pton(int af
, const char *src
, void *dst
)
1603 return (inet_pton4(src
, dst
));
1606 /* Somebody might have passed as an IPv4 address this is sick but it works */
1607 if(inet_pton4(src
, dst
))
1609 char tmp
[HOSTIPLEN
];
1610 rb_sprintf(tmp
, "::ffff:%s", src
);
1611 return (inet_pton6(tmp
, dst
));
1614 return (inet_pton6(src
, dst
));
1623 #ifndef HAVE_SOCKETPAIR
1625 /* mostly based on perl's emulation of socketpair udp */
1627 rb_inet_socketpair_udp(rb_fde_t
**newF1
, rb_fde_t
**newF2
)
1629 struct sockaddr_in addr
[2];
1630 rb_socklen_t size
= sizeof(struct sockaddr_in
);
1634 unsigned short port
;
1635 struct timeval wait
= { 0, 100000 };
1638 struct sockaddr_in readfrom
;
1639 unsigned short buf
[2];
1642 memset(&addr
, 0, sizeof(addr
));
1644 for(i
= 0; i
< 2; i
++)
1646 F
[i
] = rb_socket(AF_INET
, SOCK_DGRAM
, 0, "udp socketpair");
1649 addr
[i
].sin_family
= AF_INET
;
1650 addr
[i
].sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
1651 addr
[i
].sin_port
= 0;
1652 if(bind(rb_get_fd(F
[i
]), (struct sockaddr
*)&addr
[i
], sizeof(struct sockaddr_in
)))
1654 fd
[i
] = rb_get_fd(F
[i
]);
1657 for(i
= 0; i
< 2; i
++)
1659 if(getsockname(fd
[i
], (struct sockaddr
*)&addr
[i
], &size
))
1661 if(size
!= sizeof(struct sockaddr_in
))
1663 if(connect(fd
[!i
], (struct sockaddr
*)&addr
[i
], sizeof(struct sockaddr_in
)) == -1)
1667 for(i
= 0; i
< 2; i
++)
1669 port
= addr
[i
].sin_port
;
1670 got
= rb_write(F
[i
], &port
, sizeof(port
));
1671 if(got
!= sizeof(port
))
1679 max
= fd
[1] > fd
[0] ? fd
[1] : fd
[0];
1681 FD_SET(fd
[0], &rset
);
1682 FD_SET(fd
[1], &rset
);
1683 got
= select(max
+ 1, &rset
, NULL
, NULL
, &wait
);
1684 if(got
!= 2 || !FD_ISSET(fd
[0], &rset
) || !FD_ISSET(fd
[1], &rset
))
1691 for(i
= 0; i
< 2; i
++)
1694 int flag
= MSG_DONTWAIT
1698 got
= recvfrom(rb_get_fd(F
[i
]), (char *)&buf
, sizeof(buf
), flag
,
1699 (struct sockaddr
*)&readfrom
, &size
);
1702 if(got
!= sizeof(port
)
1703 || size
!= sizeof(struct sockaddr_in
)
1704 || buf
[0] != (unsigned short)addr
[!i
].sin_port
1705 || readfrom
.sin_family
!= addr
[!i
].sin_family
1706 || readfrom
.sin_addr
.s_addr
!= addr
[!i
].sin_addr
.s_addr
1707 || readfrom
.sin_port
!= addr
[!i
].sin_port
)
1716 #define ECONNABORTED WSAECONNABORTED
1721 errno
= ECONNABORTED
;
1723 if(errno
!= ECONNABORTED
)
1736 rb_inet_socketpair(int family
, int type
, int protocol
, int fd
[2])
1741 struct sockaddr_in listen_addr
;
1742 struct sockaddr_in connect_addr
;
1745 if(protocol
|| family
!= AF_INET
)
1747 errno
= EAFNOSUPPORT
;
1756 listener
= socket(AF_INET
, type
, 0);
1759 memset(&listen_addr
, 0, sizeof(listen_addr
));
1760 listen_addr
.sin_family
= AF_INET
;
1761 listen_addr
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
1762 listen_addr
.sin_port
= 0; /* kernel choses port. */
1763 if(bind(listener
, (struct sockaddr
*)&listen_addr
, sizeof(listen_addr
)) == -1)
1764 goto tidy_up_and_fail
;
1765 if(listen(listener
, 1) == -1)
1766 goto tidy_up_and_fail
;
1768 connector
= socket(AF_INET
, type
, 0);
1770 goto tidy_up_and_fail
;
1771 /* We want to find out the port number to connect to. */
1772 size
= sizeof(connect_addr
);
1773 if(getsockname(listener
, (struct sockaddr
*)&connect_addr
, &size
) == -1)
1774 goto tidy_up_and_fail
;
1775 if(size
!= sizeof(connect_addr
))
1776 goto abort_tidy_up_and_fail
;
1777 if(connect(connector
, (struct sockaddr
*)&connect_addr
, sizeof(connect_addr
)) == -1)
1778 goto tidy_up_and_fail
;
1780 size
= sizeof(listen_addr
);
1781 acceptor
= accept(listener
, (struct sockaddr
*)&listen_addr
, &size
);
1783 goto tidy_up_and_fail
;
1784 if(size
!= sizeof(listen_addr
))
1785 goto abort_tidy_up_and_fail
;
1787 /* Now check we are talking to ourself by matching port and host on the
1789 if(getsockname(connector
, (struct sockaddr
*)&connect_addr
, &size
) == -1)
1790 goto tidy_up_and_fail
;
1791 if(size
!= sizeof(connect_addr
)
1792 || listen_addr
.sin_family
!= connect_addr
.sin_family
1793 || listen_addr
.sin_addr
.s_addr
!= connect_addr
.sin_addr
.s_addr
1794 || listen_addr
.sin_port
!= connect_addr
.sin_port
)
1796 goto abort_tidy_up_and_fail
;
1802 abort_tidy_up_and_fail
:
1803 errno
= EINVAL
; /* I hope this is portable and appropriate. */
1807 int save_errno
= errno
;
1822 static void (*setselect_handler
) (rb_fde_t
*, unsigned int, PF
*, void *);
1823 static int (*select_handler
) (long);
1824 static int (*setup_fd_handler
) (rb_fde_t
*);
1825 static int (*io_sched_event
) (struct ev_entry
*, int);
1826 static void (*io_unsched_event
) (struct ev_entry
*);
1827 static int (*io_supports_event
) (void);
1828 static void (*io_init_event
) (void);
1829 static char iotype
[25];
1838 rb_unsupported_event(void)
1846 if(!rb_init_netio_kqueue())
1848 setselect_handler
= rb_setselect_kqueue
;
1849 select_handler
= rb_select_kqueue
;
1850 setup_fd_handler
= rb_setup_fd_kqueue
;
1851 io_sched_event
= rb_kqueue_sched_event
;
1852 io_unsched_event
= rb_kqueue_unsched_event
;
1853 io_init_event
= rb_kqueue_init_event
;
1854 io_supports_event
= rb_kqueue_supports_event
;
1855 rb_strlcpy(iotype
, "kqueue", sizeof(iotype
));
1864 if(!rb_init_netio_epoll())
1866 setselect_handler
= rb_setselect_epoll
;
1867 select_handler
= rb_select_epoll
;
1868 setup_fd_handler
= rb_setup_fd_epoll
;
1869 io_sched_event
= rb_epoll_sched_event
;
1870 io_unsched_event
= rb_epoll_unsched_event
;
1871 io_supports_event
= rb_epoll_supports_event
;
1872 io_init_event
= rb_epoll_init_event
;
1873 rb_strlcpy(iotype
, "epoll", sizeof(iotype
));
1882 if(!rb_init_netio_ports())
1884 setselect_handler
= rb_setselect_ports
;
1885 select_handler
= rb_select_ports
;
1886 setup_fd_handler
= rb_setup_fd_ports
;
1887 io_sched_event
= rb_ports_sched_event
;
1888 io_unsched_event
= rb_ports_unsched_event
;
1889 io_init_event
= rb_ports_init_event
;
1890 io_supports_event
= rb_ports_supports_event
;
1891 rb_strlcpy(iotype
, "ports", sizeof(iotype
));
1900 if(!rb_init_netio_devpoll())
1902 setselect_handler
= rb_setselect_devpoll
;
1903 select_handler
= rb_select_devpoll
;
1904 setup_fd_handler
= rb_setup_fd_devpoll
;
1905 io_sched_event
= NULL
;
1906 io_unsched_event
= NULL
;
1907 io_init_event
= NULL
;
1908 io_supports_event
= rb_unsupported_event
;
1909 rb_strlcpy(iotype
, "devpoll", sizeof(iotype
));
1918 if(!rb_init_netio_sigio())
1920 setselect_handler
= rb_setselect_sigio
;
1921 select_handler
= rb_select_sigio
;
1922 setup_fd_handler
= rb_setup_fd_sigio
;
1923 io_sched_event
= rb_sigio_sched_event
;
1924 io_unsched_event
= rb_sigio_unsched_event
;
1925 io_supports_event
= rb_sigio_supports_event
;
1926 io_init_event
= rb_sigio_init_event
;
1928 rb_strlcpy(iotype
, "sigio", sizeof(iotype
));
1937 if(!rb_init_netio_poll())
1939 setselect_handler
= rb_setselect_poll
;
1940 select_handler
= rb_select_poll
;
1941 setup_fd_handler
= rb_setup_fd_poll
;
1942 io_sched_event
= NULL
;
1943 io_unsched_event
= NULL
;
1944 io_init_event
= NULL
;
1945 io_supports_event
= rb_unsupported_event
;
1946 rb_strlcpy(iotype
, "poll", sizeof(iotype
));
1955 if(!rb_init_netio_win32())
1957 setselect_handler
= rb_setselect_win32
;
1958 select_handler
= rb_select_win32
;
1959 setup_fd_handler
= rb_setup_fd_win32
;
1960 io_sched_event
= NULL
;
1961 io_unsched_event
= NULL
;
1962 io_init_event
= NULL
;
1963 io_supports_event
= rb_unsupported_event
;
1964 rb_strlcpy(iotype
, "win32", sizeof(iotype
));
1973 if(!rb_init_netio_select())
1975 setselect_handler
= rb_setselect_select
;
1976 select_handler
= rb_select_select
;
1977 setup_fd_handler
= rb_setup_fd_select
;
1978 io_sched_event
= NULL
;
1979 io_unsched_event
= NULL
;
1980 io_init_event
= NULL
;
1981 io_supports_event
= rb_unsupported_event
;
1982 rb_strlcpy(iotype
, "select", sizeof(iotype
));
1990 rb_io_sched_event(struct ev_entry
*ev
, int when
)
1992 if(ev
== NULL
|| io_supports_event
== NULL
|| io_sched_event
== NULL
1993 || !io_supports_event())
1995 return io_sched_event(ev
, when
);
1999 rb_io_unsched_event(struct ev_entry
*ev
)
2001 if(ev
== NULL
|| io_supports_event
== NULL
|| io_unsched_event
== NULL
2002 || !io_supports_event())
2004 io_unsched_event(ev
);
2008 rb_io_supports_event(void)
2010 if(io_supports_event
== NULL
)
2012 return io_supports_event();
2016 rb_io_init_event(void)
2019 rb_event_io_register_all();
2025 char *ioenv
= getenv("LIBRB_USE_IOTYPE");
2026 rb_fd_table
= rb_malloc(RB_FD_HASH_SIZE
* sizeof(rb_dlink_list
));
2031 if(!strcmp("epoll", ioenv
))
2036 else if(!strcmp("kqueue", ioenv
))
2041 else if(!strcmp("ports", ioenv
))
2046 else if(!strcmp("poll", ioenv
))
2051 else if(!strcmp("devpoll", ioenv
))
2056 else if(!strcmp("sigio", ioenv
))
2061 else if(!strcmp("select", ioenv
))
2066 if(!strcmp("win32", ioenv
))
2091 rb_lib_log("rb_init_netio: Could not find any io handlers...giving up");
2097 rb_setselect(rb_fde_t
*F
, unsigned int type
, PF
* handler
, void *client_data
)
2099 setselect_handler(F
, type
, handler
, client_data
);
2103 rb_select(unsigned long timeout
)
2105 int ret
= select_handler(timeout
);
2111 rb_setup_fd(rb_fde_t
*F
)
2113 return setup_fd_handler(F
);
2119 rb_ignore_errno(int error
)
2126 #if defined EWOULDBLOCK
2129 #if defined(EAGAIN) && (EWOULDBLOCK != EAGAIN)
2149 #if defined(HAVE_SENDMSG) && !defined(WIN32)
2151 rb_recv_fd_buf(rb_fde_t
*F
, void *data
, size_t datasize
, rb_fde_t
**xF
, int nfds
)
2154 struct cmsghdr
*cmsg
;
2155 struct iovec iov
[1];
2157 uint8_t stype
= RB_FD_UNKNOWN
;
2159 int fd
, len
, x
, rfds
;
2161 int control_len
= CMSG_SPACE(sizeof(int) * nfds
);
2163 iov
[0].iov_base
= data
;
2164 iov
[0].iov_len
= datasize
;
2166 msg
.msg_name
= NULL
;
2167 msg
.msg_namelen
= 0;
2171 cmsg
= alloca(control_len
);
2172 msg
.msg_control
= cmsg
;
2173 msg
.msg_controllen
= control_len
;
2175 if((len
= recvmsg(rb_get_fd(F
), &msg
, 0)) <= 0)
2178 if(msg
.msg_controllen
> 0 && msg
.msg_control
!= NULL
2179 && (cmsg
= CMSG_FIRSTHDR(&msg
)) != NULL
)
2181 rfds
= ((unsigned char *)cmsg
+ cmsg
->cmsg_len
- CMSG_DATA(cmsg
)) / sizeof(int);
2183 for(x
= 0; x
< nfds
&& x
< rfds
; x
++)
2185 fd
= ((int *)CMSG_DATA(cmsg
))[x
];
2186 stype
= RB_FD_UNKNOWN
;
2187 desc
= "remote unknown";
2190 if(S_ISSOCK(st
.st_mode
))
2192 stype
= RB_FD_SOCKET
;
2193 desc
= "remote socket";
2195 else if(S_ISFIFO(st
.st_mode
))
2198 desc
= "remote pipe";
2200 else if(S_ISREG(st
.st_mode
))
2203 desc
= "remote file";
2206 xF
[x
] = rb_open(fd
, stype
, desc
);
2216 rb_send_fd_buf(rb_fde_t
*xF
, rb_fde_t
**F
, int count
, void *data
, size_t datasize
, pid_t pid
)
2220 struct cmsghdr
*cmsg
;
2221 struct iovec iov
[1];
2225 memset(&msg
, 0, sizeof(&msg
));
2228 iov
[0].iov_base
= &empty
;
2233 iov
[0].iov_base
= data
;
2234 iov
[0].iov_len
= datasize
;
2238 msg
.msg_name
= NULL
;
2239 msg
.msg_namelen
= 0;
2241 msg
.msg_control
= NULL
;
2242 msg
.msg_controllen
= 0;
2247 int len
= CMSG_SPACE(sizeof(int) * count
);
2250 msg
.msg_control
= buf
;
2251 msg
.msg_controllen
= len
;
2252 cmsg
= CMSG_FIRSTHDR(&msg
);
2253 cmsg
->cmsg_level
= SOL_SOCKET
;
2254 cmsg
->cmsg_type
= SCM_RIGHTS
;
2255 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int) * count
);
2257 for(i
= 0; i
< count
; i
++)
2259 ((int *)CMSG_DATA(cmsg
))[i
] = rb_get_fd(F
[i
]);
2261 msg
.msg_controllen
= cmsg
->cmsg_len
;
2263 n
= sendmsg(rb_get_fd(xF
), &msg
, MSG_NOSIGNAL
);
2269 rb_recv_fd_buf(rb_fde_t
*F
, void *data
, size_t datasize
, rb_fde_t
**xF
, int nfds
)
2276 rb_send_fd_buf(rb_fde_t
*xF
, rb_fde_t
**F
, int count
, void *data
, size_t datasize
, pid_t pid
)