Subject: Question on IPV4/IPV6 Multicast interoperability

From: Ghanashyam Satpathy <[email-masked]>
Date: Sun, 18 Dec 2011 03:14:15 -0800 (PST)

Hello,
 
I have a question on IPV4/IPV6 Multicast interoperability. We have succesfully upgraded our application(Windows Based) to support IPV6 and faced issue on multicast interoperability. Multicast messages sent by a IPV6 server is successfully receved by a client running on IPV6. But any client running on IPV4 is not able to receive the message.
 
Quite a no. of things I tried like using IPV4 mapped IPV6 address and V4 embeded V6 adress.But nothing seems to be working.Would like to know an unified way so that one multicast message sent by an IPV6 server should be received by both V6 and V4 client.
 
Would be great if somebody can send some code snippet(C/C++) on it.
 
Thanks.
 
Ghanashyam

---

From: Tina TSOU <[email-masked]>
Date: Tue, 20 Dec 2011 00:39:02 +0000

Ghanashyam,
http://datatracker.ietf.org/doc/draft-tsou-multrans-addr-acquisition/
http://datatracker.ietf.org/doc/draft-zhou-multrans-af1-specification/
Running code exists.
Hope it helps.

Best Regards,
Tina TSOU
http://tinatsou.weebly.com/contact.html

From: [email-masked] [mailto:[email-masked]] On Behalf Of Ghanashyam Satpathy
Sent: Sunday, December 18, 2011 3:14 AM
To: [email-masked]
Subject: Question on IPV4/IPV6 Multicast interoperability

Hello,

Thanks.

Ghanashyam

---

From: Ghanashyam Satpathy <[email-masked]>
Date: Mon, 19 Dec 2011 19:51:25 -0800 (PST)

Hello Tina,
 
Thanks for the reply and understands the theory but unable to make it in my code.
 
Here is my server and client code, both can be compiled as a console app in windows.And run as 
 
multicast_server 224.0.22.1 9210 HelloIPv4World
multicast_server ff15::1 2001 HelloIPv6World
 
multicast_client 224.0.22.1 9210
multicast_client ff15::1 2001

For the sample code if the server runs as IPV6 (multicast_server ff15::1 2001 HelloIPv6World) then cleint running in IPV6 (multicast_client ff15::1 2001) receives the multicast message.But the client running in IPV4 does not receive the multicast message.
 
I want to run the server so that both IPV4 and IPV6 client can receive the multicast messages.How to do that ,some C/C++ code sample will be great.
 
Thanks
 
Ghanashyam

 
// server.cpp : Defines the entry point for the console application.
//
/* multicast_server.c
 * This sample demonstrates a Windows multicast server that works with either
 * IPv4 or IPv6, depending on the multicast address given.
 * Requires Windows XP+/Use MSVC and platform SDK to compile.
 * Troubleshoot: Make sure you have the IPv6 stack installed by running
 *     >ipv6 install
 *
 * Usage:
 *     multicast_server multicastip port data [ttl]
 *
 * Examples:
 *     >multicast_server 224.0.22.1 9210 HelloIPv4World
 *     >multicast_server ff15::1 2001 HelloIPv6World
 *
#include <stdio.h>      /* for fprintf() */
 #include <winsock2.h> /* for socket(), connect(), send(), and recv() */
#include <ws2tcpip.h>   /* for ip options */
#include <stdlib.h>     /* for atoi() and exit() */

#if defined(_MSC_VER)
#pragma comment(lib, "ws2_32.lib")
#endif

static void DieWithError(char* errorMessage)
{
    fprintf(stderr, "%s\n", errorMessage);
    exit(EXIT_FAILURE);
}

int main(int argc, char *argv[])
{
    SOCKET    sock;                   /* Socket */
    WSADATA   wsaData;                /* For WSAStartup */
    char*     multicastIP;            /* Arg: IP Multicast address */
    char*     multicastPort;          /* Arg: Server port */
    char*     sendString;             /* Arg: String to multicast */
    size_t    sendStringLen;          /* Length of string to multicast */
    DWORD     multicastTTL;           /* Arg: TTL of multicast packets */
    ADDRINFO* multicastAddr;          /* Multicast address */
    ADDRINFO  hints          = { 0 }; /* Hints for name lookup */

    if ( WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        DieWithError("WSAStartup() failed");
    }

    if ( argc < 4 || argc > 5 )
    {
        fprintf(stderr, "Usage:  %s <Multicast Address> <Port> <Send String> [<TTL>]\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    multicastIP   = argv[1];             /* First arg:   multicast IP address */
    multicastPort = argv[2];             /* Second arg:  multicast port */
    sendString    = argv[3];             /* Third arg:   String to multicast */
    multicastTTL  = (argc == 5 ?         /* Fourth arg:  If supplied, use command-line */
                     atoi(argv[4]) : 1); /* specified TTL, else use default TTL of 1 */
    sendStringLen = strlen(sendString);  /* Find length of sendString */

    /* Resolve destination address for multicast datagrams */
    hints.ai_family   = PF_UNSPEC;
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_flags    = AI_NUMERICHOST;
    if ( getaddrinfo(multicastIP, multicastPort, &hints, &multicastAddr) != 0 )
    {
        DieWithError("getaddrinfo() failed");
    }

    printf("Using %s\n", multicastAddr->ai_family == PF_INET6 ? "IPv6" : "IPv4");

    /* Create socket for sending multicast datagrams */
    if ( (sock = socket(multicastAddr->ai_family, multicastAddr->ai_socktype, 0)) == INVALID_SOCKET )
    {
        DieWithError("socket() failed");
    }

    /* Set TTL of multicast packet */
    if ( setsockopt(sock,
                    multicastAddr->ai_family == PF_INET6 ? IPPROTO_IPV6        : IPPROTO_IP,
                    multicastAddr->ai_family == PF_INET6 ? IPV6_MULTICAST_HOPS : IP_MULTICAST_TTL,
                    (char*) &multicastTTL, sizeof(multicastTTL)) != 0 )
    {
        DieWithError("setsockopt() failed");
    }

    for (;;) /* Run forever */
    {
        if ( sendto(sock, sendString, sendStringLen, 0,
                    multicastAddr->ai_addr, multicastAddr->ai_addrlen) != sendStringLen )
        {
            DieWithError("sendto() sent a different number of bytes than expected");
        }

        Sleep(3000); /* Multicast sendString in datagram to clients every 3 seconds */
    }

    /* NOT REACHED */
    freeaddrinfo(multicastAddr);
    closesocket(sock);
    return 0;
} 

// client.cpp : Defines the entry point for the console application.
//

/* multicast_client.c
 * This sample demonstrates a Windows multicast client that works with either
 * IPv4 or IPv6, depending on the multicast address given.
 * Requires Windows XP+/Use MSVC and platform SDK to compile.
 * Troubleshoot: Make sure you have the IPv6 stack installed by running
 *     >ipv6 install
 *
 * Usage:
 *     multicast_client multicastip port
 *
 * Examples:
 *     >multicast_client 224.0.22.1 9210
 *     >multicast_client ff15::1 2001
 *
 #include <stdio.h>      /* for printf() and fprintf() */
#include <winsock2.h>   /* for socket(), connect(), sendto(), and recvfrom() */
#include <ws2tcpip.h>   /* for ip_mreq */
#include <stdlib.h>     /* for atoi() and exit() */
#include <string.h>     /* for memset() */
#include <time.h>       /* for timestamps */

#if defined(_MSC_VER)
#pragma comment(lib, "ws2_32.lib")
#endif

void DieWithError(char* errorMessage)
{
    fprintf(stderr, "%s\n", errorMessage);
    exit(EXIT_FAILURE);
}

int main(int argc, char* argv[])
{
    SOCKET     sock;                     /* Socket */
    WSADATA    wsaData;                  /* For WSAStartup */
    char*      multicastIP;              /* Arg: IP Multicast Address */
    char*      multicastPort;            /* Arg: Port */
    ADDRINFO*  multicastAddr;            /* Multicast Address */
    ADDRINFO*  localAddr;                /* Local address to bind to */
    ADDRINFO   hints          = { 0 };   /* Hints for name lookup */

    if ( WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        DieWithError("WSAStartup() failed");
    }

    if ( argc != 3 )
    {
        fprintf(stderr,"Usage: %s <Multicast IP> <Multicast Port>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    multicastIP   = argv[1];      /* First arg:  Multicast IP address */
    multicastPort = argv[2];      /* Second arg: Multicast port */

    /* Resolve the multicast group address */ hints.ai_family = PF_UNSPEC; hints.ai_flags = AI_NUMERICHOST; if ( getaddrinfo(multicastIP, NULL, &hints, &multicastAddr) != 0 ) { DieWithError("getaddrinfo() failed"); } printf("Using %s\n", multicastAddr->ai_family == PF_INET6 ? "IPv6" : "IPv4"); /* Get a local address with the same family (IPv4 or IPv6) as our multicast group */
    hints.ai_family   = multicastAddr->ai_family;
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_flags    = AI_PASSIVE; /* Return an address we can bind to */
    if ( getaddrinfo(NULL, multicastPort, &hints, &localAddr) != 0 )
    {
        DieWithError("getaddrinfo() failed");
    }

    /* Create socket for receiving datagrams */
    if ( (sock = socket(localAddr->ai_family, localAddr->ai_socktype, 0)) == INVALID_SOCKET )
    {
        DieWithError("socket() failed");
    }

    /* Bind to the multicast port */
    if ( bind(sock, localAddr->ai_addr, localAddr->ai_addrlen) != 0 )
    {
        DieWithError("bind() failed");
    }

    /* Join the multicast group. We do this seperately depending on whether we
     * are using IPv4 or IPv6. WSAJoinLeaf is supposed to be IP version agnostic
     * but it looks more complex than just duplicating the required code. */
    if ( multicastAddr->ai_family  == PF_INET &&  
         multicastAddr->ai_addrlen == sizeof(struct sockaddr_in) ) /* IPv4 */
    {
        struct ip_mreq multicastRequest;  /* Multicast address join structure */

        /* Specify the multicast group */
        memcpy(&multicastRequest.imr_multiaddr,
               &((struct sockaddr_in*)(multicastAddr->ai_addr))->sin_addr,
               sizeof(multicastRequest.imr_multiaddr));

        /* 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, (char*) &multicastRequest, sizeof(multicastRequest)) != 0 )
        {
            DieWithError("setsockopt() failed");
        }
    }
    else if ( multicastAddr->ai_family  == PF_INET6 &&
              multicastAddr->ai_addrlen == sizeof(struct sockaddr_in6) ) /* IPv6 */
    {
        struct ipv6_mreq multicastRequest;  /* Multicast address join structure */

        /* Specify the multicast group */
        memcpy(&multicastRequest.ipv6mr_multiaddr,
               &((struct sockaddr_in6*)(multicastAddr->ai_addr))->sin6_addr,
               sizeof(multicastRequest.ipv6mr_multiaddr));

        /* Accept multicast from any interface */
        multicastRequest.ipv6mr_interface = 0;

        /* Join the multicast address */
        if ( setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char*) &multicastRequest, sizeof(multicastRequest)) != 0 )
        {
            DieWithError("setsockopt() failed");
        }
    }
    else
    {
        DieWithError("Neither IPv4 or IPv6");
    }

    freeaddrinfo(localAddr);
    freeaddrinfo(multicastAddr);

    for (;;) /* Run forever */
    {
        time_t timer;
        char   recvString[500];      /* Buffer for received string */
        int    recvStringLen;        /* Length of received string */

        /* Receive a single datagram from the server */
        if ( (recvStringLen = recvfrom(sock, recvString, sizeof(recvString) - 1, 0, NULL, 0)) < 0 )
        {
            DieWithError("recvfrom() failed");
        }

        recvString[recvStringLen] = '\0';

        /* Print the received string */
        time(&timer);  /* get time stamp to print with recieved data */
        printf("Time Received: %.*s : %s\n", strlen(ctime(&timer)) - 1, ctime(&timer), recvString);
    }

    /* NOT REACHED */
    closesocket(sock);
    exit(EXIT_SUCCESS);
}
From: Tina TSOU <[email-masked]>
To: Ghanashyam Satpathy <[email-masked]>; "[email-masked]" <[email-masked]> 
Cc: "[email-masked]" <[email-masked]>; MBONED WG <[email-masked]> 
Sent: Tuesday, December 20, 2011 6:09 AM
Subject: RE: Question on IPV4/IPV6 Multicast interoperability

Ghanashyam,
 
Best Regards,
Tina TSOU
 
From:[email-masked] [mailto:[email-masked]] On Behalf Of Ghanashyam Satpathy
Sent: Sunday, December 18, 2011 3:14 AM
To: [email-masked]
Subject: Question on IPV4/IPV6 Multicast interoperability
 
Hello,

 
 
Thanks.
 
Ghanashyam

---

From: Simon Perreault <[email-masked]>
Date: Wed, 21 Dec 2011 15:30:07 -0500

> Thanks for the reply and understands the theory but unable to make it in my code.

Your code might not need any modification at all...

Normally, IPv4 multicast and IPv6 multicast are incompatible.
a) An IPv4-only listener can receive multicast from an IPv4 source.
b) An IPv6-only listener can receive multicast from an IPv6 source.
c) A dual-stack listener can receive multicast from both IPv4 and IPv6 sources.
d) But an IPvX-only listener cannot receive multicast from an IPvY-only source.

To be able to do d), you need something between the listener and the source, what 
these days gets called an "adaptation function". It typically does not require 
code changes on the source or listener.

There is currently an effort in the IETF called "multrans" trying to standardize 
methods and protocols to do that. Some vendors already have "running code" that 
can translate between IPv4 and IPv6 multicast.

Simon

> *From:* Tina TSOU <[email-masked]>
> *To:* Ghanashyam Satpathy <[email-masked]>; "[email-masked]"
> <[email-masked]>
> *Cc:* "[email-masked]" <[email-masked]>; MBONED WG <[email-masked]>
> *Sent:* Tuesday, December 20, 2011 6:09 AM
> *Subject:* RE: Question on IPV4/IPV6 Multicast interoperability
>
> Ghanashyam,
> *From:[email-masked] [mailto:[email-masked]] *On Behalf Of
> *Ghanashyam Satpathy
> *Sent:* Sunday, December 18, 2011 3:14 AM
> *To:* [email-masked]
> *Subject:* Question on IPV4/IPV6 Multicast interoperability
> Hello,
> I have a question on IPV4/IPV6 Multicast interoperability. We have succesfully
> upgraded our application(Windows Based) to support IPV6 and faced issue on
> multicast interoperability. Multicast messages sent by a IPV6 server is
> successfully receved by a client running on IPV6. But any client running on IPV4
> is not able to receive the message.
> Quite a no. of things I tried like using IPV4 mapped IPV6 address and V4 embeded
> V6 adress.But nothing seems to be working.Would like to know an unified way so
> that one multicast message sent by an IPV6 server should be received by both V6
> and V4 client.
> --------------------------------------------------------------------
> IETF IPv6 working group mailing list
> [email-masked]
> Administrative Requests: https://www.ietf.org/mailman/listinfo/ipv6
> --------------------------------------------------------------------

-- 
DTN made easy, lean, and smart --> http://postellation.viagenie.ca
NAT64/DNS64 open-source        --> http://ecdysis.viagenie.ca
STUN/TURN server               --> http://numb.viagenie.ca