initial commit
This commit is contained in:
31
lib/amb1_sdk/common/network/tftp/tftp.h
Normal file
31
lib/amb1_sdk/common/network/tftp/tftp.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef TFTP_H
|
||||
#define TFTP_H
|
||||
|
||||
#define port 69
|
||||
#define ERROR -1
|
||||
|
||||
#define RRQ 1
|
||||
#define WRQ 2
|
||||
#define DATA 3
|
||||
#define ACK 0x04
|
||||
#define ERR 0x05
|
||||
|
||||
#define BLOCK_SIZE (512+4)
|
||||
|
||||
typedef struct _tftp{
|
||||
void (*recv_handle)(unsigned char *buffer,int len, unsigned int index);
|
||||
void (*send_handle)(unsigned char *buffer,int *len, unsigned int index);
|
||||
const char *tftp_file_name;
|
||||
const char *tftp_mode;
|
||||
const char *tftp_host;
|
||||
int tftp_port;
|
||||
unsigned char tftp_buf[BLOCK_SIZE];
|
||||
int tftp_op;
|
||||
unsigned int tftp_retry_num;
|
||||
unsigned int tftp_timeout;
|
||||
}tftp;
|
||||
|
||||
int tftp_client_start(tftp *tftp_handler);
|
||||
int tftp_server_start(tftp *tftp_handler);
|
||||
|
||||
#endif
|
||||
378
lib/amb1_sdk/common/network/tftp/tftp_client.c
Normal file
378
lib/amb1_sdk/common/network/tftp/tftp_client.c
Normal file
@@ -0,0 +1,378 @@
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
#include <platform/platform_stdlib.h>
|
||||
#include <lwip/sockets.h>
|
||||
#include <lwip/netdb.h>
|
||||
#include "tftp.h"
|
||||
|
||||
#include "wifi_conf.h"
|
||||
|
||||
int req_packet (int opcode, const char *filename,const char *mode, char buf[], int size)
|
||||
{
|
||||
int len;
|
||||
|
||||
len =sprintf (buf, "%c%c%s%c%s%c", 0x00, opcode, filename, 0x00, mode, 0x00);
|
||||
|
||||
if (len == 0){
|
||||
printf ("Error in creating the request packet\r\n"); /*could not print to the client buffer */
|
||||
return -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void ip_port (struct sockaddr_in host)
|
||||
{
|
||||
printf ("The IP port pair for the host is: IP:%s Port:%d \n",inet_ntoa (host.sin_addr), ntohs (host.sin_port));
|
||||
}
|
||||
|
||||
|
||||
int tftp_client_send (const char *pFilename, struct sockaddr_in server,const char *pMode, int sock,tftp *tftp_handler)
|
||||
{
|
||||
/* local variables */
|
||||
int len, server_len, opcode, j, n, tid = 0;
|
||||
unsigned short int count = 0, rcount = 0;
|
||||
unsigned char packetbuf[64];
|
||||
char *bufindex;
|
||||
struct sockaddr_in data;
|
||||
|
||||
n = BLOCK_SIZE;
|
||||
|
||||
fd_set read_fds;
|
||||
struct timeval time_out;
|
||||
|
||||
while(1){
|
||||
|
||||
for (j = 0; j < tftp_handler->tftp_retry_num; j++){ /* this allows us to loop until we either break out by getting the correct ack OR time out because we've looped more than RETRIES times */
|
||||
|
||||
server_len = sizeof (data);
|
||||
time_out.tv_sec = tftp_handler->tftp_timeout; // Set select timeout of 3 seconds
|
||||
time_out.tv_usec = 0;
|
||||
FD_ZERO(&read_fds) ;
|
||||
FD_SET(sock, &read_fds); // Only set server fd
|
||||
if(select(sock + 1, &read_fds, NULL, NULL, &time_out) == 1){
|
||||
n = recvfrom (sock, tftp_handler->tftp_buf, BLOCK_SIZE, 0,(struct sockaddr *) &data,(socklen_t *) & server_len);
|
||||
if(n < 0){
|
||||
printf("could not read datagram\r\n");
|
||||
goto exit;
|
||||
}
|
||||
}else{
|
||||
if(count == 0){
|
||||
printf("Resend the wrq request");
|
||||
goto exit;
|
||||
}else{
|
||||
printf("timeout\r\n");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//printf("get count = %d num = %d\r\n",count,n);
|
||||
|
||||
if (!tid){
|
||||
tid = ntohs (data.sin_port); //get the tid of the server.
|
||||
server.sin_port = htons (tid); //set the tid for rest of the transfer
|
||||
}
|
||||
|
||||
if (server.sin_addr.s_addr != data.sin_addr.s_addr){ /* checks to ensure get from ip is same from ACK IP */
|
||||
printf("Error recieving file (data from invalid address)\n");
|
||||
j--;
|
||||
continue; /* we aren't going to let another connection spoil our first connection */
|
||||
}
|
||||
|
||||
if (tid != ntohs (server.sin_port)){ /* checks to ensure get from the correct TID */
|
||||
printf ("Error recieving file (data from invalid tid)\n");
|
||||
len = sprintf ((char *) packetbuf,"%c%c%c%cBad/Unknown TID%c",0x00, 0x05, 0x00, 0x05, 0x00);
|
||||
if (sendto (sock, packetbuf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len){ /* send the data packet */
|
||||
printf("Mismatch in number of sent bytes while trying to send mode error packet\n");
|
||||
}
|
||||
j--;
|
||||
continue; /* we aren't going to let another connection spoil our first connection */
|
||||
}
|
||||
|
||||
/* this formatting code is just like the code in the main function */
|
||||
bufindex = (char *) tftp_handler->tftp_buf; //start our pointer going
|
||||
if (bufindex++[0] != 0x00){
|
||||
printf ("bad first nullbyte!\n");
|
||||
goto exit;
|
||||
}
|
||||
opcode = *bufindex++;
|
||||
rcount = *bufindex++ << 8;
|
||||
rcount &= 0xff00;
|
||||
rcount += (*bufindex++ & 0x00ff);
|
||||
|
||||
if (opcode != 0X04 ){ /* ack packet should have code 3 (data) and should be ack+1 the packet we just sent */
|
||||
printf("Client: Remote host failed to ACK proper data packet # %d (got OP: %d Block: %d)\n",count, opcode, rcount);
|
||||
//printf("Badly ordered/invalid data packet (Got OP: %d Block: %d) (Wanted Op: 3 Block: %d)\n",opcode, rcount, count);
|
||||
/* sending error message */
|
||||
if (opcode > 5)
|
||||
{
|
||||
len = sprintf ((char *) packetbuf,"%c%c%c%cIllegal operation%c",0x00, 0x05, 0x00, 0x04, 0x00);
|
||||
if (sendto (sock, packetbuf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len){ /* send the data packet */
|
||||
printf("Mismatch in number of sent bytes while trying to send mode error packet\n");
|
||||
}
|
||||
}else{
|
||||
bufindex = (char *) tftp_handler->tftp_buf;
|
||||
bufindex += 3;
|
||||
printf("error opcode = %d message = %s\r\n",opcode,bufindex);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
if(rcount != count){
|
||||
//printf("error:rcount = %d count = %d\r\n",rcount,count);
|
||||
len = sprintf ((char *) tftp_handler->tftp_buf, "%c%c%c%c", 0x00, 0x03, 0x00, 0x00); /* build data packet but write out the count as zero */
|
||||
//tftp_handler->send_handle(tftp_handler->tftp_buf+4,&len,count);
|
||||
tftp_handler->tftp_buf[2] = (count & 0xFF00) >> 8; //fill in the count (top number first)
|
||||
tftp_handler->tftp_buf[3] = (count & 0x00FF); //fill in the lower part of the count
|
||||
//len+=4;
|
||||
if (sendto(sock, tftp_handler->tftp_buf, len, 0, (struct sockaddr *) &server,sizeof (server)) != len){
|
||||
printf ("Mismatch in number of sent bytes\n");
|
||||
goto exit;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
//send file to tftp server
|
||||
//printf("ok:rcount = %d count = %d\r\n",rcount,count);
|
||||
count++;
|
||||
|
||||
sprintf ((char *) tftp_handler->tftp_buf, "%c%c%c%c", 0x00, 0x03, 0x00, 0x00); /* build data packet but write out the count as zero */
|
||||
tftp_handler->send_handle(tftp_handler->tftp_buf+4,&len,count);
|
||||
tftp_handler->tftp_buf[2] = (count & 0xFF00) >> 8; //fill in the count (top number first)
|
||||
tftp_handler->tftp_buf[3] = (count & 0x00FF); //fill in the lower part of the count
|
||||
len+=4;
|
||||
//printf("len = %d\r\n",len);
|
||||
if (sendto(sock, tftp_handler->tftp_buf, len, 0, (struct sockaddr *) &server,sizeof (server)) != len){
|
||||
printf ("Mismatch in number of sent bytes\n");
|
||||
goto exit;
|
||||
}else if(len != BLOCK_SIZE){
|
||||
printf("Send file finish last chunk = %d\r\n",len-4);
|
||||
goto done;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j == tftp_handler->tftp_retry_num){
|
||||
printf ("Data recieve Timeout. Aborting transfer\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
}
|
||||
exit:
|
||||
return -1;
|
||||
done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tftp_client_get (const char *pFilename, struct sockaddr_in server,const char *pMode, int sock,tftp *tftp_handler)
|
||||
{
|
||||
/* local variables */
|
||||
int len, server_len, opcode, j, n, tid = 0;
|
||||
unsigned short int count = 0, rcount = 0;
|
||||
unsigned char packetbuf[64];
|
||||
//int errno;
|
||||
char *bufindex, ackbuf[12];
|
||||
struct sockaddr_in data;
|
||||
|
||||
n = BLOCK_SIZE;
|
||||
|
||||
fd_set read_fds;
|
||||
struct timeval time_out;
|
||||
|
||||
printf("tftp_client_get\r\n");
|
||||
|
||||
while(1){
|
||||
|
||||
if (n != BLOCK_SIZE){ /* remember if our datasize is less than a full packet this was the last packet to be received */
|
||||
|
||||
printf("Last chunk detected (file chunk size: %d). exiting while loop\n",n - 4);
|
||||
len = sprintf (ackbuf, "%c%c%c%c", 0x00, 0x04, 0x00, 0x00);
|
||||
ackbuf[2] = (count & 0xFF00) >> 8; //fill in the count (top number first)
|
||||
ackbuf[3] = (count & 0x00FF); //fill in the lower part of the count
|
||||
printf ("Sending ack # %04d (length: %d)\n", count, len);
|
||||
if (sendto(sock, ackbuf, len, 0, (struct sockaddr *) &server,sizeof (server)) != len){
|
||||
printf ("Mismatch in number of sent bytes\n");
|
||||
goto exit;
|
||||
}
|
||||
printf ("The Client has sent an ACK for packet\n");
|
||||
goto done; /* gotos are not optimal, but a good solution when exiting a multi-layer loop */
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
for (j = 0; j < tftp_handler->tftp_retry_num; j++){ /* this allows us to loop until we either break out by getting the correct ack OR time out because we've looped more than RETRIES times */
|
||||
server_len = sizeof (data);
|
||||
time_out.tv_sec = tftp_handler->tftp_timeout; // Set select timeout of 3 seconds
|
||||
time_out.tv_usec = 0;
|
||||
FD_ZERO(&read_fds) ;
|
||||
FD_SET(sock, &read_fds); // Only set server fd
|
||||
if(select(sock + 1, &read_fds, NULL, NULL, &time_out) == 1){
|
||||
n = recvfrom (sock, tftp_handler->tftp_buf, BLOCK_SIZE, 0,(struct sockaddr *) &data,(socklen_t *) & server_len);
|
||||
if(n < 0){
|
||||
printf("could not read datagram\r\n");
|
||||
goto exit;
|
||||
}
|
||||
}else{
|
||||
printf("timeout...%d\r\n",j);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!tid){
|
||||
tid = ntohs (data.sin_port); //get the tid of the server.
|
||||
server.sin_port = htons (tid); //set the tid for rest of the transfer
|
||||
}
|
||||
|
||||
if (server.sin_addr.s_addr != data.sin_addr.s_addr){ /* checks to ensure get from ip is same from ACK IP */
|
||||
printf("Error recieving file (data from invalid address)\n");
|
||||
j--;
|
||||
continue; /* we aren't going to let another connection spoil our first connection */
|
||||
}
|
||||
|
||||
if (tid != ntohs (server.sin_port)){ /* checks to ensure get from the correct TID */
|
||||
printf ("Error recieving file (data from invalid tid)\n");
|
||||
len = sprintf ((char *) packetbuf,"%c%c%c%cBad/Unknown TID%c",0x00, 0x05, 0x00, 0x05, 0x00);
|
||||
if (sendto (sock, packetbuf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len){ /* send the data packet */
|
||||
printf("Mismatch in number of sent bytes while trying to send mode error packet\n");
|
||||
}
|
||||
j--;
|
||||
continue; /* we aren't going to let another connection spoil our first connection */
|
||||
}
|
||||
|
||||
/* this formatting code is just like the code in the main function */
|
||||
bufindex = (char *) tftp_handler->tftp_buf; //start our pointer going
|
||||
if (bufindex++[0] != 0x00)
|
||||
printf ("bad first nullbyte!\n");
|
||||
opcode = *bufindex++;
|
||||
rcount = *bufindex++ << 8;
|
||||
rcount &= 0xff00;
|
||||
rcount += (*bufindex++ & 0x00ff);
|
||||
|
||||
if (opcode != 3){ /* ack packet should have code 3 (data) and should be ack+1 the packet we just sent */
|
||||
|
||||
//printf("Badly ordered/invalid data packet (Got OP: %d Block: %d) (Wanted Op: 3 Block: %d)\n",opcode, rcount, count);
|
||||
/* sending error message */
|
||||
if (opcode > 5)
|
||||
{
|
||||
len = sprintf ((char *) packetbuf,"%c%c%c%cIllegal operation%c",0x00, 0x05, 0x00, 0x04, 0x00);
|
||||
if (sendto (sock, packetbuf, len, 0, (struct sockaddr *) &server, sizeof (server)) != len){ /* send the data packet */
|
||||
printf("Mismatch in number of sent bytes while trying to send mode error packet\n");
|
||||
}
|
||||
}else{
|
||||
bufindex = (char *) tftp_handler->tftp_buf;
|
||||
bufindex += 3;
|
||||
printf("error opcode = %d message = %s\r\n",opcode,bufindex);
|
||||
goto exit;
|
||||
}
|
||||
}else{
|
||||
len = sprintf (ackbuf, "%c%c%c%c", 0x00, 0x04, 0x00, 0x00);
|
||||
ackbuf[2] = (count & 0xFF00) >> 8; //fill in the count (top number first)
|
||||
ackbuf[3] = (count & 0x00FF); //fill in the lower part of the count
|
||||
}
|
||||
|
||||
if(rcount != count){
|
||||
//printf("rcount %d %d\r\n",rcount,count);
|
||||
len = sprintf (ackbuf, "%c%c%c%c", 0x00, 0x04, 0x00, 0x00);
|
||||
ackbuf[2] = ((count-1) & 0xFF00) >> 8; //fill in the count (top number first)
|
||||
ackbuf[3] = ((count-1) & 0x00FF); //fill in the lower part of the count
|
||||
if (sendto(sock, ackbuf, len, 0, (struct sockaddr *) &server,sizeof (server)) != len){
|
||||
printf ("Mismatch in number of sent bytes\n");
|
||||
goto exit;
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (sendto(sock, ackbuf, len, 0, (struct sockaddr *) &server,sizeof (server)) != len){
|
||||
printf ("Mismatch in number of sent bytes\n");
|
||||
goto exit;
|
||||
}else{
|
||||
tftp_handler->recv_handle( tftp_handler->tftp_buf+4,n-4,count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (j == tftp_handler->tftp_retry_num){
|
||||
printf ("Data recieve Timeout. Aborting transfer\n");
|
||||
goto exit;
|
||||
}
|
||||
|
||||
}
|
||||
exit:
|
||||
return -1;
|
||||
done:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tftp_client_start(tftp *tftp_handler)
|
||||
{
|
||||
int sock, server_len, len; //,n;
|
||||
struct hostent *host; /*for host information */
|
||||
struct sockaddr_in server; //, client; /*the address structure for both the server and client */
|
||||
char request_buf[64]={0};
|
||||
|
||||
int retry_count = 0;
|
||||
|
||||
vTaskDelay(5000);
|
||||
|
||||
printf("start to tftp client\r\n");
|
||||
|
||||
if (!(host = gethostbyname (tftp_handler->tftp_host))){
|
||||
printf ("Client could not get host address information\r\n");
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
/*Create the socket, a -1 will show us an error */
|
||||
if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){
|
||||
printf ("Client: Socket could not be created");
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
|
||||
/*set the address values for the server */
|
||||
memset (&server, 0, sizeof (server)); /*Clear the structure */
|
||||
server.sin_family = AF_INET; /*address family for TCP and UDP */
|
||||
memcpy (&server.sin_addr, host->h_addr, host->h_length); /*set address of server taken from gethostbyname function */
|
||||
//server.sin_addr.s_addr = htonl (INADDR_ANY); /*use any address */
|
||||
server.sin_port = htons (tftp_handler->tftp_port); /*pick a free port */
|
||||
|
||||
server_len = sizeof (server); /*get the length of the server address */
|
||||
ip_port(server);
|
||||
|
||||
len = req_packet(tftp_handler->tftp_op,tftp_handler->tftp_file_name,tftp_handler->tftp_mode,request_buf,0);
|
||||
|
||||
RETRY:
|
||||
if(retry_count == tftp_handler->tftp_retry_num){
|
||||
printf("Try the maxium %d times \r\n",tftp_handler->tftp_retry_num);
|
||||
goto EXIT;
|
||||
}
|
||||
if (sendto (sock, request_buf, len, 0, (struct sockaddr *) &server, server_len) !=len){
|
||||
printf("Client: sendto has returend an error %d\r\n",len);
|
||||
goto EXIT;
|
||||
}
|
||||
if(tftp_handler->tftp_op == RRQ){
|
||||
printf("recv file\r\n");
|
||||
if(tftp_client_get (tftp_handler->tftp_file_name, server, tftp_handler->tftp_mode, sock,tftp_handler) == 0){
|
||||
printf("tget finish\r\n");
|
||||
close(sock);
|
||||
}else{
|
||||
printf("tget error\r\n");
|
||||
retry_count++;
|
||||
goto RETRY;
|
||||
}
|
||||
}else if(tftp_handler->tftp_op == WRQ){
|
||||
printf("send file\r\n");
|
||||
if(tftp_client_send (tftp_handler->tftp_file_name, server, tftp_handler->tftp_mode, sock,tftp_handler) == 0){
|
||||
printf("tput finish\r\n");
|
||||
close(sock);
|
||||
goto DONE;
|
||||
}else{
|
||||
printf("tput error\r\n");
|
||||
retry_count++;
|
||||
goto RETRY;
|
||||
}
|
||||
}
|
||||
DONE:
|
||||
return 0;
|
||||
EXIT:
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
401
lib/amb1_sdk/common/network/tftp/tftp_server.c
Normal file
401
lib/amb1_sdk/common/network/tftp/tftp_server.c
Normal file
@@ -0,0 +1,401 @@
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
#include <platform/platform_stdlib.h>
|
||||
#include <lwip/sockets.h>
|
||||
#include <lwip/netdb.h>
|
||||
#include "tftp.h"
|
||||
|
||||
#include "wifi_conf.h"
|
||||
|
||||
int tftp_server_recv (int sock,char *pFilename, struct sockaddr_in client, char *pMode, int tid,tftp *tftp_handler)//client put data into server
|
||||
{
|
||||
/* local variables */
|
||||
int len, client_len, opcode, i, n;
|
||||
unsigned short int count = 0, rcount = 0;
|
||||
//unsigned char filebuf[64];
|
||||
unsigned char packetbuf[64];
|
||||
extern int errno;
|
||||
char *bufindex, ackbuf[12];
|
||||
struct sockaddr_in data;
|
||||
n = BLOCK_SIZE;
|
||||
|
||||
client_len = sizeof (data);
|
||||
|
||||
fd_set read_fds;
|
||||
struct timeval time_out;
|
||||
|
||||
while (1){
|
||||
|
||||
//printf("count = %d\r\n",count);
|
||||
|
||||
len = sprintf (ackbuf, "%c%c%c%c", 0x00, 0x04, 0x00, 0x00);
|
||||
ackbuf[2] = (count & 0xFF00) >> 8; //fill in the count (top number first)
|
||||
ackbuf[3] = (count & 0x00FF); //fill in the lower part of the count
|
||||
|
||||
//printf ("Sending ack # %04d (length: %d)\n", count, len);
|
||||
|
||||
if (sendto(sock, ackbuf, len, 0, (struct sockaddr *) &client,sizeof (client)) != len){
|
||||
printf ("Mismatch in number of sent bytes\n");
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
if (n != BLOCK_SIZE){ /* remember if our datasize is less than a full packet this was the last packet to be received */
|
||||
printf("Last chunk detected (file chunk size: %d). exiting while loop\n",n - 4);
|
||||
goto FINISH; /* gotos are not optimal, but a good solution when exiting a multi-layer loop */
|
||||
}
|
||||
|
||||
count++;
|
||||
|
||||
for(i = 0; i < tftp_handler->tftp_retry_num; i++){
|
||||
|
||||
time_out.tv_sec = tftp_handler->tftp_timeout; // Set select timeout of 3 seconds
|
||||
time_out.tv_usec = 0;
|
||||
FD_ZERO(&read_fds) ;
|
||||
FD_SET(sock, &read_fds); // Only set server fd
|
||||
|
||||
if(select(sock + 1, &read_fds, NULL, NULL, &time_out) == 1){
|
||||
n = recvfrom (sock, tftp_handler->tftp_buf, BLOCK_SIZE, 0,(struct sockaddr *) &data,(socklen_t *) & client_len);
|
||||
if(n < 0){
|
||||
printf("could not read datagram\r\n");
|
||||
goto EXIT;
|
||||
}
|
||||
}else{
|
||||
printf("timeout\r\n");
|
||||
}
|
||||
|
||||
if (client.sin_addr.s_addr != data.sin_addr.s_addr) { /* checks to ensure get from ip is same from ACK IP */
|
||||
printf("Error recieving file (data from invalid address)\r\n");
|
||||
continue; /* we aren't going to let another connection spoil our first connection */
|
||||
}
|
||||
|
||||
if (tid != ntohs (client.sin_port)){ /* checks to ensure get from the correct TID */
|
||||
printf ("Error recieving file (data from invalid tid)\r\n");
|
||||
len = sprintf ((char *) packetbuf,"%c%c%c%cBad/Unknown TID%c",0x00, 0x05, 0x00, 0x05, 0x00);
|
||||
if (sendto (sock, packetbuf, len, 0, (struct sockaddr *) &client, sizeof (client)) != len){ /* send the data packet */
|
||||
printf("Mismatch in number of sent bytes while trying to send mode error packet\r\n");
|
||||
}
|
||||
i--;
|
||||
//j--;
|
||||
continue; /* we aren't going to let another connection spoil our first connection */
|
||||
}
|
||||
|
||||
/* this formatting code is just like the code in the main function */
|
||||
bufindex = (char *) tftp_handler->tftp_buf; //start our pointer going
|
||||
|
||||
if (bufindex++[0] != 0x00){
|
||||
printf ("bad first nullbyte!\n");
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
opcode = *bufindex++;
|
||||
rcount = *bufindex++ << 8;
|
||||
rcount &= 0xff00;
|
||||
rcount += (*bufindex++ & 0x00ff);
|
||||
|
||||
//printf("rcount = %d count = %d\r\n",rcount,count);
|
||||
|
||||
if (opcode != 3 || rcount != count){ /* ack packet should have code 3 (data) and should be ack+1 the packet we just sent */
|
||||
|
||||
printf("Badly ordered/invalid data packet (Got OP: %d Block: %d) (Wanted Op: 3 Block: %d)\n",opcode, rcount, count);
|
||||
/* sending error message */
|
||||
if (opcode > 5){
|
||||
len = sprintf ((char *) packetbuf,"%c%c%c%cIllegal operation%c",0x00, 0x05, 0x00, 0x04, 0x00);
|
||||
if (sendto (sock, packetbuf, len, 0, (struct sockaddr *) &client, sizeof (client)) != len){ /* send the data packet */
|
||||
printf("Mismatch in number of sent bytes while trying to send mode error packet\n");
|
||||
}
|
||||
}
|
||||
if(rcount != count){
|
||||
len = sprintf (ackbuf, "%c%c%c%c", 0x00, 0x04, 0x00, 0x00);
|
||||
ackbuf[2] = ((count-1) & 0xFF00) >> 8; //fill in the count (top number first)
|
||||
ackbuf[3] = ((count-1) & 0x00FF); //fill in the lower part of the count
|
||||
|
||||
//printf ("Sending ack # %04d (length: %d)\n", count, len);
|
||||
|
||||
if (sendto(sock, ackbuf, len, 0, (struct sockaddr *) &client,sizeof (client)) != len){
|
||||
printf ("Mismatch in number of sent bytes\n");
|
||||
goto EXIT;
|
||||
}
|
||||
}
|
||||
//goto EXIT;
|
||||
}else{
|
||||
//sum_count++;
|
||||
//printf("correct \r\n");
|
||||
tftp_handler->recv_handle(tftp_handler->tftp_buf+4,n-4,count);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
if(i== tftp_handler->tftp_retry_num){
|
||||
printf("Retry error\r\n");
|
||||
goto EXIT;
|
||||
}
|
||||
}
|
||||
FINISH:
|
||||
return 0;
|
||||
EXIT:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tftp_server_send (int sock,char *pFilename, struct sockaddr_in client, char *pMode, int tid,tftp *tftp_handler)//client put the data into server
|
||||
{
|
||||
/* local variables */
|
||||
int len, client_len, opcode, i, n;
|
||||
unsigned short int count = 0, rcount = 0;
|
||||
//unsigned char filebuf[64];
|
||||
unsigned char packetbuf[64];
|
||||
extern int errno;
|
||||
unsigned char *bufindex;
|
||||
struct sockaddr_in data;
|
||||
fd_set read_fds;
|
||||
struct timeval time_out;
|
||||
|
||||
len = BLOCK_SIZE;
|
||||
client_len = sizeof (data);
|
||||
|
||||
while (1){
|
||||
|
||||
count++;
|
||||
|
||||
if(len != BLOCK_SIZE){
|
||||
printf("Send file finish last chunk = %d\r\n",len-4);
|
||||
goto FINISH;
|
||||
}
|
||||
|
||||
sprintf ((char *) tftp_handler->tftp_buf, "%c%c%c%c", 0x00, 0x03, 0x00, 0x00); /* build data packet but write out the count as zero */
|
||||
tftp_handler->send_handle(tftp_handler->tftp_buf+4,&len,count-1);
|
||||
tftp_handler->tftp_buf[2] = (count & 0xFF00) >> 8; //fill in the count (top number first)
|
||||
tftp_handler->tftp_buf[3] = (count & 0x00FF); //fill in the lower part of the count
|
||||
len+=4;
|
||||
//printf("len = %d\r\n",len);
|
||||
if (sendto(sock, tftp_handler->tftp_buf, len, 0, (struct sockaddr *) &client,sizeof (client)) != len){
|
||||
printf ("Mismatch in number of sent bytes\n");
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
for(i = 0; i < tftp_handler->tftp_retry_num; i++){
|
||||
|
||||
time_out.tv_sec = 5; // Set select timeout of 3 seconds
|
||||
time_out.tv_usec = 0;
|
||||
FD_ZERO(&read_fds) ;
|
||||
FD_SET(sock, &read_fds); // Only set server fd
|
||||
|
||||
if(select(sock + 1, &read_fds, NULL, NULL, &time_out) == 1){
|
||||
n = recvfrom (sock, tftp_handler->tftp_buf, BLOCK_SIZE, 0,(struct sockaddr *) &data,(socklen_t *) & client_len);
|
||||
if(n < 0){
|
||||
printf("could not read datagram\r\n");
|
||||
goto EXIT;
|
||||
}
|
||||
}else{
|
||||
//continue;
|
||||
printf("timeout\r\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (client.sin_addr.s_addr != data.sin_addr.s_addr) { /* checks to ensure get from ip is same from ACK IP */
|
||||
printf("Error recieving file (data from invalid address)\r\n");
|
||||
i--;
|
||||
continue; /* we aren't going to let another connection spoil our first connection */
|
||||
}
|
||||
|
||||
if (tid != ntohs (client.sin_port)){ /* checks to ensure get from the correct TID */
|
||||
printf ("Error recieving file (data from invalid tid)\r\n");
|
||||
len = sprintf ((char *) packetbuf,"%c%c%c%cBad/Unknown TID%c",0x00, 0x05, 0x00, 0x05, 0x00);
|
||||
if (sendto (sock, packetbuf, len, 0, (struct sockaddr *) &client, sizeof (client)) != len){ /* send the data packet */
|
||||
printf("Mismatch in number of sent bytes while trying to send mode error packet\r\n");
|
||||
}
|
||||
//j--;
|
||||
i--;
|
||||
continue; /* we aren't going to let another connection spoil our first connection */
|
||||
}
|
||||
|
||||
/* this formatting code is just like the code in the main function */
|
||||
bufindex = tftp_handler->tftp_buf; //start our pointer going
|
||||
|
||||
if (bufindex++[0] != 0x00){
|
||||
printf ("bad first nullbyte!\n");
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
opcode = *bufindex++;
|
||||
rcount = *bufindex++ << 8;
|
||||
rcount &= 0xff00;
|
||||
rcount += (*bufindex++ & 0x00ff);
|
||||
|
||||
if (opcode != 4 || rcount != count){ /* ack packet should have code 3 (data) and should be ack+1 the packet we just sent */
|
||||
|
||||
printf("Badly ordered/invalid data packet (Got OP: %d Block: %d) (Wanted Op: 4 Block: %d)\n",opcode, rcount, count);
|
||||
/* sending error message */
|
||||
if (opcode > 5){
|
||||
len = sprintf ((char *) packetbuf,"%c%c%c%cIllegal operation%c",0x00, 0x05, 0x00, 0x04, 0x00);
|
||||
if (sendto (sock, packetbuf, len, 0, (struct sockaddr *) &client, sizeof (client)) != len){ /* send the data packet */
|
||||
printf("Mismatch in number of sent bytes while trying to send mode error packet\n");
|
||||
}
|
||||
goto EXIT;
|
||||
}
|
||||
if(rcount != count){
|
||||
sprintf ((char *) tftp_handler->tftp_buf, "%c%c%c%c", 0x00, 0x03, 0x00, 0x00); /* build data packet but write out the count as zero */
|
||||
tftp_handler->send_handle(tftp_handler->tftp_buf+4,&len,count-2);
|
||||
tftp_handler->tftp_buf[2] = ((count-1) & 0xFF00) >> 8; //fill in the count (top number first)
|
||||
tftp_handler->tftp_buf[3] = ((count-1) & 0x00FF); //fill in the lower part of the count
|
||||
len+=4;
|
||||
//printf("len = %d\r\n",len);
|
||||
if (sendto(sock, tftp_handler->tftp_buf, len, 0, (struct sockaddr *) &client,sizeof (client)) != len){
|
||||
printf ("Mismatch in number of sent bytes\n");
|
||||
goto EXIT;
|
||||
}
|
||||
}
|
||||
//goto EXIT;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i== tftp_handler->tftp_retry_num){
|
||||
printf("Retry error\r\n");
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
}
|
||||
FINISH:
|
||||
return 0;
|
||||
EXIT:
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tftp_server_start(tftp *tftp_handler)
|
||||
{
|
||||
int sock, n, client_len, status, tid, len;
|
||||
char opcode, filename[64], mode[12],packetbuf[64];
|
||||
unsigned char *bufindex;
|
||||
|
||||
struct sockaddr_in server, client; /*the address structure for both the server and client */
|
||||
START_AGAIN:
|
||||
|
||||
memset(&server,0,sizeof( struct sockaddr_in));
|
||||
memset(&client,0,sizeof( struct sockaddr_in));
|
||||
|
||||
if ((sock = socket (AF_INET, SOCK_DGRAM, 0)) < 0){
|
||||
printf ("Server Socket could not be created");
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
if (sock == -1) {
|
||||
printf("ERROR opening socket\r\n");
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
/*set the address values for the server */
|
||||
server.sin_family = AF_INET; /*address family for TCP and UDP */
|
||||
server.sin_addr.s_addr = htonl (INADDR_ANY); /*use any address */
|
||||
server.sin_port = htons (tftp_handler->tftp_port); /*pick a free port */
|
||||
|
||||
/*Bind the socket */
|
||||
if (bind (sock, (struct sockaddr *) &server, sizeof (server)) < 0){
|
||||
printf("Server bind failed. Server already running? Proper permissions?\n");
|
||||
//return (2);
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
client_len = sizeof (client); /*get the length of the client */
|
||||
memset (tftp_handler->tftp_buf, 0, BLOCK_SIZE); /*clear the buffer */
|
||||
|
||||
fcntl(sock, F_SETFL, fcntl(sock, F_GETFL, 0) | O_NONBLOCK);
|
||||
|
||||
fd_set read_fds;
|
||||
struct timeval time_out;
|
||||
|
||||
while (1){
|
||||
|
||||
time_out.tv_sec = 3; // Set select timeout of 3 seconds
|
||||
time_out.tv_usec = 0;
|
||||
FD_ZERO(&read_fds) ;
|
||||
FD_SET(sock, &read_fds); // Only set server fd
|
||||
|
||||
if(select(sock + 1, &read_fds, NULL, NULL, &time_out) == 1){
|
||||
n = recvfrom (sock, tftp_handler->tftp_buf, BLOCK_SIZE, 0,(struct sockaddr *) &client,(socklen_t *) & client_len);
|
||||
if(n < 0)
|
||||
printf("could not read datagram\r\n");
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf ("Connection from %s, port %d\n",inet_ntoa (client.sin_addr), ntohs (client.sin_port));
|
||||
|
||||
if (n < 0 && errno != EAGAIN){
|
||||
printf ("The server could not receive from the client");
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
bufindex = tftp_handler->tftp_buf; //start our pointer going
|
||||
if (bufindex++[0] != 0x00){ //first TFTP packet byte needs to be null. Once the value is taken increment it.
|
||||
printf ("Malformed tftp packet.\n");
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
tid = ntohs (client.sin_port); /* record the tid */
|
||||
opcode = *bufindex++; //opcode is in the second byte.
|
||||
|
||||
if (opcode == 1 || opcode == 2){ // RRQ or WRQ. The only two really valid packets on port 69
|
||||
|
||||
strncpy (filename, (char const *)bufindex, sizeof (filename) - 1); /* Our pointer has been nudged along the recieved string so the first char is the beginning of the filename. This filename is null deliimited so we can use the str family of functions */
|
||||
bufindex += strlen (filename) + 1; /* move the pointer to after the filename + null byte in the string */
|
||||
strncpy (mode, (const char*)bufindex, sizeof (mode) - 1); /* like the filename, we are at the beginning of the null delimited mode */
|
||||
bufindex += strlen (mode) + 1; /* move pointer... */
|
||||
printf ("opcode: %x filename: %s packet size: %d mode: %s\n", opcode, filename, n, mode); /*show the message to the server */
|
||||
|
||||
}else{
|
||||
printf ("opcode: %x size: %d \n", opcode, sizeof (n)); /*show the message to the server */
|
||||
|
||||
}
|
||||
|
||||
if (!strncasecmp (mode, "octet", 5) && !strncasecmp (mode, "netascii", 8)){ /* these two are the only modes we accept */
|
||||
|
||||
if (!strncasecmp (mode, "mail", 4))
|
||||
len = sprintf ((char *) packetbuf,"%c%c%c%cThis tftp server will not operate as a mail relay%c",0x00, 0x05, 0x00, 0x04, 0x00);
|
||||
else
|
||||
len = sprintf ((char *) packetbuf,"%c%c%c%cUnrecognized mode (%s)%c",0x00, 0x05, 0x00, 0x04, mode, 0x00);
|
||||
if (sendto (sock, packetbuf, len, 0, (struct sockaddr *) &client, sizeof (client)) != len){ /* send the data packet */
|
||||
printf("Mismatch in number of sent bytes while trying to send mode error packet\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (strchr (filename, 0x5C) || strchr (filename, 0x2F)) { //look for illegal characters in the filename string these are \ and /
|
||||
printf ("Client requested to upload bad file: forbidden name\n");
|
||||
len =sprintf ((char *) packetbuf,"%c%c%c%cIllegal filename.(%s) You may not attempt to descend or ascend directories.%c",0x00, 0x05, 0x00, 0x00, filename, 0x00);
|
||||
if (sendto (sock, packetbuf, len, 0, (struct sockaddr *) &client, sizeof (client)) != len){ /* send the data packet */
|
||||
printf("Mismatch in number of sent bytes while trying to send error packet\n");
|
||||
}
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
if(opcode ==WRQ){
|
||||
if(tftp_server_recv (sock,filename, client, mode, tid,tftp_handler)!=0)
|
||||
printf("Error Happen\r\n");
|
||||
else
|
||||
printf("tftp transfer finish\r\n");
|
||||
}else if(opcode ==RRQ){
|
||||
if(tftp_server_send (sock,filename, client, mode, tid,tftp_handler)!=0)
|
||||
printf("Error Happen\r\n");
|
||||
else
|
||||
printf("tftp transfer finish\r\n");
|
||||
}else{
|
||||
printf("The type is not support\r\n");
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
|
||||
status = close(sock);
|
||||
if(status != 0)
|
||||
printf("status error = %d\r\n",status);
|
||||
|
||||
|
||||
goto START_AGAIN;
|
||||
|
||||
//DONE:
|
||||
// return 0;
|
||||
EXIT:
|
||||
close(sock);
|
||||
return -1;
|
||||
}
|
||||
Reference in New Issue
Block a user