]> jfr.im git - irc/rqf/shadowircd.git/blob - libratbox/src/commio.c
dlink -> rb_dlink
[irc/rqf/shadowircd.git] / libratbox / src / commio.c
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * commio.c: Network/file related functions
4 *
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
8 *
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.
13 *
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.
18 *
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
22 * USA
23 *
24 * $Id: commio.c 25038 2008-01-23 16:03:08Z androsyn $
25 */
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>
31 #ifdef HAVE_SYS_UIO_H
32 #include <sys/uio.h>
33 #endif
34 #define HAVE_SSL 1
35
36 #ifndef MSG_NOSIGNAL
37 #define MSG_NOSIGNAL 0
38 #endif
39
40
41 struct timeout_data
42 {
43 rb_fde_t *F;
44 rb_dlink_node node;
45 time_t timeout;
46 PF *timeout_handler;
47 void *timeout_data;
48 };
49
50 rb_dlink_list *rb_fd_table;
51 static rb_bh *fd_heap;
52
53 static rb_dlink_list timeout_list;
54 static rb_dlink_list closed_list;
55
56 static struct ev_entry *rb_timeout_ev;
57
58
59 static const char *rb_err_str[] = { "Comm OK", "Error during bind()",
60 "Error during DNS lookup", "connect timeout",
61 "Error during connect()",
62 "Comm Error"
63 };
64
65 /* Highest FD and number of open FDs .. */
66 static int number_fd = 0;
67 static int rb_maxconnections = 0;
68
69 static PF rb_connect_timeout;
70 static PF rb_connect_tryconnect;
71 #ifdef RB_IPV6
72 static void mangle_mapped_sockaddr(struct sockaddr *in);
73 #endif
74
75 #ifndef HAVE_SOCKETPAIR
76 static int rb_inet_socketpair(int d, int type, int protocol, int sv[2]);
77 #endif
78
79 static inline rb_fde_t *
80 add_fd(int fd)
81 {
82 rb_fde_t *F = rb_find_fd(fd);
83 rb_dlink_list *list;
84
85 /* look up to see if we have it already */
86 if(F != NULL)
87 return F;
88
89 F = rb_bh_alloc(fd_heap);
90 F->fd = fd;
91 list = &rb_fd_table[rb_hash_fd(fd)];
92 rb_dlinkAdd(F, &F->node, list);
93 return(F);
94 }
95
96 static inline void
97 remove_fd(rb_fde_t *F)
98 {
99 rb_dlink_list *list;
100
101 if(F == NULL || !IsFDOpen(F))
102 return;
103
104 list = &rb_fd_table[rb_hash_fd(F->fd)];
105 rb_dlinkMoveNode(&F->node, list, &closed_list);
106 }
107
108 static void
109 free_fds(void)
110 {
111 rb_fde_t *F;
112 rb_dlink_node *ptr, *next;
113 RB_DLINK_FOREACH_SAFE(ptr, next, closed_list.head)
114 {
115 F = ptr->data;
116 rb_dlinkDelete(ptr, &closed_list);
117 rb_bh_free(fd_heap, F);
118 }
119 }
120
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)
124 */
125
126 #if defined (__SVR4) && defined (__sun)
127 static void
128 rb_fd_hack(int *fd)
129 {
130 int newfd;
131 if(*fd > 256 || *fd < 0)
132 return;
133 if((newfd = fcntl(*fd, F_DUPFD, 256)) != -1)
134 {
135 close(*fd);
136 *fd = newfd;
137 }
138 return;
139 }
140 #else
141 #define rb_fd_hack(fd)
142 #endif
143
144
145 /* close_all_connections() can be used *before* the system come up! */
146
147 static void
148 rb_close_all(void)
149 {
150 int i;
151 #ifndef NDEBUG
152 int fd;
153 #endif
154
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)
158 {
159 close(i);
160 }
161
162 /* XXX should his hack be done in all cases? */
163 #ifndef NDEBUG
164 /* fugly hack to reserve fd == 2 */
165 (void) close(2);
166 fd = open("stderr.log", O_WRONLY | O_CREAT | O_APPEND, 0644);
167 if(fd >= 0)
168 {
169 dup2(fd, 2);
170 close(fd);
171 }
172 #endif
173 }
174
175 /*
176 * get_sockerr - get the error value from the socket or the current errno
177 *
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
180 * gamble anyway.
181 */
182 int
183 rb_get_sockerr(rb_fde_t *F)
184 {
185 int errtmp;
186 int err = 0;
187 rb_socklen_t len = sizeof(err);
188
189 if(!(F->type & RB_FD_SOCKET))
190 return errno;
191
192 rb_get_errno();
193 errtmp = errno;
194
195 #ifdef SO_ERROR
196 if(F != NULL && !getsockopt(rb_get_fd(F), SOL_SOCKET, SO_ERROR, (char *) &err, (rb_socklen_t *) & len))
197 {
198 if(err)
199 errtmp = err;
200 }
201 errno = errtmp;
202 #endif
203 return errtmp;
204 }
205
206 /*
207 * rb_getmaxconnect - return the max number of connections allowed
208 */
209 int
210 rb_getmaxconnect(void)
211 {
212 return(rb_maxconnections);
213 }
214
215 /*
216 * set_sock_buffers - set send and receive buffers for socket
217 *
218 * inputs - fd file descriptor
219 * - size to set
220 * output - returns true (1) if successful, false (0) otherwise
221 * side effects -
222 */
223 int
224 rb_set_buffers(rb_fde_t *F, int size)
225 {
226 if(F == NULL)
227 return 0;
228 if(setsockopt
229 (F->fd, SOL_SOCKET, SO_RCVBUF, (char *) &size, sizeof(size))
230 || setsockopt(F->fd, SOL_SOCKET, SO_SNDBUF, (char *) &size, sizeof(size)))
231 return 0;
232 return 1;
233 }
234
235 /*
236 * set_non_blocking - Set the client connection into non-blocking mode.
237 *
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
241 * be done with it.
242 */
243 int
244 rb_set_nb(rb_fde_t *F)
245 {
246 int nonb = 0;
247 int res;
248 int fd;
249 if(F == NULL)
250 return 0;
251 fd = F->fd;
252
253 if((res = rb_setup_fd(F)))
254 return res;
255 #ifdef O_NONBLOCK
256 nonb |= O_NONBLOCK;
257 res = fcntl(fd, F_GETFL, 0);
258 if(-1 == res || fcntl(fd, F_SETFL, res | nonb) == -1)
259 return 0;
260 #else
261 nonb = 1;
262 res = 0;
263 if(ioctl(fd, FIONBIO, (char *)&nonb) == -1)
264 return 0;
265 #endif
266
267 return 1;
268 }
269
270 /*
271 * rb_settimeout() - set the socket timeout
272 *
273 * Set the timeout for the fd
274 */
275 void
276 rb_settimeout(rb_fde_t *F, time_t timeout, PF * callback, void *cbdata)
277 {
278 struct timeout_data *td;
279
280 if(F == NULL)
281 return;
282
283 lrb_assert(IsFDOpen(F));
284 td = F->timeout;
285 if(callback == NULL) /* user wants to remove */
286 {
287 if(td == NULL)
288 return;
289 rb_dlinkDelete(&td->node, &timeout_list);
290 rb_free(td);
291 F->timeout = NULL;
292 if(rb_dlink_list_length(&timeout_list) == 0)
293 {
294 rb_event_delete(rb_timeout_ev);
295 rb_timeout_ev = NULL;
296 }
297 return;
298 }
299
300 if(F->timeout == NULL)
301 td = F->timeout = rb_malloc(sizeof(struct timeout_data));
302
303 td->F = F;
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)
309 {
310 rb_timeout_ev = rb_event_add("rb_checktimeouts", rb_checktimeouts, NULL, 5);
311 }
312 }
313
314 /*
315 * rb_checktimeouts() - check the socket timeouts
316 *
317 * All this routine does is call the given callback/cbdata, without closing
318 * down the file descriptor. When close handlers have been implemented,
319 * this will happen.
320 */
321 void
322 rb_checktimeouts(void *notused)
323 {
324 rb_dlink_node *ptr, *next;
325 struct timeout_data *td;
326 rb_fde_t *F;
327 PF *hdl;
328 void *data;
329
330 RB_DLINK_FOREACH_SAFE(ptr, next, timeout_list.head)
331 {
332 td = ptr->data;
333 F = td->F;
334 if(F == NULL || !IsFDOpen(F))
335 continue;
336
337 if(td->timeout < rb_current_time())
338 {
339 hdl = td->timeout_handler;
340 data = td->timeout_data;
341 rb_dlinkDelete(&td->node, &timeout_list);
342 F->timeout = NULL;
343 rb_free(td);
344 hdl(F, data);
345 }
346 }
347 }
348
349 static void
350 rb_accept_tryaccept(rb_fde_t *F, void *data)
351 {
352 struct rb_sockaddr_storage st;
353 rb_fde_t *new_F;
354 rb_socklen_t addrlen = sizeof(st);
355 int new_fd;
356
357 while(1)
358 {
359 new_fd = accept(F->fd, (struct sockaddr *)&st, &addrlen);
360 rb_get_errno();
361 if(new_fd < 0)
362 {
363 rb_setselect(F, RB_SELECT_ACCEPT, rb_accept_tryaccept, NULL);
364 return;
365 }
366
367 rb_fd_hack(&new_fd);
368
369 new_F = rb_open(new_fd, RB_FD_SOCKET, "Incoming Connection");
370
371 if(unlikely(!rb_set_nb(new_F)))
372 {
373 rb_get_errno();
374 rb_lib_log("rb_accept: Couldn't set FD %d non blocking!", new_F->fd);
375 rb_close(new_F);
376 }
377
378 #ifdef RB_IPV6
379 mangle_mapped_sockaddr((struct sockaddr *)&st);
380 #endif
381
382 if(F->accept->precb != NULL)
383 {
384 if(!F->accept->precb(new_F, (struct sockaddr *)&st, addrlen, F->accept->data)) /* pre-callback decided to drop it */
385 continue;
386 }
387 #ifdef HAVE_SSL
388 if(F->type & RB_FD_SSL)
389 {
390 rb_ssl_accept_setup(F, new_fd, (struct sockaddr *)&st, addrlen);
391 }
392 else
393 #endif /* HAVE_SSL */
394 {
395 F->accept->callback(new_F, RB_OK, (struct sockaddr *)&st, addrlen, F->accept->data);
396 }
397 }
398
399 }
400
401 /* try to accept a TCP connection */
402 void
403 rb_accept_tcp(rb_fde_t *F, ACPRE *precb, ACCB *callback, void *data)
404 {
405 if(F == NULL)
406 return;
407 lrb_assert(callback);
408
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);
414 }
415
416 /*
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
423 * address family.
424 * Output: None.
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.
428 */
429 void
430 rb_connect_tcp(rb_fde_t *F, struct sockaddr *dest,
431 struct sockaddr *clocal, int socklen, CNCB * callback, void *data, int timeout)
432 {
433 if(F == NULL)
434 return;
435
436 lrb_assert(callback);
437 F->connect = rb_malloc(sizeof(struct conndata));
438 F->connect->callback = callback;
439 F->connect->data = data;
440
441 memcpy(&F->connect->hostaddr, dest, sizeof(F->connect->hostaddr));
442
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.
448 * -- adrian
449 */
450 if((clocal != NULL) && (bind(F->fd, clocal, socklen) < 0))
451 {
452 /* Failure, call the callback with RB_ERR_BIND */
453 rb_connect_callback(F, RB_ERR_BIND);
454 /* ... and quit */
455 return;
456 }
457
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);
462 }
463
464
465 /*
466 * rb_connect_callback() - call the callback, and continue with life
467 */
468 void
469 rb_connect_callback(rb_fde_t *F, int status)
470 {
471 CNCB *hdl;
472 void *data;
473
474 /* This check is gross..but probably necessary */
475 if(F == NULL || F->connect == NULL || F->connect->callback == NULL)
476 return;
477 /* Clear the connect flag + handler */
478 hdl = F->connect->callback;
479 data = F->connect->data;
480 F->connect->callback = NULL;
481
482 /* Clear the timeout handler */
483 rb_settimeout(F, 0, NULL, NULL);
484 /* Call the handler */
485 hdl(F, status, data);
486 }
487
488
489 /*
490 * rb_connect_timeout() - this gets called when the socket connection
491 * times out. This *only* can be called once connect() is initially
492 * called ..
493 */
494 static void
495 rb_connect_timeout(rb_fde_t *F, void *notused)
496 {
497 /* error! */
498 rb_connect_callback(F, RB_ERR_TIMEOUT);
499 }
500
501 /* static void rb_connect_tryconnect(int fd, void *notused)
502 * Input: The fd, the handler data(unused).
503 * Output: None.
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.
508 */
509 static void
510 rb_connect_tryconnect(rb_fde_t *F, void *notused)
511 {
512 int retval;
513
514 if(F == NULL || F->connect == NULL || F->connect->callback == NULL)
515 return;
516 /* Try the connect() */
517 retval = connect(F->fd,
518 (struct sockaddr *) &F->connect->hostaddr, GET_SS_LEN(&F->connect->hostaddr));
519 /* Error? */
520 if(retval < 0)
521 {
522 /*
523 * If we get EISCONN, then we've already connect()ed the socket,
524 * which is a good thing.
525 * -- adrian
526 */
527 rb_get_errno();
528 if(errno == EISCONN)
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);
534 else
535 /* Error? Fail with RB_ERR_CONNECT */
536 rb_connect_callback(F, RB_ERR_CONNECT);
537 return;
538 }
539 /* If we get here, we've suceeded, so call with RB_OK */
540 rb_connect_callback(F, RB_OK);
541 }
542
543
544 int
545 rb_connect_sockaddr(rb_fde_t *F, struct sockaddr *addr, int len)
546 {
547 if(F == NULL)
548 return 0;
549
550 memcpy(addr, &F->connect->hostaddr, len);
551 return 1;
552 }
553
554 /*
555 * rb_error_str() - return an error string for the given error condition
556 */
557 const char *
558 rb_errstr(int error)
559 {
560 if(error < 0 || error >= RB_ERR_MAX)
561 return "Invalid error number!";
562 return rb_err_str[error];
563 }
564
565
566 int
567 rb_socketpair(int family, int sock_type, int proto, rb_fde_t **F1, rb_fde_t **F2, const char *note)
568 {
569 int nfd[2];
570 if(number_fd >= rb_maxconnections)
571 {
572 errno = ENFILE;
573 return -1;
574 }
575
576 #ifndef WIN32
577 if(socketpair(family, sock_type, proto, nfd))
578 #else
579 if(rb_inet_socketpair(AF_INET, SOCK_STREAM, proto, nfd))
580 #endif
581 return -1;
582
583 rb_fd_hack(&nfd[0]);
584 rb_fd_hack(&nfd[1]);
585
586 *F1 = rb_open(nfd[0], RB_FD_SOCKET, note);
587 *F2 = rb_open(nfd[1], RB_FD_SOCKET, note);
588
589 if(*F1 == NULL)
590 {
591 if(*F2 != NULL)
592 rb_close(*F2);
593 return -1;
594 }
595
596 if(*F2 == NULL)
597 {
598 rb_close(*F1);
599 return -1;
600 }
601
602 /* Set the socket non-blocking, and other wonderful bits */
603 if(unlikely(!rb_set_nb(*F1)))
604 {
605 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd[0], strerror(errno));
606 rb_close(*F1);
607 rb_close(*F2);
608 return -1;
609 }
610
611 if(unlikely(!rb_set_nb(*F2)))
612 {
613 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd[1], strerror(errno));
614 rb_close(*F1);
615 rb_close(*F2);
616 return -1;
617 }
618
619 return 0;
620 }
621
622
623 int
624 rb_pipe(rb_fde_t **F1, rb_fde_t **F2, const char *desc)
625 {
626 #ifndef WIN32
627 int fd[2];
628 if(number_fd >= rb_maxconnections)
629 {
630 errno = ENFILE;
631 return -1;
632 }
633 if(pipe(fd) == -1)
634 return -1;
635 rb_fd_hack(&fd[0]);
636 rb_fd_hack(&fd[1]);
637 *F1 = rb_open(fd[0], RB_FD_PIPE, desc);
638 *F2 = rb_open(fd[1], RB_FD_PIPE, desc);
639
640 if(unlikely(!rb_set_nb(*F1)))
641 {
642 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd[0], strerror(errno));
643 rb_close(*F1);
644 rb_close(*F2);
645 return -1;
646 }
647
648 if(unlikely(!rb_set_nb(*F2)))
649 {
650 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd[1], strerror(errno));
651 rb_close(*F1);
652 rb_close(*F2);
653 return -1;
654 }
655
656
657 return 0;
658 #else
659 /* Its not a pipe..but its selectable. I'll take dirty hacks
660 * for $500 Alex.
661 */
662 return rb_socketpair(AF_INET, SOCK_STREAM, 0, F1, F2, desc);
663 #endif
664 }
665
666 /*
667 * rb_socket() - open a socket
668 *
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.
672 */
673 rb_fde_t *
674 rb_socket(int family, int sock_type, int proto, const char *note)
675 {
676 rb_fde_t *F;
677 int fd;
678 /* First, make sure we aren't going to run out of file descriptors */
679 if(unlikely(number_fd >= rb_maxconnections))
680 {
681 errno = ENFILE;
682 return NULL;
683 }
684
685 /*
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.
688 * XXX !!! -- adrian
689 */
690 fd = socket(family, sock_type, proto);
691 rb_fd_hack(&fd);
692 if(unlikely(fd < 0))
693 return NULL; /* errno will be passed through, yay.. */
694
695 #if defined(RB_IPV6) && defined(IPV6_V6ONLY)
696 /*
697 * Make sure we can take both IPv4 and IPv6 connections
698 * on an AF_INET6 socket
699 */
700 if(family == AF_INET6)
701 {
702 int off = 1;
703 if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)) == -1)
704 {
705 rb_lib_log("rb_socket: Could not set IPV6_V6ONLY option to 1 on FD %d: %s",
706 fd, strerror(errno));
707 close(fd);
708 return NULL;
709 }
710 }
711 #endif
712
713 F = rb_open(fd, RB_FD_SOCKET, note);
714 if(F == NULL)
715 return NULL;
716
717 /* Set the socket non-blocking, and other wonderful bits */
718 if(unlikely(!rb_set_nb(F)))
719 {
720 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd, strerror(errno));
721 rb_close(F);
722 return NULL;
723 }
724
725 return F;
726 }
727
728 /*
729 * If a sockaddr_storage is AF_INET6 but is a mapped IPv4
730 * socket manged the sockaddr.
731 */
732 #ifdef RB_IPV6
733 static void
734 mangle_mapped_sockaddr(struct sockaddr *in)
735 {
736 struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) in;
737
738 if(in->sa_family == AF_INET)
739 return;
740
741 if(in->sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&in6->sin6_addr))
742 {
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));
749 }
750 return;
751 }
752 #endif
753
754 /*
755 * rb_listen() - listen on a port
756 */
757 int
758 rb_listen(rb_fde_t *F, int backlog)
759 {
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);
763 }
764
765 void
766 rb_fdlist_init(int closeall, int maxfds, size_t heapsize)
767 {
768 static int initialized = 0;
769 #ifdef WIN32
770 WSADATA wsaData;
771 int err;
772 int vers = MAKEWORD(2, 0);
773
774 err = WSAStartup(vers, &wsaData);
775 if(err != 0)
776 {
777 rb_lib_die("WSAStartup failed");
778 }
779
780 #endif
781 if(!initialized)
782 {
783 rb_maxconnections = maxfds;
784 if(closeall)
785 rb_close_all();
786 /* Since we're doing this once .. */
787 initialized = 1;
788 }
789 fd_heap = rb_bh_create(sizeof(rb_fde_t), heapsize, "librb_fd_heap");
790
791 }
792
793
794 /* Called to open a given filedescriptor */
795 rb_fde_t *
796 rb_open(int fd, rb_uint8_t type, const char *desc)
797 {
798 rb_fde_t *F = add_fd(fd);
799 lrb_assert(fd >= 0);
800
801 if(unlikely(IsFDOpen(F)))
802 {
803 return NULL;
804 }
805 lrb_assert(!IsFDOpen(F));
806 F->fd = fd;
807 F->type = type;
808 SetFDOpen(F);
809
810 if(desc != NULL)
811 F->desc = rb_strndup(desc, FD_DESC_SZ);
812 number_fd++;
813 return F;
814 }
815
816
817 /* Called to close a given filedescriptor */
818 void
819 rb_close(rb_fde_t *F)
820 {
821 int type, fd;
822
823 if(F == NULL)
824 return;
825
826 fd = F->fd;
827 type = F->type;
828 lrb_assert(IsFDOpen(F));
829
830 lrb_assert(!(type & RB_FD_FILE));
831 if(unlikely(type & RB_FD_FILE))
832 {
833 lrb_assert(F->read_handler == NULL);
834 lrb_assert(F->write_handler == NULL);
835 }
836 rb_setselect(F, RB_SELECT_WRITE | RB_SELECT_READ, NULL, NULL);
837 rb_settimeout(F, 0, NULL, NULL);
838 rb_free(F->accept);
839 rb_free(F->connect);
840 rb_free(F->desc);
841 #ifdef HAVE_SSL
842 if(type & RB_FD_SSL)
843 {
844 rb_ssl_shutdown(F);
845 }
846 #endif /* HAVE_SSL */
847 if(IsFDOpen(F))
848 {
849 remove_fd(F);
850 ClearFDOpen(F);
851 }
852
853 number_fd--;
854
855 #ifdef WIN32
856 if(type & (RB_FD_SOCKET|RB_FD_PIPE))
857 {
858 closesocket(fd);
859 return;
860 } else
861 #endif
862 close(fd);
863 }
864
865
866 /*
867 * rb_dump_fd() - dump the list of active filedescriptors
868 */
869 void
870 rb_dump_fd(DUMPCB * cb, void *data)
871 {
872 static const char *empty = "";
873 rb_dlink_node *ptr;
874 rb_dlink_list *bucket;
875 rb_fde_t *F;
876 unsigned int i;
877
878 for(i = 0; i < RB_FD_HASH_SIZE; i++)
879 {
880 bucket = &rb_fd_table[i];
881
882 if(rb_dlink_list_length(bucket) <= 0)
883 continue;
884
885 RB_DLINK_FOREACH(ptr, bucket->head)
886 {
887 F = ptr->data;
888 if(F == NULL || !IsFDOpen(F))
889 continue;
890
891 cb(F->fd, F->desc ? F->desc : empty, data);
892 }
893 }
894 }
895
896 /*
897 * rb_note() - set the fd note
898 *
899 * Note: must be careful not to overflow rb_fd_table[fd].desc when
900 * calling.
901 */
902 void
903 rb_note(rb_fde_t *F, const char *string)
904 {
905 if(F == NULL)
906 return;
907
908 rb_free(F->desc);
909 F->desc = rb_strndup(string, FD_DESC_SZ);
910 }
911
912 void
913 rb_set_type(rb_fde_t *F, rb_uint8_t type)
914 {
915 /* if the caller is calling this, lets assume they have a clue */
916 F->type = type;
917 return;
918 }
919
920 rb_uint8_t
921 rb_get_type(rb_fde_t *F)
922 {
923 return F->type;
924 }
925
926 int
927 rb_fd_ssl(rb_fde_t *F)
928 {
929 if(F == NULL)
930 return 0;
931 if(F->type & RB_FD_SSL)
932 return 1;
933 return 0;
934 }
935
936 int
937 rb_get_fd(rb_fde_t *F)
938 {
939 if(F == NULL)
940 return -1;
941 return(F->fd);
942 }
943
944 rb_fde_t *
945 rb_get_fde(int fd)
946 {
947 return rb_find_fd(fd);
948 }
949
950 ssize_t
951 rb_read(rb_fde_t *F, void *buf, int count)
952 {
953 int ret;
954 if(F == NULL)
955 return 0;
956
957 /* This needs to be *before* RB_FD_SOCKET otherwise you'll process
958 * an SSL socket as a regular socket
959 */
960 #ifdef HAVE_SSL
961 if(F->type & RB_FD_SSL)
962 {
963 return rb_ssl_read(F, buf, count);
964 }
965 #endif
966 if(F->type & RB_FD_SOCKET)
967 {
968 ret = recv(F->fd, buf, count, 0);
969 if(ret < 0)
970 {
971 rb_get_errno();
972 }
973 return ret;
974 }
975
976
977 /* default case */
978 return read(F->fd, buf, count);
979 }
980
981
982 ssize_t
983 rb_write(rb_fde_t *F, const void *buf, int count)
984 {
985 int ret;
986 if(F == NULL)
987 return 0;
988
989 #ifdef HAVE_SSL
990 if(F->type & RB_FD_SSL)
991 {
992 return rb_ssl_write(F, buf, count);
993 }
994 #endif
995 if(F->type & RB_FD_SOCKET)
996 {
997 ret = send(F->fd, buf, count, MSG_NOSIGNAL);
998 if(ret < 0) {
999 rb_get_errno();
1000 }
1001 return ret;
1002 }
1003
1004 return write(F->fd, buf, count);
1005 }
1006
1007 #if defined(HAVE_SSL) || defined(WIN32) || !defined(HAVE_WRITEV)
1008 static ssize_t
1009 rb_fake_writev(rb_fde_t *F, const struct rb_iovec *vp, size_t vpcount)
1010 {
1011 size_t count = 0;
1012
1013 while (vpcount-- > 0)
1014 {
1015 size_t written = rb_write(F, vp->iov_base, vp->iov_len);
1016
1017 if (written <= 0)
1018 {
1019 if(count > 0)
1020 return count;
1021 else
1022 return written;
1023 }
1024 count += written;
1025 vp++;
1026 }
1027 return (count);
1028 }
1029 #endif
1030
1031 #if defined(WIN32) || !defined(HAVE_WRITEV)
1032 ssize_t
1033 rb_writev(rb_fde_t *F, struct rb_iovec *vecount, int count)
1034 {
1035 return rb_fake_writev(F, vecount, count);
1036 }
1037
1038 #else
1039 ssize_t
1040 rb_writev(rb_fde_t *F, struct rb_iovec *vector, int count)
1041 {
1042 if(F == NULL) {
1043 errno = EBADF;
1044 return -1;
1045 }
1046 #ifdef HAVE_SSL
1047 if(F->type & RB_FD_SSL)
1048 {
1049 return rb_fake_writev(F, vector, count);
1050 }
1051 #endif /* HAVE_SSL */
1052 #ifdef HAVE_SENDMSG
1053 if(F->type & RB_FD_SOCKET)
1054 {
1055 struct msghdr msg;
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);
1060 }
1061 #endif /* HAVE_SENDMSG */
1062 return writev(F->fd, (struct iovec *)vector, count);
1063
1064 }
1065 #endif
1066
1067
1068 /*
1069 * From: Thomas Helvey <tomh@inxpress.net>
1070 */
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"
1098 };
1099
1100 /*
1101 * inetntoa - in_addr to string
1102 * changed name to remove collision possibility and
1103 * so behaviour is guaranteed to take a pointer arg.
1104 * -avalon 23/11/92
1105 * inet_ntoa -- returned the dotted notation of a given
1106 * internet number
1107 * argv 11/90).
1108 * inet_ntoa -- its broken on some Ultrix/Dynix too. -avalon
1109 */
1110
1111 static const char *
1112 inetntoa(const char *in)
1113 {
1114 static char buf[16];
1115 char *bufptr = buf;
1116 const unsigned char *a = (const unsigned char *) in;
1117 const char *n;
1118
1119 n = IpQuadTab[*a++];
1120 while (*n)
1121 *bufptr++ = *n++;
1122 *bufptr++ = '.';
1123 n = IpQuadTab[*a++];
1124 while (*n)
1125 *bufptr++ = *n++;
1126 *bufptr++ = '.';
1127 n = IpQuadTab[*a++];
1128 while (*n)
1129 *bufptr++ = *n++;
1130 *bufptr++ = '.';
1131 n = IpQuadTab[*a];
1132 while (*n)
1133 *bufptr++ = *n++;
1134 *bufptr = '\0';
1135 return buf;
1136 }
1137
1138
1139 /*
1140 * Copyright (c) 1996-1999 by Internet Software Consortium.
1141 *
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.
1145 *
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
1153 * SOFTWARE.
1154 */
1155
1156 #define SPRINTF(x) ((size_t)rb_sprintf x)
1157
1158 /*
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.
1161 */
1162
1163 static const char *inet_ntop4(const unsigned char * src, char *dst, unsigned int size);
1164 #ifdef RB_IPV6
1165 static const char *inet_ntop6(const unsigned char * src, char *dst, unsigned int size);
1166 #endif
1167
1168 /* const char *
1169 * inet_ntop4(src, dst, size)
1170 * format an IPv4 address
1171 * return:
1172 * `dst' (as a const)
1173 * notes:
1174 * (1) uses no statics
1175 * (2) takes a unsigned char* not an in_addr as input
1176 * author:
1177 * Paul Vixie, 1996.
1178 */
1179 static const char *
1180 inet_ntop4(const unsigned char *src, char *dst, unsigned int size)
1181 {
1182 if(size < 16)
1183 return NULL;
1184 return strcpy(dst, inetntoa((const char *) src));
1185 }
1186
1187 /* const char *
1188 * inet_ntop6(src, dst, size)
1189 * convert IPv6 binary address into presentation (printable) format
1190 * author:
1191 * Paul Vixie, 1996.
1192 */
1193 #ifdef RB_IPV6
1194 static const char *
1195 inet_ntop6(const unsigned char *src, char *dst, unsigned int size)
1196 {
1197 /*
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.
1203 */
1204 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
1205 struct
1206 {
1207 int base, len;
1208 }
1209 best, cur;
1210 unsigned int words[IN6ADDRSZ / INT16SZ];
1211 int i;
1212
1213 /*
1214 * Preprocess:
1215 * Copy the input (bytewise) array into a wordwise array.
1216 * Find the longest run of 0x00's in src[] for :: shorthanding.
1217 */
1218 memset(words, '\0', sizeof words);
1219 for (i = 0; i < IN6ADDRSZ; i += 2)
1220 words[i / 2] = (src[i] << 8) | src[i + 1];
1221 best.base = -1;
1222 best.len = 0;
1223 cur.base = -1;
1224 cur.len = 0;
1225 for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
1226 {
1227 if(words[i] == 0)
1228 {
1229 if(cur.base == -1)
1230 cur.base = i, cur.len = 1;
1231 else
1232 cur.len++;
1233 }
1234 else
1235 {
1236 if(cur.base != -1)
1237 {
1238 if(best.base == -1 || cur.len > best.len)
1239 best = cur;
1240 cur.base = -1;
1241 }
1242 }
1243 }
1244 if(cur.base != -1)
1245 {
1246 if(best.base == -1 || cur.len > best.len)
1247 best = cur;
1248 }
1249 if(best.base != -1 && best.len < 2)
1250 best.base = -1;
1251
1252 /*
1253 * Format the result.
1254 */
1255 tp = tmp;
1256 for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
1257 {
1258 /* Are we inside the best run of 0x00's? */
1259 if(best.base != -1 && i >= best.base && i < (best.base + best.len))
1260 {
1261 if(i == best.base)
1262 {
1263 if(i == 0)
1264 *tp++ = '0';
1265 *tp++ = ':';
1266 }
1267 continue;
1268 }
1269 /* Are we following an initial run of 0x00s or any real hex? */
1270 if(i != 0)
1271 *tp++ = ':';
1272 /* Is this address an encapsulated IPv4? */
1273 if(i == 6 && best.base == 0 &&
1274 (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
1275 {
1276 if(!inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp)))
1277 return (NULL);
1278 tp += strlen(tp);
1279 break;
1280 }
1281 tp += SPRINTF((tp, "%x", words[i]));
1282 }
1283 /* Was it a trailing run of 0x00's? */
1284 if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
1285 *tp++ = ':';
1286 *tp++ = '\0';
1287
1288 /*
1289 * Check for overflow, copy, and we're done.
1290 */
1291
1292 if((unsigned int) (tp - tmp) > size)
1293 {
1294 return (NULL);
1295 }
1296 return strcpy(dst, tmp);
1297 }
1298 #endif
1299
1300 int
1301 rb_inet_pton_sock(const char *src, struct sockaddr *dst)
1302 {
1303 if(rb_inet_pton(AF_INET, src, &((struct sockaddr_in *) dst)->sin_addr))
1304 {
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));
1308 return 1;
1309 }
1310 #ifdef RB_IPV6
1311 else if(rb_inet_pton(AF_INET6, src, &((struct sockaddr_in6 *) dst)->sin6_addr))
1312 {
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));
1316 return 1;
1317 }
1318 #endif
1319 return 0;
1320 }
1321
1322 const char *
1323 rb_inet_ntop_sock(struct sockaddr *src, char *dst, unsigned int size)
1324 {
1325 switch (src->sa_family)
1326 {
1327 case AF_INET:
1328 return (rb_inet_ntop(AF_INET, &((struct sockaddr_in *) src)->sin_addr, dst, size));
1329 break;
1330 #ifdef RB_IPV6
1331 case AF_INET6:
1332 return (rb_inet_ntop(AF_INET6, &((struct sockaddr_in6 *) src)->sin6_addr, dst, size));
1333 break;
1334 #endif
1335 default:
1336 return NULL;
1337 break;
1338 }
1339 }
1340
1341 /* char *
1342 * rb_inet_ntop(af, src, dst, size)
1343 * convert a network format address to presentation format.
1344 * return:
1345 * pointer to presentation format address (`dst'), or NULL (see errno).
1346 * author:
1347 * Paul Vixie, 1996.
1348 */
1349 const char *
1350 rb_inet_ntop(int af, const void *src, char *dst, unsigned int size)
1351 {
1352 switch (af)
1353 {
1354 case AF_INET:
1355 return (inet_ntop4(src, dst, size));
1356 #ifdef RB_IPV6
1357 case AF_INET6:
1358 if(IN6_IS_ADDR_V4MAPPED((const struct in6_addr *) src) ||
1359 IN6_IS_ADDR_V4COMPAT((const struct in6_addr *) src))
1360 return (inet_ntop4
1361 ((const unsigned char *)
1362 &((const struct in6_addr *) src)->s6_addr[12], dst, size));
1363 else
1364 return (inet_ntop6(src, dst, size));
1365
1366
1367 #endif
1368 default:
1369 return (NULL);
1370 }
1371 /* NOTREACHED */
1372 }
1373
1374 /*
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.
1377 */
1378
1379 /* int
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).
1383 * return:
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)
1387 * author:
1388 * Paul Vixie, 1996.
1389 */
1390
1391 /* int
1392 * inet_pton4(src, dst)
1393 * like inet_aton() but without all the hexadecimal and shorthand.
1394 * return:
1395 * 1 if `src' is a valid dotted quad, else 0.
1396 * notice:
1397 * does not touch `dst' unless it's returning 1.
1398 * author:
1399 * Paul Vixie, 1996.
1400 */
1401 static int
1402 inet_pton4(const char *src, unsigned char *dst)
1403 {
1404 int saw_digit, octets, ch;
1405 unsigned char tmp[INADDRSZ], *tp;
1406
1407 saw_digit = 0;
1408 octets = 0;
1409 *(tp = tmp) = 0;
1410 while ((ch = *src++) != '\0')
1411 {
1412
1413 if(ch >= '0' && ch <= '9')
1414 {
1415 unsigned int new = *tp * 10 + (ch - '0');
1416
1417 if(new > 255)
1418 return (0);
1419 *tp = new;
1420 if(!saw_digit)
1421 {
1422 if(++octets > 4)
1423 return (0);
1424 saw_digit = 1;
1425 }
1426 }
1427 else if(ch == '.' && saw_digit)
1428 {
1429 if(octets == 4)
1430 return (0);
1431 *++tp = 0;
1432 saw_digit = 0;
1433 }
1434 else
1435 return (0);
1436 }
1437 if(octets < 4)
1438 return (0);
1439 memcpy(dst, tmp, INADDRSZ);
1440 return (1);
1441 }
1442
1443 #ifdef RB_IPV6
1444 /* int
1445 * inet_pton6(src, dst)
1446 * convert presentation level address to network order binary form.
1447 * return:
1448 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
1449 * notice:
1450 * (1) does not touch `dst' unless it's returning 1.
1451 * (2) :: in a full address is silently ignored.
1452 * credit:
1453 * inspired by Mark Andrews.
1454 * author:
1455 * Paul Vixie, 1996.
1456 */
1457
1458 static int
1459 inet_pton6(const char *src, unsigned char *dst)
1460 {
1461 static const char xdigits[] = "0123456789abcdef";
1462 unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
1463 const char *curtok;
1464 int ch, saw_xdigit;
1465 unsigned int val;
1466
1467 tp = memset(tmp, '\0', IN6ADDRSZ);
1468 endp = tp + IN6ADDRSZ;
1469 colonp = NULL;
1470 /* Leading :: requires some special handling. */
1471 if(*src == ':')
1472 if(*++src != ':')
1473 return (0);
1474 curtok = src;
1475 saw_xdigit = 0;
1476 val = 0;
1477 while ((ch = tolower(*src++)) != '\0')
1478 {
1479 const char *pch;
1480
1481 pch = strchr(xdigits, ch);
1482 if(pch != NULL)
1483 {
1484 val <<= 4;
1485 val |= (pch - xdigits);
1486 if(val > 0xffff)
1487 return (0);
1488 saw_xdigit = 1;
1489 continue;
1490 }
1491 if(ch == ':')
1492 {
1493 curtok = src;
1494 if(!saw_xdigit)
1495 {
1496 if(colonp)
1497 return (0);
1498 colonp = tp;
1499 continue;
1500 }
1501 else if(*src == '\0')
1502 {
1503 return (0);
1504 }
1505 if(tp + INT16SZ > endp)
1506 return (0);
1507 *tp++ = (unsigned char) (val >> 8) & 0xff;
1508 *tp++ = (unsigned char) val & 0xff;
1509 saw_xdigit = 0;
1510 val = 0;
1511 continue;
1512 }
1513 if(*src != '\0' && ch == '.')
1514 {
1515 if(((tp + INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0)
1516 {
1517 tp += INADDRSZ;
1518 saw_xdigit = 0;
1519 break; /* '\0' was seen by inet_pton4(). */
1520 }
1521 }
1522 else
1523 continue;
1524 return (0);
1525 }
1526 if(saw_xdigit)
1527 {
1528 if(tp + INT16SZ > endp)
1529 return (0);
1530 *tp++ = (unsigned char) (val >> 8) & 0xff;
1531 *tp++ = (unsigned char) val & 0xff;
1532 }
1533 if(colonp != NULL)
1534 {
1535 /*
1536 * Since some memmove()'s erroneously fail to handle
1537 * overlapping regions, we'll do the shift by hand.
1538 */
1539 const int n = tp - colonp;
1540 int i;
1541
1542 if(tp == endp)
1543 return (0);
1544 for (i = 1; i <= n; i++)
1545 {
1546 endp[-i] = colonp[n - i];
1547 colonp[n - i] = 0;
1548 }
1549 tp = endp;
1550 }
1551 if(tp != endp)
1552 return (0);
1553 memcpy(dst, tmp, IN6ADDRSZ);
1554 return (1);
1555 }
1556 #endif
1557 int
1558 rb_inet_pton(int af, const char *src, void *dst)
1559 {
1560 switch (af)
1561 {
1562 case AF_INET:
1563 return (inet_pton4(src, dst));
1564 #ifdef RB_IPV6
1565 case AF_INET6:
1566 /* Somebody might have passed as an IPv4 address this is sick but it works */
1567 if(inet_pton4(src, dst))
1568 {
1569 char tmp[HOSTIPLEN];
1570 rb_sprintf(tmp, "::ffff:%s", src);
1571 return (inet_pton6(tmp, dst));
1572 }
1573 else
1574 return (inet_pton6(src, dst));
1575 #endif
1576 default:
1577 return (-1);
1578 }
1579 /* NOTREACHED */
1580 }
1581
1582
1583 #ifndef HAVE_SOCKETPAIR
1584 int
1585 rb_inet_socketpair(int family, int type, int protocol, int fd[2])
1586 {
1587 int listener = -1;
1588 int connector = -1;
1589 int acceptor = -1;
1590 struct sockaddr_in listen_addr;
1591 struct sockaddr_in connect_addr;
1592 size_t size;
1593
1594 if(protocol || family != AF_INET)
1595 {
1596 errno = EAFNOSUPPORT;
1597 return -1;
1598 }
1599 if(!fd)
1600 {
1601 errno = EINVAL;
1602 return -1;
1603 }
1604
1605 listener = socket(AF_INET, type, 0);
1606 if(listener == -1)
1607 return -1;
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;
1616
1617 connector = socket(AF_INET, type, 0);
1618 if(connector == -1)
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;
1628
1629 size = sizeof(listen_addr);
1630 acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size);
1631 if(acceptor == -1)
1632 goto tidy_up_and_fail;
1633 if(size != sizeof(listen_addr))
1634 goto abort_tidy_up_and_fail;
1635 close(listener);
1636 /* Now check we are talking to ourself by matching port and host on the
1637 two sockets. */
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)
1644 {
1645 goto abort_tidy_up_and_fail;
1646 }
1647 fd[0] = connector;
1648 fd[1] = acceptor;
1649 return 0;
1650
1651 abort_tidy_up_and_fail:
1652 errno = EINVAL; /* I hope this is portable and appropriate. */
1653
1654 tidy_up_and_fail:
1655 {
1656 int save_errno = errno;
1657 if(listener != -1)
1658 close(listener);
1659 if(connector != -1)
1660 close(connector);
1661 if(acceptor != -1)
1662 close(acceptor);
1663 errno = save_errno;
1664 return -1;
1665 }
1666 }
1667
1668 #endif
1669
1670
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];
1679
1680 const char *
1681 rb_get_iotype(void)
1682 {
1683 return iotype;
1684 }
1685
1686 static int
1687 rb_unsupported_event(void)
1688 {
1689 return 0;
1690 }
1691
1692 static int
1693 try_kqueue(void)
1694 {
1695 if(!rb_init_netio_kqueue())
1696 {
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));
1705 return 0;
1706 }
1707 return -1;
1708 }
1709
1710 static int
1711 try_epoll(void)
1712 {
1713 if(!rb_init_netio_epoll())
1714 {
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));
1723 return 0;
1724 }
1725 return -1;
1726 }
1727
1728 static int
1729 try_ports(void)
1730 {
1731 if(!rb_init_netio_ports())
1732 {
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));
1741 return 0;
1742 }
1743 return -1;
1744 }
1745
1746 static int
1747 try_devpoll(void)
1748 {
1749 if(!rb_init_netio_devpoll())
1750 {
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));
1759 return 0;
1760 }
1761 return -1;
1762 }
1763
1764 static int
1765 try_sigio(void)
1766 {
1767 if(!rb_init_netio_sigio())
1768 {
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;
1776
1777 rb_strlcpy(iotype, "sigio", sizeof(iotype));
1778 return 0;
1779 }
1780 return -1;
1781 }
1782
1783 static int
1784 try_poll(void)
1785 {
1786 if(!rb_init_netio_poll())
1787 {
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));
1796 return 0;
1797 }
1798 return -1;
1799 }
1800
1801 static int
1802 try_win32(void)
1803 {
1804 if(!rb_init_netio_win32())
1805 {
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));
1814 return 0;
1815 }
1816 return -1;
1817 }
1818
1819 static int
1820 try_select(void)
1821 {
1822 if(!rb_init_netio_select())
1823 {
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));
1832 return 0;
1833 }
1834 return -1;
1835 }
1836
1837
1838 int
1839 rb_io_sched_event(struct ev_entry *ev, int when)
1840 {
1841 if(ev == NULL || io_supports_event == NULL || io_sched_event == NULL || !io_supports_event())
1842 return 0;
1843 return io_sched_event(ev, when);
1844 }
1845
1846 void
1847 rb_io_unsched_event(struct ev_entry *ev)
1848 {
1849 if(ev == NULL || io_supports_event == NULL || io_unsched_event == NULL || !io_supports_event())
1850 return;
1851 io_unsched_event(ev);
1852 }
1853 int
1854 rb_io_supports_event(void)
1855 {
1856 if(io_supports_event == NULL)
1857 return 0;
1858 return io_supports_event();
1859 }
1860
1861 void
1862 rb_io_init_event(void)
1863 {
1864 io_init_event();
1865 rb_event_io_register_all();
1866 }
1867
1868 void
1869 rb_init_netio(void)
1870 {
1871 char *ioenv = getenv("LIBRB_USE_IOTYPE");
1872 rb_fd_table = rb_malloc(RB_FD_HASH_SIZE * sizeof(rb_dlink_list));
1873 rb_init_ssl();
1874
1875 if(ioenv != NULL)
1876 {
1877 if(!strcmp("epoll", ioenv))
1878 {
1879 if(!try_epoll())
1880 return;
1881 } else
1882 if(!strcmp("kqueue", ioenv))
1883 {
1884 if(!try_kqueue())
1885 return;
1886 } else
1887 if(!strcmp("ports", ioenv))
1888 {
1889 if(!try_ports())
1890 return;
1891 } else
1892 if(!strcmp("poll", ioenv))
1893 {
1894 if(!try_poll())
1895 return;
1896 } else
1897 if(!strcmp("devpoll", ioenv))
1898 {
1899 if(!try_devpoll())
1900 return;
1901 } else
1902 if(!strcmp("sigio", ioenv))
1903 {
1904 if(!try_sigio())
1905 return;
1906 } else
1907 if(!strcmp("win32", ioenv))
1908 {
1909 if(!try_win32())
1910 return;
1911 }
1912 if(!strcmp("select", ioenv))
1913 {
1914 if(!try_select())
1915 return;
1916 }
1917
1918 }
1919
1920 if(!try_kqueue())
1921 return;
1922 if(!try_epoll())
1923 return;
1924 if(!try_ports())
1925 return;
1926 if(!try_devpoll())
1927 return;
1928 if(!try_sigio())
1929 return;
1930 if(!try_poll())
1931 return;
1932 if(!try_win32())
1933 return;
1934 if(!try_select())
1935 return;
1936
1937 rb_lib_log("rb_init_netio: Could not find any io handlers...giving up");
1938
1939 abort();
1940 }
1941
1942 void
1943 rb_setselect(rb_fde_t *F, unsigned int type, PF * handler, void *client_data)
1944 {
1945 setselect_handler(F, type, handler, client_data);
1946 }
1947
1948 int
1949 rb_select(unsigned long timeout)
1950 {
1951 int ret = select_handler(timeout);
1952 free_fds();
1953 return ret;
1954 }
1955
1956 int
1957 rb_setup_fd(rb_fde_t *F)
1958 {
1959 return setup_fd_handler(F);
1960 }
1961
1962
1963
1964 int
1965 rb_ignore_errno(int error)
1966 {
1967 switch(error)
1968 {
1969 #ifdef EINPROGRESS
1970 case EINPROGRESS:
1971 #endif
1972 #if defined EWOULDBLOCK
1973 case EWOULDBLOCK:
1974 #endif
1975 #if defined(EAGAIN) && (EWOULDBLOCK != EAGAIN)
1976 case EAGAIN:
1977 #endif
1978 #ifdef EINTR
1979 case EINTR:
1980 #endif
1981 #ifdef ERESTART
1982 case ERESTART:
1983 #endif
1984 #ifdef ENOBUFS
1985 case ENOBUFS:
1986 #endif
1987 return 1;
1988 default:
1989 break;
1990 }
1991 return 0;
1992 }
1993
1994
1995 int
1996 rb_recv_fd_buf(rb_fde_t *F, void *data, size_t datasize, rb_fde_t **xF, int nfds)
1997 {
1998 struct msghdr msg;
1999 struct cmsghdr *cmsg;
2000 struct iovec iov[1];
2001 struct stat st;
2002 rb_uint8_t stype = RB_FD_UNKNOWN;
2003 const char *desc;
2004 int fd, len, x, rfds;
2005
2006 int control_len = CMSG_SPACE(sizeof(int) * nfds);
2007
2008 iov[0].iov_base = data;
2009 iov[0].iov_len = datasize;
2010
2011 msg.msg_name = NULL;
2012 msg.msg_namelen = 0;
2013 msg.msg_iov = iov;
2014 msg.msg_iovlen = 1;
2015 msg.msg_flags = 0;
2016 cmsg = alloca(control_len);
2017 msg.msg_control = cmsg;
2018 msg.msg_controllen = control_len;
2019
2020 if((len = recvmsg(rb_get_fd(F), &msg, 0)) <= 0)
2021 return len;
2022
2023 if(msg.msg_controllen > 0 && msg.msg_control != NULL && (cmsg = CMSG_FIRSTHDR(&msg)) != NULL)
2024 {
2025 rfds = (msg.msg_controllen - sizeof(struct cmsghdr)) / sizeof(int);
2026
2027 for(x = 0; x < nfds && x < rfds; x++)
2028 {
2029 fd = ((int *)CMSG_DATA(cmsg))[x];
2030 stype = RB_FD_UNKNOWN;
2031 desc = "remote unknown";
2032 if(!fstat(fd, &st))
2033 {
2034 if(S_ISSOCK(st.st_mode))
2035 {
2036 stype = RB_FD_SOCKET;
2037 desc = "remote socket";
2038 }
2039 else if(S_ISFIFO(st.st_mode))
2040 {
2041 stype = RB_FD_PIPE;
2042 desc = "remote pipe";
2043 }
2044 else if(S_ISREG(st.st_mode))
2045 {
2046 stype = RB_FD_FILE;
2047 desc = "remote file";
2048 }
2049 }
2050 xF[x] = rb_open(fd, stype, desc);
2051 }
2052 } else
2053 *xF = NULL;
2054 return len;
2055 }
2056
2057
2058 int
2059 rb_send_fd_buf(rb_fde_t *xF, rb_fde_t **F, int count, void *data, size_t datasize)
2060 {
2061 int n;
2062 struct msghdr msg;
2063 struct cmsghdr *cmsg;
2064 struct iovec iov[1];
2065 char empty = '0';
2066 char *buf;
2067
2068 memset(&msg, 0, sizeof(&msg));
2069 if(datasize == 0)
2070 {
2071 iov[0].iov_base = &empty;
2072 iov[0].iov_len = 1;
2073 } else {
2074 iov[0].iov_base = data;
2075 iov[0].iov_len = datasize;
2076 }
2077 msg.msg_iov = iov;
2078 msg.msg_iovlen = 1;
2079 msg.msg_name = NULL;
2080 msg.msg_namelen = 0;
2081 msg.msg_flags = 0;
2082 msg.msg_control = NULL;
2083 msg.msg_controllen = 0;
2084
2085 if(count > 0)
2086 {
2087 int i;
2088 int len = CMSG_SPACE(sizeof(int) * count);
2089 buf = alloca(len);
2090
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);
2097
2098 for(i = 0; i < count; i++)
2099 {
2100 ((int *)CMSG_DATA(cmsg))[i] = rb_get_fd(F[i]);
2101 }
2102 msg.msg_controllen = cmsg->cmsg_len;
2103 }
2104 n = sendmsg(rb_get_fd(xF), &msg, MSG_NOSIGNAL);
2105 return n;
2106 }
2107