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