diff --git a/src/include/ipxe/proxy.h b/src/include/ipxe/proxy.h new file mode 100755 index 0000000..56985e9 --- /dev/null +++ b/src/include/ipxe/proxy.h @@ -0,0 +1,17 @@ +#ifndef _IPXE_PROXY_H +#define _IPXE_PROXY_H + +/** @file + * + * HTTP Proxy + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +int is_proxy_set ( ); +struct uri *get_proxy ( ); +const char *proxied_uri_host ( struct uri *uri ); +unsigned int proxied_uri_port ( struct uri *uri, unsigned int default_port ); + +#endif /* _IPXE_IP_H */ diff --git a/src/net/proxy.c b/src/net/proxy.c new file mode 100755 index 0000000..3f59115 --- /dev/null +++ b/src/net/proxy.c @@ -0,0 +1,70 @@ +#include +#include +#include +#include + +/** @file + * + * HTTP Proxy + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +struct uri *proxy_uri = NULL; + +/** HTTP proxy address setting */ +struct setting http_proxy_setting __setting ( SETTING_MISC, "" ) = { + .name = "http-proxy", + .description = "Address and port of the HTTP (not HTTPS) proxy to use, as a http scheme URI", + .type = &setting_type_string, +}; + +int is_proxy_set ( ) { + /* Later, this may be expanded to encompass other settings */ + if ( ! proxy_uri ) { + proxy_uri = get_proxy(); + } + return ! ! proxy_uri; +} + +struct uri *get_proxy ( ) { + char *http_proxy_unexpanded, *http_proxy; + + if ( setting_exists ( NULL, &http_proxy_setting ) && ! proxy_uri ) { + /* Later, this may select from multiple settings*/ + fetch_string_setting_copy ( NULL, &http_proxy_setting, &http_proxy_unexpanded ); + http_proxy = expand_settings ( http_proxy_unexpanded ); + proxy_uri = parse_uri ( http_proxy ); + free ( http_proxy_unexpanded ); + free ( http_proxy ); + /* Only the http scheme is currently supported */ + if ( strcmp ( proxy_uri->scheme, "http" ) != 0 ) { + uri_put ( proxy_uri ); + DBG ( "http-proxy must begin with \"http://\"" ); + return NULL; + } + } + + return proxy_uri; +} + +const char *proxied_uri_host ( struct uri *uri ) { + /* Later, this could select from multiple proxies, + based on hostname patterns matched against the uri */ + if ( is_proxy_set ( ) ) { + return proxy_uri->host; + } else { + return uri->host; + } +} + +unsigned int proxied_uri_port ( struct uri *uri, unsigned int default_port ) { + /* Later, this could select from multiple proxies, + based on hostname patterns matched against the uri */ + if ( is_proxy_set ( ) ) { + return uri_port ( proxy_uri, default_port); + } else { + return uri_port ( uri, default_port); + } +} diff --git a/src/include/ipxe/settings.h b/src/include/ipxe/settings.h index 45d600b..a4ce536 100644 --- a/src/include/ipxe/settings.h +++ b/src/include/ipxe/settings.h @@ -449,6 +449,8 @@ extern const struct setting mac_setting __setting ( SETTING_NETDEV, mac ); extern const struct setting busid_setting __setting ( SETTING_NETDEV, busid ); +extern struct setting +http_proxy_setting __setting ( SETTING_MISC, ip ); extern const struct setting user_class_setting __setting ( SETTING_HOST_EXTRA, user-class ); diff --git a/src/net/tcp/httpcore.c b/src/net/tcp/httpcore.c index 42a0f90..c33de55 100644 --- a/src/net/tcp/httpcore.c +++ b/src/net/tcp/httpcore.c @@ -59,6 +59,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include +#include /* Disambiguate the various error causes */ #define EACCES_401 __einfo_error ( EINFO_EACCES_401 ) @@ -263,15 +264,15 @@ static int http_socket_open ( struct http_request *http ) { /* Open socket */ memset ( &server, 0, sizeof ( server ) ); - server.st_port = htons ( uri_port ( uri, http->default_port ) ); + server.st_port = htons ( proxied_uri_port ( uri, http->default_port ) ); socket = &http->socket; if ( http->filter ) { - if ( ( rc = http->filter ( socket, uri->host, &socket ) ) != 0 ) + if ( ( rc = http->filter ( socket, proxied_uri_host ( uri ), &socket ) ) != 0 ) return rc; } if ( ( rc = xfer_open_named_socket ( socket, SOCK_STREAM, ( struct sockaddr * ) &server, - uri->host, NULL ) ) != 0 ) + proxied_uri_host ( uri ), NULL ) ) != 0 ) return rc; return 0; @@ -1348,9 +1349,15 @@ static void http_step ( struct http_request *http ) { /* Construct path URI */ memset ( &path_uri, 0, sizeof ( path_uri ) ); + if ( is_proxy_set ( ) ) { + /*include all fields*/ + memcpy( &path_uri, http->uri, sizeof( path_uri )); + }else{ path_uri.path = ( http->uri->path ? http->uri->path : "/" ); path_uri.query = http->uri->query; + } path_uri_string = format_uri_alloc ( &path_uri ); + if ( ! path_uri_string ) { rc = -ENOMEM; goto err_path_uri;