]> granicus.if.org Git - icinga2/commitdiff
Add hostname support for check_ping
authorJean Flach <jean-marcel.flach@netways.de>
Fri, 9 Sep 2016 15:17:07 +0000 (17:17 +0200)
committerJean Flach <jean-marcel.flach@netways.de>
Mon, 12 Sep 2016 15:55:14 +0000 (17:55 +0200)
ipv6 resolving has not been tested thoroughly

fixes #9831

plugins/check_ping.cpp
plugins/check_ping.h

index 591553e26bf3f0f3151e6ea781a43ca8ab63787a..409ec8cd007d72ae12fc1ef7a877adac3cde05ad 100644 (file)
@@ -46,17 +46,23 @@ INT wmain(INT argc, WCHAR **argv)
        response response;
 
        WSADATA dat;
-       WORD req = MAKEWORD(1, 1);
 
-       WSAStartup(req, &dat);
+       if (WSAStartup(MAKEWORD(2, 2), &dat)) {
+               std::cout << "WSAStartup failed\n";
+               return 3;
+       }
 
        if (parseArguments(argc, argv, vm, printInfo) != -1)
                return 3;
-       if (printInfo.ipv4) {
-               if (check_ping4(printInfo, response) != -1)
+
+       if (!resolveHostname(printInfo.host, printInfo.ipv6, printInfo.ip))
+               return 3;
+
+       if (printInfo.ipv6) {
+               if (check_ping6(printInfo, response) != -1)
                        return 3;
        } else {
-               if (check_ping6(printInfo, response) != -1)
+               if (check_ping4(printInfo, response) != -1)
                        return 3;
        }
 
@@ -76,9 +82,9 @@ INT parseArguments(INT ac, WCHAR **av, po::variables_map& vm, printInfoStruct& p
                ("help,h", "Print usage message and exit")
                ("version,V", "Print version and exit")
                ("debug,d", "Verbose/Debug output")
-               ("host,H", po::wvalue<std::wstring>()->required(), "Host ip to ping")
-               (",4", "--Host is an ipv4 address (default)")
-               (",6", "--Host is an ipv6 address")
+               ("host,H", po::wvalue<std::wstring>()->required(), "Target hostname or IP. If an IPv6 address is given, the '-6' option must be set")
+               (",4", "--Host is an IPv4 address or if it's a hostname: Resolve it to an IPv4 address (default)")
+               (",6", "--Host is an IPv6 address or if it's a hostname: Resolve it to an IPv6 address")
                ("timeout,t", po::value<INT>(), "Specify timeout for requests in ms (default=1000)")
                ("packets,p", po::value<INT>(), "Declare ping count (default=5)")
                ("warning,w", po::wvalue<std::wstring>(), "Warning values: rtt,package loss")
@@ -154,7 +160,9 @@ INT parseArguments(INT ac, WCHAR **av, po::variables_map& vm, printInfoStruct& p
                std::cout << "Conflicting options \"4\" and \"6\"" << '\n';
                return 3;
        }
-    
+       if (vm.count("-6"))
+               printInfo.ipv6 = TRUE;
+
        if (vm.count("warning")) {
                std::vector<std::wstring> sVec = splitMultiOptions(vm["warning"].as<std::wstring>());
                if (sVec.size() != 2) {
@@ -196,8 +204,7 @@ INT parseArguments(INT ac, WCHAR **av, po::variables_map& vm, printInfoStruct& p
                printInfo.timeout = vm["timeout"].as<INT>();
        if (vm.count("packets"))
                printInfo.num = vm["packets"].as<INT>();
-       if (vm.count("-6"))
-               printInfo.ipv4 = FALSE;
+
 
        printInfo.host = vm["host"].as<std::wstring>();
 
@@ -247,7 +254,45 @@ INT printOutput(printInfoStruct& printInfo, response& response)
        return state;
 }
 
-INT check_ping4(const printInfoStruct& pi, response& response)
+BOOL resolveHostname(CONST std::wstring hostname, BOOL ipv6, std::wstring& ipaddr)
+{
+       ADDRINFOW *result = NULL;
+       ADDRINFOW *ptr = NULL;
+       ADDRINFOW hints;
+       ZeroMemory(&hints, sizeof(hints));
+       wchar_t ipstringbuffer[46];
+
+       if (ipv6)
+               hints.ai_family = AF_INET6;
+       else
+               hints.ai_family = AF_INET;
+
+       if (debug)
+               std::wcout << L"Resolving hostname \"" << hostname << L"\"\n";
+
+       DWORD ret = GetAddrInfoW(hostname.c_str(), NULL, &hints, &result);
+
+       if (ret) {
+               std::cout << "Failed to resolve hostname. Winsock Error Code: " << ret << '\n';
+               return false;
+       }
+
+       if (ipv6) {
+               struct sockaddr_in6 *address6 = (struct sockaddr_in6 *) result->ai_addr;
+               InetNtop(AF_INET6, &address6->sin6_addr, ipstringbuffer, 46);
+       } else {
+               struct sockaddr_in *address4 = (struct sockaddr_in *) result->ai_addr;
+               InetNtop(AF_INET, &address4->sin_addr, ipstringbuffer, 46);
+       }
+
+       if (debug)
+               std::wcout << L"Resolved to \"" << ipstringbuffer << L"\"\n";
+
+       ipaddr = ipstringbuffer;
+       return true;
+}
+
+INT check_ping4(CONST printInfoStruct& pi, response& response)
 {
        in_addr ipDest4;
        HANDLE hIcmp;
@@ -261,13 +306,13 @@ INT check_ping4(const printInfoStruct& pi, response& response)
        if (debug)
                std::wcout << L"Parsing ip address" << '\n';
 
-       if (RtlIpv4StringToAddress(pi.host.c_str(), TRUE, &term, &ipDest4) == STATUS_INVALID_PARAMETER) {
-               std::wcout << pi.host << " is not a valid ip address\n";
+       if (RtlIpv4StringToAddress(pi.ip.c_str(), TRUE, &term, &ipDest4) == STATUS_INVALID_PARAMETER) {
+               std::wcout << pi.ip << " is not a valid ip address\n";
                return 3;
        }
 
        if (*term != L'\0') {
-               std::wcout << pi.host << " is not a valid ip address\n";
+               std::wcout << pi.ip << " is not a valid ip address\n";
                return 3;
        }
 
@@ -346,7 +391,7 @@ die:
        return 3;
 }
 
-INT check_ping6(const printInfoStruct& pi, response& response)
+INT check_ping6(CONST printInfoStruct& pi, response& response)
 {
        sockaddr_in6 ipDest6, ipSource6;
        IP_OPTION_INFORMATION ipInfo = { 30, 0, 0, 0, NULL };
@@ -361,8 +406,8 @@ INT check_ping6(const printInfoStruct& pi, response& response)
        if (debug)
                std::wcout << L"Parsing ip address" << '\n';
 
-       if (RtlIpv6StringToAddressEx(pi.host.c_str(), &ipDest6.sin6_addr, &ipDest6.sin6_scope_id, &ipDest6.sin6_port)) {
-               std::wcout << pi.host << " is not a valid ipv6 address" << '\n';
+       if (RtlIpv6StringToAddressEx(pi.ip.c_str(), &ipDest6.sin6_addr, &ipDest6.sin6_scope_id, &ipDest6.sin6_port)) {
+               std::wcout << pi.ip << " is not a valid ipv6 address" << '\n';
                return 3;
        }
 
index 178fe4badc396a34761c3844fc42eb50b4b3710e..19238d2671c6bd59ffc699c4792e564624aeaf93 100644 (file)
@@ -32,8 +32,8 @@ struct printInfoStruct
 {
        threshold warn, crit;
        threshold wpl, cpl;
-       std::wstring host;
-       BOOL ipv4 = TRUE;
+       std::wstring host, ip;
+       BOOL ipv6 = FALSE;
        DWORD timeout = 1000;
        INT num = 5;
 };
@@ -42,5 +42,6 @@ INT printOutput(printInfoStruct&, response&);
 INT parseArguments(INT, WCHAR **, boost::program_options::variables_map&, printInfoStruct&);
 INT check_ping4(CONST printInfoStruct&, response&);
 INT check_ping6(CONST printInfoStruct&, response&);
+BOOL resolveHostname(CONST std::wstring, BOOL, std::wstring&);
 
 #endif // !CHECK_PING_H