soquetes Dual-Stack para aplicativos Winsock IPv6
Para dar suporte a IPv4 e IPv6 no Windows XP com Service Pack 1 (SP1) e no Windows Server 2003, um aplicativo precisa criar dois soquetes, um soquete para uso com IPv4 e um soquete para uso com IPv6. Esses dois soquetes devem ser manipulados separadamente pelo aplicativo.
O Windows Vista e posteriores oferecem a capacidade de criar um único soquete IPv6 que pode lidar com o tráfego IPv6 e IPv4. Por exemplo, um soquete de escuta TCP para IPv6 é criado, colocado no modo de pilha dupla e associado à porta 5001. Esse soquete de pilha dupla pode aceitar conexões de clientes TCP IPv6 que se conectam à porta 5001 e de clientes TCP IPv4 que se conectam à porta 5001. Esse recurso permite um design de aplicativo bastante simplificado e reduz a sobrecarga de recursos necessária para operações de postagem em dois soquetes separados.
Criando um soquete Dual-Stack
Por padrão, um soquete IPv6 criado no Windows Vista e posterior só opera pelo protocolo IPv6. Para transformar um soquete IPv6 em um soquete de pilha dupla, a função setsockopt deve ser chamada com a opção de soquete IPV6_V6ONLY para definir esse valor como zero antes que o soquete seja associado a um endereço IP. Quando a opção IPV6_V6ONLY soquete é definida como zero, um soquete criado para a família de endereços AF_INET6 pode ser usado para enviar e receber pacotes de e para um endereço IPv6 ou um endereço mapeado IPv4.
Endereços IP com um soquete Dual-Stack
Soquetes de pilha dupla sempre exigem endereços IPv6. A capacidade de interagir com um endereço IPv4 requer o uso do formato de endereço IPv6 mapeado por IPv4. Todos os endereços IPv4 devem ser representados no formato de endereço IPv6 mapeado por IPv4, que permite que um aplicativo somente IPv6 se comunique com um nó IPv4. O formato de endereço IPv6 mapeado por IPv4 permite que o endereço IPv4 de um nó IPv4 seja representado como um endereço IPv6. O endereço IPv4 é codificado nos 32 bits de ordem inferior do endereço IPv6 e os 96 bits de ordem alta mantêm o prefixo fixo 0:0:0:0:0:FFFF. O formato de endereço IPv6 mapeado por IPv4 é especificado no RFC 4291. Para obter mais informações, consulte www.ietf.org/rfc/rfc4291.txt. A macro IN6ADDR_SETV4MAPPED em Mstcpip.h pode ser usada para converter um endereço IPv4 no formato de endereço IPv6 mapeado IPv4 necessário.
Se o protocolo subjacente for, na verdade, IPv4, o endereço IPv4 será mapeado para um formato de endereço IPv6 mapeado por IPv4. Esse é o campo da família na estrutura SOCKADDR indica AF_INET6, mas um endereço IPv6 mapeado por IPv4 é codificado na estrutura de endereços IPv6. Para um soquete de pilha dupla no modo de escuta, isso significa que todas as conexões IPv4 aceitas retornarão um endereço IPv6 mapeado por IPv4. Para um soquete de pilha dupla que está se conectando a um destino IPv4, a estrutura SOCKADDR passada para conectar deve ser um endereço IPv6 mapeado por IPv4. Os aplicativos devem ter cuidado para lidar com esses endereços IPv6 mapeados em IPv4 adequadamente e usá-los apenas com soquetes de pilha duplos. Se um endereço IP deve ser passado para um soquete IPv4 normal, o endereço deve ser um endereço IPv4 normal, não um endereço IPv6 mapeado por IPv4.
Possíveis problemas ao usar um soquete Dual-Stack
Uma possível armadilha para aplicativos é obter um endereço IPv6 mapeado por IPv4 em um soquete de pilha dupla e tentar usar o endereço IP retornado em um soquete IPv6 diferente. Por exemplo, as funções getsockname ou getpeername podem retornar um endereço IPv6 mapeado por IPv4 quando usado em um soquete de pilha dupla. Se o endereço IPv6 mapeado por IPv4 retornado for usado posteriormente em um soquete diferente que não foi definido como pilha dupla (um soquete IPv6 somente que é o comportamento padrão quando um soquete é criado), qualquer uso desse soquete IPv6 somente com um endereço IPv6 mapeado IPv4 falhará. O formato de endereço IPv6 mapeado por IPv4 só pode ser usado em um soquete de pilha dupla.
Em um soquete de datagrama de pilha dupla, se um aplicativo exigir a função LPFN_WSARECVMSG (WSARecvMsg) para retornar informações de pacote em uma estrutura WSAMSG para datagramas recebidos por IPv4, IP_PKTINFO opção de soquete deverá ser definida como true no soquete. Se apenas a opção IPV6_PKTINFO estiver definida como true no soquete, as informações do pacote serão fornecidas para datagramas recebidos por IPv6, mas talvez não sejam fornecidas para datagramas recebidos por IPv4.
Se um aplicativo tentar definir a opção de soquete IP_PKTINFO em um soquete de datagrama de pilha dupla e iPv4 estiver desabilitado no sistema, a função setsockopt falhará e WSAGetLastError retornará com um erro de WSAEINVAL. Esse mesmo erro também é retornado pela função setsockopt como resultado de outros erros. Se um aplicativo tentar definir uma opção de soquete de nível IPPROTO_IP em um soquete de pilha dupla e falhar com WSAEINVAL, o aplicativo deverá determinar se o IPv4 está desabilitado no computador local. Um método que pode ser usado para detectar se o IPv4 está habilitado ou desabilitado é chamar a função de soquete com o parâmetro af definido como AF_INET para tentar criar um soquete IPv4. Se a função de soquete falhar e WSAGetLastError retornar um erro de WSAEAFNOSUPPORT, isso significa que o IPv4 não está habilitado. Nesse caso, uma falha de função setsockopt ao tentar definir o IP_PKTINFO opção de soquete pode ser ignorada pelo aplicativo. Caso contrário, uma falha ao tentar definir a opção de soquete IP_PKTINFO deverá ser tratada como um erro inesperado.
Para um soquete de pilha dupla ao enviar datagramas com a função WSASendMsg e um aplicativo deseja especificar um endereço de origem IP local específico a ser usado, o método para lidar com isso depende do endereço IP de destino. Ao enviar para um endereço de destino IPv4 ou um endereço de destino IPv6 mapeado por IPv4, um dos objetos de dados de controle passados na estrutura WSAMSG apontada pelo parâmetro lpMsg deve conter uma estrutura in_pktinfo que contém o endereço de origem IPv4 local a ser usado para envio. Ao enviar para um endereço de destino IPv6 que não seja um endereço IPv6 mapeado por IPv4, um dos objetos de dados de controle passados na estrutura WSAMSG apontada pelo parâmetro lpMsg deve conter uma estrutura in6_pktinfo que contém o endereço de origem IPv6 local a ser usado para envio.
Tópicos relacionados