From owner-freebsd-questions@FreeBSD.ORG Fri Mar 14 05:57:04 2008 Return-Path: Delivered-To: freebsd-questions@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9F05B106566C for ; Fri, 14 Mar 2008 05:57:04 +0000 (UTC) (envelope-from mahan@mahan.org) Received: from ns.mahan.org (ns.mahan.org [67.116.10.138]) by mx1.freebsd.org (Postfix) with ESMTP id 658B28FC1D for ; Fri, 14 Mar 2008 05:57:04 +0000 (UTC) (envelope-from mahan@mahan.org) Received: from widowmaker.local (crowTrobot [67.116.10.140]) by ns.mahan.org (8.13.6/8.13.6) with ESMTP id m2E5vNYb075290; Thu, 13 Mar 2008 22:57:24 -0700 (PDT) (envelope-from mahan@mahan.org) Message-ID: <47DA13AF.5090804@mahan.org> Date: Thu, 13 Mar 2008 22:57:03 -0700 From: Patrick Mahan User-Agent: Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.8.1.12) Gecko/20080213 Thunderbird/2.0.0.12 Mnenhy/0.7.5.0 MIME-Version: 1.0 To: Andrew Falanga References: <340a29540803130910l2a5badacxe50cd81ace87e1f7@mail.gmail.com> <47D9682B.5060402@mahan.org> <340a29540803131111g20315740n629ee146bc2f8602@mail.gmail.com> In-Reply-To: <340a29540803131111g20315740n629ee146bc2f8602@mail.gmail.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Cc: FreeBSD Questions Subject: Re: Network programming question X-BeenThere: freebsd-questions@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: User questions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 14 Mar 2008 05:57:04 -0000 Andrew Falanga presented these words - circa 3/13/08 11:11 AM-> > On Thu, Mar 13, 2008 at 11:45 AM, Patrick Mahan 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