diff --git a/check_csgo/check_csgo.cpp b/check_csgo/check_csgo.cpp index 28ba4a2..e97d910 100644 --- a/check_csgo/check_csgo.cpp +++ b/check_csgo/check_csgo.cpp @@ -1,164 +1,166 @@ #include "check_csgo.h" +#include using namespace std; char *servicename = (char*)"CS:GO"; -void printVersion() -{ - cout << "check_csgo v" << VERSION << endl << endl; +void printVersion() { + cout << "check_csgo v" << VERSION << endl << endl; } -void printHelp(bool longVersion) -{ - if(longVersion) - { - printVersion(); - cout << "Check CS:GO DS instance." << endl << endl; - printHelp(false); - cout << "Options:" << endl; - cout << " -h" << endl; - cout << " Print detailed help screen" << endl; - cout << " -V" << endl; - cout << " Print version information" << endl; - cout << " -H HOSTADDRESS" << endl; - cout << " Host where the Source DS is running" << endl; - cout << " -p" << endl; - cout << " Port where the Source DS is listening. Default is 27015." << endl << endl; - return; - } - cout << "Usage: " << endl << "check_csgo [-hV] -H HOSTADDRESS [-p PORT]" << endl << endl; +void printHelp(bool longVersion) { + if(longVersion) { + printVersion(); + cout << "Check CS:GO DS instance." << endl << endl; + printHelp(false); + cout << "Options:" << endl; + cout << " -h" << endl; + cout << " Print detailed help screen" << endl; + cout << " -V" << endl; + cout << " Print version information" << endl; + cout << " -H HOSTADDRESS" << endl; + cout << " Host where the Source DS is running" << endl; + cout << " -p" << endl; + cout << " Port where the Source DS is listening. Default is 27015." << endl << endl; + return; + } + cout << "Usage: " << endl << "check_csgo [-hV] -H HOSTADDRESS [-p PORT]" << endl << endl; } -SOURCEDS_PACKET* getSourceDSResponse(int s, sockaddr_in *server) -{ - char *data = new char[DATAGRAM_LENGTH]; - int dataLength = recvMsg(s, data, DATAGRAM_LENGTH, server); - if(dataLength == -1) - { - return NULL; - } - char *header = (char*) "\xFF\xFF\xFF\xFF"; - if(memcmp(data,header,HDR_SIZE)) - { - //Invalid response, or non-supported multi-packet response format - return NULL; - } - SOURCEDS_PACKET *response = new SOURCEDS_PACKET; - response->data = data+HDR_SIZE; - response->length = dataLength; - return response; +SOURCEDS_PACKET* getSourceDSResponse(int s, sockaddr_in *server) { + char *data = new char[DATAGRAM_LENGTH]; + int dataLength = recvMsg(s, data, DATAGRAM_LENGTH, server); + if(dataLength == -1) { + return NULL; + } + char *header = (char*) "\xFF\xFF\xFF\xFF"; + if(memcmp(data,header,HDR_SIZE)) { + //Invalid response, or non-supported multi-packet response format + return NULL; + } + SOURCEDS_PACKET *response = new SOURCEDS_PACKET; + response->data = data+HDR_SIZE; + response->length = dataLength; + return response; } -int check_csgo(char *hostname, uint16_t port, SERVERINFO *server_info) -{ - struct sockaddr_in si; - struct hostent *host = NULL; - int s; - int timeout = 10; - setupSocket(port,hostname,host,timeout,&si,&s); - string discard; - - char *info_query = (char*) "\xFF\xFF\xFF\xFF\x54Source Engine Query\x00"; - - sendMsg(s,info_query, strlen(info_query)+1,&si); - SOURCEDS_PACKET *response = getSourceDSResponse(s,&si); - if(response == NULL) - { - return 2; - } - - ssize_t offset = 2; - server_info->name = string(response->data+offset,strlen(response->data+offset)); - offset += server_info->name.size()+1; - server_info->map = string(response->data+offset,strlen(response->data+offset)); - offset += server_info->map.size()+1; - discard = string(response->data+offset,strlen(response->data+offset)); - offset += discard.size() + 1; - server_info->game = string(response->data+offset,strlen(response->data+offset)); - offset += server_info->game.size()+1; - offset += 2; - server_info->players = (uint8_t) *((response->data)+offset); - server_info->max_players = (uint8_t) *((response->data)+(++offset)); - +int check_csgo(char *hostname, uint16_t port, SERVERINFO *server_info) { + struct sockaddr_in si; + struct hostent *host = NULL; + int s; + int timeout = 10; + setupSocket(port,hostname,host,timeout,&si,&s); + string discard; + + std::vector info_query; + info_query.resize(25); + memcpy(info_query.data(), "\xFF\xFF\xFF\xFF\x54Source Engine Query\x00", 25); + + sendMsg(s, reinterpret_cast(info_query.data()), info_query.size(), &si); + SOURCEDS_PACKET *response = getSourceDSResponse(s,&si); + if(response == NULL) { + return 2; + } + + if(response->data[0] == 'A') { + // Challenge response mechanism + uint32_t challenge; + size_t current_pkt_size = info_query.size(); + info_query.resize(current_pkt_size + 4); + memcpy(info_query.data() + current_pkt_size, response->data+1, 4); delete[] (response->data-HDR_SIZE); delete response; - if(server_info->players == server_info->max_players) - { - return 1; + sendMsg(s, reinterpret_cast(info_query.data()), info_query.size(), &si); + response = getSourceDSResponse(s, &si); + if(response == NULL) { + return 2; } - - return 0; + } + + ssize_t offset = 2; + server_info->name = string(response->data+offset,strlen(response->data+offset)); + offset += server_info->name.size()+1; + server_info->map = string(response->data+offset,strlen(response->data+offset)); + offset += server_info->map.size()+1; + discard = string(response->data+offset,strlen(response->data+offset)); + offset += discard.size() + 1; + server_info->game = string(response->data+offset,strlen(response->data+offset)); + offset += server_info->game.size()+1; + offset += 2; + server_info->players = (uint8_t) *((response->data)+offset); + server_info->max_players = (uint8_t) *((response->data)+(++offset)); + + delete[] (response->data-HDR_SIZE); + delete response; + + if(server_info->players == server_info->max_players) { + return 1; + } + + return 0; } -int main(int argc, char **argv) -{ - struct itimerval timer; - timer.it_value.tv_sec = 10; - timer.it_value.tv_usec = 0; - timer.it_interval.tv_sec = 0; - timer.it_interval.tv_usec = 0; - setitimer (ITIMER_VIRTUAL, &timer, 0); - - struct sigaction sa; - memset (&sa, 0, sizeof (sa)); - sa.sa_handler = &timer_handler; - sigaction (SIGVTALRM, &sa, 0); - - uint16_t port = 27015; - char *hostname = NULL; - int c; - - while ((c = getopt (argc, argv, "H:p:Vh")) != -1) - { - switch(c) - { - case 'H': - hostname = optarg; - break; - case 'p': - port = (uint16_t) str2int(optarg); - break; - case 'V': - printVersion(); - return 0; - case 'h': - printHelp(true); - return 0; - case '?': - printHelp(false); - return 3; - } - } - - if(hostname == NULL) - { - cout << "No HOSTADDRESS specified. Exiting." << endl; - return 3; - } - - SERVERINFO server_info; - int returnCode = check_csgo(hostname,port,&server_info); - - cout << servicename; - switch(returnCode) - { - case 0: - cout << " OK"; - cout << " - " << hostname << " " << server_info.name << " " << server_info.game << " " << server_info.map - << " " << (int)server_info.players << "/" << (int)server_info.max_players << " players" << endl ; - break; - - case 1: - cout << " WARNING - Server is full"; - break; - - case 2: - cout << " CRITICAL - No response"; - break; - } - - - return returnCode; +int main(int argc, char **argv) { + struct itimerval timer; + timer.it_value.tv_sec = 10; + timer.it_value.tv_usec = 0; + timer.it_interval.tv_sec = 0; + timer.it_interval.tv_usec = 0; + setitimer (ITIMER_VIRTUAL, &timer, 0); + + struct sigaction sa; + memset (&sa, 0, sizeof (sa)); + sa.sa_handler = &timer_handler; + sigaction (SIGVTALRM, &sa, 0); + + uint16_t port = 27015; + char *hostname = NULL; + int c; + + while ((c = getopt (argc, argv, "H:p:Vh")) != -1) { + switch(c) { + case 'H': + hostname = optarg; + break; + case 'p': + port = (uint16_t) str2int(optarg); + break; + case 'V': + printVersion(); + return 0; + case 'h': + printHelp(true); + return 0; + case '?': + printHelp(false); + return 3; + } + } + + if(hostname == NULL) { + cout << "No HOSTADDRESS specified. Exiting." << endl; + return 3; + } + + SERVERINFO server_info; + int returnCode = check_csgo(hostname,port,&server_info); + + cout << servicename; + switch(returnCode) { + case 0: + cout << " OK"; + cout << " - " << hostname << " " << server_info.name << " " << server_info.game << " " << server_info.map + << " " << (int)server_info.players << "/" << (int)server_info.max_players << " players" << endl ; + break; + + case 1: + cout << " WARNING - Server is full"; + break; + case 2: + cout << " CRITICAL - No response"; + break; + } + return returnCode; }