Source IP Address of Multicast Join Packets

Discussion in 'Linux Networking' started by nd_no@yahoo.com, Feb 24, 2005.

  1. Guest

    Hi,


    I'm running Linux 2.4.20 on a PC that has one ethernet device.
    However, I have it configured as multihomed as follows:


    eth0: 192.168.5.100
    eth0:1 192.170.1.200


    I'm trying to write a multicast program that joins the 239.0.1.1 group
    using the second interface (eth0:1). However, when I used ethereal to
    snoop on the IGMP join packets, the source IP address of those join
    packets is that of eth0 and not eth0:1. I have searched all over the
    net and everything states that I should set the imr_interface field of
    the mreq structure to the IP address of eth0:1 when I perform the
    IP_ADD_MEMBERSHIP setsockopt operation. This doesn't work; it always
    uses the IP address of eth0 instead of eth0:1 in the IGMP join packets.

    Here's part of my code:


    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netdb.h>
    #include <stdio.h>
    #include <unistd.h> /* close */


    #define SERVER_PORT 5500
    #define MAX_MSG 100


    int main(int argc, char *argv[]) {


    int sd, rc, n, cliLen;
    struct ip_mreq mreq;
    struct sockaddr_in cliAddr, servAddr;
    struct in_addr mcastAddr;
    struct hostent *h;
    char msg[MAX_MSG];


    if(argc!=2) {
    printf("usage : %s <mcast address>\n",argv[0]);
    exit(0);
    }


    /* get mcast address to listen to */
    h=gethostbyname(argv[1]);
    if(h==NULL) {
    printf("%s : unknown group '%s'\n",argv[0],argv[1]);
    exit(1);
    }


    memcpy(&mcastAddr, h->h_addr_list[0],h->h_length);


    /* check given address is multicast */
    if(!IN_MULTICAST(ntohl(mcastAddr.s_addr))) {
    printf("%s : given address '%s' is not multicast\n",argv[0],
    inet_ntoa(mcastAddr));
    exit(1);
    }


    /* create socket */
    sd = socket(AF_INET,SOCK_DGRAM,0);
    if(sd<0) {
    printf("%s : cannot create socket\n",argv[0]);
    exit(1);
    }


    /* bind port */
    servAddr.sin_family=AF_INET;
    servAddr.sin_addr.s_addr=htonl(INADDR_ANY);
    servAddr.sin_port=htons(SERVER_PORT);
    if(bind(sd,(struct sockaddr *) &servAddr, sizeof(servAddr))<0) {
    printf("%s : cannot bind port %d \n",argv[0],SERVER_PORT);
    exit(1);
    }


    /* join multicast group */
    mreq.imr_multiaddr.s_addr=mcastAddr.s_addr;
    mreq.imr_interface.s_addr=inet_addr("192.170.1.200");


    rc = setsockopt(sd,IPPROTO_IP,IP_ADD_MEMBERSHIP,
    (void *) &mreq, sizeof(mreq));
    if(rc<0) {
    printf("%s : cannot join multicast group '%s'",argv[0],
    inet_ntoa(mcastAddr));
    exit(1);
    }
    else {
    printf("%s : listening to mgroup %s:%d\n",
    argv[0],inet_ntoa(mcastAddr), SERVER_PORT);
     
    , Feb 24, 2005
    #1
    1. Advertisements

  2. joy Guest

    i think is correct so.
    Try to look the source code of smcroute or mrouted .
    Rembeber the multicast traffic is in Level 2 of ISO/OSI Stack.
    bye
    peppep
     
    joy, Feb 24, 2005
    #2
    1. Advertisements

  3. jimxu Guest

    servAddr.sin_addr.s_addr=htonl(INADDR_ANY);
    ------->>>> Try changing the addr: do not use INADDR_ANY, use
    inet_addr("192.170.1.200")
     
    jimxu, Feb 25, 2005
    #3
  4. Tauno Voipio Guest

    ^^^
    Please note that the second address is in a block
    managed by Hewlett-Packard. You're working for HP?
     
    Tauno Voipio, Mar 1, 2005
    #4
  5. Guest

    Thanks for your response. Unfortunately, it still doesn't work.
    Sending multicast traffic through eth0:1 (192.170.1.200) isn't an
    issue; when I monitor the transmitting multicast traffic using
    ethereal, the source address is correct - that is, it's set to
    192.170.1.200 (eth0:1).

    However, to clearify again, the question or problem I'm having is
    related to an "IGMP" packet to do the membership join at the beginning,

    not a multicast data packet. In that "IGMP" packet, the source address

    is eth0 and not eth0:1 (based on what I see from ethereal); I need it
    to be eth0:1 for what I'm doing to work. The reason why I need the
    source address to be eth0:1 is that the router to which the "IGMP"
    packet is sent only has routes for the 192.170.1.x subnet. Hence, I
    need the source address in that IGMP join packet to be 192.170.1.200
    (eth0:1). Since the source address is that of eth0, the router is
    rejecting the IGMP packet as a result of a "non-adjacent" subnet.
    Thus, I won't be able to receive multicast traffic from the router.


    I have tried the IP_MULTICAST_IF option already but that only relates
    to "transmitting multicast traffic"; it won't set the source address of

    an "IGMP" join packet correctly. Trust me, I have read the unix
    programming manual on multicast and tried a few feasible options but I
    just can't get it to work. I actually traced through the multicast
    source code in the 2.4.28 linux kernel tree and actually found out that

    it uses INADDR_ANY even when you set mreq.imr_interface.s_addr to
    192.170.1.200. Hence, it seems like a bug in the code. I have even
    sent an email to the main author (Alan Cox) of the multicast task for
    linux for help but he hasn't responded yet.
     
    , Mar 3, 2005
    #5
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.