Exemplo n.º 1
0
/*
** m_svsnick
**      parv[0] = sender
**      parv[1] = old nickname
**      parv[2] = new nickname
**      parv[3] = timestamp
*/
int  m_svsnick(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
aClient *acptr;
aClient *ocptr; /* Other client */

	if (!IsULine(sptr) || parc < 4 || (strlen(parv[2]) > NICKLEN))
		return -1; /* This looks like an error anyway -Studded */

	if (hunt_server_token(cptr, sptr, MSG_SVSNICK, TOK_SVSNICK, "%s %s :%s", 1, parc, parv) != HUNTED_ISME)
		return 0; /* Forwarded, done */

	if (do_nick_name(parv[2]) == 0)
		return 0;

	if (!(acptr = find_person(parv[1], NULL)))
		return 0; /* User not found, bail out */

	if ((ocptr = find_client(parv[2], NULL)) && ocptr != acptr) /* Collision */
	{
		exit_client(acptr, acptr, sptr,
		                   "Nickname collision due to Services enforced "
		                   "nickname change, your nick was overruled");
		return 0;
	}

	if (acptr != ocptr)
		acptr->umodes &= ~UMODE_REGNICK;
	acptr->lastnick = TS2ts(parv[3]);
	sendto_common_channels(acptr, ":%s NICK :%s", parv[1], parv[2]);
	add_history(acptr, 1);
	sendto_serv_butone_token(NULL, parv[1], MSG_NICK, TOK_NICK,
	                         "%s :%ld", parv[2], TS2ts(parv[3]));

	(void)del_from_client_hash_table(acptr->name, acptr);
	hash_check_watch(acptr, RPL_LOGOFF);

	sendto_snomask(SNO_NICKCHANGE,
		"*** Notice -- %s (%s@%s) has been forced to change his/her nickname to %s", 
		acptr->name, acptr->user->username, acptr->user->realhost, parv[2]);
	RunHook2(HOOKTYPE_LOCAL_NICKCHANGE, acptr, parv[2]);

	strlcpy(acptr->name, parv[2], sizeof acptr->name);
	add_to_client_hash_table(parv[2], acptr);
	hash_check_watch(acptr, RPL_LOGON);

	return 0;
}
Exemplo n.º 2
0
static	void	setup_me(aClient *mp)
{
	struct	passwd	*p;

	p = getpwuid(getuid());
	strncpyzt(mp->username, (p) ? p->pw_name : "unknown",
		  sizeof(mp->username));
	(void)get_my_name(mp, mp->sockhost, sizeof(mp->sockhost)-1);
	/* I think we need no hostp, especially fake one --B.  */
	mp->hostp = NULL;
	if (mp->serv->namebuf[0] == '\0')
		strncpyzt(mp->serv->namebuf, mp->sockhost, sizeof(mp->serv->namebuf));
	if (me.info == DefInfo)
		me.info = mystrdup("IRCers United");
	mp->lasttime = mp->since = mp->firsttime = time(NULL);
	mp->hopcount = 0;
	mp->authfd = -1;
	mp->auth = mp->username;
	mp->confs = NULL;
	mp->flags = 0;
	mp->acpt = mp->from = mp;
	mp->next = NULL;
	mp->user = NULL;
	mp->fd = -1;
	SetMe(mp);
	mp->serv->snum = find_server_num (ME);
	/* we don't fill our own IP -> 0 as ip lenght */
	(void) make_user(mp,0);
	istat.is_users++;	/* here, cptr->next is NULL, see make_user() */
	mp->user->flags |= FLAGS_OPER;
	mp->serv->up = mp;
	mp->serv->maskedby = mp;
	mp->serv->version |= SV_UID;
	mp->user->server = find_server_string(mp->serv->snum);
	strncpyzt(mp->user->username, (p) ? p->pw_name : "unknown",
		  sizeof(mp->user->username));
	(void) strcpy(mp->user->host, mp->name);
	SetEOB(mp);
	istat.is_eobservers = 1;

	(void)add_to_client_hash_table(mp->name, mp);
	(void)add_to_sid_hash_table(mp->serv->sid, mp);
	strncpyzt(mp->serv->verstr, PATCHLEVEL, sizeof(mp->serv->verstr));
	setup_server_channels(mp);
}
Exemplo n.º 3
0
void change_nick(aClient *acptr, char *newnick)
{
  char     nick[NICKLEN + 2];
    
  strncpy_irc(nick, newnick, NICKLEN);
  nick[NICKLEN] = '\0';

  ClearIdentified(acptr);	/* maybe not needed, but safe -Lamego */

  /* send change to common channels */
  sendto_common_channels(acptr, ":%s NICK :%s", acptr->name, nick);
  if (acptr->user)
    {
      acptr->tsinfo = CurrentTime;
      add_history(acptr,1);
      /* propagate to all servers */
      sendto_serv_butone(NULL, ":%s NICK %s :%lu",
      acptr->name, nick, acptr->tsinfo);
    }          
		  	
  /*
   **  Finally set new nick name.
  */
  if (acptr->name[0]) 
    {
      del_from_client_hash_table(acptr->name, acptr);
      hash_check_watch(acptr, RPL_LOGOFF);     
    }
		
  strcpy(acptr->name, nick);
  add_to_client_hash_table(nick, acptr);
  hash_check_watch(acptr, RPL_LOGON);
	  
  /* Lets apply nick change delay (if needed) */
  acptr->services_nick_change++;
  if(acptr->services_nick_change>1)
    {
      acptr->number_of_nick_changes = MAX_NICK_CHANGES+1;
      acptr->last_nick_change = CurrentTime;
      acptr->services_nick_change = 0;
    }
}
Exemplo n.º 4
0
/*
 * set_initial_nick
 * inputs
 * output
 * side effects	-
 *
 * This function is only called to set up an initially registering
 * client. 
 */
int
set_initial_nick(struct Client *client_p, struct Client *source_p,
                 char *nick)
{
 char buf[USERLEN + 1];
 /* Client setting NICK the first time */
  
 /* This had to be copied here to avoid problems.. */
 source_p->tsinfo = CurrentTime;
 if (source_p->name[0])
  del_from_client_hash_table(source_p->name, source_p);
 strcpy(source_p->name, nick);
 add_to_client_hash_table(nick, source_p);
 /* fd_desc is long enough */
 fd_note(client_p->localClient->fd, "Nick: %s", nick);
  
 /* They have the nick they want now.. */
 *client_p->llname = '\0';

 if (source_p->user)
 {
  strlcpy(buf, source_p->username, USERLEN);
  /*
   * USER already received, now we have NICK.
   * *NOTE* For servers "NICK" *must* precede the
   * user message (giving USER before NICK is possible
   * only for local client connection!). register_user
   * may reject the client and call exit_client for it
   * --must test this and exit m_nick too!!!
   */
#ifdef USE_IAUTH
  /*
   * Send the client to the iauth module for verification
   */
  BeginAuthorization(source_p);
#else
  if (register_local_user(client_p, source_p, nick, buf) == CLIENT_EXITED)
   return CLIENT_EXITED;
#endif
 }
 return 0;
}
Exemplo n.º 5
0
/*
** m_nick
**	parv[0] = sender prefix
**	parv[1] = nickname
**  if from new client  -taz
**	parv[2] = nick password
**  if from server:
**      parv[2] = hopcount
**      parv[3] = timestamp
**      parv[4] = username
**      parv[5] = hostname
**      parv[6] = servername
**  if NICK version 1:
**      parv[7] = servicestamp
**	parv[8] = info
**  if NICK version 2:
**	parv[7] = servicestamp
**      parv[8] = umodes
**	parv[9] = virthost, * if none
**	parv[10] = info
**  if NICKIP:
**      parv[10] = ip
**      parv[11] = info
*/
DLLFUNC CMD_FUNC(m_nick)
{
	aTKline *tklban;
	int ishold;
	aClient *acptr, *serv = NULL;
	aClient *acptrs;
	char nick[NICKLEN + 2], *s;
	Membership *mp;
	time_t lastnick = (time_t) 0;
	int  differ = 1, update_watch = 1;
	unsigned char newusr = 0, removemoder = 1;
	/*
	 * If the user didn't specify a nickname, complain
	 */
	if (parc < 2)
	{
		sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN),
		    me.name, parv[0]);
		return 0;
	}

	strncpyzt(nick, parv[1], NICKLEN + 1);

	if (MyConnect(sptr) && sptr->user && !IsAnOper(sptr))
	{
		if ((sptr->user->flood.nick_c >= NICK_COUNT) && 
		    (TStime() - sptr->user->flood.nick_t < NICK_PERIOD))
		{
			/* Throttle... */
			sendto_one(sptr, err_str(ERR_NCHANGETOOFAST), me.name, sptr->name, nick,
				(int)(NICK_PERIOD - (TStime() - sptr->user->flood.nick_t)));
			return 0;
		}
	}

	/* For a local clients, do proper nickname checking via do_nick_name()
	 * and reject the nick if it returns false.
	 * For remote clients, do a quick check by using do_remote_nick_name(),
	 * if this returned false then reject and kill it. -- Syzop
	 */
	if ((IsServer(cptr) && !do_remote_nick_name(nick)) ||
	    (!IsServer(cptr) && !do_nick_name(nick)))
	{
		sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME),
		    me.name, parv[0], parv[1], "Illegal characters");

		if (IsServer(cptr))
		{
			ircstp->is_kill++;
			sendto_failops("Bad Nick: %s From: %s %s",
			    parv[1], parv[0], get_client_name(cptr, FALSE));
			sendto_one(cptr, ":%s KILL %s :%s (%s <- %s[%s])",
			    me.name, parv[1], me.name, parv[1],
			    nick, cptr->name);
			if (sptr != cptr)
			{	/* bad nick change */
				sendto_serv_butone(cptr,
				    ":%s KILL %s :%s (%s <- %s!%s@%s)",
				    me.name, parv[0], me.name,
				    get_client_name(cptr, FALSE),
				    parv[0],
				    sptr->user ? sptr->username : "",
				    sptr->user ? sptr->user->server :
				    cptr->name);
				sptr->flags |= FLAGS_KILLED;
				return exit_client(cptr, sptr, &me, "BadNick");
			}
		}
		return 0;
	}

	/* Kill quarantined opers early... */
	if (IsServer(cptr) && (sptr->from->flags & FLAGS_QUARANTINE) &&
	    (parc >= 11) && strchr(parv[8], 'o'))
	{
		ircstp->is_kill++;
		/* Send kill to uplink only, hasn't been broadcasted to the rest, anyway */
		sendto_one(cptr, ":%s KILL %s :%s (Quarantined: no global oper privileges allowed)",
			me.name, parv[1], me.name);
		sendto_realops("QUARANTINE: Oper %s on server %s killed, due to quarantine",
			parv[1], sptr->name);
		/* (nothing to exit_client or to free, since user was never added) */
		return 0;
	}

	/*
	   ** Protocol 4 doesn't send the server as prefix, so it is possible
	   ** the server doesn't exist (a lagged net.burst), in which case
	   ** we simply need to ignore the NICK. Also when we got that server
	   ** name (again) but from another direction. --Run
	 */
	/*
	   ** We should really only deal with this for msgs from servers.
	   ** -- Aeto
	 */
	if (IsServer(cptr) &&
	    (parc > 7
	    && (!(serv = (aClient *)find_server_b64_or_real(parv[6]))
	    || serv->from != cptr->from)))
	{
		sendto_realops("Cannot find server %s (%s)", parv[6],
		    backupbuf);
		return 0;
	}
	/*
	   ** Check against nick name collisions.
	   **
	   ** Put this 'if' here so that the nesting goes nicely on the screen :)
	   ** We check against server name list before determining if the nickname
	   ** is present in the nicklist (due to the way the below for loop is
	   ** constructed). -avalon
	 */
	/* I managed to f**k this up i guess --stskeeps */
	if ((acptr = find_server(nick, NULL)))
	{
		if (MyConnect(sptr))
		{
#ifdef GUEST
			if (IsUnknown(sptr))
			{
				RunHook4(HOOKTYPE_GUEST, cptr, sptr, parc, parv);
				return 0;
			}
#endif
			sendto_one(sptr, err_str(ERR_NICKNAMEINUSE), me.name,
			    BadPtr(parv[0]) ? "*" : parv[0], nick);
			return 0;	/* NICK message ignored */
		}
	}

	/*
	   ** Check for a Q-lined nickname. If we find it, and it's our
	   ** client, just reject it. -Lefler
	   ** Allow opers to use Q-lined nicknames. -Russell
	 */
	if (!stricmp("ircd", nick))
	{
		sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name,
		    BadPtr(parv[0]) ? "*" : parv[0], nick,
		    "Reserved for internal IRCd purposes");
		return 0;
	}
	if (!stricmp("irc", nick))
	{
		sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name,
		    BadPtr(parv[0]) ? "*" : parv[0], nick,
		    "Reserved for internal IRCd purposes");
		return 0;
	}
	if (MyClient(sptr)) /* local client changin nick afterwards.. */
	{
		int xx;
		spamfilter_build_user_string(spamfilter_user, nick, sptr);
		xx = dospamfilter(sptr, spamfilter_user, SPAMF_USER, NULL, 0, NULL);
		if (xx < 0)
			return xx;
	}
	if (!IsULine(sptr) && (tklban = find_qline(sptr, nick, &ishold)))
	{
		if (IsServer(sptr) && !ishold) /* server introducing new client */
		{
			acptrs =
			    (aClient *)find_server_b64_or_real(sptr->user ==
			    NULL ? (char *)parv[6] : (char *)sptr->user->
			    server);
			/* (NEW: no unregistered q:line msgs anymore during linking) */
			if (!acptrs || (acptrs->serv && acptrs->serv->flags.synced))
				sendto_snomask(SNO_QLINE, "Q:lined nick %s from %s on %s", nick,
				    (*sptr->name != 0
				    && !IsServer(sptr) ? sptr->name : "<unregistered>"),
				    acptrs ? acptrs->name : "unknown server");
		}
		
		if (IsServer(cptr) && IsPerson(sptr) && !ishold) /* remote user changing nick */
		{
			sendto_snomask(SNO_QLINE, "Q:lined nick %s from %s on %s", nick,
				sptr->name, sptr->srvptr ? sptr->srvptr->name : "<unknown>");
		}

		if (!IsServer(cptr)) /* local */
		{
			if (ishold)
			{
				sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME),
				    me.name, BadPtr(parv[0]) ? "*" : parv[0],
				    nick, tklban->reason);
				return 0;
			}
			if (!IsOper(cptr))
			{
				sptr->since += 4; /* lag them up */
				sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME),
				    me.name, BadPtr(parv[0]) ? "*" : parv[0],
				    nick, tklban->reason);
				sendto_snomask(SNO_QLINE, "Forbidding Q-lined nick %s from %s.",
				    nick, get_client_name(cptr, FALSE));
				return 0;	/* NICK message ignored */
			}
		}
	}
	/*
	   ** acptr already has result from previous find_server()
	 */
	if (acptr)
	{
		/*
		   ** We have a nickname trying to use the same name as
		   ** a server. Send out a nick collision KILL to remove
		   ** the nickname. As long as only a KILL is sent out,
		   ** there is no danger of the server being disconnected.
		   ** Ultimate way to jupiter a nick ? >;-). -avalon
		 */
		sendto_failops("Nick collision on %s(%s <- %s)",
		    sptr->name, acptr->from->name,
		    get_client_name(cptr, FALSE));
		ircstp->is_kill++;
		sendto_one(cptr, ":%s KILL %s :%s (%s <- %s)",
		    me.name, sptr->name, me.name, acptr->from->name,
		    /* NOTE: Cannot use get_client_name
		       ** twice here, it returns static
		       ** string pointer--the other info
		       ** would be lost
		     */
		    get_client_name(cptr, FALSE));
		sptr->flags |= FLAGS_KILLED;
		return exit_client(cptr, sptr, &me, "Nick/Server collision");
	}

	if (MyClient(cptr) && !IsOper(cptr))
		cptr->since += 3;	/* Nick-flood prot. -Donwulff */

	if (!(acptr = find_client(nick, NULL)))
		goto nickkilldone;	/* No collisions, all clear... */
	/*
	   ** If the older one is "non-person", the new entry is just
	   ** allowed to overwrite it. Just silently drop non-person,
	   ** and proceed with the nick. This should take care of the
	   ** "dormant nick" way of generating collisions...
	 */
	/* Moved before Lost User Field to fix some bugs... -- Barubary */
	if (IsUnknown(acptr) && MyConnect(acptr))
	{
		/* This may help - copying code below */
		if (acptr == cptr)
			return 0;
		acptr->flags |= FLAGS_KILLED;
		exit_client(NULL, acptr, &me, "Overridden");
		goto nickkilldone;
	}
	/* A sanity check in the user field... */
	if (acptr->user == NULL)
	{
		/* This is a Bad Thing */
		sendto_failops("Lost user field for %s in change from %s",
		    acptr->name, get_client_name(cptr, FALSE));
		ircstp->is_kill++;
		sendto_one(acptr, ":%s KILL %s :%s (Lost user field!)",
		    me.name, acptr->name, me.name);
		acptr->flags |= FLAGS_KILLED;
		/* Here's the previous versions' desynch.  If the old one is
		   messed up, trash the old one and accept the new one.
		   Remember - at this point there is a new nick coming in!
		   Handle appropriately. -- Barubary */
		exit_client(NULL, acptr, &me, "Lost user field");
		goto nickkilldone;
	}
	/*
	   ** If acptr == sptr, then we have a client doing a nick
	   ** change between *equivalent* nicknames as far as server
	   ** is concerned (user is changing the case of his/her
	   ** nickname or somesuch)
	 */
	if (acptr == sptr) {
		if (strcmp(acptr->name, nick) != 0)
		{
			/* Allows change of case in his/her nick */
			removemoder = 0; /* don't set the user -r */
			goto nickkilldone;	/* -- go and process change */
		} else
			/*
			 ** This is just ':old NICK old' type thing.
			 ** Just forget the whole thing here. There is
			 ** no point forwarding it to anywhere,
			 ** especially since servers prior to this
			 ** version would treat it as nick collision.
			 */
			return 0;	/* NICK Message ignored */
	}
	/*
	   ** Note: From this point forward it can be assumed that
	   ** acptr != sptr (point to different client structures).
	 */
	/*
	   ** Decide, we really have a nick collision and deal with it
	 */
	if (!IsServer(cptr))
	{
		/*
		   ** NICK is coming from local client connection. Just
		   ** send error reply and ignore the command.
		 */
#ifdef GUEST
		if (IsUnknown(sptr))
		{
			RunHook4(HOOKTYPE_GUEST, cptr, sptr, parc, parv);
			return 0;
		}
#endif
		sendto_one(sptr, err_str(ERR_NICKNAMEINUSE),
		    /* parv[0] is empty when connecting */
		    me.name, BadPtr(parv[0]) ? "*" : parv[0], nick);
		return 0;	/* NICK message ignored */
	}
	/*
	   ** NICK was coming from a server connection.
	   ** This means we have a race condition (two users signing on
	   ** at the same time), or two net fragments reconnecting with
	   ** the same nick.
	   ** The latter can happen because two different users connected
	   ** or because one and the same user switched server during a
	   ** net break.
	   ** If we have the old protocol (no TimeStamp and no user@host)
	   ** or if the TimeStamps are equal, we kill both (or only 'new'
	   ** if it was a "NICK new"). Otherwise we kill the youngest
	   ** when user@host differ, or the oldest when they are the same.
	   ** --Run
	   **
	 */
	if (IsServer(sptr))
	{
		/*
		   ** A new NICK being introduced by a neighbouring
		   ** server (e.g. message type "NICK new" received)
		 */
		if (parc > 3)
		{
			lastnick = TS2ts(parv[3]);
			if (parc > 5)
				differ = (mycmp(acptr->user->username, parv[4])
				    || mycmp(acptr->user->realhost, parv[5]));
		}
		sendto_failops("Nick collision on %s (%s %ld <- %s %ld)",
		    acptr->name, acptr->from->name, acptr->lastnick,
		    cptr->name, lastnick);
		/*
		   **    I'm putting the KILL handling here just to make it easier
		   ** to read, it's hard to follow it the way it used to be.
		   ** Basically, this is what it will do.  It will kill both
		   ** users if no timestamp is given, or they are equal.  It will
		   ** kill the user on our side if the other server is "correct"
		   ** (user@host differ and their user is older, or user@host are
		   ** the same and their user is younger), otherwise just kill the
		   ** user an reintroduce our correct user.
		   **    The old code just sat there and "hoped" the other server
		   ** would kill their user.  Not anymore.
		   **                                               -- binary
		 */
		if (!(parc > 3) || (acptr->lastnick == lastnick))
		{
			ircstp->is_kill++;
			sendto_serv_butone(NULL,
			    ":%s KILL %s :%s (Nick Collision)",
			    me.name, acptr->name, me.name);
			acptr->flags |= FLAGS_KILLED;
			(void)exit_client(NULL, acptr, &me,
			    "Nick collision with no timestamp/equal timestamps");
			return 0;	/* We killed both users, now stop the process. */
		}

		if ((differ && (acptr->lastnick > lastnick)) ||
		    (!differ && (acptr->lastnick < lastnick)) || acptr->from == cptr)	/* we missed a QUIT somewhere ? */
		{
			ircstp->is_kill++;
			sendto_serv_butone(cptr,
			    ":%s KILL %s :%s (Nick Collision)",
			    me.name, acptr->name, me.name);
			acptr->flags |= FLAGS_KILLED;
			(void)exit_client(NULL, acptr, &me, "Nick collision");
			goto nickkilldone;	/* OK, we got rid of the "wrong" user,
						   ** now we're going to add the user the
						   ** other server introduced.
						 */
		}

		if ((differ && (acptr->lastnick < lastnick)) ||
		    (!differ && (acptr->lastnick > lastnick)))
		{
			/*
			 * Introduce our "correct" user to the other server
			 */

			sendto_one(cptr, ":%s KILL %s :%s (Nick Collision)",
			    me.name, parv[1], me.name);
			send_umode(NULL, acptr, 0, SEND_UMODES, buf);
			sendto_one_nickcmd(cptr, acptr, buf);
			if (acptr->user->away)
				sendto_one(cptr, ":%s AWAY :%s", acptr->name,
				    acptr->user->away);
			send_user_joins(cptr, acptr);
			return 0;	/* Ignore the NICK */
		}
		return 0;
	}
	else
	{
		/*
		   ** A NICK change has collided (e.g. message type ":old NICK new").
		 */
		if (parc > 2)
			lastnick = TS2ts(parv[2]);
		differ = (mycmp(acptr->user->username, sptr->user->username) ||
		    mycmp(acptr->user->realhost, sptr->user->realhost));
		sendto_failops
		    ("Nick change collision from %s to %s (%s %ld <- %s %ld)",
		    sptr->name, acptr->name, acptr->from->name, acptr->lastnick,
		    sptr->from->name, lastnick);
		if (!(parc > 2) || lastnick == acptr->lastnick)
		{
			ircstp->is_kill += 2;
			sendto_serv_butone(NULL,	/* First kill the new nick. */
			    ":%s KILL %s :%s (Self Collision)",
			    me.name, acptr->name, me.name);
			sendto_serv_butone(cptr,	/* Tell my servers to kill the old */
			    ":%s KILL %s :%s (Self Collision)",
			    me.name, sptr->name, me.name);
			sptr->flags |= FLAGS_KILLED;
			acptr->flags |= FLAGS_KILLED;
			(void)exit_client(NULL, sptr, &me, "Self Collision");
			(void)exit_client(NULL, acptr, &me, "Self Collision");
			return 0;	/* Now that I killed them both, ignore the NICK */
		}
		if ((differ && (acptr->lastnick > lastnick)) ||
		    (!differ && (acptr->lastnick < lastnick)))
		{
			/* sptr (their user) won, let's kill acptr (our user) */
			ircstp->is_kill++;
			sendto_serv_butone(cptr,
			    ":%s KILL %s :%s (Nick collision: %s <- %s)",
			    me.name, acptr->name, me.name,
			    acptr->from->name, sptr->from->name);
			acptr->flags |= FLAGS_KILLED;
			(void)exit_client(NULL, acptr, &me, "Nick collision");
			goto nickkilldone;	/* their user won, introduce new nick */
		}
		if ((differ && (acptr->lastnick < lastnick)) ||
		    (!differ && (acptr->lastnick > lastnick)))
		{
			/* acptr (our user) won, let's kill sptr (their user),
			   ** and reintroduce our "correct" user
			 */
			ircstp->is_kill++;
			/* Kill the user trying to change their nick. */
			sendto_serv_butone(cptr,
			    ":%s KILL %s :%s (Nick collision: %s <- %s)",
			    me.name, sptr->name, me.name,
			    sptr->from->name, acptr->from->name);
			sptr->flags |= FLAGS_KILLED;
			(void)exit_client(NULL, sptr, &me, "Nick collision");
			/*
			 * Introduce our "correct" user to the other server
			 */
			/* Kill their user. */
			sendto_one(cptr, ":%s KILL %s :%s (Nick Collision)",
			    me.name, parv[1], me.name);
			send_umode(NULL, acptr, 0, SEND_UMODES, buf);
			sendto_one_nickcmd(cptr, acptr, buf);
			if (acptr->user->away)
				sendto_one(cptr, ":%s AWAY :%s", acptr->name,
				    acptr->user->away);

			send_user_joins(cptr, acptr);
			return 0;	/* their user lost, ignore the NICK */
		}

	}
	return 0;		/* just in case */
      nickkilldone:
	if (IsServer(sptr))
	{
		/* A server introducing a new client, change source */

		sptr = make_client(cptr, serv);
		add_client_to_list(sptr);
		if (parc > 2)
			sptr->hopcount = TS2ts(parv[2]);
		if (parc > 3)
			sptr->lastnick = TS2ts(parv[3]);
		else		/* Little bit better, as long as not all upgraded */
			sptr->lastnick = TStime();
		if (sptr->lastnick < 0)
		{
			sendto_realops
			    ("Negative timestamp recieved from %s, resetting to TStime (%s)",
			    cptr->name, backupbuf);
			sptr->lastnick = TStime();
		}
		newusr = 1;
	}
	else if (sptr->name[0] && IsPerson(sptr))
	{
		/*
		   ** If the client belongs to me, then check to see
		   ** if client is currently on any channels where it
		   ** is currently banned.  If so, do not allow the nick
		   ** change to occur.
		   ** Also set 'lastnick' to current time, if changed.
		 */
		if (MyClient(sptr))
		{
			for (mp = sptr->user->channel; mp; mp = mp->next)
			{
				if (!is_skochanop(sptr, mp->chptr) && is_banned(sptr, mp->chptr, BANCHK_NICK))
				{
					sendto_one(sptr,
					    err_str(ERR_BANNICKCHANGE),
					    me.name, parv[0],
					    mp->chptr->chname);
					return 0;
				}
				if (CHECK_TARGET_NICK_BANS && !is_skochanop(sptr, mp->chptr) && is_banned_with_nick(sptr, mp->chptr, BANCHK_NICK, nick))
				{
					sendto_one(sptr,
					    ":%s 437 %s %s :Cannot change to a nickname banned on channel",
					    me.name, parv[0],
					    mp->chptr->chname);
					return 0;
				}
				if (!IsOper(sptr) && !IsULine(sptr)
				    && mp->chptr->mode.mode & MODE_NONICKCHANGE
				    && !is_chanownprotop(sptr, mp->chptr))
				{
					sendto_one(sptr,
					    err_str(ERR_NONICKCHANGE),
					    me.name, parv[0],
					    mp->chptr->chname);
					return 0;
				}
			}

			if (TStime() - sptr->user->flood.nick_t >= NICK_PERIOD)
			{
				sptr->user->flood.nick_t = TStime();
				sptr->user->flood.nick_c = 1;
			} else
				sptr->user->flood.nick_c++;

			sendto_snomask(SNO_NICKCHANGE, "*** Notice -- %s (%s@%s) has changed his/her nickname to %s",
				sptr->name, sptr->user->username, sptr->user->realhost, nick);

			RunHook2(HOOKTYPE_LOCAL_NICKCHANGE, sptr, nick);
		} else {
			if (!IsULine(sptr))
				sendto_snomask(SNO_FNICKCHANGE, "*** Notice -- %s (%s@%s) has changed his/her nickname to %s",
					sptr->name, sptr->user->username, sptr->user->realhost, nick);

			RunHook3(HOOKTYPE_REMOTE_NICKCHANGE, cptr, sptr, nick);
		}
		/*
		 * Client just changing his/her nick. If he/she is
		 * on a channel, send note of change to all clients
		 * on that channel. Propagate notice to other servers.
		 */
		if (mycmp(parv[0], nick) ||
		    /* Next line can be removed when all upgraded  --Run */
		    (!MyClient(sptr) && parc > 2
		    && TS2ts(parv[2]) < sptr->lastnick))
			sptr->lastnick = (MyClient(sptr)
			    || parc < 3) ? TStime() : TS2ts(parv[2]);
		if (sptr->lastnick < 0)
		{
			sendto_realops("Negative timestamp (%s)", backupbuf);
			sptr->lastnick = TStime();
		}
		add_history(sptr, 1);
		sendto_common_channels(sptr, ":%s NICK :%s", parv[0], nick);
		sendto_serv_butone_token(cptr, parv[0], MSG_NICK, TOK_NICK,
		    "%s %ld", nick, sptr->lastnick);
		if (removemoder)
			sptr->umodes &= ~UMODE_REGNICK;
	}
	else if (!sptr->name[0])
	{
#ifdef NOSPOOF
		/*
		 * Client setting NICK the first time.
		 *
		 * Generate a random string for them to pong with.
		 */
		sptr->nospoof = getrandom32();

		if (PINGPONG_WARNING)
			sendto_one(sptr, ":%s NOTICE %s :*** If you are having problems"
			    " connecting due to ping timeouts, please"
			    " type /quote pong %X or /raw pong %X now.",
			    me.name, nick, sptr->nospoof, sptr->nospoof);

		sendto_one(sptr, "PING :%X", sptr->nospoof);
#endif /* NOSPOOF */
#ifdef CONTACT_EMAIL
		sendto_one(sptr,
		    ":%s NOTICE %s :*** If you need assistance with a"
		    " connection problem, please email " CONTACT_EMAIL
		    " with the name and version of the client you are"
		    " using, and the server you tried to connect to: %s",
		    me.name, nick, me.name);
#endif /* CONTACT_EMAIL */
#ifdef CONTACT_URL
		sendto_one(sptr,
		    ":%s NOTICE %s :*** If you need assistance with"
		    " connecting to this server, %s, please refer to: "
		    CONTACT_URL, me.name, nick, me.name);
#endif /* CONTACT_URL */

		/* Copy password to the passwd field if it's given after NICK
		 * - originally by taz, modified by Wizzu
		 */
		if ((parc > 2) && (strlen(parv[2]) <= PASSWDLEN)
		    && !(sptr->listener->umodes & LISTENER_JAVACLIENT))
		{
			if (sptr->passwd)
				MyFree(sptr->passwd);
			sptr->passwd = MyMalloc(strlen(parv[2]) + 1);
			(void)strcpy(sptr->passwd, parv[2]);
		}
		/* This had to be copied here to avoid problems.. */
		(void)strcpy(sptr->name, nick);
		if (sptr->user && IsNotSpoof(sptr))
		{
			/*
			   ** USER already received, now we have NICK.
			   ** *NOTE* For servers "NICK" *must* precede the
			   ** user message (giving USER before NICK is possible
			   ** only for local client connection!). register_user
			   ** may reject the client and call exit_client for it
			   ** --must test this and exit m_nick too!!!
			 */
#ifndef NOSPOOF
			if (USE_BAN_VERSION && MyConnect(sptr))
				sendto_one(sptr, ":IRC!IRC@%s PRIVMSG %s :\1VERSION\1",
					me.name, nick);
#endif
			sptr->lastnick = TStime();	/* Always local client */
			if (register_user(cptr, sptr, nick,
			    sptr->user->username, NULL, NULL, NULL) == FLUSH_BUFFER)
				return FLUSH_BUFFER;
			strcpy(nick, sptr->name); /* don't ask, but I need this. do not remove! -- Syzop */
			update_watch = 0;
			newusr = 1;
		}
	}
	/*
	 *  Finally set new nick name.
	 */
	if (update_watch && sptr->name[0])
	{
		(void)del_from_client_hash_table(sptr->name, sptr);
		if (IsPerson(sptr))
			hash_check_watch(sptr, RPL_LOGOFF);
	}
	(void)strcpy(sptr->name, nick);
	(void)add_to_client_hash_table(nick, sptr);
	if (IsServer(cptr) && parc > 7)
	{
		parv[3] = nick;
		do_cmd(cptr, sptr, "USER", parc - 3, &parv[3]);
		if (GotNetInfo(cptr) && !IsULine(sptr))
			sendto_fconnectnotice(sptr->name, sptr->user, sptr, 0, NULL);
	}
	else if (IsPerson(sptr) && update_watch)
		hash_check_watch(sptr, RPL_LOGON);

#ifdef NEWCHFLOODPROT
	if (sptr->user && !newusr && !IsULine(sptr))
	{
		for (mp = sptr->user->channel; mp; mp = mp->next)
		{
			aChannel *chptr = mp->chptr;
			if (chptr && !(mp->flags & (CHFL_CHANOP|CHFL_VOICE|CHFL_CHANOWNER|CHFL_HALFOP|CHFL_CHANPROT)) &&
			    chptr->mode.floodprot && do_chanflood(chptr->mode.floodprot, FLD_NICK) && MyClient(sptr))
			{
				do_chanflood_action(chptr, FLD_NICK, "nick");
			}
		}	
	}
#endif
	if (newusr && !MyClient(sptr) && IsPerson(sptr))
	{
		RunHook(HOOKTYPE_REMOTE_CONNECT, sptr);
	}

	return 0;
}
Exemplo n.º 6
0
int main(int argc, char *argv[])
{
  time_t      delay = 0;
  aConfItem*  aconf;
  
  if(geteuid() == 0)
  {
  	fprintf(stderr, "ERROR: Don't run ircd as root!\n");
  	return -1;
  }

  /*
   * save server boot time right away, so getrusage works correctly
   */
  if ((CurrentTime = time(0)) == -1)
    {
      fprintf(stderr, "ERROR: Clock Failure: %s\n", strerror(errno));
      exit(errno);
    }

  /*
   * Setup corefile size immediately after boot
   */
  setup_corefile();

  /* 
   * set initialVMTop before we allocate any memory
   */
  initialVMTop = get_vm_top();

  /*
   * Initialize the Blockheap allocator
   */
  initBlockHeap();

  ServerRunning = 0;
  memset(&me, 0, sizeof(me));
  GlobalClientList = &me;       /* Pointer to beginning of Client list */
  cold_start = YES;             /* set when server first starts up */

  memset(&Count, 0, sizeof(Count));
  Count.server = 1;     /* us */

  initialize_global_set_options();

#ifdef REJECT_HOLD
  reject_held_fds = 0;
#endif

  ConfigFileEntry.dpath = DPATH;

  ConfigFileEntry.configfile = CPATH;   /* Server configuration file */

#ifdef KPATH
  ConfigFileEntry.klinefile = KPATH;         /* Server kline file */
#else
  ConfigFileEntry.klinefile = CPATH;
#endif /* KPATH */

#ifdef DLPATH
  ConfigFileEntry.dlinefile = DLPATH;
#else
  ConfigFileEntry.dlinefile = CPATH;
#endif /* DLPATH */

#ifdef GLINES
  ConfigFileEntry.glinefile = GLINEFILE;
#endif

#ifdef  ZIP_LINKS
  /* Make sure the include files match the library version number. */
  /* configure takes care of looking for zlib and zlibVersion(). */
  if (strcmp(zlibVersion(), ZLIB_VERSION) != 0)
  {
    fprintf(stderr, "WARNING: zlib include files differ from library.\n");
    fprintf(stderr, "WARNING: ZIPLINKS may fail!\n");
    fprintf(stderr, "WARNING: library %s, include files %s\n",
            zlibVersion(), ZLIB_VERSION);
  }
#endif

  myargv = argv;
  umask(077);                /* better safe than sorry --SRB */

  parse_command_line(argc, argv); 

  if (chdir(ConfigFileEntry.dpath))
    {
      perror("chdir");
      exit(-1);
    }

  /*
   * Check if daemon is already running
   */
  check_pidfile();

  init_sys(bootDaemon);
  init_log(logFileName);

  setup_signals();
  initialize_message_files();

  isupport = make_isupport();

  dbuf_init();  /* set up some dbuf stuff to control paging */
  init_hash();

  clear_scache_hash_table();    /* server cache name table */
  clear_ip_hash_table();        /* client host ip hash table */
  clear_Dline_table();          /* d line tree */
  initlists();
  initclass();
  initwhowas();
  init_stats();
  init_tree_parse(msgtab);      /* tree parse code (orabidoo) */

  fdlist_init();
  init_netio();

  read_conf_files(YES);         /* cold start init conf files */

  aconf = find_me();
  if (EmptyString(me.name))
    strncpy_irc(me.name, aconf->host, HOSTLEN);
  strncpy_irc(me.host, aconf->host, HOSTLEN);

  me.fd = -1;
  me.from = &me;
  me.servptr = &me;
  SetMe(&me);
  make_server(&me);

  me.serv->up = me.name;
  me.lasttime = me.since = me.firsttime = CurrentTime;
  add_to_client_hash_table(me.name, &me);
  
  check_class();
  write_pidfile();

  log(L_NOTICE, "Server Ready");

  ServerRunning = 1;
  while (ServerRunning) {
    usleep(100000);
    do_adns_io();
    delay = io_loop(delay);
    do_adns_io();

  }
  return 0;
}
Exemplo n.º 7
0
/*
 * m_nick 
 * parv[0] = sender prefix 
 * parv[1] = nickname 
 * parv[2] = hopcount when new user; TS when nick change 
 * parv[3] = TS
 * ---- new user only below ---- 
 * parv[4] = umode 
 * parv[5] = username 
 * parv[6] = hostname 
 * parv[7] = server 
 * parv[8] = serviceid
 * parv[9] = IP
 * parv[10] = ircname
 * -- endif
 */
int m_nick(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
    struct simBan *ban;
    aClient    *acptr, *uplink;
    Link       *lp, *lp2;
    char        nick[NICKLEN + 2];
    ts_val      newts = 0;
    int         sameuser = 0, samenick = 0;
  
    if (parc < 2)
    {
	sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN),
		   me.name, parv[0]);
	return 0;
    }
  
    if (!IsServer(sptr) && IsServer(cptr) && parc > 2)
	newts = atol(parv[2]);
    else if (IsServer(sptr) && parc > 3)
	newts = atol(parv[3]);
    else
	parc = 2;
    /*
     * parc == 2 on a normal client sign on (local) and a normal client 
     * nick change 
     * parc == 4 on a normal server-to-server client nick change
     * parc == 11 on a normal TS style server-to-server NICK introduction
     */
    if ((IsServer(sptr) || (parc > 4)) && (parc < 11))
    {
	/*
	 * We got the wrong number of params. Someone is trying to trick
	 * us. Kill it. -ThemBones As discussed with ThemBones, not much
	 * point to this code now sending a whack of global kills would
	 * also be more annoying then its worth, just note the problem,
	 * and continue -Dianora
	 */
	sendto_realops("IGNORING BAD NICK: %s[%s@%s] on %s (from %s)", parv[1],
		       (parc >= 6) ? parv[5] : "-",
		       (parc >= 7) ? parv[6] : "-",
		       (parc >= 8) ? parv[7] : "-", parv[0]);
	return 0;
     
    }
   
    strncpyzt(nick, parv[1], NICKLEN + 1);
    /*
     * if do_nick_name() returns a null name OR if the server sent a
     * nick name and do_nick_name() changed it in some way (due to rules
     * of nick creation) then reject it. If from a server and we reject
     * it, and KILL it. -avalon 4/4/92
     */
    if (do_nick_name(nick) == 0 || (IsServer(cptr) && strcmp(nick, parv[1])))
    {
	sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME),
		   me.name, parv[0], parv[1], "Erroneous Nickname");
	
	if (IsServer(cptr))
	{
	    ircstp->is_kill++;
        sendto_realops_lev(DEBUG_LEV, "Bad Nick: %s From: %s Via: %s",
			       parv[1], parv[0],
			       get_client_name(cptr, HIDEME));
	    sendto_one(cptr, ":%s KILL %s :%s (Bad Nick)",
		       me.name, parv[1], me.name);
	    if (sptr != cptr) { /* bad nick change */     
		sendto_serv_butone(cptr, ":%s KILL %s :%s (Bad Nick)", me.name,
				   parv[0], me.name);
		sptr->flags |= FLAGS_KILLED;
		return exit_client(cptr, sptr, &me, "BadNick");
	    }
	}
	return 0;
    }
    /*
     * Check against nick name collisions.
     * 
     * Put this 'if' here so that the nesting goes nicely on the screen
     * :) We check against server name list before determining if the
     * nickname is present in the nicklist (due to the way the below
     * for loop is constructed). -avalon
     */
    do
    {
	if ((acptr = find_server(nick, NULL)))
	    if (MyConnect(sptr))
	    {
		sendto_one(sptr, err_str(ERR_NICKNAMEINUSE), me.name,
			   BadPtr(parv[0]) ? "*" : parv[0], nick);
		return 0;
	    }
	
	/* 
	 * acptr already has result from find_server
	 * Well. unless we have a capricious server on the net, a nick can
	 * never be the same as a server name - Dianora
	 * That's not the only case; maybe someone broke do_nick_name
	 * or changed it so they could use "." in nicks on their network 
	 * - sedition
	 */
     
	if (acptr)
	{
	    /*
	     * We have a nickname trying to use the same name as a
	     * server. Send out a nick collision KILL to remove the
	     * nickname. As long as only a KILL is sent out, there is no
	     * danger of the server being disconnected.  Ultimate way to
	     * jupiter a nick ? >;-). -avalon
	     */
	    sendto_realops_lev(SKILL_LEV, "Nick collision on %s", sptr->name);
	    ircstp->is_kill++;
	    sendto_one(cptr, ":%s KILL %s :%s (Nick Collision)", me.name, 
		       sptr->name, me.name);
	    sptr->flags |= FLAGS_KILLED;
	    return exit_client(cptr, sptr, &me, "Nick/Server collision");
	}
	
	if (!(acptr = find_client(nick, NULL)))
	    break;
     
	/*
	 * If acptr == sptr, then we have a client doing a nick change
	 * between *equivalent* nicknames as far as server is concerned
	 * (user is changing the case of his/her nickname or somesuch)
	 */
	if (acptr == sptr)
	{
	    if (strcmp(acptr->name, nick) == 0) 
		return 0;
	    else
		break;
	} /* If user is changing nick to itself no point in propogating */
     
	/*
	 * Note: From this point forward it can be assumed that acptr !=
	 * sptr (point to different client structures).
	 *
	 * If the older one is "non-person", the new entry is just 
	 * allowed to overwrite it. Just silently drop non-person, and
	 * proceed with the nick. This should take care of the "dormant
	 * nick" way of generating collisions...
	 */
	if (IsUnknown(acptr))
	{
	    if (MyConnect(acptr))
	    {
		exit_client(NULL, acptr, &me, "Overridden");
		break;
	    }
	    else if (!(acptr->user))
	    {
		sendto_realops_lev(SKILL_LEV, "Nick Collision on %s", parv[1]);
		sendto_serv_butone(NULL, ":%s KILL %s :%s (Nick Collision)",
				   me.name, acptr->name, me.name);
		acptr->flags |= FLAGS_KILLED;
		/* Having no USER struct should be ok... */
		return exit_client(cptr, acptr, &me,
				   "Got TS NICK before Non-TS USER");
	    }
	}
     
	if (!IsServer(cptr))
	{
	    /*
	     * NICK is coming from local client connection. Just send
	     * error reply and ignore the command.
	     * parv[0] is empty on connecting clients
	     */
	    sendto_one(sptr, err_str(ERR_NICKNAMEINUSE),
		       me.name, BadPtr(parv[0]) ? "*" : parv[0], nick);
	    return 0;
	}
	/*
	 * NICK was coming from a server connection. Means that the same
	 * nick is registered for different users by different server.
	 * This is either a race condition (two users coming online about
	 * same time, or net reconnecting) or just two net fragments
	 * becoming joined and having same nicks in use. We cannot have
	 * TWO users with same nick--purge this NICK from the system with
	 * a KILL... >;)
	 *
	 * Changed to something reasonable like IsServer(sptr) (true if
	 * "NICK new", false if ":old NICK new") -orabidoo
	 */
     
	if (IsServer(sptr))
	{
	    /*
	     * A new NICK being introduced by a neighbouring server (e.g.
	     * message type "NICK new" received)
	     */
	    if (!newts || !acptr->tsinfo || (newts == acptr->tsinfo))
	    {
		sendto_realops_lev(SKILL_LEV, "Nick collision on %s", parv[1]);
		ircstp->is_kill++;
		sendto_one(acptr, err_str(ERR_NICKCOLLISION),
			   me.name, acptr->name, acptr->name);
		sendto_serv_butone(NULL, ":%s KILL %s :%s (Nick Collision)",
				   me.name, acptr->name, me.name);
		acptr->flags |= FLAGS_KILLED;
		return exit_client(cptr, acptr, &me, "Nick collision");
	    }
	    else
	    {
		/* XXX This looks messed up to me XXX - Raist */
		sameuser = (acptr->user) &&
		    mycmp(acptr->user->username, parv[5]) == 0 &&
		    mycmp(acptr->user->host, parv[6]) == 0;
		if ((sameuser && newts < acptr->tsinfo) || 
		    (!sameuser && newts > acptr->tsinfo))
		{
		    return 0;
		}
		else
		{
		    sendto_realops_lev(SKILL_LEV, "Nick collision on %s",parv[1]);
		    ircstp->is_kill++;
		    sendto_one(acptr, err_str(ERR_NICKCOLLISION),
			       me.name, acptr->name, acptr->name);
		    sendto_serv_butone(sptr, ":%s KILL %s :%s (Nick Collision)",
				       me.name, acptr->name, me.name);
		    acptr->flags |= FLAGS_KILLED;
		    (void) exit_client(cptr, acptr, &me, "Nick collision");
		    break;
		}
	    }
	}
	/*
	 * * A NICK change has collided (e.g. message type * ":old NICK
	 * new". This requires more complex cleanout. * Both clients must be
	 * purged from this server, the "new" * must be killed from the
	 * incoming connection, and "old" must * be purged from all outgoing
	 * connections.
	 */
	if (!newts || !acptr->tsinfo || (newts == acptr->tsinfo) ||
	    !sptr->user)
	{
	    sendto_realops_lev(SKILL_LEV, "Nick change collision: %s", parv[1]);
	    ircstp->is_kill++;
	    sendto_one(acptr, err_str(ERR_NICKCOLLISION),
		       me.name, acptr->name, acptr->name);
	    sendto_serv_butone(NULL, ":%s KILL %s :%s (Nick Collision)",me.name,
			       sptr->name, me.name);
	    ircstp->is_kill++;
	    sendto_serv_butone(NULL, ":%s KILL %s :%s (Nick Collision)",me.name,
			       acptr->name, me.name);
	    acptr->flags |= FLAGS_KILLED;
	    (void) exit_client(NULL, acptr, &me, "Nick collision(new)");
	    sptr->flags |= FLAGS_KILLED;
	    return exit_client(cptr, sptr, &me, "Nick collision(old)");
	}
	else
	{
	    /* XXX This looks messed up XXX */
	    sameuser = mycmp(acptr->user->username, sptr->user->username) == 0
		&& mycmp(acptr->user->host, sptr->user->host) == 0;
	    if ((sameuser && newts < acptr->tsinfo) ||
		(!sameuser && newts > acptr->tsinfo)) {
		if (sameuser)
		    sendto_realops_lev(SKILL_LEV, 
				   "Nick change collision from %s to %s",
				   sptr->name, acptr->name);
		ircstp->is_kill++;
		sendto_serv_butone(cptr, ":%s KILL %s :%s (Nick Collision)", me.name,
				   sptr->name, me.name);
		sptr->flags |= FLAGS_KILLED;
		if (sameuser)
		    return exit_client(cptr, sptr, &me, "Nick collision(old)");
		else
		    return exit_client(cptr, sptr, &me, "Nick collision(new)");
	    } 
	    else
	    {
		sendto_realops_lev(SKILL_LEV, "Nick collision on %s", acptr->name);
		
		ircstp->is_kill++;
		sendto_one(acptr, err_str(ERR_NICKCOLLISION),
			   me.name, acptr->name, acptr->name);
		sendto_serv_butone(sptr, ":%s KILL %s :%s (Nick Collision)",me.name,
				   acptr->name, me.name);
		acptr->flags |= FLAGS_KILLED;
		(void) exit_client(cptr, acptr, &me, "Nick collision");
	    }
	}
    } while (0);
    
    if (IsServer(sptr))
    {
	uplink = find_server(parv[7], NULL);
	if(!uplink)
	{
	    /* if we can't find the server this nick is on, 
	     * complain loudly and ignore it. - lucas */
	    sendto_realops("Remote nick %s on UNKNOWN server %s",
			   nick, parv[7]);
	    return 0;
	}
	sptr = make_client(cptr, uplink);
	
	/* If this is on a U: lined server, it's a U: lined client. */
	if(IsULine(uplink))
	    sptr->flags|=FLAGS_ULINE;
     
	add_client_to_list(sptr);
	if (parc > 2)
	    sptr->hopcount = atoi(parv[2]);
	if (newts)
	{
	    sptr->tsinfo = newts;
	}
	else
	{
	    newts = sptr->tsinfo = (ts_val) timeofday;
	    ts_warn("Remote nick %s introduced without a TS", nick);
	}
	/* copy the nick in place */
	(void) strcpy(sptr->name, nick);
	(void) add_to_client_hash_table(nick, sptr);
	if (parc >= 10)
	{
	    int *s, flag;
	    char *m;
       
	    /* parse the usermodes -orabidoo */
	    m = &parv[4][1];
	    while (*m)
	    {
		for (s = user_modes; (flag = *s); s += 2)
		    if (*m == *(s + 1))
		    {
			if ((flag == UMODE_o) || (flag == UMODE_O))
			    Count.oper++;
			sptr->umode |= flag & SEND_UMODES;
			break;
		    }
		m++;
	    }
	    if (parc==10)
	    {
		return do_user(nick, cptr, sptr, parv[5], parv[6],
			       parv[7], strtoul(parv[8], NULL, 0),
			       "0.0.0.0", parv[9]);
	    } else if (parc==11)
	    {
		return do_user(nick, cptr, sptr, parv[5], parv[6], parv[7],
			       strtoul(parv[8], NULL, 0),
			       parv[9], parv[10]);
	    }
	}
    }
    else if (sptr->name[0])
    {
#ifdef DONT_CHECK_QLINE_REMOTE
	if (MyConnect(sptr))
	{
#endif
	    if ((ban = check_mask_simbanned(nick, SBAN_NICK)))
	    {
#ifndef DONT_CHECK_QLINE_REMOTE
		if (!MyConnect(sptr))
		    sendto_realops("Restricted nick %s from %s on %s", nick,
				   (*sptr->name != 0 && !IsServer(sptr)) ?
				   sptr->name : "<unregistered>",
				   (sptr->user == NULL) ? ((IsServer(sptr)) ?
							   parv[6] : me.name) :
				   sptr->user->server);
#endif
		
		if (MyConnect(sptr) && (!IsServer(cptr)) && (!IsOper(cptr))
		    && (!IsULine(sptr)))
		{
		    sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name,
			       BadPtr(parv[0]) ? "*" : parv[0], nick,
			       BadPtr(ban->reason) ? "Erroneous Nickname" :
			       ban->reason);
                    if (call_hooks(CHOOK_FORBID, cptr, nick, ban) != FLUSH_BUFFER)
		        sendto_realops_lev(REJ_LEV,
			    	           "Forbidding restricted nick %s from %s",
				           nick, get_client_name(cptr, FALSE));
		    return 0;
		}
	    }
#ifdef DONT_CHECK_QLINE_REMOTE
	}
#endif
	if (MyConnect(sptr))
	{
	    if (IsRegisteredUser(sptr))
	    {
	 
		/* before we change their nick, make sure they're not banned
		 * on any channels, and!! make sure they're not changing to
		 * a banned nick -sed */
		/* a little cleaner - lucas */
	 
		for (lp = sptr->user->channel; lp; lp = lp->next)
		{
		    if (can_send(sptr, lp->value.chptr, NULL))
		    { 
			sendto_one(sptr, err_str(ERR_BANNICKCHANGE), me.name,
				   sptr->name, lp->value.chptr->chname);
			return 0;
		    }
		    if (nick_is_banned(lp->value.chptr, nick, sptr) != NULL)
		    {
			sendto_one(sptr, err_str(ERR_BANONCHAN), me.name,
				   sptr->name, nick, lp->value.chptr->chname);
			return 0;
		    }
		}
#ifdef ANTI_NICK_FLOOD
		if ((sptr->last_nick_change + MAX_NICK_TIME) < NOW)
		    sptr->number_of_nick_changes = 0;
		sptr->last_nick_change = NOW;
		sptr->number_of_nick_changes++;
	 
		if (sptr->number_of_nick_changes > MAX_NICK_CHANGES && 
		    !IsAnOper(sptr))
		{
		    sendto_one(sptr,
			       ":%s NOTICE %s :*** Notice -- Too many nick "
			       "changes. Wait %d seconds before trying again.",
			       me.name, sptr->name, MAX_NICK_TIME);
		    return 0;
		}
#endif
		/* If it changed nicks, -r it */
		if ((sptr->umode & UMODE_r) && (mycmp(parv[0], nick) != 0))
		{
		    unsigned int oldumode;
		    char mbuf[BUFSIZE];

		    oldumode = sptr->umode;
		    sptr->umode &= ~UMODE_r;
		    send_umode(sptr, sptr, oldumode, ALL_UMODES, mbuf);
		}

                /* LOCAL NICKHANGE */
                /*
                 * Client just changing his/her nick. If he/she is on a
                 * channel, send note of change to all clients on that channel.
                 * Propagate notice to other servers.
                 */
                /* if the nickname is different, set the TS */
                if (mycmp(parv[0], nick))
                {
                  sptr->tsinfo = newts ? newts : (ts_val) timeofday;
                }

		sendto_common_channels(sptr, ":%s NICK :%s", parv[0], 
				       nick);
		if (sptr->user)
		{
		    add_history(sptr, 1);
			
		    sendto_serv_butone(cptr, ":%s NICK %s :%ld",
				       parv[0], nick, sptr->tsinfo);
		}
	    }
	}
	else
	{
            /* REMOTE NICKCHANGE */
            /*
             * Client just changing his/her nick. If he/she is on a
             * channel, send note of change to all clients on that channel.
             * Propagate notice to other servers.
             */
            /* if the nickname is different, set the TS */
            if (mycmp(parv[0], nick))
            {
              sptr->tsinfo = newts ? newts : (ts_val) timeofday;
            }

	    sendto_common_channels(sptr, ":%s NICK :%s", parv[0], nick);
	    if (sptr->user)
	    {
		add_history(sptr, 1);
		
		sendto_serv_butone(cptr, ":%s NICK %s :%ld",
				   parv[0], nick, sptr->tsinfo);
	    }

	    /* If it changed nicks, -r it */
	    if (mycmp(parv[0], nick))
		sptr->umode &= ~UMODE_r;

	    /*
	     * Flush the banserial for the channels the user is in, since this
	     * could be a SVSNICK induced nick change, which overrides any ban
	     * checking on the originating server.
	     */
	    flush_user_banserial(sptr);
	}
        /* Remove dccallow entries for users who don't share common channel(s) unless they only change their nick capitalization -Kobi_S */
        if(sptr->user && mycmp(parv[0], nick))
        {
            for(lp = sptr->user->dccallow; lp; lp = lp2)
            {
                lp2 = lp->next;
                if(lp->flags == DCC_LINK_ME)
                    continue;
                if(!find_shared_chan(sptr, lp->value.cptr))
                {
                    sendto_one(lp->value.cptr, ":%s %d %s :%s has been removed from "
                               "your DCC allow list for signing off",
                               me.name, RPL_DCCINFO, lp->value.cptr->name, parv[0]);
                    del_dccallow(lp->value.cptr, sptr, 1);
                }
            }
        }
    } 
    else
    {
	/* Client setting NICK the first time */
	if (MyConnect(sptr))
	{
	    if ((ban = check_mask_simbanned(nick, SBAN_NICK)))
	    {
		if (MyConnect(sptr) && (!IsServer(cptr)) && (!IsOper(cptr))
		    && (!IsULine(sptr)))
		{
		    sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name,
			       BadPtr(parv[0]) ? "*" : parv[0], nick,
			       BadPtr(ban->reason) ? "Erroneous Nickname" :
			       ban->reason);
                    if (call_hooks(CHOOK_FORBID, cptr, nick, ban) != FLUSH_BUFFER)
		        sendto_realops_lev(REJ_LEV,
				           "Forbidding restricted nick %s from %s", nick,
				           get_client_name(cptr, FALSE));
		    return 0;
		}
	    }
	}
	
	strcpy(sptr->name, nick);
	sptr->tsinfo = timeofday;
	if (sptr->user)
	{
	    /* USER already received, now we have NICK */
       
	    if (register_user(cptr, sptr, nick, sptr->user->username, NULL)
		== FLUSH_BUFFER)
		return FLUSH_BUFFER;
	}
    }

    /* Finally set new nick name. */
    if (sptr->name[0])
    {
        del_from_client_hash_table(sptr->name, sptr);
        samenick = mycmp(sptr->name, nick) ? 0 : 1;
        if (IsPerson(sptr))
        {
            if (!samenick)
                hash_check_watch(sptr, RPL_LOGOFF);
#ifdef RWHO_PROBABILITY
            probability_change(sptr->name, nick);
#endif
        }
    }
    strcpy(sptr->name, nick);
    add_to_client_hash_table(nick, sptr);
    if (IsPerson(sptr) && !samenick)
	hash_check_watch(sptr, RPL_LOGON);
    return 0;
}
Exemplo n.º 8
0
static int
do_server_estab(aClient *cptr)
{
    aClient *acptr;
    aConnect *aconn;
    aChannel *chptr;
    int i;
    /* "refresh" inpath with host  */
    char *inpath = get_client_name(cptr, HIDEME);

    SetServer(cptr);

    Count.unknown--;
    Count.server++;
    Count.myserver++;

    if(IsZipCapable(cptr) && DoZipThis(cptr))
    {
        sendto_one(cptr, "SVINFO ZIP");
        SetZipOut(cptr);
        cptr->serv->zip_out = zip_create_output_session();
    }

#ifdef MAXBUFFERS
    /* let's try to bump up server sock_opts... -Taner */
    reset_sock_opts(cptr->fd, 1);
#endif

    /* adds to server list */
    add_to_list(&server_list, cptr);

    set_effective_class(cptr);

    /* Check one more time for good measure... is it there? */
    if ((acptr = find_name(cptr->name, NULL)))
    {
        char        nbuf[HOSTLEN * 2 + USERLEN + 5];
        aClient *bcptr;

        /*
         * While negotiating stuff, another copy of this server appeared.
         *
         * 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", cptr->name);
        if (bcptr == cptr)
        {
            sendto_gnotice("from %s: Link %s cancelled, server %s already "
                           "exists (final phase)", me.name,
                           get_client_name(bcptr, HIDEME), cptr->name);
            sendto_serv_butone(bcptr, ":%s GNOTICE :Link %s cancelled, "
                                "server %s already exists (final phase)",
                                me.name, get_client_name(bcptr, HIDEME),
                                cptr->name);
            return exit_client(bcptr, bcptr, &me,
                               "Server Exists (final phase)");
        }
        /* 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 (final phase)", me.name, nbuf, cptr->name,
                       get_client_name(cptr, HIDEME));
        sendto_serv_butone(bcptr, ":%s GNOTICE :Link %s cancelled, server %s "
                           "reintroduced by %s (final phase)", me.name, nbuf,
                           cptr->name, get_client_name(cptr, HIDEME));
        exit_client(bcptr, bcptr, &me, "Server Exists (final phase)");
    }

    /* error, error, error! if a server is U:'d, and it connects to us,
     * we need to figure that out! So, do it here. - lucas
     */

    if (find_aUserver(cptr->name))
    {
        Count.myulined++;
        cptr->flags |= FLAGS_ULINE;

        /* If the server has special u:line flags, let's set them.. */
        cptr->serv->uflags = cptr->serv->aconn->uflags;
    }

    fakelinkserver_update(cptr->name, cptr->info);

    sendto_gnotice("from %s: Link with %s established, states:%s%s%s%s",
                   me.name, inpath, ZipOut(cptr) ? " Output-compressed" : "",
                   RC4EncLink(cptr) ? " encrypted" : "",
                   IsULine(cptr) ? " ULined" : "",
                   DoesTS(cptr) ? " TS" : " Non-TS");

    /*
     * Notify everyone of the fact that this has just linked: the entire
     * network should get two of these, one explaining the link between
     * me->serv and the other between serv->me
     */

    sendto_serv_butone(NULL, ":%s GNOTICE :Link with %s established: %s",
                       me.name, inpath,
                       DoesTS(cptr) ? "TS link" : "Non-TS link!");

    add_to_client_hash_table(cptr->name, cptr);

    /* add it to scache */

    find_or_add(cptr->name);

    /*
     * Old sendto_serv_but_one() call removed because we now need to
     * send different names to different servers (domain name
     * matching) Send new server to other servers.
     */
    for (i = 0; i <= highest_fd; i++)
    {
        if (!(acptr = local[i]) || !IsServer(acptr) || acptr == cptr ||
            IsMe(acptr))
            continue;
        if ((aconn = acptr->serv->aconn) &&
            !match(my_name_for_link(me.name, aconn), cptr->name))
            continue;
        sendto_one(acptr, ":%s SERVER %s 2 :%s", me.name, cptr->name,
                   cptr->info);
    }

    /*
     * Pass on my client information to the new server
     *
     * First, pass only servers (idea is that if the link gets
     * cancelled beacause the server was already there, there are no
     * NICK's to be cancelled...). Of course, if cancellation occurs,
     * all this info is sent anyway, and I guess the link dies when a
     * read is attempted...? --msa
     *
     * Note: Link cancellation to occur at this point means that at
     * least two servers from my fragment are building up connection
     * this other fragment at the same time, it's a race condition,
     * not the normal way of operation...
     *
     * ALSO NOTE: using the get_client_name for server names-- see
     * previous *WARNING*!!! (Also, original inpath is
     * destroyed...)
     */

    aconn = cptr->serv->aconn;
    for (acptr = &me; acptr; acptr = acptr->prev)
    {
        if (acptr->from == cptr)
            continue;
        if (IsServer(acptr))
        {
            if (match(my_name_for_link(me.name, aconn), acptr->name) == 0)
                continue;
            sendto_one(cptr, ":%s SERVER %s %d :%s",
                       acptr->serv->up, acptr->name,
                       acptr->hopcount + 1, acptr->info);
        }
    }

    /* send out our SQLINES and SGLINES too */
    send_simbans(cptr, SBAN_CHAN|SBAN_NETWORK);
    send_simbans(cptr, SBAN_NICK|SBAN_NETWORK);
    send_simbans(cptr, SBAN_GCOS|SBAN_NETWORK);

    /* Send out fake server list and other 'fake' stuff */
    fakeserver_sendserver(cptr);

    /* Send UHM (user host-masking) type */
    if(confopts & FLAGS_HUB)
        sendto_one(cptr, "SVSUHM %d", uhm_type);

    /* send clone list */
    clones_send(cptr);

    /* Bursts are about to start.. send a BURST */
    if (IsBurst(cptr))
        sendto_one(cptr, "BURST");

    /*
     * * Send it in the shortened format with the TS, if it's a TS
     * server; walk the list of channels, sending all the nicks that
     * haven't been sent yet for each channel, then send the channel
     * itself -- it's less obvious than sending all nicks first, but
     * on the receiving side memory will be allocated more nicely
     * saving a few seconds in the handling of a split -orabidoo
     */
    {
        chanMember       *cm;
        static char nickissent = 1;

        nickissent = 3 - nickissent;
        /*
         * flag used for each nick to check if we've sent it yet - must
         * be different each time and !=0, so we alternate between 1 and
         * 2 -orabidoo
         */
        for (chptr = channel; chptr; chptr = chptr->nextch)
        {
            for (cm = chptr->members; cm; cm = cm->next)
            {
                acptr = cm->cptr;
                if (acptr->nicksent != nickissent)
                {
                    acptr->nicksent = nickissent;
                    if (acptr->from != cptr)
                        sendnick_TS(cptr, acptr);
                }
            }
            send_channel_modes(cptr, chptr);
        }
        /* also send out those that are not on any channel */
        for (acptr = &me; acptr; acptr = acptr->prev)
            if (acptr->nicksent != nickissent)
            {
                acptr->nicksent = nickissent;
                if (acptr->from != cptr)
                    sendnick_TS(cptr, acptr);
            }
    }

    if(confopts & FLAGS_HUB)
        fakelusers_sendlock(cptr);

    if(ZipOut(cptr))
    {
        unsigned long inb, outb;
        double rat;

        zip_out_get_stats(cptr->serv->zip_out, &inb, &outb, &rat);

        if(inb)
        {
            sendto_gnotice("from %s: Connect burst to %s: %lu bytes normal, "
                           "%lu compressed (%3.2f%%)", me.name,
                           get_client_name(cptr, HIDEME), inb, outb, rat);
            sendto_serv_butone(cptr, ":%s GNOTICE :Connect burst to %s: %lu "
                               "bytes normal, %lu compressed (%3.2f%%)",
                               me.name, get_client_name(cptr, HIDEME), inb,
                               outb, rat);
        }
    }

    /* stuff a PING at the end of this burst so we can figure out when
       the other side has finished processing it. */
    cptr->flags |= FLAGS_BURST|FLAGS_PINGSENT;
    if (IsBurst(cptr)) cptr->flags |= FLAGS_SOBSENT;
    sendto_one(cptr, "PING :%s", me.name);

    return 0;
}
Exemplo n.º 9
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;
}
Exemplo n.º 10
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);
}
Exemplo n.º 11
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;
}
Exemplo n.º 12
0
/*
 * change_local_nick
 * inputs	- pointer to server
 *		- pointer to client
 * output	- 
 * side effects	- changes nick of a LOCAL user
 *
 */
int change_local_nick(struct Client *client_p, struct Client *source_p,
                      char *nick)
{
  /*
  ** Client just changing his/her nick. If he/she is
  ** on a channel, send note of change to all clients
  ** on that channel. Propagate notice to other servers.
  */

  source_p->tsinfo = CurrentTime;

  if((source_p->localClient->last_nick_change +
       ConfigFileEntry.max_nick_time) < CurrentTime)
    source_p->localClient->number_of_nick_changes = 0;
  source_p->localClient->last_nick_change = CurrentTime;
  source_p->localClient->number_of_nick_changes++;

  if((ConfigFileEntry.anti_nick_flood && 
      (source_p->localClient->number_of_nick_changes
       <= ConfigFileEntry.max_nick_changes)) ||
     !ConfigFileEntry.anti_nick_flood || 
     (IsOper(source_p) && ConfigFileEntry.no_oper_flood))
    {
      sendto_realops_flags(FLAGS_NCHANGE, L_ALL,
			   "Nick change: From %s to %s [%s@%s]",
			   source_p->name, nick, source_p->username,
			   source_p->host);

      sendto_common_channels_local(source_p, ":%s!%s@%s NICK :%s",
				   source_p->name, source_p->username, source_p->host,
				   nick);
      if (source_p->user)
	{
	  add_history(source_p, 1);
	  
	  /* Only hubs care about lazy link nicks not being sent on yet
	   * lazylink leafs/leafs always send their nicks up to hub,
	   * hence must always propogate nick changes.
	   * hubs might not propogate a nick change, if the leaf
	   * does not know about that client yet.
	   */
          sendto_server(client_p, source_p, NULL, NOCAPS, NOCAPS,
                        NOFLAGS, ":%s NICK %s :%lu", source_p->name,
                        nick, (unsigned long) source_p->tsinfo);
	}
    }
  else
    {
      sendto_one(source_p,
                 form_str(ERR_NICKTOOFAST),me.name, source_p->name,
                 source_p->name, nick, ConfigFileEntry.max_nick_time);
      return 0;
    }

  /* Finally, add to hash */
  del_from_client_hash_table(source_p->name, source_p);
  strcpy(source_p->name, nick);
  add_to_client_hash_table(nick, source_p);

  /* Make sure everyone that has this client on its accept list
   * loses that reference. 
   */

  del_all_accepts(source_p);

  /* fd_desc is long enough */
  fd_note(client_p->localClient->fd, "Nick: %s", nick);

  return 1;
}
Exemplo n.º 13
0
/*
 * nick_from_server()
 */
static int
nick_from_server(struct Client *client_p, struct Client *source_p, int parc,
		 char *parv[], time_t newts, char *nick)
{
	if(IsServer(source_p))
	{
		/* A server introducing a new client, change source */
		source_p = make_client(client_p);
		add_client_to_list(source_p);

		if(parc > 2)
			source_p->hopcount = atoi(parv[2]);
		if(newts)
			source_p->tsinfo = newts;
		else
		{
			newts = source_p->tsinfo = CurrentTime;
			ts_warn("Remote nick %s (%s) introduced without a TS", nick, parv[0]);
		}

		/* copy the nick in place */
		(void) strcpy(source_p->name, nick);
		(void) add_to_client_hash_table(nick, source_p);

		if(parc > 8)
		{
			int flag;
			char *m;

			/* parse usermodes */
			m = &parv[4][1];
			while (*m)
			{
				flag = user_modes_from_c_to_bitmask[(unsigned char) *m];
				if(!(source_p->umodes & UMODE_INVISIBLE)
				   && (flag & UMODE_INVISIBLE))
					Count.invisi++;
				if(!(source_p->umodes & UMODE_OPER) && (flag & UMODE_OPER))
					Count.oper++;

				source_p->umodes |= flag & SEND_UMODES;
				m++;
			}

			return do_remote_user(nick, client_p, source_p, parv[5], parv[6],
					      parv[7], (parc > 9)? parv[8] : NULL,
						parv[(parc > 9)? 9 : 8]);
		}
	}
	else if(source_p->name[0])
	{
		/* client changing their nick */
		if(irccmp(parv[0], nick))
			source_p->tsinfo = newts ? newts : CurrentTime;

		sendto_common_channels_local(source_p, ":%s!%s@%s NICK :%s",
					     source_p->name, source_p->username, source_p->host,
					     nick);

		if(source_p->user)
		{
			add_history(source_p, 1);
			sendto_server(client_p, NULL, NOCAPS, NOCAPS,
				      ":%s NICK %s :%lu",
				      parv[0], nick, (unsigned long) source_p->tsinfo);
		}
	}

	/* set the new nick name */
	if(source_p->name[0])
		del_from_client_hash_table(source_p->name, source_p);

	strcpy(source_p->name, nick);
	add_to_client_hash_table(nick, source_p);

	/* remove all accepts pointing to the client */
	del_all_accepts(source_p);

	return 0;
}
Exemplo n.º 14
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);
}
Exemplo n.º 15
0
int m_hash(struct Client *cptr, struct Client *sptr,int parc,char *parv[])
{
  register int l;
  register int i;
  register struct HashEntry* tab;
  struct HashEntry* table;
  struct tm*        tmptr;
  int        deepest = 0;
  int   deeplink = 0;
  int   showlist = 0;
  int   tothits = 0;
  int        mosthit = 0;
  int   mosthits = 0;
  int   used = 0;
  int   used_now = 0;
  int   totlink = 0;
  int   size = U_MAX;
  char        ch;
  int   out = 0;
  int        link_pop[10];
  char  result_buf[256];
  char  hash_log_file[256];
  char  timebuffer[MAX_DATE_STRING];

  if (!MyClient(sptr) || !HasUmode(sptr,UMODE_DEBUG))
    {
      sendto_one(sptr, form_str(ERR_NOPRIVILEGES), me.name, parv[0]);
      return 0;
    }
  if(parc > 1)
    {
      if(!irccmp(parv[1],"iphash"))
        {
          iphash_stats(cptr,sptr,parc,parv,-1);
          return 0;
        }
      else if(!irccmp(parv[1],"Diphash"))
        {
          tmptr = localtime(&CurrentTime);
          strftime(timebuffer, MAX_DATE_STRING, "%Y%m%d%H%M", tmptr);
          sprintf(hash_log_file, "%s.%s",
		  hash_log_file_base, timebuffer);

          if ((out = open(hash_log_file, O_RDWR | O_APPEND | O_CREAT,0664))==-1)
              sendto_one(sptr, ":%s NOTICE %s :Problem opening %s",
                         me.name, parv[0], hash_log_file);
          else
            sendto_one(sptr, ":%s NOTICE %s :Writing hash log to %s",
                       me.name, parv[0], hash_log_file);

          iphash_stats(cptr,sptr,parc,parv,out);
          return 0;
        }

      ch = *parv[1];
      if (IsLower(ch))
        {
          table = clientTable;
          
        }
      else
        {
          table = channelTable;
          size = CH_MAX;
        }
      if (ch == 'L' || ch == 'l')
        {
          tmptr = localtime(&CurrentTime);
          strftime(timebuffer, MAX_DATE_STRING, "%Y%m%d%H%M", tmptr);
          sprintf(hash_log_file, "%s-%cdump.%s",
		  hash_log_file_base, ch, timebuffer);
          showlist = 1;
          if ((out = open(hash_log_file, O_RDWR|O_APPEND|O_CREAT,0664))==-1)
              sendto_one(sptr, ":%s NOTICE %s :Problem opening %s ",
                         me.name, parv[0], hash_log_file);
          else
            sendto_one(sptr, ":%s NOTICE %s :Writing hash log to %s ",
                       me.name, parv[0], hash_log_file);
        }
    }
  else
    {
      ch = '\0';
      table = clientTable;
    }

  for (i = 0; i < 10; i++)
    link_pop[i] = 0;

  for (i = 0; i < size; i++)
    {
      tab = &table[i];
      l = tab->links;
      if (showlist)
        {
        /*
          sendto_one(sptr,
          "NOTICE %s :Hash Entry:%6d Hits:%7d Links:%6d",
          parv[0], i, tab->hits, l); */
          if(out >= 0)
            {
              sprintf(result_buf,"Hash Entry:%6d Hits;%7d Links:%6d\n",
                            i, tab->hits, l);
              write(out,result_buf,strlen(result_buf));
            }
        }

      if (l > 0)
        {
          if (l < 10)
            link_pop[l]++;
          else
            link_pop[9]++;
          used_now++;
          totlink += l;
          if (l > deepest)
            {
              deepest = l;
              deeplink = i;
            }
        }
      else
        link_pop[0]++;
      l = tab->hits;
      if (l)
        {
          used++;
          tothits += l;
          if (l > mosthits)
            {
              mosthits = l;
              mosthit = i;
            }
        }
    }
  if(showlist && (out >= 0))
     (void)close(out);

  switch((int)ch)
    {
    case 'V' : case 'v' :
      {
        register struct Client* acptr;
        int        bad = 0, listlength = 0;
        
        for (acptr = GlobalClientList; acptr; acptr = acptr->next) {
          if (hash_find_client(acptr->name,acptr) != acptr)
            {
              if (ch == 'V')
                sendto_one(sptr, "NOTICE %s :Bad hash for %s",
                           parv[0], acptr->name);
              bad++;
            }
          listlength++;
        }
        sendto_one(sptr,"NOTICE %s :List Length: %d Bad Hashes: %d",
                   parv[0], listlength, bad);
      }
    case 'P' : case 'p' :
      for (i = 0; i < 10; i++)
        sendto_one(sptr,"NOTICE %s :Entires with %d links : %d",
                   parv[0], i, link_pop[i]);
      return (0);
    case 'r' :
      {
        register        struct Client        *acptr;

        sendto_one(sptr,"NOTICE %s :Rehashing Client List.", parv[0]);
        clear_client_hash_table();
        for (acptr = GlobalClientList; acptr; acptr = acptr->next)
          add_to_client_hash_table(acptr->name, acptr);
        break;
      }
    case 'R' :
      {
        register        struct Channel        *acptr;

        sendto_one(sptr,"NOTICE %s :Rehashing Channel List.", parv[0]);
        clear_channel_hash_table();
        for (acptr = channel; acptr; acptr = acptr->nextch)
          (void)add_to_channel_hash_table(acptr->chname, acptr);
        break;
      }
    case 'H' :
      if (parc > 2)
        sendto_one(sptr,"NOTICE %s :%s hash to entry %d",
                   parv[0], parv[2],
                   hash_channel_name(parv[2]));
      return (0);
    case 'h' :
      if (parc > 2)
        sendto_one(sptr,"NOTICE %s :%s hash to entry %d",
                   parv[0], parv[2],
                   hash_nick_name(parv[2]));
      return (0);
    case 'n' :
      {
        struct Client        *tmp;
        int        max;
        
        if (parc <= 2)
          return (0);
        l = atoi(parv[2]) % U_MAX;
        if (parc > 3)
          max = atoi(parv[3]) % U_MAX;
        else
          max = l;
        for (;l <= max; l++)
          for (i = 0, tmp = (struct Client *)clientTable[l].list; tmp;
               i++, tmp = tmp->hnext)
            {
              if (parv[1][2] == '1' && tmp != tmp->from)
                continue;
              sendto_one(sptr,"NOTICE %s :Node: %d #%d %s",
                         parv[0], l, i, tmp->name);
            }
        return (0);
      }
    case 'N' :
      {
        struct Channel *tmp;
        int        max;

        if (parc <= 2)
          return (0);
        l = atoi(parv[2]) % CH_MAX;
        if (parc > 3)
          max = atoi(parv[3]) % CH_MAX;
        else
          max = l;
        for (;l <= max; l++)
          for (i = 0, tmp = (struct Channel*) channelTable[l].list; tmp;
               i++, tmp = tmp->hnextch)
            sendto_one(sptr,"NOTICE %s :Node: %d #%d %s",
                       parv[0], l, i, tmp->chname);
        return (0);
      }
#ifdef DEBUGMODE
    case 'S' :

      sendto_one(sptr,"NOTICE %s :Entries Hashed: %d NonEmpty: %d of %d",
                 parv[0], totlink, used_now, size);
      if (!used_now)
        used_now = 1;
      sendto_one(sptr,"NOTICE %s :Hash Ratio (av. depth): %f %%Full: %f",
                 parv[0], (float)((1.0 * totlink) / (1.0 * used_now)),
                 (float)((1.0 * used_now) / (1.0 * size)));
      sendto_one(sptr,"NOTICE %s :Deepest Link: %d Links: %d",
                 parv[0], deeplink, deepest);
      if (!used)
        used = 1;
      sendto_one(sptr,"NOTICE %s :Total Hits: %d Unhit: %d Av Hits: %f",
                 parv[0], tothits, size-used,
                 (float)((1.0 * tothits) / (1.0 * used)));
      sendto_one(sptr,"NOTICE %s :Entry Most Hit: %d Hits: %d",
                 parv[0], mosthit, mosthits);
      sendto_one(sptr,"NOTICE %s :Client hits %d miss %d",
                 parv[0], clhits, clmiss);
      sendto_one(sptr,"NOTICE %s :Channel hits %d miss %d",
                 parv[0], chhits, chmiss);
      return 0;
#endif
    }
  return 0;
}