aboutsummaryrefslogtreecommitdiffstats
path: root/gpxe/src/net/tcp
diff options
context:
space:
mode:
Diffstat (limited to 'gpxe/src/net/tcp')
-rw-r--r--gpxe/src/net/tcp/ftp.c30
-rw-r--r--gpxe/src/net/tcp/http.c64
-rw-r--r--gpxe/src/net/tcp/https.c2
-rw-r--r--gpxe/src/net/tcp/iscsi.c79
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;