#include <cstdio>
#include <time.h>
#include <string>
-#include <hash_map.h>
-#include <map.h>
+#ifdef GCC3
+#include <ext/hash_map>
+#else
+#include <hash_map>
+#endif
+#include <map>
#include <sstream>
#include <vector>
#include <errno.h>
using namespace std;
+#ifdef GCC3
+#define nspace __gnu_cxx
+#else
+#define nspace std
+#endif
+
+int LogLevel = DEFAULT;
char ServerName[MAXBUF];
char Network[MAXBUF];
char ServerDesc[MAXBUF];
char PrefixQuit[MAXBUF];
char DieValue[MAXBUF];
int debugging = 0;
-int MODCOUNT = -1;
int WHOWAS_STALE = 48; // default WHOWAS Entries last 2 days before they go 'stale'
int WHOWAS_MAX = 100; // default 100 people maximum in the WHOWAS list
int DieDelay = 5;
time_t startup_time = time(NULL);
-template<> struct hash<in_addr>
+extern vector<Module*> modules;
+extern vector<ircd_module*> factory;
+
+extern int MODCOUNT;
+
+namespace nspace
{
- size_t operator()(const struct in_addr &a) const
+ template<> struct nspace::hash<in_addr>
{
- size_t q;
- memcpy(&q,&a,sizeof(size_t));
- return q;
- }
-};
+ size_t operator()(const struct in_addr &a) const
+ {
+ size_t q;
+ memcpy(&q,&a,sizeof(size_t));
+ return q;
+ }
+ };
-template<> struct hash<string>
-{
- size_t operator()(const string &s) const
+ template<> struct nspace::hash<string>
{
- char a[MAXBUF];
- static struct hash<const char *> strhash;
- strcpy(a,s.c_str());
- strlower(a);
- return strhash(a);
- }
-};
-
+ size_t operator()(const string &s) const
+ {
+ char a[MAXBUF];
+ static struct hash<const char *> strhash;
+ strcpy(a,s.c_str());
+ strlower(a);
+ return strhash(a);
+ }
+ };
+}
struct StrHashComp
};
-typedef hash_map<string, userrec*, hash<string>, StrHashComp> user_hash;
-typedef hash_map<string, chanrec*, hash<string>, StrHashComp> chan_hash;
-typedef hash_map<in_addr,string*, hash<in_addr>, InAddr_HashComp> address_cache;
-typedef deque<command_t> command_table;
-typedef DLLFactory<ModuleFactory> ircd_module;
+typedef nspace::hash_map<std::string, userrec*, nspace::hash<string>, StrHashComp> user_hash;
+typedef nspace::hash_map<std::string, chanrec*, nspace::hash<string>, StrHashComp> chan_hash;
+typedef nspace::hash_map<in_addr,string*, nspace::hash<in_addr>, InAddr_HashComp> address_cache;
+typedef std::deque<command_t> command_table;
-serverrec* me;
+serverrec* me[32];
server_list* servers;
user_hash clientlist;
file_cache MOTD;
file_cache RULES;
address_cache IP;
-vector<Module*> modules(255);
-vector<ircd_module*> factory(255);
+
ClassVector Classes;
struct linger linger = { 0 };
char bannerBuffer[MAXBUF];
int boundPortCount = 0;
+int portCount = 0, UDPportCount = 0, ports[MAXSOCKS];
+int defaultRoute = 0;
/* prototypes */
{
if (p)
{
- debug("deleting %s %s %s %s",p->nick,p->ident,p->dhost,p->fullname);
- debug("safedelete(userrec*): pointer is safe to delete");
+ log(DEBUG,"deleting %s %s %s %s",p->nick,p->ident,p->dhost,p->fullname);
+ log(DEBUG,"safedelete(userrec*): pointer is safe to delete");
delete p;
}
else
{
- debug("safedelete(userrec*): unsafe pointer operation squished");
+ log(DEBUG,"safedelete(userrec*): unsafe pointer operation squished");
}
}
if (p)
{
delete p;
- debug("safedelete(chanrec*): pointer is safe to delete");
+ log(DEBUG,"safedelete(chanrec*): pointer is safe to delete");
}
else
{
- debug("safedelete(chanrec*): unsafe pointer operation squished");
+ log(DEBUG,"safedelete(chanrec*): unsafe pointer operation squished");
}
}
void chop(char* str)
{
- if (strlen(str) > 512)
- {
- str[510] = '\r';
- str[511] = '\n';
- str[512] = '\0';
- }
+
+ string temp = str;
+ FOREACH_MOD OnServerRaw(temp,false);
+ const char* str2 = temp.c_str();
+ sprintf(str,"%s",str2);
+
+
+ if (strlen(str) > 512)
+ {
+ str[510] = '\r';
+ str[511] = '\n';
+ str[512] = '\0';
+ }
}
-string getservername()
+std::string getservername()
{
return ServerName;
}
-string getserverdesc()
+std::string getserverdesc()
{
return ServerDesc;
}
-string getnetworkname()
+std::string getnetworkname()
{
return Network;
}
-string getadminname()
+std::string getadminname()
{
return AdminName;
}
-string getadminemail()
+std::string getadminemail()
{
return AdminEmail;
}
-string getadminnick()
+std::string getadminnick()
{
return AdminNick;
}
-void debug(char *text, ...)
+void log(int level,char *text, ...)
{
- char textbuffer[MAXBUF];
- va_list argsPtr;
- FILE *f;
- time_t rawtime;
- struct tm * timeinfo;
+ char textbuffer[MAXBUF];
+ va_list argsPtr;
+ FILE *f;
+ time_t rawtime;
+ struct tm * timeinfo;
+ if (level < LogLevel)
+ return;
- time(&rawtime);
- timeinfo = localtime (&rawtime);
+ time(&rawtime);
+ timeinfo = localtime (&rawtime);
- if (debugging)
- {
- f = fopen("ircd.log","a+");
- if (f)
- {
- char b[MAXBUF];
- va_start (argsPtr, text);
- vsnprintf(textbuffer, MAXBUF, text, argsPtr);
- va_end(argsPtr);
- strcpy(b,asctime(timeinfo));
- b[strlen(b)-1] = ':';
- fprintf(f,"%s %s\n",b,textbuffer);
- fclose(f);
- }
- else
- {
- printf("Can't write log file, bailing!!!");
- Exit(ERROR);
- }
- }
+ f = fopen("ircd.log","a+");
+ if (f)
+ {
+ char b[MAXBUF];
+ va_start (argsPtr, text);
+ vsnprintf(textbuffer, MAXBUF, text, argsPtr);
+ va_end(argsPtr);
+ strcpy(b,asctime(timeinfo));
+ b[strlen(b)-1] = ':';
+ fprintf(f,"%s %s\n",b,textbuffer);
+ fclose(f);
+ }
+ else
+ {
+ printf("Can't write log file, bailing!!!");
+ Exit(ERROR);
+ }
}
void readfile(file_cache &F, const char* fname)
FILE* file;
char linebuf[MAXBUF];
- debug("readfile: loading %s",fname);
+ log(DEBUG,"readfile: loading %s",fname);
F.clear();
file = fopen(fname,"r");
if (file)
}
else
{
- debug("readfile: failed to load file: %s",fname);
+ log(DEBUG,"readfile: failed to load file: %s",fname);
}
- debug("readfile: loaded %s, %d lines",fname,F.size());
+ log(DEBUG,"readfile: loaded %s, %d lines",fname,F.size());
}
void ReadConfig(void)
ConfValue("power","restartpass",0,restartpass);
ConfValue("options","prefixquit",0,PrefixQuit);
ConfValue("die","value",0,DieValue);
- ConfValue("options","debug",0,dbg);
- debugging = 0;
- if (!strcmp(dbg,"on"))
- {
- debugging = 1;
- }
- DieDelay = atoi(pauseval);
- readfile(MOTD,motd);
+ ConfValue("options","loglevel",0,dbg);
+ 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(RULES,rules);
- debug("Reading connect classes");
+ log(DEBUG,"Reading connect classes");
Classes.clear();
for (int i = 0; i < ConfValueEnum("connect"); i++)
{
ConfValue("connect","password",i,Value);
strcpy(c.pass,Value);
Classes.push_back(c);
- debug("Read connect class type ALLOW, host=%s password=%s",c.host,c.pass);
+ log(DEBUG,"Read connect class type ALLOW, host=%s password=%s",c.host,c.pass);
}
else
{
strcpy(c.host,Value);
c.type = CC_DENY;
Classes.push_back(c);
- debug("Read connect class type DENY, host=%s",c.host);
+ log(DEBUG,"Read connect class type DENY, host=%s",c.host);
}
}
void Blocking(int s)
{
int flags;
- debug("Blocking: %d",s);
+ log(DEBUG,"Blocking: %d",s);
flags = fcntl(s, F_GETFL, 0);
fcntl(s, F_SETFL, flags ^ O_NONBLOCK);
}
void NonBlocking(int s)
{
int flags;
- debug("NonBlocking: %d",s);
+ log(DEBUG,"NonBlocking: %d",s);
flags = fcntl(s, F_GETFL, 0);
fcntl(s, F_SETFL, flags | O_NONBLOCK);
}
}
}
-/* verify that a user's nickname is valid */
+/* verify that a user's ident and nickname is valid */
+
+int isident(const char* n)
+{
+ int i = 0;
+ char v[MAXBUF];
+ if (!n)
+
+ {
+ return 0;
+ }
+ if (!strcmp(n,""))
+ {
+ return 0;
+ }
+ for (i = 0; i != strlen(n); i++)
+ {
+ if ((n[i] < 33) || (n[i] > 125))
+ {
+ return 0;
+ }
+ /* can't occur ANYWHERE in an Ident! */
+ if (strchr("<>,./?:;@'~#=+()*&%$£ \"!",n[i]))
+ {
+ return 0;
+ }
+ }
+ return 1;
+}
+
int isnick(const char* n)
{
/* kill the record */
if (i != chanlist.end())
{
- debug("del_channel: destroyed: %s",i->second->name);
+ log(DEBUG,"del_channel: destroyed: %s",i->second->name);
delete i->second;
chanlist.erase(i);
go_again = 1;
}
}
}
- debug("completed channel purge, killed %d",purge);
+ log(DEBUG,"completed channel purge, killed %d",purge);
}
/* returns the status character for a given user on a channel, e.g. @ for op,
sprintf(foo," %d",chan->limit);
strcat(scratch,foo);
}
- debug("chanmodes: %s %s",chan->name,scratch);
+ log(DEBUG,"chanmodes: %s %s",chan->name,scratch);
return scratch;
}
}
}
}
- debug("usercount_i: %s %d",c->name,count);
+ log(DEBUG,"usercount_i: %s %d",c->name,count);
return count;
}
}
}
}
- debug("usercount: %s %d",c->name,count);
+ log(DEBUG,"usercount: %s %d",c->name,count);
return count;
}
cname[CHANMAX-1] = '\0';
}
- debug("add_channel: %s %s",user->nick,cname);
+ log(DEBUG,"add_channel: %s %s",user->nick,cname);
if ((has_channel(user,FindChan(cname))) && (FindChan(cname)))
{
if (!FindChan(cname))
{
/* create a new one */
- debug("add_channel: creating: %s",cname);
+ log(DEBUG,"add_channel: creating: %s",cname);
{
chanlist[cname] = new chanrec();
strncpy(chanlist[cname]->setby, user->nick,NICKMAX);
chanlist[cname]->topicset = 0;
Ptr = chanlist[cname];
- debug("add_channel: created: %s",cname);
+ log(DEBUG,"add_channel: created: %s",cname);
/* set created to 2 to indicate user
* is the first in the channel
* and should be given ops */
Ptr = FindChan(cname);
if (Ptr)
{
- debug("add_channel: joining to: %s",Ptr->name);
+ log(DEBUG,"add_channel: joining to: %s",Ptr->name);
if (strcmp(Ptr->key,""))
{
- debug("add_channel: %s has key %s",Ptr->name,Ptr->key);
+ log(DEBUG,"add_channel: %s has key %s",Ptr->name,Ptr->key);
if (!key)
{
- debug("add_channel: no key given in JOIN");
+ log(DEBUG,"add_channel: no key given in JOIN");
WriteServ(user->fd,"475 %s %s :Cannot join channel (Requires key)",user->nick, Ptr->name);
return NULL;
}
else
{
- debug("key at %p is %s",key,key);
+ log(DEBUG,"key at %p is %s",key,key);
if (strcasecmp(key,Ptr->key))
{
- debug("add_channel: bad key given in JOIN");
+ log(DEBUG,"add_channel: bad key given in JOIN");
WriteServ(user->fd,"475 %s %s :Cannot join channel (Incorrect key)",user->nick, Ptr->name);
return NULL;
}
return Ptr;
}
}
- debug("add_channel: user channel max exceeded: %s %s",user->nick,cname);
+ log(DEBUG,"add_channel: user channel max exceeded: %s %s",user->nick,cname);
WriteServ(user->fd,"405 %s %s :You are on too many channels",user->nick, cname);
return NULL;
}
}
FOREACH_MOD OnUserPart(user,Ptr);
- debug("del_channel: removing: %s %s",user->nick,Ptr->name);
+ log(DEBUG,"del_channel: removing: %s %s",user->nick,Ptr->name);
for (i =0; i != MAXCHANS; i++)
{
}
user->chans[i].uc_modes = 0;
user->chans[i].channel = NULL;
- debug("del_channel: unlinked: %s %s",user->nick,Ptr->name);
+ log(DEBUG,"del_channel: unlinked: %s %s",user->nick,Ptr->name);
break;
}
}
{
chan_hash::iterator iter = chanlist.find(Ptr->name);
- debug("del_channel: destroying channel: %s",Ptr->name);
+ log(DEBUG,"del_channel: destroying channel: %s",Ptr->name);
/* kill the record */
if (iter != chanlist.end())
{
- debug("del_channel: destroyed: %s",Ptr->name);
+ log(DEBUG,"del_channel: destroyed: %s",Ptr->name);
delete iter->second;
chanlist.erase(iter);
}
return;
}
- debug("kick_channel: removing: %s %s %s",user->nick,Ptr->name,src->nick);
+ log(DEBUG,"kick_channel: removing: %s %s %s",user->nick,Ptr->name,src->nick);
if (!has_channel(user,Ptr))
{
WriteChannel(Ptr,src,"KICK %s %s :%s",Ptr->name, user->nick, reason);
user->chans[i].uc_modes = 0;
user->chans[i].channel = NULL;
- debug("del_channel: unlinked: %s %s",user->nick,Ptr->name);
+ log(DEBUG,"del_channel: unlinked: %s %s",user->nick,Ptr->name);
break;
}
}
{
chan_hash::iterator iter = chanlist.find(Ptr->name);
- debug("del_channel: destroying channel: %s",Ptr->name);
+ log(DEBUG,"del_channel: destroying channel: %s",Ptr->name);
/* kill the record */
if (iter != chanlist.end())
{
- debug("del_channel: destroyed: %s",Ptr->name);
+ log(DEBUG,"del_channel: destroyed: %s",Ptr->name);
delete iter->second;
chanlist.erase(iter);
}
return 0;
}
d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_OP;
- debug("gave ops: %s %s",d->chans[i].channel->name,d->nick);
+ log(DEBUG,"gave ops: %s %s",d->chans[i].channel->name,d->nick);
}
}
}
return 0;
}
d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_HOP;
- debug("gave h-ops: %s %s",d->chans[i].channel->name,d->nick);
+ log(DEBUG,"gave h-ops: %s %s",d->chans[i].channel->name,d->nick);
}
}
}
return 0;
}
d->chans[i].uc_modes = d->chans[i].uc_modes | UCMODE_VOICE;
- debug("gave voice: %s %s",d->chans[i].channel->name,d->nick);
+ log(DEBUG,"gave voice: %s %s",d->chans[i].channel->name,d->nick);
}
}
}
return 0;
}
d->chans[i].uc_modes ^= UCMODE_OP;
- debug("took ops: %s %s",d->chans[i].channel->name,d->nick);
+ log(DEBUG,"took ops: %s %s",d->chans[i].channel->name,d->nick);
}
}
}
return 0;
}
d->chans[i].uc_modes ^= UCMODE_HOP;
- debug("took h-ops: %s %s",d->chans[i].channel->name,d->nick);
+ log(DEBUG,"took h-ops: %s %s",d->chans[i].channel->name,d->nick);
}
}
}
return 0;
}
d->chans[i].uc_modes ^= UCMODE_VOICE;
- debug("took voice: %s %s",d->chans[i].channel->name,d->nick);
+ log(DEBUG,"took voice: %s %s",d->chans[i].channel->name,d->nick);
}
}
}
c++;
if (c>1)
return 0;
- debug("add_ban: %s %s",chan->name,user->nick);
+ log(DEBUG,"add_ban: %s %s",chan->name,user->nick);
TidyBan(dest);
for (BanList::iterator i = chan->bans.begin(); i != chan->bans.end(); i++)
return 0;
}
- debug("del_ban: %s %s",chan->name,user->nick);
+ log(DEBUG,"del_ban: %s %s",chan->name,user->nick);
for (BanList::iterator i = chan->bans.begin(); i != chan->bans.end(); i++)
{
if (!strcasecmp(i->data,dest))
return;
}
- debug("process_modes: start");
+ log(DEBUG,"process_modes: start");
strcpy(modelist,parameters[1]); /* mode list, e.g. +oo-o */
/* parameters[2] onwards are parameters for
strcpy(outlist,"+");
mdir = 1;
- debug("process_modes: modelist: %s",modelist);
+ log(DEBUG,"process_modes: modelist: %s",modelist);
for (ptr = 0; ptr < strlen(modelist); ptr++)
{
r = 0;
{
- debug("process_modes: modechar: %c",modelist[ptr]);
+ log(DEBUG,"process_modes: modechar: %c",modelist[ptr]);
+ char modechar = modelist[ptr];
switch (modelist[ptr])
{
case '-':
chan->c_private = mdir;
break;
+ default:
+ string_list p;
+ p.clear();
+ if (ModeDefined(modelist[ptr],MT_CHANNEL))
+ {
+ if ((ModeDefinedOn(modelist[ptr],MT_CHANNEL)>0) && (mdir))
+ {
+ p.push_back(parameters[param]);
+ }
+ if ((ModeDefinedOff(modelist[ptr],MT_CHANNEL)>0) && (!mdir))
+ {
+ p.push_back(parameters[param]);
+ }
+ for (int i = 0; i <= MODCOUNT; i++)
+ {
+ if (modules[i]->OnExtendedMode(user,chan,modechar,MT_CHANNEL,mdir,p))
+ {
+ char app[] = {modechar, 0};
+ strcat(outlist, app);
+ chan->SetCustomMode(modelist[ptr],mdir);
+ // include parameters in output if mode has them
+ if ((ModeDefinedOn(modelist[ptr],MT_CHANNEL)>0) || (ModeDefinedOff(modelist[ptr],MT_CHANNEL)>0))
+ {
+ chan->SetCustomModeParam(modelist[ptr],parameters[param],mdir);
+ strcpy(outpars[pc++],parameters[param++]);
+ }
+ }
+ }
+ }
+ break;
+
}
}
}
void handle_die(char **parameters, int pcnt, userrec *user)
{
- debug("die: %s",user->nick);
+ log(DEBUG,"die: %s",user->nick);
if (!strcmp(parameters[0],diepass))
{
WriteOpers("*** DIE command from %s!%s@%s, terminating...",user->nick,user->ident,user->host);
- sleep(DieDelay);
+ sleep(DieDelay);
Exit(ERROR);
}
else
void handle_restart(char **parameters, int pcnt, userrec *user)
{
- debug("restart: %s",user->nick);
- if (!strcmp(parameters[0],restartpass))
+ log(DEBUG,"restart: %s",user->nick);
+ if (!strcmp(parameters[0],restartpass))
{
- WriteOpers("*** RESTART command from %s!%s@%s, Pretending to restart till this is finished :D",user->nick,user->ident,user->host);
- sleep(DieDelay);
- Exit(ERROR);
+ WriteOpers("*** RESTART command from %s!%s@%s, Pretending to restart till this is finished :D",user->nick,user->ident,user->host);
+ sleep(DieDelay);
+ Exit(ERROR);
/* Will finish this later when i can be arsed :) */
- }
- else
+ }
+ else
{
- WriteOpers("*** Failed RESTART Command from %s!%s@%s.",user->nick,user->ident,user->host);
- }
+ WriteOpers("*** Failed RESTART Command from %s!%s@%s.",user->nick,user->ident,user->host);
+ }
}
{
user_hash::iterator iter = clientlist.find(user->nick);
- debug("kill_link: %s '%s'",user->nick,reason);
+ log(DEBUG,"kill_link: %s '%s'",user->nick,reason);
Write(user->fd,"ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,reason);
fdatasync(user->fd);
WriteOpers("*** Client exiting: %s!%s@%s [%s]",user->nick,user->ident,user->host,reason);
FOREACH_MOD OnUserQuit(user);
- debug("closing fd %d",user->fd);
+ log(DEBUG,"closing fd %d",user->fd);
/* bugfix, cant close() a nonblocking socket (sux!) */
WriteCommonExcept(user,"QUIT :%s",reason);
Blocking(user->fd);
if (iter != clientlist.end())
{
- debug("deleting user hash value %p",iter->second);
+ log(DEBUG,"deleting user hash value %p",iter->second);
delete iter->second;
clientlist.erase(iter);
}
userrec *u = Find(parameters[0]);
char killreason[MAXBUF];
- debug("kill: %s %s",parameters[0],parameters[1]);
+ log(DEBUG,"kill: %s %s",parameters[0],parameters[1]);
if (u)
{
WriteOpers("*** Local Kill by %s: %s!%s@%s (%s)",user->nick,u->nick,u->ident,u->host,parameters[1]);
bool IsDenied(userrec *user)
{
- for (ClassVector::iterator i = Classes.begin(); i != Classes.end(); i++)
- {
- if (match(user->host,i->host) && (i->type == CC_DENY))
- {
- return true;
- }
- }
- return false;
+ for (ClassVector::iterator i = Classes.begin(); i != Classes.end(); i++)
+ {
+ if (match(user->host,i->host) && (i->type == CC_DENY))
+ {
+ return true;
+ }
+ }
+ return false;
}
void send_error(char *s)
{
- debug("send_error: %s",s);
+ log(DEBUG,"send_error: %s",s);
for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
{
WriteServ(i->second->fd,"NOTICE %s :%s",i->second->nick,s);
void Error(int status)
{
- signal (SIGALRM, SIG_IGN);
- signal (SIGPIPE, SIG_IGN);
- signal (SIGTERM, SIG_IGN);
- signal (SIGABRT, SIG_IGN);
- signal (SIGSEGV, SIG_IGN);
- signal (SIGURG, SIG_IGN);
- signal (SIGKILL, SIG_IGN);
- debug("*** fell down a pothole in the road to perfection ***");
- send_error("Error! Segmentation fault! save meeeeeeeeeeeeee *splat!*");
- exit(status);
+ signal (SIGALRM, SIG_IGN);
+ signal (SIGPIPE, SIG_IGN);
+ signal (SIGTERM, SIG_IGN);
+ signal (SIGABRT, SIG_IGN);
+ signal (SIGSEGV, SIG_IGN);
+ signal (SIGURG, SIG_IGN);
+ signal (SIGKILL, SIG_IGN);
+ log(DEBUG,"*** fell down a pothole in the road to perfection ***");
+ send_error("Error! Segmentation fault! save meeeeeeeeeeeeee *splat!*");
+ exit(status);
}
int main (int argc, char *argv[])
{
Start();
- debug("*** InspIRCd starting up!");
- if (!CheckConfig())
+ log(DEBUG,"*** InspIRCd starting up!");
+ if (!FileExists(CONFIG_FILE))
{
- debug("main: no config");
+ printf("ERROR: Cannot open config file: %s\nExiting...\n",CONFIG_FILE);
+ log(DEBUG,"main: no config");
printf("ERROR: Your config file is missing, this IRCd will self destruct in 10 seconds!\n");
Exit(ERROR);
}
if (InspIRCd() == ERROR)
{
- debug("main: daemon function bailed");
+ log(DEBUG,"main: daemon function bailed");
printf("ERROR: could not initialise. Shutting down.\n");
Exit(ERROR);
}
user_hash::iterator newnick;
user_hash::iterator oldnick = clientlist.find(Old);
- debug("ReHashNick: %s %s",Old,New);
+ log(DEBUG,"ReHashNick: %s %s",Old,New);
if (!strcasecmp(Old,New))
{
- debug("old nick is new nick, skipping");
+ log(DEBUG,"old nick is new nick, skipping");
return oldnick->second;
}
if (oldnick == clientlist.end()) return NULL; /* doesnt exist */
- debug("ReHashNick: Found hashed nick %s",Old);
+ log(DEBUG,"ReHashNick: Found hashed nick %s",Old);
clientlist[New] = new userrec();
clientlist[New] = oldnick->second;
/*delete oldnick->second; */
clientlist.erase(oldnick);
- debug("ReHashNick: Nick rehashed as %s",New);
+ log(DEBUG,"ReHashNick: Nick rehashed as %s",New);
return clientlist[New];
}
{
delete i->second;
i->second = a;
- debug("added WHOWAS entry, purged an old record");
+ log(DEBUG,"added WHOWAS entry, purged an old record");
return;
}
}
}
else
{
- debug("added fresh WHOWAS entry");
+ log(DEBUG,"added fresh WHOWAS entry");
whowas[a->nick] = a;
}
}
else
{
- debug("updated WHOWAS entry");
+ log(DEBUG,"updated WHOWAS entry");
delete iter->second;
iter->second = a;
}
/* add a client connection to the sockets list */
void AddClient(int socket, char* host, int port, bool iscached)
{
- int i;
- int blocking = 1;
- char resolved[MAXBUF];
- string tempnick;
- char tn2[MAXBUF];
- user_hash::iterator iter;
+ int i;
+ int blocking = 1;
+ char resolved[MAXBUF];
+ string tempnick;
+ char tn2[MAXBUF];
+ user_hash::iterator iter;
- tempnick = ConvToStr(socket) + "-unknown";
- sprintf(tn2,"%d-unknown",socket);
+ tempnick = ConvToStr(socket) + "-unknown";
+ sprintf(tn2,"%d-unknown",socket);
iter = clientlist.find(tempnick);
clientlist[tempnick] = new userrec();
NonBlocking(socket);
- debug("AddClient: %d %s %d",socket,host,port);
+ log(DEBUG,"AddClient: %d %s %d",socket,host,port);
clientlist[tempnick]->fd = socket;
int i = 0;
char cmp[MAXBUF];
- debug("chlist: %s",user->nick);
+ log(DEBUG,"chlist: %s",user->nick);
strcpy(lst,"");
if (!user)
{
if (iter != clientlist.end())
{
- debug("deleting user hash value");
+ log(DEBUG,"deleting user hash value");
delete iter->second;
clientlist.erase(iter);
}
void handle_who(char **parameters, int pcnt, userrec *user)
{
- chanrec* Ptr;
+ chanrec* Ptr = NULL;
/* theres more to do here, but for now just close the socket */
if (pcnt == 1)
{
if ((!strcmp(parameters[0],"0")) || (!strcmp(parameters[0],"*")))
{
- Ptr = user->chans[0].channel;
- printf(user->chans[0].channel->name);
- for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
+ if (user->chans[0].channel)
{
- if ((common_channels(user,i->second)) && (isnick(i->second->nick)))
+ Ptr = user->chans[0].channel;
+ for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
{
- WriteServ(user->fd,"352 %s %s %s %s %s %s Hr@ :0 %s",user->nick, Ptr->name, i->second->ident, i->second->dhost, ServerName, i->second->nick, i->second->fullname);
+ if ((common_channels(user,i->second)) && (isnick(i->second->nick)))
+ {
+ WriteServ(user->fd,"352 %s %s %s %s %s %s Hr@ :0 %s",user->nick, Ptr->name, i->second->ident, i->second->dhost, ServerName, i->second->nick, i->second->fullname);
+ }
}
}
- WriteServ(user->fd,"315 %s %s :End of /WHO list.",user->nick, Ptr->name);
+ if (Ptr)
+ {
+ WriteServ(user->fd,"315 %s %s :End of /WHO list.",user->nick, Ptr->name);
+ }
+ else
+ {
+ WriteServ(user->fd,"315 %s %s :End of /WHO list.",user->nick, user->nick);
+ }
return;
}
if (parameters[0][0] = '#')
{
WriteServ(user->fd,"382 %s %s :Rehashing",user->nick,CONFIG_FILE);
ReadConfig();
+ FOREACH_MOD OnRehash();
WriteOpers("%s is rehashing config file %s",user->nick,CONFIG_FILE);
}
{
user->registered = 7;
user->idle_lastmsg = time(NULL);
- debug("ConnectUser: %s",user->nick);
+ log(DEBUG,"ConnectUser: %s",user->nick);
if (strcmp(Passwd(user),"") && (!user->haspassed))
{
{
if (user->registered < 3)
{
- WriteServ(user->fd,"NOTICE Auth :No ident response, ident prefixed with ~");
- strcpy(user->ident,"~"); /* we arent checking ident... but these days why bother anyway? */
- strncat(user->ident,parameters[0],IDENTMAX);
- strncpy(user->fullname,parameters[3],128);
- user->registered = (user->registered | 1);
+ if (isident(parameters[0]) == 0) {
+ // This kinda Sucks, According to the RFC thou, its either this,
+ // or "You have already registered" :p -- Craig
+ WriteServ(user->fd,"461 %s USER :Not enough parameters",user->nick);
+ }
+ else {
+ WriteServ(user->fd,"NOTICE Auth :No ident response, ident prefixed with ~");
+ strcpy(user->ident,"~"); /* we arent checking ident... but these days why bother anyway? */
+ strncat(user->ident,parameters[0],IDENTMAX);
+ strncpy(user->fullname,parameters[3],128);
+ user->registered = (user->registered | 1);
+ }
}
else
{
void handle_connect(char **parameters, int pcnt, userrec *user)
{
- WriteServ(user->fd,"NOTICE %s :*** Connecting to %s port 7000...",user->nick,parameters[0]);
- if (!me->BeginLink(parameters[0],7000,"password"))
+ WriteServ(user->fd,"NOTICE %s :*** Connecting to %s port %s...",user->nick,parameters[0],parameters[1]);
+ if (!me[defaultRoute]->BeginLink(parameters[0],atoi(parameters[1]),"password"))
{
WriteServ(user->fd,"NOTICE %s :*** Failed to send auth packet to %s!",user->nick,parameters[0]);
}
{
if (pcnt < 1)
{
- debug("not enough params for handle_nick");
+ log(DEBUG,"not enough params for handle_nick");
return;
}
if (!parameters[0])
{
- debug("invalid parameter passed to handle_nick");
+ log(DEBUG,"invalid parameter passed to handle_nick");
return;
}
if (!strlen(parameters[0]))
{
- debug("zero length new nick passed to handle_nick");
+ log(DEBUG,"zero length new nick passed to handle_nick");
return;
}
if (!user)
{
- debug("invalid user passed to handle_nick");
+ log(DEBUG,"invalid user passed to handle_nick");
return;
}
if (!user->nick)
{
- debug("invalid old nick passed to handle_nick");
+ log(DEBUG,"invalid old nick passed to handle_nick");
return;
}
if (!strcasecmp(user->nick,parameters[0]))
{
- debug("old nick is new nick, skipping");
+ log(DEBUG,"old nick is new nick, skipping");
return;
}
else
strncpy(user->nick, parameters[0],NICKMAX);
- debug("new nick set: %s",user->nick);
+ log(DEBUG,"new nick set: %s",user->nick);
if (user->registered < 3)
user->registered = (user->registered | 2);
/* user is registered now, bit 0 = USER command, bit 1 = sent a NICK command */
ConnectUser(user);
}
- debug("exit nickchange: %s",user->nick);
+ log(DEBUG,"exit nickchange: %s",user->nick);
}
int process_parameters(char **command_p,char *parameters)
return;
}
strcpy(temp,cmd);
+
+ string tmp = cmd;
+ FOREACH_MOD OnServerRaw(tmp,true);
+ const char* cmd2 = tmp.c_str();
+ snprintf(cmd,512,"%s",cmd2);
+
if (!strchr(cmd,' '))
{
/* no parameters, lets skip the formalities and not chop up
user->nping = time(NULL) + 120;
if ((items) < cmdlist[i].min_params)
{
- debug("process_command: not enough parameters: %s %s",user->nick,command);
+ log(DEBUG,"process_command: not enough parameters: %s %s",user->nick,command);
WriteServ(user->fd,"461 %s %s :Not enough parameters",user->nick,command);
return;
}
if ((!strchr(user->modes,cmdlist[i].flags_needed)) && (cmdlist[i].flags_needed))
{
- debug("process_command: permission denied: %s %s",user->nick,command);
+ log(DEBUG,"process_command: permission denied: %s %s",user->nick,command);
WriteServ(user->fd,"481 %s :Permission Denied- You do not have the required operator privilages",user->nick);
cmd_found = 1;
return;
{
if ((!isnick(user->nick)) || (user->registered != 7))
{
- debug("process_command: not registered: %s %s",user->nick,command);
+ log(DEBUG,"process_command: not registered: %s %s",user->nick,command);
WriteServ(user->fd,"451 %s :You have not registered",command);
return;
}
}
if ((user->registered == 7) || (!strcmp(command,"USER")) || (!strcmp(command,"NICK")) || (!strcmp(command,"PASS")))
{
- debug("process_command: handler: %s %s %d",user->nick,command,items);
+ log(DEBUG,"process_command: handler: %s %s %d",user->nick,command,items);
if (cmdlist[i].handler_function)
{
/* ikky /stats counters */
}
else
{
- debug("process_command: not registered: %s %s",user->nick,command);
+ log(DEBUG,"process_command: not registered: %s %s",user->nick,command);
WriteServ(user->fd,"451 %s :You have not registered",command);
return;
}
}
if ((!cmd_found) && (user))
{
- debug("process_command: not in table: %s %s",user->nick,command);
+ log(DEBUG,"process_command: not in table: %s %s",user->nick,command);
WriteServ(user->fd,"421 %s %s :Unknown command",user->nick,command);
}
}
{
createcommand("USER",handle_user,0,4);
createcommand("NICK",handle_nick,0,1);
- createcommand("QUIT",handle_quit,0,1);
+ createcommand("QUIT",handle_quit,0,0);
createcommand("VERSION",handle_version,0,0);
createcommand("PING",handle_ping,0,1);
createcommand("PONG",handle_pong,0,1);
createcommand("PASS",handle_pass,0,1);
createcommand("TRACE",handle_trace,'o',0);
createcommand("WHOWAS",handle_whowas,0,1);
- createcommand("CONNECT",handle_connect,'o',1);
+ createcommand("CONNECT",handle_connect,'o',2);
createcommand("SQUIT",handle_squit,'o',1);
}
{
return;
}
- debug("InspIRCd: processing: %s %s",user->nick,cmd);
+ log(DEBUG,"InspIRCd: processing: %s %s",user->nick,cmd);
process_command(user,cmd);
}
+void handle_link_packet(char* udp_msg, char* udp_host, int udp_port, serverrec *serv)
+{
+}
+
int InspIRCd(void)
{
struct sockaddr_in client, server;
- int portCount = 0, ports[MAXSOCKS];
char addrs[MAXBUF][255];
int openSockfd[MAXSOCKS], incomingSockfd, result = TRUE;
socklen_t length;
int count = 0, scanDetectTrigger = TRUE, showBanner = FALSE;
int selectResult = 0;
- char *temp, configToken[MAXBUF], stuff[MAXBUF], Addr[MAXBUF];
+ char *temp, configToken[MAXBUF], stuff[MAXBUF], Addr[MAXBUF], Type[MAXBUF];
char resolvedHost[MAXBUF];
fd_set selectFds;
struct timeval tv;
- int count2;
- debug("InspIRCd: startup: begin");
- debug("$Id$");
- if ((geteuid()) && (getuid()) == 0)
+ log(DEBUG,"InspIRCd: startup: begin");
+ log(DEBUG,"$Id$");
+ if (geteuid() == 0)
{
printf("WARNING!!! You are running an irc server as ROOT!!! DO NOT DO THIS!!!\n\n");
Exit(ERROR);
- debug("InspIRCd: startup: not starting with UID 0!");
+ log(DEBUG,"InspIRCd: startup: not starting with UID 0!");
}
SetupCommandTable();
- debug("InspIRCd: startup: default command table set up");
+ log(DEBUG,"InspIRCd: startup: default command table set up");
ReadConfig();
if (strcmp(DieValue,""))
printf("WARNING: %s\n\n",DieValue);
exit(0);
}
- debug("InspIRCd: startup: read config");
+ log(DEBUG,"InspIRCd: startup: read config");
+ int count2 = 0, count3 = 0;
for (count = 0; count < ConfValueEnum("bind"); count++)
{
ConfValue("bind","port",count,configToken);
ConfValue("bind","address",count,Addr);
- ports[count] = atoi(configToken);
- strcpy(addrs[count],Addr);
- debug("InspIRCd: startup: read binding %s:%d from config",addrs[count],ports[count]);
+ ConfValue("bind","type",count,Type);
+ if (!strcmp(Type,"servers"))
+ {
+ char Default[MAXBUF];
+ strcpy(Default,"no");
+ ConfValue("bind","default",count,Default);
+ if (strchr(Default,'y'))
+ {
+ defaultRoute = count3;
+ log(DEBUG,"InspIRCd: startup: binding '%s:%s' is default server route",Addr,configToken);
+ }
+ me[count3] = new serverrec(ServerName,100L,false);
+ me[count3]->CreateListener(Addr,atoi(configToken));
+ count3++;
+ }
+ else
+ {
+ ports[count2] = atoi(configToken);
+ strcpy(addrs[count2],Addr);
+ count2++;
+ }
+ log(DEBUG,"InspIRCd: startup: read binding %s:%s [%s] from config",Addr,configToken, Type);
}
- portCount = ConfValueEnum("bind");
- debug("InspIRCd: startup: read %d total ports",portCount);
+ portCount = count2;
+ UDPportCount = count3;
+
+ log(DEBUG,"InspIRCd: startup: read %d total client ports and %d total server ports",portCount,UDPportCount);
- debug("InspIRCd: startup: InspIRCd is now running!");
+ log(DEBUG,"InspIRCd: startup: InspIRCd is now running!");
printf("\n");
- for (count = 0; count < ConfValueEnum("module"); count++)
+
+ /* BugFix By Craig! :p */
+ count2 = 0;
+ for (count = 0; count2 < ConfValueEnum("module"); count2++)
{
char modfile[MAXBUF];
ConfValue("module","name",count,configToken);
sprintf(modfile,"%s/%s",MOD_PATH,configToken);
printf("Loading module... \033[1;37m%s\033[0;37m\n",modfile);
- debug("InspIRCd: startup: Loading module: %s",modfile);
-
- factory[count] = new ircd_module(modfile);
- if (factory[count]->LastError())
- {
- debug("Unable to load %s: %s",modfile,factory[count]->LastError());
- sprintf("Unable to load %s: %s\nExiting...\n",modfile,factory[count]->LastError());
- Exit(ERROR);
- }
- if (factory[count]->factory)
- {
- modules[count] = factory[count]->factory->CreateModule();
- /* save the module and the module's classfactory, if
- * this isnt done, random crashes can occur :/ */
+ log(DEBUG,"InspIRCd: startup: Loading module: %s",modfile);
+ /* If The File Doesnt exist, Trying to load it
+ * Will Segfault the IRCd.. So, check to see if
+ * it Exists, Before Proceeding. */
+ if (FileExists(modfile))
+ {
+ factory[count] = new ircd_module(modfile);
+ if (factory[count]->LastError())
+ {
+ log(DEBUG,"Unable to load %s: %s",modfile,factory[count]->LastError());
+ sprintf("Unable to load %s: %s\nExiting...\n",modfile,factory[count]->LastError());
+ Exit(ERROR);
+ }
+ if (factory[count]->factory)
+ {
+ modules[count] = factory[count]->factory->CreateModule();
+ /* save the module and the module's classfactory, if
+ * this isnt done, random crashes can occur :/ */
+ }
+ else
+ {
+ log(DEBUG,"Unable to load %s",modfile);
+ sprintf("Unable to load %s\nExiting...\n",modfile);
+ Exit(ERROR);
+ }
+ /* Increase the Count */
+ count++;
}
else
{
- debug("Unable to load %s",modfile);
- sprintf("Unable to load %s\nExiting...\n",modfile);
- Exit(ERROR);
+ log(DEBUG,"InspIRCd: startup: Module Not Found %s",modfile);
+ printf("Module Not Found: \033[1;37m%s\033[0;37m, Skipping\n",modfile);
}
}
MODCOUNT = count - 1;
- debug("Total loaded modules: %d",MODCOUNT+1);
+ log(DEBUG,"Total loaded modules: %d",MODCOUNT+1);
- me = new serverrec(ServerName,100L,false);
servers = new server_list;
servers->clear();
-
- me->CreateListener("127.0.0.1",7000);
printf("\nInspIRCd is now running!\n");
if (DaemonSeed() == ERROR)
{
- debug("InspIRCd: startup: can't daemonise");
+ log(DEBUG,"InspIRCd: startup: can't daemonise");
printf("ERROR: could not go into daemon mode. Shutting down.\n");
Exit(ERROR);
}
/* setup select call */
FD_ZERO(&selectFds);
- debug("InspIRCd: startup: zero selects");
+ log(DEBUG,"InspIRCd: startup: zero selects");
+ log(VERBOSE,"InspIRCd: startup: portCount = %d", portCount);
for (count = 0; count < portCount; count++)
{
- if ((openSockfd[boundPortCount] = OpenTCPSocket()) == ERROR)
+ if ((openSockfd[boundPortCount] = OpenTCPSocket()) == ERROR)
{
- debug("InspIRCd: startup: bad fd %d",openSockfd[boundPortCount]);
- return(ERROR);
+ log(DEBUG,"InspIRCd: startup: bad fd %d",openSockfd[boundPortCount]);
+ return(ERROR);
}
if (BindSocket(openSockfd[boundPortCount],client,server,ports[count],addrs[count]) == ERROR)
{
- debug("InspIRCd: startup: failed to bind port %d",ports[count]);
+ log(DEBUG,"InspIRCd: startup: failed to bind port %d",ports[count]);
}
else /* well we at least bound to one socket so we'll continue */
{
- boundPortCount++;
+ boundPortCount++;
}
}
- debug("InspIRCd: startup: total bound ports %d",boundPortCount);
+ log(DEBUG,"InspIRCd: startup: total bound ports %d",boundPortCount);
/* if we didn't bind to anything then abort */
if (boundPortCount == 0)
{
- debug("InspIRCd: startup: no ports bound, bailing!");
+ log(DEBUG,"InspIRCd: startup: no ports bound, bailing!");
return (ERROR);
}
tv.tv_sec = 0;
selectResult = select(MAXSOCKS, &selectFds, NULL, NULL, &tv);
- if (me->RecvPacket(udp_msg, udp_host, udp_port))
+ for (int x = 0; x != UDPportCount; x++)
{
- WriteOpers("UDP Link Packet: '%s' from %s:%d",udp_msg,udp_host,udp_port);
+ if (me[x]->RecvPacket(udp_msg, udp_host, udp_port))
+ {
+ FOREACH_MOD OnPacketReceive(udp_msg);
+ WriteOpers("UDP Link Packet: '%s' from %s:%d:%d [route%d]",udp_msg,udp_host,udp_port,me[x]->port,x);
+ // Packets must go back via the route they arrived on :)
+ handle_link_packet(udp_msg, udp_host, udp_port, me[x]);
+ }
}
for (user_hash::iterator count2 = clientlist.begin(); count2 != clientlist.end(); count2++)
{
if (!count2->second->lastping)
{
- debug("InspIRCd: ping timeout: %s",count2->second->nick);
+ log(DEBUG,"InspIRCd: ping timeout: %s",count2->second->nick);
kill_link(count2->second,"Ping timeout");
break;
}
Write(count2->second->fd,"PING :%s",ServerName);
- debug("InspIRCd: pinging: %s",count2->second->nick);
+ log(DEBUG,"InspIRCd: pinging: %s",count2->second->nick);
count2->second->lastping = 0;
count2->second->nping = time(NULL)+120;
}
else
if (result == 0)
{
- debug("InspIRCd: Exited: %s",count2->second->nick);
+ log(DEBUG,"InspIRCd: Exited: %s",count2->second->nick);
kill_link(count2->second,"Client exited");
}
else if (result > 0)
if (incomingSockfd < 0)
{
WriteOpers("*** WARNING: Accept failed on port %d (%s)", ports[count],target);
- debug("InspIRCd: accept failed: %d",ports[count]);
+ log(DEBUG,"InspIRCd: accept failed: %d",ports[count]);
break;
}
AddClient(incomingSockfd, resolved, ports[count], iscached);
- debug("InspIRCd: adding client on port %d fd=%d",ports[count],incomingSockfd);
+ log(DEBUG,"InspIRCd: adding client on port %d fd=%d",ports[count],incomingSockfd);
break;
}