Ejemplo n.º 1
0
/* ************************************************************************ */
int BlockHeapFree(BlockHeap *bh, void *ptr)
{
   Block *walker;
   unsigned long ctr;
   unsigned long bitmask;

   if (bh == NULL)
     {
#if defined(SYSLOG_BLOCK_ALLOCATOR)
       log(L_NOTICE,"blalloc.c bh == NULL");
#endif
       return 1;
     }

   for (walker = bh->base; walker != NULL; walker = walker->next)
     {
      if ((ptr >= walker->elems) && (ptr <= walker->endElem))
        {
          ctr = ((unsigned long) ptr - 
                 (unsigned long) (walker->elems))
            / (unsigned long )bh->elemSize;

          bitmask = 1L << (ctr % (sizeof(long) * 8));
          ctr = ctr / (sizeof(long) * 8);
          /* Flip the right allocation bit */
          /* Complain if the bit is already clear, something is wrong
           * (typically, someone freed the same block twice)
           */

          if( (walker->allocMap[ctr] & bitmask) == 0 )
            {
#ifdef DEBUG_BLOCK_ALLOCATOR
      log(L_WARN, "blalloc.c bit already clear in map caller %s %d",
          BH_CurrentFile, BH_CurrentLine);
      sendto_ops("blalloc.c bit already clear in map elemSize %d caller %s %d",
                         bh->elemSize,
                         BH_CurrentFile,
                         BH_CurrentLine);
              sendto_ops("Please report to the hybrid team! [email protected]");
#endif /* DEBUG_BLOCK_ALLOCATOR */
            }
          else
            {
              walker->allocMap[ctr] = walker->allocMap[ctr] & ~bitmask;
              walker->freeElems++;  bh->freeElems++;
            }
          return 0;
        }
     }
   return 1;
}
Ejemplo n.º 2
0
/*
 * m_lnotice (send notice to all local users)
 *      parv[0] = sender prefix
 *      parv[1] = message text
 */
int m_lnotice(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{ 
  char* message;
  struct Client *acptr;

  message = parc > 1 ? parv[1] : NULL;
  
  if (EmptyString(message))
    {
      sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS),
                 me.name, parv[0], "LNOTICE");
      return 0;
    }

  if (MyClient(sptr) && !IsAnOper(sptr))
    {
      sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
      return(0);
    }

  for(acptr = local_cptr_list; acptr; acptr = acptr->next_local_client)
    {      
      sendto_one(acptr,":%s NOTICE %s :%s",
         me.name, acptr->name, parv[1]);
    }

  sendto_ops("LNOTICE sent by \2%s\2",parv[0]);
  sendto_serv_butone(&me, ":%s GLOBOPS :LNOTICE on %s :%s", 
    me.name, sptr->name, parv[1]);

  return 0;      
}	                                 	
Ejemplo n.º 3
0
/*
 * Attempt to send a sequence of bytes to the connection.
 * Returns
 *
 * < 0	Some fatal error occurred, (but not EWOULDBLOCK).
 * 	This return is a request to close the socket and
 * 	clean up the link.
 * 
 * >= 0	No real error occurred, returns the number of
 * 	bytes actually transferred. EWOULDBLOCK and other
 * 	possibly similar conditions should be mapped to
 * 	zero return. Upper level routine will have to
 * 	decide what to do with those unwritten bytes...
 *
 * *NOTE*	alarm calls have been preserved, so this should
 * 	work equally well whether blocking or non-blocking
 * 	mode is used...
 */
int
deliver_it(aClient *cptr, char *str, int len)
{
	int retval;
	aClient	*acpt = cptr->acpt;

#ifdef	DEBUGMODE
	writecalls++;
#endif
	if (IsDead(cptr)
	    || (!IsServer(cptr) && !IsPerson(cptr) &&
		!IsHandshake(cptr) && !IsUnknown(cptr))) {
		str[len]='\0';
		sendto_ops("* * * DEBUG ERROR * * * !!! Calling deliver_it() for %s, status %d %s, with message: %s",
			   cptr->name, cptr->status,
			   IsDead(cptr)?"DEAD":"", str);
		return -1;
	}

	retval = socket_write(cptr->sock, str, len);
	/*
	 * Convert WOULDBLOCK to a return of "0 bytes moved". This
	 * should occur only if socket was non-blocking. Note, that
	 * all is Ok, if the 'write' just returns '0' instead of an
	 * error and errno=EWOULDBLOCK.
	 */

#ifdef DEBUGMODE
	if (retval < 0) {
		writeb[0]++;
               Debug((DEBUG_ERROR,"write error (%s) to %s",
		      strerror(errno), cptr->name));

	} else if (retval == 0)
		writeb[1]++;
	else if (retval < 16)
		writeb[2]++;
	else if (retval < 32)
		writeb[3]++;
	else if (retval < 64)
		writeb[4]++;
	else if (retval < 128)
		writeb[5]++;
	else if (retval < 256)
		writeb[6]++;
	else if (retval < 512)
		writeb[7]++;
	else if (retval < 1024)
		writeb[8]++;
	else
		writeb[9]++;
#endif
	if (retval > 0) {
		cptr->sendB += retval;
		me.sendB += retval;
		if (cptr->sendB > 1023) {
			cptr->sendK += (cptr->sendB >> 10);
			cptr->sendB &= 0x03ff;	/* 2^10 = 1024, 3ff = 1023 */
		}
Ejemplo n.º 4
0
static void
gs_error(char *msg)
{
    if (!forked)
        puts(msg);
    else
        sendto_ops("%s", msg);
}
Ejemplo n.º 5
0
int m_svsnoop(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
        aClient *acptr;

        if (!(IsULine(sptr) && parc > 2))
                return 0;
        /* svsnoop bugfix --binary */
        if (hunt_server_token(cptr, sptr, MSG_SVSNOOP, TOK_SVSNOOP, "%s :%s", 1, parc,
            parv) == HUNTED_ISME)
        {
                if (parv[2][0] == '+')
                {
                        SVSNOOP = 1;
                        sendto_ops("This server has been placed in NOOP mode");
                        for (acptr = &me; acptr; acptr = acptr->prev)
                        {
                                if (MyClient(acptr) && IsAnOper(acptr))
                                {
                                        if (IsOper(acptr))
                                        {
                                                IRCstats.operators--;
                                                VERIFY_OPERCOUNT(acptr, "svsnoop");
                                        }
					if (IsAnOper(acptr))
                                                delfrom_fdlist(acptr->slot, &oper_fdlist);
										if (IsTotalInvis(acptr)) {
											sendto_channels_inviso_join(acptr);
										}
                                        acptr->umodes &= ~(UMODE_OPER|UMODE_HELPOP|UMODE_SADMIN|UMODE_ADMIN|UMODE_LOCOP|UMODE_SERVICES|UMODE_NETADMIN);
										acptr->umodes &= ~(UMODE_WHOIS|UMODE_KIX|UMODE_HIDEOPER|UMODE_HIDEWHOIS|UMODE_TOTALINVIS|UMODE_MODEWALK|UMODE_NOFAKELAG);
                                        acptr->oflag = 0;
                                        remove_oper_snomasks(acptr);
										sendto_one(acptr, ":%s NOTICE %s :*** Your OFLAGS have been cleared, because this server has been placed in NOOP mode", me.name, acptr->name);
					RunHook2(HOOKTYPE_LOCAL_OPER, acptr, 0);
                                }
                        }

                }
                else
                {
                        SVSNOOP = 0;
                        sendto_ops("This server is no longer in NOOP mode");
                }
        }
	return 0;
}
Ejemplo n.º 6
0
int
BlockHeapFree (BlockHeap * bh, void *ptr)
{
  Block *walker;
  unsigned long ctr;
  unsigned long bitmask;
  if (bh == NULL)
  {
#if defined(USE_SYSLOG) && defined(SYSLOG_BLOCK_ALLOCATOR)
    syslog (LOG_DEBUG, "blalloc.c bh == NULL");
#endif
    return 1;
  }
  for (walker = bh->base; walker != NULL; walker = walker->next)
  {
    if ((ptr >= walker->elems) && (ptr <= walker->endElem))
    {
      ctr = ((unsigned long) ptr - (unsigned long) (walker->elems)) /
        (unsigned long) bh->elemSize;
      bitmask = 1L << (ctr % (sizeof (long) * 8));
      ctr = ctr / (sizeof (long) * 8);
      /* Flip the right allocation bit
       *
       * Complain if the bit is already clear, something is wrong
       * (typically, someone freed the same block twice)
       */
      if ((walker->allocMap[ctr] & bitmask) == 0)
      {
#if defined(USE_SYSLOG) && defined(SYSLOG_BLOCK_ALLOCATOR)
        syslog (LOG_DEBUG, "blalloc.c bit already clear in map!");
#endif
        sendto_ops ("blalloc.c bit already clear in map!");
        sendto_ops
          ("Please report to the development team! [email protected]");
      }
      else
      {
        walker->allocMap[ctr] = walker->allocMap[ctr] & ~bitmask;
        walker->freeElems++;
        bh->freeElems++;
      }
      return 0;
    }
  }
  return 1;
}
Ejemplo n.º 7
0
int m_sdesc(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
	if (!IsAdmin(sptr) && !IsCoAdmin(sptr))
	{
		sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, sptr->name);
		return 0;
	}
	
	if (parc < 2)
	{
		sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, sptr->name, "SDESC");
		return 0;
	}

	if (strlen(parv[1]) < 1)
		if (MyConnect(sptr))
		{
			sendto_one(sptr,
			    ":%s NOTICE %s :*** Nothing to change to (SDESC)",
			    me.name, sptr->name);
			return 0;
		}
	if (strlen(parv[1]) > (REALLEN))
	{
		if (MyConnect(sptr))
		{
			sendto_one(sptr,
			    ":%s NOTICE %s :*** /SDESC Error: \"Server info\" may maximum be %i characters of length",
			    me.name, sptr->name, REALLEN);
		}
		return 0;
	}

	ircsprintf(sptr->srvptr->info, "%s", parv[1]);

	sendto_serv_butone_token(cptr, sptr->name, MSG_SDESC, TOK_SDESC, ":%s",
	    parv[1]);

	if (MyConnect(sptr))
	{
		sendto_one(sptr,
		    ":%s NOTICE %s :Your \"server description\" is now set to be %s - you have to set it manually to undo it",
		    me.name, parv[0], parv[1]);
		return 0;
	}
	sendto_ops("Server description for %s is now '%s' changed by %s",
	    sptr->srvptr->name, sptr->srvptr->info, parv[0]);
	return 0;
}
Ejemplo n.º 8
0
/* Remove a temporary dccdeny line
 * parv[0] - sender
 * parv[1] - file/mask
 */
DLLFUNC CMD_FUNC(m_undccdeny)
{
	ConfigItem_deny_dcc *p;
	if (!MyClient(sptr))
		return 0;

	if (!IsAnOper(sptr) || !OPCanDCCDeny(sptr))
	{
		sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
		return 0;
	}

	if (parc < 2)
	{
		sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0],
		    "UNDCCDENY");
		return 0;
	}

	if (BadPtr(parv[1]))
	{
		sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0],
		    "UNDCCDENY");
		return 0;
	}
/* If we find an exact match even if it is a wild card only remove the exact match -- codemastr */
	if ((p = Find_deny_dcc(parv[1])) && p->flag.type2 == CONF_BAN_TYPE_TEMPORARY)
	{
		sendto_ops("%s removed a temp dccdeny for %s", parv[0],
		    parv[1]);
		DCCdeny_del(p);
		return 1;
	}
/* Next search using the wild card -- codemastr */
/* Uncommented by Stskeeps:
	else if (dcc_del_wild_match(parv[1]) == 1)
		sendto_ops
		    ("%s removed a temp dccdeny for all dccdenys matching %s",
		    parv[0], parv[1]);
*/
/* If still no match, give an error */
	else
		sendto_one(sptr,
		    "NOTICE %s :*** Unable to find a temp dccdeny matching %s",
		    parv[0], parv[1]);
	return 0;

}
Ejemplo n.º 9
0
void server_reboot() 
{
   int     i;
   sendto_ops("Aieeeee!!!  Restarting server... sbrk(0)-etext: %d",
				  (u_int) sbrk((size_t) 0) - (u_int) sbrk0);
	
   Debug((DEBUG_NOTICE, "Restarting server..."));
   dump_connections(me.fd);
   /*
    * fd 0 must be 'preserved' if either the -d or -i options have
    * been passed to us before restarting.
    */
#ifdef USE_SYSLOG
   (void) closelog();
#endif
   for (i = 3; i < MAXCONNECTIONS; i++)
      (void) close(i);

   if (!(bootopt & (BOOT_TTY | BOOT_DEBUG)))
      (void) close(2);

   (void) close(1);

   if ((bootopt & BOOT_CONSOLE))
      (void) close(0);

   if (!(bootopt & (BOOT_INETD)))
      (void) execv(MYNAME, myargv);

#ifdef USE_SYSLOG
   /* Have to reopen since it has been closed above */
   openlog(myargv[0], LOG_PID | LOG_NDELAY, LOG_FACILITY);
   syslog(LOG_CRIT, "execv(%s,%s) failed: %m\n", MYNAME, myargv[0]);
   closelog();
#endif

   Debug((DEBUG_FATAL, "Couldn't restart server: %s", strerror(errno)));
   exit(-1);
}
Ejemplo n.º 10
0
/*
 * m_rnotice (send notice to all users on a given server)
 *      parv[0] = sender prefix
 *      parv[1] = target server
 *	parv[2] = message
 */
int m_rnotice(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{ 
  char* message;
  struct Client *acptr;

  /* firs check if user has enough privileges */
  if (MyClient(sptr) && !IsAnOper(sptr))
    {
      sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
      return(0);
    }

  message = parv[2];      
  /* now check if sufficiente parameters */
  if (EmptyString(message) || parc<3 )
    {
      if(MyClient(sptr))
      sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS),
                 me.name, parv[0], "RNOTICE");
      return 0;
    }
  
  /* check we are the hunted server (send to server if not) */
  if(hunt_server (cptr, sptr, ":%s RNOTICE %s :%s", 1, parc, parv) != HUNTED_ISME)
	return 0;

  for(acptr = local_cptr_list; acptr; acptr = acptr->next_local_client)
    {      
      sendto_one(acptr,":%s NOTICE %s :%s",
         me.name, acptr->name, message);
    }

  sendto_ops("RNOTICE sent by \2%s\2",parv[0]);
  sendto_serv_butone(&me, ":%s GLOBOPS :LNOTICE to %s :%s", 
  	sptr->name, parv[1], parv[2]);

  return 0;      
}	                                 	
Ejemplo n.º 11
0
static void disable_ssl(int do_errors)
{
    if(do_errors)
    {
	char buf[384];
	unsigned long e;

	while((e = ERR_get_error()))
	{
	    ERR_error_string_n(e, buf, sizeof(buf) - 1);
	    sendto_realops("SSL ERROR: %s", buf);
	}
    }

    if(ircdssl_ctx)
    {
	SSL_CTX_free(ircdssl_ctx);
    }

    sendto_ops("Disabling SSL support due to unrecoverable SSL errors. /REHASH again to retry.");
    ssl_capable = 0;
    
    return;
}
Ejemplo n.º 12
0
/* Add a temporary dccdeny line
 *
 * parv[0] - sender
 * parv[1] - file
 * parv[2] - reason
 */
DLLFUNC CMD_FUNC(m_dccdeny)
{
	if (!MyClient(sptr))
		return 0;

	if (!IsAnOper(sptr) || !OPCanDCCDeny(sptr))
	{
		sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
		return 0;
	}
	/* fixup --Stskeeps */
	if (parc < 2)
	{
		sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0],
		    "DCCDENY");
		return 0;
	}
	
	if (BadPtr(parv[2]))
	{
		sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0],
		    "DCCDENY");
		return 0;
	}
	if (!Find_deny_dcc(parv[1]))
	{
		sendto_ops("%s added a temp dccdeny for %s (%s)", parv[0],
		    parv[1], parv[2]);
		DCCdeny_add(parv[1], parv[2], DCCDENY_HARD, CONF_BAN_TYPE_TEMPORARY);
		return 0;
	}
	else
		sendto_one(sptr, "NOTICE %s :*** %s already has a dccdeny", parv[0],
		    parv[1]);
	return 0;
}
Ejemplo n.º 13
0
/*
** deliver_it
**	Attempt to send a sequence of bytes to the connection.
**	Returns
**
**	< 0	Some fatal error occurred, (but not EWOULDBLOCK).
**		This return is a request to close the socket and
**		clean up the link.
**	
**	>= 0	No real error occurred, returns the number of
**		bytes actually transferred. EWOULDBLOCK and other
**		possibly similar conditions should be mapped to
**		zero return. Upper level routine will have to
**		decide what to do with those unwritten bytes...
**
**	*NOTE*	alarm calls have been preserved, so this should
**		work equally well whether blocking or non-blocking
**		mode is used...
**
**	*NOTE*	I nuked 'em.  At the load of current ircd servers
**		you can't run with stuff that blocks. And we don't.
*/
int  deliver_it(aClient *cptr, char *str, int len)
{
	int  retval;
	aClient *acpt = cptr->listener;

#ifdef	DEBUGMODE
	writecalls++;
#endif
#ifdef VMS
	retval = netwrite(cptr->fd, str, len);
#else
	if (IsDead(cptr) || (!IsServer(cptr) && !IsPerson(cptr)
	    && !IsHandshake(cptr) 
#ifdef USE_SSL
	    && !IsSSLHandshake(cptr)
#endif 
 
	    && !IsUnknown(cptr)))
	{
		str[len] = '\0';
		sendto_ops
		    ("* * * DEBUG ERROR * * * !!! Calling deliver_it() for %s, status %d %s, with message: %s",
		    cptr->name, cptr->status, IsDead(cptr) ? "DEAD" : "", str);
		return -1;
	}

#ifdef USE_SSL
	if (cptr->flags & FLAGS_SSL)
		 retval = ircd_SSL_write(cptr, str, len);	
	else
#endif
		retval = send(cptr->fd, str, len, 0);
	/*
	   ** Convert WOULDBLOCK to a return of "0 bytes moved". This
	   ** should occur only if socket was non-blocking. Note, that
	   ** all is Ok, if the 'write' just returns '0' instead of an
	   ** error and errno=EWOULDBLOCK.
	   **
	   ** ...now, would this work on VMS too? --msa
	 */
# ifndef _WIN32
	if (retval < 0 && (errno == EWOULDBLOCK || errno == EAGAIN ||
	    errno == ENOBUFS))
# else
		if (retval < 0 && (WSAGetLastError() == WSAEWOULDBLOCK ||
		    WSAGetLastError() == WSAENOBUFS))
# endif
		{
			retval = 0;
			SetBlocked(cptr);
		}
		else if (retval > 0)
		{
			ClearBlocked(cptr);
		}

#endif
#ifdef DEBUGMODE
	if (retval < 0)
	{
		writeb[0]++;
		Debug((DEBUG_ERROR, "write error (%s) to %s", STRERROR(ERRNO), cptr->name));

	}
	else if (retval == 0)
		writeb[1]++;
	else if (retval < 16)
		writeb[2]++;
	else if (retval < 32)
		writeb[3]++;
	else if (retval < 64)
		writeb[4]++;
	else if (retval < 128)
		writeb[5]++;
	else if (retval < 256)
		writeb[6]++;
	else if (retval < 512)
		writeb[7]++;
	else if (retval < 1024)
		writeb[8]++;
	else
		writeb[9]++;
#endif
	if (retval > 0)
	{
		cptr->sendB += retval;
		me.sendB += retval;
		if (cptr->sendB > 1023)
		{
			cptr->sendK += (cptr->sendB >> 10);
			cptr->sendB &= 0x03ff;	/* 2^10 = 1024, 3ff = 1023 */
		}
Ejemplo n.º 14
0
/*
 * start_auth
 *
 * Flag the client to show that an attempt to contact the ident server on
 * the client's host.  The connect and subsequently the socket are all put
 * into 'non-blocking' mode.  Should the connect or any later phase of the
 * identifing process fail, it is aborted and the user is given a username
 * of "unknown".
 */
void	start_auth(aClient *cptr)
{
  struct sockaddr_in	sock;
  struct sockaddr_in	localaddr;
  int			locallen;

  Debug((DEBUG_NOTICE,"start_auth(%x) fd %d status %d",
	 cptr, cptr->fd, cptr->status));
  if ((cptr->authfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
#ifdef	USE_SYSLOG
      syslog(LOG_ERR, "Unable to create auth socket for %s:%m",
	     get_client_name(cptr,TRUE));
#endif
      if (!DoingDNS(cptr))
	SetAccess(cptr);
      ircstp->is_abad++;
      return;
    }
  if (cptr->authfd >= MAXCONNECTIONS)
    {
      sendto_ops("Can't allocate fd for auth on %s",
		 get_client_name(cptr, TRUE));
      (void)close(cptr->authfd);
      return;
    }
#ifdef SHOW_HEADERS
  send(cptr->fd, REPORT_DO_ID, R_do_id, 0);
#endif
  set_non_blocking(cptr->authfd, cptr);

  /* get the local address of the client and bind to that to
   * make the auth request.  This used to be done only for
   * ifdef VIRTTUAL_HOST, but needs to be done for all clients
   * since the ident request must originate from that same address--
   * and machines with multiple IP addresses are common now
   */
  locallen = sizeof(struct sockaddr_in);
  bzero(&localaddr, locallen);
  getsockname(cptr->fd, (struct sockaddr *)&localaddr, &locallen);
  localaddr.sin_port = htons(0);

  if (bind(cptr->authfd, (struct sockaddr *)&localaddr,
	   sizeof(localaddr)) == -1)
    {
      report_error("binding auth stream socket %s:%s", cptr);
      (void)close(cptr->fd);
      return;
    }

  bcopy((char *)&cptr->ip, (char *)&sock.sin_addr,
	sizeof(struct in_addr));
  
  sock.sin_port = htons(113);
  sock.sin_family = AF_INET;

/*	(void)alarm((unsigned)4);*/
  if (connect(cptr->authfd, (struct sockaddr *)&sock,
	      sizeof(sock)) == -1 && errno != EINPROGRESS)
    {
      ircstp->is_abad++;
      /*
       * No error report from this...
       */
      /*		(void)alarm((unsigned)0);*/
      (void)close(cptr->authfd);
      cptr->authfd = -1;
      if (!DoingDNS(cptr))
	SetAccess(cptr);
#ifdef SHOW_HEADERS
      send(cptr->fd, REPORT_FAIL_ID, R_fail_id, 0);
#endif
      return;
    }
  /*	(void)alarm((unsigned)0);*/
  cptr->flags |= (FLAGS_WRAUTH|FLAGS_AUTH);
  if (cptr->authfd > highest_fd)
    highest_fd = cptr->authfd;
  return;
}
Ejemplo n.º 15
0
/*
 * Exit one client, local or remote. Assuming all dependants have
 * been already removed, and socket closed for local client.
 */
static void 
exit_one_client(aClient *cptr, aClient *sptr, aClient *from, char *comment)
{
    Link   *lp;
    
    /*
     * For a server or user quitting, propogate the information to
     * other servers (except to the one where is came from (cptr))
     */
    if (IsMe(sptr))
    {
        sendto_ops("ERROR: tried to exit me! : %s", comment);
        return;                 /* ...must *never* exit self!! */
    }
    else if (IsServer(sptr))
    {
#ifdef ALWAYS_SEND_DURING_SPLIT
        currently_processing_netsplit = YES;
#endif

        exit_server(cptr, sptr, from, comment);
        
#ifdef ALWAYS_SEND_DURING_SPLIT
        currently_processing_netsplit = NO;
#endif
        return;
    }
    else if (!(IsPerson(sptr)))
        /*
         * ...this test is *dubious*, would need * some thought.. but for
         * now it plugs a * nasty hole in the server... --msa
         */
        ;                               /* Nothing */
    else if (sptr->name[0])
    {   
        /* ...just clean all others with QUIT... */
        /*
         * If this exit is generated from "m_kill", then there is no
         * sense in sending the QUIT--KILL's have been sent instead.
         */
        if ((sptr->flags & FLAGS_KILLED) == 0) 
        {
            sendto_serv_butone(cptr, ":%s QUIT :%s",
                               sptr->name, comment);
        }
        /*
         * * If a person is on a channel, send a QUIT notice * to every
         * client (person) on the same channel (so * that the client can
         * show the "**signoff" message). * (Note: The notice is to the
         * local clients *only*)
         */
        if (sptr->user)
        {
            send_part_to_common_channels(sptr, comment);
            send_quit_to_common_channels(sptr, comment);
            while ((lp = sptr->user->channel))
                remove_user_from_channel(sptr, lp->value.chptr);

	    clones_remove(sptr);

#ifdef RWHO_PROBABILITY
            probability_remove(sptr);
#endif
            
            /* Clean up invitefield */
            while ((lp = sptr->user->invited))
                del_invite(sptr, lp->value.chptr);
            /* Clean up silences */
            while ((lp = sptr->user->silence)) 
                del_silence(sptr, lp->value.cp);
            remove_dcc_references(sptr);
            /* again, this is all that is needed */
        }
    }

    /* Remove sptr from the client list */
    if (del_from_client_hash_table(sptr->name, sptr) != 1) 
    {
        Debug((DEBUG_ERROR, "%#x !in tab %s[%s] %#x %#x %#x %d %d %#x",
               sptr, sptr->name,
               sptr->from ? sptr->from->sockhost : "??host",
               sptr->from, sptr->next, sptr->prev, sptr->fd,
               sptr->status, sptr->user));
    }
    /* remove user from watchlists */
    if(IsRegistered(sptr))
        hash_check_watch(sptr, RPL_LOGOFF);
    remove_client_from_list(sptr);
    return;
}
Ejemplo n.º 16
0
/*
 *  exit_client 
 * This is old "m_bye". Name  changed, because this is not a
 * protocol function, but a general server utility function.
 * 
 *      This function exits a client of *any* type (user, server, etc) 
 * from this server. Also, this generates all necessary prototol 
 * messages that this exit may cause. 
 * 
 *   1) If the client is a local client, then this implicitly exits
 * all other clients depending on this connection (e.g. remote
 * clients having 'from'-field that points to this. 
 * 
 *   2) If the client is a remote client, then only this is exited. 
 * 
 * For convenience, this function returns a suitable value for 
 * m_function return value: 
 * 
 *      FLUSH_BUFFER    if (cptr == sptr) 
 *      0 if (cptr != sptr)
 */
int 
exit_client(aClient *cptr, aClient *sptr, aClient *from, char *comment)
{
#ifdef  FNAME_USERLOG
    time_t on_for;
#endif
    
    if (MyConnect(sptr)) 
    {
        call_hooks(CHOOK_SIGNOFF, sptr);

        if (IsUnknown(sptr))
            Count.unknown--;
        if (IsAnOper(sptr)) 
            remove_from_list(&oper_list, sptr, NULL);
        if (sptr->flags & FLAGS_HAVERECVQ)
        {
            /* mark invalid, will be deleted in do_recvqs() */
            DLink *lp = find_dlink(recvq_clients, sptr);
            if (lp)
                lp->flags = -1;
        }
        if (IsClient(sptr))
            Count.local--;
        if (IsNegoServer(sptr))
            sendto_realops("Lost server %s during negotiation: %s", 
                           sptr->name, comment);
        
        if (IsServer(sptr)) 
        {
            Count.myserver--;
            if (IsULine(sptr))
                Count.myulined--;
            remove_from_list(&server_list, sptr, NULL);
            if (server_list == NULL) 
                server_was_split = YES;
        }
        sptr->flags |= FLAGS_CLOSING;
        if (IsPerson(sptr)) 
        {
            Link *lp, *next;
            LOpts *lopt = sptr->user->lopt;
            /* poof goes their watchlist! */
            hash_del_watch_list(sptr);
            /* if they have listopts, axe those, too */
            if(lopt != NULL) 
            {
                remove_from_list(&listing_clients, sptr, NULL);
                for (lp = lopt->yeslist; lp; lp = next) 
                {
                    next = lp->next;
                    MyFree(lp->value.cp);
                    free_link(lp);
                }
                for (lp = lopt->nolist; lp; lp = next) 
                {
                    next = lp->next;
                    MyFree(lp->value.cp);
                    free_link(lp);
                }
                                
                MyFree(sptr->user->lopt);
                sptr->user->lopt = NULL;
            }
            sendto_realops_lev(CCONN_LEV,
                               "Client exiting: %s (%s@%s) [%s] [%s]",
                               sptr->name, sptr->user->username,
                               sptr->user->host,
                               (sptr->flags & FLAGS_NORMALEX) ?
                               "Client Quit" : comment,
                               sptr->hostip);
        }
#ifdef FNAME_USERLOG
        on_for = timeofday - sptr->firsttime;
#endif
#if defined(USE_SYSLOG) && defined(SYSLOG_USERS)
        if (IsPerson(sptr))
            syslog(LOG_NOTICE, "%s (%3d:%02d:%02d): %s!%s@%s %d/%d\n",
                   myctime(sptr->firsttime),
                   on_for / 3600, (on_for % 3600) / 60,
                   on_for % 60, sptr->name,
                   sptr->user->username, sptr->user->host,
                   sptr->sendK, sptr->receiveK);
#endif
#if defined(FNAME_USERLOG)
        {
            char        linebuf[300];
            static int  logfile = -1;
            static long lasttime;
            
            /*
             * This conditional makes the logfile active only after it's
             * been created - thus logging can be turned off by removing
             * the file.
             * 
             * stop NFS hangs...most systems should be able to open a file in
             * 3 seconds. -avalon (curtesy of wumpus)
             * 
             * Keep the logfile open, syncing it every 10 seconds -Taner
             */
            if (IsPerson(sptr)) 
            {
                if (logfile == -1) 
                {
                    alarm(3);
                    logfile = open(FNAME_USERLOG, O_WRONLY | O_APPEND);
                    alarm(0);
                }
                ircsprintf(linebuf, "%s (%3d:%02d:%02d): %s!%s@%s %d/%d\n",
                           myctime(sptr->firsttime), on_for / 3600,
                           (on_for % 3600) / 60, on_for % 60,
                           sptr->name, sptr->user->username,
                           sptr->user->host, sptr->sendK, sptr->receiveK);
                alarm(3);
                write(logfile, linebuf, strlen(linebuf));
                alarm(0);
                /* Resync the file evey 10 seconds*/
                if (timeofday - lasttime > 10) 
                {
                    alarm(3);
                    close(logfile);
                    alarm(0);
                    logfile = -1;
                    lasttime = timeofday;
                }
            }
        }
#endif
        if (sptr->fd >= 0) 
        {
            if (cptr != NULL && sptr != cptr)
              sendto_one(&me, sptr, "ERROR :Closing Link: %s %s (%s)",
                           IsPerson(sptr) ? sptr->sockhost : "0.0.0.0", 
                           sptr->name, comment);
            else
              sendto_one(&me, sptr, "ERROR :Closing Link: %s (%s)",
                           IsPerson(sptr) ? sptr->sockhost : "0.0.0.0", 
                           comment);
        }
        /*
         * * Currently only server connections can have * depending
         * remote clients here, but it does no * harm to check for all
         * local clients. In * future some other clients than servers
         * might * have remotes too... *
         * 
         * Close the Client connection first and mark it * so that no
         * messages are attempted to send to it. *, The following *must*
         * make MyConnect(sptr) == FALSE!). * It also makes sptr->from ==
         * NULL, thus it's unnecessary * to test whether "sptr != acptr"
         * in the following loops.
         */
        if (IsServer(sptr)) 
        {
            sendto_ops("%s was connected for %lu seconds.  %lu/%lu "
                       "sendK/recvK.", sptr->name,
		       (long)(timeofday - sptr->firsttime),
                       sptr->sendK, sptr->receiveK);
#ifdef USE_SYSLOG
            syslog(LOG_NOTICE, "%s was connected for %lu seconds.  %lu/%lu "
                   "sendK/recvK.", sptr->name, 
                        (u_long) timeofday - sptr->firsttime,
                   sptr->sendK, sptr->receiveK);
#endif
            close_connection(sptr);
            sptr->sockerr = 0;
            sptr->flags |= FLAGS_DEADSOCKET;
        }
        else
        {
            close_connection(sptr);
            sptr->sockerr = 0;
            sptr->flags |= FLAGS_DEADSOCKET;
        }
                
    }
    exit_one_client(cptr, sptr, from, comment);
    return cptr == sptr ? FLUSH_BUFFER : 0;
}
Ejemplo n.º 17
0
/*
 *  m_server
 *       parv[0] = sender prefix
 *       parv[1] = servername
 *       parv[2] = serverinfo/hopcount
 *       parv[3] = serverinfo
 */
int m_server(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
    int     i;
    char        info[REALLEN + 1], *host;
    aClient    *acptr, *bcptr;
    aConnect   *aconn;
    int         hop;
    char        nbuf[HOSTLEN * 2 + USERLEN + 5]; /* same size as in s_misc.c */

    info[0] = '\0';

    if (parc < 2 || *parv[1] == '\0')
    {
        sendto_one(cptr, "ERROR :No servername");
        return 0;
    }

    hop = 0;
    host = parv[1];
    if (parc > 3 && atoi(parv[2]))
    {
        hop = atoi(parv[2]);
        strncpyzt(info, parv[3], REALLEN + 1);
    }
    else if (parc > 2)
    {
        strncpyzt(info, parv[2], REALLEN + 1);
        if ((parc > 3) && ((i = strlen(info)) < (REALLEN - 2)))
        {
            strcat(info, " ");
            strncat(info, parv[3], REALLEN - i - 2);
            info[REALLEN] = '\0';
        }
    }
    /*
     * July 5, 1997
     * Rewritten to throw away server cruft from users,
     * combined the hostname validity test with cleanup of host name,
     * so a cleaned up hostname can be returned as an error if
     * necessary. - Dianora
     */

    /* yes, the if(strlen) below is really needed!! */
    if (strlen(host) > HOSTLEN)
        host[HOSTLEN] = '\0';

    if (IsPerson(cptr))
    {
        /* A local link that has been identified as a USER tries
         * something fishy... ;-)
         */
        sendto_one(cptr, err_str(ERR_UNKNOWNCOMMAND),
                   me.name, parv[0], "SERVER");

        return 0;
    }
    else
        /* hostile servername check */
    {
        /*
         * Lets check for bogus names and clean them up we don't bother
         * cleaning up ones from users, becasuse we will never see them
         * any more - Dianora
         */

        int bogus_server = 0;
        int found_dot = 0;
        char clean_host[(2 * HOSTLEN) + 1];
        char *s;
        char *d;
        int n;

        s = host;
        d = clean_host;
        n = (2 * HOSTLEN) - 2;

        while (*s && n > 0)
        {
            if ((unsigned char) *s < (unsigned char) ' ')
                /* Is it a control character? */
            {
                bogus_server = 1;
                *d++ = '^';
                *d++ = (char) ((unsigned char) *s + 0x40);
                /* turn it into a printable */
                n -= 2;
            }
            else if ((unsigned char) *s > (unsigned char) '~')
            {
                bogus_server = 1;
                *d++ = '.';
                n--;
            }
            else
            {
                if (*s == '.')
                    found_dot = 1;
                *d++ = *s;
                n--;
            }
            s++;
        }
        *d = '\0';

        if ((!found_dot) || bogus_server)
        {
            sendto_one(sptr, "ERROR :Bogus server name (%s)",
                       clean_host);
            return exit_client(cptr, cptr, cptr, "Bogus server name");
        }
    }

    /* new connection */
    if (IsUnknown(cptr) || IsHandshake(cptr))
    {
        strncpyzt(cptr->name, host, sizeof(cptr->name));
        strncpyzt(cptr->info, info[0] ? info : me.name, REALLEN + 1);
        cptr->hopcount = hop;

        switch (check_server_init(cptr))
        {
            case 0:
                return m_server_estab(cptr);
            case 1:
                sendto_ops("Access check for %s in progress",
                           get_client_name(cptr, HIDEME));
                return 1;
            default:
                ircstp->is_ref++;
                sendto_ops_lev(ADMIN_LEV, "Link %s dropped, no Connect block",
                           get_client_name(cptr, TRUE));
                return exit_client(cptr, cptr, cptr, "No Connect block");
        }
    }
    
    /* already linked server */
    if (!IsServer(cptr))
        return 0;

    if ((acptr = find_name(host, NULL)))
    {
        /*
         * * This link is trying feed me a server that I already have
         * access through another path -- multiple paths not accepted
         * currently, kill this link immediately!!
         *
         * Rather than KILL the link which introduced it, KILL the
         * youngest of the two links. -avalon
         */

        bcptr = (cptr->firsttime > acptr->from->firsttime) ? cptr :
            acptr->from;
        sendto_one(bcptr, "ERROR :Server %s already exists", host);
        if (bcptr == cptr)
        {
            /* Don't complain for servers that are juped */
            /* (don't complain if the server that already exists is U: lined,
                unless I actually have a .conf U: line for it */
            if(!IsULine(acptr) || find_aUserver(acptr->name))
            {
                sendto_gnotice("from %s: Link %s cancelled, server %s already "
                               "exists", me.name, get_client_name(bcptr, HIDEME),
                               host);
                sendto_serv_butone(bcptr, ":%s GNOTICE :Link %s cancelled, "
                                   "server %s already exists", me.name,
                                   get_client_name(bcptr, HIDEME), host);
            }
            return exit_client(bcptr, bcptr, &me, "Server Exists");
        }
        /* inform all those who care (set +n) -epi */
        strcpy(nbuf, get_client_name(bcptr, HIDEME));
        sendto_gnotice("from %s: Link %s cancelled, server %s reintroduced "
                       "by %s", me.name, nbuf, host,
                       get_client_name(cptr, HIDEME));
        sendto_serv_butone(bcptr, ":%s GNOTICE :Link %s cancelled, server %s "
                           "reintroduced by %s", me.name, nbuf, host,
                           get_client_name(cptr, HIDEME));
        exit_client(bcptr, bcptr, &me, "Server Exists");
    }
    /*
     * The following if statement would be nice to remove since user
     * nicks never have '.' in them and servers must always have '.' in
     * them. There should never be a server/nick name collision, but it
     * is possible a capricious server admin could deliberately do
     * something strange.
     *
     * -Dianora
     */

    if ((acptr = find_client(host, NULL)) && acptr != cptr)
    {
        /*
         * * Server trying to use the same name as a person. Would
         * cause a fair bit of confusion. Enough to make it hellish for
         * a while and servers to send stuff to the wrong place.
         */
        sendto_one(cptr, "ERROR :Nickname %s already exists!", host);
        strcpy(nbuf, get_client_name(cptr, HIDEME));
        sendto_gnotice("from %s: Link %s cancelled, servername/nick collision",
                       me.name, nbuf);
        sendto_serv_butone(cptr, ":%s GNOTICE :Link %s cancelled, "
                           "servername/nick collision", me.name, nbuf);
        return exit_client(cptr, cptr, cptr, "Nick as Server");
    }

    if (IsServer(cptr))
    {
        /*
         * * Server is informing about a new server behind this link.
         * Create REMOTE server structure, add it to list and propagate
         * word to my other server links...
         */
        if (parc == 1 || info[0] == '\0')
        {
            sendto_one(cptr, "ERROR :No server info specified for %s", host);
            return 0;
        }
        /*
         * * See if the newly found server is behind a guaranteed leaf
         * (L-line). If so, close the link.
         *
         * Depreciated.  Kinda redundant with Hlines. -epi
         */
        if (!(cptr->serv->aconn->flags & CONN_HUB))
        {
            aconn = cptr->serv->aconn;
            sendto_gnotice("from %s: Non-Hub link %s introduced %s",
                           me.name, get_client_name(cptr, HIDEME), host);
            sendto_serv_butone(cptr,":%s GNOTICE :Non-Hub link %s introduced "
                               "%s", me.name, get_client_name(cptr, HIDEME),
                               host);
            sendto_one(cptr, "ERROR :You're not a hub (introducing %s)",
                       host);
            return exit_client(cptr, cptr, cptr, "Too many servers");
        }

        acptr = make_client(cptr, sptr);
        make_server(acptr);
        acptr->hopcount = hop;
        strncpyzt(acptr->name, host, sizeof(acptr->name));
        strncpyzt(acptr->info, info, REALLEN + 1);
        acptr->serv->up = find_or_add(parv[0]);

        fakelinkserver_update(acptr->name, acptr->info);
        SetServer(acptr);

        /*
         * if this server is behind a U-lined server, make it U-lined as
         * well. - lucas
         */

        if (IsULine(sptr) || find_aUserver(acptr->name))
        {
            acptr->flags |= FLAGS_ULINE;
            sendto_realops_lev(DEBUG_LEV, "%s introducing super server %s",
                               cptr->name, acptr->name);
        }

        Count.server++;

        add_client_to_list(acptr);
        add_to_client_hash_table(acptr->name, acptr);
        /*
         * Old sendto_serv_but_one() call removed because we now need
         * to send different names to different servers (domain name matching)
         */
        for (i = 0; i <= highest_fd; i++)
        {
            if (!(bcptr = local[i]) || !IsServer(bcptr) || bcptr == cptr ||
                IsMe(bcptr))
                continue;
            if (!(aconn = bcptr->serv->aconn))
            {
                sendto_gnotice("from %s: Lost Connect block for %s on %s."
                               " Closing", me.name,
                               get_client_name(cptr, HIDEME), host);
                sendto_serv_butone(cptr, ":%s GNOTICE :Lost Connect block for"
                                   " %s on %s. Closing", me.name,
                                   get_client_name(cptr, HIDEME), host);
                return exit_client(cptr, cptr, cptr, "Lost Connect block");
            }
            if (match(my_name_for_link(me.name, aconn), acptr->name) == 0)
                continue;
            sendto_one(bcptr, ":%s SERVER %s %d :%s",
                       parv[0], acptr->name, hop + 1, acptr->info);
        }
        return 0;
    }

    return 0;
}
Ejemplo n.º 18
0
static time_t io_loop(time_t delay)
{
  static char   to_send[200];
  static time_t lasttime  = 0;
  static long   lastrecvK = 0;
  static int    lrv       = 0;
  time_t        lasttimeofday;
  lasttimeofday = CurrentTime;

  if (CurrentTime < lasttimeofday)
    {
      ircsprintf(to_send, "System clock is running backwards - (%d < %d)",
                 CurrentTime, lasttimeofday);
      report_error(to_send, me.name, 0);
    }
  if(!next_gc)
    {
  	next_gc = CurrentTime + 600;
    }

  /*
   * This chunk of code determines whether or not
   * "life sucks", that is to say if the traffic
   * level is so high that standard server
   * commands should be restricted
   *
   * Changed by Taner so that it tells you what's going on
   * as well as allows forced on (long LCF), etc...
   */
  
  if ((CurrentTime - lasttime) >= LCF)
    {
      lrv = LRV * LCF;
      lasttime = CurrentTime;
      currlife = (float)((long)me.receiveK - lastrecvK)/(float)LCF;
      if (((long)me.receiveK - lrv) > lastrecvK )
        {
          if (!LIFESUX)
            {
              LIFESUX = 1;

              if (NOISYHTM)
                {
                  sprintf(to_send, 
                        "Entering high-traffic mode - (%.1fk/s > %dk/s)",
                                (float)currlife, LRV);
                  sendto_ops("%s", to_send);
                }
            }
          else
            {
              LIFESUX++;                /* Ok, life really sucks! */
              LCF += 2;                 /* Wait even longer */
              if (NOISYHTM) 
                {
                  sprintf(to_send,
                        "Still high-traffic mode %d%s (%d delay): %.1fk/s",
                                LIFESUX,
                                (LIFESUX & 0x04) ?  " (TURBO)" : "",
                                (int)LCF, (float)currlife);
                  sendto_ops("%s", to_send);
                }
            }
        }
      else
        {
          LCF = LOADCFREQ;
          if (LIFESUX)
            {
              LIFESUX = 0;
              if (NOISYHTM)
                sendto_ops("Resuming standard operation . . . .");
            }
        }
      lastrecvK = (long)me.receiveK;
    }

  /*
  ** We only want to connect if a connection is due,
  ** not every time through.  Note, if there are no
  ** active C lines, this call to Tryconnections is
  ** made once only; it will return 0. - avalon
  */
  if (nextconnect && CurrentTime >= nextconnect)
    nextconnect = try_connections(CurrentTime);

  /*
  ** take the smaller of the two 'timed' event times as
  ** the time of next event (stops us being late :) - avalon
  ** WARNING - nextconnect can return 0!
  */
  if (nextconnect)
    delay = IRCD_MIN(nextping, nextconnect);
  delay -= CurrentTime;
  /*
  ** Adjust delay to something reasonable [ad hoc values]
  ** (one might think something more clever here... --msa)
  ** We don't really need to check that often and as long
  ** as we don't delay too long, everything should be ok.
  ** waiting too long can cause things to timeout...
  ** i.e. PINGS -> a disconnection :(
  ** - avalon
  */
  if (delay < 1)
    delay = 1;
  else
    delay = IRCD_MIN(delay, TIMESEC);
  /*
   * We want to read servers on every io_loop, as well
   * as "busy" clients (which again, includes servers.
   * If "lifesux", then we read servers AGAIN, and then
   * flush any data to servers.
   *    -Taner
   */

#ifndef NO_PRIORITY
  read_message(0, FDL_SERVER);
  read_message(0, FDL_BUSY);
  if (LIFESUX)
    {
      read_message(0, FDL_SERVER);
      if (LIFESUX & 0x4)
        {       /* life really sucks */
          read_message(0, FDL_BUSY);
          read_message(0, FDL_SERVER);
        }
      flush_server_connections();
    }

  /*
   * CLIENT_SERVER = TRUE:
   *    If we're in normal mode, or if "lifesux" and a few
   *    seconds have passed, then read everything.
   * CLIENT_SERVER = FALSE:
   *    If it's been more than lifesux*2 seconds (that is, 
   *    at most 1 second, or at least 2s when lifesux is
   *    != 0) check everything.
   *    -Taner
   */
  {
    static time_t lslasttime=0;
#ifdef CLIENT_SERVER
    if (!LIFESUX || (lslasttime + LIFESUX) < CurrentTime)
      {
#else
    if ((lslasttime + (LIFESUX + 1)) < CurrentTime)
      {
#endif
        read_message(0, FDL_ALL); /*  check everything! */
        lslasttime = CurrentTime;
      }
   }
#else
  read_message(0, FDL_ALL); /*  check everything! */
  flush_server_connections();
#endif

  /*
  ** ...perhaps should not do these loops every time,
  ** but only if there is some chance of something
  ** happening (but, note that conf->hold times may
  ** be changed elsewhere--so precomputed next event
  ** time might be too far away... (similarly with
  ** ping times) --msa
  */

  if (CurrentTime >= nextping) {
    nextping = check_pings(CurrentTime);
    timeout_auth_queries(CurrentTime);
  }

  if (dorehash && !LIFESUX)
    {
      rehash(&me, &me, 1);
      dorehash = 0;
    }
  /*
  ** Flush output buffers on all connections now if they
  ** have data in them (or at least try to flush)
  ** -avalon
  */
  flush_connections(0);

#ifndef NO_PRIORITY
  fdlist_check(CurrentTime);
#endif
  
  if(CurrentTime >= next_gc)
  {
     block_garbage_collect();
     next_gc = CurrentTime + 600;
  }

  return delay;

}

/*
 * initalialize_global_set_options
 *
 * inputs       - none
 * output       - none
 * side effects - This sets all global set options needed 
 */

static void initialize_global_set_options(void)
{
  memset( &GlobalSetOptions, 0, sizeof(GlobalSetOptions));

  MAXCLIENTS = MAX_CLIENTS;
  NOISYHTM = NOISY_HTM;
  GlobalSetOptions.autoconn = 1;

#ifdef FLUD
  FLUDNUM = FLUD_NUM;
  FLUDTIME = FLUD_TIME;
  FLUDBLOCK = FLUD_BLOCK;
#endif

#ifdef IDLE_CHECK
  IDLETIME = MIN_IDLETIME;
#endif

#ifdef ANTI_SPAMBOT
  SPAMTIME = MIN_JOIN_LEAVE_TIME;
  SPAMNUM = MAX_JOIN_LEAVE_COUNT;
#endif

#ifdef ANTI_DRONE_FLOOD
  DRONETIME = DEFAULT_DRONE_TIME;
  DRONECOUNT = DEFAULT_DRONE_COUNT;
#endif

#ifdef NEED_SPLITCODE
 SPLITDELAY = (DEFAULT_SERVER_SPLIT_RECOVERY_TIME * 60);
 SPLITNUM = SPLIT_SMALLNET_SIZE;
 SPLITUSERS = SPLIT_SMALLNET_USER_SIZE;
 server_split_time = CurrentTime;
#endif

 /* End of global set options */

}
Ejemplo n.º 19
0
/*
 * m_ungline
 * Remove a local user@host ban.
 *
 *     parv[0] = sender
 *     parv[1] = user@host mask
 */
int m_ungline(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
    char hbuf[512];
    char *user;
    char *host;
    struct userBan *ban;
    struct userBan *existing;

    if (!IsPrivileged(sptr))
    {
        sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
        return 0;
    }

    if (parc < 2)
    {
        sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0],
                   "UNGline");
        return 0;
    }

    if ((host = strchr(parv[1], '@')))
    {
        *host++ = 0;
        user = parv[1];
    }
    else
    {
        user = "******";
        host = parv[1];
    }

    if (!(ban = make_hostbased_ban(user, host)))
    {
        sendto_one(sptr, ":%s NOTICE %s :UNGline: No such ban %s@%s", me.name,
                   parv[0], user, host);
        return 0;
    }

    ban->flags |= UBAN_GLINE;
    existing = find_userban_exact(ban, UBAN_GLINE);
    host = get_userban_host(ban, hbuf, sizeof(hbuf));
    userban_free(ban);

    if (!existing)
    {
        sendto_one(sptr, ":%s NOTICE %s :UNGLINE: No such ban %s@%s", me.name,
                   parv[0], user, host);
        return 0;
    }

    if (existing->flags & UBAN_CONF)
    {
        sendto_one(sptr, ":%s NOTICE %s :UNGLINE: %s@%s is specified in the"
                   " configuration file and cannot be removed online", me.name,
                   parv[0], user, host);
        return 0;
    }

    remove_userban(existing);
    glinestore_remove(existing);
    userban_free(existing);

    sendto_ops("%s has removed the G-Line for: [%s@%s]", sptr->name, user, host);
    sendto_serv_butone(MyConnect(sptr) ? NULL : cptr, ":%s UNGLINE %s@%s", sptr->name, user, host);
    return 0;
}
Ejemplo n.º 20
0
/*
 * m_htm - HTM command handler
 * high traffic mode info
 */
int m_htm(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  char *command;

  if (!MyClient(sptr) || !IsOper(sptr))
    {
      sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
      return 0;
    }
  sendto_one(sptr,
        ":%s NOTICE %s :HTM is %s(%d), %s. Max rate = %dk/s. Current = %.1fk/s",
          me.name, parv[0], LIFESUX ? "ON" : "OFF", LIFESUX,
          NOISYHTM ? "NOISY" : "QUIET",
          LRV, currlife);
  if (parc > 1)
    {
      command = parv[1];
      if (!irccmp(command,"TO"))
        {
          if (parc > 2)
            {
              int new_value = atoi(parv[2]);
              if (new_value < 10)
                {
                  sendto_one(sptr, ":%s NOTICE %s :Cannot set LRV < 10!",
                             me.name, parv[0]);
                }
              else
                LRV = new_value;
              sendto_one(sptr, ":%s NOTICE %s :NEW Max rate = %dk/s. Current = %.1fk/s",
                         me.name, parv[0], LRV, currlife);
              sendto_realops("%s!%s@%s set new HTM rate to %dk/s (%.1fk/s current)",
                             parv[0], sptr->username, sptr->host,
                             LRV, currlife);
            }
          else 
            sendto_one(sptr, ":%s NOTICE %s :LRV command needs an integer parameter",me.name, parv[0]);
        }
      else
        {
          if (!irccmp(command,"ON"))
            {
              LIFESUX = 1;
              sendto_one(sptr, ":%s NOTICE %s :HTM is now ON.", me.name, parv[0]);
              sendto_ops("Entering high-traffic mode: Forced by %s!%s@%s",
                         parv[0], sptr->username, sptr->host);
              LCF = 30; /* 30s */
            }
          else if (!irccmp(command,"OFF"))
            {
              LIFESUX = 0;
              LCF = LOADCFREQ;
              sendto_one(sptr, ":%s NOTICE %s :HTM is now OFF.", me.name, parv[0]);
              sendto_ops("Resuming standard operation: Forced by %s!%s@%s",
                         parv[0], sptr->username, sptr->host);
            }
          else if (!irccmp(command,"QUIET"))
            {
              sendto_ops("HTM is now QUIET");
              NOISYHTM = NO;
            }
          else if (!irccmp(command,"NOISY"))
            {
              sendto_ops("HTM is now NOISY");
              NOISYHTM = YES;
            }
          else
            sendto_one(sptr,
                       ":%s NOTICE %s :Commands are:HTM [ON] [OFF] [TO int] [QUIET] [NOISY]",
                       me.name, parv[0]);
        }
    }
  return 0;
}
Ejemplo n.º 21
0
int
main(int argc, char *argv[])
{
   uid_t         uid, euid;
   int           portarg = 0,  fd;
#ifdef SAVE_MAXCLIENT_STATS
   FILE 	*mcsfp;
#endif

   memset(&me, 0, sizeof(aClient));
	
   if ((timeofday = time(NULL)) == -1) 
   {
      (void) fprintf(stderr, "ERROR: Clock Failure (%d)\n", errno);
      exit(errno);
   }
	
   build_version();
	
   Count.server = 1;		/* us */
   Count.oper = 0;
   Count.chan = 0;
   Count.local = 0;
   Count.total = 0;
   Count.invisi = 0;
   Count.unknown = 0;
   Count.max_loc = 0;
   Count.max_tot = 0;
   Count.today = 0;
   Count.weekly = 0;
   Count.monthly = 0;
   Count.yearly = 0;
   Count.start = NOW;
   Count.day = NOW;
   Count.week = NOW;
   Count.month = NOW;
   Count.year = NOW;

#ifdef SAVE_MAXCLIENT_STATS
	mcsfp=fopen(DPATH "/.maxclients", "r");
	if(mcsfp!=NULL) {
		fscanf(mcsfp, "%d %d %li %li %li %ld %ld %ld %ld", &Count.max_loc, 
			&Count.max_tot, &Count.weekly, &Count.monthly, &Count.yearly, 
			&Count.start, &Count.week, &Count.month, &Count.year);
		fclose(mcsfp);
	}
#endif
	

	
   /*
    * this code by [email protected] 
    * it is intended to keep the ircd from being swapped out. BSD
    * swapping criteria do not match the requirements of ircd
    */
	
#ifdef INITIAL_DBUFS
   dbuf_init();			/* set up some dbuf stuff to control paging */
#endif

   sbrk0 = (char *) sbrk((size_t) 0);
   uid = getuid();
   euid = geteuid();
#ifdef	PROFIL
   (void) monstartup(0, etext);
   (void) moncontrol(1);
   (void) signal(SIGUSR1, s_monitor);
#endif
	
   myargv = argv;
   (void) umask(077);		/* better safe than sorry --SRB  */
   memset((char *) &me, '\0', sizeof(me));
	
   setup_signals();
   /*
    * * All command line parameters have the syntax "-fstring"  or "-f
    * string" (e.g. the space is optional). String may  be empty. Flag
    * characters cannot be concatenated (like "-fxyz"), it would
    * conflict with the form "-fstring".
    */
   while (--argc > 0 && (*++argv)[0] == '-') 
   {
	char       *p = argv[0] + 1;
	int         flag = *p++;
		
        if (flag == '\0' || *p == '\0') 
	{
	   if (argc > 1 && argv[1][0] != '-') 
	   {
		p = *++argv;
		argc -= 1;
	   }
	   else
		p = "";
	   }
		
      switch (flag) 
      {
		 case 'a':
			bootopt |= BOOT_AUTODIE;
			break;
		 case 'c':
			bootopt |= BOOT_CONSOLE;
			break;
		 case 'q':
			bootopt |= BOOT_QUICK;
			break;
		 case 'd':
			(void) setuid((uid_t) uid);
			dpath = p;
			break;
		 case 'o':		/* Per user local daemon... */
			(void) setuid((uid_t) uid);
			bootopt |= BOOT_OPER;
			break;
#ifdef CMDLINE_CONFIG
		 case 'f':
			(void) setuid((uid_t) uid);
			configfile = p;
			break;
			
# ifdef KPATH
		 case 'k':
			(void) setuid((uid_t) uid);
			klinefile = p;
			break;
# endif
			
#endif
		 case 'h':
			strncpyzt(me.name, p, sizeof(me.name));
			break;
		 case 'i':
			bootopt |= BOOT_INETD | BOOT_AUTODIE;
			break;
		 case 'p':
			if ((portarg = atoi(p)) > 0)
			  portnum = portarg;
			break;
		 case 's':
			bootopt |= BOOT_STDERR;
			break;
		 case 't':
			(void) setuid((uid_t) uid);
			bootopt |= BOOT_TTY;
			break;
		 case 'v':
			(void) printf("ircd %s\n", version);
			exit(0);
		 case 'x':
#ifdef	DEBUGMODE
			(void) setuid((uid_t) uid);
			debuglevel = atoi(p);
			debugmode = *p ? p : "0";
			bootopt |= BOOT_DEBUG;
			break;
#else
			(void) fprintf(stderr,
				"%s: DEBUGMODE must be defined for -x y\n",
								myargv[0]);
			exit(0);
#endif
		 default:
			bad_command();
			break;
      }
   }
	
   if (chdir(dpath)) 
   {
      perror("chdir");
      exit(-1);
   }
   if ((uid != euid) && !euid) 
   {
      (void) fprintf(stderr,
	"ERROR: do not run ircd setuid root. Make it setuid a normal user.\n");
      exit(-1);
   }
	
   if (argc > 0)
	  return bad_command();	/* This should exit out  */
   initialize_ssl();

   motd = (aMotd *) NULL;
   helpfile = (aMotd *) NULL;
   motd_tm = NULL;
#ifdef SHORT_MOTD
   shortmotd = NULL;
#endif
	
   read_motd(MOTD);
   read_help(HELPFILE);
#ifdef SHORT_MOTD
   read_shortmotd(SHORTMOTD);
#endif
	
   clear_client_hash_table();
   clear_channel_hash_table();
   clear_scache_hash_table();	/* server cache name table */
   clear_ip_hash_table();	/* client host ip hash table */

   initlists();
   initclass();
   initwhowas();
   initstats();
   init_tree_parse(msgtab);
   init_send();
   NOW = time(NULL);
   open_debugfile();
   NOW = time(NULL);
   init_fdlist(&serv_fdlist);
   init_fdlist(&oper_fdlist);
   init_fdlist(&listen_fdlist);
	
#ifndef NO_PRIORITY
   init_fdlist(&busycli_fdlist);
#endif
	
   init_fdlist(&default_fdlist);
	  {
		  int i;
		  
		  for (i = MAXCONNECTIONS + 1; i > 0; i--) 
		  {
			  default_fdlist.entry[i] = i - 1;
		  }
	  }

   if ((timeofday = time(NULL)) == -1) 
   {
#ifdef USE_SYSLOG
      syslog(LOG_WARNING, "Clock Failure (%d), TS can be corrupted", errno);
#endif
      sendto_ops("Clock Failure (%d), TS can be corrupted", errno);
   }

#ifdef WINGATE_NOTICE
   strcpy(ProxyMonURL, "http://");
   strncpyzt((ProxyMonURL + 7), DEFAULT_PROXY_INFO_URL, (TOPICLEN + 1) - 7);
   strncpyzt(ProxyMonHost, MONITOR_HOST, (HOSTLEN + 1));
#endif
	
   if (portnum < 0)
	  portnum = PORTNUM;
   me.port = portnum;
   (void) init_sys();
   me.flags = FLAGS_LISTEN;
#ifndef _WIN32
   if (bootopt & BOOT_INETD) 
   {
      me.fd = 0;
      local[0] = &me;
      me.flags = FLAGS_LISTEN;
   }
   else
#endif
	  me.fd = -1;
	
#ifdef USE_SYSLOG
# define SYSLOG_ME     "ircd"
   openlog(SYSLOG_ME, LOG_PID | LOG_NDELAY, LOG_FACILITY);
#endif
   if ((fd = openconf(configfile)) == -1) 
   {
      Debug((DEBUG_FATAL, "Failed in reading configuration file %s",
				 configfile));
      (void) printf("Couldn't open configuration file %s\n",
						  configfile);
      exit(-1);
   }
   (void) initconf(bootopt, fd);
	
   /* comstuds SEPARATE_QUOTE_KLINES_BY_DATE code */
#ifdef SEPARATE_QUOTE_KLINES_BY_DATE
	  {
		  struct tm  *tmptr;
		  char        timebuffer[20], filename[200];
		  
		  tmptr = localtime(&NOW);
		  (void) strftime(timebuffer, 20, "%y%m%d", tmptr);
		  ircsprintf(filename, "%s.%s", klinefile, timebuffer);
		  if ((fd = openconf(filename)) == -1) 
		  {
			  Debug((DEBUG_ERROR, "Failed reading kline file %s",
						filename));
			  (void) printf("Couldn't open kline file %s\n",
								 filename);
		  }
		  else
			 (void) initconf(0, fd);
	  }
#else
# ifdef KPATH
   if ((fd = openconf(klinefile)) == -1) 
   {
      Debug((DEBUG_ERROR, "Failed reading kline file %s", klinefile));
      (void) printf("Couldn't open kline file %s\n", klinefile);
   }
   else
	  (void) initconf(0, fd);
# endif
#endif
   if (!(bootopt & BOOT_INETD)) 
   {
		static char star[] = "*";
		aConfItem  *aconf;
		u_long      vaddr;
		
      if ((aconf = find_me()) && portarg <= 0 && aconf->port > 0)
		  portnum = aconf->port;

      Debug((DEBUG_ERROR, "Port = %d", portnum));

      if ((aconf->passwd[0] != '\0') && (aconf->passwd[0] != '*'))
		  vaddr = inet_addr(aconf->passwd);
      else
		  vaddr = (u_long) NULL;
		
      if (inetport(&me, star, portnum, vaddr)) 
      {
			if (bootopt & BOOT_STDERR)
			  fprintf(stderr, "Couldn't bind to primary port %d\n", portnum);
#ifdef USE_SYSLOG
			(void) syslog(LOG_CRIT, "Couldn't bind to primary port %d\n", portnum);
#endif
			exit(1);
      }
   }
   else if (inetport(&me, "*", 0, 0)) 
   {
      if (bootopt & BOOT_STDERR)
		  fprintf(stderr, "Couldn't bind to port passed from inetd\n");
#ifdef USE_SYSLOG
      (void) syslog(LOG_CRIT, "Couldn't bind to port passed from inetd\n");
#endif
      exit(1);
   }
	
   (void) get_my_name(&me, me.sockhost, sizeof(me.sockhost) - 1);
   if (me.name[0] == '\0')
	  strncpyzt(me.name, me.sockhost, sizeof(me.name));
   me.hopcount = 0;
   me.authfd = -1;
   me.confs = NULL;
   me.next = NULL;
   me.user = NULL;
   me.from = &me;
   SetMe(&me);
   make_server(&me);
   me.serv->up = me.name;
   me.lasttime = me.since = me.firsttime = NOW;
   (void) add_to_client_hash_table(me.name, &me);
	
   /* We don't want to calculate these every time they are used :) */
	
   sprintf(REPORT_DO_DNS, REPORT_DO_DNS_, me.name);
   sprintf(REPORT_FIN_DNS, REPORT_FIN_DNS_, me.name);
   sprintf(REPORT_FIN_DNSC, REPORT_FIN_DNSC_, me.name);
   sprintf(REPORT_FAIL_DNS, REPORT_FAIL_DNS_, me.name);
   sprintf(REPORT_DO_ID, REPORT_DO_ID_, me.name);
   sprintf(REPORT_FIN_ID, REPORT_FIN_ID_, me.name);
   sprintf(REPORT_FAIL_ID, REPORT_FAIL_ID_, me.name);
   R_do_dns = strlen(REPORT_DO_DNS);
   R_fin_dns = strlen(REPORT_FIN_DNS);
   R_fin_dnsc = strlen(REPORT_FIN_DNSC);
   R_fail_dns = strlen(REPORT_FAIL_DNS);
   R_do_id = strlen(REPORT_DO_ID);
   R_fin_id = strlen(REPORT_FIN_ID);
   R_fail_id = strlen(REPORT_FAIL_ID);
	
   check_class();
   if (bootopt & BOOT_OPER) 
   {
      aClient    *tmp = add_connection(&me, 0);
		
      if (!tmp)
		  exit(1);
      SetMaster(tmp);
   }
   else
	  write_pidfile();
	
   Debug((DEBUG_NOTICE, "Server ready..."));
#ifdef USE_SYSLOG
   syslog(LOG_NOTICE, "Server Ready");
#endif
   NOW = time(NULL);
	
#ifndef NO_PRIORITY
   check_fdlists();
#endif
	
   if ((timeofday = time(NULL)) == -1) 
   {
#ifdef USE_SYSLOG
      syslog(LOG_WARNING, "Clock Failure (%d), TS can be corrupted", errno);
#endif
      sendto_ops("Clock Failure (%d), TS can be corrupted", errno);
   }

#ifdef DUMP_DEBUG
   dumpfp=fopen("dump.log", "w");
#endif

   io_loop();
   return 0;
}
Ejemplo n.º 22
0
static      time_t
check_pings(time_t currenttime)
{
aClient 	*cptr;
aConfItem 	*aconf = (aConfItem *) NULL;
int     	 killflag, zkillflag, ping = 0, i;
time_t      	 oldest = 0; /* timeout removed, see EXPLANATION below */
char       	*reason, *ktype, fbuf[512];
char 		*errtxt = "No response from %s, closing link";


   for (i = 0; i <= highest_fd; i++) 
   {
      if (!(cptr = local[i]) || IsMe(cptr) || IsLog(cptr))
	 continue;

       /* Note: No need to notify opers here. It's 
	* already done when "FLAGS_DEADSOCKET" is set.
        */

      if (cptr->flags & FLAGS_DEADSOCKET) 
      {
	 (void) exit_client(cptr, cptr, &me, (cptr->flags & FLAGS_SENDQEX) ?
			    "SendQ exceeded" : "Dead socket");
	 i--;
	 continue;
      }

      killflag = NO;
      zkillflag = NO;

      if (rehashed) 
      {
	 if (zline_in_progress) 
	 {
	    if (IsPerson(cptr)) 
	    {
	       if ((aconf = find_zkill(cptr)))	
		  zkillflag = YES;
	    }
	 }
	 else 
	 {
	    if(IsPerson(cptr)) 
	    {
	       if((aconf = find_kill(cptr)))	
		  killflag = YES;	
	    }
	 }
      }

      /* Added a bit of code here to differentiate 
       * between K and Z-lines. -ThemBones
       */

      if (zkillflag || killflag)
      {
         ktype = zkillflag ? "Z-lined" : 
            ((aconf->status == CONF_KILL) ? "K-lined" : "Autokilled");

	 if (killflag) 
         {
	    sendto_ops("%s active for %s",
                       (aconf->status == CONF_KILL) ? "K-line" : "Autokill",
		       get_client_name(cptr, FALSE));
	    reason = aconf->passwd ? aconf->passwd : ktype;
	 }
	 else 
         {			/* its a Z line */
	    sendto_ops("Z-line active for %s",
		       get_client_name(cptr, FALSE));
	    reason = aconf->passwd ? aconf->passwd : "Z-lined";
	 }

	 sendto_one(cptr, err_str(ERR_YOUREBANNEDCREEP),
		    me.name, cptr->name, ktype);

         ircsprintf(fbuf, "%s: %s", ktype, reason);
	 (void) exit_client(cptr, cptr, &me, fbuf);
	 i--;			/* subtract out this fd so we check it again.. */			
	 continue;
      }

      if (IsRegistered(cptr))
	 ping = cptr->pingval;
      else
	 ping = CONNECTTIMEOUT;

      /*
       * Ok, so goto's are ugly and can be avoided here but this code
       * is already indented enough so I think its justified. -avalon
       *
       * justified by what? laziness? <g>
       * If the client pingtime is fine (ie, not larger than the client ping) 
       * skip over all the checks below. - lucas
       */

      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 (((cptr->flags & FLAGS_PINGSENT) && ((currenttime - cptr->lasttime) >= (2 * ping))) ||
             ((!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))
	          ssl_send(cptr, REPORT_FAIL_DNS, R_fail_dns, 0);
	       if (DoingAuth(cptr))
	          ssl_send(cptr, 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)) 
	    {
	       ircsprintf(fbuf, "from %s: %s", me.name, errtxt);
	       sendto_gnotice(fbuf, get_client_name(cptr, HIDEME));
	       ircsprintf(fbuf, ":%s GNOTICE :%s", me.name, errtxt);                                
	       sendto_serv_butone(cptr, fbuf, get_client_name(cptr, HIDEME));
	    }

	    (void) exit_client(cptr, cptr, &me, "Ping timeout");
	    i--;			/* subtract out this fd so we check it again.. */			
	    continue;
         } /* don't send pings during a burst, as we send them already. */

         else if (!(cptr->flags & (FLAGS_PINGSENT|FLAGS_BURST))) {
	    /*
	     * 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);
         }
      }

      /* see EXPLANATION below
       *
       * 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) 
	    (void) exit_client(cptr, cptr, &me, "Connection Timed Out");
   }

   rehashed = 0;
   zline_in_progress = 0;

   /* EXPLANATION
    * on a server with a large volume of clients, at any given point
    * there may be a client which needs to be pinged the next second,
    * or even right away (a second may have passed while running
    * check_pings). Preserving CPU time is more important than
    * pinging clients out at exact times, IMO. Therefore, I am going to make
    * check_pings always return currenttime + 9. This means that it may take
    * a user up to 9 seconds more than pingfreq to timeout. Oh well.
    * Plus, the number is 9 to 'stagger' our check_pings calls out over
    * time, to avoid doing it and the other tasks ircd does at the same time
    * all the time (which are usually done on intervals of 5 seconds or so). 
    * - lucas
    *
    *  if (!oldest || oldest < currenttime)
    *     oldest = currenttime + PINGFREQUENCY;
    */

   oldest = currenttime + 9;

   Debug((DEBUG_NOTICE, "Next check_ping() call at: %s, %d %d %d",
	  myctime(oldest), ping, oldest, currenttime));

   return oldest;
}
Ejemplo n.º 23
0
/*
** deliver_it
**	Attempt to send a sequence of bytes to the connection.
**	Returns
**
**	< 0	Some fatal error occurred, (but not EWOULDBLOCK).
**		This return is a request to close the socket and
**		clean up the link.
**
**	>= 0	No real error occurred, returns the number of
**		bytes actually transferred. EWOULDBLOCK and other
**		possibly similar conditions should be mapped to
**		zero return. Upper level routine will have to
**		decide what to do with those unwritten bytes...
**
**	*NOTE*	alarm calls have been preserved, so this should
**		work equally well whether blocking or non-blocking
**		mode is used...
**
**	*NOTE*	I nuked 'em.  At the load of current ircd servers
**		you can't run with stuff that blocks. And we don't.
*/
int  deliver_it(aClient *cptr, char *str, int len)
{
    int  retval;

    if (IsDead(cptr) || (!IsServer(cptr) && !IsPerson(cptr)
                         && !IsHandshake(cptr)
#ifdef USE_SSL
                         && !IsSSLHandshake(cptr)
#endif

                         && !IsUnknown(cptr)))
    {
        str[len] = '\0';
        sendto_ops
        ("* * * DEBUG ERROR * * * !!! Calling deliver_it() for %s, status %d %s, with message: %s",
         cptr->name, cptr->status, IsDead(cptr) ? "DEAD" : "", str);
        return -1;
    }

#ifdef USE_SSL
    if (IsSSL(cptr) && cptr->ssl != NULL)
    {
        retval = SSL_write(cptr->ssl, str, len);

        if (retval < 0)
        {
            switch (SSL_get_error(cptr->ssl, retval))
            {
            case SSL_ERROR_WANT_READ:
                /* retry later */
                return 0;
            case SSL_ERROR_WANT_WRITE:
                SET_ERRNO(P_EWOULDBLOCK);
                break;
            case SSL_ERROR_SYSCALL:
                break;
            case SSL_ERROR_SSL:
                if (ERRNO == P_EAGAIN)
                    break;
            default:
                return 0;
            }
        }
    }
    else
#endif
        retval = send(cptr->fd, str, len, 0);
    /*
       ** Convert WOULDBLOCK to a return of "0 bytes moved". This
       ** should occur only if socket was non-blocking. Note, that
       ** all is Ok, if the 'write' just returns '0' instead of an
       ** error and errno=EWOULDBLOCK.
       **
       ** ...now, would this work on VMS too? --msa
     */
    if (retval < 0 && (errno == EWOULDBLOCK || errno == EAGAIN ||
                       errno == ENOBUFS))
        retval = 0;

    if (retval > 0)
    {
        cptr->sendB += retval;
        me.sendB += retval;
        if (cptr->sendB > 1023)
        {
            cptr->sendK += (cptr->sendB >> 10);
            cptr->sendB &= 0x03ff;	/* 2^10 = 1024, 3ff = 1023 */
        }
Ejemplo n.º 24
0
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);
}
Ejemplo n.º 25
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	connecting, confrq;
  time_t	next = 0;
  aClass	*cltmp;
  aConfItem *con_conf = (aConfItem *)NULL;
  int	con_class = 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_ops("Connection to %s[%s] activated.",
		   con_conf->name, con_conf->host);
    }
  Debug((DEBUG_NOTICE,"Next connection check : %s", myctime(next)));
  return (next);
}
Ejemplo n.º 26
0
static int
m_server_estab(aClient *cptr)
{
    aConnect *aconn;
    aClient *acptr;

    char       *inpath, *host, *s, *encr;

    inpath = get_client_name(cptr, HIDEME);  /* "refresh" inpath with host  */
    host = cptr->name;

    if (!(aconn = cptr->serv->aconn))
    {
        ircstp->is_ref++;
        sendto_one(cptr, "ERROR :Lost Connect block");
        sendto_ops_lev(ADMIN_LEV, "Lost Connect block for server %s",
                           get_client_name(cptr, TRUE));
        return exit_client(cptr, cptr, cptr, "Lost Connect block");
    }

    encr = cptr->passwd;
    if (*aconn->apasswd && !StrEq(aconn->apasswd, encr))
    {
        ircstp->is_ref++;
        sendto_one(cptr, "ERROR :Wrong link password");
        sendto_ops("Link %s dropped, wrong password", inpath);
        return exit_client(cptr, cptr, cptr, "Bad Password");
    }
    memset(cptr->passwd, '\0', sizeof(cptr->passwd));

    if ((acptr = find_client(host, NULL)))
    {
        /* Don't complain about juped servers */
        if(!IsULine(acptr) || find_aUserver(acptr->name))
        {
            sendto_gnotice("from %s: Link %s dropped, server already exists",
                           me.name, inpath);
            sendto_serv_butone(cptr, ":%s GNOTICE :Link %s dropped, server already"
                               " exists", me.name, inpath);
        }
        return exit_client(cptr, cptr, cptr, "Server Exists");
    }

    if(!(confopts & FLAGS_HUB))
    {
        int i;
        for (i = 0; i <= highest_fd; i++)
            if (local[i] && IsServer(local[i]))
            {
                ircstp->is_ref++;
                sendto_one(cptr, "ERROR :I'm a leaf not a hub");
                return exit_client(cptr, cptr, cptr, "I'm a leaf");
            }
    }

    /* aconf->port is a CAPAB field, kind-of. kludge. mm, mm. */
    /* no longer! this should still get better though */
    if((aconn->flags & CONN_ZIP))
        SetZipCapable(cptr);
    if((aconn->flags & CONN_DKEY))
        SetWantDKEY(cptr);
    if (IsUnknown(cptr))
    {
        if (aconn->cpasswd[0])
            sendto_one(cptr, "PASS %s :TS", aconn->cpasswd);

        /* Pass my info to the new server */

#ifdef HAVE_ENCRYPTION_ON
        if(!WantDKEY(cptr))
            sendto_one(cptr, "CAPAB SSJOIN NOQUIT BURST UNCONNECT ZIP "
                       "NICKIP NICKIPSTR TSMODE");
        else
            sendto_one(cptr, "CAPAB SSJOIN NOQUIT BURST UNCONNECT DKEY "
                       "ZIP NICKIP NICKIPSTR TSMODE");
#else
        sendto_one(cptr, "CAPAB SSJOIN NOQUIT BURST UNCONNECT ZIP NICKIP NICKIPSTR TSMODE");
#endif

        sendto_one(cptr, "SERVER %s 1 :%s",
                   my_name_for_link(me.name, aconn),
                   (me.info[0]) ? (me.info) : "IRCers United");
    }
    else 
    {
        s = (char *) strchr(aconn->host, '@');
        *s = '\0';      /* should never be NULL -- wanna bet? -Dianora */

        Debug((DEBUG_INFO, "Check Usernames [%s]vs[%s]", aconn->host,
               cptr->username));
        if (match(aconn->host, cptr->username))
        {
            *s = '@';
            ircstp->is_ref++;
            sendto_ops("Username mismatch [%s]v[%s] : %s",
                       aconn->host, cptr->username,
                       get_client_name(cptr, HIDEME));
            sendto_one(cptr, "ERROR :No Username Match");
            return exit_client(cptr, cptr, cptr, "Bad User");
        }
        *s = '@';
    }

    /* send routing notice, this should never happen anymore */
    if (!DoesTS(cptr))
    {
        sendto_gnotice("from %s: Warning: %s linked, non-TS server",
                       me.name, get_client_name(cptr, HIDEME));
        sendto_serv_butone(cptr,
                           ":%s GNOTICE :Warning: %s linked, non-TS server",
                           me.name, get_client_name(cptr, HIDEME));
    }

    sendto_one(cptr, "SVINFO %d %d 0 :%ld", TS_CURRENT, TS_MIN,
               (ts_val) timeofday);

    /* sendto one(cptr, "CAPAB ...."); moved to after PASS but before SERVER
     * now in two places.. up above and in s_bsd.c. - lucas
     * This is to make sure we pass on our capabilities before we establish
     * a server connection
     */

    /*
     * *WARNING*
     *   In the following code in place of plain
     * server's name we send what is returned by
     * get_client_name which may add the "sockhost" after the name.
     * It's *very* *important* that there is a SPACE between
     * the name and sockhost (if present). The receiving server
     * will start the information field from this first blank and
     * thus puts the sockhost into info. ...a bit tricky, but
     * you have been warned, besides code is more neat this way...
     * --msa
     */

    cptr->serv->up = me.name;
    cptr->serv->aconn = aconn;

    throttle_remove(cipntoa(cptr));

#ifdef HAVE_ENCRYPTION_ON
    if(!CanDoDKEY(cptr) || !WantDKEY(cptr))
        return do_server_estab(cptr);
    else
    {
        SetNegoServer(cptr); /* VERY IMPORTANT THAT THIS IS HERE */
        sendto_one(cptr, "DKEY START");
    }
#else
    return do_server_estab(cptr);
#endif

    return 0;
}
Ejemplo n.º 27
0
/*
 * m_squit - SQUIT message handler
 *      parv[0] = sender prefix
 *      parv[1] = server name
 *      parv[2] = comment
 */
int m_squit(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct ConfItem* aconf;
  char*            server;
  struct Client*   acptr;
  char  *comment = (parc > 2 && parv[2]) ? parv[2] : cptr->name;

  if (!IsPrivileged(sptr))
    {
      sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
      return 0;
    }

  if (parc > 1)
    {
      server = parv[1];
      /*
      ** To accomodate host masking, a squit for a masked server
      ** name is expanded if the incoming mask is the same as
      ** the server name for that link to the name of link.
      */
      while ((*server == '*') && IsServer(cptr))
        {
          aconf = cptr->serv->nline;
          if (!aconf)
            break;
          if (!irccmp(server, my_name_for_link(me.name, aconf)))
            server = cptr->name;
          break; /* WARNING is normal here */
          /* NOTREACHED */
        }
      /*
      ** The following allows wild cards in SQUIT. Only useful
      ** when the command is issued by an oper.
      */
      for (acptr = GlobalClientList; (acptr = next_client(acptr, server));
           acptr = acptr->next)
        if (IsServer(acptr) || IsMe(acptr))
          break;
      if (acptr && IsMe(acptr))
        {
          acptr = cptr;
          server = cptr->name;
        }
    }
  else
    {
      /*
      ** This is actually protocol error. But, well, closing
      ** the link is very proper answer to that...
      **
      ** Closing the client's connection probably wouldn't do much
      ** good.. any oper out there should know that the proper way
      ** to disconnect is /QUIT :)
      **
      ** its still valid if its not a local client, its then
      ** a protocol error for sure -Dianora
      */
      if(MyClient(sptr))
        {
          sendto_one(sptr, form_str(ERR_NEEDMOREPARAMS),
               me.name, parv[0], "SQUIT");
          return 0;
        }
      else
        {
          server = cptr->host;
          acptr = cptr;
        }
    }

  /*
  ** SQUIT semantics is tricky, be careful...
  **
  ** The old (irc2.2PL1 and earlier) code just cleans away the
  ** server client from the links (because it is never true
  ** "cptr == acptr".
  **
  ** This logic here works the same way until "SQUIT host" hits
  ** the server having the target "host" as local link. Then it
  ** will do a real cleanup spewing SQUIT's and QUIT's to all
  ** directions, also to the link from which the orinal SQUIT
  ** came, generating one unnecessary "SQUIT host" back to that
  ** link.
  **
  ** One may think that this could be implemented like
  ** "hunt_server" (e.g. just pass on "SQUIT" without doing
  ** nothing until the server having the link as local is
  ** reached). Unfortunately this wouldn't work in the real life,
  ** because either target may be unreachable or may not comply
  ** with the request. In either case it would leave target in
  ** links--no command to clear it away. So, it's better just
  ** clean out while going forward, just to be sure.
  **
  ** ...of course, even better cleanout would be to QUIT/SQUIT
  ** dependant users/servers already on the way out, but
  ** currently there is not enough information about remote
  ** clients to do this...   --msa
  */
  if (!acptr)
    {
      sendto_one(sptr, form_str(ERR_NOSUCHSERVER),
                 me.name, parv[0], server);
      return 0;
    }
  if (IsLocOp(sptr) && !MyConnect(acptr))
    {
      sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
      return 0;
    }

  if (MyClient(sptr) && !IsOperRemote(sptr) && !MyConnect(acptr))
    {
      sendto_one(sptr,":%s NOTICE %s :You have no R flag",me.name,parv[0]);
      return 0;
    }

  /*
  **  Notify all opers, if my local link is remotely squitted
  */
  if (MyConnect(acptr) && !IsAnOper(cptr))
    {
      sendto_ops_butone(NULL, &me,
                        ":%s WALLOPS :Received SQUIT %s from %s (%s)",
                        me.name, server, get_client_name(sptr,FALSE), comment);
      log(L_TRACE, "SQUIT From %s : %s (%s)", parv[0], server, comment);
    }
  else if (MyConnect(acptr))
    sendto_ops("Received SQUIT %s from %s (%s)",
               acptr->name, get_client_name(sptr,FALSE), comment);
  
  return exit_client(cptr, acptr, sptr, comment);
}
Ejemplo n.º 28
0
void io_loop()
{
char to_send[200];
time_t lasttime = 0;
long lastrecvK = 0;
int  lrv = 0;
time_t      lasttimeofday;
int delay = 0;

 while(1)
 {
   lasttimeofday = timeofday;

   if ((timeofday = time(NULL)) == -1) 
   {
#ifdef USE_SYSLOG
      syslog(LOG_WARNING, "Clock Failure (%d), TS can be corrupted", errno);
#endif
      sendto_ops("Clock Failure (%d), TS can be corrupted", errno);
   }

   if (timeofday < lasttimeofday) 
   {
      ircsprintf(to_send, "System clock is running backwards - (%d < %d)",
		 timeofday, lasttimeofday);
      report_error(to_send, &me);
   }

   NOW = timeofday;

   /*
    * This chunk of code determines whether or not "life sucks", that
    * is to say if the traffic level is so high that standard server
    * commands should be restricted
    * 
    * Changed by Taner so that it tells you what's going on as well as
    * allows forced on (long LCF), etc...
    */

   if ((timeofday - lasttime) >= LCF) 
   {
      lrv = LRV * LCF;
      lasttime = timeofday;
      currlife = (me.receiveK - lastrecvK) / LCF;
      if ((me.receiveK - lrv) > lastrecvK || HTMLOCK == YES) 
      {
	 if (!lifesux) 
 	 {
	    /*
	     * In the original +th code Taner had
	     * 
	     * LCF << 1;  / * add hysteresis * /
	     * 
	     * which does nothing... so, the hybrid team changed it to
	     * 
	     * LCF <<= 1;  / * add hysteresis * /
	     * 
	     * suddenly, there were reports of clients mysteriously just
	     * dropping off... Neither rodder or I can see why it makes
	     * a difference, but lets try it this way...
	     * 
	     * The original dog3 code, does not have an LCF variable
	     * 
	     * -Dianora
	     * 
	     */
	    lifesux = 1;

	    if (noisy_htm) 
	       sendto_ops("Entering high-traffic mode - (%dk/s > %dk/s)", currlife, LRV);
	 }
	 else 
	 {
	    lifesux++;		/* Ok, life really sucks! */
	    LCF += 2;		/* Wait even longer */
	    if (noisy_htm) 
	       sendto_ops("Still high-traffic mode %d%s (%d delay): %dk/s",
			  lifesux, (lifesux > 9) ? " (TURBO)" : "", (int) LCF, currlife);

	   /* Reset htm here, because its been on a little too long.
	    * Bad Things(tm) tend to happen with HTM on too long -epi */

	    if (lifesux>15) 
	    {
	       if (noisy_htm) 
		  sendto_ops("Resetting HTM and raising limit to: %dk/s\n", LRV + 5);
	       LCF=LOADCFREQ;
	       lifesux=0;
	       LRV+=5;
	    }
	 }
      }
      else 
      {
	 LCF = LOADCFREQ;
	 if (lifesux) 
	 {
	    lifesux = 0;
	    if (noisy_htm)
	       sendto_ops("Resuming standard operation . . . .");
	 }
      }
      lastrecvK = me.receiveK;
   }
   /*
    * * We only want to connect if a connection is due, not every
    * time through.  Note, if there are no active C lines, this call
    * to Tryconnections is made once only; it will return 0. - avalon
    */

   if (nextconnect && timeofday >= nextconnect)
      nextconnect = try_connections(timeofday);

   /* DNS checks. One to timeout queries, one for cache expiries.*/

   if (timeofday >= nextdnscheck)
      nextdnscheck = timeout_query_list(timeofday);
   if (timeofday >= nextexpire)
      nextexpire = expire_cache(timeofday);

   /*
    * * take the smaller of the two 'timed' event times as the time
    * of next event (stops us being late :) - avalon WARNING -
    * nextconnect can return 0!
    */

   if (nextconnect)
      delay = MIN(nextping, nextconnect);
   else
      delay = nextping;
   delay = MIN(nextdnscheck, delay);
   delay = MIN(nextexpire, delay);
   delay -= timeofday;

   /*
    * * Adjust delay to something reasonable [ad hoc values] (one
    * might think something more clever here... --msa) 
    * We don't really need to check that often and as long 
    * as we don't delay too long, everything should be ok. 
    * waiting too long can cause things to timeout... 
    * i.e. PINGS -> a disconnection :( 
    * - avalon
    */
   if (delay < 1)
      delay = 1;
   else
      delay = MIN(delay, TIMESEC);
   /*
    * We want to read servers on every io_loop, as well as "busy"
    * clients (which again, includes servers. If "lifesux", then we
    * read servers AGAIN, and then flush any data to servers. -Taner
    */

#ifndef NO_PRIORITY
   read_message(0, &serv_fdlist);
   read_message(1, &busycli_fdlist);
   if (lifesux) 
   {
      (void) read_message(1, &serv_fdlist);
      if (lifesux > 9) 		/* life really sucks */
      {
	 (void) read_message(1, &busycli_fdlist);
	 (void) read_message(1, &serv_fdlist);
      }
      flush_fdlist_connections(&serv_fdlist);
   }

   if ((timeofday = time(NULL)) == -1) 
   {
	#ifdef USE_SYSLOG
           syslog(LOG_WARNING, "Clock Failure (%d), TS can be corrupted", errno);
	#endif
      sendto_ops("Clock Failure (%d), TS can be corrupted", errno);
   }
   /*
    * CLIENT_SERVER = TRUE: If we're in normal mode, or if "lifesux"
    * and a few seconds have passed, then read everything.
    * CLIENT_SERVER = FALSE: If it's been more than lifesux*2 seconds
    * (that is, at most 1 second, or at least 2s when lifesux is != 0)
    * check everything. -Taner
    */
   { 
      static time_t lasttime = 0;

# ifdef CLIENT_SERVER
      if (!lifesux || (lasttime + lifesux) < timeofday) {
# else
      if ((lasttime + (lifesux + 1)) < timeofday) {
# endif
	 (void) read_message(delay ? delay : 1, NULL);	/* check everything! */
	 lasttime = timeofday;
      }
   }
#else
   (void) read_message(delay, NULL);	/* check everything! */
#endif
   /*
    * * ...perhaps should not do these loops every time, but only if
    * there is some chance of something happening (but, note that
    * conf->hold times may be changed elsewhere--so precomputed next
    * event time might be too far away... (similarly with ping
    * times) --msa
    */

   if ((timeofday >= nextping))
      nextping = check_pings(timeofday);

   if (dorehash && !lifesux) 
   {
      (void) rehash(&me, &me, 1);
      dorehash = 0;
   }
   /*
    * 
    * Flush output buffers on all connections now if they 
    * have data in them (or at least try to flush)  -avalon
    *
    * flush_connections(me.fd);
    *
    * avalon, what kind of crack have you been smoking? why
    * on earth would we flush_connections blindly when
    * we already check to see if we can write (and do)
    * in read_message? There is no point, as this causes
    * lots and lots of unnecessary sendto's which 
    * 99% of the time will fail because if we couldn't
    * empty them in read_message we can't empty them here.
    * one effect: during htm, output to normal lusers
    * will lag.
    */

    /* Now we've made this call a bit smarter. */
    /* Only flush non-blocked sockets. */

    flush_connections(me.fd);

#ifndef NO_PRIORITY
   check_fdlists();
#endif

#ifdef	LOCKFILE
   /*
    * * If we have pending klines and CHECK_PENDING_KLINES minutes
    * have passed, try writing them out.  -ThemBones
    */

   if ((pending_klines) && ((timeofday - pending_kline_time)
			    >= (CHECK_PENDING_KLINES * 60)))
      do_pending_klines();
#endif
 }
}
/*
 * open_debugfile
 * 
 * If the -t option is not given on the command line when the server is
 * started, all debugging output is sent to the file set by LPATH in
 * config.h Here we just open that file and make sure it is opened to
 * fd 2 so that any fprintf's to stderr also goto the logfile.  If the
 * debuglevel is not set from the command line by -x, use /dev/null as
 * the dummy logfile as long as DEBUGMODE has been defined, else dont
 * waste the fd.
 */
static void
open_debugfile()
{
#ifdef	DEBUGMODE
int         fd;
aClient    *cptr;

   if (debuglevel >= 0) 
   {
      cptr = make_client(NULL, NULL);
      cptr->fd = 2;
      SetLog(cptr);
      cptr->port = debuglevel;
      cptr->flags = 0;
      cptr->acpt = cptr;
      local[2] = cptr;
      (void) strcpy(cptr->sockhost, me.sockhost);

      (void) printf("isatty = %d ttyname = %#x\n",
		    isatty(2), (u_int) ttyname(2));
      if (!(bootopt & BOOT_TTY)) 	/*) leave debugging output on fd */ 
      {
	 (void) truncate(LOGFILE, 0);
	 if ((fd = open(LOGFILE, O_WRONLY | O_CREAT, 0600)) < 0)
	    if ((fd = open("/dev/null", O_WRONLY)) < 0)
	       exit(-1);
	 if (fd != 2) 
    	 {
	    (void) dup2(fd, 2);
	    (void) close(fd);
	 }
	 strncpyzt(cptr->name, LOGFILE, sizeof(cptr->name));
      }
      else if (isatty(2) && ttyname(2))
	 strncpyzt(cptr->name, ttyname(2), sizeof(cptr->name));
      else
	 (void) strcpy(cptr->name, "FD2-Pipe");
      Debug((DEBUG_FATAL, "Debug: File <%s> Level: %d at %s",
	     cptr->name, cptr->port, myctime(time(NULL))));
   }
   else
      local[2] = NULL;
#endif
   return;
}
Ejemplo n.º 29
0
DLLFUNC int m_htm(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
    int  x = HUNTED_NOSUCH;
    char *command, *param;
    if (!IsOper(sptr))
    {
        sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, sptr->name);
        return 0;
    }

    switch(parc) {
    case 1:
        break;
    case 2:
        x = hunt_server_token_quiet(cptr, sptr, MSG_HTM, TOK_HTM, "%s", 1, parc, parv);
        break;
    case 3:
        x = hunt_server_token_quiet(cptr, sptr, MSG_HTM, TOK_HTM, "%s %s", 1, parc, parv);
        break;
    default:
        x = hunt_server_token_quiet(cptr, sptr, MSG_HTM, TOK_HTM, "%s %s %s", 1, parc, parv);
    }

    switch (x) {
    case HUNTED_NOSUCH:
        command = (parv[1]);
        param = (parv[2]);
        break;
    case HUNTED_ISME:
        command = (parv[2]);
        param = (parv[3]);
        break;
    default:
        return 0;
    }

#ifndef NO_FDLIST

    if (!command)
    {
        sendto_one(sptr,
                   ":%s NOTICE %s :*** Current incoming rate: %0.2f kb/s",
                   me.name, parv[0], currentrate);
        sendto_one(sptr,
                   ":%s NOTICE %s :*** Current outgoing rate: %0.2f kb/s",
                   me.name, parv[0], currentrate2);
        sendto_one(sptr,
                   ":%s NOTICE %s :*** Highest incoming rate: %0.2f kb/s",
                   me.name, parv[0], highest_rate);
        sendto_one(sptr,
                   ":%s NOTICE %s :*** Highest outgoing rate: %0.2f kb/s",
                   me.name, parv[0], highest_rate2);
        sendto_one(sptr,
                   ":%s NOTICE %s :*** High traffic mode is currently \2%s\2",
                   me.name, parv[0], (lifesux ? "ON" : "OFF"));
        sendto_one(sptr,
                   ":%s NOTICE %s :*** High traffic mode is currently in \2%s\2 mode",
                   me.name, parv[0], (noisy_htm ? "NOISY" : "QUIET"));
        sendto_one(sptr,
                   ":%s NOTICE %s :*** HTM will be activated if incoming > %i kb/s",
                   me.name, parv[0], LRV);
    }

    else
    {
        if (!stricmp(command, "ON"))
        {
            EventInfo mod;
            lifesux = 1;
            sendto_one(sptr,
                       ":%s NOTICE %s :High traffic mode is now ON.",
                       me.name, parv[0]);
            sendto_ops
            ("%s (%s@%s) forced High traffic mode to activate",
             parv[0], sptr->user->username,
             GetHost(sptr));
            LCF = 60;	/* 60 seconds */
            mod.flags = EMOD_EVERY;
            mod.every = LCF;
            LockEventSystem();
            EventMod(e_lcf, &mod);
            UnlockEventSystem();
        }
        else if (!stricmp(command, "OFF"))
        {
            EventInfo mod;
            lifesux = 0;
            LCF = LOADCFREQ;
            mod.flags = EMOD_EVERY;
            mod.every = LCF;
            LockEventSystem();
            EventMod(e_lcf, &mod);
            UnlockEventSystem();
            sendto_one(sptr,
                       ":%s NOTICE %s :High traffic mode is now OFF.",
                       me.name, parv[0]);
            sendto_ops
            ("%s (%s@%s) forced High traffic mode to deactivate",
             parv[0], sptr->user->username,
             GetHost(sptr));
        }
        else if (!stricmp(command, "TO"))
        {
            if (!param)
                sendto_one(sptr,
                           ":%s NOTICE %s :You must specify an integer value",
                           me.name, parv[0]);
            else
            {
                int  new_val = atoi(param);
                if (new_val < 10)
                    sendto_one(sptr,
                               ":%s NOTICE %s :New value must be > 10",
                               me.name, parv[0]);
                else
                {
                    LRV = new_val;
                    sendto_one(sptr,
                               ":%s NOTICE %s :New max rate is %dkb/s",
                               me.name, parv[0], LRV);
                    sendto_ops
                    ("%s (%s@%s) changed the High traffic mode max rate to %dkb/s",
                     parv[0], sptr->user->username,
                     GetHost(sptr), LRV);
                }
            }
        }
        else if (!stricmp(command, "QUIET"))
        {
            noisy_htm = 0;
            sendto_one(sptr,
                       ":%s NOTICE %s :High traffic mode is now QUIET",
                       me.name, parv[0]);
            sendto_ops("%s (%s@%s) set High traffic mode to QUIET",
                       parv[0], sptr->user->username,
                       GetHost(sptr));
        }

        else if (!stricmp(command, "NOISY"))
        {
            noisy_htm = 1;
            sendto_one(sptr,
                       ":%s NOTICE %s :High traffic mode is now NOISY",
                       me.name, parv[0]);
            sendto_ops("%s (%s@%s) set High traffic mode to NOISY",
                       parv[0], sptr->user->username,
                       GetHost(sptr));
        }
        else
            sendto_one(sptr, ":%s NOTICE %s :Unknown option: %s",
                       me.name, parv[0], command);
    }


#else
    sendto_one(sptr,
               ":%s NOTICE %s :*** High traffic mode and fdlists are not enabled on this server",
               me.name, sptr->name);
#endif
    return 0;
}
Ejemplo n.º 30
0
/*
** m_user
**	parv[0] = sender prefix
**	parv[1] = username (login name, account)
**	parv[2] = client host name (used only from other servers)
**	parv[3] = server host name (used only from other servers)
**	parv[4] = users real name info
**
** NOTE: Be advised that multiple USER messages are possible,
**       hence, always check if a certain struct is already allocated... -- Syzop
*/
DLLFUNC CMD_FUNC(m_user)
{
#define	UFLAGS	(UMODE_INVISIBLE|UMODE_WALLOP|UMODE_SERVNOTICE)
	char *username, *host, *server, *realname, *umodex = NULL, *virthost =
	    NULL, *ip = NULL;
	u_int32_t sstamp = 0;
	anUser *user;
	aClient *acptr;

	if (IsServer(cptr) && !IsUnknown(sptr))
		return 0;

	if (MyConnect(sptr) && (sptr->listener->umodes & LISTENER_SERVERSONLY))
	{
		return exit_client(cptr, sptr, sptr,
		    "This port is for servers only");
	}

	if (parc > 2 && (username = (char *)index(parv[1], '@')))
		*username = '******';
	if (parc < 5 || *parv[1] == '\0' || *parv[2] == '\0' ||
	    *parv[3] == '\0' || *parv[4] == '\0')
	{
		sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
		    me.name, parv[0], "USER");
		if (IsServer(cptr))
			sendto_ops("bad USER param count for %s from %s",
			    parv[0], get_client_name(cptr, FALSE));
		else
			return 0;
	}


	/* Copy parameters into better documenting variables */

	username = (parc < 2 || BadPtr(parv[1])) ? "<bad-boy>" : parv[1];
	host = (parc < 3 || BadPtr(parv[2])) ? "<nohost>" : parv[2];
	server = (parc < 4 || BadPtr(parv[3])) ? "<noserver>" : parv[3];

	/* This we can remove as soon as all servers have upgraded. */

	if (parc == 6 && IsServer(cptr))
	{
		if (isdigit(*parv[4]))
			sstamp = strtoul(parv[4], NULL, 10);
		realname = (BadPtr(parv[5])) ? "<bad-realname>" : parv[5];
		umodex = NULL;
	}
	else if (parc == 8 && IsServer(cptr))
	{
		if (isdigit(*parv[4]))
			sstamp = strtoul(parv[4], NULL, 10);
		realname = (BadPtr(parv[7])) ? "<bad-realname>" : parv[7];
		umodex = parv[5];
		virthost = parv[6];
	}
	else if (parc == 9 && IsServer(cptr))
	{
		if (isdigit(*parv[4]))
			sstamp = strtoul(parv[4], NULL, 10);
		realname = (BadPtr(parv[8])) ? "<bad-realname>" : parv[8];
		umodex = parv[5];
		virthost = parv[6];
		ip = parv[7];
	}
	else
	{
		realname = (BadPtr(parv[4])) ? "<bad-realname>" : parv[4];
	}
	user = make_user(sptr);

	if (!MyConnect(sptr))
	{
		if (sptr->srvptr == NULL)
			sendto_ops("WARNING, User %s introduced as being "
			    "on non-existant server %s.", sptr->name, server);
		if (SupportNS(cptr))
		{
			acptr = (aClient *)find_server_b64_or_real(server);
			if (acptr)
				user->server = find_or_add(acptr->name);
			else
				user->server = find_or_add(server);
		}
		else
			user->server = find_or_add(server);
		strlcpy(user->realhost, host, sizeof(user->realhost));
		goto user_finish;
	}

	if (!IsUnknown(sptr))
	{
		sendto_one(sptr, err_str(ERR_ALREADYREGISTRED),
		    me.name, parv[0]);
		return 0;
	}

	if (!IsServer(cptr))
	{
		sptr->umodes |= CONN_MODES;
		if (CONNECT_SNOMASK)
		{
			sptr->umodes |= UMODE_SERVNOTICE;
			create_snomask(sptr, user, CONNECT_SNOMASK);
		}
	}

	/* Set it temporarely to at least something trusted,
	 * this was copying user supplied data directly into user->realhost
	 * which seemed bad. Not to say this is much better ;p. -- Syzop
	 */
	strncpyzt(user->realhost, Inet_ia2p(&sptr->ip), sizeof(user->realhost));
	if (!user->ip_str)
		user->ip_str = strdup(Inet_ia2p(&sptr->ip));
	user->server = me_hash;
      user_finish:
	user->servicestamp = sstamp;
	strlcpy(sptr->info, realname, sizeof(sptr->info));
	if (sptr->name[0] && (IsServer(cptr) ? 1 : IsNotSpoof(sptr)))
		/* NICK and no-spoof already received, now we have USER... */
	{
		if (USE_BAN_VERSION && MyConnect(sptr))
			sendto_one(sptr, ":IRC!IRC@%s PRIVMSG %s :\1VERSION\1",
				me.name, sptr->name);
		if (strlen(username) > USERLEN)
			username[USERLEN] = '\0'; /* cut-off */
		return(
		    register_user(cptr, sptr, sptr->name, username, umodex,
		    virthost,ip));
	}
	else
		strncpyzt(sptr->user->username, username, USERLEN + 1);

	return 0;
}