private PingReply SendPrivileged (IPAddress address, int timeout, byte [] buffer, PingOptions options) { IPEndPoint target = new IPEndPoint (address, 0); IPEndPoint client = new IPEndPoint (GetNonLoopbackIP (), 0); // FIXME: support IPv6 using (Socket s = new Socket (AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.Icmp)) { if (options != null) { s.DontFragment = options.DontFragment; s.Ttl = (short) options.Ttl; } s.SendTimeout = timeout; s.ReceiveTimeout = timeout; // not sure why Identifier = 0 is unacceptable ... IcmpMessage send = new IcmpMessage (8, 0, identifier, 0, buffer); byte [] bytes = send.GetBytes (); s.SendBufferSize = bytes.Length; s.SendTo (bytes, bytes.Length, SocketFlags.None, target); DateTime sentTime = DateTime.Now; // receive bytes = new byte [100]; do { EndPoint endpoint = client; int error = 0; int rc = s.ReceiveFrom_nochecks_exc (bytes, 0, 100, SocketFlags.None, ref endpoint, false, out error); if (error != 0) { if (error == (int) SocketError.TimedOut) { return new PingReply (null, new byte [0], options, 0, IPStatus.TimedOut); } throw new NotSupportedException (String.Format ("Unexpected socket error during ping request: {0}", error)); } long rtt = (long) (DateTime.Now - sentTime).TotalMilliseconds; int headerLength = (bytes [0] & 0xF) << 2; int bodyLength = rc - headerLength; // Ping reply to different request. discard it. if (!((IPEndPoint) endpoint).Address.Equals (target.Address)) { long t = timeout - rtt; if (t <= 0) return new PingReply (null, new byte [0], options, 0, IPStatus.TimedOut); s.ReceiveTimeout = (int) t; continue; } IcmpMessage recv = new IcmpMessage (bytes, headerLength, bodyLength); /* discard ping reply to different request or echo requests if running on same host. */ if (recv.Identifier != identifier || recv.Type == 8) { long t = timeout - rtt; if (t <= 0) return new PingReply (null, new byte [0], options, 0, IPStatus.TimedOut); s.ReceiveTimeout = (int) t; continue; } return new PingReply (address, recv.Data, options, rtt, recv.IPStatus); } while (true); } }