153 lines
5.9 KiB
Text
153 lines
5.9 KiB
Text
|
--- Ident.pm.orig Sun Dec 14 08:08:02 2014
|
||
|
+++ Ident.pm Sat Sep 5 09:14:17 2015
|
||
|
@@ -2,6 +2,7 @@
|
||
|
|
||
|
use strict;
|
||
|
use Socket;
|
||
|
+use Socket::GetAddrInfo qw( getaddrinfo getnameinfo :constants );
|
||
|
use Fcntl;
|
||
|
use FileHandle;
|
||
|
use Carp;
|
||
|
@@ -50,12 +51,6 @@
|
||
|
print STDDBG "Debugging turned to level $DEBUG\n";
|
||
|
}
|
||
|
|
||
|
-# protocol number for tcp.
|
||
|
-my $tcpproto = ( getprotobyname('tcp') )[2] || 6;
|
||
|
-
|
||
|
-# get identd port (default to 113).
|
||
|
-my $identport = ( getservbyname( 'ident', 'tcp' ) )[2] || 113;
|
||
|
-
|
||
|
# what to use to make nonblocking sockets
|
||
|
my $NONBLOCK = eval "&$Config{o_nonblock}";
|
||
|
|
||
|
@@ -146,49 +141,81 @@
|
||
|
my ( $class, $localaddr, $remoteaddr, $timeout ) = @_;
|
||
|
my $self = {};
|
||
|
|
||
|
- print STDDBG "Net::Ident::newFromInAddr localaddr=", sub { inet_ntoa( $_[1] ) . ":$_[0]" }
|
||
|
- ->( sockaddr_in($localaddr) ), ", remoteaddr=", sub { inet_ntoa( $_[1] ) . ":$_[0]" }
|
||
|
- ->( sockaddr_in($remoteaddr) ), ", timeout=", defined $timeout ? $timeout : "<undef>", "\n"
|
||
|
- if $DEBUG > 1;
|
||
|
+ if ($DEBUG > 1) {
|
||
|
+ my ($err, $lip, $lport, $rip, $rport);
|
||
|
+ ($err, $lip, $lport) = getnameinfo($localaddr, NI_NUMERICHOST|NI_NUMERICSERV, 0);
|
||
|
+ ($err, $rip, $rport) = getnameinfo($remoteaddr, NI_NUMERICHOST|NI_NUMERICSERV, 0);
|
||
|
+ printf STDDBG "Net::Ident::newFromInAddr localaddr=%s port %s remoteaddr=%s port %s defined timeout=%s\n",
|
||
|
+ $lip, $lport, $rip, $rport, defined $timeout ? $timeout : "<undef>";
|
||
|
+ }
|
||
|
|
||
|
eval {
|
||
|
# unpack addresses and store in
|
||
|
- my ( $localip, $remoteip );
|
||
|
- ( $self->{localport}, $localip ) = sockaddr_in($localaddr);
|
||
|
- ( $self->{remoteport}, $remoteip ) = sockaddr_in($remoteaddr);
|
||
|
+ my($family, $err, $localip, $remoteip, @res);
|
||
|
+ $family = sockaddr_family($localaddr);
|
||
|
+ if ($family != sockaddr_family($remoteaddr)) {
|
||
|
+ die "= local and remote address family mismatch\n";
|
||
|
+ }
|
||
|
|
||
|
- # create a local binding port. We cannot bind to INADDR_ANY, it has
|
||
|
- # to be bind (bound?) to the same IP address as the connection we're
|
||
|
- # interested in on machines with multiple IP addresses
|
||
|
- my $localbind = sockaddr_in( 0, $localip );
|
||
|
+ ($err, $localip, $self->{localport}) = getnameinfo($localaddr,
|
||
|
+ NI_NUMERICHOST | NI_NUMERICSERV);
|
||
|
+ if ($err) {
|
||
|
+ die "= local getnameinfo failed: $err\n";
|
||
|
+ }
|
||
|
|
||
|
+ ($err, $remoteip, $self->{remoteport}) = getnameinfo($remoteaddr,
|
||
|
+ NI_NUMERICHOST | NI_NUMERICSERV);
|
||
|
+ if ($err) {
|
||
|
+ die "= remote getnameinfo failed: $err\n";
|
||
|
+ }
|
||
|
+
|
||
|
# store max time
|
||
|
$self->{maxtime} = defined($timeout) ? time + $timeout : undef;
|
||
|
|
||
|
- # create a remote connect point
|
||
|
- my $identbind = sockaddr_in( $identport, $remoteip );
|
||
|
+ # create a local binding port.
|
||
|
+ ($err, @res) = getaddrinfo($localip, 0, {
|
||
|
+ flags => AI_PASSIVE|AI_NUMERICHOST,
|
||
|
+ family => $family,
|
||
|
+ socktype => SOCK_STREAM
|
||
|
+ });
|
||
|
+ if ($err) {
|
||
|
+ die "= local getaddrinfo failed: $err\n";
|
||
|
+ }
|
||
|
|
||
|
- # create a new FileHandle
|
||
|
- $self->{fh} = new FileHandle;
|
||
|
+ for my $ai ( @res ) {
|
||
|
+ my $fh = new FileHandle;
|
||
|
+ socket($fh, $ai->{family}, $ai->{socktype}, $ai->{protocol})
|
||
|
+ or next;
|
||
|
|
||
|
- # create a stream socket.
|
||
|
- socket( $self->{fh}, PF_INET, SOCK_STREAM, $tcpproto )
|
||
|
- or die "= socket failed: $!\n";
|
||
|
+ # bind it to the same IP number as the local end of THESOCK
|
||
|
+ bind($fh, $ai->{addr})
|
||
|
+ or next;
|
||
|
|
||
|
- # bind it to the same IP number as the local end of THESOCK
|
||
|
- bind( $self->{fh}, $localbind ) or die "= bind failed: $!\n";
|
||
|
+ # make it a non-blocking socket
|
||
|
+ fcntl($fh, F_SETFL, $NONBLOCK) or die "= fcntl failed: $!\n";
|
||
|
|
||
|
- # make it a non-blocking socket
|
||
|
- if ( $^O ne 'MSWin32' ) {
|
||
|
- fcntl( $self->{fh}, F_SETFL, $NONBLOCK ) or die "= fcntl failed: $!\n";
|
||
|
+ $self->{fh} = $fh;
|
||
|
+ last;
|
||
|
}
|
||
|
+ if (!defined($self->{fh})) {
|
||
|
+ die "= unable to bind to $localaddr: $!\n";
|
||
|
+ }
|
||
|
|
||
|
- # connect it to the remote identd port, this can return EINPROGRESS.
|
||
|
- # for some reason, reading $! twice doesn't work as it should
|
||
|
- connect( $self->{fh}, $identbind )
|
||
|
- or $!{EINPROGRESS}
|
||
|
- or die "= connect failed: $!\n";
|
||
|
- $self->{fh}->blocking(0) if $^O eq 'MSWin32';
|
||
|
+ # create a remote connect point
|
||
|
+ ($err, @res) = getaddrinfo($remoteip, 'ident', {
|
||
|
+ flags => AI_NUMERICHOST,
|
||
|
+ family => $family,
|
||
|
+ socktype => SOCK_STREAM
|
||
|
+ });
|
||
|
+ if ($err) {
|
||
|
+ die "= remote getaddrinfo failed: $err\n";
|
||
|
+ }
|
||
|
+
|
||
|
+ for my $ai ( @res ) {
|
||
|
+ connect($self->{fh}, $ai->{addr}) or $!{EINPROGRESS} or
|
||
|
+ die "= connect failed: $!\n";
|
||
|
+ last;
|
||
|
+ }
|
||
|
};
|
||
|
if ( $@ =~ /^= (.*)/ ) {
|
||
|
|
||
|
@@ -504,10 +531,13 @@
|
||
|
sub lookupFromInAddr ($$;$) {
|
||
|
my ( $localaddr, $remoteaddr, $timeout ) = @_;
|
||
|
|
||
|
- print STDDBG "Net::Ident::lookupFromInAddr localaddr=", sub { inet_ntoa( $_[1] ) . ":$_[0]" }
|
||
|
- ->( sockaddr_in($localaddr) ), ", remoteaddr=", sub { inet_ntoa( $_[1] ) . ":$_[0]" }
|
||
|
- ->( sockaddr_in($remoteaddr) ), ", timeout=", defined $timeout ? $timeout : "<undef>", "\n"
|
||
|
- if $DEBUG > 1;
|
||
|
+ if ($DEBUG > 1) {
|
||
|
+ my ($err, $lip, $lport, $rip, $rport);
|
||
|
+ ($err, $lip, $lport) = getnameinfo($localaddr, NI_NUMERICHOST|NI_NUMERICSERV);
|
||
|
+ ($err, $rip, $rport) = getnameinfo($remoteaddr, NI_NUMERICHOST|NI_NUMERICSERV);
|
||
|
+ printf STDDBG "Net::Ident::lookupFromInAddr localaddr=%s port %s, remoteaddr=%s port %s, timeout=%s\n",
|
||
|
+ $lip, $lport, $rip, $rport, defined $timeout ? $timeout : "<undef>";
|
||
|
+ }
|
||
|
|
||
|
Net::Ident->newFromInAddr( $localaddr, $remoteaddr, $timeout )->username;
|
||
|
}
|