コード例 #1
0
ファイル: client.c プロジェクト: Cloudxtreme/ircd-ratbox
/*
 * check_klines
 * inputs	- NONE
 * output	- NONE
 * side effects - Check all connections for a pending kline against the
 * 		  client, exit the client if a kline matches.
 */
void 
check_klines(void)
{               
  struct Client *client_p;          /* current local client_p being examined */
  struct ConfItem     *aconf = (struct ConfItem *)NULL;
  char          *reason;                /* pointer to reason string */
  dlink_node    *ptr, *next_ptr;
 
  for (ptr = lclient_list.head; ptr; ptr = next_ptr)
    {
      next_ptr = ptr->next;
      client_p = ptr->data;
      
      if (IsMe(client_p))
	continue;
	
      /* if there is a returned struct ConfItem then kill it */
      if ((aconf = find_dline(&client_p->localClient->ip,
			      client_p->localClient->aftype)))
	{
	  if (aconf->status & CONF_EXEMPTDLINE)
	    continue;
	    
	  sendto_realops_flags(FLAGS_ALL, L_ALL,"DLINE active for %s",
			       get_client_name(client_p, HIDE_IP));
			       
	  if (ConfigFileEntry.kline_with_connection_closed &&
	      ConfigFileEntry.kline_with_reason)
	  {
	    reason = "Connection closed";

	    if(IsPerson(client_p))
  	      sendto_one(client_p, form_str(ERR_YOUREBANNEDCREEP),
  	                 me.name, client_p->name,
	 	         aconf->passwd ? aconf->passwd : "D-lined");
            else
	      sendto_one(client_p, "NOTICE DLINE :*** You have been D-lined");
	  }
	  else
	  {
	    if(ConfigFileEntry.kline_with_connection_closed)
	      reason = "Connection closed";
	    else if(ConfigFileEntry.kline_with_reason && aconf->passwd)
	      reason = aconf->passwd;
	    else
	      reason = "D-lined";

            if(IsPerson(client_p))
	      sendto_one(client_p, form_str(ERR_YOUREBANNEDCREEP),
	                 me.name, client_p->name, reason);
            else
	      sendto_one(client_p, "NOTICE DLINE :*** You have been D-lined");
	  }
	    
	  (void)exit_client(client_p, client_p, &me, reason);
	  continue; /* and go examine next fd/client_p */
	}

      if (IsPerson(client_p))
	{
	  if (ConfigFileEntry.glines &&
	      (aconf = find_gkill(client_p, client_p->username)))
	    {
	      if (IsExemptKline(client_p))
		{
		  sendto_realops_flags(FLAGS_ALL, L_ALL,
				       "GLINE over-ruled for %s, client is kline_exempt",
				       get_client_name(client_p, HIDE_IP));
		  continue;
		}
	      
	      if (IsExemptGline(client_p))
		{
		  sendto_realops_flags(FLAGS_ALL, L_ALL,
				       "GLINE over-ruled for %s, client is gline_exempt",
				       get_client_name(client_p, HIDE_IP));
		  continue;
		}
       
	      sendto_realops_flags(FLAGS_ALL, L_ALL, "GLINE active for %s",
				   get_client_name(client_p, HIDE_IP));
			    
	      if(ConfigFileEntry.kline_with_connection_closed &&
	         ConfigFileEntry.kline_with_reason)
 	      {
		  reason = "Connection closed";

		  sendto_one(client_p, form_str(ERR_YOUREBANNEDCREEP),
		             me.name, client_p->name,
			     aconf->passwd ? aconf->passwd : "G-lined");
	      } 
	      else 
	      {
	        if(ConfigFileEntry.kline_with_connection_closed)
		  reason = "Connection closed";
		else if(ConfigFileEntry.kline_with_reason && aconf->passwd)
		  reason = aconf->passwd;
		else
		  reason = "G-lined";

		sendto_one(client_p, form_str(ERR_YOUREBANNEDCREEP),
		           me.name, client_p->name, reason);
	      }
	
	      (void)exit_client(client_p, client_p, &me, reason);
	      /* and go examine next fd/client_p */    
	      continue;
	    } 
	  else if((aconf = find_kill(client_p))) 
	    {
	      /* if there is a returned struct ConfItem.. then kill it */
	      if (IsExemptKline(client_p))
		{
		  sendto_realops_flags(FLAGS_ALL, L_ALL,
				       "KLINE over-ruled for %s, client is kline_exempt",
				       get_client_name(client_p, HIDE_IP));
		  continue;
		}

	      sendto_realops_flags(FLAGS_ALL, L_ALL, "KLINE active for %s",
				   get_client_name(client_p, HIDE_IP));

              if(ConfigFileEntry.kline_with_connection_closed &&
	          ConfigFileEntry.kline_with_reason)
	      {
	        reason = "Connection closed";

		sendto_one(client_p, form_str(ERR_YOUREBANNEDCREEP),
		           me.name, client_p->name, 
			   aconf->passwd ? aconf->passwd : "K-lined");
              }
	      else
	      {
	        if(ConfigFileEntry.kline_with_connection_closed)
		  reason = "Connection closed";
		else if(ConfigFileEntry.kline_with_reason && aconf->passwd)
		  reason = aconf->passwd;
		else
		  reason = "K-lined";

		sendto_one(client_p, form_str(ERR_YOUREBANNEDCREEP),
		           me.name, client_p->name, reason);
              }
	      
	      (void)exit_client(client_p, client_p, &me, reason);
	      continue; 
	    }
	}
    }
 
  /* also check the unknowns list for new dlines */
  for (ptr = unknown_list.head; ptr; ptr = next_ptr)
  {
    next_ptr = ptr->next;
    client_p = ptr->data;

    if((aconf = find_dline(&client_p->localClient->ip,
                           client_p->localClient->aftype)))
    {
      if(aconf->status & CONF_EXEMPTDLINE)
        continue;

      sendto_one(client_p, "NOTICE DLINE :*** You have been D-lined");
      exit_client(client_p, client_p, &me, "D-lined");
    }
  }

}
コード例 #2
0
ファイル: ircd.c プロジェクト: grawity/ircd-hybrid-5
static	time_t	check_pings(time_t currenttime)
{		
  register	aClient	*cptr;		/* current local cptr being examined */
  aConfItem 	*aconf = (aConfItem *)NULL;
  int		ping = 0;		/* ping time value from client */
  int		i;			/* used to index through fd/cptr's */
  time_t	oldest = 0;		/* next ping time */
  time_t	timeout;		/* found necessary ping time */
  char *reason;				/* pointer to reason string */
  int die_index=0;			/* index into list */
  char ping_time_out_buffer[64];	/* blech that should be a define */

					/* of dying clients */
  dying_clients[0] = (aClient *)NULL;	/* mark first one empty */

  /*
   * I re-wrote the way klines are handled. Instead of rescanning
   * the local[] array and calling exit_client() right away, I
   * mark the client thats dying by placing a pointer to its aClient
   * into dying_clients[]. When I have examined all in local[],
   * I then examine the dying_clients[] for aClient's to exit.
   * This saves the rescan on k-lines, also greatly simplifies the code,
   *
   * Jan 28, 1998
   * -Dianora
   */

   for (i = 0; i <= highest_fd; i++)
    {
      if (!(cptr = local[i]) || IsMe(cptr) || IsLog(cptr))
	continue;		/* and go examine next fd/cptr */
      /*
      ** Note: No need to notify opers here. It's
      ** already done when "FLAGS_DEADSOCKET" is set.
      */
      if (cptr->flags & FLAGS_DEADSOCKET)
	{
	  /* N.B. EVERY single time dying_clients[] is set
	   * it must be followed by an immediate continue,
	   * to prevent this cptr from being marked again for exit.
	   * If you don't, you could cause exit_client() to be called twice
	   * for the same cptr. i.e. bad news
	   * -Dianora
	   */

	  dying_clients[die_index] = cptr;
	  dying_clients_reason[die_index++] =
	    ((cptr->flags & FLAGS_SENDQEX) ?
	     "SendQ exceeded" : "Dead socket");
	  dying_clients[die_index] = (aClient *)NULL;
	  continue;		/* and go examine next fd/cptr */
	}

      if (rehashed)
	{
	  if(dline_in_progress)
	    {
	      if(IsPerson(cptr))
		{
		  if( (aconf = find_dkill(cptr)) ) /* if there is a returned 
						      aConfItem then kill it */
		    {
		      sendto_ops("D-line active for %s",
				 get_client_name(cptr, FALSE));

		      dying_clients[die_index] = cptr;
#ifdef KLINE_WITH_REASON
		      reason = aconf->passwd ? aconf->passwd : "D-lined";
		      dying_clients_reason[die_index++] = reason;
#else
		      dying_clients_reason[die_index++] = "D-lined";
#endif
		      dying_clients[die_index] = (aClient *)NULL;
		      sendto_one(cptr, err_str(ERR_YOUREBANNEDCREEP),
				 me.name, cptr->name, reason);
		      continue;		/* and go examine next fd/cptr */
		    }
		}
	    }
	  else
	    {
	      if(IsPerson(cptr))
		{
#ifdef GLINES
		  if( (aconf = find_gkill(cptr)) )
		    {
		      sendto_ops("G-line active for %s",
				 get_client_name(cptr, FALSE));

		      dying_clients[die_index] = cptr;
#ifdef KLINE_WITH_REASON
		      reason = aconf->passwd ? aconf->passwd : "G-lined";
		      dying_clients_reason[die_index++] = reason;
#else
		      dying_clients_reason[die_index++] = "G-lined";
#endif
		      dying_clients[die_index] = (aClient *)NULL;
		      sendto_one(cptr, err_str(ERR_YOUREBANNEDCREEP),
				 me.name, cptr->name, reason);
		      continue;		/* and go examine next fd/cptr */
		    }
		  else
#endif
		  if((aconf = find_kill(cptr)))	/* if there is a returned
						   aConfItem.. then kill it */
		    {
		      sendto_ops("K-line active for %s",
				 get_client_name(cptr, FALSE));
		      dying_clients[die_index] = cptr;

#ifdef KLINE_WITH_REASON
#ifdef K_COMMENT_ONLY
		      reason = aconf->passwd ? aconf->passwd : "K-lined";
#else
		      reason = (BadPtr(aconf->passwd) || 
				!is_comment(aconf->passwd)) ?
			"K-lined" : aconf->passwd;
#endif
		      dying_clients_reason[die_index++] = reason;
#else
		      dying_clients_reason[die_index++] = "K-lined";
#endif
		      dying_clients[die_index] = (aClient *)NULL;
		      sendto_one(cptr, err_str(ERR_YOUREBANNEDCREEP),
				 me.name, cptr->name, reason);
		      continue;		/* and go examine next fd/cptr */
		    }
		}
	    }
	}

#ifdef IDLE_CHECK
      if (IsPerson(cptr))
	{
	  if( !IsElined(cptr) && ((timeofday - cptr->user->last) > idle_time))
	    {
	      aConfItem *aconf;

	      dying_clients[die_index] = cptr;
	      dying_clients_reason[die_index++] = "idle exceeder";
	      dying_clients[die_index] = (aClient *)NULL;

	      aconf = make_conf();
	      aconf->status = CONF_KILL;
	      DupString(aconf->host, cptr->user->host);
	      DupString(aconf->passwd, "idle exceeder" );
	      DupString(aconf->name, cptr->user->username);
	      aconf->port = 0;
	      aconf->hold = timeofday + 60;
	      add_temp_kline(aconf);
	      sendto_ops("Idle exceeder %s temp k-lining",
			 get_client_name(cptr,FALSE));
	      continue;		/* and go examine next fd/cptr */
	    }
	}
#endif

#ifdef REJECT_HOLD
      if (IsRejectHeld(cptr))
	{
	  if( timeofday > (cptr->firsttime + REJECT_HOLD_TIME) )
	    {
	      dying_clients[die_index] = cptr;
	      dying_clients_reason[die_index++] = "reject held client";
	      dying_clients[die_index] = (aClient *)NULL;
	      continue;		/* and go examine next fd/cptr */
	    }
	}
#endif

#if defined(R_LINES) && defined(R_LINES_OFTEN)
      /*
       * this is used for KILL lines with time restrictions
       * on them - send a message to the user being killed
       * first.
       * *** Moved up above  -taner ***
       *
       * Moved here, no more rflag -Dianora 
       */
      if (IsPerson(cptr) && find_restrict(cptr))
	{
	  sendto_ops("Restricting %s, closing link.",
		     get_client_name(cptr,FALSE));

	  dying_clients[die_index] = cptr;
	  dying_clients_reason[die_index++] = "you have been R-lined";
	  dying_clients[die_index] = (aClient *)NULL;
	  continue;			/* and go examine next fd/cptr */
	}
#endif

      if (!IsRegistered(cptr))
	ping = CONNECTTIMEOUT;
      else
	ping = get_client_ping(cptr);

      /*
       * Ok, so goto's are ugly and can be avoided here but this code
       * is already indented enough so I think its justified. -avalon
       */
       /*  if (!rflag &&
	       (ping >= currenttime - cptr->lasttime))
	      goto ping_timeout; */

      /*
       * *sigh* I think not -Dianora
       */

      if (ping < (currenttime - cptr->lasttime))
	{

	  /*
	   * If the server hasnt talked to us in 2*ping seconds
	   * and it has a ping time, then close its connection.
	   * If the client is a user and a KILL line was found
	   * to be active, close this connection too.
	   */
	  if (((currenttime - cptr->lasttime) >= (2 * ping) &&
	       (cptr->flags & FLAGS_PINGSENT)) ||
	      ((!IsRegistered(cptr) && (currenttime - cptr->since) >= ping)))
	    {
	      if (!IsRegistered(cptr) &&
		  (DoingDNS(cptr) || DoingAuth(cptr)))
		{
		  if (cptr->authfd >= 0)
		    {
		      (void)close(cptr->authfd);
		      cptr->authfd = -1;
		      cptr->count = 0;
		      *cptr->buffer = '\0';
		    }
#ifdef SHOW_HEADERS
		  if (DoingDNS(cptr))
		    send(cptr->fd, REPORT_FAIL_DNS, R_fail_dns, 0);
		  else
		    send(cptr->fd, REPORT_FAIL_ID, R_fail_id, 0);
#endif
		  Debug((DEBUG_NOTICE,"DNS/AUTH timeout %s",
			 get_client_name(cptr,TRUE)));
		  del_queries((char *)cptr);
		  ClearAuth(cptr);
		  ClearDNS(cptr);
		  SetAccess(cptr);
		  cptr->since = currenttime;
		  continue;
		}
	      if (IsServer(cptr) || IsConnecting(cptr) ||
		  IsHandshake(cptr))
		{
		  sendto_ops("No response from %s, closing link",
			     get_client_name(cptr, FALSE));
		}
	      /*
	       * this is used for KILL lines with time restrictions
	       * on them - send a messgae to the user being killed
	       * first.
	       * *** Moved up above  -taner ***
	       */
	      cptr->flags2 |= FLAGS2_PING_TIMEOUT;
	      dying_clients[die_index++] = cptr;
	      /* the reason is taken care of at exit time */
      /*      dying_clients_reason[die_index++] = "Ping timeout"; */
	      dying_clients[die_index] = (aClient *)NULL;
	      
	      /*
	       * need to start loop over because the close can
	       * affect the ordering of the local[] array.- avalon
	       *
	       ** Not if you do it right - Dianora
	       */

	      continue;
	    }
	  else if ((cptr->flags & FLAGS_PINGSENT) == 0)
	    {
	      /*
	       * if we havent PINGed the connection and we havent
	       * heard from it in a while, PING it to make sure
	       * it is still alive.
	       */
	      cptr->flags |= FLAGS_PINGSENT;
	      /* not nice but does the job */
	      cptr->lasttime = currenttime - ping;
	      sendto_one(cptr, "PING :%s", me.name);
	    }
	}
      /* ping_timeout: */
      timeout = cptr->lasttime + ping;
      while (timeout <= currenttime)
	timeout += ping;
      if (timeout < oldest || !oldest)
	oldest = timeout;

      /*
       * Check UNKNOWN connections - if they have been in this state
       * for > 100s, close them.
       */

      if (IsUnknown(cptr))
	{
	  if (cptr->firsttime ? ((timeofday - cptr->firsttime) > 100) : 0)
	    {
	      dying_clients[die_index] = cptr;
	      dying_clients_reason[die_index++] = "Connection Timed Out";
	      dying_clients[die_index] = (aClient *)NULL;
	      continue;
	    }
	}
    }

  /* Now exit clients marked for exit above.
   * it doesn't matter if local[] gets re-arranged now
   *
   * -Dianora
   */

  for(die_index = 0; (cptr = dying_clients[die_index]); die_index++)
    {
      if(cptr->flags2 & FLAGS2_PING_TIMEOUT)
	{
	  (void)ircsprintf(ping_time_out_buffer,
			    "Ping timeout: %d seconds",
			    currenttime - cptr->lasttime);
	  (void)exit_client(cptr, cptr, &me, ping_time_out_buffer );
	}
      else
	(void)exit_client(cptr, cptr, &me, dying_clients_reason[die_index]);
    }

  rehashed = 0;
  dline_in_progress = 0;

  if (!oldest || oldest < currenttime)
    oldest = currenttime + PINGFREQUENCY;
  Debug((DEBUG_NOTICE,"Next check_ping() call at: %s, %d %d %d",
	 myctime(oldest), ping, oldest, currenttime));
  
  return (oldest);
}