[C/Reseau] Connaitre le port Client connecté au port 21 du FTP

Connaitre le port Client connecté au port 21 du FTP [C/Reseau] - C - Programmation

Marsh Posté le 24-11-2012 à 16:44:15    

Bonjour,
Je veux programmer un mini shell pour gérer un connexion ftp active.
J'ai un problème puisque pour envoyer le commande PORT il faut que je précise le numéro du port qui est le N+1 de celui qui a initié la connexion.
Ma question est donc, comment connaitre le numéro de port du client qui a initié la connexion vers le port 21 du serveur ftp?
 
Merci pour votre aide !

Reply

Marsh Posté le 24-11-2012 à 16:44:15   

Reply

Marsh Posté le 24-11-2012 à 22:07:33    

Bonjour !
 
Pourquoi vouloir utiliser le (N+1) ? Vous n'avez, a priori, aucune assurance que ce port soit libre ...
 
Autant laisser faire le système : passez 0 comme numéro de port dans l'appel à la fonction bind, puis récupérez le port qui a effectivement été utilisé avec getsockname().
 
Sinon, pour répondre à votre question, getsockname devrait être la fonction dont vous avez besoin.

Reply

Marsh Posté le 24-11-2012 à 22:44:02    

Bonjour,
Merci pour la réponse,
J'utilise le N+1 car, si j'ai bien compris, c'est la convention à utiliser quand on veut faire une connexion active pour un serveur ftp non ?

Reply

Marsh Posté le 24-11-2012 à 22:52:16    

C'est possible, je ne connais pas la norme par cœur :)
 
J'aurais tendance à utiliser un port libre, sans trop me poser de question, vu que de toute façon on passe ce numéro de port au serveur, et qu'on en change à chaque commande.
 
Mais je suis peut-être hors de l'usage classique
 

Reply

Marsh Posté le 24-11-2012 à 22:57:27    

C'est ce que j'ai essayé de faire mais quand j'utilise un port libre, le serveur me répond :
200 PORT command successful. Consider using PASV.
 
N'étant pas censé recevoir le "consider using PASV", je pensais que c'était du à ça !

Reply

Marsh Posté le 25-11-2012 à 00:09:33    

Je pense que ce message est simplement là pour indiquer au client qu'il devrait utiliser le mode passif, que le serveur propose.
 
En effet, le mode passif ne demande pas de configuration réseau de la part du client (si il est derrière un firewall ou un routeur, ou une VM en mode NAT / host only, ...), contrairement au mode actif, qui nécessite que les ports du client soient accessibles par le serveur.
 
Edit : Le serveur renvoie OK, donc la commande a été bien reçue et acceptée, donc vous pouvez continuer


Message édité par Farian le 25-11-2012 à 00:10:10
Reply

Marsh Posté le 25-11-2012 à 15:14:12    

Bonjour,
Merci pour la réponse, c'était en effet dommage de bloquer sur quelque chose qui fonctionnait ^^.
 
Par la suite je vais donc essayer de créer la socket de data avec la fonction suivante :
 

Code :
  1. int connexionServeur(char * PORT)
  2. {
  3.     // structure pour faire la demande de port
  4.   struct addrinfo hints;
  5.   // structure pour stocker et lire les résultats
  6.   struct addrinfo *result, *rp;
  7.   // socket d'attente (s) et de discution (t)
  8.   int t, s=-1;
  9.   // structures pour stocker les info concernant le client
  10.   struct sockaddr_storage peer_addr;
  11.   socklen_t peer_addr_len = sizeof(peer_addr);
  12.   // variables pour tester si les fonctions donnent un résultats ou une erreur
  13.   int res;
  14.   int bon;
  15.   // Des variable pour contenir de adresse de machine et des numero de port afin de les afficher
  16.   char hname[NI_MAXHOST], sname[NI_MAXSERV];
  17.  
  18.   // on rempli la structure hints de demande d'adresse
  19.   memset(&hints, 0, sizeof(struct addrinfo));
  20.   hints.ai_family = AF_UNSPEC;    /* IPv4 ou IPv6 */
  21.   hints.ai_socktype = SOCK_STREAM; /* socket flux connectée */
  22.   hints.ai_flags = AI_PASSIVE;    /* Les signifie que toutes les addresse de la machine seront utilisée */
  23.   hints.ai_protocol = 0;          /* Any protocol */
  24.   hints.ai_addrlen = 0;
  25.   hints.ai_addr = NULL;         
  26.   hints.ai_canonname = NULL;
  27.   hints.ai_next = NULL;
  28.   // on effectue la demande pour le port PORT défini par "8888"
  29.   res = getaddrinfo(NULL, PORT, &hints, &result);
  30.   if (res != 0) { // c'est une erreur
  31.     fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(res));
  32.     exit(1);
  33.   }
  34.  
  35.   // si res = 0 le véritable résultat de la fontion est l'argument result
  36.   // qui contient une liste d'addresse correspondant à la demande on va les
  37.   // rester jusqu'a trouver une qui convien
  38.   rp = result;
  39.   bon = 0;
  40.   while (rp != NULL) { // on parcourt la liste pour en trouver une qui convienne
  41.     int yes = 1;
  42.     s = socket(rp->ai_family, rp->ai_socktype,rp->ai_protocol);
  43.     // si le résultat est -1 cela n'a pas fonctionné on recommence avec la prochaine
  44.     if (s == -1) {
  45.       perror("Création de la socket" );
  46.       rp = rp->ai_next;
  47.       continue;
  48.     }   
  49.    
  50.     res = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &yes,
  51.       sizeof(int));
  52.     if (res == -1) {
  53.             perror("setsockopt" );
  54.     rp = rp->ai_next;
  55.             continue;
  56.     }
  57.     // si la socket a été obtenue, on essaye de réserver le port
  58.     res = bind(s, rp->ai_addr, rp->ai_addrlen);
  59.     if (res == 0 ) {// cela a fonctionné on affiche l'information
  60.       bon = 1;
  61.       // on récupère des informations affichables
  62.       res = getnameinfo(rp->ai_addr, rp->ai_addrlen,
  63.   hname, NI_MAXHOST,
  64.   sname, NI_MAXSERV,
  65.   NI_NUMERICSERV|NI_NUMERICHOST);
  66.       if (res != 0) {
  67. fprintf(stderr, "getnameinfo: %s\n", gai_strerror(res));
  68. exit (1);
  69.       }
  70.       printf ("La socket %d est maintenant en attente sur l'adresse %s le port %s\n",
  71.       s, hname, sname);
  72.       break;
  73.     }
  74.     else { // sinon le bind a été impossible, il faut fermer la socket
  75.       perror("Imposible de réserver l'adresse" );
  76.       close (s);
  77.     }
  78.     rp = rp->ai_next;
  79.   }
  80.   if (bon == 0) { // Cela n'a jamais fonctionné
  81.     fprintf(stderr, "Impossible de faire un bind\n" );
  82.     exit(1);
  83.   }
  84.  
  85.   // on libère la structure devenue inutile
  86.   freeaddrinfo(result);
  87.   // ######################################################
  88.   // (2.2) Attente de connexion  
  89.   // ######################################################
  90.   res = listen (s, 5);
  91.   if (res < 0) {
  92.     perror("listen" );
  93.     close(s);
  94.     exit(1);
  95.   }
  96.   // ######################################################
  97.   // (4) Acceptation d'une connexion
  98.   // Le serveur accepte l'une des demandes arrivées depuis le listen ou
  99.   // attend s'il n'y en a pas
  100.   // ######################################################
  101.   t = accept (s, (struct sockaddr *)&peer_addr, &peer_addr_len);
  102.   // s : la socket d'attente
  103.   // peer_addr : la structure où on va stocker les infos
  104.   //             sur le client
  105.   // peer_addr_len : donnée = la taille de tadr (pour
  106.   //                éviter le dépassement)
  107.   // t : La socket qui servira pour la  
  108.   //     discution
  109.   if (t == -1) { // il y a eu une erreur
  110.     perror("accept" );
  111.     close (s);
  112.     exit(1);
  113.   }
  114.   res = getnameinfo((struct sockaddr*)&peer_addr, peer_addr_len,
  115.      hname, NI_MAXHOST,
  116.      sname, NI_MAXSERV,
  117.      NI_NUMERICSERV);
  118.   if (res != 0) {
  119.     fprintf(stderr, "getnameinfo: %s\n", gai_strerror(res));
  120.     exit (1);
  121.   }
  122.   printf ("La socket %d a eu un client depuis %s sur le port %s\n",
  123.   s, hname, sname);
  124. return(s);
  125. }


 
Le problème est que je bloque sur "La socket 4 est maintenant en attente sur l'adresse 0.0.0.0 le port 1030".
 
Ce code m'a été donné dans l'énnoncé de mon tp, je pense donc qu'il est juste, je ne vois pas pourquoi la connexion bloque sur la fonction accepte.
 
De plus le fait qu'on essaye de se connecter sur l'addresse 0.0.0.0 m'étonne mais quand je la remplace par mon adresse, le problème persiste.
 
Voilà où je l'appelle :
 

Code :
  1. envoieMessage(socketClient,"PORT 109,212,179,190,4,6\n" );
  2. nblus=recv(socketClient,buf,TAILLE_BUFF,0);
  3. if(nblus==0)
  4. {
  5. printf("Erreur de reception de message\n" );
  6. return -1;
  7. }
  8. buf[nblus]='\0';
  9. printf("%s",buf);
  10. connexionServeur("1030" );


 
Merci

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed