Browse Source

[tftp] Temporary fix for conveying TFTP block size to callers

pxe_tftp.c assumes that the first seek on its data-transfer interface
represents the block size.  Apart from being an ugly hack, this will
also screw up file size calculation for files smaller than one block.

The proper solution would be to extend the data-transfer interface to
support the reporting of stat()-like data.  This is not going to
happen until the cost of adding interface methods is reduced (a fix I
have planned since June 2008).

In the meantime, abuse the xfer_window() method to return the block
size, since it is not being used for anything else and is vaguely
justifiable.

Astonishingly, having returned the incorrect TFTP blocksize via
PXENV_TFTP_OPEN for almost a year seems not to have affected any of
the test cases run during that time; this bug was found only when
someone tried running the heavily-patched version of pxegrub found in
OpenSolaris.
tags/v0.9.7
Michael Brown 15 years ago
parent
commit
1284773363
2 changed files with 23 additions and 8 deletions
  1. 4
    7
      src/arch/i386/interface/pxe/pxe_tftp.c
  2. 19
    1
      src/net/udp/tftp.c

+ 4
- 7
src/arch/i386/interface/pxe/pxe_tftp.c View File

@@ -113,12 +113,6 @@ static int pxe_tftp_xfer_deliver_iob ( struct xfer_interface *xfer __unused,
113 113
 	/* Calculate new buffer position */
114 114
 	pxe_tftp.offset += len;
115 115
 
116
-	/* Mildly ugly hack; assume that the first non-zero seek
117
-	 * indicates the block size.
118
-	 */
119
-	if ( pxe_tftp.blksize == 0 )
120
-		pxe_tftp.blksize = pxe_tftp.offset;
121
-
122 116
 	/* Record maximum offset as the file size */
123 117
 	if ( pxe_tftp.max_offset < pxe_tftp.offset )
124 118
 		pxe_tftp.max_offset = pxe_tftp.offset;
@@ -265,10 +259,12 @@ PXENV_EXIT_t pxenv_tftp_open ( struct s_PXENV_TFTP_OPEN *tftp_open ) {
265 259
 
266 260
 	/* Wait for OACK to arrive so that we have the block size */
267 261
 	while ( ( ( rc = pxe_tftp.rc ) == -EINPROGRESS ) &&
268
-		( pxe_tftp.blksize == 0 ) ) {
262
+		( pxe_tftp.max_offset == 0 ) ) {
269 263
 		step();
270 264
 	}
265
+	pxe_tftp.blksize = xfer_window ( &pxe_tftp.xfer );
271 266
 	tftp_open->PacketSize = pxe_tftp.blksize;
267
+	DBG ( " blksize=%d", tftp_open->PacketSize );
272 268
 
273 269
 	/* EINPROGRESS is normal; we don't wait for the whole transfer */
274 270
 	if ( rc == -EINPROGRESS )
@@ -571,6 +567,7 @@ PXENV_EXIT_t pxenv_tftp_get_fsize ( struct s_PXENV_TFTP_GET_FSIZE
571 567
 		step();
572 568
 	}
573 569
 	tftp_get_fsize->FileSize = pxe_tftp.max_offset;
570
+	DBG ( " fsize=%d", tftp_get_fsize->FileSize );
574 571
 
575 572
 	/* EINPROGRESS is normal; we don't wait for the whole transfer */
576 573
 	if ( rc == -EINPROGRESS )

+ 19
- 1
src/net/udp/tftp.c View File

@@ -986,11 +986,29 @@ static void tftp_xfer_close ( struct xfer_interface *xfer, int rc ) {
986 986
 	tftp_done ( tftp, rc );
987 987
 }
988 988
 
989
+/**
990
+ * Check flow control window
991
+ *
992
+ * @v xfer		Data transfer interface
993
+ * @ret len		Length of window
994
+ */
995
+static size_t tftp_xfer_window ( struct xfer_interface *xfer ) {
996
+	struct tftp_request *tftp =
997
+		container_of ( xfer, struct tftp_request, xfer );
998
+
999
+	/* We abuse this data-xfer method to convey the blocksize to
1000
+	 * the caller.  This really should be done using some kind of
1001
+	 * stat() method, but we don't yet have the facility to do
1002
+	 * that.
1003
+	 */
1004
+	return tftp->blksize;
1005
+}
1006
+
989 1007
 /** TFTP data transfer interface operations */
990 1008
 static struct xfer_interface_operations tftp_xfer_operations = {
991 1009
 	.close		= tftp_xfer_close,
992 1010
 	.vredirect	= ignore_xfer_vredirect,
993
-	.window		= unlimited_xfer_window,
1011
+	.window		= tftp_xfer_window,
994 1012
 	.alloc_iob	= default_xfer_alloc_iob,
995 1013
 	.deliver_iob	= xfer_deliver_as_raw,
996 1014
 	.deliver_raw	= ignore_xfer_deliver_raw,

Loading…
Cancel
Save