int CNetServer::BanRemove(NETADDR Addr) { int IpHash = (Addr.ip[0]+Addr.ip[1]+Addr.ip[2]+Addr.ip[3]+Addr.ip[4]+Addr.ip[5]+Addr.ip[6]+Addr.ip[7]+ Addr.ip[8]+Addr.ip[9]+Addr.ip[10]+Addr.ip[11]+Addr.ip[12]+Addr.ip[13]+Addr.ip[14]+Addr.ip[15])&0xff; CBan *pBan = m_aBans[IpHash]; MACRO_LIST_FIND(pBan, m_pHashNext, net_addr_comp(&pBan->m_Info.m_Addr, &Addr) == 0); if(pBan) { BanRemoveByObject(pBan); return 0; } return -1; }
int CNetServer::Update() { int Now = time_timestamp(); for(int i = 0; i < MaxClients(); i++) { m_aSlots[i].m_Connection.Update(); if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_ERROR) Drop(i, m_aSlots[i].m_Connection.ErrorString()); } // remove expired bans while(m_BanPool_FirstUsed && m_BanPool_FirstUsed->m_Info.m_Expires > -1 && m_BanPool_FirstUsed->m_Info.m_Expires < Now) { CBan *pBan = m_BanPool_FirstUsed; BanRemoveByObject(pBan); } return 0; }
int CNetServer::BanAdd(NETADDR Addr, int Seconds, const char *pReason) { int IpHash = (Addr.ip[0]+Addr.ip[1]+Addr.ip[2]+Addr.ip[3]+Addr.ip[4]+Addr.ip[5]+Addr.ip[6]+Addr.ip[7]+ Addr.ip[8]+Addr.ip[9]+Addr.ip[10]+Addr.ip[11]+Addr.ip[12]+Addr.ip[13]+Addr.ip[14]+Addr.ip[15])&0xff; int Stamp = -1; CBan *pBan; // remove the port Addr.port = 0; if(Seconds) Stamp = time_timestamp() + Seconds; // search to remove it if it already exists pBan = m_aBans[IpHash]; MACRO_LIST_FIND(pBan, m_pHashNext, net_addr_comp(&pBan->m_Info.m_Addr, &Addr) == 0); if(pBan) BanRemoveByObject(pBan); if(!m_BanPool_FirstFree) return -1; // fetch and clear the new ban pBan = m_BanPool_FirstFree; MACRO_LIST_UNLINK(pBan, m_BanPool_FirstFree, m_pPrev, m_pNext); // setup the ban info pBan->m_Info.m_Expires = Stamp; pBan->m_Info.m_Addr = Addr; str_copy(pBan->m_Info.m_Reason, pReason, sizeof(pBan->m_Info.m_Reason)); // add it to the ban hash MACRO_LIST_LINK_FIRST(pBan, m_aBans[IpHash], m_pHashPrev, m_pHashNext); // insert it into the used list { if(m_BanPool_FirstUsed) { CBan *pInsertAfter = m_BanPool_FirstUsed; MACRO_LIST_FIND(pInsertAfter, m_pNext, Stamp < pInsertAfter->m_Info.m_Expires); if(pInsertAfter && Stamp != -1) pInsertAfter = pInsertAfter->m_pPrev; else { // add to last if (m_BanPool_FirstUsed->m_Info.m_Expires == -1) pInsertAfter = 0; else { pInsertAfter = m_BanPool_FirstUsed; while(pInsertAfter->m_pNext && pInsertAfter->m_pNext->m_Info.m_Expires != -1) pInsertAfter = pInsertAfter->m_pNext; } } if(pInsertAfter) { MACRO_LIST_LINK_AFTER(pBan, pInsertAfter, m_pPrev, m_pNext); } else { MACRO_LIST_LINK_FIRST(pBan, m_BanPool_FirstUsed, m_pPrev, m_pNext); } } else { MACRO_LIST_LINK_FIRST(pBan, m_BanPool_FirstUsed, m_pPrev, m_pNext); } } // drop banned clients { char Buf[128]; NETADDR BanAddr; if(Stamp > -1) { int Mins = (Seconds + 59) / 60; if(Mins <= 1) str_format(Buf, sizeof(Buf), "You have been banned for 1 minute (%s)", pReason); else str_format(Buf, sizeof(Buf), "You have been banned for %d minutes (%s)", Mins, pReason); } else str_format(Buf, sizeof(Buf), "You have been banned for life (%s)", pReason); for(int i = 0; i < MaxClients(); i++) { BanAddr = m_aSlots[i].m_Connection.PeerAddress(); BanAddr.port = 0; if(net_addr_comp(&Addr, &BanAddr) == 0) Drop(i, Buf); } } return 0; }