Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Migration de IPv4 vers IPv6

8 réponses
Avatar
Olivier Miakinen
Bonjour,

je suis en train (mieux vaut tard que jamais) de commencer la migration
de programmes de IPv4 vers IPv6, et je me pose un certain nombre de
questions.

Avant de passer au « vrai » IPv6, je commence par utiliser les adresses
« IPv4-mapped IPv6 ». Si j'ai bien tout compris, sachant que je fais de
l'UDP, il me suffit en gros de remplacer « socket(AF_INET, SOCK_DGRAM,
0) » par « socket(AF_INET6, SOCK_DGRAM, 0) », et pour sendto() et
recvfrom() d'utiliser la nouvelle structure avec l'adresse IPv6
::ffff:a.b.c.d au lieu de l'ancienne avec l'adresse a.b.c.d. Je n'en
suis pas encore là, mais ça ne devrait pas tarder.

Ma première question concerne l'adresse localhost. Pour faire des
requêtes vers un service n'ayant pas encore migré vers IPv6, est-ce
que je dois utiliser l'adresse ::ffff:127.0.0.1 ou bien est-ce que
cela fonctionnera aussi bien si j'utilise ::1, le noyau sachant de
lui-même transformer cette adresse pour mon destinaire IPv4-only ?

Mon autre question ne concerne plus UDP mais ICMP. Le premier client
que je dois migrer ne se contente pas d'envoyer des paquets UDP, mais
il se met aussi à l'écoute des paquets ICMP_UNREACH (en particulier
ICMP_UNREACH_PORT) pour savoir qu'il n'a aucune chance d'obtenir de
réponse à ses requêtes UDP. Aussi, il lui arrive d'envoyer des
requêtes ICMP_ECHO, ICMP_TSTAMP et ICMP_MASKREQ. Est-ce que ce genre
de choses peut se faire avec un socket(AF_INET6, SOCK_RAW, ...) aussi
simplement que dans le cas de SOCK_DGRAM ?

Cordialement,
--
Olivier Miakinen

8 réponses

Avatar
Xavier Roche
Le 24/05/2012 20:49, Olivier Miakinen a écrit :
Ma première question concerne l'adresse localhost. Pour faire des
requêtes vers un service n'ayant pas encore migré vers IPv6, est-ce
que je dois utiliser l'adresse ::ffff:127.0.0.1 ou bien est-ce que
cela fonctionnera aussi bien si j'utilise ::1, le noyau sachant de
lui-même transformer cette adresse pour mon destinaire IPv4-only ?



Non, ::1 est une "vrai" IPv6. ::ffff:127.0.0.1 est une vrai-fausse IPv6,
qui reviens a se connecter en IPv4.

Les adresses mappées ::ffff ne sont du reste envoyées sur un serveur que
si ce dernier a activé la fonctionnalité d'écoute sur les deux
protocoles à la fois (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY,
&zero, sizeof(zero)))

Plus d'infos ici:

http://pubs.opengroup.org/onlinepubs/007904875/functions/xsh_chap02_10.html
IPV6_V6ONLY
This socket option restricts AF_INET6 sockets to IPv6 communications
only. AF_INET6 sockets may be used for both IPv4 and IPv6
communications. Some applications may want to restrict their use of an
AF_INET6 socket to IPv6 communications only. For these applications, the
IPv6_V6ONLY socket option is defined. When this option is turned on, the
socket can be used to send and receive IPv6 packets only. This is an
IPPROTO_IPV6-level option.
The parameter type of this option is a pointer to an int which is used
as a Boolean value. (Default value: 0)

(Note: la valeur par défaut n'est pas 0 sous Windows)

Et également
http://tools.ietf.org/html/rfc3493.html
Avatar
Olivier Miakinen
Bonjour Xavier,

Le 24/05/2012 21:21, Xavier Roche a écrit :

Ma première question concerne l'adresse localhost. Pour faire des
requêtes vers un service n'ayant pas encore migré vers IPv6, est-ce
que je dois utiliser l'adresse ::ffff:127.0.0.1 ou bien est-ce que
cela fonctionnera aussi bien si j'utilise ::1, le noyau sachant de
lui-même transformer cette adresse pour mon destinaire IPv4-only ?



Non, ::1 est une "vrai" IPv6. ::ffff:127.0.0.1 est une vrai-fausse IPv6,
qui reviens a se connecter en IPv4.



Bien, cela confirme ce que je supposais. Il faudra donc à terme que je
prévoie la possibilité de choisir entre les deux types de localhost.

Les adresses mappées ::ffff ne sont du reste envoyées sur un serveur que
si ce dernier a activé la fonctionnalité d'écoute sur les deux
protocoles à la fois (setsockopt(sock->fd, IPPROTO_IPV6, IPV6_V6ONLY,
&zero, sizeof(zero)))

Plus d'infos ici:

http://pubs.opengroup.org/onlinepubs/007904875/functions/xsh_chap02_10.html



Merci pour ce lien, j'y apprends entre autre choses que la façon
standard de faire des IO non bloquantes est avec fcntl et O_NONBLOCK.
Selon les programmes, on voit des ioctl au lieu de fcntl, et puis des
FIONBIO, O_NDELAY, FIOASYNC, etc. (je suis sûr d'en avoir vu plusieurs
autres mais leurs noms m'échappent).

Mais je vois que je dois tester deux valeurs, EAGAIN et EWOULDBLOCK :
http://stackoverflow.com/questions/7003234/which-systems-define-eagain-and-ewouldblock-as-different-values


Par ailleurs j'y trouve également setsockopt avec SO_BROADCAST et
SO_REUSEADDR, ce qui me rassure car j'en ai besoin aussi.


IPV6_V6ONLY
This socket option restricts AF_INET6 sockets to IPv6 communications
only. AF_INET6 sockets may be used for both IPv4 and IPv6
communications. Some applications may want to restrict their use of an
AF_INET6 socket to IPv6 communications only. For these applications, the
IPv6_V6ONLY socket option is defined. When this option is turned on, the
socket can be used to send and receive IPv6 packets only. This is an
IPPROTO_IPV6-level option.
The parameter type of this option is a pointer to an int which is used
as a Boolean value. (Default value: 0)

(Note: la valeur par défaut n'est pas 0 sous Windows)



Oh, cela veut dire que sous Windows il faut forcer la valeur à 0...
merci, je m'en souviendrai (les programmes doivent tourner aussi bien
sous Windows que sous AIX, SunOS ou Solaris, Linux, et peut-être
d'autres).

Et également
http://tools.ietf.org/html/rfc3493.html



Oui, ça j'étais déjà en train de le lire.


Merci en tout cas pour toutes ces infos. Et concernant SOCK_RAW et ICMP,
tu as des idées ?


Cordialement,
--
Olivier Miakinen
Avatar
Xavier Roche
On 05/25/2012 12:11 AM, Olivier Miakinen wrote:
Merci en tout cas pour toutes ces infos. Et concernant SOCK_RAW et ICMP,
tu as des idées ?



Du tout -- jamais touché à ça :)
Avatar
Olivier Miakinen
Le 25/05/2012 08:49, Xavier Roche m'a répondu :

Merci en tout cas pour toutes ces infos. Et concernant SOCK_RAW et ICMP,
tu as des idées ?



Du tout -- jamais touché à ça :)



Je suis en train de lire la page suivante :
<http://livre.g6.asso.fr/index.php/Programmation_d%27applications_bis>

... et du coup je me demande si je ne vais pas plutôt dupliquer les
sockets, les unes pour IPv4 et les autres pour IPv6. Cela me semble
finalement moins risqué pour ICMP, et aussi cela permettra de conserver
la compatibilité avec IPv4 seul si jamais on se trouvait sur une
machine qui ne supporte pas IPv6.

Quant au piège de IPV6_V6ONLY contre lequel tu m'as mis en garde, il
est parfaitement bien signalé, exemples à l'appui.

Encore merci, Xavier.

Cordialement,
--
Olivier Miakinen
Avatar
Pascal Hambourg
Salut,

Olivier Miakinen a écrit :
Merci en tout cas pour toutes ces infos. Et concernant SOCK_RAW et ICMP,
tu as des idées ?







Je soupçonne que ça ne marche qu'avec les sockets utilisant les
protocoles de transport comme TCP et UDP, qui fonctionnent de la même
façon en IPv4 et IPv6. ICMP et ICMPv6 sont deux protocoles différents et
incompatibles, comme IPv4 et IPv6.

et du coup je me demande si je ne vais pas plutôt dupliquer les
sockets, les unes pour IPv4 et les autres pour IPv6.



C'est préférable, AMA. D'autre part, il ne faut pas oublier qu'une
socket IPv6 ne peut accepter les communications en IPv4 que si elle
écoute sur l'adresse indéfinie ::.
Avatar
Olivier Miakinen
Il y a plus d'une semaine (désolé pour le retard), Pascal Hambourg
m'a répondu :

Merci en tout cas pour toutes ces infos. Et concernant SOCK_RAW et ICMP,
tu as des idées ?







Je soupçonne que ça ne marche qu'avec les sockets utilisant les
protocoles de transport comme TCP et UDP, qui fonctionnent de la même
façon en IPv4 et IPv6. ICMP et ICMPv6 sont deux protocoles différents et
incompatibles, comme IPv4 et IPv6.



Oui, j'ai continué mes recherches et j'en suis arrivé à la même
conclusion.

et du coup je me demande si je ne vais pas plutôt dupliquer les
sockets, les unes pour IPv4 et les autres pour IPv6.



C'est préférable, AMA.



Merci de la confirmation, en tout cas j'en suis parfaitement
convaincu maintenant.

D'autre part, il ne faut pas oublier qu'une
socket IPv6 ne peut accepter les communications en IPv4 que si elle
écoute sur l'adresse indéfinie ::.



C'était bien l'idée de toute façon. Mais cette affirmation m'étonne
malgré tout : une socket IPv6 ne pourrait pas écouter sur l'une de
ses adresses IPv4 sous la forme « mapped IPv6 » ::ffff:a.c.b.d ?

Cordialement,
--
Olivier Miakinen
Avatar
Pascal Hambourg
Olivier Miakinen a écrit :
Il y a plus d'une semaine (désolé pour le retard), Pascal Hambourg
m'a répondu :

D'autre part, il ne faut pas oublier qu'une
socket IPv6 ne peut accepter les communications en IPv4 que si elle
écoute sur l'adresse indéfinie ::.



C'était bien l'idée de toute façon. Mais cette affirmation m'étonne
malgré tout : une socket IPv6 ne pourrait pas écouter sur l'une de
ses adresses IPv4 sous la forme « mapped IPv6 » ::ffff:a.c.b.d ?



Je suppose que si (y a pas de raison), mais l'idée ne m'était même pas
venue de faire un truc pareil.
Avatar
Olivier Miakinen
Le 09/06/2012 12:35, Pascal Hambourg a écrit :

C'était bien l'idée de toute façon. Mais cette affirmation m'étonne
malgré tout : une socket IPv6 ne pourrait pas écouter sur l'une de
ses adresses IPv4 sous la forme « mapped IPv6 » ::ffff:a.c.b.d ?



Je suppose que si (y a pas de raison), mais l'idée ne m'était même pas
venue de faire un truc pareil.



;-)