#include "message.h"
#include "mode.h"
#include "commands.h"
+#include "xline.h"
#ifdef GCC3
#define nspace __gnu_cxx
void readfile(file_cache &F, const char* fname)
{
- FILE* file;
- char linebuf[MAXBUF];
-
- log(DEBUG,"readfile: loading %s",fname);
- F.clear();
- file = fopen(fname,"r");
- if (file)
- {
- while (!feof(file))
- {
- fgets(linebuf,sizeof(linebuf),file);
- linebuf[strlen(linebuf)-1]='\0';
- if (!strcmp(linebuf,""))
- {
- strcpy(linebuf," ");
- }
- if (!feof(file))
- {
- F.push_back(linebuf);
- }
- }
- fclose(file);
- }
- else
- {
- log(DEBUG,"readfile: failed to load file: %s",fname);
- }
- log(DEBUG,"readfile: loaded %s, %d lines",fname,F.size());
+ FILE* file;
+ char linebuf[MAXBUF];
+
+ log(DEBUG,"readfile: loading %s",fname);
+ F.clear();
+ file = fopen(fname,"r");
+ if (file)
+ {
+ while (!feof(file))
+ {
+ fgets(linebuf,sizeof(linebuf),file);
+ linebuf[strlen(linebuf)-1]='\0';
+ if (!strcmp(linebuf,""))
+ {
+ strcpy(linebuf," ");
+ }
+ if (!feof(file))
+ {
+ F.push_back(linebuf);
+ }
+ }
+ fclose(file);
+ }
+ else
+ {
+ log(DEBUG,"readfile: failed to load file: %s",fname);
+ }
+ log(DEBUG,"readfile: loaded %s, %d lines",fname,F.size());
}
void ReadConfig(void)
{
- char dbg[MAXBUF],pauseval[MAXBUF],Value[MAXBUF],timeout[MAXBUF],NB[MAXBUF],flood[MAXBUF];
- ConnectClass c;
-
- LoadConf(CONFIG_FILE,&config_f);
-
- ConfValue("server","name",0,ServerName,&config_f);
- ConfValue("server","description",0,ServerDesc,&config_f);
- ConfValue("server","network",0,Network,&config_f);
- ConfValue("admin","name",0,AdminName,&config_f);
- ConfValue("admin","email",0,AdminEmail,&config_f);
- ConfValue("admin","nick",0,AdminNick,&config_f);
- ConfValue("files","motd",0,motd,&config_f);
- ConfValue("files","rules",0,rules,&config_f);
- ConfValue("power","diepass",0,diepass,&config_f);
- ConfValue("power","pause",0,pauseval,&config_f);
- ConfValue("power","restartpass",0,restartpass,&config_f);
- ConfValue("options","prefixquit",0,PrefixQuit,&config_f);
- ConfValue("die","value",0,DieValue,&config_f);
- ConfValue("options","loglevel",0,dbg,&config_f);
- ConfValue("options","netbuffersize",0,NB,&config_f);
- NetBufferSize = atoi(NB);
- if ((!NetBufferSize) || (NetBufferSize > 65535) || (NetBufferSize < 1024))
- {
- log(DEFAULT,"No NetBufferSize specified or size out of range, setting to default of 10240.");
- NetBufferSize = 10240;
- }
- if (!strcmp(dbg,"debug"))
- LogLevel = DEBUG;
- if (!strcmp(dbg,"verbose"))
- LogLevel = VERBOSE;
- if (!strcmp(dbg,"default"))
- LogLevel = DEFAULT;
- if (!strcmp(dbg,"sparse"))
- LogLevel = SPARSE;
- if (!strcmp(dbg,"none"))
- LogLevel = NONE;
- readfile(MOTD,motd);
- log(DEBUG,"Reading message of the day");
- readfile(RULES,rules);
- log(DEBUG,"Reading connect classes");
- Classes.clear();
- for (int i = 0; i < ConfValueEnum("connect",&config_f); i++)
- {
- strcpy(Value,"");
- ConfValue("connect","allow",i,Value,&config_f);
- ConfValue("connect","timeout",i,timeout,&config_f);
- ConfValue("connect","flood",i,flood,&config_f);
- if (strcmp(Value,""))
- {
- strcpy(c.host,Value);
- c.type = CC_ALLOW;
+ char dbg[MAXBUF],pauseval[MAXBUF],Value[MAXBUF],timeout[MAXBUF],NB[MAXBUF],flood[MAXBUF];
+ ConnectClass c;
+
+ LoadConf(CONFIG_FILE,&config_f);
+
+ ConfValue("server","name",0,ServerName,&config_f);
+ ConfValue("server","description",0,ServerDesc,&config_f);
+ ConfValue("server","network",0,Network,&config_f);
+ ConfValue("admin","name",0,AdminName,&config_f);
+ ConfValue("admin","email",0,AdminEmail,&config_f);
+ ConfValue("admin","nick",0,AdminNick,&config_f);
+ ConfValue("files","motd",0,motd,&config_f);
+ ConfValue("files","rules",0,rules,&config_f);
+ ConfValue("power","diepass",0,diepass,&config_f);
+ ConfValue("power","pause",0,pauseval,&config_f);
+ ConfValue("power","restartpass",0,restartpass,&config_f);
+ ConfValue("options","prefixquit",0,PrefixQuit,&config_f);
+ ConfValue("die","value",0,DieValue,&config_f);
+ ConfValue("options","loglevel",0,dbg,&config_f);
+ ConfValue("options","netbuffersize",0,NB,&config_f);
+ NetBufferSize = atoi(NB);
+ if ((!NetBufferSize) || (NetBufferSize > 65535) || (NetBufferSize < 1024))
+ {
+ log(DEFAULT,"No NetBufferSize specified or size out of range, setting to default of 10240.");
+ NetBufferSize = 10240;
+ }
+ if (!strcmp(dbg,"debug"))
+ LogLevel = DEBUG;
+ if (!strcmp(dbg,"verbose"))
+ LogLevel = VERBOSE;
+ if (!strcmp(dbg,"default"))
+ LogLevel = DEFAULT;
+ if (!strcmp(dbg,"sparse"))
+ LogLevel = SPARSE;
+ if (!strcmp(dbg,"none"))
+ LogLevel = NONE;
+ readfile(MOTD,motd);
+ log(DEFAULT,"Reading message of the day...");
+ readfile(RULES,rules);
+ log(DEFAULT,"Reading connect classes...");
+ Classes.clear();
+ for (int i = 0; i < ConfValueEnum("connect",&config_f); i++)
+ {
strcpy(Value,"");
- ConfValue("connect","password",i,Value,&config_f);
- strcpy(c.pass,Value);
- c.registration_timeout = 90; // default is 2 minutes
- c.flood = atoi(flood);
- if (atoi(timeout)>0)
+ ConfValue("connect","allow",i,Value,&config_f);
+ ConfValue("connect","timeout",i,timeout,&config_f);
+ ConfValue("connect","flood",i,flood,&config_f);
+ if (strcmp(Value,""))
+ {
+ strcpy(c.host,Value);
+ c.type = CC_ALLOW;
+ strcpy(Value,"");
+ ConfValue("connect","password",i,Value,&config_f);
+ strcpy(c.pass,Value);
+ c.registration_timeout = 90; // default is 2 minutes
+ c.flood = atoi(flood);
+ if (atoi(timeout)>0)
+ {
+ c.registration_timeout = atoi(timeout);
+ }
+ Classes.push_back(c);
+ log(DEBUG,"Read connect class type ALLOW, host=%s password=%s timeout=%d flood=%d",c.host,c.pass,c.registration_timeout,c.flood);
+ }
+ else
{
- c.registration_timeout = atoi(timeout);
+ ConfValue("connect","deny",i,Value,&config_f);
+ strcpy(c.host,Value);
+ c.type = CC_DENY;
+ Classes.push_back(c);
+ log(DEBUG,"Read connect class type DENY, host=%s",c.host);
}
- Classes.push_back(c);
- log(DEBUG,"Read connect class type ALLOW, host=%s password=%s timeout=%d flood=%d",c.host,c.pass,c.registration_timeout,c.flood);
- }
- else
- {
- ConfValue("connect","deny",i,Value,&config_f);
- strcpy(c.host,Value);
- c.type = CC_DENY;
- Classes.push_back(c);
- log(DEBUG,"Read connect class type DENY, host=%s",c.host);
- }
- }
+ }
+ log(DEFAULT,"Reading K lines,Q lines and Z lines from config...");
+ read_xline_defaults();
+ log(DEFAULT,"Applying K lines, Q lines and Z lines...");
+ apply_lines();
+ log(DEFAULT,"Done reading configuration file, InspIRCd is now running.");
}
/* write formatted text to a socket, in same format as printf */
void Write(int sock,char *text, ...)
{
- if (!text)
- {
- log(DEFAULT,"*** BUG *** Write was given an invalid parameter");
- return;
- }
- char textbuffer[MAXBUF];
- va_list argsPtr;
- char tb[MAXBUF];
-
- va_start (argsPtr, text);
- vsnprintf(textbuffer, MAXBUF, text, argsPtr);
- va_end(argsPtr);
- sprintf(tb,"%s\r\n",textbuffer);
- chop(tb);
- if (sock != -1)
- {
- write(sock,tb,strlen(tb));
- update_stats_l(sock,strlen(tb)); /* add one line-out to stats L for this fd */
- }
+ if (!text)
+ {
+ log(DEFAULT,"*** BUG *** Write was given an invalid parameter");
+ return;
+ }
+ char textbuffer[MAXBUF];
+ va_list argsPtr;
+ char tb[MAXBUF];
+
+ va_start (argsPtr, text);
+ vsnprintf(textbuffer, MAXBUF, text, argsPtr);
+ va_end(argsPtr);
+ sprintf(tb,"%s\r\n",textbuffer);
+ chop(tb);
+ if (sock != -1)
+ {
+ write(sock,tb,strlen(tb));
+ update_stats_l(sock,strlen(tb)); /* add one line-out to stats L for this fd */
+ }
}
/* write a server formatted numeric response to a single socket */
void WriteServ(int sock, char* text, ...)
{
- if (!text)
- {
- log(DEFAULT,"*** BUG *** WriteServ was given an invalid parameter");
- return;
- }
- char textbuffer[MAXBUF],tb[MAXBUF];
- va_list argsPtr;
- va_start (argsPtr, text);
-
- vsnprintf(textbuffer, MAXBUF, text, argsPtr);
- va_end(argsPtr);
- sprintf(tb,":%s %s\r\n",ServerName,textbuffer);
- chop(tb);
- if (sock != -1)
- {
- write(sock,tb,strlen(tb));
- update_stats_l(sock,strlen(tb)); /* add one line-out to stats L for this fd */
- }
+ if (!text)
+ {
+ log(DEFAULT,"*** BUG *** WriteServ was given an invalid parameter");
+ return;
+ }
+ char textbuffer[MAXBUF],tb[MAXBUF];
+ va_list argsPtr;
+ va_start (argsPtr, text);
+
+ vsnprintf(textbuffer, MAXBUF, text, argsPtr);
+ va_end(argsPtr);
+ sprintf(tb,":%s %s\r\n",ServerName,textbuffer);
+ chop(tb);
+ if (sock != -1)
+ {
+ write(sock,tb,strlen(tb));
+ update_stats_l(sock,strlen(tb)); /* add one line-out to stats L for this fd */
+ }
}
/* write text from an originating user to originating user */
void WriteFrom(int sock, userrec *user,char* text, ...)
{
- if ((!text) || (!user))
- {
- log(DEFAULT,"*** BUG *** WriteFrom was given an invalid parameter");
- return;
- }
- char textbuffer[MAXBUF],tb[MAXBUF];
- va_list argsPtr;
- va_start (argsPtr, text);
-
- vsnprintf(textbuffer, MAXBUF, text, argsPtr);
- va_end(argsPtr);
- sprintf(tb,":%s!%s@%s %s\r\n",user->nick,user->ident,user->dhost,textbuffer);
- chop(tb);
- if (sock != -1)
- {
- write(sock,tb,strlen(tb));
- update_stats_l(sock,strlen(tb)); /* add one line-out to stats L for this fd */
- }
+ if ((!text) || (!user))
+ {
+ log(DEFAULT,"*** BUG *** WriteFrom was given an invalid parameter");
+ return;
+ }
+ char textbuffer[MAXBUF],tb[MAXBUF];
+ va_list argsPtr;
+ va_start (argsPtr, text);
+
+ vsnprintf(textbuffer, MAXBUF, text, argsPtr);
+ va_end(argsPtr);
+ sprintf(tb,":%s!%s@%s %s\r\n",user->nick,user->ident,user->dhost,textbuffer);
+ chop(tb);
+ if (sock != -1)
+ {
+ write(sock,tb,strlen(tb));
+ update_stats_l(sock,strlen(tb)); /* add one line-out to stats L for this fd */
+ }
}
/* write text to an destination user from a source user (e.g. user privmsg) */
{
// use the stamdard J token with no privilages.
char buffer[MAXBUF];
- snprintf(buffer,MAXBUF,"J %s :%s",user->nick,Ptr->name);
+ snprintf(buffer,MAXBUF,"J %s %s",user->nick,Ptr->name);
NetSendToAll(buffer);
}
WriteServ(src->fd,"441 %s %s %s :They are not on that channel",src->nick, user->nick, Ptr->name);
return;
}
- if ((cstatus(src,Ptr) < STATUS_HOP) || (cstatus(src,Ptr) < cstatus(user,Ptr)))
+ if (((cstatus(src,Ptr) < STATUS_HOP) || (cstatus(src,Ptr) < cstatus(user,Ptr))) && (!is_uline(src->server)))
{
if (cstatus(src,Ptr) == STATUS_HOP)
{
}
}
+void kill_link_silent(userrec *user,const char* r)
+{
+ user_hash::iterator iter = clientlist.find(user->nick);
+
+ char reason[MAXBUF];
+
+ strncpy(reason,r,MAXBUF);
+
+ if (strlen(reason)>MAXQUIT)
+ {
+ reason[MAXQUIT-1] = '\0';
+ }
+
+ log(DEBUG,"kill_link: %s '%s'",user->nick,reason);
+ Write(user->fd,"ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,reason);
+ log(DEBUG,"closing fd %d",user->fd);
+
+ /* bugfix, cant close() a nonblocking socket (sux!) */
+ if (user->registered == 7) {
+ FOREACH_MOD OnUserQuit(user);
+ WriteCommonExcept(user,"QUIT :%s",reason);
+
+ // Q token must go to ALL servers!!!
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF,"Q %s :%s",user->nick,reason);
+ NetSendToAll(buffer);
+ }
+
+ /* push the socket on a stack of sockets due to be closed at the next opportunity
+ * 'Client exited' is an exception to this as it means the client side has already
+ * closed the socket, we don't need to do it.
+ */
+ fd_reap.push_back(user->fd);
+
+ bool do_purge = false;
+
+ if (iter != clientlist.end())
+ {
+ log(DEBUG,"deleting user hash value %d",iter->second);
+ if ((iter->second) && (user->registered == 7)) {
+ delete iter->second;
+ }
+ clientlist.erase(iter);
+ }
+
+ if (user->registered == 7) {
+ purge_empty_chans();
+ }
+}
+
// looks up a users password for their connection class (<ALLOW>/<DENY> tags)
/* add a client connection to the sockets list */
-void AddClient(int socket, char* host, int port, bool iscached)
+void AddClient(int socket, char* host, int port, bool iscached, char* ip)
{
int i;
int blocking = 1;
clientlist[tempnick]->nping = time(NULL)+240;
clientlist[tempnick]->lastping = 1;
clientlist[tempnick]->port = port;
+ strncpy(clientlist[tempnick]->ip,ip,32);
if (iscached)
{
if (clientlist.size() == MAXCLIENTS)
kill_link(clientlist[tempnick],"No more connections allowed in this class");
+
+ char* r = matches_zline(ip);
+ if (r)
+ {
+ char reason[MAXBUF];
+ snprintf(reason,MAXBUF,"Z-Lined: %s",r);
+ kill_link(clientlist[tempnick],reason);
+ }
}
return;
}
+ char match_against[MAXBUF];
+ snprintf(match_against,MAXBUF,"%s@%s",user->ident,user->host);
+ char* r = matches_gline(match_against);
+ if (r)
+ {
+ char reason[MAXBUF];
+ snprintf(reason,MAXBUF,"G-Lined: %s",r);
+ kill_link_silent(user,reason);
+ return;
+ }
+
+ r = matches_kline(user->host);
+ if (r)
+ {
+ char reason[MAXBUF];
+ snprintf(reason,MAXBUF,"K-Lined: %s",r);
+ kill_link_silent(user,reason);
+ return;
+ }
+
WriteServ(user->fd,"NOTICE Auth :Welcome to \002%s\002!",Network);
WriteServ(user->fd,"001 %s :Welcome to the %s IRC Network %s!%s@%s",user->nick,Network,user->nick,user->ident,user->host);
WriteServ(user->fd,"002 %s :Your host is %s, running version %s",user->nick,ServerName,VERSION);
WriteServ(user->fd,"003 %s :This server was created %s %s",user->nick,__TIME__,__DATE__);
- WriteServ(user->fd,"004 %s :%s %s iowghraAsORVSxNCWqBzvdHtGI lvhopsmntikrRcaqOALQbSeKVfHGCuzN",user->nick,ServerName,VERSION);
- WriteServ(user->fd,"005 %s :MAP KNOCK SAFELIST HCN MAXCHANNELS=20 MAXBANS=60 NICKLEN=30 TOPICLEN=307 KICKLEN=307 MAXTARGETS=20 AWAYLEN=307 :are supported by this server",user->nick);
- WriteServ(user->fd,"005 %s :WALLCHOPS WATCH=128 SILENCE=5 MODES=13 CHANTYPES=# PREFIX=(ohv)@%c+ CHANMODES=ohvbeqa,kfL,l,psmntirRcOAQKVHGCuzN NETWORK=%s :are supported by this server",user->nick,'%',Network);
+ WriteServ(user->fd,"004 %s %s %s iowghraAsORVSxNCWqBzvdHtGI lvhopsmntikrRcaqOALQbSeKVfHGCuzN",user->nick,ServerName,VERSION);
+ WriteServ(user->fd,"005 %s MAP KNOCK SAFELIST HCN MAXCHANNELS=20 MAXBANS=60 NICKLEN=30 TOPICLEN=307 KICKLEN=307 MAXTARGETS=20 AWAYLEN=307 :are supported by this server",user->nick);
+ WriteServ(user->fd,"005 %s WALLCHOPS WATCH=128 SILENCE=5 MODES=13 CHANTYPES=# PREFIX=(ohv)@%c+ CHANMODES=ohvbeqa,kfL,l,psmntirRcOAQKVHGCuzN NETWORK=%s :are supported by this server",user->nick,'%',Network);
ShowMOTD(user);
FOREACH_MOD OnUserConnect(user);
WriteOpers("*** Client connecting on port %d: %s!%s@%s",user->port,user->nick,user->ident,user->host);
void force_nickchange(userrec* user,const char* newnick)
{
char nick[MAXBUF];
+ int MOD_RESULT = 0;
+
strcpy(nick,"");
+
+ FOREACH_RESULT(OnUserPreNick(user,newnick));
+ if (MOD_RESULT) {
+ kill_link(user,"Nickname collision");
+ return;
+ }
+ if (matches_qline(newnick))
+ {
+ kill_link(user,"Nickname collision");
+ return;
+ }
if (user)
{
createcommand("MODULES",handle_modules,'o',0);
createcommand("LINKS",handle_links,0,0);
createcommand("MAP",handle_map,0,0);
+ createcommand("KLINE",handle_kline,'o',1);
+ createcommand("GLINE",handle_gline,'o',1);
+ createcommand("ZLINE",handle_zline,'o',1);
+ createcommand("QLINE",handle_qline,'o',1);
}
void process_buffer(const char* cmdbuf,userrec *user)
void DoSync(serverrec* serv, char* tcp_host)
{
char data[MAXBUF];
+ log(DEBUG,"Sending sync");
// send start of sync marker: Y <timestamp>
// at this point the ircd receiving it starts broadcasting this netburst to all ircds
// except the ones its receiving it from.
serv->SendPacket(data,tcp_host);
}
}
- // send end of sync marker: E <timestamp>
snprintf(data,MAXBUF,"F %d",time(NULL));
serv->SendPacket(data,tcp_host);
+ log(DEBUG,"Sent sync");
// ircd sends its serverlist after the end of sync here
}
#ifdef _POSIX_PRIORITY_SCHEDULING
sched_yield();
#endif
+ // update the status of klines, etc
+ expire_lines();
fd_set sfd;
timeval tval;
break;
}
// during a netburst, send all data to all other linked servers
- if ((nb_start>0) && (udp_msg[0] != 'Y') && (udp_msg[0] != 'X') && (udp_msg[0] != 'F'))
+ if ((((nb_start>0) && (udp_msg[0] != 'Y') && (udp_msg[0] != 'X') && (udp_msg[0] != 'F'))) || (is_uline(tcp_host)))
{
- NetSendToAllExcept(tcp_host,udp_msg);
+ if (is_uline(tcp_host))
+ {
+ if ((udp_msg[0] != 'Y') && (udp_msg[0] != 'X') && (udp_msg[0] != 'F'))
+ {
+ NetSendToAllExcept(tcp_host,udp_msg);
+ }
+ }
+ else
+ NetSendToAllExcept(tcp_host,udp_msg);
}
FOREACH_MOD OnPacketReceive(udp_msg);
handle_link_packet(udp_msg, tcp_host, me[x]);
}
else
{
- AddClient(incomingSockfd, resolved, ports[count], iscached);
+ AddClient(incomingSockfd, resolved, ports[count], iscached, target);
log(DEBUG,"InspIRCd: adding client on port %d fd=%d",ports[count],incomingSockfd);
}
goto label;