IPv6 socket: AddMembership drops the multicast group instead

Viewed 87

I want to join an IPv6 multicast group (in this example: "ff15::2a") via C# code.

What Worked

The following Python implementation works perfectly:

import socket
import struct

with socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) as s:
    # Build the request bytes (multicast address + interface [0])
    address_bytes = socket.inet_pton(socket.AF_INET6, "ff15::2a")
    interface_id = struct.pack("@I", 0)

    s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_JOIN_GROUP, address_bytes + interface_id)

And sends the following packet:

wireshark screenshot of the correct packet

What Didn't Work

The following C# implementation sends the wrong packet:

using System;
using System.Net.Sockets;

Socket socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp);

//Build the request bytes (multicast address + interface [0])
byte[] addressBytes = IPAddress.Parse("ff15::2a").GetAddressBytes();
byte[] optionValue = new byte[addressBytes.Length + sizeof(int)];
Buffer.BlockCopy(addressBytes, 0, optionValue, 0, addressBytes.Length);

socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, optionValue);

Notice - changed to EXCLUDE!

wireshark screenshot of the wrong packet

Remarks

  • SocketOptionName.DropMembership sends the opposite packet too, but I can't use it as a workaround because it throws an exception if I'm not a member of the group already
  • C# works fine with IPv4 multicast, but not IPv6
  • I tested C# in .NET 6, .NET Core 3.1 and .NET Framework (Mono)
  • This alternative implementation has the same issue:
using System;
using System.Net.Sockets;

Socket socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Dgram, ProtocolType.Udp);

IPAddress address = IPAddress.Parse("ff15::2a");
socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.AddMembership, new IPv6MulticastOption(address));
0 Answers
Related