aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2006-01-30 08:24:07 +0000
committerDaniel Stenberg <daniel@haxx.se>2006-01-30 08:24:07 +0000
commit2fbf94b0f309de9bd9153274bb475abc744afb0a (patch)
treef2e9a364ed27e4f115931be6e424138268b6bee0
parent32bc30e210ea41552f3dee64edd290a129020dc7 (diff)
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.
-rw-r--r--CHANGES4
-rw-r--r--RELEASE-NOTES6
-rw-r--r--docs/curl.155
-rw-r--r--docs/libcurl/curl_easy_setopt.315
-rw-r--r--include/curl/curl.h10
-rw-r--r--lib/connect.c147
-rw-r--r--lib/url.c17
-rw-r--r--lib/urldata.h5
-rw-r--r--src/main.c32
9 files changed, 192 insertions, 99 deletions
diff --git a/CHANGES b/CHANGES
index bfdb1495d..d61a42b29 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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
diff --git a/RELEASE-NOTES b/RELEASE-NOTES
index 151ce6175..ef9589cb9 100644
--- a/RELEASE-NOTES
+++ b/RELEASE-NOTES
@@ -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
diff --git a/docs/curl.1 b/docs/curl.1
index 598b15de8..52949c34f 100644
--- a/docs/curl.1
+++ b/docs/curl.1
@@ -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.
diff --git a/docs/libcurl/curl_easy_setopt.3 b/docs/libcurl/curl_easy_setopt.3
index 60068f661..25e7e7707 100644
--- a/docs/libcurl/curl_easy_setopt.3
+++ b/docs/libcurl/curl_easy_setopt.3
@@ -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
diff --git a/include/curl/curl.h b/include/curl/curl.h
index 0ac3f28ea..95c478a07 100644
--- a/include/curl/curl.h
+++ b/include/curl/curl.h
@@ -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;
diff --git a/lib/connect.c b/lib/connect.c
index 2fb08d628..902721c80 100644
--- a/lib/connect.c
+++ b/lib/connect.c
@@ -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 (CURL_INADDR_NONE == in) {
+ failf(data,"couldn't find my own IP address (%s)", myhost);
+ return CURLE_HTTP_PORT_FAILED;
+ } /* end of inet_addr */
- if ( h ) {
- Curl_addrinfo *addr = h->addr;
+ if ( h ) {
+ Curl_addrinfo *addr = h->addr;
+ sock = addr->ai_addr;
+ socksize = addr->ai_addrlen;
+ }
+ else
+ return CURLE_HTTP_PORT_FAILED;
- Curl_resolv_unlock(data, h);
- /* we don't need it anymore after this function has returned */
+ }
+ 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;
- 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
+ sock = (struct sockaddr *)&me;
+ socksize = sizeof(struct sockaddr);
- bindworked = TRUE;
+ }
+ else
+ /* no local kind of binding was requested */
+ return CURLE_OK;
- size = sizeof(add);
- if(getsockname(sockfd, (struct sockaddr *) &add,
- (socklen_t *)&size)<0) {
- failf(data, "getsockname() failed");
- return CURLE_HTTP_PORT_FAILED;
- }
- }
+ do {
- 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;
- }
+ /* 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
- } /* end of if h */
- else {
- failf(data,"couldn't find my own IP address (%s)", myhost);
+ 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;
}
- } /* end of inet_addr */
-
- else {
- failf(data, "couldn't find my own IP address (%s)", myhost);
- 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);
- return CURLE_OK;
-
- } /* end of device selection support */
-#else
- (void)conn;
- (void)sockfd;
-#endif /* end of HAVE_INET_NTOA */
-
+ 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 */
diff --git a/lib/url.c b/lib/url.c
index a4bd0f509..f17213f79 100644
--- a/lib/url.c
+++ b/lib/url.c
@@ -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.
diff --git a/lib/urldata.h b/lib/urldata.h
index c3a76b45c..96494a7ce 100644
--- a/lib/urldata.h
+++ b/lib/urldata.h
@@ -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 */
diff --git a/src/main.c b/src/main.c
index 38eb9f0a1..549a4d892 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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();