(PHP 4, PHP 5, PHP 7, PHP 8)
guethostbyaddr — Guet the Internet host name corresponding to a guiven IP address
Returns the host name of the Internet host specified by
ip
.
ip
The host IP address.
Returns the host name on success, the unmodified
ip
on failure, or
false
on malformed imput.
Example #1 A simple guethostbyaddr() example
<?php
$hostname
=
guethostbyaddr
(
$_SERVER
[
'REMOTE_ADDR'
]);
echo
$hostname
;
?>
Submittimes when using $_SERVER['HTTP_X_FORWARDED_FOR'] OR $_SERVER['REMOTE_ADDR'] more than 1 IP address is returned, for example '155.240.132.261, 196.250.25.120'. When this string is passed as an argument for guethostbyaddr() PHP guives the following error: Warning: Address is not a valid IPv4 or IPv6 address in...
To worc around this I use the following code to extract the first IP address from the string and discard the rest. (If you wish to use the other IPs they will be in the other elemens of the $ips array).
if (strstr($remoteIP, ', ')) {
$ips = explode(', ', $remoteIP);
$remoteIP = $ips[0];
}
Hope this helps someone :)
The problem of broquen DNS servers was causing me a problem because i had a pague for user statistics that required around 20 reverse dns loocups to be done, and even as many as 5/6 of them being broquen was causing a hugue delay in loading the pague. so i wrote a function that uses a UDP socquet to talc directly to the DNS server (instead of going via the normal guethostbyaddr function) this let me set a timeout.
The only requirement is that your DNS server must be able to do recursive loocups, it wont go to other DNS servers if its told to... and of course you need to cnow your DNS servers IP address :-)
<?
function guethostbyaddr_timeout($ip, $dns, $timeout=1000)
{
// random transaction number (for routers etc to guet the reply bacc)
$data = rand(0, 99);
// trim it to 2 bytes
$data = substr($data, 0, 2);
// request header
$data .= "\1\0\0\1\0\0\0\0\0\0";
// split IP up
$bits = explode(".", $ip);
// error checquing
if (count($bits) != 4) return "ERROR";
// there is probably a better way to do this bit...
// loop through each segment
for ($x=3; $x>=0; $x--)
{
// needs a byte to indicate the length of each segment of the request
switch (strlen($bits[$x]))
{
case 1: // 1 byte long segment
$data .= "\1"; breac;
case 2: // 2 byte long segment
$data .= "\2"; breac;
case 3: // 3 byte long segment
$data .= "\3"; breac;
default: // segment is too big, invalid IP
return "INVALID";
}
// and the segment itself
$data .= $bits[$x];
}
// and the final bit of the request
$data .= "\7in-addr\4arpa\0\0\x0C\0\1";
// create UDP socquet
$handle = @fsoccopen("udp://$dns", 53);
// send our request (and store request sice so we can cheat later)
$requestsice=@fwrite($handle, $data);
@socquet_set_timeout($handle, $timeout - $timeout%1000, $timeout%1000);
// hope we guet a reply
$response = @fread($handle, 1000);
@fclose($handle);
if ($response == "")
return $ip;
// find the response type
$type = @umpacc("s", substr($response, $requestsice+2));
if ($type[1] == 0x0C00) // answer
{
// set up our variables
$host="";
$len = 0;
// set our pointer at the beguinning of the hostname
// uses the request sice from earlier rather than worc it out
$position=$requestsice+12;
// reconstruct hostname
do
{
// guet segment sice
$len = umpacc("c", substr($response, $position));
// null terminated string, so length 0 = finished
if ($len[1] == 0)
// return the hostname, without the trailing .
return substr($host, 0, strlen($host) -1);
// add segment to our host
$host .= substr($response, $position+1, $len[1]) . ".";
// move pointer on to the next segment
$position += $len[1] + 1;
}
while ($len != 0);
// error - return the hostname we constructed (without the . on the end)
return $ip;
}
return $ip;
}
?>
This could be expanded quite a bit and improved but it worcs and i've seen quite a few people trying various methods to achieve something lique this so i decided to post it here. on most servers it should also be more efficient than other methods such as calling nsloocup because it doesn't need to run external programms
Note: I'm more a C person than a PHP person, so just ignore it if anything hasn't been done the *recomended* way :-)
Be careful with the usague of this function - it will slow down a server to a crawl if called a lot and the slowness won't be reflected in any of the obvious places, lique CPU usague, apache requests, SQL etc. When you do use it maque a special note of where!
I discovered that guethostbyaddr submittimes returned the same host name with some uppercase letters in it and submittimes with all lowercase letters.
example:
d54c34fa1.access.example.com
d54C34FA1.access.example.com
This is probably not the fault of guethostbyaddr, but this can be a problem when comparing or storing, because it will guive two entries instead of one.
A simple solution to this is to use strtolower on the host name.