Example #1
0
/*
 * dead_link - Adds client to a list of clients that need an exit_client()
 *
 */
void dead_link(struct Client *client_p)
{
  dlink_node *m;
  const char *notice;
  if(IsClosing(client_p))
    return;

  linebuf_donebuf(&client_p->localClient->buf_recvq);
  linebuf_donebuf(&client_p->localClient->buf_sendq);
  
  if(client_p->flags & FLAGS_SENDQEX)
    notice = "Max SendQ exceeded";
  else
    notice = "Dead link";
    	
  if (!IsPerson(client_p) && !IsUnknown(client_p) && !IsClosing(client_p))
  {
    sendto_realops_flags(FLAGS_ALL, L_ADMIN,
                         notice, get_client_name(client_p, HIDE_IP));
    sendto_realops_flags(FLAGS_ALL, L_OPER,
                         notice, get_client_name(client_p, MASK_IP));
  }
  Debug((DEBUG_ERROR, notice, get_client_name(to, HIDE_IP)));
  assert(dlinkFind(&abort_list, client_p) == NULL);
  m = make_dlink_node();
  dlinkAdd(client_p, m, &abort_list);
  SetDead(client_p); /* You are dead my friend */
}
Example #2
0
/*! \brief Blindly opers up given source_p, using conf info.
 *         All checks on passwords have already been done.
 * \param source_p Pointer to given client to oper
 * \param conf operator {} configuration record
 */
static void
oper_up(struct Client *source_p, const struct MaskItem *conf)
{
  const unsigned int old = source_p->umodes;

  ++Count.oper;
  SetOper(source_p);

  if (conf->modes)
    AddUMode(source_p, conf->modes);
  else if (ConfigGeneral.oper_umodes)
    AddUMode(source_p, ConfigGeneral.oper_umodes);

  if (!(old & UMODE_INVISIBLE) && HasUMode(source_p, UMODE_INVISIBLE))
    ++Count.invisi;
  else if ((old & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE))
    --Count.invisi;

  assert(dlinkFind(&oper_list, source_p) == NULL);
  dlinkAdd(source_p, make_dlink_node(), &oper_list);

  AddOFlag(source_p, conf->port);

  if (HasOFlag(source_p, OPER_FLAG_ADMIN))
    AddUMode(source_p, UMODE_ADMIN);

  if (!EmptyString(conf->whois))
  {
    svstag_attach(&source_p->svstags, RPL_WHOISOPERATOR, "+", conf->whois);
    sendto_server(NULL, 0, 0, ":%s SVSTAG %s %ju %u + :%s",
                  me.id, source_p->id, source_p->tsinfo,
                  RPL_WHOISOPERATOR, conf->whois);
  }

  ilog(LOG_TYPE_OPER, "OPER %s by %s!%s@%s", conf->name, source_p->name,
       source_p->username, source_p->host);
  sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE, "%s is now an operator",
                       get_oper_name(source_p));
  sendto_server(NULL, 0, 0, ":%s GLOBOPS :%s is now an operator",
                me.id, get_oper_name(source_p));

  send_umode_out(source_p, old);
  sendto_one_numeric(source_p, &me, RPL_YOUREOPER);
}
Example #3
0
/* ************************************************************************ */
int
_BlockHeapFree(BlockHeap * bh, void *ptr)
{
    Block *block;
    struct MemBlock *memblock;
    
    assert(bh != NULL);
    assert(ptr != NULL);

    if (bh == NULL)
      {

        ilog(L_NOTICE, "balloc.c:BlockHeapFree() bh == NULL");
        return(1);
      }

    if (ptr == NULL)
      {
        ilog(L_NOTICE, "balloc.BlockHeapFree() ptr == NULL");
        return(1);
      }

    memblock = (void *)((size_t)ptr - sizeof(MemBlock));
    assert(memblock->block != NULL);
    if(memblock->block == NULL)
    {
      outofmemory();
    }
    /* Is this block really on the used list? */
    assert(dlinkFind(&memblock->block->used_list, memblock) == NULL); 

    block = memblock->block;
    bh->freeElems++;
    block->freeElems++;
    mem_frob(ptr, bh->elemSize);
    dlinkDelete(&memblock->self, &block->used_list);
    dlinkAdd(ptr, &memblock->self, &block->free_list);
    return(0);
}
Example #4
0
/*
** mo_jupe
**      parv[0] = sender prefix
**      parv[1] = server we're juping
**      parv[2] = reason for jupe
*/
static void mo_jupe(struct Client *client_p, struct Client *source_p,
                    int parc, char *parv[])
{
  struct Client *target_p;
  struct Client *ajupe;
  dlink_node *m;
  char reason[REALLEN+2];

  if(!ServerInfo.hub)
    return;

  if(!IsOperAdmin(source_p))
    {
      sendto_one(source_p, ":%s NOTICE %s :You must be an admin to use this command",
                 me.name, parv[0]);
      return;
    }

  if (bogus_host(parv[1]))
    {
      sendto_one(source_p, ":%s NOTICE %s :Invalid servername: %s",
                 me.name, parv[0], parv[1]);
      return;
    }

  if(match(parv[1], me.name))
  {
    sendto_one(source_p, ":%s NOTICE %s :I cant jupe myself!",
	       me.name, source_p->name);
    return;
  }

  sendto_wallops_flags(UMODE_WALLOP, &me,
                       "JUPE for %s requested by %s: %s",
			 parv[1], get_oper_name(source_p), parv[2]);

  sendto_server(NULL, NOCAPS, NOCAPS, 
                ":%s WALLOPS :JUPE for %s requested by %s!%s@%s: %s",
                parv[0], parv[1], source_p->name, 
                source_p->username, source_p->host, parv[2]);
  ilog(L_NOTICE, "JUPE for %s requested by %s: %s",
                parv[1], get_oper_name(source_p), parv[2]);

  target_p= find_server(parv[1]);

  if(target_p)
    exit_client(client_p, target_p, &me, parv[2]);

  sendto_server(NULL, NOCAPS, NOCAPS,
                ":%s SERVER %s 1 :JUPED: %s",
                me.name, parv[1], parv[2]);

  sendto_realops_flags(UMODE_ALL, L_ALL,
                       "Link with %s established: (JUPED) link",
		       parv[1]);

  ajupe = make_client(NULL);

  /* make_client() adds client to unknown_list */
  m = dlinkFind(&unknown_list, ajupe);
  if(m != NULL)
    dlinkDelete(m, &unknown_list);
  free_dlink_node(m);

  make_server(ajupe);
  ajupe->hopcount = 1;
  strlcpy(ajupe->name,parv[1],HOSTLEN);

  /* we need to give 7 chars to prepend "JUPED: " */
  if(strlen(parv[2]) > (REALLEN-7))
    parv[2][REALLEN-7] = '\0';
  ircsprintf(reason, "%s %s", "JUPED:", parv[2]);
  
  strlcpy(ajupe->info,reason,REALLEN);
  ajupe->serv->up = me.name;
  ajupe->servptr = &me;
  SetServer(ajupe);
  SetDead(ajupe);
  
  Count.server++;
  Count.myserver++;

  /* Some day, all these lists will be consolidated *sigh* */
  add_client_to_list(ajupe);
  add_to_client_hash_table(ajupe->name, ajupe);
  dlinkAdd(ajupe, &ajupe->lnode, &ajupe->servptr->serv->servers);
  add_server_to_list(ajupe);
}
Example #5
0
/*
** Exit one client, local or remote. Assuming all dependents have
** been already removed, and socket closed for local client.
*/
static void exit_one_client(struct Client *client_p,
                            struct Client *source_p,
                            struct Client *from, const char *comment)
{
  struct Client* target_p;
  dlink_node *lp;
  dlink_node *next_lp;

  if (IsServer(source_p))
    {
      if (source_p->servptr && source_p->servptr->serv)
        del_client_from_llist(&(source_p->servptr->serv->servers),
                                    source_p);
      else
        ts_warn("server %s without servptr!", source_p->name);

      if(!IsMe(source_p))
        remove_server_from_list(source_p);
    }
  else if (source_p->servptr && source_p->servptr->serv)
    {
      del_client_from_llist(&(source_p->servptr->serv->users), source_p);
    }
  /* there are clients w/o a servptr: unregistered ones */

  /*
  **  For a server or user quitting, propogate the information to
  **  other servers (except to the one where is came from (client_p))
  */
  if (IsMe(source_p))
    {
      sendto_realops_flags(FLAGS_ALL, L_ALL,
			   "ERROR: tried to exit me! : %s", comment);
      return;        /* ...must *never* exit self!! */
    }
  else if (IsServer(source_p))
    {
      /*
      ** Old sendto_serv_but_one() call removed because we now
      ** need to send different names to different servers
      ** (domain name matching)
      */
      /*
      ** The bulk of this is done in remove_dependents now, all
      ** we have left to do is send the SQUIT upstream.  -orabidoo
      */
      if (source_p->localClient)
      {
	if(source_p->localClient->ctrlfd > -1)
	{
          fd_close(source_p->localClient->ctrlfd);
	  source_p->localClient->ctrlfd = -1;

#ifndef HAVE_SOCKETPAIR
          fd_close(source_p->localClient->ctrlfd_r);
	  fd_close(source_p->localClient->fd_r);
	  
	  source_p->localClient->ctrlfd_r = -1;
	  source_p->localClient->fd_r = -1;
#endif
	}
      }

      target_p = source_p->from;
      if (target_p && IsServer(target_p) && target_p != client_p && !IsMe(target_p) &&
          (source_p->flags & FLAGS_KILLED) == 0)
        sendto_one(target_p, ":%s SQUIT %s :%s", from->name, source_p->name, comment);
    }
  else if (source_p->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 ((source_p->flags & FLAGS_KILLED) == 0)
        {
          sendto_server(client_p, source_p, NULL, NOCAPS, NOCAPS,
                        NOFLAGS, ":%s QUIT :%s", source_p->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 (source_p->user)
        {
          sendto_common_channels_local(source_p, ":%s!%s@%s QUIT :%s",
				       source_p->name,
				       source_p->username,
				       source_p->host,
				       comment);

          for (lp = source_p->user->channel.head; lp; lp = next_lp)
	    {
	      next_lp = lp->next;
	      remove_user_from_channel(lp->data, source_p);
	    }
          /* Should not be in any channels now */
          assert(source_p->user->channel.head == NULL);
          
          /* Clean up invitefield */
          for (lp = source_p->user->invited.head; lp; lp = next_lp)
           {
              next_lp = lp->next;
              del_invite(lp->data, source_p);
           }

          /* Clean up allow lists */
          del_all_accepts(source_p);

	  add_history(source_p, 0);
	  off_history(source_p);

	  if (HasID(source_p))
	    del_from_id_hash_table(source_p->user->id, source_p);
  
          /* again, this is all that is needed */
        }
    }
  
  /* 
   * Remove source_p from the client lists
   */
  del_from_client_hash_table(source_p->name, source_p);

  /* remove from global client list */
  remove_client_from_list(source_p);

  /* Check to see if the client isn't already on the dead list */
  assert(dlinkFind(&dead_list, source_p) == NULL);
  /* add to dead client dlist */
  lp = make_dlink_node();
  SetDead(source_p);
  dlinkAdd(source_p, lp, &dead_list);
}
Example #6
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:
**
**        CLIENT_EXITED        if (client_p == source_p)
**        0                if (client_p != source_p)
*/
int exit_client(
                struct Client* client_p, /* The local client originating the
                                          * exit or NULL, if this exit is
                                          * generated by this server for
                                          * internal reasons.
                                          * This will not get any of the
                                          * generated messages. */
                struct Client* source_p, /* Client exiting */
                struct Client* from,     /* Client firing off this Exit,
                                          * never NULL! */
                const char* comment      /* Reason for the exit */
               )
{
  char comment1[HOSTLEN + HOSTLEN + 2];
  dlink_node *m;
  fprintf(stderr, "Exiting client: %s\n", comment);
  if (MyConnect(source_p))
    {
      /* DO NOT REMOVE. exit_client can be called twice after a failed
       * read/write.
       */
      if(IsClosing(source_p))
        return 0;

      SetClosing(source_p);
      if (source_p->flags & FLAGS_IPHASH)
        remove_one_ip(&source_p->localClient->ip);

      delete_adns_queries(source_p->localClient->dns_query);
      delete_identd_queries(source_p);
      client_flush_input(source_p);

      /* This source_p could have status of one of STAT_UNKNOWN, STAT_CONNECTING
       * STAT_HANDSHAKE or STAT_UNKNOWN
       * all of which are lumped together into unknown_list
       *
       * In all above cases IsRegistered() will not be true.
       */
      if (!IsRegistered(source_p))
	{
	  m = dlinkFind(&unknown_list,source_p);
	  if(m != NULL)
	    {
	      dlinkDelete(m, &unknown_list);
	      free_dlink_node(m);
	    }
	}
      if (IsOper(source_p))
        {
	  m = dlinkFind(&oper_list,source_p);
	  if(m != NULL)
	    {
	      dlinkDelete(m, &oper_list);
	      free_dlink_node(m);
	    }
        }
      if (IsClient(source_p))
        {
          Count.local--;

          if(IsPerson(source_p))        /* a little extra paranoia */
            {
	      m = dlinkFind(&lclient_list,source_p);
	      if(m != NULL)
		{
		  dlinkDelete(m,&lclient_list);
		  free_dlink_node(m);
		}
            }
        }

      /* As soon as a client is known to be a server of some sort
       * it has to be put on the serv_list, or SJOIN's to this new server
       * from the connect burst will not be seen.
       */
      if (IsServer(source_p) || IsConnecting(source_p) ||
          IsHandshake(source_p))
	{
	  m = dlinkFind(&serv_list,source_p);
	  if(m != NULL)
	    {
	      dlinkDelete(m,&serv_list);
	      free_dlink_node(m);
              unset_chcap_usage_counts(source_p);
	    }
	}

      if (IsServer(source_p))
        {
          Count.myserver--;
	  if(ServerInfo.hub)
	    remove_lazylink_flags(source_p->localClient->serverMask);
	  else
	    uplink = NULL;
        }

      if (IsPerson(source_p))
        sendto_realops_flags(FLAGS_CCONN, L_ALL,
                             "Client exiting: %s (%s@%s) [%s] [%s]",
                             source_p->name, source_p->username, source_p->host,
                             comment, source_p->localClient->sockhost);

      log_user_exit(source_p);

      if (source_p->localClient->fd >= 0)
	{
	  if (client_p != NULL && source_p != client_p)
	    sendto_one(source_p, "ERROR :Closing Link: %s %s (%s)",
		       source_p->host, source_p->name, comment);
	  else
	    sendto_one(source_p, "ERROR :Closing Link: %s (%s)",
		       source_p->host, 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(source_p) == FALSE!).
      ** It also makes source_p->from == NULL, thus it's unnecessary
      ** to test whether "source_p != target_p" in the following loops.
      */
     close_connection(source_p);
    }

  if(IsServer(source_p))
    {        
      if(ConfigServerHide.hide_servers)
	{
          /* set netsplit message to "me.name *.split" to still show 
	   * that its a split, but hide the servers splitting
	   */
	  ircsprintf(comment1,"%s *.split", me.name);
	}
      else
	{
	  if((source_p->serv) && (source_p->serv->up))
	    strcpy(comment1, source_p->serv->up);
	  else
	    strcpy(comment1, "<Unknown>");

	  strcat(comment1," ");
	  strcat(comment1, source_p->name);
	}

      remove_dependents(client_p, source_p, from, comment, comment1);

      if (source_p->servptr == &me)
        {
          sendto_realops_flags(FLAGS_ALL, L_ALL,
		       "%s was connected for %d seconds.  %d/%d sendK/recvK.",
			       source_p->name, (int)(CurrentTime - source_p->firsttime),
			       source_p->localClient->sendK,
			       source_p->localClient->receiveK);
          ilog(L_NOTICE, "%s was connected for %d seconds.  %d/%d sendK/recvK.",
              source_p->name, CurrentTime - source_p->firsttime, 
              source_p->localClient->sendK, source_p->localClient->receiveK);
        }
    }
  exit_one_client(client_p, source_p, from, comment);
  return client_p == source_p ? CLIENT_EXITED : 0;
}