Andrew Falanga presented these words - circa 3/13/08 11:11 AM->
On Thu, Mar 13, 2008 at 11:45 AM, Patrick Mahan <[EMAIL PROTECTED]> 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-questions@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-questions
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to