|
|||
|
|||
|
#include "inspircd.h"#include "users.h"#include "channels.h"Include dependency graph for cmd_stats.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.
Classes | |
| class | cmd_stats |
| Handle /STATS. More... | |
Functions | |
| DllExport void | DoStats (InspIRCd *Instance, char statschar, userrec *user, string_list &results) |
|
||||||||||||||||||||
|
Definition at line 50 of file cmd_stats.cpp. References classbase::age, connection::bytes_in, connection::bytes_out, InspIRCd::chanlist, ServerConfig::Classes, InspIRCd::clientlist, CommandParser::cmdlist, connection::cmds_in, connection::cmds_out, InspIRCd::Config, ServerConfig::config_data, ServerConfig::ConfValue(), ConvToStr(), userrec::dhost, InspIRCd::factory, FOREACH_RESULT, Extensible::GetExt(), CommandParser::GetHandler(), userrec::GetIPString(), command_t::HandleInternal(), connection::host, I_OnStats, userrec::ident, IS_LOCAL, IS_OPER, InspIRCd::IsNick(), serverstats::LastCPU, serverstats::LastSampled, InspIRCd::local_users, MAXBUF, MAXCLIENTS, InspIRCd::modules, ServerConfig::MOTD, userrec::nick, InspIRCd::Parser, ServerConfig::ports, ServerConfig::RULES, RUSAGE_SELF, userrec::sendq, userrec::server, ServerConfig::ServerName, InspIRCd::SNO, InspIRCd::startup_time, InspIRCd::stats, XLineManager::stats_e(), XLineManager::stats_g(), XLineManager::stats_k(), XLineManager::stats_q(), XLineManager::stats_z(), serverstats::statsAccept, serverstats::statsCollisions, serverstats::statsConnects, serverstats::statsDnsBad, serverstats::statsDnsGood, serverstats::statsRecv, serverstats::statsRefused, serverstats::statsSent, serverstats::statsUnknown, InspIRCd::Time(), InspIRCd::ULine(), ServerConfig::UserStats, WHOWAS_STATS, ServerConfig::WhoWasGroupSize, ServerConfig::WhoWasMaxGroups, SnomaskManager::WriteToSnoMask(), and InspIRCd::XLines. Referenced by cmd_stats::Handle(), and TreeSocket::Stats(). 00051 { 00052 std::string sn = ServerInstance->Config->ServerName; 00053 00054 if ((!*ServerInstance->Config->UserStats && !IS_OPER(user)) || (!IS_OPER(user) && !ServerInstance->ULine(user->server) && !strchr(ServerInstance->Config->UserStats,statschar))) 00055 { 00056 results.push_back(sn+std::string(" 481 ")+user->nick+" :Permission denied - STATS "+statschar+" is oper-only"); 00057 return; 00058 } 00059 00060 int MOD_RESULT = 0; 00061 FOREACH_RESULT(I_OnStats,OnStats(statschar,user,results)); 00062 if (MOD_RESULT) 00063 return; 00064 00065 switch (statschar) 00066 { 00067 /* stats p (show listening ports and registered clients on each) */ 00068 case 'p': 00069 { 00070 for (size_t i = 0; i < ServerInstance->Config->ports.size(); i++) 00071 { 00072 std::string ip = ServerInstance->Config->ports[i]->GetIP(); 00073 if (ip.empty()) 00074 ip.assign("*"); 00075 00076 results.push_back(sn+" 249 "+user->nick+" :"+ ip + ":"+ConvToStr(ServerInstance->Config->ports[i]->GetPort())+" (client, " + 00077 ServerInstance->Config->ports[i]->GetDescription() + ")"); 00078 } 00079 } 00080 break; 00081 00082 case 'n': 00083 case 'c': 00084 { 00085 /* This stats symbol must be handled by a linking module */ 00086 } 00087 break; 00088 00089 case 'i': 00090 { 00091 int idx = 0; 00092 for (ClassVector::iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++) 00093 { 00094 results.push_back(sn+" 215 "+user->nick+" I NOMATCH * "+i->GetHost()+" "+ConvToStr(MAXCLIENTS)+" "+ConvToStr(idx)+" "+ServerInstance->Config->ServerName+" *"); 00095 idx++; 00096 } 00097 } 00098 break; 00099 00100 case 'Y': 00101 { 00102 int idx = 0; 00103 for (ClassVector::iterator i = ServerInstance->Config->Classes.begin(); i != ServerInstance->Config->Classes.end(); i++) 00104 { 00105 results.push_back(sn+" 218 "+user->nick+" Y "+ConvToStr(idx)+" "+ConvToStr(i->GetPingTime())+" 0 "+ConvToStr(i->GetSendqMax())+" :"+ 00106 ConvToStr(i->GetFlood())+" "+ConvToStr(i->GetRegTimeout())); 00107 idx++; 00108 } 00109 } 00110 break; 00111 00112 case 'U': 00113 { 00114 char ulined[MAXBUF]; 00115 for (int i = 0; i < ServerInstance->Config->ConfValueEnum(ServerInstance->Config->config_data, "uline"); i++) 00116 { 00117 ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "uline","server", i, ulined, MAXBUF); 00118 results.push_back(sn+" 248 "+user->nick+" U "+std::string(ulined)); 00119 } 00120 } 00121 break; 00122 00123 case 'P': 00124 { 00125 int idx = 0; 00126 for (user_hash::iterator i = ServerInstance->clientlist->begin(); i != ServerInstance->clientlist->end(); i++) 00127 { 00128 if (IS_OPER(i->second) && !ServerInstance->ULine(i->second->server)) 00129 { 00130 results.push_back(sn+" 249 "+user->nick+" :"+i->second->nick+" ("+i->second->ident+"@"+i->second->dhost+") Idle: "+ 00131 (IS_LOCAL(i->second) ? ConvToStr(ServerInstance->Time() - i->second->idle_lastmsg) + " secs" : "unavailable")); 00132 idx++; 00133 } 00134 } 00135 results.push_back(sn+" 249 "+user->nick+" :"+ConvToStr(idx)+" OPER(s)"); 00136 } 00137 break; 00138 00139 case 'k': 00140 ServerInstance->XLines->stats_k(user,results); 00141 break; 00142 00143 case 'g': 00144 ServerInstance->XLines->stats_g(user,results); 00145 break; 00146 00147 case 'q': 00148 ServerInstance->XLines->stats_q(user,results); 00149 break; 00150 00151 case 'Z': 00152 ServerInstance->XLines->stats_z(user,results); 00153 break; 00154 00155 case 'e': 00156 ServerInstance->XLines->stats_e(user,results); 00157 break; 00158 00159 /* stats m (list number of times each command has been used, plus bytecount) */ 00160 case 'm': 00161 for (command_table::iterator i = ServerInstance->Parser->cmdlist.begin(); i != ServerInstance->Parser->cmdlist.end(); i++) 00162 { 00163 if (i->second->use_count) 00164 { 00165 /* RPL_STATSCOMMANDS */ 00166 results.push_back(sn+" 212 "+user->nick+" "+i->second->command+" "+ConvToStr(i->second->use_count)+" "+ConvToStr(i->second->total_bytes)); 00167 } 00168 } 00169 break; 00170 00171 /* stats z (debug and memory info) */ 00172 case 'z': 00173 { 00174 results.push_back(sn+" 240 "+user->nick+" :InspIRCd(CLASS) "+ConvToStr(sizeof(InspIRCd))+" bytes"); 00175 results.push_back(sn+" 249 "+user->nick+" :Users(HASH_MAP) "+ConvToStr(ServerInstance->clientlist->size())+" ("+ConvToStr(ServerInstance->clientlist->size()*sizeof(userrec))+" bytes)"); 00176 results.push_back(sn+" 249 "+user->nick+" :Channels(HASH_MAP) "+ConvToStr(ServerInstance->chanlist->size())+" ("+ConvToStr(ServerInstance->chanlist->size()*sizeof(chanrec))+" bytes)"); 00177 results.push_back(sn+" 249 "+user->nick+" :Commands(VECTOR) "+ConvToStr(ServerInstance->Parser->cmdlist.size())+" ("+ConvToStr(ServerInstance->Parser->cmdlist.size()*sizeof(command_t))+" bytes)"); 00178 00179 if (!ServerInstance->Config->WhoWasGroupSize == 0 && !ServerInstance->Config->WhoWasMaxGroups == 0) 00180 { 00181 command_t* whowas_command = ServerInstance->Parser->GetHandler("WHOWAS"); 00182 if (whowas_command) 00183 { 00184 std::deque<classbase*> params; 00185 Extensible whowas_stats; 00186 params.push_back(&whowas_stats); 00187 whowas_command->HandleInternal(WHOWAS_STATS, params); 00188 if (whowas_stats.GetExt("stats")) 00189 { 00190 char* stats; 00191 whowas_stats.GetExt("stats", stats); 00192 results.push_back(sn+" 249 "+user->nick+" :"+ConvToStr(stats)); 00193 } 00194 } 00195 } 00196 00197 results.push_back(sn+" 249 "+user->nick+" :MOTD(VECTOR) "+ConvToStr(ServerInstance->Config->MOTD.size())+", RULES(VECTOR) "+ConvToStr(ServerInstance->Config->RULES.size())); 00198 results.push_back(sn+" 249 "+user->nick+" :Modules(VECTOR) "+ConvToStr(ServerInstance->modules.size())+" ("+ConvToStr(ServerInstance->modules.size()*sizeof(Module))+" bytes)"); 00199 results.push_back(sn+" 249 "+user->nick+" :ClassFactories(VECTOR) "+ConvToStr(ServerInstance->factory.size())+" ("+ConvToStr(ServerInstance->factory.size()*sizeof(ircd_module))+" bytes)"); 00200 00201 #ifndef WIN32 00202 /* Moved this down here so all the not-windows stuff (look w00tie, I didn't say win32!) is in one ifndef. 00203 * Also cuts out some identical code in both branches of the ifndef. -- Om 00204 */ 00205 rusage R; 00206 00207 /* Not sure why we were doing '0' with a RUSAGE_SELF comment rather than just using RUSAGE_SELF -- Om */ 00208 if (!getrusage(RUSAGE_SELF,&R)) /* RUSAGE_SELF */ 00209 { 00210 results.push_back(sn+" 249 "+user->nick+" :Total allocation: "+ConvToStr(R.ru_maxrss)+"K"); 00211 results.push_back(sn+" 249 "+user->nick+" :Signals: "+ConvToStr(R.ru_nsignals)); 00212 results.push_back(sn+" 249 "+user->nick+" :Page faults: "+ConvToStr(R.ru_majflt)); 00213 results.push_back(sn+" 249 "+user->nick+" :Swaps: "+ConvToStr(R.ru_nswap)); 00214 results.push_back(sn+" 249 "+user->nick+" :Context Switches: Voluntary; "+ConvToStr(R.ru_nvcsw)+" Involuntary; "+ConvToStr(R.ru_nivcsw)); 00215 00216 timeval tv; 00217 char percent[30]; 00218 gettimeofday(&tv, NULL); 00219 00220 float n_elapsed = ((tv.tv_sec - ServerInstance->stats->LastSampled.tv_sec) * 1000000 + tv.tv_usec - ServerInstance->stats->LastSampled.tv_usec); 00221 float n_eaten = ((R.ru_utime.tv_sec - ServerInstance->stats->LastCPU.tv_sec) * 1000000 + R.ru_utime.tv_usec - ServerInstance->stats->LastCPU.tv_usec); 00222 float per = (n_eaten / n_elapsed) * 100; 00223 00224 snprintf(percent, 30, "%03.5f%%", per); 00225 results.push_back(sn+" 249 "+user->nick+" :CPU Usage: "+percent); 00226 } 00227 #endif 00228 } 00229 break; 00230 00231 case 'T': 00232 { 00233 char buffer[MAXBUF]; 00234 results.push_back(sn+" 249 "+user->nick+" :accepts "+ConvToStr(ServerInstance->stats->statsAccept)+" refused "+ConvToStr(ServerInstance->stats->statsRefused)); 00235 results.push_back(sn+" 249 "+user->nick+" :unknown commands "+ConvToStr(ServerInstance->stats->statsUnknown)); 00236 results.push_back(sn+" 249 "+user->nick+" :nick collisions "+ConvToStr(ServerInstance->stats->statsCollisions)); 00237 results.push_back(sn+" 249 "+user->nick+" :dns requests "+ConvToStr(ServerInstance->stats->statsDnsGood+ServerInstance->stats->statsDnsBad)+" succeeded "+ConvToStr(ServerInstance->stats->statsDnsGood)+" failed "+ConvToStr(ServerInstance->stats->statsDnsBad)); 00238 results.push_back(sn+" 249 "+user->nick+" :connection count "+ConvToStr(ServerInstance->stats->statsConnects)); 00239 snprintf(buffer,MAXBUF," 249 %s :bytes sent %5.2fK recv %5.2fK",user->nick,ServerInstance->stats->statsSent / 1024,ServerInstance->stats->statsRecv / 1024); 00240 results.push_back(sn+buffer); 00241 } 00242 break; 00243 00244 /* stats o */ 00245 case 'o': 00246 for (int i = 0; i < ServerInstance->Config->ConfValueEnum(ServerInstance->Config->config_data, "oper"); i++) 00247 { 00248 char LoginName[MAXBUF]; 00249 char HostName[MAXBUF]; 00250 char OperType[MAXBUF]; 00251 ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "oper","name", i, LoginName, MAXBUF); 00252 ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "oper","host", i, HostName, MAXBUF); 00253 ServerInstance->Config->ConfValue(ServerInstance->Config->config_data, "oper","type", i, OperType, MAXBUF); 00254 results.push_back(sn+" 243 "+user->nick+" O "+HostName+" * "+LoginName+" "+OperType+" 0"); 00255 } 00256 break; 00257 00258 /* stats l (show user I/O stats) */ 00259 case 'l': 00260 results.push_back(sn+" 211 "+user->nick+" :nick[ident@host] sendq cmds_out bytes_out cmds_in bytes_in time_open"); 00261 for (std::vector<userrec*>::iterator n = ServerInstance->local_users.begin(); n != ServerInstance->local_users.end(); n++) 00262 { 00263 userrec* i = *n; 00264 if (ServerInstance->IsNick(i->nick)) 00265 { 00266 results.push_back(sn+" 211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->dhost+"] "+ConvToStr(i->sendq.length())+" "+ConvToStr(i->cmds_out)+" "+ConvToStr(i->bytes_out)+" "+ConvToStr(i->cmds_in)+" "+ConvToStr(i->bytes_in)+" "+ConvToStr(ServerInstance->Time() - i->age)); 00267 } 00268 } 00269 break; 00270 00271 /* stats L (show user I/O stats with IP addresses) */ 00272 case 'L': 00273 results.push_back(sn+" 211 "+user->nick+" :nick[ident@ip] sendq cmds_out bytes_out cmds_in bytes_in time_open"); 00274 for (std::vector<userrec*>::iterator n = ServerInstance->local_users.begin(); n != ServerInstance->local_users.end(); n++) 00275 { 00276 userrec* i = *n; 00277 if (ServerInstance->IsNick(i->nick)) 00278 { 00279 results.push_back(sn+" 211 "+user->nick+" "+i->nick+"["+i->ident+"@"+i->GetIPString()+"] "+ConvToStr(i->sendq.length())+" "+ConvToStr(i->cmds_out)+" "+ConvToStr(i->bytes_out)+" "+ConvToStr(i->cmds_in)+" "+ConvToStr(i->bytes_in)+" "+ConvToStr(ServerInstance->Time() - i->age)); 00280 } 00281 } 00282 break; 00283 00284 /* stats u (show server uptime) */ 00285 case 'u': 00286 { 00287 time_t current_time = 0; 00288 current_time = ServerInstance->Time(); 00289 time_t server_uptime = current_time - ServerInstance->startup_time; 00290 struct tm* stime; 00291 stime = gmtime(&server_uptime); 00292 /* i dont know who the hell would have an ircd running for over a year nonstop, but 00293 * Craig suggested this, and it seemed a good idea so in it went */ 00294 if (stime->tm_year > 70) 00295 { 00296 char buffer[MAXBUF]; 00297 snprintf(buffer,MAXBUF," 242 %s :Server up %d years, %d days, %.2d:%.2d:%.2d",user->nick,(stime->tm_year-70),stime->tm_yday,stime->tm_hour,stime->tm_min,stime->tm_sec); 00298 results.push_back(sn+buffer); 00299 } 00300 else 00301 { 00302 char buffer[MAXBUF]; 00303 snprintf(buffer,MAXBUF," 242 %s :Server up %d days, %.2d:%.2d:%.2d",user->nick,stime->tm_yday,stime->tm_hour,stime->tm_min,stime->tm_sec); 00304 results.push_back(sn+buffer); 00305 } 00306 } 00307 break; 00308 00309 default: 00310 break; 00311 } 00312 00313 results.push_back(sn+" 219 "+user->nick+" "+statschar+" :End of /STATS report"); 00314 ServerInstance->SNO->WriteToSnoMask('t',"%s '%c' requested by %s (%s@%s)",(!strcmp(user->server,ServerInstance->Config->ServerName) ? "Stats" : "Remote stats"),statschar,user->nick,user->ident,user->host); 00315 00316 return; 00317 }
|