From owner-freebsd-net@FreeBSD.ORG Tue Feb 3 10:13:55 2009 Return-Path: Delivered-To: freebsd-net@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 39803106566C for ; Tue, 3 Feb 2009 10:13:55 +0000 (UTC) (envelope-from rwatson@FreeBSD.org) Received: from cyrus.watson.org (cyrus.watson.org [65.122.17.42]) by mx1.freebsd.org (Postfix) with ESMTP id F3CB68FC12 for ; Tue, 3 Feb 2009 10:13:54 +0000 (UTC) (envelope-from rwatson@FreeBSD.org) Received: from fledge.watson.org (fledge.watson.org [65.122.17.41]) by cyrus.watson.org (Postfix) with ESMTPS id 9C7CB46B03; Tue, 3 Feb 2009 05:13:54 -0500 (EST) Date: Tue, 3 Feb 2009 10:13:54 +0000 (GMT) From: Robert Watson X-X-Sender: robert@fledge.watson.org To: Derek Tattersall In-Reply-To: <20090202222414.GA59860@oriental.arm.org> Message-ID: References: <20090201183057.GA47405@oriental.arm.org> <20090202222414.GA59860@oriental.arm.org> User-Agent: Alpine 2.00 (BSF 1167 2008-08-23) MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed Cc: freebsd-net@FreeBSD.org Subject: Re: Multicast source address in recvfrom() X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 03 Feb 2009 10:13:55 -0000 > * Robert Watson [090202 17:06]: >> On Sun, 1 Feb 2009, Derek Tattersall wrote: >> >>> In order to become familiar with multicast implementation using FreeBSD, I >>> found via Google a pair of test programs which multicast sent a simple >>> text message and received the text message. I added some code to report >>> the source address, because none of the references that I looked at >>> specified the source IP address in the frame. >>> >>> I ran the sender on A -current system, AMD64 vintage last week. The >>> receiver was on a -current system I386 vintage last week. TCPDUMP shows >>> the source IP address in the frame as (correctly) 192.168.0.15. The >>> receiver reports the source IP address as 200.231.191.191. I have also >>> run the same test with an OpenBSD 4.4 Release I386 system as the receiver. >>> The openBSD system reports the sender as 192.168.0.15. A Fedora 10 system >>> reported the source IP address as 0.0.0.0. >>> >>> Googling the RFCs and other information and referring to Comer's and >>> Stevens' books on TCPIP I can't determine what should be reported. Does >>> anybody have clue for me? >> >> It might depend on how you're querying the source address. Could you post >> a code excerpt? > > It's a straightforward test program. Your assumption, that the address returned from recvfrom(2) should be correct, seems generally right to me. However, it looks like you may not be initializing senderLen to the size of senderAddr, which means that the size getting passed in may be random stack garbage. In which case what you find in the sockaddr_in might also be random stack garbage, or might be the address, depending on whether the uninitialized length was long enough to fit an IP address in. Could you try adding something like: senderLen = sizeof(senderAddr); before the call to recvfrom(2)? Thanks, Robert N M Watson Computer Laboratory University of Cambridge > > /********************************************************************** > * > * MulticastReceiver.c: Receive a multicast message > * > * Copyright (C) 2009 Derek Tattersall. > * > * See the COPYING file for license information. > * > * Author: Derek Tattersall > * > * Latest Revision: Sat Jan 31 07:21:04 2009 > * > **********************************************************************/ > > /* Includes***********************************************************/ > #include /* for printf() and fprintf() */ > #include /* for socket(), connect(), sendto(), and recvfrom() */ > #include /* for sockaddr_in and inet_addr() */ > #include /* for IPPROTO_UDP */ > #include /* for atoi() and exit() */ > #include /* for memset() */ > #include /* for close() */ > > > /* Defines ***********************************************************/ > #define MAXRECVSTRING 255 /* Longest string to receive */ > > /* Type Definitions **************************************************/ > > /* Function Declarations *********************************************/ > void DieWithError(char *errorMessage); /* External error handling function */ > > /* Global Variables **************************************************/ > > /* Function Implementations ******************************************/ > int main(int argc, char *argv[]) > { > int sock; /* Socket */ > struct sockaddr_in multicastAddr; /* Multicast Address */ > char *multicastIP; /* IP Multicast Address */ > unsigned short multicastPort; /* Port */ > struct sockaddr_in senderAddr; /* Sender Address */ > int senderLen; /* length of sender address socket */ > char senderAddrBuf[INET_ADDRSTRLEN]; /* conversion buffer */ > char recvString[MAXRECVSTRING+1]; /* Buffer for received string */ > int recvStringLen; /* Length of received string */ > struct ip_mreq multicastRequest; /* Multicast address join structure */ > > if (argc != 3) /* Test for correct number of arguments */ > { > fprintf(stderr,"Usage: %s \n", argv[0]); > exit(1); > } > > multicastIP = argv[1]; /* First arg: Multicast IP address (dotted quad) */ > multicastPort = atoi(argv[2]);/* Second arg: Multicast port */ > > /* Create a best-effort datagram socket using UDP */ > if ((sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) > DieWithError("socket() failed"); > > /* Construct bind structure */ > memset(&multicastAddr, 0, sizeof(multicastAddr)); /* Zero out structure */ > multicastAddr.sin_family = AF_INET; /* Internet address family */ > multicastAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */ > multicastAddr.sin_port = htons(multicastPort); /* Multicast port */ > > /* Bind to the multicast port */ > if (bind(sock, (struct sockaddr *) &multicastAddr, sizeof(multicastAddr)) < 0) > DieWithError("bind() failed"); > > /* Specify the multicast group */ > multicastRequest.imr_multiaddr.s_addr = inet_addr(multicastIP); > /* Accept multicast from any interface */ > multicastRequest.imr_interface.s_addr = htonl(INADDR_ANY); > /* Join the multicast address */ > if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *) &multicastRequest, > sizeof(multicastRequest)) < 0) > DieWithError("setsockopt() failed"); > > /* Receive a single datagram from the server */ > if ((recvStringLen = recvfrom(sock, recvString, MAXRECVSTRING, 0, (struct sockaddr *)&senderAddr, (socklen_t *)&senderLen)) < 0) > DieWithError("recvfrom() failed"); > > if ((inet_ntop(AF_INET, &senderAddr.sin_addr.s_addr, senderAddrBuf, INET_ADDRSTRLEN)) == 0) > senderAddrBuf[0] = '\0'; > recvString[recvStringLen] = '\0'; > printf("Received from %s: %s\n", senderAddrBuf, recvString); /* Print the received string */ > > close(sock); > exit(0); > } > > /* vim: set sts=0 sw=8 ts=8: *****************************************/ > Note that the sender's address is taken from the recvfrom call per the > man page and printed via inet_ntop call. The DieWithError routine is a > simple print error message and exit with a 1. I have used similar code > with UDP recieving apps before. > -- > Best regards, > Derek Tattersall > dlt@mebtel.net dlt666@yahoo.com dtatters@gmail.com >