#include "server.h" void DROP_SERVER(char* serverHost, char** givenPort, int* listenSocket){ if( DEBUGMOD&HDR ) printf("====== DROP_SERVER(%s, %s, %d) ======\n\n", serverHost, *givenPort, *listenSocket); // FONCTIONNEMENT struct addrinfo hints; // contiendra le filtre/format struct addrinfo* addrinfo; // contiendra les infos du serveur int SOCKET, BIND, LISTEN; // file_desc(s) // INFOS struct sockaddr_storage serverInfo; // contiendra les informations du server socklen_t sockaddr_len = sizeof(struct sockaddr_storage); char infoHost[maxHostLen]; // contiendra l'adresse du server char infoPort[maxPortLen]; // contiendra le port du server /* [1] On définit le filtre/format =======================================================*/ memset(&hints, 0, sizeof(struct addrinfo)); // on vide le filtre hints.ai_family = AF_UNSPEC; // Allow IPv4 ou IPv6 hints.ai_socktype = SOCK_STREAM; // TCP (SOCK_DGRAM = UDP) hints.ai_flags = AI_PASSIVE; // mode SERVER hints.ai_protocol = 0; // non spécifié if( DEBUGMOD&SCK ) printf("============HINTS===========\n"); if( DEBUGMOD&SCK ) printf( "AI_FLAGS = %d\n", hints.ai_flags ); // int if( DEBUGMOD&SCK ) printf( "AI_FAMILY = %d\n", hints.ai_family ); // int if( DEBUGMOD&SCK ) printf( "AI_SOCKTYPE = %d\n", hints.ai_socktype ); // int if( DEBUGMOD&SCK ) printf( "AI_PROTOCOL = %d\n", hints.ai_protocol ); // int if( DEBUGMOD&SCK ) printf( "AI_ADDRLEN = %d\n", hints.ai_addrlen ); // int if( DEBUGMOD&SCK ) printf("\n"); /* [2] On récupère les infos =======================================================*/ if( strlen(*givenPort) == 0 ) // si pas défini, port dynamique getaddrinfo(serverHost, 0, &hints, &addrinfo); else // sinon manuel getaddrinfo(serverHost, *givenPort, &hints, &addrinfo); // Remarque: port=0 donc va être défini dynamiquement if( DEBUGMOD&SCK ) printf("=============RES============\n"); if( DEBUGMOD&SCK ) printf( "AI_FLAGS = %d\n", addrinfo->ai_flags ); // int if( DEBUGMOD&SCK ) printf( "AI_FAMILY = %d\n", addrinfo->ai_family ); // int if( DEBUGMOD&SCK ) printf( "AI_SOCKTYPE = %d\n", addrinfo->ai_socktype ); // int if( DEBUGMOD&SCK ) printf( "AI_PROTOCOL = %d\n", addrinfo->ai_protocol ); // int if( DEBUGMOD&SCK ) printf( "AI_ADDRLEN = %d\n", addrinfo->ai_addrlen ); // int if( DEBUGMOD&SCK ) printf("\n"); /* [3] Création de la socket =======================================================*/ SOCKET = socket(addrinfo->ai_family, addrinfo->ai_socktype, 0); if( DEBUGMOD&SCK ) printf("SOCKET = %d\n", SOCKET); // si erreur if( SOCKET == -1 ) return; /* [4] On publie la SOCKET =======================================================*/ BIND = bind( SOCKET, addrinfo->ai_addr, addrinfo->ai_addrlen ); if( DEBUGMOD&SCK ) printf("BIND = %d\n", BIND); // si erreur if( BIND == -1 ) return; /* [5] On récupère les informations du serveur (host/port) =======================================================*/ int getInfo = getsockname(SOCKET, (struct sockaddr *) &serverInfo, &sockaddr_len); if( getInfo == -1 ) return; getInfo = getnameinfo( // on récupère le host et le port (struct sockaddr *) &serverInfo, sizeof(serverInfo), infoHost, maxHostLen, infoPort, maxPortLen, NI_NUMERICHOST | NI_NUMERICSERV ); if( getInfo == -1 ) return; if( DEBUGMOD&SCK ) printf("Server host: %s\n", infoHost); if( DEBUGMOD&SCK ) printf("Server port: %s\n", infoPort); // on a plus besoin des infos de l'adresse freeaddrinfo(addrinfo); /* [6] On met la socket sur écoute =======================================================*/ LISTEN = listen(SOCKET, maxListLen); if( DEBUGMOD&SCK ) printf("LISTEN = %d\n", LISTEN); // si erreur if( LISTEN == -1 ) return; /* [7] On envoie les données par référence =======================================================*/ // port *givenPort = malloc( maxPortLen ); strcpy(*givenPort, infoPort); // socket d'écoute *listenSocket = SOCKET; } // CMD: CLIENT (SRV) PROXY (CLT) FTP // DTA: CLIENT (CLT) PROXY (CLT) FTP // void MANAGE_REQUEST(char* pRequest, int* DUSER_SOCKET, int* DFTP_SOCKET){ if( DEBUGMOD&HDR ) printf("====== MANAGE_REQUEST(%s, %d, %d) ======\n\n", pRequest, *DUSER_SOCKET, *DFTP_SOCKET); char answer[maxBuffLen]; // contiendra la réponse int nbSend; // contiendra le nombre de données envoyées char rCommand[10]; // contiendra les commandes (1ère partie) char rContent[maxBuffLen]; // contiendra le contenu associé à la commande (2ème partie) // on vide les buffers memset(&rCommand, '\0', sizeof(rCommand)); memset(&rContent, '\0', sizeof(rContent)); memset(&answer, '\0', sizeof(answer)); /* [1] On découpe la requête en 2 parties ================================================*/ splitFtpRequest(pRequest, rCommand, rContent); /* [2] Selection en fonction de @rCommand ================================================*/ /* (1) PORT a1,a2,a3,a4,p1,p2 => utilisateur (actif) --------------------------------------------*/ if( strcmp(rCommand, "PORT") == 0 ){ int a1, a2, a3, a4 = 0; int p1, p2 = 0; char serverHost[maxHostLen]; char serverPort[maxPortLen]; char BUFFER[maxBuffLen]; sscanf(pRequest, "PORT %d,%d,%d,%d,%d,%d", &a1, &a2, &a3, &a4, &p1, &p2); // on récupère l'adresse en sprintf(serverHost, "%d.%d.%d.%d", a1, a2, a3, a4); // on récupère le port en sprintf(serverPort, "%d", p1*256+p2); // on se connecte au client if( DEBUGMOD&SCK ) printf("CONNECTING TO CLIENT %s:%s\n", serverHost, serverPort); CONNECT_CLIENT(serverHost, serverPort, DUSER_SOCKET); if( DEBUGMOD&SCK ) printf("CONNECTED TO CLIENT %s:%s\n", serverHost, serverPort); // on envoie PASV car on veut être en mode passif entre le proxy et le serveur FTP strcpy(pRequest, "PASV\n"); } // WAIT_SOCKET_UPDATE(DFTP_SOCKET, BUFFER); // xPrint("FTPLIST: %s\n", BUFFER); /* [3] Envoi de la réponse ================================================*/ } void MANAGE_RESPONSE(int* USER_SOCKET, int* FTP_SOCKET, char* pAnswer, int* DUSER_SOCKET, int* DFTP_SOCKET){ if( DEBUGMOD&HDR ) printf("====== MANAGE_RESPONSE(%d, %s, %d, %d) ======\n\n", *USER_SOCKET, pAnswer, *DUSER_SOCKET, *DFTP_SOCKET); char response[maxBuffLen]; // contiendra la réponse char ftpCodeStr[4]; // contiendra le code FTP (1ère partie) char ftpText[maxBuffLen]; // contiendra le texte associé à la commande (2ème partie) int ftpCode; // contiendra le code FTP en numérique // on vide les buffers memset(&ftpCodeStr, '\0', sizeof(ftpCode)); memset(&ftpText, '\0', sizeof(ftpText)); memset(&response, '\0', sizeof(response)); /* [1] On découpe la requête en 2 parties ================================================*/ splitFtpResponse(pAnswer, ftpCodeStr, ftpText); // on met le code FTP en ftpCode = atoi( ftpCodeStr ); /* [2] Selection en fonction de @ftpCode ================================================*/ /* (2) Demande d'username --------------------------------------------*/ if( ftpCode == 220 ) strcpy(response, WLCM_MSG); /* (3) username OK -> demande MDP --------------------------------------------*/ else if( ftpCode == 331 ) strcpy(response, USER_MSG); /* (4) Bon mdp -> connection --------------------------------------------*/ else if( ftpCode == 230 ) strcpy(response, PASS_BON_MSG); /* (5) Mauvais mdp -> connection --------------------------------------------*/ else if( ftpCode == 530 ) strcpy(response, PASS_BAD_MSG); /* (6) Info SYST --------------------------------------------*/ // else if( ftpCode == 215 ) // strcpy(response, "bla\n"); /* (7) LOGOUT => EXIT --------------------------------------------*/ else if( ftpCode == 221 ) strcpy(response, EXIT_MSG); /* (8) Mode passif => On lance les SOCKETS du BUS DE DONNEES --------------------------------------------*/ else if( ftpCode == 227 ){ // on lance la SOCKET FTP du BUS DE DONNEES int a1, a2, a3, a4 = 0; int p1, p2 = 0; char serverHost[maxHostLen]; char serverPort[maxPortLen]; sscanf(pAnswer, "227 Entering Passive Mode (%d,%d,%d,%d,%d,%d)", &a1, &a2, &a3, &a4, &p1, &p2); // on récupère l'adresse en sprintf(serverHost, "%d.%d.%d.%d", a1, a2, a3, a4); // on récupère le port en sprintf(serverPort, "%d", p1*256+p2); // on se connecte au serveur FTP if( DEBUGMOD&SCK ) printf("CONNECTING TO FTP %s:%s\n", serverHost, serverPort); CONNECT_CLIENT(serverHost, serverPort, DFTP_SOCKET); if( DEBUGMOD&SCK ) printf("CONNECTED TO FTP %s:%s\n", serverHost, serverPort); strcpy(response, "200 PORT command successful\n"); } /* (9) On lit la SOCKET FTP du BUS DE DONNEES --------------------------------------------*/ else if( ftpCode == 150 ){ // on lit la SOCKET FTP du BUS DE DONNEES char BUFFER[maxBuffLen]; /* 1. Envoi au client de l'écoute de la réponse (associée) du BUS DE DONNEES */ // sread(FTP_SOCKET, BUFFER); // if( DEBUGMOD&CMD ) xPrint("F->P: %s\n", BUFFER); /* 2. On lit la SOCKET FTP (BUS DE DONNEES)*/ int nbRead = WAIT_SOCKET_UPDATE(DFTP_SOCKET, BUFFER); if( DEBUGMOD&DAT && nbRead == -1 ) printf("ERROR\n"); else if( DEBUGMOD&DAT ) xPrint("[BUS_IN]: %s\n", BUFFER); /* 3. On redirige sur la SOCKET utilisateur (BUS DE DONNEES) */ int nbSend = swrite(DUSER_SOCKET, BUFFER); if( DEBUGMOD&DAT && nbSend == -1 ) printf("ERROR\n"); else if( DEBUGMOD&DAT ) xPrint("[BUS_OUT]: %s\n", BUFFER); if( DEBUGMOD&DAT ) xPrint("BUS_FTP->BUS_CLIENT: %s\n", BUFFER); /* 4. On ferme les SOCKETS du BUS DE DONNEES */ close(*DFTP_SOCKET); if( DEBUGMOD&CMD ) printf("BUS_FTP fermé\n"); close(*DUSER_SOCKET); if( DEBUGMOD&CMD ) printf("BUS_USER fermé\n"); // on vide les SOCKET FTP des 2 BUS WAIT_SOCKET_UPDATE(FTP_SOCKET, BUFFER); // command if( DEBUGMOD&SCK ) printf("FTP[CMD] vidé: %s\n", BUFFER); WAIT_SOCKET_UPDATE(DFTP_SOCKET, BUFFER); // données if( DEBUGMOD&SCK ) printf("FTP[DAT] vidé: %s\n", BUFFER); swrite(USER_SOCKET, "150 Connection établie!\n"); if( DEBUGMOD&CMD ) xPrint("P->C: %s\n", "150 Connection établie!\n"); // fin de la transaction strcpy(response, "226 Données reçues!\n"); } /* (10) Fin de transfert de données --------------------------------------------*/ else if( ftpCode == 226 ){ // on ferme les SOCKETS du BUS DE DONNEES strcpy(response, "226 Fin de la transaction!\n"); close(*DUSER_SOCKET); close(*DFTP_SOCKET); } /* (n) Commande inconnue --------------------------------------------*/ else strcpy(response, pAnswer); /* [3] Retour de la réponse ================================================*/ strcpy(pAnswer, response); } int WAIT_SOCKET_UPDATE(int* pSocket, char* pBuffer){ memset(pBuffer, 0, maxBuffLen); // on vide le buffer int nbRead = 0; do{ nbRead = sread(pSocket, pBuffer); // si on est déconnecté, on ferme la SOCKET if( nbRead == -1 ){ printf("Client déconnecté!\n"); return -1; } }while( pBuffer[nbRead-1] != '\n' && pBuffer[nbRead-2] != '\r' ); // on retourne -1 si erreur, SINON 0 return nbRead; } // void prefixFtpResponse(char* pBuffer, char* ftpCode){ // }