* ---------------------------------------------------
*/
+using namespace std;
+
+#include "inspircd_config.h"
#include "inspircd.h"
#include "inspircd_io.h"
#include "inspircd_util.h"
-#include "inspircd_config.h"
#include <unistd.h>
-#include <fcntl.h>
#include <sys/errno.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>
+
#ifdef USE_KQUEUE
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#endif
+
+#ifdef USE_EPOLL
+#include <sys/epoll.h>
+#endif
+
#include <cstdio>
#include <time.h>
#include <string>
#include <map>
#include <sstream>
#include <vector>
-#include <errno.h>
#include <deque>
-#include <errno.h>
-#include <unistd.h>
-#include <sched.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include "xline.h"
#include "inspstring.h"
#include "dnsqueue.h"
-
-#ifdef GCC3
-#define nspace __gnu_cxx
-#else
-#define nspace std
-#endif
-
-using namespace std;
+#include "helperfuncs.h"
+#include "hashcomp.h"
#ifdef USE_KQUEUE
extern int kq;
#endif
+#ifdef USE_EPOLL
+int ep;
+#endif
+
extern int MODCOUNT;
extern std::vector<Module*> modules;
extern std::vector<ircd_module*> factory;
const long duration_w = duration_d * 7;
const long duration_y = duration_w * 52;
-namespace nspace
-{
-#ifdef GCC34
- template<> struct hash<in_addr>
-#else
- template<> struct nspace::hash<in_addr>
-#endif
- {
- size_t operator()(const struct in_addr &a) const
- {
- size_t q;
- memcpy(&q,&a,sizeof(size_t));
- return q;
- }
- };
-#ifdef GCC34
- template<> struct hash<string>
-#else
- template<> struct nspace::hash<string>
-#endif
- {
- size_t operator()(const string &s) const
- {
- char a[MAXBUF];
- static struct hash<const char *> strhash;
- strlcpy(a,s.c_str(),MAXBUF);
- strlower(a);
- return strhash(a);
- }
- };
-}
-
-
-struct StrHashComp
-{
-
- bool operator()(const string& s1, const string& s2) const
- {
- char a[MAXBUF],b[MAXBUF];
- strlcpy(a,s1.c_str(),MAXBUF);
- strlcpy(b,s2.c_str(),MAXBUF);
- strlower(a);
- strlower(b);
- return (strcasecmp(a,b) == 0);
- }
-
-};
-
-struct InAddr_HashComp
-{
-
- bool operator()(const in_addr &s1, const in_addr &s2) const
- {
- size_t q;
- size_t p;
-
- memcpy(&q,&s1,sizeof(size_t));
- memcpy(&p,&s2,sizeof(size_t));
-
- return (q == p);
- }
-
-};
-
-
-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 nspace::hash_map<std::string, WhoWasUser*, nspace::hash<string>, StrHashComp> whowas_hash;
+typedef nspace::hash_map<std::string, userrec*, nspace::hash<string>, irc::StrHashComp> user_hash;
+typedef nspace::hash_map<std::string, chanrec*, nspace::hash<string>, irc::StrHashComp> chan_hash;
+typedef nspace::hash_map<in_addr,string*, nspace::hash<in_addr>, irc::InAddr_HashComp> address_cache;
+typedef nspace::hash_map<std::string, WhoWasUser*, nspace::hash<string>, irc::StrHashComp> whowas_hash;
typedef std::deque<command_t> command_table;
}
}
+void handle_commands(char **parameters, int pcnt, userrec *user)
+{
+ for (int i = 0; i < cmdlist.size(); i++)
+ {
+ WriteServ(user->fd,"902 %s :%s %s %d",user->nick,cmdlist[i].command,cmdlist[i].source,cmdlist[i].min_params);
+ }
+ WriteServ(user->fd,"903 %s :End of COMMANDS list",user->nick);
+}
+
void handle_kick(char **parameters, int pcnt, userrec *user)
{
chanrec* Ptr = FindChan(parameters[0]);
sleep(1);
for (int i = 0; i < 65536; i++)
{
- int on = 1;
- struct linger linger = { 0 };
- setsockopt(i, SOL_SOCKET, SO_REUSEADDR, (const char*)&on, sizeof(on));
- linger.l_onoff = 1;
- linger.l_linger = 1;
- setsockopt(i, SOL_SOCKET, SO_LINGER, (const char*)&linger,sizeof(linger));
- Blocking(i);
+ shutdown(i,2);
close(i);
}
sleep(2);
void handle_invite(char **parameters, int pcnt, userrec *user)
{
- userrec* u = Find(parameters[0]);
- chanrec* c = FindChan(parameters[1]);
-
- if ((!c) || (!u))
+ if (pcnt == 2)
{
- if (!c)
+ userrec* u = Find(parameters[0]);
+ chanrec* c = FindChan(parameters[1]);
+
+ if ((!c) || (!u))
{
- WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[1]);
+ if (!c)
+ {
+ WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[1]);
+ }
+ else
+ {
+ if (c->binarymodes & CM_INVITEONLY)
+ {
+ WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]);
+ }
+ }
+
+ return;
}
- else
+
+ if (c->binarymodes & CM_INVITEONLY)
{
- if (c->binarymodes & CM_INVITEONLY)
+ if (cstatus(user,c) < STATUS_HOP)
{
- WriteServ(user->fd,"401 %s %s :No such nick/channel",user->nick, parameters[0]);
+ WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, c->name);
+ return;
}
}
+ if (has_channel(u,c))
+ {
+ WriteServ(user->fd,"443 %s %s %s :Is already on channel %s",user->nick,u->nick,c->name,c->name);
+ return;
+ }
+ if (!has_channel(user,c))
+ {
+ WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, c->name);
+ return;
+ }
- return;
- }
+ int MOD_RESULT = 0;
+ FOREACH_RESULT(OnUserPreInvite(user,u,c));
+ if (MOD_RESULT == 1) {
+ return;
+ }
- if (c->binarymodes & CM_INVITEONLY)
+ u->InviteTo(c->name);
+ WriteFrom(u->fd,user,"INVITE %s :%s",u->nick,c->name);
+ WriteServ(user->fd,"341 %s %s %s",user->nick,u->nick,c->name);
+
+ // i token must go to ALL servers!!!
+ char buffer[MAXBUF];
+ snprintf(buffer,MAXBUF,"i %s %s %s",u->nick,user->nick,c->name);
+ NetSendToAll(buffer);
+ }
+ else
{
- if (cstatus(user,c) < STATUS_HOP)
+ // pinched from ircu - invite with not enough parameters shows channels
+ // youve been invited to but haven't joined yet.
+ InvitedList* il = user->GetInviteList();
+ for (InvitedList::iterator i = il->begin(); i != il->end(); i++)
{
- WriteServ(user->fd,"482 %s %s :You must be at least a half-operator to change modes on this channel",user->nick, c->name);
- return;
+ if (i->channel) {
+ WriteServ(user->fd,"346 %s :%s",user->nick,i->channel);
+ }
}
+ WriteServ(user->fd,"347 %s :End of INVITE list",user->nick);
}
- if (has_channel(u,c))
- {
- WriteServ(user->fd,"443 %s %s %s :Is already on channel %s",user->nick,u->nick,c->name,c->name);
- return;
- }
- if (!has_channel(user,c))
- {
- WriteServ(user->fd,"442 %s %s :You're not on that channel!",user->nick, c->name);
- return;
- }
-
- int MOD_RESULT = 0;
- FOREACH_RESULT(OnUserPreInvite(user,u,c));
- if (MOD_RESULT == 1) {
- return;
- }
-
- u->InviteTo(c->name);
- WriteFrom(u->fd,user,"INVITE %s :%s",u->nick,c->name);
- WriteServ(user->fd,"341 %s %s %s",user->nick,u->nick,c->name);
-
- // i token must go to ALL servers!!!
- char buffer[MAXBUF];
- snprintf(buffer,MAXBUF,"i %s %s %s",u->nick,user->nick,c->name);
- NetSendToAll(buffer);
}
void handle_topic(char **parameters, int pcnt, userrec *user)
strlcpy(topic,parameters[1],MAXBUF);
if (strlen(topic)>MAXTOPIC)
{
- topic[MAXTOPIC-1] = '\0';
+ topic[MAXTOPIC] = '\0';
}
if (!strcasecmp(user->server,ServerName))
log(DEBUG,"kqueue: Failed to remove user from queue!");
}
#endif
- shutdown(user->fd,2);
- close(user->fd);
+#ifdef USE_EPOLL
+ struct epoll_event ev;
+ ev.events = EPOLLIN | EPOLLET;
+ ev.data.fd = user->fd;
+ int i = epoll_ctl(ep, EPOLL_CTL_DEL, user->fd, &ev);
+ if (i < 0)
+ {
+ log(DEBUG,"epoll: List deletion failure!");
+ }
+#endif
+ user->CloseSocket();
}
if (iter != clientlist.end())
WriteServ(user->fd,"352 %s %s %s %s %s %s %s :0 %s",user->nick, Ptr ? Ptr->name : "*", i->second->ident, i->second->dhost, i->second->server, i->second->nick, tmp, i->second->fullname);
n_list++;
if (n_list > MaxWhoResults)
+ {
+ WriteServ(user->fd,"523 %s WHO :Command aborted: More results than configured limit",user->nick);
break;
+ }
}
}
}
Ptr = FindChan(parameters[0]);
if (Ptr)
{
+ int n_list = 0;
for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
{
if ((has_channel(i->second,Ptr)) && (isnick(i->second->nick)))
if (strchr(i->second->modes,'o')) { strlcat(tmp, "*", 9); }
strlcat(tmp, cmode(i->second, Ptr),5);
WriteServ(user->fd,"352 %s %s %s %s %s %s %s :0 %s",user->nick, Ptr->name, i->second->ident, i->second->dhost, i->second->server, i->second->nick, tmp, i->second->fullname);
+ n_list++;
+ if (n_list > MaxWhoResults)
+ {
+ WriteServ(user->fd,"523 %s WHO :Command aborted: More results than configured limit",user->nick);
+ break;
+ }
+
}
}
WriteServ(user->fd,"315 %s %s :End of /WHO list.",user->nick, parameters[0]);
{
if (isnick(i->second->nick))
{
- WriteServ(user->fd,"211 %s :%s:%d %s %d %d %d %d",user->nick,ServerName,i->second->port,i->second->nick,i->second->bytes_in,i->second->cmds_in,i->second->bytes_out,i->second->cmds_out);
+ WriteServ(user->fd,"211 %s :%s:%d %s %d %d %d %d",user->nick,i->second->server,i->second->port,i->second->nick,i->second->bytes_in,i->second->cmds_in,i->second->bytes_out,i->second->cmds_out);
}
else
{
- WriteServ(user->fd,"211 %s :%s:%d (unknown@%d) %d %d %d %d",user->nick,ServerName,i->second->port,i->second->fd,i->second->bytes_in,i->second->cmds_in,i->second->bytes_out,i->second->cmds_out);
+ WriteServ(user->fd,"211 %s :%s:%d (unknown@%d) %d %d %d %d",user->nick,i->second->server,i->second->port,i->second->fd,i->second->bytes_in,i->second->cmds_in,i->second->bytes_out,i->second->cmds_out);
}
}
}
-void handle_connect(char **parameters, int pcnt, userrec *user)
+
+void ConnectServer(char* servermask,userrec* user)
{
- char Link_ServerName[1024];
- char Link_IPAddr[1024];
- char Link_Port[1024];
- char Link_Pass[1024];
- int LinkPort;
- bool found = false;
+ char Link_ServerName[1024];
+ char Link_IPAddr[1024];
+ char Link_Port[1024];
+ char Link_Pass[1024];
+ int LinkPort;
+ bool found = false;
- for (int i = 0; i < ConfValueEnum("link",&config_f); i++)
- {
- if (!found)
- {
- ConfValue("link","name",i,Link_ServerName,&config_f);
- ConfValue("link","ipaddr",i,Link_IPAddr,&config_f);
- ConfValue("link","port",i,Link_Port,&config_f);
- ConfValue("link","sendpass",i,Link_Pass,&config_f);
- log(DEBUG,"(%d) Comparing against name='%s', ipaddr='%s', port='%s', recvpass='%s'",i,Link_ServerName,Link_IPAddr,Link_Port,Link_Pass);
- LinkPort = atoi(Link_Port);
- if (match(Link_ServerName,parameters[0])) {
- found = true;
- break;
- }
- }
- }
-
- if (!found) {
- WriteServ(user->fd,"NOTICE %s :*** Failed to connect to %s: No servers matching this pattern are configured for linking.",user->nick,parameters[0]);
- return;
- }
-
- // TODO: Perform a check here to stop a server being linked twice!
+ for (int i = 0; i < ConfValueEnum("link",&config_f); i++)
+ {
+ if (!found)
+ {
+ ConfValue("link","name",i,Link_ServerName,&config_f);
+ ConfValue("link","ipaddr",i,Link_IPAddr,&config_f);
+ ConfValue("link","port",i,Link_Port,&config_f);
+ ConfValue("link","sendpass",i,Link_Pass,&config_f);
+ LinkPort = atoi(Link_Port);
+ if (match(Link_ServerName,servermask)) {
+ found = true;
+ break;
+ }
+ }
+ }
- WriteServ(user->fd,"NOTICE %s :*** Connecting to %s (%s) port %s...",user->nick,Link_ServerName,Link_IPAddr,Link_Port);
+ if (!found) {
+ if (user)
+ WriteServ(user->fd,"NOTICE %s :*** Failed to connect to %s: No servers matching this pattern are configured for linking.",user->nick,servermask);
+ return;
+ }
- if (me[defaultRoute])
- {
- me[defaultRoute]->BeginLink(Link_IPAddr,LinkPort,Link_Pass,Link_ServerName,me[defaultRoute]->port);
- return;
- }
- else
+ if (user)
{
- WriteServ(user->fd,"NOTICE %s :No default route is defined for server connections on this server. You must define a server connection to be default route so that sockets can be bound to it.",user->nick);
+ WriteServ(user->fd,"NOTICE %s :*** Connecting to %s (%s) port %s...",user->nick,Link_ServerName,Link_IPAddr,Link_Port);
}
+ else WriteOpers("*** Autoconnecting to %s (%s) port %s...",Link_ServerName,Link_IPAddr,Link_Port);
+
+ if (me[defaultRoute])
+ {
+ me[defaultRoute]->BeginLink(Link_IPAddr,LinkPort,Link_Pass,Link_ServerName,me[defaultRoute]->port);
+ return;
+ }
+ else
+ {
+ if (user)
+ WriteServ(user->fd,"NOTICE %s :No default route is defined for server connections on this server. You must define a server connection to be default route so that sockets can be bound to it.",user->nick);
+ }
+}
+
+
+void handle_connect(char **parameters, int pcnt, userrec *user)
+{
+ ConnectServer(parameters[0],user);
}
void handle_squit(char **parameters, int pcnt, userrec *user)
{
for (int k = 0; k < me[j]->connectors.size(); k++)
{
- snprintf(line,MAXBUF,"006 %s :%c-%s",user->nick,islast(me[j]->connectors[k].GetServerName().c_str()),me[j]->connectors[k].GetServerName().c_str());
+ int state = me[j]->connectors[k].GetState();
+ snprintf(line,MAXBUF,"006 %s :%c%s%s",user->nick,islast(me[j]->connectors[k].GetServerName().c_str()),state == STATE_NOAUTH_INBOUND || state == STATE_NOAUTH_OUTBOUND ? "-*" : "--", me[j]->connectors[k].GetServerName().c_str());
while (strlen(line) < 50)
strcat(line," ");
WriteServ(user->fd,"%s%d (%.2f%%)",line,map_count(me[j]->connectors[k].GetServerName().c_str()),(float)(((float)map_count(me[j]->connectors[k].GetServerName().c_str())/(float)registered_usercount())*100));
snprintf(global,MAXBUF,"| %s %s",user->nick,TypeName);
NetSendToAll(global);
ConfValue("type","host",j,HostName,&config_f);
- ChangeDisplayedHost(user,HostName);
+ if (*HostName)
+ ChangeDisplayedHost(user,HostName);
strlcpy(user->oper,TypeName,NICKMAX);
found = true;
fail2 = false;
}
}
}
+ log(DEBUG,"Done with netsplit.");
}
unsigned long authcookie;
char buffer[MAXBUF];
int MOD_RESULT = 0;
+ ircd_connector* cn = source->FindHost(tcp_host);
+
switch(token)
{
// Y <TS>
// ?
// ping
case '?':
- reply->SendPacket("!",tcp_host);
+ snprintf(buffer,MAXBUF,"%s !",CreateSum().c_str());
+ reply->SendPacket(buffer,tcp_host);
break;
// ?
// pong
case '!':
+ if (cn)
+ cn->ResetPing();
break;
// *
// no operation
char buffer[MAXBUF];
snprintf(buffer,MAXBUF,"E :Server %s already exists!",servername);
serv->SendPacket(buffer,tcp_host);
+ serv->FlushWriteBuffers();
RemoveServer(tcp_host);
return;
}
- if (atoi(revision) != GetRevision())
+ if (std::string(revision) != GetRevision())
{
- WriteOpers("CONNECT aborted: Could not link to %s, is an incompatible version %s, our version is %d",servername,revision,GetRevision());
+ WriteOpers("CONNECT aborted: Could not link to %s, is an incompatible version %s, our version is %s",servername,revision,GetRevision().c_str());
char buffer[MAXBUF];
snprintf(buffer,MAXBUF,"E :Version number mismatch");
serv->SendPacket(buffer,tcp_host);
+ serv->FlushWriteBuffers();
RemoveServer(tcp_host);
RemoveServer(servername);
return;
char buffer[MAXBUF];
snprintf(buffer,MAXBUF,"E :Access is denied (no matching link block)");
serv->SendPacket(buffer,tcp_host);
+ serv->FlushWriteBuffers();
WriteOpers("CONNECT from %s denied, no matching link block",servername);
RemoveServer(tcp_host);
RemoveServer(servername);
char buffer[MAXBUF];
snprintf(buffer,MAXBUF,"E :Access is denied (no matching link block)");
serv->SendPacket(buffer,tcp_host);
+ serv->FlushWriteBuffers();
WriteOpers("CONNECT from %s denied, no matching link block",servername);
RemoveServer(tcp_host);
RemoveServer(servername);
char buffer[MAXBUF];
snprintf(buffer,MAXBUF,"E :Access is denied (Server exists in the mesh)");
serv->SendPacket(buffer,tcp_host);
+ serv->FlushWriteBuffers();
WriteOpers("CONNECT from %s denied, \"%s\" already exists!",tcp_host,servername);
RemoveServer(tcp_host);
return;
char buffer[MAXBUF];
snprintf(buffer,MAXBUF,"E :Access is denied (no matching link block)");
serv->SendPacket(buffer,tcp_host);
+ serv->FlushWriteBuffers();
WriteOpers("CONNECT from %s denied, no matching link block",servername);
RemoveServer(tcp_host);
RemoveServer(servername);