Added CURLOPT_LOCALPORT and CURLOPT_LOCALPORTRANGE to libcurl. Set with the

curl tool with --local-port. Plain and simply set the range of ports to bind
the local end of connections to. Implemented on to popular demand.

Not extensively tested. Please let me know how it works.
This commit is contained in:
Daniel Stenberg 2006-01-30 08:24:07 +00:00
parent 32bc30e210
commit 2fbf94b0f3
9 changed files with 196 additions and 103 deletions

View File

@ -7,6 +7,10 @@
Changelog
Daniel (30 January 2006)
- Added CURLOPT_LOCALPORT and CURLOPT_LOCALPORTRANGE to libcurl. Set with the
curl tool with --local-port. Plain and simply set the range of ports to bind
the local end of connections to. Implemented on to popular demand.
- Based on an error report by Philippe Vaucher, we no longer count a retried
connection setup as a follow-redirect. It turns out 1) this fails when a FTP
connection is re-setup and 2) it does make the max-redirs counter behave

View File

@ -5,12 +5,14 @@ Curl and libcurl 7.15.2
Available command line options: 109
Available curl_easy_setopt() options: 125
Number of public functions in libcurl: 46
Amount of public web site mirrors: 28
Amount of public web site mirrors: 30
Number of known libcurl bindings: 32
Number of contributors: 474
This release includes the following changes:
o CURLOPT_LOCALPORT and CURLOPT_LOCALPORTRANGE (--local-port) added
o Dropped support for the LPRT ftp command
o Gopher is now officially abandoned as a protocol (lib)curl tries to support.
o curl_global_init() and curl_global_cleanup() are now using a refcount so
that it is now legal to call them multiple times. See updated info for
@ -22,7 +24,7 @@ This release includes the following bugfixes:
redirect and thus prevents a weird error that would occur if a FTP
connection died on an attempted re-use
o Try PASV after failing to connect to the port the EPSV response contained
o -P [IP] with ipv6-enabled curl
o -P [IP] with non-local address with ipv6-enabled curl
o -P [hostname] with ipv6-disabled curl
o libcurl.m4 was updated
o configure no longer warns if the current path contains a space

View File

@ -5,7 +5,7 @@
.\" * | (__| |_| | _ <| |___
.\" * \___|\___/|_| \_\_____|
.\" *
.\" * Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
.\" *
.\" * This software is licensed as described in the file COPYING, which
.\" * you should have received as part of this distribution. The terms
@ -100,7 +100,7 @@ most secure one the remote site claims it supports. This is done by first
doing a request and checking the response-headers, thus inducing an extra
network round-trip. This is used instead of setting a specific authentication
method, which you can do with \fI--basic\fP, \fI--digest\fP, \fI--ntlm\fP, and
\fI--negotiate\fP. (Added in 7.10.6)
\fI--negotiate\fP.
Note that using --anyauth is not recommended if you do uploads from stdin,
since it may require data to be sent twice and then the client must be able to
@ -140,7 +140,7 @@ If this option is used twice, the second one will disable ASCII usage.
(HTTP) Tells curl to use HTTP Basic authentication. This is the default and
this option is usually pointless, unless you use it to override a previously
set option that sets a different authentication method (such as \fI--ntlm\fP,
\fI--digest\fP and \fI--negotiate\fP). (Added in 7.10.6)
\fI--digest\fP and \fI--negotiate\fP).
If this option is used several times, the following occurrences make no
difference.
@ -243,7 +243,7 @@ append data.
prevents the password from being sent over the wire in clear text. Use this in
combination with the normal \fI-u/--user\fP option to set user name and
password. See also \fI--ntlm\fP, \fI--negotiate\fP and \fI--anyauth\fP for
related options. (Added in curl 7.10.6)
related options.
If this option is used several times, the following occurrences make no
difference.
@ -253,7 +253,7 @@ active FTP transfers. Curl will normally always first attempt to use EPRT,
then LPRT before using PORT, but with this option, it will use PORT right
away. EPRT and LPRT are extensions to the original FTP protocol, may not work
on all servers but enable more functionality in a better way than the
traditional PORT command. (Added in 7.10.5)
traditional PORT command.
If this option is used several times, each occurrence will toggle this on/off.
.IP "--disable-epsv"
@ -351,7 +351,7 @@ If this option is used twice, the second will override the previous use.
.IP "--ftp-create-dirs"
(FTP) When an FTP URL/operation uses a path that doesn't currently exist on
the server, the standard behavior of curl is to fail. Using this option, curl
will instead attempt to create missing directories. (Added in 7.10.7)
will instead attempt to create missing directories.
If this option is used twice, the second will again disable directory creation.
.IP "--ftp-pasv"
@ -484,15 +484,14 @@ If this option is used twice, the second will again disable header only.
(HTTP) When curl is told to read cookies from a given file, this option will
make it discard all "session cookies". This will basically have the same effect
as if a new session is started. Typical browsers always discard session
cookies when they're closed down. (Added in 7.9.7)
cookies when they're closed down.
If this option is used several times, each occurrence will toggle this on/off.
.IP "-k/--insecure"
(SSL) This option explicitly allows curl to perform "insecure" SSL connections
and transfers. Starting with curl 7.10, all SSL connections will be attempted
to be made secure by using the CA certificate bundle installed by
default. This makes all connections considered "insecure" to fail unless
\fI-k/--insecure\fP is used.
and transfers. All SSL connections are attempted to be made secure by using
the CA certificate bundle installed by default. This makes all connections
considered "insecure" to fail unless \fI-k/--insecure\fP is used.
If this option is used twice, the second time will again disable it.
.IP "--key <key>"
@ -559,8 +558,6 @@ If you are also using the \fI-Y/--speed-limit\fP option, that option will take
precedence and might cripple the rate-limiting slightly, to help keeping the
speed-limit logic working.
This option was introduced in curl 7.10.
If this option is used several times, the last one will be used.
.IP "-l/--list-only"
(FTP)
@ -574,6 +571,11 @@ list only files in their response to NLST; they do not include
subdirectories and symbolic links.
If this option is used twice, the second will again disable list only.
.IP "--local-port <num>[-num]"
Set a prefered number or range of local port numbers to use for the
connection(s). Note that port numbers by nature is a scarce resource that
will be busy at times so setting this range to something too narrow might
cause unnecessary connection setup failures. (Added in 7.15.2)
.IP "-L/--location"
(HTTP/HTTPS) If the server reports that the requested page has moved to a
different location (indicated with a Location: header and a 3XX response code)
@ -637,7 +639,7 @@ Very similar to \fI--netrc\fP, but this option makes the .netrc usage
designed by Microsoft and is used in their web applications. It is primarily
meant as a support for Kerberos5 authentication but may be also used along
with another authentication methods. For more information see IETF draft
draft-brezak-spnego-http-04.txt. (Added in 7.10.6)
draft-brezak-spnego-http-04.txt.
This option requires that the library was built with GSSAPI support. This is
not very common. Use \fI-V/--version\fP to see if your version supports
@ -662,7 +664,7 @@ designed by Microsoft and is used by IIS web servers. It is a proprietary
protocol, reversed engineered by clever people and implemented in curl based
on their efforts. This kind of behavior should not be endorsed, you should
encourage everyone who uses NTLM to switch to a public and documented
authentication method instead. Such as Digest. (Added in 7.10.6)
authentication method instead. Such as Digest.
If you want to enable NTLM for your proxy authentication, then use
\fI--proxy-ntlm\fP.
@ -702,8 +704,8 @@ You may use this option as many times as you have number of URLs.
If this option is used several times, the last one will be used.
.IP "--proxy-anyauth"
Tells curl to pick a suitable authentication method when communicating with
the given proxy. This will cause an extra request/response round-trip. Added
in curl 7.13.2.
the given proxy. This will cause an extra request/response round-trip. (Added
in 7.13.2)
If this option is used twice, the second will again disable the proxy use-any
authentication.
@ -894,13 +896,10 @@ this is used on a http(s) server, the PUT command will be used.
Use the file name "-" (a single dash) to use stdin instead of a given file.
Before 7.10.8, when this option was used several times, the last one was used.
In curl 7.10.8 and later, you can specify one -T for each URL on the command
line. Each -T + URL pair specifies what to upload and to where. curl also
supports "globbing" of the -T argument, meaning that you can upload multiple
files to a single URL by using the same URL globbing style supported in the
URL, like this:
You can specify one -T for each URL on the command line. Each -T + URL pair
specifies what to upload and to where. curl also supports "globbing" of the -T
argument, meaning that you can upload multiple files to a single URL by using
the same URL globbing style supported in the URL, like this:
curl -T "{file1,file2}" http://www.uploadtothissite.com
@ -911,7 +910,6 @@ curl -T "img[1-1000].png" ftp://ftp.picturemania.com/upload/
Enables a full trace dump of all incoming and outgoing data, including
descriptive information, to the given output file. Use "-" as filename to have
the output sent to stdout.
(Added in 7.9.7)
If this option is used several times, the last one will be used.
.IP "--trace-ascii <file>"
@ -922,7 +920,6 @@ the output sent to stdout.
This is very similar to \fI--trace\fP, but leaves out the hex part and only
shows the ASCII part of the dump. It makes smaller output that might be easier
to read for untrained humans.
(Added in 7.9.7)
If this option is used several times, the last one will be used.
.IP "--trace-time"
@ -1083,7 +1080,7 @@ The average download speed that curl measured for the complete download.
The average upload speed that curl measured for the complete upload.
.TP
.B content_type
The Content-Type of the requested document, if there was any. (Added in 7.9.5)
The Content-Type of the requested document, if there was any.
.TP
.B num_connects
Number of new connects made in the recent transfer. (Added in 7.12.3)
@ -1182,11 +1179,11 @@ Note that not all FTP server allow 3rd party transfers. (Added in 7.13.0)
.IP "-4/--ipv4"
If libcurl is capable of resolving an address to multiple IP versions (which
it is if it is ipv6-capable), this option tells libcurl to resolve names to
IPv4 addresses only. (Added in 7.10.8)
IPv4 addresses only.
.IP "-6/--ipv6"
If libcurl is capable of resolving an address to multiple IP versions (which
it is if it is ipv6-capable), this option tells libcurl to resolve names to
IPv6 addresses only. (Added in 7.10.8)
IPv6 addresses only.
.IP "-#/--progress-bar"
Make curl display progress information as a progress bar instead of the
default statistics.

View File

@ -21,7 +21,7 @@
.\" * $Id$
.\" **************************************************************************
.\"
.TH curl_easy_setopt 3 "27 Oct 2005" "libcurl 7.14.2" "libcurl Manual"
.TH curl_easy_setopt 3 "28 Jan 2006" "libcurl 7.15.2" "libcurl Manual"
.SH NAME
curl_easy_setopt \- set options for a curl easy handle
.SH SYNOPSIS
@ -335,6 +335,19 @@ don't want this tunneling option.
Pass a char * as parameter. This set the interface name to use as outgoing
network interface. The name can be an interface name, an IP address or a host
name.
.IP CURLOPT_LOCALPORT
Pass a long. This sets the local port number of the socket used for
connection. This can be used in combination with \fICURLOPT_INTERFACE\fP and
you are recommended to use \fICURLOPT_LOCALPORTRANGE\fP as well when this is
set. Note that port numbers are only valid 1 - 65535. (Added in 7.15.2)
.IP CURLOPT_LOCALPORTRANGE
Pass a long. This is the number of attempts libcurl should do to find a
working local port number. It starts with the given \fICURLOPT_LOCALPORT\fP
and adds one to the number for each retry. Setting this value to 1 or below
will make libcurl do only one try for exact port number. Note that port
numbers by nature is a scarce resource that will be busy at times so setting
this value to something too low might cause unnecessary connection setup
failures. (Added in 7.15.2)
.IP CURLOPT_DNS_CACHE_TIMEOUT
Pass a long, this sets the timeout in seconds. Name resolves will be kept in
memory for this number of seconds. Set to zero (0) to completely disable

View File

@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -915,6 +915,14 @@ typedef enum {
/* Select "file method" to use when doing FTP */
CINIT(FTP_FILEMETHOD, LONG, 138),
/* Local port number to bind the socket to */
CINIT(LOCALPORT, LONG, 139),
/* Number of ports to try, including the first one set with LOCALPORT.
Thus, setting it to 1 will make no additional attempts but the first.
*/
CINIT(LOCALPORTRANGE, LONG, 140),
CURLOPT_LASTENTRY /* the last unused */
} CURLoption;

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -98,6 +98,7 @@
#include "memory.h"
#include "select.h"
#include "url.h" /* for Curl_safefree() */
#include "sockaddr.h" /* required for Curl_sockaddr_storage */
/* The last #include file should be: */
#include "memdebug.h"
@ -239,16 +240,20 @@ int waitconnect(curl_socket_t sockfd, /* socket */
static CURLcode bindlocal(struct connectdata *conn,
curl_socket_t sockfd)
{
#ifdef HAVE_INET_NTOA
bool bindworked = FALSE;
struct SessionHandle *data = conn->data;
struct sockaddr_in me;
struct sockaddr *sock = NULL; /* bind to this address */
socklen_t socksize; /* size of the data sock points to */
unsigned short port = data->set.localport; /* use this port number, 0 for
"random" */
/* how many port numbers to try to bind to, increasing one at a time */
int portnum = data->set.localportrange;
/*************************************************************
* Select device to bind socket to
*************************************************************/
if (strlen(data->set.device)<255) {
if (data->set.device && (strlen(data->set.device)<255) ) {
struct Curl_dns_entry *h=NULL;
size_t size;
char myhost[256] = "";
in_addr_t in;
int rc;
@ -266,8 +271,10 @@ static CURLcode bindlocal(struct connectdata *conn,
if(rc == CURLRESOLV_PENDING)
(void)Curl_wait_for_resolv(conn, &h);
if(h)
if(h) {
was_iface = TRUE;
Curl_resolv_unlock(data, h);
}
}
if(!was_iface) {
@ -279,9 +286,11 @@ static CURLcode bindlocal(struct connectdata *conn,
if(rc == CURLRESOLV_PENDING)
(void)Curl_wait_for_resolv(conn, &h);
if(h)
if(h) {
/* we know data->set.device is shorter than the myhost array */
strcpy(myhost, data->set.device);
Curl_resolv_unlock(data, h);
}
}
if(! *myhost) {
@ -295,7 +304,7 @@ static CURLcode bindlocal(struct connectdata *conn,
return CURLE_HTTP_PORT_FAILED;
}
infof(data, "We bind local end to %s\n", myhost);
infof(data, "Bind local address to %s\n", myhost);
#ifdef SO_BINDTODEVICE
/* I am not sure any other OSs than Linux that provide this feature, and
@ -323,60 +332,79 @@ static CURLcode bindlocal(struct connectdata *conn,
#endif
in=inet_addr(myhost);
if (CURL_INADDR_NONE != in) {
if ( h ) {
Curl_addrinfo *addr = h->addr;
Curl_resolv_unlock(data, h);
/* we don't need it anymore after this function has returned */
if( bind(sockfd, addr->ai_addr, (socklen_t)addr->ai_addrlen) >= 0) {
/* we succeeded to bind */
#ifdef ENABLE_IPV6
struct sockaddr_in6 add;
#else
struct sockaddr_in add;
#endif
bindworked = TRUE;
size = sizeof(add);
if(getsockname(sockfd, (struct sockaddr *) &add,
(socklen_t *)&size)<0) {
failf(data, "getsockname() failed");
return CURLE_HTTP_PORT_FAILED;
}
}
if(!bindworked) {
data->state.os_errno = Curl_ourerrno();
failf(data, "bind failure: %s",
Curl_strerror(conn, data->state.os_errno));
return CURLE_HTTP_PORT_FAILED;
}
} /* end of if h */
else {
failf(data,"couldn't find my own IP address (%s)", myhost);
return CURLE_HTTP_PORT_FAILED;
}
if (CURL_INADDR_NONE == in) {
failf(data,"couldn't find my own IP address (%s)", myhost);
return CURLE_HTTP_PORT_FAILED;
} /* end of inet_addr */
else {
failf(data, "couldn't find my own IP address (%s)", myhost);
return CURLE_HTTP_PORT_FAILED;
if ( h ) {
Curl_addrinfo *addr = h->addr;
sock = addr->ai_addr;
socksize = addr->ai_addrlen;
}
else
return CURLE_HTTP_PORT_FAILED;
}
else if(port) {
/* if a local port number is requested but no local IP, extract the
address from the socket */
memset(&me, 0, sizeof(struct sockaddr));
me.sin_family = AF_INET;
me.sin_addr.s_addr = INADDR_ANY;
sock = (struct sockaddr *)&me;
socksize = sizeof(struct sockaddr);
}
else
/* no local kind of binding was requested */
return CURLE_OK;
} /* end of device selection support */
#else
(void)conn;
(void)sockfd;
#endif /* end of HAVE_INET_NTOA */
do {
/* Set port number to bind to, 0 makes the system pick one */
if(sock->sa_family == AF_INET)
((struct sockaddr_in *)sock)->sin_port = htons(port);
#ifdef ENABLE_IPV6
else
((struct sockaddr_in6 *)sock)->sin6_port = htons(port);
#endif
if( bind(sockfd, sock, socksize) >= 0) {
/* we succeeded to bind */
struct Curl_sockaddr_storage add;
unsigned short port;
size_t size;
size = sizeof(add);
if(getsockname(sockfd, (struct sockaddr *) &add,
(socklen_t *)&size)<0) {
failf(data, "getsockname() failed");
return CURLE_HTTP_PORT_FAILED;
}
if(((struct sockaddr *)&add)->sa_family == AF_INET)
port = ntohs(((struct sockaddr_in *)&add)->sin_port);
#ifdef ENABLE_IPV6
else
port = ntohs(((struct sockaddr_in6 *)&add)->sin6_port);
#endif
infof(data, "Local port: %d\n", port);
return CURLE_OK;
}
if(--portnum > 0) {
infof(data, "Bind to local port %d failed, trying next\n", port);
port++; /* try next port */
}
else
break;
} while(1);
data->state.os_errno = Curl_ourerrno();
failf(data, "bind failure: %s",
Curl_strerror(conn, data->state.os_errno));
return CURLE_HTTP_PORT_FAILED;
}
/*
@ -618,6 +646,8 @@ static void nosigpipe(struct connectdata *conn,
infof(data, "Could not set SO_NOSIGPIPE: %s\n",
Curl_strerror(conn, Curl_ourerrno()));
}
#else
#define nosigpipe(x,y)
#endif
/* singleipconnect() connects to the given IP only, and it may return without
@ -634,6 +664,7 @@ singleipconnect(struct connectdata *conn,
bool isconnected;
struct SessionHandle *data = conn->data;
curl_socket_t sockfd;
CURLcode res;
sockfd = socket(ai->ai_family, conn->socktype, ai->ai_protocol);
if (sockfd == CURL_SOCKET_BAD)
@ -647,17 +678,13 @@ singleipconnect(struct connectdata *conn,
if(data->set.tcp_nodelay)
tcpnodelay(conn, sockfd);
#ifdef SO_NOSIGPIPE
nosigpipe(conn, sockfd);
#endif
if(conn->data->set.device) {
/* user selected to bind the outgoing socket to a specified "device"
before doing connect */
CURLcode res = bindlocal(conn, sockfd);
if(res) {
sclose(sockfd); /* close socket and bail out */
return CURL_SOCKET_BAD;
}
/* possibly bind the local end to an IP, interface or port */
res = bindlocal(conn, sockfd);
if(res) {
sclose(sockfd); /* close socket and bail out */
return CURL_SOCKET_BAD;
}
/* set socket non-blocking */

View File

@ -1222,13 +1222,26 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
*/
data->set.crlf = va_arg(param, long)?TRUE:FALSE;
break;
case CURLOPT_INTERFACE:
/*
* Set what interface to bind to when performing an operation and thus
* what from-IP your connection will use.
* Set what interface or address/hostname to bind the socket to when
* performing an operation and thus what from-IP your connection will use.
*/
data->set.device = va_arg(param, char *);
break;
case CURLOPT_LOCALPORT:
/*
* Set what local port to bind the socket to when performing an operation.
*/
data->set.localport = (unsigned short) va_arg(param, long);
break;
case CURLOPT_LOCALPORTRANGE:
/*
* Set number of local ports to try, starting with CURLOPT_LOCALPORT.
*/
data->set.localportrange = (int) va_arg(param, long);
break;
case CURLOPT_KRB4LEVEL:
/*
* A string that defines the krb4 security level.

View File

@ -970,7 +970,10 @@ struct UserDefined {
of strlen(), and then the data *may* be binary
(contain zero bytes) */
char *ftpport; /* port to send with the FTP PORT command */
char *device; /* network interface to use */
char *device; /* local network interface/address to use */
unsigned short localport; /* local port number to bind to */
int localportrange; /* number of additional port numbers to test in case the
'localport' one can't be bind()ed */
curl_write_callback fwrite; /* function that stores the output */
curl_write_callback fwrite_header; /* function that stores headers */
curl_read_callback fread; /* function that reads the input */

View File

@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@ -271,6 +271,8 @@ struct Configurable {
char *headerfile;
char *ftpport;
char *iface;
int localport;
int localportrange;
unsigned short porttouse;
char *range;
long low_speed_limit;
@ -519,12 +521,13 @@ static void help(void)
" -i/--include Include protocol headers in the output (H/F)",
" -I/--head Show document info only",
" -j/--junk-session-cookies Ignore session cookies read from file (H)",
" --interface <interface> Specify network interface to use",
" --interface <interface> Specify network interface/address to use",
" --krb4 <level> Enable krb4 with specified security level (F)",
" -k/--insecure Allow connections to SSL sites without certs (H)",
" -K/--config Specify which config file to read",
" -l/--list-only List only names of an FTP directory (F)",
" --limit-rate <rate> Limit transfer speed to this rate",
" --local-port <num>[-num] Force use of these local port numbers\n",
" -L/--location Follow Location: hints (H)",
" --location-trusted Follow Location: and send authentication even ",
" to other hostnames (H)",
@ -1261,7 +1264,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{
char letter;
char subletter=0; /* subletters can only occur on long options */
int rc; /* generic return code variable */
const char *parse=NULL;
unsigned int j;
time_t now;
@ -1326,6 +1329,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{"$p", "ignore-content-length", FALSE},
{"$q", "ftp-skip-pasv-ip", FALSE},
{"$r", "ftp-method", TRUE},
{"$s", "local-port", TRUE},
{"0", "http1.0", FALSE},
{"1", "tlsv1", FALSE},
@ -1739,6 +1743,22 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
case 'r': /* --ftp-method (undocumented at this point) */
config->ftp_filemethod = ftpfilemethod(config, nextarg);
break;
case 's': /* --local-port */
rc = sscanf(nextarg, "%d - %d",
&config->localport,
&config->localportrange);
if(!rc)
return PARAM_BAD_USE;
else if(rc == 1)
config->localportrange = 1; /* default number of ports to try */
else {
config->localportrange -= config->localport;
if(config->localportrange < 1) {
warnf(config, "bad range input\n");
return PARAM_BAD_USE;
}
}
break;
}
break;
case '#': /* --progress-bar */
@ -3972,6 +3992,12 @@ operate(struct Configurable *config, int argc, char *argv[])
/* curl 7.15.1 */
curl_easy_setopt(curl, CURLOPT_FTP_FILEMETHOD, config->ftp_filemethod);
/* curl 7.15.2 */
if(config->localport) {
curl_easy_setopt(curl, CURLOPT_LOCALPORT, config->localport);
curl_easy_setopt(curl, CURLOPT_LOCALPORTRANGE, config->localportrange);
}
retry_numretries = config->req_retry;
retrystart = curlx_tvnow();