简体   繁体   中英

Unable to multicast using IPv6

Here is the code for the sender and the receiver (combined).

int main (int argc, char *argv[]) {
  struct in6_addr localInterface;
  struct sockaddr_in6 groupSock;
  // socket descriptor for multicast
  int sd;

  char databuf[10];
  // length of message
  int datalen = sizeof(databuf);

  /* Create a datagram socket on which to send/receive. */
  sd = socket(AF_INET6, SOCK_DGRAM, 0);

  if(sd < 0) {
    perror("Opening datagram socket error");
    exit(1);
  }
  else {
    printf("Opening the datagram socket...OK.\n");
  }

  /* Enable SO_REUSEADDR to allow multiple instances of this */
  /* application to receive copies of the multicast datagrams. */
  {
    int reuse = 1;
    if(setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *)&reuse, sizeof(reuse)) < 0)
      {
    perror("Setting SO_REUSEADDR error");
    close(sd);
    exit(1);
      }

    else {
      printf("Setting SO_REUSEADDR...OK.\n");
    }
  }

  /* Initialize the group sockaddr structure with a */
  memset((char *) &groupSock, 0, sizeof(groupSock));
  groupSock.sin6_family = AF_INET6;
  // address of the group
  // groupSock.sin6_addr = inet6_addr("ff5e::/16");
  inet_pton(AF_INET6, "ff5e::/16", &(groupSock.sin6_addr));

  groupSock.sin6_port = htons(4321);

  /* Set local interface for outbound multicast datagrams. */
  /* The IP address specified must be associated with a local, */
  /* multicast capable interface. */
  char *ip_address = argv[2];
  inet_pton (AF_INET6, ip_address, &(localInterface.s6_addr));

  memset((char *) &localInterface, 0, sizeof(localInterface));  

  int ifindex;
  ifindex = if_nametoindex ("eth5");
  printf ("ifindex is %d\n", ifindex);

  if(setsockopt(sd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)))
    {
      perror("Setting local interface error");
      exit(1);
    }
  else {
    printf("Setting the local interface...OK\n");
  }

  // choice is 0 for sending and 1 for receiving
  int choice;
  sscanf (argv[1], "%d", &choice);

  // if sending
  if (choice == 0) {
    int i;
    for (i = 0; i < datalen-1; ++i) {
      databuf[i] = 'a';
    }
    databuf[i] = 0;

    if (sendto(sd, databuf, datalen, 0, (struct sockaddr*)&groupSock, sizeof(groupSock)) < 0) {
      printf ("Error in send\n");
    }

    else {
      printf ("Send okay!\n");
    }
  }

  // if receiving
  else if (choice == 1) {
    groupSock.sin6_addr = in6addr_any;
    if(bind(sd, (struct sockaddr*)&groupSock, sizeof(groupSock))) {
      perror("Binding datagram socket error");
      close(sd);
      exit(1);
    }

    else {
      printf("Binding datagram socket...OK.\n");
    }

    /* Join the multicast group ff5e::/16 on the local  */
    /* interface. Note that this IP_ADD_MEMBERSHIP option must be */
    /* called for each local interface over which the multicast */
    /* datagrams are to be received. */
    struct ipv6_mreq group;
    inet_pton (AF_INET6, "ff5e::", &(group.ipv6mr_multiaddr.s6_addr));

    // group.imr_interface.s6_addr = inet_addr(ip_address);
    group.ipv6mr_interface = ifindex;

    if(setsockopt(sd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0) {
      perror("Adding multicast group error");
      close(sd);
      exit(1);
    }

    else {
      printf("Adding multicast group...OK.\n");
    }

    if (read(sd, databuf, datalen) < 0) {
      perror("Error in read");
    }

    else {
      printf("Read Okay\n");
      printf ("Message is : %s\n", databuf);
    }
  }

}

The receiver does not receive the message if the sender and receiver are on different nodes (I have checked that they are connected by using ping6). I am working on Linux Ubuntu 14.04. Capturing ipv6 packets using tcpdump reveals that the packet is not sent at the sender side. What is the problem?

One problem is that you have a poorly chosen IPv6 multicast address. The FF5E:: breaks down like this:

  • FF means it is multicast.
  • 5 is the flag set ( 0101 ), and this value is an invalid set of flags. The highest bit set means you have an embedded RP address, which you clearly don't. To do this the flag set must be 7 ( 0111 ), and then follow all the rules for embedding the RP address.
  • E means it is Global scope.

This multicast address properly should be dropped in any path where it meets a router.

See RFCs 4291, 3306, and 3956 for creating IPv6 multicast addresses, including the meanings of the flags and scopes.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM