[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

how to capture & replay multicast traffic



Hello,

I have two programs:
- sender ... which generates some UDP multicast traffic
- listener ... which listens to a given UDP multicast group
               (in this case 233.65.120.153:64968)
When I compile these two programs, all seems to be working fine.
All "listeners" on the local network are getting data from the "sender".
So I believe that routers/switches are configured properly and the
transmitted packets have correct Ethernet/IP/UDP headers.

Now I am trying to capture the traffic with "tcpdump":

    sudo tcpdump -i eth0 -X 'dst 233.65.120.153' -w 0.pcap

(attached).

However, when I try to replay this pcap-file:

    $ sudo tcpreplay -i eth0 0.pcap
    sending out eth0
    processing file: 0.pcap
    Actual: 4 packets (240 bytes) sent in 3.00 seconds
    Rated: 80.0 bps, 0.00 Mbps, 1.33 pps
    Statistics for network device: eth0
        Attempted packets:         4
        Successful packets:        4
        Failed packets:            0
        Retried packets (ENOBUFS): 0
        Retried packets (EAGAIN):

None of the listeners on a given multicast sees that traffic.
I am sure there is a pretty good reason for that but I cannot figure
this out. :-/

I have check that:
- last 3 bytes at of the destination MAC address
  correspond to last three bytes of the destination IP address.
- destination IP is OK
- destination port is OK

If anybody has some good advice what I did wrong, any help would be most
welcome. Thanks in advance.
/* Compatible listeners:
 * - ~/work/net/udp-multicast/2/listener        ... works on the local machine as well as on the remote one
 * - sudo tcpdump -i eth0 -X dst 225.0.0.37     ... works on the local machine
 *                                                  works on a remote machine if some of its processes subscribed to a given multicast
 *                                                  (tcpdump does not subscribe itself)
 *                                                  To subscribe the remote machine to our multicast, we can either run the aforementioned listener,
 *                                                  or execute this command:
 *                                                  - iperf -s -u -B 225.0.0.37
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define HELLO_PORT 64968
#define HELLO_GROUP "233.65.120.153"

main(int argc, char *argv[])
{
     struct sockaddr_in addr;
     int fd, cnt;
     struct ip_mreq mreq;
     char *message="abcd";

     /* Create what looks like an ordinary UDP socket:
        AF_INET ... IPv4
	SOCK_DGRAM ... UDP
	0 ... required constant
      */
     if ((fd=socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
	  perror("socket");
	  exit(1);
     }

     /* Set up destination address:
        AF_INET ... IPv4
	HELLO_GROUP ... the IP-address of the multicast group
	                to which we want to multicast
	HELLO_PORT ... the UDP port that on which we want to multicast
      */
     memset(&addr, 0, sizeof(addr));
     addr.sin_family=AF_INET;
     addr.sin_addr.s_addr=inet_addr(HELLO_GROUP);
     addr.sin_port=htons(HELLO_PORT);
     
     /* now just sendto() our destination! */
     while (1) {
	  if (sendto(fd, message, strlen(message), 0, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
	       perror("sendto");
	       exit(1);
	  }
	  sleep(1);
     }
}
/*
 * Compatible senders:
 * - ~/work/net/udp-multicast/2/sender
 * - ~/doc/ocaml/net/udp-multicast/1/sender
 */

/* sudo tcpdump -X -vv -i eth0 'dst 225.0.0.37' */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#define HELLO_PORT 64968
#define HELLO_GROUP "233.65.120.153"
#define MSGBUFSIZE 1000000

char msgbuf[MSGBUFSIZE];

main(int argc, char *argv[])
{
     struct sockaddr_in addr;
     int fd, nbytes,addrlen;
     struct ip_mreq mreq;

     u_int yes=1;            /*** MODIFICATION TO ORIGINAL */

     /* Create what looks like an ordinary UDP socket:
	AF_INET ... IPv4
	SOCK_DGRAM ... UDP
	0 ... required constant
      */
    if ((fd=socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
         perror("socket");
         exit(1);
    }

    /* Allow multiple sockets to use the same PORT number:
       SOL_SOCKET ... manipulate properties of the socket API itself
       SO_REUSEADDR ... Allow reuse of local addresses for bind
     */
    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) < 0) {
       perror("Reusing ADDR failed");
       exit(1);
       }

     /* set up destination address */
     memset(&addr,0,sizeof(addr));
     addr.sin_family=AF_INET;
     addr.sin_addr.s_addr=htonl(INADDR_ANY); /* N.B.: differs from sender */
     addr.sin_port=htons(HELLO_PORT);
     
     /* bind to receive address */
     if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0) {
	  perror("bind");
	  exit(1);
     }
     
     /* use setsockopt() to request that the kernel join a multicast group */
     mreq.imr_multiaddr.s_addr=inet_addr(HELLO_GROUP);
     mreq.imr_interface.s_addr=htonl(INADDR_ANY);
     if (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) {
	  perror("setsockopt");
	  exit(1);
     }

     /* now just enter a read-print loop */
     while (1) {
	  addrlen=sizeof(addr);
	  memset(msgbuf, 0, MSGBUFSIZE);
	  if ((nbytes=recvfrom(fd, msgbuf, MSGBUFSIZE,0,
			       (struct sockaddr *) &addr, &addrlen)) < 0) {
	       perror("recvfrom");
	       exit(1);
	  }
	  printf("Incoming message size = %d\n", nbytes);
	  int i;
	  for (i=0; i < nbytes; i++)
		  printf("%02x ", ((unsigned char) msgbuf[i]));
	  printf("\n");
     }
}

Attachment: 0.pcap
Description: application/vnd.tcpdump.pcap


Reply to: