[tftp] Explicitly abort connection whenever parent interface is closed

Fetching the TFTP file size is currently implemented via a custom
"tftpsize://" protocol hack.  Generalise this approach to instead
close the TFTP connection whenever the parent data-transfer interface
is closed.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
pull/34/head
Michael Brown 2015-02-06 12:08:54 +00:00
parent 2d3f2b2446
commit 2dfdcae938
2 changed files with 23 additions and 48 deletions

View File

@ -171,8 +171,7 @@ static struct pxe_tftp_connection pxe_tftp = {
* @ret rc Return status code * @ret rc Return status code
*/ */
static int pxe_tftp_open ( uint32_t ipaddress, unsigned int port, static int pxe_tftp_open ( uint32_t ipaddress, unsigned int port,
const unsigned char *filename, size_t blksize, const unsigned char *filename, size_t blksize ) {
int sizeonly ) {
char uri_string[PXE_TFTP_URI_LEN]; char uri_string[PXE_TFTP_URI_LEN];
struct in_addr address; struct in_addr address;
int rc; int rc;
@ -189,10 +188,9 @@ static int pxe_tftp_open ( uint32_t ipaddress, unsigned int port,
address.s_addr = ipaddress; address.s_addr = ipaddress;
if ( ! port ) if ( ! port )
port = htons ( TFTP_PORT ); port = htons ( TFTP_PORT );
snprintf ( uri_string, sizeof ( uri_string ), "tftp%s://%s:%d%s%s", snprintf ( uri_string, sizeof ( uri_string ), "tftp://%s:%d%s%s",
sizeonly ? "size" : "", inet_ntoa ( address ), inet_ntoa ( address ), ntohs ( port ),
ntohs ( port ), ( ( filename[0] == '/' ) ? "" : "/" ), ( ( filename[0] == '/' ) ? "" : "/" ), filename );
filename );
DBG ( " %s", uri_string ); DBG ( " %s", uri_string );
/* Open PXE TFTP connection */ /* Open PXE TFTP connection */
@ -259,8 +257,7 @@ static PXENV_EXIT_t pxenv_tftp_open ( struct s_PXENV_TFTP_OPEN *tftp_open ) {
if ( ( rc = pxe_tftp_open ( tftp_open->ServerIPAddress, if ( ( rc = pxe_tftp_open ( tftp_open->ServerIPAddress,
tftp_open->TFTPPort, tftp_open->TFTPPort,
tftp_open->FileName, tftp_open->FileName,
tftp_open->PacketSize, tftp_open->PacketSize ) ) != 0 ) {
0) ) != 0 ) {
tftp_open->Status = PXENV_STATUS ( rc ); tftp_open->Status = PXENV_STATUS ( rc );
return PXENV_EXIT_FAILURE; return PXENV_EXIT_FAILURE;
} }
@ -483,7 +480,7 @@ PXENV_EXIT_t pxenv_tftp_read_file ( struct s_PXENV_TFTP_READ_FILE
/* Open TFTP file */ /* Open TFTP file */
if ( ( rc = pxe_tftp_open ( tftp_read_file->ServerIPAddress, 0, if ( ( rc = pxe_tftp_open ( tftp_read_file->ServerIPAddress, 0,
tftp_read_file->FileName, 0, 0 ) ) != 0 ) { tftp_read_file->FileName, 0 ) ) != 0 ) {
tftp_read_file->Status = PXENV_STATUS ( rc ); tftp_read_file->Status = PXENV_STATUS ( rc );
return PXENV_EXIT_FAILURE; return PXENV_EXIT_FAILURE;
} }
@ -553,7 +550,7 @@ static PXENV_EXIT_t pxenv_tftp_get_fsize ( struct s_PXENV_TFTP_GET_FSIZE
/* Open TFTP file */ /* Open TFTP file */
if ( ( rc = pxe_tftp_open ( tftp_get_fsize->ServerIPAddress, 0, if ( ( rc = pxe_tftp_open ( tftp_get_fsize->ServerIPAddress, 0,
tftp_get_fsize->FileName, 0, 1 ) ) != 0 ) { tftp_get_fsize->FileName, 0 ) ) != 0 ) {
tftp_get_fsize->Status = PXENV_STATUS ( rc ); tftp_get_fsize->Status = PXENV_STATUS ( rc );
return PXENV_EXIT_FAILURE; return PXENV_EXIT_FAILURE;
} }

View File

@ -149,8 +149,6 @@ enum {
TFTP_FL_RRQ_MULTICAST = 0x0004, TFTP_FL_RRQ_MULTICAST = 0x0004,
/** Perform MTFTP recovery on timeout */ /** Perform MTFTP recovery on timeout */
TFTP_FL_MTFTP_RECOVERY = 0x0008, TFTP_FL_MTFTP_RECOVERY = 0x0008,
/** Only get filesize and then abort the transfer */
TFTP_FL_SIZEONLY = 0x0010,
}; };
/** Maximum number of MTFTP open requests before falling back to TFTP */ /** Maximum number of MTFTP open requests before falling back to TFTP */
@ -759,14 +757,6 @@ static int tftp_rx_oack ( struct tftp_request *tftp, void *buf, size_t len ) {
goto done; goto done;
} }
/* Abort request if only trying to determine file size */
if ( tftp->flags & TFTP_FL_SIZEONLY ) {
rc = 0;
tftp_send_error ( tftp, 0, "TFTP Aborted" );
tftp_done ( tftp, rc );
return rc;
}
/* Request next data block */ /* Request next data block */
tftp_send_packet ( tftp ); tftp_send_packet ( tftp );
@ -794,13 +784,6 @@ static int tftp_rx_data ( struct tftp_request *tftp,
size_t data_len; size_t data_len;
int rc; int rc;
if ( tftp->flags & TFTP_FL_SIZEONLY ) {
/* If we get here then server doesn't support SIZE option */
rc = -ENOTSUP;
tftp_send_error ( tftp, 0, "TFTP Aborted" );
goto done;
}
/* Sanity check */ /* Sanity check */
if ( iob_len ( iobuf ) < sizeof ( *data ) ) { if ( iob_len ( iobuf ) < sizeof ( *data ) ) {
DBGC ( tftp, "TFTP %p received underlength DATA packet " DBGC ( tftp, "TFTP %p received underlength DATA packet "
@ -1036,10 +1019,25 @@ static size_t tftp_xfer_window ( struct tftp_request *tftp ) {
return tftp->blksize; return tftp->blksize;
} }
/**
* Terminate download
*
* @v tftp TFTP connection
* @v rc Reason for close
*/
static void tftp_close ( struct tftp_request *tftp, int rc ) {
/* Abort download */
tftp_send_error ( tftp, 0, "TFTP Aborted" );
/* Close TFTP request */
tftp_done ( tftp, rc );
}
/** TFTP data transfer interface operations */ /** TFTP data transfer interface operations */
static struct interface_operation tftp_xfer_operations[] = { static struct interface_operation tftp_xfer_operations[] = {
INTF_OP ( xfer_window, struct tftp_request *, tftp_xfer_window ), INTF_OP ( xfer_window, struct tftp_request *, tftp_xfer_window ),
INTF_OP ( intf_close, struct tftp_request *, tftp_done ), INTF_OP ( intf_close, struct tftp_request *, tftp_close ),
}; };
/** TFTP data transfer interface descriptor */ /** TFTP data transfer interface descriptor */
@ -1125,26 +1123,6 @@ struct uri_opener tftp_uri_opener __uri_opener = {
.open = tftp_open, .open = tftp_open,
}; };
/**
* Initiate TFTP-size request
*
* @v xfer Data transfer interface
* @v uri Uniform Resource Identifier
* @ret rc Return status code
*/
static int tftpsize_open ( struct interface *xfer, struct uri *uri ) {
return tftp_core_open ( xfer, uri, TFTP_PORT, NULL,
( TFTP_FL_RRQ_SIZES |
TFTP_FL_SIZEONLY ) );
}
/** TFTP URI opener */
struct uri_opener tftpsize_uri_opener __uri_opener = {
.scheme = "tftpsize",
.open = tftpsize_open,
};
/** /**
* Initiate TFTM download * Initiate TFTM download
* *