Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

setsockopt() problem

26 views
Skip to first unread message

j...@invalid.address

unread,
Dec 31, 2002, 10:55:13 AM12/31/02
to
I'm seeing something that seems wrong to me. Given the following code:

#include <stdlib.h>
#include <iostream.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>

extern int errno;

int main(int argc, char *argv[])
{
int listenfd;
struct sockaddr_in addr;

if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
cerr << "socket failed: " << strerror(errno) << '\n';
return 1;
}

socklen_t flag;
socklen_t fs = sizeof flag;
setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &flag, fs);
getsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (void*)&flag,&fs);
cerr << "errno = " << strerror(errno) << '\n';
cerr << "flag = " << hex << flag << '\n';
cerr << "SO_REUSEADDR = " << hex << SO_REUSEADDR << '\n';

memset((void *)&addr, 0, sizeof (struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(9999);

if(bind(listenfd,(sockaddr *)&addr,sizeof (struct sockaddr_in)) < 0)
{
cerr << "bind failed: " << strerror(errno) << '\n';
return 1;
}

if(listen(listenfd, 5) < 0)
{
cerr << "listen failed: " << strerror(errno) << '\n';
return 1;
}
}

I get the following output:

errno = Success
flag = 1
SO_REUSEADDR = 2

I usually test flag with getsockopt() after calling setsockopt(), to
verify the correct bit is set, and this is giving me problems. Anyone
know what's happening here? I'm likely doing something stupid, but
I've been looking at it so long I probably can't see it now.

This is g++ 2.96 on RedHat 7.1

Thanks

Barry Margolin

unread,
Dec 31, 2002, 11:11:19 AM12/31/02
to
In article <m3znqmf...@invalid.address>, <j...@invalid.address> wrote:
>int main(int argc, char *argv[])
>{
> int listenfd;
> struct sockaddr_in addr;
>
> if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
> {
> cerr << "socket failed: " << strerror(errno) << '\n';
> return 1;
> }
>
> socklen_t flag;

Flag should be an int, not socklen_t.

> socklen_t fs = sizeof flag;
> setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &flag, fs);
> getsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (void*)&flag,&fs);

--
Barry Margolin, bar...@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.

D.C. van Moolenbroek

unread,
Dec 31, 2002, 11:32:53 AM12/31/02
to
<j...@invalid.address> wrote:
> socklen_t flag;
> socklen_t fs = sizeof flag;
> setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &flag, fs);

You'll want to assign a value to the the "flag" variable, before passing its
offset to setsockopt()...

Nothing seems to be wrong with the output you get though, or am I missing
something?

Regards,

David

--
class sig{static void main(String[]s){for// D.C. van Moolenbroek
(int _=0;19>_;System.out.print((char)(52^// (CS student, VU, NL)
"Y`KbddaZ}`P#KJ#caBG".charAt(_++)-9)));}}// -Java sigs look bad-


j...@invalid.address

unread,
Dec 31, 2002, 11:39:46 AM12/31/02
to
Barry Margolin <bar...@genuity.net> writes:

> In article <m3znqmf...@invalid.address>, <j...@invalid.address> wrote:
> >int main(int argc, char *argv[])
> >{
> > int listenfd;
> > struct sockaddr_in addr;
> >
> > if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
> > {
> > cerr << "socket failed: " << strerror(errno) << '\n';
> > return 1;
> > }
> >
> > socklen_t flag;
>
> Flag should be an int, not socklen_t.

That doesn't make any difference. Same output (the two are the same
size on my machine).

j...@invalid.address

unread,
Dec 31, 2002, 11:49:27 AM12/31/02
to
"D.C. van Moolenbroek" <dcvm...@cs.vu.nl> writes:

> <j...@invalid.address> wrote:
> > socklen_t flag;
> > socklen_t fs = sizeof flag;
> > setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &flag, fs);
>
> You'll want to assign a value to the the "flag" variable, before
> passing its offset to setsockopt()...

Well, yeah, I guess that would be a good thing to do :-(. Funny thing
is, it doesn't change the output. I still get a 0 return from
getsockopt(), but the bits don't match up.

> Nothing seems to be wrong with the output you get though, or am I
> missing something?

Just that the bits don't match. I expect getsockopt() to return bit
two set in flag, but I get bit 1 set.

It doesn't seem to have a practical effect on Linux, as I can
immediately restart the server whether or not I set
SO_REUSEADDR. However, my code (which runs on a number of machines)
checks to be sure the bit is set after setsockopt(), and in this case,
it's causing my code to think an error occurred.

Phil Frisbie, Jr.

unread,
Dec 31, 2002, 12:07:02 PM12/31/02
to
j...@invalid.address wrote:
>
> I'm seeing something that seems wrong to me. Given the following code:

Why not tell us why you think it is wrong? More comments below.

> #include <stdlib.h>
> #include <iostream.h>
> #include <errno.h>
> #include <unistd.h>
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <netinet/in.h>
> #include <string.h>
>
> extern int errno;
>
> int main(int argc, char *argv[])
> {
> int listenfd;
> struct sockaddr_in addr;
>
> if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
> {
> cerr << "socket failed: " << strerror(errno) << '\n';
> return 1;
> }
>
> socklen_t flag;

Should be an int.

> socklen_t fs = sizeof flag;

Again, should be an int. Even though on your platform socklen_t may be the same
as int does not make it right. Details like this can REALLY screw you up when
you try to compile on a different platform.

> setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &flag, fs);

Here is an error! You did not assign a value to flag before you used it. You
should have received a compiler warning about that.

> getsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (void*)&flag,&fs);

Should use (char *) and not (void *). Also, you should be checking the return
values of setsockopt() and getsockopt().

> cerr << "errno = " << strerror(errno) << '\n';

At this point, any error set by setsockopt() is gone because getsockopt()
succeeded.

> cerr << "flag = " << hex << flag << '\n';
> cerr << "SO_REUSEADDR = " << hex << SO_REUSEADDR << '\n';
>
> memset((void *)&addr, 0, sizeof (struct sockaddr_in));
> addr.sin_family = AF_INET;
> addr.sin_addr.s_addr = htonl(INADDR_ANY);
> addr.sin_port = htons(9999);
>
> if(bind(listenfd,(sockaddr *)&addr,sizeof (struct sockaddr_in)) < 0)
> {
> cerr << "bind failed: " << strerror(errno) << '\n';
> return 1;
> }
>
> if(listen(listenfd, 5) < 0)
> {
> cerr << "listen failed: " << strerror(errno) << '\n';
> return 1;
> }
> }
>
> I get the following output:
>
> errno = Success
> flag = 1
> SO_REUSEADDR = 2
>
> I usually test flag with getsockopt() after calling setsockopt(), to
> verify the correct bit is set, and this is giving me problems. Anyone
> know what's happening here? I'm likely doing something stupid, but
> I've been looking at it so long I probably can't see it now.
>
> This is g++ 2.96 on RedHat 7.1
>
> Thanks


Phil Frisbie, Jr.
Hawk Software
http://www.hawksoft.com

Barry Margolin

unread,
Dec 31, 2002, 12:17:28 PM12/31/02
to
In article <3E11CEB5...@hawksoft.com>,
Phil Frisbie, Jr. <ph...@hawksoft.com> wrote:

>j...@invalid.address wrote:
>Should be an int.
>
>> socklen_t fs = sizeof flag;
>
>Again, should be an int.

No it shouldn't. The Solaris 2.6 man page says it should be size_t, and
Unix Network Programming Vol.1 says socklen_t.

>> setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &flag, fs);
>
>Here is an error! You did not assign a value to flag before you used it. You
>should have received a compiler warning about that.

Since it's only be used as the argument to the & operator, I wouldn't
expect a warning. The compiler can't tell whether the function is using it
as input or output.

D.C. van Moolenbroek

unread,
Dec 31, 2002, 12:29:01 PM12/31/02
to
<j...@invalid.address> wrote:
> "D.C. van Moolenbroek" <dcvm...@cs.vu.nl> writes:
>
> > <j...@invalid.address> wrote:
> > You'll want to assign a value to the the "flag" variable, before
> > passing its offset to setsockopt()...
>
> Well, yeah, I guess that would be a good thing to do :-(. Funny thing
> is, it doesn't change the output.

That's just "luck"; setsockopt(SO_REUSEADDR) expects either a zero or a
nonzero value, and the chance that the flag-variable is "accidentally"
initialized to zero will usually be pretty small (depending on quite a few
things). But you can never assume anything at that point of course...

> I still get a 0 return from
> getsockopt(), but the bits don't match up.
>
> > Nothing seems to be wrong with the output you get though, or am I
> > missing something?
>
> Just that the bits don't match. I expect getsockopt() to return bit
> two set in flag, but I get bit 1 set.
>

getsockopt() returns the particular value assigned to a setting. For
SO_REUSEADDR, that's a boolean, not a bitmask or something; if you get back
a nonzero value, it's set, otherwise it's not. There is no further
definition of "nonzero value" here.

So if you want to test whether SO_REUSEADDR is set, it's sufficient to test
the value returned by getsockopt() on being nonzero. It is IMHO doubtful how
useful such a check is though; after all, if setsockopt() succeeded, you can
assume that the flag is really set...

> It doesn't seem to have a practical effect on Linux, as I can
> immediately restart the server whether or not I set
> SO_REUSEADDR.

I assume that you have only set up a listening server so far, and not really
let it accept connections yet. Once you really create connections to the
server, and then restart it, the leftovers of these connections will be the
cause of bind() failing with an "address already in use" error, which will
not occur when you set SO_REUSEADDR. That's the basic (simplified) idea.

Peter Jones

unread,
Dec 31, 2002, 12:31:11 PM12/31/02
to
On Tue, 31 Dec 2002 15:55:13 +0000, jo wrote:
> #include <stdlib.h>
> #include <iostream.h>
> #include <errno.h>
> #include <unistd.h>
> #include <sys/types.h>
> #include <sys/socket.h>
> #include <netinet/in.h>
> #include <string.h>

Why are you still using iostream.h?

> socklen_t flag;
> socklen_t fs = sizeof flag;
> setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &flag, fs);
> getsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (void*)&flag,&fs);

You should recompile this code with -Wall and see if you get a warning about
using "flag" before it was initized with a value. You are using flag in a
call to setsockopt here without having set it to 1 first.

Save yourself some time and use: http://pmade.org/pjones/software/netxx/

--
Peter Jones <unix;c++;crypto;vi;4wd;geek> [ http://pmade.org ]

j...@invalid.address

unread,
Dec 31, 2002, 12:35:30 PM12/31/02
to
"Phil Frisbie, Jr." <ph...@hawksoft.com> writes:

> j...@invalid.address wrote:
> >
> > I'm seeing something that seems wrong to me. Given the following
> > code:
>
> Why not tell us why you think it is wrong? More comments below.

I expect flag to have bit two set, since that's the value of
SO_REUSEADDR on my platform.

> > socklen_t flag;
>
> Should be an int.

Doesn't make a difference, they're the same size on my platform.

> > socklen_t fs = sizeof flag;
>
> Again, should be an int.

My man page says socklen_t.

> Even though on your platform socklen_t may be the same as int does
> not make it right. Details like this can REALLY screw you up when
> you try to compile on a different platform.

Yep. That's what the preprocessor is for though. If the man page (and
the header file) say socklen_t for g++, then that's what I use when
compiling with g++.

> > setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &flag, fs);
>
> Here is an error! You did not assign a value to flag before you used
> it. You should have received a compiler warning about that.

Yes, someone else pointed that out. Oddly enough though, it doesn't
change anything. I still get exactly the same results.

> > getsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (void*)&flag,&fs);
>
> Should use (char *) and not (void *). Also, you should be checking the return
> values of setsockopt() and getsockopt().
>
> > cerr << "errno = " << strerror(errno) << '\n';
>
> At this point, any error set by setsockopt() is gone because
> getsockopt() succeeded.

Yes, but *why* did it succeed, if it doesn't return bit two set?

j...@invalid.address

unread,
Dec 31, 2002, 12:52:26 PM12/31/02
to
"D.C. van Moolenbroek" <dcvm...@cs.vu.nl> writes:

> <j...@invalid.address> wrote:
> > "D.C. van Moolenbroek" <dcvm...@cs.vu.nl> writes:
> >
> > > <j...@invalid.address> wrote:
> > > You'll want to assign a value to the the "flag" variable, before
> > > passing its offset to setsockopt()...
> >
> > Well, yeah, I guess that would be a good thing to do :-(. Funny
> > thing is, it doesn't change the output.
>
> That's just "luck"; setsockopt(SO_REUSEADDR) expects either a zero
> or a nonzero value, and the chance that the flag-variable is
> "accidentally" initialized to zero will usually be pretty small
> (depending on quite a few things). But you can never assume anything
> at that point of course...

I guess I was looking at it too long. That's fairly obvious now that
you mention it.

> getsockopt() returns the particular value assigned to a setting. For
> SO_REUSEADDR, that's a boolean, not a bitmask or something; if you
> get back a nonzero value, it's set, otherwise it's not. There is no
> further definition of "nonzero value" here.

Ahh, that's the part I was missing. For some reason I had the idea
that it returned a bitmap, and the man page doesn't say either way.

> So if you want to test whether SO_REUSEADDR is set, it's sufficient
> to test the value returned by getsockopt() on being nonzero. It is
> IMHO doubtful how useful such a check is though; after all, if
> setsockopt() succeeded, you can assume that the flag is really
> set...

I do it that way because of the explanation in Stevens' UNP. I don't
have my copy here, and don't recall it now (I originally wrote the
code years ago, and I'm just now moving it to linux).

The source code for the book does a check like this as well.

> > It doesn't seem to have a practical effect on Linux, as I can
> > immediately restart the server whether or not I set
> > SO_REUSEADDR.
>
> I assume that you have only set up a listening server so far, and
> not really let it accept connections yet. Once you really create
> connections to the server, and then restart it, the leftovers of
> these connections will be the cause of bind() failing with an
> "address already in use" error, which will not occur when you set
> SO_REUSEADDR. That's the basic (simplified) idea.

Thanks very much.

Barry Margolin

unread,
Dec 31, 2002, 1:36:36 PM12/31/02
to
In article <m3fzsef...@invalid.address>, <j...@invalid.address> wrote:
>Ahh, that's the part I was missing. For some reason I had the idea
>that it returned a bitmap, and the man page doesn't say either way.

What did you think it was a bitmap of? If there were a call to get *all*
the flag options, I could see that being a bitmap. But why would a call to
get a single option's value return a map?

j...@invalid.address

unread,
Dec 31, 2002, 5:10:39 PM12/31/02
to
Barry Margolin <bar...@genuity.net> writes:

> In article <m3fzsef...@invalid.address>, <j...@invalid.address> wrote:
> >Ahh, that's the part I was missing. For some reason I had the idea
> >that it returned a bitmap, and the man page doesn't say either way.
>
> What did you think it was a bitmap of? If there were a call to get
> *all* the flag options, I could see that being a bitmap. But why
> would a call to get a single option's value return a map?

Well, it does on the platforms I most often work on (AIX and Solaris).

Both of those platforms give the following output from the test
program:

flag = 4
SO_REUSEADDR = 4

which looks like a bitmap to me.

nobody

unread,
Dec 31, 2002, 5:12:56 PM12/31/02
to
j...@invalid.address wrote:
> "Phil Frisbie, Jr." <ph...@hawksoft.com> writes:
>
> > j...@invalid.address wrote:
> > >
> > > I'm seeing something that seems wrong to me. Given the following
> > > code:
[ ... ]

> > > int listenfd;
> > > struct sockaddr_in addr;
> > >
> > > if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)

style point: this should be PF_INET (it happens that AF_INET == PF_INET,
but this is not officially guaranteed; the man page will bear this out)

> > > {
> > > cerr << "socket failed: " << strerror(errno) << '\n';
> > > return 1;
> > > }
> > >
> > > socklen_t flag;

> > > socklen_t fs = sizeof flag;

> > > setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &flag, fs);

> > > getsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (void*)&flag,&fs);


> > > cerr << "errno = " << strerror(errno) << '\n';

> > > cerr << "flag = " << hex << flag << '\n';
> > > cerr << "SO_REUSEADDR = " << hex << SO_REUSEADDR << '\n';

[ ... ]


> > > I get the following output:
> > >
> > > errno = Success
> > > flag = 1
> > > SO_REUSEADDR = 2

[ ... ]


> > > This is g++ 2.96 on RedHat 7.1
> >

> > Why not tell us why you think it is wrong? More comments below.
>
> I expect flag to have bit two set, since that's the value of
> SO_REUSEADDR on my platform.

That's not how setsockopt/getsockopt work. For this option the
"flag" is an int used as an on/off indicator. Such parameters
are set to zero to disable the option or to indicate that it is
disabled, and are set to a non-zero value (typically 1) to
enable the option or to indicate this it is enabled. The man
page bears this out:

Most socket-level options utilize an int parameter for
optval. For setsockopt, the parameter should be non-zero
to enable a boolean option, or zero if the option is to be
disabled.

So, the output you get from getsockopt indicates that the option
was, in fact, set.

> > > socklen_t flag;
> >
> > Should be an int.
>
> Doesn't make a difference, they're the same size on my platform.

It should be an int (as the man page says) if you want to make
sure that your code can run on future versions of your platform
(the definition of socklen_t COULD change, after all).

A point of greater practical importance is that this needs to be
initialized to a non-zero value before being fed to setsockopt in
order to set the option. Your code does not do this. It seems to
be happening by accident when you run your program but relying on
this is bad idea. I suggest that you change the declaration to
"int flag = 1".

> > > socklen_t fs = sizeof flag;
> >
> > Again, should be an int.
>
> My man page says socklen_t.

Indeed it does.

> > Even though on your platform socklen_t may be the same as int does
> > not make it right. Details like this can REALLY screw you up when
> > you try to compile on a different platform.
>
> Yep. That's what the preprocessor is for though. If the man page (and
> the header file) say socklen_t for g++, then that's what I use when
> compiling with g++.

That's correct. But you need to be aware that this will not port to
other platforms. [I think it was a bad idea for Linux to deviate from
the de-fact standard BSD socket interface; all it does is create
portability problems.]

> > > setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &flag, fs);
> >
> > Here is an error! You did not assign a value to flag before you used
> > it. You should have received a compiler warning about that.
>
> Yes, someone else pointed that out. Oddly enough though, it doesn't
> change anything. I still get exactly the same results.

That's because "flag" just happened to have a non-zero value. That
could change next time you run the code.

> > > getsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (void*)&flag,&fs);
> >
> > Should use (char *) and not (void *). Also, you should be checking the
> > return values of setsockopt() and getsockopt().

He's right. Your platform declares this as (void *), but the normal
BSD interface declares it as (char *). You don't need the cast to
(void *) because both C++ and C allow an implicit conversion from
(T *) to (void *) for any object type T. Putting in a (char *) in
its place will make it easier to port to other platforms, and will
not prevent a clean compilation on your Linux platform.

> > > cerr << "errno = " << strerror(errno) << '\n';
> >
> > At this point, any error set by setsockopt() is gone because
> > getsockopt() succeeded.
>
> Yes, but *why* did it succeed, if it doesn't return bit two set?

Actually errno set by setsockopt() would be gone whether or not
getsockopt() succeeded. The latter succeeded because you called
it with valid parameters. The flag value could be any non-zero
value (on my Solaris 2.4_x86 platform SO_REUSEADDR is 4 and
getsockopt returns 4 in flag).

Now, let me suggest an improved version of the code that will compile
cleanly both as a C program and as a C++ program, and which will do
the same on a Solaris 2.4_x86 platform. Note in particular how
perror is much more compact (and provides better messages) than
your homebrew alternative. Even if you like <iostream> for other
stuff, you should use it!

#include <stdlib.h>
#include <stdio.h>


#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>

extern int errno;

int main(void)
{
int listenfd = -1;
int result = -1;
int flag = 1;
#ifdef __linux


socklen_t fs = sizeof flag;

#else
int fs = sizeof flag;
#endif
struct sockaddr_in addr;
const int backlog = 5;

if((listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket failed");
return 1;
}

result = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, fs);
printf("result = %d, errno = %d, flag = 0x%08x, SO_REUSEADDR = 0x%08x\n",
result, errno, flag, SO_REUSEADDR);
result = getsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, &fs);
printf("result = %d, errno = %d, flag = 0x%08x, SO_REUSEADDR = 0x%08x\n",
result, errno, flag, SO_REUSEADDR);

memset(&addr, 0, sizeof (struct sockaddr_in));


addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(9999);

if(bind(listenfd, (struct sockaddr *)&addr, sizeof (struct sockaddr_in)) < 0)
{
perror("bind failed");
return 1;
}

if(listen(listenfd, backlog) < 0)
{
perror("listen failed");
return 1;
}

return 0;
}

Andrew Gierth

unread,
Dec 31, 2002, 7:58:00 PM12/31/02
to
>>>>> "nobody" == nobody <nobody@[127.0.0.1]> writes:

>> > > if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)

nobody> style point: this should be PF_INET

no, AF_INET is correct.

nobody> (it happens that AF_INET == PF_INET, but this is not
nobody> officially guaranteed; the man page will bear this out)

PF_INET would have been correct for historical reasons (only), but in
fact the PF_* names have never been standardised, and are not even
mentioned in current standards (and are therefore not even guaranteed
to exist at all) except to the extent that sys/socket.h is still
allowed to define them as macros.

I don't know who is propagating this particular piece of nonsense, but
I wish they'd stop it.

--
Andrew.

comp.unix.programmer FAQ: see <URL: http://www.erlenstar.demon.co.uk/unix/>

Barry Margolin

unread,
Dec 31, 2002, 8:18:00 PM12/31/02
to

When you said bitmap, I thought you meant something with multiple bits set;
that's why I thought it was curious that you expected this.

I expect that in some implementations, the code for getsockopt() looks
something like:

return socket.options & flag

where socket.options is a bit map, and all the SO_XXX values are masks for
the appropriate bit, so this will then return either 0 or SO_XXX.

But it's not the only way to implement it, and other code might result in
different values, as long as they have the appropriate boolean state.

nobody

unread,
Jan 1, 2003, 6:15:10 AM1/1/03
to
Andrew Gierth wrote:
> >>>>> "nobody" == nobody <nobody@[127.0.0.1]> writes:
>
> >> > > if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
>
> nobody> style point: this should be PF_INET
>
> no, AF_INET is correct.

Not according to the relevant man pages.

> nobody> (it happens that AF_INET == PF_INET, but this is not
> nobody> officially guaranteed; the man page will bear this out)
>
> PF_INET would have been correct for historical reasons (only), but in
> fact the PF_* names have never been standardised, and are not even
> mentioned in current standards (and are therefore not even guaranteed
> to exist at all) except to the extent that sys/socket.h is still
> allowed to define them as macros.

What standards?

> I don't know who is propagating this particular piece of nonsense, but
> I wish they'd stop it.

SOCKET(2) Linux Programmer's Manual SOCKET(2)


NAME
socket - create an endpoint for communication

SYNOPSIS
#include <sys/types.h>
#include <sys/socket.h>

int socket(int domain, int type, int protocol);

DESCRIPTION
Socket creates an endpoint for communication and returns a
descriptor.

The domain parameter specifies a communications domain
within which communication will take place; this selects
the protocol family which should be used. These families
are defined in <sys/socket.h>. The currently understood
formats include:

PF_UNIX, PF_LOCAL
UNIX protocols for local communication

PF_INET
IPv4 Internet protocols; see ip(4)

PF_INET6
IPv6 Internet protocols

[ ... ]

The man pages for Solaris 2.4 through Solaris 8 say something very
similar, as do those for Free BSD, Net BSD, and Open BSD.

'nuff said.

nobody

j...@invalid.address

unread,
Jan 1, 2003, 6:44:39 AM1/1/03
to
nobody <nobody@[127.0.0.1]> writes:

> Andrew Gierth wrote:
> > >>>>> "nobody" == nobody <nobody@[127.0.0.1]> writes:
> >
> > >> > > if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
> >
> > nobody> style point: this should be PF_INET
> >
> > no, AF_INET is correct.
>
> Not according to the relevant man pages.
>
> > nobody> (it happens that AF_INET == PF_INET, but this is not
> > nobody> officially guaranteed; the man page will bear this out)
> >
> > PF_INET would have been correct for historical reasons (only), but in
> > fact the PF_* names have never been standardised, and are not even
> > mentioned in current standards (and are therefore not even guaranteed
> > to exist at all) except to the extent that sys/socket.h is still
> > allowed to define them as macros.
>
> What standards?

POSIX/SUS defines AF* macros, but not PF*

http://www.opengroup.org/onlinepubs/007904975/basedefs/sys/socket.h.html

> > I don't know who is propagating this particular piece of nonsense,
> > but I wish they'd stop it.
>
> SOCKET(2) Linux Programmer's Manual SOCKET(2)
>
>
> NAME
> socket - create an endpoint for communication
>
> SYNOPSIS
> #include <sys/types.h>
> #include <sys/socket.h>
>
> int socket(int domain, int type, int protocol);
>
> DESCRIPTION
> Socket creates an endpoint for communication and returns a
> descriptor.
>
> The domain parameter specifies a communications domain
> within which communication will take place; this selects
> the protocol family which should be used. These families
> are defined in <sys/socket.h>. The currently understood
> formats include:

This doesn't say the PF_* form is standard, only that it's one of the
currently understood formats. In fact, Linux and the others you
mentioned also understand AF_* macros, which are standard.

Casper H.S. Dik

unread,
Jan 1, 2003, 11:06:40 AM1/1/03
to
nobody <nobody@[127.0.0.1]> writes:

>What standards?

The UNIX standards.

>> I don't know who is propagating this particular piece of nonsense, but
>> I wish they'd stop it.

>SOCKET(2) Linux Programmer's Manual SOCKET(2)

If that's what the Linux manual suggest, it is wrong.


Read the Unix manual pages at http://www.opengroup.org

Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.

nobody

unread,
Jan 1, 2003, 2:25:40 PM1/1/03
to
j...@invalid.address writes:
>
> nobody <nobody@[127.0.0.1]> writes:
>
> > Andrew Gierth wrote:
> > > >>>>> "nobody" == nobody <nobody@[127.0.0.1]> writes:
> > >
> > > >> > > if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
> > >
> > > nobody> style point: this should be PF_INET
> > >
> > > no, AF_INET is correct.
> >
> > Not according to the relevant man pages.
> >
> > > nobody> (it happens that AF_INET == PF_INET, but this is not
> > > nobody> officially guaranteed; the man page will bear this out)
> > >
> > > PF_INET would have been correct for historical reasons (only), but in
> > > fact the PF_* names have never been standardised, and are not even
> > > mentioned in current standards (and are therefore not even guaranteed
> > > to exist at all) except to the extent that sys/socket.h is still
> > > allowed to define them as macros.
> >
> > What standards?
>
> POSIX/SUS defines AF* macros, but not PF*
>
> http://www.opengroup.org/onlinepubs/007904975/basedefs/sys/socket.h.html

Thanks for the pointer. It's interesting, but it's not authoritative
for any particular platform. The platform's manuals are.

[ snip linux man page excerpt showing PF_* as "domain" values ]


> This doesn't say the PF_* form is standard, only that it's one of the
> currently understood formats. In fact, Linux and the others you
> mentioned also understand AF_* macros, which are standard.

The AF_* are not mentioned in this platform's documentation as possible
values of socket "domain" parameters. They figure as values of
sin_family in the sockaddr structure. It's true, of course, that each
PF_* is in fact the same as the corresponding AF_*.

Casper H.S. Dik writes:
> If that's what the Linux manual suggest, it is wrong.

It's not just Linux; its Solaris, too, at least up thru Solaris 8,
and every *BSD that I can find on line.

> Read the Unix manual pages at http://www.opengroup.org

Why in the world would anyone consider that more authoritative than
the platform's man page???

Anyway, I see that this is an old chestnut that's been generating
more heat than light for as long as it has been discussed. Here
is an excerpt from article <4k1grt$5...@noao.edu> by the late
W. Richard Stevens dated 1996/04/04. Those who are interested
can find the rest of the thread on google.

W. Richard Stevens wrote:
> > So why the difference?
> > AF vs PF?
> > What does the difference mean?
>
> AF = address family. These constants go into the sin_family member of the
> socket address structure.
>
> PF = protocol family. These constants are the first argument to socket().
>
> Historically AF_foo = PF_foo, so lots of code, exmaples, books, man pages,
> etc. use them interchangeably. I've never seen an example where the two
> are different.

I've had enough of this discussion.

nobody

Casper H.S. Dik

unread,
Jan 1, 2003, 3:43:56 PM1/1/03
to
nobody <nobody@[127.0.0.1]> writes:

>The AF_* are not mentioned in this platform's documentation as possible
>values of socket "domain" parameters. They figure as values of
>sin_family in the sockaddr structure. It's true, of course, that each
>PF_* is in fact the same as the corresponding AF_*.

This is the defacto standard; the PF_* constants were added almost as
an afterthought and were never enforced (i.e., they really ought to go)


>Casper H.S. Dik writes:
>> If that's what the Linux manual suggest, it is wrong.

>It's not just Linux; its Solaris, too, at least up thru Solaris 8,
>and every *BSD that I can find on line.

Some Solaris manual pages, not the standards conformant (socket(3xnet))
pages.

The standard defined behaviour works on all system; it's bad to
insist on old legacy interfaces that served no purpose; the standardization
process rightly optimized them out.

>Why in the world would anyone consider that more authoritative than
>the platform's man page???

Because we're in "comp.unix.programmer" and "comp.protocols.tcp-ip", not
in "comp.someos.software.development".

j...@invalid.address

unread,
Jan 1, 2003, 6:22:22 PM1/1/03
to
nobody <nobody@[127.0.0.1]> writes:

> j...@invalid.address writes:
> >
> > nobody <nobody@[127.0.0.1]> writes:
> >
> > > Andrew Gierth wrote:
> > > > >>>>> "nobody" == nobody <nobody@[127.0.0.1]> writes:
> > > >
> > > > >> > > if((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
> > > >
> > > > nobody> style point: this should be PF_INET
> > > >
> > > > no, AF_INET is correct.
> > >
> > > Not according to the relevant man pages.
> > >
> > > > nobody> (it happens that AF_INET == PF_INET, but this is not
> > > > nobody> officially guaranteed; the man page will bear this out)
> > > >
> > > > PF_INET would have been correct for historical reasons (only),
> > > > but in fact the PF_* names have never been standardised, and
> > > > are not even mentioned in current standards (and are therefore
> > > > not even guaranteed to exist at all) except to the extent that
> > > > sys/socket.h is still allowed to define them as macros.
> > >
> > > What standards?
> >
> > POSIX/SUS defines AF* macros, but not PF*
> >
> > http://www.opengroup.org/onlinepubs/007904975/basedefs/sys/socket.h.html
>
> Thanks for the pointer. It's interesting, but it's not authoritative
> for any particular platform. The platform's manuals are.

It's authoritative for any platform claiming POSIX compliance, which
is quite a few.

I think I understand your point, I've made one similar to it myself at
times. If the platform one is working on is not standard compliant,
then of course all you have to go on is what the platform actually
does. In practice, however, it's better to write standard compliant
code as much as possible and ifdef around nonstandard implementations.

0 new messages