13 * Process a TFTP block
15 * @v state TFTP transfer state
16 * @v tftp_state::block Last received data block
17 * @v tftp_state::blksize Transfer block size
18 * @v data The data block to process
19 * @v buffer The buffer to fill with the data
20 * @ret True Block processed successfully
21 * @ret False Block not processed successfully
22 * @ret tftp_state::block Incremented if applicable
23 * @ret *eof End-of-file marker
24 * @err #PXENV_STATUS_TFTP_INVALID_PACKET_SIZE Packet is too large
25 * @err other As returned by fill_buffer()
27 * Process a TFTP DATA packet that has been received. If the data
28 * packet is the next data packet in the stream, its contents will be
29 * placed in the #buffer and tftp_state::block will be incremented.
30 * If the packet is the final packet, end-of-file will be indicated
33 * If the data packet is a duplicate, then process_tftp_data() will
34 * still return True, though nothing will be done with the packet. A
35 * False return value always indicates an error that should abort the
38 static inline int process_tftp_data ( struct tftp_state *state,
39 struct tftp_data *data,
40 struct buffer *buffer,
44 /* Check it's the correct DATA block */
45 if ( ntohs ( data->block ) != ( state->block + 1 ) ) {
46 DBG ( "TFTP: got block %d, wanted block %d\n",
47 ntohs ( data->block ), state->block + 1 );
50 /* Check it's an acceptable size */
51 blksize = ( ntohs ( data->udp.len )
52 + offsetof ( typeof ( *data ), udp )
53 - offsetof ( typeof ( *data ), data ) );
54 if ( blksize > state->blksize ) {
55 DBG ( "TFTP: oversized block size %d (max %d)\n",
56 blksize, state->blksize );
57 errno = PXENV_STATUS_TFTP_INVALID_PACKET_SIZE;
60 /* Place block in the buffer */
61 if ( ! fill_buffer ( buffer, data->data, state->block * state->blksize,
63 DBG ( "TFTP: could not place data in buffer: %m\n" );
66 /* Increment block counter */
69 *eof = ( blksize < state->blksize );
74 * Download a file via TFTP
76 * @v server TFTP server
78 * @v buffer Buffer into which to load file
79 * @ret True File was downloaded successfully
80 * @ret False File was not downloaded successfully
81 * @err #PXENV_STATUS_TFTP_UNKNOWN_OPCODE Unknown type of TFTP block received
82 * @err other As returned by tftp_open()
83 * @err other As returned by tftp_process_opts()
84 * @err other As returned by tftp_ack()
85 * @err other As returned by tftp_process_data()
87 * Download a file from a TFTP server into the specified buffer.
89 static int tftp ( char *url __unused, struct sockaddr_in *server, char *file,
90 struct buffer *buffer ) {
91 struct tftp_state state;
92 union tftp_any *reply;
95 /* Initialise TFTP state */
96 memset ( &state, 0, sizeof ( state ) );
97 state.server = *server;
100 if ( ! tftp_open ( &state, file, &reply ) ) {
101 DBG ( "TFTP: could not open %@:%d/%s : %m\n",
102 server->sin_addr.s_addr, server->sin_port, file );
106 /* Process OACK, if any */
107 if ( ntohs ( reply->common.opcode ) == TFTP_OACK ) {
108 if ( ! tftp_process_opts ( &state, &reply->oack ) ) {
109 DBG ( "TFTP: option processing failed : %m\n" );
115 /* Fetch file, a block at a time */
117 /* Get next block to process. (On the first time
118 * through, we may already have a block from
122 if ( ! tftp_ack ( &state, &reply ) ) {
123 DBG ( "TFTP: could not get next block: %m\n" );
128 /* Check it's a DATA block */
129 if ( ntohs ( reply->common.opcode ) != TFTP_DATA ) {
130 DBG ( "TFTP: unexpected opcode %d\n",
131 ntohs ( reply->common.opcode ) );
132 errno = PXENV_STATUS_TFTP_UNKNOWN_OPCODE;
135 /* Process the DATA block */
136 if ( ! process_tftp_data ( &state, &reply->data, buffer,
142 /* ACK the final packet, as a courtesy to the server */
143 tftp_ack_nowait ( &state );
148 struct protocol tftp_protocol __default_protocol = {
150 .default_port = TFTP_PORT,