Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IO::Socket::INET failing for CNAME #12557

Open
p5pRT opened this issue Nov 12, 2012 · 7 comments
Open

IO::Socket::INET failing for CNAME #12557

p5pRT opened this issue Nov 12, 2012 · 7 comments

Comments

@p5pRT
Copy link

p5pRT commented Nov 12, 2012

Migrated from rt.perl.org#115706 (status was 'open')

Searchable as RT115706$

@p5pRT
Copy link
Author

p5pRT commented Nov 12, 2012

From shmuel+CPAN@patriot.net

There is a discussion of this problem in comp.lang.perl.misc starting
with Message-ID​: <4edae754$3$fuzhry+tra$mr2ice@​news.patriot.net>, with
an archived copy at
<http​://www.rhinocerus.net/forum/lang-perl-misc/690988-io-socket-inet-hostname-restrictions.html>.
I tested the patch from Ben Morrow and it works on OS/2.

Note Ben's comment "Looking about a bit, I found
http​://cr.yp.to/docs/connect.html, which mentions this connect-twice
strategy as a way of performing a non- blocking connect and still
getting the correct error. It also says that it doesn't always work,
and that you should use getpeername instead (and for all djb's...
um... charm, he's usually right about things like this). So, I think
this counts as a bug in IO​::Socket, since there are common situations
on common operating systems where it doesn't work properly."

--
  Shmuel (Seymour J.) Metz, SysProg and JOAT
  Atid/2 <http​://patriot.net/~shmuel>
We don't care. We don't have to care, we're Congress.
(S877​: The Shut up and Eat Your spam act of 2003)

@p5pRT
Copy link
Author

p5pRT commented Nov 13, 2012

From @jkeenan

On Mon Nov 12 15​:52​:18 2012, shmuel+CPAN@​patriot.net wrote​:

There is a discussion of this problem in comp.lang.perl.misc starting
with Message-ID​: <4edae754$3$fuzhry+tra$mr2ice@​news.patriot.net>, with
an archived copy at
<http​://www.rhinocerus.net/forum/lang-perl-misc/690988-io-socket-inet-
hostname-restrictions.html>.
I tested the patch from Ben Morrow and it works on OS/2.

That's a fairly long email thread. I suspect that most readers of this
list will at most skim it. That means the issue will get less attention
than it perhaps deserved.

Would it be possible to summarize the problem and attach the patch directly?

Thank you very much.
Jim Keenan

@p5pRT
Copy link
Author

p5pRT commented Nov 13, 2012

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented Nov 13, 2012

From shmuel+bitcard.org@patriot.net

On Mon Nov 12 16​:15​:29 2012, jkeenan wrote​:

On Mon Nov 12 15​:52​:18 2012, shmuel+CPAN@​patriot.net wrote​:

There is a discussion of this problem in comp.lang.perl.misc starting
with Message-ID​: <4edae754$3$fuzhry+tra$mr2ice@​news.patriot.net>, with
an archived copy at
<http​://www.rhinocerus.net/forum/lang-perl-misc/690988-io-socket-inet-
hostname-restrictions.html>.
I tested the patch from Ben Morrow and it works on OS/2.

That's a fairly long email thread. I suspect that most readers of this
list will at most skim it. That means the issue will get less attention
than it perhaps deserved.

Would it be possible to summarize the problem and attach the patch
directly?

Thank you very much.
Jim Keenan

I've attached Ben Morrow's patch, which works under OS/2. Here's what I
believe to be the relevant parts of Ben's articles in that thread​:

*Interesting*. I believe there's at least one bug here, in IO​::Socket,
but it's not entirely clear.

First, the workaround​: don't use Timeout. Find some other way of timing
out the operation, like alarm(). The CNAMEs are a red herring​: what
matters is that that machine doesn't accept connections on port 43. The
'Invalid argument' is just the wrong error​: without Timeout, you should
see 'Connection refused', which is the right answer.

[You don't need to read the rest unless you're interested...]

That ->new call gives me exactly the same result as you​: EINVAL from
connect(). Since I didn't think connect(2) was even *able* to return
EINVAL, I ran it under ktrace​: this showed two calls to connect. The
first failed with EINPROGRESS, the second with EINVAL. Retrying without
Timeout consistently gave 'Connection refused' instead.

Looking at the source of IO​::Socket, the logic if Timeout is specified
is approximately

set non-blocking mode on the socket
try to connect
if connect fails with EINPROGRESS
select(2) for write, with the given timeout
if the select doesn't time out
retry the connect
if that connect succeeds, return success
if it failed with EISCONN, or we are on Win32 and it failed
with WSAEINVAL, return *success*
otherwise, return the error from the second connect

The EISCONN case is the strange one. There is a comment

# Some systems refuse to re-connect() to
# an already open socket and set errno to EISCONN.
# Windows sets errno to WSAEINVAL (10022)

and it turns out that it's not just Win32 that returns EINVAL in that
case, it's at least current versions of FreeBSD and, presumably, OS/2 as
well. However, even given that, returning success is *completely wrong*.
The sequence of events is

- app calls connect(2) on a non-blocking socket
- connect(2) fails with EINPROGRESS
- app calls select(2)-for-write
- some time later, a RST packet comes in
- select(2) returns socket as ready
- app calls connect(2) again
- connect(2) fails with EISCONN/EINVAL

The EISCONN/EINVAL error is saying 'this socket isn't fit to be reused'​:
it doesn't tell you *anything* about whether the second connection
attempt succeeded or failed. (In fact, you get the same EINVAL if you
attempt to re-connect a TCP socket while it's in TIME_WAIT state after a
successful close.)

Looking about a bit, I found http​://cr.yp.to/docs/connect.html, which
mentions this connect-twice strategy as a way of performing a non-
blocking connect and still getting the correct error. It also says that
it doesn't always work, and that you should use getpeername instead (and
for all djb's... um... charm, he's usually right about things like
this). So, I think this counts as a bug in IO​::Socket, since there are
common situations on common operating systems where it doesn't work
properly.

[Oddly, it looks from the CVS log as though FreeBSD used to return
EISCONN in this situation, as the IO​::Socket code was kind-of expecting,
but it was changed to EINVAL in 2006. It's not clear to me why,
especially since there now appears to be no way to get an EISCONN error
from a TCP socket.]

--
Shmuel (Seymour J.) Metz

@p5pRT
Copy link
Author

p5pRT commented Nov 13, 2012

From shmuel+bitcard.org@patriot.net

Socket.pm.patch
Path: border1.nntp.dca.giganews.com!novia!amsnews11.chello.com!xlned.com!feeder5.xlned.com!feed.xsnews.nl!border-1.ams.xsnews.nl!ecngs!feeder.ecngs.de!border1.nntp.ams.giganews.com!nntp.giganews.com!local2.nntp.ams.giganews.com!nntp.bt.com!news.bt.com.POSTED!not-for-mail
NNTP-Posting-Date: Wed, 07 Dec 2011 18:03:06 -0600
Newsgroups: comp.lang.perl.misc
Subject: Re: IO::Socket::INET hostname restrictions?
References: <4edae754$3$fuzhry+tra$mr2ice@news.patriot.net> <Nf-dnZw65uvr7kDTnZ2dnUVZ8tydnZ2d@bt.com> <4edf82d9$21$fuzhry+tra$mr2ice@news.patriot.net> <dfGdndQWk9hVEULTnZ2dnUVZ7rqdnZ2d@bt.com>
From: Ben Morrow <ben@morrow.me.uk>
Content-type: text/plain; charset=UTF-8
X-Newsreader: trn 4.0-test77 (Sep 1, 2010)
Originator: mauzo@anubis.morrow.me.uk (Ben Morrow)
Date: Wed, 7 Dec 2011 23:54:09 +0000
Message-ID: <1ua5r8-ac2.ln1@anubis.morrow.me.uk>
Lines: 42
X-Usenet-Provider: http://www.giganews.com
X-AuthenticatedUsername: NoAuthUser
X-Trace: sv3-6W3s8xwBWJ4+yCaM6dkp6rgox1m2lVg+sCrGOm/PkK43FvIOrD5BwGh8lI3mCq6PMcpgny6zD7AJ32x!vIziyMZB8hczj/6H1D1GvkShrARl6AOkp+K2QvbExwVXWfWqAZnlMTqxdrsOpBilsyksvkQ=
X-Complaints-To: abuse@btinternet.com
X-DMCA-Complaints-To: abuse@btinternet.com
X-Abuse-and-DMCA-Info: Please be sure to forward a copy of ALL headers
X-Abuse-and-DMCA-Info: Otherwise we will be unable to process your complaint properly
X-Postfilter: 1.3.40
Bytes: 3102
X-Original-Bytes: 2912
Xref: number.nntp.dca.giganews.com comp.lang.perl.misc:690120


Quoth Ben Morrow <ben@morrow.me.uk>:
> 
> I do intend to report this as a bug in IO::Socket, when I get round to
> it.

If and when you get gcc working, would you be able to test this patch?
You would need to download and unpack the IO-1.25 tarball from CPAN,
apply the patch, and verify that it both passes 'make test' and gives a
more sensible error in the situation we've been discussing. 

If you don't want to install the patched version you can use 'perl
-Mblib' from within the build directory to test the built-but-not-
installed modules. If you do want to install it, it should be perfectly
safe to install with 'make install': it will simply overwrite the IO::*
modules which came with your perl with newer versions.

Ben

diff -ur IO-1.25/lib/IO/Socket.pm IO/lib/IO/Socket.pm
--- IO-1.25/lib/IO/Socket.pm	2009-05-14 00:47:42.000000000 +0100
+++ IO/lib/IO/Socket.pm	2011-12-07 16:35:52.859688028 +0000
@@ -122,12 +122,12 @@
 		$err = $! || (exists &Errno::ETIMEDOUT ? &Errno::ETIMEDOUT : 1);
 		$@ = "connect: timeout";
 	    }
-	    elsif (!connect($sock,$addr) &&
-                not ($!{EISCONN} || ($! == 10022 && $^O eq 'MSWin32'))
-            ) {
-		# Some systems refuse to re-connect() to
-		# an already open socket and set errno to EISCONN.
-		# Windows sets errno to WSAEINVAL (10022)
+	    elsif (!getpeername($sock)) {
+                if ($!{ENOTCONN}) {
+                    # this read will fail, but will give us the error
+                    # from connect(2) in $!
+                    sysread $sock, my $tmp, 1;
+                }
 		$err = $!;
 		$@ = "connect: $!";
 	    }



@p5pRT
Copy link
Author

p5pRT commented Nov 14, 2012

From Shmuel+gen@patriot.net

In <rt-3.6.HEAD-17500-1352765729-1406.115706-94-0@​perl.org>, on
11/12/2012
  at 04​:15 PM, "James E Keenan via RT" <perlbug-followup@​perl.org>
said​:

Would it be possible to summarize the problem and attach the patch
directly?

Done. Is it possible to reassign ownership to userid shmuel? Thanks.

--
  Shmuel (Seymour J.) Metz, SysProg and JOAT
  Atid/2 <http​://patriot.net/~shmuel>
We don't care. We don't have to care, we're Congress.
(S877​: The Shut up and Eat Your spam act of 2003)

@p5pRT
Copy link
Author

p5pRT commented Nov 14, 2012

From @jkeenan

On Wed Nov 14 13​:06​:37 2012, Shmuel+gen@​patriot.net wrote​:

Done. Is it possible to reassign ownership to userid shmuel? Thanks.

You are already listed as a Requestor on this ticket. That should suffice to give you
email notifications of all posts to the ticket.

(We don't seem to use "Owner" very much. Most tickets never acquire an "Owner". I
myself tend to use it only when the ticket is one where I have applied the decisive
patch. Being an "Owner" also requires a commit bit to this queue.)

HTH

Thank you very much.
Jim Keenan

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants