From 323cdf8c4c510fc6da081b96994d0131c11a29dd Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 30 Mar 2009 13:24:56 +0100 Subject: [PATCH] [xfer] Implement xfer_vreopen() to properly handle redirections When handling a redirection event, we need to close the existing connection before opening the new connection. --- src/arch/i386/interface/pxe/pxe_tftp.c | 2 +- src/core/downloader.c | 2 +- src/core/open.c | 28 ++++++++++++++++++++++++++ src/core/posix_io.c | 2 +- src/include/gpxe/open.h | 2 ++ src/net/tcp/ftp.c | 4 ++-- src/net/tcp/http.c | 2 +- src/net/tcp/iscsi.c | 2 +- src/net/tls.c | 2 +- src/net/udp/dhcp.c | 2 +- src/net/udp/dns.c | 2 +- src/net/udp/slam.c | 4 ++-- src/net/udp/tftp.c | 4 ++-- 13 files changed, 44 insertions(+), 14 deletions(-) diff --git a/src/arch/i386/interface/pxe/pxe_tftp.c b/src/arch/i386/interface/pxe/pxe_tftp.c index 715a0b61..cc7f830a 100644 --- a/src/arch/i386/interface/pxe/pxe_tftp.c +++ b/src/arch/i386/interface/pxe/pxe_tftp.c @@ -138,7 +138,7 @@ static void pxe_tftp_xfer_close ( struct xfer_interface *xfer __unused, static struct xfer_interface_operations pxe_tftp_xfer_ops = { .close = pxe_tftp_xfer_close, - .vredirect = xfer_vopen, + .vredirect = xfer_vreopen, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = pxe_tftp_xfer_deliver_iob, diff --git a/src/core/downloader.c b/src/core/downloader.c index 0a443db2..83027d38 100644 --- a/src/core/downloader.c +++ b/src/core/downloader.c @@ -205,7 +205,7 @@ static void downloader_xfer_close ( struct xfer_interface *xfer, int rc ) { /** Downloader data transfer interface operations */ static struct xfer_interface_operations downloader_xfer_operations = { .close = downloader_xfer_close, - .vredirect = xfer_vopen, + .vredirect = xfer_vreopen, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = downloader_xfer_deliver_iob, diff --git a/src/core/open.c b/src/core/open.c index 89a96d72..beb67a03 100644 --- a/src/core/open.c +++ b/src/core/open.c @@ -53,6 +53,8 @@ int xfer_open_uri ( struct xfer_interface *xfer, struct uri *uri ) { /* Find opener which supports this URI scheme */ for_each_table_entry ( opener, URI_OPENERS ) { if ( strcmp ( resolved_uri->scheme, opener->scheme ) == 0 ) { + DBGC ( xfer, "XFER %p opening %s URI\n", + xfer, opener->scheme ); rc = opener->open ( xfer, resolved_uri ); goto done; } @@ -170,3 +172,29 @@ int xfer_open ( struct xfer_interface *xfer, int type, ... ) { va_end ( args ); return rc; } + +/** + * Reopen location + * + * @v xfer Data transfer interface + * @v type Location type + * @v args Remaining arguments depend upon location type + * @ret rc Return status code + * + * This will close the existing connection and open a new connection + * using xfer_vopen(). It is intended to be used as a .vredirect + * method handler. + */ +int xfer_vreopen ( struct xfer_interface *xfer, int type, va_list args ) { + struct xfer_interface_operations *op = xfer->op; + + /* Close existing connection */ + xfer_nullify ( xfer ); + xfer_close ( xfer, 0 ); + + /* Restore to operational status */ + xfer->op = op; + + /* Open new location */ + return xfer_vopen ( xfer, type, args ); +} diff --git a/src/core/posix_io.c b/src/core/posix_io.c index e0459bdf..6f6d815a 100644 --- a/src/core/posix_io.c +++ b/src/core/posix_io.c @@ -137,7 +137,7 @@ posix_file_xfer_deliver_iob ( struct xfer_interface *xfer, /** POSIX file data transfer interface operations */ static struct xfer_interface_operations posix_file_xfer_operations = { .close = posix_file_xfer_close, - .vredirect = xfer_vopen, + .vredirect = xfer_vreopen, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = posix_file_xfer_deliver_iob, diff --git a/src/include/gpxe/open.h b/src/include/gpxe/open.h index 61fb0ef5..136ff87f 100644 --- a/src/include/gpxe/open.h +++ b/src/include/gpxe/open.h @@ -97,5 +97,7 @@ extern int xfer_open_socket ( struct xfer_interface *xfer, int semantics, struct sockaddr *peer, struct sockaddr *local ); extern int xfer_vopen ( struct xfer_interface *xfer, int type, va_list args ); extern int xfer_open ( struct xfer_interface *xfer, int type, ... ); +extern int xfer_vreopen ( struct xfer_interface *xfer, int type, + va_list args ); #endif /* _GPXE_OPEN_H */ diff --git a/src/net/tcp/ftp.c b/src/net/tcp/ftp.c index 445e32bb..0719bf72 100644 --- a/src/net/tcp/ftp.c +++ b/src/net/tcp/ftp.c @@ -335,7 +335,7 @@ static int ftp_control_deliver_raw ( struct xfer_interface *control, /** FTP control channel operations */ static struct xfer_interface_operations ftp_control_operations = { .close = ftp_control_close, - .vredirect = xfer_vopen, + .vredirect = xfer_vreopen, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = xfer_deliver_as_raw, @@ -402,7 +402,7 @@ static int ftp_data_deliver_iob ( struct xfer_interface *data, /** FTP data channel operations */ static struct xfer_interface_operations ftp_data_operations = { .close = ftp_data_closed, - .vredirect = xfer_vopen, + .vredirect = xfer_vreopen, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = ftp_data_deliver_iob, diff --git a/src/net/tcp/http.c b/src/net/tcp/http.c index 93ccfd3b..b7cbea46 100644 --- a/src/net/tcp/http.c +++ b/src/net/tcp/http.c @@ -464,7 +464,7 @@ static void http_socket_close ( struct xfer_interface *socket, int rc ) { /** HTTP socket operations */ static struct xfer_interface_operations http_socket_operations = { .close = http_socket_close, - .vredirect = xfer_vopen, + .vredirect = xfer_vreopen, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = http_socket_deliver_iob, diff --git a/src/net/tcp/iscsi.c b/src/net/tcp/iscsi.c index 45519e66..51c2beea 100644 --- a/src/net/tcp/iscsi.c +++ b/src/net/tcp/iscsi.c @@ -1514,7 +1514,7 @@ static int iscsi_vredirect ( struct xfer_interface *socket, int type, va_end ( tmp ); } - return xfer_vopen ( socket, type, args ); + return xfer_vreopen ( socket, type, args ); } diff --git a/src/net/tls.c b/src/net/tls.c index 73f9ad06..25f18f79 100644 --- a/src/net/tls.c +++ b/src/net/tls.c @@ -1625,7 +1625,7 @@ static int tls_cipherstream_deliver_raw ( struct xfer_interface *xfer, /** TLS ciphertext stream operations */ static struct xfer_interface_operations tls_cipherstream_operations = { .close = tls_cipherstream_close, - .vredirect = xfer_vopen, + .vredirect = xfer_vreopen, .window = filter_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = xfer_deliver_as_raw, diff --git a/src/net/udp/dhcp.c b/src/net/udp/dhcp.c index 97e64617..289e41ad 100644 --- a/src/net/udp/dhcp.c +++ b/src/net/udp/dhcp.c @@ -1107,7 +1107,7 @@ static int dhcp_deliver_iob ( struct xfer_interface *xfer, /** DHCP data transfer interface operations */ static struct xfer_interface_operations dhcp_xfer_operations = { .close = ignore_xfer_close, - .vredirect = xfer_vopen, + .vredirect = xfer_vreopen, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = dhcp_deliver_iob, diff --git a/src/net/udp/dns.c b/src/net/udp/dns.c index a498aefc..c1da454b 100644 --- a/src/net/udp/dns.c +++ b/src/net/udp/dns.c @@ -459,7 +459,7 @@ static void dns_xfer_close ( struct xfer_interface *socket, int rc ) { /** DNS socket operations */ static struct xfer_interface_operations dns_socket_operations = { .close = dns_xfer_close, - .vredirect = xfer_vopen, + .vredirect = xfer_vreopen, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = xfer_deliver_as_raw, diff --git a/src/net/udp/slam.c b/src/net/udp/slam.c index 6add99bc..71043f45 100644 --- a/src/net/udp/slam.c +++ b/src/net/udp/slam.c @@ -614,7 +614,7 @@ static void slam_socket_close ( struct xfer_interface *socket, int rc ) { /** SLAM unicast socket data transfer operations */ static struct xfer_interface_operations slam_socket_operations = { .close = slam_socket_close, - .vredirect = xfer_vopen, + .vredirect = xfer_vreopen, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = slam_socket_deliver, @@ -640,7 +640,7 @@ static void slam_mc_socket_close ( struct xfer_interface *mc_socket, int rc ){ /** SLAM multicast socket data transfer operations */ static struct xfer_interface_operations slam_mc_socket_operations = { .close = slam_mc_socket_close, - .vredirect = xfer_vopen, + .vredirect = xfer_vreopen, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = slam_mc_socket_deliver, diff --git a/src/net/udp/tftp.c b/src/net/udp/tftp.c index 19525f79..be7e58af 100644 --- a/src/net/udp/tftp.c +++ b/src/net/udp/tftp.c @@ -934,7 +934,7 @@ static int tftp_socket_deliver_iob ( struct xfer_interface *socket, /** TFTP socket operations */ static struct xfer_interface_operations tftp_socket_operations = { .close = ignore_xfer_close, - .vredirect = xfer_vopen, + .vredirect = xfer_vreopen, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = tftp_socket_deliver_iob, @@ -961,7 +961,7 @@ static int tftp_mc_socket_deliver_iob ( struct xfer_interface *mc_socket, /** TFTP multicast socket operations */ static struct xfer_interface_operations tftp_mc_socket_operations = { .close = ignore_xfer_close, - .vredirect = xfer_vopen, + .vredirect = xfer_vreopen, .window = unlimited_xfer_window, .alloc_iob = default_xfer_alloc_iob, .deliver_iob = tftp_mc_socket_deliver_iob,