Esempio n. 1
0
int ju_addjupe(void *source, int cargc, char **cargv) {
  nick *np = (nick*)source;
  int result, duration;

  if (cargc < 3) {
    return CMD_USAGE;
  }

  if (jupe_find(cargv[0]) != NULL) {
    controlreply(np, "There is already a jupe for that server.");
    return CMD_OK;
  }

  duration = durationtolong(cargv[1]);

  if (duration > JUPE_MAX_EXPIRE) {
    controlreply(np, "A jupe's maximum duration is %s. Could not create jupe.", longtoduration(JUPE_MAX_EXPIRE, 0));
    return CMD_OK;
  }

  result = jupe_add(cargv[0], cargv[2], duration, JUPE_ACTIVE);

  if (result) {
    controlwall(NO_OPER, NL_MISC, "%s added JUPE for '%s' expiring in %s with reason %s", controlid(np), cargv[0], longtoduration(duration, 0), cargv[2]);
    controlreply(np, "Done.");
  } else
    controlreply(np, "Jupe could not be created.");

  return CMD_OK;
}
Esempio n. 2
0
int ju_deactivatejupe(void *source, int cargc, char **cargv) {
  nick *np = (nick*)source;
  jupe_t *jupe;

  if (cargc < 1) {
    return CMD_USAGE;
  }

  jupe = jupe_find(cargv[0]);

  if (jupe == NULL) {
    controlreply(np, "There is no such jupe.");
    return CMD_OK;
  }

  if ((jupe->ju_flags & JUPE_ACTIVE) == 0) {
    controlreply(np, "This jupe is already deactivated.");
    return CMD_OK;
  }

  jupe_deactivate(jupe);

  controlwall(NO_OPER, NL_MISC, "%s deactivated JUPE for '%s'", controlid(np), cargv[0]);
  controlreply(np, "Done.");
  return CMD_OK;
}
Esempio n. 3
0
/** Send a jupe (or a list of jupes) to a server.
 * @param[in] sptr Client searching for jupes.
 * @param[in] server Name of jupe to search for (if NULL, list all).
 * @return Zero.
 */
int
jupe_list(struct Client *sptr, char *server)
{
  struct Jupe *jupe;
  struct Jupe *sjupe;

  if (server) {
    if (!(jupe = jupe_find(server))) /* no such jupe */
      return send_reply(sptr, ERR_NOSUCHJUPE, server);

    /* send jupe information along */
    send_reply(sptr, RPL_JUPELIST, jupe->ju_server, jupe->ju_expire + TSoffset,
	       JupeIsLocal(jupe) ? cli_name(&me) : "*",
	       JupeIsActive(jupe) ? '+' : '-', jupe->ju_reason);
  } else {
    for (jupe = GlobalJupeList; jupe; jupe = sjupe) { /* go through jupes */
      sjupe = jupe->ju_next;

      if (jupe->ju_expire <= CurrentTime) /* expire any that need expiring */
	jupe_free(jupe);
      else /* send jupe information along */
	send_reply(sptr, RPL_JUPELIST, jupe->ju_server,
		   jupe->ju_expire + TSoffset,
		   JupeIsLocal(jupe) ? cli_name(&me) : "*",
		   JupeIsActive(jupe) ? '+' : '-', jupe->ju_reason);
    }
  }

  /* end of jupe information */
  return send_reply(sptr, RPL_ENDOFJUPELIST);
}
/*
 * ms_jupe - server message handler
 *
 * parv[0] = Send prefix
 *
 * From server:
 *
 * parv[1] = Target: server numeric or *
 * parv[2] = (+|-)<server name>
 * parv[3] = Expiration offset
 * parv[4] = Last modification time
 * parv[5] = Comment
 *
 */
int ms_jupe(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
    struct Client *acptr = 0;
    struct Jupe *ajupe;
    unsigned int flags = 0;
    time_t expire_off, lastmod;
    char *server = parv[2], *target = parv[1], *reason = parv[5];

    if (parc < 6)
        return need_more_params(sptr, "JUPE");

    if (!(target[0] == '*' && target[1] == '\0')) {
        if (!(acptr = FindNServer(target)))
            return 0; /* no such server */

        if (!IsMe(acptr)) { /* manually propagate, since we don't set it */
            sendcmdto_one(sptr, CMD_JUPE, acptr, "%s %s %s %s :%s", target, server,
                          parv[3], parv[4], reason);
            return 0;
        }

        flags |= JUPE_LOCAL;
    }

    if (*server == '-')
        server++;
    else if (*server == '+') {
        flags |= JUPE_ACTIVE;
        server++;
    }

    expire_off = atoi(parv[3]);
    lastmod = atoi(parv[4]);

    ajupe = jupe_find(server);

    if (ajupe) {
        if (JupeIsLocal(ajupe) && !(flags & JUPE_LOCAL)) /* global over local */
            jupe_free(ajupe);
        else if (JupeLastMod(ajupe) < lastmod) { /* new modification */
            if (flags & JUPE_ACTIVE)
                return jupe_activate(cptr, sptr, ajupe, lastmod, flags);
            else
                return jupe_deactivate(cptr, sptr, ajupe, lastmod, flags);
        } else if (JupeLastMod(ajupe) == lastmod || IsBurstOrBurstAck(cptr))
            return 0;
        else
            return jupe_resend(cptr, ajupe); /* other server desynched WRT jupes */
    }

    return jupe_add(cptr, sptr, server, reason, expire_off, lastmod, flags);
}
Esempio n. 5
0
/** 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;
}
/*
 * mo_jupe - oper message handler
 *
 * parv[0] = Send prefix
 * parv[1] = [[+|-]<server name>]
 *
 * Local (to me) style:
 *
 * parv[2] = [Expiration offset]
 * parv[3] = [Comment]
 *
 * Global (or remote local) style:
 *
 * parv[2] = [target]
 * parv[3] = [Expiration offset]
 * parv[4] = [Comment]
 *
 */
int mo_jupe(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
    struct Client *acptr = 0;
    struct Jupe *ajupe;
    unsigned int flags = 0;
    time_t expire_off;
    char *server = parv[1], *target = 0, *reason;

    if (parc < 2)
        return jupe_list(sptr, 0);

    if (*server == '+') {
        flags |= JUPE_ACTIVE;
        server++;
    } else if (*server == '-')
        server++;
    else
        return jupe_list(sptr, server);

    if (!feature_bool(FEAT_CONFIG_OPERCMDS))
        return send_reply(sptr, ERR_DISABLED, "JUPE");

    if (parc == 4) {
        expire_off = atoi(parv[2]);
        reason = parv[3];
        flags |= JUPE_LOCAL;
    } else if (parc > 4) {
        target = parv[2];
        expire_off = atoi(parv[3]);
        reason = parv[4];
    } else
        return need_more_params(sptr, "JUPE");

    if (target) {
        if (!(target[0] == '*' && target[1] == '\0')) {
            if (!(acptr = find_match_server(target)))
                return send_reply(sptr, ERR_NOSUCHSERVER, target);

            if (!IsMe(acptr)) { /* manually propagate, since we don't set it */
                if (!HasPriv(sptr, PRIV_JUPE))
                    return send_reply(sptr, ERR_NOPRIVILEGES);

                sendcmdto_one(sptr, CMD_JUPE, acptr, "%C %c%s %s %Tu :%s", acptr,
                              flags & JUPE_ACTIVE ? '+' : '-', server, parv[3],
                              TStime(), reason);
                return 0;
            } else if (!HasPriv(sptr, PRIV_LOCAL_JUPE))
                return send_reply(sptr, ERR_NOPRIVILEGES);

            flags |= JUPE_LOCAL;
        } else if (!HasPriv(sptr, PRIV_JUPE))
            return send_reply(sptr, ERR_NOPRIVILEGES);
    }

    ajupe = jupe_find(server);

    if (ajupe) {
        if (JupeIsLocal(ajupe) && !(flags & JUPE_LOCAL)) /* global over local */
            jupe_free(ajupe);
        else {
            if (flags & JUPE_ACTIVE)
                return jupe_activate(cptr, sptr, ajupe, TStime(), flags);
            else
                return jupe_deactivate(cptr, sptr, ajupe, TStime(), flags);
        }
    }

    return jupe_add(cptr, sptr, server, reason, expire_off, TStime(), flags);
}
Esempio n. 7
0
/** Handle a CONNECT message from a server.
 *
 * \a parv has the following elements:
 * \li \a parv[1] is the server that should initiate the connection
 * \li \a parv[2] is the port number to connect on (zero for the default)
 * \li \a parv[3] is the server to connect to
 *
 * 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 ms_connect(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  unsigned short   port;
  unsigned short   tmpport;
  const char*      rule;
  struct ConfItem* aconf;
  struct Client*   acptr;
  struct Jupe*     ajupe;

  assert(0 != cptr);
  assert(0 != sptr);

  if (!IsPrivileged(sptr))
    return send_reply(sptr, ERR_NOPRIVILEGES);

  if (parc < 4) {
    /*
     * this is coming from a server which should have already
     * checked it's args, if we don't have parc == 4, something
     * isn't right.
     */
    protocol_violation(sptr, "Too few parameters to connect");
    return need_more_params(sptr, "CONNECT");
  }

  if (hunt_server_cmd(sptr, CMD_CONNECT, cptr, 1, "%s %s :%C", 3, parc, parv)
      != HUNTED_ISME)
    return 0;

  /*
   * need to find the conf entry first so we can use the server name from
   * the conf entry instead of parv[1] to find out if the server is already
   * present below. --Bleep
   */
  if (0 == (aconf = conf_find_server(parv[1]))) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: Host %s not listed "
		  "in ircd.conf", sptr, parv[1]);
    return 0;
  }
  /*
   * use aconf->name to look up the server
   */
  if ((acptr = FindServer(aconf->name))) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: Server %s already "
		  "exists from %s", sptr, parv[1], cli_name(cli_from(acptr)));
    return 0;
  }
  /*
   * Evaluate connection rules...  If no rules found, allow the
   * connect.   Otherwise stop with the first true rule (ie: rules
   * are ored together.  Oper connects are effected only by D
   * lines (CRULEALL) not d lines (CRULEAUTO).
   */
  if ((rule = conf_eval_crule(aconf->name, CRULE_ALL))) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: Disallowed by rule: %s", sptr, rule);
    return 0;
  }
  /*
   * Check to see if the server is juped; if it is, disallow the connect
   */
  if ((ajupe = jupe_find(aconf->name)) && JupeIsActive(ajupe)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: Server %s is juped: %s",
		  sptr, JupeServer(ajupe), JupeReason(ajupe));
    return 0;
  }

  /*
   * Allow opers to /connect foo.* 0 bah.* to connect foo and bah
   * using the conf's configured port
   */
  port = atoi(parv[2]);
  /*
   * save the old port
   */
  tmpport = aconf->address.port;
  if (port)
    aconf->address.port = port;
  else
    port = aconf->address.port;

  /*
   * Notify all operators about remote connect requests
   */
  sendwallto_group(&me, WALL_WALLOPS, 0,
                   "Remote CONNECT %s %s from %s", parv[1],
                   parv[2] ? parv[2] : "",
                   get_client_name(sptr, HIDE_IP));
  log_write(LS_NETWORK, L_INFO, 0, "CONNECT From %C : %s %s", sptr, parv[1],
	    parv[2] ? parv[2] : "");

  if (connect_server(aconf, sptr)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :*** Connecting to %s.", sptr,
		  aconf->name);
  }
  else {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :*** Connection to %s failed",
		  sptr, aconf->name);
  }
  aconf->address.port = tmpport;
  return 0;
}
Esempio n. 8
0
/** Handle a CONNECT message from an operator.
 *
 * \a parv has the following elements:
 * \li \a parv[1] is the server that should initiate the connection
 * \li \a parv[2] is the port number to connect on (zero for the default)
 * \li \a parv[3] is the server to connect to
 *
 * 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 mo_connect(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  unsigned short   port;
  unsigned short   tmpport;
  const char*      rule;
  struct ConfItem* aconf;
  struct Client*   acptr;
  struct Jupe*     ajupe;

  assert(0 != cptr);
  assert(cptr == sptr);
  assert(IsAnOper(sptr));

  if (parc < 2)
    return need_more_params(sptr, "CONNECT");

  if (parc > 3) {
    /*
     * if parc > 3, we are trying to connect two remote
     * servers to each other
     */
    if (IsLocOp(sptr)) {
      /*
       * Only allow LocOps to make local CONNECTS --SRB
       */
      return send_reply(cptr, ERR_NOPRIVILEGES);
    }
    else {
      struct Client* acptr2;
      struct Client* acptr3;

      if (!(acptr3 = find_match_server(parv[3]))) {
        return send_reply(sptr, ERR_NOSUCHSERVER, parv[3]);
      }

      /*
       * Look for closest matching server 
       * needed for "/connect blah 4400 *"?
       */
      for (acptr2 = acptr3; acptr2 != &me; acptr2 = cli_serv(acptr2)->up) {
        if (!match(parv[3], cli_name(acptr2)))
          acptr3 = acptr2;
      }
      parv[3] = cli_name(acptr3);
      if (hunt_server_cmd(sptr, CMD_CONNECT, cptr, 1, "%s %s :%C", 3, parc,
			  parv) != HUNTED_ISME)
        return 0;
    }
  }
  /*
   * need to find the conf entry first so we can use the server name from
   * the conf entry instead of parv[1] to find out if the server is already
   * present below. --Bleep
   */
  if (0 == (aconf = conf_find_server(parv[1]))) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: Host %s not listed "
		  "in ircd.conf", sptr, parv[1]);
    return 0;
  }
  /*
   * use aconf->name to look up the server, see above
   */
  if ((acptr = FindServer(aconf->name))) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: Server %s already "
		  "exists from %s", sptr, parv[1], cli_name(cli_from(acptr)));
    return 0;
  }
  /*
   * Evaluate connection rules...  If no rules found, allow the
   * connect.   Otherwise stop with the first true rule (ie: rules
   * are ored together.  Oper connects are effected only by D
   * lines (CRULEALL) not d lines (CRULEAUTO).
   */
  if ((rule = conf_eval_crule(aconf->name, CRULE_ALL))) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: Disallowed by rule: %s", sptr, rule);
    return 0;
  }
  /*
   * Check to see if the server is juped; if it is, disallow the connect
   */
  if ((ajupe = jupe_find(aconf->name)) && JupeIsActive(ajupe)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: Server %s is juped: %s",
		  sptr, JupeServer(ajupe), JupeReason(ajupe));
    return 0;
  }
  /*
   *  Get port number from user, if given. If not specified,
   *  use the default from configuration structure. If missing
   *  from there, then use the precompiled default.
   */
  port = aconf->address.port;
  if (parc > 2) {
    assert(0 != parv[2]);
    if (0 == (port = atoi(parv[2]))) {
      sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: Invalid port number",
		    sptr);
      return 0;
    }
  }
  if (0 == port && 0 == (port = feature_int(FEAT_SERVER_PORT))) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :Connect: missing port number",
		  sptr);
    return 0;
  }

  tmpport = aconf->address.port;
  aconf->address.port = port;

  if (connect_server(aconf, sptr)) {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :*** Connecting to %s.", sptr,
		  aconf->name);
  }
  else {
    sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :*** Connection to %s failed",
		  sptr, aconf->name);
  }
  aconf->address.port = tmpport;
  return 0;
}
Esempio n. 9
0
/** Look for any connections that we should try to initiate.
 * Reschedules itself to run again at the appropriate time.
 * @param[in] ev Timer event (ignored).
 */
static void try_connections(struct Event* ev) {
  struct ConfItem*  aconf;
  struct ConfItem** pconf;
  time_t            next;
  struct Jupe*      ajupe;
  int               hold;
  int               done;

  assert(ET_EXPIRE == ev_type(ev));
  assert(0 != ev_timer(ev));

  Debug((DEBUG_NOTICE, "Connection check at   : %s", myctime(CurrentTime)));
  next = CurrentTime + feature_int(FEAT_CONNECTFREQUENCY);
  done = 0;

  for (aconf = GlobalConfList; aconf; aconf = aconf->next) {
    /* Only consider server items with non-zero port and non-zero
     * connect times that are not actively juped.
     */
    if (!(aconf->status & CONF_SERVER)
        || aconf->address.port == 0
        || !(aconf->flags & CONF_AUTOCONNECT)
        || ((ajupe = jupe_find(aconf->name)) && JupeIsActive(ajupe)))
      continue;

    /* Do we need to postpone this connection further? */
    hold = aconf->hold > CurrentTime;

    /* Update next possible connection check time. */
    if (hold && next > aconf->hold)
        next = aconf->hold;

    /* Do not try to connect if its use is still on hold until future,
     * we have already initiated a connection this try_connections(),
     * too many links in its connection class, it is already linked,
     * or if connect rules forbid a link now.
     */
    if (hold || done
        || (ConfLinks(aconf) > ConfMaxLinks(aconf))
        || FindServer(aconf->name)
        || conf_eval_crule(aconf->name, CRULE_MASK))
      continue;

    /* Ensure it is at the end of the list for future checks. */
    if (aconf->next) {
      /* Find aconf's location in the list and splice it out. */
      for (pconf = &GlobalConfList; *pconf; pconf = &(*pconf)->next)
        if (*pconf == aconf)
          *pconf = aconf->next;
      /* Reinsert it at the end of the list (where pconf is now). */
      *pconf = aconf;
      aconf->next = 0;
    }

    /* Activate the connection itself. */
    if (connect_server(aconf, 0))
      sendto_opmask_butone(0, SNO_OLDSNO, "Connection to %s activated.",
			   aconf->name);

    /* And stop looking for further candidates. */
    done = 1;
  }

  Debug((DEBUG_NOTICE, "Next connection check : %s", myctime(next)));
  timer_add(&connect_timer, try_connections, 0, TT_ABSOLUTE, next);
}