#include "socketengine.h"
#include "wildcard.h"
#include "xline.h"
-#include "cull_list.h"
#include "commands/cmd_whowas.h"
static unsigned long already_sent[MAX_DESCRIPTORS] = {0};
delete[] n->second;
}
}
-
+
conf->opertypes.clear();
return true;
}
delete[] n->second;
}
}
-
+
conf->operclass.clear();
return true;
}
{
const char* TypeName = values[0].GetString();
const char* Classes = values[1].GetString();
-
+
conf->opertypes[TypeName] = strdup(Classes);
return true;
}
{
const char* ClassName = values[0].GetString();
const char* CommandList = values[1].GetString();
-
+
conf->operclass[ClassName] = strdup(CommandList);
return true;
}
try
{
bool cached;
- res_reverse = new UserResolver(this->ServerInstance, this, this->GetIPString(), DNS_QUERY_REVERSE, cached);
+ res_reverse = new UserResolver(this->ServerInstance, this, this->GetIPString(), this->GetProtocolFamily() == AF_INET ? DNS_QUERY_PTR4 : DNS_QUERY_PTR6, cached);
this->ServerInstance->AddResolver(res_reverse, cached);
}
catch (CoreException& e)
{
bool cached;
#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), cached);
+ if (this->bound_user->GetProtocolFamily() == AF_INET6)
+ {
+ /* IPV6 forward lookup (with possibility of 4in6) */
+ 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), cached);
+ }
+ else
+ {
+ /* IPV4 lookup (mixed protocol mode) */
+ bound_user->res_forward = new UserResolver(this->ServerInstance, this->bound_user, result, DNS_QUERY_A, cached);
+ }
#else
+ /* IPV4 lookup (ipv4 only mode) */
bound_user->res_forward = new UserResolver(this->ServerInstance, this->bound_user, result, DNS_QUERY_A, cached);
#endif
this->ServerInstance->AddResolver(bound_user->res_forward, cached);
ServerInstance->local_clones.erase(x);
}
}
-
+
clonemap::iterator y = ServerInstance->global_clones.find(this->GetIPString());
if (y != ServerInstance->global_clones.end())
{
shutdown(this->fd,2);
close(this->fd);
}
-
+
char* userrec::GetFullHost()
{
if (this->cached_fullhost)
char* mycmd;
char* savept;
char* savept2;
-
+
/*
* users on remote servers can completely bypass all permissions based checks.
* This prevents desyncs when one server has different type/class tags to another.
*/
if (!IS_LOCAL(this))
return true;
-
+
// are they even an oper at all?
if (*this->oper)
{
try
{
std::string::size_type i = a.rfind('\r');
-
+
while (i != std::string::npos)
{
a.erase(i, 1);
if (a.length())
recvq.append(a);
-
+
if (recvq.length() > (unsigned)this->recvqmax)
{
this->SetWriteError("RecvQ exceeded");
ServerInstance->WriteOpers("*** User %s RecvQ of %d exceeds connect class maximum of %d",this->nick,recvq.length(),this->recvqmax);
return false;
}
-
+
return true;
}
{
if (!recvq.length())
return "";
-
+
/* Strip any leading \r or \n off the string.
* Usually there are only one or two of these,
* so its is computationally cheap to do.
*/
while ((*recvq.begin() == '\r') || (*recvq.begin() == '\n'))
recvq.erase(recvq.begin());
-
+
for (std::string::iterator x = recvq.begin(); x != recvq.end(); x++)
{
/* Find the first complete line, return it as the
{
if (*this->GetWriteError())
return;
-
+
if (sendq.length() + data.length() > (unsigned)this->sendqmax)
{
/*
return;
}
- try
+ try
{
if (data.length() > 512)
sendq.append(data.substr(0,510)).append("\r\n");
void userrec::QuitUser(InspIRCd* Instance, userrec *user, const std::string &quitreason)
{
- user_hash::iterator iter = Instance->clientlist->find(user->nick);
- std::string reason = quitreason;
-
- if (reason.length() > MAXQUIT - 1)
- reason.resize(MAXQUIT - 1);
-
- if (user->registered != REG_ALL)
- if (Instance->unregistered_count)
- Instance->unregistered_count--;
-
- if (IS_LOCAL(user))
- {
- user->Write("ERROR :Closing link (%s@%s) [%s]",user->ident,user->host,reason.c_str());
- if ((!user->sendq.empty()) && (!(*user->GetWriteError())))
- user->FlushWriteBuf();
- }
-
- if (user->registered == REG_ALL)
- {
- user->PurgeEmptyChannels();
- user->WriteCommonExcept("QUIT :%s",reason.c_str());
- FOREACH_MOD_I(Instance,I_OnUserQuit,OnUserQuit(user,reason));
- }
-
- FOREACH_MOD_I(Instance,I_OnUserDisconnect,OnUserDisconnect(user));
-
- if (IS_LOCAL(user))
- {
- if (Instance->Config->GetIOHook(user->GetPort()))
- {
- try
- {
- Instance->Config->GetIOHook(user->GetPort())->OnRawSocketClose(user->fd);
- }
- catch (CoreException& modexcept)
- {
- Instance->Log(DEBUG, "%s threw an exception: %s", modexcept.GetSource(), modexcept.GetReason());
- }
- }
-
- Instance->SE->DelFd(user);
- user->CloseSocket();
- }
-
- /*
- * this must come before the ServerInstance->SNO->WriteToSnoMaskso that it doesnt try to fill their buffer with anything
- * if they were an oper with +sn +qQ.
- */
- if (user->registered == REG_ALL)
- {
- if (IS_LOCAL(user))
- Instance->SNO->WriteToSnoMask('q',"Client exiting: %s!%s@%s [%s]",user->nick,user->ident,user->host,reason.c_str());
- else
- Instance->SNO->WriteToSnoMask('Q',"Client exiting on server %s: %s!%s@%s [%s]",user->server,user->nick,user->ident,user->host,reason.c_str());
- user->AddToWhoWas();
- }
-
- if (iter != Instance->clientlist->end())
- {
- if (IS_LOCAL(user))
- {
- std::vector<userrec*>::iterator x = find(Instance->local_users.begin(),Instance->local_users.end(),user);
- if (x != Instance->local_users.end())
- Instance->local_users.erase(x);
- }
- Instance->clientlist->erase(iter);
- DELETE(user);
- }
+ Instance->GlobalCulls.AddItem(user, quitreason.c_str());
}
}
/* add a client connection to the sockets list */
-void userrec::AddClient(InspIRCd* Instance, int socket, int port, bool iscached, insp_inaddr ip)
+void userrec::AddClient(InspIRCd* Instance, int socket, int port, bool iscached, int socketfamily, sockaddr* ip)
{
std::string tempnick = ConvToStr(socket) + "-unknown";
user_hash::iterator iter = Instance->clientlist->find(tempnick);
- const char *ipaddr = insp_ntoa(ip);
+ char ipaddr[MAXBUF];
+#ifdef IPV6
+ if (socketfamily == AF_INET6)
+ inet_ntop(AF_INET6, &((const sockaddr_in6*)ip)->sin6_addr, ipaddr, sizeof(ipaddr));
+ else
+ inet_ntop(AF_INET, &((const sockaddr_in*)ip)->sin_addr, ipaddr, sizeof(ipaddr));
+#else
+ inet_ntop(AF_INET, &((const sockaddr_in*)ip)->sin_addr, ipaddr, sizeof(ipaddr));
+#endif
userrec* New;
int j = 0;
New->signon = Instance->Time() + Instance->Config->dns_timeout;
New->lastping = 1;
- New->SetSockAddr(AF_FAMILY, ipaddr, port);
+ New->SetSockAddr(socketfamily, ipaddr, port);
/* Smarter than your average bear^H^H^H^Hset of strlcpys. */
for (const char* temp = New->GetIPString(); *temp && j < 64; temp++, j++)
return 0;
}
-void userrec::FullConnect(CullList* Goners)
+void userrec::FullConnect()
{
ServerInstance->stats->statsConnects++;
this->idle_lastmsg = ServerInstance->Time();
if ((!a) || (a->GetType() == CC_DENY))
{
- Goners->AddItem(this,"Unauthorised connection");
+ ServerInstance->GlobalCulls.AddItem(this,"Unauthorised connection");
return;
}
if ((!a->GetPass().empty()) && (!this->haspassed))
{
- Goners->AddItem(this,"Invalid password");
+ ServerInstance->GlobalCulls.AddItem(this,"Invalid password");
return;
}
-
+
if (this->LocalCloneCount() > a->GetMaxLocal())
{
- Goners->AddItem(this, "No more connections allowed from your host via this connect class (local)");
+ ServerInstance->GlobalCulls.AddItem(this, "No more connections allowed from your host via this connect class (local)");
ServerInstance->WriteOpers("*** WARNING: maximum LOCAL connections (%ld) exceeded for IP %s", a->GetMaxLocal(), this->GetIPString());
return;
}
else if (this->GlobalCloneCount() > a->GetMaxGlobal())
{
- Goners->AddItem(this, "No more connections allowed from your host via this connect class (global)");
+ ServerInstance->GlobalCulls.AddItem(this, "No more connections allowed from your host via this connect class (global)");
ServerInstance->WriteOpers("*** WARNING: maximum GLOBAL connections (%ld) exceeded for IP %s",a->GetMaxGlobal(), this->GetIPString());
return;
}
if (!this->exempt)
{
GLine* r = ServerInstance->XLines->matches_gline(this);
-
+
if (r)
{
char reason[MAXBUF];
snprintf(reason,MAXBUF,"G-Lined: %s",r->reason);
- Goners->AddItem(this, reason);
+ ServerInstance->GlobalCulls.AddItem(this, reason);
return;
}
-
+
KLine* n = ServerInstance->XLines->matches_kline(this);
-
+
if (n)
{
char reason[MAXBUF];
snprintf(reason,MAXBUF,"K-Lined: %s",n->reason);
- Goners->AddItem(this, reason);
+ ServerInstance->GlobalCulls.AddItem(this, reason);
return;
}
int MOD_RESULT = 0;
this->InvalidateCache();
-
+
FOREACH_RESULT(I_OnUserPreNick,OnUserPreNick(this, newnick));
if (MOD_RESULT)
ServerInstance->stats->statsCollisions++;
return false;
}
-
+
if (ServerInstance->XLines->matches_qline(newnick))
{
ServerInstance->stats->statsCollisions++;
case AF_INET6:
{
static char temp[1024];
-
+
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) */
case AF_INET6:
{
static char temp[1024];
-
+
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) */
try
{
- ServerInstance->Log(DEBUG,"<- %s", text.c_str());
+ /* ServerInstance->Log(DEBUG,"<- %s", text.c_str());
+ * WARNING: The above debug line is VERY loud, do NOT
+ * enable it till we have a good way of filtering it
+ * out of the logs (e.g. 1.2 would be good).
+ */
text.append("\r\n");
}
catch (...)
char tb[MAXBUF];
snprintf(tb,MAXBUF,":%s %s",user->GetFullHost(),text.c_str());
-
+
this->Write(std::string(tb));
}
{
bool sent_to_at_least_one = false;
char tb[MAXBUF];
-
+
if (this->registered != REG_ALL)
return;
-
+
uniq_id++;
/* We dont want to be doing this n times, just once */
snprintf(tb,MAXBUF,":%s %s",this->GetFullHost(),text.c_str());
std::string out = tb;
-
+
for (UCListIter v = this->chans.begin(); v != this->chans.end(); v++)
{
CUList* ulist = v->first->GetUsers();
}
}
}
-
+
/*
* if the user was not in any channels, no users will receive the text. Make sure the user
* receives their OWN message for WriteCommon
}
void userrec::WriteWallOps(const char* text, ...)
-{
+{
char textbuffer[MAXBUF];
va_list argsPtr;
va_start(argsPtr, text);
vsnprintf(textbuffer, MAXBUF, text, argsPtr);
- va_end(argsPtr);
-
+ va_end(argsPtr);
+
this->WriteWallOps(std::string(textbuffer));
-}
+}
/* return 0 or 1 depending if users u and u2 share one or more common channels
* (used by QUIT, NICK etc which arent channel specific notices)
prefix << this->nick << " " << dest->nick << " :";
line = prefix.str();
int namelen = strlen(ServerInstance->Config->ServerName) + 6;
-
+
for (start = 0; (pos = cl.find(' ', start)) != std::string::npos; start = pos+1)
{
length = (pos == std::string::npos) ? cl.length() : pos;
-
+
if (line.length() + namelen + length - start > 510)
{
ServerInstance->SendWhoisLine(this, dest, 319, "%s", line.c_str());
line = prefix.str();
}
-
+
if(pos == std::string::npos)
{
line.append(cl.substr(start, length - start));
line.append(cl.substr(start, length - start + 1));
}
}
-
+
if (line.length())
{
ServerInstance->SendWhoisLine(this, dest, 319, "%s", line.c_str());