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 25375 2008-05-16 15:19:51Z 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 static 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]);
79 static inline rb_fde_t
*
82 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 list
= &rb_fd_table
[rb_hash_fd(fd
)];
92 rb_dlinkAdd(F
, &F
->node
, list
);
97 remove_fd(rb_fde_t
*F
)
101 if(F
== NULL
|| !IsFDOpen(F
))
104 list
= &rb_fd_table
[rb_hash_fd(F
->fd
)];
105 rb_dlinkMoveNode(&F
->node
, list
, &closed_list
);
112 rb_dlink_node
*ptr
, *next
;
113 RB_DLINK_FOREACH_SAFE(ptr
, next
, closed_list
.head
)
116 rb_dlinkDelete(ptr
, &closed_list
);
117 rb_bh_free(fd_heap
, F
);
121 /* 32bit solaris is kinda slow and stdio only supports fds < 256
122 * so we got to do this crap below.
123 * (BTW Fuck you Sun, I hate your guts and I hope you go bankrupt soon)
126 #if defined (__SVR4) && defined (__sun)
131 if(*fd
> 256 || *fd
< 0)
133 if((newfd
= fcntl(*fd
, F_DUPFD
, 256)) != -1)
141 #define rb_fd_hack(fd)
145 /* close_all_connections() can be used *before* the system come up! */
155 /* XXX someone tell me why we care about 4 fd's ? */
156 /* XXX btw, fd 3 is used for profiler ! */
157 for (i
= 4; i
< rb_maxconnections
; ++i
)
162 /* XXX should his hack be done in all cases? */
164 /* fugly hack to reserve fd == 2 */
166 fd
= open("stderr.log", O_WRONLY
| O_CREAT
| O_APPEND
, 0644);
176 * get_sockerr - get the error value from the socket or the current errno
178 * Get the *real* error from the socket (well try to anyway..).
179 * This may only work when SO_DEBUG is enabled but its worth the
183 rb_get_sockerr(rb_fde_t
*F
)
187 rb_socklen_t len
= sizeof(err
);
189 if(!(F
->type
& RB_FD_SOCKET
))
196 if(F
!= NULL
&& !getsockopt(rb_get_fd(F
), SOL_SOCKET
, SO_ERROR
, (char *) &err
, (rb_socklen_t
*) & len
))
207 * rb_getmaxconnect - return the max number of connections allowed
210 rb_getmaxconnect(void)
212 return(rb_maxconnections
);
216 * set_sock_buffers - set send and receive buffers for socket
218 * inputs - fd file descriptor
220 * output - returns true (1) if successful, false (0) otherwise
224 rb_set_buffers(rb_fde_t
*F
, int size
)
229 (F
->fd
, SOL_SOCKET
, SO_RCVBUF
, (char *) &size
, sizeof(size
))
230 || setsockopt(F
->fd
, SOL_SOCKET
, SO_SNDBUF
, (char *) &size
, sizeof(size
)))
236 * set_non_blocking - Set the client connection into non-blocking mode.
238 * inputs - fd to set into non blocking mode
239 * output - 1 if successful 0 if not
240 * side effects - use POSIX compliant non blocking and
244 rb_set_nb(rb_fde_t
*F
)
253 if((res
= rb_setup_fd(F
)))
257 res
= fcntl(fd
, F_GETFL
, 0);
258 if(-1 == res
|| fcntl(fd
, F_SETFL
, res
| nonb
) == -1)
263 if(ioctl(fd
, FIONBIO
, (char *)&nonb
) == -1)
271 * rb_settimeout() - set the socket timeout
273 * Set the timeout for the fd
276 rb_settimeout(rb_fde_t
*F
, time_t timeout
, PF
* callback
, void *cbdata
)
278 struct timeout_data
*td
;
283 lrb_assert(IsFDOpen(F
));
285 if(callback
== NULL
) /* user wants to remove */
289 rb_dlinkDelete(&td
->node
, &timeout_list
);
292 if(rb_dlink_list_length(&timeout_list
) == 0)
294 rb_event_delete(rb_timeout_ev
);
295 rb_timeout_ev
= NULL
;
300 if(F
->timeout
== NULL
)
301 td
= F
->timeout
= rb_malloc(sizeof(struct timeout_data
));
304 td
->timeout
= rb_current_time() + timeout
;
305 td
->timeout_handler
= callback
;
306 td
->timeout_data
= cbdata
;
307 rb_dlinkAdd(td
, &td
->node
, &timeout_list
);
308 if(rb_timeout_ev
== NULL
)
310 rb_timeout_ev
= rb_event_add("rb_checktimeouts", rb_checktimeouts
, NULL
, 5);
315 * rb_checktimeouts() - check the socket timeouts
317 * All this routine does is call the given callback/cbdata, without closing
318 * down the file descriptor. When close handlers have been implemented,
322 rb_checktimeouts(void *notused
)
324 rb_dlink_node
*ptr
, *next
;
325 struct timeout_data
*td
;
330 RB_DLINK_FOREACH_SAFE(ptr
, next
, timeout_list
.head
)
334 if(F
== NULL
|| !IsFDOpen(F
))
337 if(td
->timeout
< rb_current_time())
339 hdl
= td
->timeout_handler
;
340 data
= td
->timeout_data
;
341 rb_dlinkDelete(&td
->node
, &timeout_list
);
350 rb_accept_tryaccept(rb_fde_t
*F
, void *data
)
352 struct rb_sockaddr_storage st
;
354 rb_socklen_t addrlen
= sizeof(st
);
359 new_fd
= accept(F
->fd
, (struct sockaddr
*)&st
, &addrlen
);
363 rb_setselect(F
, RB_SELECT_ACCEPT
, rb_accept_tryaccept
, NULL
);
369 new_F
= rb_open(new_fd
, RB_FD_SOCKET
, "Incoming Connection");
371 if(rb_unlikely(!rb_set_nb(new_F
)))
374 rb_lib_log("rb_accept: Couldn't set FD %d non blocking!", new_F
->fd
);
379 mangle_mapped_sockaddr((struct sockaddr
*)&st
);
382 if(F
->accept
->precb
!= NULL
)
384 if(!F
->accept
->precb(new_F
, (struct sockaddr
*)&st
, addrlen
, F
->accept
->data
)) /* pre-callback decided to drop it */
388 if(F
->type
& RB_FD_SSL
)
390 rb_ssl_accept_setup(F
, new_fd
, (struct sockaddr
*)&st
, addrlen
);
393 #endif /* HAVE_SSL */
395 F
->accept
->callback(new_F
, RB_OK
, (struct sockaddr
*)&st
, addrlen
, F
->accept
->data
);
401 /* try to accept a TCP connection */
403 rb_accept_tcp(rb_fde_t
*F
, ACPRE
*precb
, ACCB
*callback
, void *data
)
407 lrb_assert(callback
);
409 F
->accept
= rb_malloc(sizeof(struct acceptdata
));
410 F
->accept
->callback
= callback
;
411 F
->accept
->data
= data
;
412 F
->accept
->precb
= precb
;
413 rb_accept_tryaccept(F
, NULL
);
417 * void rb_connect_tcp(int fd, struct sockaddr *dest,
418 * struct sockaddr *clocal, int socklen,
419 * CNCB *callback, void *data, int timeout)
420 * Input: An fd to connect with, a host and port to connect to,
421 * a local sockaddr to connect from + length(or NULL to use the
422 * default), a callback, the data to pass into the callback, the
425 * Side-effects: A non-blocking connection to the host is started, and
426 * if necessary, set up for selection. The callback given
427 * may be called now, or it may be called later.
430 rb_connect_tcp(rb_fde_t
*F
, struct sockaddr
*dest
,
431 struct sockaddr
*clocal
, int socklen
, CNCB
* callback
, void *data
, int timeout
)
436 lrb_assert(callback
);
437 F
->connect
= rb_malloc(sizeof(struct conndata
));
438 F
->connect
->callback
= callback
;
439 F
->connect
->data
= data
;
441 memcpy(&F
->connect
->hostaddr
, dest
, sizeof(F
->connect
->hostaddr
));
443 /* Note that we're using a passed sockaddr here. This is because
444 * generally you'll be bind()ing to a sockaddr grabbed from
445 * getsockname(), so this makes things easier.
446 * XXX If NULL is passed as local, we should later on bind() to the
447 * virtual host IP, for completeness.
450 if((clocal
!= NULL
) && (bind(F
->fd
, clocal
, socklen
) < 0))
452 /* Failure, call the callback with RB_ERR_BIND */
453 rb_connect_callback(F
, RB_ERR_BIND
);
458 /* We have a valid IP, so we just call tryconnect */
459 /* Make sure we actually set the timeout here .. */
460 rb_settimeout(F
, timeout
, rb_connect_timeout
, NULL
);
461 rb_connect_tryconnect(F
, NULL
);
466 * rb_connect_callback() - call the callback, and continue with life
469 rb_connect_callback(rb_fde_t
*F
, int status
)
473 int errtmp
= errno
; /* save errno as rb_settimeout clobbers it sometimes */
475 /* This check is gross..but probably necessary */
476 if(F
== NULL
|| F
->connect
== NULL
|| F
->connect
->callback
== NULL
)
478 /* Clear the connect flag + handler */
479 hdl
= F
->connect
->callback
;
480 data
= F
->connect
->data
;
481 F
->connect
->callback
= NULL
;
484 /* Clear the timeout handler */
485 rb_settimeout(F
, 0, NULL
, NULL
);
487 /* Call the handler */
488 hdl(F
, status
, data
);
493 * rb_connect_timeout() - this gets called when the socket connection
494 * times out. This *only* can be called once connect() is initially
498 rb_connect_timeout(rb_fde_t
*F
, void *notused
)
501 rb_connect_callback(F
, RB_ERR_TIMEOUT
);
504 /* static void rb_connect_tryconnect(int fd, void *notused)
505 * Input: The fd, the handler data(unused).
507 * Side-effects: Try and connect with pending connect data for the FD. If
508 * we succeed or get a fatal error, call the callback.
509 * Otherwise, it is still blocking or something, so register
510 * to select for a write event on this FD.
513 rb_connect_tryconnect(rb_fde_t
*F
, void *notused
)
517 if(F
== NULL
|| F
->connect
== NULL
|| F
->connect
->callback
== NULL
)
519 /* Try the connect() */
520 retval
= connect(F
->fd
,
521 (struct sockaddr
*) &F
->connect
->hostaddr
, GET_SS_LEN(&F
->connect
->hostaddr
));
526 * If we get EISCONN, then we've already connect()ed the socket,
527 * which is a good thing.
532 rb_connect_callback(F
, RB_OK
);
533 else if(rb_ignore_errno(errno
))
534 /* Ignore error? Reschedule */
535 rb_setselect(F
, RB_SELECT_CONNECT
,
536 rb_connect_tryconnect
, NULL
);
538 /* Error? Fail with RB_ERR_CONNECT */
539 rb_connect_callback(F
, RB_ERR_CONNECT
);
542 /* If we get here, we've suceeded, so call with RB_OK */
543 rb_connect_callback(F
, RB_OK
);
548 rb_connect_sockaddr(rb_fde_t
*F
, struct sockaddr
*addr
, int len
)
553 memcpy(addr
, &F
->connect
->hostaddr
, len
);
558 * rb_error_str() - return an error string for the given error condition
563 if(error
< 0 || error
>= RB_ERR_MAX
)
564 return "Invalid error number!";
565 return rb_err_str
[error
];
570 rb_socketpair(int family
, int sock_type
, int proto
, rb_fde_t
**F1
, rb_fde_t
**F2
, const char *note
)
573 if(number_fd
>= rb_maxconnections
)
580 if(socketpair(family
, sock_type
, proto
, nfd
))
582 if(rb_inet_socketpair(AF_INET
, SOCK_STREAM
, proto
, nfd
))
589 *F1
= rb_open(nfd
[0], RB_FD_SOCKET
, note
);
590 *F2
= rb_open(nfd
[1], RB_FD_SOCKET
, note
);
605 /* Set the socket non-blocking, and other wonderful bits */
606 if(rb_unlikely(!rb_set_nb(*F1
)))
608 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd
[0], strerror(errno
));
614 if(rb_unlikely(!rb_set_nb(*F2
)))
616 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd
[1], strerror(errno
));
627 rb_pipe(rb_fde_t
**F1
, rb_fde_t
**F2
, const char *desc
)
631 if(number_fd
>= rb_maxconnections
)
640 *F1
= rb_open(fd
[0], RB_FD_PIPE
, desc
);
641 *F2
= rb_open(fd
[1], RB_FD_PIPE
, desc
);
643 if(rb_unlikely(!rb_set_nb(*F1
)))
645 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
[0], strerror(errno
));
651 if(rb_unlikely(!rb_set_nb(*F2
)))
653 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
[1], strerror(errno
));
662 /* Its not a pipe..but its selectable. I'll take dirty hacks
665 return rb_socketpair(AF_INET
, SOCK_STREAM
, 0, F1
, F2
, desc
);
670 * rb_socket() - open a socket
672 * This is a highly highly cut down version of squid's rb_open() which
673 * for the most part emulates socket(), *EXCEPT* it fails if we're about
674 * to run out of file descriptors.
677 rb_socket(int family
, int sock_type
, int proto
, const char *note
)
681 /* First, make sure we aren't going to run out of file descriptors */
682 if(rb_unlikely(number_fd
>= rb_maxconnections
))
689 * Next, we try to open the socket. We *should* drop the reserved FD
690 * limit if/when we get an error, but we can deal with that later.
693 fd
= socket(family
, sock_type
, proto
);
695 if(rb_unlikely(fd
< 0))
696 return NULL
; /* errno will be passed through, yay.. */
698 #if defined(RB_IPV6) && defined(IPV6_V6ONLY)
700 * Make sure we can take both IPv4 and IPv6 connections
701 * on an AF_INET6 socket
703 if(family
== AF_INET6
)
706 if(setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &off
, sizeof(off
)) == -1)
708 rb_lib_log("rb_socket: Could not set IPV6_V6ONLY option to 1 on FD %d: %s",
709 fd
, strerror(errno
));
716 F
= rb_open(fd
, RB_FD_SOCKET
, note
);
720 /* Set the socket non-blocking, and other wonderful bits */
721 if(rb_unlikely(!rb_set_nb(F
)))
723 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
, strerror(errno
));
732 * If a sockaddr_storage is AF_INET6 but is a mapped IPv4
733 * socket manged the sockaddr.
737 mangle_mapped_sockaddr(struct sockaddr
*in
)
739 struct sockaddr_in6
*in6
= (struct sockaddr_in6
*) in
;
741 if(in
->sa_family
== AF_INET
)
744 if(in
->sa_family
== AF_INET6
&& IN6_IS_ADDR_V4MAPPED(&in6
->sin6_addr
))
746 struct sockaddr_in in4
;
747 memset(&in4
, 0, sizeof(struct sockaddr_in
));
748 in4
.sin_family
= AF_INET
;
749 in4
.sin_port
= in6
->sin6_port
;
750 in4
.sin_addr
.s_addr
= ((rb_uint32_t
*) & in6
->sin6_addr
)[3];
751 memcpy(in
, &in4
, sizeof(struct sockaddr_in
));
758 * rb_listen() - listen on a port
761 rb_listen(rb_fde_t
*F
, int backlog
)
763 F
->type
= RB_FD_SOCKET
|RB_FD_LISTEN
;
764 /* Currently just a simple wrapper for the sake of being complete */
765 return listen(F
->fd
, backlog
);
769 rb_fdlist_init(int closeall
, int maxfds
, size_t heapsize
)
771 static int initialized
= 0;
775 int vers
= MAKEWORD(2, 0);
777 err
= WSAStartup(vers
, &wsaData
);
780 rb_lib_die("WSAStartup failed");
786 rb_maxconnections
= maxfds
;
789 /* Since we're doing this once .. */
792 fd_heap
= rb_bh_create(sizeof(rb_fde_t
), heapsize
, "librb_fd_heap");
797 /* Called to open a given filedescriptor */
799 rb_open(int fd
, rb_uint8_t type
, const char *desc
)
801 rb_fde_t
*F
= add_fd(fd
);
804 if(rb_unlikely(IsFDOpen(F
)))
808 lrb_assert(!IsFDOpen(F
));
814 F
->desc
= rb_strndup(desc
, FD_DESC_SZ
);
820 /* Called to close a given filedescriptor */
822 rb_close(rb_fde_t
*F
)
831 lrb_assert(IsFDOpen(F
));
833 lrb_assert(!(type
& RB_FD_FILE
));
834 if(rb_unlikely(type
& RB_FD_FILE
))
836 lrb_assert(F
->read_handler
== NULL
);
837 lrb_assert(F
->write_handler
== NULL
);
839 rb_setselect(F
, RB_SELECT_WRITE
| RB_SELECT_READ
, NULL
, NULL
);
840 rb_settimeout(F
, 0, NULL
, NULL
);
849 #endif /* HAVE_SSL */
859 if(type
& (RB_FD_SOCKET
|RB_FD_PIPE
))
870 * rb_dump_fd() - dump the list of active filedescriptors
873 rb_dump_fd(DUMPCB
* cb
, void *data
)
875 static const char *empty
= "";
877 rb_dlink_list
*bucket
;
881 for(i
= 0; i
< RB_FD_HASH_SIZE
; i
++)
883 bucket
= &rb_fd_table
[i
];
885 if(rb_dlink_list_length(bucket
) <= 0)
888 RB_DLINK_FOREACH(ptr
, bucket
->head
)
891 if(F
== NULL
|| !IsFDOpen(F
))
894 cb(F
->fd
, F
->desc
? F
->desc
: empty
, data
);
900 * rb_note() - set the fd note
902 * Note: must be careful not to overflow rb_fd_table[fd].desc when
906 rb_note(rb_fde_t
*F
, const char *string
)
912 F
->desc
= rb_strndup(string
, FD_DESC_SZ
);
916 rb_set_type(rb_fde_t
*F
, rb_uint8_t type
)
918 /* if the caller is calling this, lets assume they have a clue */
924 rb_get_type(rb_fde_t
*F
)
930 rb_fd_ssl(rb_fde_t
*F
)
934 if(F
->type
& RB_FD_SSL
)
940 rb_get_fd(rb_fde_t
*F
)
950 return rb_find_fd(fd
);
954 rb_read(rb_fde_t
*F
, void *buf
, int count
)
960 /* This needs to be *before* RB_FD_SOCKET otherwise you'll process
961 * an SSL socket as a regular socket
964 if(F
->type
& RB_FD_SSL
)
966 return rb_ssl_read(F
, buf
, count
);
969 if(F
->type
& RB_FD_SOCKET
)
971 ret
= recv(F
->fd
, buf
, count
, 0);
981 return read(F
->fd
, buf
, count
);
986 rb_write(rb_fde_t
*F
, const void *buf
, int count
)
993 if(F
->type
& RB_FD_SSL
)
995 return rb_ssl_write(F
, buf
, count
);
998 if(F
->type
& RB_FD_SOCKET
)
1000 ret
= send(F
->fd
, buf
, count
, MSG_NOSIGNAL
);
1007 return write(F
->fd
, buf
, count
);
1010 #if defined(HAVE_SSL) || defined(WIN32) || !defined(HAVE_WRITEV)
1012 rb_fake_writev(rb_fde_t
*F
, const struct rb_iovec
*vp
, size_t vpcount
)
1016 while (vpcount
-- > 0)
1018 ssize_t written
= rb_write(F
, vp
->iov_base
, vp
->iov_len
);
1034 #if defined(WIN32) || !defined(HAVE_WRITEV)
1036 rb_writev(rb_fde_t
*F
, struct rb_iovec
*vecount
, int count
)
1038 return rb_fake_writev(F
, vecount
, count
);
1043 rb_writev(rb_fde_t
*F
, struct rb_iovec
*vector
, int count
)
1050 if(F
->type
& RB_FD_SSL
)
1052 return rb_fake_writev(F
, vector
, count
);
1054 #endif /* HAVE_SSL */
1056 if(F
->type
& RB_FD_SOCKET
)
1059 memset(&msg
, 0, sizeof(msg
));
1060 msg
.msg_iov
= (struct iovec
*)vector
;
1061 msg
.msg_iovlen
= count
;
1062 return sendmsg(F
->fd
, &msg
, MSG_NOSIGNAL
);
1064 #endif /* HAVE_SENDMSG */
1065 return writev(F
->fd
, (struct iovec
*)vector
, count
);
1072 * From: Thomas Helvey <tomh@inxpress.net>
1074 static const char *IpQuadTab
[] = {
1075 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
1076 "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
1077 "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
1078 "30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
1079 "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
1080 "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
1081 "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
1082 "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
1083 "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
1084 "90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
1085 "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
1086 "110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
1087 "120", "121", "122", "123", "124", "125", "126", "127", "128", "129",
1088 "130", "131", "132", "133", "134", "135", "136", "137", "138", "139",
1089 "140", "141", "142", "143", "144", "145", "146", "147", "148", "149",
1090 "150", "151", "152", "153", "154", "155", "156", "157", "158", "159",
1091 "160", "161", "162", "163", "164", "165", "166", "167", "168", "169",
1092 "170", "171", "172", "173", "174", "175", "176", "177", "178", "179",
1093 "180", "181", "182", "183", "184", "185", "186", "187", "188", "189",
1094 "190", "191", "192", "193", "194", "195", "196", "197", "198", "199",
1095 "200", "201", "202", "203", "204", "205", "206", "207", "208", "209",
1096 "210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
1097 "220", "221", "222", "223", "224", "225", "226", "227", "228", "229",
1098 "230", "231", "232", "233", "234", "235", "236", "237", "238", "239",
1099 "240", "241", "242", "243", "244", "245", "246", "247", "248", "249",
1100 "250", "251", "252", "253", "254", "255"
1104 * inetntoa - in_addr to string
1105 * changed name to remove collision possibility and
1106 * so behaviour is guaranteed to take a pointer arg.
1108 * inet_ntoa -- returned the dotted notation of a given
1111 * inet_ntoa -- its broken on some Ultrix/Dynix too. -avalon
1115 inetntoa(const char *in
)
1117 static char buf
[16];
1119 const unsigned char *a
= (const unsigned char *) in
;
1122 n
= IpQuadTab
[*a
++];
1126 n
= IpQuadTab
[*a
++];
1130 n
= IpQuadTab
[*a
++];
1143 * Copyright (c) 1996-1999 by Internet Software Consortium.
1145 * Permission to use, copy, modify, and distribute this software for any
1146 * purpose with or without fee is hereby granted, provided that the above
1147 * copyright notice and this permission notice appear in all copies.
1149 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
1150 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
1151 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
1152 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
1153 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
1154 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
1155 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
1159 #define SPRINTF(x) ((size_t)rb_sprintf x)
1162 * WARNING: Don't even consider trying to compile this on a system where
1163 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
1166 static const char *inet_ntop4(const unsigned char * src
, char *dst
, unsigned int size
);
1168 static const char *inet_ntop6(const unsigned char * src
, char *dst
, unsigned int size
);
1172 * inet_ntop4(src, dst, size)
1173 * format an IPv4 address
1175 * `dst' (as a const)
1177 * (1) uses no statics
1178 * (2) takes a unsigned char* not an in_addr as input
1183 inet_ntop4(const unsigned char *src
, char *dst
, unsigned int size
)
1187 return strcpy(dst
, inetntoa((const char *) src
));
1191 * inet_ntop6(src, dst, size)
1192 * convert IPv6 binary address into presentation (printable) format
1198 inet_ntop6(const unsigned char *src
, char *dst
, unsigned int size
)
1201 * Note that int32_t and int16_t need only be "at least" large enough
1202 * to contain a value of the specified size. On some systems, like
1203 * Crays, there is no such thing as an integer variable with 16 bits.
1204 * Keep this in mind if you think this function should have been coded
1205 * to use pointer overlays. All the world's not a VAX.
1207 char tmp
[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp
;
1213 unsigned int words
[IN6ADDRSZ
/ INT16SZ
];
1218 * Copy the input (bytewise) array into a wordwise array.
1219 * Find the longest run of 0x00's in src[] for :: shorthanding.
1221 memset(words
, '\0', sizeof words
);
1222 for (i
= 0; i
< IN6ADDRSZ
; i
+= 2)
1223 words
[i
/ 2] = (src
[i
] << 8) | src
[i
+ 1];
1228 for (i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++)
1233 cur
.base
= i
, cur
.len
= 1;
1241 if(best
.base
== -1 || cur
.len
> best
.len
)
1249 if(best
.base
== -1 || cur
.len
> best
.len
)
1252 if(best
.base
!= -1 && best
.len
< 2)
1256 * Format the result.
1259 for (i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++)
1261 /* Are we inside the best run of 0x00's? */
1262 if(best
.base
!= -1 && i
>= best
.base
&& i
< (best
.base
+ best
.len
))
1272 /* Are we following an initial run of 0x00s or any real hex? */
1275 /* Is this address an encapsulated IPv4? */
1276 if(i
== 6 && best
.base
== 0 &&
1277 (best
.len
== 6 || (best
.len
== 5 && words
[5] == 0xffff)))
1279 if(!inet_ntop4(src
+ 12, tp
, sizeof tmp
- (tp
- tmp
)))
1284 tp
+= SPRINTF((tp
, "%x", words
[i
]));
1286 /* Was it a trailing run of 0x00's? */
1287 if(best
.base
!= -1 && (best
.base
+ best
.len
) == (IN6ADDRSZ
/ INT16SZ
))
1292 * Check for overflow, copy, and we're done.
1295 if((unsigned int) (tp
- tmp
) > size
)
1299 return strcpy(dst
, tmp
);
1304 rb_inet_pton_sock(const char *src
, struct sockaddr
*dst
)
1306 if(rb_inet_pton(AF_INET
, src
, &((struct sockaddr_in
*) dst
)->sin_addr
))
1308 ((struct sockaddr_in
*) dst
)->sin_port
= 0;
1309 ((struct sockaddr_in
*) dst
)->sin_family
= AF_INET
;
1310 SET_SS_LEN(dst
, sizeof(struct sockaddr_in
));
1314 else if(rb_inet_pton(AF_INET6
, src
, &((struct sockaddr_in6
*) dst
)->sin6_addr
))
1316 ((struct sockaddr_in6
*) dst
)->sin6_port
= 0;
1317 ((struct sockaddr_in6
*) dst
)->sin6_family
= AF_INET6
;
1318 SET_SS_LEN(dst
, sizeof(struct sockaddr_in6
));
1326 rb_inet_ntop_sock(struct sockaddr
*src
, char *dst
, unsigned int size
)
1328 switch (src
->sa_family
)
1331 return (rb_inet_ntop(AF_INET
, &((struct sockaddr_in
*) src
)->sin_addr
, dst
, size
));
1335 return (rb_inet_ntop(AF_INET6
, &((struct sockaddr_in6
*) src
)->sin6_addr
, dst
, size
));
1345 * rb_inet_ntop(af, src, dst, size)
1346 * convert a network format address to presentation format.
1348 * pointer to presentation format address (`dst'), or NULL (see errno).
1353 rb_inet_ntop(int af
, const void *src
, char *dst
, unsigned int size
)
1358 return (inet_ntop4(src
, dst
, size
));
1361 if(IN6_IS_ADDR_V4MAPPED((const struct in6_addr
*) src
) ||
1362 IN6_IS_ADDR_V4COMPAT((const struct in6_addr
*) src
))
1364 ((const unsigned char *)
1365 &((const struct in6_addr
*) src
)->s6_addr
[12], dst
, size
));
1367 return (inet_ntop6(src
, dst
, size
));
1378 * WARNING: Don't even consider trying to compile this on a system where
1379 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
1383 * rb_inet_pton(af, src, dst)
1384 * convert from presentation format (which usually means ASCII printable)
1385 * to network format (which is usually some kind of binary format).
1387 * 1 if the address was valid for the specified address family
1388 * 0 if the address wasn't valid (`dst' is untouched in this case)
1389 * -1 if some other error occurred (`dst' is untouched in this case, too)
1395 * inet_pton4(src, dst)
1396 * like inet_aton() but without all the hexadecimal and shorthand.
1398 * 1 if `src' is a valid dotted quad, else 0.
1400 * does not touch `dst' unless it's returning 1.
1405 inet_pton4(const char *src
, unsigned char *dst
)
1407 int saw_digit
, octets
, ch
;
1408 unsigned char tmp
[INADDRSZ
], *tp
;
1413 while ((ch
= *src
++) != '\0')
1416 if(ch
>= '0' && ch
<= '9')
1418 unsigned int new = *tp
* 10 + (ch
- '0');
1430 else if(ch
== '.' && saw_digit
)
1442 memcpy(dst
, tmp
, INADDRSZ
);
1448 * inet_pton6(src, dst)
1449 * convert presentation level address to network order binary form.
1451 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
1453 * (1) does not touch `dst' unless it's returning 1.
1454 * (2) :: in a full address is silently ignored.
1456 * inspired by Mark Andrews.
1462 inet_pton6(const char *src
, unsigned char *dst
)
1464 static const char xdigits
[] = "0123456789abcdef";
1465 unsigned char tmp
[IN6ADDRSZ
], *tp
, *endp
, *colonp
;
1470 tp
= memset(tmp
, '\0', IN6ADDRSZ
);
1471 endp
= tp
+ IN6ADDRSZ
;
1473 /* Leading :: requires some special handling. */
1480 while ((ch
= tolower(*src
++)) != '\0')
1484 pch
= strchr(xdigits
, ch
);
1488 val
|= (pch
- xdigits
);
1504 else if(*src
== '\0')
1508 if(tp
+ INT16SZ
> endp
)
1510 *tp
++ = (unsigned char) (val
>> 8) & 0xff;
1511 *tp
++ = (unsigned char) val
& 0xff;
1516 if(*src
!= '\0' && ch
== '.')
1518 if(((tp
+ INADDRSZ
) <= endp
) && inet_pton4(curtok
, tp
) > 0)
1522 break; /* '\0' was seen by inet_pton4(). */
1531 if(tp
+ INT16SZ
> endp
)
1533 *tp
++ = (unsigned char) (val
>> 8) & 0xff;
1534 *tp
++ = (unsigned char) val
& 0xff;
1539 * Since some memmove()'s erroneously fail to handle
1540 * overlapping regions, we'll do the shift by hand.
1542 const int n
= tp
- colonp
;
1547 for (i
= 1; i
<= n
; i
++)
1549 endp
[-i
] = colonp
[n
- i
];
1556 memcpy(dst
, tmp
, IN6ADDRSZ
);
1561 rb_inet_pton(int af
, const char *src
, void *dst
)
1566 return (inet_pton4(src
, dst
));
1569 /* Somebody might have passed as an IPv4 address this is sick but it works */
1570 if(inet_pton4(src
, dst
))
1572 char tmp
[HOSTIPLEN
];
1573 rb_sprintf(tmp
, "::ffff:%s", src
);
1574 return (inet_pton6(tmp
, dst
));
1577 return (inet_pton6(src
, dst
));
1586 #ifndef HAVE_SOCKETPAIR
1588 rb_inet_socketpair(int family
, int type
, int protocol
, int fd
[2])
1593 struct sockaddr_in listen_addr
;
1594 struct sockaddr_in connect_addr
;
1597 if(protocol
|| family
!= AF_INET
)
1599 errno
= EAFNOSUPPORT
;
1608 listener
= socket(AF_INET
, type
, 0);
1611 memset(&listen_addr
, 0, sizeof(listen_addr
));
1612 listen_addr
.sin_family
= AF_INET
;
1613 listen_addr
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
1614 listen_addr
.sin_port
= 0; /* kernel choses port. */
1615 if(bind(listener
, (struct sockaddr
*) &listen_addr
, sizeof(listen_addr
)) == -1)
1616 goto tidy_up_and_fail
;
1617 if(listen(listener
, 1) == -1)
1618 goto tidy_up_and_fail
;
1620 connector
= socket(AF_INET
, type
, 0);
1622 goto tidy_up_and_fail
;
1623 /* We want to find out the port number to connect to. */
1624 size
= sizeof(connect_addr
);
1625 if(getsockname(listener
, (struct sockaddr
*) &connect_addr
, &size
) == -1)
1626 goto tidy_up_and_fail
;
1627 if(size
!= sizeof(connect_addr
))
1628 goto abort_tidy_up_and_fail
;
1629 if(connect(connector
, (struct sockaddr
*) &connect_addr
, sizeof(connect_addr
)) == -1)
1630 goto tidy_up_and_fail
;
1632 size
= sizeof(listen_addr
);
1633 acceptor
= accept(listener
, (struct sockaddr
*) &listen_addr
, &size
);
1635 goto tidy_up_and_fail
;
1636 if(size
!= sizeof(listen_addr
))
1637 goto abort_tidy_up_and_fail
;
1639 /* Now check we are talking to ourself by matching port and host on the
1641 if(getsockname(connector
, (struct sockaddr
*) &connect_addr
, &size
) == -1)
1642 goto tidy_up_and_fail
;
1643 if(size
!= sizeof(connect_addr
)
1644 || listen_addr
.sin_family
!= connect_addr
.sin_family
1645 || listen_addr
.sin_addr
.s_addr
!= connect_addr
.sin_addr
.s_addr
1646 || listen_addr
.sin_port
!= connect_addr
.sin_port
)
1648 goto abort_tidy_up_and_fail
;
1654 abort_tidy_up_and_fail
:
1655 errno
= EINVAL
; /* I hope this is portable and appropriate. */
1659 int save_errno
= errno
;
1674 static void (*setselect_handler
) (rb_fde_t
*, unsigned int, PF
*, void *);
1675 static int (*select_handler
) (long);
1676 static int (*setup_fd_handler
) (rb_fde_t
*);
1677 static int (*io_sched_event
) (struct ev_entry
*, int);
1678 static void (*io_unsched_event
) (struct ev_entry
*);
1679 static int (*io_supports_event
) (void);
1680 static void (*io_init_event
) (void);
1681 static char iotype
[25];
1690 rb_unsupported_event(void)
1698 if(!rb_init_netio_kqueue())
1700 setselect_handler
= rb_setselect_kqueue
;
1701 select_handler
= rb_select_kqueue
;
1702 setup_fd_handler
= rb_setup_fd_kqueue
;
1703 io_sched_event
= rb_kqueue_sched_event
;
1704 io_unsched_event
= rb_kqueue_unsched_event
;
1705 io_init_event
= rb_kqueue_init_event
;
1706 io_supports_event
= rb_kqueue_supports_event
;
1707 rb_strlcpy(iotype
, "kqueue", sizeof(iotype
));
1716 if(!rb_init_netio_epoll())
1718 setselect_handler
= rb_setselect_epoll
;
1719 select_handler
= rb_select_epoll
;
1720 setup_fd_handler
= rb_setup_fd_epoll
;
1721 io_sched_event
= rb_epoll_sched_event
;
1722 io_unsched_event
= rb_epoll_unsched_event
;
1723 io_supports_event
= rb_epoll_supports_event
;
1724 io_init_event
= rb_epoll_init_event
;
1725 rb_strlcpy(iotype
, "epoll", sizeof(iotype
));
1734 if(!rb_init_netio_ports())
1736 setselect_handler
= rb_setselect_ports
;
1737 select_handler
= rb_select_ports
;
1738 setup_fd_handler
= rb_setup_fd_ports
;
1739 io_sched_event
= NULL
;
1740 io_unsched_event
= NULL
;
1741 io_init_event
= NULL
;
1742 io_supports_event
= rb_unsupported_event
;
1743 rb_strlcpy(iotype
, "ports", sizeof(iotype
));
1752 if(!rb_init_netio_devpoll())
1754 setselect_handler
= rb_setselect_devpoll
;
1755 select_handler
= rb_select_devpoll
;
1756 setup_fd_handler
= rb_setup_fd_devpoll
;
1757 io_sched_event
= NULL
;
1758 io_unsched_event
= NULL
;
1759 io_init_event
= NULL
;
1760 io_supports_event
= rb_unsupported_event
;
1761 rb_strlcpy(iotype
, "devpoll", sizeof(iotype
));
1770 if(!rb_init_netio_sigio())
1772 setselect_handler
= rb_setselect_sigio
;
1773 select_handler
= rb_select_sigio
;
1774 setup_fd_handler
= rb_setup_fd_sigio
;
1775 io_sched_event
= rb_sigio_sched_event
;
1776 io_unsched_event
= rb_sigio_unsched_event
;
1777 io_supports_event
= rb_sigio_supports_event
;
1778 io_init_event
= rb_sigio_init_event
;
1780 rb_strlcpy(iotype
, "sigio", sizeof(iotype
));
1789 if(!rb_init_netio_poll())
1791 setselect_handler
= rb_setselect_poll
;
1792 select_handler
= rb_select_poll
;
1793 setup_fd_handler
= rb_setup_fd_poll
;
1794 io_sched_event
= NULL
;
1795 io_unsched_event
= NULL
;
1796 io_init_event
= NULL
;
1797 io_supports_event
= rb_unsupported_event
;
1798 rb_strlcpy(iotype
, "poll", sizeof(iotype
));
1807 if(!rb_init_netio_win32())
1809 setselect_handler
= rb_setselect_win32
;
1810 select_handler
= rb_select_win32
;
1811 setup_fd_handler
= rb_setup_fd_win32
;
1812 io_sched_event
= NULL
;
1813 io_unsched_event
= NULL
;
1814 io_init_event
= NULL
;
1815 io_supports_event
= rb_unsupported_event
;
1816 rb_strlcpy(iotype
, "win32", sizeof(iotype
));
1825 if(!rb_init_netio_select())
1827 setselect_handler
= rb_setselect_select
;
1828 select_handler
= rb_select_select
;
1829 setup_fd_handler
= rb_setup_fd_select
;
1830 io_sched_event
= NULL
;
1831 io_unsched_event
= NULL
;
1832 io_init_event
= NULL
;
1833 io_supports_event
= rb_unsupported_event
;
1834 rb_strlcpy(iotype
, "select", sizeof(iotype
));
1842 rb_io_sched_event(struct ev_entry
*ev
, int when
)
1844 if(ev
== NULL
|| io_supports_event
== NULL
|| io_sched_event
== NULL
|| !io_supports_event())
1846 return io_sched_event(ev
, when
);
1850 rb_io_unsched_event(struct ev_entry
*ev
)
1852 if(ev
== NULL
|| io_supports_event
== NULL
|| io_unsched_event
== NULL
|| !io_supports_event())
1854 io_unsched_event(ev
);
1857 rb_io_supports_event(void)
1859 if(io_supports_event
== NULL
)
1861 return io_supports_event();
1865 rb_io_init_event(void)
1868 rb_event_io_register_all();
1874 char *ioenv
= getenv("LIBRB_USE_IOTYPE");
1875 rb_fd_table
= rb_malloc(RB_FD_HASH_SIZE
* sizeof(rb_dlink_list
));
1880 if(!strcmp("epoll", ioenv
))
1885 if(!strcmp("kqueue", ioenv
))
1890 if(!strcmp("ports", ioenv
))
1895 if(!strcmp("poll", ioenv
))
1900 if(!strcmp("devpoll", ioenv
))
1905 if(!strcmp("sigio", ioenv
))
1910 if(!strcmp("win32", ioenv
))
1915 if(!strcmp("select", ioenv
))
1940 rb_lib_log("rb_init_netio: Could not find any io handlers...giving up");
1946 rb_setselect(rb_fde_t
*F
, unsigned int type
, PF
* handler
, void *client_data
)
1948 setselect_handler(F
, type
, handler
, client_data
);
1952 rb_select(unsigned long timeout
)
1954 int ret
= select_handler(timeout
);
1960 rb_setup_fd(rb_fde_t
*F
)
1962 return setup_fd_handler(F
);
1968 rb_ignore_errno(int error
)
1975 #if defined EWOULDBLOCK
1978 #if defined(EAGAIN) && (EWOULDBLOCK != EAGAIN)
1999 rb_recv_fd_buf(rb_fde_t
*F
, void *data
, size_t datasize
, rb_fde_t
**xF
, int nfds
)
2002 struct cmsghdr
*cmsg
;
2003 struct iovec iov
[1];
2005 rb_uint8_t stype
= RB_FD_UNKNOWN
;
2007 int fd
, len
, x
, rfds
;
2009 int control_len
= CMSG_SPACE(sizeof(int) * nfds
);
2011 iov
[0].iov_base
= data
;
2012 iov
[0].iov_len
= datasize
;
2014 msg
.msg_name
= NULL
;
2015 msg
.msg_namelen
= 0;
2019 cmsg
= alloca(control_len
);
2020 msg
.msg_control
= cmsg
;
2021 msg
.msg_controllen
= control_len
;
2023 if((len
= recvmsg(rb_get_fd(F
), &msg
, 0)) <= 0)
2026 if(msg
.msg_controllen
> 0 && msg
.msg_control
!= NULL
&& (cmsg
= CMSG_FIRSTHDR(&msg
)) != NULL
)
2028 rfds
= (msg
.msg_controllen
- sizeof(struct cmsghdr
)) / sizeof(int);
2030 for(x
= 0; x
< nfds
&& x
< rfds
; x
++)
2032 fd
= ((int *)CMSG_DATA(cmsg
))[x
];
2033 stype
= RB_FD_UNKNOWN
;
2034 desc
= "remote unknown";
2037 if(S_ISSOCK(st
.st_mode
))
2039 stype
= RB_FD_SOCKET
;
2040 desc
= "remote socket";
2042 else if(S_ISFIFO(st
.st_mode
))
2045 desc
= "remote pipe";
2047 else if(S_ISREG(st
.st_mode
))
2050 desc
= "remote file";
2053 xF
[x
] = rb_open(fd
, stype
, desc
);
2062 rb_send_fd_buf(rb_fde_t
*xF
, rb_fde_t
**F
, int count
, void *data
, size_t datasize
)
2066 struct cmsghdr
*cmsg
;
2067 struct iovec iov
[1];
2071 memset(&msg
, 0, sizeof(&msg
));
2074 iov
[0].iov_base
= &empty
;
2077 iov
[0].iov_base
= data
;
2078 iov
[0].iov_len
= datasize
;
2082 msg
.msg_name
= NULL
;
2083 msg
.msg_namelen
= 0;
2085 msg
.msg_control
= NULL
;
2086 msg
.msg_controllen
= 0;
2091 int len
= CMSG_SPACE(sizeof(int) * count
);
2094 msg
.msg_control
= buf
;
2095 msg
.msg_controllen
= len
;
2096 cmsg
= CMSG_FIRSTHDR(&msg
);
2097 cmsg
->cmsg_level
= SOL_SOCKET
;
2098 cmsg
->cmsg_type
= SCM_RIGHTS
;
2099 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int) * count
);
2101 for(i
= 0; i
< count
; i
++)
2103 ((int *)CMSG_DATA(cmsg
))[i
] = rb_get_fd(F
[i
]);
2105 msg
.msg_controllen
= cmsg
->cmsg_len
;
2107 n
= sendmsg(rb_get_fd(xF
), &msg
, MSG_NOSIGNAL
);