]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/inspircd.cpp
Added ability to update routing table on the fly if a connection is lost
[user/henk/code/inspircd.git] / src / inspircd.cpp
index ca1041e691e5c9fc9caa7ae7ffb64c78bf798016..f178a9f0b0d549e68f1b6d2826d6b135f761429a 100644 (file)
@@ -892,6 +892,8 @@ void NetSendToCommon(userrec* u, char* s)
        char buffer[MAXBUF];
        snprintf(buffer,MAXBUF,"%s",s);
        
+       log(DEBUG,"NetSendToCommon: '%s' '%s'",u->nick,s);
+
        for (int j = 0; j < 32; j++)
        {
                if (me[j] != NULL)
@@ -913,6 +915,8 @@ void NetSendToAll(char* s)
        char buffer[MAXBUF];
        snprintf(buffer,MAXBUF,"%s",s);
        
+       log(DEBUG,"NetSendToAll: '%s'",s);
+
        for (int j = 0; j < 32; j++)
        {
                if (me[j] != NULL)
@@ -931,6 +935,8 @@ void NetSendToOne(char* target,char* s)
        char buffer[MAXBUF];
        snprintf(buffer,MAXBUF,"%s",s);
        
+       log(DEBUG,"NetSendToOne: '%s' '%s'",target,s);
+
        for (int j = 0; j < 32; j++)
        {
                if (me[j] != NULL)
@@ -951,6 +957,8 @@ void NetSendToAllExcept(char* target,char* s)
        char buffer[MAXBUF];
        snprintf(buffer,MAXBUF,"%s",s);
        
+       log(DEBUG,"NetSendToAllExcept: '%s' '%s'",target,s);
+       
        for (int j = 0; j < 32; j++)
        {
                if (me[j] != NULL)
@@ -2811,7 +2819,6 @@ bool process_module_umode(char umode, userrec* source, void* dest, bool adding)
        }
        else
        {
-               log(DEBUG,"*** BUG *** Non-module umode passed to process_module_umode!");
                if (faked)
                {
                        delete s2;
@@ -5342,29 +5349,35 @@ void handle_squit(char **parameters, int pcnt, userrec *user)
        // send out an squit across the mesh and then clear the server list (for local squit)
 }
 
-char islast(serverrec* s)
+char islast(const char* s)
 {
        char c = '`';
-       /*for (int j = 0; j < 255; j++)
+       for (int j = 0; j < 32; j++)
        {
-               if (servers[j] != NULL)
-               {
-                       c = '|';
-               }
-               if (servers[j] == s)
-               {
-                       c = '`';
+               if (me[j] != NULL)
+               {
+                       for (int k = 0; k < me[j]->connectors.size(); k++)
+                       {
+                               if (strcasecmp(me[j]->connectors[k].GetServerName().c_str(),s))
+                               {
+                                       c = '|';
+                               }
+                               if (!strcasecmp(me[j]->connectors[k].GetServerName().c_str(),s))
+                               {
+                                       c = '`';
+                               }
+                       }
                }
-       }*/
+       }
        return c;
 }
 
-long map_count(serverrec* s)
+long map_count(const char* s)
 {
        int c = 0;
        for (user_hash::const_iterator i = clientlist.begin(); i != clientlist.end(); i++)
        {
-               if ((i->second->fd) && (isnick(i->second->nick)) && (!strcasecmp(i->second->server,s->name))) c++;
+               if ((i->second->fd) && (isnick(i->second->nick)) && (!strcasecmp(i->second->server,s))) c++;
        }
        return c;
 }
@@ -5372,12 +5385,15 @@ long map_count(serverrec* s)
 void handle_links(char **parameters, int pcnt, userrec *user)
 {
        WriteServ(user->fd,"364 %s %s %s :0 %s",user->nick,ServerName,ServerName,ServerDesc);
-       for (int j = 0; j < 255; j++)
+       for (int j = 0; j < 32; j++)
        {
-       //      if (servers[j] != NULL)
-       //      {
-       //              WriteServ(user->fd,"364 %s %s %s :1 %s",user->nick,servers[j]->name,ServerName,servers[j]->description);
-       //      }
+               if (me[j] != NULL)
+               {
+                       for (int k = 0; k < me[j]->connectors.size(); k++)
+                       {
+                               WriteServ(user->fd,"364 %s %s %s :1 %s",user->nick,me[j]->connectors[k].GetServerName().c_str(),ServerName,me[j]->connectors[k].GetDescription().c_str());
+                       }
+               }
        }
        WriteServ(user->fd,"365 %s * :End of /LINKS list.",user->nick);
 }
@@ -5389,15 +5405,18 @@ void handle_map(char **parameters, int pcnt, userrec *user)
        while (strlen(line) < 50)
                strcat(line," ");
        WriteServ(user->fd,"%s%d (%.2f%%)",line,local_count(),(float)(((float)local_count()/(float)usercnt())*100));
-       for (int j = 0; j < 255; j++)
+       for (int j = 0; j < 32; j++)
        {
-       //      if (servers[j] != NULL)
-       //      {
-       //              snprintf(line,MAXBUF,"006 %s :%c-%s",user->nick,islast(servers[j]),servers[j]->name);
-       //              while (strlen(line) < 50)
-       //                      strcat(line," ");
-       //              WriteServ(user->fd,"%s%d (%.2f%%)",line,map_count(servers[j]),(float)(((float)map_count(servers[j])/(float)usercnt())*100));
-       //      }
+               if (me[j] != NULL)
+               {
+                       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());
+                               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)usercnt())*100));
+                       }
+               }
        }
        WriteServ(user->fd,"007 %s :End of /MAP",user->nick);
 }
@@ -5430,7 +5449,7 @@ void handle_oper(char **parameters, int pcnt, userrec *user)
                                {
                                        /* found this oper's opertype */
                                        ConfValue("type","host",j,Hostname,&config_f);
-                                       strncpy(user->dhost,Hostname,256);
+                                       ChangeDisplayedHost(user,Hostname);
                                }
                        }
                        if (!strchr(user->modes,'o'))
@@ -6322,7 +6341,7 @@ void handle_N(char token,char* params,serverrec* source,serverrec* reply, char*
        strncpy(clientlist[nick]->host, host,160);
        strncpy(clientlist[nick]->dhost, dhost,160);
        strncpy(clientlist[nick]->server, server,256);
-       strncpy(clientlist[nick]->ident, ident,10); // +1 char to compensate for '~'
+       strncpy(clientlist[nick]->ident, ident,10); // +1 char to compensate for tilde
        strncpy(clientlist[nick]->fullname, gecos,128);
        clientlist[nick]->signon = TS;
        clientlist[nick]->nping = 0; // this is ignored for a remote user anyway.
@@ -6369,13 +6388,25 @@ void handle_b(char token,char* params,serverrec* source,serverrec* reply, char*
 void handle_plus(char token,char* params,serverrec* source,serverrec* reply, char* udp_host)
 {
        // %s %s %d %d
+       // + test3.chatspike.net 7010 -2016508415
        char* servername = strtok(params," ");
        char* ipaddr = strtok(NULL," ");
        char* ipport = strtok(NULL," ");
        char* cookie = strtok(NULL," ");
+       log(DEBUG," ");
+       log(DEBUG," ");
+       log(DEBUG,"*** Connecting back to %s:%d",ipaddr,atoi(ipport));
        me[defaultRoute]->MeshCookie(ipaddr,atoi(ipport),atoi(cookie),servername);
+       log(DEBUG," ");
 }
 
+void handle_R(char token,char* params,serverrec* source,serverrec* reply, char* udp_host)
+{
+       char* server = strtok(params," ");
+       char* data = strtok(NULL,"\r\n");
+       log(DEBUG,"Forwarded packet '%s' to '%s'",data,server);
+       NetSendToOne(server,data);
+}
 
 void handle_J(char token,char* params,serverrec* source,serverrec* reply, char* udp_host)
 {
@@ -6429,9 +6460,71 @@ void handle_J(char token,char* params,serverrec* source,serverrec* reply, char*
        }
 }
 
+void NetSendMyRoutingTable()
+{
+       // send out a line saying what is reachable to us.
+       // E.g. if A is linked to B C and D, send out:
+       // $ A B C D
+       // if its only linked to B and D send out:
+       // $ A B D
+       // if it has no links, dont even send out the line at all.
+       char buffer[MAXBUF];
+       sprintf(buffer,"$ %s",ServerName);
+       bool sendit = false;
+       for (int i = 0; i < 32; i++)
+       {
+               if (me[i] != NULL)
+               {
+                       for (int j = 0; j < me[i]->connectors.size(); j++)
+                       {
+                               if (me[i]->connectors[j].GetState() != STATE_DISCONNECTED)
+                               {
+                                       strncat(buffer," ",MAXBUF);
+                                       strncat(buffer,me[i]->connectors[j].GetServerName().c_str(),MAXBUF);
+                                       sendit = true;
+                               }
+                       }
+               }
+       }
+       if (sendit)
+               NetSendToAll(buffer);
+}
+
+void handle_dollar(char token,char* params,serverrec* source,serverrec* reply, char* udp_host)
+{
+       log(DEBUG,"Storing routing table...");
+       char* sourceserver = strtok(params," ");
+       char* server = strtok(NULL," ");
+       for (int i = 0; i < 32; i++)
+       {
+               if (me[i] != NULL)
+               {
+                       for (int j = 0; j < me[i]->connectors.size(); j++)
+                       {
+                               if (!strcasecmp(me[i]->connectors[j].GetServerName().c_str(),sourceserver))
+                               {
+                                       me[i]->connectors[j].routes.clear();
+                                       log(DEBUG,"Found entry for source server.");
+                                       while (server)
+                                       {
+                                               // store each route
+                                               me[i]->connectors[j].routes.push_back(server);
+                                               log(DEBUG,"*** Stored route: %s -> %s -> %s",ServerName,sourceserver,server);
+                                               server = strtok(NULL," ");
+                                       }
+                                       return;
+                               }
+                       }
+               }
+       }
+       log(DEBUG,"Warning! routing table received from nonexistent server!");
+}
+
+
 void process_restricted_commands(char token,char* params,serverrec* source,serverrec* reply, char* udp_host,char* ipaddr,int port)
 {
        long authcookie = rand()*rand();
+       char buffer[MAXBUF];
 
        switch(token)
        {
@@ -6442,11 +6535,14 @@ void process_restricted_commands(char token,char* params,serverrec* source,serve
                        WriteOpers("Server %s is starting netburst.",udp_host);
                        // now broadcast this new servers address out to all servers that are linked to us,
                        // except the newcomer. They'll all attempt to connect back to it.
-                       char buffer[MAXBUF];
-                       snprintf(buffer,MAXBUF,"+ %s %s %d %d",udp_host,ipaddr,port,authcookie);
-                       NetSendToAllExcept(buffer,udp_host);
+
+                       // give the server its authcookie.
                        snprintf(buffer,MAXBUF,"~ %d",authcookie);
-                       NetSendToAllExcept(buffer,udp_host);
+                       source->SendPacket(buffer,udp_host);
+                       // tell all the other servers to use this authcookie to connect back again
+                       // got '+ test3.chatspike.net 7010 -2016508415' from test.chatspike.net
+                       snprintf(buffer,MAXBUF,"+ %s %s %d %d",udp_host,ipaddr,port,authcookie);
+                       NetSendToAllExcept(udp_host,buffer);
                break;
                // ~
                // Store authcookie
@@ -6454,12 +6550,22 @@ void process_restricted_commands(char token,char* params,serverrec* source,serve
                // without user or password, using it.
                case '~':
                        auth_cookies.push_back(atoi(params));
-                       log(DEBUG,"Stored auth cookie, will permit servers with auth-cookie %d",atoi(params));
+                       log(DEBUG,"*** Stored auth cookie, will permit servers with auth-cookie %d",atoi(params));
                break;
                // connect back to a server using an authcookie
                case '+':
                        handle_plus(token,params,source,reply,udp_host);
                break;
+               // routing table
+               case '$':
+                       handle_dollar(token,params,source,reply,udp_host);
+               break;
+               // R <server> <data>
+               // redirect token, send all of <data> along to the given 
+               // server as this server has been found to still have a route to it
+               case 'R':
+                       handle_R(token,params,source,reply,udp_host);
+               break;
                // ?
                // ping
                case '?':
@@ -6573,7 +6679,7 @@ void process_restricted_commands(char token,char* params,serverrec* source,serve
                        WriteOpers("Sending my netburst to %s",udp_host);
                        DoSync(source,udp_host);
                        WriteOpers("Send of netburst to %s completed",udp_host);
-               
+                       NetSendMyRoutingTable();
                break;
                // anything else
                default:
@@ -6603,9 +6709,31 @@ void handle_link_packet(char* udp_msg, char* udp_host, serverrec *serv)
                        if (auth_cookies[u] == atoi(cookie))
                        {
                                WriteOpers("Allowed cookie from %s, is now part of the mesh",servername);
+
+
+                               for (int j = 0; j < 32; j++)
+                               {
+                                       if (me[j] != NULL)
+                                       {
+                                               for (int k = 0; k < me[j]->connectors.size(); k++)
+                                               {
+                                                       if (!strcasecmp(me[j]->connectors[k].GetServerName().c_str(),udp_host))
+                                                       {
+                                                               me[j]->connectors[k].SetServerName(servername);
+                                                               NetSendMyRoutingTable();
+                                                               return;
+                                                       }
+                                               }
+                                       }
+                                       WriteOpers("\2WARNING!\2 %s sent us an authentication packet but we are not authenticating with this server right now! Possible intrusion attempt!",udp_host);
+                                       return;
+                               }
+
+
                                return;
                        }
                }
+               // bad cookie, bad bad! go sit in the corner!
                WriteOpers("Bad cookie from %s!",servername);
                return;
        }
@@ -6710,6 +6838,7 @@ void handle_link_packet(char* udp_msg, char* udp_host, serverrec *serv)
                                                                sprintf(buffer,"X 0");
                                                                serv->SendPacket(buffer,udp_host);
                                                                DoSync(me[j],udp_host);
+                                                               NetSendMyRoutingTable();
                                                                return;
                                                        }
                                                }
@@ -6954,7 +7083,7 @@ int InspIRCd(void)
 
                // *FIX* Instead of closing sockets in kill_link when they receive the ERROR :blah line, we should queue
                // them in a list, then reap the list every second or so.
-               if (reap_counter>5000)
+               if (reap_counter>2500)
                {
                        if (fd_reap.size() > 0)
                        {
@@ -6968,6 +7097,7 @@ int InspIRCd(void)
                        fd_reap.clear();
                        reap_counter=0;
                }
+               reap_counter++;
 
                fd_set serverfds;
                FD_ZERO(&serverfds);
@@ -6988,11 +7118,16 @@ int InspIRCd(void)
                        {
                                if (FD_ISSET (me[x]->fd, &serverfds))
                                {
-                                       char remotehost[MAXBUF];
+                                       char remotehost[MAXBUF],resolved[MAXBUF];
+                                       length = sizeof (client);
                                        incomingSockfd = accept (me[x]->fd, (sockaddr *) &client, &length);
-                                       strncpy (remotehost,(char *) inet_ntoa (client.sin_addr),MAXBUF);
+                                       strncpy(remotehost,(char *)inet_ntoa(client.sin_addr),MAXBUF);
+                                       if(CleanAndResolve(resolved, remotehost) != TRUE)
+                                       {
+                                               strncpy(resolved,remotehost,MAXBUF);
+                                       }
                                        // add to this connections ircd_connector vector
-                                       me[x]->AddIncoming(incomingSockfd,remotehost,ntohs(client.sin_port));
+                                       me[x]->AddIncoming(incomingSockfd,resolved,ntohs(client.sin_port));
                                }
                        }
                }
@@ -7008,14 +7143,14 @@ int InspIRCd(void)
                                        char udp_msg[MAXBUF];
                                        strncpy(udp_msg,msgs[ctr].c_str(),MAXBUF);
                                        if (strlen(udp_msg)<1)
-                                       {
+                                               {
                                                log(DEBUG,"Invalid string from %s [route%d]",udp_host,x);
                                                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'))
                                        {
-                                               NetSendToAllExcept(udp_msg,udp_host);
+                                               NetSendToAllExcept(udp_host,udp_msg);
                                        }
                                        FOREACH_MOD OnPacketReceive(udp_msg);
                                        handle_link_packet(udp_msg, udp_host, me[x]);
@@ -7203,7 +7338,6 @@ int InspIRCd(void)
                FD_SET (openSockfd[count], &selectFds);
        }
 
-       reap_counter++;
        tv.tv_usec = 1;
        selectResult = select(MAXSOCKS, &selectFds, NULL, NULL, &tv);
 
@@ -7215,6 +7349,7 @@ int InspIRCd(void)
                {
                        if (FD_ISSET (openSockfd[count], &selectFds))
                        {
+                               length = sizeof (client);
                                incomingSockfd = accept (openSockfd[count], (struct sockaddr *) &client, &length);
                              
                                address_cache::iterator iter = IP.find(client.sin_addr);