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
;
72 static void mangle_mapped_sockaddr(struct sockaddr
*in
);
74 #ifndef HAVE_SOCKETPAIR
75 static int rb_inet_socketpair(int d
, int type
, int protocol
, rb_platform_fd_t sv
[2]);
76 static int rb_inet_socketpair_udp(rb_fde_t
**newF1
, rb_fde_t
**newF2
);
79 static inline rb_fde_t
*
80 add_fd(rb_platform_fd_t fd
)
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
)
115 if(F
->type
& (RB_FD_SOCKET
| RB_FD_PIPE
))
121 rb_dlinkDelete(ptr
, &closed_list
);
122 rb_bh_free(fd_heap
, F
);
126 /* 32bit solaris is kinda slow and stdio only supports fds < 256
127 * so we got to do this crap below.
128 * (BTW Fuck you Sun, I hate your guts and I hope you go bankrupt soon)
131 #if defined (__SVR4) && defined (__sun)
136 if(*fd
> 256 || *fd
< 0)
138 if((newfd
= fcntl(*fd
, F_DUPFD
, 256)) != -1)
146 #define rb_fd_hack(fd)
150 /* close_all_connections() can be used *before* the system come up! */
158 /* XXX someone tell me why we care about 4 fd's ? */
159 /* XXX btw, fd 3 is used for profiler ! */
160 for(i
= 3; i
< rb_maxconnections
; ++i
)
168 * get_sockerr - get the error value from the socket or the current errno
170 * Get the *real* error from the socket (well try to anyway..).
171 * This may only work when SO_DEBUG is enabled but its worth the
175 rb_get_sockerr(rb_fde_t
*F
)
179 rb_socklen_t len
= sizeof(err
);
181 if(!(F
->type
& RB_FD_SOCKET
))
189 && !getsockopt(rb_get_fd(F
), SOL_SOCKET
, SO_ERROR
, (char *)&err
, (rb_socklen_t
*) & len
))
200 * rb_getmaxconnect - return the max number of connections allowed
203 rb_getmaxconnect(void)
205 return (rb_maxconnections
);
209 * set_sock_buffers - set send and receive buffers for socket
211 * inputs - fd file descriptor
213 * output - returns true (1) if successful, false (0) otherwise
217 rb_set_buffers(rb_fde_t
*F
, int size
)
222 (F
->fd
, SOL_SOCKET
, SO_RCVBUF
, (char *)&size
, sizeof(size
))
223 || setsockopt(F
->fd
, SOL_SOCKET
, SO_SNDBUF
, (char *)&size
, sizeof(size
)))
229 * set_non_blocking - Set the client connection into non-blocking mode.
231 * inputs - fd to set into non blocking mode
232 * output - 1 if successful 0 if not
233 * side effects - use POSIX compliant non blocking and
237 rb_set_nb(rb_fde_t
*F
)
246 if((res
= rb_setup_fd(F
)))
250 res
= fcntl(fd
, F_GETFL
, 0);
251 if(-1 == res
|| fcntl(fd
, F_SETFL
, res
| nonb
) == -1)
256 if(ioctl(fd
, FIONBIO
, (char *)&nonb
) == -1)
264 * rb_settimeout() - set the socket timeout
266 * Set the timeout for the fd
269 rb_settimeout(rb_fde_t
*F
, time_t timeout
, PF
* callback
, void *cbdata
)
271 struct timeout_data
*td
;
276 lrb_assert(IsFDOpen(F
));
278 if(callback
== NULL
) /* user wants to remove */
282 rb_dlinkDelete(&td
->node
, &timeout_list
);
285 if(rb_dlink_list_length(&timeout_list
) == 0)
287 rb_event_delete(rb_timeout_ev
);
288 rb_timeout_ev
= NULL
;
293 if(F
->timeout
== NULL
)
294 td
= F
->timeout
= rb_malloc(sizeof(struct timeout_data
));
297 td
->timeout
= rb_current_time() + timeout
;
298 td
->timeout_handler
= callback
;
299 td
->timeout_data
= cbdata
;
300 rb_dlinkAdd(td
, &td
->node
, &timeout_list
);
301 if(rb_timeout_ev
== NULL
)
303 rb_timeout_ev
= rb_event_add("rb_checktimeouts", rb_checktimeouts
, NULL
, 5);
308 * rb_checktimeouts() - check the socket timeouts
310 * All this routine does is call the given callback/cbdata, without closing
311 * down the file descriptor. When close handlers have been implemented,
315 rb_checktimeouts(void *notused
)
317 rb_dlink_node
*ptr
, *next
;
318 struct timeout_data
*td
;
323 RB_DLINK_FOREACH_SAFE(ptr
, next
, timeout_list
.head
)
327 if(F
== NULL
|| !IsFDOpen(F
))
330 if(td
->timeout
< rb_current_time())
332 hdl
= td
->timeout_handler
;
333 data
= td
->timeout_data
;
334 rb_dlinkDelete(&td
->node
, &timeout_list
);
343 rb_accept_tryaccept(rb_fde_t
*F
, void *data
)
345 struct rb_sockaddr_storage st
;
347 rb_socklen_t addrlen
;
352 memset(&st
, 0, sizeof(st
));
353 addrlen
= sizeof(st
);
355 new_fd
= accept(F
->fd
, (struct sockaddr
*)&st
, &addrlen
);
359 rb_setselect(F
, RB_SELECT_ACCEPT
, rb_accept_tryaccept
, NULL
);
365 new_F
= rb_open(new_fd
, RB_FD_SOCKET
, "Incoming Connection");
370 ("rb_accept: new_F == NULL on incoming connection. Closing new_fd == %d\n",
376 if(rb_unlikely(!rb_set_nb(new_F
)))
379 rb_lib_log("rb_accept: Couldn't set FD %d non blocking!", new_F
->fd
);
383 mangle_mapped_sockaddr((struct sockaddr
*)&st
);
385 if(F
->accept
->precb
!= NULL
)
387 if(!F
->accept
->precb(new_F
, (struct sockaddr
*)&st
, addrlen
, F
->accept
->data
)) /* pre-callback decided to drop it */
391 if(F
->type
& RB_FD_SSL
)
393 rb_ssl_accept_setup(F
, new_F
, (struct sockaddr
*)&st
, addrlen
);
396 #endif /* HAVE_SSL */
398 F
->accept
->callback(new_F
, RB_OK
, (struct sockaddr
*)&st
, addrlen
,
405 /* try to accept a TCP connection */
407 rb_accept_tcp(rb_fde_t
*F
, ACPRE
* precb
, ACCB
* callback
, void *data
)
411 lrb_assert(callback
);
413 F
->accept
= rb_malloc(sizeof(struct acceptdata
));
414 F
->accept
->callback
= callback
;
415 F
->accept
->data
= data
;
416 F
->accept
->precb
= precb
;
417 rb_accept_tryaccept(F
, NULL
);
421 * void rb_connect_tcp(rb_platform_fd_t fd, struct sockaddr *dest,
422 * struct sockaddr *clocal,
423 * CNCB *callback, void *data, int timeout)
424 * Input: An fd to connect with, a host and port to connect to,
425 * a local sockaddr to connect from (or NULL to use the
426 * default), a callback, the data to pass into the callback, the
429 * Side-effects: A non-blocking connection to the host is started, and
430 * if necessary, set up for selection. The callback given
431 * may be called now, or it may be called later.
434 rb_connect_tcp(rb_fde_t
*F
, struct sockaddr
*dest
,
435 struct sockaddr
*clocal
, CNCB
* callback
, void *data
, int timeout
)
440 lrb_assert(callback
);
441 F
->connect
= rb_malloc(sizeof(struct conndata
));
442 F
->connect
->callback
= callback
;
443 F
->connect
->data
= data
;
445 memcpy(&F
->connect
->hostaddr
, dest
, sizeof(F
->connect
->hostaddr
));
447 /* Note that we're using a passed sockaddr here. This is because
448 * generally you'll be bind()ing to a sockaddr grabbed from
449 * getsockname(), so this makes things easier.
450 * XXX If NULL is passed as local, we should later on bind() to the
451 * virtual host IP, for completeness.
454 if((clocal
!= NULL
) && (bind(F
->fd
, clocal
, GET_SS_LEN(clocal
)) < 0))
456 /* Failure, call the callback with RB_ERR_BIND */
457 rb_connect_callback(F
, RB_ERR_BIND
);
462 /* We have a valid IP, so we just call tryconnect */
463 /* Make sure we actually set the timeout here .. */
464 rb_settimeout(F
, timeout
, rb_connect_timeout
, NULL
);
465 rb_connect_tryconnect(F
, NULL
);
470 * rb_connect_callback() - call the callback, and continue with life
473 rb_connect_callback(rb_fde_t
*F
, int status
)
477 int errtmp
= errno
; /* save errno as rb_settimeout clobbers it sometimes */
479 /* This check is gross..but probably necessary */
480 if(F
== NULL
|| F
->connect
== NULL
|| F
->connect
->callback
== NULL
)
482 /* Clear the connect flag + handler */
483 hdl
= F
->connect
->callback
;
484 data
= F
->connect
->data
;
485 F
->connect
->callback
= NULL
;
488 /* Clear the timeout handler */
489 rb_settimeout(F
, 0, NULL
, NULL
);
491 /* Call the handler */
492 hdl(F
, status
, data
);
497 * rb_connect_timeout() - this gets called when the socket connection
498 * times out. This *only* can be called once connect() is initially
502 rb_connect_timeout(rb_fde_t
*F
, void *notused
)
505 rb_connect_callback(F
, RB_ERR_TIMEOUT
);
508 /* static void rb_connect_tryconnect(rb_platform_fd_t fd, void *notused)
509 * Input: The fd, the handler data(unused).
511 * Side-effects: Try and connect with pending connect data for the FD. If
512 * we succeed or get a fatal error, call the callback.
513 * Otherwise, it is still blocking or something, so register
514 * to select for a write event on this FD.
517 rb_connect_tryconnect(rb_fde_t
*F
, void *notused
)
521 if(F
== NULL
|| F
->connect
== NULL
|| F
->connect
->callback
== NULL
)
523 /* Try the connect() */
524 retval
= connect(F
->fd
,
525 (struct sockaddr
*)&F
->connect
->hostaddr
,
526 GET_SS_LEN(&F
->connect
->hostaddr
));
531 * If we get EISCONN, then we've already connect()ed the socket,
532 * which is a good thing.
537 rb_connect_callback(F
, RB_OK
);
538 else if(rb_ignore_errno(errno
))
539 /* Ignore error? Reschedule */
540 rb_setselect(F
, RB_SELECT_CONNECT
, rb_connect_tryconnect
, NULL
);
542 /* Error? Fail with RB_ERR_CONNECT */
543 rb_connect_callback(F
, RB_ERR_CONNECT
);
546 /* If we get here, we've suceeded, so call with RB_OK */
547 rb_connect_callback(F
, RB_OK
);
552 rb_connect_sockaddr(rb_fde_t
*F
, struct sockaddr
*addr
, int len
)
557 memcpy(addr
, &F
->connect
->hostaddr
, len
);
562 * rb_error_str() - return an error string for the given error condition
567 if(error
< 0 || error
>= RB_ERR_MAX
)
568 return "Invalid error number!";
569 return rb_err_str
[error
];
574 rb_socketpair(int family
, int sock_type
, int proto
, rb_fde_t
**F1
, rb_fde_t
**F2
, const char *note
)
576 rb_platform_fd_t nfd
[2];
577 if(number_fd
>= rb_maxconnections
)
583 #ifdef HAVE_SOCKETPAIR
584 if(socketpair(family
, sock_type
, proto
, nfd
))
586 if(sock_type
== SOCK_DGRAM
)
588 return rb_inet_socketpair_udp(F1
, F2
);
591 if(rb_inet_socketpair(AF_INET
, sock_type
, proto
, nfd
))
598 *F1
= rb_open(nfd
[0], RB_FD_SOCKET
, note
);
599 *F2
= rb_open(nfd
[1], RB_FD_SOCKET
, note
);
614 /* Set the socket non-blocking, and other wonderful bits */
615 if(rb_unlikely(!rb_set_nb(*F1
)))
617 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd
[0], strerror(errno
));
623 if(rb_unlikely(!rb_set_nb(*F2
)))
625 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd
[1], strerror(errno
));
636 rb_pipe(rb_fde_t
**F1
, rb_fde_t
**F2
, const char *desc
)
639 rb_platform_fd_t fd
[2];
640 if(number_fd
>= rb_maxconnections
)
649 *F1
= rb_open(fd
[0], RB_FD_PIPE
, desc
);
650 *F2
= rb_open(fd
[1], RB_FD_PIPE
, desc
);
652 if(rb_unlikely(!rb_set_nb(*F1
)))
654 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
[0], strerror(errno
));
660 if(rb_unlikely(!rb_set_nb(*F2
)))
662 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
[1], strerror(errno
));
671 /* Its not a pipe..but its selectable. I'll take dirty hacks
674 return rb_socketpair(AF_INET
, SOCK_STREAM
, 0, F1
, F2
, desc
);
679 * rb_socket() - open a socket
681 * This is a highly highly cut down version of squid's rb_open() which
682 * for the most part emulates socket(), *EXCEPT* it fails if we're about
683 * to run out of file descriptors.
686 rb_socket(int family
, int sock_type
, int proto
, const char *note
)
690 /* First, make sure we aren't going to run out of file descriptors */
691 if(rb_unlikely(number_fd
>= rb_maxconnections
))
698 * Next, we try to open the socket. We *should* drop the reserved FD
699 * limit if/when we get an error, but we can deal with that later.
702 fd
= socket(family
, sock_type
, proto
);
704 if(rb_unlikely(fd
< 0))
705 return NULL
; /* errno will be passed through, yay.. */
708 * Make sure we can take both IPv4 and IPv6 connections
709 * on an AF_INET6 socket
711 if(family
== AF_INET6
)
714 if(setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, (void *) &off
, sizeof(off
)) == -1)
716 rb_lib_log("rb_socket: Could not set IPV6_V6ONLY option to 1 on FD %d: %s",
717 fd
, strerror(errno
));
723 F
= rb_open(fd
, RB_FD_SOCKET
, note
);
726 rb_lib_log("rb_socket: rb_open returns NULL on FD %d: %s, closing fd", fd
,
731 /* Set the socket non-blocking, and other wonderful bits */
732 if(rb_unlikely(!rb_set_nb(F
)))
734 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
, strerror(errno
));
743 * If a sockaddr_storage is AF_INET6 but is a mapped IPv4
744 * socket manged the sockaddr.
747 mangle_mapped_sockaddr(struct sockaddr
*in
)
749 struct sockaddr_in6
*in6
= (struct sockaddr_in6
*)in
;
751 if(in
->sa_family
== AF_INET6
&& IN6_IS_ADDR_V4MAPPED(&in6
->sin6_addr
))
753 struct sockaddr_in in4
;
754 memset(&in4
, 0, sizeof(struct sockaddr_in
));
755 in4
.sin_family
= AF_INET
;
756 in4
.sin_port
= in6
->sin6_port
;
757 in4
.sin_addr
.s_addr
= ((uint32_t *)&in6
->sin6_addr
)[3];
758 memcpy(in
, &in4
, sizeof(struct sockaddr_in
));
763 * rb_listen() - listen on a port
766 rb_listen(rb_fde_t
*F
, int backlog
, int defer_accept
)
770 F
->type
= RB_FD_SOCKET
| RB_FD_LISTEN
;
771 result
= listen(F
->fd
, backlog
);
773 #ifdef TCP_DEFER_ACCEPT
774 if (defer_accept
&& !result
)
776 (void)setsockopt(F
->fd
, IPPROTO_TCP
, TCP_DEFER_ACCEPT
, &backlog
, sizeof(int));
779 #ifdef SO_ACCEPTFILTER
780 if (defer_accept
&& !result
)
782 struct accept_filter_arg afa
;
784 memset(&afa
, '\0', sizeof afa
);
785 rb_strlcpy(afa
.af_name
, "dataready", sizeof afa
.af_name
);
786 (void)setsockopt(F
->fd
, SOL_SOCKET
, SO_ACCEPTFILTER
, &afa
,
795 rb_fdlist_init(int closeall
, int maxfds
, size_t heapsize
)
797 static int initialized
= 0;
801 int vers
= MAKEWORD(2, 0);
803 err
= WSAStartup(vers
, &wsaData
);
806 rb_lib_die("WSAStartup failed");
812 rb_maxconnections
= maxfds
;
815 /* Since we're doing this once .. */
818 fd_heap
= rb_bh_create(sizeof(rb_fde_t
), heapsize
, "librb_fd_heap");
823 /* Called to open a given filedescriptor */
825 rb_open(rb_platform_fd_t fd
, uint8_t type
, const char *desc
)
832 lrb_assert(!IsFDOpen(F
));
833 if(rb_unlikely(IsFDOpen(F
)))
836 if(F
!= NULL
&& F
->desc
!= NULL
)
840 rb_lib_log("Trying to rb_open an already open FD: %d desc: %s", fd
, fdesc
);
848 F
->desc
= rb_strndup(desc
, FD_DESC_SZ
);
854 /* Called to close a given filedescriptor */
856 rb_close(rb_fde_t
*F
)
865 lrb_assert(IsFDOpen(F
));
867 lrb_assert(!(type
& RB_FD_FILE
));
868 if(rb_unlikely(type
& RB_FD_FILE
))
870 lrb_assert(F
->read_handler
== NULL
);
871 lrb_assert(F
->write_handler
== NULL
);
873 rb_setselect(F
, RB_SELECT_WRITE
| RB_SELECT_READ
, NULL
, NULL
);
874 rb_settimeout(F
, 0, NULL
, NULL
);
883 #endif /* HAVE_SSL */
890 if(type
& RB_FD_LISTEN
)
891 shutdown(fd
, SHUT_RDWR
);
896 * rb_dump_fd() - dump the list of active filedescriptors
899 rb_dump_fd(DUMPCB
* cb
, void *data
)
901 static const char *empty
= "";
903 rb_dlink_list
*bucket
;
907 for(i
= 0; i
< RB_FD_HASH_SIZE
; i
++)
909 bucket
= &rb_fd_table
[i
];
911 if(rb_dlink_list_length(bucket
) <= 0)
914 RB_DLINK_FOREACH(ptr
, bucket
->head
)
917 if(F
== NULL
|| !IsFDOpen(F
))
920 cb(F
->fd
, F
->desc
? F
->desc
: empty
, data
);
926 * rb_note() - set the fd note
928 * Note: must be careful not to overflow rb_fd_table[fd].desc when
932 rb_note(rb_fde_t
*F
, const char *string
)
938 F
->desc
= rb_strndup(string
, FD_DESC_SZ
);
942 rb_set_type(rb_fde_t
*F
, uint8_t type
)
944 /* if the caller is calling this, lets assume they have a clue */
950 rb_get_type(rb_fde_t
*F
)
956 rb_fd_ssl(rb_fde_t
*F
)
960 if(F
->type
& RB_FD_SSL
)
966 rb_get_fd(rb_fde_t
*F
)
974 rb_get_fde(rb_platform_fd_t fd
)
976 return rb_find_fd(fd
);
980 rb_read(rb_fde_t
*F
, void *buf
, int count
)
986 /* This needs to be *before* RB_FD_SOCKET otherwise you'll process
987 * an SSL socket as a regular socket
990 if(F
->type
& RB_FD_SSL
)
992 return rb_ssl_read(F
, buf
, count
);
995 if(F
->type
& RB_FD_SOCKET
)
997 ret
= recv(F
->fd
, buf
, count
, 0);
1007 return read(F
->fd
, buf
, count
);
1012 rb_write(rb_fde_t
*F
, const void *buf
, int count
)
1019 if(F
->type
& RB_FD_SSL
)
1021 return rb_ssl_write(F
, buf
, count
);
1024 if(F
->type
& RB_FD_SOCKET
)
1026 ret
= send(F
->fd
, buf
, count
, MSG_NOSIGNAL
);
1034 return write(F
->fd
, buf
, count
);
1037 #if defined(HAVE_SSL) || defined(WIN32) || !defined(HAVE_WRITEV)
1039 rb_fake_writev(rb_fde_t
*F
, const struct rb_iovec
*vp
, size_t vpcount
)
1043 while(vpcount
-- > 0)
1045 ssize_t written
= rb_write(F
, vp
->iov_base
, vp
->iov_len
);
1061 #if defined(WIN32) || !defined(HAVE_WRITEV)
1063 rb_writev(rb_fde_t
*F
, struct rb_iovec
* vecount
, int count
)
1065 return rb_fake_writev(F
, vecount
, count
);
1070 rb_writev(rb_fde_t
*F
, struct rb_iovec
* vector
, int count
)
1078 if(F
->type
& RB_FD_SSL
)
1080 return rb_fake_writev(F
, vector
, count
);
1082 #endif /* HAVE_SSL */
1084 if(F
->type
& RB_FD_SOCKET
)
1087 memset(&msg
, 0, sizeof(msg
));
1088 msg
.msg_iov
= (struct iovec
*)vector
;
1089 msg
.msg_iovlen
= count
;
1090 return sendmsg(F
->fd
, &msg
, MSG_NOSIGNAL
);
1092 #endif /* HAVE_SENDMSG */
1093 return writev(F
->fd
, (struct iovec
*)vector
, count
);
1100 * From: Thomas Helvey <tomh@inxpress.net>
1102 static const char *IpQuadTab
[] = {
1103 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
1104 "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
1105 "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
1106 "30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
1107 "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
1108 "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
1109 "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
1110 "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
1111 "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
1112 "90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
1113 "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
1114 "110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
1115 "120", "121", "122", "123", "124", "125", "126", "127", "128", "129",
1116 "130", "131", "132", "133", "134", "135", "136", "137", "138", "139",
1117 "140", "141", "142", "143", "144", "145", "146", "147", "148", "149",
1118 "150", "151", "152", "153", "154", "155", "156", "157", "158", "159",
1119 "160", "161", "162", "163", "164", "165", "166", "167", "168", "169",
1120 "170", "171", "172", "173", "174", "175", "176", "177", "178", "179",
1121 "180", "181", "182", "183", "184", "185", "186", "187", "188", "189",
1122 "190", "191", "192", "193", "194", "195", "196", "197", "198", "199",
1123 "200", "201", "202", "203", "204", "205", "206", "207", "208", "209",
1124 "210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
1125 "220", "221", "222", "223", "224", "225", "226", "227", "228", "229",
1126 "230", "231", "232", "233", "234", "235", "236", "237", "238", "239",
1127 "240", "241", "242", "243", "244", "245", "246", "247", "248", "249",
1128 "250", "251", "252", "253", "254", "255"
1132 * inetntoa - in_addr to string
1133 * changed name to remove collision possibility and
1134 * so behaviour is guaranteed to take a pointer arg.
1136 * inet_ntoa -- returned the dotted notation of a given
1139 * inet_ntoa -- its broken on some Ultrix/Dynix too. -avalon
1143 inetntoa(const char *in
)
1145 static char buf
[16];
1147 const unsigned char *a
= (const unsigned char *)in
;
1150 n
= IpQuadTab
[*a
++];
1154 n
= IpQuadTab
[*a
++];
1158 n
= IpQuadTab
[*a
++];
1170 * WARNING: Don't even consider trying to compile this on a system where
1171 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
1174 static const char *inet_ntop4(const unsigned char *src
, char *dst
, unsigned int size
);
1175 static const char *inet_ntop6(const unsigned char *src
, char *dst
, unsigned int size
);
1178 * inet_ntop4(src, dst, size)
1179 * format an IPv4 address
1181 * `dst' (as a const)
1183 * (1) uses no statics
1184 * (2) takes a unsigned char* not an in_addr as input
1189 inet_ntop4(const unsigned char *src
, char *dst
, unsigned int size
)
1193 return strcpy(dst
, inetntoa((const char *)src
));
1197 * inet_ntop6(src, dst, size)
1198 * convert IPv6 binary address into presentation (printable) format
1203 inet_ntop6(const unsigned char *src
, char *dst
, unsigned int size
)
1206 * Note that int32_t and int16_t need only be "at least" large enough
1207 * to contain a value of the specified size. On some systems, like
1208 * Crays, there is no such thing as an integer variable with 16 bits.
1209 * Keep this in mind if you think this function should have been coded
1210 * to use pointer overlays. All the world's not a VAX.
1212 char tmp
[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp
;
1218 unsigned int words
[IN6ADDRSZ
/ INT16SZ
];
1223 * Copy the input (bytewise) array into a wordwise array.
1224 * Find the longest run of 0x00's in src[] for :: shorthanding.
1226 memset(words
, '\0', sizeof words
);
1227 for(i
= 0; i
< IN6ADDRSZ
; i
+= 2)
1228 words
[i
/ 2] = (src
[i
] << 8) | src
[i
+ 1];
1233 for(i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++)
1238 cur
.base
= i
, cur
.len
= 1;
1246 if(best
.base
== -1 || cur
.len
> best
.len
)
1254 if(best
.base
== -1 || cur
.len
> best
.len
)
1257 if(best
.base
!= -1 && best
.len
< 2)
1261 * Format the result.
1264 for(i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++)
1266 /* Are we inside the best run of 0x00's? */
1267 if(best
.base
!= -1 && i
>= best
.base
&& i
< (best
.base
+ best
.len
))
1277 /* Are we following an initial run of 0x00s or any real hex? */
1280 /* Is this address an encapsulated IPv4? */
1281 if(i
== 6 && best
.base
== 0 &&
1282 (best
.len
== 6 || (best
.len
== 5 && words
[5] == 0xffff)))
1284 if(!inet_ntop4(src
+ 12, tp
, sizeof tmp
- (tp
- tmp
)))
1289 tp
+= sprintf(tp
, "%x", words
[i
]);
1291 /* Was it a trailing run of 0x00's? */
1292 if(best
.base
!= -1 && (best
.base
+ best
.len
) == (IN6ADDRSZ
/ INT16SZ
))
1297 * Check for overflow, copy, and we're done.
1300 if((unsigned int)(tp
- tmp
) > size
)
1304 return memcpy(dst
, tmp
, tp
- tmp
);
1308 rb_inet_pton_sock(const char *src
, struct sockaddr
*dst
)
1310 memset(dst
, 0, sizeof(*dst
));
1311 if(rb_inet_pton(AF_INET
, src
, &((struct sockaddr_in
*)dst
)->sin_addr
))
1313 SET_SS_FAMILY(dst
, AF_INET
);
1314 SET_SS_PORT(dst
, 0);
1315 SET_SS_LEN(dst
, sizeof(struct sockaddr_in
));
1318 else if(rb_inet_pton(AF_INET6
, src
, &((struct sockaddr_in6
*)dst
)->sin6_addr
))
1320 SET_SS_FAMILY(dst
, AF_INET6
);
1321 SET_SS_PORT(dst
, 0);
1322 SET_SS_LEN(dst
, sizeof(struct sockaddr_in6
));
1329 rb_inet_ntop_sock(struct sockaddr
*src
, char *dst
, unsigned int size
)
1331 switch (src
->sa_family
)
1334 return (rb_inet_ntop(AF_INET
, &((struct sockaddr_in
*)src
)->sin_addr
, dst
, size
));
1336 return (rb_inet_ntop
1337 (AF_INET6
, &((struct sockaddr_in6
*)src
)->sin6_addr
, dst
, size
));
1344 * rb_inet_ntop(af, src, dst, size)
1345 * convert a network format address to presentation format.
1347 * pointer to presentation format address (`dst'), or NULL (see errno).
1352 rb_inet_ntop(int af
, const void *src
, char *dst
, unsigned int size
)
1357 return (inet_ntop4(src
, dst
, size
));
1359 if(IN6_IS_ADDR_V4MAPPED((const struct in6_addr
*)src
) ||
1360 IN6_IS_ADDR_V4COMPAT((const struct in6_addr
*)src
))
1362 ((const unsigned char *)&((const struct in6_addr
*)src
)->
1363 s6_addr
[12], dst
, size
));
1365 return (inet_ntop6(src
, dst
, size
));
1373 * WARNING: Don't even consider trying to compile this on a system where
1374 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
1378 * rb_inet_pton(af, src, dst)
1379 * convert from presentation format (which usually means ASCII printable)
1380 * to network format (which is usually some kind of binary format).
1382 * 1 if the address was valid for the specified address family
1383 * 0 if the address wasn't valid (`dst' is untouched in this case)
1384 * -1 if some other error occurred (`dst' is untouched in this case, too)
1390 * inet_pton4(src, dst)
1391 * like inet_aton() but without all the hexadecimal and shorthand.
1393 * 1 if `src' is a valid dotted quad, else 0.
1395 * does not touch `dst' unless it's returning 1.
1400 inet_pton4(const char *src
, unsigned char *dst
)
1402 int saw_digit
, octets
, ch
;
1403 unsigned char tmp
[INADDRSZ
], *tp
;
1408 while((ch
= *src
++) != '\0')
1411 if(ch
>= '0' && ch
<= '9')
1413 unsigned int new = *tp
* 10 + (ch
- '0');
1425 else if(ch
== '.' && saw_digit
)
1437 memcpy(dst
, tmp
, INADDRSZ
);
1442 * inet_pton6(src, dst)
1443 * convert presentation level address to network order binary form.
1445 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
1447 * (1) does not touch `dst' unless it's returning 1.
1448 * (2) :: in a full address is silently ignored.
1450 * inspired by Mark Andrews.
1456 inet_pton6(const char *src
, unsigned char *dst
)
1458 static const char xdigits
[] = "0123456789abcdef";
1459 unsigned char tmp
[IN6ADDRSZ
], *tp
, *endp
, *colonp
;
1464 tp
= memset(tmp
, '\0', IN6ADDRSZ
);
1465 endp
= tp
+ IN6ADDRSZ
;
1467 /* Leading :: requires some special handling. */
1474 while((ch
= tolower((unsigned char)*src
++)) != '\0')
1478 pch
= strchr(xdigits
, ch
);
1482 val
|= (pch
- xdigits
);
1498 else if(*src
== '\0')
1502 if(tp
+ INT16SZ
> endp
)
1504 *tp
++ = (unsigned char)(val
>> 8) & 0xff;
1505 *tp
++ = (unsigned char)val
& 0xff;
1510 if(*src
!= '\0' && ch
== '.')
1512 if(((tp
+ INADDRSZ
) <= endp
) && inet_pton4(curtok
, tp
) > 0)
1516 break; /* '\0' was seen by inet_pton4(). */
1525 if(tp
+ INT16SZ
> endp
)
1527 *tp
++ = (unsigned char)(val
>> 8) & 0xff;
1528 *tp
++ = (unsigned char)val
& 0xff;
1533 * Since some memmove()'s erroneously fail to handle
1534 * overlapping regions, we'll do the shift by hand.
1536 const int n
= tp
- colonp
;
1541 for(i
= 1; i
<= n
; i
++)
1543 endp
[-i
] = colonp
[n
- i
];
1550 memcpy(dst
, tmp
, IN6ADDRSZ
);
1555 rb_inet_pton(int af
, const char *src
, void *dst
)
1560 return (inet_pton4(src
, dst
));
1562 /* Somebody might have passed as an IPv4 address this is sick but it works */
1563 if(inet_pton4(src
, dst
))
1565 char tmp
[HOSTIPLEN
];
1566 sprintf(tmp
, "::ffff:%s", src
);
1567 return (inet_pton6(tmp
, dst
));
1570 return (inet_pton6(src
, dst
));
1578 #ifndef HAVE_SOCKETPAIR
1580 /* mostly based on perl's emulation of socketpair udp */
1582 rb_inet_socketpair_udp(rb_fde_t
**newF1
, rb_fde_t
**newF2
)
1584 struct sockaddr_in addr
[2];
1585 rb_socklen_t size
= sizeof(struct sockaddr_in
);
1587 rb_platform_fd_t fd
[2];
1589 unsigned short port
;
1590 struct timeval wait
= { 0, 100000 };
1593 struct sockaddr_in readfrom
;
1594 unsigned short buf
[2];
1597 memset(&addr
, 0, sizeof(addr
));
1599 for(i
= 0; i
< 2; i
++)
1601 F
[i
] = rb_socket(AF_INET
, SOCK_DGRAM
, 0, "udp socketpair");
1604 addr
[i
].sin_family
= AF_INET
;
1605 addr
[i
].sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
1606 addr
[i
].sin_port
= 0;
1607 if(bind(rb_get_fd(F
[i
]), (struct sockaddr
*)&addr
[i
], sizeof(struct sockaddr_in
)))
1609 fd
[i
] = rb_get_fd(F
[i
]);
1612 for(i
= 0; i
< 2; i
++)
1614 if(getsockname(fd
[i
], (struct sockaddr
*)&addr
[i
], &size
))
1616 if(size
!= sizeof(struct sockaddr_in
))
1618 if(connect(fd
[!i
], (struct sockaddr
*)&addr
[i
], sizeof(struct sockaddr_in
)) == -1)
1622 for(i
= 0; i
< 2; i
++)
1624 port
= addr
[i
].sin_port
;
1625 got
= rb_write(F
[i
], &port
, sizeof(port
));
1626 if(got
!= sizeof(port
))
1634 max
= fd
[1] > fd
[0] ? fd
[1] : fd
[0];
1636 FD_SET(fd
[0], &rset
);
1637 FD_SET(fd
[1], &rset
);
1638 got
= select(max
+ 1, &rset
, NULL
, NULL
, &wait
);
1639 if(got
!= 2 || !FD_ISSET(fd
[0], &rset
) || !FD_ISSET(fd
[1], &rset
))
1646 for(i
= 0; i
< 2; i
++)
1649 int flag
= MSG_DONTWAIT
1653 got
= recvfrom(rb_get_fd(F
[i
]), (char *)&buf
, sizeof(buf
), flag
,
1654 (struct sockaddr
*)&readfrom
, &size
);
1657 if(got
!= sizeof(port
)
1658 || size
!= sizeof(struct sockaddr_in
)
1659 || buf
[0] != (unsigned short)addr
[!i
].sin_port
1660 || readfrom
.sin_family
!= addr
[!i
].sin_family
1661 || readfrom
.sin_addr
.s_addr
!= addr
[!i
].sin_addr
.s_addr
1662 || readfrom
.sin_port
!= addr
[!i
].sin_port
)
1671 #ifndef ECONNABORTED
1672 #define ECONNABORTED WSAECONNABORTED
1678 errno
= ECONNABORTED
;
1680 if(errno
!= ECONNABORTED
)
1693 rb_inet_socketpair(int family
, int type
, int protocol
, rb_platform_fd_t fd
[2])
1698 struct sockaddr_in listen_addr
;
1699 struct sockaddr_in connect_addr
;
1702 if(protocol
|| family
!= AF_INET
)
1704 errno
= EAFNOSUPPORT
;
1713 listener
= socket(AF_INET
, type
, 0);
1716 memset(&listen_addr
, 0, sizeof(listen_addr
));
1717 listen_addr
.sin_family
= AF_INET
;
1718 listen_addr
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
1719 listen_addr
.sin_port
= 0; /* kernel choses port. */
1720 if(bind(listener
, (struct sockaddr
*)&listen_addr
, sizeof(listen_addr
)) == -1)
1721 goto tidy_up_and_fail
;
1722 if(listen(listener
, 1) == -1)
1723 goto tidy_up_and_fail
;
1725 connector
= socket(AF_INET
, type
, 0);
1727 goto tidy_up_and_fail
;
1728 /* We want to find out the port number to connect to. */
1729 size
= sizeof(connect_addr
);
1730 if(getsockname(listener
, (struct sockaddr
*)&connect_addr
, &size
) == -1)
1731 goto tidy_up_and_fail
;
1732 if(size
!= sizeof(connect_addr
))
1733 goto abort_tidy_up_and_fail
;
1734 if(connect(connector
, (struct sockaddr
*)&connect_addr
, sizeof(connect_addr
)) == -1)
1735 goto tidy_up_and_fail
;
1737 size
= sizeof(listen_addr
);
1738 acceptor
= accept(listener
, (struct sockaddr
*)&listen_addr
, &size
);
1740 goto tidy_up_and_fail
;
1741 if(size
!= sizeof(listen_addr
))
1742 goto abort_tidy_up_and_fail
;
1744 /* Now check we are talking to ourself by matching port and host on the
1746 if(getsockname(connector
, (struct sockaddr
*)&connect_addr
, &size
) == -1)
1747 goto tidy_up_and_fail
;
1748 if(size
!= sizeof(connect_addr
)
1749 || listen_addr
.sin_family
!= connect_addr
.sin_family
1750 || listen_addr
.sin_addr
.s_addr
!= connect_addr
.sin_addr
.s_addr
1751 || listen_addr
.sin_port
!= connect_addr
.sin_port
)
1753 goto abort_tidy_up_and_fail
;
1759 abort_tidy_up_and_fail
:
1760 errno
= EINVAL
; /* I hope this is portable and appropriate. */
1764 int save_errno
= errno
;
1779 static void (*setselect_handler
) (rb_fde_t
*, unsigned int, PF
*, void *);
1780 static int (*select_handler
) (long);
1781 static int (*setup_fd_handler
) (rb_fde_t
*);
1782 static int (*io_sched_event
) (struct ev_entry
*, int);
1783 static void (*io_unsched_event
) (struct ev_entry
*);
1784 static int (*io_supports_event
) (void);
1785 static void (*io_init_event
) (void);
1786 static char iotype
[25];
1795 rb_unsupported_event(void)
1803 if(!rb_init_netio_kqueue())
1805 setselect_handler
= rb_setselect_kqueue
;
1806 select_handler
= rb_select_kqueue
;
1807 setup_fd_handler
= rb_setup_fd_kqueue
;
1808 io_sched_event
= rb_kqueue_sched_event
;
1809 io_unsched_event
= rb_kqueue_unsched_event
;
1810 io_init_event
= rb_kqueue_init_event
;
1811 io_supports_event
= rb_kqueue_supports_event
;
1812 rb_strlcpy(iotype
, "kqueue", sizeof(iotype
));
1821 if(!rb_init_netio_epoll())
1823 setselect_handler
= rb_setselect_epoll
;
1824 select_handler
= rb_select_epoll
;
1825 setup_fd_handler
= rb_setup_fd_epoll
;
1826 io_sched_event
= rb_epoll_sched_event
;
1827 io_unsched_event
= rb_epoll_unsched_event
;
1828 io_supports_event
= rb_epoll_supports_event
;
1829 io_init_event
= rb_epoll_init_event
;
1830 rb_strlcpy(iotype
, "epoll", sizeof(iotype
));
1839 if(!rb_init_netio_ports())
1841 setselect_handler
= rb_setselect_ports
;
1842 select_handler
= rb_select_ports
;
1843 setup_fd_handler
= rb_setup_fd_ports
;
1844 io_sched_event
= rb_ports_sched_event
;
1845 io_unsched_event
= rb_ports_unsched_event
;
1846 io_init_event
= rb_ports_init_event
;
1847 io_supports_event
= rb_ports_supports_event
;
1848 rb_strlcpy(iotype
, "ports", sizeof(iotype
));
1857 if(!rb_init_netio_devpoll())
1859 setselect_handler
= rb_setselect_devpoll
;
1860 select_handler
= rb_select_devpoll
;
1861 setup_fd_handler
= rb_setup_fd_devpoll
;
1862 io_sched_event
= NULL
;
1863 io_unsched_event
= NULL
;
1864 io_init_event
= NULL
;
1865 io_supports_event
= rb_unsupported_event
;
1866 rb_strlcpy(iotype
, "devpoll", sizeof(iotype
));
1875 if(!rb_init_netio_sigio())
1877 setselect_handler
= rb_setselect_sigio
;
1878 select_handler
= rb_select_sigio
;
1879 setup_fd_handler
= rb_setup_fd_sigio
;
1880 io_sched_event
= rb_sigio_sched_event
;
1881 io_unsched_event
= rb_sigio_unsched_event
;
1882 io_supports_event
= rb_sigio_supports_event
;
1883 io_init_event
= rb_sigio_init_event
;
1885 rb_strlcpy(iotype
, "sigio", sizeof(iotype
));
1894 if(!rb_init_netio_poll())
1896 setselect_handler
= rb_setselect_poll
;
1897 select_handler
= rb_select_poll
;
1898 setup_fd_handler
= rb_setup_fd_poll
;
1899 io_sched_event
= NULL
;
1900 io_unsched_event
= NULL
;
1901 io_init_event
= NULL
;
1902 io_supports_event
= rb_unsupported_event
;
1903 rb_strlcpy(iotype
, "poll", sizeof(iotype
));
1912 if(!rb_init_netio_win32())
1914 setselect_handler
= rb_setselect_win32
;
1915 select_handler
= rb_select_win32
;
1916 setup_fd_handler
= rb_setup_fd_win32
;
1917 io_sched_event
= NULL
;
1918 io_unsched_event
= NULL
;
1919 io_init_event
= NULL
;
1920 io_supports_event
= rb_unsupported_event
;
1921 rb_strlcpy(iotype
, "win32", sizeof(iotype
));
1930 if(!rb_init_netio_select())
1932 setselect_handler
= rb_setselect_select
;
1933 select_handler
= rb_select_select
;
1934 setup_fd_handler
= rb_setup_fd_select
;
1935 io_sched_event
= NULL
;
1936 io_unsched_event
= NULL
;
1937 io_init_event
= NULL
;
1938 io_supports_event
= rb_unsupported_event
;
1939 rb_strlcpy(iotype
, "select", sizeof(iotype
));
1947 rb_io_sched_event(struct ev_entry
*ev
, int when
)
1949 if(ev
== NULL
|| io_supports_event
== NULL
|| io_sched_event
== NULL
1950 || !io_supports_event())
1952 return io_sched_event(ev
, when
);
1956 rb_io_unsched_event(struct ev_entry
*ev
)
1958 if(ev
== NULL
|| io_supports_event
== NULL
|| io_unsched_event
== NULL
1959 || !io_supports_event())
1961 io_unsched_event(ev
);
1965 rb_io_supports_event(void)
1967 if(io_supports_event
== NULL
)
1969 return io_supports_event();
1973 rb_io_init_event(void)
1976 rb_event_io_register_all();
1982 char *ioenv
= getenv("LIBRB_USE_IOTYPE");
1983 rb_fd_table
= rb_malloc(RB_FD_HASH_SIZE
* sizeof(rb_dlink_list
));
1988 if(!strcmp("epoll", ioenv
))
1993 else if(!strcmp("kqueue", ioenv
))
1998 else if(!strcmp("ports", ioenv
))
2003 else if(!strcmp("poll", ioenv
))
2008 else if(!strcmp("devpoll", ioenv
))
2013 else if(!strcmp("sigio", ioenv
))
2018 else if(!strcmp("select", ioenv
))
2023 if(!strcmp("win32", ioenv
))
2048 rb_lib_log("rb_init_netio: Could not find any io handlers...giving up");
2054 rb_setselect(rb_fde_t
*F
, unsigned int type
, PF
* handler
, void *client_data
)
2056 setselect_handler(F
, type
, handler
, client_data
);
2060 rb_select(unsigned long timeout
)
2062 int ret
= select_handler(timeout
);
2068 rb_setup_fd(rb_fde_t
*F
)
2070 return setup_fd_handler(F
);
2075 rb_ignore_errno(int error
)
2082 #if defined EWOULDBLOCK
2085 #if defined(EAGAIN) && (EWOULDBLOCK != EAGAIN)
2105 #if defined(HAVE_SENDMSG) && !defined(WIN32)
2107 rb_recv_fd_buf(rb_fde_t
*F
, void *data
, size_t datasize
, rb_fde_t
**xF
, int nfds
)
2110 struct cmsghdr
*cmsg
;
2111 struct iovec iov
[1];
2113 uint8_t stype
= RB_FD_UNKNOWN
;
2115 rb_platform_fd_t fd
, len
, x
, rfds
;
2117 int control_len
= CMSG_SPACE(sizeof(int) * nfds
);
2119 iov
[0].iov_base
= data
;
2120 iov
[0].iov_len
= datasize
;
2122 msg
.msg_name
= NULL
;
2123 msg
.msg_namelen
= 0;
2127 cmsg
= alloca(control_len
);
2128 msg
.msg_control
= cmsg
;
2129 msg
.msg_controllen
= control_len
;
2131 if((len
= recvmsg(rb_get_fd(F
), &msg
, 0)) <= 0)
2134 if(msg
.msg_controllen
> 0 && msg
.msg_control
!= NULL
2135 && (cmsg
= CMSG_FIRSTHDR(&msg
)) != NULL
)
2137 rfds
= ((unsigned char *)cmsg
+ cmsg
->cmsg_len
- CMSG_DATA(cmsg
)) / sizeof(int);
2139 for(x
= 0; x
< nfds
&& x
< rfds
; x
++)
2141 fd
= ((int *)CMSG_DATA(cmsg
))[x
];
2142 stype
= RB_FD_UNKNOWN
;
2143 desc
= "remote unknown";
2146 if(S_ISSOCK(st
.st_mode
))
2148 stype
= RB_FD_SOCKET
;
2149 desc
= "remote socket";
2151 else if(S_ISFIFO(st
.st_mode
))
2154 desc
= "remote pipe";
2156 else if(S_ISREG(st
.st_mode
))
2159 desc
= "remote file";
2162 xF
[x
] = rb_open(fd
, stype
, desc
);
2172 rb_send_fd_buf(rb_fde_t
*xF
, rb_fde_t
**F
, int count
, void *data
, size_t datasize
, pid_t pid
)
2175 struct cmsghdr
*cmsg
;
2176 struct iovec iov
[1];
2179 memset(&msg
, 0, sizeof(msg
));
2182 iov
[0].iov_base
= &empty
;
2187 iov
[0].iov_base
= data
;
2188 iov
[0].iov_len
= datasize
;
2192 msg
.msg_name
= NULL
;
2193 msg
.msg_namelen
= 0;
2195 msg
.msg_control
= NULL
;
2196 msg
.msg_controllen
= 0;
2200 size_t ucount
= (size_t)count
;
2201 int len
= CMSG_SPACE(sizeof(int) * count
);
2204 msg
.msg_control
= buf
;
2205 msg
.msg_controllen
= len
;
2206 cmsg
= CMSG_FIRSTHDR(&msg
);
2207 cmsg
->cmsg_level
= SOL_SOCKET
;
2208 cmsg
->cmsg_type
= SCM_RIGHTS
;
2209 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int) * count
);
2211 for(size_t i
= 0; i
< ucount
; i
++)
2213 ((int *)CMSG_DATA(cmsg
))[i
] = rb_get_fd(F
[i
]);
2215 msg
.msg_controllen
= cmsg
->cmsg_len
;
2216 return sendmsg(rb_get_fd(xF
), &msg
, MSG_NOSIGNAL
);
2218 return sendmsg(rb_get_fd(xF
), &msg
, MSG_NOSIGNAL
);
2220 #else /* defined(HAVE_SENDMSG) && !defined(WIN32) */
2223 rb_recv_fd_buf(rb_fde_t
*F
, void *data
, size_t datasize
, rb_fde_t
**xF
, int nfds
)
2230 rb_send_fd_buf(rb_fde_t
*xF
, rb_fde_t
**F
, int count
, void *data
, size_t datasize
, pid_t pid
)
2236 #endif /* defined(HAVE_SENDMSG) && !defined(WIN32) */
2239 rb_ipv4_from_ipv6(const struct sockaddr_in6
*restrict ip6
, struct sockaddr_in
*restrict ip4
)
2243 if (!memcmp(ip6
->sin6_addr
.s6_addr
, "\x20\x02", 2))
2245 /* 6to4 and similar */
2246 memcpy(&ip4
->sin_addr
, ip6
->sin6_addr
.s6_addr
+ 2, 4);
2248 else if (!memcmp(ip6
->sin6_addr
.s6_addr
, "\x20\x01\x00\x00", 4))
2251 for (i
= 0; i
< 4; i
++)
2252 ((uint8_t *)&ip4
->sin_addr
)[i
] = 0xFF ^
2253 ip6
->sin6_addr
.s6_addr
[12 + i
];
2257 SET_SS_LEN(ip4
, sizeof(struct sockaddr_in
));
2258 ip4
->sin_family
= AF_INET
;