Beispiel #1
0
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);
}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
}
Beispiel #4
0
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);
}
Beispiel #5
0
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;
}
Beispiel #6
0
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);
		}
	}
}
Beispiel #7
0
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);
}
Beispiel #8
0
/*
 * 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);
}
Beispiel #9
0
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;
}
Beispiel #10
0
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;
}
Beispiel #11
0
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;
}
Beispiel #12
0
void _fat_close(struct vfs_file_s *file)
{
	int fd = (int)file->priv[0];
	rb_close(fd);
}
Beispiel #13
0
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;
}