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