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
 #include <gpxe/udp.h>
11
 #include <gpxe/udp.h>
12
 #include <gpxe/async.h>
12
 #include <gpxe/async.h>
13
 #include <gpxe/retry.h>
13
 #include <gpxe/retry.h>
14
+#include <gpxe/buffer.h>
14
 
15
 
15
 #define TFTP_PORT	       69 /**< Default TFTP server port */
16
 #define TFTP_PORT	       69 /**< Default TFTP server port */
16
 #define	TFTP_DEFAULT_BLKSIZE  512 /**< Default TFTP data block size */
17
 #define	TFTP_DEFAULT_BLKSIZE  512 /**< Default TFTP data block size */
89
 	struct udp_connection udp;
90
 	struct udp_connection udp;
90
 	/** Filename */
91
 	/** Filename */
91
 	const char *filename;
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
 	 * Transfer ID
118
 	 * Transfer ID
105
 	 *
119
 	 *
119
 	 * (i.e. that no blocks have yet been received).
133
 	 * (i.e. that no blocks have yet been received).
120
 	 */
134
 	 */
121
 	int state;
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
 	/** Asynchronous operation for this session */
137
 	/** Asynchronous operation for this session */
144
 	struct async_operation aop;
138
 	struct async_operation aop;

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

59
 
59
 
60
 	tftp->blksize = strtoul ( value, &end, 10 );
60
 	tftp->blksize = strtoul ( value, &end, 10 );
61
 	if ( *end ) {
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
 		return -EINVAL;
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
 	return 0;
68
 	return 0;
68
 }
69
 }
80
 
81
 
81
 	tftp->tsize = strtoul ( value, &end, 10 );
82
 	tftp->tsize = strtoul ( value, &end, 10 );
82
 	if ( *end ) {
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
 		return -EINVAL;
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
 	return 0;
90
 	return 0;
89
 }
91
 }
112
 			return option->process ( tftp, value );
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
 	return -EINVAL;
120
 	return -EINVAL;
119
 }
121
 }
201
 	void *data;
203
 	void *data;
202
 	void *end;
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
 	data = rrq->data;
208
 	data = rrq->data;
207
 	end = ( buf + len );
209
 	end = ( buf + len );
218
 	return udp_send ( &tftp->udp, buf, ( data - buf ) );
220
 	return udp_send ( &tftp->udp, buf, ( data - buf ) );
219
 
221
 
220
  overflow:
222
  overflow:
221
-	DBG ( "TFTP %p RRQ out of space\n", tftp );
223
+	DBGC ( tftp, "TFTP %p RRQ out of space\n", tftp );
222
 	return -ENOBUFS;
224
 	return -ENOBUFS;
223
 }
225
 }
224
 
226
 
239
 
241
 
240
 	/* Sanity check */
242
 	/* Sanity check */
241
 	if ( len < sizeof ( *oack ) ) {
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
 		return -EINVAL;
246
 		return -EINVAL;
245
 	}
247
 	}
246
 	if ( end[-1] != '\0' ) {
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
 		return -EINVAL;
251
 		return -EINVAL;
249
 	}
252
 	}
250
 
253
 
253
 	while ( name < end ) {
256
 	while ( name < end ) {
254
 		value = ( name + strlen ( name ) + 1 );
257
 		value = ( name + strlen ( name ) + 1 );
255
 		if ( value == end ) {
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
 			return -EINVAL;
261
 			return -EINVAL;
259
 		}
262
 		}
260
 		if ( ( rc = tftp_process_option ( tftp, name, value ) ) != 0 )
263
 		if ( ( rc = tftp_process_option ( tftp, name, value ) ) != 0 )
279
 static int tftp_rx_data ( struct tftp_session *tftp, void *buf, size_t len ) {
282
 static int tftp_rx_data ( struct tftp_session *tftp, void *buf, size_t len ) {
280
 	struct tftp_data *data = buf;
283
 	struct tftp_data *data = buf;
281
 	unsigned int block;
284
 	unsigned int block;
285
+	size_t data_offset;
282
 	size_t data_len;
286
 	size_t data_len;
287
+	int rc;
283
 
288
 
284
 	/* Sanity check */
289
 	/* Sanity check */
285
 	if ( len < sizeof ( *data ) ) {
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
 		return -EINVAL;
293
 		return -EINVAL;
289
 	}
294
 	}
290
 
295
 
291
-	/* Pass to callback */
296
+	/* Fill data buffer */
292
 	block = ntohs ( data->block );
297
 	block = ntohs ( data->block );
298
+	data_offset = ( ( block - 1 ) * tftp->blksize );
293
 	data_len = ( len - offsetof ( typeof ( *data ), data ) );
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
 	/* Mark block as received */
308
 	/* Mark block as received */
297
 	tftp_received ( tftp, block );
309
 	tftp_received ( tftp, block );
334
 
346
 
335
 	/* Sanity check */
347
 	/* Sanity check */
336
 	if ( len < sizeof ( *error ) ) {
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
 		return -EINVAL;
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
 	/* Determine final operation result */
357
 	/* Determine final operation result */
346
 	err = ntohs ( error->errcode );
358
 	err = ntohs ( error->errcode );
392
 	struct tftp_common *common = data;
404
 	struct tftp_common *common = data;
393
 	
405
 	
394
 	if ( len < sizeof ( *common ) ) {
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
 		return -EINVAL;
409
 		return -EINVAL;
398
 	}
410
 	}
399
 
411
 
400
 	/* Filter by TID.  Set TID on first response received */
412
 	/* Filter by TID.  Set TID on first response received */
401
 	if ( tftp->tid ) {
413
 	if ( tftp->tid ) {
402
 		if ( tftp->tid != st_src->st_port ) {
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
 			return -EINVAL;
418
 			return -EINVAL;
407
 		}
419
 		}
408
 	} else {
420
 	} else {
409
 		tftp->tid = st_src->st_port;
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
 		udp_connect_port ( &tftp->udp, tftp->tid );
424
 		udp_connect_port ( &tftp->udp, tftp->tid );
413
 	}
425
 	}
414
 
426
 
415
 	/* Filter by source address */
427
 	/* Filter by source address */
416
 	if ( memcmp ( st_src, udp_peer ( &tftp->udp ),
428
 	if ( memcmp ( st_src, udp_peer ( &tftp->udp ),
417
 		      sizeof ( *st_src ) ) != 0 ) {
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
 		return -EINVAL;
432
 		return -EINVAL;
420
 	}
433
 	}
421
 
434
 
427
 	case htons ( TFTP_ERROR ):
440
 	case htons ( TFTP_ERROR ):
428
 		return tftp_rx_error ( tftp, data, len );
441
 		return tftp_rx_error ( tftp, data, len );
429
 	default:
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
 		return -EINVAL;
445
 		return -EINVAL;
433
 	};
446
 	};
434
 }
447
 }
449
 	int rc;
462
 	int rc;
450
 
463
 
451
 	assert ( tftp->filename != NULL );
464
 	assert ( tftp->filename != NULL );
452
-	assert ( tftp->callback != NULL );
465
+	assert ( tftp->buffer != NULL );
453
 	assert ( tftp->udp.peer.st_family != 0 );
466
 	assert ( tftp->udp.peer.st_family != 0 );
454
 
467
 
455
 	/* Initialise TFTP session */
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
 	if ( ! tftp->request_blksize )
469
 	if ( ! tftp->request_blksize )
461
 		tftp->request_blksize = TFTP_MAX_BLKSIZE;
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
 	/* Open UDP connection */
478
 	/* Open UDP connection */
464
 	if ( ( rc = udp_open ( &tftp->udp, 0 ) ) != 0 ) {
479
 	if ( ( rc = udp_open ( &tftp->udp, 0 ) ) != 0 ) {

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

5
 #include <gpxe/tftp.h>
5
 #include <gpxe/tftp.h>
6
 #include <gpxe/async.h>
6
 #include <gpxe/async.h>
7
 #include <gpxe/uaccess.h>
7
 #include <gpxe/uaccess.h>
8
+#include <gpxe/buffer.h>
8
 #include "pxe.h"
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
 int test_tftp ( struct net_device *netdev, struct sockaddr_tcpip *target,
11
 int test_tftp ( struct net_device *netdev, struct sockaddr_tcpip *target,
19
 		const char *filename ) {
12
 		const char *filename ) {
20
 	struct tftp_session tftp;
13
 	struct tftp_session tftp;
14
+	struct buffer buffer;
21
 	int rc;
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
 	memset ( &tftp, 0, sizeof ( tftp ) );
21
 	memset ( &tftp, 0, sizeof ( tftp ) );
24
 	udp_connect ( &tftp.udp, target );
22
 	udp_connect ( &tftp.udp, target );
25
 	tftp.filename = filename;
23
 	tftp.filename = filename;
26
-	tftp.callback = test_tftp_callback;
24
+	tftp.buffer = &buffer;
27
 
25
 
28
 	printf ( "Fetching \"%s\" via TFTP\n", filename );
26
 	printf ( "Fetching \"%s\" via TFTP\n", filename );
29
 	if ( ( rc = async_wait ( tftp_get ( &tftp ) ) ) != 0 )
27
 	if ( ( rc = async_wait ( tftp_get ( &tftp ) ) ) != 0 )

Loading…
Cancel
Save