L'interface de programmation "socket" IPv6

From Livre IPv6

Revision as of 06:52, 14 December 2005 by Laurent Toutain (Talk | contribs) (Ce qui a changé)

Ce qui a changé

Les changements opérés de façon à intégrer IPv6 concernent les quatre domaines suivants :

  • les structures de données d'adresses ;
  • l'interface socket ;
  • les primitives de conversion entre noms et adresses ;
  • les fonctions de conversions d'adresses.

Ces changements ont été minimisés autant que possible de manière à faciliter le portage des applications IPv4 existantes. En outre, et ce point est important, cette nouvelle API doit permettre l'interopérabilité entre machines IPv4 et machines IPv6 grâce au mécanisme de double pile décrit ci-après.

L'API décrite ici est celle utilisée en Solaris, Linux et systèmes *BSD. Elle correspond à celle définie dans le RFC 3493 avec quelques modifications nécessaires pour prendre en compte les dernières évolutions des protocoles sous-jacents. Cette API est explicitement conçue pour fonctionner sur des machines possédant la double pile IPv4 et IPv6 (cf. See Double pile IPv4/IPv6 pour le schéma d'implémentation d'une telle double pile sous UNIX 4.4BSD). Cette API "socket" est celle disponible dans de nombreux environnements de programmation tels que Java, perl, python, ruby, ...

CS191.gif

Une API "avancée", décrite dans le RFC 3542 permet de programmer les échanges réseaux de manière très précise. Elle sera également utilisée mais de manière succinte et essentiellement par le biais de l'exemple one_ping6.

Les structures de données d'adresses

Une nouvelle famille d'adresses ayant pour nom AF_INET6 et dont la valeur peut varier d'une implémentation à l'autre, a été définie (dans sys/socket.h). Également, une nouvelle famille de protocoles ayant pour nom PF_INET6 a été définie (dans sys/socket.h). En principe, on doit avoir :

#define PF_INET6 AF_INET6

La structure de données destinée à contenir une adresse IPv6 est définie comme suit (dans netinet/in.h) :

struct in6_addr {
   uint8_t s6_addr[16];
};

les octets constituant l'adresse étant rangés comme d'habitude dans l'ordre réseau (network byte order).

La structure de données IPv6 struct sockaddr_in6, est équivalente à la structure struct sockaddr_in d'IPv4. Elle est définie comme suit (dans netinet/in.h) pour les systèmes dérivés d'UNIX 4.3BSD :

struct sockaddr_in6 {
   sa_family_t sin6_family;   /* AF_INET6 */
   in_port_t sin6_port;       /* numéro de port */
   uint32_t sin6_flowinfo;    /* identificateur de flux */
   struct in6_addr sin6_addr; /* adresse IPv6 */
   uint32_t sin6_scope_id;    /* ensemble d'interfaces correspondant
                               * à la portée de l'adresse */
};

Il faut noter que cette structure a une longueur de 28 octets, et est donc plus grande que le type générique struct sockaddr. Il n'est donc plus possible de réserver une struct sockaddr si la valeur à stocker peut être une struct sockaddr_in6. Afin de faciliter la tâche des implémenteurs, une nouvelle structure de données, struct sockaddr_storage, a été définie. Celle-ci est de taille suffisante afin de pouvoir prendre en compte tous les protocoles supportés et alignée de telle sorte que les conversions de type entre pointeurs vers les structures de données d'adresse des protocoles supportés et pointeurs vers elle-même n'engendrent pas de problèmes d'alignement. Un exemple d'utilisation pourrait être le suivant :

struct sockaddr_storage ss;
 
struct sockaddr_in *sin = (struct sockaddr_in *) &ss;
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;

Dans la version 4.4 d'UNIX BSD, la longueur du champ sin6_family est passée de 2 octets à 1 octet. L'octet ainsi récupéré contient la taille de la structure sockaddr_in6 et sert à effectuer correctement la conversion de type vers la structure de données générique sockaddr utilisée par bon nombre de primitives de l'interface socket.

La macro-définition SIN6_LEN, présente dans toute implémentation 4.4BSD, permet alors de distinguer les versions. Les autres champs restant inchangés, cette structure est presque identique à celle de la précédente version :

#define SIN6_LEN
 
struct sockaddr_in6 {
   u_int8_t sin6_len;         /* la longueur de cette structure */
   sa_family_t sin6_family;   /* AF_INET6 */
   in_port_t sin6_port;       /* numéro de port */
   uint32_t sin6_flowinfo;    /* identificateur de flux */
   struct in6_addr sin6_addr; /* adresse IPv6 */
   uint32_t sin6_scope_id;    /* ensemble d'interfaces correspondant
                               * à la portée de l'adresse */
};

Si le champ sin6_len existe (ce qui est testable par le fait que le symbole SIN6_LEN est défini), il doit être initialisé par la taille de la structure sockaddr_in6.

On notera la présence de deux nouveaux champs (ils n'ont pas d'équivalents dans la structure sockaddr_in) dans la structure de données sockaddr_in6<§tt>, les champs <tt>sin6_flowinfo et sin6_scope_id. Le premier, en réalité structuré, est décrit dans le RFC 2460 et Identificateur de flux. Le second désigne un ensemble d'interfaces en adéquation avec la portée de l'adresse contenue dans le champ sin6_addr. Par exemple, si l'adresse en question est de type lien local, le champ sin6_scope_id devrait être un index d'interface.

Personal tools