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()",
65 /* Highest FD and number of open FDs .. */
66 static int number_fd
= 0;
67 int rb_maxconnections
= 0;
69 static PF rb_connect_timeout
;
70 static PF rb_connect_tryconnect
;
72 static void mangle_mapped_sockaddr(struct sockaddr
*in
);
75 #ifndef HAVE_SOCKETPAIR
76 static int rb_inet_socketpair(int d
, int type
, int protocol
, int sv
[2]);
77 static int rb_inet_socketpair_udp(rb_fde_t
**newF1
, rb_fde_t
**newF2
);
80 static inline rb_fde_t
*
83 rb_fde_t
*F
= rb_find_fd(fd
);
85 /* look up to see if we have it already */
89 F
= rb_bh_alloc(fd_heap
);
91 rb_dlinkAdd(F
, &F
->node
, &rb_fd_table
[rb_hash_fd(fd
)]);
96 remove_fd(rb_fde_t
*F
)
98 if(F
== NULL
|| !IsFDOpen(F
))
101 rb_dlinkMoveNode(&F
->node
, &rb_fd_table
[rb_hash_fd(F
->fd
)], &closed_list
);
108 rb_dlink_node
*ptr
, *next
;
109 RB_DLINK_FOREACH_SAFE(ptr
, next
, closed_list
.head
)
112 rb_dlinkDelete(ptr
, &closed_list
);
113 rb_bh_free(fd_heap
, F
);
117 /* 32bit solaris is kinda slow and stdio only supports fds < 256
118 * so we got to do this crap below.
119 * (BTW Fuck you Sun, I hate your guts and I hope you go bankrupt soon)
122 #if defined (__SVR4) && defined (__sun)
127 if(*fd
> 256 || *fd
< 0)
129 if((newfd
= fcntl(*fd
, F_DUPFD
, 256)) != -1)
137 #define rb_fd_hack(fd)
141 /* close_all_connections() can be used *before* the system come up! */
149 /* XXX someone tell me why we care about 4 fd's ? */
150 /* XXX btw, fd 3 is used for profiler ! */
151 for(i
= 3; i
< rb_maxconnections
; ++i
)
159 * get_sockerr - get the error value from the socket or the current errno
161 * Get the *real* error from the socket (well try to anyway..).
162 * This may only work when SO_DEBUG is enabled but its worth the
166 rb_get_sockerr(rb_fde_t
*F
)
170 rb_socklen_t len
= sizeof(err
);
172 if(!(F
->type
& RB_FD_SOCKET
))
180 && !getsockopt(rb_get_fd(F
), SOL_SOCKET
, SO_ERROR
, (char *)&err
, (rb_socklen_t
*) & len
))
191 * rb_getmaxconnect - return the max number of connections allowed
194 rb_getmaxconnect(void)
196 return (rb_maxconnections
);
200 * set_sock_buffers - set send and receive buffers for socket
202 * inputs - fd file descriptor
204 * output - returns true (1) if successful, false (0) otherwise
208 rb_set_buffers(rb_fde_t
*F
, int size
)
213 (F
->fd
, SOL_SOCKET
, SO_RCVBUF
, (char *)&size
, sizeof(size
))
214 || setsockopt(F
->fd
, SOL_SOCKET
, SO_SNDBUF
, (char *)&size
, sizeof(size
)))
220 * set_non_blocking - Set the client connection into non-blocking mode.
222 * inputs - fd to set into non blocking mode
223 * output - 1 if successful 0 if not
224 * side effects - use POSIX compliant non blocking and
228 rb_set_nb(rb_fde_t
*F
)
237 if((res
= rb_setup_fd(F
)))
241 res
= fcntl(fd
, F_GETFL
, 0);
242 if(-1 == res
|| fcntl(fd
, F_SETFL
, res
| nonb
) == -1)
247 if(ioctl(fd
, FIONBIO
, (char *)&nonb
) == -1)
255 * rb_settimeout() - set the socket timeout
257 * Set the timeout for the fd
260 rb_settimeout(rb_fde_t
*F
, time_t timeout
, PF
* callback
, void *cbdata
)
262 struct timeout_data
*td
;
267 lrb_assert(IsFDOpen(F
));
269 if(callback
== NULL
) /* user wants to remove */
273 rb_dlinkDelete(&td
->node
, &timeout_list
);
276 if(rb_dlink_list_length(&timeout_list
) == 0)
278 rb_event_delete(rb_timeout_ev
);
279 rb_timeout_ev
= NULL
;
284 if(F
->timeout
== NULL
)
285 td
= F
->timeout
= rb_malloc(sizeof(struct timeout_data
));
288 td
->timeout
= rb_current_time() + timeout
;
289 td
->timeout_handler
= callback
;
290 td
->timeout_data
= cbdata
;
291 rb_dlinkAdd(td
, &td
->node
, &timeout_list
);
292 if(rb_timeout_ev
== NULL
)
294 rb_timeout_ev
= rb_event_add("rb_checktimeouts", rb_checktimeouts
, NULL
, 5);
299 * rb_checktimeouts() - check the socket timeouts
301 * All this routine does is call the given callback/cbdata, without closing
302 * down the file descriptor. When close handlers have been implemented,
306 rb_checktimeouts(void *notused
)
308 rb_dlink_node
*ptr
, *next
;
309 struct timeout_data
*td
;
314 RB_DLINK_FOREACH_SAFE(ptr
, next
, timeout_list
.head
)
318 if(F
== NULL
|| !IsFDOpen(F
))
321 if(td
->timeout
< rb_current_time())
323 hdl
= td
->timeout_handler
;
324 data
= td
->timeout_data
;
325 rb_dlinkDelete(&td
->node
, &timeout_list
);
334 rb_accept_tryaccept(rb_fde_t
*F
, void *data
)
336 struct rb_sockaddr_storage st
;
338 rb_socklen_t addrlen
= sizeof(st
);
343 new_fd
= accept(F
->fd
, (struct sockaddr
*)&st
, &addrlen
);
347 rb_setselect(F
, RB_SELECT_ACCEPT
, rb_accept_tryaccept
, NULL
);
353 new_F
= rb_open(new_fd
, RB_FD_SOCKET
, "Incoming Connection");
358 ("rb_accept: new_F == NULL on incoming connection. Closing new_fd == %d\n",
364 if(rb_unlikely(!rb_set_nb(new_F
)))
367 rb_lib_log("rb_accept: Couldn't set FD %d non blocking!", new_F
->fd
);
372 mangle_mapped_sockaddr((struct sockaddr
*)&st
);
375 if(F
->accept
->precb
!= NULL
)
377 if(!F
->accept
->precb(new_F
, (struct sockaddr
*)&st
, addrlen
, F
->accept
->data
)) /* pre-callback decided to drop it */
381 if(F
->type
& RB_FD_SSL
)
383 rb_ssl_accept_setup(F
, new_F
, (struct sockaddr
*)&st
, addrlen
);
386 #endif /* HAVE_SSL */
388 F
->accept
->callback(new_F
, RB_OK
, (struct sockaddr
*)&st
, addrlen
,
395 /* try to accept a TCP connection */
397 rb_accept_tcp(rb_fde_t
*F
, ACPRE
* precb
, ACCB
* callback
, void *data
)
401 lrb_assert(callback
);
403 F
->accept
= rb_malloc(sizeof(struct acceptdata
));
404 F
->accept
->callback
= callback
;
405 F
->accept
->data
= data
;
406 F
->accept
->precb
= precb
;
407 rb_accept_tryaccept(F
, NULL
);
411 * void rb_connect_tcp(int fd, struct sockaddr *dest,
412 * struct sockaddr *clocal, int socklen,
413 * CNCB *callback, void *data, int timeout)
414 * Input: An fd to connect with, a host and port to connect to,
415 * a local sockaddr to connect from + length(or NULL to use the
416 * default), a callback, the data to pass into the callback, the
419 * Side-effects: A non-blocking connection to the host is started, and
420 * if necessary, set up for selection. The callback given
421 * may be called now, or it may be called later.
424 rb_connect_tcp(rb_fde_t
*F
, struct sockaddr
*dest
,
425 struct sockaddr
*clocal
, int socklen
, CNCB
* callback
, void *data
, int timeout
)
430 lrb_assert(callback
);
431 F
->connect
= rb_malloc(sizeof(struct conndata
));
432 F
->connect
->callback
= callback
;
433 F
->connect
->data
= data
;
435 memcpy(&F
->connect
->hostaddr
, dest
, sizeof(F
->connect
->hostaddr
));
437 /* Note that we're using a passed sockaddr here. This is because
438 * generally you'll be bind()ing to a sockaddr grabbed from
439 * getsockname(), so this makes things easier.
440 * XXX If NULL is passed as local, we should later on bind() to the
441 * virtual host IP, for completeness.
444 if((clocal
!= NULL
) && (bind(F
->fd
, clocal
, socklen
) < 0))
446 /* Failure, call the callback with RB_ERR_BIND */
447 rb_connect_callback(F
, RB_ERR_BIND
);
452 /* We have a valid IP, so we just call tryconnect */
453 /* Make sure we actually set the timeout here .. */
454 rb_settimeout(F
, timeout
, rb_connect_timeout
, NULL
);
455 rb_connect_tryconnect(F
, NULL
);
460 * rb_connect_callback() - call the callback, and continue with life
463 rb_connect_callback(rb_fde_t
*F
, int status
)
467 int errtmp
= errno
; /* save errno as rb_settimeout clobbers it sometimes */
469 /* This check is gross..but probably necessary */
470 if(F
== NULL
|| F
->connect
== NULL
|| F
->connect
->callback
== NULL
)
472 /* Clear the connect flag + handler */
473 hdl
= F
->connect
->callback
;
474 data
= F
->connect
->data
;
475 F
->connect
->callback
= NULL
;
478 /* Clear the timeout handler */
479 rb_settimeout(F
, 0, NULL
, NULL
);
481 /* Call the handler */
482 hdl(F
, status
, data
);
487 * rb_connect_timeout() - this gets called when the socket connection
488 * times out. This *only* can be called once connect() is initially
492 rb_connect_timeout(rb_fde_t
*F
, void *notused
)
495 rb_connect_callback(F
, RB_ERR_TIMEOUT
);
498 /* static void rb_connect_tryconnect(int fd, void *notused)
499 * Input: The fd, the handler data(unused).
501 * Side-effects: Try and connect with pending connect data for the FD. If
502 * we succeed or get a fatal error, call the callback.
503 * Otherwise, it is still blocking or something, so register
504 * to select for a write event on this FD.
507 rb_connect_tryconnect(rb_fde_t
*F
, void *notused
)
511 if(F
== NULL
|| F
->connect
== NULL
|| F
->connect
->callback
== NULL
)
513 /* Try the connect() */
514 retval
= connect(F
->fd
,
515 (struct sockaddr
*)&F
->connect
->hostaddr
,
516 GET_SS_LEN(&F
->connect
->hostaddr
));
521 * If we get EISCONN, then we've already connect()ed the socket,
522 * which is a good thing.
527 rb_connect_callback(F
, RB_OK
);
528 else if(rb_ignore_errno(errno
))
529 /* Ignore error? Reschedule */
530 rb_setselect(F
, RB_SELECT_CONNECT
, rb_connect_tryconnect
, NULL
);
532 /* Error? Fail with RB_ERR_CONNECT */
533 rb_connect_callback(F
, RB_ERR_CONNECT
);
536 /* If we get here, we've suceeded, so call with RB_OK */
537 rb_connect_callback(F
, RB_OK
);
542 rb_connect_sockaddr(rb_fde_t
*F
, struct sockaddr
*addr
, int len
)
547 memcpy(addr
, &F
->connect
->hostaddr
, len
);
552 * rb_error_str() - return an error string for the given error condition
557 if(error
< 0 || error
>= RB_ERR_MAX
)
558 return "Invalid error number!";
559 return rb_err_str
[error
];
564 rb_socketpair(int family
, int sock_type
, int proto
, rb_fde_t
**F1
, rb_fde_t
**F2
, const char *note
)
567 if(number_fd
>= rb_maxconnections
)
573 #ifdef HAVE_SOCKETPAIR
574 if(socketpair(family
, sock_type
, proto
, nfd
))
576 if(sock_type
== SOCK_DGRAM
)
578 return rb_inet_socketpair_udp(F1
, F2
);
581 if(rb_inet_socketpair(AF_INET
, sock_type
, proto
, nfd
))
588 *F1
= rb_open(nfd
[0], RB_FD_SOCKET
, note
);
589 *F2
= rb_open(nfd
[1], RB_FD_SOCKET
, note
);
604 /* Set the socket non-blocking, and other wonderful bits */
605 if(rb_unlikely(!rb_set_nb(*F1
)))
607 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd
[0], strerror(errno
));
613 if(rb_unlikely(!rb_set_nb(*F2
)))
615 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd
[1], strerror(errno
));
626 rb_pipe(rb_fde_t
**F1
, rb_fde_t
**F2
, const char *desc
)
630 if(number_fd
>= rb_maxconnections
)
639 *F1
= rb_open(fd
[0], RB_FD_PIPE
, desc
);
640 *F2
= rb_open(fd
[1], RB_FD_PIPE
, desc
);
642 if(rb_unlikely(!rb_set_nb(*F1
)))
644 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
[0], strerror(errno
));
650 if(rb_unlikely(!rb_set_nb(*F2
)))
652 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
[1], strerror(errno
));
661 /* Its not a pipe..but its selectable. I'll take dirty hacks
664 return rb_socketpair(AF_INET
, SOCK_STREAM
, 0, F1
, F2
, desc
);
669 * rb_socket() - open a socket
671 * This is a highly highly cut down version of squid's rb_open() which
672 * for the most part emulates socket(), *EXCEPT* it fails if we're about
673 * to run out of file descriptors.
676 rb_socket(int family
, int sock_type
, int proto
, const char *note
)
680 /* First, make sure we aren't going to run out of file descriptors */
681 if(rb_unlikely(number_fd
>= rb_maxconnections
))
688 * Next, we try to open the socket. We *should* drop the reserved FD
689 * limit if/when we get an error, but we can deal with that later.
692 fd
= socket(family
, sock_type
, proto
);
694 if(rb_unlikely(fd
< 0))
695 return NULL
; /* errno will be passed through, yay.. */
697 #if defined(RB_IPV6) && defined(IPV6_V6ONLY)
699 * Make sure we can take both IPv4 and IPv6 connections
700 * on an AF_INET6 socket
702 if(family
== AF_INET6
)
705 if(setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &off
, sizeof(off
)) == -1)
707 rb_lib_log("rb_socket: Could not set IPV6_V6ONLY option to 1 on FD %d: %s",
708 fd
, strerror(errno
));
715 F
= rb_open(fd
, RB_FD_SOCKET
, note
);
718 rb_lib_log("rb_socket: rb_open returns NULL on FD %d: %s, closing fd", fd
,
723 /* Set the socket non-blocking, and other wonderful bits */
724 if(rb_unlikely(!rb_set_nb(F
)))
726 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
, strerror(errno
));
735 * If a sockaddr_storage is AF_INET6 but is a mapped IPv4
736 * socket manged the sockaddr.
740 mangle_mapped_sockaddr(struct sockaddr
*in
)
742 struct sockaddr_in6
*in6
= (struct sockaddr_in6
*)in
;
744 if(in
->sa_family
== AF_INET
)
747 if(in
->sa_family
== AF_INET6
&& IN6_IS_ADDR_V4MAPPED(&in6
->sin6_addr
))
749 struct sockaddr_in in4
;
750 memset(&in4
, 0, sizeof(struct sockaddr_in
));
751 in4
.sin_family
= AF_INET
;
752 in4
.sin_port
= in6
->sin6_port
;
753 in4
.sin_addr
.s_addr
= ((uint32_t *)&in6
->sin6_addr
)[3];
754 memcpy(in
, &in4
, sizeof(struct sockaddr_in
));
761 * rb_listen() - listen on a port
764 rb_listen(rb_fde_t
*F
, int backlog
)
766 F
->type
= RB_FD_SOCKET
| RB_FD_LISTEN
;
767 /* Currently just a simple wrapper for the sake of being complete */
768 return listen(F
->fd
, backlog
);
772 rb_fdlist_init(int closeall
, int maxfds
, size_t heapsize
)
774 static int initialized
= 0;
778 int vers
= MAKEWORD(2, 0);
780 err
= WSAStartup(vers
, &wsaData
);
783 rb_lib_die("WSAStartup failed");
789 rb_maxconnections
= maxfds
;
792 /* Since we're doing this once .. */
795 fd_heap
= rb_bh_create(sizeof(rb_fde_t
), heapsize
, "librb_fd_heap");
800 /* Called to open a given filedescriptor */
802 rb_open(int fd
, uint8_t type
, const char *desc
)
809 lrb_assert(!IsFDOpen(F
));
810 if(rb_unlikely(IsFDOpen(F
)))
813 if(F
!= NULL
&& F
->desc
!= NULL
)
817 rb_lib_log("Trying to rb_open an already open FD: %d desc: %s", fd
, fdesc
);
825 F
->desc
= rb_strndup(desc
, FD_DESC_SZ
);
831 /* Called to close a given filedescriptor */
833 rb_close(rb_fde_t
*F
)
842 lrb_assert(IsFDOpen(F
));
844 lrb_assert(!(type
& RB_FD_FILE
));
845 if(rb_unlikely(type
& RB_FD_FILE
))
847 lrb_assert(F
->read_handler
== NULL
);
848 lrb_assert(F
->write_handler
== NULL
);
850 rb_setselect(F
, RB_SELECT_WRITE
| RB_SELECT_READ
, NULL
, NULL
);
851 rb_settimeout(F
, 0, NULL
, NULL
);
860 #endif /* HAVE_SSL */
870 if(type
& (RB_FD_SOCKET
| RB_FD_PIPE
))
882 * rb_dump_fd() - dump the list of active filedescriptors
885 rb_dump_fd(DUMPCB
* cb
, void *data
)
887 static const char *empty
= "";
889 rb_dlink_list
*bucket
;
893 for(i
= 0; i
< RB_FD_HASH_SIZE
; i
++)
895 bucket
= &rb_fd_table
[i
];
897 if(rb_dlink_list_length(bucket
) <= 0)
900 RB_DLINK_FOREACH(ptr
, bucket
->head
)
903 if(F
== NULL
|| !IsFDOpen(F
))
906 cb(F
->fd
, F
->desc
? F
->desc
: empty
, data
);
912 * rb_note() - set the fd note
914 * Note: must be careful not to overflow rb_fd_table[fd].desc when
918 rb_note(rb_fde_t
*F
, const char *string
)
924 F
->desc
= rb_strndup(string
, FD_DESC_SZ
);
928 rb_set_type(rb_fde_t
*F
, uint8_t type
)
930 /* if the caller is calling this, lets assume they have a clue */
936 rb_get_type(rb_fde_t
*F
)
942 rb_fd_ssl(rb_fde_t
*F
)
946 if(F
->type
& RB_FD_SSL
)
952 rb_get_fd(rb_fde_t
*F
)
962 return rb_find_fd(fd
);
966 rb_read(rb_fde_t
*F
, void *buf
, int count
)
972 /* This needs to be *before* RB_FD_SOCKET otherwise you'll process
973 * an SSL socket as a regular socket
976 if(F
->type
& RB_FD_SSL
)
978 return rb_ssl_read(F
, buf
, count
);
981 if(F
->type
& RB_FD_SOCKET
)
983 ret
= recv(F
->fd
, buf
, count
, 0);
993 return read(F
->fd
, buf
, count
);
998 rb_write(rb_fde_t
*F
, const void *buf
, int count
)
1005 if(F
->type
& RB_FD_SSL
)
1007 return rb_ssl_write(F
, buf
, count
);
1010 if(F
->type
& RB_FD_SOCKET
)
1012 ret
= send(F
->fd
, buf
, count
, MSG_NOSIGNAL
);
1020 return write(F
->fd
, buf
, count
);
1023 #if defined(HAVE_SSL) || defined(WIN32) || !defined(HAVE_WRITEV)
1025 rb_fake_writev(rb_fde_t
*F
, const struct rb_iovec
*vp
, size_t vpcount
)
1029 while(vpcount
-- > 0)
1031 ssize_t written
= rb_write(F
, vp
->iov_base
, vp
->iov_len
);
1047 #if defined(WIN32) || !defined(HAVE_WRITEV)
1049 rb_writev(rb_fde_t
*F
, struct rb_iovec
* vecount
, int count
)
1051 return rb_fake_writev(F
, vecount
, count
);
1056 rb_writev(rb_fde_t
*F
, struct rb_iovec
* vector
, int count
)
1064 if(F
->type
& RB_FD_SSL
)
1066 return rb_fake_writev(F
, vector
, count
);
1068 #endif /* HAVE_SSL */
1070 if(F
->type
& RB_FD_SOCKET
)
1073 memset(&msg
, 0, sizeof(msg
));
1074 msg
.msg_iov
= (struct iovec
*)vector
;
1075 msg
.msg_iovlen
= count
;
1076 return sendmsg(F
->fd
, &msg
, MSG_NOSIGNAL
);
1078 #endif /* HAVE_SENDMSG */
1079 return writev(F
->fd
, (struct iovec
*)vector
, count
);
1086 * From: Thomas Helvey <tomh@inxpress.net>
1088 static const char *IpQuadTab
[] = {
1089 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
1090 "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
1091 "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
1092 "30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
1093 "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
1094 "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
1095 "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
1096 "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
1097 "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
1098 "90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
1099 "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
1100 "110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
1101 "120", "121", "122", "123", "124", "125", "126", "127", "128", "129",
1102 "130", "131", "132", "133", "134", "135", "136", "137", "138", "139",
1103 "140", "141", "142", "143", "144", "145", "146", "147", "148", "149",
1104 "150", "151", "152", "153", "154", "155", "156", "157", "158", "159",
1105 "160", "161", "162", "163", "164", "165", "166", "167", "168", "169",
1106 "170", "171", "172", "173", "174", "175", "176", "177", "178", "179",
1107 "180", "181", "182", "183", "184", "185", "186", "187", "188", "189",
1108 "190", "191", "192", "193", "194", "195", "196", "197", "198", "199",
1109 "200", "201", "202", "203", "204", "205", "206", "207", "208", "209",
1110 "210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
1111 "220", "221", "222", "223", "224", "225", "226", "227", "228", "229",
1112 "230", "231", "232", "233", "234", "235", "236", "237", "238", "239",
1113 "240", "241", "242", "243", "244", "245", "246", "247", "248", "249",
1114 "250", "251", "252", "253", "254", "255"
1118 * inetntoa - in_addr to string
1119 * changed name to remove collision possibility and
1120 * so behaviour is guaranteed to take a pointer arg.
1122 * inet_ntoa -- returned the dotted notation of a given
1125 * inet_ntoa -- its broken on some Ultrix/Dynix too. -avalon
1129 inetntoa(const char *in
)
1131 static char buf
[16];
1133 const unsigned char *a
= (const unsigned char *)in
;
1136 n
= IpQuadTab
[*a
++];
1140 n
= IpQuadTab
[*a
++];
1144 n
= IpQuadTab
[*a
++];
1157 * Copyright (c) 1996-1999 by Internet Software Consortium.
1159 * Permission to use, copy, modify, and distribute this software for any
1160 * purpose with or without fee is hereby granted, provided that the above
1161 * copyright notice and this permission notice appear in all copies.
1163 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
1164 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
1165 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
1166 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
1167 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
1168 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
1169 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
1173 #define SPRINTF(x) ((size_t)rb_sprintf x)
1176 * WARNING: Don't even consider trying to compile this on a system where
1177 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
1180 static const char *inet_ntop4(const unsigned char *src
, char *dst
, unsigned int size
);
1182 static const char *inet_ntop6(const unsigned char *src
, char *dst
, unsigned int size
);
1186 * inet_ntop4(src, dst, size)
1187 * format an IPv4 address
1189 * `dst' (as a const)
1191 * (1) uses no statics
1192 * (2) takes a unsigned char* not an in_addr as input
1197 inet_ntop4(const unsigned char *src
, char *dst
, unsigned int size
)
1201 return rb_strlcpy(dst
, inetntoa((const char *)src
), size
);
1205 * inet_ntop6(src, dst, size)
1206 * convert IPv6 binary address into presentation (printable) format
1212 inet_ntop6(const unsigned char *src
, char *dst
, unsigned int size
)
1215 * Note that int32_t and int16_t need only be "at least" large enough
1216 * to contain a value of the specified size. On some systems, like
1217 * Crays, there is no such thing as an integer variable with 16 bits.
1218 * Keep this in mind if you think this function should have been coded
1219 * to use pointer overlays. All the world's not a VAX.
1221 char tmp
[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp
;
1227 unsigned int words
[IN6ADDRSZ
/ INT16SZ
];
1232 * Copy the input (bytewise) array into a wordwise array.
1233 * Find the longest run of 0x00's in src[] for :: shorthanding.
1235 memset(words
, '\0', sizeof words
);
1236 for(i
= 0; i
< IN6ADDRSZ
; i
+= 2)
1237 words
[i
/ 2] = (src
[i
] << 8) | src
[i
+ 1];
1242 for(i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++)
1247 cur
.base
= i
, cur
.len
= 1;
1255 if(best
.base
== -1 || cur
.len
> best
.len
)
1263 if(best
.base
== -1 || cur
.len
> best
.len
)
1266 if(best
.base
!= -1 && best
.len
< 2)
1270 * Format the result.
1273 for(i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++)
1275 /* Are we inside the best run of 0x00's? */
1276 if(best
.base
!= -1 && i
>= best
.base
&& i
< (best
.base
+ best
.len
))
1286 /* Are we following an initial run of 0x00s or any real hex? */
1289 /* Is this address an encapsulated IPv4? */
1290 if(i
== 6 && best
.base
== 0 &&
1291 (best
.len
== 6 || (best
.len
== 5 && words
[5] == 0xffff)))
1293 if(!inet_ntop4(src
+ 12, tp
, sizeof tmp
- (tp
- tmp
)))
1298 tp
+= SPRINTF((tp
, "%x", words
[i
]));
1300 /* Was it a trailing run of 0x00's? */
1301 if(best
.base
!= -1 && (best
.base
+ best
.len
) == (IN6ADDRSZ
/ INT16SZ
))
1306 * Check for overflow, copy, and we're done.
1309 if((unsigned int)(tp
- tmp
) > size
)
1313 return rb_strlcpy(dst
, tmp
, size
);
1318 rb_inet_pton_sock(const char *src
, struct sockaddr
*dst
)
1320 if(rb_inet_pton(AF_INET
, src
, &((struct sockaddr_in
*)dst
)->sin_addr
))
1322 ((struct sockaddr_in
*)dst
)->sin_port
= 0;
1323 ((struct sockaddr_in
*)dst
)->sin_family
= AF_INET
;
1324 SET_SS_LEN(dst
, sizeof(struct sockaddr_in
));
1328 else if(rb_inet_pton(AF_INET6
, src
, &((struct sockaddr_in6
*)dst
)->sin6_addr
))
1330 ((struct sockaddr_in6
*)dst
)->sin6_port
= 0;
1331 ((struct sockaddr_in6
*)dst
)->sin6_family
= AF_INET6
;
1332 SET_SS_LEN(dst
, sizeof(struct sockaddr_in6
));
1340 rb_inet_ntop_sock(struct sockaddr
*src
, char *dst
, unsigned int size
)
1342 switch (src
->sa_family
)
1345 return (rb_inet_ntop(AF_INET
, &((struct sockaddr_in
*)src
)->sin_addr
, dst
, size
));
1349 return (rb_inet_ntop
1350 (AF_INET6
, &((struct sockaddr_in6
*)src
)->sin6_addr
, dst
, size
));
1360 * rb_inet_ntop(af, src, dst, size)
1361 * convert a network format address to presentation format.
1363 * pointer to presentation format address (`dst'), or NULL (see errno).
1368 rb_inet_ntop(int af
, const void *src
, char *dst
, unsigned int size
)
1373 return (inet_ntop4(src
, dst
, size
));
1376 if(IN6_IS_ADDR_V4MAPPED((const struct in6_addr
*)src
) ||
1377 IN6_IS_ADDR_V4COMPAT((const struct in6_addr
*)src
))
1379 ((const unsigned char *)&((const struct in6_addr
*)src
)->
1380 s6_addr
[12], dst
, size
));
1382 return (inet_ntop6(src
, dst
, size
));
1393 * WARNING: Don't even consider trying to compile this on a system where
1394 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
1398 * rb_inet_pton(af, src, dst)
1399 * convert from presentation format (which usually means ASCII printable)
1400 * to network format (which is usually some kind of binary format).
1402 * 1 if the address was valid for the specified address family
1403 * 0 if the address wasn't valid (`dst' is untouched in this case)
1404 * -1 if some other error occurred (`dst' is untouched in this case, too)
1410 * inet_pton4(src, dst)
1411 * like inet_aton() but without all the hexadecimal and shorthand.
1413 * 1 if `src' is a valid dotted quad, else 0.
1415 * does not touch `dst' unless it's returning 1.
1420 inet_pton4(const char *src
, unsigned char *dst
)
1422 int saw_digit
, octets
, ch
;
1423 unsigned char tmp
[INADDRSZ
], *tp
;
1428 while((ch
= *src
++) != '\0')
1431 if(ch
>= '0' && ch
<= '9')
1433 unsigned int new = *tp
* 10 + (ch
- '0');
1445 else if(ch
== '.' && saw_digit
)
1457 memcpy(dst
, tmp
, INADDRSZ
);
1463 * inet_pton6(src, dst)
1464 * convert presentation level address to network order binary form.
1466 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
1468 * (1) does not touch `dst' unless it's returning 1.
1469 * (2) :: in a full address is silently ignored.
1471 * inspired by Mark Andrews.
1477 inet_pton6(const char *src
, unsigned char *dst
)
1479 static const char xdigits
[] = "0123456789abcdef";
1480 unsigned char tmp
[IN6ADDRSZ
], *tp
, *endp
, *colonp
;
1485 tp
= memset(tmp
, '\0', IN6ADDRSZ
);
1486 endp
= tp
+ IN6ADDRSZ
;
1488 /* Leading :: requires some special handling. */
1495 while((ch
= tolower(*src
++)) != '\0')
1499 pch
= strchr(xdigits
, ch
);
1503 val
|= (pch
- xdigits
);
1519 else if(*src
== '\0')
1523 if(tp
+ INT16SZ
> endp
)
1525 *tp
++ = (unsigned char)(val
>> 8) & 0xff;
1526 *tp
++ = (unsigned char)val
& 0xff;
1531 if(*src
!= '\0' && ch
== '.')
1533 if(((tp
+ INADDRSZ
) <= endp
) && inet_pton4(curtok
, tp
) > 0)
1537 break; /* '\0' was seen by inet_pton4(). */
1546 if(tp
+ INT16SZ
> endp
)
1548 *tp
++ = (unsigned char)(val
>> 8) & 0xff;
1549 *tp
++ = (unsigned char)val
& 0xff;
1554 * Since some memmove()'s erroneously fail to handle
1555 * overlapping regions, we'll do the shift by hand.
1557 const int n
= tp
- colonp
;
1562 for(i
= 1; i
<= n
; i
++)
1564 endp
[-i
] = colonp
[n
- i
];
1571 memcpy(dst
, tmp
, IN6ADDRSZ
);
1576 rb_inet_pton(int af
, const char *src
, void *dst
)
1581 return (inet_pton4(src
, dst
));
1584 /* Somebody might have passed as an IPv4 address this is sick but it works */
1585 if(inet_pton4(src
, dst
))
1587 char tmp
[HOSTIPLEN
];
1588 rb_sprintf(tmp
, "::ffff:%s", src
);
1589 return (inet_pton6(tmp
, dst
));
1592 return (inet_pton6(src
, dst
));
1601 #ifndef HAVE_SOCKETPAIR
1603 /* mostly based on perl's emulation of socketpair udp */
1605 rb_inet_socketpair_udp(rb_fde_t
**newF1
, rb_fde_t
**newF2
)
1607 struct sockaddr_in addr
[2];
1608 rb_socklen_t size
= sizeof(struct sockaddr_in
);
1612 unsigned short port
;
1613 struct timeval wait
= { 0, 100000 };
1616 struct sockaddr_in readfrom
;
1617 unsigned short buf
[2];
1620 memset(&addr
, 0, sizeof(addr
));
1622 for(i
= 0; i
< 2; i
++)
1624 F
[i
] = rb_socket(AF_INET
, SOCK_DGRAM
, 0, "udp socketpair");
1627 addr
[i
].sin_family
= AF_INET
;
1628 addr
[i
].sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
1629 addr
[i
].sin_port
= 0;
1630 if(bind(rb_get_fd(F
[i
]), (struct sockaddr
*)&addr
[i
], sizeof(struct sockaddr_in
)))
1632 fd
[i
] = rb_get_fd(F
[i
]);
1635 for(i
= 0; i
< 2; i
++)
1637 if(getsockname(fd
[i
], (struct sockaddr
*)&addr
[i
], &size
))
1639 if(size
!= sizeof(struct sockaddr_in
))
1641 if(connect(fd
[!i
], (struct sockaddr
*)&addr
[i
], sizeof(struct sockaddr_in
)) == -1)
1645 for(i
= 0; i
< 2; i
++)
1647 port
= addr
[i
].sin_port
;
1648 got
= rb_write(F
[i
], &port
, sizeof(port
));
1649 if(got
!= sizeof(port
))
1657 max
= fd
[1] > fd
[0] ? fd
[1] : fd
[0];
1659 FD_SET(fd
[0], &rset
);
1660 FD_SET(fd
[1], &rset
);
1661 got
= select(max
+ 1, &rset
, NULL
, NULL
, &wait
);
1662 if(got
!= 2 || !FD_ISSET(fd
[0], &rset
) || !FD_ISSET(fd
[1], &rset
))
1669 for(i
= 0; i
< 2; i
++)
1672 int flag
= MSG_DONTWAIT
1676 got
= recvfrom(rb_get_fd(F
[i
]), (char *)&buf
, sizeof(buf
), flag
,
1677 (struct sockaddr
*)&readfrom
, &size
);
1680 if(got
!= sizeof(port
)
1681 || size
!= sizeof(struct sockaddr_in
)
1682 || buf
[0] != (unsigned short)addr
[!i
].sin_port
1683 || readfrom
.sin_family
!= addr
[!i
].sin_family
1684 || readfrom
.sin_addr
.s_addr
!= addr
[!i
].sin_addr
.s_addr
1685 || readfrom
.sin_port
!= addr
[!i
].sin_port
)
1694 #define ECONNABORTED WSAECONNABORTED
1699 errno
= ECONNABORTED
;
1701 if(errno
!= ECONNABORTED
)
1714 rb_inet_socketpair(int family
, int type
, int protocol
, int fd
[2])
1719 struct sockaddr_in listen_addr
;
1720 struct sockaddr_in connect_addr
;
1723 if(protocol
|| family
!= AF_INET
)
1725 errno
= EAFNOSUPPORT
;
1734 listener
= socket(AF_INET
, type
, 0);
1737 memset(&listen_addr
, 0, sizeof(listen_addr
));
1738 listen_addr
.sin_family
= AF_INET
;
1739 listen_addr
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
1740 listen_addr
.sin_port
= 0; /* kernel choses port. */
1741 if(bind(listener
, (struct sockaddr
*)&listen_addr
, sizeof(listen_addr
)) == -1)
1742 goto tidy_up_and_fail
;
1743 if(listen(listener
, 1) == -1)
1744 goto tidy_up_and_fail
;
1746 connector
= socket(AF_INET
, type
, 0);
1748 goto tidy_up_and_fail
;
1749 /* We want to find out the port number to connect to. */
1750 size
= sizeof(connect_addr
);
1751 if(getsockname(listener
, (struct sockaddr
*)&connect_addr
, &size
) == -1)
1752 goto tidy_up_and_fail
;
1753 if(size
!= sizeof(connect_addr
))
1754 goto abort_tidy_up_and_fail
;
1755 if(connect(connector
, (struct sockaddr
*)&connect_addr
, sizeof(connect_addr
)) == -1)
1756 goto tidy_up_and_fail
;
1758 size
= sizeof(listen_addr
);
1759 acceptor
= accept(listener
, (struct sockaddr
*)&listen_addr
, &size
);
1761 goto tidy_up_and_fail
;
1762 if(size
!= sizeof(listen_addr
))
1763 goto abort_tidy_up_and_fail
;
1765 /* Now check we are talking to ourself by matching port and host on the
1767 if(getsockname(connector
, (struct sockaddr
*)&connect_addr
, &size
) == -1)
1768 goto tidy_up_and_fail
;
1769 if(size
!= sizeof(connect_addr
)
1770 || listen_addr
.sin_family
!= connect_addr
.sin_family
1771 || listen_addr
.sin_addr
.s_addr
!= connect_addr
.sin_addr
.s_addr
1772 || listen_addr
.sin_port
!= connect_addr
.sin_port
)
1774 goto abort_tidy_up_and_fail
;
1780 abort_tidy_up_and_fail
:
1781 errno
= EINVAL
; /* I hope this is portable and appropriate. */
1785 int save_errno
= errno
;
1800 static void (*setselect_handler
) (rb_fde_t
*, unsigned int, PF
*, void *);
1801 static int (*select_handler
) (long);
1802 static int (*setup_fd_handler
) (rb_fde_t
*);
1803 static int (*io_sched_event
) (struct ev_entry
*, int);
1804 static void (*io_unsched_event
) (struct ev_entry
*);
1805 static int (*io_supports_event
) (void);
1806 static void (*io_init_event
) (void);
1807 static char iotype
[25];
1816 rb_unsupported_event(void)
1824 if(!rb_init_netio_kqueue())
1826 setselect_handler
= rb_setselect_kqueue
;
1827 select_handler
= rb_select_kqueue
;
1828 setup_fd_handler
= rb_setup_fd_kqueue
;
1829 io_sched_event
= rb_kqueue_sched_event
;
1830 io_unsched_event
= rb_kqueue_unsched_event
;
1831 io_init_event
= rb_kqueue_init_event
;
1832 io_supports_event
= rb_kqueue_supports_event
;
1833 rb_strlcpy(iotype
, "kqueue", sizeof(iotype
));
1842 if(!rb_init_netio_epoll())
1844 setselect_handler
= rb_setselect_epoll
;
1845 select_handler
= rb_select_epoll
;
1846 setup_fd_handler
= rb_setup_fd_epoll
;
1847 io_sched_event
= rb_epoll_sched_event
;
1848 io_unsched_event
= rb_epoll_unsched_event
;
1849 io_supports_event
= rb_epoll_supports_event
;
1850 io_init_event
= rb_epoll_init_event
;
1851 rb_strlcpy(iotype
, "epoll", sizeof(iotype
));
1860 if(!rb_init_netio_ports())
1862 setselect_handler
= rb_setselect_ports
;
1863 select_handler
= rb_select_ports
;
1864 setup_fd_handler
= rb_setup_fd_ports
;
1865 io_sched_event
= rb_ports_sched_event
;
1866 io_unsched_event
= rb_ports_unsched_event
;
1867 io_init_event
= rb_ports_init_event
;
1868 io_supports_event
= rb_ports_supports_event
;
1869 rb_strlcpy(iotype
, "ports", sizeof(iotype
));
1878 if(!rb_init_netio_devpoll())
1880 setselect_handler
= rb_setselect_devpoll
;
1881 select_handler
= rb_select_devpoll
;
1882 setup_fd_handler
= rb_setup_fd_devpoll
;
1883 io_sched_event
= NULL
;
1884 io_unsched_event
= NULL
;
1885 io_init_event
= NULL
;
1886 io_supports_event
= rb_unsupported_event
;
1887 rb_strlcpy(iotype
, "devpoll", sizeof(iotype
));
1896 if(!rb_init_netio_sigio())
1898 setselect_handler
= rb_setselect_sigio
;
1899 select_handler
= rb_select_sigio
;
1900 setup_fd_handler
= rb_setup_fd_sigio
;
1901 io_sched_event
= rb_sigio_sched_event
;
1902 io_unsched_event
= rb_sigio_unsched_event
;
1903 io_supports_event
= rb_sigio_supports_event
;
1904 io_init_event
= rb_sigio_init_event
;
1906 rb_strlcpy(iotype
, "sigio", sizeof(iotype
));
1915 if(!rb_init_netio_poll())
1917 setselect_handler
= rb_setselect_poll
;
1918 select_handler
= rb_select_poll
;
1919 setup_fd_handler
= rb_setup_fd_poll
;
1920 io_sched_event
= NULL
;
1921 io_unsched_event
= NULL
;
1922 io_init_event
= NULL
;
1923 io_supports_event
= rb_unsupported_event
;
1924 rb_strlcpy(iotype
, "poll", sizeof(iotype
));
1933 if(!rb_init_netio_win32())
1935 setselect_handler
= rb_setselect_win32
;
1936 select_handler
= rb_select_win32
;
1937 setup_fd_handler
= rb_setup_fd_win32
;
1938 io_sched_event
= NULL
;
1939 io_unsched_event
= NULL
;
1940 io_init_event
= NULL
;
1941 io_supports_event
= rb_unsupported_event
;
1942 rb_strlcpy(iotype
, "win32", sizeof(iotype
));
1951 if(!rb_init_netio_select())
1953 setselect_handler
= rb_setselect_select
;
1954 select_handler
= rb_select_select
;
1955 setup_fd_handler
= rb_setup_fd_select
;
1956 io_sched_event
= NULL
;
1957 io_unsched_event
= NULL
;
1958 io_init_event
= NULL
;
1959 io_supports_event
= rb_unsupported_event
;
1960 rb_strlcpy(iotype
, "select", sizeof(iotype
));
1968 rb_io_sched_event(struct ev_entry
*ev
, int when
)
1970 if(ev
== NULL
|| io_supports_event
== NULL
|| io_sched_event
== NULL
1971 || !io_supports_event())
1973 return io_sched_event(ev
, when
);
1977 rb_io_unsched_event(struct ev_entry
*ev
)
1979 if(ev
== NULL
|| io_supports_event
== NULL
|| io_unsched_event
== NULL
1980 || !io_supports_event())
1982 io_unsched_event(ev
);
1986 rb_io_supports_event(void)
1988 if(io_supports_event
== NULL
)
1990 return io_supports_event();
1994 rb_io_init_event(void)
1997 rb_event_io_register_all();
2003 char *ioenv
= getenv("LIBRB_USE_IOTYPE");
2004 rb_fd_table
= rb_malloc(RB_FD_HASH_SIZE
* sizeof(rb_dlink_list
));
2009 if(!strcmp("epoll", ioenv
))
2014 else if(!strcmp("kqueue", ioenv
))
2019 else if(!strcmp("ports", ioenv
))
2024 else if(!strcmp("poll", ioenv
))
2029 else if(!strcmp("devpoll", ioenv
))
2034 else if(!strcmp("sigio", ioenv
))
2039 else if(!strcmp("select", ioenv
))
2044 if(!strcmp("win32", ioenv
))
2069 rb_lib_log("rb_init_netio: Could not find any io handlers...giving up");
2075 rb_setselect(rb_fde_t
*F
, unsigned int type
, PF
* handler
, void *client_data
)
2077 setselect_handler(F
, type
, handler
, client_data
);
2081 rb_select(unsigned long timeout
)
2083 int ret
= select_handler(timeout
);
2089 rb_setup_fd(rb_fde_t
*F
)
2091 return setup_fd_handler(F
);
2097 rb_ignore_errno(int error
)
2104 #if defined EWOULDBLOCK
2107 #if defined(EAGAIN) && (EWOULDBLOCK != EAGAIN)
2127 #if defined(HAVE_SENDMSG) && !defined(WIN32)
2129 rb_recv_fd_buf(rb_fde_t
*F
, void *data
, size_t datasize
, rb_fde_t
**xF
, int nfds
)
2132 struct cmsghdr
*cmsg
;
2133 struct iovec iov
[1];
2135 uint8_t stype
= RB_FD_UNKNOWN
;
2137 int fd
, len
, x
, rfds
;
2139 int control_len
= CMSG_SPACE(sizeof(int) * nfds
);
2141 iov
[0].iov_base
= data
;
2142 iov
[0].iov_len
= datasize
;
2144 msg
.msg_name
= NULL
;
2145 msg
.msg_namelen
= 0;
2149 cmsg
= alloca(control_len
);
2150 msg
.msg_control
= cmsg
;
2151 msg
.msg_controllen
= control_len
;
2153 if((len
= recvmsg(rb_get_fd(F
), &msg
, 0)) <= 0)
2156 if(msg
.msg_controllen
> 0 && msg
.msg_control
!= NULL
2157 && (cmsg
= CMSG_FIRSTHDR(&msg
)) != NULL
)
2159 rfds
= ((unsigned char *)cmsg
+ cmsg
->cmsg_len
- CMSG_DATA(cmsg
)) / sizeof(int);
2161 for(x
= 0; x
< nfds
&& x
< rfds
; x
++)
2163 fd
= ((int *)CMSG_DATA(cmsg
))[x
];
2164 stype
= RB_FD_UNKNOWN
;
2165 desc
= "remote unknown";
2168 if(S_ISSOCK(st
.st_mode
))
2170 stype
= RB_FD_SOCKET
;
2171 desc
= "remote socket";
2173 else if(S_ISFIFO(st
.st_mode
))
2176 desc
= "remote pipe";
2178 else if(S_ISREG(st
.st_mode
))
2181 desc
= "remote file";
2184 xF
[x
] = rb_open(fd
, stype
, desc
);
2194 rb_send_fd_buf(rb_fde_t
*xF
, rb_fde_t
**F
, int count
, void *data
, size_t datasize
, pid_t pid
)
2198 struct cmsghdr
*cmsg
;
2199 struct iovec iov
[1];
2203 memset(&msg
, 0, sizeof(&msg
));
2206 iov
[0].iov_base
= &empty
;
2211 iov
[0].iov_base
= data
;
2212 iov
[0].iov_len
= datasize
;
2216 msg
.msg_name
= NULL
;
2217 msg
.msg_namelen
= 0;
2219 msg
.msg_control
= NULL
;
2220 msg
.msg_controllen
= 0;
2225 int len
= CMSG_SPACE(sizeof(int) * count
);
2228 msg
.msg_control
= buf
;
2229 msg
.msg_controllen
= len
;
2230 cmsg
= CMSG_FIRSTHDR(&msg
);
2231 cmsg
->cmsg_level
= SOL_SOCKET
;
2232 cmsg
->cmsg_type
= SCM_RIGHTS
;
2233 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int) * count
);
2235 for(i
= 0; i
< count
; i
++)
2237 ((int *)CMSG_DATA(cmsg
))[i
] = rb_get_fd(F
[i
]);
2239 msg
.msg_controllen
= cmsg
->cmsg_len
;
2241 n
= sendmsg(rb_get_fd(xF
), &msg
, MSG_NOSIGNAL
);
2247 rb_recv_fd_buf(rb_fde_t
*F
, void *data
, size_t datasize
, rb_fde_t
**xF
, int nfds
)
2254 rb_send_fd_buf(rb_fde_t
*xF
, rb_fde_t
**F
, int count
, void *data
, size_t datasize
, pid_t pid
)