static void rb_read_timerfd(rb_fde_t *F, void *data) { struct ev_entry *event = (struct ev_entry *)data; int retlen; uint64_t count; if(event == NULL) { rb_close(F); return; } retlen = rb_read(F, &count, sizeof(count)); if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno))) { rb_close(F); rb_lib_log("rb_read_timerfd: timerfd[%s] closed on error: %s", event->name, strerror(errno)); return; } rb_setselect(F, RB_SELECT_READ, rb_read_timerfd, event); rb_run_event(event); }
void rb_helper_close(rb_helper *helper) { if(helper == NULL) return; rb_kill(helper->pid, SIGKILL); rb_close(helper->ifd); rb_close(helper->ofd); rb_free(helper); }
static void accept_ssld(rb_fde_t *F, struct sockaddr *addr, struct sockaddr *laddr, struct Listener *listener) { ssl_ctl_t *ctl; rb_fde_t *xF[2]; if(rb_socketpair(AF_UNIX, SOCK_STREAM, 0, &xF[0], &xF[1], "Incoming ssld Connection") == -1) { ilog_error("creating SSL/TLS socket pairs"); rb_close(F); return; } ctl = start_ssld_accept(F, xF[1], rb_get_fd(xF[0])); /* this will close F for us */ add_connection(listener, xF[0], addr, laddr, ctl); }
static void rb_ssl_setup_client_context(rb_fde_t *F) { int ret; mbedtls_ssl_init(SSL_P(ssl)); if ((ret = mbedtls_ssl_setup(SSL_P(F), &F->sctx->config)) != 0) { rb_lib_log("rb_ssl_setup_client_context: failed to set up ssl context: -0x%x", -ret); rb_close(F); return; } mbedtls_ssl_set_bio(SSL_P(ssl), F, rb_ssl_write_cb, rb_ssl_read_cb, NULL); }
void rb_epoll_unsched_event(struct ev_entry *event) { #ifdef USE_TIMERFD_CREATE if(can_do_timerfd) { rb_close((rb_fde_t *)event->comm_ptr); event->comm_ptr = NULL; return; } #endif timer_delete(*((timer_t *) event->comm_ptr)); rb_free(event->comm_ptr); event->comm_ptr = NULL; }
static void signalfd_handler(rb_fde_t *F, void *data) { static struct our_signalfd_siginfo fdsig[SIGFDIOV_COUNT]; static struct iovec iov[SIGFDIOV_COUNT]; struct ev_entry *ev; int ret, x; for(x = 0; x < SIGFDIOV_COUNT; x++) { iov[x].iov_base = &fdsig[x]; iov[x].iov_len = sizeof(struct our_signalfd_siginfo); } while(1) { ret = readv(rb_get_fd(F), iov, SIGFDIOV_COUNT); if(ret == 0 || (ret < 0 && !rb_ignore_errno(errno))) { rb_close(F); rb_epoll_init_event(); return; } if(ret < 0) { rb_setselect(F, RB_SELECT_READ, signalfd_handler, NULL); return; } for(x = 0; x < ret / (int)sizeof(struct our_signalfd_siginfo); x++) { #if __WORDSIZE == 32 && defined(__sparc__) uint32_t *q = (uint32_t *)&fdsig[x].svptr; ev = (struct ev_entry *)q[0]; #else ev = (struct ev_entry *)(uintptr_t)(fdsig[x].svptr); #endif if(ev == NULL) continue; rb_run_event(ev); } } }
static void accept_callback(rb_fde_t *F, int status, struct sockaddr *addr, rb_socklen_t addrlen, void *data) { struct Listener *listener = data; struct rb_sockaddr_storage lip; unsigned int locallen = sizeof(struct rb_sockaddr_storage); ServerStats.is_ac++; if(getsockname(rb_get_fd(F), (struct sockaddr *) &lip, &locallen) < 0) { /* this can fail if the connection disappeared in the meantime */ rb_close(F); return; } add_connection(listener, F, addr, (struct sockaddr *)&lip); }
/* * close_listener - close a single listener */ void close_listener(struct Listener *listener) { s_assert(listener != NULL); if(listener == NULL) return; if(listener->F != NULL) { rb_close(listener->F); listener->F = NULL; } listener->active = 0; if(listener->ref_count) return; free_listener(listener); }
static int accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, void *data) { struct Listener *listener = (struct Listener *)data; char buf[BUFSIZE]; struct ConfItem *aconf; static time_t last_oper_notice = 0; int len; if(listener->ssl && (!ssl_ok || !get_ssld_count())) { rb_close(F); return 0; } if((maxconnections - 10) < rb_get_fd(F)) /* XXX this is kinda bogus */ { ++ServerStats.is_ref; /* * slow down the whining to opers bit */ if((last_oper_notice + 20) <= rb_current_time()) { sendto_realops_snomask(SNO_GENERAL, L_ALL, "All connections in use. (%s)", get_listener_name(listener)); last_oper_notice = rb_current_time(); } rb_write(F, "ERROR :All connections in use\r\n", 32); rb_close(F); /* Re-register a new IO request for the next accept .. */ return 0; } aconf = find_dline(addr, addr->sa_family); if(aconf != NULL && (aconf->status & CONF_EXEMPTDLINE)) return 1; /* Do an initial check we aren't connecting too fast or with too many * from this IP... */ if(aconf != NULL) { ServerStats.is_ref++; if(ConfigFileEntry.dline_with_reason) { len = rb_snprintf(buf, sizeof(buf), "ERROR :*** Banned: %s\r\n", get_user_ban_reason(aconf)); if (len >= (int)(sizeof(buf)-1)) { buf[sizeof(buf) - 3] = '\r'; buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 1] = '\0'; } } else strcpy(buf, "ERROR :You have been D-lined.\r\n"); rb_write(F, buf, strlen(buf)); rb_close(F); return 0; } if(check_reject(F, addr)) return 0; if(throttle_add(addr)) { rb_write(F, toofast, strlen(toofast)); rb_close(F); return 0; } return 1; }
static int inetport(struct Listener *listener) { rb_fde_t *F; int ret; int opt = 1; /* * At first, open a new socket */ F = rb_socket(GET_SS_FAMILY(&listener->addr), SOCK_STREAM, 0, "Listener socket"); #ifdef RB_IPV6 if(listener->addr.ss_family == AF_INET6) { struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&listener->addr; if(!IN6_ARE_ADDR_EQUAL(&in6->sin6_addr, &in6addr_any)) { rb_inet_ntop(AF_INET6, &in6->sin6_addr, listener->vhost, sizeof(listener->vhost)); listener->name = listener->vhost; } } else #endif { struct sockaddr_in *in = (struct sockaddr_in *)&listener->addr; if(in->sin_addr.s_addr != INADDR_ANY) { rb_inet_ntop(AF_INET, &in->sin_addr, listener->vhost, sizeof(listener->vhost)); listener->name = listener->vhost; } } if(F == NULL) { ilog_error("opening listener socket"); return 0; } else if((maxconnections - 10) < rb_get_fd(F)) /* XXX this is kinda bogus*/ { ilog_error("no more connections left for listener"); rb_close(F); return 0; } /* * XXX - we don't want to do all this crap for a listener * set_sock_opts(listener); */ if(setsockopt(rb_get_fd(F), SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt))) { ilog_error("setting SO_REUSEADDR for listener"); rb_close(F); return 0; } /* * Bind a port to listen for new connections if port is non-null, * else assume it is already open and try get something from it. */ if(bind(rb_get_fd(F), (struct sockaddr *) &listener->addr, GET_SS_LEN(&listener->addr))) { ilog_error("binding listener socket"); rb_close(F); return 0; } if((ret = rb_listen(F, RATBOX_SOMAXCONN))) { ilog_error("listen()"); rb_close(F); return 0; } listener->F = F; rb_accept_tcp(listener->F, accept_precallback, accept_callback, listener); return 1; }
static int inetport(struct Listener *listener) { rb_fde_t *F; int opt = 1; const char *errstr; /* * At first, open a new socket */ F = rb_socket(GET_SS_FAMILY(&listener->addr), SOCK_STREAM, 0, "Listener socket"); #ifdef RB_IPV6 if(listener->addr.ss_family == AF_INET6) { struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&listener->addr; if(!IN6_ARE_ADDR_EQUAL(&in6->sin6_addr, &in6addr_any)) { rb_inet_ntop(AF_INET6, &in6->sin6_addr, listener->vhost, sizeof(listener->vhost)); listener->name = listener->vhost; } } else #endif { struct sockaddr_in *in = (struct sockaddr_in *)&listener->addr; if(in->sin_addr.s_addr != INADDR_ANY) { rb_inet_ntop(AF_INET, &in->sin_addr, listener->vhost, sizeof(listener->vhost)); listener->name = listener->vhost; } } if(F == NULL) { sendto_realops_snomask(SNO_GENERAL, L_ALL, "Cannot open socket for listener on port %d", get_listener_port(listener)); ilog(L_MAIN, "Cannot open socket for listener %s", get_listener_name(listener)); return 0; } else if((maxconnections - 10) < rb_get_fd(F)) /* XXX this is kinda bogus*/ { ilog_error("no more connections left for listener"); sendto_realops_snomask(SNO_GENERAL, L_ALL, "No more connections left for listener on port %d", get_listener_port(listener)); ilog(L_MAIN, "No more connections left for listener %s", get_listener_name(listener)); rb_close(F); return 0; } /* * XXX - we don't want to do all this crap for a listener * set_sock_opts(listener); */ if(setsockopt(rb_get_fd(F), SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt))) { errstr = strerror(rb_get_sockerr(F)); sendto_realops_snomask(SNO_GENERAL, L_ALL, "Cannot set SO_REUSEADDR for listener on port %d: %s", get_listener_port(listener), errstr); ilog(L_MAIN, "Cannot set SO_REUSEADDR for listener %s: %s", get_listener_name(listener), errstr); rb_close(F); return 0; } /* * Bind a port to listen for new connections if port is non-null, * else assume it is already open and try get something from it. */ if(bind(rb_get_fd(F), (struct sockaddr *) &listener->addr, GET_SS_LEN(&listener->addr))) { errstr = strerror(rb_get_sockerr(F)); sendto_realops_snomask(SNO_GENERAL, L_ALL, "Cannot bind for listener on port %d: %s", get_listener_port(listener), errstr); ilog(L_MAIN, "Cannot bind for listener %s: %s", get_listener_name(listener), errstr); rb_close(F); return 0; } if(rb_listen(F, CHARYBDIS_SOMAXCONN, listener->defer_accept)) { errstr = strerror(rb_get_sockerr(F)); sendto_realops_snomask(SNO_GENERAL, L_ALL, "Cannot listen() for listener on port %d: %s", get_listener_port(listener), errstr); ilog(L_MAIN, "Cannot listen() for listener %s: %s", get_listener_name(listener), errstr); rb_close(F); return 0; } listener->F = F; rb_accept_tcp(listener->F, accept_precallback, accept_callback, listener); return 1; }
void _fat_close(struct vfs_file_s *file) { int fd = (int)file->priv[0]; rb_close(fd); }
rb_helper * rb_helper_start(const char *name, const char *fullpath, rb_helper_cb * read_cb, rb_helper_cb * error_cb) { rb_helper *helper; const char *parv[2]; char buf[128]; char fx[16], fy[16]; rb_fde_t *in_f[2]; rb_fde_t *out_f[2]; pid_t pid; if(access(fullpath, X_OK) == -1) return NULL; helper = rb_malloc(sizeof(rb_helper)); snprintf(buf, sizeof(buf), "%s helper - read", name); if(rb_pipe(&in_f[0], &in_f[1], buf) < 0) { rb_free(helper); return NULL; } snprintf(buf, sizeof(buf), "%s helper - write", name); if(rb_pipe(&out_f[0], &out_f[1], buf) < 0) { rb_free(helper); return NULL; } snprintf(fx, sizeof(fx), "%d", rb_get_fd(in_f[1])); snprintf(fy, sizeof(fy), "%d", rb_get_fd(out_f[0])); rb_set_nb(in_f[0]); rb_set_nb(in_f[1]); rb_set_nb(out_f[0]); rb_set_nb(out_f[1]); rb_setenv("IFD", fy, 1); rb_setenv("OFD", fx, 1); rb_setenv("MAXFD", "256", 1); snprintf(buf, sizeof(buf), "-ircd %s daemon", name); parv[0] = buf; parv[1] = NULL; #ifdef _WIN32 SetHandleInformation((HANDLE) rb_get_fd(in_f[1]), HANDLE_FLAG_INHERIT, 1); SetHandleInformation((HANDLE) rb_get_fd(out_f[0]), HANDLE_FLAG_INHERIT, 1); #endif pid = rb_spawn_process(fullpath, (const char **)parv); if(pid == -1) { rb_close(in_f[0]); rb_close(in_f[1]); rb_close(out_f[0]); rb_close(out_f[1]); rb_free(helper); return NULL; } rb_close(in_f[1]); rb_close(out_f[0]); rb_linebuf_newbuf(&helper->sendq); rb_linebuf_newbuf(&helper->recvq); helper->ifd = in_f[0]; helper->ofd = out_f[1]; helper->read_cb = read_cb; helper->error_cb = error_cb; helper->fork_count = 0; helper->pid = pid; return helper; }