| <?php | |
| 
 | |
| 	$data = "var tracepoints = {'points': ["; | |
| 
 | |
| 	define ("SOL_IP", 0); | |
| 	define ("IP_TTL", 2);	// On OSX, use '4' instead of '2'. | |
| 	 | |
| 	 | |
| 	$dest_url = "google.com"; | |
| 	 | |
| 	$maximum_hops = 30; | |
| 	$port = 33434; | |
| 	 | |
| 	function ip2geo ($host) { | |
| 		global $argv; | |
| 		// Get GeoIP info | |
| 		@$data = file_get_contents('http://ipinfo.io/'.$host); | |
| 		if ($data) { | |
| 			$data = json_decode($data); | |
| 			return $data->loc; | |
| 		} else { | |
| 			// An error has accourred | |
| 			return "(No geo info found)"; | |
| 		} | |
| 	} | |
| 	 | |
| 	$dest_addr = gethostbyname ($dest_url); | |
| 
 | |
| 	$ttl = 1; | |
| 	while ($ttl < $maximum_hops) { | |
| 		// Create ICMP and UDP sockets | |
| 		$recv_socket = socket_create (AF_INET, SOCK_RAW, getprotobyname ('icmp')); | |
| 		$send_socket = socket_create (AF_INET, SOCK_DGRAM, getprotobyname ('udp')); | |
| 
 | |
| 		// Set TTL to current lifetime | |
| 		socket_set_option ($send_socket, SOL_IP, IP_TTL, $ttl); | |
| 
 | |
| 		// Bind receiving ICMP socket to default IP (no port needed since it's ICMP) | |
| 		socket_bind ($recv_socket, 0, 0); | |
| 
 | |
| 		// Save the current time for roundtrip calculation | |
| 		$t1 = microtime (true); | |
| 
 | |
| 		// Send a zero sized UDP packet towards the destination | |
| 		socket_sendto ($send_socket, "", 0, 0, $dest_addr, $port); | |
| 
 | |
| 		// Wait for an event to occur on the socket or timeout after 5 seconds. This will take care of the | |
| 		// hanging when no data is received (packet is dropped silently for example) | |
| 		$r = array ($recv_socket); | |
| 		$w = $e = array (); | |
| 		socket_select ($r, $w, $e, 5, 0); | |
| 
 | |
| 		// Nothing to read, which means a timeout has occurred. | |
| 		if (count ($r)) { | |
| 			// Receive data from socket (and fetch destination address from where this data was found) | |
| 			socket_recvfrom ($recv_socket, $buf, 512, 0, $recv_addr, $recv_port); | |
| 
 | |
| 			$recv_geo = ip2geo ($recv_addr); | |
| 
 | |
| 			$recv_geo_split = explode(",", $recv_geo); | |
| 
 | |
| 			$data .= sprintf("{'x':%s,'y':%s},", $recv_geo_split[0], $recv_geo_split[1]); | |
| 
 | |
| 		} | |
| 
 | |
| 		socket_close ($recv_socket); | |
| 		socket_close ($send_socket); | |
| 
 | |
| 		$ttl++; | |
| 
 | |
| 		if ($recv_addr == $dest_addr) break; | |
| 	} | |
| 
 | |
| 	$data = substr($data, 0, -1) . "]}";  | |
| 
 | |
| 	printf ("%s\n", $data); | |
| 
 | |
| 	$fp = fopen('traceroute.js', 'w'); | |
| 	fwrite($fp, json_encode($data)); | |
| 	fclose($fp); | |
| 
 | |
| 
 | |
| ?>
 |