📄 tftps.c
字号:
/***************************************************************************************
File: tftps.c
Date: 7.10.2002
Version: 0.1
Author: Jari Lahti (jari@violasystems.com)
Description: This file implements TFTP protocol server
Version Info: 7.10.2002 - First version (Jari Lahti)
***************************************************************************************/
#include "opentcp.h"
UINT8 tftpsapp_init = 0;
/* TFTPS states */
#define TFTPS_STATE_ENABLED 1
#define TFTPS_STATE_CONNECTED 2
/* TFTP Error codes */
#define TFTP_NOTDEFINED 0 /* Not Definet Error */
#define TFTP_ACCESSVIOLATION 2 /* Access Violation Error */
#define TFTP_ILLEGALOPERATION 4 /* Not supported Opcode */
/* TFTP Opcodes */
#define TFTP_OPCODE_WRQ 2 /* Packet is Write Request */
#define TFTP_OPCODE_DATA 3 /* Data Packet */
#define TFTP_OPCODE_ACK 4 /* ACK Packet */
#define TFTP_OPCODE_ERROR 5 /* Error Packet */
struct
{
UINT8 state;
INT8 sochandle;
UINT16 tmrhandle;
UINT32 remip;
UINT16 remport;
UINT16 blocknumber;
UINT32 bytecount;
UINT8 retries;
} Tftps;
/********************************************************************************
Function: init_tftps
Parameters: void
Return val: INT8 - (>=0) OK
(-1) Error
Date: 7.19.2002
Desc: This function should be called before the TFTP Server application
is used to set the operating parameters of it
*********************************************************************************/
INT8 init_tftps (void)
{
/* Already initialized? */
if(tftpsapp_init)
return(1);
/* Get socket handle */
Tftps.sochandle = udp_getsocket(0, tftps_eventlistener, UDP_OPT_SEND_CS | UDP_OPT_CHECK_CS);
if(Tftps.sochandle < 0)
return(-1);
/* Put it to listening mode */
if( udp_open(Tftps.sochandle, TFTPS_SERVERPORT) < 0 )
return(-1);
/* Get timer handle */
Tftps.tmrhandle = get_timer();
Tftps.state = TFTPS_STATE_ENABLED;
Tftps.remip = 0;
Tftps.remport = 0;
Tftps.retries = 0;
Tftps.blocknumber = 0;
Tftps.bytecount = 0;
tftpsapp_init = 1;
return(1);
}
/********************************************************************************
Function: tftps_run
Parameters: void
Return val: void
Date: 7.10.2002
Desc: The main thread of TFTP server that should be called periodically
*********************************************************************************/
void tftps_run (void)
{
if(tftpsapp_init == 0)
return;
/* Check for timeouts */
if(Tftps.state == TFTPS_STATE_CONNECTED)
{
if(check_timer(Tftps.tmrhandle) == 0)
TFTP_DeleteSocket();
}
}
INT32 tftps_eventlistener (INT8 cbhandle, UINT8 event, UINT32 remip, UINT16 remport, UINT16 bufindex, UINT16 dlen)
{
UINT16 opcode;
UINT16 i;
UINT8 ch;
UINT16 u16temp;
UINT8 fname[TFTPS_FILENAME_MAXLEN];
if(tftpsapp_init == 0)
return(-1);
if(cbhandle != Tftps.sochandle)
return(-1);
/* If we are on other state than enabled, check that we are talking with the same gyu */
if( Tftps.state != TFTPS_STATE_ENABLED)
{
if(remip != Tftps.remip)
return(-1);
if(remport != Tftps.remport)
return(-1);
}
if(dlen < 2)
return(-1);
/* Bind socket */
Tftps.remip = remip;
Tftps.remport = remport;
/* Get information */
NETWORK_RECEIVE_INITIALIZE(bufindex);
opcode = RECEIVE_NETWORK_B();
opcode <<= 8;
opcode |= RECEIVE_NETWORK_B();
dlen -= 2;
/* Process it */
switch(opcode)
{
case TFTP_OPCODE_WRQ: /* Write request? */
/* Get filename */
fname[0] = '\0';
for(i=0; i<dlen; i++)
{
if(i >= TFTPS_FILENAME_MAXLEN)
{
TFTP_SendError(TFTP_NOTDEFINED);
TFTP_DeleteSocket();
return(1);
}
ch = RECEIVE_NETWORK_B();
fname[i] = ch;
if(ch == '\0')
{
i++;
break;
}
}
dlen -= i;
/* Check here the filename */
if( otcp_bufsearch(&fname[0], TFTPS_FILENAME_MAXLEN, (UINT8*)"ws100.upn",0) < 0 )
{
TFTP_SendError(TFTP_ACCESSVIOLATION);
TFTP_DeleteSocket();
return(1);
}
/* Check mode, only octet mode is supported */
if(dlen < 6)
{
TFTP_SendError(TFTP_NOTDEFINED);
TFTP_DeleteSocket();
return(1);
}
if( (RECEIVE_NETWORK_B() != 'o') || (RECEIVE_NETWORK_B() != 'c') || (RECEIVE_NETWORK_B() != 't') ||
(RECEIVE_NETWORK_B() != 'e') || (RECEIVE_NETWORK_B() != 't') || (RECEIVE_NETWORK_B() != '\0') )
{
TFTP_SendError(TFTP_NOTDEFINED);
TFTP_DeleteSocket();
return(1);
}
/* All OK, send ACK */
Tftps.state = TFTPS_STATE_CONNECTED;
Tftps.blocknumber = 0;
Tftps.bytecount = 0;
Tftps.retries = TFTPS_DEF_RETRIES;
init_timer(Tftps.tmrhandle, TFTPS_TIMEOUT*TIMERTIC);
TFTP_SendAck();
Tftps.blocknumber++;
return(1);
case TFTP_OPCODE_DATA: /* Data Packet ? */
if(Tftps.state != TFTPS_STATE_CONNECTED)
{
TFTP_SendError(TFTP_NOTDEFINED);
TFTP_DeleteSocket();
return(1);
}
if(dlen < 2)
{
TFTP_SendError(TFTP_NOTDEFINED);
TFTP_DeleteSocket();
return(1);
}
/* Get block number */
u16temp = RECEIVE_NETWORK_B();
u16temp <<= 8;
u16temp |= RECEIVE_NETWORK_B();
dlen -= 2;
if( (u16temp < Tftps.blocknumber) && (Tftps.blocknumber > 0) )
{
/* Duplicate msg, send ACK again */
if( Tftps.retries > 0 )
{
Tftps.retries--;
Tftps.blocknumber--;
TFTP_SendAck();
Tftps.blocknumber++;
}
else
{
TFTP_SendError(TFTP_NOTDEFINED);
TFTP_DeleteSocket();
}
return(1);
}
if( u16temp != Tftps.blocknumber )
{
/* Something really wrong */
TFTP_SendError(TFTP_NOTDEFINED);
TFTP_DeleteSocket();
return(1);
}
/* Read the data here with RECEIVE_NETWORK_B() */
if( dlen < 512 )
{
/* Other side Wants to close */
TFTP_SendAck();
TFTP_DeleteSocket();
return(1);
}
/* All OK */
Tftps.retries = TFTPS_DEF_RETRIES;
init_timer(Tftps.tmrhandle, TFTPS_TIMEOUT*TIMERTIC);
TFTP_SendAck();
Tftps.blocknumber++;
return(1);
case TFTP_OPCODE_ERROR:
TFTP_DeleteSocket();
return(1);
default:
/* Unsupported Opcode, Send error */
TFTP_SendError(TFTP_ILLEGALOPERATION);
TFTP_DeleteSocket();
return(1);
}
}
void TFTP_SendAck (void)
{
/* Send a TFTP ACK packet */
OTCP_TXBUF[UDP_APP_OFFSET + 0] = 0; /* Opcode */
OTCP_TXBUF[UDP_APP_OFFSET + 1] = 4;
OTCP_TXBUF[UDP_APP_OFFSET + 2] = (UINT8)(Tftps.blocknumber >> 8);
OTCP_TXBUF[UDP_APP_OFFSET + 3] = (UINT8)Tftps.blocknumber;
udp_send(Tftps.sochandle, Tftps.remip, Tftps.remport, &OTCP_TXBUF[UDP_APP_OFFSET], NETWORK_TX_BUFFER_SIZE - UDP_APP_OFFSET, 4);
}
void TFTP_SendError (UINT8 errno )
{
/* Send TFTP Error -packet */
OTCP_TXBUF[UDP_APP_OFFSET + 0] = 0; /* Opcode */
OTCP_TXBUF[UDP_APP_OFFSET + 1] = 5;
OTCP_TXBUF[UDP_APP_OFFSET + 2] = (UINT8)(Tftps.blocknumber >> 8);
OTCP_TXBUF[UDP_APP_OFFSET + 3] = (UINT8)Tftps.blocknumber;
OTCP_TXBUF[UDP_APP_OFFSET + 4] = errno;
OTCP_TXBUF[UDP_APP_OFFSET + 5] = '\0';
OTCP_TXBUF[UDP_APP_OFFSET + 6] = 0;
udp_send(Tftps.sochandle, Tftps.remip, Tftps.remport, &OTCP_TXBUF[UDP_APP_OFFSET], NETWORK_TX_BUFFER_SIZE - UDP_APP_OFFSET, 7);
}
void TFTP_DeleteSocket (void)
{
/* Clear Socket Data */
Tftps.blocknumber = 0;
Tftps.state = TFTPS_STATE_ENABLED;
Tftps.retries = 0;
Tftps.remip = 0;
Tftps.remport = 0;
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -