Pregunta


En IPv4, La versión 3 de IGMP agrega soporte para el "filtrado de origen", es decir, la capacidad de un sistema para informar interés en recibir paquetes solamente de direcciones de origen específicas.

Estoy usando IGMPV3 en una aplicación C# para apoyar este comportamiento. Así es como lo hago.

Ahora estoy en el proceso para agregar soporte a IPv6 en mi aplicación y necesito obtener el mismo comportamiento que en IPv4. Por lo que he leído, el protocolo equivalente a IGMPV3 en IPv6 es MLDV2. ¿Alguien tiene alguna idea sobre cómo implementar esto en C# con Socket?

¡Gracias!

¿Fue útil?

Solución

los RFC3678 La API independiente del protocolo solo está disponible en Vista+, lo que podría explicar el problema.

Si C# Runtime es compatible con IPv6, tendrá que intentar hacer coincidir con el Group_req o Group_source_req estructuras. No hay una API específica de IPv6 para que SSM coincida con la API IPv4 porque los desarrolladores finalmente abandonaron la duplicación inanida de las API y finalmente se establecieron en un súper conjunto.

Desafortunadamente, es probable que C# implementa ipv6_mreq por AddMembership y AddSourceMembership falla. La documentación está completamente ausente en los detalles.

Todos SocketOptionName Los valores requeridos no están definidos en C#:

/* RFC 3678 */
#define MCAST_JOIN_GROUP       41
#define MCAST_LEAVE_GROUP      42
#define MCAST_BLOCK_SOURCE     43
#define MCAST_UNBLOCK_SOURCE   44
#define MCAST_JOIN_SOURCE_GROUP        45
#define MCAST_LEAVE_SOURCE_GROUP       46
#define MCAST_MSFILTER         47

Otros consejos

Para hacer un seguimiento de la respuesta de Steve-O, todavía es posible realizar el filtrado de la fuente en IPv6 en C#, incluso si el sistema.net.sockets.socketOptionName Enumeration no define las opciones requeridas lanzando el número directamente.

(SocketOptionName) 45; //MCAST_JOIN_SOURCE_GROUP

La función SetSocketOption del socket permitirá que la llamada se vaya al "Socket de Windows" incluso si la opción no se reconoce. La verdadera lucha se convierte en la estructura de datos en sí que debe enviarse junto a la opción. Para establecer el filtrado de la fuente, la estructura de datos debe ser como esta: Group_source_req. La estructura anterior está usando un sockaddr_storage que generalmente está dentro de una unión con sockaddr_in y sockaddr_in6. Para replicar este comportamiento, podemos definir las mismas estructuras como esta:

private unsafe struct sockaddr_storage
{
    public short ss_family;             //2
    private fixed byte __ss_pad1[6];    //6
    private Int64 __ss_align;           //8
    private fixed byte __ss_pad2[112];  //112
}
private unsafe struct sockaddr_in
{
    public ushort sin_family;       //2
    public ushort sin_port;         //2
    public fixed byte sin_addr[4];  //4
    private fixed byte sub_zero[8]; //8
 }
private unsafe struct sockaddr_in6
{
    public ushort sin6_family;       //2
    public ushort sin6_port;         //2
    public int sin6_flowinfo;        //4
    public fixed byte sin6_addr[16]; //16
    public uint sin6_scope_id;       //4
}
private struct group_source_req
{
    public uint gr_interface;           //4
    //Compiler add a padding here:      //4
    public sockaddr_storage gr_group;   //128
    public sockaddr_storage gr_source;  //128
}

Ahora puede crear un sockaddr_in6 haciendo esto:

sockaddr_in6 sockIn = new sockaddr_in6
{
    sin6_family = (ushort) endPoint.AddressFamily,
    sin6_port = (ushort)endPoint.Port,
    sin6_scope_id = 0
};
for (int i = 0; i < endPoint.Address.GetAddressBytes().Length; i++)
{
    sockIn.sin6_addr[i] = endPoint.Address.GetAddressBytes()[i];
}

Los bytes del sockaddr_in6 ahora se pueden extraer utilizando la solución proporcionada aquí y copiado directamente en un sockaddr_storage creado anteriormente:

sockaddr_storage sock = new sockaddr_storage
{
    ss_family = (short)endPoint.AddressFamily
};
//[...]
byte[] sockInData = getBytes(sockIn);
byte* sockData = (byte*) &sock;
for (int i = 0; i < sockInData.Length; i++)
{
    sockData [i] = sockInData[i];
}

Ahora que tiene un sockaddr_storage, puede asignarlo a group_source_req y extraer los datos del grupo_source_req como lo hicimos anteriormente y usarlo como el valor cuando establece la opción.

socket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName) 45, /*data extracted from group_source_req*/);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top