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)
}
}
-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;
}
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());
}
}
}
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;
}
}
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);
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? */
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())
{
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)
{
}
/* 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;
_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");
_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;
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;
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...");
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;
}
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
}
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;
}
WriteServ(user->fd,"001 %s :Welcome to the %s IRC Network %s!%s@%s",user->nick,Config->Network,user->nick,user->ident,user->host);
WriteServ(user->fd,"002 %s :Your host is %s, running version %s",user->nick,Config->ServerName,VERSION);
WriteServ(user->fd,"003 %s :This server was created %s %s",user->nick,__TIME__,__DATE__);
- WriteServ(user->fd,"004 %s %s %s iowghrasxRVSCWBG lvhopsmntikrcaqbegIOLQRSKVHGCNT vhobeIaqglk",user->nick,Config->ServerName,VERSION);
+ WriteServ(user->fd,"004 %s %s %s %s %s %s",user->nick,Config->ServerName,VERSION,ServerInstance->ModeGrok->UserModeList().c_str(),ServerInstance->ModeGrok->ChannelModeList().c_str(),+ServerInstance->ModeGrok->ParaModeList().c_str());
// anfl @ #ratbox, efnet reminded me that according to the RFC this cant contain more than 13 tokens per line...
// so i'd better split it :)
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()
}
}
}
+
+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 "";
+}
+