// server.cpp : Defines the entry point for the console application.
//
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <netdb.h>
#include "pthread.h"
#include <string.h>
#include <arpa/inet.h>
#include <signal.h>
typedef struct threadinfo{
int socket;
struct sockaddr_in infosocket;
int comando;
char * comando_data;
unsigned int host;
int esesclavo;
} threadinfo;
typedef struct tcontrolinfo{
unsigned int hostesclavo;
unsigned int hostcontrolador;
unsigned int portcontrolador;
unsigned int portesclavo;
unsigned int hostftp;
int socket;
pthread_cond_t * condpas;
int * condpasvariable;
}tcontrolinfo;
threadinfo gwdatoscomunicador;
int socketprincipal; //utilizado solo para SIGINT ke lo cierre
void * thread_dataport(tcontrolinfo *);
void * threadprincipalftp(threadinfo *);
void * mandacontrolthread(tcontrolinfo *);
void acaba(int);
int mandacontrol(int,int,int,int,int);
int nthread;
pthread_cond_t condpasive;
//pthread_cond_t comunicador_haydatos;
pthread_mutex_t lock1;
int haydatos;
pthread_t threadkrap;
unsigned int comunicador_host;
unsigned int dsthost;
unsigned int localhost;
unsigned int dsthostftp;
int dstport;
int localport;
int iport;
int main(int argc, char* argv[])
{
int ilens;
int soket=0,sok2=0;
struct sockaddr_in sin;
struct sockaddr addr_accept;
threadinfo * puntinfothread;
int on;
//signal(SIGINT,acaba);
iport=7001;
nthread=0;
//inicializamos mutexes para comunicador master
pthread_mutex_init (&lock1, NULL);
pthread_cond_init (&condpasive, NULL);
//pthread_cond_init (&comunicador_nohaydatos, NULL);
//pthread_mutex_lock(&comunicador_lock);
//haydatos=0;
//pthread_cond_signal (&comunicador_nohaydatos);
//pthread_mutex_unlock (&comunicador_lock);
//pthread_create (&threadkrap, NULL, comunicador_master, 0);
if (argc<5 )
{
printf("eid0 inverse conection ftp emulator listener, \n usage: %s localip localport targetipcontroller targetport targetipftp\nRemember that the inverse conection hub must be running and the ipdest must be connected\n",argv[0]);
return 0;
}
//printf("Iniciando socket hacia fichero %s",argv[1]);
dsthost=inet_addr(argv[3]);
//dsthostftp=inet_addr(argv
dstport=atoi(argv[4]);
localport=atoi(argv[2]);
localhost=inet_addr(argv[1]);
if (argc==6) dsthostftp=inet_addr(argv[5]);
else dsthostftp=inet_addr("127.0.0.1");
memset (&sin,0,sizeof(sin));
sin.sin_family=PF_INET;
sin.sin_port=htons(localport);
//sin.sin_port=htons(1500);
//char * target_ip=argv[1];
//char target_ip[60]="192.168.0.1";
sin.sin_addr.s_addr=INADDR_ANY;
if ((soket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))==-1)
{
perror("error de socket");
return 0;
}
socketprincipal=soket;
on=1;
setsockopt(soket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (bind(soket,(const struct sockaddr *) &sin,sizeof(sin)))
{
perror("error en bind");
return 0;
}
if (listen(soket,3))
{
printf("error en listen");
return 0;
}
printf("bindeado en port %s\n",argv[2]);
ilens=sizeof(struct sockaddr_in);
//contathread=0;
while (1)
{
if ((sok2=accept(soket,&addr_accept,&ilens))==-1)
{
perror("error en accept");
return 0;
}
printf("main: llamando a threadprincipal\n");
puntinfothread=malloc(sizeof(threadinfo));
puntinfothread->socket=sok2;
//puntinfothread->threadid=contathread;
memcpy(&(puntinfothread->infosocket),&addr_accept,sizeof(struct sockaddr));
pthread_create(&threadkrap, NULL, threadprincipalftp,(void *)puntinfothread);
}
return 0;
}
void * threadprincipalftp(threadinfo * infothread)
{
int soket1,soket2,soket3;
char buffer[4096];
int locport;
int ilens;
struct sockaddr_in sin2;
struct sockaddr addr_accept;
pthread_cond_t condpas;
int condpasvariable;
fd_set fdsr;
int nbyt;
char * i1,*i3;
unsigned int i2,i4;
char buffernumero[50];
int numero[6];
int puertopasive;
int psoket; //sokets del server
pthread_t threadheader;
//threadinfo * puntinfothread;
char * buffer2; //buffer ke guardara informacion modificadat
tcontrolinfo * controlinfo;
soket1=(infothread)->socket;
free(infothread);
//char pasivo[200];
//mandacontrol(srcport,dsthost,dstport);
pthread_cond_init (&condpas, NULL);
printf("threadprincipalftp: iniciado\n");
if ((soket2=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))==-1)
{
perror("error de socket");
return 0;
}
comienzobind:
memset (&sin2,0,sizeof(struct sockaddr_in));
sin2.sin_family=PF_INET;
pthread_mutex_lock(&lock1);
sin2.sin_port=htons(iport);
locport=iport++;
pthread_mutex_unlock(&lock1);
sin2.sin_addr.s_addr=INADDR_ANY;
if (bind(soket2,(const struct sockaddr *) &sin2,sizeof(struct sockaddr)))
{
perror("error en bind");
goto comienzobind;
}
mandacontrol(dsthost,localhost,locport,dstport,dsthostftp);
if (listen(soket2,3))
{
printf("error en listen");
goto comienzobind;
}
printf("principalftp: bindeado en port %i\n",locport);
ilens=sizeof(struct sockaddr_in);
//contathread=0;
if ((soket3=accept(soket2,&addr_accept,&ilens))==-1) {
perror("error en accept");
goto comienzobind;
}
printf("principalftp: Se ha conectado el esclavo!!\n");
while (1) {
FD_ZERO(&fdsr);
//FD_ZERO(&fdse);
FD_SET(soket1,&fdsr);
//FD_SET(soket1,&fdse);
FD_SET(soket3,&fdsr);
//FD_SET(soket3,&fdse);
if (select(soket3+1, &fdsr, NULL, NULL, NULL) == -1) {
perror("principal: select");
goto quit;
}
if (FD_ISSET(soket1,&fdsr)){
if ((nbyt = recv(soket1,buffer,4095,0)) <= 0)
{
shutdown(soket3,1);
goto quit;
}
if ((send(soket3,buffer,nbyt,0)) <= 0)
goto quit;
}
if (FD_ISSET(soket3,&fdsr)) {
if ((nbyt = recv(soket3,buffer,4095,0)) <= 0)
{
shutdown(soket1,1);
goto quit;
}
buffer[nbyt]=0;
if ((i1=strstr(buffer,"227 Ent")))
{
printf("ENCONTRANDO PASV!! PASAMOS A CAMBIARLO!\n");
if ((i1=strchr(i1,'('))==0)
{perror("error de PASV");
//goto sinpasv;
}
i4=(unsigned int)i1;
for (i2=0;i2<5;i2++)
{
i1++;
i3=strchr(i1,',');
memcpy(buffernumero,i1,i3-i1);
buffernumero[i3-i1]=0;
numero[i2]=atoi(buffernumero);
i1=i3;
}
i3=strchr(i1,')');
i1++;
memcpy(buffernumero,i1,i3-i1);
buffernumero[i3-i1]=0;
numero[i2]=atoi(buffernumero);
//printf("numeros:%d,%d,%d,%d,%d,%d\n",numero[0],numero[1],numero[2],numero[3],numero[4],numero[5]);
//y ahora bindeamos un puerto nuevo
if ((psoket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))==-1)
{
perror("error de socket");
return 0;
}
comienzobind2:
memset (&sin2,0,sizeof(struct sockaddr));
sin2.sin_family=PF_INET;
pthread_mutex_lock(&lock1);
sin2.sin_port=htons(iport);
puertopasive=iport++;
pthread_mutex_unlock(&lock1);
sin2.sin_addr.s_addr=INADDR_ANY;
if (bind(psoket,(const struct sockaddr *) &sin2,sizeof(struct sockaddr)))
{
perror("error en bind");
goto comienzobind2;
}
//ahora crearemos un thread nuevo ke eskuche el el data port
condpasvariable=0;
controlinfo=malloc(sizeof(tcontrolinfo));
//mandacontrol(dsthost,localhost,locport,dstport);
controlinfo->socket=psoket;
controlinfo->hostesclavo=dsthost;
controlinfo->hostcontrolador=localhost;
controlinfo->portcontrolador=puertopasive;
controlinfo->portesclavo=((numero[4]<<8)|numero[5]);
controlinfo->condpas=&condpas;
controlinfo->condpasvariable=&condpasvariable;
printf("portesclavo original=%u\n",controlinfo->portesclavo);
//pthread_mutex_lock(&lock1);
//condpas=0;
//pthread_mutex_unlock(&lock1);
pthread_create(&threadheader, NULL, thread_dataport,(void *)controlinfo);
//ahora sustituiremos el comando
buffer2=malloc(4096);
memcpy(buffer2,buffer,i4-(unsigned int)buffer);//copiamos hasta (
sprintf(buffernumero,"(%u,%u,%u,%u,%u,%u",((unsigned char*)&localhost)[0],((unsigned char*)&localhost)[1],((unsigned char*)&localhost)[2],((unsigned char*)&localhost)[3],((unsigned char*)&puertopasive)[1],((unsigned char*)&puertopasive)[0]);
printf("comando pasive modificado a %s\n",buffernumero);
memcpy((char *)((unsigned int)buffer2+(unsigned int)i4-(unsigned int)buffer),buffernumero,strlen(buffernumero)+1);//copiamos el 0 para markarlo
i4=strlen(buffer2);
//printf("prueba: ->%s\n",buffer2);
//printf("-->%i,%i\n",1+nbyt-(unsigned int)i3+(unsigned int)buffer,i4);
memcpy(&(buffer2[i4]),i3,1+nbyt-(unsigned int)i3+(unsigned int)buffer);
//memcpy(&(buffer2[i4]),i3,1+nbyt-(unsigned int)i3+(unsigned int)buffer);
i4+=1+nbyt-(unsigned int)i3+(unsigned int)buffer;//nuevo tamaño de pakete de salida
buffer2[i4]=0;
//ahora tenemos ke esperar a bindear el puerto
pthread_mutex_lock(&lock1);
while (condpasvariable==0)
pthread_cond_wait(&condpas,&lock1);
pthread_mutex_unlock(&lock1);
condpasvariable=0;
sleep(2);
if ((send(soket1,buffer2,i4,0)) <= 0)
goto quit;
free(buffer2);
}//if strstr(227 PASSIVE)
else
if ((send(soket1,buffer,nbyt,0)) <= 0) goto quit;
}
}
quit:
//shutdown(osock,2);
printf("principal: cerrando sockets\n");
//shutdown(soket2,1);
//shutdown(soket3,1);
//shutdown(soket1,1);
close(soket3);
close(soket3);
close(soket1);
pthread_exit(0);
}
void * thread_dataport(tcontrolinfo * control)
{
int psoket,psoket2,psoket3,ilens;
int nbyt;
fd_set fdsr;
struct sockaddr addr_accept;
char buffer[10000];
int retselect;
unsigned int hostesclavo;
unsigned int hostcontrolador;
unsigned int hostftp;
int portesclavo;
int portcontrolador;
hostftp=control->hostftp;
hostesclavo=control->hostesclavo;
hostcontrolador=control->hostcontrolador;
portcontrolador=control->portcontrolador;
portesclavo=control->portesclavo;
// printf("threaddataport: mensaje control con datos %u,%u,%u,%u,%u\n",hostesclavo,hostcontrolador,portcontrolador,portesclavo,dsthostftp);
nbyt=0; //quita un warning;
psoket=control->socket;
//decimos al principal ke ya le puede decir al cliente ke se conecte
pthread_mutex_lock(&lock1);
*(control->condpasvariable)=1;
pthread_cond_signal(control->condpas);
pthread_mutex_unlock(&lock1);
if (listen(psoket,3)==-1)
{
printf("error en listen,data port acabado con error\n");
close(psoket);
return 0;
}
ilens=sizeof(struct sockaddr_in);
//contathread=0;
if ((psoket2=accept(psoket,&addr_accept,&ilens))==-1) {
perror("error en accept");
return 0;
//goto quit2;
}
printf("ftpdata: Se ha conectado el cliente\n");
mandacontrol(hostesclavo,hostcontrolador,portcontrolador,portesclavo,dsthostftp);
//ahora el stream ha mandado un mensaje de control sobre el server, esperaremos ke se nos conecte if ((psoket3=accept(psoket,&addr_accept,&ilens))==-1) {
perror("ftpdata: error en accept de server\n");
goto quit2;
}
printf("ftpdata: Se ha conectado el server\n");
/* Wait until buffer is not full */
retselect=1;
while (1) {
FD_ZERO(&fdsr);
//FD_ZERO(&fdse);
FD_SET(psoket2,&fdsr);
//FD_SET(psoket2,&fdse);
FD_SET(psoket3,&fdsr);
//FD_SET(psoket3,&fdse);
if ((select(psoket3+1, &fdsr, NULL, NULL, NULL)) == -1) {
perror("principal: select");
goto quit2;
}
if (retselect !=0) printf("dataport:Tenemos datos del select\n");
if (FD_ISSET(psoket2,&fdsr)){
if ((nbyt = recv(psoket2,buffer,9999,0)) <= 0)
{
shutdown(psoket3,1);
goto quit2;
}
if ((send(psoket3,buffer,nbyt,0)) <= 0)
goto quit2;
if (retselect !=0) printf("dataprt:Tenemos datos del select2\n");
}
if (FD_ISSET(psoket3,&fdsr)){
if ((nbyt = recv(psoket3,buffer,9999,0)) <= 0)
{
shutdown(psoket,1);
goto quit2;
}
if ((send(psoket2,buffer,nbyt,0)) <= 0) goto quit2;
if (retselect !=0) printf("dataprt:Tenemos datos del select3\n");
}
retselect=0;
}//while(1)
quit2:
free(control);
//shutdown(psoket,1);
//shutdown(psoket2,1);
//shutdown(psoket3,1);
//shutdown(psoket,1);
//close(psoket);
close(psoket2);
close(psoket3);
close(psoket);
printf("acabado conexion dataport\n");
pthread_exit(0);
//return 0;
}
int mandacontrol(hostesclavo,hostcontrol,portcontrol,portesclavo,hostftp)
{
tcontrolinfo *controlinfo;
controlinfo=malloc(sizeof(tcontrolinfo));
controlinfo->hostesclavo=hostesclavo;
controlinfo->hostcontrolador=hostcontrol;
controlinfo->portcontrolador=portcontrol;
controlinfo->portesclavo=portesclavo;
controlinfo->hostftp=hostftp;
pthread_create(&threadkrap, NULL, mandacontrolthread,(void *)controlinfo);
return 0;
}
void * mandacontrolthread(tcontrolinfo * control)
{
int soket;
char pakete[100];
struct sockaddr_in sin;
unsigned int hostesclavo;
unsigned int hostcontrolador;
unsigned int hostftp;
int portesclavo;
int portcontrolador;
hostesclavo=control->hostesclavo;
hostcontrolador=control->hostcontrolador;
portcontrolador=control->portcontrolador;
portesclavo=control->portesclavo;
hostftp=control->hostftp;
free(control);
memset(&sin,0,sizeof(struct sockaddr));
sin.sin_family=AF_INET;
sin.sin_port=htons(7000);
sin.sin_addr.s_addr=inet_addr("127.0.0.1");
if ((soket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))==-1)
perror("mandacontrol: socket");
if (connect(soket,(struct sockaddr *)&sin,sizeof(struct sockaddr))==-1)
perror("mandacontrol: connect");
sprintf(pakete,"CONTROL%03u.%03u.%03u.%03uREDIRECCIONAPUERTO%03u.%03u.%03u.%03u%05u%05u%03u.%03u.%03u.%03u\n",((unsigned char *)(&hostesclavo))[0],((unsigned char *)(&hostesclavo))[1],((unsigned char *)(&hostesclavo))[2],((unsigned char *)(&hostesclavo))[3],((unsigned char *)(&hostcontrolador))[0],((unsigned char *)(&hostcontrolador))[1],((unsigned char *)(&hostcontrolador))[2],((unsigned char *)(&hostcontrolador))[3],(unsigned int)portcontrolador,(unsigned int)portesclavo,((unsigned char *)(&hostftp))[0],((unsigned char *)(&hostftp))[1],((unsigned char *)(&hostftp))[2],((unsigned char *)(&hostftp))[3]);
printf("mandando pakete de control: %s\n",pakete);
send(soket,pakete,strlen(pakete),0);
shutdown(soket,2);
close(soket);
pthread_exit(0);
}
void acaba(senyal)
{
printf("Se acabo!!\n");
//close(socketprincipal);
exit(1);
}