summaryrefslogtreecommitdiff
path: root/src/ne_request.c
diff options
context:
space:
mode:
authorjoe <joe@61a7d7f5-40b7-0310-9c16-bb0ea8cb1845>2009-09-02 20:25:59 +0000
committerjoe <joe@61a7d7f5-40b7-0310-9c16-bb0ea8cb1845>2009-09-02 20:25:59 +0000
commit0c0d9e018139ae66940da2f4c0fd0ed9ad6dc17f (patch)
tree6a5e5256af93594dbcb7dce747ae92a3e20f2712 /src/ne_request.c
parent4fdb8ff9bfd904e6cbd82245782260672c814c64 (diff)
downloadneon-0c0d9e018139ae66940da2f4c0fd0ed9ad6dc17f.tar.gz
* src/ne_request.c (socks_origin_lookup): New function.
(open_connection): Use it to fix support for SOCKSv4 servers. * test/request.c (socks_v4_proxy): Add test case. git-svn-id: http://svn.webdav.org/repos/projects/neon/trunk@1713 61a7d7f5-40b7-0310-9c16-bb0ea8cb1845
Diffstat (limited to 'src/ne_request.c')
-rw-r--r--src/ne_request.c71
1 files changed, 59 insertions, 12 deletions
diff --git a/src/ne_request.c b/src/ne_request.c
index 72ce448..6eaacde 100644
--- a/src/ne_request.c
+++ b/src/ne_request.c
@@ -1122,7 +1122,7 @@ static int read_response_headers(ne_request *req)
}
/* Perform any necessary DNS lookup for the host given by *info;
- * return NE_ code. */
+ * returns NE_ code with error string set on error. */
static int lookup_host(ne_session *sess, struct host_info *info)
{
NE_DEBUG(NE_DBG_HTTP, "Doing DNS lookup on %s...\n", info->hostname);
@@ -1514,6 +1514,42 @@ static int do_connect(ne_session *sess, struct host_info *host)
return NE_OK;
}
+/* For a SOCKSv4 proxy only, the IP address of the origin server (in
+ * addition to the proxy) must be known, and must be an IPv4 address.
+ * Returns NE_*; connection closed and error string set on error. */
+static int socks_origin_lookup(ne_session *sess)
+{
+ const ne_inet_addr *ia;
+ int ret;
+
+ ret = lookup_host(sess, &sess->server);
+ if (ret) {
+ /* lookup_host already set the error string. */
+ ne_close_connection(sess);
+ return ret;
+ }
+
+ /* Find the first IPv4 address available for the server. */
+ for (ia = ne_addr_first(sess->server.address);
+ ia && ne_iaddr_typeof(ia) == ne_iaddr_ipv6;
+ ia = ne_addr_next(sess->server.address)) {
+ /* noop */
+ }
+
+ /* ... if any */
+ if (ia == NULL) {
+ ne_set_error(sess, _("Could not find IPv4 address of "
+ "hostname %s for SOCKS v4 proxy"),
+ sess->server.hostname);
+ ne_close_connection(sess);
+ return NE_LOOKUP;
+ }
+
+ sess->server.current = ia;
+
+ return ret;
+}
+
static int open_connection(ne_session *sess)
{
int ret;
@@ -1545,17 +1581,28 @@ static int open_connection(ne_session *sess)
}
if (ret == NE_OK && sess->nexthop->proxy == PROXY_SOCKS) {
- ret = ne_sock_proxy(sess->socket, sess->socks_ver, NULL,
- sess->server.hostname, sess->server.port,
- sess->socks_user, sess->socks_password);
- if (ret) {
- ne_set_error(sess,
- _("Could not establish connection from "
- "SOCKS proxy (%s:%u): %s"),
- sess->nexthop->hostname,
- sess->nexthop->port,
- ne_sock_error(sess->socket));
- ne_close_connection(sess);
+ /* Special-case for SOCKS v4 proxies, which require the
+ * client to resolve the origin server IP address. */
+ if (sess->socks_ver == NE_SOCK_SOCKSV4) {
+ ret = socks_origin_lookup(sess);
+ }
+
+ if (ret == NE_OK) {
+ /* Perform the SOCKS handshake, instructing the proxy
+ * to set up the connection to the origin server. */
+ ret = ne_sock_proxy(sess->socket, sess->socks_ver,
+ sess->server.current,
+ sess->server.hostname, sess->server.port,
+ sess->socks_user, sess->socks_password);
+ if (ret) {
+ ne_set_error(sess,
+ _("Could not establish connection from "
+ "SOCKS proxy (%s:%u): %s"),
+ sess->nexthop->hostname,
+ sess->nexthop->port,
+ ne_sock_error(sess->socket));
+ ne_close_connection(sess);
+ }
}
}