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