uclient-http: fix Host: header for literal IPv6 addresses
authorMatthias Schiffer <mschiffer@universe-factory.net>
Tue, 5 Sep 2017 18:02:37 +0000 (20:02 +0200)
committerMatthias Schiffer <mschiffer@universe-factory.net>
Wed, 6 Sep 2017 13:37:56 +0000 (15:37 +0200)
For literal IPv6 addresses, the host header must have the form

  Host: [...]

including the square brackets, as it may also contain a port. Some
webservers ignore the missing brackets, while others will return error 400.

IPv6 addresses are determined by searching for ':' characters in the host,
as neither IPv4 addresses nor DNS names can contain colons. An alternative
would be to add a flag to the uclient_url struct; but as this struct is
exposed in public headers, such a change could be considered an ABI change,
making a backport difficult.

Signed-off-by: Matthias Schiffer <mschiffer@universe-factory.net>
Acked-by: Jo-Philipp Wich <jo@mein.io>
uclient-http.c

index ac9d50f..ef8de98 100644 (file)
@@ -20,6 +20,7 @@
 #include <ctype.h>
 #include <unistd.h>
 #include <stdint.h>
 #include <ctype.h>
 #include <unistd.h>
 #include <stdint.h>
+#include <string.h>
 #include <fcntl.h>
 
 #include <libubox/ustream.h>
 #include <fcntl.h>
 
 #include <libubox/ustream.h>
@@ -562,6 +563,7 @@ uclient_http_send_headers(struct uclient_http *uh)
        struct uclient_url *url = uh->uc.url;
        struct blob_attr *cur;
        enum request_type req_type = uh->req_type;
        struct uclient_url *url = uh->uc.url;
        struct blob_attr *cur;
        enum request_type req_type = uh->req_type;
+       bool literal_ipv6;
        int rem;
 
        if (uh->state >= HTTP_STATE_HEADERS_SENT)
        int rem;
 
        if (uh->state >= HTTP_STATE_HEADERS_SENT)
@@ -570,11 +572,15 @@ uclient_http_send_headers(struct uclient_http *uh)
        if (uh->uc.proxy_url)
                url = uh->uc.proxy_url;
 
        if (uh->uc.proxy_url)
                url = uh->uc.proxy_url;
 
+       literal_ipv6 = strchr(url->host, ':');
+
        ustream_printf(uh->us,
                "%s %s HTTP/1.1\r\n"
        ustream_printf(uh->us,
                "%s %s HTTP/1.1\r\n"
-               "Host: %s%s%s\r\n",
-               request_types[req_type],
-               url->location, url->host,
+               "Host: %s%s%s%s%s\r\n",
+               request_types[req_type], url->location,
+               literal_ipv6 ? "[" : "",
+               url->host,
+               literal_ipv6 ? "]" : "",
                url->port ? ":" : "",
                url->port ? url->port : "");
 
                url->port ? ":" : "",
                url->port ? url->port : "");