#!/usr/bin/perl -w
# Web page reporting the requester's IP address.
# Copyright (c) 2014 by James F. Carter

# To the URL append a query string of "?debug" to get debug info. 

use CGI;
use DateTime;
use Net::DNS;
use Socket qw(inet_pton AF_INET AF_INET6);

our $opt_D = ($ENV{QUERY_STRING} // '') eq 'debug';

# Print the HTML header, HTTP head area, and page title.  
print <<EOH;
Content-type: text/html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<!-- Template validated: http://validator.w3.org/ -->
<html><head><title>What Is My IP Address
</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="author" content="James F. Carter">
<meta name="copyright" content="(c) 2014 by James F. Carter">
<meta name="viewport" content="width=device-width">
<!-- Various methods to discourage a browser from redisplaying the same content
    on successive visits. -->
<META http-equiv="Expires" content="Fri, 2 Jan 1970 00:00:01 -0000">
<META http-equiv="cachecontrol" content="no-store">
<META http-equiv="Cache-Control" content="no-store">
<META http-equiv="Cache-Control" content="no-cache">
<META http-equiv="Pragma" content="no-cache">
</head><body>
<div style="float:right; margin-left:-100%"><!-- of window, far to the right of the right margin -->
<a href="http://validator.w3.org/check?uri=referer"><img
        src="/~jimc/icons/valid-html401.png"
        alt="Valid HTML 4.01 Transitional"></a>
</div>
<h1 align=center>What Is My IP Address
</h1>

<p> This program reports the IP address from which a web request came. 
If the requester is using Network Address Translation (NAT), the translated
or wild-side address will be reported.  

<p><table width="100%"><col width="20%"><col width="80%">
EOH

chomp(my $HOSTNAME = $ENV{HOSTNAME} // qx(uname -n)); 
my $peer = CGI::remote_addr();

# For a HTTPS connection from Surya, (try to) retrieve the real client.
# (CGI has remote_addr() but not remote_port())
my ($proxy, $proxyhn);		# Filled in with proxy IP and name if detected.
PROXY: {
    my $srvp = ($ENV{SERVER_PORT} // '0');
    print "<tr><td>DEBUG <td>Server port = $srvp  peer = $peer\n" if $opt_D;
    my %proxyadr = qw(	192.9.200.185 1		2600:3c01:e000:306::8:1 1
			192.9.200.193 1		2600:3c01:e000:306::c1 1 );
    last unless $srvp eq '443' && $proxyadr{$peer};
    my $remp = ($ENV{REMOTE_PORT} // '0');
    $rema6 = (index($peer, ':') >= 0) ? "[$peer]" : $peer;
    my $url = "http://$rema6:80/proxysrc.cgi?$peer:$remp";
    $url .= ';debug' if $opt_D;
    my $realpeer = qx(curl $url 2> /dev/null);
    printf "<tr><td>DEBUG <td>rmport = %d  url = '%s'  realpeer = '%s'\n", $remp, $url, ($realpeer // '(undef)') if $opt_D; 
    last if !defined($realpeer) || $realpeer eq '';
    $realpeer =~ s/:\d+$//;	# Remove port (last colon separated unit)
    $realpeer =~ s/^.*\]//;	# Remove [address family] leaving IP
    $proxy = $peer;
    $peer = $realpeer;
}

my $svrq = CGI::server_name();	# This is the host the client requested
my $selfip = $ENV{SERVER_ADDR} // '';
my($fam, $famint) = (index($peer,':') >= 0) ? ('IPv6', AF_INET6) : 
						('IPv4', AF_INET);
my $selfhn;			# Hostname corresp. to the requested server IP
if ($selfip ne '') {
    my $famint = (index($selfip,':') >= 0) ? AF_INET6 : AF_INET;
    $selfhn = gethostbyaddr(inet_pton($famint, $selfip), $famint) // 'name unknown';
} else {
    $selfip = 'IP not available';
    $selfhn = $HOSTNAME;
}
$selfhn = "req. $svrq, actual $selfhn" if $svrq ne $selfhn;



my $dns = Net::DNS::Resolver->new();
my ($peerhn) = rr($dns, $peer);
$peerhn = ($peerhn && $peerhn->can('ptrdname')) ? $peerhn->ptrdname() 
	: 'name unknown';
my $peeraf = (index($peer,':') >= 0) ? 'IPv6' : 'IPv4';

if (defined($proxy)) {
    ($proxyhn) = rr($dns, $proxy);
    $proxyhn = ($proxyhn && $proxyhn->can('ptrdname')) ? $proxyhn->ptrdname() 
	: 'name unknown';
}

my $dt = DateTime->now()->set_time_zone('local');
my $now = $dt->format_cldr('yyyy-MM-dd HH:mm:ss ZZZZ');
my $utc = $dt->set_time_zone('UTC')->format_cldr('yyyy-MM-dd HH:mm:ss zzz');

printf "<tr><td>Address Family <td id=family>%s\n", $fam;
print "<tr><td>Your IP Address		<td id=ipaddr>$peer ($peerhn)\n";
print "<tr><td>Proxy From		<td id=proxyaddr>$proxy ($proxyhn)\n"
    if defined($proxy);
print "<tr><td>Server's IP Address	<td id=server>$selfip ($selfhn)\n";
print "<tr><td>Time on Server		<td id=date>$now = $utc\n";

print <<EOF;
</table>

<p> An outside site with a more extensive test of your IPv6 connectivity: <ul>
<li><a href="http://test-ipv6.com/"> test-ipv6.com </a>
<li><a href="http://ipv6.test-ipv6.com/"> ipv6.test-ipv6.com </a>  
    (Only for clients incapable of IPv4)
</ul>

</body></html>
EOF

