]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/commands.cpp
Added m_watch.cpp (provides /WATCH for notify) and fixes to allow it to work
[user/henk/code/inspircd.git] / src / commands.cpp
index 23d285eee8281f2a5ccf9d2e7dd3d5043f7315e1..3a9399f7c5b9ae455c931710b229ab84858c23c8 100644 (file)
  * ---------------------------------------------------
  */
 
+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 <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 "helperfuncs.h"
 #include "hashcomp.h"
 
-using namespace std;
-
 #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;
@@ -177,6 +187,15 @@ void handle_part(char **parameters, int pcnt, userrec *user)
        }
 }
 
+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]);
@@ -284,13 +303,7 @@ void handle_restart(char **parameters, int pcnt, userrec *user)
                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);
@@ -515,7 +528,7 @@ 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))
@@ -921,8 +934,17 @@ void handle_quit(char **parameters, int pcnt, userrec *user)
                         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())
@@ -968,7 +990,10 @@ void handle_who(char **parameters, int pcnt, userrec *user)
                                                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;
+                                               }
                                        }
                                }
                        }
@@ -987,6 +1012,7 @@ void handle_who(char **parameters, int pcnt, userrec *user)
                        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)))
@@ -1001,6 +1027,13 @@ void handle_who(char **parameters, int pcnt, userrec *user)
                                                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]);
@@ -1130,8 +1163,8 @@ void handle_user(char **parameters, int pcnt, userrec *user)
                }
                else {
                        strcpy(user->ident,"~"); /* we arent checking ident... but these days why bother anyway? */
-                       strlcat(user->ident,parameters[0],IDENTMAX);
-                       strlcpy(user->fullname,parameters[3],128);
+                       strlcat(user->ident,parameters[0],IDENTMAX+1);
+                       strlcpy(user->fullname,parameters[3],MAXGECOS);
                        user->registered = (user->registered | 1);
                }
        }
@@ -1195,12 +1228,12 @@ void handle_away(char **parameters, int pcnt, userrec *user)
 {
        if (pcnt)
        {
-               strlcpy(user->awaymsg,parameters[0],512);
+               strlcpy(user->awaymsg,parameters[0],MAXAWAY);
                WriteServ(user->fd,"306 %s :You have been marked as being away",user->nick);
        }
        else
        {
-               strlcpy(user->awaymsg,"",512);
+               strlcpy(user->awaymsg,"",MAXAWAY);
                WriteServ(user->fd,"305 %s :You are no longer marked as being away",user->nick);
        }
 }
@@ -1456,11 +1489,11 @@ void handle_stats(char **parameters, int pcnt, userrec *user)
                {
                        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);
                        }
                        
                }
@@ -1491,50 +1524,60 @@ void handle_stats(char **parameters, int pcnt, userrec *user)
        
 }
 
-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)
@@ -1630,7 +1673,8 @@ void handle_map(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));
@@ -1704,7 +1748,8 @@ void handle_oper(char **parameters, int pcnt, userrec *user)
                                        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;
@@ -2241,6 +2286,11 @@ void handle_n(char token,char* params,serverrec* source,serverrec* reply, char*
                if (!user->nick) return;
                strlcpy(user->nick, newnick,NICKMAX);
                log(DEBUG,"new nick set: %s",user->nick);
+               if (user->registered == 7)
+               {
+                       FOREACH_MOD OnUserPostNick(user,oldnick);
+               }
+
        }
 }
 
@@ -2361,9 +2411,9 @@ void handle_N(char token,char* params,serverrec* source,serverrec* reply, char*
        strlcpy(clientlist[nick]->nick, nick,NICKMAX);
        strlcpy(clientlist[nick]->host, host,160);
        strlcpy(clientlist[nick]->dhost, dhost,160);
-       strlcpy(clientlist[nick]->server, server,256);
-       strlcpy(clientlist[nick]->ident, ident,10); // +1 char to compensate for tilde
-       strlcpy(clientlist[nick]->fullname, gecos,128);
+       clientlist[nick]->server = (char*)FindServerNamePtr(server);
+       strlcpy(clientlist[nick]->ident, ident,IDENTMAX+1); // +1 char to compensate for tilde
+       strlcpy(clientlist[nick]->fullname, gecos,MAXGECOS);
        strlcpy(clientlist[nick]->ip,ipaddr,16);
        clientlist[nick]->signon = TS;
        clientlist[nick]->nping = 0; // this is ignored for a remote user anyway.
@@ -2403,7 +2453,7 @@ void handle_a(char token,char* params,serverrec* source,serverrec* reply, char*
        userrec* user = Find(nick);
 
        if (user)
-               strlcpy(user->fullname,gecos,MAXBUF);
+               strlcpy(user->fullname,gecos,MAXGECOS);
 }
 
 void handle_b(char token,char* params,serverrec* source,serverrec* reply, char* tcp_host, char* tcp_sum)
@@ -2609,6 +2659,7 @@ void handle_amp(char token,char* params,serverrec* source,serverrec* reply, char
                        }
                }
        }
+       log(DEBUG,"Done with netsplit.");
 }
 
 unsigned long authcookie;
@@ -2786,6 +2837,8 @@ void process_restricted_commands(char token,char* params,serverrec* source,serve
        char buffer[MAXBUF];
        int MOD_RESULT = 0;
 
+       ircd_connector* cn = source->FindHost(tcp_host);
+
        switch(token)
        {
                // Y <TS>
@@ -2829,11 +2882,14 @@ void process_restricted_commands(char token,char* params,serverrec* source,serve
                // ?
                // 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
@@ -3211,6 +3267,7 @@ void handle_link_packet(char* tcp_msg, char* tcp_host, serverrec *serv,char* tcp
                                                                me[j]->connectors[k].SetServerName(servername);
                                                                me[j]->connectors[k].SetDescription(serverdesc);
                                                                me[j]->connectors[k].SetState(STATE_CONNECTED);
+                                                               AddServerName(servername);
                                                                NetSendMyRoutingTable();
                                                                return;
                                                        }
@@ -3250,16 +3307,18 @@ void handle_link_packet(char* tcp_msg, char* tcp_host, serverrec *serv,char* tcp
                        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;
@@ -3275,7 +3334,6 @@ void handle_link_packet(char* tcp_msg, char* tcp_host, serverrec *serv,char* tcp
                        }
                }
                
-               
                char Link_ServerName[1024];
                char Link_IPAddr[1024];
                char Link_Port[1024];
@@ -3305,6 +3363,7 @@ void handle_link_packet(char* tcp_msg, char* tcp_host, serverrec *serv,char* tcp
                                        if (!strcasecmp(serv->connectors[t].GetServerName().c_str(),servername))
                                        {
                                                serv->connectors[t].SetState(STATE_CONNECTED);
+                                               AddServerName(servername);
                                        }
                                }
                
@@ -3314,6 +3373,7 @@ void handle_link_packet(char* tcp_msg, char* tcp_host, serverrec *serv,char* tcp
                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);
@@ -3370,6 +3430,7 @@ void handle_link_packet(char* tcp_msg, char* tcp_host, serverrec *serv,char* tcp
                                                                char buffer[MAXBUF];
                                                                me[j]->connectors[k].SetDescription(serverdesc);
                                                                me[j]->connectors[k].SetState(STATE_CONNECTED);
+                                                               AddServerName(servername);
                                                                snprintf(buffer,MAXBUF,"%s X 0",CreateSum().c_str());
                                                                serv->SendPacket(buffer,tcp_host);
                                                                DoSync(me[j],tcp_host);
@@ -3387,6 +3448,7 @@ void handle_link_packet(char* tcp_msg, char* tcp_host, serverrec *serv,char* tcp
                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);
@@ -3425,6 +3487,7 @@ void handle_link_packet(char* tcp_msg, char* tcp_host, serverrec *serv,char* tcp
                                                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;
@@ -3461,6 +3524,7 @@ void handle_link_packet(char* tcp_msg, char* tcp_host, serverrec *serv,char* tcp
                                                                me[j]->connectors[k].SetDescription(serverdesc);
                                                                me[j]->connectors[k].SetServerName(servername);
                                                                me[j]->connectors[k].SetState(STATE_SERVICES);
+                                                               AddServerName(servername);
                                                                snprintf(buffer,MAXBUF,"%s X 0",CreateSum().c_str());
                                                                serv->SendPacket(buffer,servername);
                                                                snprintf(buffer,MAXBUF,"%s s %s %s %lu :%s",CreateSum().c_str(),ServerName,Link_SendPass,LinkPort,ServerDesc);
@@ -3485,6 +3549,7 @@ void handle_link_packet(char* tcp_msg, char* tcp_host, serverrec *serv,char* tcp
                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);