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
25 #include <libratbox_config.h>
26 #include <ratbox_lib.h>
27 #include <commio-int.h>
28 #include <commio-ssl.h>
29 #include <event-int.h>
36 #define MSG_NOSIGNAL 0
49 rb_dlink_list
*rb_fd_table
;
50 static rb_bh
*fd_heap
;
52 static rb_dlink_list timeout_list
;
53 static rb_dlink_list closed_list
;
55 static struct ev_entry
*rb_timeout_ev
;
58 static const char *rb_err_str
[] = { "Comm OK", "Error during bind()",
59 "Error during DNS lookup", "connect timeout",
60 "Error during connect()",
64 /* Highest FD and number of open FDs .. */
65 static int number_fd
= 0;
66 int rb_maxconnections
= 0;
68 static PF rb_connect_timeout
;
69 static PF rb_connect_tryconnect
;
71 static void mangle_mapped_sockaddr(struct sockaddr
*in
);
74 #ifndef HAVE_SOCKETPAIR
75 static int rb_inet_socketpair(int d
, int type
, int protocol
, int sv
[2]);
76 static int rb_inet_socketpair_udp(rb_fde_t
**newF1
, rb_fde_t
**newF2
);
79 static inline rb_fde_t
*
82 rb_fde_t
*F
= rb_find_fd(fd
);
84 /* look up to see if we have it already */
88 F
= rb_bh_alloc(fd_heap
);
90 rb_dlinkAdd(F
, &F
->node
, &rb_fd_table
[rb_hash_fd(fd
)]);
95 remove_fd(rb_fde_t
*F
)
97 if(F
== NULL
|| !IsFDOpen(F
))
100 rb_dlinkMoveNode(&F
->node
, &rb_fd_table
[rb_hash_fd(F
->fd
)], &closed_list
);
107 rb_dlink_node
*ptr
, *next
;
108 RB_DLINK_FOREACH_SAFE(ptr
, next
, closed_list
.head
)
111 rb_dlinkDelete(ptr
, &closed_list
);
112 rb_bh_free(fd_heap
, F
);
116 /* 32bit solaris is kinda slow and stdio only supports fds < 256
117 * so we got to do this crap below.
118 * (BTW Fuck you Sun, I hate your guts and I hope you go bankrupt soon)
121 #if defined (__SVR4) && defined (__sun)
126 if(*fd
> 256 || *fd
< 0)
128 if((newfd
= fcntl(*fd
, F_DUPFD
, 256)) != -1)
136 #define rb_fd_hack(fd)
140 /* close_all_connections() can be used *before* the system come up! */
148 /* XXX someone tell me why we care about 4 fd's ? */
149 /* XXX btw, fd 3 is used for profiler ! */
150 for(i
= 3; i
< rb_maxconnections
; ++i
)
158 * get_sockerr - get the error value from the socket or the current errno
160 * Get the *real* error from the socket (well try to anyway..).
161 * This may only work when SO_DEBUG is enabled but its worth the
165 rb_get_sockerr(rb_fde_t
*F
)
169 rb_socklen_t len
= sizeof(err
);
171 if(!(F
->type
& RB_FD_SOCKET
))
179 && !getsockopt(rb_get_fd(F
), SOL_SOCKET
, SO_ERROR
, (char *)&err
, (rb_socklen_t
*) & len
))
190 * rb_getmaxconnect - return the max number of connections allowed
193 rb_getmaxconnect(void)
195 return (rb_maxconnections
);
199 * set_sock_buffers - set send and receive buffers for socket
201 * inputs - fd file descriptor
203 * output - returns true (1) if successful, false (0) otherwise
207 rb_set_buffers(rb_fde_t
*F
, int size
)
212 (F
->fd
, SOL_SOCKET
, SO_RCVBUF
, (char *)&size
, sizeof(size
))
213 || setsockopt(F
->fd
, SOL_SOCKET
, SO_SNDBUF
, (char *)&size
, sizeof(size
)))
219 * set_non_blocking - Set the client connection into non-blocking mode.
221 * inputs - fd to set into non blocking mode
222 * output - 1 if successful 0 if not
223 * side effects - use POSIX compliant non blocking and
227 rb_set_nb(rb_fde_t
*F
)
236 if((res
= rb_setup_fd(F
)))
240 res
= fcntl(fd
, F_GETFL
, 0);
241 if(-1 == res
|| fcntl(fd
, F_SETFL
, res
| nonb
) == -1)
246 if(ioctl(fd
, FIONBIO
, (char *)&nonb
) == -1)
254 * rb_settimeout() - set the socket timeout
256 * Set the timeout for the fd
259 rb_settimeout(rb_fde_t
*F
, time_t timeout
, PF
* callback
, void *cbdata
)
261 struct timeout_data
*td
;
266 lrb_assert(IsFDOpen(F
));
268 if(callback
== NULL
) /* user wants to remove */
272 rb_dlinkDelete(&td
->node
, &timeout_list
);
275 if(rb_dlink_list_length(&timeout_list
) == 0)
277 rb_event_delete(rb_timeout_ev
);
278 rb_timeout_ev
= NULL
;
283 if(F
->timeout
== NULL
)
284 td
= F
->timeout
= rb_malloc(sizeof(struct timeout_data
));
287 td
->timeout
= rb_current_time() + timeout
;
288 td
->timeout_handler
= callback
;
289 td
->timeout_data
= cbdata
;
290 rb_dlinkAdd(td
, &td
->node
, &timeout_list
);
291 if(rb_timeout_ev
== NULL
)
293 rb_timeout_ev
= rb_event_add("rb_checktimeouts", rb_checktimeouts
, NULL
, 5);
298 * rb_checktimeouts() - check the socket timeouts
300 * All this routine does is call the given callback/cbdata, without closing
301 * down the file descriptor. When close handlers have been implemented,
305 rb_checktimeouts(void *notused
)
307 rb_dlink_node
*ptr
, *next
;
308 struct timeout_data
*td
;
313 RB_DLINK_FOREACH_SAFE(ptr
, next
, timeout_list
.head
)
317 if(F
== NULL
|| !IsFDOpen(F
))
320 if(td
->timeout
< rb_current_time())
322 hdl
= td
->timeout_handler
;
323 data
= td
->timeout_data
;
324 rb_dlinkDelete(&td
->node
, &timeout_list
);
333 rb_accept_tryaccept(rb_fde_t
*F
, void *data
)
335 struct rb_sockaddr_storage st
;
337 rb_socklen_t addrlen
= sizeof(st
);
342 new_fd
= accept(F
->fd
, (struct sockaddr
*)&st
, &addrlen
);
346 rb_setselect(F
, RB_SELECT_ACCEPT
, rb_accept_tryaccept
, NULL
);
352 new_F
= rb_open(new_fd
, RB_FD_SOCKET
, "Incoming Connection");
357 ("rb_accept: new_F == NULL on incoming connection. Closing new_fd == %d\n",
363 if(rb_unlikely(!rb_set_nb(new_F
)))
366 rb_lib_log("rb_accept: Couldn't set FD %d non blocking!", new_F
->fd
);
371 mangle_mapped_sockaddr((struct sockaddr
*)&st
);
374 if(F
->accept
->precb
!= NULL
)
376 if(!F
->accept
->precb(new_F
, (struct sockaddr
*)&st
, addrlen
, F
->accept
->data
)) /* pre-callback decided to drop it */
380 if(F
->type
& RB_FD_SSL
)
382 rb_ssl_accept_setup(F
, new_F
, (struct sockaddr
*)&st
, addrlen
);
385 #endif /* HAVE_SSL */
387 F
->accept
->callback(new_F
, RB_OK
, (struct sockaddr
*)&st
, addrlen
,
394 /* try to accept a TCP connection */
396 rb_accept_tcp(rb_fde_t
*F
, ACPRE
* precb
, ACCB
* callback
, void *data
)
400 lrb_assert(callback
);
402 F
->accept
= rb_malloc(sizeof(struct acceptdata
));
403 F
->accept
->callback
= callback
;
404 F
->accept
->data
= data
;
405 F
->accept
->precb
= precb
;
406 rb_accept_tryaccept(F
, NULL
);
410 * void rb_connect_tcp(int fd, struct sockaddr *dest,
411 * struct sockaddr *clocal, int socklen,
412 * CNCB *callback, void *data, int timeout)
413 * Input: An fd to connect with, a host and port to connect to,
414 * a local sockaddr to connect from + length(or NULL to use the
415 * default), a callback, the data to pass into the callback, the
418 * Side-effects: A non-blocking connection to the host is started, and
419 * if necessary, set up for selection. The callback given
420 * may be called now, or it may be called later.
423 rb_connect_tcp(rb_fde_t
*F
, struct sockaddr
*dest
,
424 struct sockaddr
*clocal
, int socklen
, CNCB
* callback
, void *data
, int timeout
)
429 lrb_assert(callback
);
430 F
->connect
= rb_malloc(sizeof(struct conndata
));
431 F
->connect
->callback
= callback
;
432 F
->connect
->data
= data
;
434 memcpy(&F
->connect
->hostaddr
, dest
, sizeof(F
->connect
->hostaddr
));
436 /* Note that we're using a passed sockaddr here. This is because
437 * generally you'll be bind()ing to a sockaddr grabbed from
438 * getsockname(), so this makes things easier.
439 * XXX If NULL is passed as local, we should later on bind() to the
440 * virtual host IP, for completeness.
443 if((clocal
!= NULL
) && (bind(F
->fd
, clocal
, socklen
) < 0))
445 /* Failure, call the callback with RB_ERR_BIND */
446 rb_connect_callback(F
, RB_ERR_BIND
);
451 /* We have a valid IP, so we just call tryconnect */
452 /* Make sure we actually set the timeout here .. */
453 rb_settimeout(F
, timeout
, rb_connect_timeout
, NULL
);
454 rb_connect_tryconnect(F
, NULL
);
459 * rb_connect_callback() - call the callback, and continue with life
462 rb_connect_callback(rb_fde_t
*F
, int status
)
466 int errtmp
= errno
; /* save errno as rb_settimeout clobbers it sometimes */
468 /* This check is gross..but probably necessary */
469 if(F
== NULL
|| F
->connect
== NULL
|| F
->connect
->callback
== NULL
)
471 /* Clear the connect flag + handler */
472 hdl
= F
->connect
->callback
;
473 data
= F
->connect
->data
;
474 F
->connect
->callback
= NULL
;
477 /* Clear the timeout handler */
478 rb_settimeout(F
, 0, NULL
, NULL
);
480 /* Call the handler */
481 hdl(F
, status
, data
);
486 * rb_connect_timeout() - this gets called when the socket connection
487 * times out. This *only* can be called once connect() is initially
491 rb_connect_timeout(rb_fde_t
*F
, void *notused
)
494 rb_connect_callback(F
, RB_ERR_TIMEOUT
);
497 /* static void rb_connect_tryconnect(int fd, void *notused)
498 * Input: The fd, the handler data(unused).
500 * Side-effects: Try and connect with pending connect data for the FD. If
501 * we succeed or get a fatal error, call the callback.
502 * Otherwise, it is still blocking or something, so register
503 * to select for a write event on this FD.
506 rb_connect_tryconnect(rb_fde_t
*F
, void *notused
)
510 if(F
== NULL
|| F
->connect
== NULL
|| F
->connect
->callback
== NULL
)
512 /* Try the connect() */
513 retval
= connect(F
->fd
,
514 (struct sockaddr
*)&F
->connect
->hostaddr
,
515 GET_SS_LEN(&F
->connect
->hostaddr
));
520 * If we get EISCONN, then we've already connect()ed the socket,
521 * which is a good thing.
526 rb_connect_callback(F
, RB_OK
);
527 else if(rb_ignore_errno(errno
))
528 /* Ignore error? Reschedule */
529 rb_setselect(F
, RB_SELECT_CONNECT
, rb_connect_tryconnect
, NULL
);
531 /* Error? Fail with RB_ERR_CONNECT */
532 rb_connect_callback(F
, RB_ERR_CONNECT
);
535 /* If we get here, we've suceeded, so call with RB_OK */
536 rb_connect_callback(F
, RB_OK
);
541 rb_connect_sockaddr(rb_fde_t
*F
, struct sockaddr
*addr
, int len
)
546 memcpy(addr
, &F
->connect
->hostaddr
, len
);
551 * rb_error_str() - return an error string for the given error condition
556 if(error
< 0 || error
>= RB_ERR_MAX
)
557 return "Invalid error number!";
558 return rb_err_str
[error
];
563 rb_socketpair(int family
, int sock_type
, int proto
, rb_fde_t
**F1
, rb_fde_t
**F2
, const char *note
)
566 if(number_fd
>= rb_maxconnections
)
572 #ifdef HAVE_SOCKETPAIR
573 if(socketpair(family
, sock_type
, proto
, nfd
))
575 if(sock_type
== SOCK_DGRAM
)
577 return rb_inet_socketpair_udp(F1
, F2
);
580 if(rb_inet_socketpair(AF_INET
, sock_type
, proto
, nfd
))
587 *F1
= rb_open(nfd
[0], RB_FD_SOCKET
, note
);
588 *F2
= rb_open(nfd
[1], RB_FD_SOCKET
, note
);
603 /* Set the socket non-blocking, and other wonderful bits */
604 if(rb_unlikely(!rb_set_nb(*F1
)))
606 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd
[0], strerror(errno
));
612 if(rb_unlikely(!rb_set_nb(*F2
)))
614 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd
[1], strerror(errno
));
625 rb_pipe(rb_fde_t
**F1
, rb_fde_t
**F2
, const char *desc
)
629 if(number_fd
>= rb_maxconnections
)
638 *F1
= rb_open(fd
[0], RB_FD_PIPE
, desc
);
639 *F2
= rb_open(fd
[1], RB_FD_PIPE
, desc
);
641 if(rb_unlikely(!rb_set_nb(*F1
)))
643 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
[0], strerror(errno
));
649 if(rb_unlikely(!rb_set_nb(*F2
)))
651 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
[1], strerror(errno
));
660 /* Its not a pipe..but its selectable. I'll take dirty hacks
663 return rb_socketpair(AF_INET
, SOCK_STREAM
, 0, F1
, F2
, desc
);
668 * rb_socket() - open a socket
670 * This is a highly highly cut down version of squid's rb_open() which
671 * for the most part emulates socket(), *EXCEPT* it fails if we're about
672 * to run out of file descriptors.
675 rb_socket(int family
, int sock_type
, int proto
, const char *note
)
679 /* First, make sure we aren't going to run out of file descriptors */
680 if(rb_unlikely(number_fd
>= rb_maxconnections
))
687 * Next, we try to open the socket. We *should* drop the reserved FD
688 * limit if/when we get an error, but we can deal with that later.
691 fd
= socket(family
, sock_type
, proto
);
693 if(rb_unlikely(fd
< 0))
694 return NULL
; /* errno will be passed through, yay.. */
696 #if defined(RB_IPV6) && defined(IPV6_V6ONLY)
698 * Make sure we can take both IPv4 and IPv6 connections
699 * on an AF_INET6 socket
701 if(family
== AF_INET6
)
704 if(setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &off
, sizeof(off
)) == -1)
706 rb_lib_log("rb_socket: Could not set IPV6_V6ONLY option to 1 on FD %d: %s",
707 fd
, strerror(errno
));
714 F
= rb_open(fd
, RB_FD_SOCKET
, note
);
717 rb_lib_log("rb_socket: rb_open returns NULL on FD %d: %s, closing fd", fd
,
722 /* Set the socket non-blocking, and other wonderful bits */
723 if(rb_unlikely(!rb_set_nb(F
)))
725 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
, strerror(errno
));
734 * If a sockaddr_storage is AF_INET6 but is a mapped IPv4
735 * socket manged the sockaddr.
739 mangle_mapped_sockaddr(struct sockaddr
*in
)
741 struct sockaddr_in6
*in6
= (struct sockaddr_in6
*)in
;
743 if(in
->sa_family
== AF_INET
)
746 if(in
->sa_family
== AF_INET6
&& IN6_IS_ADDR_V4MAPPED(&in6
->sin6_addr
))
748 struct sockaddr_in in4
;
749 memset(&in4
, 0, sizeof(struct sockaddr_in
));
750 in4
.sin_family
= AF_INET
;
751 in4
.sin_port
= in6
->sin6_port
;
752 in4
.sin_addr
.s_addr
= ((uint32_t *)&in6
->sin6_addr
)[3];
753 memcpy(in
, &in4
, sizeof(struct sockaddr_in
));
760 * rb_listen() - listen on a port
763 rb_listen(rb_fde_t
*F
, int backlog
)
765 F
->type
= RB_FD_SOCKET
| RB_FD_LISTEN
;
766 /* Currently just a simple wrapper for the sake of being complete */
767 return listen(F
->fd
, backlog
);
771 rb_fdlist_init(int closeall
, int maxfds
, size_t heapsize
)
773 static int initialized
= 0;
777 int vers
= MAKEWORD(2, 0);
779 err
= WSAStartup(vers
, &wsaData
);
782 rb_lib_die("WSAStartup failed");
788 rb_maxconnections
= maxfds
;
791 /* Since we're doing this once .. */
794 fd_heap
= rb_bh_create(sizeof(rb_fde_t
), heapsize
, "librb_fd_heap");
799 /* Called to open a given filedescriptor */
801 rb_open(int fd
, uint8_t type
, const char *desc
)
808 lrb_assert(!IsFDOpen(F
));
809 if(rb_unlikely(IsFDOpen(F
)))
812 if(F
!= NULL
&& F
->desc
!= NULL
)
816 rb_lib_log("Trying to rb_open an already open FD: %d desc: %s", fd
, fdesc
);
824 F
->desc
= rb_strndup(desc
, FD_DESC_SZ
);
830 /* Called to close a given filedescriptor */
832 rb_close(rb_fde_t
*F
)
841 lrb_assert(IsFDOpen(F
));
843 lrb_assert(!(type
& RB_FD_FILE
));
844 if(rb_unlikely(type
& RB_FD_FILE
))
846 lrb_assert(F
->read_handler
== NULL
);
847 lrb_assert(F
->write_handler
== NULL
);
849 rb_setselect(F
, RB_SELECT_WRITE
| RB_SELECT_READ
, NULL
, NULL
);
850 rb_settimeout(F
, 0, NULL
, NULL
);
859 #endif /* HAVE_SSL */
869 if(type
& (RB_FD_SOCKET
| RB_FD_PIPE
))
881 * rb_dump_fd() - dump the list of active filedescriptors
884 rb_dump_fd(DUMPCB
* cb
, void *data
)
886 static const char *empty
= "";
888 rb_dlink_list
*bucket
;
892 for(i
= 0; i
< RB_FD_HASH_SIZE
; i
++)
894 bucket
= &rb_fd_table
[i
];
896 if(rb_dlink_list_length(bucket
) <= 0)
899 RB_DLINK_FOREACH(ptr
, bucket
->head
)
902 if(F
== NULL
|| !IsFDOpen(F
))
905 cb(F
->fd
, F
->desc
? F
->desc
: empty
, data
);
911 * rb_note() - set the fd note
913 * Note: must be careful not to overflow rb_fd_table[fd].desc when
917 rb_note(rb_fde_t
*F
, const char *string
)
923 F
->desc
= rb_strndup(string
, FD_DESC_SZ
);
927 rb_set_type(rb_fde_t
*F
, uint8_t type
)
929 /* if the caller is calling this, lets assume they have a clue */
935 rb_get_type(rb_fde_t
*F
)
941 rb_fd_ssl(rb_fde_t
*F
)
945 if(F
->type
& RB_FD_SSL
)
951 rb_get_fd(rb_fde_t
*F
)
961 return rb_find_fd(fd
);
965 rb_read(rb_fde_t
*F
, void *buf
, int count
)
971 /* This needs to be *before* RB_FD_SOCKET otherwise you'll process
972 * an SSL socket as a regular socket
975 if(F
->type
& RB_FD_SSL
)
977 return rb_ssl_read(F
, buf
, count
);
980 if(F
->type
& RB_FD_SOCKET
)
982 ret
= recv(F
->fd
, buf
, count
, 0);
992 return read(F
->fd
, buf
, count
);
997 rb_write(rb_fde_t
*F
, const void *buf
, int count
)
1004 if(F
->type
& RB_FD_SSL
)
1006 return rb_ssl_write(F
, buf
, count
);
1009 if(F
->type
& RB_FD_SOCKET
)
1011 ret
= send(F
->fd
, buf
, count
, MSG_NOSIGNAL
);
1019 return write(F
->fd
, buf
, count
);
1022 #if defined(HAVE_SSL) || defined(WIN32) || !defined(HAVE_WRITEV)
1024 rb_fake_writev(rb_fde_t
*F
, const struct rb_iovec
*vp
, size_t vpcount
)
1028 while(vpcount
-- > 0)
1030 ssize_t written
= rb_write(F
, vp
->iov_base
, vp
->iov_len
);
1046 #if defined(WIN32) || !defined(HAVE_WRITEV)
1048 rb_writev(rb_fde_t
*F
, struct rb_iovec
* vecount
, int count
)
1050 return rb_fake_writev(F
, vecount
, count
);
1055 rb_writev(rb_fde_t
*F
, struct rb_iovec
* vector
, int count
)
1063 if(F
->type
& RB_FD_SSL
)
1065 return rb_fake_writev(F
, vector
, count
);
1067 #endif /* HAVE_SSL */
1069 if(F
->type
& RB_FD_SOCKET
)
1072 memset(&msg
, 0, sizeof(msg
));
1073 msg
.msg_iov
= (struct iovec
*)vector
;
1074 msg
.msg_iovlen
= count
;
1075 return sendmsg(F
->fd
, &msg
, MSG_NOSIGNAL
);
1077 #endif /* HAVE_SENDMSG */
1078 return writev(F
->fd
, (struct iovec
*)vector
, count
);
1085 * From: Thomas Helvey <tomh@inxpress.net>
1087 static const char *IpQuadTab
[] = {
1088 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
1089 "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
1090 "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
1091 "30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
1092 "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
1093 "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
1094 "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
1095 "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
1096 "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
1097 "90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
1098 "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
1099 "110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
1100 "120", "121", "122", "123", "124", "125", "126", "127", "128", "129",
1101 "130", "131", "132", "133", "134", "135", "136", "137", "138", "139",
1102 "140", "141", "142", "143", "144", "145", "146", "147", "148", "149",
1103 "150", "151", "152", "153", "154", "155", "156", "157", "158", "159",
1104 "160", "161", "162", "163", "164", "165", "166", "167", "168", "169",
1105 "170", "171", "172", "173", "174", "175", "176", "177", "178", "179",
1106 "180", "181", "182", "183", "184", "185", "186", "187", "188", "189",
1107 "190", "191", "192", "193", "194", "195", "196", "197", "198", "199",
1108 "200", "201", "202", "203", "204", "205", "206", "207", "208", "209",
1109 "210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
1110 "220", "221", "222", "223", "224", "225", "226", "227", "228", "229",
1111 "230", "231", "232", "233", "234", "235", "236", "237", "238", "239",
1112 "240", "241", "242", "243", "244", "245", "246", "247", "248", "249",
1113 "250", "251", "252", "253", "254", "255"
1117 * inetntoa - in_addr to string
1118 * changed name to remove collision possibility and
1119 * so behaviour is guaranteed to take a pointer arg.
1121 * inet_ntoa -- returned the dotted notation of a given
1124 * inet_ntoa -- its broken on some Ultrix/Dynix too. -avalon
1128 inetntoa(const char *in
)
1130 static char buf
[16];
1132 const unsigned char *a
= (const unsigned char *)in
;
1135 n
= IpQuadTab
[*a
++];
1139 n
= IpQuadTab
[*a
++];
1143 n
= IpQuadTab
[*a
++];
1156 * Copyright (c) 1996-1999 by Internet Software Consortium.
1158 * Permission to use, copy, modify, and distribute this software for any
1159 * purpose with or without fee is hereby granted, provided that the above
1160 * copyright notice and this permission notice appear in all copies.
1162 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
1163 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
1164 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
1165 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
1166 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
1167 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
1168 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
1172 #define SPRINTF(x) ((size_t)rb_sprintf x)
1175 * WARNING: Don't even consider trying to compile this on a system where
1176 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
1179 static const char *inet_ntop4(const unsigned char *src
, char *dst
, unsigned int size
);
1181 static const char *inet_ntop6(const unsigned char *src
, char *dst
, unsigned int size
);
1185 * inet_ntop4(src, dst, size)
1186 * format an IPv4 address
1188 * `dst' (as a const)
1190 * (1) uses no statics
1191 * (2) takes a unsigned char* not an in_addr as input
1196 inet_ntop4(const unsigned char *src
, char *dst
, unsigned int size
)
1200 return strcpy(dst
, inetntoa((const char *)src
));
1204 * inet_ntop6(src, dst, size)
1205 * convert IPv6 binary address into presentation (printable) format
1211 inet_ntop6(const unsigned char *src
, char *dst
, unsigned int size
)
1214 * Note that int32_t and int16_t need only be "at least" large enough
1215 * to contain a value of the specified size. On some systems, like
1216 * Crays, there is no such thing as an integer variable with 16 bits.
1217 * Keep this in mind if you think this function should have been coded
1218 * to use pointer overlays. All the world's not a VAX.
1220 char tmp
[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp
;
1226 unsigned int words
[IN6ADDRSZ
/ INT16SZ
];
1231 * Copy the input (bytewise) array into a wordwise array.
1232 * Find the longest run of 0x00's in src[] for :: shorthanding.
1234 memset(words
, '\0', sizeof words
);
1235 for(i
= 0; i
< IN6ADDRSZ
; i
+= 2)
1236 words
[i
/ 2] = (src
[i
] << 8) | src
[i
+ 1];
1241 for(i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++)
1246 cur
.base
= i
, cur
.len
= 1;
1254 if(best
.base
== -1 || cur
.len
> best
.len
)
1262 if(best
.base
== -1 || cur
.len
> best
.len
)
1265 if(best
.base
!= -1 && best
.len
< 2)
1269 * Format the result.
1272 for(i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++)
1274 /* Are we inside the best run of 0x00's? */
1275 if(best
.base
!= -1 && i
>= best
.base
&& i
< (best
.base
+ best
.len
))
1285 /* Are we following an initial run of 0x00s or any real hex? */
1288 /* Is this address an encapsulated IPv4? */
1289 if(i
== 6 && best
.base
== 0 &&
1290 (best
.len
== 6 || (best
.len
== 5 && words
[5] == 0xffff)))
1292 if(!inet_ntop4(src
+ 12, tp
, sizeof tmp
- (tp
- tmp
)))
1297 tp
+= SPRINTF((tp
, "%x", words
[i
]));
1299 /* Was it a trailing run of 0x00's? */
1300 if(best
.base
!= -1 && (best
.base
+ best
.len
) == (IN6ADDRSZ
/ INT16SZ
))
1305 * Check for overflow, copy, and we're done.
1308 if((unsigned int)(tp
- tmp
) > size
)
1312 return strcpy(dst
, tmp
);
1317 rb_inet_pton_sock(const char *src
, struct sockaddr
*dst
)
1319 if(rb_inet_pton(AF_INET
, src
, &((struct sockaddr_in
*)dst
)->sin_addr
))
1321 ((struct sockaddr_in
*)dst
)->sin_port
= 0;
1322 ((struct sockaddr_in
*)dst
)->sin_family
= AF_INET
;
1323 SET_SS_LEN(dst
, sizeof(struct sockaddr_in
));
1327 else if(rb_inet_pton(AF_INET6
, src
, &((struct sockaddr_in6
*)dst
)->sin6_addr
))
1329 ((struct sockaddr_in6
*)dst
)->sin6_port
= 0;
1330 ((struct sockaddr_in6
*)dst
)->sin6_family
= AF_INET6
;
1331 SET_SS_LEN(dst
, sizeof(struct sockaddr_in6
));
1339 rb_inet_ntop_sock(struct sockaddr
*src
, char *dst
, unsigned int size
)
1341 switch (src
->sa_family
)
1344 return (rb_inet_ntop(AF_INET
, &((struct sockaddr_in
*)src
)->sin_addr
, dst
, size
));
1348 return (rb_inet_ntop
1349 (AF_INET6
, &((struct sockaddr_in6
*)src
)->sin6_addr
, dst
, size
));
1359 * rb_inet_ntop(af, src, dst, size)
1360 * convert a network format address to presentation format.
1362 * pointer to presentation format address (`dst'), or NULL (see errno).
1367 rb_inet_ntop(int af
, const void *src
, char *dst
, unsigned int size
)
1372 return (inet_ntop4(src
, dst
, size
));
1375 if(IN6_IS_ADDR_V4MAPPED((const struct in6_addr
*)src
) ||
1376 IN6_IS_ADDR_V4COMPAT((const struct in6_addr
*)src
))
1378 ((const unsigned char *)&((const struct in6_addr
*)src
)->
1379 s6_addr
[12], dst
, size
));
1381 return (inet_ntop6(src
, dst
, size
));
1392 * WARNING: Don't even consider trying to compile this on a system where
1393 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
1397 * rb_inet_pton(af, src, dst)
1398 * convert from presentation format (which usually means ASCII printable)
1399 * to network format (which is usually some kind of binary format).
1401 * 1 if the address was valid for the specified address family
1402 * 0 if the address wasn't valid (`dst' is untouched in this case)
1403 * -1 if some other error occurred (`dst' is untouched in this case, too)
1409 * inet_pton4(src, dst)
1410 * like inet_aton() but without all the hexadecimal and shorthand.
1412 * 1 if `src' is a valid dotted quad, else 0.
1414 * does not touch `dst' unless it's returning 1.
1419 inet_pton4(const char *src
, unsigned char *dst
)
1421 int saw_digit
, octets
, ch
;
1422 unsigned char tmp
[INADDRSZ
], *tp
;
1427 while((ch
= *src
++) != '\0')
1430 if(ch
>= '0' && ch
<= '9')
1432 unsigned int new = *tp
* 10 + (ch
- '0');
1444 else if(ch
== '.' && saw_digit
)
1456 memcpy(dst
, tmp
, INADDRSZ
);
1462 * inet_pton6(src, dst)
1463 * convert presentation level address to network order binary form.
1465 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
1467 * (1) does not touch `dst' unless it's returning 1.
1468 * (2) :: in a full address is silently ignored.
1470 * inspired by Mark Andrews.
1476 inet_pton6(const char *src
, unsigned char *dst
)
1478 static const char xdigits
[] = "0123456789abcdef";
1479 unsigned char tmp
[IN6ADDRSZ
], *tp
, *endp
, *colonp
;
1484 tp
= memset(tmp
, '\0', IN6ADDRSZ
);
1485 endp
= tp
+ IN6ADDRSZ
;
1487 /* Leading :: requires some special handling. */
1494 while((ch
= tolower(*src
++)) != '\0')
1498 pch
= strchr(xdigits
, ch
);
1502 val
|= (pch
- xdigits
);
1518 else if(*src
== '\0')
1522 if(tp
+ INT16SZ
> endp
)
1524 *tp
++ = (unsigned char)(val
>> 8) & 0xff;
1525 *tp
++ = (unsigned char)val
& 0xff;
1530 if(*src
!= '\0' && ch
== '.')
1532 if(((tp
+ INADDRSZ
) <= endp
) && inet_pton4(curtok
, tp
) > 0)
1536 break; /* '\0' was seen by inet_pton4(). */
1545 if(tp
+ INT16SZ
> endp
)
1547 *tp
++ = (unsigned char)(val
>> 8) & 0xff;
1548 *tp
++ = (unsigned char)val
& 0xff;
1553 * Since some memmove()'s erroneously fail to handle
1554 * overlapping regions, we'll do the shift by hand.
1556 const int n
= tp
- colonp
;
1561 for(i
= 1; i
<= n
; i
++)
1563 endp
[-i
] = colonp
[n
- i
];
1570 memcpy(dst
, tmp
, IN6ADDRSZ
);
1575 rb_inet_pton(int af
, const char *src
, void *dst
)
1580 return (inet_pton4(src
, dst
));
1583 /* Somebody might have passed as an IPv4 address this is sick but it works */
1584 if(inet_pton4(src
, dst
))
1586 char tmp
[HOSTIPLEN
];
1587 rb_sprintf(tmp
, "::ffff:%s", src
);
1588 return (inet_pton6(tmp
, dst
));
1591 return (inet_pton6(src
, dst
));
1600 #ifndef HAVE_SOCKETPAIR
1602 /* mostly based on perl's emulation of socketpair udp */
1604 rb_inet_socketpair_udp(rb_fde_t
**newF1
, rb_fde_t
**newF2
)
1606 struct sockaddr_in addr
[2];
1607 rb_socklen_t size
= sizeof(struct sockaddr_in
);
1611 unsigned short port
;
1612 struct timeval wait
= { 0, 100000 };
1615 struct sockaddr_in readfrom
;
1616 unsigned short buf
[2];
1619 memset(&addr
, 0, sizeof(addr
));
1621 for(i
= 0; i
< 2; i
++)
1623 F
[i
] = rb_socket(AF_INET
, SOCK_DGRAM
, 0, "udp socketpair");
1626 addr
[i
].sin_family
= AF_INET
;
1627 addr
[i
].sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
1628 addr
[i
].sin_port
= 0;
1629 if(bind(rb_get_fd(F
[i
]), (struct sockaddr
*)&addr
[i
], sizeof(struct sockaddr_in
)))
1631 fd
[i
] = rb_get_fd(F
[i
]);
1634 for(i
= 0; i
< 2; i
++)
1636 if(getsockname(fd
[i
], (struct sockaddr
*)&addr
[i
], &size
))
1638 if(size
!= sizeof(struct sockaddr_in
))
1640 if(connect(fd
[!i
], (struct sockaddr
*)&addr
[i
], sizeof(struct sockaddr_in
)) == -1)
1644 for(i
= 0; i
< 2; i
++)
1646 port
= addr
[i
].sin_port
;
1647 got
= rb_write(F
[i
], &port
, sizeof(port
));
1648 if(got
!= sizeof(port
))
1656 max
= fd
[1] > fd
[0] ? fd
[1] : fd
[0];
1658 FD_SET(fd
[0], &rset
);
1659 FD_SET(fd
[1], &rset
);
1660 got
= select(max
+ 1, &rset
, NULL
, NULL
, &wait
);
1661 if(got
!= 2 || !FD_ISSET(fd
[0], &rset
) || !FD_ISSET(fd
[1], &rset
))
1668 for(i
= 0; i
< 2; i
++)
1671 int flag
= MSG_DONTWAIT
1675 got
= recvfrom(rb_get_fd(F
[i
]), (char *)&buf
, sizeof(buf
), flag
,
1676 (struct sockaddr
*)&readfrom
, &size
);
1679 if(got
!= sizeof(port
)
1680 || size
!= sizeof(struct sockaddr_in
)
1681 || buf
[0] != (unsigned short)addr
[!i
].sin_port
1682 || readfrom
.sin_family
!= addr
[!i
].sin_family
1683 || readfrom
.sin_addr
.s_addr
!= addr
[!i
].sin_addr
.s_addr
1684 || readfrom
.sin_port
!= addr
[!i
].sin_port
)
1693 #define ECONNABORTED WSAECONNABORTED
1698 errno
= ECONNABORTED
;
1700 if(errno
!= ECONNABORTED
)
1713 rb_inet_socketpair(int family
, int type
, int protocol
, int fd
[2])
1718 struct sockaddr_in listen_addr
;
1719 struct sockaddr_in connect_addr
;
1722 if(protocol
|| family
!= AF_INET
)
1724 errno
= EAFNOSUPPORT
;
1733 listener
= socket(AF_INET
, type
, 0);
1736 memset(&listen_addr
, 0, sizeof(listen_addr
));
1737 listen_addr
.sin_family
= AF_INET
;
1738 listen_addr
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
1739 listen_addr
.sin_port
= 0; /* kernel choses port. */
1740 if(bind(listener
, (struct sockaddr
*)&listen_addr
, sizeof(listen_addr
)) == -1)
1741 goto tidy_up_and_fail
;
1742 if(listen(listener
, 1) == -1)
1743 goto tidy_up_and_fail
;
1745 connector
= socket(AF_INET
, type
, 0);
1747 goto tidy_up_and_fail
;
1748 /* We want to find out the port number to connect to. */
1749 size
= sizeof(connect_addr
);
1750 if(getsockname(listener
, (struct sockaddr
*)&connect_addr
, &size
) == -1)
1751 goto tidy_up_and_fail
;
1752 if(size
!= sizeof(connect_addr
))
1753 goto abort_tidy_up_and_fail
;
1754 if(connect(connector
, (struct sockaddr
*)&connect_addr
, sizeof(connect_addr
)) == -1)
1755 goto tidy_up_and_fail
;
1757 size
= sizeof(listen_addr
);
1758 acceptor
= accept(listener
, (struct sockaddr
*)&listen_addr
, &size
);
1760 goto tidy_up_and_fail
;
1761 if(size
!= sizeof(listen_addr
))
1762 goto abort_tidy_up_and_fail
;
1764 /* Now check we are talking to ourself by matching port and host on the
1766 if(getsockname(connector
, (struct sockaddr
*)&connect_addr
, &size
) == -1)
1767 goto tidy_up_and_fail
;
1768 if(size
!= sizeof(connect_addr
)
1769 || listen_addr
.sin_family
!= connect_addr
.sin_family
1770 || listen_addr
.sin_addr
.s_addr
!= connect_addr
.sin_addr
.s_addr
1771 || listen_addr
.sin_port
!= connect_addr
.sin_port
)
1773 goto abort_tidy_up_and_fail
;
1779 abort_tidy_up_and_fail
:
1780 errno
= EINVAL
; /* I hope this is portable and appropriate. */
1784 int save_errno
= errno
;
1799 static void (*setselect_handler
) (rb_fde_t
*, unsigned int, PF
*, void *);
1800 static int (*select_handler
) (long);
1801 static int (*setup_fd_handler
) (rb_fde_t
*);
1802 static int (*io_sched_event
) (struct ev_entry
*, int);
1803 static void (*io_unsched_event
) (struct ev_entry
*);
1804 static int (*io_supports_event
) (void);
1805 static void (*io_init_event
) (void);
1806 static char iotype
[25];
1815 rb_unsupported_event(void)
1823 if(!rb_init_netio_kqueue())
1825 setselect_handler
= rb_setselect_kqueue
;
1826 select_handler
= rb_select_kqueue
;
1827 setup_fd_handler
= rb_setup_fd_kqueue
;
1828 io_sched_event
= rb_kqueue_sched_event
;
1829 io_unsched_event
= rb_kqueue_unsched_event
;
1830 io_init_event
= rb_kqueue_init_event
;
1831 io_supports_event
= rb_kqueue_supports_event
;
1832 rb_strlcpy(iotype
, "kqueue", sizeof(iotype
));
1841 if(!rb_init_netio_epoll())
1843 setselect_handler
= rb_setselect_epoll
;
1844 select_handler
= rb_select_epoll
;
1845 setup_fd_handler
= rb_setup_fd_epoll
;
1846 io_sched_event
= rb_epoll_sched_event
;
1847 io_unsched_event
= rb_epoll_unsched_event
;
1848 io_supports_event
= rb_epoll_supports_event
;
1849 io_init_event
= rb_epoll_init_event
;
1850 rb_strlcpy(iotype
, "epoll", sizeof(iotype
));
1859 if(!rb_init_netio_ports())
1861 setselect_handler
= rb_setselect_ports
;
1862 select_handler
= rb_select_ports
;
1863 setup_fd_handler
= rb_setup_fd_ports
;
1864 io_sched_event
= rb_ports_sched_event
;
1865 io_unsched_event
= rb_ports_unsched_event
;
1866 io_init_event
= rb_ports_init_event
;
1867 io_supports_event
= rb_ports_supports_event
;
1868 rb_strlcpy(iotype
, "ports", sizeof(iotype
));
1877 if(!rb_init_netio_devpoll())
1879 setselect_handler
= rb_setselect_devpoll
;
1880 select_handler
= rb_select_devpoll
;
1881 setup_fd_handler
= rb_setup_fd_devpoll
;
1882 io_sched_event
= NULL
;
1883 io_unsched_event
= NULL
;
1884 io_init_event
= NULL
;
1885 io_supports_event
= rb_unsupported_event
;
1886 rb_strlcpy(iotype
, "devpoll", sizeof(iotype
));
1895 if(!rb_init_netio_sigio())
1897 setselect_handler
= rb_setselect_sigio
;
1898 select_handler
= rb_select_sigio
;
1899 setup_fd_handler
= rb_setup_fd_sigio
;
1900 io_sched_event
= rb_sigio_sched_event
;
1901 io_unsched_event
= rb_sigio_unsched_event
;
1902 io_supports_event
= rb_sigio_supports_event
;
1903 io_init_event
= rb_sigio_init_event
;
1905 rb_strlcpy(iotype
, "sigio", sizeof(iotype
));
1914 if(!rb_init_netio_poll())
1916 setselect_handler
= rb_setselect_poll
;
1917 select_handler
= rb_select_poll
;
1918 setup_fd_handler
= rb_setup_fd_poll
;
1919 io_sched_event
= NULL
;
1920 io_unsched_event
= NULL
;
1921 io_init_event
= NULL
;
1922 io_supports_event
= rb_unsupported_event
;
1923 rb_strlcpy(iotype
, "poll", sizeof(iotype
));
1932 if(!rb_init_netio_win32())
1934 setselect_handler
= rb_setselect_win32
;
1935 select_handler
= rb_select_win32
;
1936 setup_fd_handler
= rb_setup_fd_win32
;
1937 io_sched_event
= NULL
;
1938 io_unsched_event
= NULL
;
1939 io_init_event
= NULL
;
1940 io_supports_event
= rb_unsupported_event
;
1941 rb_strlcpy(iotype
, "win32", sizeof(iotype
));
1950 if(!rb_init_netio_select())
1952 setselect_handler
= rb_setselect_select
;
1953 select_handler
= rb_select_select
;
1954 setup_fd_handler
= rb_setup_fd_select
;
1955 io_sched_event
= NULL
;
1956 io_unsched_event
= NULL
;
1957 io_init_event
= NULL
;
1958 io_supports_event
= rb_unsupported_event
;
1959 rb_strlcpy(iotype
, "select", sizeof(iotype
));
1967 rb_io_sched_event(struct ev_entry
*ev
, int when
)
1969 if(ev
== NULL
|| io_supports_event
== NULL
|| io_sched_event
== NULL
1970 || !io_supports_event())
1972 return io_sched_event(ev
, when
);
1976 rb_io_unsched_event(struct ev_entry
*ev
)
1978 if(ev
== NULL
|| io_supports_event
== NULL
|| io_unsched_event
== NULL
1979 || !io_supports_event())
1981 io_unsched_event(ev
);
1985 rb_io_supports_event(void)
1987 if(io_supports_event
== NULL
)
1989 return io_supports_event();
1993 rb_io_init_event(void)
1996 rb_event_io_register_all();
2002 char *ioenv
= getenv("LIBRB_USE_IOTYPE");
2003 rb_fd_table
= rb_malloc(RB_FD_HASH_SIZE
* sizeof(rb_dlink_list
));
2008 if(!strcmp("epoll", ioenv
))
2013 else if(!strcmp("kqueue", ioenv
))
2018 else if(!strcmp("ports", ioenv
))
2023 else if(!strcmp("poll", ioenv
))
2028 else if(!strcmp("devpoll", ioenv
))
2033 else if(!strcmp("sigio", ioenv
))
2038 else if(!strcmp("select", ioenv
))
2043 if(!strcmp("win32", ioenv
))
2068 rb_lib_log("rb_init_netio: Could not find any io handlers...giving up");
2074 rb_setselect(rb_fde_t
*F
, unsigned int type
, PF
* handler
, void *client_data
)
2076 setselect_handler(F
, type
, handler
, client_data
);
2080 rb_select(unsigned long timeout
)
2082 int ret
= select_handler(timeout
);
2088 rb_setup_fd(rb_fde_t
*F
)
2090 return setup_fd_handler(F
);
2096 rb_ignore_errno(int error
)
2103 #if defined EWOULDBLOCK
2106 #if defined(EAGAIN) && (EWOULDBLOCK != EAGAIN)
2126 #if defined(HAVE_SENDMSG) && !defined(WIN32)
2128 rb_recv_fd_buf(rb_fde_t
*F
, void *data
, size_t datasize
, rb_fde_t
**xF
, int nfds
)
2131 struct cmsghdr
*cmsg
;
2132 struct iovec iov
[1];
2134 uint8_t stype
= RB_FD_UNKNOWN
;
2136 int fd
, len
, x
, rfds
;
2138 int control_len
= CMSG_SPACE(sizeof(int) * nfds
);
2140 iov
[0].iov_base
= data
;
2141 iov
[0].iov_len
= datasize
;
2143 msg
.msg_name
= NULL
;
2144 msg
.msg_namelen
= 0;
2148 cmsg
= alloca(control_len
);
2149 msg
.msg_control
= cmsg
;
2150 msg
.msg_controllen
= control_len
;
2152 if((len
= recvmsg(rb_get_fd(F
), &msg
, 0)) <= 0)
2155 if(msg
.msg_controllen
> 0 && msg
.msg_control
!= NULL
2156 && (cmsg
= CMSG_FIRSTHDR(&msg
)) != NULL
)
2158 rfds
= ((unsigned char *)cmsg
+ cmsg
->cmsg_len
- CMSG_DATA(cmsg
)) / sizeof(int);
2160 for(x
= 0; x
< nfds
&& x
< rfds
; x
++)
2162 fd
= ((int *)CMSG_DATA(cmsg
))[x
];
2163 stype
= RB_FD_UNKNOWN
;
2164 desc
= "remote unknown";
2167 if(S_ISSOCK(st
.st_mode
))
2169 stype
= RB_FD_SOCKET
;
2170 desc
= "remote socket";
2172 else if(S_ISFIFO(st
.st_mode
))
2175 desc
= "remote pipe";
2177 else if(S_ISREG(st
.st_mode
))
2180 desc
= "remote file";
2183 xF
[x
] = rb_open(fd
, stype
, desc
);
2193 rb_send_fd_buf(rb_fde_t
*xF
, rb_fde_t
**F
, int count
, void *data
, size_t datasize
, pid_t pid
)
2197 struct cmsghdr
*cmsg
;
2198 struct iovec iov
[1];
2202 memset(&msg
, 0, sizeof(&msg
));
2205 iov
[0].iov_base
= &empty
;
2210 iov
[0].iov_base
= data
;
2211 iov
[0].iov_len
= datasize
;
2215 msg
.msg_name
= NULL
;
2216 msg
.msg_namelen
= 0;
2218 msg
.msg_control
= NULL
;
2219 msg
.msg_controllen
= 0;
2224 int len
= CMSG_SPACE(sizeof(int) * count
);
2227 msg
.msg_control
= buf
;
2228 msg
.msg_controllen
= len
;
2229 cmsg
= CMSG_FIRSTHDR(&msg
);
2230 cmsg
->cmsg_level
= SOL_SOCKET
;
2231 cmsg
->cmsg_type
= SCM_RIGHTS
;
2232 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int) * count
);
2234 for(i
= 0; i
< count
; i
++)
2236 ((int *)CMSG_DATA(cmsg
))[i
] = rb_get_fd(F
[i
]);
2238 msg
.msg_controllen
= cmsg
->cmsg_len
;
2240 n
= sendmsg(rb_get_fd(xF
), &msg
, MSG_NOSIGNAL
);
2246 rb_recv_fd_buf(rb_fde_t
*F
, void *data
, size_t datasize
, rb_fde_t
**xF
, int nfds
)
2253 rb_send_fd_buf(rb_fde_t
*xF
, rb_fde_t
**F
, int count
, void *data
, size_t datasize
, pid_t pid
)