Esempio n. 1
0
/*
 * mr_server - SERVER message handler
 *      parv[0] = sender prefix
 *      parv[1] = servername
 *      parv[2] = serverinfo/hopcount
 *      parv[3] = serverinfo
 */
static void mr_server(struct Client *client_p, struct Client *source_p,
                      int parc, char *parv[])
{
  char             info[REALLEN + 1];
  char             *name;
  struct Client    *target_p;
  int hop;

  if (parc < 4)
    {
      sendto_one(client_p,"ERROR :No servername");
      exit_client(client_p, client_p, client_p, "Wrong number of args");
      return;
    }

  name = parv[1];
  hop = atoi(parv[2]);
  strlcpy(info, parv[3], REALLEN);

  /* 
   * Reject a direct nonTS server connection if we're TS_ONLY -orabidoo
   */
  if (!DoesTS(client_p))
    {
      sendto_realops_flags(FLAGS_ALL, L_ADMIN,"Link %s dropped, non-TS server",
			   get_client_name(client_p, HIDE_IP));
      sendto_realops_flags(FLAGS_ALL, L_OPER,"Link %s dropped, non-TS server",
			   get_client_name(client_p, MASK_IP));
      exit_client(client_p, client_p, client_p, "Non-TS server");
      return;
    }

  if (bogus_host(name))
  {
    exit_client(client_p, client_p, client_p, "Bogus server name");
    return;
  }

  /* Now we just have to call check_server and everything should be
   * check for us... -A1kmm. */
  switch (check_server(name, client_p, CHECK_SERVER_NOCRYPTLINK))
  {
    case -1:
      if (ConfigFileEntry.warn_no_nline)
      {
        sendto_realops_flags(FLAGS_ALL, L_ADMIN,
           "Unauthorized server connection attempt from %s: No entry for "
           "servername %s", get_client_name(client_p, HIDE_IP), name);

        sendto_realops_flags(FLAGS_ALL, L_OPER,
           "Unauthorized server connection attempt from %s: No entry for "
           "servername %s", get_client_name(client_p, MASK_IP), name);
      }
      
      exit_client(client_p, client_p, client_p, "Invalid servername.");
      return;
      /* NOT REACHED */
      break;
      
    case -2:
      sendto_realops_flags(FLAGS_ALL, L_ADMIN,
           "Unauthorized server connection attempt from %s: Bad password "
           "for server %s", get_client_name(client_p, HIDE_IP), name);

      sendto_realops_flags(FLAGS_ALL, L_OPER,
           "Unauthorized server connection attempt from %s: Bad password "
           "for server %s", get_client_name(client_p, MASK_IP), name);

      exit_client(client_p, client_p, client_p, "Invalid password.");
      return;
      /* NOT REACHED */
      break;
      
    case -3:
      sendto_realops_flags(FLAGS_ALL, L_ADMIN,
           "Unauthorized server connection attempt from %s: Invalid host "
           "for server %s", get_client_name(client_p, HIDE_IP), name);

      sendto_realops_flags(FLAGS_ALL, L_OPER,
           "Unauthorized server connection attempt from %s: Invalid host "
           "for server %s", get_client_name(client_p, MASK_IP), name);

      exit_client(client_p, client_p, client_p, "Invalid host.");
      return;
      /* NOT REACHED */
      break;
    
    /* servername is > HOSTLEN */
    case -4:
      sendto_realops_flags(FLAGS_ALL, L_ADMIN,
                           "Invalid servername %s from %s",
			   name, get_client_name(client_p, HIDE_IP));
      sendto_realops_flags(FLAGS_ALL, L_OPER,
		           "Invalid servername %s from %s",
			   name, get_client_name(client_p, MASK_IP));

      exit_client(client_p, client_p, client_p, "Invalid servername.");
      return;
      /* NOT REACHED */
      break;
  }
    
  if ((target_p = server_exists(name)))
    {
      /*
       * 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
       *
       * Definitely don't do that here. This is from an unregistered
       * connect - A1kmm.
       */
      sendto_realops_flags(FLAGS_ALL, L_ADMIN,
         "Attempt to re-introduce server %s from %s", name,
         get_client_name(client_p, HIDE_IP));

      sendto_realops_flags(FLAGS_ALL, L_OPER,
         "Attempt to re-introduce server %s from %s", name,
         get_client_name(client_p, MASK_IP));

      sendto_one(client_p, "ERROR :Server already exists.");
      exit_client(client_p, client_p, client_p, "Server Exists");
      return;
    }

  if(ServerInfo.hub && IsCapable(client_p, CAP_LL))
    {
      if(IsCapable(client_p, CAP_HUB))
        {
          ClearCap(client_p,CAP_LL);
          sendto_realops_flags(FLAGS_ALL, L_ALL,
               "*** LazyLinks to a hub from a hub, thats a no-no.");
        }
      else
        {
          client_p->localClient->serverMask = nextFreeMask();

          if(!client_p->localClient->serverMask)
            {
              sendto_realops_flags(FLAGS_ALL, L_ALL,
                                   "serverMask is full!");
              /* try and negotiate a non LL connect */
              ClearCap(client_p,CAP_LL);
            }
        }
    }
  else if (IsCapable(client_p, CAP_LL))
    {
      if(!IsCapable(client_p, CAP_HUB))
        {
          ClearCap(client_p,CAP_LL);
          sendto_realops_flags(FLAGS_ALL, L_ALL,
               "*** LazyLinks to a leaf from a leaf, thats a no-no.");
        }
    }

  /*
   * if we are connecting (Handshake), we already have the name from the
   * C:line in client_p->name
   */

  strlcpy(client_p->name, name, HOSTLEN+1);
  set_server_gecos(client_p, info);
  client_p->hopcount = hop;
  server_estab(client_p);
}
Esempio n. 2
0
/*
 * m_lljoin
 *      parv[0] = sender prefix
 *      parv[1] = channel
 *      parv[2] = nick ("!nick" == cjoin)
 *      parv[3] = key (optional)
 *
 * If a lljoin is received, from our uplink, join
 * the requested client to the given channel, or ignore it
 * if there is an error.
 *
 *   Ok, the way this works. Leaf client tries to join a channel, 
 * it doesn't exist so the join does a cburst request on behalf of the
 * client, and aborts that join. The cburst sjoin's the channel if it
 * exists on the hub, and sends back an LLJOIN to the leaf. Thats where
 * this is now..
 *
 */
static void
ms_lljoin(struct Client *client_p, struct Client *source_p,
          int parc, char *parv[])
{
  char *chname = NULL;
  char *nick = NULL;
  char *key = NULL;
  int  flags;
  int  i;
  struct Client *target_p;
  struct Channel *chptr;

  if (uplink && !IsCapable(uplink,CAP_LL))
  {
      sendto_realops_flags(UMODE_ALL, L_ALL,
			   "*** LLJOIN requested from non LL server %s",
			   client_p->name);
      return;
  }

  chname = parv[1];
  if(chname == NULL)
    return;

  nick = parv[2];
  if(nick == NULL)
    return;

  if(parc >3)
  {
    key = parv[3];
  }

  flags = 0;

  target_p = find_person(nick);

  if( !target_p || !target_p->user )
    return;

  if( !MyClient(target_p) )
    return;

  chptr = get_or_create_channel(target_p, chname, NULL);
  flags = CHFL_CHANOP;
   
  if(!chptr)
    return;

  if (dlink_list_length(&chptr->members) == 0)
    flags = CHFL_CHANOP;
  else
    flags = 0;

  /* XXX in m_join.c :( */
  /* check_spambot_warning(target_p, chname); */

  /* They _could_ join a channel twice due to lag */
  if(chptr)
  {
    if (IsMember(target_p, chptr))    /* already a member, ignore this */
      return;
  }
  else
  {
    sendto_one(target_p, form_str(ERR_UNAVAILRESOURCE),
               me.name, nick, chptr->chname);
    return;
  }

  if ((i = can_join(target_p, chptr, key)))
  {
    sendto_one(target_p, form_str(i),
               me.name, nick, chptr->chname);
    return;
  }

  if ((dlink_list_length(&target_p->user->channel) >= ConfigChannel.max_chans_per_user) &&
      (!IsOper(target_p) || (dlink_list_length(&target_p->user->channel) >=
                             ConfigChannel.max_chans_per_user*3)))
  {
      sendto_one(target_p, form_str(ERR_TOOMANYCHANNELS),
		 me.name, nick, chptr->chname );
      return; 
  }
  
  if (flags == CHFL_CHANOP)
  {
      chptr->channelts = CurrentTime;

      sendto_one(uplink,
		 ":%s SJOIN %lu %s + :@%s",
		 me.name,
		 (unsigned long) chptr->channelts,
		 chptr->chname,
		 nick);
  }

  sendto_one(uplink,
             ":%s SJOIN %lu %s + :%s",
	     me.name,
	     (unsigned long) chptr->channelts,
	     chptr->chname,
	     nick);

  add_user_to_channel(chptr, target_p, flags);

  sendto_channel_local(ALL_MEMBERS, chptr,
		       ":%s!%[email protected]%s JOIN :%s",
		       target_p->name,
		       target_p->username,
		       target_p->host,
		       chptr->chname);
  
  if (flags & CHFL_CHANOP)
  {
    chptr->mode.mode |= MODE_TOPICLIMIT;
    chptr->mode.mode |= MODE_NOPRIVMSGS;
      
    sendto_channel_local(ALL_MEMBERS,chptr,
                         ":%s MODE %s +nt",
                         me.name, chptr->chname);
    sendto_one(uplink, 
               ":%s MODE %s +nt",
               me.name, chptr->chname);
  }

  channel_member_names(target_p, chptr, 1);
}
Esempio n. 3
0
/*
 * ms_server - SERVER message handler
 *      parv[0] = sender prefix
 *      parv[1] = servername
 *      parv[2] = serverinfo/hopcount
 *      parv[3] = serverinfo
 */
static void ms_server(struct Client *client_p, struct Client *source_p,
                      int parc, char *parv[])
{
  char             info[REALLEN + 1];
                   /* same size as in s_misc.c */
  char*            name;
  struct Client*   target_p;
  struct Client*   bclient_p;
  struct ConfItem* aconf;
  int              hop;
  int              hlined = 0;
  int              llined = 0;
  dlink_node	   *ptr;

  /* Just to be sure -A1kmm. */
  if (!IsServer(source_p))
   return;

  if (parc < 4)
    {
      sendto_one(client_p,"ERROR :No servername");
      return;
    }

  name = parv[1];
  hop = atoi(parv[2]);
  strlcpy(info, parv[3], REALLEN);

  if ((target_p = server_exists(name)))
    {
      /*
       * 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
       *
       * I think that we should exit the link itself, not the introducer,
       * and we should always exit the most recently received(i.e. the
       * one we are receiving this SERVER for. -A1kmm
       *
       * You *cant* do this, if you link somewhere, it bursts you a server
       * that already exists, then sends you a client burst, you squit the
       * server, but you keep getting the burst of clients on a server that
       * doesnt exist, although ircd can handle it, its not a realistic
       * solution.. --fl_ 
       */
      /* It is behind a host-masked server. Completely ignore the
       * server message(don't propagate or we will delink from whoever
       * we propagate to). -A1kmm */
      if (irccmp(target_p->name, name) && target_p->from==client_p)
        return;

      sendto_one(client_p, "ERROR :Server %s already exists", name);
	
      sendto_realops_flags(FLAGS_ALL, L_ADMIN,
	                   "Link %s cancelled, server %s already exists",
		 	   get_client_name(client_p, SHOW_IP), name);
      sendto_realops_flags(FLAGS_ALL, L_OPER,
	                   "Link %s cancelled, server %s already exists",
		 	   client_p->name, name);
      
        exit_client(client_p, client_p, &me, "Server Exists");
	return;
    }
  
  /* 
   * User nicks never have '.' in them and server names
   * must always have '.' in them.
   */
  if (strchr(name,'.') == NULL)
    {
      /*
       * 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(client_p,"ERROR :Nickname %s already exists!", name);
      sendto_realops_flags(FLAGS_ALL, L_ADMIN,
			   "Link %s cancelled: Server/nick collision on %s",
		/* inpath */ get_client_name(client_p, HIDE_IP), name);
      sendto_realops_flags(FLAGS_ALL, L_OPER,
          "Link %s cancelled: Server/nick collision on %s",
	  get_client_name(client_p, MASK_IP), name);
      exit_client(client_p, client_p, client_p, "Nick as Server");
      return;
    }

  /*
   * 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(client_p, "ERROR :No server info specified for %s", name);
      return;
    }

  /*
   * See if the newly found server is behind a guaranteed
   * leaf. If so, close the link.
   *
   */

  for (aconf = ConfigItemList; aconf; aconf=aconf->next)
    {
     if ((aconf->status & (CONF_LEAF|CONF_HUB)) == 0)
       continue;

     if (match(aconf->name, client_p->name))
       {
        if (aconf->status == CONF_HUB)
	  {
	    if(match(aconf->host, name))
	      hlined++;
	  }
        else if (aconf->status == CONF_LEAF)
	  {
	    if(match(aconf->host, name))
	      llined++;
	  }
       }
    }

  /* Ok, this way this works is
   *
   * A server can have a CONF_HUB allowing it to introduce servers
   * behind it.
   *
   * connect {
   *            name = "irc.bighub.net";
   *            hub_mask="*";
   *            ...
   * 
   * That would allow "irc.bighub.net" to introduce anything it wanted..
   *
   * However
   *
   * connect {
   *            name = "irc.somehub.fi";
   *		hub_mask="*";
   *		leaf_mask="*.edu";
   *...
   * Would allow this server in finland to hub anything but
   * .edu's
   */

  /* Ok, check client_p can hub the new server, and make sure it's not a LL */
  if (!hlined || (IsCapable(client_p, CAP_LL) && !IsCapable(client_p, CAP_HUB)))
    {
      /* OOOPs nope can't HUB */
      sendto_realops_flags(FLAGS_ALL, L_ADMIN, "Non-Hub link %s introduced %s.",
                get_client_name(client_p, HIDE_IP), name);

      sendto_realops_flags(FLAGS_ALL, L_OPER,
          "Non-Hub link %s introduced %s.",
	  get_client_name(client_p, MASK_IP), name);

      exit_client(NULL, source_p, &me, "No matching hub_mask.");
      return;
    }

  /* Check for the new server being leafed behind this HUB */
  if (llined)
    {
      /* OOOPs nope can't HUB this leaf */
      sendto_realops_flags(FLAGS_ALL, L_ADMIN,
            "Link %s introduced leafed server %s.",
	    get_client_name(client_p, HIDE_IP), name);
      sendto_realops_flags(FLAGS_ALL, L_OPER, 
            "Link %s introduced leafed server %s.",
            client_p->name, name);
      /* If it is new, we are probably misconfigured, so split the
       * non-hub server introducing this. Otherwise, split the new
       * server. -A1kmm.
       */
      /* wastes too much bandwidth, generates too many errors on
       * larger networks, dont bother. --fl_
       */
#if 0
      if ((CurrentTime - source_p->firsttime) < 20)
        {
          exit_client(NULL, source_p, &me, "Leafed Server.");
          return;
        }
      else
        {
          sendto_one(source_p, ":%s SQUIT %s :Sorry, Leafed server.",
                     me.name, name);
          return;
        }
#endif

      exit_client(NULL, client_p, &me, "Leafed Server.");
      return;
    }
  
  if(strlen(name) > HOSTLEN)
  {
    sendto_realops_flags(FLAGS_ALL, L_ADMIN,
 		         "Link %s introduced server with invalid servername %s",
		         get_client_name(client_p, HIDE_IP), name);
    sendto_realops_flags(FLAGS_ALL, L_OPER,
		         "Link %s introduced server with invalid servername %s",
			 client_p->name, name);
    
    exit_client(NULL, client_p, &me, "Invalid servername introduced.");
    return;
  }

  target_p = make_client(client_p);
  make_server(target_p);
  target_p->hopcount = hop;

  strlcpy(target_p->name, name, HOSTLEN+1);
  
  set_server_gecos(target_p, info);

  target_p->serv->up = find_or_add(parv[0]);
  target_p->servptr = source_p;

  SetServer(target_p);

  Count.server++;

  add_client_to_list(target_p);
  add_server_to_list(target_p);
  add_to_client_hash_table(target_p->name, target_p);
  add_client_to_llist(&(target_p->servptr->serv->servers), target_p);


  /*
   * Old sendto_serv_but_one() call removed because we now
   * need to send different names to different servers
   * (domain name matching)
   */
  for (ptr = serv_list.head; ptr; ptr = ptr->next)
    {
      bclient_p = ptr->data;

      if (bclient_p == client_p)
	continue;
      if (!(aconf = bclient_p->serv->sconf))
	{
	  sendto_realops_flags(FLAGS_ALL, L_ADMIN, 
	        "Lost N-line for %s on %s. Closing",
		get_client_name(client_p, HIDE_IP), name);
	  sendto_realops_flags(FLAGS_ALL, L_OPER, 
	        "Lost N-line for %s on %s. Closing",
		get_client_name(client_p, MASK_IP), name);
	  exit_client(client_p, client_p, client_p, "Lost N line");
          return;
	}
      if (match(my_name_for_link(me.name, aconf), target_p->name))
	continue;

      sendto_one(bclient_p, ":%s SERVER %s %d :%s%s",
		 parv[0], target_p->name, hop + 1,
		 target_p->hidden_server ? "(H) " : "",
		 target_p->info);
    }
    
  if (!IsRelay(target_p))  
  	sendto_realops_flags(FLAGS_EXTERNAL, L_ALL,
                       "Server %s being introduced by %s",
		       			target_p->name, source_p->name);
}
Esempio n. 4
0
/*
 *
 *	parc	number of arguments ('sender' counted as one!)
 *	parv[0] pointer to 'sender' (may point to empty string) (not used)
 *	parv[1]..parv[parc-1]
 *		pointers to additional parameters, this is a NULL
 *		terminated list (parv[parc] == NULL).
 *
 * *WARNING*
 *	Numerics are mostly error reports. If there is something
 *	wrong with the message, just *DROP* it! Don't even think of
 *	sending back a neat error message -- big danger of creating
 *	a ping pong error message...
 */
static void
do_numeric(char numeric[], struct Client *client_p, struct Client *source_p, int parc, char *parv[])
{
	struct Client *target_p;
	struct Channel *chptr;
	static char buffer[IRCD_BUFSIZE * 2];
	if(parc < 2 || !IsServer(source_p))
		return;

	/* Remap low number numerics. */
	if(numeric[0] == '0')
		numeric[0] = '1';

	/*
	 * Prepare the parameter portion of the message into 'buffer'.
	 * (Because the buffer is twice as large as the message buffer
	 * for the socket, no overflow can occur here... ...on current
	 * assumptions--bets are off, if these are changed --msa)
	 * Note: if buffer is non-empty, it will begin with SPACE.
	 */
	if(parc > 1)
	{
		char *t = buffer;	/* Current position within the buffer */
		int i;
		int tl;		/* current length of presently being built string in t */
		for(i = 2; i < (parc - 1); i++)
		{
			tl = sprintf(t, " %s", parv[i]);
			t += tl;
		}
		sprintf(t, " :%s", parv[parc - 1]);
	}

	if((target_p = find_client(parv[1])) != NULL)
	{
		if(IsMe(target_p))
		{
			/*
			 * We shouldn't get numerics sent to us,
			 * any numerics we do get indicate a bug somewhere..
			 */
			/* ugh.	 this is here because of nick collisions.  when two servers
			 * relink, they burst each other their nicks, then perform collides.
			 * if there is a nick collision, BOTH servers will kill their own
			 * nicks, and BOTH will kill the other servers nick, which wont exist,
			 * because it will have been already killed by the local server.
			 *
			 * unfortunately, as we cant guarantee other servers will do the
			 * "right thing" on a nick collision, we have to keep both kills.  
			 * ergo we need to ignore ERR_NOSUCHNICK. --fl_
			 */
			/* quick comment. This _was_ tried. i.e. assume the other servers
			 * will do the "right thing" and kill a nick that is colliding.
			 * unfortunately, it did not work. --Dianora
			 */
			/* note, now we send PING on server connect, we can
			 * also get ERR_NOSUCHSERVER..
			 */
			if(atoi(numeric) != ERR_NOSUCHNICK && atoi(numeric) != ERR_NOSUCHSERVER)
				sendto_realops_flags(UMODE_ALL, L_ADMIN,
						     "*** %s(via %s) sent a %s numeric to me: %s",
						     source_p->name, client_p->name, numeric, buffer);
			return;
		}
		else if(target_p->from == client_p)
		{
			/* This message changed direction (nick collision?)
			 * ignore it.
			 */
			return;
		}

		/* csircd will send out unknown umode flag for +a (admin), drop it here. */
		if((atoi(numeric) == ERR_UMODEUNKNOWNFLAG) && MyClient(target_p))
			return;

		/* Fake it for server hiding, if its our client */
		sendto_one(target_p, ":%s %s %s%s",
			   get_id(source_p, target_p), numeric, get_id(target_p, target_p), buffer);
		return;
	}
	else if((chptr = find_channel(parv[1])) != NULL)
		sendto_channel_local(ALL_MEMBERS, chptr,
				     ":%s %s %s %s", source_p->name, numeric, chptr->chname, buffer);
}