mirror of
https://github.com/ipxe/ipxe
synced 2026-02-14 02:31:26 +03:00
[image] Add "--timeout" parameter to image downloading commands
iPXE will detect timeout failures in several situations: network link-up, DHCP, TCP connection attempts, unacknowledged TCP data, etc. This does not cover all possible circumstances. For example, if a connection to a web server is successfully established and the web server acknowledges the HTTP request but never sends any data in response, then no timeout will be triggered. There is no timeout defined within the HTTP specifications, and the underlying TCP connection will not generate a timeout since it has no way to know that the HTTP layer is expecting to receive data from the server. Add a "--timeout" parameter to "imgfetch", "chain", etc. If no progress is made (i.e. no data is downloaded) within the timeout period, then the download will be aborted. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -188,7 +188,8 @@ static int comboot_fetch_kernel ( char *kernel_file, char *cmdline ) {
|
|||||||
DBG ( "COMBOOT: fetching initrd '%s'\n", initrd_file );
|
DBG ( "COMBOOT: fetching initrd '%s'\n", initrd_file );
|
||||||
|
|
||||||
/* Fetch initrd */
|
/* Fetch initrd */
|
||||||
if ( ( rc = imgdownload_string ( initrd_file, &initrd ) ) != 0){
|
if ( ( rc = imgdownload_string ( initrd_file, 0,
|
||||||
|
&initrd ) ) != 0 ) {
|
||||||
DBG ( "COMBOOT: could not fetch initrd: %s\n",
|
DBG ( "COMBOOT: could not fetch initrd: %s\n",
|
||||||
strerror ( rc ) );
|
strerror ( rc ) );
|
||||||
return rc;
|
return rc;
|
||||||
@@ -202,7 +203,7 @@ static int comboot_fetch_kernel ( char *kernel_file, char *cmdline ) {
|
|||||||
DBG ( "COMBOOT: fetching kernel '%s'\n", kernel_file );
|
DBG ( "COMBOOT: fetching kernel '%s'\n", kernel_file );
|
||||||
|
|
||||||
/* Fetch kernel */
|
/* Fetch kernel */
|
||||||
if ( ( rc = imgdownload_string ( kernel_file, &kernel ) ) != 0 ) {
|
if ( ( rc = imgdownload_string ( kernel_file, 0, &kernel ) ) != 0 ) {
|
||||||
DBG ( "COMBOOT: could not fetch kernel: %s\n",
|
DBG ( "COMBOOT: could not fetch kernel: %s\n",
|
||||||
strerror ( rc ) );
|
strerror ( rc ) );
|
||||||
return rc;
|
return rc;
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ static int console_exec ( int argc, char **argv ) {
|
|||||||
if ( opts.picture ) {
|
if ( opts.picture ) {
|
||||||
|
|
||||||
/* Acquire image */
|
/* Acquire image */
|
||||||
if ( ( rc = imgacquire ( opts.picture, &image ) ) != 0 )
|
if ( ( rc = imgacquire ( opts.picture, 0, &image ) ) != 0 )
|
||||||
goto err_acquire;
|
goto err_acquire;
|
||||||
|
|
||||||
/* Convert to pixel buffer */
|
/* Convert to pixel buffer */
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ static int digest_exec ( int argc, char **argv,
|
|||||||
for ( i = optind ; i < argc ; i++ ) {
|
for ( i = optind ; i < argc ; i++ ) {
|
||||||
|
|
||||||
/* Acquire image */
|
/* Acquire image */
|
||||||
if ( ( rc = imgacquire ( argv[i], &image ) ) != 0 )
|
if ( ( rc = imgacquire ( argv[i], 0, &image ) ) != 0 )
|
||||||
continue;
|
continue;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
len = image->len;
|
len = image->len;
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
|||||||
struct imgsingle_options {
|
struct imgsingle_options {
|
||||||
/** Image name */
|
/** Image name */
|
||||||
char *name;
|
char *name;
|
||||||
|
/** Download timeout */
|
||||||
|
unsigned long timeout;
|
||||||
/** Replace image */
|
/** Replace image */
|
||||||
int replace;
|
int replace;
|
||||||
/** Free image after execution */
|
/** Free image after execution */
|
||||||
@@ -49,13 +51,17 @@ struct imgsingle_options {
|
|||||||
/** "img{single}" option list */
|
/** "img{single}" option list */
|
||||||
static union {
|
static union {
|
||||||
/* "imgexec" takes all three options */
|
/* "imgexec" takes all three options */
|
||||||
struct option_descriptor imgexec[3];
|
struct option_descriptor imgexec[4];
|
||||||
/* Other "img{single}" commands take only --name and --autofree */
|
/* Other "img{single}" commands take only --name, --timeout,
|
||||||
struct option_descriptor imgsingle[2];
|
* and --autofree
|
||||||
|
*/
|
||||||
|
struct option_descriptor imgsingle[3];
|
||||||
} opts = {
|
} opts = {
|
||||||
.imgexec = {
|
.imgexec = {
|
||||||
OPTION_DESC ( "name", 'n', required_argument,
|
OPTION_DESC ( "name", 'n', required_argument,
|
||||||
struct imgsingle_options, name, parse_string ),
|
struct imgsingle_options, name, parse_string ),
|
||||||
|
OPTION_DESC ( "timeout", 't', required_argument,
|
||||||
|
struct imgsingle_options, timeout, parse_timeout),
|
||||||
OPTION_DESC ( "autofree", 'a', no_argument,
|
OPTION_DESC ( "autofree", 'a', no_argument,
|
||||||
struct imgsingle_options, autofree, parse_flag ),
|
struct imgsingle_options, autofree, parse_flag ),
|
||||||
OPTION_DESC ( "replace", 'r', no_argument,
|
OPTION_DESC ( "replace", 'r', no_argument,
|
||||||
@@ -68,7 +74,8 @@ struct imgsingle_descriptor {
|
|||||||
/** Command descriptor */
|
/** Command descriptor */
|
||||||
struct command_descriptor *cmd;
|
struct command_descriptor *cmd;
|
||||||
/** Function to use to acquire the image */
|
/** Function to use to acquire the image */
|
||||||
int ( * acquire ) ( const char *name, struct image **image );
|
int ( * acquire ) ( const char *name, unsigned long timeout,
|
||||||
|
struct image **image );
|
||||||
/** Pre-action to take upon image, or NULL */
|
/** Pre-action to take upon image, or NULL */
|
||||||
void ( * preaction ) ( struct image *image );
|
void ( * preaction ) ( struct image *image );
|
||||||
/** Action to take upon image, or NULL */
|
/** Action to take upon image, or NULL */
|
||||||
@@ -114,7 +121,8 @@ static int imgsingle_exec ( int argc, char **argv,
|
|||||||
|
|
||||||
/* Acquire the image */
|
/* Acquire the image */
|
||||||
if ( name_uri ) {
|
if ( name_uri ) {
|
||||||
if ( ( rc = desc->acquire ( name_uri, &image ) ) != 0 )
|
if ( ( rc = desc->acquire ( name_uri, opts.timeout,
|
||||||
|
&image ) ) != 0 )
|
||||||
goto err_acquire;
|
goto err_acquire;
|
||||||
} else {
|
} else {
|
||||||
image = image_find_selected();
|
image = image_find_selected();
|
||||||
|
|||||||
@@ -86,6 +86,8 @@ struct imgverify_options {
|
|||||||
char *signer;
|
char *signer;
|
||||||
/** Keep signature after verification */
|
/** Keep signature after verification */
|
||||||
int keep;
|
int keep;
|
||||||
|
/** Download timeout */
|
||||||
|
unsigned long timeout;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** "imgverify" option list */
|
/** "imgverify" option list */
|
||||||
@@ -94,6 +96,8 @@ static struct option_descriptor imgverify_opts[] = {
|
|||||||
struct imgverify_options, signer, parse_string ),
|
struct imgverify_options, signer, parse_string ),
|
||||||
OPTION_DESC ( "keep", 'k', no_argument,
|
OPTION_DESC ( "keep", 'k', no_argument,
|
||||||
struct imgverify_options, keep, parse_flag ),
|
struct imgverify_options, keep, parse_flag ),
|
||||||
|
OPTION_DESC ( "timeout", 't', required_argument,
|
||||||
|
struct imgverify_options, timeout, parse_timeout),
|
||||||
};
|
};
|
||||||
|
|
||||||
/** "imgverify" command descriptor */
|
/** "imgverify" command descriptor */
|
||||||
@@ -127,11 +131,12 @@ static int imgverify_exec ( int argc, char **argv ) {
|
|||||||
signature_name_uri = argv[ optind + 1 ];
|
signature_name_uri = argv[ optind + 1 ];
|
||||||
|
|
||||||
/* Acquire the image */
|
/* Acquire the image */
|
||||||
if ( ( rc = imgacquire ( image_name_uri, &image ) ) != 0 )
|
if ( ( rc = imgacquire ( image_name_uri, opts.timeout, &image ) ) != 0 )
|
||||||
goto err_acquire_image;
|
goto err_acquire_image;
|
||||||
|
|
||||||
/* Acquire the signature image */
|
/* Acquire the signature image */
|
||||||
if ( ( rc = imgacquire ( signature_name_uri, &signature ) ) != 0 )
|
if ( ( rc = imgacquire ( signature_name_uri, opts.timeout,
|
||||||
|
&signature ) ) != 0 )
|
||||||
goto err_acquire_signature;
|
goto err_acquire_signature;
|
||||||
|
|
||||||
/* Verify image */
|
/* Verify image */
|
||||||
|
|||||||
@@ -11,9 +11,12 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
|||||||
|
|
||||||
#include <ipxe/image.h>
|
#include <ipxe/image.h>
|
||||||
|
|
||||||
extern int imgdownload ( struct uri *uri, struct image **image );
|
extern int imgdownload ( struct uri *uri, unsigned long timeout,
|
||||||
extern int imgdownload_string ( const char *uri_string, struct image **image );
|
struct image **image );
|
||||||
extern int imgacquire ( const char *name, struct image **image );
|
extern int imgdownload_string ( const char *uri_string, unsigned long timeout,
|
||||||
|
struct image **image );
|
||||||
|
extern int imgacquire ( const char *name, unsigned long timeout,
|
||||||
|
struct image **image );
|
||||||
extern void imgstat ( struct image *image );
|
extern void imgstat ( struct image *image );
|
||||||
|
|
||||||
#endif /* _USR_IMGMGMT_H */
|
#endif /* _USR_IMGMGMT_H */
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ int uriboot ( struct uri *filename, struct uri *root_path, int drive,
|
|||||||
|
|
||||||
/* Attempt filename boot if applicable */
|
/* Attempt filename boot if applicable */
|
||||||
if ( filename ) {
|
if ( filename ) {
|
||||||
if ( ( rc = imgdownload ( filename, &image ) ) != 0 )
|
if ( ( rc = imgdownload ( filename, 0, &image ) ) != 0 )
|
||||||
goto err_download;
|
goto err_download;
|
||||||
image->flags |= IMAGE_AUTO_UNREGISTER;
|
image->flags |= IMAGE_AUTO_UNREGISTER;
|
||||||
if ( ( rc = image_exec ( image ) ) != 0 ) {
|
if ( ( rc = image_exec ( image ) ) != 0 ) {
|
||||||
|
|||||||
@@ -40,10 +40,12 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
|||||||
* Download a new image
|
* Download a new image
|
||||||
*
|
*
|
||||||
* @v uri URI
|
* @v uri URI
|
||||||
|
* @v timeout Download timeout
|
||||||
* @v image Image to fill in
|
* @v image Image to fill in
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
int imgdownload ( struct uri *uri, struct image **image ) {
|
int imgdownload ( struct uri *uri, unsigned long timeout,
|
||||||
|
struct image **image ) {
|
||||||
const char *password;
|
const char *password;
|
||||||
char *uri_string_redacted;
|
char *uri_string_redacted;
|
||||||
int rc;
|
int rc;
|
||||||
@@ -80,7 +82,7 @@ int imgdownload ( struct uri *uri, struct image **image ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for download to complete */
|
/* Wait for download to complete */
|
||||||
if ( ( rc = monojob_wait ( uri_string_redacted, 0 ) ) != 0 )
|
if ( ( rc = monojob_wait ( uri_string_redacted, timeout ) ) != 0 )
|
||||||
goto err_monojob_wait;
|
goto err_monojob_wait;
|
||||||
|
|
||||||
/* Register image */
|
/* Register image */
|
||||||
@@ -105,17 +107,19 @@ int imgdownload ( struct uri *uri, struct image **image ) {
|
|||||||
* Download a new image
|
* Download a new image
|
||||||
*
|
*
|
||||||
* @v uri_string URI string
|
* @v uri_string URI string
|
||||||
|
* @v timeout Download timeout
|
||||||
* @v image Image to fill in
|
* @v image Image to fill in
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
int imgdownload_string ( const char *uri_string, struct image **image ) {
|
int imgdownload_string ( const char *uri_string, unsigned long timeout,
|
||||||
|
struct image **image ) {
|
||||||
struct uri *uri;
|
struct uri *uri;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if ( ! ( uri = parse_uri ( uri_string ) ) )
|
if ( ! ( uri = parse_uri ( uri_string ) ) )
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
rc = imgdownload ( uri, image );
|
rc = imgdownload ( uri, timeout, image );
|
||||||
|
|
||||||
uri_put ( uri );
|
uri_put ( uri );
|
||||||
return rc;
|
return rc;
|
||||||
@@ -125,10 +129,12 @@ int imgdownload_string ( const char *uri_string, struct image **image ) {
|
|||||||
* Acquire an image
|
* Acquire an image
|
||||||
*
|
*
|
||||||
* @v name_uri Name or URI string
|
* @v name_uri Name or URI string
|
||||||
|
* @v timeout Download timeout
|
||||||
* @v image Image to fill in
|
* @v image Image to fill in
|
||||||
* @ret rc Return status code
|
* @ret rc Return status code
|
||||||
*/
|
*/
|
||||||
int imgacquire ( const char *name_uri, struct image **image ) {
|
int imgacquire ( const char *name_uri, unsigned long timeout,
|
||||||
|
struct image **image ) {
|
||||||
|
|
||||||
/* If we already have an image with the specified name, use it */
|
/* If we already have an image with the specified name, use it */
|
||||||
*image = find_image ( name_uri );
|
*image = find_image ( name_uri );
|
||||||
@@ -136,7 +142,7 @@ int imgacquire ( const char *name_uri, struct image **image ) {
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Otherwise, download a new image */
|
/* Otherwise, download a new image */
|
||||||
return imgdownload_string ( name_uri, image );
|
return imgdownload_string ( name_uri, timeout, image );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user