-
-
-static void
-accept_connection(int pfd, void *data)
-{
- static time_t last_oper_notice = 0;
- struct rb_sockaddr_storage sai;
- socklen_t addrlen = sizeof(sai);
- int fd;
- listener_t *listener = data;
- struct ConfItem *aconf;
- char buf[BUFSIZE];
-
- s_assert(listener != NULL);
- if(listener == NULL)
- return;
- /*
- * There may be many reasons for error return, but
- * in otherwise correctly working environment the
- * probable cause is running out of file descriptors
- * (EMFILE, ENFILE or others?). The man pages for
- * accept don't seem to list these as possible,
- * although it's obvious that it may happen here.
- * Thus no specific errors are tested at this
- * point, just assume that connections cannot
- * be accepted until some old is closed first.
- */
-
- fd = rb_accept(listener->fd, (struct sockaddr *)&sai, &addrlen);
- if(fd < 0)
- {
- /* Re-register a new IO request for the next accept .. */
- rb_setselect(listener->fd, FDLIST_SERVICE,
- COMM_SELECT_READ, accept_connection, listener, 0);
- return;
- }
-
- /* This needs to be done here, otherwise we break dlines */
- mangle_mapped_sockaddr((struct sockaddr *)&sai);
-
- /*
- * check for connection limit
- * TBD: this is stupid... either we have a socket or we don't. -nenolod
- */
- if((rb_get_maxconnections() - 10) < fd)
- {
- ++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();
- }
-
- write(fd, "ERROR :All connections in use\r\n", 32);
- rb_close(fd);
- /* Re-register a new IO request for the next accept .. */
- rb_setselect(listener->fd, FDLIST_SERVICE,
- COMM_SELECT_READ, accept_connection, listener, 0);
- return;
- }
-
- /* Do an initial check we aren't connecting too fast or with too many
- * from this IP... */
- aconf = find_dline((struct sockaddr *) &sai, sai.ss_family);
- /* check it wasn't an exempt */
- if (aconf != NULL && (aconf->status & CONF_EXEMPTDLINE) == 0)
- {
- ServerStats->is_ref++;
-
- if(ConfigFileEntry.dline_with_reason)
- {
- if (rb_snprintf(buf, sizeof(buf), "ERROR :*** Banned: %s\r\n", aconf->passwd) >= (sizeof(buf)-1))
- {
- buf[sizeof(buf) - 3] = '\r';
- buf[sizeof(buf) - 2] = '\n';
- buf[sizeof(buf) - 1] = '\0';
- }
- }
- else
- rb_sprintf(buf, "ERROR :You have been D-lined.\r\n");
-
- write(fd, buf, strlen(buf));
- rb_close(fd);
-
- /* Re-register a new IO request for the next accept .. */
- rb_setselect(listener->fd, FDLIST_SERVICE,
- COMM_SELECT_READ, accept_connection, listener, 0);
- return;
- }
-
- ServerStats->is_ac++;
- add_connection(listener, fd, (struct sockaddr *)&sai, aconf ? 1 : 0);
-
- /* Re-register a new IO request for the next accept .. */
- rb_setselect(listener->fd, FDLIST_SERVICE, COMM_SELECT_READ,
- accept_connection, listener, 0);
-}