Exemple #1
0
/** Find a ConfItem that has the same name and user+host fields as
 * specified.  Requires an exact match for \a name.
 * @param name Name to match
 * @param cptr Client to match against
 * @param statmask Filter for ConfItem::status
 * @return First found matching ConfItem.
 */
struct ConfItem* find_conf_exact(const char* name, struct Client *cptr, int statmask)
{
  struct ConfItem *tmp;

  for (tmp = GlobalConfList; tmp; tmp = tmp->next) {
    if (!(tmp->status & statmask) || !tmp->name || !tmp->host ||
        0 != ircd_strcmp(tmp->name, name))
      continue;
    if (tmp->username
        && (EmptyString(cli_username(cptr))
            || match(tmp->username, cli_username(cptr))))
      continue;
    if (tmp->addrbits < 0)
    {
      if (match(tmp->host, cli_sockhost(cptr)))
        continue;
    }
    else if (!ipmask_check(&cli_ip(cptr), &tmp->address.addr, tmp->addrbits))
      continue;
    if ((tmp->status & CONF_OPERATOR)
        && (MaxLinks(tmp->conn_class) > 0)
        && (tmp->clients >= MaxLinks(tmp->conn_class)))
      continue;
    return tmp;
  }
  return 0;
}
Exemple #2
0
/** Report connection classes to a client.
 * @param[in] sptr Client requesting statistics.
 * @param[in] sd Stats descriptor for request (ignored).
 * @param[in] param Extra parameter from user (ignored).
 */
void
report_classes(struct Client *sptr, const struct StatDesc *sd,
               char *param)
{
  struct ConnectionClass *cltmp;

  for (cltmp = connClassList; cltmp; cltmp = cltmp->next)
    send_reply(sptr, RPL_STATSYLINE, (cltmp->valid ? 'Y' : 'y'),
               ConClass(cltmp), PingFreq(cltmp), ConFreq(cltmp),
               MaxLinks(cltmp), MaxSendq(cltmp), Links(cltmp) - 1);
}
Exemple #3
0
/** Initialize the connection class list.
 * A connection class named "default" is created, with ping frequency,
 * connection frequency, maximum links and max SendQ values from the
 * corresponding configuration features.
 */
void init_class(void)
{
  if (!connClassList) {
    connClassList = (struct ConnectionClass*) make_class();
    connClassList->next   = 0;
  }

  /* We had better not try and free this... */
  ConClass(connClassList) = "default";
  PingFreq(connClassList) = feature_int(FEAT_PINGFREQUENCY);
  ConFreq(connClassList)  = feature_int(FEAT_CONNECTFREQUENCY);
  MaxLinks(connClassList) = feature_int(FEAT_MAXIMUM_LINKS);
  MaxSendq(connClassList) = feature_uint(FEAT_DEFAULTMAXSENDQLENGTH);
  connClassList->valid    = 1;
  Links(connClassList)    = 1;
}
Exemple #4
0
/** Make sure we have a connection class named \a name.
 * If one does not exist, create it.  Then set its ping frequency,
 * connection frequency, maximum link count, and max SendQ according
 * to the parameters.
 * @param[in] name Connection class name.
 * @param[in] ping Ping frequency for clients in this class.
 * @param[in] confreq Connection frequency for clients.
 * @param[in] maxli Maximum link count for class.
 * @param[in] sendq Max SendQ for clients.
 */
void add_class(char *name, unsigned int ping, unsigned int confreq,
               unsigned int maxli, unsigned int sendq)
{
  struct ConnectionClass* p;

  Debug((DEBUG_DEBUG, "Add Class %s: cf: %u pf: %u ml: %u sq: %d",
         name, confreq, ping, maxli, sendq));
  assert(name != NULL);
  p = do_find_class(name, 1);
  if (!p)
    p = make_class();
  else
    MyFree(ConClass(p));
  ConClass(p) = name;
  ConFreq(p) = confreq;
  PingFreq(p) = ping;
  MaxLinks(p) = maxli;
  MaxSendq(p) = (sendq > 0U) ?
    sendq : feature_uint(FEAT_DEFAULTMAXSENDQLENGTH);
  p->valid = 1;
}
Exemple #5
0
/** Unlink (and dereference) invalid connection classes.
 * This is used in combination with class_mark_delete() during rehash
 * to get rid of connection classes that are no longer in the
 * configuration.
 */
void class_delete_marked(void)
{
  struct ConnectionClass* cl;
  struct ConnectionClass* prev;

  Debug((DEBUG_DEBUG, "Class check:"));

  for (prev = cl = connClassList; cl; cl = prev->next) {
    Debug((DEBUG_DEBUG, "Class %s : CF: %d PF: %d ML: %d LI: %d SQ: %d",
           ConClass(cl), ConFreq(cl), PingFreq(cl), MaxLinks(cl),
           Links(cl), MaxSendq(cl)));
    /*
     * unlink marked classes, delete unreferenced ones
     */
    if (cl->valid || Links(cl) > 1)
      prev = cl;
    else
    {
      prev->next = cl->next;
      free_class(cl);
    }
  }
}
Exemple #6
0
/*
** try_connections
**
**	Scan through configuration and try new connections.
**	Returns the calendar time when the next call to this
**	function should be made latest. (No harm done if this
**	is called earlier or later...)
*/
static	time_t	try_connections(time_t currenttime)
{
	Reg	aConfItem *aconf;
	Reg	aClient *cptr;
	aConfItem **pconf;
	int	confrq;
	time_t	next = 0;
	aClass	*cltmp;
	aConfItem *con_conf = NULL;
	int	allheld = 1;
#ifdef DISABLE_DOUBLE_CONNECTS
	int	i;
#endif

	if ((bootopt & BOOT_STANDALONE))
		return 0;

	Debug((DEBUG_NOTICE,"Connection check at   : %s",
		myctime(currenttime)));
	for (aconf = conf; aconf; aconf = aconf->next )
	{
		/* not a C-line */
		if (!(aconf->status & (CONF_CONNECT_SERVER|CONF_ZCONNECT_SERVER)))
			continue;

		/* not a candidate for AC */
		if (aconf->port <= 0)
			continue;

		cltmp = Class(aconf);
		/* not a candidate for AC */
		if (MaxLinks(cltmp) == 0)
			continue;

		/* minimize next to lowest hold time of all AC-able C-lines */
		if (next > aconf->hold || next == 0)
			next = aconf->hold;

		/* skip conf if the use of it is on hold until future. */
		if (aconf->hold > currenttime)
			continue;

		/* at least one candidate not held for future, good */
		allheld = 0;

		/* see if another link in this conf is allowed */
		if (Links(cltmp) >= MaxLinks(cltmp))
			continue;
		
		/* next possible check after connfreq secs for this C-line */
		confrq = get_con_freq(cltmp);
		aconf->hold = currenttime + confrq;

		/* is this server already connected? */
		cptr = find_name(aconf->name, (aClient *)NULL);
		if (!cptr)
			cptr = find_mask(aconf->name, (aClient *)NULL);

		/* matching client already exists, no AC to it */
		if (cptr)
			continue;

		/* no such server, check D-lines */
		if (find_denied(aconf->name, Class(cltmp)))
			continue;

#ifdef DISABLE_DOUBLE_CONNECTS
		/* Much better would be traversing only unknown
		** connections, but this requires another global
		** variable, adding and removing from there in
		** proper places etc. Some day. --B. */
		for (i = highest_fd; i >= 0; i--)
		{
			if (!(cptr = local[i]) ||
				cptr->status > STAT_UNKNOWN)
			{
				continue;
			}
			/* an unknown traveller we have */
			if (
#ifndef INET6
				cptr->ip.s_addr == aconf->ipnum.s_addr
#else
				!memcmp(cptr->ip.s6_addr,
					aconf->ipnum.s6_addr, 16)
#endif
			)
			{
				/* IP the same. Coincidence? Maybe.
				** Do not cause havoc with double connect. */
				break;
			}
			cptr = NULL;
		}
		if (cptr)
		{
			sendto_flag(SCH_SERVER, "AC to %s postponed", aconf->name);
			continue;
		}
#endif
		/* we have a candidate! */

		/* choose the best. */
		if (!con_conf ||
		     (con_conf->pref > aconf->pref && aconf->pref >= 0) ||
		     (con_conf->pref == -1 &&
		      Class(cltmp) > ConfClass(con_conf)))
		{
			con_conf = aconf;
		}
		/* above is my doubt: if we always choose best connection
		** and it always fails connecting, we may never try another,
		** even "worse"; what shall we do? --Beeth */
	}
	if (con_conf)
	{
		if (con_conf->next)  /* are we already last? */
		{
			for (pconf = &conf; (aconf = *pconf);
			     pconf = &(aconf->next))
				/* put the current one at the end and
				 * make sure we try all connections
				 */
				if (aconf == con_conf)
					*pconf = aconf->next;
			(*pconf = con_conf)->next = 0;
		}

		/* "Penalty" for being the best, so in next call of
		 * try_connections() other servers have chance. --B. */
		con_conf->hold += get_con_freq(Class(con_conf));

		if (!iconf.aconnect)
		{
			sendto_flag(SCH_NOTICE,
				"Connection to %s deferred. Autoconnect "
				"administratively disabled", con_conf->name);
		}
		else if (connect_server(con_conf, (aClient *)NULL,
				   (struct hostent *)NULL) == 0)
		{
			sendto_flag(SCH_NOTICE,
				    "Connection to %s[%s] activated.",
				    con_conf->name, con_conf->host);
		}
	}
	else
	if (allheld == 0)	/* disable AC only when some C: got checked */
	{
		/* No suitable conf for AC was found, so why bother checking
		** again? If some server quits, it'd get reenabled --B. */
		next = 0;
	}
	Debug((DEBUG_NOTICE,"Next connection check : %s", myctime(next)));
	return (next);
}
Exemple #7
0
/*
 * try_connections 
 * 
 *      Scan through configuration and try new connections. 
 *   Returns  the calendar time when the next call to this 
 *      function should be made latest. (No harm done if this 
 *      is called earlier or later...)
 */
static      time_t
try_connections(time_t currenttime)
{
aConfItem *aconf, **pconf, *con_conf = (aConfItem *) NULL;
aClient   *cptr;
aClass    *cltmp;
int        connecting, confrq, con_class = 0;
time_t      next = 0;

   connecting = FALSE;

   Debug((DEBUG_NOTICE, "Connection check at   : %s",
	  myctime(currenttime)));

   for (aconf = conf; aconf; aconf = aconf->next) {
      /* Also when already connecting! (update holdtimes) --SRB */
      if (!(aconf->status & CONF_CONNECT_SERVER) || aconf->port <= 0)
	 continue;
      cltmp = Class (aconf);

      /*
       * * Skip this entry if the use of it is still on hold until 
       * future. Otherwise handle this entry (and set it on hold 
       * until next time). Will reset only hold times, if already 
       * made one successfull connection... [this algorithm is a bit
       * fuzzy... -- msa >;) ]
       */

      if ((aconf->hold > currenttime)) 
      {
	 if ((next > aconf->hold) || (next == 0))
	    next = aconf->hold;
	 continue;
      }

      confrq = get_con_freq(cltmp);
      aconf->hold = currenttime + confrq;

      /* Found a CONNECT config with port specified, scan clients 
       * and see if this server is already connected?
       */

      cptr = find_name(aconf->name, (aClient *) NULL);

      if (!cptr && (Links(cltmp) < MaxLinks(cltmp)) &&
	  (!connecting || (Class (cltmp) > con_class))) 
      {
	con_class = Class (cltmp);

 	con_conf = aconf;
	 /* We connect only one at time... */
	connecting = TRUE;
      }

      if ((next > aconf->hold) || (next == 0))
	 next = aconf->hold;
   }

   if (connecting) 
   {
      if (con_conf->next) 	/* are we already last? */
      {
	 for (pconf = &conf; (aconf = *pconf);
	      pconf = &(aconf->next))
	    /*
	     * put the current one at the end and make sure we try all
	     * connections
	     */
	    if (aconf == con_conf)
	       *pconf = aconf->next;
	 (*pconf = con_conf)->next = 0;
      }
      if (connect_server(con_conf, (aClient *) NULL,
			 (struct hostent *) NULL) == 0)
	 sendto_gnotice("from %s: Connection to %s activated.", me.name, con_conf->name);
   }
   Debug((DEBUG_NOTICE, "Next connection check : %s", myctime(next)));
   return (next);
}