check_upnp.cpp 3.38 KB
#include "check_upnp.h"

using namespace std;

char *servicename = (char*)"UPnP";

void printVersion()
{
	cout << "check_upnp v" << VERSION << endl << endl;
}

void printHelp(bool longVersion)
{
	if(longVersion)
	{
		printVersion();
		cout << "Check UPnP server" << 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 UPnP server is running" << endl;
		return;
	}
	cout << "Usage: " << endl << "check_upnp [-hV] -H HOSTADDRESS" << endl << endl;
}

int check_upnp(char *hostname, string *serverinfo)
{
    char buffer[MAX_UDP+1];
    struct sockaddr_in si;
    struct hostent *host = NULL;
    int s;
    int timeout = 10;
    struct hostent *he;
    struct in_addr **addr_list;

    he = gethostbyname(hostname);
    if(he == NULL)
    {
        *serverinfo = "Can't resolve " + string(hostname);
        return 3;
    }
    addr_list = (struct in_addr **) he->h_addr_list;
    char targetIP[16];
    strcpy(targetIP,inet_ntoa(*addr_list[0]));

    setupSocket(1900,(char*)"239.255.255.250",host,timeout,&si,&s);
    memset(buffer,0x00,MAX_UDP+1);
	char *discover = (char*) "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nMX: 5\r\nST: urn:schemas-upnp-org:device:MediaServer:1\r\n\r\n";
	sendMsg(s,discover,strlen(discover),&si);
    int recvstatus;
    while(true)
    {
        recvstatus = recvMsg(s, buffer, MAX_UDP, &si);
        if(recvstatus == -1)
        {
            *serverinfo = "No response";
            return 2;
        }

        char *sourceIP = inet_ntoa(si.sin_addr);
        if(!strcmp(sourceIP,targetIP))
        {
            stringstream ss(buffer);
            string line;
            while(getline(ss,line,'\n'))
            {
                if(line.length() > strlen("SERVER:"))
                {
                    if (line.substr(0,strlen("SERVER:")) == "SERVER:")
                    {
                        *serverinfo = line.substr(0,line.size() - 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;
	}

	string serverinfo = "";
	int returnCode = check_upnp(hostname,&serverinfo);

	cout << servicename;
	switch(returnCode)
	{
		case 0:
			cout << " OK - " << serverinfo << endl ;
			break;

		case 2:
			cout << " CRITICAL - No response" << endl;
			break;

        case 3:
            cout << " UNKNOWN - " << serverinfo << endl;
	}

	return returnCode;
}