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
26 #include <librb_config.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
, rb_platform_fd_t sv
[2]);
78 static int rb_inet_socketpair_udp(rb_fde_t
**newF1
, rb_fde_t
**newF2
);
81 static inline rb_fde_t
*
82 add_fd(rb_platform_fd_t fd
)
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
)
117 if(F
->type
& (RB_FD_SOCKET
| RB_FD_PIPE
))
123 rb_dlinkDelete(ptr
, &closed_list
);
124 rb_bh_free(fd_heap
, F
);
128 /* 32bit solaris is kinda slow and stdio only supports fds < 256
129 * so we got to do this crap below.
130 * (BTW Fuck you Sun, I hate your guts and I hope you go bankrupt soon)
133 #if defined (__SVR4) && defined (__sun)
138 if(*fd
> 256 || *fd
< 0)
140 if((newfd
= fcntl(*fd
, F_DUPFD
, 256)) != -1)
148 #define rb_fd_hack(fd)
152 /* close_all_connections() can be used *before* the system come up! */
160 /* XXX someone tell me why we care about 4 fd's ? */
161 /* XXX btw, fd 3 is used for profiler ! */
162 for(i
= 3; i
< rb_maxconnections
; ++i
)
170 * get_sockerr - get the error value from the socket or the current errno
172 * Get the *real* error from the socket (well try to anyway..).
173 * This may only work when SO_DEBUG is enabled but its worth the
177 rb_get_sockerr(rb_fde_t
*F
)
181 rb_socklen_t len
= sizeof(err
);
183 if(!(F
->type
& RB_FD_SOCKET
))
191 && !getsockopt(rb_get_fd(F
), SOL_SOCKET
, SO_ERROR
, (char *)&err
, (rb_socklen_t
*) & len
))
202 * rb_getmaxconnect - return the max number of connections allowed
205 rb_getmaxconnect(void)
207 return (rb_maxconnections
);
211 * set_sock_buffers - set send and receive buffers for socket
213 * inputs - fd file descriptor
215 * output - returns true (1) if successful, false (0) otherwise
219 rb_set_buffers(rb_fde_t
*F
, int size
)
224 (F
->fd
, SOL_SOCKET
, SO_RCVBUF
, (char *)&size
, sizeof(size
))
225 || setsockopt(F
->fd
, SOL_SOCKET
, SO_SNDBUF
, (char *)&size
, sizeof(size
)))
231 * set_non_blocking - Set the client connection into non-blocking mode.
233 * inputs - fd to set into non blocking mode
234 * output - 1 if successful 0 if not
235 * side effects - use POSIX compliant non blocking and
239 rb_set_nb(rb_fde_t
*F
)
248 if((res
= rb_setup_fd(F
)))
252 res
= fcntl(fd
, F_GETFL
, 0);
253 if(-1 == res
|| fcntl(fd
, F_SETFL
, res
| nonb
) == -1)
258 if(ioctl(fd
, FIONBIO
, (char *)&nonb
) == -1)
266 * rb_settimeout() - set the socket timeout
268 * Set the timeout for the fd
271 rb_settimeout(rb_fde_t
*F
, time_t timeout
, PF
* callback
, void *cbdata
)
273 struct timeout_data
*td
;
278 lrb_assert(IsFDOpen(F
));
280 if(callback
== NULL
) /* user wants to remove */
284 rb_dlinkDelete(&td
->node
, &timeout_list
);
287 if(rb_dlink_list_length(&timeout_list
) == 0)
289 rb_event_delete(rb_timeout_ev
);
290 rb_timeout_ev
= NULL
;
295 if(F
->timeout
== NULL
)
296 td
= F
->timeout
= rb_malloc(sizeof(struct timeout_data
));
299 td
->timeout
= rb_current_time() + timeout
;
300 td
->timeout_handler
= callback
;
301 td
->timeout_data
= cbdata
;
302 rb_dlinkAdd(td
, &td
->node
, &timeout_list
);
303 if(rb_timeout_ev
== NULL
)
305 rb_timeout_ev
= rb_event_add("rb_checktimeouts", rb_checktimeouts
, NULL
, 5);
310 * rb_checktimeouts() - check the socket timeouts
312 * All this routine does is call the given callback/cbdata, without closing
313 * down the file descriptor. When close handlers have been implemented,
317 rb_checktimeouts(void *notused
)
319 rb_dlink_node
*ptr
, *next
;
320 struct timeout_data
*td
;
325 RB_DLINK_FOREACH_SAFE(ptr
, next
, timeout_list
.head
)
329 if(F
== NULL
|| !IsFDOpen(F
))
332 if(td
->timeout
< rb_current_time())
334 hdl
= td
->timeout_handler
;
335 data
= td
->timeout_data
;
336 rb_dlinkDelete(&td
->node
, &timeout_list
);
345 rb_accept_tryaccept(rb_fde_t
*F
, void *data
)
347 struct rb_sockaddr_storage st
;
349 rb_socklen_t addrlen
= sizeof(st
);
354 new_fd
= accept(F
->fd
, (struct sockaddr
*)&st
, &addrlen
);
358 rb_setselect(F
, RB_SELECT_ACCEPT
, rb_accept_tryaccept
, NULL
);
364 new_F
= rb_open(new_fd
, RB_FD_SOCKET
, "Incoming Connection");
369 ("rb_accept: new_F == NULL on incoming connection. Closing new_fd == %d\n",
375 if(rb_unlikely(!rb_set_nb(new_F
)))
378 rb_lib_log("rb_accept: Couldn't set FD %d non blocking!", new_F
->fd
);
383 mangle_mapped_sockaddr((struct sockaddr
*)&st
);
386 if(F
->accept
->precb
!= NULL
)
388 if(!F
->accept
->precb(new_F
, (struct sockaddr
*)&st
, addrlen
, F
->accept
->data
)) /* pre-callback decided to drop it */
392 if(F
->type
& RB_FD_SSL
)
394 rb_ssl_accept_setup(F
, new_F
, (struct sockaddr
*)&st
, addrlen
);
397 #endif /* HAVE_SSL */
399 F
->accept
->callback(new_F
, RB_OK
, (struct sockaddr
*)&st
, addrlen
,
406 /* try to accept a TCP connection */
408 rb_accept_tcp(rb_fde_t
*F
, ACPRE
* precb
, ACCB
* callback
, void *data
)
412 lrb_assert(callback
);
414 F
->accept
= rb_malloc(sizeof(struct acceptdata
));
415 F
->accept
->callback
= callback
;
416 F
->accept
->data
= data
;
417 F
->accept
->precb
= precb
;
418 rb_accept_tryaccept(F
, NULL
);
422 * void rb_connect_tcp(rb_platform_fd_t fd, struct sockaddr *dest,
423 * struct sockaddr *clocal,
424 * CNCB *callback, void *data, int timeout)
425 * Input: An fd to connect with, a host and port to connect to,
426 * a local sockaddr to connect from (or NULL to use the
427 * default), a callback, the data to pass into the callback, the
430 * Side-effects: A non-blocking connection to the host is started, and
431 * if necessary, set up for selection. The callback given
432 * may be called now, or it may be called later.
435 rb_connect_tcp(rb_fde_t
*F
, struct sockaddr
*dest
,
436 struct sockaddr
*clocal
, CNCB
* callback
, void *data
, int timeout
)
441 lrb_assert(callback
);
442 F
->connect
= rb_malloc(sizeof(struct conndata
));
443 F
->connect
->callback
= callback
;
444 F
->connect
->data
= data
;
446 memcpy(&F
->connect
->hostaddr
, dest
, sizeof(F
->connect
->hostaddr
));
448 /* Note that we're using a passed sockaddr here. This is because
449 * generally you'll be bind()ing to a sockaddr grabbed from
450 * getsockname(), so this makes things easier.
451 * XXX If NULL is passed as local, we should later on bind() to the
452 * virtual host IP, for completeness.
455 if((clocal
!= NULL
) && (bind(F
->fd
, clocal
, GET_SS_LEN(clocal
)) < 0))
457 /* Failure, call the callback with RB_ERR_BIND */
458 rb_connect_callback(F
, RB_ERR_BIND
);
463 /* We have a valid IP, so we just call tryconnect */
464 /* Make sure we actually set the timeout here .. */
465 rb_settimeout(F
, timeout
, rb_connect_timeout
, NULL
);
466 rb_connect_tryconnect(F
, NULL
);
471 * rb_connect_callback() - call the callback, and continue with life
474 rb_connect_callback(rb_fde_t
*F
, int status
)
478 int errtmp
= errno
; /* save errno as rb_settimeout clobbers it sometimes */
480 /* This check is gross..but probably necessary */
481 if(F
== NULL
|| F
->connect
== NULL
|| F
->connect
->callback
== NULL
)
483 /* Clear the connect flag + handler */
484 hdl
= F
->connect
->callback
;
485 data
= F
->connect
->data
;
486 F
->connect
->callback
= NULL
;
489 /* Clear the timeout handler */
490 rb_settimeout(F
, 0, NULL
, NULL
);
492 /* Call the handler */
493 hdl(F
, status
, data
);
498 * rb_connect_timeout() - this gets called when the socket connection
499 * times out. This *only* can be called once connect() is initially
503 rb_connect_timeout(rb_fde_t
*F
, void *notused
)
506 rb_connect_callback(F
, RB_ERR_TIMEOUT
);
509 /* static void rb_connect_tryconnect(rb_platform_fd_t fd, void *notused)
510 * Input: The fd, the handler data(unused).
512 * Side-effects: Try and connect with pending connect data for the FD. If
513 * we succeed or get a fatal error, call the callback.
514 * Otherwise, it is still blocking or something, so register
515 * to select for a write event on this FD.
518 rb_connect_tryconnect(rb_fde_t
*F
, void *notused
)
522 if(F
== NULL
|| F
->connect
== NULL
|| F
->connect
->callback
== NULL
)
524 /* Try the connect() */
525 retval
= connect(F
->fd
,
526 (struct sockaddr
*)&F
->connect
->hostaddr
,
527 GET_SS_LEN(&F
->connect
->hostaddr
));
532 * If we get EISCONN, then we've already connect()ed the socket,
533 * which is a good thing.
538 rb_connect_callback(F
, RB_OK
);
539 else if(rb_ignore_errno(errno
))
540 /* Ignore error? Reschedule */
541 rb_setselect(F
, RB_SELECT_CONNECT
, rb_connect_tryconnect
, NULL
);
543 /* Error? Fail with RB_ERR_CONNECT */
544 rb_connect_callback(F
, RB_ERR_CONNECT
);
547 /* If we get here, we've suceeded, so call with RB_OK */
548 rb_connect_callback(F
, RB_OK
);
553 rb_connect_sockaddr(rb_fde_t
*F
, struct sockaddr
*addr
, int len
)
558 memcpy(addr
, &F
->connect
->hostaddr
, len
);
563 * rb_error_str() - return an error string for the given error condition
568 if(error
< 0 || error
>= RB_ERR_MAX
)
569 return "Invalid error number!";
570 return rb_err_str
[error
];
575 rb_socketpair(int family
, int sock_type
, int proto
, rb_fde_t
**F1
, rb_fde_t
**F2
, const char *note
)
577 rb_platform_fd_t nfd
[2];
578 if(number_fd
>= rb_maxconnections
)
584 #ifdef HAVE_SOCKETPAIR
585 if(socketpair(family
, sock_type
, proto
, nfd
))
587 if(sock_type
== SOCK_DGRAM
)
589 return rb_inet_socketpair_udp(F1
, F2
);
592 if(rb_inet_socketpair(AF_INET
, sock_type
, proto
, nfd
))
599 *F1
= rb_open(nfd
[0], RB_FD_SOCKET
, note
);
600 *F2
= rb_open(nfd
[1], RB_FD_SOCKET
, note
);
615 /* Set the socket non-blocking, and other wonderful bits */
616 if(rb_unlikely(!rb_set_nb(*F1
)))
618 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd
[0], strerror(errno
));
624 if(rb_unlikely(!rb_set_nb(*F2
)))
626 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd
[1], strerror(errno
));
637 rb_pipe(rb_fde_t
**F1
, rb_fde_t
**F2
, const char *desc
)
640 rb_platform_fd_t fd
[2];
641 if(number_fd
>= rb_maxconnections
)
650 *F1
= rb_open(fd
[0], RB_FD_PIPE
, desc
);
651 *F2
= rb_open(fd
[1], RB_FD_PIPE
, desc
);
653 if(rb_unlikely(!rb_set_nb(*F1
)))
655 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
[0], strerror(errno
));
661 if(rb_unlikely(!rb_set_nb(*F2
)))
663 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
[1], strerror(errno
));
672 /* Its not a pipe..but its selectable. I'll take dirty hacks
675 return rb_socketpair(AF_INET
, SOCK_STREAM
, 0, F1
, F2
, desc
);
680 * rb_socket() - open a socket
682 * This is a highly highly cut down version of squid's rb_open() which
683 * for the most part emulates socket(), *EXCEPT* it fails if we're about
684 * to run out of file descriptors.
687 rb_socket(int family
, int sock_type
, int proto
, const char *note
)
691 /* First, make sure we aren't going to run out of file descriptors */
692 if(rb_unlikely(number_fd
>= rb_maxconnections
))
699 * Next, we try to open the socket. We *should* drop the reserved FD
700 * limit if/when we get an error, but we can deal with that later.
703 fd
= socket(family
, sock_type
, proto
);
705 if(rb_unlikely(fd
< 0))
706 return NULL
; /* errno will be passed through, yay.. */
708 #if defined(RB_IPV6) && defined(IPV6_V6ONLY)
710 * Make sure we can take both IPv4 and IPv6 connections
711 * on an AF_INET6 socket
713 if(family
== AF_INET6
)
716 if(setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, (void *) &off
, sizeof(off
)) == -1)
718 rb_lib_log("rb_socket: Could not set IPV6_V6ONLY option to 1 on FD %d: %s",
719 fd
, strerror(errno
));
726 F
= rb_open(fd
, RB_FD_SOCKET
, note
);
729 rb_lib_log("rb_socket: rb_open returns NULL on FD %d: %s, closing fd", fd
,
734 /* Set the socket non-blocking, and other wonderful bits */
735 if(rb_unlikely(!rb_set_nb(F
)))
737 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
, strerror(errno
));
746 * If a sockaddr_storage is AF_INET6 but is a mapped IPv4
747 * socket manged the sockaddr.
751 mangle_mapped_sockaddr(struct sockaddr
*in
)
753 struct sockaddr_in6
*in6
= (struct sockaddr_in6
*)in
;
755 if(in
->sa_family
== AF_INET
)
758 if(in
->sa_family
== AF_INET6
&& IN6_IS_ADDR_V4MAPPED(&in6
->sin6_addr
))
760 struct sockaddr_in in4
;
761 memset(&in4
, 0, sizeof(struct sockaddr_in
));
762 in4
.sin_family
= AF_INET
;
763 in4
.sin_port
= in6
->sin6_port
;
764 in4
.sin_addr
.s_addr
= ((uint32_t *)&in6
->sin6_addr
)[3];
765 memcpy(in
, &in4
, sizeof(struct sockaddr_in
));
772 * rb_listen() - listen on a port
775 rb_listen(rb_fde_t
*F
, int backlog
, int defer_accept
)
779 F
->type
= RB_FD_SOCKET
| RB_FD_LISTEN
;
780 result
= listen(F
->fd
, backlog
);
782 #ifdef TCP_DEFER_ACCEPT
783 if (defer_accept
&& !result
)
785 (void)setsockopt(F
->fd
, IPPROTO_TCP
, TCP_DEFER_ACCEPT
, &backlog
, sizeof(int));
788 #ifdef SO_ACCEPTFILTER
789 if (defer_accept
&& !result
)
791 struct accept_filter_arg afa
;
793 memset(&afa
, '\0', sizeof afa
);
794 rb_strlcpy(afa
.af_name
, "dataready", sizeof afa
.af_name
);
795 (void)setsockopt(F
->fd
, SOL_SOCKET
, SO_ACCEPTFILTER
, &afa
,
804 rb_fdlist_init(int closeall
, int maxfds
, size_t heapsize
)
806 static int initialized
= 0;
810 int vers
= MAKEWORD(2, 0);
812 err
= WSAStartup(vers
, &wsaData
);
815 rb_lib_die("WSAStartup failed");
821 rb_maxconnections
= maxfds
;
824 /* Since we're doing this once .. */
827 fd_heap
= rb_bh_create(sizeof(rb_fde_t
), heapsize
, "librb_fd_heap");
832 /* Called to open a given filedescriptor */
834 rb_open(rb_platform_fd_t fd
, uint8_t type
, const char *desc
)
841 lrb_assert(!IsFDOpen(F
));
842 if(rb_unlikely(IsFDOpen(F
)))
845 if(F
!= NULL
&& F
->desc
!= NULL
)
849 rb_lib_log("Trying to rb_open an already open FD: %d desc: %s", fd
, fdesc
);
857 F
->desc
= rb_strndup(desc
, FD_DESC_SZ
);
863 /* Called to close a given filedescriptor */
865 rb_close(rb_fde_t
*F
)
874 lrb_assert(IsFDOpen(F
));
876 lrb_assert(!(type
& RB_FD_FILE
));
877 if(rb_unlikely(type
& RB_FD_FILE
))
879 lrb_assert(F
->read_handler
== NULL
);
880 lrb_assert(F
->write_handler
== NULL
);
882 rb_setselect(F
, RB_SELECT_WRITE
| RB_SELECT_READ
, NULL
, NULL
);
883 rb_settimeout(F
, 0, NULL
, NULL
);
892 #endif /* HAVE_SSL */
899 if(type
& RB_FD_LISTEN
)
900 shutdown(fd
, SHUT_RDWR
);
905 * rb_dump_fd() - dump the list of active filedescriptors
908 rb_dump_fd(DUMPCB
* cb
, void *data
)
910 static const char *empty
= "";
912 rb_dlink_list
*bucket
;
916 for(i
= 0; i
< RB_FD_HASH_SIZE
; i
++)
918 bucket
= &rb_fd_table
[i
];
920 if(rb_dlink_list_length(bucket
) <= 0)
923 RB_DLINK_FOREACH(ptr
, bucket
->head
)
926 if(F
== NULL
|| !IsFDOpen(F
))
929 cb(F
->fd
, F
->desc
? F
->desc
: empty
, data
);
935 * rb_note() - set the fd note
937 * Note: must be careful not to overflow rb_fd_table[fd].desc when
941 rb_note(rb_fde_t
*F
, const char *string
)
947 F
->desc
= rb_strndup(string
, FD_DESC_SZ
);
951 rb_set_type(rb_fde_t
*F
, uint8_t type
)
953 /* if the caller is calling this, lets assume they have a clue */
959 rb_get_type(rb_fde_t
*F
)
965 rb_fd_ssl(rb_fde_t
*F
)
969 if(F
->type
& RB_FD_SSL
)
975 rb_get_fd(rb_fde_t
*F
)
983 rb_get_fde(rb_platform_fd_t fd
)
985 return rb_find_fd(fd
);
989 rb_read(rb_fde_t
*F
, void *buf
, int count
)
995 /* This needs to be *before* RB_FD_SOCKET otherwise you'll process
996 * an SSL socket as a regular socket
999 if(F
->type
& RB_FD_SSL
)
1001 return rb_ssl_read(F
, buf
, count
);
1004 if(F
->type
& RB_FD_SOCKET
)
1006 ret
= recv(F
->fd
, buf
, count
, 0);
1016 return read(F
->fd
, buf
, count
);
1021 rb_write(rb_fde_t
*F
, const void *buf
, int count
)
1028 if(F
->type
& RB_FD_SSL
)
1030 return rb_ssl_write(F
, buf
, count
);
1033 if(F
->type
& RB_FD_SOCKET
)
1035 ret
= send(F
->fd
, buf
, count
, MSG_NOSIGNAL
);
1043 return write(F
->fd
, buf
, count
);
1046 #if defined(HAVE_SSL) || defined(WIN32) || !defined(HAVE_WRITEV)
1048 rb_fake_writev(rb_fde_t
*F
, const struct rb_iovec
*vp
, size_t vpcount
)
1052 while(vpcount
-- > 0)
1054 ssize_t written
= rb_write(F
, vp
->iov_base
, vp
->iov_len
);
1070 #if defined(WIN32) || !defined(HAVE_WRITEV)
1072 rb_writev(rb_fde_t
*F
, struct rb_iovec
* vecount
, int count
)
1074 return rb_fake_writev(F
, vecount
, count
);
1079 rb_writev(rb_fde_t
*F
, struct rb_iovec
* vector
, int count
)
1087 if(F
->type
& RB_FD_SSL
)
1089 return rb_fake_writev(F
, vector
, count
);
1091 #endif /* HAVE_SSL */
1093 if(F
->type
& RB_FD_SOCKET
)
1096 memset(&msg
, 0, sizeof(msg
));
1097 msg
.msg_iov
= (struct iovec
*)vector
;
1098 msg
.msg_iovlen
= count
;
1099 return sendmsg(F
->fd
, &msg
, MSG_NOSIGNAL
);
1101 #endif /* HAVE_SENDMSG */
1102 return writev(F
->fd
, (struct iovec
*)vector
, count
);
1109 * From: Thomas Helvey <tomh@inxpress.net>
1111 static const char *IpQuadTab
[] = {
1112 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
1113 "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
1114 "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
1115 "30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
1116 "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
1117 "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
1118 "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
1119 "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
1120 "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
1121 "90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
1122 "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
1123 "110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
1124 "120", "121", "122", "123", "124", "125", "126", "127", "128", "129",
1125 "130", "131", "132", "133", "134", "135", "136", "137", "138", "139",
1126 "140", "141", "142", "143", "144", "145", "146", "147", "148", "149",
1127 "150", "151", "152", "153", "154", "155", "156", "157", "158", "159",
1128 "160", "161", "162", "163", "164", "165", "166", "167", "168", "169",
1129 "170", "171", "172", "173", "174", "175", "176", "177", "178", "179",
1130 "180", "181", "182", "183", "184", "185", "186", "187", "188", "189",
1131 "190", "191", "192", "193", "194", "195", "196", "197", "198", "199",
1132 "200", "201", "202", "203", "204", "205", "206", "207", "208", "209",
1133 "210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
1134 "220", "221", "222", "223", "224", "225", "226", "227", "228", "229",
1135 "230", "231", "232", "233", "234", "235", "236", "237", "238", "239",
1136 "240", "241", "242", "243", "244", "245", "246", "247", "248", "249",
1137 "250", "251", "252", "253", "254", "255"
1141 * inetntoa - in_addr to string
1142 * changed name to remove collision possibility and
1143 * so behaviour is guaranteed to take a pointer arg.
1145 * inet_ntoa -- returned the dotted notation of a given
1148 * inet_ntoa -- its broken on some Ultrix/Dynix too. -avalon
1152 inetntoa(const char *in
)
1154 static char buf
[16];
1156 const unsigned char *a
= (const unsigned char *)in
;
1159 n
= IpQuadTab
[*a
++];
1163 n
= IpQuadTab
[*a
++];
1167 n
= IpQuadTab
[*a
++];
1179 * WARNING: Don't even consider trying to compile this on a system where
1180 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
1183 static const char *inet_ntop4(const unsigned char *src
, char *dst
, unsigned int size
);
1185 static const char *inet_ntop6(const unsigned char *src
, char *dst
, unsigned int size
);
1189 * inet_ntop4(src, dst, size)
1190 * format an IPv4 address
1192 * `dst' (as a const)
1194 * (1) uses no statics
1195 * (2) takes a unsigned char* not an in_addr as input
1200 inet_ntop4(const unsigned char *src
, char *dst
, unsigned int size
)
1204 return strcpy(dst
, inetntoa((const char *)src
));
1208 * inet_ntop6(src, dst, size)
1209 * convert IPv6 binary address into presentation (printable) format
1215 inet_ntop6(const unsigned char *src
, char *dst
, unsigned int size
)
1218 * Note that int32_t and int16_t need only be "at least" large enough
1219 * to contain a value of the specified size. On some systems, like
1220 * Crays, there is no such thing as an integer variable with 16 bits.
1221 * Keep this in mind if you think this function should have been coded
1222 * to use pointer overlays. All the world's not a VAX.
1224 char tmp
[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp
;
1230 unsigned int words
[IN6ADDRSZ
/ INT16SZ
];
1235 * Copy the input (bytewise) array into a wordwise array.
1236 * Find the longest run of 0x00's in src[] for :: shorthanding.
1238 memset(words
, '\0', sizeof words
);
1239 for(i
= 0; i
< IN6ADDRSZ
; i
+= 2)
1240 words
[i
/ 2] = (src
[i
] << 8) | src
[i
+ 1];
1245 for(i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++)
1250 cur
.base
= i
, cur
.len
= 1;
1258 if(best
.base
== -1 || cur
.len
> best
.len
)
1266 if(best
.base
== -1 || cur
.len
> best
.len
)
1269 if(best
.base
!= -1 && best
.len
< 2)
1273 * Format the result.
1276 for(i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++)
1278 /* Are we inside the best run of 0x00's? */
1279 if(best
.base
!= -1 && i
>= best
.base
&& i
< (best
.base
+ best
.len
))
1289 /* Are we following an initial run of 0x00s or any real hex? */
1292 /* Is this address an encapsulated IPv4? */
1293 if(i
== 6 && best
.base
== 0 &&
1294 (best
.len
== 6 || (best
.len
== 5 && words
[5] == 0xffff)))
1296 if(!inet_ntop4(src
+ 12, tp
, sizeof tmp
- (tp
- tmp
)))
1301 tp
+= sprintf(tp
, "%x", words
[i
]);
1303 /* Was it a trailing run of 0x00's? */
1304 if(best
.base
!= -1 && (best
.base
+ best
.len
) == (IN6ADDRSZ
/ INT16SZ
))
1309 * Check for overflow, copy, and we're done.
1312 if((unsigned int)(tp
- tmp
) > size
)
1316 return memcpy(dst
, tmp
, tp
- tmp
);
1321 rb_inet_pton_sock(const char *src
, struct sockaddr
*dst
)
1323 if(rb_inet_pton(AF_INET
, src
, &((struct sockaddr_in
*)dst
)->sin_addr
))
1325 SET_SS_FAMILY(dst
, AF_INET
);
1326 SET_SS_PORT(dst
, 0);
1327 SET_SS_LEN(dst
, sizeof(struct sockaddr_in
));
1331 else if(rb_inet_pton(AF_INET6
, src
, &((struct sockaddr_in6
*)dst
)->sin6_addr
))
1333 SET_SS_FAMILY(dst
, AF_INET6
);
1334 SET_SS_PORT(dst
, 0);
1335 SET_SS_LEN(dst
, sizeof(struct sockaddr_in6
));
1343 rb_inet_ntop_sock(struct sockaddr
*src
, char *dst
, unsigned int size
)
1345 switch (src
->sa_family
)
1348 return (rb_inet_ntop(AF_INET
, &((struct sockaddr_in
*)src
)->sin_addr
, dst
, size
));
1351 return (rb_inet_ntop
1352 (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((unsigned char)*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 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
);
1610 rb_platform_fd_t fd
[2];
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 #ifndef ECONNABORTED
1695 #define ECONNABORTED WSAECONNABORTED
1701 errno
= ECONNABORTED
;
1703 if(errno
!= ECONNABORTED
)
1716 rb_inet_socketpair(int family
, int type
, int protocol
, rb_platform_fd_t fd
[2])
1721 struct sockaddr_in listen_addr
;
1722 struct sockaddr_in connect_addr
;
1725 if(protocol
|| family
!= AF_INET
)
1727 errno
= EAFNOSUPPORT
;
1736 listener
= socket(AF_INET
, type
, 0);
1739 memset(&listen_addr
, 0, sizeof(listen_addr
));
1740 listen_addr
.sin_family
= AF_INET
;
1741 listen_addr
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
1742 listen_addr
.sin_port
= 0; /* kernel choses port. */
1743 if(bind(listener
, (struct sockaddr
*)&listen_addr
, sizeof(listen_addr
)) == -1)
1744 goto tidy_up_and_fail
;
1745 if(listen(listener
, 1) == -1)
1746 goto tidy_up_and_fail
;
1748 connector
= socket(AF_INET
, type
, 0);
1750 goto tidy_up_and_fail
;
1751 /* We want to find out the port number to connect to. */
1752 size
= sizeof(connect_addr
);
1753 if(getsockname(listener
, (struct sockaddr
*)&connect_addr
, &size
) == -1)
1754 goto tidy_up_and_fail
;
1755 if(size
!= sizeof(connect_addr
))
1756 goto abort_tidy_up_and_fail
;
1757 if(connect(connector
, (struct sockaddr
*)&connect_addr
, sizeof(connect_addr
)) == -1)
1758 goto tidy_up_and_fail
;
1760 size
= sizeof(listen_addr
);
1761 acceptor
= accept(listener
, (struct sockaddr
*)&listen_addr
, &size
);
1763 goto tidy_up_and_fail
;
1764 if(size
!= sizeof(listen_addr
))
1765 goto abort_tidy_up_and_fail
;
1767 /* Now check we are talking to ourself by matching port and host on the
1769 if(getsockname(connector
, (struct sockaddr
*)&connect_addr
, &size
) == -1)
1770 goto tidy_up_and_fail
;
1771 if(size
!= sizeof(connect_addr
)
1772 || listen_addr
.sin_family
!= connect_addr
.sin_family
1773 || listen_addr
.sin_addr
.s_addr
!= connect_addr
.sin_addr
.s_addr
1774 || listen_addr
.sin_port
!= connect_addr
.sin_port
)
1776 goto abort_tidy_up_and_fail
;
1782 abort_tidy_up_and_fail
:
1783 errno
= EINVAL
; /* I hope this is portable and appropriate. */
1787 int save_errno
= errno
;
1802 static void (*setselect_handler
) (rb_fde_t
*, unsigned int, PF
*, void *);
1803 static int (*select_handler
) (long);
1804 static int (*setup_fd_handler
) (rb_fde_t
*);
1805 static int (*io_sched_event
) (struct ev_entry
*, int);
1806 static void (*io_unsched_event
) (struct ev_entry
*);
1807 static int (*io_supports_event
) (void);
1808 static void (*io_init_event
) (void);
1809 static char iotype
[25];
1818 rb_unsupported_event(void)
1826 if(!rb_init_netio_kqueue())
1828 setselect_handler
= rb_setselect_kqueue
;
1829 select_handler
= rb_select_kqueue
;
1830 setup_fd_handler
= rb_setup_fd_kqueue
;
1831 io_sched_event
= rb_kqueue_sched_event
;
1832 io_unsched_event
= rb_kqueue_unsched_event
;
1833 io_init_event
= rb_kqueue_init_event
;
1834 io_supports_event
= rb_kqueue_supports_event
;
1835 rb_strlcpy(iotype
, "kqueue", sizeof(iotype
));
1844 if(!rb_init_netio_epoll())
1846 setselect_handler
= rb_setselect_epoll
;
1847 select_handler
= rb_select_epoll
;
1848 setup_fd_handler
= rb_setup_fd_epoll
;
1849 io_sched_event
= rb_epoll_sched_event
;
1850 io_unsched_event
= rb_epoll_unsched_event
;
1851 io_supports_event
= rb_epoll_supports_event
;
1852 io_init_event
= rb_epoll_init_event
;
1853 rb_strlcpy(iotype
, "epoll", sizeof(iotype
));
1862 if(!rb_init_netio_ports())
1864 setselect_handler
= rb_setselect_ports
;
1865 select_handler
= rb_select_ports
;
1866 setup_fd_handler
= rb_setup_fd_ports
;
1867 io_sched_event
= rb_ports_sched_event
;
1868 io_unsched_event
= rb_ports_unsched_event
;
1869 io_init_event
= rb_ports_init_event
;
1870 io_supports_event
= rb_ports_supports_event
;
1871 rb_strlcpy(iotype
, "ports", sizeof(iotype
));
1880 if(!rb_init_netio_devpoll())
1882 setselect_handler
= rb_setselect_devpoll
;
1883 select_handler
= rb_select_devpoll
;
1884 setup_fd_handler
= rb_setup_fd_devpoll
;
1885 io_sched_event
= NULL
;
1886 io_unsched_event
= NULL
;
1887 io_init_event
= NULL
;
1888 io_supports_event
= rb_unsupported_event
;
1889 rb_strlcpy(iotype
, "devpoll", sizeof(iotype
));
1898 if(!rb_init_netio_sigio())
1900 setselect_handler
= rb_setselect_sigio
;
1901 select_handler
= rb_select_sigio
;
1902 setup_fd_handler
= rb_setup_fd_sigio
;
1903 io_sched_event
= rb_sigio_sched_event
;
1904 io_unsched_event
= rb_sigio_unsched_event
;
1905 io_supports_event
= rb_sigio_supports_event
;
1906 io_init_event
= rb_sigio_init_event
;
1908 rb_strlcpy(iotype
, "sigio", sizeof(iotype
));
1917 if(!rb_init_netio_poll())
1919 setselect_handler
= rb_setselect_poll
;
1920 select_handler
= rb_select_poll
;
1921 setup_fd_handler
= rb_setup_fd_poll
;
1922 io_sched_event
= NULL
;
1923 io_unsched_event
= NULL
;
1924 io_init_event
= NULL
;
1925 io_supports_event
= rb_unsupported_event
;
1926 rb_strlcpy(iotype
, "poll", sizeof(iotype
));
1935 if(!rb_init_netio_win32())
1937 setselect_handler
= rb_setselect_win32
;
1938 select_handler
= rb_select_win32
;
1939 setup_fd_handler
= rb_setup_fd_win32
;
1940 io_sched_event
= NULL
;
1941 io_unsched_event
= NULL
;
1942 io_init_event
= NULL
;
1943 io_supports_event
= rb_unsupported_event
;
1944 rb_strlcpy(iotype
, "win32", sizeof(iotype
));
1953 if(!rb_init_netio_select())
1955 setselect_handler
= rb_setselect_select
;
1956 select_handler
= rb_select_select
;
1957 setup_fd_handler
= rb_setup_fd_select
;
1958 io_sched_event
= NULL
;
1959 io_unsched_event
= NULL
;
1960 io_init_event
= NULL
;
1961 io_supports_event
= rb_unsupported_event
;
1962 rb_strlcpy(iotype
, "select", sizeof(iotype
));
1970 rb_io_sched_event(struct ev_entry
*ev
, int when
)
1972 if(ev
== NULL
|| io_supports_event
== NULL
|| io_sched_event
== NULL
1973 || !io_supports_event())
1975 return io_sched_event(ev
, when
);
1979 rb_io_unsched_event(struct ev_entry
*ev
)
1981 if(ev
== NULL
|| io_supports_event
== NULL
|| io_unsched_event
== NULL
1982 || !io_supports_event())
1984 io_unsched_event(ev
);
1988 rb_io_supports_event(void)
1990 if(io_supports_event
== NULL
)
1992 return io_supports_event();
1996 rb_io_init_event(void)
1999 rb_event_io_register_all();
2005 char *ioenv
= getenv("LIBRB_USE_IOTYPE");
2006 rb_fd_table
= rb_malloc(RB_FD_HASH_SIZE
* sizeof(rb_dlink_list
));
2011 if(!strcmp("epoll", ioenv
))
2016 else if(!strcmp("kqueue", ioenv
))
2021 else if(!strcmp("ports", ioenv
))
2026 else if(!strcmp("poll", ioenv
))
2031 else if(!strcmp("devpoll", ioenv
))
2036 else if(!strcmp("sigio", ioenv
))
2041 else if(!strcmp("select", ioenv
))
2046 if(!strcmp("win32", ioenv
))
2071 rb_lib_log("rb_init_netio: Could not find any io handlers...giving up");
2077 rb_setselect(rb_fde_t
*F
, unsigned int type
, PF
* handler
, void *client_data
)
2079 setselect_handler(F
, type
, handler
, client_data
);
2083 rb_select(unsigned long timeout
)
2085 int ret
= select_handler(timeout
);
2091 rb_setup_fd(rb_fde_t
*F
)
2093 return setup_fd_handler(F
);
2098 rb_ignore_errno(int error
)
2105 #if defined EWOULDBLOCK
2108 #if defined(EAGAIN) && (EWOULDBLOCK != EAGAIN)
2128 #if defined(HAVE_SENDMSG) && !defined(WIN32)
2130 rb_recv_fd_buf(rb_fde_t
*F
, void *data
, size_t datasize
, rb_fde_t
**xF
, int nfds
)
2133 struct cmsghdr
*cmsg
;
2134 struct iovec iov
[1];
2136 uint8_t stype
= RB_FD_UNKNOWN
;
2138 rb_platform_fd_t fd
, len
, x
, rfds
;
2140 int control_len
= CMSG_SPACE(sizeof(int) * nfds
);
2142 iov
[0].iov_base
= data
;
2143 iov
[0].iov_len
= datasize
;
2145 msg
.msg_name
= NULL
;
2146 msg
.msg_namelen
= 0;
2150 cmsg
= alloca(control_len
);
2151 msg
.msg_control
= cmsg
;
2152 msg
.msg_controllen
= control_len
;
2154 if((len
= recvmsg(rb_get_fd(F
), &msg
, 0)) <= 0)
2157 if(msg
.msg_controllen
> 0 && msg
.msg_control
!= NULL
2158 && (cmsg
= CMSG_FIRSTHDR(&msg
)) != NULL
)
2160 rfds
= ((unsigned char *)cmsg
+ cmsg
->cmsg_len
- CMSG_DATA(cmsg
)) / sizeof(int);
2162 for(x
= 0; x
< nfds
&& x
< rfds
; x
++)
2164 fd
= ((int *)CMSG_DATA(cmsg
))[x
];
2165 stype
= RB_FD_UNKNOWN
;
2166 desc
= "remote unknown";
2169 if(S_ISSOCK(st
.st_mode
))
2171 stype
= RB_FD_SOCKET
;
2172 desc
= "remote socket";
2174 else if(S_ISFIFO(st
.st_mode
))
2177 desc
= "remote pipe";
2179 else if(S_ISREG(st
.st_mode
))
2182 desc
= "remote file";
2185 xF
[x
] = rb_open(fd
, stype
, desc
);
2195 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];
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;
2223 size_t ucount
= (size_t)count
;
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(size_t i
= 0; i
< ucount
; i
++)
2236 ((int *)CMSG_DATA(cmsg
))[i
] = rb_get_fd(F
[i
]);
2238 msg
.msg_controllen
= cmsg
->cmsg_len
;
2239 return sendmsg(rb_get_fd(xF
), &msg
, MSG_NOSIGNAL
);
2241 return sendmsg(rb_get_fd(xF
), &msg
, MSG_NOSIGNAL
);
2243 #else /* defined(HAVE_SENDMSG) && !defined(WIN32) */
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
)
2259 #endif /* defined(HAVE_SENDMSG) && !defined(WIN32) */
2263 rb_ipv4_from_ipv6(const struct sockaddr_in6
*restrict ip6
, struct sockaddr_in
*restrict ip4
)
2267 if (!memcmp(ip6
->sin6_addr
.s6_addr
, "\x20\x02", 2))
2269 /* 6to4 and similar */
2270 memcpy(&ip4
->sin_addr
, ip6
->sin6_addr
.s6_addr
+ 2, 4);
2272 else if (!memcmp(ip6
->sin6_addr
.s6_addr
, "\x20\x01\x00\x00", 4))
2275 for (i
= 0; i
< 4; i
++)
2276 ((uint8_t *)&ip4
->sin_addr
)[i
] = 0xFF ^
2277 ip6
->sin6_addr
.s6_addr
[12 + i
];
2281 SET_SS_LEN(ip4
, sizeof(struct sockaddr_in
));
2282 ip4
->sin_family
= AF_INET
;
2288 rb_ipv4_from_ipv6(const struct sockaddr_in6
*restrict ip6
, struct sockaddr_in
*restrict ip4
)
2292 #endif /* RB_IPV6 */