From d1a123b1f4f265aa415d647212c64fb02d47e208 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 9 Aug 2006 00:09:29 +0000 Subject: [PATCH] Added TFTP test code (currently just dumps file to console). --- src/include/gpxe/tftp.h | 10 ++++++++++ src/net/udp/tftp.c | 9 ++++++--- src/tests/dhcptest.c | 18 ++++++++++++++++-- src/tests/tftptest.c | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 src/tests/tftptest.c diff --git a/src/include/gpxe/tftp.h b/src/include/gpxe/tftp.h index e5c599bc..68589b52 100644 --- a/src/include/gpxe/tftp.h +++ b/src/include/gpxe/tftp.h @@ -119,6 +119,12 @@ struct tftp_session { * (i.e. that no blocks have yet been received). */ int state; + /** Requested data block size + * + * This is the "blksize" option requested from the TFTP + * server. It may or may not be honoured. + */ + unsigned int request_blksize; /** Data block size * * This is the "blksize" option negotiated with the TFTP @@ -140,4 +146,8 @@ struct tftp_session { struct retry_timer timer; }; +/* Function prototypes */ + +extern struct async_operation * tftp_get ( struct tftp_session *tftp ); + #endif /* _GPXE_TFTP_H */ diff --git a/src/net/udp/tftp.c b/src/net/udp/tftp.c index 39839bea..2b00cd78 100644 --- a/src/net/udp/tftp.c +++ b/src/net/udp/tftp.c @@ -207,9 +207,10 @@ static int tftp_send_rrq ( struct tftp_session *tftp, void *buf, size_t len ) { end = ( buf + len ); if ( data > end ) goto overflow; - data += snprintf ( data, ( end - data ), - "%s%coctet%cblksize%c%d%ctsize%c0", - tftp->filename, 0, 0, 0, tftp->blksize, 0, 0 ) + 1; + data += ( snprintf ( data, ( end - data ), + "%s%coctet%cblksize%c%d%ctsize%c0", + tftp->filename, 0, 0, 0, + tftp->request_blksize, 0, 0 ) + 1 ); if ( data > end ) goto overflow; rrq->opcode = htons ( TFTP_RRQ ); @@ -456,6 +457,8 @@ struct async_operation * tftp_get ( struct tftp_session *tftp ) { tftp->timer.expired = tftp_timer_expired; tftp->state = -1; tftp->blksize = TFTP_DEFAULT_BLKSIZE; + if ( ! tftp->request_blksize ) + tftp->request_blksize = TFTP_MAX_BLKSIZE; /* Open UDP connection */ if ( ( rc = udp_open ( &tftp->udp, 0 ) ) != 0 ) { diff --git a/src/tests/dhcptest.c b/src/tests/dhcptest.c index 4bb2e11e..2afe6faf 100644 --- a/src/tests/dhcptest.c +++ b/src/tests/dhcptest.c @@ -57,6 +57,21 @@ static int test_dhcp_hello ( char *helloname ) { return 0; } +static int test_dhcp_tftp ( char *tftpname ) { + union { + struct sockaddr_in sin; + struct sockaddr_tcpip st; + } target; + + memset ( &target, 0, sizeof ( target ) ); + target.sin.sin_family = AF_INET; + target.sin.sin_port = htons ( 69 ); + find_global_dhcp_ipv4_option ( DHCP_EB_SIADDR, + &target.sin.sin_addr ); + + return test_tftp ( &target.st, tftpname ); +} + static int test_dhcp_boot ( struct net_device *netdev, char *filename ) { if ( strncmp ( filename, "aoe:", 4 ) == 0 ) { return test_dhcp_aoe_boot ( netdev, &filename[4] ); @@ -65,8 +80,7 @@ static int test_dhcp_boot ( struct net_device *netdev, char *filename ) { } else if ( strncmp ( filename, "hello:", 6 ) == 0 ) { return test_dhcp_hello ( &filename[6] ); } else { - printf ( "Don't know how to boot %s\n", filename ); - return -EPROTONOSUPPORT; + return test_dhcp_tftp ( filename ); } } diff --git a/src/tests/tftptest.c b/src/tests/tftptest.c new file mode 100644 index 00000000..ba4c5d0f --- /dev/null +++ b/src/tests/tftptest.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include +#include + +static void test_tftp_callback ( struct tftp_session *tftp __unused, + unsigned int block __unused, + void *data, size_t len ) { + unsigned int i; + char c; + + for ( i = 0 ; i < len ; i++ ) { + c = * ( ( char * ) data + i ); + if ( c == '\r' ) { + /* Print nothing */ + } else if ( ( c == '\n' ) || ( c >= 32 ) || ( c <= 126 ) ) { + putchar ( c ); + } else { + putchar ( '.' ); + } + } +} + +int test_tftp ( struct sockaddr_tcpip *target, const char *filename ) { + struct tftp_session tftp; + + memset ( &tftp, 0, sizeof ( tftp ) ); + udp_connect ( &tftp.udp, target ); + tftp.filename = filename; + tftp.callback = test_tftp_callback; + + return async_wait ( tftp_get ( &tftp ) ); +}