Date: Mon, 2 Feb 2009 17:24:14 -0500 From: Derek Tattersall <dlt@mebtel.net> To: Robert Watson <rwatson@FreeBSD.org> Cc: freebsd-net@FreeBSD.org Subject: Re: Multicast source address in recvfrom() Message-ID: <20090202222414.GA59860@oriental.arm.org> In-Reply-To: <alpine.BSF.2.00.0902021827470.77103@fledge.watson.org> References: <20090201183057.GA47405@oriental.arm.org> <alpine.BSF.2.00.0902021827470.77103@fledge.watson.org>
next in thread | previous in thread | raw e-mail | index | archive | help
* Robert Watson <rwatson@FreeBSD.org> [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 <stdio.h> /* for printf() and fprintf() */ #include <sys/socket.h> /* for socket(), connect(), sendto(), and recvfrom() */ #include <arpa/inet.h> /* for sockaddr_in and inet_addr() */ #include <netinet/in.h> /* for IPPROTO_UDP */ #include <stdlib.h> /* for atoi() and exit() */ #include <string.h> /* for memset() */ #include <unistd.h> /* 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 <Multicast IP> <Multicast Port>\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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20090202222414.GA59860>