]> jfr.im git - irc/rqf/shadowircd.git/blob - libratbox/src/commio.c
5f677289187e1b15709172c22151a678d7deb9bf
[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 25375 2008-05-16 15:19:51Z 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(rb_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 int errtmp = errno; /* save errno as rb_settimeout clobbers it sometimes */
474
475 /* This check is gross..but probably necessary */
476 if(F == NULL || F->connect == NULL || F->connect->callback == NULL)
477 return;
478 /* Clear the connect flag + handler */
479 hdl = F->connect->callback;
480 data = F->connect->data;
481 F->connect->callback = NULL;
482
483
484 /* Clear the timeout handler */
485 rb_settimeout(F, 0, NULL, NULL);
486 errno = errtmp;
487 /* Call the handler */
488 hdl(F, status, data);
489 }
490
491
492 /*
493 * rb_connect_timeout() - this gets called when the socket connection
494 * times out. This *only* can be called once connect() is initially
495 * called ..
496 */
497 static void
498 rb_connect_timeout(rb_fde_t *F, void *notused)
499 {
500 /* error! */
501 rb_connect_callback(F, RB_ERR_TIMEOUT);
502 }
503
504 /* static void rb_connect_tryconnect(int fd, void *notused)
505 * Input: The fd, the handler data(unused).
506 * Output: None.
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.
511 */
512 static void
513 rb_connect_tryconnect(rb_fde_t *F, void *notused)
514 {
515 int retval;
516
517 if(F == NULL || F->connect == NULL || F->connect->callback == NULL)
518 return;
519 /* Try the connect() */
520 retval = connect(F->fd,
521 (struct sockaddr *) &F->connect->hostaddr, GET_SS_LEN(&F->connect->hostaddr));
522 /* Error? */
523 if(retval < 0)
524 {
525 /*
526 * If we get EISCONN, then we've already connect()ed the socket,
527 * which is a good thing.
528 * -- adrian
529 */
530 rb_get_errno();
531 if(errno == EISCONN)
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);
537 else
538 /* Error? Fail with RB_ERR_CONNECT */
539 rb_connect_callback(F, RB_ERR_CONNECT);
540 return;
541 }
542 /* If we get here, we've suceeded, so call with RB_OK */
543 rb_connect_callback(F, RB_OK);
544 }
545
546
547 int
548 rb_connect_sockaddr(rb_fde_t *F, struct sockaddr *addr, int len)
549 {
550 if(F == NULL)
551 return 0;
552
553 memcpy(addr, &F->connect->hostaddr, len);
554 return 1;
555 }
556
557 /*
558 * rb_error_str() - return an error string for the given error condition
559 */
560 const char *
561 rb_errstr(int error)
562 {
563 if(error < 0 || error >= RB_ERR_MAX)
564 return "Invalid error number!";
565 return rb_err_str[error];
566 }
567
568
569 int
570 rb_socketpair(int family, int sock_type, int proto, rb_fde_t **F1, rb_fde_t **F2, const char *note)
571 {
572 int nfd[2];
573 if(number_fd >= rb_maxconnections)
574 {
575 errno = ENFILE;
576 return -1;
577 }
578
579 #ifndef WIN32
580 if(socketpair(family, sock_type, proto, nfd))
581 #else
582 if(rb_inet_socketpair(AF_INET, SOCK_STREAM, proto, nfd))
583 #endif
584 return -1;
585
586 rb_fd_hack(&nfd[0]);
587 rb_fd_hack(&nfd[1]);
588
589 *F1 = rb_open(nfd[0], RB_FD_SOCKET, note);
590 *F2 = rb_open(nfd[1], RB_FD_SOCKET, note);
591
592 if(*F1 == NULL)
593 {
594 if(*F2 != NULL)
595 rb_close(*F2);
596 return -1;
597 }
598
599 if(*F2 == NULL)
600 {
601 rb_close(*F1);
602 return -1;
603 }
604
605 /* Set the socket non-blocking, and other wonderful bits */
606 if(rb_unlikely(!rb_set_nb(*F1)))
607 {
608 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd[0], strerror(errno));
609 rb_close(*F1);
610 rb_close(*F2);
611 return -1;
612 }
613
614 if(rb_unlikely(!rb_set_nb(*F2)))
615 {
616 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd[1], strerror(errno));
617 rb_close(*F1);
618 rb_close(*F2);
619 return -1;
620 }
621
622 return 0;
623 }
624
625
626 int
627 rb_pipe(rb_fde_t **F1, rb_fde_t **F2, const char *desc)
628 {
629 #ifndef WIN32
630 int fd[2];
631 if(number_fd >= rb_maxconnections)
632 {
633 errno = ENFILE;
634 return -1;
635 }
636 if(pipe(fd) == -1)
637 return -1;
638 rb_fd_hack(&fd[0]);
639 rb_fd_hack(&fd[1]);
640 *F1 = rb_open(fd[0], RB_FD_PIPE, desc);
641 *F2 = rb_open(fd[1], RB_FD_PIPE, desc);
642
643 if(rb_unlikely(!rb_set_nb(*F1)))
644 {
645 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd[0], strerror(errno));
646 rb_close(*F1);
647 rb_close(*F2);
648 return -1;
649 }
650
651 if(rb_unlikely(!rb_set_nb(*F2)))
652 {
653 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd[1], strerror(errno));
654 rb_close(*F1);
655 rb_close(*F2);
656 return -1;
657 }
658
659
660 return 0;
661 #else
662 /* Its not a pipe..but its selectable. I'll take dirty hacks
663 * for $500 Alex.
664 */
665 return rb_socketpair(AF_INET, SOCK_STREAM, 0, F1, F2, desc);
666 #endif
667 }
668
669 /*
670 * rb_socket() - open a socket
671 *
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.
675 */
676 rb_fde_t *
677 rb_socket(int family, int sock_type, int proto, const char *note)
678 {
679 rb_fde_t *F;
680 int fd;
681 /* First, make sure we aren't going to run out of file descriptors */
682 if(rb_unlikely(number_fd >= rb_maxconnections))
683 {
684 errno = ENFILE;
685 return NULL;
686 }
687
688 /*
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.
691 * XXX !!! -- adrian
692 */
693 fd = socket(family, sock_type, proto);
694 rb_fd_hack(&fd);
695 if(rb_unlikely(fd < 0))
696 return NULL; /* errno will be passed through, yay.. */
697
698 #if defined(RB_IPV6) && defined(IPV6_V6ONLY)
699 /*
700 * Make sure we can take both IPv4 and IPv6 connections
701 * on an AF_INET6 socket
702 */
703 if(family == AF_INET6)
704 {
705 int off = 1;
706 if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)) == -1)
707 {
708 rb_lib_log("rb_socket: Could not set IPV6_V6ONLY option to 1 on FD %d: %s",
709 fd, strerror(errno));
710 close(fd);
711 return NULL;
712 }
713 }
714 #endif
715
716 F = rb_open(fd, RB_FD_SOCKET, note);
717 if(F == NULL)
718 return NULL;
719
720 /* Set the socket non-blocking, and other wonderful bits */
721 if(rb_unlikely(!rb_set_nb(F)))
722 {
723 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd, strerror(errno));
724 rb_close(F);
725 return NULL;
726 }
727
728 return F;
729 }
730
731 /*
732 * If a sockaddr_storage is AF_INET6 but is a mapped IPv4
733 * socket manged the sockaddr.
734 */
735 #ifdef RB_IPV6
736 static void
737 mangle_mapped_sockaddr(struct sockaddr *in)
738 {
739 struct sockaddr_in6 *in6 = (struct sockaddr_in6 *) in;
740
741 if(in->sa_family == AF_INET)
742 return;
743
744 if(in->sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&in6->sin6_addr))
745 {
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));
752 }
753 return;
754 }
755 #endif
756
757 /*
758 * rb_listen() - listen on a port
759 */
760 int
761 rb_listen(rb_fde_t *F, int backlog)
762 {
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);
766 }
767
768 void
769 rb_fdlist_init(int closeall, int maxfds, size_t heapsize)
770 {
771 static int initialized = 0;
772 #ifdef WIN32
773 WSADATA wsaData;
774 int err;
775 int vers = MAKEWORD(2, 0);
776
777 err = WSAStartup(vers, &wsaData);
778 if(err != 0)
779 {
780 rb_lib_die("WSAStartup failed");
781 }
782
783 #endif
784 if(!initialized)
785 {
786 rb_maxconnections = maxfds;
787 if(closeall)
788 rb_close_all();
789 /* Since we're doing this once .. */
790 initialized = 1;
791 }
792 fd_heap = rb_bh_create(sizeof(rb_fde_t), heapsize, "librb_fd_heap");
793
794 }
795
796
797 /* Called to open a given filedescriptor */
798 rb_fde_t *
799 rb_open(int fd, rb_uint8_t type, const char *desc)
800 {
801 rb_fde_t *F = add_fd(fd);
802 lrb_assert(fd >= 0);
803
804 if(rb_unlikely(IsFDOpen(F)))
805 {
806 return NULL;
807 }
808 lrb_assert(!IsFDOpen(F));
809 F->fd = fd;
810 F->type = type;
811 SetFDOpen(F);
812
813 if(desc != NULL)
814 F->desc = rb_strndup(desc, FD_DESC_SZ);
815 number_fd++;
816 return F;
817 }
818
819
820 /* Called to close a given filedescriptor */
821 void
822 rb_close(rb_fde_t *F)
823 {
824 int type, fd;
825
826 if(F == NULL)
827 return;
828
829 fd = F->fd;
830 type = F->type;
831 lrb_assert(IsFDOpen(F));
832
833 lrb_assert(!(type & RB_FD_FILE));
834 if(rb_unlikely(type & RB_FD_FILE))
835 {
836 lrb_assert(F->read_handler == NULL);
837 lrb_assert(F->write_handler == NULL);
838 }
839 rb_setselect(F, RB_SELECT_WRITE | RB_SELECT_READ, NULL, NULL);
840 rb_settimeout(F, 0, NULL, NULL);
841 rb_free(F->accept);
842 rb_free(F->connect);
843 rb_free(F->desc);
844 #ifdef HAVE_SSL
845 if(type & RB_FD_SSL)
846 {
847 rb_ssl_shutdown(F);
848 }
849 #endif /* HAVE_SSL */
850 if(IsFDOpen(F))
851 {
852 remove_fd(F);
853 ClearFDOpen(F);
854 }
855
856 number_fd--;
857
858 #ifdef WIN32
859 if(type & (RB_FD_SOCKET|RB_FD_PIPE))
860 {
861 closesocket(fd);
862 return;
863 } else
864 #endif
865 close(fd);
866 }
867
868
869 /*
870 * rb_dump_fd() - dump the list of active filedescriptors
871 */
872 void
873 rb_dump_fd(DUMPCB * cb, void *data)
874 {
875 static const char *empty = "";
876 rb_dlink_node *ptr;
877 rb_dlink_list *bucket;
878 rb_fde_t *F;
879 unsigned int i;
880
881 for(i = 0; i < RB_FD_HASH_SIZE; i++)
882 {
883 bucket = &rb_fd_table[i];
884
885 if(rb_dlink_list_length(bucket) <= 0)
886 continue;
887
888 RB_DLINK_FOREACH(ptr, bucket->head)
889 {
890 F = ptr->data;
891 if(F == NULL || !IsFDOpen(F))
892 continue;
893
894 cb(F->fd, F->desc ? F->desc : empty, data);
895 }
896 }
897 }
898
899 /*
900 * rb_note() - set the fd note
901 *
902 * Note: must be careful not to overflow rb_fd_table[fd].desc when
903 * calling.
904 */
905 void
906 rb_note(rb_fde_t *F, const char *string)
907 {
908 if(F == NULL)
909 return;
910
911 rb_free(F->desc);
912 F->desc = rb_strndup(string, FD_DESC_SZ);
913 }
914
915 void
916 rb_set_type(rb_fde_t *F, rb_uint8_t type)
917 {
918 /* if the caller is calling this, lets assume they have a clue */
919 F->type = type;
920 return;
921 }
922
923 rb_uint8_t
924 rb_get_type(rb_fde_t *F)
925 {
926 return F->type;
927 }
928
929 int
930 rb_fd_ssl(rb_fde_t *F)
931 {
932 if(F == NULL)
933 return 0;
934 if(F->type & RB_FD_SSL)
935 return 1;
936 return 0;
937 }
938
939 int
940 rb_get_fd(rb_fde_t *F)
941 {
942 if(F == NULL)
943 return -1;
944 return(F->fd);
945 }
946
947 rb_fde_t *
948 rb_get_fde(int fd)
949 {
950 return rb_find_fd(fd);
951 }
952
953 ssize_t
954 rb_read(rb_fde_t *F, void *buf, int count)
955 {
956 ssize_t ret;
957 if(F == NULL)
958 return 0;
959
960 /* This needs to be *before* RB_FD_SOCKET otherwise you'll process
961 * an SSL socket as a regular socket
962 */
963 #ifdef HAVE_SSL
964 if(F->type & RB_FD_SSL)
965 {
966 return rb_ssl_read(F, buf, count);
967 }
968 #endif
969 if(F->type & RB_FD_SOCKET)
970 {
971 ret = recv(F->fd, buf, count, 0);
972 if(ret < 0)
973 {
974 rb_get_errno();
975 }
976 return ret;
977 }
978
979
980 /* default case */
981 return read(F->fd, buf, count);
982 }
983
984
985 ssize_t
986 rb_write(rb_fde_t *F, const void *buf, int count)
987 {
988 ssize_t ret;
989 if(F == NULL)
990 return 0;
991
992 #ifdef HAVE_SSL
993 if(F->type & RB_FD_SSL)
994 {
995 return rb_ssl_write(F, buf, count);
996 }
997 #endif
998 if(F->type & RB_FD_SOCKET)
999 {
1000 ret = send(F->fd, buf, count, MSG_NOSIGNAL);
1001 if(ret < 0) {
1002 rb_get_errno();
1003 }
1004 return ret;
1005 }
1006
1007 return write(F->fd, buf, count);
1008 }
1009
1010 #if defined(HAVE_SSL) || defined(WIN32) || !defined(HAVE_WRITEV)
1011 static ssize_t
1012 rb_fake_writev(rb_fde_t *F, const struct rb_iovec *vp, size_t vpcount)
1013 {
1014 ssize_t count = 0;
1015
1016 while (vpcount-- > 0)
1017 {
1018 ssize_t written = rb_write(F, vp->iov_base, vp->iov_len);
1019
1020 if (written <= 0)
1021 {
1022 if(count > 0)
1023 return count;
1024 else
1025 return written;
1026 }
1027 count += written;
1028 vp++;
1029 }
1030 return (count);
1031 }
1032 #endif
1033
1034 #if defined(WIN32) || !defined(HAVE_WRITEV)
1035 ssize_t
1036 rb_writev(rb_fde_t *F, struct rb_iovec *vecount, int count)
1037 {
1038 return rb_fake_writev(F, vecount, count);
1039 }
1040
1041 #else
1042 ssize_t
1043 rb_writev(rb_fde_t *F, struct rb_iovec *vector, int count)
1044 {
1045 if(F == NULL) {
1046 errno = EBADF;
1047 return -1;
1048 }
1049 #ifdef HAVE_SSL
1050 if(F->type & RB_FD_SSL)
1051 {
1052 return rb_fake_writev(F, vector, count);
1053 }
1054 #endif /* HAVE_SSL */
1055 #ifdef HAVE_SENDMSG
1056 if(F->type & RB_FD_SOCKET)
1057 {
1058 struct msghdr msg;
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);
1063 }
1064 #endif /* HAVE_SENDMSG */
1065 return writev(F->fd, (struct iovec *)vector, count);
1066
1067 }
1068 #endif
1069
1070
1071 /*
1072 * From: Thomas Helvey <tomh@inxpress.net>
1073 */
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"
1101 };
1102
1103 /*
1104 * inetntoa - in_addr to string
1105 * changed name to remove collision possibility and
1106 * so behaviour is guaranteed to take a pointer arg.
1107 * -avalon 23/11/92
1108 * inet_ntoa -- returned the dotted notation of a given
1109 * internet number
1110 * argv 11/90).
1111 * inet_ntoa -- its broken on some Ultrix/Dynix too. -avalon
1112 */
1113
1114 static const char *
1115 inetntoa(const char *in)
1116 {
1117 static char buf[16];
1118 char *bufptr = buf;
1119 const unsigned char *a = (const unsigned char *) in;
1120 const char *n;
1121
1122 n = IpQuadTab[*a++];
1123 while (*n)
1124 *bufptr++ = *n++;
1125 *bufptr++ = '.';
1126 n = IpQuadTab[*a++];
1127 while (*n)
1128 *bufptr++ = *n++;
1129 *bufptr++ = '.';
1130 n = IpQuadTab[*a++];
1131 while (*n)
1132 *bufptr++ = *n++;
1133 *bufptr++ = '.';
1134 n = IpQuadTab[*a];
1135 while (*n)
1136 *bufptr++ = *n++;
1137 *bufptr = '\0';
1138 return buf;
1139 }
1140
1141
1142 /*
1143 * Copyright (c) 1996-1999 by Internet Software Consortium.
1144 *
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.
1148 *
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
1156 * SOFTWARE.
1157 */
1158
1159 #define SPRINTF(x) ((size_t)rb_sprintf x)
1160
1161 /*
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.
1164 */
1165
1166 static const char *inet_ntop4(const unsigned char * src, char *dst, unsigned int size);
1167 #ifdef RB_IPV6
1168 static const char *inet_ntop6(const unsigned char * src, char *dst, unsigned int size);
1169 #endif
1170
1171 /* const char *
1172 * inet_ntop4(src, dst, size)
1173 * format an IPv4 address
1174 * return:
1175 * `dst' (as a const)
1176 * notes:
1177 * (1) uses no statics
1178 * (2) takes a unsigned char* not an in_addr as input
1179 * author:
1180 * Paul Vixie, 1996.
1181 */
1182 static const char *
1183 inet_ntop4(const unsigned char *src, char *dst, unsigned int size)
1184 {
1185 if(size < 16)
1186 return NULL;
1187 return strcpy(dst, inetntoa((const char *) src));
1188 }
1189
1190 /* const char *
1191 * inet_ntop6(src, dst, size)
1192 * convert IPv6 binary address into presentation (printable) format
1193 * author:
1194 * Paul Vixie, 1996.
1195 */
1196 #ifdef RB_IPV6
1197 static const char *
1198 inet_ntop6(const unsigned char *src, char *dst, unsigned int size)
1199 {
1200 /*
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.
1206 */
1207 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
1208 struct
1209 {
1210 int base, len;
1211 }
1212 best, cur;
1213 unsigned int words[IN6ADDRSZ / INT16SZ];
1214 int i;
1215
1216 /*
1217 * Preprocess:
1218 * Copy the input (bytewise) array into a wordwise array.
1219 * Find the longest run of 0x00's in src[] for :: shorthanding.
1220 */
1221 memset(words, '\0', sizeof words);
1222 for (i = 0; i < IN6ADDRSZ; i += 2)
1223 words[i / 2] = (src[i] << 8) | src[i + 1];
1224 best.base = -1;
1225 best.len = 0;
1226 cur.base = -1;
1227 cur.len = 0;
1228 for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
1229 {
1230 if(words[i] == 0)
1231 {
1232 if(cur.base == -1)
1233 cur.base = i, cur.len = 1;
1234 else
1235 cur.len++;
1236 }
1237 else
1238 {
1239 if(cur.base != -1)
1240 {
1241 if(best.base == -1 || cur.len > best.len)
1242 best = cur;
1243 cur.base = -1;
1244 }
1245 }
1246 }
1247 if(cur.base != -1)
1248 {
1249 if(best.base == -1 || cur.len > best.len)
1250 best = cur;
1251 }
1252 if(best.base != -1 && best.len < 2)
1253 best.base = -1;
1254
1255 /*
1256 * Format the result.
1257 */
1258 tp = tmp;
1259 for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
1260 {
1261 /* Are we inside the best run of 0x00's? */
1262 if(best.base != -1 && i >= best.base && i < (best.base + best.len))
1263 {
1264 if(i == best.base)
1265 {
1266 if(i == 0)
1267 *tp++ = '0';
1268 *tp++ = ':';
1269 }
1270 continue;
1271 }
1272 /* Are we following an initial run of 0x00s or any real hex? */
1273 if(i != 0)
1274 *tp++ = ':';
1275 /* Is this address an encapsulated IPv4? */
1276 if(i == 6 && best.base == 0 &&
1277 (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
1278 {
1279 if(!inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp)))
1280 return (NULL);
1281 tp += strlen(tp);
1282 break;
1283 }
1284 tp += SPRINTF((tp, "%x", words[i]));
1285 }
1286 /* Was it a trailing run of 0x00's? */
1287 if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
1288 *tp++ = ':';
1289 *tp++ = '\0';
1290
1291 /*
1292 * Check for overflow, copy, and we're done.
1293 */
1294
1295 if((unsigned int) (tp - tmp) > size)
1296 {
1297 return (NULL);
1298 }
1299 return strcpy(dst, tmp);
1300 }
1301 #endif
1302
1303 int
1304 rb_inet_pton_sock(const char *src, struct sockaddr *dst)
1305 {
1306 if(rb_inet_pton(AF_INET, src, &((struct sockaddr_in *) dst)->sin_addr))
1307 {
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));
1311 return 1;
1312 }
1313 #ifdef RB_IPV6
1314 else if(rb_inet_pton(AF_INET6, src, &((struct sockaddr_in6 *) dst)->sin6_addr))
1315 {
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));
1319 return 1;
1320 }
1321 #endif
1322 return 0;
1323 }
1324
1325 const char *
1326 rb_inet_ntop_sock(struct sockaddr *src, char *dst, unsigned int size)
1327 {
1328 switch (src->sa_family)
1329 {
1330 case AF_INET:
1331 return (rb_inet_ntop(AF_INET, &((struct sockaddr_in *) src)->sin_addr, dst, size));
1332 break;
1333 #ifdef RB_IPV6
1334 case AF_INET6:
1335 return (rb_inet_ntop(AF_INET6, &((struct sockaddr_in6 *) src)->sin6_addr, dst, size));
1336 break;
1337 #endif
1338 default:
1339 return NULL;
1340 break;
1341 }
1342 }
1343
1344 /* char *
1345 * rb_inet_ntop(af, src, dst, size)
1346 * convert a network format address to presentation format.
1347 * return:
1348 * pointer to presentation format address (`dst'), or NULL (see errno).
1349 * author:
1350 * Paul Vixie, 1996.
1351 */
1352 const char *
1353 rb_inet_ntop(int af, const void *src, char *dst, unsigned int size)
1354 {
1355 switch (af)
1356 {
1357 case AF_INET:
1358 return (inet_ntop4(src, dst, size));
1359 #ifdef RB_IPV6
1360 case AF_INET6:
1361 if(IN6_IS_ADDR_V4MAPPED((const struct in6_addr *) src) ||
1362 IN6_IS_ADDR_V4COMPAT((const struct in6_addr *) src))
1363 return (inet_ntop4
1364 ((const unsigned char *)
1365 &((const struct in6_addr *) src)->s6_addr[12], dst, size));
1366 else
1367 return (inet_ntop6(src, dst, size));
1368
1369
1370 #endif
1371 default:
1372 return (NULL);
1373 }
1374 /* NOTREACHED */
1375 }
1376
1377 /*
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.
1380 */
1381
1382 /* int
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).
1386 * return:
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)
1390 * author:
1391 * Paul Vixie, 1996.
1392 */
1393
1394 /* int
1395 * inet_pton4(src, dst)
1396 * like inet_aton() but without all the hexadecimal and shorthand.
1397 * return:
1398 * 1 if `src' is a valid dotted quad, else 0.
1399 * notice:
1400 * does not touch `dst' unless it's returning 1.
1401 * author:
1402 * Paul Vixie, 1996.
1403 */
1404 static int
1405 inet_pton4(const char *src, unsigned char *dst)
1406 {
1407 int saw_digit, octets, ch;
1408 unsigned char tmp[INADDRSZ], *tp;
1409
1410 saw_digit = 0;
1411 octets = 0;
1412 *(tp = tmp) = 0;
1413 while ((ch = *src++) != '\0')
1414 {
1415
1416 if(ch >= '0' && ch <= '9')
1417 {
1418 unsigned int new = *tp * 10 + (ch - '0');
1419
1420 if(new > 255)
1421 return (0);
1422 *tp = new;
1423 if(!saw_digit)
1424 {
1425 if(++octets > 4)
1426 return (0);
1427 saw_digit = 1;
1428 }
1429 }
1430 else if(ch == '.' && saw_digit)
1431 {
1432 if(octets == 4)
1433 return (0);
1434 *++tp = 0;
1435 saw_digit = 0;
1436 }
1437 else
1438 return (0);
1439 }
1440 if(octets < 4)
1441 return (0);
1442 memcpy(dst, tmp, INADDRSZ);
1443 return (1);
1444 }
1445
1446 #ifdef RB_IPV6
1447 /* int
1448 * inet_pton6(src, dst)
1449 * convert presentation level address to network order binary form.
1450 * return:
1451 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
1452 * notice:
1453 * (1) does not touch `dst' unless it's returning 1.
1454 * (2) :: in a full address is silently ignored.
1455 * credit:
1456 * inspired by Mark Andrews.
1457 * author:
1458 * Paul Vixie, 1996.
1459 */
1460
1461 static int
1462 inet_pton6(const char *src, unsigned char *dst)
1463 {
1464 static const char xdigits[] = "0123456789abcdef";
1465 unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
1466 const char *curtok;
1467 int ch, saw_xdigit;
1468 unsigned int val;
1469
1470 tp = memset(tmp, '\0', IN6ADDRSZ);
1471 endp = tp + IN6ADDRSZ;
1472 colonp = NULL;
1473 /* Leading :: requires some special handling. */
1474 if(*src == ':')
1475 if(*++src != ':')
1476 return (0);
1477 curtok = src;
1478 saw_xdigit = 0;
1479 val = 0;
1480 while ((ch = tolower(*src++)) != '\0')
1481 {
1482 const char *pch;
1483
1484 pch = strchr(xdigits, ch);
1485 if(pch != NULL)
1486 {
1487 val <<= 4;
1488 val |= (pch - xdigits);
1489 if(val > 0xffff)
1490 return (0);
1491 saw_xdigit = 1;
1492 continue;
1493 }
1494 if(ch == ':')
1495 {
1496 curtok = src;
1497 if(!saw_xdigit)
1498 {
1499 if(colonp)
1500 return (0);
1501 colonp = tp;
1502 continue;
1503 }
1504 else if(*src == '\0')
1505 {
1506 return (0);
1507 }
1508 if(tp + INT16SZ > endp)
1509 return (0);
1510 *tp++ = (unsigned char) (val >> 8) & 0xff;
1511 *tp++ = (unsigned char) val & 0xff;
1512 saw_xdigit = 0;
1513 val = 0;
1514 continue;
1515 }
1516 if(*src != '\0' && ch == '.')
1517 {
1518 if(((tp + INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0)
1519 {
1520 tp += INADDRSZ;
1521 saw_xdigit = 0;
1522 break; /* '\0' was seen by inet_pton4(). */
1523 }
1524 }
1525 else
1526 continue;
1527 return (0);
1528 }
1529 if(saw_xdigit)
1530 {
1531 if(tp + INT16SZ > endp)
1532 return (0);
1533 *tp++ = (unsigned char) (val >> 8) & 0xff;
1534 *tp++ = (unsigned char) val & 0xff;
1535 }
1536 if(colonp != NULL)
1537 {
1538 /*
1539 * Since some memmove()'s erroneously fail to handle
1540 * overlapping regions, we'll do the shift by hand.
1541 */
1542 const int n = tp - colonp;
1543 int i;
1544
1545 if(tp == endp)
1546 return (0);
1547 for (i = 1; i <= n; i++)
1548 {
1549 endp[-i] = colonp[n - i];
1550 colonp[n - i] = 0;
1551 }
1552 tp = endp;
1553 }
1554 if(tp != endp)
1555 return (0);
1556 memcpy(dst, tmp, IN6ADDRSZ);
1557 return (1);
1558 }
1559 #endif
1560 int
1561 rb_inet_pton(int af, const char *src, void *dst)
1562 {
1563 switch (af)
1564 {
1565 case AF_INET:
1566 return (inet_pton4(src, dst));
1567 #ifdef RB_IPV6
1568 case AF_INET6:
1569 /* Somebody might have passed as an IPv4 address this is sick but it works */
1570 if(inet_pton4(src, dst))
1571 {
1572 char tmp[HOSTIPLEN];
1573 rb_sprintf(tmp, "::ffff:%s", src);
1574 return (inet_pton6(tmp, dst));
1575 }
1576 else
1577 return (inet_pton6(src, dst));
1578 #endif
1579 default:
1580 return (-1);
1581 }
1582 /* NOTREACHED */
1583 }
1584
1585
1586 #ifndef HAVE_SOCKETPAIR
1587 int
1588 rb_inet_socketpair(int family, int type, int protocol, int fd[2])
1589 {
1590 int listener = -1;
1591 int connector = -1;
1592 int acceptor = -1;
1593 struct sockaddr_in listen_addr;
1594 struct sockaddr_in connect_addr;
1595 size_t size;
1596
1597 if(protocol || family != AF_INET)
1598 {
1599 errno = EAFNOSUPPORT;
1600 return -1;
1601 }
1602 if(!fd)
1603 {
1604 errno = EINVAL;
1605 return -1;
1606 }
1607
1608 listener = socket(AF_INET, type, 0);
1609 if(listener == -1)
1610 return -1;
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;
1619
1620 connector = socket(AF_INET, type, 0);
1621 if(connector == -1)
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;
1631
1632 size = sizeof(listen_addr);
1633 acceptor = accept(listener, (struct sockaddr *) &listen_addr, &size);
1634 if(acceptor == -1)
1635 goto tidy_up_and_fail;
1636 if(size != sizeof(listen_addr))
1637 goto abort_tidy_up_and_fail;
1638 close(listener);
1639 /* Now check we are talking to ourself by matching port and host on the
1640 two sockets. */
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)
1647 {
1648 goto abort_tidy_up_and_fail;
1649 }
1650 fd[0] = connector;
1651 fd[1] = acceptor;
1652 return 0;
1653
1654 abort_tidy_up_and_fail:
1655 errno = EINVAL; /* I hope this is portable and appropriate. */
1656
1657 tidy_up_and_fail:
1658 {
1659 int save_errno = errno;
1660 if(listener != -1)
1661 close(listener);
1662 if(connector != -1)
1663 close(connector);
1664 if(acceptor != -1)
1665 close(acceptor);
1666 errno = save_errno;
1667 return -1;
1668 }
1669 }
1670
1671 #endif
1672
1673
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];
1682
1683 const char *
1684 rb_get_iotype(void)
1685 {
1686 return iotype;
1687 }
1688
1689 static int
1690 rb_unsupported_event(void)
1691 {
1692 return 0;
1693 }
1694
1695 static int
1696 try_kqueue(void)
1697 {
1698 if(!rb_init_netio_kqueue())
1699 {
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));
1708 return 0;
1709 }
1710 return -1;
1711 }
1712
1713 static int
1714 try_epoll(void)
1715 {
1716 if(!rb_init_netio_epoll())
1717 {
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));
1726 return 0;
1727 }
1728 return -1;
1729 }
1730
1731 static int
1732 try_ports(void)
1733 {
1734 if(!rb_init_netio_ports())
1735 {
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));
1744 return 0;
1745 }
1746 return -1;
1747 }
1748
1749 static int
1750 try_devpoll(void)
1751 {
1752 if(!rb_init_netio_devpoll())
1753 {
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));
1762 return 0;
1763 }
1764 return -1;
1765 }
1766
1767 static int
1768 try_sigio(void)
1769 {
1770 if(!rb_init_netio_sigio())
1771 {
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;
1779
1780 rb_strlcpy(iotype, "sigio", sizeof(iotype));
1781 return 0;
1782 }
1783 return -1;
1784 }
1785
1786 static int
1787 try_poll(void)
1788 {
1789 if(!rb_init_netio_poll())
1790 {
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));
1799 return 0;
1800 }
1801 return -1;
1802 }
1803
1804 static int
1805 try_win32(void)
1806 {
1807 if(!rb_init_netio_win32())
1808 {
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));
1817 return 0;
1818 }
1819 return -1;
1820 }
1821
1822 static int
1823 try_select(void)
1824 {
1825 if(!rb_init_netio_select())
1826 {
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));
1835 return 0;
1836 }
1837 return -1;
1838 }
1839
1840
1841 int
1842 rb_io_sched_event(struct ev_entry *ev, int when)
1843 {
1844 if(ev == NULL || io_supports_event == NULL || io_sched_event == NULL || !io_supports_event())
1845 return 0;
1846 return io_sched_event(ev, when);
1847 }
1848
1849 void
1850 rb_io_unsched_event(struct ev_entry *ev)
1851 {
1852 if(ev == NULL || io_supports_event == NULL || io_unsched_event == NULL || !io_supports_event())
1853 return;
1854 io_unsched_event(ev);
1855 }
1856 int
1857 rb_io_supports_event(void)
1858 {
1859 if(io_supports_event == NULL)
1860 return 0;
1861 return io_supports_event();
1862 }
1863
1864 void
1865 rb_io_init_event(void)
1866 {
1867 io_init_event();
1868 rb_event_io_register_all();
1869 }
1870
1871 void
1872 rb_init_netio(void)
1873 {
1874 char *ioenv = getenv("LIBRB_USE_IOTYPE");
1875 rb_fd_table = rb_malloc(RB_FD_HASH_SIZE * sizeof(rb_dlink_list));
1876 rb_init_ssl();
1877
1878 if(ioenv != NULL)
1879 {
1880 if(!strcmp("epoll", ioenv))
1881 {
1882 if(!try_epoll())
1883 return;
1884 } else
1885 if(!strcmp("kqueue", ioenv))
1886 {
1887 if(!try_kqueue())
1888 return;
1889 } else
1890 if(!strcmp("ports", ioenv))
1891 {
1892 if(!try_ports())
1893 return;
1894 } else
1895 if(!strcmp("poll", ioenv))
1896 {
1897 if(!try_poll())
1898 return;
1899 } else
1900 if(!strcmp("devpoll", ioenv))
1901 {
1902 if(!try_devpoll())
1903 return;
1904 } else
1905 if(!strcmp("sigio", ioenv))
1906 {
1907 if(!try_sigio())
1908 return;
1909 } else
1910 if(!strcmp("win32", ioenv))
1911 {
1912 if(!try_win32())
1913 return;
1914 }
1915 if(!strcmp("select", ioenv))
1916 {
1917 if(!try_select())
1918 return;
1919 }
1920
1921 }
1922
1923 if(!try_kqueue())
1924 return;
1925 if(!try_epoll())
1926 return;
1927 if(!try_ports())
1928 return;
1929 if(!try_devpoll())
1930 return;
1931 if(!try_sigio())
1932 return;
1933 if(!try_poll())
1934 return;
1935 if(!try_win32())
1936 return;
1937 if(!try_select())
1938 return;
1939
1940 rb_lib_log("rb_init_netio: Could not find any io handlers...giving up");
1941
1942 abort();
1943 }
1944
1945 void
1946 rb_setselect(rb_fde_t *F, unsigned int type, PF * handler, void *client_data)
1947 {
1948 setselect_handler(F, type, handler, client_data);
1949 }
1950
1951 int
1952 rb_select(unsigned long timeout)
1953 {
1954 int ret = select_handler(timeout);
1955 free_fds();
1956 return ret;
1957 }
1958
1959 int
1960 rb_setup_fd(rb_fde_t *F)
1961 {
1962 return setup_fd_handler(F);
1963 }
1964
1965
1966
1967 int
1968 rb_ignore_errno(int error)
1969 {
1970 switch(error)
1971 {
1972 #ifdef EINPROGRESS
1973 case EINPROGRESS:
1974 #endif
1975 #if defined EWOULDBLOCK
1976 case EWOULDBLOCK:
1977 #endif
1978 #if defined(EAGAIN) && (EWOULDBLOCK != EAGAIN)
1979 case EAGAIN:
1980 #endif
1981 #ifdef EINTR
1982 case EINTR:
1983 #endif
1984 #ifdef ERESTART
1985 case ERESTART:
1986 #endif
1987 #ifdef ENOBUFS
1988 case ENOBUFS:
1989 #endif
1990 return 1;
1991 default:
1992 break;
1993 }
1994 return 0;
1995 }
1996
1997
1998 int
1999 rb_recv_fd_buf(rb_fde_t *F, void *data, size_t datasize, rb_fde_t **xF, int nfds)
2000 {
2001 struct msghdr msg;
2002 struct cmsghdr *cmsg;
2003 struct iovec iov[1];
2004 struct stat st;
2005 rb_uint8_t stype = RB_FD_UNKNOWN;
2006 const char *desc;
2007 int fd, len, x, rfds;
2008
2009 int control_len = CMSG_SPACE(sizeof(int) * nfds);
2010
2011 iov[0].iov_base = data;
2012 iov[0].iov_len = datasize;
2013
2014 msg.msg_name = NULL;
2015 msg.msg_namelen = 0;
2016 msg.msg_iov = iov;
2017 msg.msg_iovlen = 1;
2018 msg.msg_flags = 0;
2019 cmsg = alloca(control_len);
2020 msg.msg_control = cmsg;
2021 msg.msg_controllen = control_len;
2022
2023 if((len = recvmsg(rb_get_fd(F), &msg, 0)) <= 0)
2024 return len;
2025
2026 if(msg.msg_controllen > 0 && msg.msg_control != NULL && (cmsg = CMSG_FIRSTHDR(&msg)) != NULL)
2027 {
2028 rfds = (msg.msg_controllen - sizeof(struct cmsghdr)) / sizeof(int);
2029
2030 for(x = 0; x < nfds && x < rfds; x++)
2031 {
2032 fd = ((int *)CMSG_DATA(cmsg))[x];
2033 stype = RB_FD_UNKNOWN;
2034 desc = "remote unknown";
2035 if(!fstat(fd, &st))
2036 {
2037 if(S_ISSOCK(st.st_mode))
2038 {
2039 stype = RB_FD_SOCKET;
2040 desc = "remote socket";
2041 }
2042 else if(S_ISFIFO(st.st_mode))
2043 {
2044 stype = RB_FD_PIPE;
2045 desc = "remote pipe";
2046 }
2047 else if(S_ISREG(st.st_mode))
2048 {
2049 stype = RB_FD_FILE;
2050 desc = "remote file";
2051 }
2052 }
2053 xF[x] = rb_open(fd, stype, desc);
2054 }
2055 } else
2056 *xF = NULL;
2057 return len;
2058 }
2059
2060
2061 int
2062 rb_send_fd_buf(rb_fde_t *xF, rb_fde_t **F, int count, void *data, size_t datasize)
2063 {
2064 int n;
2065 struct msghdr msg;
2066 struct cmsghdr *cmsg;
2067 struct iovec iov[1];
2068 char empty = '0';
2069 char *buf;
2070
2071 memset(&msg, 0, sizeof(&msg));
2072 if(datasize == 0)
2073 {
2074 iov[0].iov_base = &empty;
2075 iov[0].iov_len = 1;
2076 } else {
2077 iov[0].iov_base = data;
2078 iov[0].iov_len = datasize;
2079 }
2080 msg.msg_iov = iov;
2081 msg.msg_iovlen = 1;
2082 msg.msg_name = NULL;
2083 msg.msg_namelen = 0;
2084 msg.msg_flags = 0;
2085 msg.msg_control = NULL;
2086 msg.msg_controllen = 0;
2087
2088 if(count > 0)
2089 {
2090 int i;
2091 int len = CMSG_SPACE(sizeof(int) * count);
2092 buf = alloca(len);
2093
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);
2100
2101 for(i = 0; i < count; i++)
2102 {
2103 ((int *)CMSG_DATA(cmsg))[i] = rb_get_fd(F[i]);
2104 }
2105 msg.msg_controllen = cmsg->cmsg_len;
2106 }
2107 n = sendmsg(rb_get_fd(xF), &msg, MSG_NOSIGNAL);
2108 return n;
2109 }
2110