Browse code

Add parsing of dhcp-option PROXY_HTTP

This adds support for setting a HTTP proxy that should be used after
connecting to a VPN.

The syntax has been picked to have compatibility with OpenVPN3.
Otherwise I would have used HTTP-PROXY instead.

Since this option requires an additional argument compared to the
existing dhcp-option keywords, move checking the number of arguments
to the individual keywords.

Signed-off-by: Arne Schwabe <arne@rfc2549.org>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <20210416110955.1162574-1-arne@rfc2549.org>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg22129.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>

Arne Schwabe authored on 2021/04/16 20:09:55
Showing 4 changed files
... ...
@@ -183,6 +183,12 @@ routing.
183 183
   :code:`DISABLE-NBT`
184 184
         Disable Netbios-over-TCP/IP.
185 185
 
186
+  :code: `PROXY_HTTP` ``host`` ``port``
187
+        Sets a HTTP proxy that should be used when connected to the VPN.
188
+
189
+        This option currently only works on OpenVPN for Android and requires
190
+        Android 10 or later.
191
+
186 192
 --ifconfig args
187 193
   Set TUN/TAP adapter parameters. It requires the *IP address* of the local
188 194
   VPN endpoint. For TUN devices in point-to-point mode, the next argument
... ...
@@ -7435,22 +7435,22 @@ add_option(struct options *options,
7435 7435
     }
7436 7436
 #endif /* ifdef _WIN32 */
7437 7437
 #if defined(_WIN32) || defined(TARGET_ANDROID)
7438
-    else if (streq(p[0], "dhcp-option") && p[1] && !p[3])
7438
+    else if (streq(p[0], "dhcp-option") && p[1])
7439 7439
     {
7440 7440
         struct tuntap_options *o = &options->tuntap_options;
7441 7441
         VERIFY_PERMISSION(OPT_P_IPWIN32);
7442 7442
         bool ipv6dns = false;
7443 7443
 
7444 7444
         if ((streq(p[1], "DOMAIN") || streq(p[1], "ADAPTER_DOMAIN_SUFFIX"))
7445
-            && p[2])
7445
+            && p[2] && !p[3])
7446 7446
         {
7447 7447
             o->domain = p[2];
7448 7448
         }
7449
-        else if (streq(p[1], "NBS") && p[2])
7449
+        else if (streq(p[1], "NBS") && p[2] && !p[3])
7450 7450
         {
7451 7451
             o->netbios_scope = p[2];
7452 7452
         }
7453
-        else if (streq(p[1], "NBT") && p[2])
7453
+        else if (streq(p[1], "NBT") && p[2] && !p[3])
7454 7454
         {
7455 7455
             int t;
7456 7456
             t = atoi(p[2]);
... ...
@@ -7461,7 +7461,8 @@ add_option(struct options *options,
7461 7461
             }
7462 7462
             o->netbios_node_type = t;
7463 7463
         }
7464
-        else if ((streq(p[1], "DNS") || streq(p[1], "DNS6")) && p[2] && (!strstr(p[2], ":") || ipv6_addr_safe(p[2])))
7464
+        else if ((streq(p[1], "DNS") || streq(p[1], "DNS6")) && p[2] && !p[3]
7465
+                && (!strstr(p[2], ":") || ipv6_addr_safe(p[2])))
7465 7466
         {
7466 7467
             if (strstr(p[2], ":"))
7467 7468
             {
... ...
@@ -7474,19 +7475,19 @@ add_option(struct options *options,
7474 7474
                 dhcp_option_address_parse("DNS", p[2], o->dns, &o->dns_len, msglevel);
7475 7475
             }
7476 7476
         }
7477
-        else if (streq(p[1], "WINS") && p[2])
7477
+        else if (streq(p[1], "WINS") && p[2] && !p[3])
7478 7478
         {
7479 7479
             dhcp_option_address_parse("WINS", p[2], o->wins, &o->wins_len, msglevel);
7480 7480
         }
7481
-        else if (streq(p[1], "NTP") && p[2])
7481
+        else if (streq(p[1], "NTP") && p[2] && !p[3])
7482 7482
         {
7483 7483
             dhcp_option_address_parse("NTP", p[2], o->ntp, &o->ntp_len, msglevel);
7484 7484
         }
7485
-        else if (streq(p[1], "NBDD") && p[2])
7485
+        else if (streq(p[1], "NBDD") && p[2] && !p[3])
7486 7486
         {
7487 7487
             dhcp_option_address_parse("NBDD", p[2], o->nbdd, &o->nbdd_len, msglevel);
7488 7488
         }
7489
-        else if (streq(p[1], "DOMAIN-SEARCH") && p[2])
7489
+        else if (streq(p[1], "DOMAIN-SEARCH") && p[2] && !p[3])
7490 7490
         {
7491 7491
             if (o->domain_search_list_len < N_SEARCH_LIST_LEN)
7492 7492
             {
... ...
@@ -7502,6 +7503,13 @@ add_option(struct options *options,
7502 7502
         {
7503 7503
             o->disable_nbt = 1;
7504 7504
         }
7505
+#if defined(TARGET_ANDROID)
7506
+        else if (streq(p[1], "PROXY_HTTP") && p[3] && !p[4])
7507
+        {
7508
+            o->http_proxy_port = atoi(p[3]);
7509
+            o->http_proxy = p[2];
7510
+        }
7511
+#endif
7505 7512
         else
7506 7513
         {
7507 7514
             msg(msglevel, "--dhcp-option: unknown option type '%s' or missing or unknown parameter", p[1]);
... ...
@@ -1870,6 +1870,13 @@ open_tun(const char *dev, const char *dev_type, const char *dev_node, struct tun
1870 1870
         management_android_control(management, "DNSDOMAIN", tt->options.domain);
1871 1871
     }
1872 1872
 
1873
+    if (tt->options.http_proxy)
1874
+    {
1875
+        struct buffer buf = alloc_buf_gc(strlen(tt->options.http_proxy) + 20, &gc);
1876
+        buf_printf(&buf, "%s %d", tt->options.http_proxy, tt->options.http_proxy_port);
1877
+        management_android_control(management, "HTTPPROXY", BSTR(&buf));
1878
+    }
1879
+
1873 1880
     int android_method = managment_android_persisttun_action(management);
1874 1881
 
1875 1882
     /* Android 4.4 workaround */
... ...
@@ -128,6 +128,10 @@ struct tuntap_options {
128 128
 
129 129
     struct in6_addr dns6[N_DHCP_ADDR];
130 130
     int dns6_len;
131
+#if defined(TARGET_ANDROID)
132
+    const char *http_proxy;
133
+    int http_proxy_port;
134
+#endif
131 135
 };
132 136
 
133 137
 #elif defined(TARGET_LINUX)