Browse Source

Update TFTP to use a struct buffer rather than a callback.

Add debug autocolourisation to TFTP.
tags/v0.9.3
Michael Brown 18 years ago
parent
commit
0010e10ef3
3 changed files with 80 additions and 73 deletions
  1. 22
    28
      src/include/gpxe/tftp.h
  2. 51
    36
      src/net/udp/tftp.c
  3. 7
    9
      src/tests/tftptest.c

+ 22
- 28
src/include/gpxe/tftp.h View File

@@ -11,6 +11,7 @@
11 11
 #include <gpxe/udp.h>
12 12
 #include <gpxe/async.h>
13 13
 #include <gpxe/retry.h>
14
+#include <gpxe/buffer.h>
14 15
 
15 16
 #define TFTP_PORT	       69 /**< Default TFTP server port */
16 17
 #define	TFTP_DEFAULT_BLKSIZE  512 /**< Default TFTP data block size */
@@ -89,17 +90,30 @@ struct tftp_session {
89 90
 	struct udp_connection udp;
90 91
 	/** Filename */
91 92
 	const char *filename;
93
+	/** Data buffer to fill */
94
+	struct buffer *buffer;
95
+	/** Requested data block size
96
+	 *
97
+	 * This is the "blksize" option requested from the TFTP
98
+	 * server.  It may or may not be honoured.
99
+	 */
100
+	unsigned int request_blksize;
92 101
 
93
-	/**
94
-	 * Callback function
102
+	/** Data block size
103
+	 *
104
+	 * This is the "blksize" option negotiated with the TFTP
105
+	 * server.  (If the TFTP server does not support TFTP options,
106
+	 * this will default to 512).
107
+	 */
108
+	unsigned int blksize;
109
+	/** File size
95 110
 	 *
96
-	 * @v tftp		TFTP connection
97
-	 * @v block		Block number
98
-	 * @v data		Data
99
-	 * @v len		Length of data
111
+	 * This is the value returned in the "tsize" option from the
112
+	 * TFTP server.  If the TFTP server does not support the
113
+	 * "tsize" option, this value will be zero.
100 114
 	 */
101
-	void ( * callback ) ( struct tftp_session *tftp, unsigned int block,
102
-			      void *data, size_t len );
115
+	unsigned long tsize;
116
+
103 117
 	/**
104 118
 	 * Transfer ID
105 119
 	 *
@@ -119,26 +133,6 @@ struct tftp_session {
119 133
 	 * (i.e. that no blocks have yet been received).
120 134
 	 */
121 135
 	int state;
122
-	/** Requested data block size
123
-	 *
124
-	 * This is the "blksize" option requested from the TFTP
125
-	 * server.  It may or may not be honoured.
126
-	 */
127
-	unsigned int request_blksize;
128
-	/** Data block size
129
-	 *
130
-	 * This is the "blksize" option negotiated with the TFTP
131
-	 * server.  (If the TFTP server does not support TFTP options,
132
-	 * this will default to 512).
133
-	 */
134
-	unsigned int blksize;
135
-	/** File size
136
-	 *
137
-	 * This is the value returned in the "tsize" option from the
138
-	 * TFTP server.  If the TFTP server does not support the
139
-	 * "tsize" option, this value will be zero.
140
-	 */
141
-	unsigned long tsize;
142 136
 	
143 137
 	/** Asynchronous operation for this session */
144 138
 	struct async_operation aop;

+ 51
- 36
src/net/udp/tftp.c View File

@@ -59,10 +59,11 @@ static int tftp_process_blksize ( struct tftp_session *tftp,
59 59
 
60 60
 	tftp->blksize = strtoul ( value, &end, 10 );
61 61
 	if ( *end ) {
62
-		DBG ( "TFTP %p got invalid blksize \"%s\"\n", tftp, value );
62
+		DBGC ( tftp, "TFTP %p got invalid blksize \"%s\"\n",
63
+		       tftp, value );
63 64
 		return -EINVAL;
64 65
 	}
65
-	DBG ( "TFTP %p blksize=%d\n", tftp, tftp->blksize );
66
+	DBGC ( tftp, "TFTP %p blksize=%d\n", tftp, tftp->blksize );
66 67
 
67 68
 	return 0;
68 69
 }
@@ -80,10 +81,11 @@ static int tftp_process_tsize ( struct tftp_session *tftp,
80 81
 
81 82
 	tftp->tsize = strtoul ( value, &end, 10 );
82 83
 	if ( *end ) {
83
-		DBG ( "TFTP %p got invalid tsize \"%s\"\n", tftp, value );
84
+		DBGC ( tftp, "TFTP %p got invalid tsize \"%s\"\n",
85
+		       tftp, value );
84 86
 		return -EINVAL;
85 87
 	}
86
-	DBG ( "TFTP %p tsize=%ld\n", tftp, tftp->tsize );
88
+	DBGC ( tftp, "TFTP %p tsize=%ld\n", tftp, tftp->tsize );
87 89
 
88 90
 	return 0;
89 91
 }
@@ -112,8 +114,8 @@ static int tftp_process_option ( struct tftp_session *tftp,
112 114
 			return option->process ( tftp, value );
113 115
 	}
114 116
 
115
-	DBG ( "TFTP %p received unknown option \"%s\" = \"%s\"\n",
116
-	      tftp, name, value );
117
+	DBGC ( tftp, "TFTP %p received unknown option \"%s\" = \"%s\"\n",
118
+	       tftp, name, value );
117 119
 
118 120
 	return -EINVAL;
119 121
 }
@@ -201,7 +203,7 @@ static int tftp_send_rrq ( struct tftp_session *tftp, void *buf, size_t len ) {
201 203
 	void *data;
202 204
 	void *end;
203 205
 
204
-	DBG ( "TFTP %p requesting \"%s\"\n", tftp, tftp->filename );
206
+	DBGC ( tftp, "TFTP %p requesting \"%s\"\n", tftp, tftp->filename );
205 207
 
206 208
 	data = rrq->data;
207 209
 	end = ( buf + len );
@@ -218,7 +220,7 @@ static int tftp_send_rrq ( struct tftp_session *tftp, void *buf, size_t len ) {
218 220
 	return udp_send ( &tftp->udp, buf, ( data - buf ) );
219 221
 
220 222
  overflow:
221
-	DBG ( "TFTP %p RRQ out of space\n", tftp );
223
+	DBGC ( tftp, "TFTP %p RRQ out of space\n", tftp );
222 224
 	return -ENOBUFS;
223 225
 }
224 226
 
@@ -239,12 +241,13 @@ static int tftp_rx_oack ( struct tftp_session *tftp, void *buf, size_t len ) {
239 241
 
240 242
 	/* Sanity check */
241 243
 	if ( len < sizeof ( *oack ) ) {
242
-		DBG ( "TFTP %p received underlength OACK packet length %d\n",
243
-		      tftp, len );
244
+		DBGC ( tftp, "TFTP %p received underlength OACK packet "
245
+		       "length %d\n", tftp, len );
244 246
 		return -EINVAL;
245 247
 	}
246 248
 	if ( end[-1] != '\0' ) {
247
-		DBG ( "TFTP %p received OACK missing final NUL\n", tftp );
249
+		DBGC ( tftp, "TFTP %p received OACK missing final NUL\n",
250
+		       tftp );
248 251
 		return -EINVAL;
249 252
 	}
250 253
 
@@ -253,8 +256,8 @@ static int tftp_rx_oack ( struct tftp_session *tftp, void *buf, size_t len ) {
253 256
 	while ( name < end ) {
254 257
 		value = ( name + strlen ( name ) + 1 );
255 258
 		if ( value == end ) {
256
-			DBG ( "TFTP %p received OACK missing value for option "
257
-			      "\"%s\"\n", tftp, name );
259
+			DBGC ( tftp, "TFTP %p received OACK missing value "
260
+			       "for option \"%s\"\n", tftp, name );
258 261
 			return -EINVAL;
259 262
 		}
260 263
 		if ( ( rc = tftp_process_option ( tftp, name, value ) ) != 0 )
@@ -279,19 +282,28 @@ static int tftp_rx_oack ( struct tftp_session *tftp, void *buf, size_t len ) {
279 282
 static int tftp_rx_data ( struct tftp_session *tftp, void *buf, size_t len ) {
280 283
 	struct tftp_data *data = buf;
281 284
 	unsigned int block;
285
+	size_t data_offset;
282 286
 	size_t data_len;
287
+	int rc;
283 288
 
284 289
 	/* Sanity check */
285 290
 	if ( len < sizeof ( *data ) ) {
286
-		DBG ( "TFTP %p received underlength DATA packet length %d\n",
287
-		      tftp, len );
291
+		DBGC ( tftp, "TFTP %p received underlength DATA packet "
292
+		       "length %d\n", tftp, len );
288 293
 		return -EINVAL;
289 294
 	}
290 295
 
291
-	/* Pass to callback */
296
+	/* Fill data buffer */
292 297
 	block = ntohs ( data->block );
298
+	data_offset = ( ( block - 1 ) * tftp->blksize );
293 299
 	data_len = ( len - offsetof ( typeof ( *data ), data ) );
294
-	tftp->callback ( tftp, block, data->data, data_len );
300
+	if ( ( rc = fill_buffer ( tftp->buffer, data->data, data_offset,
301
+				  data_len ) ) != 0 ) {
302
+		DBGC ( tftp, "TFTP %p could not fill data buffer: %s\n",
303
+		       tftp, strerror ( rc ) );
304
+		tftp_done ( tftp, rc );
305
+		return rc;
306
+	}
295 307
 
296 308
 	/* Mark block as received */
297 309
 	tftp_received ( tftp, block );
@@ -334,13 +346,13 @@ static int tftp_rx_error ( struct tftp_session *tftp, void *buf, size_t len ) {
334 346
 
335 347
 	/* Sanity check */
336 348
 	if ( len < sizeof ( *error ) ) {
337
-		DBG ( "TFTP %p received underlength ERROR packet length %d\n",
338
-		      tftp, len );
349
+		DBGC ( tftp, "TFTP %p received underlength ERROR packet "
350
+		       "length %d\n", tftp, len );
339 351
 		return -EINVAL;
340 352
 	}
341 353
 
342
-	DBG ( "TFTP %p received ERROR packet with code %d, message \"%s\"\n",
343
-	      tftp, ntohs ( error->errcode ), error->errmsg );
354
+	DBGC ( tftp, "TFTP %p received ERROR packet with code %d, message "
355
+	       "\"%s\"\n", tftp, ntohs ( error->errcode ), error->errmsg );
344 356
 	
345 357
 	/* Determine final operation result */
346 358
 	err = ntohs ( error->errcode );
@@ -392,30 +404,31 @@ static int tftp_newdata ( struct udp_connection *conn, void *data, size_t len,
392 404
 	struct tftp_common *common = data;
393 405
 	
394 406
 	if ( len < sizeof ( *common ) ) {
395
-		DBG ( "TFTP %p received underlength packet length %d\n",
396
-		      tftp, len );
407
+		DBGC ( tftp, "TFTP %p received underlength packet length %d\n",
408
+		       tftp, len );
397 409
 		return -EINVAL;
398 410
 	}
399 411
 
400 412
 	/* Filter by TID.  Set TID on first response received */
401 413
 	if ( tftp->tid ) {
402 414
 		if ( tftp->tid != st_src->st_port ) {
403
-			DBG ( "TFTP %p received packet from wrong port "
404
-			      "(got %d, wanted %d)\n", tftp,
405
-			      ntohs ( st_src->st_port ), ntohs ( tftp->tid ) );
415
+			DBGC ( tftp, "TFTP %p received packet from wrong port "
416
+			       "(got %d, wanted %d)\n", tftp,
417
+			       ntohs ( st_src->st_port ), ntohs ( tftp->tid ));
406 418
 			return -EINVAL;
407 419
 		}
408 420
 	} else {
409 421
 		tftp->tid = st_src->st_port;
410
-		DBG ( "TFTP %p using remote port %d\n", tftp,
411
-		      ntohs ( tftp->tid ) );
422
+		DBGC ( tftp, "TFTP %p using remote port %d\n", tftp,
423
+		       ntohs ( tftp->tid ) );
412 424
 		udp_connect_port ( &tftp->udp, tftp->tid );
413 425
 	}
414 426
 
415 427
 	/* Filter by source address */
416 428
 	if ( memcmp ( st_src, udp_peer ( &tftp->udp ),
417 429
 		      sizeof ( *st_src ) ) != 0 ) {
418
-		DBG ( "TFTP %p received packet from foreign source\n", tftp );
430
+		DBGC ( tftp, "TFTP %p received packet from foreign source\n",
431
+		       tftp );
419 432
 		return -EINVAL;
420 433
 	}
421 434
 
@@ -427,8 +440,8 @@ static int tftp_newdata ( struct udp_connection *conn, void *data, size_t len,
427 440
 	case htons ( TFTP_ERROR ):
428 441
 		return tftp_rx_error ( tftp, data, len );
429 442
 	default:
430
-		DBG ( "TFTP %p received strange packet type %d\n", tftp,
431
-		      ntohs ( common->opcode ) );
443
+		DBGC ( tftp, "TFTP %p received strange packet type %d\n", tftp,
444
+		       ntohs ( common->opcode ) );
432 445
 		return -EINVAL;
433 446
 	};
434 447
 }
@@ -449,16 +462,18 @@ struct async_operation * tftp_get ( struct tftp_session *tftp ) {
449 462
 	int rc;
450 463
 
451 464
 	assert ( tftp->filename != NULL );
452
-	assert ( tftp->callback != NULL );
465
+	assert ( tftp->buffer != NULL );
453 466
 	assert ( tftp->udp.peer.st_family != 0 );
454 467
 
455 468
 	/* Initialise TFTP session */
456
-	tftp->udp.udp_op = &tftp_udp_operations;
457
-	tftp->timer.expired = tftp_timer_expired;
458
-	tftp->state = -1;
459
-	tftp->blksize = TFTP_DEFAULT_BLKSIZE;
460 469
 	if ( ! tftp->request_blksize )
461 470
 		tftp->request_blksize = TFTP_MAX_BLKSIZE;
471
+	tftp->blksize = TFTP_DEFAULT_BLKSIZE;
472
+	tftp->tsize = 0;
473
+	tftp->tid = 0;
474
+	tftp->state = -1;
475
+	tftp->udp.udp_op = &tftp_udp_operations;
476
+	tftp->timer.expired = tftp_timer_expired;
462 477
 
463 478
 	/* Open UDP connection */
464 479
 	if ( ( rc = udp_open ( &tftp->udp, 0 ) ) != 0 ) {

+ 7
- 9
src/tests/tftptest.c View File

@@ -5,25 +5,23 @@
5 5
 #include <gpxe/tftp.h>
6 6
 #include <gpxe/async.h>
7 7
 #include <gpxe/uaccess.h>
8
+#include <gpxe/buffer.h>
8 9
 #include "pxe.h"
9 10
 
10
-static void test_tftp_callback ( struct tftp_session *tftp, unsigned int block,
11
-				 void *data, size_t len ) {
12
-	unsigned long offset = ( ( block - 1 ) * tftp->blksize );
13
-	userptr_t pxe_buffer = real_to_user ( 0, 0x7c00 );
14
-
15
-	copy_to_user ( pxe_buffer, offset, data, len );
16
-}
17
-
18 11
 int test_tftp ( struct net_device *netdev, struct sockaddr_tcpip *target,
19 12
 		const char *filename ) {
20 13
 	struct tftp_session tftp;
14
+	struct buffer buffer;
21 15
 	int rc;
22 16
 
17
+	memset ( &buffer, 0, sizeof ( buffer ) );
18
+	buffer.addr = real_to_user ( 0, 0x7c00 );
19
+	buffer.len = ( 512 * 1024 - 0x7c00 );
20
+
23 21
 	memset ( &tftp, 0, sizeof ( tftp ) );
24 22
 	udp_connect ( &tftp.udp, target );
25 23
 	tftp.filename = filename;
26
-	tftp.callback = test_tftp_callback;
24
+	tftp.buffer = &buffer;
27 25
 
28 26
 	printf ( "Fetching \"%s\" via TFTP\n", filename );
29 27
 	if ( ( rc = async_wait ( tftp_get ( &tftp ) ) ) != 0 )

Loading…
Cancel
Save