示例#1
0
/** Apply GeoIP country data to a client.
 * @param[in] cptr Client to apply GeoIP country data to.
 */
void geoip_apply(struct Client* cptr)
{
#ifdef USE_GEOIP
  int gcid = 0;
#endif /* USE_GEOIP */
#ifdef USE_GEOIP_GL
  GeoIPLookup gl;
#endif /* USE_GEOIP_GL */

  if (!feature_bool(FEAT_GEOIP_ENABLE))
    return;

  if (!(cptr))
    return;

#ifdef USE_GEOIP
  if (irc_in_addr_is_ipv4(&cli_ip(cptr))) {
    /* User is IPv4 so use gi4. */
    if (gi4 != NULL)
#ifdef USE_GEOIP_GL
      gcid = GeoIP_id_by_addr_gl(gi4, cli_sock_ip(cptr), &gl);
#else
      gcid = GeoIP_id_by_addr(gi4, cli_sock_ip(cptr));
#endif /* USE_GEOIP_GL */
  } else {
    /* User is IPv6 so use gi6. */
    if (gi6 != NULL)
#ifdef USE_GEOIP_GL
      gcid = GeoIP_id_by_addr_v6_gl(gi6, cli_sock_ip(cptr), &gl);
#else
      gcid = GeoIP_id_by_addr_v6(gi6, cli_sock_ip(cptr));
#endif /* USE_GEOIP_GL */
  }
#endif /* USE_GEOIP */

#ifdef USE_GEOIP
  if (gcid == 0) {
#endif /* USE_GEOIP */
    ircd_strncpy((char *)&cli_countrycode(cptr), "--", 3);
    ircd_strncpy((char *)&cli_countryname(cptr), "Unknown", 8);
    ircd_strncpy((char *)&cli_continentcode(cptr), "--", 3);
    ircd_strncpy((char *)&cli_continentname(cptr), "Unknown", 8);
#ifdef USE_GEOIP
  } else {
    ircd_strncpy((char *)&cli_countrycode(cptr), GeoIP_code_by_id(gcid), 3);
    ircd_strncpy((char *)&cli_countryname(cptr), GeoIP_name_by_id(gcid), 256);
    ircd_strncpy((char *)&cli_continentcode(cptr), GeoIP_continent_by_id(gcid), 3);
    ircd_strncpy((char *)&cli_continentname(cptr), geoip_continent_name_by_code(GeoIP_continent_by_id(gcid)), 256);
  }
#endif /* USE_GEOIP */

  SetGeoIP(cptr);
}
示例#2
0
/** Find a matching Z-line for a user.
 * @param[in] cptr Client to compare against.
 * @param[in] flags Bitwise combination of ZLINE_GLOBAL and/or
 * ZLINE_LASTMOD to limit matches.
 * @return Matching Z-line, or NULL if none are found.
 */
struct Zline *
zline_lookup(struct Client *cptr, unsigned int flags)
{
  struct Zline *zline;
  struct Zline *szline;

  if (find_except_conf(cptr, EFLAG_ZLINE))
    return 0;

  zliter(GlobalZlineList, zline, szline) {
    if ((flags & ZLINE_GLOBAL && zline->zl_flags & ZLINE_LOCAL) ||
        (flags & ZLINE_LASTMOD && !zline->zl_lastmod))
      continue;

    if (ZlineIsIpMask(zline)) {
      if (!irc_in_addr_type_cmp(&cli_ip(cptr), &zline->zl_addr) && zline->zl_bits)
        continue;
      if (!ipmask_check(&cli_ip(cptr), &zline->zl_addr, zline->zl_bits))
        continue;
    }
    else {
      if (match(zline->zl_mask, cli_sock_ip(cptr)) != 0)
        continue;
    }
    if (ZlineIsActive(zline))
      return zline;
  }
  /*
   * No Zlines matched
   */
  return 0;
}
/** Return the name of the client for various tracking and admin
 * purposes. The main purpose of this function is to return the
 * "socket host" name of the client, if that differs from the
 * advertised name (other than case).  But, this can be used on any
 * client structure.
 * @param sptr Client to operate on.
 * @param showip If non-zero, append [username\@text-ip] to name.
 * @return Either cli_name(\a sptr) or a static buffer.
 */
const char* get_client_name(const struct Client* sptr, int showip)
{
  static char nbuf[HOSTLEN * 2 + USERLEN + 5];

  if (!MyConnect(sptr) || !showip)
    return cli_name(sptr);
  ircd_snprintf(0, nbuf, sizeof(nbuf), "%s[%s@%s]", cli_name(sptr),
                IsIdented(sptr) ? cli_username(sptr) : "",
                cli_sock_ip(sptr));
  return nbuf;
}
示例#4
0
/** Check local clients against a new Z-line.
 * If the Z-line is inactive, return immediately.
 * Otherwise, if any users match it, disconnect them.
 * @param[in] cptr Peer connect that sent the Z-line.
 * @param[in] sptr Client that originated the Z-line.
 * @param[in] zline New Z-line to check.
 * @return Zero, unless \a sptr Z-lined himself, in which case CPTR_KILLED.
 */
static int
do_zline(struct Client *cptr, struct Client *sptr, struct Zline *zline)
{
  struct Client *acptr;
  int fd, retval = 0, tval;

  if (feature_bool(FEAT_DISABLE_ZLINES))
    return 0; /* Z-lines are disabled */

  if (!ZlineIsActive(zline)) /* no action taken on inactive zlines */
    return 0;

  for (fd = HighestFd; fd >= 0; --fd) {
    /*
     * get the users!
     */
    if ((acptr = LocalClientArray[fd])) {
      if (!cli_user(acptr))
	continue;

      if (find_except_conf(acptr, EFLAG_ZLINE))
        continue;

      /* IP zline */
      if (ZlineIsIpMask(zline)) {
        if (!irc_in_addr_type_cmp(&cli_ip(acptr), &zline->zl_addr) && zline->zl_bits)
          continue;
        if (!ipmask_check(&cli_ip(acptr), &zline->zl_addr, zline->zl_bits))
          continue;
      }
      else {
        if (match(zline->zl_mask, cli_sock_ip(acptr)) != 0)
          continue;
      }

      /* ok, here's one that got Z-lined */
      send_reply(acptr, SND_EXPLICIT | ERR_YOUREBANNEDCREEP, ":%s",
      	   zline->zl_reason);

      /* let the ops know about it */
      sendto_opmask_butone_global(&me, SNO_GLINE, "Z-line active for %s",
                           get_client_name(acptr, SHOW_IP));

      /* and get rid of him */
      if ((tval = exit_client_msg(cptr, acptr, &me, "Z-lined%s%s%s",
          (!feature_bool(FEAT_HIS_ZLINE_REASON) ? " (" : ""),
          (!feature_bool(FEAT_HIS_ZLINE_REASON) ? zline->zl_reason : ""),
          (!feature_bool(FEAT_HIS_ZLINE_REASON) ? ")" : ""))))
        retval = tval; /* retain killed status */
    }
  }
  return retval;
}
/*
 * release_auth_client - release auth client from auth system
 * this adds the client into the local client lists so it can be read by
 * the main io processing loop
 */
static void release_auth_client(struct Client* client)
{
  assert(0 != client);
  cli_auth(client) = 0;
  cli_lasttime(client) = cli_since(client) = CurrentTime;
  if (cli_fd(client) > HighestFd)
    HighestFd = cli_fd(client);
  LocalClientArray[cli_fd(client)] = client;

  add_client_to_list(client);
  socket_events(&(cli_socket(client)), SOCK_ACTION_SET | SOCK_EVENT_READABLE);
  Debug((DEBUG_INFO, "Auth: release_auth_client %s@%s[%s]",
         cli_username(client), cli_sockhost(client), cli_sock_ip(client)));
}
示例#6
0
文件: m_server.c 项目: mojadita/ircd
/** Handle a SERVER message from an unregistered connection.
 *
 * \a parv has the following elements:
 * \li \a parv[1] is the server name
 * \li \a parv[2] is the hop count to the server
 * \li \a parv[3] is the start timestamp for the server
 * \li \a parv[4] is the link timestamp
 * \li \a parv[5] is the protocol version (P10 or J10)
 * \li \a parv[6] is the numnick mask for the server
 * \li \a parv[7] is a string of flags like +hs to mark hubs and services
 * \li \a parv[\a parc - 1] is the server description
 *
 * See @ref m_functions for discussion of the arguments.
 * @param[in] cptr Client that sent us the message.
 * @param[in] sptr Original source of message.
 * @param[in] parc Number of arguments.
 * @param[in] parv Argument vector.
 */
int mr_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  char*            host;
  struct ConfItem* aconf;
  struct Jupe*     ajupe;
  unsigned int     hop;
  int              ret;
  unsigned short   prot;
  time_t           start_timestamp;
  time_t           timestamp;
  time_t           recv_time;
  time_t           ghost;

  if (IsUserPort(cptr))
    return exit_client_msg(cptr, cptr, &me,
                           "Cannot connect a server to a user port");

  if (parc < 8)
  {
    need_more_params(sptr, "SERVER");
    return exit_client(cptr, cptr, &me, "Need more parameters");
  }
  host = clean_servername(parv[1]);
  if (!host)
  {
    sendto_opmask(0, SNO_OLDSNO, "Bogus server name (%s) from %s",
                  host, cli_name(cptr));
    return exit_client_msg(cptr, cptr, &me, "Bogus server name (%s)", host);
  }

  if ((ajupe = jupe_find(host)) && JupeIsActive(ajupe))
    return exit_client_msg(cptr, sptr, &me, "Juped: %s", JupeReason(ajupe));

  /* check connection rules */
  if (0 != conf_eval_crule(host, CRULE_ALL)) {
    ServerStats->is_ref++;
    sendto_opmask(0, SNO_OLDSNO, "Refused connection from %s.", cli_name(cptr));
    return exit_client(cptr, cptr, &me, "Disallowed by connection rule");
  }

  log_write(LS_NETWORK, L_NOTICE, LOG_NOSNOTICE, "SERVER: %s %s[%s]", host,
	    cli_sockhost(cptr), cli_sock_ip(cptr));

  /*
   * Detect protocol
   */
  hop = atoi(parv[2]);
  start_timestamp = atoi(parv[3]);
  timestamp = atoi(parv[4]);
  prot = parse_protocol(parv[5]);
  if (!prot)
    return exit_client_msg(cptr, sptr, &me, "Bogus protocol (%s)", parv[5]);
  else if (prot < atoi(MINOR_PROTOCOL))
    return exit_new_server(cptr, sptr, host, timestamp,
                           "Incompatible protocol: %s", parv[5]);

  Debug((DEBUG_INFO, "Got SERVER %s with timestamp [%s] age %Tu (%Tu)",
	 host, parv[4], start_timestamp, cli_serv(&me)->timestamp));

  if (timestamp < OLDEST_TS || start_timestamp < OLDEST_TS)
    return exit_client_msg(cptr, sptr, &me,
        "Bogus timestamps (%s %s)", parv[3], parv[4]);

  /* If the server had a different name before, change it. */
  if (!EmptyString(cli_name(cptr)) &&
      (IsUnknown(cptr) || IsHandshake(cptr)) &&
      0 != ircd_strcmp(cli_name(cptr), host))
    hChangeClient(cptr, host);
  ircd_strncpy(cli_name(cptr), host, HOSTLEN);
  ircd_strncpy(cli_info(cptr), parv[parc-1][0] ? parv[parc-1] : cli_name(&me), REALLEN);
  cli_hopcount(cptr) = hop;

  if (conf_check_server(cptr)) {
    ++ServerStats->is_ref;
    sendto_opmask(0, SNO_OLDSNO, "Received unauthorized connection from %s",
                  cli_name(cptr));
    log_write(LS_NETWORK, L_NOTICE, LOG_NOSNOTICE, "Received unauthorized "
              "connection from %C [%s]", cptr,
              ircd_ntoa(&cli_ip(cptr)));
    return exit_client(cptr, cptr, &me, "No Connect block");
  }

  host = cli_name(cptr);

  update_load();

  if (!(aconf = find_conf_byname(cli_confs(cptr), host, CONF_SERVER))) {
    ++ServerStats->is_ref;
    sendto_opmask(0, SNO_OLDSNO, "Access denied. No conf line for server %s",
                  cli_name(cptr));
    return exit_client_msg(cptr, cptr, &me,
                           "Access denied. No conf line for server %s", cli_name(cptr));
  }

#if defined(USE_SSL)
  if (!verify_sslclifp(cptr, aconf)) {
    ++ServerStats->is_ref;
    sendto_opmask(0, SNO_OLDSNO, "Access denied (SSL fingerprint mismatch) %s",
                  cli_name(cptr));
    return exit_client_msg(cptr, cptr, &me,
                           "No Access (SSL fingerprint mismatch) %s", cli_name(cptr));
  }
#endif

  if (*aconf->passwd && !!strcmp(aconf->passwd, cli_passwd(cptr))) {
    ++ServerStats->is_ref;
    sendto_opmask(0, SNO_OLDSNO, "Access denied (passwd mismatch) %s",
                  cli_name(cptr));
    return exit_client_msg(cptr, cptr, &me,
                           "No Access (passwd mismatch) %s", cli_name(cptr));
  }

  memset(cli_passwd(cptr), 0, sizeof(cli_passwd(cptr)));

  ret = check_loop_and_lh(cptr, sptr, &ghost, host, (parc > 7 ? parv[6] : NULL), timestamp, hop, 1);
  if (ret != 1)
    return ret;

  make_server(cptr);
  cli_serv(cptr)->timestamp = timestamp;
  cli_serv(cptr)->prot = prot;
  cli_serv(cptr)->ghost = ghost;
  memset(cli_privs(cptr), 255, sizeof(struct Privs));
  ClrPriv(cptr, PRIV_SET);
  SetServerYXX(cptr, cptr, parv[6]);
  update_uworld_flags(cptr);

  if (*parv[7] == '+')
    set_server_flags(cptr, parv[7] + 1);

  recv_time = TStime();
  check_start_timestamp(cptr, timestamp, start_timestamp, recv_time);
  ret = server_estab(cptr, aconf);

  if (feature_bool(FEAT_RELIABLE_CLOCK) &&
      abs(cli_serv(cptr)->timestamp - recv_time) > 30) {
    sendto_opmask(0, SNO_OLDSNO, "Connected to a net with a "
                  "timestamp-clock difference of %Td seconds! "
                  "Used SETTIME to correct this.",
                  timestamp - recv_time);
    sendcmdto_prio_one(&me, CMD_SETTIME, cptr, "%Tu :%s", TStime(),
		       cli_name(&me));
  }

  return ret;
}
/*
 * auth_dns_callback - called when resolver query finishes
 * if the query resulted in a successful search, hp will contain
 * a non-null pointer, otherwise hp will be null.
 * set the client on it's way to a connection completion, regardless
 * of success of failure
 */
static void auth_dns_callback(void* vptr, struct DNSReply* reply)
{
  struct AuthRequest* auth = (struct AuthRequest*) vptr;

  assert(0 != auth);
  /*
   * need to do this here so auth_kill_client doesn't
   * try have the resolver delete the query it's about
   * to delete anyways. --Bleep
   */
  ClearDNSPending(auth);

  if (reply) {
    const struct hostent* hp = reply->hp;
    int i;
    assert(0 != hp);
    /*
     * Verify that the host to ip mapping is correct both ways and that
     * the ip#(s) for the socket is listed for the host.
     */
    for (i = 0; hp->h_addr_list[i]; ++i) {
      if (0 == memcmp(hp->h_addr_list[i], &(cli_ip(auth->client)),
                      sizeof(struct in_addr)))
         break;
    }
    if (!hp->h_addr_list[i]) {
      if (IsUserPort(auth->client))
        sendheader(auth->client, REPORT_IP_MISMATCH);
      sendto_opmask_butone(0, SNO_IPMISMATCH, "IP# Mismatch: %s != %s[%s]",
			   cli_sock_ip(auth->client), hp->h_name, 
			   ircd_ntoa(hp->h_addr_list[0]));
      if (feature_bool(FEAT_KILL_IPMISMATCH)) {
	auth_kill_client(auth);
	return;
      }
    } else if (!auth_verify_hostname(hp->h_name, HOSTLEN)) {
      if (IsUserPort(auth->client))
	sendheader(auth->client, REPORT_INVAL_DNS);
    } else {
      ++reply->ref_count;
      cli_dns_reply(auth->client) = reply;
      ircd_strncpy(cli_sockhost(auth->client), hp->h_name, HOSTLEN);
      if (IsUserPort(auth->client))
        sendheader(auth->client, REPORT_FIN_DNS);
    }
  }
  else {
    /*
     * this should have already been done by s_bsd.c in add_connection
     *
     * strcpy(auth->client->sockhost, auth->client->sock_ip);
     */
    if (IsUserPort(auth->client))
      sendheader(auth->client, REPORT_FAIL_DNS);
  }
  if (!IsDoingAuth(auth)) {
    release_auth_client(auth->client);
    unlink_auth_request(auth, &AuthIncompleteList);
    free_auth_request(auth);
  }
}
示例#8
0
文件: s_bsd.c 项目: mojadita/ircd
void add_connection(struct Listener* listener, int fd, void *ssl) {
#else
void add_connection(struct Listener* listener, int fd) {
#endif
  struct irc_sockaddr addr;
  struct Client      *new_client;
  time_t             next_target = 0;
#if defined(USE_SSL)
  char *sslfp;
#endif

  const char* const throttle_message =
         "ERROR :Your host is trying to (re)connect too fast -- throttled\r\n";
       /* 12345678901234567890123456789012345679012345678901234567890123456 */
  const char* const register_message =
         "ERROR :Unable to complete your registration\r\n";

  assert(0 != listener);

  /*
   * Removed preliminary access check. Full check is performed in m_server and
   * m_user instead. Also connection time out help to get rid of unwanted
   * connections.
   */
  if (!os_get_peername(fd, &addr) || !os_set_nonblocking(fd)) {
    ++ServerStats->is_ref;
#if defined(USE_SSL)
    ssl_murder(ssl, fd, NULL);
#else
    close(fd);
#endif
    return;
  }
  /*
   * Disable IP (*not* TCP) options.  In particular, this makes it impossible
   * to use source routing to connect to the server.  If we didn't do this
   * (and if intermediate networks didn't drop source-routed packets), an
   * attacker could successfully IP spoof us...and even return the anti-spoof
   * ping, because the options would cause the packet to be routed back to
   * the spoofer's machine.  When we disable the IP options, we delete the
   * source route, and the normal routing takes over.
   */
  os_disable_options(fd);

  if (listener_server(listener))
  {
    new_client = make_client(0, STAT_UNKNOWN_SERVER);
  }
  else
  {
    /*
     * Add this local client to the IPcheck registry.
     *
     * If they're throttled, murder them, but tell them why first.
     */
    if (!IPcheck_local_connect(&addr.addr, &next_target))
    {
      ++ServerStats->is_ref;
#if defined(USE_SSL)
      ssl_murder(ssl, fd, throttle_message);
#else
      write(fd, throttle_message, strlen(throttle_message));
      close(fd);
#endif
      return;
    }
    new_client = make_client(0, STAT_UNKNOWN_USER);
    SetIPChecked(new_client);
  }

  /*
   * Copy ascii address to 'sockhost' just in case. Then we have something
   * valid to put into error messages...
   */
  ircd_ntoa_r(cli_sock_ip(new_client), &addr.addr);
  strcpy(cli_sockhost(new_client), cli_sock_ip(new_client));
  memcpy(&cli_ip(new_client), &addr.addr, sizeof(cli_ip(new_client)));

  if (next_target)
    cli_nexttarget(new_client) = next_target;

  cli_fd(new_client) = fd;
  if (!socket_add(&(cli_socket(new_client)), client_sock_callback,
		  (void*) cli_connect(new_client), SS_CONNECTED, 0, fd)) {
    ++ServerStats->is_ref;
#if defined(USE_SSL)
    ssl_murder(ssl, fd, register_message);
#else
    write(fd, register_message, strlen(register_message));
    close(fd);
#endif
    cli_fd(new_client) = -1;
    return;
  }
#if defined(USE_SSL)
  if (ssl) {
    cli_socket(new_client).s_ssl = ssl;
    sslfp = ssl_get_fingerprint(ssl);
    if (sslfp)
      ircd_strncpy(cli_sslclifp(new_client), sslfp, BUFSIZE+1);
  }
#endif
  cli_freeflag(new_client) |= FREEFLAG_SOCKET;
  cli_listener(new_client) = listener;
  ++listener->ref_count;

  Count_newunknown(UserStats);
  /* if we've made it this far we can put the client on the auth query pile */
  start_auth(new_client);
}

/** Determines whether to tell the events engine we're interested in
 * writable events.
 * @param cptr Client for which to decide this.
 */
void update_write(struct Client* cptr)
{
  /* If there are messages that need to be sent along, or if the client
   * is in the middle of a /list, then we need to tell the engine that
   * we're interested in writable events--otherwise, we need to drop
   * that interest.
   */
  socket_events(&(cli_socket(cptr)),
		((MsgQLength(&cli_sendQ(cptr)) || cli_listing(cptr)) ?
		 SOCK_ACTION_ADD : SOCK_ACTION_DEL) | SOCK_EVENT_WRITABLE);
}
示例#9
0
文件: s_bsd.c 项目: mojadita/ircd
/** Set up address and port and make a connection.
 * @param aconf Provides the connection information.
 * @param cptr Client structure for the peer.
 * @return Non-zero on success; zero on failure.
 */
static int connect_inet(struct ConfItem* aconf, struct Client* cptr)
{
  const struct irc_sockaddr *local;
  IOResult result;
  int family = 0;

  assert(0 != aconf);
  assert(0 != cptr);
  /*
   * Might as well get sockhost from here, the connection is attempted
   * with it so if it fails its useless.
   */
  if (irc_in_addr_valid(&aconf->origin.addr))
    local = &aconf->origin;
  else if (irc_in_addr_is_ipv4(&aconf->address.addr)) {
    local = &VirtualHost_v4;
    family = AF_INET;
  } else
    local = &VirtualHost_v6;
  cli_fd(cptr) = os_socket(local, SOCK_STREAM, cli_name(cptr), family);
  if (cli_fd(cptr) < 0)
    return 0;

  /*
   * save connection info in client
   */
  memcpy(&cli_ip(cptr), &aconf->address.addr, sizeof(cli_ip(cptr)));
  ircd_ntoa_r(cli_sock_ip(cptr), &cli_ip(cptr));
  /*
   * we want a big buffer for server connections
   */
  if (!os_set_sockbufs(cli_fd(cptr), feature_int(FEAT_SOCKSENDBUF), feature_int(FEAT_SOCKRECVBUF))) {
    cli_error(cptr) = errno;
    report_error(SETBUFS_ERROR_MSG, cli_name(cptr), errno);
    close(cli_fd(cptr));
    cli_fd(cptr) = -1;
    return 0;
  }
  /*
   * Set the TOS bits - this is nonfatal if it doesn't stick.
   */
  if (!os_set_tos(cli_fd(cptr), feature_int(FEAT_TOS_SERVER))) {
    report_error(TOS_ERROR_MSG, cli_name(cptr), errno);
  }
  if ((result = os_connect_nonb(cli_fd(cptr), &aconf->address)) == IO_FAILURE) {
    cli_error(cptr) = errno;
    report_error(CONNECT_ERROR_MSG, cli_name(cptr), errno);
    close(cli_fd(cptr));
    cli_fd(cptr) = -1;
    return 0;
  }
  if (!socket_add(&(cli_socket(cptr)), client_sock_callback,
		  (void*) cli_connect(cptr),
		  (result == IO_SUCCESS) ? SS_CONNECTED : SS_CONNECTING,
		  SOCK_EVENT_READABLE, cli_fd(cptr))) {
    cli_error(cptr) = ENFILE;
    report_error(REGISTER_ERROR_MSG, cli_name(cptr), ENFILE);
    close(cli_fd(cptr));
    cli_fd(cptr) = -1;
    return 0;
  }
  cli_freeflag(cptr) |= FREEFLAG_SOCKET;
  return 1;
}
示例#10
0
文件: s_bsd.c 项目: Niichan/snircd
/** Creates a client which has just connected to us on the given fd.
 * The sockhost field is initialized with the ip# of the host.
 * The client is not added to the linked list of clients, it is
 * passed off to the auth handler for dns and ident queries.
 * @param listener Listening socket that received the connection.
 * @param fd File descriptor of new connection.
 */
void add_connection(struct Listener* listener, int fd) {
  struct irc_sockaddr addr;
  struct Client      *new_client;
  time_t             next_target = 0;

  const char* const throttle_message =
         "ERROR :Your host is trying to (re)connect too fast -- throttled\r\n";
       /* 12345678901234567890123456789012345679012345678901234567890123456 */
  const char* const register_message =
         "ERROR :Unable to complete your registration\r\n";

  assert(0 != listener);

  /*
   * Removed preliminary access check. Full check is performed in m_server and
   * m_user instead. Also connection time out help to get rid of unwanted
   * connections.
   */
  if (!os_get_peername(fd, &addr) || !os_set_nonblocking(fd)) {
    ++ServerStats->is_ref;
    close(fd);
    return;
  }
  /*
   * Disable IP (*not* TCP) options.  In particular, this makes it impossible
   * to use source routing to connect to the server.  If we didn't do this
   * (and if intermediate networks didn't drop source-routed packets), an
   * attacker could successfully IP spoof us...and even return the anti-spoof
   * ping, because the options would cause the packet to be routed back to
   * the spoofer's machine.  When we disable the IP options, we delete the
   * source route, and the normal routing takes over.
   */
  os_disable_options(fd);

  if (listener_server(listener))
  {
    new_client = make_client(0, STAT_UNKNOWN_SERVER);
  }
  else
  {
    /*
     * Add this local client to the IPcheck registry.
     *
     * If they're throttled, murder them, but tell them why first.
     */
    if (!IPcheck_local_connect(&addr.addr, &next_target))
    {
      ++ServerStats->is_ref;
      write(fd, throttle_message, strlen(throttle_message));
      close(fd);
      return;
    }
    new_client = make_client(0, STAT_UNKNOWN_USER);
    SetIPChecked(new_client);
  }

  /*
   * Copy ascii address to 'sockhost' just in case. Then we have something
   * valid to put into error messages...
   */
  ircd_ntoa_r(cli_sock_ip(new_client), &addr.addr);
  strcpy(cli_sockhost(new_client), cli_sock_ip(new_client));
  memcpy(&cli_ip(new_client), &addr.addr, sizeof(cli_ip(new_client)));

  if (next_target)
    cli_nexttarget(new_client) = next_target;

  cli_fd(new_client) = fd;
  if (!socket_add(&(cli_socket(new_client)), client_sock_callback,
		  (void*) cli_connect(new_client), SS_CONNECTED, 0, fd)) {
    ++ServerStats->is_ref;
    write(fd, register_message, strlen(register_message));
    close(fd);
    cli_fd(new_client) = -1;
    return;
  }
  cli_freeflag(new_client) |= FREEFLAG_SOCKET;
  cli_listener(new_client) = listener;
  ++listener->ref_count;

  Count_newunknown(UserStats);
  /* if we've made it this far we can put the client on the auth query pile */
  start_auth(new_client);
}