diff options
| author | Michael Brown | 2005-06-01 20:00:01 +0200 |
|---|---|---|
| committer | Michael Brown | 2005-06-01 20:00:01 +0200 |
| commit | f2198e8a654581f97daaeda301cd8735aa9e3254 (patch) | |
| tree | c4cd52cc9c647771ba08f4e627b8e4e04cd69930 /src/proto/tftp.c | |
| parent | Remove prototypes for obsolete functions (diff) | |
| download | ipxe-f2198e8a654581f97daaeda301cd8735aa9e3254.tar.gz ipxe-f2198e8a654581f97daaeda301cd8735aa9e3254.tar.xz ipxe-f2198e8a654581f97daaeda301cd8735aa9e3254.zip | |
Don't choke on duplicate OACK packets.
Make await_tftp() static and create tftp_get() for fetching the next TFTP
packet instead.
Diffstat (limited to 'src/proto/tftp.c')
| -rw-r--r-- | src/proto/tftp.c | 55 |
1 files changed, 31 insertions, 24 deletions
diff --git a/src/proto/tftp.c b/src/proto/tftp.c index 53706448d..9231c5162 100644 --- a/src/proto/tftp.c +++ b/src/proto/tftp.c @@ -103,40 +103,47 @@ static int tftp ( char *url __unused, struct sockaddr_in *server, char *file, return 0; } - /* Process OACK, if any */ - if ( ntohs ( reply->common.opcode ) == TFTP_OACK ) { - if ( ! tftp_process_opts ( &state, &reply->oack ) ) { - DBG ( "TFTP: option processing failed : %m\n" ); - return 0; - } - reply = NULL; - } - /* Fetch file, a block at a time */ do { - /* Get next block to process. (On the first time - * through, we may already have a block from - * tftp_open()). - */ - if ( ! reply ) { - if ( ! tftp_ack ( &state, &reply ) ) { - DBG ( "TFTP: could not get next block: %m\n" ); + twiddle(); + switch ( ntohs ( reply->common.opcode ) ) { + case TFTP_DATA: + if ( ! process_tftp_data ( &state, &reply->data, + buffer, &eof ) ) { + tftp_error ( &state, TFTP_ERR_ILLEGAL_OP, + NULL ); return 0; } - } - twiddle(); - /* Check it's a DATA block */ - if ( ntohs ( reply->common.opcode ) != TFTP_DATA ) { + 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; } - /* Process the DATA block */ - if ( ! process_tftp_data ( &state, &reply->data, buffer, - &eof ) ) + /* Fetch the next data block */ + if ( ! tftp_ack ( &state, &reply ) ) { + DBG ( "TFTP: could not get next block: %m\n" ); + tftp_error ( &state, TFTP_ERR_ILLEGAL_OP, NULL ); return 0; - reply = NULL; + } } while ( ! eof ); /* ACK the final packet, as a courtesy to the server */ |
