]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[params] Allow for arbitrary HTTP request headers to be specified
authorMichael Brown <mcb30@ipxe.org>
Tue, 28 Feb 2023 17:46:13 +0000 (17:46 +0000)
committerMichael Brown <mcb30@ipxe.org>
Wed, 1 Mar 2023 12:20:02 +0000 (12:20 +0000)
Extend the request parameter mechanism to allow for arbitrary HTTP
headers to be specified via e.g.:

  params
  param --header Referer http://www.example.com
  imgfetch http://192.168.0.1/script.ipxe##params

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/core/params.c
src/hci/commands/param_cmd.c
src/include/ipxe/params.h
src/net/tcp/httpcore.c
src/tests/uri_test.c

index 23206bef6f79d200a7e52415d28027f9ae7232a0..58c829f622b49ffb274d003822f982e71e29b099 100644 (file)
@@ -123,10 +123,12 @@ struct parameters * create_parameters ( const char *name ) {
  * @v params           Parameter list
  * @v key              Parameter key
  * @v value            Parameter value
+ * @v flags            Parameter flags
  * @ret param          Parameter, or NULL on failure
  */
 struct parameter * add_parameter ( struct parameters *params,
-                                  const char *key, const char *value ) {
+                                  const char *key, const char *value,
+                                  unsigned int flags ) {
        struct parameter *param;
        size_t key_len;
        size_t value_len;
@@ -147,11 +149,14 @@ struct parameter * add_parameter ( struct parameters *params,
        param->key = key_copy;
        strcpy ( value_copy, value );
        param->value = value_copy;
+       param->flags = flags;
 
        /* Add to list of parameters */
        list_add_tail ( &param->list, &params->entries );
 
-       DBGC ( params, "PARAMS \"%s\" added \"%s\"=\"%s\"\n",
-              params->name, param->key, param->value );
+       DBGC ( params, "PARAMS \"%s\" added \"%s\"=\"%s\"%s%s\n",
+              params->name, param->key, param->value,
+              ( ( param->flags & PARAMETER_FORM ) ? " (form)" : "" ),
+              ( ( param->flags & PARAMETER_HEADER ) ? " (header)" : "" ) );
        return param;
 }
index 9e3260de1a99e9461bb49a96ff99c94bc534d28c..dad99f8409814c78f0a0420a2b9654f58ff91119 100644 (file)
@@ -90,12 +90,16 @@ static int params_exec ( int argc, char **argv ) {
 struct param_options {
        /** Parameter list name */
        char *params;
+       /** Parameter is a header */
+       int header;
 };
 
 /** "param" option list */
 static struct option_descriptor param_opts[] = {
        OPTION_DESC ( "params", 'p', required_argument,
                      struct param_options, params, parse_string ),
+       OPTION_DESC ( "header", 'H', no_argument,
+                     struct param_options, header, parse_flag ),
 };
 
 /** "param" command descriptor */
@@ -114,6 +118,7 @@ static int param_exec ( int argc, char **argv ) {
        struct param_options opts;
        char *key;
        char *value;
+       unsigned int flags;
        struct parameters *params;
        struct parameter *param;
        int rc;
@@ -132,12 +137,15 @@ static int param_exec ( int argc, char **argv ) {
                goto err_parse_value;
        }
 
+       /* Construct flags */
+       flags = ( opts.header ? PARAMETER_HEADER : PARAMETER_FORM );
+
        /* Identify parameter list */
        if ( ( rc = parse_parameters ( opts.params, &params ) ) != 0 )
                goto err_parse_parameters;
 
        /* Add parameter */
-       param = add_parameter ( params, key, value );
+       param = add_parameter ( params, key, value, flags );
        if ( ! param ) {
                rc = -ENOMEM;
                goto err_add_parameter;
index 955f57acc6632bf4eb89f4cfd1ede20f1b3dd158..61e46e029c1a0229e6654ed7b8b026c155e6fac6 100644 (file)
@@ -32,8 +32,16 @@ struct parameter {
        const char *key;
        /** Value */
        const char *value;
+       /** Flags */
+       unsigned int flags;
 };
 
+/** Request parameter is a form parameter */
+#define PARAMETER_FORM 0x0001
+
+/** Request parameter is a header parameter */
+#define PARAMETER_HEADER 0x0002
+
 /**
  * Increment request parameter list reference count
  *
@@ -78,6 +86,7 @@ claim_parameters ( struct parameters *params ) {
 extern struct parameters * find_parameters ( const char *name );
 extern struct parameters * create_parameters ( const char *name );
 extern struct parameter * add_parameter ( struct parameters *params,
-                                         const char *key, const char *value );
+                                         const char *key, const char *value,
+                                         unsigned int flags );
 
 #endif /* _IPXE_PARAMS_H */
index c970d54bfa98965786820c947b57bd4ddeb67734..9ad39656d540f5ecd941aca38da18d1c8c1a3ad5 100644 (file)
@@ -830,7 +830,9 @@ static int http_transfer_complete ( struct http_transaction *http ) {
  */
 static int http_format_headers ( struct http_transaction *http, char *buf,
                                 size_t len ) {
+       struct parameters *params = http->uri->params;
        struct http_request_header *header;
+       struct parameter *param;
        size_t used;
        size_t remaining;
        char *line;
@@ -844,7 +846,7 @@ static int http_format_headers ( struct http_transaction *http, char *buf,
                DBGC2 ( http, "HTTP %p TX %s\n", http, buf );
        used += ssnprintf ( ( buf + used ), ( len - used ), "\r\n" );
 
-       /* Construct all headers */
+       /* Construct all fixed headers */
        for_each_table_entry ( header, HTTP_REQUEST_HEADERS ) {
 
                /* Determine header value length */
@@ -869,6 +871,23 @@ static int http_format_headers ( struct http_transaction *http, char *buf,
                used += ssnprintf ( ( buf + used ), ( len - used ), "\r\n" );
        }
 
+       /* Construct parameter headers, if any */
+       if ( params ) {
+
+               /* Construct all parameter headers */
+               for_each_param ( param, params ) {
+
+                       /* Skip non-header parameters */
+                       if ( ! ( param->flags & PARAMETER_HEADER ) )
+                               continue;
+
+                       /* Add parameter */
+                       used += ssnprintf ( ( buf + used ), ( len - used ),
+                                           "%s: %s\r\n", param->key,
+                                           param->value );
+               }
+       }
+
        /* Construct terminating newline */
        used += ssnprintf ( ( buf + used ), ( len - used ), "\r\n" );
 
@@ -1851,14 +1870,15 @@ static struct http_state http_trailers = {
  */
 
 /**
- * Construct HTTP parameter list
+ * Construct HTTP form parameter list
  *
  * @v params           Parameter list
  * @v buf              Buffer to contain HTTP POST parameters
  * @v len              Length of buffer
  * @ret len            Length of parameter list (excluding terminating NUL)
  */
-static size_t http_params ( struct parameters *params, char *buf, size_t len ) {
+static size_t http_form_params ( struct parameters *params, char *buf,
+                                size_t len ) {
        struct parameter *param;
        ssize_t remaining = len;
        size_t frag_len;
@@ -1867,6 +1887,10 @@ static size_t http_params ( struct parameters *params, char *buf, size_t len ) {
        len = 0;
        for_each_param ( param, params ) {
 
+               /* Skip non-form parameters */
+               if ( ! ( param->flags & PARAMETER_FORM ) )
+                       continue;
+
                /* Add the "&", if applicable */
                if ( len ) {
                        if ( remaining > 0 )
@@ -1920,25 +1944,26 @@ int http_open_uri ( struct interface *xfer, struct uri *uri ) {
        size_t check_len;
        int rc;
 
-       /* Calculate length of parameter list, if any */
-       len = ( params ? http_params ( params, NULL, 0 ) : 0 );
+       /* Calculate length of form parameter list, if any */
+       len = ( params ? http_form_params ( params, NULL, 0 ) : 0 );
 
-       /* Use POST if and only if there are parameters */
+       /* Use POST if and only if there are form parameters */
        if ( len ) {
 
                /* Use POST */
                method = &http_post;
                type = "application/x-www-form-urlencoded";
 
-               /* Allocate temporary parameter list */
+               /* Allocate temporary form parameter list */
                data = zalloc ( len + 1 /* NUL */ );
                if ( ! data ) {
                        rc = -ENOMEM;
                        goto err_alloc;
                }
 
-               /* Construct temporary parameter list */
-               check_len = http_params ( params, data, ( len + 1 /* NUL */ ) );
+               /* Construct temporary form parameter list */
+               check_len = http_form_params ( params, data,
+                                              ( len + 1 /* NUL */ ) );
                assert ( check_len == len );
 
        } else {
index 5e70603230a5b1b9875d5d2f00ef61ffe92dfa62..9d2f6dba5c068e8b40ff5178296f8cab77b81d45 100644 (file)
@@ -98,6 +98,8 @@ struct uri_params_test_list {
        const char *key;
        /** Value */
        const char *value;
+       /** Flags */
+       unsigned int flags;
 };
 
 /** A request parameter URI test */
@@ -428,6 +430,7 @@ static void uri_params_list_okx ( struct uri_params_test *test,
                              file, line );
                        okx ( strcmp ( param->value, list->value ) == 0,
                              file, line );
+                       okx ( param->flags == list->flags, file, line );
                        list++;
                }
                okx ( list->key == NULL, file, line );
@@ -456,7 +459,8 @@ static void uri_params_okx ( struct uri_params_test *test, const char *file,
        okx ( params != NULL, file, line );
        if ( params ) {
                for ( list = test->list ; list->key ; list++ ) {
-                       param = add_parameter ( params, list->key, list->value);
+                       param = add_parameter ( params, list->key, list->value,
+                                               list->flags );
                        okx ( param != NULL, file, line );
                }
        }
@@ -884,18 +888,22 @@ static struct uri_params_test_list uri_params_list[] = {
        {
                "vendor",
                "10ec",
+               PARAMETER_FORM,
        },
        {
                "device",
                "8139",
+               PARAMETER_FORM,
        },
        {
                "uuid",
                "f59fac00-758f-498f-9fe5-87d790045d94",
+               PARAMETER_HEADER,
        },
        {
                NULL,
                NULL,
+               0,
        }
 };
 
@@ -917,14 +925,17 @@ static struct uri_params_test_list uri_named_params_list[] = {
        {
                "mac",
                "00:1e:65:80:d3:b6",
+               PARAMETER_FORM,
        },
        {
                "serial",
                "LXTQ20Z1139322762F2000",
+               PARAMETER_FORM,
        },
        {
                NULL,
                NULL,
+               0,
        }
 };