Récupération de l’adresse IP / du port à partir du descripteur de socket

J’écris un clone d’inetd dans lequel je dois exécuter un serveur qui imprime l’adresse IP et le port du client qui s’y connecte.

Au STDIN et à mesure que STDIN et STDOUT avec le descripteur de socket, ma solution initiale consistait à récupérer la structure sockaddr_in , qui contient les informations nécessaires. Faire ceci avec getsockname() , cependant, renvoie une structure vide, avec tous les bits mis à 0.

Une idée de ce qui ne va pas avec mon approche? Existe-t-il d’autres méthodes que je peux utiliser pour récupérer l’IP / le port?

Merci

Comme R .. l’a fait remarquer, vous devriez utiliser getpeername . Cette fonction et getsockname prennent tous deux un descripteur de fichier comme premier argument, et non un pointeur de stream ( FILE * ). Utilisez fileno(stdin) pour obtenir le descripteur de fichier pour une entrée standard (ou STDIN_FILENO en STDIN_FILENO , car il est constant).

De plus, le dernier argument de getsockname et getpeername devrait être un pointeur sur socklen_t , pas une constante, et vous devriez utiliser un sockaddr_in pour TCP / IP:

 struct sockaddr_in peeraddr; socklen_t peeraddrlen = sizeof(peeraddr); getpeername(STDIN_FILENO, &peeraddr, &peeraddrlen); 

Voir un exemple complet ici .

Utilisez getpeername . Je suppose que votre problème est que getsockname renvoie les informations pour votre propre côté (local) du socket, qui est probablement lié à 0.0.0.0 (ce qui signifie qu’il peut accepter les connexions de toutes les interfaces).

Edit: Je pense avoir trouvé votre bug en train de lire le code. Cette ligne est fausse:

 getsockname(stdin, &addr, sizeof(addr)); 

Les fonctions getsockname et getpeername prennent un troisième argument socklen_t * (un pointeur ), et non un size_t . Le compilateur devrait vous getsockname cette erreur, sauf si vous avez oublié d’inclure un en-tête avec le prototype de getsockname . En outre, comme cela a déjà été dit, stdin est incorrect. Essayer:

 socklen_t len = sizeof addr; getpeername(0, &addr, &len); 

ou (C99 seulement):

 getpeername(0, &addr, (socklen_t[1]){sizeof addr}); 

Vous devriez également vérifier la valeur de retour; si vous le faisiez, vous verriez que cela renvoie des erreurs.

Si vous avez besoin de ces informations pour le client distant, vous devez appeler getpeername () .