It seems the proxy handling code was initially written to only handle
proxies in the form of IP addresses. 38b75abddb5b changed that
implicitly by always doing a hostname lookup for the proxy address,
which fixes proxies given by hostname but breaks ip based proxy
configuration (as sending an A query to most DNS server for an ip
address gets you a result with no answers).

Clean up the confusion by not overloading the meaning of the address
field in web_session and short-circuiting the lookup iff either the
proxy host or the real host is an ip address (as applicable).

Signed-off-by: Sjoerd Simons <[email protected]>
---
 gweb/gweb.c | 67 +++++++++++++++++++++++++++++++++++++++----------------------
 1 file changed, 43 insertions(+), 24 deletions(-)

diff --git a/gweb/gweb.c b/gweb/gweb.c
index 8cdd5d9..e5d6d56 100644
--- a/gweb/gweb.c
+++ b/gweb/gweb.c
@@ -68,6 +68,7 @@ struct web_session {
 
        char *address;
        char *host;
+       char *proxy_host;
        uint16_t port;
        unsigned long flags;
        struct addrinfo *addr;
@@ -190,6 +191,7 @@ static void free_session(struct web_session *session)
        g_free(session->content_type);
 
        g_free(session->host);
+       g_free(session->proxy_host);
        g_free(session->address);
        if (session->addr)
                freeaddrinfo(session->addr);
@@ -1190,27 +1192,20 @@ static int parse_url(struct web_session *session,
                }
        }
 
-       session->address = g_strdup(host);
+       session->proxy_host = g_strdup(host);
 
        g_free(scheme);
 
        return 0;
 }
 
-static void resolv_result(GResolvResultStatus status,
-                                       char **results, gpointer user_data)
+static void got_address (struct web_session *session, const char *address)
 {
-       struct web_session *session = user_data;
        struct addrinfo hints;
        char *port;
        int ret;
 
-       if (!results || !results[0]) {
-               call_result_func(session, 404);
-               return;
-       }
-
-       debug(session->web, "address %s", results[0]);
+       debug(session->web, "address %s", address);
 
        memset(&hints, 0, sizeof(struct addrinfo));
        hints.ai_flags = AI_NUMERICHOST;
@@ -1222,7 +1217,7 @@ static void resolv_result(GResolvResultStatus status,
        }
 
        port = g_strdup_printf("%u", session->port);
-       ret = getaddrinfo(results[0], port, &hints, &session->addr);
+       ret = getaddrinfo(address, port, &hints, &session->addr);
        g_free(port);
        if (ret != 0 || !session->addr) {
                call_result_func(session, 400);
@@ -1230,7 +1225,8 @@ static void resolv_result(GResolvResultStatus status,
        }
 
        g_free(session->address);
-       session->address = g_strdup(results[0]);
+       session->address = g_strdup(address);
+
        call_route_func(session);
 
        if (create_transport(session) < 0) {
@@ -1239,12 +1235,42 @@ static void resolv_result(GResolvResultStatus status,
        }
 }
 
+static void resolv_result(GResolvResultStatus status,
+                                       char **results, gpointer user_data)
+{
+       struct web_session *session = user_data;
+
+       if (!results || !results[0]) {
+               call_result_func(session, 404);
+               return;
+       }
+
+       got_address (session, results[0]);
+}
+
+bool is_ip_address(const char *host)
+{
+       struct addrinfo hints;
+       struct addrinfo *addr;
+       int result;
+
+       memset(&hints, 0, sizeof(struct addrinfo));
+       hints.ai_flags = AI_NUMERICHOST;
+       addr = NULL;
+
+       result = getaddrinfo(host, NULL, &hints, &addr);
+       freeaddrinfo(addr);
+
+       return result == 0;
+}
+
 static guint do_request(GWeb *web, const char *url,
                                const char *type, GWebInputFunc input,
                                int fd, gsize length, GWebResultFunc func,
                                GWebRouteFunc route, gpointer user_data)
 {
        struct web_session *session;
+       const gchar *host;
 
        if (!web || !url)
                return 0;
@@ -1260,7 +1286,7 @@ static guint do_request(GWeb *web, const char *url,
                return 0;
        }
 
-       debug(web, "address %s", session->address);
+       debug(web, "proxy host %s", session->proxy_host);
        debug(web, "port %u", session->port);
        debug(web, "host %s", session->host);
        debug(web, "flags %lu", session->flags);
@@ -1301,19 +1327,12 @@ static guint do_request(GWeb *web, const char *url,
        session->header_done = false;
        session->body_done = false;
 
-       if (!session->address && inet_aton(session->host, NULL) == 0) {
-               session->resolv_action = g_resolv_lookup_hostname(web->resolv,
-                                       session->host, resolv_result, session);
-               if (session->resolv_action == 0) {
-                       free_session(session);
-                       return 0;
-               }
+       host = session->proxy_host ? session->proxy_host : session->host;
+       if (is_ip_address (host)) {
+               got_address (session, host);
        } else {
-               if (!session->address)
-                       session->address = g_strdup(session->host);
-
                session->resolv_action = g_resolv_lookup_hostname(web->resolv,
-                                       session->address, resolv_result, 
session);
+                                       host, resolv_result, session);
                if (session->resolv_action == 0) {
                        free_session(session);
                        return 0;
-- 
1.8.5.2

_______________________________________________
connman mailing list
[email protected]
https://lists.connman.net/mailman/listinfo/connman

Reply via email to