| #ifndef _IPXE_HTTP_H | |
| #define _IPXE_HTTP_H | |
| /** @file | |
| * | |
| * Hyper Text Transport Protocol | |
| * | |
| */ | |
| FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); | |
| FILE_SECBOOT ( PERMITTED ); | |
| #include <stdint.h> | |
| #include <ipxe/refcnt.h> | |
| #include <ipxe/interface.h> | |
| #include <ipxe/iobuf.h> | |
| #include <ipxe/process.h> | |
| #include <ipxe/retry.h> | |
| #include <ipxe/linebuf.h> | |
| #include <ipxe/pool.h> | |
| #include <ipxe/tables.h> | |
| #include <ipxe/ntlm.h> | |
| struct http_transaction; | |
| struct http_connection; | |
| /****************************************************************************** | |
| * | |
| * HTTP URI schemes | |
| * | |
| ****************************************************************************** | |
| */ | |
| /** HTTP default port */ | |
| #define HTTP_PORT 80 | |
| /** HTTPS default port */ | |
| #define HTTPS_PORT 443 | |
| /** An HTTP URI scheme */ | |
| struct http_scheme { | |
| /** Scheme name (e.g. "http" or "https") */ | |
| const char *name; | |
| /** Default port */ | |
| unsigned int port; | |
| /** Transport-layer filter (if any) | |
| * | |
| * @v conn HTTP connection | |
| * @ret rc Return status code | |
| */ | |
| int ( * filter ) ( struct http_connection *conn ); | |
| }; | |
| /** HTTP scheme table */ | |
| #define HTTP_SCHEMES __table ( struct http_scheme, "http_schemes" ) | |
| /** Declare an HTTP scheme */ | |
| #define __http_scheme __table_entry ( HTTP_SCHEMES, 01 ) | |
| /****************************************************************************** | |
| * | |
| * Connections | |
| * | |
| ****************************************************************************** | |
| */ | |
| /** An HTTP connection | |
| * | |
| * This represents a potentially reusable connection to an HTTP | |
| * server. | |
| */ | |
| struct http_connection { | |
| /** Reference count */ | |
| struct refcnt refcnt; | |
| /** Connection URI | |
| * | |
| * This encapsulates the server (and protocol) used for the | |
| * connection. This may be the origin server or a proxy | |
| * server. | |
| */ | |
| struct uri *uri; | |
| /** HTTP scheme */ | |
| struct http_scheme *scheme; | |
| /** Transport layer interface */ | |
| struct interface socket; | |
| /** Data transfer interface */ | |
| struct interface xfer; | |
| /** Pooled connection */ | |
| struct pooled_connection pool; | |
| }; | |
| /****************************************************************************** | |
| * | |
| * HTTP methods | |
| * | |
| ****************************************************************************** | |
| */ | |
| /** An HTTP method */ | |
| struct http_method { | |
| /** Method name (e.g. "GET" or "POST") */ | |
| const char *name; | |
| /** Flags */ | |
| unsigned int flags; | |
| }; | |
| /** HTTP method has a request body */ | |
| #define HTTP_FL_REQ_BODY 0x0001 | |
| /** HTTP method table */ | |
| #define HTTP_METHODS __table ( struct http_method, "http_methods" ) | |
| /** Declare an HTTP method */ | |
| #define __http_method __table_entry ( HTTP_METHODS, 01 ) | |
| extern struct http_method http_head __http_method; | |
| extern struct http_method http_get __http_method; | |
| extern struct http_method http_post __http_method; | |
| extern struct http_method http_put __http_method; | |
| /****************************************************************************** | |
| * | |
| * Requests | |
| * | |
| ****************************************************************************** | |
| */ | |
| /** HTTP Digest authentication client nonce count | |
| * | |
| * We choose to generate a new client nonce each time. | |
| */ | |
| #define HTTP_DIGEST_NC "00000001" | |
| /** HTTP Digest authentication client nonce length | |
| * | |
| * We choose to use a 32-bit hex client nonce. | |
| */ | |
| #define HTTP_DIGEST_CNONCE_LEN 8 | |
| /** HTTP Digest authentication response length | |
| * | |
| * The Digest authentication response is a Base16-encoded 16-byte MD5 | |
| * checksum. | |
| */ | |
| #define HTTP_DIGEST_RESPONSE_LEN 32 | |
| /** HTTP request range descriptor */ | |
| struct http_request_range { | |
| /** Range start */ | |
| size_t start; | |
| /** Range length, or zero for no range request */ | |
| size_t len; | |
| }; | |
| /** HTTP request content descriptor */ | |
| struct http_request_content { | |
| /** Content type (if any) */ | |
| const char *type; | |
| /** Content data (if any) */ | |
| const void *data; | |
| /** Content length */ | |
| size_t len; | |
| }; | |
| /** HTTP request Basic authentication descriptor */ | |
| struct http_request_auth_basic { | |
| /** Username */ | |
| const char *username; | |
| /** Password */ | |
| const char *password; | |
| }; | |
| /** HTTP request Digest authentication descriptor */ | |
| struct http_request_auth_digest { | |
| /** Username */ | |
| const char *username; | |
| /** Quality of protection */ | |
| const char *qop; | |
| /** Algorithm */ | |
| const char *algorithm; | |
| /** Client nonce */ | |
| char cnonce[ HTTP_DIGEST_CNONCE_LEN + 1 /* NUL */ ]; | |
| /** Response */ | |
| char response[ HTTP_DIGEST_RESPONSE_LEN + 1 /* NUL */ ]; | |
| }; | |
| /** HTTP request NTLM authentication descriptor */ | |
| struct http_request_auth_ntlm { | |
| /** Username */ | |
| const char *username; | |
| /** LAN Manager response */ | |
| struct ntlm_lm_response lm; | |
| /** NT response */ | |
| struct ntlm_nt_response nt; | |
| /** Authenticate message length */ | |
| size_t len; | |
| }; | |
| /** HTTP request authentication descriptor */ | |
| struct http_request_auth { | |
| /** Authentication scheme (if any) */ | |
| struct http_authentication *auth; | |
| /** Per-scheme information */ | |
| union { | |
| /** Basic authentication descriptor */ | |
| struct http_request_auth_basic basic; | |
| /** Digest authentication descriptor */ | |
| struct http_request_auth_digest digest; | |
| /** NTLM authentication descriptor */ | |
| struct http_request_auth_ntlm ntlm; | |
| }; | |
| }; | |
| /** An HTTP request | |
| * | |
| * This represents a single request to be sent to a server, including | |
| * the values required to construct all headers. | |
| * | |
| * Pointers within this structure must point to storage which is | |
| * guaranteed to remain valid for the lifetime of the containing HTTP | |
| * transaction. | |
| */ | |
| struct http_request { | |
| /** Method */ | |
| struct http_method *method; | |
| /** Request URI string */ | |
| const char *uri; | |
| /** Server host name */ | |
| const char *host; | |
| /** Range descriptor */ | |
| struct http_request_range range; | |
| /** Content descriptor */ | |
| struct http_request_content content; | |
| /** Authentication descriptor */ | |
| struct http_request_auth auth; | |
| }; | |
| /** An HTTP request header */ | |
| struct http_request_header { | |
| /** Header name (e.g. "User-Agent") */ | |
| const char *name; | |
| /** Construct remaining header line | |
| * | |
| * @v http HTTP transaction | |
| * @v buf Buffer | |
| * @v len Length of buffer | |
| * @ret len Header length if present, or negative error | |
| */ | |
| int ( * format ) ( struct http_transaction *http, char *buf, | |
| size_t len ); | |
| }; | |
| /** HTTP request header table */ | |
| #define HTTP_REQUEST_HEADERS \ | |
| __table ( struct http_request_header, "http_request_headers" ) | |
| /** Declare an HTTP request header */ | |
| #define __http_request_header __table_entry ( HTTP_REQUEST_HEADERS, 01 ) | |
| /****************************************************************************** | |
| * | |
| * Responses | |
| * | |
| ****************************************************************************** | |
| */ | |
| /** HTTP response transfer descriptor */ | |
| struct http_response_transfer { | |
| /** Transfer encoding */ | |
| struct http_transfer_encoding *encoding; | |
| }; | |
| /** HTTP response content descriptor */ | |
| struct http_response_content { | |
| /** Content length (may be zero) */ | |
| size_t len; | |
| /** Content encoding */ | |
| struct http_content_encoding *encoding; | |
| }; | |
| /** HTTP response Basic authorization descriptor */ | |
| struct http_response_auth_basic { | |
| }; | |
| /** HTTP response Digest authorization descriptor */ | |
| struct http_response_auth_digest { | |
| /** Realm */ | |
| const char *realm; | |
| /** Quality of protection */ | |
| const char *qop; | |
| /** Algorithm */ | |
| const char *algorithm; | |
| /** Nonce */ | |
| const char *nonce; | |
| /** Opaque */ | |
| const char *opaque; | |
| }; | |
| /** HTTP response NTLM authorization descriptor */ | |
| struct http_response_auth_ntlm { | |
| /** Challenge message */ | |
| struct ntlm_challenge *challenge; | |
| /** Challenge information */ | |
| struct ntlm_challenge_info info; | |
| }; | |
| /** HTTP response authorization descriptor */ | |
| struct http_response_auth { | |
| /** Authentication scheme (if any) */ | |
| struct http_authentication *auth; | |
| /** Per-scheme information */ | |
| union { | |
| /** Basic authorization descriptor */ | |
| struct http_response_auth_basic basic; | |
| /** Digest authorization descriptor */ | |
| struct http_response_auth_digest digest; | |
| /** NTLM authorization descriptor */ | |
| struct http_response_auth_ntlm ntlm; | |
| }; | |
| }; | |
| /** An HTTP response | |
| * | |
| * This represents a single response received from the server, | |
| * including all values parsed from headers. | |
| * | |
| * Pointers within this structure may point into the raw response | |
| * buffer, and so should be invalidated when the response buffer is | |
| * modified or discarded. | |
| */ | |
| struct http_response { | |
| /** Raw response header lines | |
| * | |
| * This is the raw response data received from the server, up | |
| * to and including the terminating empty line. String | |
| * pointers within the response may point into this data | |
| * buffer; NUL terminators will be added (overwriting the | |
| * original terminating characters) as needed. | |
| */ | |
| struct line_buffer headers; | |
| /** Status code | |
| * | |
| * This is the raw HTTP numeric status code (e.g. 404). | |
| */ | |
| unsigned int status; | |
| /** Return status code | |
| * | |
| * This is the iPXE return status code corresponding to the | |
| * HTTP status code (e.g. -ENOENT). | |
| */ | |
| int rc; | |
| /** Redirection location */ | |
| const char *location; | |
| /** Transfer descriptor */ | |
| struct http_response_transfer transfer; | |
| /** Content descriptor */ | |
| struct http_response_content content; | |
| /** Authorization descriptor */ | |
| struct http_response_auth auth; | |
| /** Retry delay (in seconds) */ | |
| unsigned int retry_after; | |
| /** Flags */ | |
| unsigned int flags; | |
| }; | |
| /** HTTP response flags */ | |
| enum http_response_flags { | |
| /** Keep connection alive after close */ | |
| HTTP_RESPONSE_KEEPALIVE = 0x0001, | |
| /** Content length specified */ | |
| HTTP_RESPONSE_CONTENT_LEN = 0x0002, | |
| /** Transaction may be retried on failure */ | |
| HTTP_RESPONSE_RETRY = 0x0004, | |
| }; | |
| /** An HTTP response header */ | |
| struct http_response_header { | |
| /** Header name (e.g. "Transfer-Encoding") */ | |
| const char *name; | |
| /** Parse header line | |
| * | |
| * @v http HTTP transaction | |
| * @v line Remaining header line | |
| * @ret rc Return status code | |
| */ | |
| int ( * parse ) ( struct http_transaction *http, char *line ); | |
| }; | |
| /** HTTP response header table */ | |
| #define HTTP_RESPONSE_HEADERS \ | |
| __table ( struct http_response_header, "http_response_headers" ) | |
| /** Declare an HTTP response header */ | |
| #define __http_response_header __table_entry ( HTTP_RESPONSE_HEADERS, 01 ) | |
| /****************************************************************************** | |
| * | |
| * Transactions | |
| * | |
| ****************************************************************************** | |
| */ | |
| /** HTTP transaction state */ | |
| struct http_state { | |
| /** Transmit data | |
| * | |
| * @v http HTTP transaction | |
| * @ret rc Return status code | |
| */ | |
| int ( * tx ) ( struct http_transaction *http ); | |
| /** Receive data | |
| * | |
| * @v http HTTP transaction | |
| * @v iobuf I/O buffer (may be claimed) | |
| * @ret rc Return status code | |
| */ | |
| int ( * rx ) ( struct http_transaction *http, | |
| struct io_buffer **iobuf ); | |
| /** Server connection closed | |
| * | |
| * @v http HTTP transaction | |
| * @v rc Reason for close | |
| */ | |
| void ( * close ) ( struct http_transaction *http, int rc ); | |
| }; | |
| /** An HTTP transaction */ | |
| struct http_transaction { | |
| /** Reference count */ | |
| struct refcnt refcnt; | |
| /** Data transfer interface */ | |
| struct interface xfer; | |
| /** Content-decoded interface */ | |
| struct interface content; | |
| /** Transfer-decoded interface */ | |
| struct interface transfer; | |
| /** Server connection */ | |
| struct interface conn; | |
| /** Transmit process */ | |
| struct process process; | |
| /** Reconnection timer */ | |
| struct retry_timer retry; | |
| /** Idle connection watchdog timer */ | |
| struct retry_timer watchdog; | |
| /** Request URI */ | |
| struct uri *uri; | |
| /** Request */ | |
| struct http_request request; | |
| /** Response */ | |
| struct http_response response; | |
| /** Temporary line buffer */ | |
| struct line_buffer linebuf; | |
| /** Transaction state */ | |
| struct http_state *state; | |
| /** Accumulated transfer-decoded length */ | |
| size_t len; | |
| /** Chunk length remaining */ | |
| size_t remaining; | |
| }; | |
| /****************************************************************************** | |
| * | |
| * Transfer encoding | |
| * | |
| ****************************************************************************** | |
| */ | |
| /** An HTTP transfer encoding */ | |
| struct http_transfer_encoding { | |
| /** Name */ | |
| const char *name; | |
| /** Initialise transfer encoding | |
| * | |
| * @v http HTTP transaction | |
| * @ret rc Return status code | |
| */ | |
| int ( * init ) ( struct http_transaction *http ); | |
| /** Receive data state */ | |
| struct http_state state; | |
| }; | |
| /** HTTP transfer encoding table */ | |
| #define HTTP_TRANSFER_ENCODINGS \ | |
| __table ( struct http_transfer_encoding, "http_transfer_encodings" ) | |
| /** Declare an HTTP transfer encoding */ | |
| #define __http_transfer_encoding __table_entry ( HTTP_TRANSFER_ENCODINGS, 01 ) | |
| /****************************************************************************** | |
| * | |
| * Content encoding | |
| * | |
| ****************************************************************************** | |
| */ | |
| /** An HTTP content encoding */ | |
| struct http_content_encoding { | |
| /** Name */ | |
| const char *name; | |
| /** Check if content encoding is supported for this request | |
| * | |
| * @v http HTTP transaction | |
| * @ret supported Content encoding is supported for this request | |
| */ | |
| int ( * supported ) ( struct http_transaction *http ); | |
| /** Initialise content encoding | |
| * | |
| * @v http HTTP transaction | |
| * @ret rc Return status code | |
| */ | |
| int ( * init ) ( struct http_transaction *http ); | |
| }; | |
| /** HTTP content encoding table */ | |
| #define HTTP_CONTENT_ENCODINGS \ | |
| __table ( struct http_content_encoding, "http_content_encodings" ) | |
| /** Declare an HTTP content encoding */ | |
| #define __http_content_encoding __table_entry ( HTTP_CONTENT_ENCODINGS, 01 ) | |
| /****************************************************************************** | |
| * | |
| * Authentication | |
| * | |
| ****************************************************************************** | |
| */ | |
| /** An HTTP authentication scheme */ | |
| struct http_authentication { | |
| /** Name (e.g. "Digest") */ | |
| const char *name; | |
| /** Parse remaining "WWW-Authenticate" header line | |
| * | |
| * @v http HTTP transaction | |
| * @v line Remaining header line | |
| * @ret rc Return status code | |
| */ | |
| int ( * parse ) ( struct http_transaction *http, char *line ); | |
| /** Perform authentication | |
| * | |
| * @v http HTTP transaction | |
| * @ret rc Return status code | |
| */ | |
| int ( * authenticate ) ( struct http_transaction *http ); | |
| /** Construct remaining "Authorization" header line | |
| * | |
| * @v http HTTP transaction | |
| * @v buf Buffer | |
| * @v len Length of buffer | |
| * @ret len Header length if present, or negative error | |
| */ | |
| int ( * format ) ( struct http_transaction *http, char *buf, | |
| size_t len ); | |
| }; | |
| /** HTTP authentication scheme table */ | |
| #define HTTP_AUTHENTICATIONS \ | |
| __table ( struct http_authentication, "http_authentications" ) | |
| /** Declare an HTTP authentication scheme */ | |
| #define __http_authentication __table_entry ( HTTP_AUTHENTICATIONS, 01 ) | |
| /****************************************************************************** | |
| * | |
| * General | |
| * | |
| ****************************************************************************** | |
| */ | |
| extern char * http_token ( char **line, char **value ); | |
| extern int http_connect ( struct interface *xfer, struct uri *uri ); | |
| extern int http_open ( struct interface *xfer, struct http_method *method, | |
| struct uri *uri, struct http_request_range *range, | |
| struct http_request_content *content ); | |
| extern int http_open_uri ( struct interface *xfer, struct uri *uri ); | |
| #endif /* _IPXE_HTTP_H */ |