Example #1
0
void
accept_connection()
{
  struct sockaddr_in peer;
  struct sockaddr_in me;
  int fd;

  if ((fd = comm_accept(theHttpConnection, &peer, &me)) < 0) {
    char err[200];
    if (errno == EMFILE) {
      sprintf(err, "SDKtest_server: accept_connection accept failure (current fd limit = %d)", fd_limit);
    } else {
      sprintf(err, "SDKtest_server: accept_connection accept failure");
    }
    perror(err);
    return;
  }

  if (fd >= max_users) {
    fprintf(stderr, "Error : too many simultaneous connections. \n");
    printf("Error : too many simultaneous connections. \n");
    exit(-1);
  }

  BIGGEST_FD = max(BIGGEST_FD, fd);
  fd_table[fd].state = READABLE;
  fd_table[fd].read_offset = 0;
  fd_table[fd].keepalive = 0;
  fd_table[fd].keepalive_requests = 0;
  fd_table[fd].inbufptr = fd_table[fd].inbuf;
}
static void
accept_connection(int pfd, void *data)
{
	static time_t last_oper_notice = 0;

	struct irc_sockaddr_storage sai;
	socklen_t addrlen = sizeof(sai);
	int fd;
	struct Listener *listener = data;
	struct ConfItem *aconf;
	char buf[BUFSIZE];

	s_assert(listener != NULL);
	if(listener == NULL)
		return;


	for(;;)			/* loop until something breaks us out */
	{

		/*
		 * 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 = comm_accept(listener->fd, (struct sockaddr *) &sai, &addrlen);

		/* This needs to be done here, otherwise we break dlines */
		mangle_mapped_sockaddr((struct sockaddr *) &sai);

		if(fd < 0)
		{
			/* Re-register a new IO request for the next accept .. */
			comm_setselect(listener->fd, FDLIST_SERVICE,
				       COMM_SELECT_READ, accept_connection, listener);
			return;
		}
		/*
		 * check for connection limit
		 */
		if((maxconnections - 10) < fd)
		{
			++ServerStats->is_ref;
			/*
			 * slow down the whining to opers bit
			 */
			if((last_oper_notice + 20) <= CurrentTime)
			{
				sendto_realops_flags(UMODE_ALL, L_ALL,
						     "All connections in use. (%s)",
						     get_listener_name(listener));
				last_oper_notice = CurrentTime;
			}

			write(fd, "ERROR :All connections in use\r\n", 32);
			comm_close(fd);
			/* Re-register a new IO request for the next accept .. */
			comm_setselect(listener->fd, FDLIST_SERVICE,
				       COMM_SELECT_READ, accept_connection, listener);
			return;
		}

		/* Do an initial check we aren't connecting too fast or with too many
		 * from this IP... */
		if((aconf = conf_connect_allowed((struct sockaddr *) &sai, sai.ss_family)) != NULL)
		{
			ServerStats->is_ref++;

			if(ConfigFileEntry.dline_with_reason)
			{
				if(ircsnprintf
				   (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
				ircsprintf(buf, "ERROR :You have been D-lined.\r\n");

			write(fd, buf, strlen(buf));
			comm_close(fd);

			/* Re-register a new IO request for the next accept .. */
			comm_setselect(listener->fd, FDLIST_SERVICE,
				       COMM_SELECT_READ, accept_connection, listener);
			return;
		}

		ServerStats->is_ac++;
		add_connection(listener, fd, (struct sockaddr *) &sai);

	}
	/* Re-register a new IO request for the next accept .. */
	comm_setselect(listener->fd, FDLIST_SERVICE, COMM_SELECT_READ,
		       accept_connection, listener);
}
Example #3
0
static void 
accept_connection(int pfd, void *data)
{
  static time_t      last_oper_notice = 0;

  struct irc_sockaddr sai;
  struct irc_inaddr addr;
  int                fd;
  int pe;
  struct Listener *  listener = data;

  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 = comm_accept(listener->fd, &sai);

  copy_s_addr(IN_ADDR(addr), S_ADDR(sai));

#ifdef IPV6
  if((IN6_IS_ADDR_V4MAPPED(&IN_ADDR2(addr))) ||
  	(IN6_IS_ADDR_V4COMPAT(&IN_ADDR2(addr))))
  {
    memmove(&addr.sins.sin.s_addr, addr.sins.sin6.s6_addr+12,
            sizeof(struct in_addr));

    sai.sins.sin.sin_family = AF_INET;
  }
#endif

  if (fd < 0)
    {
      /* Re-register a new IO request for the next accept .. */
      comm_setselect(listener->fd, FDLIST_SERVICE, COMM_SELECT_READ,
                     accept_connection, listener, 0);
      return;
    }
  /*
   * check for connection limit
   */
  if ((MAXCONNECTIONS - 10) < fd)
    {
      ++ServerStats->is_ref;
      /*
       * slow down the whining to opers bit
       */
      if((last_oper_notice + 20) <= CurrentTime)
	{
	  sendto_realops_flags(UMODE_ALL, L_ALL,"All connections in use. (%s)",
			       get_listener_name(listener));
	  last_oper_notice = CurrentTime;
	}

      send(fd, "ERROR :All connections in use\r\n", 32, 0);
      fd_close(fd);
      /* Re-register a new IO request for the next accept .. */
      comm_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... */
  if ((pe = conf_connect_allowed(&addr, sai.sins.sin.sin_family)) != 0)
  {
    ServerStats->is_ref++;

    /* XXX - this can only be BANNED_CLIENT? */
    switch (pe)
    {
      case BANNED_CLIENT:
        send(fd, DLINE_WARNING, sizeof(DLINE_WARNING)-1, 0);
        break;
    }

    fd_close(fd);

    /* Re-register a new IO request for the next accept .. */
    comm_setselect(listener->fd, FDLIST_SERVICE, COMM_SELECT_READ,
                   accept_connection, listener, 0);
    return;
  }

  ServerStats->is_ac++;

  add_connection(listener, fd);

  /* Re-register a new IO request for the next accept .. */
  comm_setselect(listener->fd, FDLIST_SERVICE, COMM_SELECT_READ,
    accept_connection, listener, 0);
}