コード例 #1
0
ファイル: listener.c プロジェクト: Macs/NeoIRCd
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;
}
コード例 #2
0
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);
}
コード例 #3
0
ファイル: listener.c プロジェクト: jdhore/charybdis
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;
}
コード例 #4
0
static int
inetport(struct Listener *listener)
{
	int fd;
	int opt = 1;

	/*
	 * At first, open a new socket
	 */

	fd = comm_socket(listener->addr.ss_family, SOCK_STREAM, 0, "Listener socket");

#ifdef 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))
		{
			inetntop(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)
		{
			inetntop(AF_INET, &in->sin_addr, listener->vhost, sizeof(listener->vhost));
			listener->name = listener->vhost;
		}
	}


	if(fd == -1)
	{
		report_error("opening listener socket %s:%s",
			     get_listener_name(listener), get_listener_name(listener), errno);
		return 0;
	}
	else if((maxconnections - 10) < fd)
	{
		report_error("no more connections left for listener %s:%s",
			     get_listener_name(listener), get_listener_name(listener), errno);
		comm_close(fd);
		return 0;
	}
	/*
	 * XXX - we don't want to do all this crap for a listener
	 * set_sock_opts(listener);
	 */
	if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt)))
	{
		report_error("setting SO_REUSEADDR for listener %s:%s",
			     get_listener_name(listener), get_listener_name(listener), errno);
		comm_close(fd);
		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(fd, (struct sockaddr *) &listener->addr, GET_SS_LEN(listener->addr)))
	{
		report_error("binding listener socket %s:%s",
			     get_listener_name(listener), get_listener_name(listener), errno);
		comm_close(fd);
		return 0;
	}

	if(listen(fd, RATBOX_SOMAXCONN))
	{
		report_error("listen failed for %s:%s",
			     get_listener_name(listener), get_listener_name(listener), errno);
		comm_close(fd);
		return 0;
	}

	listener->fd = fd;

	/* Listen completion events are READ events .. */

	accept_connection(fd, listener);
	return 1;
}
コード例 #5
0
ファイル: listener.c プロジェクト: Cloudxtreme/ircd-ratbox
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);
}
コード例 #6
0
ファイル: listener.c プロジェクト: Cloudxtreme/ircd-ratbox
static int 
inetport(struct Listener* listener)
{
  struct irc_sockaddr lsin;
  int                fd;
  int                opt = 1;

  /*
   * At first, open a new socket
   */
  fd = comm_open(DEF_FAM, SOCK_STREAM, 0, "Listener socket");

#ifdef IPV6
  if (!IN6_ARE_ADDR_EQUAL((struct in6_addr *)&listener->addr, &in6addr_any))
  {
#else
  if (INADDR_ANY != listener->addr.sins.sin.s_addr)
  {
#endif
    inetntop(DEF_FAM, &IN_ADDR(listener->addr), listener->vhost, HOSTLEN);
    listener->name = listener->vhost;
  }

  if (fd == -1)
  {
    report_error(L_ALL, "opening listener socket %s:%s",
                 get_listener_name(listener), errno);
    return 0;
  }
  else if ((HARD_FDLIMIT - 10) < fd)
  {
    report_error(L_ALL, "no more connections left for listener %s:%s",
                 get_listener_name(listener), errno);
    fd_close(fd);
    return 0;
  }
  /*
   * XXX - we don't want to do all this crap for a listener
   * set_sock_opts(listener);
   */
  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*) &opt, sizeof(opt)))
  {
    report_error(L_ALL, "setting SO_REUSEADDR for listener %s:%s",
                 get_listener_name(listener), errno);
    fd_close(fd);
    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.
   */
  memset(&lsin, 0, sizeof(struct irc_sockaddr));
  S_FAM(lsin) = DEF_FAM;
  copy_s_addr(S_ADDR(lsin), IN_ADDR(listener->addr));
  S_PORT(lsin) = htons(listener->port);


  if (bind(fd, (struct sockaddr*) &SOCKADDR(lsin),
      sizeof(struct irc_sockaddr)))
  {
    report_error(L_ALL, "binding listener socket %s:%s",
                 get_listener_name(listener), errno);
    fd_close(fd);
    return 0;
  }

  if (listen(fd, HYBRID_SOMAXCONN)) {
    report_error(L_ALL, "listen failed for %s:%s",
                 get_listener_name(listener), errno);
    fd_close(fd);
    return 0;
  }

  /*
   * XXX - this should always work, performance will suck if it doesn't
   */
  if (!set_non_blocking(fd))
    report_error(L_ALL, NONB_ERROR_MSG, get_listener_name(listener), errno);

  listener->fd = fd;

  /* Listen completion events are READ events .. */

  accept_connection(fd, listener);
  return 1;
}

static struct Listener* 
find_listener(int port, struct irc_inaddr *addr)
{
  struct Listener* listener = NULL;
  struct Listener* last_closed = NULL;

  for (listener = ListenerPollList; listener; listener = listener->next)
  {

    if ( (port == listener->port) &&
         (!memcmp(&PIN_ADDR(addr),
                 &IN_ADDR(listener->addr),
                 sizeof(struct irc_inaddr))))
    {
      /* Try to return an open listener, otherwise reuse a closed one */
      if (listener->fd == -1)
        last_closed = listener;
      else
        return listener;
    }
  }
  return last_closed;
}


/*
 * add_listener- create a new listener
 * port - the port number to listen on
 * vhost_ip - if non-null must contain a valid IP address string in
 * the format "255.255.255.255"
 */
void 
add_listener(int port, const char* vhost_ip)
{
  struct Listener* listener;
  struct irc_inaddr   vaddr;

  /*
   * if no port in conf line, don't bother
   */
  if (port == 0)
    return;

#ifdef IPV6
  copy_s_addr(IN_ADDR(vaddr), &in6addr_any);
#else
  copy_s_addr(IN_ADDR(vaddr), INADDR_ANY);
#endif

  if (vhost_ip)
  {
    if(inetpton(DEF_FAM, vhost_ip, &IN_ADDR(vaddr)) <= 0)
      return;
  }

  if ((listener = find_listener(port, &vaddr)))
  {
    if (listener->fd > -1)
      return;
  }
  else
  {
    listener = make_listener(port, &vaddr);
    listener->next = ListenerPollList;
    ListenerPollList = listener;
  }

  listener->fd = -1;

  if (inetport(listener))
    listener->active = 1;
  else
    close_listener(listener);
}

/*
 * close_listener - close a single listener
 */
void close_listener(struct Listener* listener)
{
  assert(listener != NULL);
  if(listener == NULL)
    return;
  if (listener->fd >= 0)
  {
    fd_close(listener->fd);
    listener->fd = -1;
  }

  listener->active = 0;

  if (listener->ref_count)
    return;

  free_listener(listener);
}
コード例 #7
0
ファイル: listener.c プロジェクト: diegoagudo/ptlink.ircd
void accept_connection(struct Listener* listener)
{
  static time_t      last_oper_notice = 0;
  struct SOCKADDR_IN addr;
  socklen_t          addrlen = sizeof(struct SOCKADDR_IN);
  int                fd;

  assert(0 != listener);

  listener->last_accept = CurrentTime;
  /*
   * 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.
   */
  if (-1 == (fd = accept(listener->fd, (struct sockaddr*) &addr, &addrlen))) {
    if (EAGAIN == errno)
       return;
    /*
     * slow down the whining to opers bit
     */
    if((last_oper_notice + 20) <= CurrentTime) {
      report_error("Error accepting connection %s:%s", 
                 listener->name, errno);
      last_oper_notice = CurrentTime;
    }
    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("All connections in use. (%s)", 
                     get_listener_name(listener));
      last_oper_notice = CurrentTime;
    }
    send(fd, "ERROR :All connections in use\r\n", 32, 0);
    CLOSE(fd);
    return;
  }
  /*
   * check to see if listener is shutting down
   */
  if (!listener->active) {
    ++ServerStats->is_ref;
    send(fd, "ERROR :Use another port\r\n", 25, 0);
    CLOSE(fd);
    return;
  }
  /*
   * check conf for ip address access
   */
  if (!conf_connect_allowed(addr.SIN_ADDR)) {
    ServerStats->is_ref++;
#ifdef REPORT_DLINE_TO_USER
     send(fd, "NOTICE DLINE :*** You have been D-lined\r\n", 41, 0);
#endif
    CLOSE(fd);
    return;
  }
  ServerStats->is_ac++;
  nextping = CurrentTime;
  add_connection(listener, fd);
}
コード例 #8
0
ファイル: listener.c プロジェクト: diegoagudo/ptlink.ircd
static int inetport(struct Listener* listener)
{
  struct SOCKADDR_IN port_sin;
  int                fd;
  int                opt = 1;

  /*
   * At first, open a new socket
   */
  fd = socket(AFINET, SOCK_STREAM, 0);

  if (-1 == fd) {
    report_error("opening listener socket %s:%s", 
                 get_listener_name(listener), errno);
    return 0;
  }
  else if ((HARD_FDLIMIT - 10) < fd) {
    report_error("no more connections left for listener %s:%s", 
                 get_listener_name(listener), errno);
    CLOSE(fd);
    return 0;
  }
  /* 
   * XXX - we don't want to do all this crap for a listener
   * set_sock_opts(listener);
   */ 
  if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*) &opt, sizeof(opt))) {
    report_error("setting SO_REUSEADDR for listener %s:%s", 
                 get_listener_name(listener), errno);
    CLOSE(fd);
    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.
   */
  memset(&port_sin, 0, sizeof(port_sin));
  port_sin.SIN_FAMILY = AFINET;
  port_sin.SIN_PORT   = htons(listener->port);
#ifdef __CYGWIN__
  port_sin.sin_addr   = listener->addr;
  
  if (INADDR_ANY != listener->addr.S_ADDR) {
    strncpy_irc(listener->vhost, inetntoa((char *)&listener->addr), HOSTLEN);
    listener->name = listener->vhost;
  }
  
#else
#ifdef IPV6
  bcopy((const char*)listener->addr.S_ADDR, (char*)port_sin.SIN_ADDR.S_ADDR, sizeof(struct IN_ADDR));
  if ( bcmp((char*)listener->addr.S_ADDR, &INADDRANY, sizeof(struct IN_ADDR)) == 0 ) 
#else
  port_sin.sin_addr   = listener->addr;
  if (INADDRANY != listener->addr.s_addr) 
#endif      
  {
 	struct addrinfo *ans;
	int ret;
        char port[5];
	char tmp[HOSTLEN];
      	/*
     	 * XXX - blocking call to getaddrinfo
         */
	sprintf( port, "%d", listener->port);
#ifdef IPV6
	inetntop(AFINET, &listener->addr, tmp, HOSTLEN);
#else
	inet_ntop(AF_INET, &listener->addr, tmp, HOSTLEN);
#endif
	ret = getaddrinfo(tmp, port, NULL, &ans );
	if( ret == 0  && ans->ai_canonname)
	  strncpy_irc(listener->vhost, ans->ai_canonname, HOSTLEN);
    }

#endif
                 
  if (bind(fd, (struct sockaddr*) &port_sin, sizeof(port_sin))) {
    report_error("binding listener socket %s:%s", 
                 get_listener_name(listener), errno);
    CLOSE(fd);
    return 0;
  }

  if (listen(fd, HYBRID_SOMAXCONN)) {
    report_error("listen failed for %s:%s", 
                 get_listener_name(listener), errno);
    CLOSE(fd);
    return 0;
  }

  /*
   * XXX - this should always work, performance will suck if it doesn't
   */
  if (!set_non_blocking(fd))
    report_error(NONB_ERROR_MSG, get_listener_name(listener), errno);

  listener->fd = fd;

  return 1;
}