2017-01-26 1 views
2

J'ai affaire à une ancienne base de code, dans laquelle ipv6 multicast ne semble pas fonctionner. Lorsque j'essaie de lier() le socket à ff01 :: 1, il échoue. Le socket est en cours de création dans mon interface ethernet. Liaison du socket à in6addr_any, qui est "::", aboutit à une liaison réussie, mais aucun paquet n'est jamais reçu, sauf pour ceux qui sont envoyés par l'application elle-même, en utilisant le socket donné (IPV6_MULTICAST_LOOP est défini) . Ces paquets ne semblent jamais quitter l'application non plus. Ils ne sont pas visibles dans wireshark lorsque vous essayez de capturer des paquets dans l'interface ethernet. Seuls les paquets de multidiffusion externes entrants sont visibles. Aucun d'eux n'atteint mon application.Quelles sont les exigences pour la multidiffusion ipv6 utilisant des douilles simples?

Le système est Ubuntu 16.04 avec Linux 4.4.0.

Un échantillon du code de configuration:

#define MCASTADDRC "ff01::1" 

    int mcast::bind_mcast(const char *interface) { 

    this->net = socket(AF_INET6, SOCK_DGRAM, 0);   
    inet_pton(AF_INET6,MCASTADDRC,&this->multicast.ipv6mr_multiaddr); 

    this->ifaceaddr.sin6_family = AF_INET6; 
    this->ifaceaddr.sin6_port = htons(SRVPORT); 
    this->ifaceaddr.sin6_addr = in6addr_any; 

    // interface for multicast 
    this->mcastaddr.sin6_family = AF_INET6; 
    this->mcastaddr.sin6_port = htons(SRVPORT); 
    this->mcastaddr.sin6_addr = this->multicast.ipv6mr_multiaddr; 


    int opcoes = fcntl(this->net, F_GETFL, 0); 

    if (fcntl(this->net, F_SETFL, opcoes | O_NONBLOCK) == -1) { 
     // fail 
     return(false); 
    } 

    if (bind(net, (struct sockaddr *) &this->ifaceaddr, sizeof(this->ifaceaddr)) == -1) { 
     // fail      
     return(false); 
    } 

    this->ifaceindex = if_nametoindex(interface); 
    this->multicast.ipv6mr_interface = this->ifaceindex; 
    this->ifaceaddr.sin6_scope_id = this->ifaceindex; 

    int mcast_loop = 1; 
    if (setsockopt(this->net, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &mcast_loop, sizeof(mcast_loop))) { 
     //fail 
     return(false); 
    } 

    if (setsockopt(this->net, IPPROTO_IPV6, IPV6_MULTICAST_IF, &this->ifaceindex, sizeof(this->ifaceindex))) { 
     //fail 
     return(false); 
    } 

    if (setsockopt(this->net, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &this->multicast, sizeof(this->multicast))) { 
     //fail 
     return(false); 
    } 
    int optval = 6000000; 
    int optlen = sizeof(optval); 
    if (setsockopt(this->net, SOL_SOCKET, SO_RCVBUF, &optval, sizeof(optval))) { 

     exit(0); 
    } 
    if (getsockopt(this->net, SOL_SOCKET, SO_RCVBUF, &optval, (socklen_t *)&optlen)) { 
     // fail 
     exit(0); 
    } 

    if(optval < 262142) { 
     // buffer is too small, we failed 
     exit(0); 
    } 

    return(true); // success 

} 
+0

Ceci est C++, pas c! – Olaf

+0

@Olaf Vous avez raison, juste parce que les fonctions que j'utilise ont un lien C cela ne signifie pas que mon code est C. J'ai édité la question en conséquence. –

Répondre

4

Bits 12-15 (à partir de 0) dans une adresse de multidiffusion IPv6 spécifie l'étendue de multidiffusion.

Une adresse de multidiffusion de la forme ff01::/16 a une portée de 1 qui signifie l'interface locale. De tels paquets ne peuvent être envoyés sur aucun lien réseau. C'est pourquoi vous ne pouvez recevoir aucun paquet avec une telle adresse d'autres hôtes.

Vous devez utiliser une adresse avec une valeur de portée différente. Une portée de 2 peut être envoyée sur le réseau local, mais pas entre les routeurs, tandis qu'une portée de (15) est globalement routable.

Également, exécutez netstat -ng lorsque votre programme est en cours d'exécution pour vous assurer que vous avez rejoint le groupe de multidiffusion approprié sur l'interface appropriée. Voir la page Wikipédia pour multicast addresses pour plus de détails.

+0

Cela a été utile pour déterminer ce qui n'allait pas dans le code. Mais alors j'ai cette situation très bizarre, car les paquets envoyés par les autres hôtes sont tous adressés à "ff01 :: 1". Les paquets envoyés à ma carte réseau sont donc eux-mêmes des liens locaux. Cela ne semble pas bien. –