Code:
if g++ -DHAVE_CONFIG_H -I. -I/root/server/src -I.. -O0 -g3 -MT server.o -MD -MP -MF ".deps/server.Tpo" -c -o server.o /root/server/src/server.cpp; then mv -f ".deps/server.Tpo" ".deps/server.Po"; else rm -f ".deps/server.Tpo"; exit 1; fi
/bin/sh ../libtool --tag=CXX --mode=link g++ -O0 -g3 -o server server.o
g++ -O0 -g3 -o server server.o
server.o(.text+0xfec): In function `tftpd_general(void*)':
/root/server/src/server.cpp:50: undefined reference to `pthread_detach'
server.o(.text+0x10dc): In function `tftp_connection(sockaddr_in, short, char*)':
/root/server/src/server.cpp:75: undefined reference to `pthread_create'
collect2: ld returned 1 exit status
gmake[2]: *** [server] Error 1
gmake[2]: Target `all' not remade because of errors.
gmake[2]: Nothing to be done for `all-am'.
gmake[1]:
*** [all-recursive] Error 1
gmake: *** [all] Error 2
*** Exited with status: 2 ***
if g++ -DHAVE_CONFIG_H -I. -I/root/server/src -I.. -O0 -g3 -MT server.o -MD -MP -MF ".deps/server.Tpo" -c -o server.o /root/server/src/server.cpp; then mv -f ".deps/server.Tpo" ".deps/server.Po"; else rm -f ".deps/server.Tpo"; exit 1; fi
/bin/sh ../libtool --tag=CXX --mode=link g++ -O0 -g3 -o server server.o
g++ -O0 -g3 -o server server.o
server.o(.text+0xfec): In function `tftpd_general(void*)':
/root/server/src/server.cpp:50: undefined reference to `pthread_detach'
server.o(.text+0x10dc): In function `tftp_connection(sockaddr_in, short, char*)':
/root/server/src/server.cpp:75: undefined reference to `pthread_create'
collect2: ld returned 1 exit status
gmake[2]: *** [server] Error 1
gmake[2]: Target `all' not remade because of errors.
gmake[2]: Nothing to be done for `all-am'.
gmake[1]:
*** [all-recursive] Error 1
gmake: *** [all] Error 2
*** Exited with status: 2 ***
to je izlaz
evo sad code
Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <syslog.h>
#include <netinet/in.h>
#include <pthread.h>
#include "tftp.h"
//int creer_socket(int type, int *ptr_port, struct sockaddr_in *ptr_adresse);
int TimeOut,NumberTimeOut,PortTFTP;
typedef struct connect_info_tag_S
{
char *name;
struct sockaddr_in address;
short job;
} connect_info_S;
void *tftpd_general(void *t)
{
connect_info_S *ci=(connect_info_S *)t;
int factice=0;
FILE *f;
int r=255;
if (ci->job==RRQ)
{
f=fopen(ci->name,"rb");
r=tftp_send(&ci->address,ci->name,"octet",0,TFTPsread,f);
fclose(f);
} else
{
f=fopen(ci->name,"wb");
r=tftp_receive(&ci->address,ci->name,"octet",0,TFTPswrite,f);
fclose(f);
};
if (r!=0) fprintf(stderr,"error tftp.\n");
free(ci->name);
free(ci);
pthread_detach(pthread_self());
pthread_exit(&factice);
return 0;
};
int tftp_connection(struct sockaddr_in _address, short _job, char *_name)
{
char *cp=_name;
pthread_t pthread_ident;
connect_info_S *ci;
while ((cp<_name+SEGSIZE-5)&&(*cp!=' ')&&(*cp!='\0')) cp++;
if ((*cp!= ' ')&&(*cp!='\0'))
{
return 255;
};
*cp='\0';
ci=(connect_info_S*)malloc(sizeof(connect_info_S));
ci->name=(char*)malloc(cp-_name+1);
strcpy(ci->name,_name);
ci->address=_address; ci->job=_job;
tftpd_general(ci);
pthread_create ( &pthread_ident, NULL,::tftpd_general, ci );
return 0;
};
int main(int argc, char *argv[])
{
struct sockaddr_in address;
int lg=sizeof(address),n;
int desc_socket;
char buf[PKTSIZE];
struct tftphdr *tp=(tftphdr *)&buf;
if (argc!=2)
{
printf("You must specify on the command line the number of the TFTP initial accept PORT.\n");
exit(255);
};
TimeOut=3;
NumberTimeOut=7;
PortTFTP=atol(argv[1]);
if (PortTFTP==0)
{
printf("invalid port number.");
exit(254);
};
/* creation et attachement du socket d'ecoute */
if ((desc_socket=creer_socket(SOCK_DGRAM, &PortTFTP, NULL))==-1)
{
syslog(LOG_ERR,"creation socket serveur: %m.\n");
exit(2);
};
printf("standard_tftp_server launched on port %i.\n",PortTFTP);
while (1)
{
do
n=recvfrom(desc_socket,tp,PKTSIZE,0,(sockaddr *)&address,(uint*)&lg);
while (n<0);
fprintf(stderr,"connection.\n");
tp->th_opcode=htons((u_short)tp->th_opcode);
if ((tp->th_opcode == WRQ)||(tp->th_opcode==RRQ))
tftp_connection(address,tp->th_opcode,&tp->th_stuff[0]);
};
};
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <syslog.h>
#include <netinet/in.h>
#include <pthread.h>
#include "tftp.h"
//int creer_socket(int type, int *ptr_port, struct sockaddr_in *ptr_adresse);
int TimeOut,NumberTimeOut,PortTFTP;
typedef struct connect_info_tag_S
{
char *name;
struct sockaddr_in address;
short job;
} connect_info_S;
void *tftpd_general(void *t)
{
connect_info_S *ci=(connect_info_S *)t;
int factice=0;
FILE *f;
int r=255;
if (ci->job==RRQ)
{
f=fopen(ci->name,"rb");
r=tftp_send(&ci->address,ci->name,"octet",0,TFTPsread,f);
fclose(f);
} else
{
f=fopen(ci->name,"wb");
r=tftp_receive(&ci->address,ci->name,"octet",0,TFTPswrite,f);
fclose(f);
};
if (r!=0) fprintf(stderr,"error tftp.\n");
free(ci->name);
free(ci);
pthread_detach(pthread_self());
pthread_exit(&factice);
return 0;
};
int tftp_connection(struct sockaddr_in _address, short _job, char *_name)
{
char *cp=_name;
pthread_t pthread_ident;
connect_info_S *ci;
while ((cp<_name+SEGSIZE-5)&&(*cp!=' ')&&(*cp!='\0')) cp++;
if ((*cp!= ' ')&&(*cp!='\0'))
{
return 255;
};
*cp='\0';
ci=(connect_info_S*)malloc(sizeof(connect_info_S));
ci->name=(char*)malloc(cp-_name+1);
strcpy(ci->name,_name);
ci->address=_address; ci->job=_job;
tftpd_general(ci);
pthread_create ( &pthread_ident, NULL,::tftpd_general, ci );
return 0;
};
int main(int argc, char *argv[])
{
struct sockaddr_in address;
int lg=sizeof(address),n;
int desc_socket;
char buf[PKTSIZE];
struct tftphdr *tp=(tftphdr *)&buf;
if (argc!=2)
{
printf("You must specify on the command line the number of the TFTP initial accept PORT.\n");
exit(255);
};
TimeOut=3;
NumberTimeOut=7;
PortTFTP=atol(argv[1]);
if (PortTFTP==0)
{
printf("invalid port number.");
exit(254);
};
/* creation et attachement du socket d'ecoute */
if ((desc_socket=creer_socket(SOCK_DGRAM, &PortTFTP, NULL))==-1)
{
syslog(LOG_ERR,"creation socket serveur: %m.\n");
exit(2);
};
printf("standard_tftp_server launched on port %i.\n",PortTFTP);
while (1)
{
do
n=recvfrom(desc_socket,tp,PKTSIZE,0,(sockaddr *)&address,(uint*)&lg);
while (n<0);
fprintf(stderr,"connection.\n");
tp->th_opcode=htons((u_short)tp->th_opcode);
if ((tp->th_opcode == WRQ)||(tp->th_opcode==RRQ))
tftp_connection(address,tp->th_opcode,&tp->th_stuff[0]);
};
};
evo i tftp.h ako neko zeli da proba
Code:
/***************************************************************************
* Copyright (C) 2007 by Refik Becirovic *
* [email protected] *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <syslog.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <unistd.h>
#include <stropts.h>
#include <stdio.h>
#include <unistd.h>
#define MIN(a,b) ((a)<(b)?(a):(b))
static struct sockaddr_in address;
int creer_socket(int type, int *ptr_port, struct sockaddr_in *ptr_adresse)
{
int desc; /* descripteur socket */
unsigned int duz=sizeof(struct sockaddr_in); /* taille adresse */
/* creation socket */
if ((desc=socket(AF_INET, type, 0))==-1)
{
fprintf(stderr,"Creation socket impossible");
return -1;
};
/* preparation de l'adresse d'attachement */
address.sin_family=AF_INET;
address.sin_addr.s_addr=htonl(INADDR_ANY);
address.sin_port=htons(*ptr_port); /*numero du port en format reseau */
/* demande d'attachement du socket */
if (bind(desc,(sockaddr *)&address,duz)==-1)
{
fprintf(stderr,"Attachement socket impossible.\n");
close(desc);
return -1;
};
/* recuperation de l'adresse effective d'attachement */
if (ptr_adresse!=NULL)
getsockname(desc,(sockaddr *)ptr_adresse,&duz);
return desc;
}
typedef unsigned long DWORD;
typedef int BOOL;
typedef unsigned char BYTE;
typedef unsigned short WORD;
#define SEGSIZE 512 /* data segment size */
#define PKTSIZE SEGSIZE+4 /* full packet size */
/*
* Packet types.
*/
#define RRQ 1 /* read request */
#define WRQ 2 /* write request */
#define DATA 3 /* data packet */
#define ACK 4 /* acknowledgement */
#define ERROR 5 /* error code */
#define th_block th_u.tu_block
#define th_code th_u.tu_code
#define th_stuff th_u.tu_stuff
#define th_msg th_data
/*
* Error codes.
*/
#define EUNDEF 0 /* not defined */
#define ENOTFOUND 1 /* file not found */
#define EACCESS 2 /* access violation */
#define ENOSPACE 3 /* disk full or allocation exceeded */
#define EBADOP 4 /* illegal TFTP operation */
#define EBADID 5 /* unknown transfer ID */
#define EEXISTS 6 /* file already exists */
#define ENOUSER 7 /* no such user */
struct tftphdr {
short th_opcode; /* packet type */
union {
unsigned short tu_block; /* block # */
short tu_code; /* error code */
char tu_stuff[1]; /* request packet stuff */
} th_u;
char th_data[1]; /* data or error string */
} __attribute__((packed));
extern int TimeOut,NumberTimeOut;
char TFTPswrite(char *data,long n,char first,void *f)
{
fwrite(data,n,1,(FILE *)f);
return 0;
};
char TFTPsread(char *data,long *n,char first,void *f)
{
*n=fread(data,1,SEGSIZE,(FILE *)f);
return 0;
};
typedef struct TFTParg_buffer_tag
{
char *dat;
long l;
} TFTParg_buffer;
char TFTPsSendBuffer(char *data,long *s,char first,void *a)
{
long size=MIN(PKTSIZE-4,((TFTParg_buffer *)a)->l);
*s=size;
memcpy(data,((TFTParg_buffer *)a)->dat,size);
((TFTParg_buffer *)a)->l-=size; ((TFTParg_buffer *)a)->dat+=size;
return 0;
};
int tftp_receive_ext(struct sockaddr_in *to1,char *name,char *mode,int InClient,
char (*TFTPwrite)(char *,long ,char,void *),
void *argu,int vPKTSIZE)
{
char *buf,*ackbuf,*dat,*cp;
tftphdr *dp,*ap;
int i,size,n,ntimeout,peer;
struct timeval tv;
u_short nextBlockNumber;
fd_set lecture;
struct sockaddr_in from,to=*to1;
size_t fromlen=sizeof(from),tolen=fromlen;
buf=(char*)malloc(vPKTSIZE);
if (buf==NULL)
{
fprintf(stderr,"TFTP: out of memory.\n");
return 255;
};
ackbuf=(char*)malloc(vPKTSIZE);
if (ackbuf==NULL)
{
fprintf(stderr,"TFTP: out of memory.\n");
free(buf);
return 255;
};
dp=(tftphdr *)buf;
ap=(tftphdr *)ackbuf;
dat=(char*)&dp->th_data[0];
cp=(char*)&ap->th_stuff[0];
i=0;
if ((peer=creer_socket(SOCK_DGRAM, &i, NULL))<0)
{
syslog(LOG_ERR,"creation socket client: %m\n");
free(buf); free(ackbuf);
return 255;
};
if (InClient)
{
ap->th_opcode=htons((u_short)RRQ);
strcpy(cp, name);
cp += strlen(name);
*cp++ = '\0';
strcpy(cp, mode);
cp += strlen(mode);
*cp++ = '\0';
size=(DWORD)cp-(DWORD)ackbuf;
} else
{
ap->th_opcode=htons((u_short)ACK);
ap->th_block=0;
size=4;
};
nextBlockNumber=1;
do
{
ntimeout=0;
do
{
if (ntimeout==NumberTimeOut) { close(peer); free(buf); free(ackbuf); return 255;}
if (sendto(peer,ap,size,0,(struct sockaddr *)&to,tolen)!=size)
{
syslog(LOG_ERR, "tftp: write: %m\n");
close(peer); free(buf); free(ackbuf);
return 255;
}
do
{
n=-1;
FD_ZERO(&lecture);
FD_SET(peer,&lecture);
tv.tv_sec=TimeOut; tv.tv_usec=0;
if ((i=select(peer+1, &lecture, NULL, NULL, &tv))==-1)
{
syslog(LOG_ERR,"erreur select.\n");
close(peer); free(buf); free(ackbuf);
return 255;
};
if (i>0) n=recvfrom(peer, dp, vPKTSIZE, 0,(struct sockaddr *)&from, &fromlen);
} while ((n<0)&&(i>0));
if (i>0)
{
to.sin_port=from.sin_port;
dp->th_opcode = ntohs((u_short)dp->th_opcode);
dp->th_block = ntohs((u_short)dp->th_block);
if (dp->th_opcode != DATA)
{
close(peer); free(buf); free(ackbuf);
return 255;
};
if (dp->th_block != nextBlockNumber)
{
/* Re-synchronize with the other side */
ioctl(peer, FIONREAD, &i); //i=number of byte in read-buffer
while (i)
{
recv(peer, dp, vPKTSIZE, 0);
ioctl(peer, FIONREAD, &i);
};
dp->th_block=nextBlockNumber+1;
};
};
ntimeout++;
} while (dp->th_block!=nextBlockNumber);
ap->th_block=htons(nextBlockNumber);
nextBlockNumber++;
if (nextBlockNumber==2)
{
ap->th_opcode=htons((u_short)ACK); // seulement utile si InClient=1
size=4;
};
// les données sont dans dat et leur longueur est de n-4
if (n-4>0)
{
if (nextBlockNumber==2) i=(*TFTPwrite)(dat,n-4,1,argu);
else i=(*TFTPwrite)(dat,n-4,0,argu);
if (i)
{
close(peer); free(buf); free(ackbuf);
return i;
};
};
} while (n == vPKTSIZE);
/* send the "final" ack */
sendto(peer, ap, 4, 0,(struct sockaddr *)&to,tolen);
close(peer); free(buf); free(ackbuf);
return 0;
};
int tftp_receive(struct sockaddr_in *to1,char *name,char *mode,int InClient,
char (*TFTPwrite)(char *,long ,char,void *),
void *argu)
{
return tftp_receive_ext(to1,name,mode,InClient,TFTPwrite,argu,PKTSIZE);
};
int tftp_send_ext(struct sockaddr_in *to1,char *name,char *mode,int InClient,
char (*TFTPread)(char *,long *,char,void *),
void *argu, int vPKTSIZE)
{
char *buf,*ackbuf,*dat,*cp;
tftphdr *dp,*ap;
int i,size,Oldsize=vPKTSIZE,n,ntimeout,peer;
ushort nextBlockNumber;
struct timeval tv;
fd_set lecture;
struct sockaddr_in from,to=*to1;
size_t fromlen=sizeof(from),tolen=fromlen;
buf=(char*)malloc(vPKTSIZE);
if (buf==NULL)
{
fprintf(stderr,"TFTP: out of memory.\n");
return 255;
};
ackbuf=(char*)malloc(vPKTSIZE);
if (ackbuf==NULL)
{
fprintf(stderr,"TFTP: out of memory.\n");
free(buf); return 255;
};
dp=(tftphdr *)buf;
ap=(tftphdr *)ackbuf;
dat=(char*)&dp->th_data[0];
cp=(char*)&dp->th_stuff[0];
i=0;
if ((peer=creer_socket(SOCK_DGRAM, &i, NULL))<0)
{
syslog(LOG_ERR,"creation socket client: %m\n");
free(buf); free(ackbuf);
return 255;
};
if (InClient)
{
dp->th_opcode=htons((u_short)WRQ);
strcpy(cp, name);
cp += strlen(name);
*cp++ = '\0';
strcpy(cp, mode);
cp += strlen(mode);
*cp++ = '\0';
size=(DWORD)cp-(DWORD)buf;
nextBlockNumber=0;
} else
{
dp->th_opcode=htons((u_short)DATA);
dp->th_block=htons((ushort)1);
if ((*TFTPread)(dat,(long*)(&size),1,argu)!=0)
{
close(peer); free(buf); free(ackbuf);
return 255;
};
size+=4;
nextBlockNumber=1;
};
do
{
ntimeout=0;
do
{
if (ntimeout==NumberTimeOut) { close(peer); free(buf); free(ackbuf); return 255;}
if (sendto(peer,dp,size,0,(struct sockaddr *)&to,tolen)!=size)
{
syslog(LOG_ERR, "tftp: write: %m\n");
close(peer); free(buf); free(ackbuf);
return 255;
};
do
{
n=-1;
FD_ZERO(&lecture);
FD_SET(peer,&lecture);
tv.tv_sec=TimeOut; tv.tv_usec=0;
if ((i=select(peer+1, &lecture, NULL, NULL, &tv))==-1)
{
syslog(LOG_ERR,"erreur select.\n");
close(peer); free(buf); free(ackbuf);
return 255;
};
if (i>0) // = time out not expired
n=recvfrom(peer, ap, vPKTSIZE, 0,(struct sockaddr *)&from, &fromlen);
} while ((n<0)&&(i>0));
if (i>0)
{
to.sin_port=from.sin_port;
ap->th_opcode = ntohs((u_short)ap->th_opcode);
ap->th_block = ntohs((u_short)ap->th_block);
if (ap->th_opcode != ACK) { close(peer); free(buf); free(ackbuf); return 255;}
if (ap->th_block != nextBlockNumber)
{
/* Re-synchronize with the other side */
ioctl(peer, FIONREAD, &i); //i=number of byte in read-buffer
while (i)
{
recv(peer, ap, vPKTSIZE, 0);
ioctl(peer, FIONREAD, &i);
};
ap->th_block=nextBlockNumber+1;
};
};
ntimeout++;
} while (ap->th_block!=nextBlockNumber);
if ((size<vPKTSIZE)&&(nextBlockNumber!=0)) break; // tout a déjŕ été envoyé dans le 1er packet de DATA
// attention pour ce test si on fait le "tour" du ushort !!
nextBlockNumber++;
dp->th_block=htons(nextBlockNumber);
if (nextBlockNumber==1)
{
dp->th_opcode=htons((u_short)DATA); // seulement utile si InClient=1
i=(*TFTPread)(dat,(long*)(&size),1,argu);
} else
{
Oldsize=size;
if (Oldsize==vPKTSIZE) i=(*TFTPread)(dat,(long*)(&size),0,argu);
else i=0;
};
if (i)
{
close(peer); free(buf); free(ackbuf);
return i;
};
size+=4;
} while (Oldsize==vPKTSIZE);
close(peer); free(buf); free(ackbuf);
return 0;
};
int tftp_send(struct sockaddr_in *to1,char *name,char *mode,int InClient,
char (*TFTPread)(char *,long *,char,void *),
void *argu)
{
return tftp_send_ext(to1,name,mode,InClient,TFTPread,argu,PKTSIZE);
};
int tftp_send_buffer(struct sockaddr_in *to,char *name,char *mode,char *datas,DWORD l)
{
TFTParg_buffer a;
a.dat=datas;
a.l=l;
return tftp_send(to,name,mode,1,TFTPsSendBuffer,&a);
};
/***************************************************************************
* Copyright (C) 2007 by Refik Becirovic *
* [email protected] *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <syslog.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <unistd.h>
#include <stropts.h>
#include <stdio.h>
#include <unistd.h>
#define MIN(a,b) ((a)<(b)?(a):(b))
static struct sockaddr_in address;
int creer_socket(int type, int *ptr_port, struct sockaddr_in *ptr_adresse)
{
int desc; /* descripteur socket */
unsigned int duz=sizeof(struct sockaddr_in); /* taille adresse */
/* creation socket */
if ((desc=socket(AF_INET, type, 0))==-1)
{
fprintf(stderr,"Creation socket impossible");
return -1;
};
/* preparation de l'adresse d'attachement */
address.sin_family=AF_INET;
address.sin_addr.s_addr=htonl(INADDR_ANY);
address.sin_port=htons(*ptr_port); /*numero du port en format reseau */
/* demande d'attachement du socket */
if (bind(desc,(sockaddr *)&address,duz)==-1)
{
fprintf(stderr,"Attachement socket impossible.\n");
close(desc);
return -1;
};
/* recuperation de l'adresse effective d'attachement */
if (ptr_adresse!=NULL)
getsockname(desc,(sockaddr *)ptr_adresse,&duz);
return desc;
}
typedef unsigned long DWORD;
typedef int BOOL;
typedef unsigned char BYTE;
typedef unsigned short WORD;
#define SEGSIZE 512 /* data segment size */
#define PKTSIZE SEGSIZE+4 /* full packet size */
/*
* Packet types.
*/
#define RRQ 1 /* read request */
#define WRQ 2 /* write request */
#define DATA 3 /* data packet */
#define ACK 4 /* acknowledgement */
#define ERROR 5 /* error code */
#define th_block th_u.tu_block
#define th_code th_u.tu_code
#define th_stuff th_u.tu_stuff
#define th_msg th_data
/*
* Error codes.
*/
#define EUNDEF 0 /* not defined */
#define ENOTFOUND 1 /* file not found */
#define EACCESS 2 /* access violation */
#define ENOSPACE 3 /* disk full or allocation exceeded */
#define EBADOP 4 /* illegal TFTP operation */
#define EBADID 5 /* unknown transfer ID */
#define EEXISTS 6 /* file already exists */
#define ENOUSER 7 /* no such user */
struct tftphdr {
short th_opcode; /* packet type */
union {
unsigned short tu_block; /* block # */
short tu_code; /* error code */
char tu_stuff[1]; /* request packet stuff */
} th_u;
char th_data[1]; /* data or error string */
} __attribute__((packed));
extern int TimeOut,NumberTimeOut;
char TFTPswrite(char *data,long n,char first,void *f)
{
fwrite(data,n,1,(FILE *)f);
return 0;
};
char TFTPsread(char *data,long *n,char first,void *f)
{
*n=fread(data,1,SEGSIZE,(FILE *)f);
return 0;
};
typedef struct TFTParg_buffer_tag
{
char *dat;
long l;
} TFTParg_buffer;
char TFTPsSendBuffer(char *data,long *s,char first,void *a)
{
long size=MIN(PKTSIZE-4,((TFTParg_buffer *)a)->l);
*s=size;
memcpy(data,((TFTParg_buffer *)a)->dat,size);
((TFTParg_buffer *)a)->l-=size; ((TFTParg_buffer *)a)->dat+=size;
return 0;
};
int tftp_receive_ext(struct sockaddr_in *to1,char *name,char *mode,int InClient,
char (*TFTPwrite)(char *,long ,char,void *),
void *argu,int vPKTSIZE)
{
char *buf,*ackbuf,*dat,*cp;
tftphdr *dp,*ap;
int i,size,n,ntimeout,peer;
struct timeval tv;
u_short nextBlockNumber;
fd_set lecture;
struct sockaddr_in from,to=*to1;
size_t fromlen=sizeof(from),tolen=fromlen;
buf=(char*)malloc(vPKTSIZE);
if (buf==NULL)
{
fprintf(stderr,"TFTP: out of memory.\n");
return 255;
};
ackbuf=(char*)malloc(vPKTSIZE);
if (ackbuf==NULL)
{
fprintf(stderr,"TFTP: out of memory.\n");
free(buf);
return 255;
};
dp=(tftphdr *)buf;
ap=(tftphdr *)ackbuf;
dat=(char*)&dp->th_data[0];
cp=(char*)&ap->th_stuff[0];
i=0;
if ((peer=creer_socket(SOCK_DGRAM, &i, NULL))<0)
{
syslog(LOG_ERR,"creation socket client: %m\n");
free(buf); free(ackbuf);
return 255;
};
if (InClient)
{
ap->th_opcode=htons((u_short)RRQ);
strcpy(cp, name);
cp += strlen(name);
*cp++ = '\0';
strcpy(cp, mode);
cp += strlen(mode);
*cp++ = '\0';
size=(DWORD)cp-(DWORD)ackbuf;
} else
{
ap->th_opcode=htons((u_short)ACK);
ap->th_block=0;
size=4;
};
nextBlockNumber=1;
do
{
ntimeout=0;
do
{
if (ntimeout==NumberTimeOut) { close(peer); free(buf); free(ackbuf); return 255;}
if (sendto(peer,ap,size,0,(struct sockaddr *)&to,tolen)!=size)
{
syslog(LOG_ERR, "tftp: write: %m\n");
close(peer); free(buf); free(ackbuf);
return 255;
}
do
{
n=-1;
FD_ZERO(&lecture);
FD_SET(peer,&lecture);
tv.tv_sec=TimeOut; tv.tv_usec=0;
if ((i=select(peer+1, &lecture, NULL, NULL, &tv))==-1)
{
syslog(LOG_ERR,"erreur select.\n");
close(peer); free(buf); free(ackbuf);
return 255;
};
if (i>0) n=recvfrom(peer, dp, vPKTSIZE, 0,(struct sockaddr *)&from, &fromlen);
} while ((n<0)&&(i>0));
if (i>0)
{
to.sin_port=from.sin_port;
dp->th_opcode = ntohs((u_short)dp->th_opcode);
dp->th_block = ntohs((u_short)dp->th_block);
if (dp->th_opcode != DATA)
{
close(peer); free(buf); free(ackbuf);
return 255;
};
if (dp->th_block != nextBlockNumber)
{
/* Re-synchronize with the other side */
ioctl(peer, FIONREAD, &i); //i=number of byte in read-buffer
while (i)
{
recv(peer, dp, vPKTSIZE, 0);
ioctl(peer, FIONREAD, &i);
};
dp->th_block=nextBlockNumber+1;
};
};
ntimeout++;
} while (dp->th_block!=nextBlockNumber);
ap->th_block=htons(nextBlockNumber);
nextBlockNumber++;
if (nextBlockNumber==2)
{
ap->th_opcode=htons((u_short)ACK); // seulement utile si InClient=1
size=4;
};
// les données sont dans dat et leur longueur est de n-4
if (n-4>0)
{
if (nextBlockNumber==2) i=(*TFTPwrite)(dat,n-4,1,argu);
else i=(*TFTPwrite)(dat,n-4,0,argu);
if (i)
{
close(peer); free(buf); free(ackbuf);
return i;
};
};
} while (n == vPKTSIZE);
/* send the "final" ack */
sendto(peer, ap, 4, 0,(struct sockaddr *)&to,tolen);
close(peer); free(buf); free(ackbuf);
return 0;
};
int tftp_receive(struct sockaddr_in *to1,char *name,char *mode,int InClient,
char (*TFTPwrite)(char *,long ,char,void *),
void *argu)
{
return tftp_receive_ext(to1,name,mode,InClient,TFTPwrite,argu,PKTSIZE);
};
int tftp_send_ext(struct sockaddr_in *to1,char *name,char *mode,int InClient,
char (*TFTPread)(char *,long *,char,void *),
void *argu, int vPKTSIZE)
{
char *buf,*ackbuf,*dat,*cp;
tftphdr *dp,*ap;
int i,size,Oldsize=vPKTSIZE,n,ntimeout,peer;
ushort nextBlockNumber;
struct timeval tv;
fd_set lecture;
struct sockaddr_in from,to=*to1;
size_t fromlen=sizeof(from),tolen=fromlen;
buf=(char*)malloc(vPKTSIZE);
if (buf==NULL)
{
fprintf(stderr,"TFTP: out of memory.\n");
return 255;
};
ackbuf=(char*)malloc(vPKTSIZE);
if (ackbuf==NULL)
{
fprintf(stderr,"TFTP: out of memory.\n");
free(buf); return 255;
};
dp=(tftphdr *)buf;
ap=(tftphdr *)ackbuf;
dat=(char*)&dp->th_data[0];
cp=(char*)&dp->th_stuff[0];
i=0;
if ((peer=creer_socket(SOCK_DGRAM, &i, NULL))<0)
{
syslog(LOG_ERR,"creation socket client: %m\n");
free(buf); free(ackbuf);
return 255;
};
if (InClient)
{
dp->th_opcode=htons((u_short)WRQ);
strcpy(cp, name);
cp += strlen(name);
*cp++ = '\0';
strcpy(cp, mode);
cp += strlen(mode);
*cp++ = '\0';
size=(DWORD)cp-(DWORD)buf;
nextBlockNumber=0;
} else
{
dp->th_opcode=htons((u_short)DATA);
dp->th_block=htons((ushort)1);
if ((*TFTPread)(dat,(long*)(&size),1,argu)!=0)
{
close(peer); free(buf); free(ackbuf);
return 255;
};
size+=4;
nextBlockNumber=1;
};
do
{
ntimeout=0;
do
{
if (ntimeout==NumberTimeOut) { close(peer); free(buf); free(ackbuf); return 255;}
if (sendto(peer,dp,size,0,(struct sockaddr *)&to,tolen)!=size)
{
syslog(LOG_ERR, "tftp: write: %m\n");
close(peer); free(buf); free(ackbuf);
return 255;
};
do
{
n=-1;
FD_ZERO(&lecture);
FD_SET(peer,&lecture);
tv.tv_sec=TimeOut; tv.tv_usec=0;
if ((i=select(peer+1, &lecture, NULL, NULL, &tv))==-1)
{
syslog(LOG_ERR,"erreur select.\n");
close(peer); free(buf); free(ackbuf);
return 255;
};
if (i>0) // = time out not expired
n=recvfrom(peer, ap, vPKTSIZE, 0,(struct sockaddr *)&from, &fromlen);
} while ((n<0)&&(i>0));
if (i>0)
{
to.sin_port=from.sin_port;
ap->th_opcode = ntohs((u_short)ap->th_opcode);
ap->th_block = ntohs((u_short)ap->th_block);
if (ap->th_opcode != ACK) { close(peer); free(buf); free(ackbuf); return 255;}
if (ap->th_block != nextBlockNumber)
{
/* Re-synchronize with the other side */
ioctl(peer, FIONREAD, &i); //i=number of byte in read-buffer
while (i)
{
recv(peer, ap, vPKTSIZE, 0);
ioctl(peer, FIONREAD, &i);
};
ap->th_block=nextBlockNumber+1;
};
};
ntimeout++;
} while (ap->th_block!=nextBlockNumber);
if ((size<vPKTSIZE)&&(nextBlockNumber!=0)) break; // tout a déjŕ été envoyé dans le 1er packet de DATA
// attention pour ce test si on fait le "tour" du ushort !!
nextBlockNumber++;
dp->th_block=htons(nextBlockNumber);
if (nextBlockNumber==1)
{
dp->th_opcode=htons((u_short)DATA); // seulement utile si InClient=1
i=(*TFTPread)(dat,(long*)(&size),1,argu);
} else
{
Oldsize=size;
if (Oldsize==vPKTSIZE) i=(*TFTPread)(dat,(long*)(&size),0,argu);
else i=0;
};
if (i)
{
close(peer); free(buf); free(ackbuf);
return i;
};
size+=4;
} while (Oldsize==vPKTSIZE);
close(peer); free(buf); free(ackbuf);
return 0;
};
int tftp_send(struct sockaddr_in *to1,char *name,char *mode,int InClient,
char (*TFTPread)(char *,long *,char,void *),
void *argu)
{
return tftp_send_ext(to1,name,mode,InClient,TFTPread,argu,PKTSIZE);
};
int tftp_send_buffer(struct sockaddr_in *to,char *name,char *mode,char *datas,DWORD l)
{
TFTParg_buffer a;
a.dat=datas;
a.l=l;
return tftp_send(to,name,mode,1,TFTPsSendBuffer,&a);
};
refa