diff options
Diffstat (limited to 'gpxe/src/net/tcp')
-rw-r--r-- | gpxe/src/net/tcp/ftp.c | 30 | ||||
-rw-r--r-- | gpxe/src/net/tcp/http.c | 64 | ||||
-rw-r--r-- | gpxe/src/net/tcp/https.c | 2 | ||||
-rw-r--r-- | gpxe/src/net/tcp/iscsi.c | 79 |
4 files changed, 88 insertions, 87 deletions
diff --git a/gpxe/src/net/tcp/ftp.c b/gpxe/src/net/tcp/ftp.c index 445e32bb..920e537a 100644 --- a/gpxe/src/net/tcp/ftp.c +++ b/gpxe/src/net/tcp/ftp.c @@ -131,11 +131,33 @@ static const char * ftp_uri_path ( struct ftp_request *ftp ) { return ftp->uri->path; } +/** + * Retrieve FTP user + * + * @v ftp FTP request + * @ret user FTP user + */ +static const char * ftp_user ( struct ftp_request *ftp ) { + static char *ftp_default_user = "anonymous"; + return ftp->uri->user ? ftp->uri->user : ftp_default_user; +} + +/** + * Retrieve FTP password + * + * @v ftp FTP request + * @ret password FTP password + */ +static const char * ftp_password ( struct ftp_request *ftp ) { + static char *ftp_default_password = "etherboot@etherboot.org"; + return ftp->uri->password ? ftp->uri->password : ftp_default_password; +} + /** FTP control channel strings */ static struct ftp_control_string ftp_strings[] = { [FTP_CONNECT] = { NULL, NULL }, - [FTP_USER] = { "USER anonymous", NULL }, - [FTP_PASS] = { "PASS etherboot@etherboot.org", NULL }, + [FTP_USER] = { "USER ", ftp_user }, + [FTP_PASS] = { "PASS ", ftp_password }, [FTP_TYPE] = { "TYPE I", NULL }, [FTP_PASV] = { "PASV", NULL }, [FTP_RETR] = { "RETR ", ftp_uri_path }, @@ -335,7 +357,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 +424,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/gpxe/src/net/tcp/http.c b/gpxe/src/net/tcp/http.c index 93ccfd3b..a365b2a4 100644 --- a/gpxe/src/net/tcp/http.c +++ b/gpxe/src/net/tcp/http.c @@ -16,6 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +FILE_LICENCE ( GPL2_OR_LATER ); + /** * @file * @@ -138,6 +140,8 @@ static void http_done ( struct http_request *http, int rc ) { static int http_response_to_rc ( unsigned int response ) { switch ( response ) { case 200: + case 301: + case 302: return 0; case 404: return -ENOENT; @@ -181,6 +185,28 @@ static int http_rx_response ( struct http_request *http, char *response ) { } /** + * Handle HTTP Location header + * + * @v http HTTP request + * @v value HTTP header value + * @ret rc Return status code + */ +static int http_rx_location ( struct http_request *http, const char *value ) { + int rc; + + /* Redirect to new location */ + DBGC ( http, "HTTP %p redirecting to %s\n", http, value ); + if ( ( rc = xfer_redirect ( &http->xfer, LOCATION_URI_STRING, + value ) ) != 0 ) { + DBGC ( http, "HTTP %p could not redirect: %s\n", + http, strerror ( rc ) ); + return rc; + } + + return 0; +} + +/** * Handle HTTP Content-Length header * * @v http HTTP request @@ -223,6 +249,10 @@ struct http_header_handler { /** List of HTTP header handlers */ static struct http_header_handler http_header_handlers[] = { { + .header = "Location", + .rx = http_rx_location, + }, + { .header = "Content-Length", .rx = http_rx_content_length, }, @@ -387,9 +417,7 @@ static int http_socket_deliver_iob ( struct xfer_interface *socket, static void http_step ( struct process *process ) { struct http_request *http = container_of ( process, struct http_request, process ); - const char *path = http->uri->path; const char *host = http->uri->host; - const char *query = http->uri->query; const char *user = http->uri->user; const char *password = ( http->uri->password ? http->uri->password : "" ); @@ -399,27 +427,24 @@ static void http_step ( struct process *process ) { char user_pw[ user_pw_len + 1 /* NUL */ ]; char user_pw_base64[ user_pw_base64_len + 1 /* NUL */ ]; int rc; + int request_len = unparse_uri ( NULL, 0, http->uri, + URI_PATH_BIT | URI_QUERY_BIT ); if ( xfer_window ( &http->socket ) ) { + char request[request_len + 1]; + + /* Construct path?query request */ + unparse_uri ( request, sizeof ( request ), http->uri, + URI_PATH_BIT | URI_QUERY_BIT ); /* We want to execute only once */ process_del ( &http->process ); /* Construct authorisation, if applicable */ if ( user ) { - char *buf = user_pw; - ssize_t remaining = sizeof ( user_pw ); - size_t len; - - /* URI-decode the username and password */ - len = uri_decode ( user, buf, remaining ); - buf += len; - remaining -= len; - *(remaining--, buf++) = ':'; - len = uri_decode ( password, buf, remaining ); - buf += len; - remaining -= len; - assert ( remaining >= 0 ); + /* Make "user:password" string from decoded fields */ + snprintf ( user_pw, sizeof ( user_pw ), "%s:%s", + user, password ); /* Base64-encode the "user:password" string */ base64_encode ( user_pw, user_pw_base64 ); @@ -427,14 +452,13 @@ static void http_step ( struct process *process ) { /* Send GET request */ if ( ( rc = xfer_printf ( &http->socket, - "GET %s%s%s HTTP/1.0\r\n" + "GET %s%s HTTP/1.0\r\n" "User-Agent: gPXE/" VERSION "\r\n" "%s%s%s" "Host: %s\r\n" "\r\n", - ( path ? path : "/" ), - ( query ? "?" : "" ), - ( query ? query : "" ), + http->uri->path ? "" : "/", + request, ( user ? "Authorization: Basic " : "" ), ( user ? user_pw_base64 : "" ), @@ -464,7 +488,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/gpxe/src/net/tcp/https.c b/gpxe/src/net/tcp/https.c index 15ab32ef..7a2961f2 100644 --- a/gpxe/src/net/tcp/https.c +++ b/gpxe/src/net/tcp/https.c @@ -16,6 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +FILE_LICENCE ( GPL2_OR_LATER ); + /** * @file * diff --git a/gpxe/src/net/tcp/iscsi.c b/gpxe/src/net/tcp/iscsi.c index 45519e66..771384b9 100644 --- a/gpxe/src/net/tcp/iscsi.c +++ b/gpxe/src/net/tcp/iscsi.c @@ -16,6 +16,8 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +FILE_LICENCE ( GPL2_OR_LATER ); + #include <stddef.h> #include <string.h> #include <stdlib.h> @@ -180,9 +182,10 @@ static void iscsi_close_connection ( struct iscsi_session *iscsi, int rc ) { static void iscsi_scsi_done ( struct iscsi_session *iscsi, int rc ) { assert ( iscsi->tx_state == ISCSI_TX_IDLE ); + assert ( iscsi->command != NULL ); + iscsi->command->rc = rc; iscsi->command = NULL; - iscsi->rc = rc; } /**************************************************************************** @@ -1514,7 +1517,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 ); } @@ -1548,37 +1551,24 @@ static int iscsi_command ( struct scsi_device *scsi, container_of ( scsi->backend, struct iscsi_session, refcnt ); int rc; + /* Abort immediately if we have a recorded permanent failure */ + if ( iscsi->instant_rc ) + return iscsi->instant_rc; + /* Record SCSI command */ iscsi->command = command; - /* Abort immediately if we have a recorded permanent failure */ - if ( iscsi->instant_rc ) { - rc = iscsi->instant_rc; - goto done; - } - /* Issue command or open connection as appropriate */ if ( iscsi->status ) { iscsi_start_command ( iscsi ); } else { - if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) - goto done; + if ( ( rc = iscsi_open_connection ( iscsi ) ) != 0 ) { + iscsi->command = NULL; + return rc; + } } - /* Wait for command to complete */ - iscsi->rc = -EINPROGRESS; - while ( iscsi->rc == -EINPROGRESS ) - step(); - rc = iscsi->rc; - - done: - iscsi->command = NULL; - return rc; -} - -static int iscsi_detached_command ( struct scsi_device *scsi __unused, - struct scsi_command *command __unused ) { - return -ENODEV; + return 0; } /** @@ -1593,7 +1583,7 @@ void iscsi_detach ( struct scsi_device *scsi ) { xfer_nullify ( &iscsi->socket ); iscsi_close_connection ( iscsi, 0 ); process_del ( &iscsi->process ); - scsi->command = iscsi_detached_command; + scsi->command = scsi_detached_command; ref_put ( scsi->backend ); scsi->backend = NULL; } @@ -1616,42 +1606,6 @@ enum iscsi_root_path_component { }; /** - * Parse iSCSI LUN - * - * @v iscsi iSCSI session - * @v lun_string LUN string representation (as per RFC4173) - * @ret rc Return status code - */ -static int iscsi_parse_lun ( struct iscsi_session *iscsi, - const char *lun_string ) { - union { - uint64_t u64; - uint16_t u16[4]; - } lun; - char *p; - int i; - - memset ( &lun, 0, sizeof ( lun ) ); - if ( lun_string ) { - p = ( char * ) lun_string; - - for ( i = 0 ; i < 4 ; i++ ) { - lun.u16[i] = htons ( strtoul ( p, &p, 16 ) ); - if ( *p == '\0' ) - break; - if ( *p != '-' ) - return -EINVAL; - p++; - } - if ( *p ) - return -EINVAL; - } - - iscsi->lun = lun.u64; - return 0; -} - -/** * Parse iSCSI root path * * @v iscsi iSCSI session @@ -1689,7 +1643,7 @@ static int iscsi_parse_root_path ( struct iscsi_session *iscsi, iscsi->target_port = strtoul ( rp_comp[RP_PORT], NULL, 10 ); if ( ! iscsi->target_port ) iscsi->target_port = ISCSI_PORT; - if ( ( rc = iscsi_parse_lun ( iscsi, rp_comp[RP_LUN] ) ) != 0 ) { + if ( ( rc = scsi_parse_lun ( rp_comp[RP_LUN], &iscsi->lun ) ) != 0 ) { DBGC ( iscsi, "iSCSI %p invalid LUN \"%s\"\n", iscsi, rp_comp[RP_LUN] ); return rc; @@ -1809,7 +1763,6 @@ int iscsi_attach ( struct scsi_device *scsi, const char *root_path ) { /* Attach parent interface, mortalise self, and return */ scsi->backend = ref_get ( &iscsi->refcnt ); scsi->command = iscsi_command; - scsi->lun = iscsi->lun; ref_put ( &iscsi->refcnt ); return 0; |