summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2016-01-25 00:18:33 +0100
committerFelix Fietkau <nbd@openwrt.org>2016-01-25 00:18:33 +0100
commitf50a654323bbfeb0de53aa2178755b282bcc9d22 (patch)
tree819e5436d6c8c273fa5c45d01b59de016c2583b3
parentcaa8052ac55218a687593f3dcf30229016e48b0d (diff)
downloaduclient-f50a654323bbfeb0de53aa2178755b282bcc9d22.tar.gz
http: add support for specifying ipv4/ipv6 preference
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
-rw-r--r--uclient-fetch.c17
-rw-r--r--uclient-http.c27
-rw-r--r--uclient.h1
3 files changed, 42 insertions, 3 deletions
diff --git a/uclient-fetch.c b/uclient-fetch.c
index 851994f..f65fab2 100644
--- a/uclient-fetch.c
+++ b/uclient-fetch.c
@@ -18,6 +18,7 @@
#define _GNU_SOURCE
#include <sys/stat.h>
+#include <sys/socket.h>
#include <unistd.h>
#include <stdio.h>
#include <dlfcn.h>
@@ -439,6 +440,8 @@ static int usage(const char *progname)
fprintf(stderr,
"Usage: %s [options] <URL>\n"
"Options:\n"
+ " -4: Use IPv4 only\n"
+ " -6: Use IPv6 only\n"
" -q: Turn off status messages\n"
" -O <file>: Redirect output to file (use \"-\" for stdout)\n"
" -P <dir>: Set directory for output files\n"
@@ -530,11 +533,12 @@ int main(int argc, char **argv)
bool has_cert = false;
int i, ch;
int rc;
+ int af = -1;
signal(SIGPIPE, SIG_IGN);
init_ustream_ssl();
- while ((ch = getopt_long(argc, argv, "cO:P:qsT:U:Y:", longopts, &longopt_idx)) != -1) {
+ while ((ch = getopt_long(argc, argv, "46cO:P:qsT:U:Y:", longopts, &longopt_idx)) != -1) {
switch(ch) {
case 0:
switch (longopt_idx) {
@@ -584,6 +588,12 @@ int main(int argc, char **argv)
return usage(progname);
}
break;
+ case '4':
+ af = AF_INET;
+ break;
+ case '6':
+ af = AF_INET6;
+ break;
case 'c':
resume = true;
break;
@@ -652,7 +662,8 @@ int main(int argc, char **argv)
proxy_url = get_proxy_url(argv[0]);
if (proxy_url) {
cl = uclient_new(proxy_url, auth_str, &cb);
- uclient_set_proxy_url(cl, argv[0], NULL);
+ if (cl)
+ uclient_set_proxy_url(cl, argv[0], NULL);
} else {
cl = uclient_new(argv[0], auth_str, &cb);
}
@@ -660,6 +671,8 @@ int main(int argc, char **argv)
fprintf(stderr, "Failed to allocate uclient context\n");
return 1;
}
+ if (af >= 0)
+ uclient_http_set_address_family(cl, af);
if (ssl_ctx && default_certs)
init_ca_cert();
diff --git a/uclient-http.c b/uclient-http.c
index 5e5f996..f080e41 100644
--- a/uclient-http.c
+++ b/uclient-http.c
@@ -15,6 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <sys/socket.h>
#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
@@ -90,6 +91,8 @@ struct uclient_http {
long read_chunked;
long content_length;
+ int usock_flags;
+
uint32_t nc;
struct blob_buf headers;
@@ -120,7 +123,7 @@ static int uclient_do_connect(struct uclient_http *uh, const char *port)
memset(&uh->uc.remote_addr, 0, sizeof(uh->uc.remote_addr));
- fd = usock_inet(USOCK_TCP, uh->uc.url->host, port, &uh->uc.remote_addr);
+ fd = usock_inet(USOCK_TCP | uh->usock_flags, uh->uc.url->host, port, &uh->uc.remote_addr);
if (fd < 0)
return -1;
@@ -1129,6 +1132,28 @@ int uclient_http_set_ssl_ctx(struct uclient *cl, const struct ustream_ssl_ops *o
return 0;
}
+int uclient_http_set_address_family(struct uclient *cl, int af)
+{
+ struct uclient_http *uh = container_of(cl, struct uclient_http, uc);
+
+ if (cl->backend != &uclient_backend_http)
+ return -1;
+
+ switch (af) {
+ case AF_INET:
+ uh->usock_flags = USOCK_IPV4ONLY;
+ break;
+ case AF_INET6:
+ uh->usock_flags = USOCK_IPV6ONLY;
+ break;
+ default:
+ uh->usock_flags = 0;
+ break;
+ }
+
+ return 0;
+}
+
const struct uclient_backend uclient_backend_http = {
.prefix = uclient_http_prefix,
diff --git a/uclient.h b/uclient.h
index 504fc35..e3695db 100644
--- a/uclient.h
+++ b/uclient.h
@@ -125,5 +125,6 @@ int uclient_http_redirect(struct uclient *cl);
int uclient_http_set_ssl_ctx(struct uclient *cl, const struct ustream_ssl_ops *ops,
struct ustream_ssl_ctx *ctx, bool require_validation);
+int uclient_http_set_address_family(struct uclient *cl, int af);
#endif