|
@@ -49,6 +49,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
|
49
|
49
|
#include <ipxe/blockdev.h>
|
50
|
50
|
#include <ipxe/acpi.h>
|
51
|
51
|
#include <ipxe/version.h>
|
|
52
|
+#include <ipxe/params.h>
|
52
|
53
|
#include <ipxe/http.h>
|
53
|
54
|
|
54
|
55
|
/* Disambiguate the various error causes */
|
|
@@ -1059,17 +1060,101 @@ static char * http_digest_auth ( struct http_request *http,
|
1059
|
1060
|
return auth;
|
1060
|
1061
|
}
|
1061
|
1062
|
|
|
1063
|
+/**
|
|
1064
|
+ * Generate HTTP POST parameter list
|
|
1065
|
+ *
|
|
1066
|
+ * @v http HTTP request
|
|
1067
|
+ * @v buf Buffer to contain HTTP POST parameters
|
|
1068
|
+ * @v len Length of buffer
|
|
1069
|
+ * @ret len Length of parameter list (excluding terminating NUL)
|
|
1070
|
+ */
|
|
1071
|
+static size_t http_post_params ( struct http_request *http,
|
|
1072
|
+ char *buf, size_t len ) {
|
|
1073
|
+ struct parameter *param;
|
|
1074
|
+ ssize_t remaining = len;
|
|
1075
|
+ size_t frag_len;
|
|
1076
|
+
|
|
1077
|
+ /* Add each parameter in the form "key=value", joined with "&" */
|
|
1078
|
+ len = 0;
|
|
1079
|
+ for_each_param ( param, http->uri->params ) {
|
|
1080
|
+
|
|
1081
|
+ /* Add the "&", if applicable */
|
|
1082
|
+ if ( len ) {
|
|
1083
|
+ if ( remaining > 0 )
|
|
1084
|
+ *buf = '&';
|
|
1085
|
+ buf++;
|
|
1086
|
+ len++;
|
|
1087
|
+ remaining--;
|
|
1088
|
+ }
|
|
1089
|
+
|
|
1090
|
+ /* URI-encode the key */
|
|
1091
|
+ frag_len = uri_encode ( param->key, buf, remaining, 0 );
|
|
1092
|
+ buf += frag_len;
|
|
1093
|
+ len += frag_len;
|
|
1094
|
+ remaining -= frag_len;
|
|
1095
|
+
|
|
1096
|
+ /* Add the "=" */
|
|
1097
|
+ if ( remaining > 0 )
|
|
1098
|
+ *buf = '=';
|
|
1099
|
+ buf++;
|
|
1100
|
+ len++;
|
|
1101
|
+ remaining--;
|
|
1102
|
+
|
|
1103
|
+ /* URI-encode the value */
|
|
1104
|
+ frag_len = uri_encode ( param->value, buf, remaining, 0 );
|
|
1105
|
+ buf += frag_len;
|
|
1106
|
+ len += frag_len;
|
|
1107
|
+ remaining -= frag_len;
|
|
1108
|
+ }
|
|
1109
|
+
|
|
1110
|
+ /* Ensure string is NUL-terminated even if no parameters are present */
|
|
1111
|
+ if ( remaining > 0 )
|
|
1112
|
+ *buf = '\0';
|
|
1113
|
+
|
|
1114
|
+ return len;
|
|
1115
|
+}
|
|
1116
|
+
|
|
1117
|
+/**
|
|
1118
|
+ * Generate HTTP POST body
|
|
1119
|
+ *
|
|
1120
|
+ * @v http HTTP request
|
|
1121
|
+ * @ret post I/O buffer containing POST body, or NULL on error
|
|
1122
|
+ */
|
|
1123
|
+static struct io_buffer * http_post ( struct http_request *http ) {
|
|
1124
|
+ struct io_buffer *post;
|
|
1125
|
+ size_t len;
|
|
1126
|
+ size_t check_len;
|
|
1127
|
+
|
|
1128
|
+ /* Calculate length of parameter list */
|
|
1129
|
+ len = http_post_params ( http, NULL, 0 );
|
|
1130
|
+
|
|
1131
|
+ /* Allocate parameter list */
|
|
1132
|
+ post = alloc_iob ( len + 1 /* NUL */ );
|
|
1133
|
+ if ( ! post )
|
|
1134
|
+ return NULL;
|
|
1135
|
+
|
|
1136
|
+ /* Fill parameter list */
|
|
1137
|
+ check_len = http_post_params ( http, iob_put ( post, len ),
|
|
1138
|
+ ( len + 1 /* NUL */ ) );
|
|
1139
|
+ assert ( len == check_len );
|
|
1140
|
+ DBGC ( http, "HTTP %p POST %s\n", http, ( ( char * ) post->data ) );
|
|
1141
|
+
|
|
1142
|
+ return post;
|
|
1143
|
+}
|
|
1144
|
+
|
1062
|
1145
|
/**
|
1063
|
1146
|
* HTTP process
|
1064
|
1147
|
*
|
1065
|
1148
|
* @v http HTTP request
|
1066
|
1149
|
*/
|
1067
|
1150
|
static void http_step ( struct http_request *http ) {
|
|
1151
|
+ struct io_buffer *post;
|
1068
|
1152
|
size_t uri_len;
|
1069
|
1153
|
char *method;
|
1070
|
1154
|
char *uri;
|
1071
|
1155
|
char *range;
|
1072
|
1156
|
char *auth;
|
|
1157
|
+ char *content;
|
1073
|
1158
|
int len;
|
1074
|
1159
|
int rc;
|
1075
|
1160
|
|
|
@@ -1088,7 +1173,8 @@ static void http_step ( struct http_request *http ) {
|
1088
|
1173
|
}
|
1089
|
1174
|
|
1090
|
1175
|
/* Determine method */
|
1091
|
|
- method = ( ( http->flags & HTTP_HEAD_ONLY ) ? "HEAD" : "GET" );
|
|
1176
|
+ method = ( ( http->flags & HTTP_HEAD_ONLY ) ? "HEAD" :
|
|
1177
|
+ ( http->uri->params ? "POST" : "GET" ) );
|
1092
|
1178
|
|
1093
|
1179
|
/* Construct path?query request */
|
1094
|
1180
|
uri_len = ( unparse_uri ( NULL, 0, http->uri,
|
|
@@ -1136,6 +1222,25 @@ static void http_step ( struct http_request *http ) {
|
1136
|
1222
|
auth = NULL;
|
1137
|
1223
|
}
|
1138
|
1224
|
|
|
1225
|
+ /* Construct POST content, if applicable */
|
|
1226
|
+ if ( http->uri->params ) {
|
|
1227
|
+ post = http_post ( http );
|
|
1228
|
+ if ( ! post ) {
|
|
1229
|
+ rc = -ENOMEM;
|
|
1230
|
+ goto err_post;
|
|
1231
|
+ }
|
|
1232
|
+ len = asprintf ( &content, "Content-Type: "
|
|
1233
|
+ "application/x-www-form-urlencoded\r\n"
|
|
1234
|
+ "Content-Length: %zd\r\n", iob_len ( post ) );
|
|
1235
|
+ if ( len < 0 ) {
|
|
1236
|
+ rc = len;
|
|
1237
|
+ goto err_content;
|
|
1238
|
+ }
|
|
1239
|
+ } else {
|
|
1240
|
+ post = NULL;
|
|
1241
|
+ content = NULL;
|
|
1242
|
+ }
|
|
1243
|
+
|
1139
|
1244
|
/* Mark request as transmitted */
|
1140
|
1245
|
http->flags &= ~HTTP_TX_PENDING;
|
1141
|
1246
|
|
|
@@ -1144,7 +1249,7 @@ static void http_step ( struct http_request *http ) {
|
1144
|
1249
|
"%s %s HTTP/1.1\r\n"
|
1145
|
1250
|
"User-Agent: iPXE/%s\r\n"
|
1146
|
1251
|
"Host: %s%s%s\r\n"
|
1147
|
|
- "%s%s%s"
|
|
1252
|
+ "%s%s%s%s"
|
1148
|
1253
|
"\r\n",
|
1149
|
1254
|
method, uri, product_version, http->uri->host,
|
1150
|
1255
|
( http->uri->port ?
|
|
@@ -1154,11 +1259,24 @@ static void http_step ( struct http_request *http ) {
|
1154
|
1259
|
( ( http->flags & HTTP_CLIENT_KEEPALIVE ) ?
|
1155
|
1260
|
"Connection: keep-alive\r\n" : "" ),
|
1156
|
1261
|
( range ? range : "" ),
|
1157
|
|
- ( auth ? auth : "" ) ) ) != 0 ) {
|
|
1262
|
+ ( auth ? auth : "" ),
|
|
1263
|
+ ( content ? content : "" ) ) ) != 0 ) {
|
1158
|
1264
|
goto err_xfer;
|
1159
|
1265
|
}
|
1160
|
1266
|
|
|
1267
|
+ /* Send POST content, if applicable */
|
|
1268
|
+ if ( post ) {
|
|
1269
|
+ if ( ( rc = xfer_deliver_iob ( &http->socket,
|
|
1270
|
+ iob_disown ( post ) ) ) != 0 )
|
|
1271
|
+ goto err_xfer_post;
|
|
1272
|
+ }
|
|
1273
|
+
|
|
1274
|
+ err_xfer_post:
|
1161
|
1275
|
err_xfer:
|
|
1276
|
+ free ( content );
|
|
1277
|
+ err_content:
|
|
1278
|
+ free ( post );
|
|
1279
|
+ err_post:
|
1162
|
1280
|
free ( auth );
|
1163
|
1281
|
err_auth:
|
1164
|
1282
|
free ( range );
|