diff options
author | Michael Brown | 2006-08-09 01:45:52 +0200 |
---|---|---|
committer | Michael Brown | 2006-08-09 01:45:52 +0200 |
commit | 3611cb17b74740588059c5fe2d11545c6e11f573 (patch) | |
tree | 99449753bd7dfcafbd4269ec5be54d228c486c26 /src/proto | |
parent | The prototype for strcasecmp() is apparently in strings.h. (diff) | |
download | ipxe-3611cb17b74740588059c5fe2d11545c6e11f573.tar.gz ipxe-3611cb17b74740588059c5fe2d11545c6e11f573.tar.xz ipxe-3611cb17b74740588059c5fe2d11545c6e11f573.zip |
Initial (untested) implementation of TFTP over the new UDP API.
Diffstat (limited to 'src/proto')
-rw-r--r-- | src/proto/tftp.c | 165 |
1 files changed, 0 insertions, 165 deletions
diff --git a/src/proto/tftp.c b/src/proto/tftp.c deleted file mode 100644 index 3f6bf35a..00000000 --- a/src/proto/tftp.c +++ /dev/null @@ -1,165 +0,0 @@ -#include "etherboot.h" -#include "proto.h" -#include "errno.h" -#include "tftp.h" -#include "tftpcore.h" - -/** @file - * - * TFTP protocol - */ - -/** - * Process a TFTP block - * - * @v state TFTP transfer state - * @v tftp_state::block Last received data block - * @v tftp_state::blksize Transfer block size - * @v data The data block to process - * @v buffer The buffer to fill with the data - * @ret True Block processed successfully - * @ret False Block not processed successfully - * @ret tftp_state::block Incremented if applicable - * @ret *eof End-of-file marker - * @err #PXENV_STATUS_TFTP_INVALID_PACKET_SIZE Packet is too large - * @err other As returned by fill_buffer() - * - * Process a TFTP DATA packet that has been received. If the data - * packet is the next data packet in the stream, its contents will be - * placed in the #buffer and tftp_state::block will be incremented. - * If the packet is the final packet, end-of-file will be indicated - * via #eof. - * - * If the data packet is a duplicate, then process_tftp_data() will - * still return True, though nothing will be done with the packet. A - * False return value always indicates an error that should abort the - * transfer. - */ -static inline int tftp_process_data ( struct tftp_state *state, - struct tftp_data *data, - struct buffer *buffer, - int *eof ) { - unsigned int blksize; - - /* Check it's the correct DATA block */ - if ( ntohs ( data->block ) != ( state->block + 1 ) ) { - DBG ( "TFTP: got block %d, wanted block %d\n", - ntohs ( data->block ), state->block + 1 ); - return 1; - } - /* Check it's an acceptable size */ - blksize = ( ntohs ( data->udp.len ) - + offsetof ( typeof ( *data ), udp ) - - offsetof ( typeof ( *data ), data ) ); - if ( blksize > state->blksize ) { - DBG ( "TFTP: oversized block size %d (max %d)\n", - blksize, state->blksize ); - errno = PXENV_STATUS_TFTP_INVALID_PACKET_SIZE; - return 0; - } - /* Place block in the buffer */ - if ( ! fill_buffer ( buffer, data->data, state->block * state->blksize, - blksize ) ) { - DBG ( "TFTP: could not place data in buffer: %m\n" ); - return 0; - } - /* Increment block counter */ - state->block++; - /* Set EOF marker */ - *eof = ( blksize < state->blksize ); - return 1; -} - -/** - * Download a file via TFTP - * - * @v server TFTP server - * @v file File name - * @v buffer Buffer into which to load file - * @ret True File was downloaded successfully - * @ret False File was not downloaded successfully - * @err #PXENV_STATUS_TFTP_UNKNOWN_OPCODE Unknown type of TFTP block received - * @err other As returned by tftp_open() - * @err other As returned by tftp_process_opts() - * @err other As returned by tftp_ack() - * @err other As returned by tftp_process_data() - * - * Download a file from a TFTP server into the specified buffer. - */ -static int tftp ( char *url __unused, struct sockaddr_in *server, char *file, - struct buffer *buffer ) { - struct tftp_state state; - union tftp_any *reply; - int eof = 0; - - /* Initialise TFTP state */ - memset ( &state, 0, sizeof ( state ) ); - state.server = *server; - - /* Open the file */ - if ( ! tftp_open ( &state, file, &reply, 0 ) ) { - DBG ( "TFTP: could not open %@:%d/%s : %m\n", - server->sin_addr.s_addr, server->sin_port, file ); - return 0; - } - - /* Fetch file, a block at a time */ - while ( 1 ) { - twiddle(); - switch ( ntohs ( reply->common.opcode ) ) { - case TFTP_DATA: - if ( ! tftp_process_data ( &state, &reply->data, - buffer, &eof ) ) { - tftp_error ( &state, TFTP_ERR_ILLEGAL_OP, - NULL ); - return 0; - } - break; - case TFTP_OACK: - if ( state.block ) { - /* OACK must be first block, if present */ - DBG ( "TFTP: OACK after block %d\n", - state.block ); - errno = PXENV_STATUS_TFTP_UNKNOWN_OPCODE; - tftp_error ( &state, TFTP_ERR_ILLEGAL_OP, - NULL ); - return 0; - } - if ( ! tftp_process_opts ( &state, &reply->oack ) ) { - DBG ( "TFTP: option processing failed: %m\n" ); - tftp_error ( &state, TFTP_ERR_BAD_OPTS, NULL ); - return 0; - } - break; - default: - DBG ( "TFTP: unexpected opcode %d\n", - ntohs ( reply->common.opcode ) ); - errno = PXENV_STATUS_TFTP_UNKNOWN_OPCODE; - tftp_error ( &state, TFTP_ERR_ILLEGAL_OP, NULL ); - return 0; - } - /* If we have reached EOF, stop here */ - if ( eof ) - break; - /* Fetch the next data block */ - if ( ! tftp_ack ( &state, &reply ) ) { - DBG ( "TFTP: could not get next block: %m\n" ); - if ( ! reply ) { - tftp_error ( &state, TFTP_ERR_ILLEGAL_OP, - NULL ); - } - return 0; - } - } - - /* ACK the final packet, as a courtesy to the server */ - tftp_ack_nowait ( &state ); - - return 1; -} - -struct protocol tftp_protocol __default_protocol = { - .name = "tftp", - .default_port = TFTP_PORT, - .load = tftp, -}; |