📄 tftpc.c
字号:
* DESCRIPTION
*
* This function is responsible for sending an acknowledgement of
* a TFTP data packet. The data is copied from the user's buffer
* into the TFTP CB send buffer. This function also updates the
* pointer into the user's buffer and the number of bytes left
* to send in the buffer.
*
* INPUTS
*
* *tftp_con The pointer to TFTP Control Block
*
* OUTPUTS
*
* The Number of bytes sent on success.
*
*************************************************************************/
INT32 TFTPC_Send_Data(TFTP_CB *tftp_con)
{
UINT16 num_bytes;
UINT32 bytes_read;
/* Fill in the opcode and block number. */
PUT16(tftp_con->trans_buf, 0, TFTP_DATA_OPCODE);
PUT16(tftp_con->trans_buf, 2, tftp_con->block_number);
/* Determine the number of bytes that will be sent in this packet - if
* we have blksize or more bytes to send, we will send blksize bytes,
* else, we will send the remainder of the file as our last packet
*/
bytes_read = FAL_Fread(&(tftp_con->trans_buf[4]), tftp_con->options.blksize,
tftp_con->file_desc);
if(bytes_read == tftp_con->options.blksize)
num_bytes = tftp_con->options.blksize;
else
num_bytes = (UINT16)bytes_read;
/* If we sent less than blksize bytes, we know it was the last packet */
if (num_bytes < tftp_con->options.blksize)
tftp_con->status = TRANSFER_COMPLETE;
/* Send the data. */
return (INT32)(NU_Send_To(tftp_con->socket_number,
tftp_con->trans_buf,
(UINT16)(num_bytes + TFTP_HEADER_SIZE), 0,
&tftp_con->server_addr, 0));
} /* end TFTPC_Send_Data */
/*************************************************************************
*
* FUNCTION
*
* TFTPC_Retransmit
*
* DESCRIPTION
*
* This function will retransmit the last packet sent.
*
* INPUTS
*
* *tftp_con The pointer to TFTP Control Block.
* nbytes The number of bytes to retransmit.
*
* OUTPUTS
*
* The Number of bytes sent on success.
*
*************************************************************************/
STATUS TFTPC_Retransmit(TFTP_CB *tftp_con, INT32 nbytes)
{
return((INT)NU_Send_To(tftp_con->socket_number, tftp_con->trans_buf,
(UINT16)nbytes, 0, &tftp_con->server_addr, 0));
}/* TFTPC_Retransmit */
/*************************************************************************
*
* FUNCTION
*
* TFTPC_Error
*
* DESCRIPTION
*
* This function will send an error packet.
*
* INPUTS
*
* *tftp_con The pointer to TFTP Control Block.
* error_code The TFTP error code.
* *err_string The error message to send.
*
* OUTPUTS
*
* The Number of bytes sent on success.
*
*************************************************************************/
STATUS TFTPC_Error(TFTP_CB *tftp_con, INT16 error_code, char *err_string)
{
INT16 bytes_sent, send_size;
/* Fill in the opcode and block number. */
PUT16(tftp_con->trans_buf, 0, TFTP_ERROR_OPCODE);
PUT16(tftp_con->trans_buf, 2, error_code);
strcpy(&tftp_con->trans_buf[4], err_string);
/* Size equals the length of the error string plus the null terminator. */
send_size = (INT16)(strlen(err_string) + 1);
/* Send the datagram. */
bytes_sent = (INT16)(NU_Send_To(tftp_con->socket_number,
tftp_con->trans_buf,
(UINT16)(send_size + TFTP_HEADER_SIZE),
0, &tftp_con->server_addr, 0));
return (bytes_sent);
} /* end TFTPC_Error */
/*************************************************************************
*
* FUNCTION
*
* TFTPC_Check_Options
*
* DESCRIPTION
*
* This function compares the options sent by the client with those
* returned from the server to be sure they are valid.
*
* INPUTS
*
* *tftp_con The pointer to TFTP Control Block.
* bytes_received The bytes received in the OACK packet from the
* server.
*
* OUTPUTS
*
* If the options are rejected, TFTP_BAD_OPTION,
* If there is not tsize space available, TFTP_DISK_FULL
* Else, NU_SUCCESS
*
*************************************************************************/
STATUS TFTPC_Check_Options(TFTP_CB *tftp_con, INT32 bytes_received)
{
INT16 count = 2, count1;
char temp1[TFTP_PARSING_LENGTH];
char temp2[TFTP_PARSING_LENGTH];
char *op_holder;
char *value_holder;
/* Set each acknowledgement field initially to false - we must track
* acknowledged options only, and if an option was requested and
* not acknowledged, we must reset its value to the default for
* that option
*/
tftp_con->options.timeout_acknowledged = NU_FALSE;
tftp_con->options.blksize_acknowledged = NU_FALSE;
tftp_con->options.tsize_acknowledged = NU_FALSE;
/* Check if the server changed our requested option values */
while (count < bytes_received)
{
count1 = 0;
/* Parse the first option from the transmission buffer */
while (tftp_con->trans_buf[count] != '\0')
{
temp1[count1] = tftp_con->trans_buf[count];
count ++;
count1 ++;
}
/* Null terminate temp1 */
temp1[count1] = '\0';
op_holder = (CHAR *)&temp1;
count++;
count1 = 0;
/* Parse the first value from the transmission buffer */
while (tftp_con->trans_buf[count] != '\0')
{
temp2[count1] = tftp_con->trans_buf[count];
count ++;
count1 ++;
}
/* Null terminate temp2 */
temp2[count1] = '\0';
value_holder = (CHAR *)&temp2;
count++;
/* The server has the authority to change the value of some
* options we specified; check each returned option's value
* and determine if any difference is valid
*/
if (strcmp(op_holder, "timeout") == 0)
{
/* The server may not change our timeout value */
if ((UINT16)NU_ATOI(value_holder) != tftp_con->options.timeout)
return(TFTP_BAD_OPTION);
/* The server acknowledged our timeout option */
tftp_con->options.timeout_acknowledged = NU_TRUE;
}
else if (strcmp(op_holder, "tsize") == 0)
{
/* If the file is bigger than we can hold, error */
if ((UINT32)NU_ATOI(value_holder) > FAL_Disk_Space())
return(TFTP_DISK_FULL);
else
{
tftp_con->options.tsize = (UINT32)(NU_ATOI(value_holder));
tftp_con->options.tsize_acknowledged = NU_TRUE;
}
}
else if (strcmp(op_holder, "blksize") == 0)
{
/* The server may not return a blksize larger than we
* requested
*/
if (((UINT16)NU_ATOI(value_holder) > tftp_con->options.blksize) ||
((UINT16)NU_ATOI(value_holder) == 0))
return(TFTP_BAD_OPTION);
/* The server may return a blksize smaller than we
* requested; therefore, set our blksize to that value
*/
else if ((UINT16)NU_ATOI(value_holder) < tftp_con->options.blksize)
tftp_con->options.blksize = (UINT16)(NU_ATOI(value_holder));
/* The server acknowledged our blksize option */
tftp_con->options.blksize_acknowledged = NU_TRUE;
}
/* Otherwise, the server is sending us unsupported options */
else
TFTPC_Error(tftp_con, 8, "Error: Option Not Supported. ");
}
/* We may use only those options that the server acknowledges - if
* the server did not acknowledge an option, set it back to the default
*/
if (tftp_con->options.timeout_acknowledged != NU_TRUE)
tftp_con->options.timeout = TFTP_TIMEOUT_DEFAULT;
if (tftp_con->options.blksize_acknowledged != NU_TRUE)
tftp_con->options.blksize = TFTP_BLOCK_SIZE_DEFAULT;
return(NU_SUCCESS);
}
/*************************************************************************
*
* FUNCTION
*
* TFTPC_Set_Options
*
* DESCRIPTION
*
* This function verifies the validity of the blksize and timeout
* options requested - if they are invalid, it sets them to the
* valid defaults.
*
* INPUTS
*
* buf_size Size of the user buffer.
* *ops Pointer to the options structure.
*
* OUTPUTS
*
* NU_SUCCESS
*
*************************************************************************/
STATUS TFTPC_Set_Options(UINT32 buf_size, TFTP_OPTIONS *ops)
{
/* If the user did not specify a blksize, set it to the default
* Also, if the user passes in a value larger than a UINT16 for
* blksize, sets blksize to default. Or, if the user specifies a
* value larger than the max, set it to the default
*/
if ((ops->blksize < TFTP_BLOCK_SIZE_MIN) ||
(ops->blksize > TFTP_BLOCK_SIZE_MAX))
ops->blksize = TFTP_BLOCK_SIZE_DEFAULT;
/* If the blksize is greater than the transmission size, set it
* to the blksize - it is wasteful to allocate more memory for a
* transmission buffer than we need
*/
if ((ops->blksize > buf_size) && (buf_size != 0))
ops->blksize = (UINT16)buf_size;
/* Per RFC 2349, the timeout interval must be between 1 and 255 - if
* the timeout is 0, then the user did not specify a timeout, and we
* want the server to use its default and we will use our default;
* therefore, leave it 0 for now.
*/
if (ops->timeout > 255)
ops->timeout = TFTP_TIMEOUT_DEFAULT;
return (NU_SUCCESS);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -