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