Hi,
I'm making a windows port of some tftp client / server code from here
I've got the server working sucessfully with a diffrent client, however I have come to an impasse with the client code.
As I keep getting a server unreachable error, having tried over my local network and over localhost
Both the server and client for the most part share the same code, so my best guess is its an issue with hostent
or a windows specific header I have missed out.
since the server uses tftphdr instead of hostent.
any help will be appreciated thanks.
client.cpp
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <string.h>
#include <process.h>
#include <memory.h>
#include "tftp.h"
int TimeOut,NumberTimeOut,PortTFTP;
int create_socket(int type, int *ptr_port, struct sockaddr_in *ptr_address);
void tftp_connection(struct sockaddr_in *address,char *name)
{
FILE *f;
int r=255;
f=fopen(name,"rb");
r=tftp_send(address,name,"octet",1,TFTPsread,f);
fclose(f);
if (r!=0) printf("error tftp.\n\n");
};
using namespace std;
int main(int argc,char **argv)
{
struct hostent *hp; /* assigned to the server addres */
struct sockaddr_in server_connection;
TimeOut=7; //time out length
NumberTimeOut=3; // number of time outs
if (argc<2) {
fprintf(stderr,"Usage: client.exe <server_name or ip address> <port> <file_name>\n\n"
"All transfers are binary. If the file already exists, it will be replaced.\n\n");
exit(2);
};
//server address aquisition from the first argv
if ((hp=gethostbyname(argv[1]))==NULL) {
fprintf(stderr,"server %s is unreachable.\n",argv[1]);
exit(2);
}
else
{
printf("Server has sucessfully been reached\n");
}
PortTFTP=atol(argv[2]); //port definition matching command line argument
if (PortTFTP==0)
{
fprintf(stderr,"invalid port number.\n");
exit(3);
};
server_connection.sin_family=AF_INET;
server_connection.sin_port=htons(PortTFTP);
memcpy(&server_connection.sin_addr.s_addr, hp->h_addr, hp->h_length);
tftp_connection(&server_connection,argv[3]); //argv[3] is the file to be transfered
return 0;
};
tftp.h
#ifndef __TFTP_H
#define __TFTP_H 1
/*
*custom declaration
*/
#pragma pack(1)
typedef unsigned long DWORD;
typedef int BOOL;
typedef unsigned char BYTE;
typedef unsigned short WORD;
/*
* Trivial File Transfer Protocol (IEN-133)
*/
#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 */
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 */
} ;
#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
int tftp_receive(struct sockaddr_in *to, char *name, char *mode, int InClient,
char (*TFTPwrite)(char *,long ,char,void *),
void *argu);
int tftp_receive_ext(struct sockaddr_in *to1,char *name,char *mode,int InClient,
char (*TFTPwrite)(char *,long ,char,void *),
void *argu,int vPKTSIZE);
int tftp_send(struct sockaddr_in *to,char *name,char *mode,int InClient,
char (*TFTPread)(char *,long *,char,void *),
void *argu);
int tftp_send_ext(struct sockaddr_in *to,char *name,char *mode,int InClient,
char (*TFTPread)(char *,long *,char,void *),
void *argu,int vPKTSIZE);
char TFTPswrite(char *data,long n,char first,void *f);
// return 0 if no error.
char TFTPsread(char *data,long *n,char first,void *f);
// return 0 if no error.
int tftp_send_buffer(struct sockaddr_in *to,char *name,char *mode,char *datas,DWORD l);
/*
* 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 */
#endif /* tftp.h */
`
tftp.cpp
`
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#include "tftp.h"
#pragma comment(lib, "ws2_32.lib")
extern int TimeOut,NumberTimeOut;
#ifdef __sun__
#define FIONREAD I_NREAD
#endif
#define MIN(a,b) ((a)<(b)?(a):(b))
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;
}
extern int create_socket(int type, int *ptr_port, struct sockaddr_in *ptr_address);
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;
SOCKET dataSocket;
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 ((dataSocket=create_socket(SOCK_DGRAM, &i, NULL))<0)
{
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)
{
closesocket(dataSocket);
free(buf);
free(ackbuf);
return 255;
}
if (sendto(dataSocket,(const char*)ap,size,0,(struct sockaddr *)&to,tolen)!=size)
{
closesocket(dataSocket);
free(buf);
free(ackbuf);
return 255;
}
do
{
n=-1;
FD_ZERO(&lecture);
FD_SET(dataSocket,&lecture);
tv.tv_sec=TimeOut; tv.tv_usec=0;
if ((i=select(dataSocket+1, &lecture, NULL, NULL, &tv))==-1)
{
closesocket(dataSocket);
free(buf);
free(ackbuf);
return 255;
}
if (i>0)
n=recvfrom(dataSocket, (char *)dp, vPKTSIZE, 0,(struct sockaddr *)&from, (int *)&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)
{
closesocket(dataSocket);
free(buf);
free(ackbuf);
return 255;
}
if (dp->th_block != nextBlockNumber)
{
/* Re-synchronize with the other side */
ioctlsocket(dataSocket, FIONREAD, (u_long *)&i); //i=number of byte in read-buffer
while (i)
{
recv(dataSocket, (char *)dp, vPKTSIZE, 0);
ioctlsocket(dataSocket, FIONREAD, (u_long *)&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);
size=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)
{
closesocket(dataSocket);
free(buf);
free(ackbuf);
return i;
}
}
} while (n == vPKTSIZE);
/* send the "final" aknowledgement */
sendto(dataSocket, (const char *)ap, 4, 0,(struct sockaddr *)&to,tolen);
closesocket(dataSocket);
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,dataSocket;
unsigned short 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 ((dataSocket=create_socket(SOCK_DGRAM, &i, NULL))<0)
{
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((u_short)1);
if ((*TFTPread)(dat,(long*)(&size),1,argu)!=0)
{
closesocket(dataSocket);
free(buf);
free(ackbuf);
return 255;
}
size+=4;
nextBlockNumber=1;
}
do
{
ntimeout=0;
do
{
if (ntimeout==NumberTimeOut)
{
closesocket(dataSocket);
free(buf);
free(ackbuf);
return 255;
}
if (sendto(dataSocket,(const char *)dp,size,0,(struct sockaddr *)&to,tolen)!=size)
{
closesocket(dataSocket);
free(buf);
free(ackbuf);
return 255;
}
do
{
n=-1;
FD_ZERO(&lecture);
FD_SET(dataSocket,&lecture);
tv.tv_sec=TimeOut; tv.tv_usec=0;
if ((i=select(dataSocket+1, &lecture, NULL, NULL, &tv))==-1)
{
closesocket(dataSocket);
free(buf);
free(ackbuf);
return 255;
}
if (i>0) // = time out not expired
n=recvfrom(dataSocket, (char*)ap, vPKTSIZE, 0,(struct sockaddr *)&from, (int *)&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)
{
closesocket(dataSocket);
free(buf);
free(ackbuf);
return 255;
}
if (ap->th_block != nextBlockNumber)
{
/* Re-synchronize with the other side */
ioctlsocket(dataSocket, FIONREAD, (u_long *)&i); //i=number of byte in read-buffer
while (i)
{
recv(dataSocket, (char *)ap, vPKTSIZE, 0);
ioctlsocket(dataSocket, FIONREAD, (u_long *)&i);
}
ap->th_block=nextBlockNumber+1;
}
}
ntimeout++;
} while (ap->th_block!=nextBlockNumber);
if ((size<vPKTSIZE)&&(nextBlockNumber!=0)) break;
nextBlockNumber++;
dp->th_block=htons(nextBlockNumber);
if (nextBlockNumber==1)
{
dp->th_opcode=htons((u_short)DATA);
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)
{
closesocket(dataSocket);
free(buf);
free(ackbuf);
return i;
}
size+=4;
} while (Oldsize==vPKTSIZE);
closesocket(dataSocket);
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);
}
open_sok.cpp socket opener
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
static struct sockaddr_in address;
int create_socket(int type, int *ptr_port, struct sockaddr_in *ptr_address)
{
SOCKET desc;
unsigned int length=sizeof(struct sockaddr_in);
if ((desc = socket(AF_INET, type, 0)) == INVALID_SOCKET)
{
printf(" Error Cannot Create Socket!\n ");
return -1;
}
address.sin_family=AF_INET;
address.sin_addr.s_addr=htonl(INADDR_ANY);
address.sin_port=htons(*ptr_port);
if (bind(desc,(sockaddr *)&address,length) == SOCKET_ERROR)
{
printf("Socket attchment impossible. AND the error is %d\n", WSAGetLastError());
closesocket(desc);
return -1;
}
if (ptr_address!=NULL)
getsockname(desc,(sockaddr *)ptr_address, (int *)&length);
return desc;
}