From owner-freebsd-net@FreeBSD.ORG Mon Feb 2 22:24:18 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 54ED41065672 for ; Mon, 2 Feb 2009 22:24:18 +0000 (UTC) (envelope-from dlt@mebtel.net) Received: from mail959c35.nsolutionszone.com (mail959c35.nsolutionszone.com [209.235.152.149]) by mx1.freebsd.org (Postfix) with ESMTP id 165F28FC1B for ; Mon, 2 Feb 2009 22:24:17 +0000 (UTC) (envelope-from dlt@mebtel.net) X-POP-User: dlt.mebtel.net Received: from localhost (66-79-79-183.dsl.mebtel.net [66.79.79.183]) by mail959c35.nsolutionszone.com (8.13.6.20060614/8.13.1) with ESMTP id n12MOEIg006271; Mon, 2 Feb 2009 22:24:15 GMT Date: Mon, 2 Feb 2009 17:24:14 -0500 From: Derek Tattersall To: Robert Watson Message-ID: <20090202222414.GA59860@oriental.arm.org> References: <20090201183057.GA47405@oriental.arm.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.4.2.3i 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 Reply-To: dlt@mebtel.net List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 02 Feb 2009 22:24:18 -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? > > Hi Derek: > > It might depend on how you're querying the source address. Could you post > a code excerpt? > > Robert N M Watson > Computer Laboratory > University of Cambridge It's a straightforward test program. /********************************************************************** * * 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