summaryrefslogtreecommitdiff
path: root/forum/utils/ping.php
blob: 8977df5e4a0994b9d499a8f79eb9f2c5c81873aa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
<?php
$g_icmp_error = "No Error";

// timeout in ms
function ping($host, $timeout)
{
	$port = 0;
	$datasize = 64;
	global $g_icmp_error;
	$g_icmp_error = "No Error";
	$ident = array(ord('J'), ord('C'));
	$seq   = array(rand(0, 255), rand(0, 255));

	$packet = '';
	$packet .= chr(8); // type = 8 : request
	$packet .= chr(0); // code = 0

	$packet .= chr(0); // checksum init
	$packet .= chr(0); // checksum init

	$packet .= chr($ident[0]); // identifier
	$packet .= chr($ident[1]); // identifier

	$packet .= chr($seq[0]); // seq
	$packet .= chr($seq[1]); // seq

	for ($i = 0; $i < $datasize; $i++)
		$packet .= chr(0);

	$chk = icmpChecksum($packet);

	$packet[2] = $chk[0]; // checksum init
	$packet[3] = $chk[1]; // checksum init

	$sock = socket_create(AF_INET, SOCK_RAW,  getprotobyname('icmp'));
	$time_start = microtime();
	socket_sendto($sock, $packet, strlen($packet), 0, $host, $port);
   

	$read   = array($sock);
	$write  = NULL;
	$except = NULL;

	$select = socket_select($read, $write, $except, 0, $timeout * 1000);
	if ($select === NULL)
		{
			$g_icmp_error = "Select Error";
			socket_close($sock);
			return -1;
		}
	elseif ($select === 0)
		{
			$g_icmp_error = "Timeout";
			socket_close($sock);
			return -1;
		}

	$recv = '';
	$time_stop = microtime();
	socket_recvfrom($sock, $recv, 65535, 0, $host, $port);
	$recv = unpack('C*', $recv);
       
	if ($recv[10] !== 1) // ICMP proto = 1
		{
			$g_icmp_error = "Not ICMP packet";
			socket_close($sock);
			return -1;
		}

	if ($recv[21] !== 0) // ICMP response = 0
		{
			$g_icmp_error = "Not ICMP response";
			socket_close($sock);
			return -1;
		}

	if ($ident[0] !== $recv[25] || $ident[1] !== $recv[26])
		{
			$g_icmp_error = "Bad identification number";
			socket_close($sock);
			return -1;
		}
       
	if ($seq[0] !== $recv[27] || $seq[1] !== $recv[28])
		{
			$g_icmp_error = "Bad sequence number";
			socket_close($sock);
			return -1;
		}

	$ms = ($time_stop - $time_start) * 1000;
       
	if ($ms < 0)
		{
			$g_icmp_error = "Response too long";
			$ms = -1;
		}

	socket_close($sock);

	return $ms;
}

function icmpChecksum($data)
{
	$bit = unpack('n*', $data);
	$sum = array_sum($bit);

	if (strlen($data) % 2) {
		$temp = unpack('C*', $data[strlen($data) - 1]);
		$sum += $temp[1];
	}

	$sum = ($sum >> 16) + ($sum & 0xffff);
	$sum += ($sum >> 16);

	return pack('n*', ~$sum);
}

function getLastIcmpError()
{
	global $g_icmp_error;
	return $g_icmp_error;
}

?>