You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tftp.c 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #include "etherboot.h"
  2. #include "proto.h"
  3. #include "errno.h"
  4. #include "tftp.h"
  5. #include "tftpcore.h"
  6. /** @file
  7. *
  8. * TFTP protocol
  9. */
  10. /**
  11. * Process a TFTP block
  12. *
  13. * @v state TFTP transfer state
  14. * @v tftp_state::block Last received data block
  15. * @v tftp_state::blksize Transfer block size
  16. * @v data The data block to process
  17. * @v buffer The buffer to fill with the data
  18. * @ret True Block processed successfully
  19. * @ret False Block not processed successfully
  20. * @ret tftp_state::block Incremented if applicable
  21. * @ret *eof End-of-file marker
  22. * @err #PXENV_STATUS_TFTP_INVALID_PACKET_SIZE Packet is too large
  23. * @err other As returned by fill_buffer()
  24. *
  25. * Process a TFTP DATA packet that has been received. If the data
  26. * packet is the next data packet in the stream, its contents will be
  27. * placed in the #buffer and tftp_state::block will be incremented.
  28. * If the packet is the final packet, end-of-file will be indicated
  29. * via #eof.
  30. *
  31. * If the data packet is a duplicate, then process_tftp_data() will
  32. * still return True, though nothing will be done with the packet. A
  33. * False return value always indicates an error that should abort the
  34. * transfer.
  35. */
  36. static inline int tftp_process_data ( struct tftp_state *state,
  37. struct tftp_data *data,
  38. struct buffer *buffer,
  39. int *eof ) {
  40. unsigned int blksize;
  41. /* Check it's the correct DATA block */
  42. if ( ntohs ( data->block ) != ( state->block + 1 ) ) {
  43. DBG ( "TFTP: got block %d, wanted block %d\n",
  44. ntohs ( data->block ), state->block + 1 );
  45. return 1;
  46. }
  47. /* Check it's an acceptable size */
  48. blksize = ( ntohs ( data->udp.len )
  49. + offsetof ( typeof ( *data ), udp )
  50. - offsetof ( typeof ( *data ), data ) );
  51. if ( blksize > state->blksize ) {
  52. DBG ( "TFTP: oversized block size %d (max %d)\n",
  53. blksize, state->blksize );
  54. errno = PXENV_STATUS_TFTP_INVALID_PACKET_SIZE;
  55. return 0;
  56. }
  57. /* Place block in the buffer */
  58. if ( ! fill_buffer ( buffer, data->data, state->block * state->blksize,
  59. blksize ) ) {
  60. DBG ( "TFTP: could not place data in buffer: %m\n" );
  61. return 0;
  62. }
  63. /* Increment block counter */
  64. state->block++;
  65. /* Set EOF marker */
  66. *eof = ( blksize < state->blksize );
  67. return 1;
  68. }
  69. /**
  70. * Download a file via TFTP
  71. *
  72. * @v server TFTP server
  73. * @v file File name
  74. * @v buffer Buffer into which to load file
  75. * @ret True File was downloaded successfully
  76. * @ret False File was not downloaded successfully
  77. * @err #PXENV_STATUS_TFTP_UNKNOWN_OPCODE Unknown type of TFTP block received
  78. * @err other As returned by tftp_open()
  79. * @err other As returned by tftp_process_opts()
  80. * @err other As returned by tftp_ack()
  81. * @err other As returned by tftp_process_data()
  82. *
  83. * Download a file from a TFTP server into the specified buffer.
  84. */
  85. static int tftp ( char *url __unused, struct sockaddr_in *server, char *file,
  86. struct buffer *buffer ) {
  87. struct tftp_state state;
  88. union tftp_any *reply;
  89. int eof = 0;
  90. /* Initialise TFTP state */
  91. memset ( &state, 0, sizeof ( state ) );
  92. state.server = *server;
  93. /* Open the file */
  94. if ( ! tftp_open ( &state, file, &reply, 0 ) ) {
  95. DBG ( "TFTP: could not open %@:%d/%s : %m\n",
  96. server->sin_addr.s_addr, server->sin_port, file );
  97. return 0;
  98. }
  99. /* Fetch file, a block at a time */
  100. while ( 1 ) {
  101. twiddle();
  102. switch ( ntohs ( reply->common.opcode ) ) {
  103. case TFTP_DATA:
  104. if ( ! tftp_process_data ( &state, &reply->data,
  105. buffer, &eof ) ) {
  106. tftp_error ( &state, TFTP_ERR_ILLEGAL_OP,
  107. NULL );
  108. return 0;
  109. }
  110. break;
  111. case TFTP_OACK:
  112. if ( state.block ) {
  113. /* OACK must be first block, if present */
  114. DBG ( "TFTP: OACK after block %d\n",
  115. state.block );
  116. errno = PXENV_STATUS_TFTP_UNKNOWN_OPCODE;
  117. tftp_error ( &state, TFTP_ERR_ILLEGAL_OP,
  118. NULL );
  119. return 0;
  120. }
  121. if ( ! tftp_process_opts ( &state, &reply->oack ) ) {
  122. DBG ( "TFTP: option processing failed: %m\n" );
  123. tftp_error ( &state, TFTP_ERR_BAD_OPTS, NULL );
  124. return 0;
  125. }
  126. break;
  127. default:
  128. DBG ( "TFTP: unexpected opcode %d\n",
  129. ntohs ( reply->common.opcode ) );
  130. errno = PXENV_STATUS_TFTP_UNKNOWN_OPCODE;
  131. tftp_error ( &state, TFTP_ERR_ILLEGAL_OP, NULL );
  132. return 0;
  133. }
  134. /* If we have reached EOF, stop here */
  135. if ( eof )
  136. break;
  137. /* Fetch the next data block */
  138. if ( ! tftp_ack ( &state, &reply ) ) {
  139. DBG ( "TFTP: could not get next block: %m\n" );
  140. if ( ! reply ) {
  141. tftp_error ( &state, TFTP_ERR_ILLEGAL_OP,
  142. NULL );
  143. }
  144. return 0;
  145. }
  146. }
  147. /* ACK the final packet, as a courtesy to the server */
  148. tftp_ack_nowait ( &state );
  149. return 1;
  150. }
  151. struct protocol tftp_protocol __default_protocol = {
  152. .name = "tftp",
  153. .default_port = TFTP_PORT,
  154. .load = tftp,
  155. };