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 25038 2008-01-23 16:03:08Z 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(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
)
474 /* This check is gross..but probably necessary */
475 if(F
== NULL
|| F
->connect
== NULL
|| F
->connect
->callback
== NULL
)
477 /* Clear the connect flag + handler */
478 hdl
= F
->connect
->callback
;
479 data
= F
->connect
->data
;
480 F
->connect
->callback
= NULL
;
482 /* Clear the timeout handler */
483 rb_settimeout(F
, 0, NULL
, NULL
);
484 /* Call the handler */
485 hdl(F
, status
, data
);
490 * rb_connect_timeout() - this gets called when the socket connection
491 * times out. This *only* can be called once connect() is initially
495 rb_connect_timeout(rb_fde_t
*F
, void *notused
)
498 rb_connect_callback(F
, RB_ERR_TIMEOUT
);
501 /* static void rb_connect_tryconnect(int fd, void *notused)
502 * Input: The fd, the handler data(unused).
504 * Side-effects: Try and connect with pending connect data for the FD. If
505 * we succeed or get a fatal error, call the callback.
506 * Otherwise, it is still blocking or something, so register
507 * to select for a write event on this FD.
510 rb_connect_tryconnect(rb_fde_t
*F
, void *notused
)
514 if(F
== NULL
|| F
->connect
== NULL
|| F
->connect
->callback
== NULL
)
516 /* Try the connect() */
517 retval
= connect(F
->fd
,
518 (struct sockaddr
*) &F
->connect
->hostaddr
, GET_SS_LEN(&F
->connect
->hostaddr
));
523 * If we get EISCONN, then we've already connect()ed the socket,
524 * which is a good thing.
529 rb_connect_callback(F
, RB_OK
);
530 else if(rb_ignore_errno(errno
))
531 /* Ignore error? Reschedule */
532 rb_setselect(F
, RB_SELECT_CONNECT
,
533 rb_connect_tryconnect
, NULL
);
535 /* Error? Fail with RB_ERR_CONNECT */
536 rb_connect_callback(F
, RB_ERR_CONNECT
);
539 /* If we get here, we've suceeded, so call with RB_OK */
540 rb_connect_callback(F
, RB_OK
);
545 rb_connect_sockaddr(rb_fde_t
*F
, struct sockaddr
*addr
, int len
)
550 memcpy(addr
, &F
->connect
->hostaddr
, len
);
555 * rb_error_str() - return an error string for the given error condition
560 if(error
< 0 || error
>= RB_ERR_MAX
)
561 return "Invalid error number!";
562 return rb_err_str
[error
];
567 rb_socketpair(int family
, int sock_type
, int proto
, rb_fde_t
**F1
, rb_fde_t
**F2
, const char *note
)
570 if(number_fd
>= rb_maxconnections
)
577 if(socketpair(family
, sock_type
, proto
, nfd
))
579 if(rb_inet_socketpair(AF_INET
, SOCK_STREAM
, proto
, nfd
))
586 *F1
= rb_open(nfd
[0], RB_FD_SOCKET
, note
);
587 *F2
= rb_open(nfd
[1], RB_FD_SOCKET
, note
);
602 /* Set the socket non-blocking, and other wonderful bits */
603 if(unlikely(!rb_set_nb(*F1
)))
605 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd
[0], strerror(errno
));
611 if(unlikely(!rb_set_nb(*F2
)))
613 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd
[1], strerror(errno
));
624 rb_pipe(rb_fde_t
**F1
, rb_fde_t
**F2
, const char *desc
)
628 if(number_fd
>= rb_maxconnections
)
637 *F1
= rb_open(fd
[0], RB_FD_PIPE
, desc
);
638 *F2
= rb_open(fd
[1], RB_FD_PIPE
, desc
);
640 if(unlikely(!rb_set_nb(*F1
)))
642 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
[0], strerror(errno
));
648 if(unlikely(!rb_set_nb(*F2
)))
650 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
[1], strerror(errno
));
659 /* Its not a pipe..but its selectable. I'll take dirty hacks
662 return rb_socketpair(AF_INET
, SOCK_STREAM
, 0, F1
, F2
, desc
);
667 * rb_socket() - open a socket
669 * This is a highly highly cut down version of squid's rb_open() which
670 * for the most part emulates socket(), *EXCEPT* it fails if we're about
671 * to run out of file descriptors.
674 rb_socket(int family
, int sock_type
, int proto
, const char *note
)
678 /* First, make sure we aren't going to run out of file descriptors */
679 if(unlikely(number_fd
>= rb_maxconnections
))
686 * Next, we try to open the socket. We *should* drop the reserved FD
687 * limit if/when we get an error, but we can deal with that later.
690 fd
= socket(family
, sock_type
, proto
);
693 return NULL
; /* errno will be passed through, yay.. */
695 #if defined(RB_IPV6) && defined(IPV6_V6ONLY)
697 * Make sure we can take both IPv4 and IPv6 connections
698 * on an AF_INET6 socket
700 if(family
== AF_INET6
)
703 if(setsockopt(fd
, IPPROTO_IPV6
, IPV6_V6ONLY
, &off
, sizeof(off
)) == -1)
705 rb_lib_log("rb_socket: Could not set IPV6_V6ONLY option to 1 on FD %d: %s",
706 fd
, strerror(errno
));
713 F
= rb_open(fd
, RB_FD_SOCKET
, note
);
717 /* Set the socket non-blocking, and other wonderful bits */
718 if(unlikely(!rb_set_nb(F
)))
720 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd
, strerror(errno
));
729 * If a sockaddr_storage is AF_INET6 but is a mapped IPv4
730 * socket manged the sockaddr.
734 mangle_mapped_sockaddr(struct sockaddr
*in
)
736 struct sockaddr_in6
*in6
= (struct sockaddr_in6
*) in
;
738 if(in
->sa_family
== AF_INET
)
741 if(in
->sa_family
== AF_INET6
&& IN6_IS_ADDR_V4MAPPED(&in6
->sin6_addr
))
743 struct sockaddr_in in4
;
744 memset(&in4
, 0, sizeof(struct sockaddr_in
));
745 in4
.sin_family
= AF_INET
;
746 in4
.sin_port
= in6
->sin6_port
;
747 in4
.sin_addr
.s_addr
= ((rb_uint32_t
*) & in6
->sin6_addr
)[3];
748 memcpy(in
, &in4
, sizeof(struct sockaddr_in
));
755 * rb_listen() - listen on a port
758 rb_listen(rb_fde_t
*F
, int backlog
)
760 F
->type
= RB_FD_SOCKET
|RB_FD_LISTEN
;
761 /* Currently just a simple wrapper for the sake of being complete */
762 return listen(F
->fd
, backlog
);
766 rb_fdlist_init(int closeall
, int maxfds
, size_t heapsize
)
768 static int initialized
= 0;
772 int vers
= MAKEWORD(2, 0);
774 err
= WSAStartup(vers
, &wsaData
);
777 rb_lib_die("WSAStartup failed");
783 rb_maxconnections
= maxfds
;
786 /* Since we're doing this once .. */
789 fd_heap
= rb_bh_create(sizeof(rb_fde_t
), heapsize
, "librb_fd_heap");
794 /* Called to open a given filedescriptor */
796 rb_open(int fd
, rb_uint8_t type
, const char *desc
)
798 rb_fde_t
*F
= add_fd(fd
);
801 if(unlikely(IsFDOpen(F
)))
805 lrb_assert(!IsFDOpen(F
));
811 F
->desc
= rb_strndup(desc
, FD_DESC_SZ
);
817 /* Called to close a given filedescriptor */
819 rb_close(rb_fde_t
*F
)
828 lrb_assert(IsFDOpen(F
));
830 lrb_assert(!(type
& RB_FD_FILE
));
831 if(unlikely(type
& RB_FD_FILE
))
833 lrb_assert(F
->read_handler
== NULL
);
834 lrb_assert(F
->write_handler
== NULL
);
836 rb_setselect(F
, RB_SELECT_WRITE
| RB_SELECT_READ
, NULL
, NULL
);
837 rb_settimeout(F
, 0, NULL
, NULL
);
846 #endif /* HAVE_SSL */
856 if(type
& (RB_FD_SOCKET
|RB_FD_PIPE
))
867 * rb_dump_fd() - dump the list of active filedescriptors
870 rb_dump_fd(DUMPCB
* cb
, void *data
)
872 static const char *empty
= "";
874 rb_dlink_list
*bucket
;
878 for(i
= 0; i
< RB_FD_HASH_SIZE
; i
++)
880 bucket
= &rb_fd_table
[i
];
882 if(rb_dlink_list_length(bucket
) <= 0)
885 RB_DLINK_FOREACH(ptr
, bucket
->head
)
888 if(F
== NULL
|| !IsFDOpen(F
))
891 cb(F
->fd
, F
->desc
? F
->desc
: empty
, data
);
897 * rb_note() - set the fd note
899 * Note: must be careful not to overflow rb_fd_table[fd].desc when
903 rb_note(rb_fde_t
*F
, const char *string
)
909 F
->desc
= rb_strndup(string
, FD_DESC_SZ
);
913 rb_set_type(rb_fde_t
*F
, rb_uint8_t type
)
915 /* if the caller is calling this, lets assume they have a clue */
921 rb_get_type(rb_fde_t
*F
)
927 rb_fd_ssl(rb_fde_t
*F
)
931 if(F
->type
& RB_FD_SSL
)
937 rb_get_fd(rb_fde_t
*F
)
947 return rb_find_fd(fd
);
951 rb_read(rb_fde_t
*F
, void *buf
, int count
)
957 /* This needs to be *before* RB_FD_SOCKET otherwise you'll process
958 * an SSL socket as a regular socket
961 if(F
->type
& RB_FD_SSL
)
963 return rb_ssl_read(F
, buf
, count
);
966 if(F
->type
& RB_FD_SOCKET
)
968 ret
= recv(F
->fd
, buf
, count
, 0);
978 return read(F
->fd
, buf
, count
);
983 rb_write(rb_fde_t
*F
, const void *buf
, int count
)
990 if(F
->type
& RB_FD_SSL
)
992 return rb_ssl_write(F
, buf
, count
);
995 if(F
->type
& RB_FD_SOCKET
)
997 ret
= send(F
->fd
, buf
, count
, MSG_NOSIGNAL
);
1004 return write(F
->fd
, buf
, count
);
1007 #if defined(HAVE_SSL) || defined(WIN32) || !defined(HAVE_WRITEV)
1009 rb_fake_writev(rb_fde_t
*F
, const struct rb_iovec
*vp
, size_t vpcount
)
1013 while (vpcount
-- > 0)
1015 size_t written
= rb_write(F
, vp
->iov_base
, vp
->iov_len
);
1031 #if defined(WIN32) || !defined(HAVE_WRITEV)
1033 rb_writev(rb_fde_t
*F
, struct rb_iovec
*vecount
, int count
)
1035 return rb_fake_writev(F
, vecount
, count
);
1040 rb_writev(rb_fde_t
*F
, struct rb_iovec
*vector
, int count
)
1047 if(F
->type
& RB_FD_SSL
)
1049 return rb_fake_writev(F
, vector
, count
);
1051 #endif /* HAVE_SSL */
1053 if(F
->type
& RB_FD_SOCKET
)
1056 memset(&msg
, 0, sizeof(msg
));
1057 msg
.msg_iov
= (struct iovec
*)vector
;
1058 msg
.msg_iovlen
= count
;
1059 return sendmsg(F
->fd
, &msg
, MSG_NOSIGNAL
);
1061 #endif /* HAVE_SENDMSG */
1062 return writev(F
->fd
, (struct iovec
*)vector
, count
);
1069 * From: Thomas Helvey <tomh@inxpress.net>
1071 static const char *IpQuadTab
[] = {
1072 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
1073 "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
1074 "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
1075 "30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
1076 "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
1077 "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
1078 "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
1079 "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
1080 "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
1081 "90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
1082 "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
1083 "110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
1084 "120", "121", "122", "123", "124", "125", "126", "127", "128", "129",
1085 "130", "131", "132", "133", "134", "135", "136", "137", "138", "139",
1086 "140", "141", "142", "143", "144", "145", "146", "147", "148", "149",
1087 "150", "151", "152", "153", "154", "155", "156", "157", "158", "159",
1088 "160", "161", "162", "163", "164", "165", "166", "167", "168", "169",
1089 "170", "171", "172", "173", "174", "175", "176", "177", "178", "179",
1090 "180", "181", "182", "183", "184", "185", "186", "187", "188", "189",
1091 "190", "191", "192", "193", "194", "195", "196", "197", "198", "199",
1092 "200", "201", "202", "203", "204", "205", "206", "207", "208", "209",
1093 "210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
1094 "220", "221", "222", "223", "224", "225", "226", "227", "228", "229",
1095 "230", "231", "232", "233", "234", "235", "236", "237", "238", "239",
1096 "240", "241", "242", "243", "244", "245", "246", "247", "248", "249",
1097 "250", "251", "252", "253", "254", "255"
1101 * inetntoa - in_addr to string
1102 * changed name to remove collision possibility and
1103 * so behaviour is guaranteed to take a pointer arg.
1105 * inet_ntoa -- returned the dotted notation of a given
1108 * inet_ntoa -- its broken on some Ultrix/Dynix too. -avalon
1112 inetntoa(const char *in
)
1114 static char buf
[16];
1116 const unsigned char *a
= (const unsigned char *) in
;
1119 n
= IpQuadTab
[*a
++];
1123 n
= IpQuadTab
[*a
++];
1127 n
= IpQuadTab
[*a
++];
1140 * Copyright (c) 1996-1999 by Internet Software Consortium.
1142 * Permission to use, copy, modify, and distribute this software for any
1143 * purpose with or without fee is hereby granted, provided that the above
1144 * copyright notice and this permission notice appear in all copies.
1146 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
1147 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
1148 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
1149 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
1150 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
1151 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
1152 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
1156 #define SPRINTF(x) ((size_t)rb_sprintf x)
1159 * WARNING: Don't even consider trying to compile this on a system where
1160 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
1163 static const char *inet_ntop4(const unsigned char * src
, char *dst
, unsigned int size
);
1165 static const char *inet_ntop6(const unsigned char * src
, char *dst
, unsigned int size
);
1169 * inet_ntop4(src, dst, size)
1170 * format an IPv4 address
1172 * `dst' (as a const)
1174 * (1) uses no statics
1175 * (2) takes a unsigned char* not an in_addr as input
1180 inet_ntop4(const unsigned char *src
, char *dst
, unsigned int size
)
1184 return strcpy(dst
, inetntoa((const char *) src
));
1188 * inet_ntop6(src, dst, size)
1189 * convert IPv6 binary address into presentation (printable) format
1195 inet_ntop6(const unsigned char *src
, char *dst
, unsigned int size
)
1198 * Note that int32_t and int16_t need only be "at least" large enough
1199 * to contain a value of the specified size. On some systems, like
1200 * Crays, there is no such thing as an integer variable with 16 bits.
1201 * Keep this in mind if you think this function should have been coded
1202 * to use pointer overlays. All the world's not a VAX.
1204 char tmp
[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp
;
1210 unsigned int words
[IN6ADDRSZ
/ INT16SZ
];
1215 * Copy the input (bytewise) array into a wordwise array.
1216 * Find the longest run of 0x00's in src[] for :: shorthanding.
1218 memset(words
, '\0', sizeof words
);
1219 for (i
= 0; i
< IN6ADDRSZ
; i
+= 2)
1220 words
[i
/ 2] = (src
[i
] << 8) | src
[i
+ 1];
1225 for (i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++)
1230 cur
.base
= i
, cur
.len
= 1;
1238 if(best
.base
== -1 || cur
.len
> best
.len
)
1246 if(best
.base
== -1 || cur
.len
> best
.len
)
1249 if(best
.base
!= -1 && best
.len
< 2)
1253 * Format the result.
1256 for (i
= 0; i
< (IN6ADDRSZ
/ INT16SZ
); i
++)
1258 /* Are we inside the best run of 0x00's? */
1259 if(best
.base
!= -1 && i
>= best
.base
&& i
< (best
.base
+ best
.len
))
1269 /* Are we following an initial run of 0x00s or any real hex? */
1272 /* Is this address an encapsulated IPv4? */
1273 if(i
== 6 && best
.base
== 0 &&
1274 (best
.len
== 6 || (best
.len
== 5 && words
[5] == 0xffff)))
1276 if(!inet_ntop4(src
+ 12, tp
, sizeof tmp
- (tp
- tmp
)))
1281 tp
+= SPRINTF((tp
, "%x", words
[i
]));
1283 /* Was it a trailing run of 0x00's? */
1284 if(best
.base
!= -1 && (best
.base
+ best
.len
) == (IN6ADDRSZ
/ INT16SZ
))
1289 * Check for overflow, copy, and we're done.
1292 if((unsigned int) (tp
- tmp
) > size
)
1296 return strcpy(dst
, tmp
);
1301 rb_inet_pton_sock(const char *src
, struct sockaddr
*dst
)
1303 if(rb_inet_pton(AF_INET
, src
, &((struct sockaddr_in
*) dst
)->sin_addr
))
1305 ((struct sockaddr_in
*) dst
)->sin_port
= 0;
1306 ((struct sockaddr_in
*) dst
)->sin_family
= AF_INET
;
1307 SET_SS_LEN(dst
, sizeof(struct sockaddr_in
));
1311 else if(rb_inet_pton(AF_INET6
, src
, &((struct sockaddr_in6
*) dst
)->sin6_addr
))
1313 ((struct sockaddr_in6
*) dst
)->sin6_port
= 0;
1314 ((struct sockaddr_in6
*) dst
)->sin6_family
= AF_INET6
;
1315 SET_SS_LEN(dst
, sizeof(struct sockaddr_in6
));
1323 rb_inet_ntop_sock(struct sockaddr
*src
, char *dst
, unsigned int size
)
1325 switch (src
->sa_family
)
1328 return (rb_inet_ntop(AF_INET
, &((struct sockaddr_in
*) src
)->sin_addr
, dst
, size
));
1332 return (rb_inet_ntop(AF_INET6
, &((struct sockaddr_in6
*) src
)->sin6_addr
, dst
, size
));
1342 * rb_inet_ntop(af, src, dst, size)
1343 * convert a network format address to presentation format.
1345 * pointer to presentation format address (`dst'), or NULL (see errno).
1350 rb_inet_ntop(int af
, const void *src
, char *dst
, unsigned int size
)
1355 return (inet_ntop4(src
, dst
, size
));
1358 if(IN6_IS_ADDR_V4MAPPED((const struct in6_addr
*) src
) ||
1359 IN6_IS_ADDR_V4COMPAT((const struct in6_addr
*) src
))
1361 ((const unsigned char *)
1362 &((const struct in6_addr
*) src
)->s6_addr
[12], dst
, size
));
1364 return (inet_ntop6(src
, dst
, size
));
1375 * WARNING: Don't even consider trying to compile this on a system where
1376 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
1380 * rb_inet_pton(af, src, dst)
1381 * convert from presentation format (which usually means ASCII printable)
1382 * to network format (which is usually some kind of binary format).
1384 * 1 if the address was valid for the specified address family
1385 * 0 if the address wasn't valid (`dst' is untouched in this case)
1386 * -1 if some other error occurred (`dst' is untouched in this case, too)
1392 * inet_pton4(src, dst)
1393 * like inet_aton() but without all the hexadecimal and shorthand.
1395 * 1 if `src' is a valid dotted quad, else 0.
1397 * does not touch `dst' unless it's returning 1.
1402 inet_pton4(const char *src
, unsigned char *dst
)
1404 int saw_digit
, octets
, ch
;
1405 unsigned char tmp
[INADDRSZ
], *tp
;
1410 while ((ch
= *src
++) != '\0')
1413 if(ch
>= '0' && ch
<= '9')
1415 unsigned int new = *tp
* 10 + (ch
- '0');
1427 else if(ch
== '.' && saw_digit
)
1439 memcpy(dst
, tmp
, INADDRSZ
);
1445 * inet_pton6(src, dst)
1446 * convert presentation level address to network order binary form.
1448 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
1450 * (1) does not touch `dst' unless it's returning 1.
1451 * (2) :: in a full address is silently ignored.
1453 * inspired by Mark Andrews.
1459 inet_pton6(const char *src
, unsigned char *dst
)
1461 static const char xdigits
[] = "0123456789abcdef";
1462 unsigned char tmp
[IN6ADDRSZ
], *tp
, *endp
, *colonp
;
1467 tp
= memset(tmp
, '\0', IN6ADDRSZ
);
1468 endp
= tp
+ IN6ADDRSZ
;
1470 /* Leading :: requires some special handling. */
1477 while ((ch
= tolower(*src
++)) != '\0')
1481 pch
= strchr(xdigits
, ch
);
1485 val
|= (pch
- xdigits
);
1501 else if(*src
== '\0')
1505 if(tp
+ INT16SZ
> endp
)
1507 *tp
++ = (unsigned char) (val
>> 8) & 0xff;
1508 *tp
++ = (unsigned char) val
& 0xff;
1513 if(*src
!= '\0' && ch
== '.')
1515 if(((tp
+ INADDRSZ
) <= endp
) && inet_pton4(curtok
, tp
) > 0)
1519 break; /* '\0' was seen by inet_pton4(). */
1528 if(tp
+ INT16SZ
> endp
)
1530 *tp
++ = (unsigned char) (val
>> 8) & 0xff;
1531 *tp
++ = (unsigned char) val
& 0xff;
1536 * Since some memmove()'s erroneously fail to handle
1537 * overlapping regions, we'll do the shift by hand.
1539 const int n
= tp
- colonp
;
1544 for (i
= 1; i
<= n
; i
++)
1546 endp
[-i
] = colonp
[n
- i
];
1553 memcpy(dst
, tmp
, IN6ADDRSZ
);
1558 rb_inet_pton(int af
, const char *src
, void *dst
)
1563 return (inet_pton4(src
, dst
));
1566 /* Somebody might have passed as an IPv4 address this is sick but it works */
1567 if(inet_pton4(src
, dst
))
1569 char tmp
[HOSTIPLEN
];
1570 rb_sprintf(tmp
, "::ffff:%s", src
);
1571 return (inet_pton6(tmp
, dst
));
1574 return (inet_pton6(src
, dst
));
1583 #ifndef HAVE_SOCKETPAIR
1585 rb_inet_socketpair(int family
, int type
, int protocol
, int fd
[2])
1590 struct sockaddr_in listen_addr
;
1591 struct sockaddr_in connect_addr
;
1594 if(protocol
|| family
!= AF_INET
)
1596 errno
= EAFNOSUPPORT
;
1605 listener
= socket(AF_INET
, type
, 0);
1608 memset(&listen_addr
, 0, sizeof(listen_addr
));
1609 listen_addr
.sin_family
= AF_INET
;
1610 listen_addr
.sin_addr
.s_addr
= htonl(INADDR_LOOPBACK
);
1611 listen_addr
.sin_port
= 0; /* kernel choses port. */
1612 if(bind(listener
, (struct sockaddr
*) &listen_addr
, sizeof(listen_addr
)) == -1)
1613 goto tidy_up_and_fail
;
1614 if(listen(listener
, 1) == -1)
1615 goto tidy_up_and_fail
;
1617 connector
= socket(AF_INET
, type
, 0);
1619 goto tidy_up_and_fail
;
1620 /* We want to find out the port number to connect to. */
1621 size
= sizeof(connect_addr
);
1622 if(getsockname(listener
, (struct sockaddr
*) &connect_addr
, &size
) == -1)
1623 goto tidy_up_and_fail
;
1624 if(size
!= sizeof(connect_addr
))
1625 goto abort_tidy_up_and_fail
;
1626 if(connect(connector
, (struct sockaddr
*) &connect_addr
, sizeof(connect_addr
)) == -1)
1627 goto tidy_up_and_fail
;
1629 size
= sizeof(listen_addr
);
1630 acceptor
= accept(listener
, (struct sockaddr
*) &listen_addr
, &size
);
1632 goto tidy_up_and_fail
;
1633 if(size
!= sizeof(listen_addr
))
1634 goto abort_tidy_up_and_fail
;
1636 /* Now check we are talking to ourself by matching port and host on the
1638 if(getsockname(connector
, (struct sockaddr
*) &connect_addr
, &size
) == -1)
1639 goto tidy_up_and_fail
;
1640 if(size
!= sizeof(connect_addr
)
1641 || listen_addr
.sin_family
!= connect_addr
.sin_family
1642 || listen_addr
.sin_addr
.s_addr
!= connect_addr
.sin_addr
.s_addr
1643 || listen_addr
.sin_port
!= connect_addr
.sin_port
)
1645 goto abort_tidy_up_and_fail
;
1651 abort_tidy_up_and_fail
:
1652 errno
= EINVAL
; /* I hope this is portable and appropriate. */
1656 int save_errno
= errno
;
1671 static void (*setselect_handler
) (rb_fde_t
*, unsigned int, PF
*, void *);
1672 static int (*select_handler
) (long);
1673 static int (*setup_fd_handler
) (rb_fde_t
*);
1674 static int (*io_sched_event
) (struct ev_entry
*, int);
1675 static void (*io_unsched_event
) (struct ev_entry
*);
1676 static int (*io_supports_event
) (void);
1677 static void (*io_init_event
) (void);
1678 static char iotype
[25];
1687 rb_unsupported_event(void)
1695 if(!rb_init_netio_kqueue())
1697 setselect_handler
= rb_setselect_kqueue
;
1698 select_handler
= rb_select_kqueue
;
1699 setup_fd_handler
= rb_setup_fd_kqueue
;
1700 io_sched_event
= rb_kqueue_sched_event
;
1701 io_unsched_event
= rb_kqueue_unsched_event
;
1702 io_init_event
= rb_kqueue_init_event
;
1703 io_supports_event
= rb_kqueue_supports_event
;
1704 rb_strlcpy(iotype
, "kqueue", sizeof(iotype
));
1713 if(!rb_init_netio_epoll())
1715 setselect_handler
= rb_setselect_epoll
;
1716 select_handler
= rb_select_epoll
;
1717 setup_fd_handler
= rb_setup_fd_epoll
;
1718 io_sched_event
= rb_epoll_sched_event
;
1719 io_unsched_event
= rb_epoll_unsched_event
;
1720 io_supports_event
= rb_epoll_supports_event
;
1721 io_init_event
= rb_epoll_init_event
;
1722 rb_strlcpy(iotype
, "epoll", sizeof(iotype
));
1731 if(!rb_init_netio_ports())
1733 setselect_handler
= rb_setselect_ports
;
1734 select_handler
= rb_select_ports
;
1735 setup_fd_handler
= rb_setup_fd_ports
;
1736 io_sched_event
= NULL
;
1737 io_unsched_event
= NULL
;
1738 io_init_event
= NULL
;
1739 io_supports_event
= rb_unsupported_event
;
1740 rb_strlcpy(iotype
, "ports", sizeof(iotype
));
1749 if(!rb_init_netio_devpoll())
1751 setselect_handler
= rb_setselect_devpoll
;
1752 select_handler
= rb_select_devpoll
;
1753 setup_fd_handler
= rb_setup_fd_devpoll
;
1754 io_sched_event
= NULL
;
1755 io_unsched_event
= NULL
;
1756 io_init_event
= NULL
;
1757 io_supports_event
= rb_unsupported_event
;
1758 rb_strlcpy(iotype
, "devpoll", sizeof(iotype
));
1767 if(!rb_init_netio_sigio())
1769 setselect_handler
= rb_setselect_sigio
;
1770 select_handler
= rb_select_sigio
;
1771 setup_fd_handler
= rb_setup_fd_sigio
;
1772 io_sched_event
= rb_sigio_sched_event
;
1773 io_unsched_event
= rb_sigio_unsched_event
;
1774 io_supports_event
= rb_sigio_supports_event
;
1775 io_init_event
= rb_sigio_init_event
;
1777 rb_strlcpy(iotype
, "sigio", sizeof(iotype
));
1786 if(!rb_init_netio_poll())
1788 setselect_handler
= rb_setselect_poll
;
1789 select_handler
= rb_select_poll
;
1790 setup_fd_handler
= rb_setup_fd_poll
;
1791 io_sched_event
= NULL
;
1792 io_unsched_event
= NULL
;
1793 io_init_event
= NULL
;
1794 io_supports_event
= rb_unsupported_event
;
1795 rb_strlcpy(iotype
, "poll", sizeof(iotype
));
1804 if(!rb_init_netio_win32())
1806 setselect_handler
= rb_setselect_win32
;
1807 select_handler
= rb_select_win32
;
1808 setup_fd_handler
= rb_setup_fd_win32
;
1809 io_sched_event
= NULL
;
1810 io_unsched_event
= NULL
;
1811 io_init_event
= NULL
;
1812 io_supports_event
= rb_unsupported_event
;
1813 rb_strlcpy(iotype
, "win32", sizeof(iotype
));
1822 if(!rb_init_netio_select())
1824 setselect_handler
= rb_setselect_select
;
1825 select_handler
= rb_select_select
;
1826 setup_fd_handler
= rb_setup_fd_select
;
1827 io_sched_event
= NULL
;
1828 io_unsched_event
= NULL
;
1829 io_init_event
= NULL
;
1830 io_supports_event
= rb_unsupported_event
;
1831 rb_strlcpy(iotype
, "select", sizeof(iotype
));
1839 rb_io_sched_event(struct ev_entry
*ev
, int when
)
1841 if(ev
== NULL
|| io_supports_event
== NULL
|| io_sched_event
== NULL
|| !io_supports_event())
1843 return io_sched_event(ev
, when
);
1847 rb_io_unsched_event(struct ev_entry
*ev
)
1849 if(ev
== NULL
|| io_supports_event
== NULL
|| io_unsched_event
== NULL
|| !io_supports_event())
1851 io_unsched_event(ev
);
1854 rb_io_supports_event(void)
1856 if(io_supports_event
== NULL
)
1858 return io_supports_event();
1862 rb_io_init_event(void)
1865 rb_event_io_register_all();
1871 char *ioenv
= getenv("LIBRB_USE_IOTYPE");
1872 rb_fd_table
= rb_malloc(RB_FD_HASH_SIZE
* sizeof(rb_dlink_list
));
1877 if(!strcmp("epoll", ioenv
))
1882 if(!strcmp("kqueue", ioenv
))
1887 if(!strcmp("ports", ioenv
))
1892 if(!strcmp("poll", ioenv
))
1897 if(!strcmp("devpoll", ioenv
))
1902 if(!strcmp("sigio", ioenv
))
1907 if(!strcmp("win32", ioenv
))
1912 if(!strcmp("select", ioenv
))
1937 rb_lib_log("rb_init_netio: Could not find any io handlers...giving up");
1943 rb_setselect(rb_fde_t
*F
, unsigned int type
, PF
* handler
, void *client_data
)
1945 setselect_handler(F
, type
, handler
, client_data
);
1949 rb_select(unsigned long timeout
)
1951 int ret
= select_handler(timeout
);
1957 rb_setup_fd(rb_fde_t
*F
)
1959 return setup_fd_handler(F
);
1965 rb_ignore_errno(int error
)
1972 #if defined EWOULDBLOCK
1975 #if defined(EAGAIN) && (EWOULDBLOCK != EAGAIN)
1996 rb_recv_fd_buf(rb_fde_t
*F
, void *data
, size_t datasize
, rb_fde_t
**xF
, int nfds
)
1999 struct cmsghdr
*cmsg
;
2000 struct iovec iov
[1];
2002 rb_uint8_t stype
= RB_FD_UNKNOWN
;
2004 int fd
, len
, x
, rfds
;
2006 int control_len
= CMSG_SPACE(sizeof(int) * nfds
);
2008 iov
[0].iov_base
= data
;
2009 iov
[0].iov_len
= datasize
;
2011 msg
.msg_name
= NULL
;
2012 msg
.msg_namelen
= 0;
2016 cmsg
= alloca(control_len
);
2017 msg
.msg_control
= cmsg
;
2018 msg
.msg_controllen
= control_len
;
2020 if((len
= recvmsg(rb_get_fd(F
), &msg
, 0)) <= 0)
2023 if(msg
.msg_controllen
> 0 && msg
.msg_control
!= NULL
&& (cmsg
= CMSG_FIRSTHDR(&msg
)) != NULL
)
2025 rfds
= (msg
.msg_controllen
- sizeof(struct cmsghdr
)) / sizeof(int);
2027 for(x
= 0; x
< nfds
&& x
< rfds
; x
++)
2029 fd
= ((int *)CMSG_DATA(cmsg
))[x
];
2030 stype
= RB_FD_UNKNOWN
;
2031 desc
= "remote unknown";
2034 if(S_ISSOCK(st
.st_mode
))
2036 stype
= RB_FD_SOCKET
;
2037 desc
= "remote socket";
2039 else if(S_ISFIFO(st
.st_mode
))
2042 desc
= "remote pipe";
2044 else if(S_ISREG(st
.st_mode
))
2047 desc
= "remote file";
2050 xF
[x
] = rb_open(fd
, stype
, desc
);
2059 rb_send_fd_buf(rb_fde_t
*xF
, rb_fde_t
**F
, int count
, void *data
, size_t datasize
)
2063 struct cmsghdr
*cmsg
;
2064 struct iovec iov
[1];
2068 memset(&msg
, 0, sizeof(&msg
));
2071 iov
[0].iov_base
= &empty
;
2074 iov
[0].iov_base
= data
;
2075 iov
[0].iov_len
= datasize
;
2079 msg
.msg_name
= NULL
;
2080 msg
.msg_namelen
= 0;
2082 msg
.msg_control
= NULL
;
2083 msg
.msg_controllen
= 0;
2088 int len
= CMSG_SPACE(sizeof(int) * count
);
2091 msg
.msg_control
= buf
;
2092 msg
.msg_controllen
= len
;
2093 cmsg
= CMSG_FIRSTHDR(&msg
);
2094 cmsg
->cmsg_level
= SOL_SOCKET
;
2095 cmsg
->cmsg_type
= SCM_RIGHTS
;
2096 cmsg
->cmsg_len
= CMSG_LEN(sizeof(int) * count
);
2098 for(i
= 0; i
< count
; i
++)
2100 ((int *)CMSG_DATA(cmsg
))[i
] = rb_get_fd(F
[i
]);
2102 msg
.msg_controllen
= cmsg
->cmsg_len
;
2104 n
= sendmsg(rb_get_fd(xF
), &msg
, MSG_NOSIGNAL
);