]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/users.cpp
kick_channel -> chanrec::KickUser(), server_kick_channel -> chanrec::ServerKickUser()
[user/henk/code/inspircd.git] / src / users.cpp
index ced542d3c8bcedcd5299040476bb51d1253ec0df..34c347cb934deac5aaa0a576a1383801fa20e7cd 100644 (file)
@@ -139,7 +139,7 @@ void userrec::StartDNSLookup()
        log(DEBUG,"Commencing reverse lookup");
        try
        {
-               res_reverse = new UserResolver(this, insp_ntoa(this->ip4), false);
+               res_reverse = new UserResolver(this, this->GetIPString(), false);
                MyServer->AddResolver(res_reverse);
        }
        catch (ModuleException& e)
@@ -148,8 +148,9 @@ void userrec::StartDNSLookup()
        }
 }
 
-UserResolver::UserResolver(userrec* user, std::string to_resolve, bool forward) : Resolver(to_resolve, forward), bound_user(user)
+UserResolver::UserResolver(userrec* user, std::string to_resolve, bool forward) : Resolver(to_resolve, forward ? DNS_QUERY_FORWARD : DNS_QUERY_REVERSE), bound_user(user)
 {
+       this->fwd = forward;
        this->bound_fd = user->fd;
 }
 
@@ -172,24 +173,28 @@ void UserResolver::OnLookupComplete(const std::string &result)
        else if ((this->fwd) && (fd_ref_table[this->bound_fd] == this->bound_user))
        {
                /* Both lookups completed */
-               if (insp_ntoa(this->bound_user->ip4) == result)
+               if (this->bound_user->GetIPString() == result)
                {
                        std::string hostname = this->bound_user->stored_host;
                        if (hostname.length() < 65)
                        {
-                               WriteServ(this->bound_fd, "NOTICE Auth :*** Found your hostname (%s)", this->bound_user->stored_host.c_str());
+                               /* Hostnames starting with : are not a good thing (tm) */
+                               if (*(hostname.c_str()) == ':')
+                                       hostname = "0" + hostname;
+
+                               WriteServ(this->bound_fd, "NOTICE Auth :*** Found your hostname (%s)", hostname.c_str());
                                this->bound_user->dns_done = true;
                                strlcpy(this->bound_user->dhost, hostname.c_str(),64);
                                strlcpy(this->bound_user->host, hostname.c_str(),64);
                        }
                        else
                        {
-                               WriteServ(this->bound_fd, "NOTICE Auth :*** Your hostname is longer than the maximum of 64 characters, using your IP address (%s) instead.", insp_ntoa(this->bound_user->ip4));
+                               WriteServ(this->bound_fd, "NOTICE Auth :*** Your hostname is longer than the maximum of 64 characters, using your IP address (%s) instead.", this->bound_user->GetIPString());
                        }
                }
                else
                {
-                       WriteServ(this->bound_fd, "NOTICE Auth :*** Your hostname does not match up with your IP address. Sorry, using your IP address (%s) instead.", insp_ntoa(this->bound_user->ip4));
+                       WriteServ(this->bound_fd, "NOTICE Auth :*** Your hostname does not match up with your IP address. Sorry, using your IP address (%s) instead.", this->bound_user->GetIPString());
                }
        }
 }
@@ -199,7 +204,7 @@ void UserResolver::OnError(ResolverError e, const std::string &errormessage)
        if (fd_ref_table[this->bound_fd] == this->bound_user)
        {
                /* Error message here */
-               WriteServ(this->bound_fd, "NOTICE Auth :*** Could not resolve your hostname, using your IP address (%s) instead.", insp_ntoa(this->bound_user->ip4));
+               WriteServ(this->bound_fd, "NOTICE Auth :*** Could not resolve your hostname, using your IP address (%s) instead.", this->bound_user->GetIPString());
                this->bound_user->dns_done = true;
        }
 }
@@ -262,11 +267,13 @@ userrec::userrec()
        server = (char*)FindServerNamePtr(Config->ServerName);
        reset_due = TIME;
        lines_in = fd = lastping = signon = idle_lastmsg = nping = registered = 0;
-       timeout = flood = port = bytes_in = bytes_out = cmds_in = cmds_out = 0;
+       timeout = flood = bytes_in = bytes_out = cmds_in = cmds_out = 0;
        haspassed = dns_done = false;
        recvq = "";
        sendq = "";
+       WriteError = "";
        res_forward = res_reverse = NULL;
+       ip = NULL;
        chans.clear();
        invites.clear();
        chans.resize(MAXCHANS);
@@ -288,6 +295,20 @@ userrec::~userrec()
                ucrec* x = (ucrec*)*n;
                delete x;
        }
+
+       if (ip)
+       {
+               if (this->GetProtocolFamily() == AF_INET)
+               {
+                       delete (sockaddr_in*)ip;
+               }
+#ifdef SUPPORT_IP6LINKS
+               else
+               {
+                       delete (sockaddr_in6*)ip;
+               }
+#endif
+       }
 }
 
 /* XXX - minor point, other *Host functions return a char *, this one creates it. Might be nice to be consistant? */
@@ -580,6 +601,7 @@ void userrec::FlushWriteBuf()
 
 void userrec::SetWriteError(const std::string &error)
 {
+       log(DEBUG,"SetWriteError: %s",error.c_str());
        // don't try to set the error twice, its already set take the first string.
        if (!this->WriteError.length())
        {
@@ -649,11 +671,11 @@ void kill_link(userrec *user,const char* r)
 
        if (IS_LOCAL(user))
        {
-               if (Config->GetIOHook(user->port))
+               if (Config->GetIOHook(user->GetPort()))
                {
                        try
                        {
-                               Config->GetIOHook(user->port)->OnRawSocketClose(user->fd);
+                               Config->GetIOHook(user->GetPort())->OnRawSocketClose(user->fd);
                        }
                        catch (ModuleException& modexcept)
                        {
@@ -765,11 +787,11 @@ void MaintainWhoWas(time_t TIME)
 }
 
 /* add a client connection to the sockets list */
-void AddClient(int socket, int port, bool iscached, insp_inaddr ip4)
+void AddClient(int socket, int port, bool iscached, insp_inaddr ip)
 {
        std::string tempnick = ConvToStr(socket) + "-unknown";
        user_hash::iterator iter = clientlist.find(tempnick);
-       const char *ipaddr = insp_ntoa(ip4);
+       const char *ipaddr = insp_ntoa(ip);
        userrec* _new;
        int j = 0;
 
@@ -796,11 +818,6 @@ void AddClient(int socket, int port, bool iscached, insp_inaddr ip4)
        _new->fd = socket;
        strlcpy(_new->nick,tempnick.c_str(),NICKMAX-1);
 
-       /* Smarter than your average bear^H^H^H^Hset of strlcpys. */
-       for (const char* temp = ipaddr; *temp && j < 64; temp++, j++)
-               _new->dhost[j] = _new->host[j] = *temp;
-       _new->dhost[j] = _new->host[j] = 0;
-
        _new->server = FindServerNamePtr(Config->ServerName);
        /* We don't need range checking here, we KNOW 'unknown\0' will fit into the ident field. */
        strcpy(_new->ident, "unknown");
@@ -808,9 +825,16 @@ void AddClient(int socket, int port, bool iscached, insp_inaddr ip4)
        _new->registered = REG_NONE;
        _new->signon = TIME + Config->dns_timeout;
        _new->lastping = 1;
-       _new->ip4 = ip4;
-       _new->port = port;
 
+       log(DEBUG,"Setting socket addresses");
+       _new->SetSockAddr(AF_FAMILY, ipaddr, port);
+       log(DEBUG,"Socket addresses set.");
+
+       /* Smarter than your average bear^H^H^H^Hset of strlcpys. */
+        for (const char* temp = _new->GetIPString(); *temp && j < 64; temp++, j++)
+               _new->dhost[j] = _new->host[j] = *temp;
+       _new->dhost[j] = _new->host[j] = 0;
+                       
        // set the registration timeout for this user
        unsigned long class_regtimeout = 90;
        int class_flood = 0;
@@ -820,7 +844,7 @@ void AddClient(int socket, int port, bool iscached, insp_inaddr ip4)
 
        for (ClassVector::iterator i = Config->Classes.begin(); i != Config->Classes.end(); i++)
        {
-               if ((i->type == CC_ALLOW) && (match(ipaddr,i->host.c_str())))
+               if ((i->type == CC_ALLOW) && (match(ipaddr,i->host.c_str(),true)))
                {
                        class_regtimeout = (unsigned long)i->registration_timeout;
                        class_flood = i->flood;
@@ -884,7 +908,11 @@ void AddClient(int socket, int port, bool iscached, insp_inaddr ip4)
 
        if (socket > -1)
        {
-               ServerInstance->SE->AddFd(socket,true,X_ESTAB_CLIENT);
+               if (!ServerInstance->SE->AddFd(socket,true,X_ESTAB_CLIENT))
+               {
+                       kill_link(_new, "Internal error handling connection");
+                       return;
+               }
        }
 
        WriteServ(_new->fd,"NOTICE Auth :*** Looking up your hostname...");
@@ -892,19 +920,16 @@ void AddClient(int socket, int port, bool iscached, insp_inaddr ip4)
 
 long FindMatchingGlobal(userrec* user)
 {
+       char u1[1024];
+       char u2[1024];
        long x = 0;
        for (user_hash::const_iterator a = clientlist.begin(); a != clientlist.end(); a++)
        {
-#ifdef IPV6
-               /* I dont think theres any faster way of matching two ipv6 addresses than memcmp
-                * Let me know if you think of one.
-                 */
-               if (!memcmp(a->second->ip4.s6_addr, user->ip4.s6_addr, sizeof(in6_addr)))
-                       x++;
-#else
-               if (a->second->ip4.s_addr == user->ip4.s_addr)
-                       x++;
-#endif
+               /* We have to match ip's as strings - we don't know what protocol
+                * a remote user may be using
+                */
+               if (!strcasecmp(a->second->GetIPString(u1), user->GetIPString(u2)))
+                               x++;
        }
        return x;
 }
@@ -917,10 +942,14 @@ long FindMatchingLocal(userrec* user)
                userrec* comp = *a;
 #ifdef IPV6
                /* I dont think theres any faster way of matching two ipv6 addresses than memcmp */
-               if (!memcmp(comp->ip4.s6_addr, user->ip4.s6_addr, sizeof(in6_addr)))
+               in6_addr* s1 = &(((sockaddr_in6*)comp->ip)->sin6_addr);
+               in6_addr* s2 = &(((sockaddr_in6*)user->ip)->sin6_addr);
+               if (!memcmp(s1->s6_addr, s2->s6_addr, sizeof(in6_addr)))
                        x++;
 #else
-               if (comp->ip4.s_addr == user->ip4.s_addr)
+               in_addr* s1 = &((sockaddr_in*)comp->ip)->sin_addr;
+               in_addr* s2 = &((sockaddr_in*)user->ip)->sin_addr;
+               if (s1->s_addr == s2->s_addr)
                        x++;
 #endif
        }
@@ -950,13 +979,13 @@ void FullConnectUser(userrec* user, CullList* Goners)
        if (FindMatchingLocal(user) > a.maxlocal)
        {
                Goners->AddItem(user,"No more connections allowed from your host via this connect class (local)");
-               WriteOpers("*** WARNING: maximum LOCAL connections (%ld) exceeded for IP %s",a.maxlocal,insp_ntoa(user->ip4));
+               WriteOpers("*** WARNING: maximum LOCAL connections (%ld) exceeded for IP %s",a.maxlocal,user->GetIPString());
                return;
        }
        else if (FindMatchingGlobal(user) > a.maxglobal)
        {
                Goners->AddItem(user,"No more connections allowed from your host via this connect class (global)");
-               WriteOpers("*** WARNING: maximum GLOBAL connections (%ld) exceeded for IP %s",a.maxglobal,insp_ntoa(user->ip4));
+               WriteOpers("*** WARNING: maximum GLOBAL connections (%ld) exceeded for IP %s",a.maxglobal,user->GetIPString());
                return;
        }
 
@@ -1024,7 +1053,7 @@ void FullConnectUser(userrec* user, CullList* Goners)
        FOREACH_MOD(I_OnUserConnect,OnUserConnect(user));
        FOREACH_MOD(I_OnGlobalConnect,OnGlobalConnect(user));
        user->registered = REG_ALL;
-       WriteOpers("*** Client connecting on port %lu: %s!%s@%s [%s]",(unsigned long)user->port,user->nick,user->ident,user->host,insp_ntoa(user->ip4));
+       WriteOpers("*** Client connecting on port %d: %s!%s@%s [%s]",user->GetPort(),user->nick,user->ident,user->host,user->GetIPString());
 }
 
 /** ReHashNick()
@@ -1098,3 +1127,156 @@ void force_nickchange(userrec* user,const char* newnick)
                }
        }
 }
+
+void userrec::SetSockAddr(int protocol_family, const char* ip, int port)
+{
+       switch (protocol_family)
+       {
+#ifdef SUPPORT_IP6LINKS
+               case AF_INET6:
+               {
+                       log(DEBUG,"Set inet6 protocol address");
+                       sockaddr_in6* sin = new sockaddr_in6;
+                       sin->sin6_family = AF_INET6;
+                       sin->sin6_port = port;
+                       inet_pton(AF_INET6, ip, &sin->sin6_addr);
+                       this->ip = (sockaddr*)sin;
+               }
+               break;
+#endif
+               case AF_INET:
+               {
+                       log(DEBUG,"Set inet4 protocol address");
+                       sockaddr_in* sin = new sockaddr_in;
+                       sin->sin_family = AF_INET;
+                       sin->sin_port = port;
+                       inet_pton(AF_INET, ip, &sin->sin_addr);
+                       this->ip = (sockaddr*)sin;
+               }
+               break;
+               default:
+                       log(DEBUG,"Ut oh, I dont know protocol %d to be set on '%s'!", protocol_family, this->nick);
+               break;
+       }
+}
+
+int userrec::GetPort()
+{
+       if (this->ip == NULL)
+               return 0;
+
+       switch (this->GetProtocolFamily())
+       {
+#ifdef SUPPORT_IP6LINKS
+               case AF_INET6:
+               {
+                       sockaddr_in6* sin = (sockaddr_in6*)this->ip;
+                       return sin->sin6_port;
+               }
+               break;
+#endif
+               case AF_INET:
+               {
+                       sockaddr_in* sin = (sockaddr_in*)this->ip;
+                       return sin->sin_port;
+               }
+               break;
+               default:
+                       log(DEBUG,"Ut oh, '%s' has an unknown protocol family!",this->nick);
+               break;
+       }
+       return 0;
+}
+
+int userrec::GetProtocolFamily()
+{
+       if (this->ip == NULL)
+               return 0;
+
+       sockaddr_in* sin = (sockaddr_in*)this->ip;
+       return sin->sin_family;
+}
+
+const char* userrec::GetIPString()
+{
+       static char buf[1024];
+       static char temp[1024];
+
+       if (this->ip == NULL)
+               return "";
+
+       switch (this->GetProtocolFamily())
+       {
+#ifdef SUPPORT_IP6LINKS
+               case AF_INET6:
+               {
+                       sockaddr_in6* sin = (sockaddr_in6*)this->ip;
+                       inet_ntop(sin->sin6_family, &sin->sin6_addr, buf, sizeof(buf));
+                       /* IP addresses starting with a : on irc are a Bad Thing (tm) */
+                       if (*buf == ':')
+                       {
+                               strlcpy(&temp[1], buf, sizeof(temp));
+                               *temp = '0';
+                               return temp;
+                       }
+                       return buf;
+               }
+               break;
+#endif
+               case AF_INET:
+               {
+                       sockaddr_in* sin = (sockaddr_in*)this->ip;
+                       inet_ntop(sin->sin_family, &sin->sin_addr, buf, sizeof(buf));
+                       return buf;
+               }
+               break;
+               default:
+                       log(DEBUG,"Ut oh, '%s' has an unknown protocol family!",this->nick);
+               break;
+       }
+       return "";
+}
+
+const char* userrec::GetIPString(char* buf)
+{
+       static char temp[1024];
+
+       if (this->ip == NULL)
+       {
+               *buf = 0;
+               return buf;
+       }
+
+       switch (this->GetProtocolFamily())
+       {
+#ifdef SUPPORT_IP6LINKS
+               case AF_INET6:
+               {
+                       sockaddr_in6* sin = (sockaddr_in6*)this->ip;
+                       inet_ntop(sin->sin6_family, &sin->sin6_addr, buf, sizeof(buf));
+                       /* IP addresses starting with a : on irc are a Bad Thing (tm) */
+                       if (*buf == ':')
+                       {
+                               strlcpy(&temp[1], buf, sizeof(temp));
+                               *temp = '0';
+                               strlcpy(buf, temp, sizeof(temp));
+                       }
+                       return buf;
+               }
+               break;
+#endif
+               case AF_INET:
+               {
+                       sockaddr_in* sin = (sockaddr_in*)this->ip;
+                       inet_ntop(sin->sin_family, &sin->sin_addr, buf, sizeof(buf));
+                       return buf;
+               }
+               break;
+
+               default:
+                       log(DEBUG,"Ut oh, '%s' has an unknown protocol family!",this->nick);
+               break;
+       }
+       return "";
+}
+