Liaison de sockets à des adresses IPv6

J’essaie d’écrire un serveur Web qui écoute à la fois les adresses IPv4 et IPv6. Cependant, le code que j’ai écrit à l’origine ne fonctionnait pas. Ensuite, j’ai découvert que les structures IPv6 fonctionnaient à la fois pour IPv4 et IPv6. Alors maintenant, j’utilise les structures IPv6, cependant, seules les adresses IPv4 fonctionnent. Cet article, pourquoi ne puis-je pas lier le socket ipv6 à une adresse linklocal , qui dit d’append server.sin6_scope_id = 5; donc je l’ai fait mais il n’accepte toujours pas les connexions telnet IPv6. Toute aide serait grandement appréciée car je suis complètement perplexe.
Merci!

Mon code est ci-dessous:

 void initialize_server(int port, int connections, char* address) { struct sockaddr_in6 socket_struct; /*Creates the socket*/ if ((sock_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { syslog(LOG_ERR, "%s\n", strerror(errno)); exit(EXIT_FAILURE); }/*Ends the socket creation*/ /*Populates the socket address structure*/ socket_struct.sin6_family = AF_INET6; if(address == NULL) socket_struct.sin6_addr=in6addr_any; else { inet_pton(AF_INET6, "fe80::216:3eff:fec3:3c22", (void *)&socket_struct.sin6_addr.s6_addr); } socket_struct.sin6_port =htons(port); socket_struct.sin6_scope_id = 0; if (bind(sock_fd, (struct sockaddr*) &socket_struct, sizeof(socket_struct)) < 0) { syslog(LOG_ERR, "%s\n", strerror(errno)); exit(EXIT_FAILURE); }//Ends the binding. if (listen(sock_fd, connections) <0) { syslog(LOG_ERR, "%s\n", strerror(errno)); exit(EXIT_FAILURE); }//Ends the listening function }//ends the initialize server function. 

Vous créez un socket dans la famille AF_INET , mais vous essayez ensuite de le lier à une adresse de la famille AF_INET6 . Passez à l’utilisation de AF_INET6 dans votre appel à socket() .

Dire “server.sin6_scope_id = 5;” est arbitraire. Je me suis battu avec ce temps moi-même et a découvert que vous devez utiliser la scope réelle de l’interface que vous souhaitez lier. On peut le trouver avec une petite fonction obsure mais utile.

 #include  server.sin6_scope_id=if_nametoindex("eth0"); 

Bien sûr, le codage en dur sur un adaptateur particulier est mauvais, le codage à courte vue. Une solution plus complète consiste à les parcourir en boucle et à les faire correspondre à l’adresse IP à laquelle vous vous associez. Ce qui suit n’est pas parfait dans la mesure où il ne tient pas compte des bizarreries comme avoir des adresses non canoniques et deux adaptateurs avec la même adresse IP, etc. Mais cet exemple de fonction fonctionne très bien et devrait vous aider à démarrer.

 #include  // strcmp #include  // if_nametoindex() #include  // getifaddrs() #include  // NI_ constants // returns 0 on error unsigned getScopeForIp(const char *ip){ struct ifaddrs *addrs; char ipAddress[NI_MAXHOST]; unsigned scope=0; // walk over the list of all interface addresses getifaddrs(&addrs); for(ifaddrs *addr=addrs;addr;addr=addr->ifa_next){ if (addr->ifa_addr && addr->ifa_addr->sa_family==AF_INET6){ // only interestd in ipv6 ones getnameinfo(addr->ifa_addr,sizeof(struct sockaddr_in6),ipAddress,sizeof(ipAddress),NULL,0,NI_NUMERICHOST); // result actually contains the interface name, so ssortingp it for(int i=0;ipAddress[i];i++){ if(ipAddress[i]=='%'){ ipAddress[i]='\0'; break; } } // if the ip matches, convert the interface name to a scope index if(strcmp(ipAddress,ip)==0){ scope=if_nametoindex(addr->ifa_name); break; } } } freeifaddrs(addrs); return scope; }