Пример #1
0
/*
 * add_to_channel_hash_table
 */
void add_to_channel_hash_table(const char* name, struct Channel* chptr)
{
  struct Channel *achptr;
  unsigned int hashv;
  assert(0 != name);
  assert(0 != chptr);

  if ((achptr = hash_find_channel(name, NULL)))
    {
      sendto_ops_flag(UMODE_DEBUG, "WTF: Already got %s in hash table but something tried to add it again, dumping core",
		      name);
      logprintf(L_WARN, "WTF: Already got %s in hash table but something tried to add it again, dumping core",
	  name);
      flush_connections(0);
      abort();
    }
  hashv = hash_channel_name(name);
  if ((channelTable[hashv].links == 0) && (channelTable[hashv].list != NULL))
    {
      sendto_ops_flag(UMODE_DEBUG, "WTF: channelTable[%d].links == 0 but list not NULL. Whacking list...",
		      hashv);
      logprintf(L_WARN, "WTF: channelTable[%d].links == 0 but list not NULL. Whacking list...",
	  hashv);
      channelTable[hashv].list = NULL;
    }
  chptr->hnextch = (struct Channel*) channelTable[hashv].list;
  channelTable[hashv].list = (void*) chptr;
  ++channelTable[hashv].links;
  ++channelTable[hashv].hits;
}
Пример #2
0
/** Restart the server with a message.
 * @param[in] message Message to log and send to operators.
 */
void server_restart(const char *message)
{
  static int restarting = 0;

  /* inhibit sending any server notices; we may be in a loop */
  log_write(LS_SYSTEM, L_WARNING, LOG_NOSNOTICE, "Restarting Server: %s",
	    message);
  if (restarting++) /* increment restarting to prevent looping */
    return;

  sendto_opmask_butone(0, SNO_OLDSNO, "Restarting server: %s", message);
  Debug((DEBUG_NOTICE, "Restarting server..."));
  flush_connections(0);

  log_close();

  close_connections(!(thisServer.bootopt & (BOOT_TTY | BOOT_DEBUG | BOOT_CHKCONF)));

  reap_children();

  execv(SPATH, thisServer.argv);

  /* Have to reopen since it has been closed above */
  log_reopen();

  log_write(LS_SYSTEM, L_CRIT, 0, "execv(%s,%s) failed: %m", SPATH,
	    *thisServer.argv);

  Debug((DEBUG_FATAL, "Couldn't restart server \"%s\": %s",
         SPATH, (strerror(errno)) ? strerror(errno) : ""));
  exit(8);
}
Пример #3
0
VOIDSIG s_die()
{
#ifdef	USE_SYSLOG
	(void)syslog(LOG_CRIT, "Server Killed By SIGTERM");
#endif
	flush_connections(me.fd);
	exit(-1);
}
Пример #4
0
/** Terminate the server with a message.
 * @param[in] message Message to log and send to operators.
 */
void server_die(const char *message)
{
  /* log_write will send out message to both log file and as server notice */
  log_write(LS_SYSTEM, L_CRIT, 0, "Server terminating: %s", message);
  flush_connections(0);
  close_connections(1);
  running = 0;
}
Пример #5
0
/** Immediately terminate the server with a message.
 * @param[in] message Message to log, but not send to operators.
 */
void server_panic(const char *message)
{
  /* inhibit sending server notice--we may be panicking due to low memory */
  log_write(LS_SYSTEM, L_CRIT, LOG_NOSNOTICE, "Server panic: %s", message);
  flush_connections(0);
  log_close();
  close_connections(1);
  exit(1);
}
Пример #6
0
RETSIGTYPE s_die(int s)
{
	sendto_serv_v(NULL, SV_UID, ":%s SDIE", me.serv->sid);
#ifdef	USE_SYSLOG
	(void)syslog(LOG_CRIT, "Server Killed By SIGTERM");
	(void)closelog();
#endif
	logfiles_close();
	ircd_writetune(tunefile);
	flush_connections(me.fd);
	exit(-1);
}
Пример #7
0
void	server_reboot(void)
{
	Reg	int	i;

	sendto_flag(SCH_NOTICE, "Aieeeee!!!  Restarting server... (%u)",
		    (u_int)((char *)sbrk((size_t)0)-sbrk0));

	Debug((DEBUG_NOTICE,"Restarting server..."));
	flush_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
	logfiles_close();
	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) || isatty(0))
		(void)close(0);
	ircd_writetune(tunefile);
	if (!(bootopt & BOOT_INETD))
	    {
		(void)execv(IRCD_PATH, myargv);
#ifdef USE_SYSLOG
		/* Have to reopen since it has been closed above */
		
		openlog(mybasename(myargv[0]), LOG_PID|LOG_NDELAY, LOG_FACILITY);
		syslog(LOG_CRIT, "execv(%s,%s) failed: %m\n", IRCD_PATH,
		       myargv[0]);
		closelog();
#endif
		Debug((DEBUG_FATAL,"Couldn't restart server: %s",
		       strerror(errno)));
	    }
	exit(-1);
}
Пример #8
0
void	server_reboot()
{
  Reg	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..."));
  flush_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) || isatty(0))
    (void)close(0);
  if (!(bootopt & (BOOT_INETD|BOOT_OPER)))
    (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);
}
Пример #9
0
/** Append bytes to a data buffer.
 * @param[in] dyn Buffer to append to.
 * @param[in] buf Data to append.
 * @param[in] length Number of bytes to append.
 * @return Non-zero on success, or zero on failure.
 */
int dbuf_put(struct DBuf *dyn, const char *buf, unsigned int length)
{
  struct DBufBuffer** h;
  struct DBufBuffer*  db;
  unsigned int chunk;

  assert(0 != dyn);
  assert(0 != buf);
  /*
   * Locate the last non-empty buffer. If the last buffer is full,
   * the loop will terminate with 'db==NULL'.
   * This loop assumes that the 'dyn->length' field is correctly
   * maintained, as it should--no other check really needed.
   */
  if (!dyn->length)
    h = &(dyn->head);
  else
    h = &(dyn->tail);
  /*
   * Append users data to buffer, allocating buffers as needed
   */
  dyn->length += length;

  for (; length > 0; h = &(db->next)) {
    if (0 == (db = *h)) {
      if (0 == (db = dbuf_alloc())) {
	if (feature_bool(FEAT_HAS_FERGUSON_FLUSHER)) {
	  /*
	   * from "Married With Children" episode were Al bought a REAL toilet
	   * on the black market because he was tired of the wimpy water
	   * conserving toilets they make these days --Bleep
	   */
	  /*
	   * Apparently this doesn't work, the server _has_ to
	   * dump a few clients to handle the load. A fully loaded
	   * server cannot handle a net break without dumping some
	   * clients. If we flush the connections here under a full
	   * load we may end up starving the kernel for mbufs and
	   * crash the machine
	   */
	  /*
	   * attempt to recover from buffer starvation before
	   * bailing this may help servers running out of memory
	   */
	  flush_connections(0);
	  db = dbuf_alloc();
	}

        if (0 == db)
          return dbuf_malloc_error(dyn);
      }
      dyn->tail = db;
      *h = db;
      db->next = 0;
      db->start = db->end = db->data;
    }
    chunk = (db->data + DBUF_SIZE) - db->end;
    if (chunk) {
      if (chunk > length)
        chunk = length;

      memcpy(db->end, buf, chunk);

      length -= chunk;
      buf += chunk;
      db->end += chunk;
    }
  }
  return 1;
}
Пример #10
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 */

}
Пример #11
0
/*
 * m_die - DIE command handler
 */
int m_die(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct Client* acptr;
  int      i;

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

  if (!IsOperDie(sptr))
    {
      sendto_one(sptr,":%s NOTICE %s :You have no D flag", me.name, parv[0]);
      return 0;
    }

  if (parc < 2)
    {
      sendto_one(sptr,":%s NOTICE %s :Need server name /die %s",
                 me.name,sptr->name,me.name);
      return 0;
    }
  else
    {
      if (irccmp(parv[1], me.name))
        {
          sendto_one(sptr,":%s NOTICE %s :Mismatch on /die %s",
                     me.name,sptr->name,me.name);
          return 0;
        }
    }

  for (i = 0; i <= highest_fd; i++)
    {
      if (!(acptr = local[i]))
        continue;
      if (IsClient(acptr))
        {
          if(IsAnOper(acptr))
            sendto_one(acptr,
                       ":%s NOTICE %s :Server Terminating. %s",
                       me.name, acptr->name,
                       get_client_name(sptr, HIDE_IP));
          else
            sendto_one(acptr,
                       ":%s NOTICE %s :Server Terminating. %s",
                       me.name, acptr->name,
                       get_client_name(sptr, MASK_IP));
        }
      else if (IsServer(acptr))
        sendto_one(acptr, ":%s ERROR :Terminated by %s",
                   me.name, get_client_name(sptr, MASK_IP));
    }
  flush_connections(0);
  irclog(L_NOTICE, "Server terminated by %s", get_client_name(sptr, HIDE_IP));
  /* 
   * this is a normal exit, tell the os it's ok 
   */
  exit(0);
  /* NOT REACHED */
  return 0;
}
Пример #12
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;
}
Пример #13
0
/** Attempt to send a sequence of bytes to the connection.
 * As a side effect, updates \a cptr's FLAG_BLOCKED setting
 * and sendB/sendK fields.
 * @param cptr Client that should receive data.
 * @param buf Message buffer to send to client.
 * @return Negative on connection-fatal error; otherwise
 *  number of bytes sent.
 */
unsigned int deliver_it(struct Client *cptr, struct MsgQ *buf)
{
  unsigned int bytes_written = 0;
  unsigned int bytes_count = 0;
  assert(0 != cptr);

#if defined(USE_SSL)
  switch (client_sendv(cptr, buf, &bytes_count, &bytes_written)) {
#else
  switch (os_sendv_nonb(cli_fd(cptr), buf, &bytes_count, &bytes_written)) {
#endif
  case IO_SUCCESS:
    ClrFlag(cptr, FLAG_BLOCKED);

    cli_sendB(cptr) += bytes_written;
    cli_sendB(&me)  += bytes_written;
    /* A partial write implies that future writes will block. */
    if (bytes_written < bytes_count)
      SetFlag(cptr, FLAG_BLOCKED);
    break;
  case IO_BLOCKED:
    SetFlag(cptr, FLAG_BLOCKED);
    break;
  case IO_FAILURE:
    cli_error(cptr) = errno;
    SetFlag(cptr, FLAG_DEADSOCKET);
    break;
  }
  return bytes_written;
}

/** Complete non-blocking connect()-sequence. Check access and
 * terminate connection, if trouble detected.
 * @param cptr Client to which we have connected, with all ConfItem structs attached.
 * @return Zero on failure (caller should exit_client()), non-zero on success.
 */
static int completed_connection(struct Client* cptr)
{
  struct ConfItem *aconf;
  time_t newts;
  struct Client *acptr;
  int i;
#if defined(USE_SSL)
  char *sslfp;
  int r;
#endif

  assert(0 != cptr);

  /*
   * get the socket status from the fd first to check if
   * connection actually succeeded
   */
  if ((cli_error(cptr) = os_get_sockerr(cli_fd(cptr)))) {
    const char* msg = strerror(cli_error(cptr));
    if (!msg)
      msg = "Unknown error";
    sendto_opmask(0, SNO_OLDSNO, "Connection failed to %s: %s",
                  cli_name(cptr), msg);
    return 0;
  }
  if (!(aconf = find_conf_byname(cli_confs(cptr), cli_name(cptr), CONF_SERVER))) {
    sendto_opmask(0, SNO_OLDSNO, "Lost Server Line for %s", cli_name(cptr));
    return 0;
  }

#if defined(USE_SSL)
  if (aconf->flags & CONF_SSL) {
    r = ssl_connect(&(cli_socket(cptr)));
    if (r == -1) {
      sendto_opmask(0, SNO_OLDSNO, "Connection failed to %s: SSL error",
                    cli_name(cptr));
      return 0;
    } else if (r == 0)
      return 1;
    sslfp = ssl_get_fingerprint(cli_socket(cptr).s_ssl);
    if (sslfp)
      ircd_strncpy(cli_sslclifp(cptr), sslfp, BUFSIZE+1);
    SetSSL(cptr);
  }
#endif

  if (s_state(&(cli_socket(cptr))) == SS_CONNECTING)
    socket_state(&(cli_socket(cptr)), SS_CONNECTED);

  if (!EmptyString(aconf->passwd))
    sendrawto_one(cptr, MSG_PASS " :%s", aconf->passwd);

  /*
   * Create a unique timestamp
   */
  newts = TStime();
  for (i = HighestFd; i > -1; --i) {
    if ((acptr = LocalClientArray[i]) &&
        (IsServer(acptr) || IsHandshake(acptr))) {
      if (cli_serv(acptr)->timestamp >= newts)
        newts = cli_serv(acptr)->timestamp + 1;
    }
  }
  assert(0 != cli_serv(cptr));

  cli_serv(cptr)->timestamp = newts;
  SetHandshake(cptr);
  /*
   * Make us timeout after twice the timeout for DNS look ups
   */
  cli_lasttime(cptr) = CurrentTime;
  ClearPingSent(cptr);

/* TODO: NEGOCIACION
  envia_config_req(cptr);
*/

  sendrawto_one(cptr, MSG_SERVER " %s 1 %Tu %Tu J%s %s%s +%s6 :%s",
                cli_name(&me), cli_serv(&me)->timestamp, newts,
		MAJOR_PROTOCOL, NumServCap(&me),
		feature_bool(FEAT_HUB) ? "h" : "", cli_info(&me));

#if defined(DDB)
  ddb_burst(cptr);
#endif

  return (IsDead(cptr)) ? 0 : 1;
}

/** Close the physical connection.  Side effects: MyConnect(cptr)
 * becomes false and cptr->from becomes NULL.
 * @param cptr Client to disconnect.
 */
void close_connection(struct Client *cptr)
{
  struct ConfItem* aconf;

  if (IsServer(cptr)) {
    ServerStats->is_sv++;
    ServerStats->is_sbs += cli_sendB(cptr);
    ServerStats->is_sbr += cli_receiveB(cptr);
    ServerStats->is_sti += CurrentTime - cli_firsttime(cptr);
    /*
     * If the connection has been up for a long amount of time, schedule
     * a 'quick' reconnect, else reset the next-connect cycle.
     */
    if ((aconf = find_conf_exact(cli_name(cptr), cptr, CONF_SERVER))) {
      /*
       * Reschedule a faster reconnect, if this was a automatically
       * connected configuration entry. (Note that if we have had
       * a rehash in between, the status has been changed to
       * CONF_ILLEGAL). But only do this if it was a "good" link.
       */
      aconf->hold = CurrentTime;
      aconf->hold += ((aconf->hold - cli_since(cptr) >
		       feature_int(FEAT_HANGONGOODLINK)) ?
		      feature_int(FEAT_HANGONRETRYDELAY) : ConfConFreq(aconf));
/*        if (nextconnect > aconf->hold) */
/*          nextconnect = aconf->hold; */
    }
  }
  else if (IsUser(cptr)) {
    ServerStats->is_cl++;
    ServerStats->is_cbs += cli_sendB(cptr);
    ServerStats->is_cbr += cli_receiveB(cptr);
    ServerStats->is_cti += CurrentTime - cli_firsttime(cptr);
  }
  else
    ServerStats->is_ni++;

#if defined(USE_ZLIB)
  /*
   * Siempre es una conexion nuestra
   */
  if (cli_connect(cptr)->zlib_negociation & ZLIB_IN) {
    inflateEnd(cli_connect(cptr)->comp_in);
    MyFree(cli_connect(cptr)->comp_in);
  }
  if (cli_connect(cptr)->zlib_negociation & ZLIB_OUT) {
    deflateEnd(cli_connect(cptr)->comp_out);
    MyFree(cli_connect(cptr)->comp_out);
  }
#endif

  if (-1 < cli_fd(cptr)) {
    flush_connections(cptr);
    LocalClientArray[cli_fd(cptr)] = 0;
    close(cli_fd(cptr));
    socket_del(&(cli_socket(cptr))); /* queue a socket delete */
    cli_fd(cptr) = -1;
    cli_freeflag(cptr) &= ~FREEFLAG_SOCKET;
  }
  SetFlag(cptr, FLAG_DEADSOCKET);

  MsgQClear(&(cli_sendQ(cptr)));
  client_drop_sendq(cli_connect(cptr));
  DBufClear(&(cli_recvQ(cptr)));
  memset(cli_passwd(cptr), 0, sizeof(cli_passwd(cptr)));
  set_snomask(cptr, 0, SNO_SET);

  det_confs_butmask(cptr, 0);

  if (cli_listener(cptr)) {
    release_listener(cli_listener(cptr));
    cli_listener(cptr) = 0;
  }

  for ( ; HighestFd > 0; --HighestFd) {
    if (LocalClientArray[HighestFd])
      break;
  }
}

/** Close all unregistered connections.
 * @param source Oper who requested the close.
 * @return Number of closed connections.
 */
int net_close_unregistered_connections(struct Client* source)
{
  int            i;
  struct Client* cptr;
  int            count = 0;
  assert(0 != source);

  for (i = HighestFd; i > 0; --i) {
    if ((cptr = LocalClientArray[i]) && !IsRegistered(cptr)) {
      send_reply(source, RPL_CLOSING, get_client_name(source, HIDE_IP));
      exit_client(source, cptr, &me, "Oper Closing");
      ++count;
    }
  }
  return count;
}
Пример #14
0
/** Close the physical connection.  Side effects: MyConnect(cptr)
 * becomes false and cptr->from becomes NULL.
 * @param cptr Client to disconnect.
 */
void close_connection(struct Client *cptr)
{
  struct ConfItem* aconf;

  if (IsServer(cptr)) {
    ServerStats->is_sv++;
    ServerStats->is_sbs += cli_sendB(cptr);
    ServerStats->is_sbr += cli_receiveB(cptr);
    ServerStats->is_sti += CurrentTime - cli_firsttime(cptr);
    /*
     * If the connection has been up for a long amount of time, schedule
     * a 'quick' reconnect, else reset the next-connect cycle.
     */
    if ((aconf = find_conf_exact(cli_name(cptr), cptr, CONF_SERVER))) {
      /*
       * Reschedule a faster reconnect, if this was a automatically
       * connected configuration entry. (Note that if we have had
       * a rehash in between, the status has been changed to
       * CONF_ILLEGAL). But only do this if it was a "good" link.
       */
      aconf->hold = CurrentTime;
      aconf->hold += ((aconf->hold - cli_since(cptr) >
		       feature_int(FEAT_HANGONGOODLINK)) ?
		      feature_int(FEAT_HANGONRETRYDELAY) : ConfConFreq(aconf));
/*        if (nextconnect > aconf->hold) */
/*          nextconnect = aconf->hold; */
    }
  }
  else if (IsUser(cptr)) {
    ServerStats->is_cl++;
    ServerStats->is_cbs += cli_sendB(cptr);
    ServerStats->is_cbr += cli_receiveB(cptr);
    ServerStats->is_cti += CurrentTime - cli_firsttime(cptr);
  }
  else
    ServerStats->is_ni++;

  if (-1 < cli_fd(cptr)) {
    flush_connections(cptr);
    LocalClientArray[cli_fd(cptr)] = 0;
    close(cli_fd(cptr));
    socket_del(&(cli_socket(cptr))); /* queue a socket delete */
    cli_fd(cptr) = -1;
  }
  SetFlag(cptr, FLAG_DEADSOCKET);

  MsgQClear(&(cli_sendQ(cptr)));
  client_drop_sendq(cli_connect(cptr));
  DBufClear(&(cli_recvQ(cptr)));
  memset(cli_passwd(cptr), 0, sizeof(cli_passwd(cptr)));
  set_snomask(cptr, 0, SNO_SET);

  det_confs_butmask(cptr, 0);

  if (cli_listener(cptr)) {
    release_listener(cli_listener(cptr));
    cli_listener(cptr) = 0;
  }

  for ( ; HighestFd > 0; --HighestFd) {
    if (LocalClientArray[HighestFd])
      break;
  }
}