socks filter: pass operation parameters
No binary (build failed)
—
(log yok)
| @@ -374,7 +374,27 @@ connect_sub_chain: | |
| /* sub-chain connected, do we need to add more? */ | |
| #ifndef CURL_DISABLE_PROXY | |
| if(ctx->state < CF_SETUP_CNNCT_SOCKS && cf->conn->bits.socksproxy) { | |
| - | result = Curl_cf_socks_proxy_insert_after(cf, data); |
| + | /* for the secondary socket (FTP), use the "connect to host" |
| + | * but ignore the "connect to port" (use the secondary port) |
| + | */ |
| + | const char *hostname = |
| + | cf->conn->bits.httpproxy ? |
| + | cf->conn->http_proxy.host.name : |
| + | cf->conn->bits.conn_to_host ? |
| + | cf->conn->conn_to_host.name : |
| + | cf->sockindex == SECONDARYSOCKET ? |
| + | cf->conn->secondaryhostname : cf->conn->host.name; |
| + | uint16_t port = |
| + | cf->conn->bits.httpproxy ? cf->conn->http_proxy.port : |
| + | cf->sockindex == SECONDARYSOCKET ? cf->conn->secondary_port : |
| + | cf->conn->bits.conn_to_port ? cf->conn->conn_to_port : |
| + | cf->conn->remote_port; |
| + | const char *user = cf->conn->socks_proxy.user; |
| + | const char *passwd = cf->conn->socks_proxy.passwd; |
| + | |
| + | result = Curl_cf_socks_proxy_insert_after( |
| + | cf, data, hostname, port, cf->conn->ip_version, |
| + | cf->conn->socks_proxy.proxytype, user, passwd); |
| if(result) | |
| return result; | |
| ctx->state = CF_SETUP_CNNCT_SOCKS; | |
| @@ -95,19 +95,21 @@ static const char * const cf_socks_statename[] = { | |
| #define SOCKS_CHUNKS 1 | |
| - | struct socks_state { |
| + | struct socks_ctx { |
| enum socks_state_t state; | |
| struct bufq iobuf; | |
| - | const char *hostname; |
| uint16_t remote_port; | |
| - | const char *proxy_user; |
| - | const char *proxy_password; |
| + | const char *user; |
| + | const char *passwd; |
| CURLproxycode presult; | |
| uint32_t resolv_id; | |
| + | uint8_t ip_version; |
| + | uint8_t proxy_type; |
| unsigned char version; | |
| BIT(resolve_local); | |
| BIT(start_resolving); | |
| BIT(socks4a); | |
| + | char hostname[1]; |
| }; | |
| #if defined(HAVE_GSSAPI) || defined(USE_WINDOWS_SSPI) | |
| @@ -129,13 +131,15 @@ CURLcode Curl_blockread_all(struct Curl_cfilter *cf, | |
| *pnread = 0; | |
| for(;;) { | |
| timediff_t timeout_ms = Curl_timeleft_ms(data); | |
| + | curl_socket_t sock = Curl_conn_cf_get_socket(cf, data); |
| + | |
| if(timeout_ms < 0) { | |
| /* we already got the timeout */ | |
| return CURLE_OPERATION_TIMEDOUT; | |
| } | |
| if(!timeout_ms) | |
| timeout_ms = TIMEDIFF_T_MAX; | |
| - | if(SOCKET_READABLE(cf->conn->sock[cf->sockindex], timeout_ms) <= 0) |
| + | if(SOCKET_READABLE(sock, timeout_ms) <= 0) |
| return CURLE_OPERATION_TIMEDOUT; | |
| result = Curl_conn_cf_recv(cf->next, data, buf, blen, &nread); | |
| if(result == CURLE_AGAIN) | |
| @@ -164,7 +168,7 @@ CURLcode Curl_blockread_all(struct Curl_cfilter *cf, | |
| #endif | |
| /* always use this function to change state, to make debugging easier */ | |
| - | static void socksstate(struct socks_state *sx, |
| + | static void socksstate(struct socks_ctx *sx, |
| struct Curl_cfilter *cf, | |
| struct Curl_easy *data, | |
| enum socks_state_t state | |
| @@ -191,7 +195,7 @@ static void socksstate(struct socks_state *sx, | |
| #endif | |
| } | |
| - | static CURLproxycode socks_failed(struct socks_state *sx, |
| + | static CURLproxycode socks_failed(struct socks_ctx *sx, |
| struct Curl_cfilter *cf, | |
| struct Curl_easy *data, | |
| CURLproxycode presult) | |
| @@ -201,7 +205,7 @@ static CURLproxycode socks_failed(struct socks_state *sx, | |
| return presult; | |
| } | |
| - | static CURLproxycode socks_flush(struct socks_state *sx, |
| + | static CURLproxycode socks_flush(struct socks_ctx *sx, |
| struct Curl_cfilter *cf, | |
| struct Curl_easy *data, | |
| bool *done) | |
| @@ -225,7 +229,7 @@ static CURLproxycode socks_flush(struct socks_state *sx, | |
| return CURLPX_OK; | |
| } | |
| - | static CURLproxycode socks_recv(struct socks_state *sx, |
| + | static CURLproxycode socks_recv(struct socks_ctx *sx, |
| struct Curl_cfilter *cf, | |
| struct Curl_easy *data, | |
| size_t min_bytes, | |
| @@ -259,7 +263,7 @@ static CURLproxycode socks_recv(struct socks_state *sx, | |
| return CURLPX_OK; | |
| } | |
| - | static CURLproxycode socks4_req_add_hd(struct socks_state *sx, |
| + | static CURLproxycode socks4_req_add_hd(struct socks_ctx *sx, |
| struct Curl_easy *data) | |
| { | |
| unsigned char buf[4]; | |
| @@ -278,14 +282,14 @@ static CURLproxycode socks4_req_add_hd(struct socks_state *sx, | |
| return CURLPX_OK; | |
| } | |
| - | static CURLproxycode socks4_req_add_user(struct socks_state *sx, |
| + | static CURLproxycode socks4_req_add_user(struct socks_ctx *sx, |
| struct Curl_easy *data) | |
| { | |
| CURLcode result; | |
| size_t nwritten; | |
| - | if(sx->proxy_user) { |
| - | size_t plen = strlen(sx->proxy_user); |
| + | if(sx->user) { |
| + | size_t plen = strlen(sx->user); |
| if(plen > 255) { | |
| /* there is no real size limit to this field in the protocol, but | |
| SOCKS5 limits the proxy user field to 255 bytes and it seems likely | |
| @@ -294,7 +298,7 @@ static CURLproxycode socks4_req_add_user(struct socks_state *sx, | |
| return CURLPX_LONG_USER; | |
| } | |
| /* add proxy name WITH trailing zero */ | |
| - | result = Curl_bufq_cwrite(&sx->iobuf, sx->proxy_user, plen + 1, |
| + | result = Curl_bufq_cwrite(&sx->iobuf, sx->user, plen + 1, |
| &nwritten); | |
| if(result || (nwritten != (plen + 1))) | |
| return CURLPX_SEND_REQUEST; | |
| @@ -309,7 +313,7 @@ static CURLproxycode socks4_req_add_user(struct socks_state *sx, | |
| return CURLPX_OK; | |
| } | |
| - | static CURLproxycode socks4_resolving(struct socks_state *sx, |
| + | static CURLproxycode socks4_resolving(struct socks_ctx *sx, |
| struct Curl_cfilter *cf, | |
| struct Curl_easy *data, | |
| bool *done) | |
| @@ -323,9 +327,8 @@ static CURLproxycode socks4_resolving(struct socks_state *sx, | |
| if(sx->start_resolving) { | |
| /* need to resolve hostname to add destination address */ | |
| sx->start_resolving = FALSE; | |
| - | DEBUGASSERT(sx->hostname && *sx->hostname); |
| result = Curl_cf_dns_insert_after( | |
| - | cf, data, Curl_resolv_dns_queries(data, cf->conn->ip_version), |
| + | cf, data, Curl_resolv_dns_queries(data, sx->ip_version), |
| sx->hostname, sx->remote_port, TRNSPRT_TCP, TRUE); | |
| if(result) { | |
| failf(data, "unable to create DNS filter for socks"); | |
| @@ -370,7 +373,7 @@ static CURLproxycode socks4_resolving(struct socks_state *sx, | |
| return CURLPX_OK; | |
| } | |
| - | static CURLproxycode socks4_check_resp(struct socks_state *sx, |
| + | static CURLproxycode socks4_check_resp(struct socks_ctx *sx, |
| struct Curl_cfilter *cf, | |
| struct Curl_easy *data) | |
| { | |
| @@ -459,7 +462,7 @@ static CURLproxycode socks4_check_resp(struct socks_state *sx, | |
| * Nonsupport "Identification Protocol (RFC1413)" | |
| */ | |
| static CURLproxycode socks4_connect(struct Curl_cfilter *cf, | |
| - | struct socks_state *sx, |
| + | struct socks_ctx *sx, |
| struct Curl_easy *data) | |
| { | |
| size_t nwritten; | |
| @@ -477,16 +480,14 @@ process_state: | |
| case SOCKS4_ST_START: | |
| Curl_bufq_reset(&sx->iobuf); | |
| sx->start_resolving = FALSE; | |
| - | sx->socks4a = (cf->conn->socks_proxy.proxytype == CURLPROXY_SOCKS4A); |
| + | sx->socks4a = (sx->proxy_type == CURLPROXY_SOCKS4A); |
| sx->resolve_local = !sx->socks4a; | |
| sx->presult = CURLPX_OK; | |
| /* SOCKS4 can only do IPv4, insist! */ | |
| - | cf->conn->ip_version = CURL_IPRESOLVE_V4; |
| - | CURL_TRC_CF(data, cf, "SOCKS4%s communication to%s %s:%u", |
| - | sx->socks4a ? "a" : "", |
| - | cf->conn->bits.httpproxy ? " HTTP proxy" : "", |
| - | sx->hostname, sx->remote_port); |
| + | sx->ip_version = CURL_IPRESOLVE_V4; |
| + | CURL_TRC_CF(data, cf, "SOCKS4%s connecting to %s:%u", |
| + | sx->socks4a ? "a" : "", sx->hostname, sx->remote_port); |
| /* | |
| * Compose socks4 request | |
| @@ -579,7 +580,7 @@ process_state: | |
| } | |
| static CURLproxycode socks5_req0_init(struct Curl_cfilter *cf, | |
| - | struct socks_state *sx, |
| + | struct socks_ctx *sx, |
| struct Curl_easy *data) | |
| { | |
| const unsigned char auth = data->set.socks5auth; | |
| @@ -601,7 +602,7 @@ static CURLproxycode socks5_req0_init(struct Curl_cfilter *cf, | |
| "CURLOPT_SOCKS5_AUTH: %u", auth); | |
| if(!(auth & CURLAUTH_BASIC)) | |
| /* disable username/password auth */ | |
| - | sx->proxy_user = NULL; |
| + | sx->user = NULL; |
| req[0] = 5; /* version */ | |
| nauths = 1; | |
| @@ -612,7 +613,7 @@ static CURLproxycode socks5_req0_init(struct Curl_cfilter *cf, | |
| req[1 + nauths] = 1; /* GSS-API */ | |
| } | |
| #endif | |
| - | if(sx->proxy_user) { |
| + | if(sx->user) { |
| ++nauths; | |
| req[1 + nauths] = 2; /* username/password */ | |
| } | |
| @@ -625,7 +626,7 @@ static CURLproxycode socks5_req0_init(struct Curl_cfilter *cf, | |
| return CURLPX_OK; | |
| } | |
| - | static CURLproxycode socks5_check_resp0(struct socks_state *sx, |
| + | static CURLproxycode socks5_check_resp0(struct socks_ctx *sx, |
| struct Curl_cfilter *cf, | |
| struct Curl_easy *data) | |
| { | |
| @@ -677,7 +678,7 @@ static CURLproxycode socks5_check_resp0(struct socks_state *sx, | |
| } | |
| static CURLproxycode socks5_auth_init(struct Curl_cfilter *cf, | |
| - | struct socks_state *sx, |
| + | struct socks_ctx *sx, |
| struct Curl_easy *data) | |
| { | |
| /* Needs username and password */ | |
| @@ -685,9 +686,9 @@ static CURLproxycode socks5_auth_init(struct Curl_cfilter *cf, | |
| unsigned char buf[2]; | |
| CURLcode result; | |
| - | if(sx->proxy_user && sx->proxy_password) { |
| - | ulen = strlen(sx->proxy_user); |
| - | plen = strlen(sx->proxy_password); |
| + | if(sx->user && sx->passwd) { |
| + | ulen = strlen(sx->user); |
| + | plen = strlen(sx->passwd); |
| /* the lengths must fit in a single byte */ | |
| if(ulen > 255) { | |
| failf(data, "Excessive username length for proxy auth"); | |
| @@ -712,7 +713,7 @@ static CURLproxycode socks5_auth_init(struct Curl_cfilter *cf, | |
| if(result || (nwritten != 2)) | |
| return CURLPX_SEND_REQUEST; | |
| if(ulen) { | |
| - | result = Curl_bufq_cwrite(&sx->iobuf, sx->proxy_user, ulen, &nwritten); |
| + | result = Curl_bufq_cwrite(&sx->iobuf, sx->user, ulen, &nwritten); |
| if(result || (nwritten != ulen)) | |
| return CURLPX_SEND_REQUEST; | |
| } | |
| @@ -721,7 +722,7 @@ static CURLproxycode socks5_auth_init(struct Curl_cfilter *cf, | |
| if(result || (nwritten != 1)) | |
| return CURLPX_SEND_REQUEST; | |
| if(plen) { | |
| - | result = Curl_bufq_cwrite(&sx->iobuf, sx->proxy_password, plen, &nwritten); |
| + | result = Curl_bufq_cwrite(&sx->iobuf, sx->passwd, plen, &nwritten); |
| if(result || (nwritten != plen)) | |
| return CURLPX_SEND_REQUEST; | |
| } | |
| @@ -729,7 +730,7 @@ static CURLproxycode socks5_auth_init(struct Curl_cfilter *cf, | |
| return CURLPX_OK; | |
| } | |
| - | static CURLproxycode socks5_check_auth_resp(struct socks_state *sx, |
| + | static CURLproxycode socks5_check_auth_resp(struct socks_ctx *sx, |
| struct Curl_cfilter *cf, | |
| struct Curl_easy *data) | |
| { | |
| @@ -754,7 +755,7 @@ static CURLproxycode socks5_check_auth_resp(struct socks_state *sx, | |
| return CURLPX_OK; | |
| } | |
| - | static CURLproxycode socks5_req1_init(struct socks_state *sx, |
| + | static CURLproxycode socks5_req1_init(struct socks_ctx *sx, |
| struct Curl_cfilter *cf, | |
| struct Curl_easy *data) | |
| { | |
| @@ -823,7 +824,7 @@ static CURLproxycode socks5_req1_init(struct socks_state *sx, | |
| return CURLPX_OK; | |
| } | |
| - | static CURLproxycode socks5_resolving(struct socks_state *sx, |
| + | static CURLproxycode socks5_resolving(struct socks_ctx *sx, |
| struct Curl_cfilter *cf, | |
| struct Curl_easy *data, | |
| bool *done) | |
| @@ -842,9 +843,8 @@ static CURLproxycode socks5_resolving(struct socks_state *sx, | |
| if(sx->start_resolving) { | |
| /* need to resolve hostname to add destination address */ | |
| sx->start_resolving = FALSE; | |
| - | DEBUGASSERT(sx->hostname && *sx->hostname); |
| result = Curl_cf_dns_insert_after( | |
| - | cf, data, Curl_resolv_dns_queries(data, cf->conn->ip_version), |
| + | cf, data, Curl_resolv_dns_queries(data, sx->ip_version), |
| sx->hostname, sx->remote_port, TRNSPRT_TCP, TRUE); | |
| if(result) { | |
| failf(data, "unable to create DNS filter for socks"); | |
| @@ -928,7 +928,7 @@ out: | |
| return presult; | |
| } | |
| - | static CURLproxycode socks5_recv_resp1(struct socks_state *sx, |
| + | static CURLproxycode socks5_recv_resp1(struct socks_ctx *sx, |
| struct Curl_cfilter *cf, | |
| struct Curl_easy *data, | |
| bool *done) | |
| @@ -1027,7 +1027,7 @@ static CURLproxycode socks5_recv_resp1(struct socks_state *sx, | |
| * destination server. | |
| */ | |
| static CURLproxycode socks5_connect(struct Curl_cfilter *cf, | |
| - | struct socks_state *sx, |
| + | struct socks_ctx *sx, |
| struct Curl_easy *data) | |
| { | |
| CURLproxycode presult; | |
| @@ -1037,14 +1037,13 @@ process_state: | |
| switch(sx->state) { | |
| case SOCKS_ST_INIT: | |
| sx->version = 5; | |
| - | sx->resolve_local = (cf->conn->socks_proxy.proxytype == CURLPROXY_SOCKS5); |
| + | sx->resolve_local = (sx->proxy_type == CURLPROXY_SOCKS5); |
| sxstate(sx, cf, data, SOCKS5_ST_START); | |
| FALLTHROUGH(); | |
| case SOCKS5_ST_START: | |
| - | if(cf->conn->bits.httpproxy) |
| - | CURL_TRC_CF(data, cf, "SOCKS5: connecting to HTTP proxy %s port %u", |
| - | sx->hostname, sx->remote_port); |
| + | CURL_TRC_CF(data, cf, "SOCKS5: connecting to %s:%u", |
| + | sx->hostname, sx->remote_port); |
| presult = socks5_req0_init(cf, sx, data); | |
| if(presult) | |
| return socks_failed(sx, cf, data, presult); | |
| @@ -1179,13 +1178,11 @@ process_state: | |
| } | |
| } | |
| - | static void socks_proxy_cf_free(struct Curl_cfilter *cf) |
| + | static void socks_proxy_ctx_free(struct socks_ctx *ctx) |
| { | |
| - | struct socks_state *sxstate = cf->ctx; |
| - | if(sxstate) { |
| - | Curl_bufq_free(&sxstate->iobuf); |
| - | curlx_free(sxstate); |
| - | cf->ctx = NULL; |
| + | if(ctx) { |
| + | Curl_bufq_free(&ctx->iobuf); |
| + | curlx_free(ctx); |
| } | |
| } | |
| @@ -1200,11 +1197,9 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf, | |
| struct Curl_easy *data, | |
| bool *done) | |
| { | |
| - | CURLcode result; |
| - | struct connectdata *conn = cf->conn; |
| - | int sockindex = cf->sockindex; |
| - | struct socks_state *sx = cf->ctx; |
| + | struct socks_ctx *ctx = cf->ctx; |
| CURLproxycode pxresult = CURLPX_OK; | |
| + | CURLcode result; |
| if(cf->connected) { | |
| *done = TRUE; | |
| @@ -1215,47 +1210,19 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf, | |
| if(result || !*done) | |
| return result; | |
| - | if(!sx) { |
| - | cf->ctx = sx = curlx_calloc(1, sizeof(*sx)); |
| - | if(!sx) { |
| - | result = CURLE_OUT_OF_MEMORY; |
| - | goto out; |
| - | } |
| - | |
| - | /* for the secondary socket (FTP), use the "connect to host" |
| - | * but ignore the "connect to port" (use the secondary port) |
| - | */ |
| - | sx->hostname = |
| - | conn->bits.httpproxy ? |
| - | conn->http_proxy.host.name : |
| - | conn->bits.conn_to_host ? |
| - | conn->conn_to_host.name : |
| - | sockindex == SECONDARYSOCKET ? |
| - | conn->secondaryhostname : conn->host.name; |
| - | sx->remote_port = |
| - | conn->bits.httpproxy ? conn->http_proxy.port : |
| - | sockindex == SECONDARYSOCKET ? conn->secondary_port : |
| - | conn->bits.conn_to_port ? conn->conn_to_port : |
| - | (uint16_t)conn->remote_port; |
| - | sx->proxy_user = conn->socks_proxy.user; |
| - | sx->proxy_password = conn->socks_proxy.passwd; |
| - | Curl_bufq_init2(&sx->iobuf, SOCKS_CHUNK_SIZE, SOCKS_CHUNKS, |
| - | BUFQ_OPT_SOFT_LIMIT); |
| - | } |
| - | |
| - | switch(conn->socks_proxy.proxytype) { |
| + | switch(ctx->proxy_type) { |
| case CURLPROXY_SOCKS5: | |
| case CURLPROXY_SOCKS5_HOSTNAME: | |
| - | pxresult = socks5_connect(cf, sx, data); |
| + | pxresult = socks5_connect(cf, ctx, data); |
| break; | |
| case CURLPROXY_SOCKS4: | |
| case CURLPROXY_SOCKS4A: | |
| - | pxresult = socks4_connect(cf, sx, data); |
| + | pxresult = socks4_connect(cf, ctx, data); |
| break; | |
| default: | |
| - | failf(data, "unknown proxytype option given"); |
| + | DEBUGASSERT(0); /* should not come here, checked it at creation time */ |
| result = CURLE_COULDNT_CONNECT; | |
| goto out; | |
| } | |
| @@ -1265,7 +1232,7 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf, | |
| data->info.pxcode = pxresult; | |
| goto out; | |
| } | |
| - | else if(sx->state != SOCKS_ST_SUCCESS) |
| + | else if(ctx->state != SOCKS_ST_SUCCESS) |
| goto out; | |
| #ifdef CURLVERBOSE | |
| @@ -1275,20 +1242,23 @@ static CURLcode socks_proxy_cf_connect(struct Curl_cfilter *cf, | |
| if(!Curl_conn_cf_get_ip_info(cf->next, data, &is_ipv6, &ipquad)) | |
| infof(data, "Opened %sSOCKS connection from %s port %d to %s port %d " | |
| "(via %s port %u)", | |
| - | (sockindex == SECONDARYSOCKET) ? "2nd " : "", |
| + | (cf->sockindex == SECONDARYSOCKET) ? "2nd " : "", |
| ipquad.local_ip, ipquad.local_port, | |
| - | sx->hostname, sx->remote_port, |
| + | ctx->hostname, ctx->remote_port, |
| ipquad.remote_ip, ipquad.remote_port); | |
| else | |
| infof(data, "Opened %sSOCKS connection", | |
| - | (sockindex == SECONDARYSOCKET) ? "2nd " : ""); |
| + | (cf->sockindex == SECONDARYSOCKET) ? "2nd " : ""); |
| } | |
| #endif | |
| - | socks_proxy_cf_free(cf); |
| cf->connected = TRUE; | |
| out: | |
| *done = (bool)cf->connected; | |
| + | if(*done || result) { |
| + | ctx->user = NULL; |
| + | ctx->passwd = NULL; |
| + | } |
| return result; | |
| } | |
| @@ -1296,7 +1266,7 @@ static CURLcode socks_cf_adjust_pollset(struct Curl_cfilter *cf, | |
| struct Curl_easy *data, | |
| struct easy_pollset *ps) | |
| { | |
| - | struct socks_state *sx = cf->ctx; |
| + | struct socks_ctx *sx = cf->ctx; |
| CURLcode result = CURLE_OK; | |
| if(!cf->connected && sx) { | |
| @@ -1323,24 +1293,24 @@ static CURLcode socks_cf_adjust_pollset(struct Curl_cfilter *cf, | |
| static void socks_proxy_cf_close(struct Curl_cfilter *cf, | |
| struct Curl_easy *data) | |
| { | |
| - | DEBUGASSERT(cf->next); |
| cf->connected = FALSE; | |
| - | socks_proxy_cf_free(cf); |
| - | cf->next->cft->do_close(cf->next, data); |
| + | if(cf->next) |
| + | cf->next->cft->do_close(cf->next, data); |
| } | |
| static void socks_proxy_cf_destroy(struct Curl_cfilter *cf, | |
| struct Curl_easy *data) | |
| { | |
| (void)data; | |
| - | socks_proxy_cf_free(cf); |
| + | socks_proxy_ctx_free(cf->ctx); |
| + | cf->ctx = NULL; |
| } | |
| static CURLcode socks_cf_query(struct Curl_cfilter *cf, | |
| struct Curl_easy *data, | |
| int query, int *pres1, void *pres2) | |
| { | |
| - | struct socks_state *sx = cf->ctx; |
| + | struct socks_ctx *sx = cf->ctx; |
| switch(query) { | |
| case CF_QUERY_HOST_PORT: | |
| @@ -1383,15 +1353,53 @@ struct Curl_cftype Curl_cft_socks_proxy = { | |
| }; | |
| CURLcode Curl_cf_socks_proxy_insert_after(struct Curl_cfilter *cf_at, | |
| - | struct Curl_easy *data) |
| + | struct Curl_easy *data, |
| + | const char *hostname, |
| + | uint16_t port, |
| + | uint8_t ip_version, |
| + | uint8_t proxy_type, |
| + | const char *user, |
| + | const char *passwd) |
| { | |
| struct Curl_cfilter *cf; | |
| + | struct socks_ctx *ctx; |
| + | size_t hostlen = hostname ? strlen(hostname) : 0; |
| CURLcode result; | |
| - | (void)data; |
| - | result = Curl_cf_create(&cf, &Curl_cft_socks_proxy, NULL); |
| + | if(!hostlen) |
| + | return CURLE_FAILED_INIT; |
| + | |
| + | switch(proxy_type) { |
| + | case CURLPROXY_SOCKS5: |
| + | case CURLPROXY_SOCKS5_HOSTNAME: |
| + | case CURLPROXY_SOCKS4: |
| + | case CURLPROXY_SOCKS4A: |
| + | break; /* all supported */ |
| + | default: |
| + | failf(data, "unknown proxytype %d option given", proxy_type); |
| + | return CURLE_COULDNT_CONNECT; |
| + | } |
| + | |
| + | /* NUL byte already part of struct size */ |
| + | ctx = curlx_calloc(1, sizeof(*ctx) + hostlen); |
| + | if(!ctx) { |
| + | return CURLE_OUT_OF_MEMORY; |
| + | } |
| + | |
| + | memcpy(ctx->hostname, hostname, hostlen); |
| + | ctx->remote_port = port; |
| + | ctx->ip_version = ip_version; |
| + | ctx->proxy_type = proxy_type; |
| + | ctx->user = user; |
| + | ctx->passwd = passwd; |
| + | Curl_bufq_init2(&ctx->iobuf, SOCKS_CHUNK_SIZE, SOCKS_CHUNKS, |
| + | BUFQ_OPT_SOFT_LIMIT); |
| + | |
| + | result = Curl_cf_create(&cf, &Curl_cft_socks_proxy, ctx); |
| if(!result) | |
| Curl_conn_cf_insert_after(cf_at, cf); | |
| + | else |
| + | socks_proxy_ctx_free(ctx); |
| return result; | |
| } | |
| @@ -46,8 +46,19 @@ CURLcode Curl_SOCKS5_gssapi_negotiate(struct Curl_cfilter *cf, | |
| struct Curl_easy *data); | |
| #endif | |
| + | /* Insert a SOCKS filter after `cf_at` for connecting to `hostname` |
| + | * and `port` with optional credentials. |
| + | * Credentials are NOT duplicated and are |
| + | * expected to exist during connect phase. |
| + | */ |
| CURLcode Curl_cf_socks_proxy_insert_after(struct Curl_cfilter *cf_at, | |
| - | struct Curl_easy *data); |
| + | struct Curl_easy *data, |
| + | const char *hostname, |
| + | uint16_t port, |
| + | uint8_t ip_version, |
| + | uint8_t proxy_type, |
| + | const char *user, |
| + | const char *passwd); |
| extern struct Curl_cftype Curl_cft_socks_proxy; | |