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