return true;
}
-bool DoType(ServerConfig* conf, const char* tag, char** entries, void** values, int* types)
+bool DoType(ServerConfig* conf, const char* tag, char** entries, ValueList &values, int* types)
{
- char* TypeName = (char*)values[0];
- char* Classes = (char*)values[1];
+ const char* TypeName = values[0].GetString();
+ const char* Classes = values[1].GetString();
conf->opertypes[TypeName] = strdup(Classes);
conf->GetInstance()->Log(DEBUG,"Read oper TYPE '%s' with classes '%s'",TypeName,Classes);
return true;
}
-bool DoClass(ServerConfig* conf, const char* tag, char** entries, void** values, int* types)
+bool DoClass(ServerConfig* conf, const char* tag, char** entries, ValueList &values, int* types)
{
- char* ClassName = (char*)values[0];
- char* CommandList = (char*)values[1];
+ const char* ClassName = values[0].GetString();
+ const char* CommandList = values[1].GetString();
conf->operclass[ClassName] = strdup(CommandList);
conf->GetInstance()->Log(DEBUG,"Read oper CLASS '%s' with commands '%s'",ClassName,CommandList);
try
{
ServerInstance->Log(DEBUG,"Passing instance: %08x",this->ServerInstance);
- res_reverse = new UserResolver(this->ServerInstance, this, this->GetIPString(), false);
+ res_reverse = new UserResolver(this->ServerInstance, this, this->GetIPString(), DNS_QUERY_REVERSE);
this->ServerInstance->AddResolver(res_reverse);
}
catch (ModuleException& e)
}
}
-UserResolver::UserResolver(InspIRCd* Instance, userrec* user, std::string to_resolve, bool forward) :
- Resolver(Instance, to_resolve, forward ? DNS_QUERY_FORWARD : DNS_QUERY_REVERSE), bound_user(user)
+UserResolver::UserResolver(InspIRCd* Instance, userrec* user, std::string to_resolve, QueryType qt) :
+ Resolver(Instance, to_resolve, qt), bound_user(user)
{
- this->fwd = forward;
+ this->fwd = (qt == DNS_QUERY_A || qt == DNS_QUERY_AAAA);
this->bound_fd = user->GetFd();
}
/* Check we didnt time out */
if (this->bound_user->registered != REG_ALL)
{
- bound_user->res_forward = new UserResolver(this->ServerInstance, this->bound_user, result, true);
+#ifdef IPV6
+ const char *ip = this->bound_user->GetIPString();
+ bound_user->res_forward = new UserResolver(this->ServerInstance, this->bound_user, result, (strstr(ip,"0::ffff:") == ip ? DNS_QUERY_A : DNS_QUERY_AAAA));
+#else
+ bound_user->res_forward = new UserResolver(this->ServerInstance, this->bound_user, result, DNS_QUERY_A);
+#endif
this->ServerInstance->AddResolver(bound_user->res_forward);
}
}
else if ((this->fwd) && (ServerInstance->SE->GetRef(this->bound_fd) == this->bound_user))
{
/* Both lookups completed */
- if (this->bound_user->GetIPString() == result)
+ std::string result2 = "0::ffff:";
+ result2.append(result);
+ if (this->bound_user->GetIPString() == result || this->bound_user->GetIPString() == result2)
{
std::string hostname = this->bound_user->stored_host;
if (hostname.length() < 65)
*password = *nick = *ident = *host = *dhost = *fullname = *awaymsg = *oper = 0;
server = (char*)Instance->FindServerNamePtr(Instance->Config->ServerName);
reset_due = ServerInstance->Time();
+ age = ServerInstance->Time(true);
lines_in = lastping = signon = idle_lastmsg = nping = registered = 0;
ChannelCount = timeout = flood = bytes_in = bytes_out = cmds_in = cmds_out = 0;
haspassed = dns_done = false;
}
}
-/* XXX - minor point, other *Host functions return a char *, this one creates it. Might be nice to be consistant? */
-void userrec::MakeHost(char* nhost)
+char* userrec::MakeHost()
{
+ static char nhost[MAXBUF];
/* This is much faster than snprintf */
char* t = nhost;
for(char* n = ident; *n; n++)
for(char* n = host; *n; n++)
*t++ = *n;
*t = 0;
+ return nhost;
+}
+
+char* userrec::MakeHostIP()
+{
+ static char ihost[MAXBUF];
+ /* This is much faster than snprintf */
+ char* t = ihost;
+ for(char* n = ident; *n; n++)
+ *t++ = *n;
+ *t++ = '@';
+ for(const char* n = this->GetIPString(); *n; n++)
+ *t++ = *n;
+ *t = 0;
+ return ihost;
}
void userrec::CloseSocket()
free(gecos);
}
- /* every hour, run this function which removes all entries over 3 days */
+ /* every hour, run this function which removes all entries older than Config->WhoWasMaxKeep */
void MaintainWhoWas(InspIRCd* ServerInstance, time_t t)
{
for (whowas_users::iterator iter = ServerInstance->whowas.begin(); iter != ServerInstance->whowas.end(); iter++)
whowas_set* n = (whowas_set*)iter->second;
if (n->size())
{
- while ((n->begin() != n->end()) && ((*n->begin())->signon < t - 259200)) // 3 days
+ while ((n->begin() != n->end()) && ((*n->begin())->signon < t - ServerInstance->Config->WhoWasMaxKeep))
{
WhoWasGroup *a = *(n->begin());
DELETE(a);
}
}
}
+ /* on rehash, refactor maps according to new conf values */
+ void PruneWhoWas(InspIRCd* ServerInstance, time_t t)
+ {
+ /* config values */
+ int groupsize = ServerInstance->Config->WhoWasGroupSize;
+ int maxgroups = ServerInstance->Config->WhoWasMaxGroups;
+ int maxkeep = ServerInstance->Config->WhoWasMaxKeep;
+
+ int groupcount = ServerInstance->whowas.size();
+ /* iterate whowas_fifo oldest first */
+ whowas_users_fifo::iterator iter, safeiter;
+ for (iter = ServerInstance->whowas_fifo.begin(); iter != ServerInstance->whowas_fifo.end(); iter++)
+ {
+ /** prune all groups that has expired due to new maxkeep time and
+ * also any group number higher than new maxgroups. The oldest are
+ * removed first due to iteration over whowas_fifo
+ */
+ if (groupcount > maxgroups || iter->first < t - maxkeep)
+ {
+ whowas_set* n = (whowas_set*)ServerInstance->whowas.find(iter->second)->second;
+ if (n->size())
+ {
+ while (n->begin() != n->end())
+ {
+ WhoWasGroup *a = *(n->begin());
+ DELETE(a);
+ n->erase(n->begin());
+ }
+ }
+ ServerInstance->whowas.erase(iter->second);
+ /* use a safe iter copy for erase and set the orig iter old valid ref by decrementing it */
+ safeiter = iter;
+ --iter;
+ ServerInstance->whowas_fifo.erase(safeiter);
+ }
+ else {
+ /* also trim individual groupsizes in case groupsize should have been lowered */
+ whowas_set* n = (whowas_set*)ServerInstance->whowas.find(iter->second)->second;
+ if (n->size())
+ {
+ int nickcount = n->size();
+ while (n->begin() != n->end() && nickcount > groupsize)
+ {
+ WhoWasGroup *a = *(n->begin());
+ DELETE(a);
+ n->erase(n->begin());
+ nickcount--;
+ }
+ }
+ }
+ groupcount--;
+ }
+ }
};
};
/* adds or updates an entry in the whowas list */
void userrec::AddToWhoWas()
{
+ /* if whowas disabled */
+ if (ServerInstance->Config->WhoWasGroupSize == 0 || ServerInstance->Config->WhoWasMaxGroups == 0)
+ {
+ return;
+ }
+
irc::whowas::whowas_users::iterator iter = ServerInstance->whowas.find(this->nick);
ServerInstance->Log(DEBUG,"Add to whowas lists");
irc::whowas::WhoWasGroup *a = new irc::whowas::WhoWasGroup(this);
n->push_back(a);
ServerInstance->whowas[this->nick] = n;
+ ServerInstance->whowas_fifo[ServerInstance->Time()] = this->nick;
+ if ((int)(ServerInstance->whowas.size()) > ServerInstance->Config->WhoWasMaxGroups)
+ {
+ ServerInstance->Log(DEBUG,"Maxgroups of %d reached deleting oldest group '%s'",ServerInstance->Config->WhoWasMaxGroups, ServerInstance->whowas_fifo.begin()->second.c_str());
+ ServerInstance->whowas.erase(ServerInstance->whowas_fifo.begin()->second);
+ ServerInstance->whowas_fifo.erase(ServerInstance->whowas_fifo.begin());
+ }
}
else
{
ServerInstance->Log(DEBUG,"Using existing whowas group for %s",this->nick);
- if (group->size() > 10)
+ if ((int)(group->size()) >= ServerInstance->Config->WhoWasGroupSize)
{
- ServerInstance->Log(DEBUG,"Trimming existing group to ten entries for %s",this->nick);
+ ServerInstance->Log(DEBUG,"Trimming existing group '%s' to %d entries",this->nick, ServerInstance->Config->WhoWasGroupSize);
irc::whowas::WhoWasGroup *a = (irc::whowas::WhoWasGroup*)*(group->begin());
DELETE(a);
group->pop_front();
if (this->ServerInstance->Config->CycleHosts)
this->WriteCommonExcept("%s","QUIT :Changing hosts");
- strlcpy(this->dhost,host,63);
+ /* Fix by Om: userrec::dhost is 65 long, this was truncating some long hosts */
+ strlcpy(this->dhost,host,64);
if (this->ServerInstance->Config->CycleHosts)
{
if (line.length() + namelen + length - start > 510)
{
- this->Write(line);
+ ServerInstance->SendWhoisLine(this, dest, 319, "%s", line.c_str());
line = prefix.str();
}
this->FlushWriteBuf();
break;
case EVENT_ERROR:
- this->SetWriteError(strerror(errornum));
+ this->SetWriteError(errornum ? strerror(errornum) : "EOF from client");
break;
}
}
ServerInstance->Log(DEBUG,"Exception in userrec::HandleEvent intercepted");
}
}
-