OVH Cloud OVH Cloud

socket sans bind : getsockname possible ?

21 réponses
Avatar
Olivier Miakinen
[diapublication dans trois groupes, dont ceux sur Unix et Windows,
suivi vers fr.comp.reseaux.ip seul]

Bonjour,

Dans un programme en C utilisant les sockets, une fonction
reçoit un socket initialisé par la fonction socket(), mais
où le bind() n'a pas encore été fait. La fonction voudrait
déterminer quel type d'adresse on peut attacher à ce socket
(entre AF_INET et AF_INET6 à priori) : peut-elle utiliser
la fonction getsockname() pour ce faire, ou bien est-ce que
l'on risque une erreur sur certains OS du fait que le bind()
n'est pas fait ?

P.-S. : même si la question ne se pose pas vraiment, par
curiosité j'aimerais savoir aussi ce qu'il en est des
protocoles autres que IPv4 et IPv6, par exemple AF_UNIX

Cordialement,
--
Olivier Miakinen

10 réponses

1 2 3
Avatar
Olivier Miakinen
Le 16/05/2014 12:58, Nicolas George a écrit :

La seule option réaliste, par exemple pour IPv6, est de tenter de binder



Non, ce n'est pas une option réaliste, c'est un hack pas fiable.

La solution réaliste, c'est de faire en sorte que l'information nécessaire
soit disponible sans avoir à aller la repêcher à des endroits inaccessibles.
Si ce n'est pas le cas, il faut réorganiser le programme pour que ça le
soit.



Sachant que l'information *existe* dans le socket, c'est dommage
d'être obligé de la conserver en plus à côté.

On pourrait dire la même chose des adresse et port sources :
puisque celui qui a fait le bind sait ce qu'il a mis dans
sockaddr, pourquoi ne pas l'obliger à s'en souvenir plutôt
que de lui fournir une fonction getsockaddr ? ;-)
Avatar
Olivier Miakinen
Le 16/05/2014 11:52, Xavier Roche a écrit :

Je ne vois pas bien comment. De plus (*1) il est bien spécifié que le
comportement est indéterminé sans lien prélable...

(*1)
<http://pubs.opengroup.org/onlinepubs/009695399/functions/getsockname.html>



Pour info, ça fonctionne sur nos Unix (AIX, Sun, Linux), seul
Windows fait de la résistance. Je suis bien conscient que ça
reste un comportement indéterminé, mais je parierais bien que
ça ne nous donnera jamais une réponse trompeuse (du style AF_INET
si c'est de l'AF_INET6) : à mon avis, soit ça donne une réponse
et elle est correcte, soit ça renvoie une erreur et il ne reste
plus qu'à tenter une autre approche.
Avatar
Xavier Roche
On 05/16/2014 03:16 PM, Olivier Miakinen wrote:
si c'est de l'AF_INET6) : à mon avis, soit ça donne une réponse
et elle est correcte, soit ça renvoie une erreur et il ne reste
plus qu'à tenter une autre approche.



"If the socket has not been bound to a local name, the value stored in
the object pointed to by address is unspecified."

Ce qui m’inquiète c'est pas qu'il soit dit que la valeur est indéfinie
(ie. sous-entendu, la fonction ne renvoi pas une erreur)
Avatar
Olivier Miakinen
Le 16/05/2014 15:23, Xavier Roche a écrit :

"If the socket has not been bound to a local name, the value stored in
the object pointed to by address is unspecified."

Ce qui m’inquiète c'est pas qu'il soit dit que la valeur est indéfinie
(ie. sous-entendu, la fonction ne renvoi pas une erreur)



Ce qui m'arrangerait, c'est que ça veuille dire « the value is
"unspecified" » plutôt que « the value is unspecified », c'est-
à-dire que l'on y trouve l'« unspecified address » correspondant
au protocole (soit '0.0.0.0', soit '::') ! ;-)

En tout cas, c'est ce qui me semblerait le plus logique pour AF_INET
et AF_INET6, car je ne vois pas l'intérêt qu'il y aurait à distinguer
dans le noyau entre un bind non fait et un bind fait avec adresse
unspecified et port nul.

Mais je comprends bien que la doc ne soit pas plus précise puisque
ce qui est évident pour AF_INET et AF_INET6 ne l'est sans doute
pas pour les autres protocoles.
Avatar
Nicolas George
Olivier Miakinen , dans le message <ll52oc$30nh$,
a écrit :
On pourrait dire la même chose des adresse et port sources :



Seulement si on n'a rien compris.

puisque celui qui a fait le bind sait ce qu'il a mis dans
sockaddr,



Ça c'est pour le port local, et encore seulement s'il a fait un bind()
explicite avec un port non nul. De fait, quelqu'un qui a fait un bind()
explicite et qui fait ensuite un getsockaddr() est un idiot.
Avatar
Olivier Miakinen
Le 16/05/2014 16:13, Nicolas George a écrit :

On pourrait dire la même chose des adresse et port sources :



Seulement si on n'a rien compris.



Pourquoi te crois-tu si souvent obligé d'être désagréable ?

puisque celui qui a fait le bind sait ce qu'il a mis dans
sockaddr,



Ça c'est pour le port local, et encore seulement s'il a fait un bind()
explicite avec un port non nul. De fait, quelqu'un qui a fait un bind()
explicite et qui fait ensuite un getsockaddr() est un idiot.



Même remarque.
Avatar
Nicolas George
Olivier Miakinen , dans le message <ll58qt$5ke$,
a écrit :
Pourquoi te crois-tu si souvent obligé d'être désagréable ?



Parce que j'ai trop souvent à subir les bugs de programmes écrits par des
incompétents qui ont recours à ce genre de hack. J'aurais espéré que
signaler à l'OP que son problème était mal posé à la base suffirait, je suis
désespéré que d'aucuns l'encouragent dans une solution néfaste.
Avatar
Xavier Roche
Le 16/05/2014 19:37, Nicolas George a écrit :
Parce que j'ai trop souvent à subir les bugs de programmes écrits par des
incompétents qui ont recours à ce genre de hack.



Quel est le problème de faire un getsockopt(SO_DOMAIN) ? A moins que le
hack doit le bind local ? Dans les deux cas je ne vois pas en quoi c'est
un "hack": tout est défini dans POSIX.
Avatar
Bruno Ducrot
On 2014-05-16, Olivier Miakinen wrote:
Le 16/05/2014 12:55, Xavier Roche a écrit :

Ah, si, j'avais la berlue, en tout les cas sous Linux:

SO_DOMAIN (since Linux 2.6.32)
Retrieves the socket domain as an integer, returning a value
such as AF_INET6. See socket(2) for details. This socket
option is read-only.





Qui n'apparait pas dans
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html


Tiens ? Oui.

On trouve par exemple sur la toile un code qui vérifie que le
socket est un AF_INET ou un AF_INET6 avant de lui appliquer
d'autres getsockopt :

https://git.fedorahosted.org/cgit/conga.git/plain/ricci/common/Socket.cpp
<cit.>



Encore un machin écrit exclusivement pour Linux qu'il faudra,
une fois de plus, modifier pour que ça marche sous FreeBSD, et
aussi certainement pour d'autres OS.

A plus,

--
Bruno Ducrot

A quoi ca sert que Ducrot hisse des carcasses ?
Avatar
Xavier Roche
Le 16/05/2014 22:59, Bruno Ducrot a écrit :
Qui n'apparait pas dans
http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html



Oui absolument. Mais ce n'est pas étonnant, ni anormal: POSIX n'est pas
là pour inventer, il est là pour /standardiser/.

En clair la chronologie est en général la suivante:
* une ou (mieux) plusieurs implémentations ajoutent une fonctionnalité
(Linux, BSD, Solaris ...)
* cette fonctionnalité a un sens, fais consensus
* POSIX étudie l'opportunité de la rendre standard en l'intégrant

Pour moi l'existence de SO_TYPE ("get the type of the socket") sans
SO_DOMAIN (voir un SO_PROTOCOL) n'a pas de sens. Mais il y a peut être
une raison cachée ?
1 2 3