]> jfr.im git - irc/rqf/shadowircd.git/blob - libratbox/src/commio.c
Copied libratbox and related stuff from shadowircd upstream.
[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 26096 2008-09-20 01:05:42Z 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 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 static int rb_inet_socketpair_udp(rb_fde_t **newF1, rb_fde_t **newF2);
78 #endif
79
80 static inline rb_fde_t *
81 add_fd(int fd)
82 {
83 rb_fde_t *F = rb_find_fd(fd);
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 rb_dlinkAdd(F, &F->node, &rb_fd_table[rb_hash_fd(fd)]);
92 return (F);
93 }
94
95 static inline void
96 remove_fd(rb_fde_t *F)
97 {
98 if(F == NULL || !IsFDOpen(F))
99 return;
100
101 rb_dlinkMoveNode(&F->node, &rb_fd_table[rb_hash_fd(F->fd)], &closed_list);
102 }
103
104 static void
105 free_fds(void)
106 {
107 rb_fde_t *F;
108 rb_dlink_node *ptr, *next;
109 RB_DLINK_FOREACH_SAFE(ptr, next, closed_list.head)
110 {
111 F = ptr->data;
112 rb_dlinkDelete(ptr, &closed_list);
113 rb_bh_free(fd_heap, F);
114 }
115 }
116
117 /* 32bit solaris is kinda slow and stdio only supports fds < 256
118 * so we got to do this crap below.
119 * (BTW Fuck you Sun, I hate your guts and I hope you go bankrupt soon)
120 */
121
122 #if defined (__SVR4) && defined (__sun)
123 static void
124 rb_fd_hack(int *fd)
125 {
126 int newfd;
127 if(*fd > 256 || *fd < 0)
128 return;
129 if((newfd = fcntl(*fd, F_DUPFD, 256)) != -1)
130 {
131 close(*fd);
132 *fd = newfd;
133 }
134 return;
135 }
136 #else
137 #define rb_fd_hack(fd)
138 #endif
139
140
141 /* close_all_connections() can be used *before* the system come up! */
142
143 static void
144 rb_close_all(void)
145 {
146 #ifndef _WIN32
147 int i;
148
149 /* XXX someone tell me why we care about 4 fd's ? */
150 /* XXX btw, fd 3 is used for profiler ! */
151 for(i = 3; i < rb_maxconnections; ++i)
152 {
153 close(i);
154 }
155 #endif
156 }
157
158 /*
159 * get_sockerr - get the error value from the socket or the current errno
160 *
161 * Get the *real* error from the socket (well try to anyway..).
162 * This may only work when SO_DEBUG is enabled but its worth the
163 * gamble anyway.
164 */
165 int
166 rb_get_sockerr(rb_fde_t *F)
167 {
168 int errtmp;
169 int err = 0;
170 rb_socklen_t len = sizeof(err);
171
172 if(!(F->type & RB_FD_SOCKET))
173 return errno;
174
175 rb_get_errno();
176 errtmp = errno;
177
178 #ifdef SO_ERROR
179 if(F != NULL
180 && !getsockopt(rb_get_fd(F), SOL_SOCKET, SO_ERROR, (char *)&err, (rb_socklen_t *) & len))
181 {
182 if(err)
183 errtmp = err;
184 }
185 errno = errtmp;
186 #endif
187 return errtmp;
188 }
189
190 /*
191 * rb_getmaxconnect - return the max number of connections allowed
192 */
193 int
194 rb_getmaxconnect(void)
195 {
196 return (rb_maxconnections);
197 }
198
199 /*
200 * set_sock_buffers - set send and receive buffers for socket
201 *
202 * inputs - fd file descriptor
203 * - size to set
204 * output - returns true (1) if successful, false (0) otherwise
205 * side effects -
206 */
207 int
208 rb_set_buffers(rb_fde_t *F, int size)
209 {
210 if(F == NULL)
211 return 0;
212 if(setsockopt
213 (F->fd, SOL_SOCKET, SO_RCVBUF, (char *)&size, sizeof(size))
214 || setsockopt(F->fd, SOL_SOCKET, SO_SNDBUF, (char *)&size, sizeof(size)))
215 return 0;
216 return 1;
217 }
218
219 /*
220 * set_non_blocking - Set the client connection into non-blocking mode.
221 *
222 * inputs - fd to set into non blocking mode
223 * output - 1 if successful 0 if not
224 * side effects - use POSIX compliant non blocking and
225 * be done with it.
226 */
227 int
228 rb_set_nb(rb_fde_t *F)
229 {
230 int nonb = 0;
231 int res;
232 int fd;
233 if(F == NULL)
234 return 0;
235 fd = F->fd;
236
237 if((res = rb_setup_fd(F)))
238 return res;
239 #ifdef O_NONBLOCK
240 nonb |= O_NONBLOCK;
241 res = fcntl(fd, F_GETFL, 0);
242 if(-1 == res || fcntl(fd, F_SETFL, res | nonb) == -1)
243 return 0;
244 #else
245 nonb = 1;
246 res = 0;
247 if(ioctl(fd, FIONBIO, (char *)&nonb) == -1)
248 return 0;
249 #endif
250
251 return 1;
252 }
253
254 /*
255 * rb_settimeout() - set the socket timeout
256 *
257 * Set the timeout for the fd
258 */
259 void
260 rb_settimeout(rb_fde_t *F, time_t timeout, PF * callback, void *cbdata)
261 {
262 struct timeout_data *td;
263
264 if(F == NULL)
265 return;
266
267 lrb_assert(IsFDOpen(F));
268 td = F->timeout;
269 if(callback == NULL) /* user wants to remove */
270 {
271 if(td == NULL)
272 return;
273 rb_dlinkDelete(&td->node, &timeout_list);
274 rb_free(td);
275 F->timeout = NULL;
276 if(rb_dlink_list_length(&timeout_list) == 0)
277 {
278 rb_event_delete(rb_timeout_ev);
279 rb_timeout_ev = NULL;
280 }
281 return;
282 }
283
284 if(F->timeout == NULL)
285 td = F->timeout = rb_malloc(sizeof(struct timeout_data));
286
287 td->F = F;
288 td->timeout = rb_current_time() + timeout;
289 td->timeout_handler = callback;
290 td->timeout_data = cbdata;
291 rb_dlinkAdd(td, &td->node, &timeout_list);
292 if(rb_timeout_ev == NULL)
293 {
294 rb_timeout_ev = rb_event_add("rb_checktimeouts", rb_checktimeouts, NULL, 5);
295 }
296 }
297
298 /*
299 * rb_checktimeouts() - check the socket timeouts
300 *
301 * All this routine does is call the given callback/cbdata, without closing
302 * down the file descriptor. When close handlers have been implemented,
303 * this will happen.
304 */
305 void
306 rb_checktimeouts(void *notused)
307 {
308 rb_dlink_node *ptr, *next;
309 struct timeout_data *td;
310 rb_fde_t *F;
311 PF *hdl;
312 void *data;
313
314 RB_DLINK_FOREACH_SAFE(ptr, next, timeout_list.head)
315 {
316 td = ptr->data;
317 F = td->F;
318 if(F == NULL || !IsFDOpen(F))
319 continue;
320
321 if(td->timeout < rb_current_time())
322 {
323 hdl = td->timeout_handler;
324 data = td->timeout_data;
325 rb_dlinkDelete(&td->node, &timeout_list);
326 F->timeout = NULL;
327 rb_free(td);
328 hdl(F, data);
329 }
330 }
331 }
332
333 static void
334 rb_accept_tryaccept(rb_fde_t *F, void *data)
335 {
336 struct rb_sockaddr_storage st;
337 rb_fde_t *new_F;
338 rb_socklen_t addrlen = sizeof(st);
339 int new_fd;
340
341 while(1)
342 {
343 new_fd = accept(F->fd, (struct sockaddr *)&st, &addrlen);
344 rb_get_errno();
345 if(new_fd < 0)
346 {
347 rb_setselect(F, RB_SELECT_ACCEPT, rb_accept_tryaccept, NULL);
348 return;
349 }
350
351 rb_fd_hack(&new_fd);
352
353 new_F = rb_open(new_fd, RB_FD_SOCKET, "Incoming Connection");
354
355 if(new_F == NULL)
356 {
357 rb_lib_log
358 ("rb_accept: new_F == NULL on incoming connection. Closing new_fd == %d\n",
359 new_fd);
360 close(new_fd);
361 continue;
362 }
363
364 if(rb_unlikely(!rb_set_nb(new_F)))
365 {
366 rb_get_errno();
367 rb_lib_log("rb_accept: Couldn't set FD %d non blocking!", new_F->fd);
368 rb_close(new_F);
369 }
370
371 #ifdef RB_IPV6
372 mangle_mapped_sockaddr((struct sockaddr *)&st);
373 #endif
374
375 if(F->accept->precb != NULL)
376 {
377 if(!F->accept->precb(new_F, (struct sockaddr *)&st, addrlen, F->accept->data)) /* pre-callback decided to drop it */
378 continue;
379 }
380 #ifdef HAVE_SSL
381 if(F->type & RB_FD_SSL)
382 {
383 rb_ssl_accept_setup(F, new_F, (struct sockaddr *)&st, addrlen);
384 }
385 else
386 #endif /* HAVE_SSL */
387 {
388 F->accept->callback(new_F, RB_OK, (struct sockaddr *)&st, addrlen,
389 F->accept->data);
390 }
391 }
392
393 }
394
395 /* try to accept a TCP connection */
396 void
397 rb_accept_tcp(rb_fde_t *F, ACPRE * precb, ACCB * callback, void *data)
398 {
399 if(F == NULL)
400 return;
401 lrb_assert(callback);
402
403 F->accept = rb_malloc(sizeof(struct acceptdata));
404 F->accept->callback = callback;
405 F->accept->data = data;
406 F->accept->precb = precb;
407 rb_accept_tryaccept(F, NULL);
408 }
409
410 /*
411 * void rb_connect_tcp(int fd, struct sockaddr *dest,
412 * struct sockaddr *clocal, int socklen,
413 * CNCB *callback, void *data, int timeout)
414 * Input: An fd to connect with, a host and port to connect to,
415 * a local sockaddr to connect from + length(or NULL to use the
416 * default), a callback, the data to pass into the callback, the
417 * address family.
418 * Output: None.
419 * Side-effects: A non-blocking connection to the host is started, and
420 * if necessary, set up for selection. The callback given
421 * may be called now, or it may be called later.
422 */
423 void
424 rb_connect_tcp(rb_fde_t *F, struct sockaddr *dest,
425 struct sockaddr *clocal, int socklen, CNCB * callback, void *data, int timeout)
426 {
427 if(F == NULL)
428 return;
429
430 lrb_assert(callback);
431 F->connect = rb_malloc(sizeof(struct conndata));
432 F->connect->callback = callback;
433 F->connect->data = data;
434
435 memcpy(&F->connect->hostaddr, dest, sizeof(F->connect->hostaddr));
436
437 /* Note that we're using a passed sockaddr here. This is because
438 * generally you'll be bind()ing to a sockaddr grabbed from
439 * getsockname(), so this makes things easier.
440 * XXX If NULL is passed as local, we should later on bind() to the
441 * virtual host IP, for completeness.
442 * -- adrian
443 */
444 if((clocal != NULL) && (bind(F->fd, clocal, socklen) < 0))
445 {
446 /* Failure, call the callback with RB_ERR_BIND */
447 rb_connect_callback(F, RB_ERR_BIND);
448 /* ... and quit */
449 return;
450 }
451
452 /* We have a valid IP, so we just call tryconnect */
453 /* Make sure we actually set the timeout here .. */
454 rb_settimeout(F, timeout, rb_connect_timeout, NULL);
455 rb_connect_tryconnect(F, NULL);
456 }
457
458
459 /*
460 * rb_connect_callback() - call the callback, and continue with life
461 */
462 void
463 rb_connect_callback(rb_fde_t *F, int status)
464 {
465 CNCB *hdl;
466 void *data;
467 int errtmp = errno; /* save errno as rb_settimeout clobbers it sometimes */
468
469 /* This check is gross..but probably necessary */
470 if(F == NULL || F->connect == NULL || F->connect->callback == NULL)
471 return;
472 /* Clear the connect flag + handler */
473 hdl = F->connect->callback;
474 data = F->connect->data;
475 F->connect->callback = NULL;
476
477
478 /* Clear the timeout handler */
479 rb_settimeout(F, 0, NULL, NULL);
480 errno = errtmp;
481 /* Call the handler */
482 hdl(F, status, data);
483 }
484
485
486 /*
487 * rb_connect_timeout() - this gets called when the socket connection
488 * times out. This *only* can be called once connect() is initially
489 * called ..
490 */
491 static void
492 rb_connect_timeout(rb_fde_t *F, void *notused)
493 {
494 /* error! */
495 rb_connect_callback(F, RB_ERR_TIMEOUT);
496 }
497
498 /* static void rb_connect_tryconnect(int fd, void *notused)
499 * Input: The fd, the handler data(unused).
500 * Output: None.
501 * Side-effects: Try and connect with pending connect data for the FD. If
502 * we succeed or get a fatal error, call the callback.
503 * Otherwise, it is still blocking or something, so register
504 * to select for a write event on this FD.
505 */
506 static void
507 rb_connect_tryconnect(rb_fde_t *F, void *notused)
508 {
509 int retval;
510
511 if(F == NULL || F->connect == NULL || F->connect->callback == NULL)
512 return;
513 /* Try the connect() */
514 retval = connect(F->fd,
515 (struct sockaddr *)&F->connect->hostaddr,
516 GET_SS_LEN(&F->connect->hostaddr));
517 /* Error? */
518 if(retval < 0)
519 {
520 /*
521 * If we get EISCONN, then we've already connect()ed the socket,
522 * which is a good thing.
523 * -- adrian
524 */
525 rb_get_errno();
526 if(errno == EISCONN)
527 rb_connect_callback(F, RB_OK);
528 else if(rb_ignore_errno(errno))
529 /* Ignore error? Reschedule */
530 rb_setselect(F, RB_SELECT_CONNECT, rb_connect_tryconnect, NULL);
531 else
532 /* Error? Fail with RB_ERR_CONNECT */
533 rb_connect_callback(F, RB_ERR_CONNECT);
534 return;
535 }
536 /* If we get here, we've suceeded, so call with RB_OK */
537 rb_connect_callback(F, RB_OK);
538 }
539
540
541 int
542 rb_connect_sockaddr(rb_fde_t *F, struct sockaddr *addr, int len)
543 {
544 if(F == NULL)
545 return 0;
546
547 memcpy(addr, &F->connect->hostaddr, len);
548 return 1;
549 }
550
551 /*
552 * rb_error_str() - return an error string for the given error condition
553 */
554 const char *
555 rb_errstr(int error)
556 {
557 if(error < 0 || error >= RB_ERR_MAX)
558 return "Invalid error number!";
559 return rb_err_str[error];
560 }
561
562
563 int
564 rb_socketpair(int family, int sock_type, int proto, rb_fde_t **F1, rb_fde_t **F2, const char *note)
565 {
566 int nfd[2];
567 if(number_fd >= rb_maxconnections)
568 {
569 errno = ENFILE;
570 return -1;
571 }
572
573 #ifdef HAVE_SOCKETPAIR
574 if(socketpair(family, sock_type, proto, nfd))
575 #else
576 if(sock_type == SOCK_DGRAM)
577 {
578 return rb_inet_socketpair_udp(F1, F2);
579 }
580
581 if(rb_inet_socketpair(AF_INET, sock_type, proto, nfd))
582 #endif
583 return -1;
584
585 rb_fd_hack(&nfd[0]);
586 rb_fd_hack(&nfd[1]);
587
588 *F1 = rb_open(nfd[0], RB_FD_SOCKET, note);
589 *F2 = rb_open(nfd[1], RB_FD_SOCKET, note);
590
591 if(*F1 == NULL)
592 {
593 if(*F2 != NULL)
594 rb_close(*F2);
595 return -1;
596 }
597
598 if(*F2 == NULL)
599 {
600 rb_close(*F1);
601 return -1;
602 }
603
604 /* Set the socket non-blocking, and other wonderful bits */
605 if(rb_unlikely(!rb_set_nb(*F1)))
606 {
607 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd[0], strerror(errno));
608 rb_close(*F1);
609 rb_close(*F2);
610 return -1;
611 }
612
613 if(rb_unlikely(!rb_set_nb(*F2)))
614 {
615 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", nfd[1], strerror(errno));
616 rb_close(*F1);
617 rb_close(*F2);
618 return -1;
619 }
620
621 return 0;
622 }
623
624
625 int
626 rb_pipe(rb_fde_t **F1, rb_fde_t **F2, const char *desc)
627 {
628 #ifndef _WIN32
629 int fd[2];
630 if(number_fd >= rb_maxconnections)
631 {
632 errno = ENFILE;
633 return -1;
634 }
635 if(pipe(fd) == -1)
636 return -1;
637 rb_fd_hack(&fd[0]);
638 rb_fd_hack(&fd[1]);
639 *F1 = rb_open(fd[0], RB_FD_PIPE, desc);
640 *F2 = rb_open(fd[1], RB_FD_PIPE, desc);
641
642 if(rb_unlikely(!rb_set_nb(*F1)))
643 {
644 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd[0], strerror(errno));
645 rb_close(*F1);
646 rb_close(*F2);
647 return -1;
648 }
649
650 if(rb_unlikely(!rb_set_nb(*F2)))
651 {
652 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd[1], strerror(errno));
653 rb_close(*F1);
654 rb_close(*F2);
655 return -1;
656 }
657
658
659 return 0;
660 #else
661 /* Its not a pipe..but its selectable. I'll take dirty hacks
662 * for $500 Alex.
663 */
664 return rb_socketpair(AF_INET, SOCK_STREAM, 0, F1, F2, desc);
665 #endif
666 }
667
668 /*
669 * rb_socket() - open a socket
670 *
671 * This is a highly highly cut down version of squid's rb_open() which
672 * for the most part emulates socket(), *EXCEPT* it fails if we're about
673 * to run out of file descriptors.
674 */
675 rb_fde_t *
676 rb_socket(int family, int sock_type, int proto, const char *note)
677 {
678 rb_fde_t *F;
679 int fd;
680 /* First, make sure we aren't going to run out of file descriptors */
681 if(rb_unlikely(number_fd >= rb_maxconnections))
682 {
683 errno = ENFILE;
684 return NULL;
685 }
686
687 /*
688 * Next, we try to open the socket. We *should* drop the reserved FD
689 * limit if/when we get an error, but we can deal with that later.
690 * XXX !!! -- adrian
691 */
692 fd = socket(family, sock_type, proto);
693 rb_fd_hack(&fd);
694 if(rb_unlikely(fd < 0))
695 return NULL; /* errno will be passed through, yay.. */
696
697 #if defined(RB_IPV6) && defined(IPV6_V6ONLY)
698 /*
699 * Make sure we can take both IPv4 and IPv6 connections
700 * on an AF_INET6 socket
701 */
702 if(family == AF_INET6)
703 {
704 int off = 1;
705 if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &off, sizeof(off)) == -1)
706 {
707 rb_lib_log("rb_socket: Could not set IPV6_V6ONLY option to 1 on FD %d: %s",
708 fd, strerror(errno));
709 close(fd);
710 return NULL;
711 }
712 }
713 #endif
714
715 F = rb_open(fd, RB_FD_SOCKET, note);
716 if(F == NULL)
717 {
718 rb_lib_log("rb_socket: rb_open returns NULL on FD %d: %s, closing fd", fd,
719 strerror(errno));
720 close(fd);
721 return NULL;
722 }
723 /* Set the socket non-blocking, and other wonderful bits */
724 if(rb_unlikely(!rb_set_nb(F)))
725 {
726 rb_lib_log("rb_open: Couldn't set FD %d non blocking: %s", fd, strerror(errno));
727 rb_close(F);
728 return NULL;
729 }
730
731 return F;
732 }
733
734 /*
735 * If a sockaddr_storage is AF_INET6 but is a mapped IPv4
736 * socket manged the sockaddr.
737 */
738 #ifdef RB_IPV6
739 static void
740 mangle_mapped_sockaddr(struct sockaddr *in)
741 {
742 struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)in;
743
744 if(in->sa_family == AF_INET)
745 return;
746
747 if(in->sa_family == AF_INET6 && IN6_IS_ADDR_V4MAPPED(&in6->sin6_addr))
748 {
749 struct sockaddr_in in4;
750 memset(&in4, 0, sizeof(struct sockaddr_in));
751 in4.sin_family = AF_INET;
752 in4.sin_port = in6->sin6_port;
753 in4.sin_addr.s_addr = ((uint32_t *)&in6->sin6_addr)[3];
754 memcpy(in, &in4, sizeof(struct sockaddr_in));
755 }
756 return;
757 }
758 #endif
759
760 /*
761 * rb_listen() - listen on a port
762 */
763 int
764 rb_listen(rb_fde_t *F, int backlog)
765 {
766 F->type = RB_FD_SOCKET | RB_FD_LISTEN;
767 /* Currently just a simple wrapper for the sake of being complete */
768 return listen(F->fd, backlog);
769 }
770
771 void
772 rb_fdlist_init(int closeall, int maxfds, size_t heapsize)
773 {
774 static int initialized = 0;
775 #ifdef _WIN32
776 WSADATA wsaData;
777 int err;
778 int vers = MAKEWORD(2, 0);
779
780 err = WSAStartup(vers, &wsaData);
781 if(err != 0)
782 {
783 rb_lib_die("WSAStartup failed");
784 }
785
786 #endif
787 if(!initialized)
788 {
789 rb_maxconnections = maxfds;
790 if(closeall)
791 rb_close_all();
792 /* Since we're doing this once .. */
793 initialized = 1;
794 }
795 fd_heap = rb_bh_create(sizeof(rb_fde_t), heapsize, "librb_fd_heap");
796
797 }
798
799
800 /* Called to open a given filedescriptor */
801 rb_fde_t *
802 rb_open(int fd, uint8_t type, const char *desc)
803 {
804 rb_fde_t *F;
805 lrb_assert(fd >= 0);
806
807 F = add_fd(fd);
808
809 lrb_assert(!IsFDOpen(F));
810 if(rb_unlikely(IsFDOpen(F)))
811 {
812 const char *fdesc;
813 if(F != NULL && F->desc != NULL)
814 fdesc = F->desc;
815 else
816 fdesc = "NULL";
817 rb_lib_log("Trying to rb_open an already open FD: %d desc: %s", fd, fdesc);
818 return NULL;
819 }
820 F->fd = fd;
821 F->type = type;
822 SetFDOpen(F);
823
824 if(desc != NULL)
825 F->desc = rb_strndup(desc, FD_DESC_SZ);
826 number_fd++;
827 return F;
828 }
829
830
831 /* Called to close a given filedescriptor */
832 void
833 rb_close(rb_fde_t *F)
834 {
835 int type, fd;
836
837 if(F == NULL)
838 return;
839
840 fd = F->fd;
841 type = F->type;
842 lrb_assert(IsFDOpen(F));
843
844 lrb_assert(!(type & RB_FD_FILE));
845 if(rb_unlikely(type & RB_FD_FILE))
846 {
847 lrb_assert(F->read_handler == NULL);
848 lrb_assert(F->write_handler == NULL);
849 }
850 rb_setselect(F, RB_SELECT_WRITE | RB_SELECT_READ, NULL, NULL);
851 rb_settimeout(F, 0, NULL, NULL);
852 rb_free(F->accept);
853 rb_free(F->connect);
854 rb_free(F->desc);
855 #ifdef HAVE_SSL
856 if(type & RB_FD_SSL)
857 {
858 rb_ssl_shutdown(F);
859 }
860 #endif /* HAVE_SSL */
861 if(IsFDOpen(F))
862 {
863 remove_fd(F);
864 ClearFDOpen(F);
865 }
866
867 number_fd--;
868
869 #ifdef _WIN32
870 if(type & (RB_FD_SOCKET | RB_FD_PIPE))
871 {
872 closesocket(fd);
873 return;
874 }
875 else
876 #endif
877 close(fd);
878 }
879
880
881 /*
882 * rb_dump_fd() - dump the list of active filedescriptors
883 */
884 void
885 rb_dump_fd(DUMPCB * cb, void *data)
886 {
887 static const char *empty = "";
888 rb_dlink_node *ptr;
889 rb_dlink_list *bucket;
890 rb_fde_t *F;
891 unsigned int i;
892
893 for(i = 0; i < RB_FD_HASH_SIZE; i++)
894 {
895 bucket = &rb_fd_table[i];
896
897 if(rb_dlink_list_length(bucket) <= 0)
898 continue;
899
900 RB_DLINK_FOREACH(ptr, bucket->head)
901 {
902 F = ptr->data;
903 if(F == NULL || !IsFDOpen(F))
904 continue;
905
906 cb(F->fd, F->desc ? F->desc : empty, data);
907 }
908 }
909 }
910
911 /*
912 * rb_note() - set the fd note
913 *
914 * Note: must be careful not to overflow rb_fd_table[fd].desc when
915 * calling.
916 */
917 void
918 rb_note(rb_fde_t *F, const char *string)
919 {
920 if(F == NULL)
921 return;
922
923 rb_free(F->desc);
924 F->desc = rb_strndup(string, FD_DESC_SZ);
925 }
926
927 void
928 rb_set_type(rb_fde_t *F, uint8_t type)
929 {
930 /* if the caller is calling this, lets assume they have a clue */
931 F->type = type;
932 return;
933 }
934
935 uint8_t
936 rb_get_type(rb_fde_t *F)
937 {
938 return F->type;
939 }
940
941 int
942 rb_fd_ssl(rb_fde_t *F)
943 {
944 if(F == NULL)
945 return 0;
946 if(F->type & RB_FD_SSL)
947 return 1;
948 return 0;
949 }
950
951 int
952 rb_get_fd(rb_fde_t *F)
953 {
954 if(F == NULL)
955 return -1;
956 return (F->fd);
957 }
958
959 rb_fde_t *
960 rb_get_fde(int fd)
961 {
962 return rb_find_fd(fd);
963 }
964
965 ssize_t
966 rb_read(rb_fde_t *F, void *buf, int count)
967 {
968 ssize_t ret;
969 if(F == NULL)
970 return 0;
971
972 /* This needs to be *before* RB_FD_SOCKET otherwise you'll process
973 * an SSL socket as a regular socket
974 */
975 #ifdef HAVE_SSL
976 if(F->type & RB_FD_SSL)
977 {
978 return rb_ssl_read(F, buf, count);
979 }
980 #endif
981 if(F->type & RB_FD_SOCKET)
982 {
983 ret = recv(F->fd, buf, count, 0);
984 if(ret < 0)
985 {
986 rb_get_errno();
987 }
988 return ret;
989 }
990
991
992 /* default case */
993 return read(F->fd, buf, count);
994 }
995
996
997 ssize_t
998 rb_write(rb_fde_t *F, const void *buf, int count)
999 {
1000 ssize_t ret;
1001 if(F == NULL)
1002 return 0;
1003
1004 #ifdef HAVE_SSL
1005 if(F->type & RB_FD_SSL)
1006 {
1007 return rb_ssl_write(F, buf, count);
1008 }
1009 #endif
1010 if(F->type & RB_FD_SOCKET)
1011 {
1012 ret = send(F->fd, buf, count, MSG_NOSIGNAL);
1013 if(ret < 0)
1014 {
1015 rb_get_errno();
1016 }
1017 return ret;
1018 }
1019
1020 return write(F->fd, buf, count);
1021 }
1022
1023 #if defined(HAVE_SSL) || defined(WIN32) || !defined(HAVE_WRITEV)
1024 static ssize_t
1025 rb_fake_writev(rb_fde_t *F, const struct rb_iovec *vp, size_t vpcount)
1026 {
1027 ssize_t count = 0;
1028
1029 while(vpcount-- > 0)
1030 {
1031 ssize_t written = rb_write(F, vp->iov_base, vp->iov_len);
1032
1033 if(written <= 0)
1034 {
1035 if(count > 0)
1036 return count;
1037 else
1038 return written;
1039 }
1040 count += written;
1041 vp++;
1042 }
1043 return (count);
1044 }
1045 #endif
1046
1047 #if defined(WIN32) || !defined(HAVE_WRITEV)
1048 ssize_t
1049 rb_writev(rb_fde_t *F, struct rb_iovec * vecount, int count)
1050 {
1051 return rb_fake_writev(F, vecount, count);
1052 }
1053
1054 #else
1055 ssize_t
1056 rb_writev(rb_fde_t *F, struct rb_iovec * vector, int count)
1057 {
1058 if(F == NULL)
1059 {
1060 errno = EBADF;
1061 return -1;
1062 }
1063 #ifdef HAVE_SSL
1064 if(F->type & RB_FD_SSL)
1065 {
1066 return rb_fake_writev(F, vector, count);
1067 }
1068 #endif /* HAVE_SSL */
1069 #ifdef HAVE_SENDMSG
1070 if(F->type & RB_FD_SOCKET)
1071 {
1072 struct msghdr msg;
1073 memset(&msg, 0, sizeof(msg));
1074 msg.msg_iov = (struct iovec *)vector;
1075 msg.msg_iovlen = count;
1076 return sendmsg(F->fd, &msg, MSG_NOSIGNAL);
1077 }
1078 #endif /* HAVE_SENDMSG */
1079 return writev(F->fd, (struct iovec *)vector, count);
1080
1081 }
1082 #endif
1083
1084
1085 /*
1086 * From: Thomas Helvey <tomh@inxpress.net>
1087 */
1088 static const char *IpQuadTab[] = {
1089 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
1090 "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
1091 "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
1092 "30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
1093 "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
1094 "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
1095 "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
1096 "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
1097 "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
1098 "90", "91", "92", "93", "94", "95", "96", "97", "98", "99",
1099 "100", "101", "102", "103", "104", "105", "106", "107", "108", "109",
1100 "110", "111", "112", "113", "114", "115", "116", "117", "118", "119",
1101 "120", "121", "122", "123", "124", "125", "126", "127", "128", "129",
1102 "130", "131", "132", "133", "134", "135", "136", "137", "138", "139",
1103 "140", "141", "142", "143", "144", "145", "146", "147", "148", "149",
1104 "150", "151", "152", "153", "154", "155", "156", "157", "158", "159",
1105 "160", "161", "162", "163", "164", "165", "166", "167", "168", "169",
1106 "170", "171", "172", "173", "174", "175", "176", "177", "178", "179",
1107 "180", "181", "182", "183", "184", "185", "186", "187", "188", "189",
1108 "190", "191", "192", "193", "194", "195", "196", "197", "198", "199",
1109 "200", "201", "202", "203", "204", "205", "206", "207", "208", "209",
1110 "210", "211", "212", "213", "214", "215", "216", "217", "218", "219",
1111 "220", "221", "222", "223", "224", "225", "226", "227", "228", "229",
1112 "230", "231", "232", "233", "234", "235", "236", "237", "238", "239",
1113 "240", "241", "242", "243", "244", "245", "246", "247", "248", "249",
1114 "250", "251", "252", "253", "254", "255"
1115 };
1116
1117 /*
1118 * inetntoa - in_addr to string
1119 * changed name to remove collision possibility and
1120 * so behaviour is guaranteed to take a pointer arg.
1121 * -avalon 23/11/92
1122 * inet_ntoa -- returned the dotted notation of a given
1123 * internet number
1124 * argv 11/90).
1125 * inet_ntoa -- its broken on some Ultrix/Dynix too. -avalon
1126 */
1127
1128 static const char *
1129 inetntoa(const char *in)
1130 {
1131 static char buf[16];
1132 char *bufptr = buf;
1133 const unsigned char *a = (const unsigned char *)in;
1134 const char *n;
1135
1136 n = IpQuadTab[*a++];
1137 while(*n)
1138 *bufptr++ = *n++;
1139 *bufptr++ = '.';
1140 n = IpQuadTab[*a++];
1141 while(*n)
1142 *bufptr++ = *n++;
1143 *bufptr++ = '.';
1144 n = IpQuadTab[*a++];
1145 while(*n)
1146 *bufptr++ = *n++;
1147 *bufptr++ = '.';
1148 n = IpQuadTab[*a];
1149 while(*n)
1150 *bufptr++ = *n++;
1151 *bufptr = '\0';
1152 return buf;
1153 }
1154
1155
1156 /*
1157 * Copyright (c) 1996-1999 by Internet Software Consortium.
1158 *
1159 * Permission to use, copy, modify, and distribute this software for any
1160 * purpose with or without fee is hereby granted, provided that the above
1161 * copyright notice and this permission notice appear in all copies.
1162 *
1163 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
1164 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
1165 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
1166 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
1167 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
1168 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
1169 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
1170 * SOFTWARE.
1171 */
1172
1173 #define SPRINTF(x) ((size_t)rb_sprintf x)
1174
1175 /*
1176 * WARNING: Don't even consider trying to compile this on a system where
1177 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
1178 */
1179
1180 static const char *inet_ntop4(const unsigned char *src, char *dst, unsigned int size);
1181 #ifdef RB_IPV6
1182 static const char *inet_ntop6(const unsigned char *src, char *dst, unsigned int size);
1183 #endif
1184
1185 /* const char *
1186 * inet_ntop4(src, dst, size)
1187 * format an IPv4 address
1188 * return:
1189 * `dst' (as a const)
1190 * notes:
1191 * (1) uses no statics
1192 * (2) takes a unsigned char* not an in_addr as input
1193 * author:
1194 * Paul Vixie, 1996.
1195 */
1196 static const char *
1197 inet_ntop4(const unsigned char *src, char *dst, unsigned int size)
1198 {
1199 if(size < 16)
1200 return NULL;
1201 return strcpy(dst, inetntoa((const char *)src));
1202 }
1203
1204 /* const char *
1205 * inet_ntop6(src, dst, size)
1206 * convert IPv6 binary address into presentation (printable) format
1207 * author:
1208 * Paul Vixie, 1996.
1209 */
1210 #ifdef RB_IPV6
1211 static const char *
1212 inet_ntop6(const unsigned char *src, char *dst, unsigned int size)
1213 {
1214 /*
1215 * Note that int32_t and int16_t need only be "at least" large enough
1216 * to contain a value of the specified size. On some systems, like
1217 * Crays, there is no such thing as an integer variable with 16 bits.
1218 * Keep this in mind if you think this function should have been coded
1219 * to use pointer overlays. All the world's not a VAX.
1220 */
1221 char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
1222 struct
1223 {
1224 int base, len;
1225 }
1226 best, cur;
1227 unsigned int words[IN6ADDRSZ / INT16SZ];
1228 int i;
1229
1230 /*
1231 * Preprocess:
1232 * Copy the input (bytewise) array into a wordwise array.
1233 * Find the longest run of 0x00's in src[] for :: shorthanding.
1234 */
1235 memset(words, '\0', sizeof words);
1236 for(i = 0; i < IN6ADDRSZ; i += 2)
1237 words[i / 2] = (src[i] << 8) | src[i + 1];
1238 best.base = -1;
1239 best.len = 0;
1240 cur.base = -1;
1241 cur.len = 0;
1242 for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
1243 {
1244 if(words[i] == 0)
1245 {
1246 if(cur.base == -1)
1247 cur.base = i, cur.len = 1;
1248 else
1249 cur.len++;
1250 }
1251 else
1252 {
1253 if(cur.base != -1)
1254 {
1255 if(best.base == -1 || cur.len > best.len)
1256 best = cur;
1257 cur.base = -1;
1258 }
1259 }
1260 }
1261 if(cur.base != -1)
1262 {
1263 if(best.base == -1 || cur.len > best.len)
1264 best = cur;
1265 }
1266 if(best.base != -1 && best.len < 2)
1267 best.base = -1;
1268
1269 /*
1270 * Format the result.
1271 */
1272 tp = tmp;
1273 for(i = 0; i < (IN6ADDRSZ / INT16SZ); i++)
1274 {
1275 /* Are we inside the best run of 0x00's? */
1276 if(best.base != -1 && i >= best.base && i < (best.base + best.len))
1277 {
1278 if(i == best.base)
1279 {
1280 if(i == 0)
1281 *tp++ = '0';
1282 *tp++ = ':';
1283 }
1284 continue;
1285 }
1286 /* Are we following an initial run of 0x00s or any real hex? */
1287 if(i != 0)
1288 *tp++ = ':';
1289 /* Is this address an encapsulated IPv4? */
1290 if(i == 6 && best.base == 0 &&
1291 (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
1292 {
1293 if(!inet_ntop4(src + 12, tp, sizeof tmp - (tp - tmp)))
1294 return (NULL);
1295 tp += strlen(tp);
1296 break;
1297 }
1298 tp += SPRINTF((tp, "%x", words[i]));
1299 }
1300 /* Was it a trailing run of 0x00's? */
1301 if(best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ))
1302 *tp++ = ':';
1303 *tp++ = '\0';
1304
1305 /*
1306 * Check for overflow, copy, and we're done.
1307 */
1308
1309 if((unsigned int)(tp - tmp) > size)
1310 {
1311 return (NULL);
1312 }
1313 return strcpy(dst, tmp);
1314 }
1315 #endif
1316
1317 int
1318 rb_inet_pton_sock(const char *src, struct sockaddr *dst)
1319 {
1320 if(rb_inet_pton(AF_INET, src, &((struct sockaddr_in *)dst)->sin_addr))
1321 {
1322 ((struct sockaddr_in *)dst)->sin_port = 0;
1323 ((struct sockaddr_in *)dst)->sin_family = AF_INET;
1324 SET_SS_LEN(dst, sizeof(struct sockaddr_in));
1325 return 1;
1326 }
1327 #ifdef RB_IPV6
1328 else if(rb_inet_pton(AF_INET6, src, &((struct sockaddr_in6 *)dst)->sin6_addr))
1329 {
1330 ((struct sockaddr_in6 *)dst)->sin6_port = 0;
1331 ((struct sockaddr_in6 *)dst)->sin6_family = AF_INET6;
1332 SET_SS_LEN(dst, sizeof(struct sockaddr_in6));
1333 return 1;
1334 }
1335 #endif
1336 return 0;
1337 }
1338
1339 const char *
1340 rb_inet_ntop_sock(struct sockaddr *src, char *dst, unsigned int size)
1341 {
1342 switch (src->sa_family)
1343 {
1344 case AF_INET:
1345 return (rb_inet_ntop(AF_INET, &((struct sockaddr_in *)src)->sin_addr, dst, size));
1346 break;
1347 #ifdef RB_IPV6
1348 case AF_INET6:
1349 return (rb_inet_ntop
1350 (AF_INET6, &((struct sockaddr_in6 *)src)->sin6_addr, dst, size));
1351 break;
1352 #endif
1353 default:
1354 return NULL;
1355 break;
1356 }
1357 }
1358
1359 /* char *
1360 * rb_inet_ntop(af, src, dst, size)
1361 * convert a network format address to presentation format.
1362 * return:
1363 * pointer to presentation format address (`dst'), or NULL (see errno).
1364 * author:
1365 * Paul Vixie, 1996.
1366 */
1367 const char *
1368 rb_inet_ntop(int af, const void *src, char *dst, unsigned int size)
1369 {
1370 switch (af)
1371 {
1372 case AF_INET:
1373 return (inet_ntop4(src, dst, size));
1374 #ifdef RB_IPV6
1375 case AF_INET6:
1376 if(IN6_IS_ADDR_V4MAPPED((const struct in6_addr *)src) ||
1377 IN6_IS_ADDR_V4COMPAT((const struct in6_addr *)src))
1378 return (inet_ntop4
1379 ((const unsigned char *)&((const struct in6_addr *)src)->
1380 s6_addr[12], dst, size));
1381 else
1382 return (inet_ntop6(src, dst, size));
1383
1384
1385 #endif
1386 default:
1387 return (NULL);
1388 }
1389 /* NOTREACHED */
1390 }
1391
1392 /*
1393 * WARNING: Don't even consider trying to compile this on a system where
1394 * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
1395 */
1396
1397 /* int
1398 * rb_inet_pton(af, src, dst)
1399 * convert from presentation format (which usually means ASCII printable)
1400 * to network format (which is usually some kind of binary format).
1401 * return:
1402 * 1 if the address was valid for the specified address family
1403 * 0 if the address wasn't valid (`dst' is untouched in this case)
1404 * -1 if some other error occurred (`dst' is untouched in this case, too)
1405 * author:
1406 * Paul Vixie, 1996.
1407 */
1408
1409 /* int
1410 * inet_pton4(src, dst)
1411 * like inet_aton() but without all the hexadecimal and shorthand.
1412 * return:
1413 * 1 if `src' is a valid dotted quad, else 0.
1414 * notice:
1415 * does not touch `dst' unless it's returning 1.
1416 * author:
1417 * Paul Vixie, 1996.
1418 */
1419 static int
1420 inet_pton4(const char *src, unsigned char *dst)
1421 {
1422 int saw_digit, octets, ch;
1423 unsigned char tmp[INADDRSZ], *tp;
1424
1425 saw_digit = 0;
1426 octets = 0;
1427 *(tp = tmp) = 0;
1428 while((ch = *src++) != '\0')
1429 {
1430
1431 if(ch >= '0' && ch <= '9')
1432 {
1433 unsigned int new = *tp * 10 + (ch - '0');
1434
1435 if(new > 255)
1436 return (0);
1437 *tp = new;
1438 if(!saw_digit)
1439 {
1440 if(++octets > 4)
1441 return (0);
1442 saw_digit = 1;
1443 }
1444 }
1445 else if(ch == '.' && saw_digit)
1446 {
1447 if(octets == 4)
1448 return (0);
1449 *++tp = 0;
1450 saw_digit = 0;
1451 }
1452 else
1453 return (0);
1454 }
1455 if(octets < 4)
1456 return (0);
1457 memcpy(dst, tmp, INADDRSZ);
1458 return (1);
1459 }
1460
1461 #ifdef RB_IPV6
1462 /* int
1463 * inet_pton6(src, dst)
1464 * convert presentation level address to network order binary form.
1465 * return:
1466 * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
1467 * notice:
1468 * (1) does not touch `dst' unless it's returning 1.
1469 * (2) :: in a full address is silently ignored.
1470 * credit:
1471 * inspired by Mark Andrews.
1472 * author:
1473 * Paul Vixie, 1996.
1474 */
1475
1476 static int
1477 inet_pton6(const char *src, unsigned char *dst)
1478 {
1479 static const char xdigits[] = "0123456789abcdef";
1480 unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
1481 const char *curtok;
1482 int ch, saw_xdigit;
1483 unsigned int val;
1484
1485 tp = memset(tmp, '\0', IN6ADDRSZ);
1486 endp = tp + IN6ADDRSZ;
1487 colonp = NULL;
1488 /* Leading :: requires some special handling. */
1489 if(*src == ':')
1490 if(*++src != ':')
1491 return (0);
1492 curtok = src;
1493 saw_xdigit = 0;
1494 val = 0;
1495 while((ch = tolower(*src++)) != '\0')
1496 {
1497 const char *pch;
1498
1499 pch = strchr(xdigits, ch);
1500 if(pch != NULL)
1501 {
1502 val <<= 4;
1503 val |= (pch - xdigits);
1504 if(val > 0xffff)
1505 return (0);
1506 saw_xdigit = 1;
1507 continue;
1508 }
1509 if(ch == ':')
1510 {
1511 curtok = src;
1512 if(!saw_xdigit)
1513 {
1514 if(colonp)
1515 return (0);
1516 colonp = tp;
1517 continue;
1518 }
1519 else if(*src == '\0')
1520 {
1521 return (0);
1522 }
1523 if(tp + INT16SZ > endp)
1524 return (0);
1525 *tp++ = (unsigned char)(val >> 8) & 0xff;
1526 *tp++ = (unsigned char)val & 0xff;
1527 saw_xdigit = 0;
1528 val = 0;
1529 continue;
1530 }
1531 if(*src != '\0' && ch == '.')
1532 {
1533 if(((tp + INADDRSZ) <= endp) && inet_pton4(curtok, tp) > 0)
1534 {
1535 tp += INADDRSZ;
1536 saw_xdigit = 0;
1537 break; /* '\0' was seen by inet_pton4(). */
1538 }
1539 }
1540 else
1541 continue;
1542 return (0);
1543 }
1544 if(saw_xdigit)
1545 {
1546 if(tp + INT16SZ > endp)
1547 return (0);
1548 *tp++ = (unsigned char)(val >> 8) & 0xff;
1549 *tp++ = (unsigned char)val & 0xff;
1550 }
1551 if(colonp != NULL)
1552 {
1553 /*
1554 * Since some memmove()'s erroneously fail to handle
1555 * overlapping regions, we'll do the shift by hand.
1556 */
1557 const int n = tp - colonp;
1558 int i;
1559
1560 if(tp == endp)
1561 return (0);
1562 for(i = 1; i <= n; i++)
1563 {
1564 endp[-i] = colonp[n - i];
1565 colonp[n - i] = 0;
1566 }
1567 tp = endp;
1568 }
1569 if(tp != endp)
1570 return (0);
1571 memcpy(dst, tmp, IN6ADDRSZ);
1572 return (1);
1573 }
1574 #endif
1575 int
1576 rb_inet_pton(int af, const char *src, void *dst)
1577 {
1578 switch (af)
1579 {
1580 case AF_INET:
1581 return (inet_pton4(src, dst));
1582 #ifdef RB_IPV6
1583 case AF_INET6:
1584 /* Somebody might have passed as an IPv4 address this is sick but it works */
1585 if(inet_pton4(src, dst))
1586 {
1587 char tmp[HOSTIPLEN];
1588 rb_sprintf(tmp, "::ffff:%s", src);
1589 return (inet_pton6(tmp, dst));
1590 }
1591 else
1592 return (inet_pton6(src, dst));
1593 #endif
1594 default:
1595 return (-1);
1596 }
1597 /* NOTREACHED */
1598 }
1599
1600
1601 #ifndef HAVE_SOCKETPAIR
1602
1603 /* mostly based on perl's emulation of socketpair udp */
1604 static int
1605 rb_inet_socketpair_udp(rb_fde_t **newF1, rb_fde_t **newF2)
1606 {
1607 struct sockaddr_in addr[2];
1608 rb_socklen_t size = sizeof(struct sockaddr_in);
1609 rb_fde_t *F[2];
1610 unsigned int fd[2];
1611 int i, got;
1612 unsigned short port;
1613
1614 memset(&addr, 0, sizeof(addr));
1615
1616 for(i = 0; i < 2; i++)
1617 {
1618 F[i] = rb_socket(AF_INET, SOCK_DGRAM, 0, "udp socketpair");
1619 if(F[i] == NULL)
1620 goto failed;
1621 addr[i].sin_family = AF_INET;
1622 addr[i].sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1623 addr[i].sin_port = 0;
1624 if(bind(rb_get_fd(F[i]), (struct sockaddr *)&addr[i], sizeof(struct sockaddr_in)))
1625 goto failed;
1626 fd[i] = rb_get_fd(F[i]);
1627 }
1628
1629 for(i = 0; i < 2; i++)
1630 {
1631 if(getsockname(fd[i], (struct sockaddr *)&addr[i], &size))
1632 goto failed;
1633 if(size != sizeof(struct sockaddr_in))
1634 goto failed;
1635 if(connect(fd[!i], (struct sockaddr *)&addr[i], sizeof(struct sockaddr_in)) == -1)
1636 goto failed;
1637 }
1638
1639 for(i = 0; i < 2; i++)
1640 {
1641 port = addr[i].sin_port;
1642 got = rb_write(F[i], &port, sizeof(port));
1643 if(got != sizeof(port))
1644 {
1645 if(got == -1)
1646 goto failed;
1647 goto abort_failed;
1648 }
1649 }
1650
1651
1652 struct timeval wait = { 0, 100000 };
1653
1654 int max = fd[1] > fd[0] ? fd[1] : fd[0];
1655 fd_set rset;
1656 FD_ZERO(&rset);
1657 FD_SET(fd[0], &rset);
1658 FD_SET(fd[1], &rset);
1659 got = select(max + 1, &rset, NULL, NULL, &wait);
1660 if(got != 2 || !FD_ISSET(fd[0], &rset) || !FD_ISSET(fd[1], &rset))
1661 {
1662 if(got == -1)
1663 goto failed;
1664 goto abort_failed;
1665 }
1666
1667 struct sockaddr_in readfrom;
1668 unsigned short buf[2];
1669 for(i = 0; i < 2; i++)
1670 {
1671 #ifdef MSG_DONTWAIT
1672 int flag = MSG_DONTWAIT
1673 #else
1674 int flag = 0;
1675 #endif
1676 got = recvfrom(rb_get_fd(F[i]), (char *)&buf, sizeof(buf), flag,
1677 (struct sockaddr *)&readfrom, &size);
1678 if(got == -1)
1679 goto failed;
1680 if(got != sizeof(port)
1681 || size != sizeof(struct sockaddr_in)
1682 || buf[0] != (unsigned short)addr[!i].sin_port
1683 || readfrom.sin_family != addr[!i].sin_family
1684 || readfrom.sin_addr.s_addr != addr[!i].sin_addr.s_addr
1685 || readfrom.sin_port != addr[!i].sin_port)
1686 goto abort_failed;
1687 }
1688
1689 *newF1 = F[0];
1690 *newF2 = F[1];
1691 return 0;
1692
1693 #ifdef _WIN32
1694 #define ECONNABORTED WSAECONNABORTED
1695 #endif
1696
1697 abort_failed:
1698 rb_get_errno();
1699 errno = ECONNABORTED;
1700 failed:
1701 if(errno != ECONNABORTED)
1702 rb_get_errno();
1703 int o_errno = errno;
1704 if(F[0] != NULL)
1705 rb_close(F[0]);
1706 if(F[1] != NULL)
1707 rb_close(F[1]);
1708 errno = o_errno;
1709 return -1;
1710 }
1711
1712
1713 int
1714 rb_inet_socketpair(int family, int type, int protocol, int fd[2])
1715 {
1716 int listener = -1;
1717 int connector = -1;
1718 int acceptor = -1;
1719 struct sockaddr_in listen_addr;
1720 struct sockaddr_in connect_addr;
1721 rb_socklen_t size;
1722
1723 if(protocol || family != AF_INET)
1724 {
1725 errno = EAFNOSUPPORT;
1726 return -1;
1727 }
1728 if(!fd)
1729 {
1730 errno = EINVAL;
1731 return -1;
1732 }
1733
1734 listener = socket(AF_INET, type, 0);
1735 if(listener == -1)
1736 return -1;
1737 memset(&listen_addr, 0, sizeof(listen_addr));
1738 listen_addr.sin_family = AF_INET;
1739 listen_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1740 listen_addr.sin_port = 0; /* kernel choses port. */
1741 if(bind(listener, (struct sockaddr *)&listen_addr, sizeof(listen_addr)) == -1)
1742 goto tidy_up_and_fail;
1743 if(listen(listener, 1) == -1)
1744 goto tidy_up_and_fail;
1745
1746 connector = socket(AF_INET, type, 0);
1747 if(connector == -1)
1748 goto tidy_up_and_fail;
1749 /* We want to find out the port number to connect to. */
1750 size = sizeof(connect_addr);
1751 if(getsockname(listener, (struct sockaddr *)&connect_addr, &size) == -1)
1752 goto tidy_up_and_fail;
1753 if(size != sizeof(connect_addr))
1754 goto abort_tidy_up_and_fail;
1755 if(connect(connector, (struct sockaddr *)&connect_addr, sizeof(connect_addr)) == -1)
1756 goto tidy_up_and_fail;
1757
1758 size = sizeof(listen_addr);
1759 acceptor = accept(listener, (struct sockaddr *)&listen_addr, &size);
1760 if(acceptor == -1)
1761 goto tidy_up_and_fail;
1762 if(size != sizeof(listen_addr))
1763 goto abort_tidy_up_and_fail;
1764 close(listener);
1765 /* Now check we are talking to ourself by matching port and host on the
1766 two sockets. */
1767 if(getsockname(connector, (struct sockaddr *)&connect_addr, &size) == -1)
1768 goto tidy_up_and_fail;
1769 if(size != sizeof(connect_addr)
1770 || listen_addr.sin_family != connect_addr.sin_family
1771 || listen_addr.sin_addr.s_addr != connect_addr.sin_addr.s_addr
1772 || listen_addr.sin_port != connect_addr.sin_port)
1773 {
1774 goto abort_tidy_up_and_fail;
1775 }
1776 fd[0] = connector;
1777 fd[1] = acceptor;
1778 return 0;
1779
1780 abort_tidy_up_and_fail:
1781 errno = EINVAL; /* I hope this is portable and appropriate. */
1782
1783 tidy_up_and_fail:
1784 {
1785 int save_errno = errno;
1786 if(listener != -1)
1787 close(listener);
1788 if(connector != -1)
1789 close(connector);
1790 if(acceptor != -1)
1791 close(acceptor);
1792 errno = save_errno;
1793 return -1;
1794 }
1795 }
1796
1797 #endif
1798
1799
1800 static void (*setselect_handler) (rb_fde_t *, unsigned int, PF *, void *);
1801 static int (*select_handler) (long);
1802 static int (*setup_fd_handler) (rb_fde_t *);
1803 static int (*io_sched_event) (struct ev_entry *, int);
1804 static void (*io_unsched_event) (struct ev_entry *);
1805 static int (*io_supports_event) (void);
1806 static void (*io_init_event) (void);
1807 static char iotype[25];
1808
1809 const char *
1810 rb_get_iotype(void)
1811 {
1812 return iotype;
1813 }
1814
1815 static int
1816 rb_unsupported_event(void)
1817 {
1818 return 0;
1819 }
1820
1821 static int
1822 try_kqueue(void)
1823 {
1824 if(!rb_init_netio_kqueue())
1825 {
1826 setselect_handler = rb_setselect_kqueue;
1827 select_handler = rb_select_kqueue;
1828 setup_fd_handler = rb_setup_fd_kqueue;
1829 io_sched_event = rb_kqueue_sched_event;
1830 io_unsched_event = rb_kqueue_unsched_event;
1831 io_init_event = rb_kqueue_init_event;
1832 io_supports_event = rb_kqueue_supports_event;
1833 rb_strlcpy(iotype, "kqueue", sizeof(iotype));
1834 return 0;
1835 }
1836 return -1;
1837 }
1838
1839 static int
1840 try_epoll(void)
1841 {
1842 if(!rb_init_netio_epoll())
1843 {
1844 setselect_handler = rb_setselect_epoll;
1845 select_handler = rb_select_epoll;
1846 setup_fd_handler = rb_setup_fd_epoll;
1847 io_sched_event = rb_epoll_sched_event;
1848 io_unsched_event = rb_epoll_unsched_event;
1849 io_supports_event = rb_epoll_supports_event;
1850 io_init_event = rb_epoll_init_event;
1851 rb_strlcpy(iotype, "epoll", sizeof(iotype));
1852 return 0;
1853 }
1854 return -1;
1855 }
1856
1857 static int
1858 try_ports(void)
1859 {
1860 if(!rb_init_netio_ports())
1861 {
1862 setselect_handler = rb_setselect_ports;
1863 select_handler = rb_select_ports;
1864 setup_fd_handler = rb_setup_fd_ports;
1865 io_sched_event = NULL;
1866 io_unsched_event = NULL;
1867 io_init_event = NULL;
1868 io_supports_event = rb_unsupported_event;
1869 rb_strlcpy(iotype, "ports", sizeof(iotype));
1870 return 0;
1871 }
1872 return -1;
1873 }
1874
1875 static int
1876 try_devpoll(void)
1877 {
1878 if(!rb_init_netio_devpoll())
1879 {
1880 setselect_handler = rb_setselect_devpoll;
1881 select_handler = rb_select_devpoll;
1882 setup_fd_handler = rb_setup_fd_devpoll;
1883 io_sched_event = NULL;
1884 io_unsched_event = NULL;
1885 io_init_event = NULL;
1886 io_supports_event = rb_unsupported_event;
1887 rb_strlcpy(iotype, "devpoll", sizeof(iotype));
1888 return 0;
1889 }
1890 return -1;
1891 }
1892
1893 static int
1894 try_sigio(void)
1895 {
1896 if(!rb_init_netio_sigio())
1897 {
1898 setselect_handler = rb_setselect_sigio;
1899 select_handler = rb_select_sigio;
1900 setup_fd_handler = rb_setup_fd_sigio;
1901 io_sched_event = rb_sigio_sched_event;
1902 io_unsched_event = rb_sigio_unsched_event;
1903 io_supports_event = rb_sigio_supports_event;
1904 io_init_event = rb_sigio_init_event;
1905
1906 rb_strlcpy(iotype, "sigio", sizeof(iotype));
1907 return 0;
1908 }
1909 return -1;
1910 }
1911
1912 static int
1913 try_poll(void)
1914 {
1915 if(!rb_init_netio_poll())
1916 {
1917 setselect_handler = rb_setselect_poll;
1918 select_handler = rb_select_poll;
1919 setup_fd_handler = rb_setup_fd_poll;
1920 io_sched_event = NULL;
1921 io_unsched_event = NULL;
1922 io_init_event = NULL;
1923 io_supports_event = rb_unsupported_event;
1924 rb_strlcpy(iotype, "poll", sizeof(iotype));
1925 return 0;
1926 }
1927 return -1;
1928 }
1929
1930 static int
1931 try_win32(void)
1932 {
1933 if(!rb_init_netio_win32())
1934 {
1935 setselect_handler = rb_setselect_win32;
1936 select_handler = rb_select_win32;
1937 setup_fd_handler = rb_setup_fd_win32;
1938 io_sched_event = NULL;
1939 io_unsched_event = NULL;
1940 io_init_event = NULL;
1941 io_supports_event = rb_unsupported_event;
1942 rb_strlcpy(iotype, "win32", sizeof(iotype));
1943 return 0;
1944 }
1945 return -1;
1946 }
1947
1948 static int
1949 try_select(void)
1950 {
1951 if(!rb_init_netio_select())
1952 {
1953 setselect_handler = rb_setselect_select;
1954 select_handler = rb_select_select;
1955 setup_fd_handler = rb_setup_fd_select;
1956 io_sched_event = NULL;
1957 io_unsched_event = NULL;
1958 io_init_event = NULL;
1959 io_supports_event = rb_unsupported_event;
1960 rb_strlcpy(iotype, "select", sizeof(iotype));
1961 return 0;
1962 }
1963 return -1;
1964 }
1965
1966
1967 int
1968 rb_io_sched_event(struct ev_entry *ev, int when)
1969 {
1970 if(ev == NULL || io_supports_event == NULL || io_sched_event == NULL
1971 || !io_supports_event())
1972 return 0;
1973 return io_sched_event(ev, when);
1974 }
1975
1976 void
1977 rb_io_unsched_event(struct ev_entry *ev)
1978 {
1979 if(ev == NULL || io_supports_event == NULL || io_unsched_event == NULL
1980 || !io_supports_event())
1981 return;
1982 io_unsched_event(ev);
1983 }
1984
1985 int
1986 rb_io_supports_event(void)
1987 {
1988 if(io_supports_event == NULL)
1989 return 0;
1990 return io_supports_event();
1991 }
1992
1993 void
1994 rb_io_init_event(void)
1995 {
1996 io_init_event();
1997 rb_event_io_register_all();
1998 }
1999
2000 void
2001 rb_init_netio(void)
2002 {
2003 char *ioenv = getenv("LIBRB_USE_IOTYPE");
2004 rb_fd_table = rb_malloc(RB_FD_HASH_SIZE * sizeof(rb_dlink_list));
2005 rb_init_ssl();
2006
2007 if(ioenv != NULL)
2008 {
2009 if(!strcmp("epoll", ioenv))
2010 {
2011 if(!try_epoll())
2012 return;
2013 }
2014 else if(!strcmp("kqueue", ioenv))
2015 {
2016 if(!try_kqueue())
2017 return;
2018 }
2019 else if(!strcmp("ports", ioenv))
2020 {
2021 if(!try_ports())
2022 return;
2023 }
2024 else if(!strcmp("poll", ioenv))
2025 {
2026 if(!try_poll())
2027 return;
2028 }
2029 else if(!strcmp("devpoll", ioenv))
2030 {
2031 if(!try_devpoll())
2032 return;
2033 }
2034 else if(!strcmp("sigio", ioenv))
2035 {
2036 if(!try_sigio())
2037 return;
2038 }
2039 else if(!strcmp("select", ioenv))
2040 {
2041 if(!try_select())
2042 return;
2043 }
2044 if(!strcmp("win32", ioenv))
2045 {
2046 if(!try_win32())
2047 return;
2048 }
2049
2050 }
2051
2052 if(!try_kqueue())
2053 return;
2054 if(!try_epoll())
2055 return;
2056 if(!try_ports())
2057 return;
2058 if(!try_devpoll())
2059 return;
2060 if(!try_sigio())
2061 return;
2062 if(!try_poll())
2063 return;
2064 if(!try_win32())
2065 return;
2066 if(!try_select())
2067 return;
2068
2069 rb_lib_log("rb_init_netio: Could not find any io handlers...giving up");
2070
2071 abort();
2072 }
2073
2074 void
2075 rb_setselect(rb_fde_t *F, unsigned int type, PF * handler, void *client_data)
2076 {
2077 setselect_handler(F, type, handler, client_data);
2078 }
2079
2080 int
2081 rb_select(unsigned long timeout)
2082 {
2083 int ret = select_handler(timeout);
2084 free_fds();
2085 return ret;
2086 }
2087
2088 int
2089 rb_setup_fd(rb_fde_t *F)
2090 {
2091 return setup_fd_handler(F);
2092 }
2093
2094
2095
2096 int
2097 rb_ignore_errno(int error)
2098 {
2099 switch (error)
2100 {
2101 #ifdef EINPROGRESS
2102 case EINPROGRESS:
2103 #endif
2104 #if defined EWOULDBLOCK
2105 case EWOULDBLOCK:
2106 #endif
2107 #if defined(EAGAIN) && (EWOULDBLOCK != EAGAIN)
2108 case EAGAIN:
2109 #endif
2110 #ifdef EINTR
2111 case EINTR:
2112 #endif
2113 #ifdef ERESTART
2114 case ERESTART:
2115 #endif
2116 #ifdef ENOBUFS
2117 case ENOBUFS:
2118 #endif
2119 return 1;
2120 default:
2121 break;
2122 }
2123 return 0;
2124 }
2125
2126
2127 #if defined(HAVE_SENDMSG) && !defined(WIN32)
2128 int
2129 rb_recv_fd_buf(rb_fde_t *F, void *data, size_t datasize, rb_fde_t **xF, int nfds)
2130 {
2131 struct msghdr msg;
2132 struct cmsghdr *cmsg;
2133 struct iovec iov[1];
2134 struct stat st;
2135 uint8_t stype = RB_FD_UNKNOWN;
2136 const char *desc;
2137 int fd, len, x, rfds;
2138
2139 int control_len = CMSG_SPACE(sizeof(int) * nfds);
2140
2141 iov[0].iov_base = data;
2142 iov[0].iov_len = datasize;
2143
2144 msg.msg_name = NULL;
2145 msg.msg_namelen = 0;
2146 msg.msg_iov = iov;
2147 msg.msg_iovlen = 1;
2148 msg.msg_flags = 0;
2149 cmsg = alloca(control_len);
2150 msg.msg_control = cmsg;
2151 msg.msg_controllen = control_len;
2152
2153 if((len = recvmsg(rb_get_fd(F), &msg, 0)) <= 0)
2154 return len;
2155
2156 if(msg.msg_controllen > 0 && msg.msg_control != NULL
2157 && (cmsg = CMSG_FIRSTHDR(&msg)) != NULL)
2158 {
2159 rfds = (msg.msg_controllen - sizeof(struct cmsghdr)) / sizeof(int);
2160
2161 for(x = 0; x < nfds && x < rfds; x++)
2162 {
2163 fd = ((int *)CMSG_DATA(cmsg))[x];
2164 stype = RB_FD_UNKNOWN;
2165 desc = "remote unknown";
2166 if(!fstat(fd, &st))
2167 {
2168 if(S_ISSOCK(st.st_mode))
2169 {
2170 stype = RB_FD_SOCKET;
2171 desc = "remote socket";
2172 }
2173 else if(S_ISFIFO(st.st_mode))
2174 {
2175 stype = RB_FD_PIPE;
2176 desc = "remote pipe";
2177 }
2178 else if(S_ISREG(st.st_mode))
2179 {
2180 stype = RB_FD_FILE;
2181 desc = "remote file";
2182 }
2183 }
2184 xF[x] = rb_open(fd, stype, desc);
2185 }
2186 }
2187 else
2188 *xF = NULL;
2189 return len;
2190 }
2191
2192
2193 int
2194 rb_send_fd_buf(rb_fde_t *xF, rb_fde_t **F, int count, void *data, size_t datasize, pid_t pid)
2195 {
2196 int n;
2197 struct msghdr msg;
2198 struct cmsghdr *cmsg;
2199 struct iovec iov[1];
2200 char empty = '0';
2201 char *buf;
2202
2203 memset(&msg, 0, sizeof(&msg));
2204 if(datasize == 0)
2205 {
2206 iov[0].iov_base = &empty;
2207 iov[0].iov_len = 1;
2208 }
2209 else
2210 {
2211 iov[0].iov_base = data;
2212 iov[0].iov_len = datasize;
2213 }
2214 msg.msg_iov = iov;
2215 msg.msg_iovlen = 1;
2216 msg.msg_name = NULL;
2217 msg.msg_namelen = 0;
2218 msg.msg_flags = 0;
2219 msg.msg_control = NULL;
2220 msg.msg_controllen = 0;
2221
2222 if(count > 0)
2223 {
2224 int i;
2225 int len = CMSG_SPACE(sizeof(int) * count);
2226 buf = alloca(len);
2227
2228 msg.msg_control = buf;
2229 msg.msg_controllen = len;
2230 cmsg = CMSG_FIRSTHDR(&msg);
2231 cmsg->cmsg_level = SOL_SOCKET;
2232 cmsg->cmsg_type = SCM_RIGHTS;
2233 cmsg->cmsg_len = CMSG_LEN(sizeof(int) * count);
2234
2235 for(i = 0; i < count; i++)
2236 {
2237 ((int *)CMSG_DATA(cmsg))[i] = rb_get_fd(F[i]);
2238 }
2239 msg.msg_controllen = cmsg->cmsg_len;
2240 }
2241 n = sendmsg(rb_get_fd(xF), &msg, MSG_NOSIGNAL);
2242 return n;
2243 }
2244 #else
2245 #ifndef _WIN32
2246 int
2247 rb_recv_fd_buf(rb_fde_t *F, void *data, size_t datasize, rb_fde_t **xF, int nfds)
2248 {
2249 errno = ENOSYS;
2250 return -1;
2251 }
2252
2253 int
2254 rb_send_fd_buf(rb_fde_t *xF, rb_fde_t **F, int count, void *data, size_t datasize, pid_t pid)
2255 {
2256 errno = ENOSYS;
2257 return -1;
2258 }
2259 #endif
2260 #endif