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