1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/*
2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle
3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2004--2005, Google Inc.
4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without
6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met:
7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  1. Redistributions of source code must retain the above copyright notice,
9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer.
10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  2. Redistributions in binary form must reproduce the above copyright notice,
11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     this list of conditions and the following disclaimer in the documentation
12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     and/or other materials provided with the distribution.
13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *  3. The name of the author may not be used to endorse or promote products
14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *     derived from this software without specific prior written permission.
15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *
16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */
27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
28f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/byteorder.h"
29f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/common.h"
30f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/socketaddress.h"
31f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/winping.h"
32f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/logging.h"
33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <cassert>
34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace talk_base {
36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
37f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
38f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Found in IPExport.h
39f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
41f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochtypedef struct icmp_echo_reply {
42f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ULONG   Address;            // Replying address
43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ULONG   Status;             // Reply IP_STATUS
44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ULONG   RoundTripTime;      // RTT in milliseconds
45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    USHORT  DataSize;           // Reply data size in bytes
46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    USHORT  Reserved;           // Reserved for system use
47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    PVOID   Data;               // Pointer to the reply data
48f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    struct ip_option_information Options; // Reply options
49f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} ICMP_ECHO_REPLY, * PICMP_ECHO_REPLY;
50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
52f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// IP_STATUS codes returned from IP APIs
53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_STATUS_BASE              11000
56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
57f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_SUCCESS                  0
58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_BUF_TOO_SMALL            (IP_STATUS_BASE + 1)
59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_DEST_NET_UNREACHABLE     (IP_STATUS_BASE + 2)
60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_DEST_HOST_UNREACHABLE    (IP_STATUS_BASE + 3)
61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_DEST_PROT_UNREACHABLE    (IP_STATUS_BASE + 4)
62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_DEST_PORT_UNREACHABLE    (IP_STATUS_BASE + 5)
63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_NO_RESOURCES             (IP_STATUS_BASE + 6)
64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_BAD_OPTION               (IP_STATUS_BASE + 7)
65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_HW_ERROR                 (IP_STATUS_BASE + 8)
66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_PACKET_TOO_BIG           (IP_STATUS_BASE + 9)
67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_REQ_TIMED_OUT            (IP_STATUS_BASE + 10)
68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_BAD_REQ                  (IP_STATUS_BASE + 11)
69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_BAD_ROUTE                (IP_STATUS_BASE + 12)
70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_TTL_EXPIRED_TRANSIT      (IP_STATUS_BASE + 13)
71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_TTL_EXPIRED_REASSEM      (IP_STATUS_BASE + 14)
72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_PARAM_PROBLEM            (IP_STATUS_BASE + 15)
73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_SOURCE_QUENCH            (IP_STATUS_BASE + 16)
74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_OPTION_TOO_BIG           (IP_STATUS_BASE + 17)
75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_BAD_DESTINATION          (IP_STATUS_BASE + 18)
76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
77f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_ADDR_DELETED             (IP_STATUS_BASE + 19)
78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_SPEC_MTU_CHANGE          (IP_STATUS_BASE + 20)
79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_MTU_CHANGE               (IP_STATUS_BASE + 21)
80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_UNLOAD                   (IP_STATUS_BASE + 22)
81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_ADDR_ADDED               (IP_STATUS_BASE + 23)
82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_MEDIA_CONNECT            (IP_STATUS_BASE + 24)
83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_MEDIA_DISCONNECT         (IP_STATUS_BASE + 25)
84f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_BIND_ADAPTER             (IP_STATUS_BASE + 26)
85f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_UNBIND_ADAPTER           (IP_STATUS_BASE + 27)
86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_DEVICE_DOES_NOT_EXIST    (IP_STATUS_BASE + 28)
87f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_DUPLICATE_ADDRESS        (IP_STATUS_BASE + 29)
88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_INTERFACE_METRIC_CHANGE  (IP_STATUS_BASE + 30)
89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_RECONFIG_SECFLTR         (IP_STATUS_BASE + 31)
90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_NEGOTIATING_IPSEC        (IP_STATUS_BASE + 32)
91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_INTERFACE_WOL_CAPABILITY_CHANGE  (IP_STATUS_BASE + 33)
92f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_DUPLICATE_IPADD          (IP_STATUS_BASE + 34)
93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_GENERAL_FAILURE          (IP_STATUS_BASE + 50)
95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define MAX_IP_STATUS               IP_GENERAL_FAILURE
96f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_PENDING                  (IP_STATUS_BASE + 255)
97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
98f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
99f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Values used in the IP header Flags field.
100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_FLAG_DF      0x2         // Don't fragment this packet.
102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Supported IP Option Types.
105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// These types define the options which may be used in the OptionsData field
107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// of the ip_option_information structure.  See RFC 791 for a complete
108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// description of each.
109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_OPT_EOL      0          // End of list option
111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_OPT_NOP      1          // No operation
112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_OPT_SECURITY 0x82       // Security option
113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_OPT_LSRR     0x83       // Loose source route
114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_OPT_SSRR     0x89       // Strict source route
115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_OPT_RR       0x7        // Record route
116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_OPT_TS       0x44       // Timestamp
117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_OPT_SID      0x88       // Stream ID (obsolete)
118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define IP_OPT_ROUTER_ALERT 0x94  // Router Alert Option
119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#define MAX_OPT_SIZE    40         // Maximum length of IP options in bytes
121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Global Constants and Types
124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst char * const ICMP_DLL_NAME = "icmp.dll";
127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst char * const ICMP_CREATE_FUNC = "IcmpCreateFile";
128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst char * const ICMP_CLOSE_FUNC = "IcmpCloseHandle";
129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochconst char * const ICMP_SEND_FUNC = "IcmpSendEcho";
130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochinline uint32 ReplySize(uint32 data_size) {
132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // A ping error message is 8 bytes long, so make sure we allow for at least
133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  // 8 bytes of reply data.
134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return sizeof(ICMP_ECHO_REPLY) + talk_base::_max<uint32>(8, data_size);
135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// WinPing
139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochWinPing::WinPing()
142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    : dll_(0), hping_(INVALID_HANDLE_VALUE), create_(0), close_(0), send_(0),
143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      data_(0), dlen_(0), reply_(0), rlen_(0), valid_(false) {
144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  dll_ = LoadLibraryA(ICMP_DLL_NAME);
146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!dll_) {
147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LERROR) << "LoadLibrary: " << GetLastError();
148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  create_ = (PIcmpCreateFile) GetProcAddress(dll_, ICMP_CREATE_FUNC);
152f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  close_ = (PIcmpCloseHandle) GetProcAddress(dll_, ICMP_CLOSE_FUNC);
153f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  send_ = (PIcmpSendEcho) GetProcAddress(dll_, ICMP_SEND_FUNC);
154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!create_ || !close_ || !send_) {
155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LERROR) << "GetProcAddress(ICMP_*): " << GetLastError();
156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
159f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  hping_ = create_();
160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (hping_ == INVALID_HANDLE_VALUE) {
161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LERROR) << "IcmpCreateFile: " << GetLastError();
162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return;
163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  dlen_ = 0;
166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  rlen_ = ReplySize(dlen_);
167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  data_ = new char[dlen_];
168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  reply_ = new char[rlen_];
169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  valid_ = true;
171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochWinPing::~WinPing() {
174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (dll_)
175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    FreeLibrary(dll_);
176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if ((hping_ != INVALID_HANDLE_VALUE) && close_) {
178f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (!close_(hping_))
179f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      LOG(WARNING) << "IcmpCloseHandle: " << GetLastError();
180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  delete[] data_;
183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  delete reply_;
184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochWinPing::PingResult WinPing::Ping(
187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    uint32 ip, uint32 data_size, uint32 timeout, uint8 ttl,
188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    bool allow_fragments) {
189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  assert(IsValid());
191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  IP_OPTION_INFORMATION ipopt;
193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  memset(&ipopt, 0, sizeof(ipopt));
194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (!allow_fragments)
195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    ipopt.Flags |= IP_FLAG_DF;
196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  ipopt.Ttl = ttl;
197f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  uint32 reply_size = ReplySize(data_size);
199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (data_size > dlen_) {
201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    delete [] data_;
202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    dlen_ = data_size;
203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    data_ = new char[dlen_];
204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    memset(data_, 'z', dlen_);
205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (reply_size > rlen_) {
208f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    delete [] reply_;
209f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    rlen_ = reply_size;
210f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    reply_ = new char[rlen_];
211f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
212f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
213f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  DWORD result = send_(hping_, talk_base::HostToNetwork32(ip),
214f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                       data_, uint16(data_size), &ipopt,
215f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                       reply_, reply_size, timeout);
216f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  if (result == 0) {
217f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    long error = GetLastError();
218f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (error == IP_PACKET_TOO_BIG)
219f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return PING_TOO_LARGE;
220f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    if (error == IP_REQ_TIMED_OUT)
221f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch      return PING_TIMEOUT;
222f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    LOG(LERROR) << "IcmpSendEcho(" << talk_base::SocketAddress::IPToString(ip)
223f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch                << ", " << data_size << "): " << error;
224f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch    return PING_FAIL;
225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  }
226f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch  return PING_SUCCESS;
228f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}
229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Microsoft Documenation
232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Routine Name:
235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     IcmpCreateFile
237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Routine Description:
239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     Opens a handle on which ICMP Echo Requests can be issued.
241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Arguments:
243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
244f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     None.
245f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
246f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Return Value:
247f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
248f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     An open file handle or INVALID_HANDLE_VALUE. Extended error information
249f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     is available by calling GetLastError().
250f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
251f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Routine Name:
254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
255f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     IcmpCloseHandle
256f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
257f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Routine Description:
258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     Closes a handle opened by ICMPOpenFile.
260f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
261f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Arguments:
262f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
263f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     IcmpHandle  - The handle to close.
264f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
265f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Return Value:
266f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
267f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     TRUE if the handle was closed successfully, otherwise FALSE. Extended
268f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     error information is available by calling GetLastError().
269f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
270f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
271f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
272f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Routine Name:
273f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
274f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     IcmpSendEcho
275f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
276f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Routine Description:
277f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
278f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     Sends an ICMP Echo request and returns any replies. The
279f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     call returns when the timeout has expired or the reply buffer
280f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     is filled.
281f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
282f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Arguments:
283f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
284f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     IcmpHandle           - An open handle returned by ICMPCreateFile.
285f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
286f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     DestinationAddress   - The destination of the echo request.
287f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
288f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     RequestData          - A buffer containing the data to send in the
289f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//                            request.
290f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
291f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     RequestSize          - The number of bytes in the request data buffer.
292f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
293f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     RequestOptions       - Pointer to the IP header options for the request.
294f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//                            May be NULL.
295f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
296f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     ReplyBuffer          - A buffer to hold any replies to the request.
297f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//                            On return, the buffer will contain an array of
298f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//                            ICMP_ECHO_REPLY structures followed by the
299f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//                            options and data for the replies. The buffer
300f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//                            should be large enough to hold at least one
301f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//                            ICMP_ECHO_REPLY structure plus
302f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//                            MAX(RequestSize, 8) bytes of data since an ICMP
303f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//                            error message contains 8 bytes of data.
304f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
305f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     ReplySize            - The size in bytes of the reply buffer.
306f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
307f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     Timeout              - The time in milliseconds to wait for replies.
308f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
309f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// Return Value:
310f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
311f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     Returns the number of ICMP_ECHO_REPLY structures stored in ReplyBuffer.
312f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     The status of each reply is contained in the structure. If the return
313f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     value is zero, extended error information is available via
314f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//     GetLastError().
315f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//
316f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch//////////////////////////////////////////////////////////////////////
317f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch
318f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} // namespace talk_base
319