1f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org/*
2f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *
4f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
5f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
6f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
7f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
8f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
9f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org */
10f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
11f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/winping.h"
12f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
13f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include <assert.h>
14f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include <Iphlpapi.h>
15f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
16ff689be3c0c59c1be29aaa0697aa0f762566d6c6andresp@webrtc.org#include <algorithm>
17ff689be3c0c59c1be29aaa0697aa0f762566d6c6andresp@webrtc.org
18f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/byteorder.h"
19f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/common.h"
20f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/ipaddress.h"
21f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/logging.h"
22f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/nethelpers.h"
23f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#include "webrtc/base/socketaddress.h"
24f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
25f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgnamespace rtc {
26f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
27f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//////////////////////////////////////////////////////////////////////
28f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Found in IPExport.h
29f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//////////////////////////////////////////////////////////////////////
30f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
31f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgtypedef struct icmp_echo_reply {
32f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    ULONG   Address;            // Replying address
33f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    ULONG   Status;             // Reply IP_STATUS
34f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    ULONG   RoundTripTime;      // RTT in milliseconds
35f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    USHORT  DataSize;           // Reply data size in bytes
36f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    USHORT  Reserved;           // Reserved for system use
37f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    PVOID   Data;               // Pointer to the reply data
38f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    struct ip_option_information Options; // Reply options
39f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} ICMP_ECHO_REPLY, * PICMP_ECHO_REPLY;
40f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
41f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgtypedef struct icmpv6_echo_reply_lh {
42f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  sockaddr_in6    Address;
43f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  ULONG           Status;
44f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  unsigned int    RoundTripTime;
45f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} ICMPV6_ECHO_REPLY, *PICMPV6_ECHO_REPLY;
46f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
47f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
48f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// IP_STATUS codes returned from IP APIs
49f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
50f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
51f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_STATUS_BASE              11000
52f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
53f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_SUCCESS                  0
54f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_BUF_TOO_SMALL            (IP_STATUS_BASE + 1)
55f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_DEST_NET_UNREACHABLE     (IP_STATUS_BASE + 2)
56f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_DEST_HOST_UNREACHABLE    (IP_STATUS_BASE + 3)
57f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_DEST_PROT_UNREACHABLE    (IP_STATUS_BASE + 4)
58f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_DEST_PORT_UNREACHABLE    (IP_STATUS_BASE + 5)
59f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_NO_RESOURCES             (IP_STATUS_BASE + 6)
60f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_BAD_OPTION               (IP_STATUS_BASE + 7)
61f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_HW_ERROR                 (IP_STATUS_BASE + 8)
62f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_PACKET_TOO_BIG           (IP_STATUS_BASE + 9)
63f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_REQ_TIMED_OUT            (IP_STATUS_BASE + 10)
64f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_BAD_REQ                  (IP_STATUS_BASE + 11)
65f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_BAD_ROUTE                (IP_STATUS_BASE + 12)
66f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_TTL_EXPIRED_TRANSIT      (IP_STATUS_BASE + 13)
67f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_TTL_EXPIRED_REASSEM      (IP_STATUS_BASE + 14)
68f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_PARAM_PROBLEM            (IP_STATUS_BASE + 15)
69f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_SOURCE_QUENCH            (IP_STATUS_BASE + 16)
70f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_OPTION_TOO_BIG           (IP_STATUS_BASE + 17)
71f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_BAD_DESTINATION          (IP_STATUS_BASE + 18)
72f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
73f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_ADDR_DELETED             (IP_STATUS_BASE + 19)
74f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_SPEC_MTU_CHANGE          (IP_STATUS_BASE + 20)
75f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_MTU_CHANGE               (IP_STATUS_BASE + 21)
76f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_UNLOAD                   (IP_STATUS_BASE + 22)
77f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_ADDR_ADDED               (IP_STATUS_BASE + 23)
78f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_MEDIA_CONNECT            (IP_STATUS_BASE + 24)
79f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_MEDIA_DISCONNECT         (IP_STATUS_BASE + 25)
80f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_BIND_ADAPTER             (IP_STATUS_BASE + 26)
81f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_UNBIND_ADAPTER           (IP_STATUS_BASE + 27)
82f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_DEVICE_DOES_NOT_EXIST    (IP_STATUS_BASE + 28)
83f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_DUPLICATE_ADDRESS        (IP_STATUS_BASE + 29)
84f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_INTERFACE_METRIC_CHANGE  (IP_STATUS_BASE + 30)
85f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_RECONFIG_SECFLTR         (IP_STATUS_BASE + 31)
86f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_NEGOTIATING_IPSEC        (IP_STATUS_BASE + 32)
87f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_INTERFACE_WOL_CAPABILITY_CHANGE  (IP_STATUS_BASE + 33)
88f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_DUPLICATE_IPADD          (IP_STATUS_BASE + 34)
89f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
90f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_GENERAL_FAILURE          (IP_STATUS_BASE + 50)
91f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define MAX_IP_STATUS               IP_GENERAL_FAILURE
92f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_PENDING                  (IP_STATUS_BASE + 255)
93f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
94f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
95f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Values used in the IP header Flags field.
96f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
97f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_FLAG_DF      0x2         // Don't fragment this packet.
98f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
99f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
100f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Supported IP Option Types.
101f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
102f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// These types define the options which may be used in the OptionsData field
103f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// of the ip_option_information structure.  See RFC 791 for a complete
104f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// description of each.
105f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
106f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_OPT_EOL      0          // End of list option
107f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_OPT_NOP      1          // No operation
108f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_OPT_SECURITY 0x82       // Security option
109f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_OPT_LSRR     0x83       // Loose source route
110f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_OPT_SSRR     0x89       // Strict source route
111f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_OPT_RR       0x7        // Record route
112f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_OPT_TS       0x44       // Timestamp
113f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_OPT_SID      0x88       // Stream ID (obsolete)
114f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define IP_OPT_ROUTER_ALERT 0x94  // Router Alert Option
115f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
116f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org#define MAX_OPT_SIZE    40         // Maximum length of IP options in bytes
117f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
118f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//////////////////////////////////////////////////////////////////////
119f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Global Constants and Types
120f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//////////////////////////////////////////////////////////////////////
121f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
122f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgconst char * const ICMP_DLL_NAME = "Iphlpapi.dll";
123f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgconst char * const ICMP_CREATE_FUNC = "IcmpCreateFile";
124f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgconst char * const ICMP_CLOSE_FUNC = "IcmpCloseHandle";
125f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgconst char * const ICMP_SEND_FUNC = "IcmpSendEcho";
126f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgconst char * const ICMP6_CREATE_FUNC = "Icmp6CreateFile";
127f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgconst char * const ICMP6_SEND_FUNC = "Icmp6SendEcho2";
128f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
1290c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströminline uint32_t ReplySize(uint32_t data_size, int family) {
130f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (family == AF_INET) {
131f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // A ping error message is 8 bytes long, so make sure we allow for at least
132f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // 8 bytes of reply data.
1330c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    return sizeof(ICMP_ECHO_REPLY) + std::max<uint32_t>(8, data_size);
134f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  } else if (family == AF_INET6) {
135f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // Per MSDN, Send6IcmpEcho2 needs at least one ICMPV6_ECHO_REPLY,
136f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // 8 bytes for ICMP header, _and_ an IO_BLOCK_STATUS (2 pointers),
137f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    // in addition to the data size.
138f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return sizeof(ICMPV6_ECHO_REPLY) + data_size + 8 + (2 * sizeof(DWORD*));
139f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  } else {
140f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return 0;
141f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
142f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
143f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
144f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//////////////////////////////////////////////////////////////////////
145f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// WinPing
146f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//////////////////////////////////////////////////////////////////////
147f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
148f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgWinPing::WinPing()
149f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    : dll_(0), hping_(INVALID_HANDLE_VALUE), create_(0), close_(0), send_(0),
150f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      create6_(0), send6_(0), data_(0), dlen_(0), reply_(0),
151f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      rlen_(0), valid_(false) {
152f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
153f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  dll_ = LoadLibraryA(ICMP_DLL_NAME);
154f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (!dll_) {
155f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    LOG(LERROR) << "LoadLibrary: " << GetLastError();
156f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return;
157f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
158f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
159f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  create_ = (PIcmpCreateFile) GetProcAddress(dll_, ICMP_CREATE_FUNC);
160f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  close_ = (PIcmpCloseHandle) GetProcAddress(dll_, ICMP_CLOSE_FUNC);
161f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  send_ = (PIcmpSendEcho) GetProcAddress(dll_, ICMP_SEND_FUNC);
162f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (!create_ || !close_ || !send_) {
163f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    LOG(LERROR) << "GetProcAddress(ICMP_*): " << GetLastError();
164f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return;
165f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
166f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  hping_ = create_();
167f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (hping_ == INVALID_HANDLE_VALUE) {
168f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    LOG(LERROR) << "IcmpCreateFile: " << GetLastError();
169f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return;
170f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
171f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
172f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (HasIPv6Enabled()) {
173f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    create6_ = (PIcmp6CreateFile) GetProcAddress(dll_, ICMP6_CREATE_FUNC);
174f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    send6_ = (PIcmp6SendEcho2) GetProcAddress(dll_, ICMP6_SEND_FUNC);
175f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    if (!create6_ || !send6_) {
176f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      LOG(LERROR) << "GetProcAddress(ICMP6_*): " << GetLastError();
177f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      return;
178f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    }
179f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    hping6_ = create6_();
180f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    if (hping6_ == INVALID_HANDLE_VALUE) {
181f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      LOG(LERROR) << "Icmp6CreateFile: " << GetLastError();
182f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    }
183f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
184f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
185f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  dlen_ = 0;
186f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  rlen_ = ReplySize(dlen_, AF_INET);
187f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  data_ = new char[dlen_];
188f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  reply_ = new char[rlen_];
189f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
190f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  valid_ = true;
191f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
192f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
193f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.orgWinPing::~WinPing() {
194f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if ((hping_ != INVALID_HANDLE_VALUE) && close_) {
195f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    if (!close_(hping_))
196f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      LOG(WARNING) << "IcmpCloseHandle: " << GetLastError();
197f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
198f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if ((hping6_ != INVALID_HANDLE_VALUE) && close_) {
199f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    if (!close_(hping6_)) {
200f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      LOG(WARNING) << "Icmp6CloseHandle: " << GetLastError();
201f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    }
202f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
203f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
204f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (dll_)
205f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    FreeLibrary(dll_);
206f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
207f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  delete[] data_;
208f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  delete[] reply_;
209f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
210f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
2110c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter BoströmWinPing::PingResult WinPing::Ping(IPAddress ip,
2120c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                  uint32_t data_size,
2130c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                  uint32_t timeout,
2140c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                  uint8_t ttl,
2150c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                                  bool allow_fragments) {
216f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (data_size == 0 || timeout == 0 || ttl == 0) {
217f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    LOG(LERROR) << "IcmpSendEcho: data_size/timeout/ttl is 0.";
218f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return PING_INVALID_PARAMS;
219f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
220f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
221f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  assert(IsValid());
222f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
223f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  IP_OPTION_INFORMATION ipopt;
224f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  memset(&ipopt, 0, sizeof(ipopt));
225f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (!allow_fragments)
226f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    ipopt.Flags |= IP_FLAG_DF;
227f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  ipopt.Ttl = ttl;
228f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
2290c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t reply_size = ReplySize(data_size, ip.family());
230f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
231f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (data_size > dlen_) {
232f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    delete [] data_;
233f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    dlen_ = data_size;
234f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    data_ = new char[dlen_];
235f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    memset(data_, 'z', dlen_);
236f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
237f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
238f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (reply_size > rlen_) {
239f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    delete [] reply_;
240f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    rlen_ = reply_size;
241f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    reply_ = new char[rlen_];
242f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
243f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  DWORD result = 0;
244f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (ip.family() == AF_INET) {
2450c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    result = send_(hping_, ip.ipv4_address().S_un.S_addr, data_,
2460c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                   uint16_t(data_size), &ipopt, reply_, reply_size, timeout);
247f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  } else if (ip.family() == AF_INET6) {
248f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    sockaddr_in6 src = {0};
249f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    sockaddr_in6 dst = {0};
250f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    src.sin6_family = AF_INET6;
251f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    dst.sin6_family = AF_INET6;
252f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    dst.sin6_addr = ip.ipv6_address();
2530c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    result = send6_(hping6_, NULL, NULL, NULL, &src, &dst, data_,
2540c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström                    int16_t(data_size), &ipopt, reply_, reply_size, timeout);
255f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
256f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  if (result == 0) {
257f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    DWORD error = GetLastError();
258f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    if (error == IP_PACKET_TOO_BIG)
259f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      return PING_TOO_LARGE;
260f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    if (error == IP_REQ_TIMED_OUT)
261f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org      return PING_TIMEOUT;
262f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    LOG(LERROR) << "IcmpSendEcho(" << ip.ToSensitiveString()
263f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org                << ", " << data_size << "): " << error;
264f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org    return PING_FAIL;
265f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  }
266f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
267f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org  return PING_SUCCESS;
268f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org}
269f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
270f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//////////////////////////////////////////////////////////////////////
271f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Microsoft Documenation
272f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//////////////////////////////////////////////////////////////////////
273f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
274f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Routine Name:
275f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
276f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     IcmpCreateFile
277f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
278f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Routine Description:
279f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
280f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     Opens a handle on which ICMP Echo Requests can be issued.
281f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
282f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Arguments:
283f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
284f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     None.
285f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
286f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Return Value:
287f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
288f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     An open file handle or INVALID_HANDLE_VALUE. Extended error information
289f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     is available by calling GetLastError().
290f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
291f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//////////////////////////////////////////////////////////////////////
292f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
293f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Routine Name:
294f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
295f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     IcmpCloseHandle
296f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
297f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Routine Description:
298f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
299f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     Closes a handle opened by ICMPOpenFile.
300f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
301f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Arguments:
302f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
303f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     IcmpHandle  - The handle to close.
304f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
305f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Return Value:
306f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
307f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     TRUE if the handle was closed successfully, otherwise FALSE. Extended
308f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     error information is available by calling GetLastError().
309f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
310f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//////////////////////////////////////////////////////////////////////
311f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
312f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Routine Name:
313f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
314f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     IcmpSendEcho
315f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
316f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Routine Description:
317f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
318f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     Sends an ICMP Echo request and returns any replies. The
319f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     call returns when the timeout has expired or the reply buffer
320f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     is filled.
321f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
322f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Arguments:
323f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
324f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     IcmpHandle           - An open handle returned by ICMPCreateFile.
325f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
326f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     DestinationAddress   - The destination of the echo request.
327f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
328f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     RequestData          - A buffer containing the data to send in the
329f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//                            request.
330f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
331f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     RequestSize          - The number of bytes in the request data buffer.
332f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
333f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     RequestOptions       - Pointer to the IP header options for the request.
334f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//                            May be NULL.
335f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
336f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     ReplyBuffer          - A buffer to hold any replies to the request.
337f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//                            On return, the buffer will contain an array of
338f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//                            ICMP_ECHO_REPLY structures followed by the
339f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//                            options and data for the replies. The buffer
340f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//                            should be large enough to hold at least one
341f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//                            ICMP_ECHO_REPLY structure plus
342f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//                            MAX(RequestSize, 8) bytes of data since an ICMP
343f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//                            error message contains 8 bytes of data.
344f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
345f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     ReplySize            - The size in bytes of the reply buffer.
346f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
347f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     Timeout              - The time in milliseconds to wait for replies.
348f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
349f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org// Return Value:
350f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
351f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     Returns the number of ICMP_ECHO_REPLY structures stored in ReplyBuffer.
352f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     The status of each reply is contained in the structure. If the return
353f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     value is zero, extended error information is available via
354f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//     GetLastError().
355f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//
356f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org//////////////////////////////////////////////////////////////////////
357f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org
358f048872e915a3ee229044ec4bc541f6cbf9e4de1henrike@webrtc.org} // namespace rtc
359