Re: trouble receiving multicast

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

 



This is an old problem that I'm still debugging... I found a way to
"jury-rig" it so that it would work, so it slid on the priority scale.
Now I'm re-investigating it.

To recap, I have a machine with several network interfaces.  eth0 is
the main interface, and the default route is set to it.  eth1 receives
multicast data via a gateway that's not under our control.

If I run "tcpdump -i eth1", I can see all of the multicast packets.
However, my application doesn't receive the data.  Attached is the
program I'm using to test receiving multicast packets, and for
utility, a program to send packets.  A quick skim by other people in
the past hasn't come up with any glaring errors.

My "jury rigged" system was to set up eth1 as the default gateway and
manually configure important subnets to go through eth0.  If this is
the case, then my application receives broadcasts fine.

I've just figured out something more useful.  If the IP address on
eth1 is on the same subnet that the multicast broadcasts are sent
from, then the application receives packets.  If it is not on the same
subnet (ie, same IP, different netmask), the application doesn't
receive packets.

tcpdump always sees multicast packets regardless of the interface's IP
address.

Is this correct behavior?

Thanks,
Wes

-- 
http://www.woahnelly.net/~wes/          OpenPGP key = 0xA5CA6644
fingerprint = FDE5 21D8 9D8B 386F 128F  DF52 3F52 D582 A5CA 6644

/** \file A tool for subscribing to multicast addresses. */


#include <stdlib.h>
#include <iostream>
#include <unistd.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/un.h>




int main(int argc, char **argv)
{
    if (argc != 4) {
	std::cout << "usage:  mcastsend mcastaddr port msg" << std::endl;
	return 1;
    }

    const char *mcastaddr = argv[1];
    int port = atoi(argv[2]);
    const char *msg = argv[3];


    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    try {
        // reuse socket
        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char*>(&port), sizeof(port)) != 0)
            throw "couldn't set socket to reuse";

        // bind socket
        struct sockaddr_in saddr;
        saddr.sin_family = AF_INET;
        saddr.sin_port = htons(port);
        if (inet_pton(AF_INET, mcastaddr, &saddr.sin_addr) <= 0)
            throw "inet_pton failed";
        if (connect(fd, (struct sockaddr *) &saddr,
                    sizeof(saddr)) != 0)
            throw "couldn't connect";

        size_t sent = send(fd, msg, strlen(msg), MSG_NOSIGNAL);
        if (sent != strlen(msg))
            throw "error sending msg";
    } catch (const char *err) {
        std::cout << "error:  " << err << std::endl;
        return 1;
    }
    return 0;
}

/** \file A tool for subscribing to multicast addresses. */


#include <stdlib.h>
#include <iostream>
#include <unistd.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/un.h>




int main(int argc, char **argv)
{
    if (argc != 4) {
	std::cout << "usage:  mcasttest dev mcastaddr port" << std::endl;
	return 1;
    }

    const char *dev = argv[1];
    const char *mcastaddr = argv[2];
    int port = atoi(argv[3]);


    int fd = socket(AF_INET, SOCK_DGRAM, 0);
    try {
        // reuse socket
        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, reinterpret_cast<const char*>(&port), sizeof(port)) != 0)
            throw "couldn't set socket to reuse";

        // bind socket
        struct sockaddr_in saddr;
        saddr.sin_family = AF_INET;
        saddr.sin_port = htons(port);
        saddr.sin_addr.s_addr = htonl(INADDR_ANY);
        if (bind(fd, (struct sockaddr *) &saddr, sizeof(saddr)) != 0)
            throw "couldn't bind address";


        // join mcast group
        struct ip_mreq mreq;
        bzero(&mreq, sizeof(mreq));
        if (inet_pton(AF_INET, mcastaddr, &mreq.imr_multiaddr) <= 0)
            throw "couldn't set mcast address";
        struct ifreq ifreq;
        strncpy(ifreq.ifr_name, dev, IFNAMSIZ);

        if (ioctl(fd, SIOCGIFADDR, &ifreq) < 0)
            throw "couldn't get iface address";

        memcpy(&mreq.imr_interface,
               &((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr,
               sizeof(struct in_addr));

        if (setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
                       reinterpret_cast<const char*>(&mreq), sizeof(mreq)) != 0)
            throw "couldn't join mcast group";
    } catch (const char *err) {
        std::cout << "error:  " << err << std::endl;
        return 1;
    }

    const unsigned int bufsize = 1024;
    char buf[bufsize];
    size_t amt = 0;
    while ( (amt = read(fd, buf, bufsize)) > 0)
        std::cout << "got " << amt << " bytes" << std::endl;

    return 0;
}

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux