Subject: Re: Strange behavious of getpeername(2) on pipe
To: Martin J. Laubach <mjl@emsi.priv.at>
From: Frank van der Linden <fvdl@wasabisystems.com>
List: tech-kern
Date: 03/27/2001 15:47:47
On Tue, Mar 27, 2001 at 03:22:05PM +0200, Martin J. Laubach wrote:
> if(getpeername(fd) != 0 && errno == ENOTCONN)
> {
> ... fastcgi, input comes via socket and special protocol ...
> }
> else
> {
> ... normal cgi, input comes via pipe ...
> }
>
> Unfortunately, this works on all tested unixoid systems (Solaris 7,
> AIX, SINIS, FreeBSD, even OpenBSD!) but not on NetBSD.
>
> Therefore: ist our behaviour correct, and if so, what work-arounds
> are possible?
Our pipe call is based on the old BSD implementation, using a pair
of sockets. getpeername() should fail, but because of the implementation,
it succeeds as a side effect.
This doesn't happen anymore on the other BSDs (nor on any other modern
Unix I know), because they adopted a VM-based pipe implementation. Which
is a lot faster, and we should adopt it too. It's a localized, clean
change (basically a seperate source file), so if someone wants to look
at integrating it, be my guest.
Anyway, to determine if something is not a remote socket (i.e.
a plain filedescriptor or an AF_LOCAL socket), you might
want to do something like:
int
is_remote_socket(int fd)
{
struct sockaddr_storage ss;
socklen_t slen;
slen = sizeof ss;
if (getsockname(fd, &ss, &slen) == -1 || ss.ss_len == 0 ||
ss.ss_family == AF_LOCAL)
return 0;
return 1;
}
I'm not sure if this is exactly what you're looking for, but
in combination with getpeername() and the connected state of
a socket you can get the data you want in this case. I assume
that for CGI stuff you're not listening to AF_LOCAL (AF_UNIX)
sockets.
- Frank
--
Frank van der Linden fvdl@wasabisystems.com
======================================================================
Quality NetBSD CDs, Support & Service. http://www.wasabisystems.com/