List Info

Thread: Network programming question




Network programming question
user name
2008-03-13 11:10:01
Hi,

I'd like to know why the inet_pton(3) doesn't fill in the
address
family of the proper structure passed into it.  I'm at a
complete loss
for why.  Here's the prototype:

int inet_pton(int af, const char * restrict src, void *
restrict dst);


Three arguments only.  The address family, hm, I'm passing
it in; the
address string in printable ASCII text, and a void pointer
to the
address structure to put the address into, presumably one of
the
sockaddr_* family structures for AF_INET or AF_INET6
(further, the man
page says that this function is only valid for these two
families now
anyway).

>From some coding for a program, I did find that this
function,
inet_pton(3), *does* in fact mangle the sin_family member of
the
sockaddr_in structure, so why not "mangle" it to
what it should be?  I
was doing something like this:

// valid code above
sockaddr_in   sa;

sa.sin_family = AF_INET;
sa.sin_port = htons(3252);

inet_pton(AF_INET, "192.168.0.1", &sa);

sendto(sa, msg, strlen(msg), 0, (struct sockaddr*)&sa,
sizeof(sa));


The call to sendto is wrapped in an if an was failing for
errno code
47, Address family not supported by protocol (I was using
UDP).  I
changed the assignment of AF_INET to the sa.sin_family
member to
*after* the call to inet_pton(3) and suddenly everything
worked.  Why?
 Since the address family was used by inet_pton(3) to figure
out how
to read the address and assign it to sa.sin_addr.s_addr, why
not
simply assign AF_INET to the address family member in
inet_pton(3)?

I'm not trying to be argumentative.  I'm just curious.  It
seems like
redundancy.  I've used the address family to tell
inet_pton(3) how to
operate, and then this function can't assign it to the
sockaddr_in
structure passed to it?  This makes little sense.  In case
it's
because I'm using older FBSD libraries that had a flaw
fixed, I'm
using FreeBSD 6.2-RELEASE-p4.  Is this because that's how
POSIX
defined it to work?  Is this the right venue or should I try
one of
the other mailing lists?

Thanks,
Andy



-- 
 A: Because it messes up the order in which people normally
read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
_______________________________________________
freebsd-questionsfreebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-que
stions
To unsubscribe, send any mail to
"freebsd-questions-unsubscribefreebsd.org"

Re: Network programming question
country flaguser name
United States
2008-03-13 12:45:15

Andrew Falanga presented these words - circa 3/13/08 9:10
AM->
> Hi,
> 
> I'd like to know why the inet_pton(3) doesn't fill in
the address
> family of the proper structure passed into it.  I'm at
a complete loss
> for why.  Here's the prototype:
> 
> int inet_pton(int af, const char * restrict src, void *
restrict dst);
> 
> 
> Three arguments only.  The address family, hm, I'm
passing it in; the
> address string in printable ASCII text, and a void
pointer to the
> address structure to put the address into, presumably
one of the
> sockaddr_* family structures for AF_INET or AF_INET6
(further, the man
> page says that this function is only valid for these
two families now
> anyway).
> 
>>From some coding for a program, I did find that this
function,
> inet_pton(3), *does* in fact mangle the sin_family
member of the
> sockaddr_in structure, so why not "mangle" it
to what it should be?  I
> was doing something like this:
> 
> // valid code above
> sockaddr_in   sa;
> 
> sa.sin_family = AF_INET;
> sa.sin_port = htons(3252);
> 
> inet_pton(AF_INET, "192.168.0.1", &sa);
> 
> sendto(sa, msg, strlen(msg), 0, (struct
sockaddr*)&sa, sizeof(sa));
> 

See man inet_pton . . . for details.

Briefly, inet_pton() doesn't understand sockaddr structures.
 Instead,
it only understands in_addr or in6_addr structures which are
included
inside the sockaddr structure.  So your above example should
be changed
to

   // valid code above
   sockaddr_in sa;
   int res;

   sa.sin_family = AF_INET;
   sa.sin_port = htons(3252);

   if ((res = inet_pton(AF_INET, "192.168.0.1",
&sa.sin_addr)) < 0)
     perror("inet_pton");

   if (!res)  // error occurred
     fprintf(stderr, "Address notation incorrect for
AF_INET addressn");

> 
> The call to sendto is wrapped in an if an was failing
for errno code
> 47, Address family not supported by protocol (I was
using UDP).  I
> changed the assignment of AF_INET to the sa.sin_family
member to
> *after* the call to inet_pton(3) and suddenly
everything worked.  Why?
>  Since the address family was used by inet_pton(3) to
figure out how
> to read the address and assign it to
sa.sin_addr.s_addr, why not
> simply assign AF_INET to the address family member in
inet_pton(3)?
>

Because it is treating the sockaddr_in structure as an
in_addr structure
which is clobbering the sin_family field.

> I'm not trying to be argumentative.  I'm just curious. 
It seems like
> redundancy.  I've used the address family to tell
inet_pton(3) how to
> operate, and then this function can't assign it to the
sockaddr_in
> structure passed to it?  This makes little sense.  In
case it's
> because I'm using older FBSD libraries that had a flaw
fixed, I'm
> using FreeBSD 6.2-RELEASE-p4.  Is this because that's
how POSIX
> defined it to work?  Is this the right venue or should
I try one of
> the other mailing lists?
> 

RTM,

Patrick
_______________________________________________
freebsd-questionsfreebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-que
stions
To unsubscribe, send any mail to
"freebsd-questions-unsubscribefreebsd.org"

Re: Network programming question
user name
2008-03-13 13:11:28
On Thu, Mar 13, 2008 at 11:45 AM, Patrick Mahan
<mahanmahan.org> wrote:
>
>
>  Andrew Falanga presented these words - circa 3/13/08
9:10 AM->
>
> > Hi,
>
>  See man inet_pton . . . for details.
>
>  Briefly, inet_pton() doesn't understand sockaddr
structures.  Instead,
>  it only understands in_addr or in6_addr structures
which are included
>  inside the sockaddr structure.  So your above example
should be changed
>  to
>

Ok, I should have thought of that when reading the manual.

>
>    if ((res = inet_pton(AF_INET,
"192.168.0.1", &sa.sin_addr)) < 0)
>      perror("inet_pton");
>
>
>  Because it is treating the sockaddr_in structure as an
in_addr structure
>  which is clobbering the sin_family field.
>

If this is true, then why are my packets sent at all?  The
definition
of sockaddr_in (from /usr/include/netinet/in.h):

struct sockaddr_in {
	uint8_t	sin_len;
	sa_family_t	sin_family;
	in_port_t	sin_port;
	struct	in_addr sin_addr;
	char	sin_zero[8];
};


The definition of in_addr (from /usr/include/netinet/in.h):

struct in_addr {
	in_addr_t s_addr;
};

The definition of in_addr_t (from
/usr/include/netinet/in.h):
typedef	uint32_t		in_addr_t;

Passing in what I have, the address should indeed (as you've
pointed
out) clobber the sin_family member.  However, since in_addr
is
basically an unsigned integer, i.e. 4 bytes wide, shouldn't
inet_pton(3) clobber sin_len, sin_family & sin_port
before ever
reaching sin_addr?  The sin_len & sin_family are 8 bit
quantities, the
sin_port is 16 bits, that's 32.  If inet_pton(3) is
expecting only an
in_addr I would think that a call to sendto(2) would fail
because the
address in sin_addr is not filled, correct?

Andy

-- 
 A: Because it messes up the order in which people normally
read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
_______________________________________________
freebsd-questionsfreebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-que
stions
To unsubscribe, send any mail to
"freebsd-questions-unsubscribefreebsd.org"

Re: Network programming question
country flaguser name
United States
2008-03-14 00:57:03

Andrew Falanga presented these words - circa 3/13/08 11:11
AM->
> On Thu, Mar 13, 2008 at 11:45 AM, Patrick Mahan
<mahanmahan.org> wrote:
>>
>>  Andrew Falanga presented these words - circa
3/13/08 9:10 AM->
>>
>>> Hi,
>>  See man inet_pton . . . for details.
>>
>>  Briefly, inet_pton() doesn't understand sockaddr
structures.  Instead,
>>  it only understands in_addr or in6_addr structures
which are included
>>  inside the sockaddr structure.  So your above
example should be changed
>>  to
>>
> 
> Ok, I should have thought of that when reading the
manual.
> 
>>    if ((res = inet_pton(AF_INET,
"192.168.0.1", &sa.sin_addr)) < 0)
>>      perror("inet_pton");
>>
>>
>>  Because it is treating the sockaddr_in structure
as an in_addr structure
>>  which is clobbering the sin_family field.
>>
> 
> If this is true, then why are my packets sent at all? 
The definition
> of sockaddr_in (from /usr/include/netinet/in.h):
> 
> struct sockaddr_in {
> 	uint8_t	sin_len;
> 	sa_family_t	sin_family;
> 	in_port_t	sin_port;
> 	struct	in_addr sin_addr;
> 	char	sin_zero[8];
> };
> 
> 
> The definition of in_addr (from
/usr/include/netinet/in.h):
> 
> struct in_addr {
> 	in_addr_t s_addr;
> };
> 
> The definition of in_addr_t (from
/usr/include/netinet/in.h):
> typedef	uint32_t		in_addr_t;
> 
> Passing in what I have, the address should indeed (as
you've pointed
> out) clobber the sin_family member.  However, since
in_addr is
> basically an unsigned integer, i.e. 4 bytes wide,
shouldn't
> inet_pton(3) clobber sin_len, sin_family & sin_port
before ever
> reaching sin_addr?  The sin_len & sin_family are 8
bit quantities, the
> sin_port is 16 bits, that's 32.  If inet_pton(3) is
expecting only an
> in_addr I would think that a call to sendto(2) would
fail because the
> address in sin_addr is not filled, correct?

inet_pton() clobbered the fields you pointed out.  In fact
the sin_family
field was being set to 0x01 which caused your initial
EADDRNOTSUPPORT error
you were seeing.  You quick change fixed that problem. 
However, (depending
on how sockaddr_in structure is actually allocated) the
sin_addr field was
0.0.0.0.  This is actually an accepted form of the broadcast
address for UDP
packets.  I forget exactly who the culprit was (Sun comes to
mind) but there
was a need to allow broadcasts to 0.0.0.0 (which is also
know as INADDR_ANY).
So, therefore, sendto() succeeded, just not in the way you
expected.  Looking
at in_pcbconnect_setup() in the kernel shows that actually
the packet is sent
to the local primary interface address.

Let's look at what really happen to that packet -

   "192.168.0.1" after being mangled by
inet_pton() gives
   the field sin_addr.s_addr of 0x0100A8C0.  This should
make
   your sockaddr_in structure look like -

     sa.sin_len = 0x01
     sa.sin_family = 0x00
     sa.sin_port = 0xA8C0 (which is port 49320)
     sa.sin_addr.s_addr = 0x00000000

So the sendto() call was sending a packet to your local
interface for port 49320.
And since UDP is a connectionless protocol, you don't have a
way (unless it is
builtin to your application protocol) to determine an error.
 For example, TFTP
sends back notification for every dgram received.

I hope this helps with your understanding.  I highly
recommend if you are going
to do more network programming that you obtain at least some
books on the subject.


Patrick
_______________________________________________
freebsd-questionsfreebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-que
stions
To unsubscribe, send any mail to
"freebsd-questions-unsubscribefreebsd.org"

Re: Network programming question
user name
2008-03-14 10:23:59
On Thu, Mar 13, 2008 at 11:57 PM, Patrick Mahan
<mahanmahan.org> wrote:
>
>
>
>  inet_pton() clobbered the fields you pointed out.  In
fact the sin_family
>  field was being set to 0x01 which caused your initial
EADDRNOTSUPPORT error
>  you were seeing.  You quick change fixed that problem.
 However, (depending
>  on how sockaddr_in structure is actually allocated)
the sin_addr field was
>  0.0.0.0.  This is actually an accepted form of the
broadcast address for UDP
>  packets.  I forget exactly who the culprit was (Sun
comes to mind) but there
>  was a need to allow broadcasts to 0.0.0.0 (which is
also know as INADDR_ANY).
>  So, therefore, sendto() succeeded, just not in the way
you expected.  Looking
>  at in_pcbconnect_setup() in the kernel shows that
actually the packet is sent
>  to the local primary interface address.
>
>  Let's look at what really happen to that packet -
>
>    "192.168.0.1" after being mangled by
inet_pton() gives
>    the field sin_addr.s_addr of 0x0100A8C0.  This
should make
>    your sockaddr_in structure look like -
>
>      sa.sin_len = 0x01
>      sa.sin_family = 0x00
>      sa.sin_port = 0xA8C0 (which is port 49320)
>      sa.sin_addr.s_addr = 0x00000000
>
>  So the sendto() call was sending a packet to your
local interface for port 49320.
>  And since UDP is a connectionless protocol, you don't
have a way (unless it is
>  builtin to your application protocol) to determine an
error.  For example, TFTP
>  sends back notification for every dgram received.
>
>  I hope this helps with your understanding.  I highly
recommend if you are going
>  to do more network programming that you obtain at
least some books on the subject.
>
>
>  Patrick
>

Thanks much for this explanation.  Books would be good, yes.
 I guys
got to learn somehow.  Thanks for taking the time to explain
it.
That's interesting that a broadcast may be sent to 0.0.0.0. 
I knew
that 0.0.0.0 is equal to INADDR_ANY.  However, I thought it
wasn't
possible to send to that address, only to bind to it locally
for a
server application.

Andy

-- 
 A: Because it messes up the order in which people normally
read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
_______________________________________________
freebsd-questionsfreebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-que
stions
To unsubscribe, send any mail to
"freebsd-questions-unsubscribefreebsd.org"

[1-5]

about | contact  Other archives ( Real Estate discussion Medical topics )