⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 m_server.c

📁 Unreal irc 服务器源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *   IRC - Internet Relay Chat, src/modules/out.c *   (C) 2004 The UnrealIRCd Team * *   See file AUTHORS in IRC package for additional names of *   the programmers. * *   This program is free software; you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 1, or (at your option) *   any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY; without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *   GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program; if not, write to the Free Software *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "config.h"#include "struct.h"#include "common.h"#include "sys.h"#include "numeric.h"#include "msg.h"#include "proto.h"#include "channel.h"#include <time.h>#include <sys/stat.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#ifdef _WIN32#include <io.h>#endif#include <fcntl.h>#include "h.h"#ifdef STRIPBADWORDS#include "badwords.h"#endif#include "version.h"void send_channel_modes(aClient *cptr, aChannel *chptr);void send_channel_modes_sjoin(aClient *cptr, aChannel *chptr);void send_channel_modes_sjoin3(aClient *cptr, aChannel *chptr);DLLFUNC int m_server(aClient *cptr, aClient *sptr, int parc, char *parv[]);static char buf[BUFSIZE];#define MSG_SERVER 	"SERVER"	#define TOK_SERVER 	"'"	ModuleHeader MOD_HEADER(m_server)  = {	"m_server",	"$Id: m_server.c,v 1.1.6.8 2006/12/22 21:10:33 syzop Exp $",	"command /server", 	"3.2-b8-1",	NULL     };DLLFUNC int MOD_INIT(m_server)(ModuleInfo *modinfo){	add_CommandX(MSG_SERVER, TOK_SERVER, m_server, MAXPARA, M_UNREGISTERED|M_SERVER);	MARK_AS_OFFICIAL_MODULE(modinfo);	return MOD_SUCCESS;}DLLFUNC int MOD_LOAD(m_server)(int module_load){	return MOD_SUCCESS;}DLLFUNC int MOD_UNLOAD(m_server)(int module_unload){	if (del_Command(MSG_SERVER, TOK_SERVER, m_server) < 0)	{		sendto_realops("Failed to delete commands when unloading %s",			MOD_HEADER(m_server).name);	}	return MOD_SUCCESS;}int m_server_synch(aClient *cptr, long numeric, ConfigItem_link *conf);/*** m_server**	parv[0] = sender prefix**	parv[1] = servername**      parv[2] = hopcount**      parv[3] = numeric**      parv[4] = serverinfo**** on old protocols, serverinfo is parv[3], and numeric is left out****  Recode 2001 by Stskeeps*/DLLFUNC CMD_FUNC(m_server){	char *servername = NULL;	/* Pointer for servername */ /*	char *password = NULL; */	char *ch = NULL;	/* */	char *inpath = get_client_name(cptr, TRUE);	aClient *acptr = NULL, *ocptr = NULL;	ConfigItem_ban *bconf;	int  hop = 0, numeric = 0;	char info[REALLEN + 61];	ConfigItem_link *aconf = NULL;	ConfigItem_deny_link *deny;	char *flags = NULL, *protocol = NULL, *inf = NULL, *num = NULL;	/* Ignore it  */	if (IsPerson(sptr))	{		sendto_one(cptr, err_str(ERR_ALREADYREGISTRED),		    me.name, parv[0]);		sendto_one(cptr,		    ":%s %s %s :*** Sorry, but your IRC program doesn't appear to support changing servers.",		    me.name, IsWebTV(cptr) ? "PRIVMSG" : "NOTICE", cptr->name);		sptr->since += 7;		return 0;	}	/*	 *  We do some parameter checks now. We want atleast upto serverinfo now	 */	if (parc < 4 || (!*parv[3]))	{		sendto_one(sptr, "ERROR :Not enough SERVER parameters");		return exit_client(cptr, sptr, &me, 			"Not enough parameters");			}	if (IsUnknown(cptr) && (cptr->listener->umodes & LISTENER_CLIENTSONLY))	{		return exit_client(cptr, sptr, &me,		    "This port is for clients only");	}	/* Now, let us take a look at the parameters we got	 * Passes here:	 *    Check for bogus server name	 */	servername = parv[1];	/* Cut off if too big */	if (strlen(servername) > HOSTLEN)		servername[HOSTLEN] = '\0';	/* Check if bogus, like spaces and ~'s */	for (ch = servername; *ch; ch++)		if (*ch <= ' ' || *ch > '~')			break;	if (*ch || !index(servername, '.'))	{		sendto_one(sptr, "ERROR :Bogus server name (%s)", servername);		sendto_snomask		    (SNO_JUNK,		    "WARNING: Bogus server name (%s) from %s (maybe just a fishy client)",		    servername, get_client_name(cptr, TRUE));		return exit_client(cptr, sptr, &me, "Bogus server name");	}	if ((IsUnknown(cptr) || IsHandshake(cptr)) && !cptr->passwd)	{		sendto_one(sptr, "ERROR :Missing password");		return exit_client(cptr, sptr, &me, "Missing password");	}	/*	 * Now, we can take a look at it all	 */	if (IsUnknown(cptr) || IsHandshake(cptr))	{		char xerrmsg[256];		ConfigItem_link *link;				strcpy(xerrmsg, "No matching link configuration");		/* First check if the server is in the list */		if (!servername) {			strcpy(xerrmsg, "Null servername");			goto errlink;		}		if (cptr->serv && cptr->serv->conf)		{			/* We already know what block we are dealing with (outgoing connect!) */			link = cptr->serv->conf;		} else {			/* Hunt the linkblock down ;) */			for(link = conf_link; link; link = (ConfigItem_link *) link->next)				if (!match(link->servername, servername))					break;		}		if (!link) {			snprintf(xerrmsg, 256, "No link block named '%s'", servername);			goto errlink;		}		if (link->username && match(link->username, cptr->username)) {			snprintf(xerrmsg, 256, "Username '%s' didn't match '%s'",				cptr->username, link->username);			/* I assume nobody will have 2 link blocks with the same servername			 * and different username. -- Syzop			 */			goto errlink;		}		/* For now, we don't check based on DNS, it is slow, and IPs are better.		 * We also skip checking if link::options::nohostcheck is set.		 */		if (link->options & CONNECT_NOHOSTCHECK)		{			aconf = link;			goto nohostcheck;		}		aconf = Find_link(cptr->username, cptr->sockhost, cptr->sockhost,		    servername);		#ifdef INET6		/*  		 * We first try match on uncompressed form ::ffff:192.168.1.5 thing included		*/		if (!aconf)			aconf = Find_link(cptr->username, cptr->sockhost, Inet_ia2pNB(&cptr->ip, 0), servername);		/* 		 * Then on compressed 		*/		if (!aconf)			aconf = Find_link(cptr->username, cptr->sockhost, Inet_ia2pNB(&cptr->ip, 1), servername);#endif				if (!aconf)		{			snprintf(xerrmsg, 256, "Server is in link block but IP/host didn't match");errlink:			/* Send the "simple" error msg to the server */			sendto_one(cptr,			    "ERROR :Link denied (No matching link configuration) %s",			    inpath);			/* And send the "verbose" error msg only to local failops */			sendto_locfailops			    ("Link denied for %s(%s@%s) (%s) %s",			    servername, cptr->username, cptr->sockhost, xerrmsg, inpath);			return exit_client(cptr, sptr, &me,			    "Link denied (No matching link configuration)");		}nohostcheck:		/* Now for checking passwords */		if (Auth_Check(cptr, aconf->recvauth, cptr->passwd) == -1)		{			sendto_one(cptr,			    "ERROR :Link denied (Authentication failed) %s",			    inpath);			sendto_locfailops			    ("Link denied (Authentication failed [Bad password?]) %s", inpath);			return exit_client(cptr, sptr, &me,			    "Link denied (Authentication failed)");		}		/*		 * Third phase, we check that the server does not exist		 * already		 */		if ((acptr = find_server(servername, NULL)))		{			/* Found. Bad. Quit. */			acptr = acptr->from;			ocptr =			    (cptr->firsttime > acptr->firsttime) ? acptr : cptr;			acptr =			    (cptr->firsttime > acptr->firsttime) ? cptr : acptr;			sendto_one(acptr,			    "ERROR :Server %s already exists from %s",			    servername,			    (ocptr->from ? ocptr->from->name : "<nobody>"));			sendto_realops			    ("Link %s cancelled, server %s already exists from %s",			    get_client_name(acptr, TRUE), servername,			    (ocptr->from ? ocptr->from->name : "<nobody>"));			return exit_client(acptr, acptr, acptr,			    "Server Exists");		}		if ((bconf = Find_ban(NULL, servername, CONF_BAN_SERVER)))		{			sendto_realops				("Cancelling link %s, banned server",				get_client_name(cptr, TRUE));			sendto_one(cptr, "ERROR :Banned server (%s)", bconf->reason ? bconf->reason : "no reason");			return exit_client(cptr, cptr, &me, "Banned server");		}		if (aconf->class->clients + 1 > aconf->class->maxclients)		{			sendto_realops				("Cancelling link %s, full class",					get_client_name(cptr, TRUE));			return exit_client(cptr, cptr, &me, "Full class");		}		/* OK, let us check in the data now now */		hop = TS2ts(parv[2]);		numeric = (parc > 4) ? TS2ts(parv[3]) : 0;		if ((numeric < 0) || (numeric > 255))		{			sendto_realops				("Cancelling link %s, invalid numeric",					get_client_name(cptr, TRUE));			return exit_client(cptr, cptr, &me, "Invalid numeric");		}		strncpyzt(info, parv[parc - 1], REALLEN + 61);		strncpyzt(cptr->name, servername, sizeof(cptr->name));		cptr->hopcount = hop;		/* Add ban server stuff */		if (SupportVL(cptr))		{			/* we also have a fail safe incase they say they are sending			 * VL stuff and don't -- codemastr			 */			ConfigItem_deny_version *vlines;			inf = NULL;			protocol = NULL;			flags = NULL;			num = NULL;			protocol = (char *)strtok((char *)info, "-");			if (protocol)				flags = (char *)strtok((char *)NULL, "-");			if (flags)				num = (char *)strtok((char *)NULL, " ");			if (num)				inf = (char *)strtok((char *)NULL, "");			if (inf) {				strncpyzt(cptr->info, inf[0] ? inf : me.name,				    sizeof(cptr->info));				for (vlines = conf_deny_version; vlines; vlines = (ConfigItem_deny_version *) vlines->next) {					if (!match(vlines->mask, cptr->name))						break;				}				if (vlines) {					char *proto = vlines->version;					char *vflags = vlines->flags;					int version, result = 0, i;					protocol++;					version = atoi(protocol);					switch (*proto) {						case '<':							proto++;							if (version < atoi(proto))								result = 1;							break;						case '>':							proto++;							if (version > atoi(proto))								result = 1;							break;						case '=':							proto++;							if (version == atoi(proto))								result = 1;							break;						case '!':							proto++;							if (version != atoi(proto))								result = 1;							break;						default:							if (version == atoi(proto))								result = 1;							break;					}					if (version == 0 || *proto == '*')						result = 0;					if (result)						return exit_client(cptr, cptr, cptr,							"Denied by V:line");					for (i = 0; vflags[i]; i++) {						if (vflags[i] == '!') {							i++;							if (strchr(flags, vflags[i])) {								result = 1;								break;							}						}						else if (!strchr(flags, vflags[i])) {								result = 1;								break;						}					}					if (*vflags == '*' || !strcmp(flags, "0"))						result = 0;					if (result)						return exit_client(cptr, cptr, cptr,							"Denied by V:line");				}			}			else				strncpyzt(cptr->info, info[0] ? info : me.name,				    sizeof(cptr->info));		}		else				strncpyzt(cptr->info, info[0] ? info : me.name,					sizeof(cptr->info));		/* Numerics .. */		numeric = num ? atol(num) : numeric;		if (numeric)		{			if ((numeric < 0) || (numeric > 254))			{				sendto_locfailops("Link %s denied, numeric '%d' out of range (should be 0-254)",					inpath, numeric);				return exit_client(cptr, cptr, cptr,				    "Numeric out of range (0-254)");			}			if (numeric_collides(numeric))			{				sendto_locfailops("Link %s denied, colliding server numeric",					inpath);				return exit_client(cptr, cptr, cptr,				    "Colliding server numeric (choose another)");			}		}		for (deny = conf_deny_link; deny; deny = (ConfigItem_deny_link *) deny->next) {			if (deny->flag.type == CRULE_ALL && !match(deny->mask, servername)				&& crule_eval(deny->rule)) {				sendto_ops("Refused connection from %s.",					get_client_host(cptr));				return exit_client(cptr, cptr, cptr,					"Disallowed by connection rule");			}		}		if (aconf->options & CONNECT_QUARANTINE)			cptr->flags |= FLAGS_QUARANTINE;		/* Start synch now */		if (m_server_synch(cptr, numeric, aconf) == FLUSH_BUFFER)			return FLUSH_BUFFER;	}	else	{		return m_server_remote(cptr, sptr, parc, parv);	}	return 0;}CMD_FUNC(m_server_remote){	aClient *acptr, *ocptr, *bcptr;	ConfigItem_link	*aconf;	ConfigItem_ban *bconf;	int 	hop;	char	info[REALLEN + 61];	long	numeric = 0;	char	*servername = parv[1];	int	i;	if ((acptr = find_server(servername, NULL)))	{		/* Found. Bad. Quit. */		acptr = acptr->from;		ocptr =		    (cptr->firsttime > acptr->firsttime) ? acptr : cptr;		acptr =		    (cptr->firsttime > acptr->firsttime) ? cptr : acptr;		sendto_one(acptr,		    "ERROR :Server %s already exists from %s",		    servername,		    (ocptr->from ? ocptr->from->name : "<nobody>"));		sendto_realops		    ("Link %s cancelled, server %s already exists from %s",		    get_client_name(acptr, TRUE), servername,		    (ocptr->from ? ocptr->from->name : "<nobody>"));		if (acptr == cptr) {			return exit_client(acptr, acptr, acptr, "Server Exists");		} else {			/* AFAIK this can cause crashes if this happends remotely because			 * we will still receive msgs for some time because of lag.			 * Two possible solutions: unlink the directly connected server (cptr)			 * and/or fix all those commands which blindly trust server input. -- Syzop			 */			exit_client(acptr, acptr, acptr, "Server Exists");			return 0;		}	}	if ((bconf = Find_ban(NULL, servername, CONF_BAN_SERVER)))	{		sendto_realops			("Cancelling link %s, banned server %s",			get_client_name(cptr, TRUE), servername);		sendto_one(cptr, "ERROR :Banned server (%s)", bconf->reason ? bconf->reason : "no reason");		return exit_client(cptr, cptr, &me, "Brought in banned server");	}	/* OK, let us check in the data now now */	hop = TS2ts(parv[2]);	numeric = (parc > 4) ? TS2ts(parv[3]) : 0;	if ((numeric < 0) || (numeric > 255))	{		sendto_realops			("Cancelling link %s, invalid numeric at server %s",				get_client_name(cptr, TRUE), servername);		sendto_one(cptr, "ERROR :Invalid numeric (%s)",			servername);		return exit_client(cptr, cptr, &me, "Invalid remote numeric");	}	strncpyzt(info, parv[parc - 1], REALLEN + 61);	if (!cptr->serv->conf)	{		sendto_realops("Lost conf for %s!!, dropping link", cptr->name);		return exit_client(cptr, cptr, cptr, "Lost configuration");	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -