Question


En IPv4, version 3 de IGMP ajoute le support pour « source de filtrage », qui est, la capacité d'un système à intérêt du rapport dans la réception des paquets uniquement à partir des adresses de sources spécifiques.

J'utilise IGMPv3 dans une application C # pour soutenir ce comportement. Voici comment je le fais.

Je suis en train d'ajouter le support pour IPv6 dans ma demande et je dois obtenir le même comportement que dans IPv4. D'après ce que j'ai lu, le protocole équivalent à IGMPv3 IPv6 est MLDv2 . Quelqu'un at-il une idée sur la façon de mettre en œuvre ce en C # avec Socket?

Merci!

Était-ce utile?

La solution

Le RFC3678 protocole API indépendant est uniquement disponible dans Vista + ce qui pourrait expliquer le problème.

Si C # l'exécution ne supporte entièrement IPv6, vous devrez essayer de faire correspondre le GROUP_REQ ou ipv6_mreq pour AddMembership et AddSourceMembership échoue. La documentation est complètement absent sur les détails.

Toutes les valeurs de SocketOptionName requises ne sont pas définis 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

Autres conseils

Pour donner suite à la réponse de Steve-o, il est encore possible de faire la source de filtrage en IPv6 en C #, même si l'énumération System.Net.Sockets.SocketOptionName ne définit pas les options requises par coulée directement le numéro.

(SocketOptionName) 45; //MCAST_JOIN_SOURCE_GROUP

La fonction SetSocketOption de la prise laissera le feu d'appel aux « fenêtres socket », même si l'on ne reconnaît pas l'option. La lutte réelle devient la structure de données lui-même qui doit être envoyé le long du côté de l'option. Pour filtrer la source de jeu structure de données doit être comme celui-ci: group_source_req . Le struct précédent utilise un sockaddr_storage qui est habituellement à l'intérieur d'une union avec sockaddr_in et < a href = "https://msdn.microsoft.com/en-us/library/windows/hardware/ff570824(v=vs.85).aspx" rel = "nofollow noreferrer"> sockaddr_in6 . Pour reproduire ce comportement, nous pouvons définir les mêmes struct comme ceci:

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
}

Vous pouvez maintenant créer un sockaddr_in6 en faisant ceci:

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];
}

Les octets du sockaddr_in6 peut maintenant être extrait en utilisant la solution fournie ici et copiés directement dans un sockaddr_storage précédemment créé:

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];
}

Maintenant que vous avez un sockaddr_storage vous pouvez l'assigner à group_source_req et extraire les données du group_source_req comme nous l'avons fait plus tôt et l'utiliser comme la valeur lorsque vous définissez l'option.

socket.SetSocketOption(SocketOptionLevel.IPv6, (SocketOptionName) 45, /*data extracted from group_source_req*/);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top