Compare commits
91 Commits
curl-7_14_
...
curl-7_15_
Author | SHA1 | Date | |
---|---|---|---|
![]() |
96cec4dfd7 | ||
![]() |
943aea6267 | ||
![]() |
b433e4a1e7 | ||
![]() |
20f1966c0e | ||
![]() |
ab1f5c3edd | ||
![]() |
b2be6799f2 | ||
![]() |
ea2618fc6f | ||
![]() |
62fdf8eaed | ||
![]() |
d3569a3572 | ||
![]() |
89df76e449 | ||
![]() |
e5b2f33b4f | ||
![]() |
934d312f50 | ||
![]() |
68917eb517 | ||
![]() |
3beb2f6b5d | ||
![]() |
b29017f15b | ||
![]() |
db83a0ebbc | ||
![]() |
6d9fddb95d | ||
![]() |
4284190cc4 | ||
![]() |
5e4cbd2d24 | ||
![]() |
06c3bec65d | ||
![]() |
e8c3bb45ba | ||
![]() |
4ec55a964d | ||
![]() |
b9420864c0 | ||
![]() |
bf6588b6a7 | ||
![]() |
e43217e664 | ||
![]() |
e19ee2d102 | ||
![]() |
b4c53e2cfd | ||
![]() |
a2902de67c | ||
![]() |
da192f7955 | ||
![]() |
a2210d23c3 | ||
![]() |
bd5a622400 | ||
![]() |
b9494cb0d6 | ||
![]() |
0f73af4470 | ||
![]() |
45e26b5c02 | ||
![]() |
6af5ea38ce | ||
![]() |
b6f0aa4394 | ||
![]() |
774dab58f6 | ||
![]() |
e3bdb98f7a | ||
![]() |
58d628c9f8 | ||
![]() |
1e69394545 | ||
![]() |
1cf798ad14 | ||
![]() |
da3992d2e9 | ||
![]() |
48908e4633 | ||
![]() |
f5ae149338 | ||
![]() |
3fe5311967 | ||
![]() |
6a48639c68 | ||
![]() |
e7093b3ca8 | ||
![]() |
d0a4104c0c | ||
![]() |
90559bed53 | ||
![]() |
973a18cf03 | ||
![]() |
3c666ce57a | ||
![]() |
a1287ec64f | ||
![]() |
5fbfa1bfa8 | ||
![]() |
da3ecc91f8 | ||
![]() |
09c8f558f7 | ||
![]() |
528a149def | ||
![]() |
29e36afb6b | ||
![]() |
0e39543d35 | ||
![]() |
0de20d8ee6 | ||
![]() |
cd5de5c0e5 | ||
![]() |
bd5afc26bd | ||
![]() |
9542dfdcdc | ||
![]() |
97a6d7b1a8 | ||
![]() |
209b9d4374 | ||
![]() |
0b8ccd0ae7 | ||
![]() |
0b7f5ad508 | ||
![]() |
8a38805e82 | ||
![]() |
836d88a4b8 | ||
![]() |
d5268ed511 | ||
![]() |
0e7d93858d | ||
![]() |
2164d760b7 | ||
![]() |
b9c8de598b | ||
![]() |
9889a811db | ||
![]() |
9e38d882b9 | ||
![]() |
e8635044b5 | ||
![]() |
56dea0ac9a | ||
![]() |
e8b77477c7 | ||
![]() |
64298e528d | ||
![]() |
4f1465e7c7 | ||
![]() |
6120041b69 | ||
![]() |
8c1213627d | ||
![]() |
3e6ae6eeb8 | ||
![]() |
291e9aeabd | ||
![]() |
a3d776187a | ||
![]() |
e55f502e2f | ||
![]() |
e369270f88 | ||
![]() |
7e845e7cfd | ||
![]() |
56d9624b56 | ||
![]() |
911d135deb | ||
![]() |
8107b90678 | ||
![]() |
7722452b98 |
134
CHANGES
134
CHANGES
@@ -7,6 +7,100 @@
|
|||||||
Changelog
|
Changelog
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Version 7.15.0 (13 October 2005)
|
||||||
|
|
||||||
|
Daniel (12 October 2005)
|
||||||
|
- Michael Sutton of iDEFENSE reported and I fixed a securitfy flaw in the NTLM
|
||||||
|
code that would overflow a buffer if given a too long user name or domain
|
||||||
|
name. This would happen if you enable NTLM authentication and either
|
||||||
|
|
||||||
|
A - pass in a user name and domain name to libcurl that together are longer
|
||||||
|
than 192 bytes
|
||||||
|
|
||||||
|
B - allow (lib)curl to follow HTTP "redirects" (Location: and the
|
||||||
|
appropriate HTTP 30x response code) and the new URL contains a URL with
|
||||||
|
a user name and domain name that together are longer than 192 bytes
|
||||||
|
|
||||||
|
See http://curl.haxx.se/docs/security.html for further details and updates
|
||||||
|
|
||||||
|
Daniel (5 October 2005)
|
||||||
|
- Darryl House reported a problem with using -z to download files from FTP.
|
||||||
|
It turned out that if the given time stamp was exact the same as the remote
|
||||||
|
time stamp, the file would still wrongly be downloaded. Added test case 272
|
||||||
|
to verify.
|
||||||
|
|
||||||
|
Daniel (4 October 2005)
|
||||||
|
- Domenico Andreoli fixed a man page malformat and removed odd (0xa0) bytes
|
||||||
|
from the configure script.
|
||||||
|
|
||||||
|
- Michael Wallner reported that the date parser had wrong offset stored for
|
||||||
|
the MEST and CEST time zones.
|
||||||
|
|
||||||
|
Daniel (27 September 2005)
|
||||||
|
- David Yan filed bug #1299181 (http://curl.haxx.se/bug/view.cgi?id=1299181)
|
||||||
|
that identified a silly problem with Content-Range: headers with the 'bytes'
|
||||||
|
keyword written in a different case than all lowercase! It would cause a
|
||||||
|
segfault!
|
||||||
|
|
||||||
|
- TJ Saunders of the proftpd project identified and pointed out problems with
|
||||||
|
the modified FTPS negotiation change of August 19 2005. Thus, we revert the
|
||||||
|
change back to pre-7.14.1 status.
|
||||||
|
|
||||||
|
Daniel (21 September 2005)
|
||||||
|
- Fixed "cut off" sentence in the libcurl-tutorial man page:
|
||||||
|
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=329305
|
||||||
|
|
||||||
|
- Clarified in the curl_easy_setopt man page what the default
|
||||||
|
CURLOPT_WRITEFUNCTION and CURLOPT_WRITEDATA mean:
|
||||||
|
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=329311
|
||||||
|
|
||||||
|
- Clarified in the curl_easy_setopt man page that CURLOPT_ERRORBUFFER
|
||||||
|
sometimes doesn't fill in the buffer even though it is supposed to:
|
||||||
|
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=329313
|
||||||
|
|
||||||
|
- When CURLE_URL_MALFORMAT is returned due to a missing URL, it now has an
|
||||||
|
error string set.
|
||||||
|
|
||||||
|
Daniel (19 September 2005)
|
||||||
|
- Dmitry Bartsevich made the SSPI support work on Windows 9x as well.
|
||||||
|
|
||||||
|
Daniel (15 September 2005)
|
||||||
|
- Added a TFTP server to the test suite and made the test suite capable of
|
||||||
|
using it.
|
||||||
|
|
||||||
|
Daniel (7 September 2005)
|
||||||
|
- Ben Madsen's detailed reports that funnily enough only occurred with certain
|
||||||
|
glibc versions turned out to be curl using an already closed file handle
|
||||||
|
during certain conditions (like when saving FTP server "headers").
|
||||||
|
|
||||||
|
- Scott Davis helped me track down a problem in the test HTTP server that made
|
||||||
|
test case 56 wrongly fail at times. It turned out it was due to the server
|
||||||
|
finding the end of a chunked-encoded POST too early.
|
||||||
|
|
||||||
|
Daniel (6 September 2005)
|
||||||
|
- Now curl warns if an unknown variable is used in the -w/--writeout argument.
|
||||||
|
|
||||||
|
Daniel (4 September 2005)
|
||||||
|
- I applied Nicolas Fran<61>ois' man page patch he posted to the Debian bug
|
||||||
|
tracker. It corrected two lines that started with apostrophes, which isn't
|
||||||
|
legal nroff format. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=326511
|
||||||
|
|
||||||
|
- Added --ftp-skip-pasv-ip to the command line tool, that sets the new
|
||||||
|
CURLOPT_FTP_SKIP_PASV_IP option. It makes libcurl re-use the control
|
||||||
|
connection's IP address when setting up the data connection instead of
|
||||||
|
extractting the IP address from the PASV response. It has turned out this
|
||||||
|
feature is frequently needed by people to circumvent silly servers and silly
|
||||||
|
firewalls, especially when FTPS is used and the PASV command-response is
|
||||||
|
sent encrtyped.
|
||||||
|
|
||||||
|
Sponsored by CU*Answers
|
||||||
|
|
||||||
|
Daniel (1 September 2005)
|
||||||
|
- John Kelly added TFTP support to libcurl. A bunch of new error codes was
|
||||||
|
added. TODO: add them to docs. add TFTP server to test suite. add TFTP to
|
||||||
|
list of protocols whereever those are mentioned.
|
||||||
|
|
||||||
Version 7.14.1 (1 September 2005)
|
Version 7.14.1 (1 September 2005)
|
||||||
|
|
||||||
Daniel (29 August 2005)
|
Daniel (29 August 2005)
|
||||||
@@ -93,10 +187,11 @@ Daniel (9 August 2005)
|
|||||||
zone names thus limiting the effect of this bug.
|
zone names thus limiting the effect of this bug.
|
||||||
|
|
||||||
Daniel (8 August 2005)
|
Daniel (8 August 2005)
|
||||||
- Jon Grubbs filed bug report #1249962 which identified a problem with NTLM on
|
- Jon Grubbs filed bug report #1249962
|
||||||
a HTTP proxy if an FTP URL was given. libcurl now properly switches to pure
|
(http://curl.haxx.se/bug/view.cgi?id=1249962) which identified a problem
|
||||||
HTTP internally when an HTTP proxy is used, even for FTP URLs. The problem
|
with NTLM on a HTTP proxy if an FTP URL was given. libcurl now properly
|
||||||
would also occur with other multi-pass auth methods.
|
switches to pure HTTP internally when an HTTP proxy is used, even for FTP
|
||||||
|
URLs. The problem would also occur with other multi-pass auth methods.
|
||||||
|
|
||||||
Daniel (7 August 2005)
|
Daniel (7 August 2005)
|
||||||
- When curl is built with GnuTLS, curl-config didn't include "SSL" when
|
- When curl is built with GnuTLS, curl-config didn't include "SSL" when
|
||||||
@@ -125,11 +220,11 @@ Daniel (12 July 2005)
|
|||||||
contains a flawed chunked encoding stream that still works the same.
|
contains a flawed chunked encoding stream that still works the same.
|
||||||
|
|
||||||
Daniel (5 July 2005)
|
Daniel (5 July 2005)
|
||||||
- Gisle Vanem came up with a nice little work-around for bug #1230118. It
|
- Gisle Vanem came up with a nice little work-around for bug #1230118
|
||||||
seems the Windows (MSVC) libc time functions may return data one hour off if
|
(http://curl.haxx.se/bug/view.cgi?id=1230118). It seems the Windows (MSVC)
|
||||||
TZ is not set and automatic DST adjustment is enabled. This made
|
libc time functions may return data one hour off if TZ is not set and
|
||||||
curl_getdate() return wrong value, and it also concerned internal cookie
|
automatic DST adjustment is enabled. This made curl_getdate() return wrong
|
||||||
expirations etc.
|
value, and it also concerned internal cookie expirations etc.
|
||||||
|
|
||||||
Daniel (4 July 2005)
|
Daniel (4 July 2005)
|
||||||
- Andrew Bushnell provided enough info for me to tell that we badly needed to
|
- Andrew Bushnell provided enough info for me to tell that we badly needed to
|
||||||
@@ -165,8 +260,9 @@ Daniel (22 June 2005)
|
|||||||
- David Shaw updated libcurl.m4
|
- David Shaw updated libcurl.m4
|
||||||
|
|
||||||
Daniel (14 June 2005)
|
Daniel (14 June 2005)
|
||||||
- Gisle Vanem fixed a potential thread handle leak. Bug report #1216500.
|
- Gisle Vanem fixed a potential thread handle leak. Bug report #1216500
|
||||||
Comment in http://curl.haxx.se/mail/lib-2005-06/0059.html
|
(http://curl.haxx.se/bug/view.cgi?id=1216500). Comment in
|
||||||
|
http://curl.haxx.se/mail/lib-2005-06/0059.html
|
||||||
|
|
||||||
Daniel (13 June 2005)
|
Daniel (13 June 2005)
|
||||||
- Made buildconf run libtoolize in the ares dir too (inspired by Tupone's
|
- Made buildconf run libtoolize in the ares dir too (inspired by Tupone's
|
||||||
@@ -202,7 +298,7 @@ Daniel (3 June 2005)
|
|||||||
Daniel (1 June 2005)
|
Daniel (1 June 2005)
|
||||||
- The configure check for c-ares now adds the cares lib before the other libs,
|
- The configure check for c-ares now adds the cares lib before the other libs,
|
||||||
to make it build fine with mingw. Inspired by Tupone Alfredo's bug report
|
to make it build fine with mingw. Inspired by Tupone Alfredo's bug report
|
||||||
(and patch) #1212940
|
and patch: http://curl.haxx.se/bug/view.cgi?id=1212940
|
||||||
|
|
||||||
Daniel (31 May 2005)
|
Daniel (31 May 2005)
|
||||||
- Todd Kulesza reported a flaw in the proxy option, since a numerical IPv6
|
- Todd Kulesza reported a flaw in the proxy option, since a numerical IPv6
|
||||||
@@ -214,7 +310,7 @@ Daniel (30 May 2005)
|
|||||||
- Eric Cooper reported about a problem with HTTP servers that responds with
|
- Eric Cooper reported about a problem with HTTP servers that responds with
|
||||||
binary zeroes within the headers. They confused libcurl to do wrong so the
|
binary zeroes within the headers. They confused libcurl to do wrong so the
|
||||||
downloaded headers become incomplete. The fix is now verified with test case
|
downloaded headers become incomplete. The fix is now verified with test case
|
||||||
262.
|
262. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=310948
|
||||||
|
|
||||||
Daniel (25 May 2005)
|
Daniel (25 May 2005)
|
||||||
- Fixed problems with the test suite, and in particular the FTP test cases
|
- Fixed problems with the test suite, and in particular the FTP test cases
|
||||||
@@ -236,9 +332,10 @@ Daniel (20 May 2005)
|
|||||||
docs.
|
docs.
|
||||||
|
|
||||||
Daniel (18 May 2005)
|
Daniel (18 May 2005)
|
||||||
- John McGowan identified a problem in bug report #1204435 with malformed URLs
|
- John McGowan identified a problem in bug report #1204435
|
||||||
like "http://somehost?data" as it added a slash too much in the request
|
(http://curl.haxx.se/bug/view.cgi?id=1204435) with malformed URLs like
|
||||||
("GET /?data/"...). Added test case 260 to verify.
|
"http://somehost?data" as it added a slash too much in the request ("GET
|
||||||
|
/?data/"...). Added test case 260 to verify.
|
||||||
|
|
||||||
- The configure check for strerror_r() failed to detect the proper API at
|
- The configure check for strerror_r() failed to detect the proper API at
|
||||||
times, like on HP-UX 10.20. Then lib/strerror.c badly assumed the glibc
|
times, like on HP-UX 10.20. Then lib/strerror.c badly assumed the glibc
|
||||||
@@ -261,8 +358,9 @@ Daniel (12 May 2005)
|
|||||||
- When doing a second request (after a disconnect) using the same easy handle,
|
- When doing a second request (after a disconnect) using the same easy handle,
|
||||||
over a proxy that uses NTLM authentication, libcurl failed to use NTLM again
|
over a proxy that uses NTLM authentication, libcurl failed to use NTLM again
|
||||||
properly (the auth method was accidentally reset to the same as had been set
|
properly (the auth method was accidentally reset to the same as had been set
|
||||||
for host auth, which defaults to Basic). Bug report #1200661 identified the
|
for host auth, which defaults to Basic). Bug report #1200661
|
||||||
the problem and the fix.
|
(http://curl.haxx.se/bug/view.cgi?id=1200661) identified the the problem and
|
||||||
|
the fix.
|
||||||
|
|
||||||
- If -z/--time-cond is used with an invalid date syntax, this is no longer
|
- If -z/--time-cond is used with an invalid date syntax, this is no longer
|
||||||
silently discarded. Instead a proper warning message is diplayed that
|
silently discarded. Instead a proper warning message is diplayed that
|
||||||
|
@@ -1,74 +1,46 @@
|
|||||||
Curl and libcurl 7.14.1
|
Curl and libcurl 7.15.0
|
||||||
|
|
||||||
Public curl release number: 89
|
Public curl release number: 90
|
||||||
Releases counted from the very beginning: 116
|
Releases counted from the very beginning: 117
|
||||||
Available command line options: 108
|
Available command line options: 109
|
||||||
Available curl_easy_setopt() options: 123
|
Available curl_easy_setopt() options: 124
|
||||||
Number of public functions in libcurl: 46
|
Number of public functions in libcurl: 46
|
||||||
Amount of public web site mirrors: 25
|
Amount of public web site mirrors: 24
|
||||||
Number of known libcurl bindings: 31
|
Number of known libcurl bindings: 32
|
||||||
Number of contributors: 447
|
Number of contributors: 451
|
||||||
|
|
||||||
This release includes the following changes:
|
This release includes the following changes:
|
||||||
|
|
||||||
o GNU GSS support
|
o --ftp-skip-pasv-ip / CURLOPT_FTP_SKIP_PASV_IP (sponsored by CU*Answers)
|
||||||
o --ignore-content-length and CURLOPT_IGNORE_CONTENT_LENGTH added
|
o TFTP support added
|
||||||
o negotiates data connection SSL earlier when doing FTPS with PASV
|
|
||||||
o CURLOPT_COOKIELIST and CURLINFO_COOKIELIST
|
|
||||||
o trailer support for chunked encoded data streams
|
|
||||||
o -x/CURL_PROXY strings may now contain user+password
|
|
||||||
o --trace-time now outputs the full microsecond, all 6 digits
|
|
||||||
|
|
||||||
This release includes the following bugfixes:
|
This release includes the following bugfixes:
|
||||||
|
|
||||||
o MSVC build problem with the DSP file
|
o user+domain name buffer overflow in the NTLM code (security flaw)
|
||||||
o windows threaded resolver access violation with multi interface
|
o -z over FTP now considers equal timestamps "not modified since"
|
||||||
o test suite works with valgrind 3
|
o Weird characters removed from the configure script
|
||||||
o CA cert verification with GnuTLS builds
|
o Fixed time zone offsets for MEST and CEST for the time parser
|
||||||
o handles expiry times in cookie files that go beyond 32 bits in size
|
o HTTP Content-Range header parser crash
|
||||||
o several client problems with files, such as doing -d @file when the file
|
o FTPS negotiation timeouts/errors
|
||||||
isn't readable now gets a warning displayed
|
o SSPI works even for Windows 9x
|
||||||
o write callback abort didn't always "take"
|
o crash in --dump-header on FTP
|
||||||
o the curl -z "bad syntax" warning is now hidden when -s is used
|
o test 56 runs better
|
||||||
o curl -d @nonexisting no longer makes a GET
|
|
||||||
o minor debug callback data size
|
|
||||||
o date parsing of dates including daylight savings time zone names
|
|
||||||
o using NTLM over proxy with an FTP URL
|
|
||||||
o curl-config --features now displays SSL when built with GnuTLS too
|
|
||||||
o CURLOPT_HTTPGET, CURLOPT_POST and CURLOPT_HTTPPOST reset CURLOPT_NOBODY
|
|
||||||
o builds fine on AmigaOS again
|
|
||||||
o corrected date parsing on Windows with auto-DST-adjust enabled
|
|
||||||
o treats CONNECT 407 responses with bodies better during Digest/NTLM auth
|
|
||||||
o improved strerror_r() API guessing when cross-compiling
|
|
||||||
o debug builds work on Tru64
|
|
||||||
o improved libcurl.m4
|
|
||||||
o possible memory leak in windows name resolves
|
|
||||||
o c-ares enabled build with mingw
|
|
||||||
o proxy host set with numerical IPv6 address
|
|
||||||
o better treatment of binary zeroes in HTTP response headers
|
|
||||||
o fixed the notorious FTP server failure in the test suite
|
|
||||||
o better checking of text output in the test suite on windows
|
|
||||||
o FTP servers' TYPE command response check made less strict
|
|
||||||
o URL-without-slash as in http://somehost?data
|
|
||||||
o strerror_r() configure check for HP-UX 10.20 (and others)
|
|
||||||
o time parse work-around on HP-UX 10.20 since its gmtime_r() is broken
|
|
||||||
|
|
||||||
Other curl-related news since the previous public release:
|
Other curl-related news since the previous public release:
|
||||||
|
|
||||||
o cURLpp 0.5.2 was released at http://rrette.com/curlpp.html
|
o http://curl.freemirror.de/ is a new German mirror
|
||||||
o Rexx/CURL 1.3 was released at http://rexxcurl.sf.net/
|
o All curl relatd mailing list information and subscribers on cool.haxx.se
|
||||||
o http://curl.miscellaneousmirror.org is a new German curl mirror
|
were lost due to a malicious user exploiting a security hole on the
|
||||||
o LuaCURL by Alexander Marinov at http://luacurl.luaforge.net/
|
server. Attempts have been made to put back susbcribers on the lists, but
|
||||||
o http://curl.hostingzero.com/ is a new US curl mirror
|
many have been lost: http://curl.haxx.se/mail/lost.html
|
||||||
o ocurl 0.2.1 was released at http://sourceforge.net/projects/ocurl
|
o New S-Lang binding: http://curl.haxx.se/libcurl/slang/
|
||||||
|
o TclCurl 0.14.1: http://personal1.iddeo.es/andresgarci/tclcurl/english/
|
||||||
|
o pycurl 7.14.1: http://pycurl.sf.net/
|
||||||
|
|
||||||
This release would not have looked like this without help, code, reports and
|
This release would not have looked like this without help, code, reports and
|
||||||
advice from friends like these:
|
advice from friends like these:
|
||||||
|
|
||||||
John McGowan, Georg Wicherski, Andres Garcia, Eric Cooper, Todd Kulesza,
|
o John Kelly, Nicolas Fran<61>ois, Scott Davis, Ben Madsen, Dmitry Bartsevich,
|
||||||
Tupone Alfredo, Gisle Vanem, David Shaw, Andrew Bushnell, Dan Fandrich,
|
David Yan, Michael Wallner, Domenico Andreoli, Darryl House
|
||||||
Adrian Schuur, Diego Casorran, Peteris Krumins, Jon Grubbs, Christopher
|
|
||||||
R. Palmer, Mario Schroeder, Richard Clayton, James Bursa, Jeff Pohlmeyer,
|
|
||||||
Norbert Novotny, Toby Peterson, Simon Josefsson, Igor Polyakov, Kevin Lussier
|
|
||||||
|
|
||||||
Thanks! (and sorry if I forgot to mention someone)
|
Thanks! (and sorry if I forgot to mention someone)
|
||||||
|
@@ -1,12 +1,7 @@
|
|||||||
Issues not sorted in any particular order.
|
To get fixed in 7.15.0 (planned release: November 2005)
|
||||||
|
|
||||||
To get fixed in 7.14.1 (planned release: August 2005)
|
|
||||||
======================
|
======================
|
||||||
|
|
||||||
To get fixed in 7.14.2 (planned release: October 2005)
|
60 - CONNECT 407 responses that kills the connection (not very likely though)
|
||||||
======================
|
|
||||||
|
|
||||||
60 - CONNECT 407 responses that kills the connection
|
|
||||||
|
|
||||||
63 -
|
63 -
|
||||||
|
|
||||||
|
12
ares/CHANGES
12
ares/CHANGES
@@ -1,5 +1,17 @@
|
|||||||
Changelog for the c-ares project
|
Changelog for the c-ares project
|
||||||
|
|
||||||
|
* September 18
|
||||||
|
|
||||||
|
- Added constants that will be used by ares_getaddrinfo
|
||||||
|
|
||||||
|
- Made ares_getnameinfo use the reentrant getservbyport (getservbyport_r) if it is
|
||||||
|
available to ensure it works properly in a threaded environment.
|
||||||
|
|
||||||
|
* September 10
|
||||||
|
|
||||||
|
- configure fix for detecting a member in the sockaddr_in6 struct which failed
|
||||||
|
on ipv6-enabled HP-UX 11.00
|
||||||
|
|
||||||
Version 1.3.0 (August 29, 2004)
|
Version 1.3.0 (August 29, 2004)
|
||||||
|
|
||||||
* August 21
|
* August 21
|
||||||
|
@@ -1,291 +1,318 @@
|
|||||||
dnl Check for how to set a socket to non-blocking state. There seems to exist
|
dnl Check for how to set a socket to non-blocking state. There seems to exist
|
||||||
dnl four known different ways, with the one used almost everywhere being POSIX
|
dnl four known different ways, with the one used almost everywhere being POSIX
|
||||||
dnl and XPG3, while the other different ways for different systems (old BSD,
|
dnl and XPG3, while the other different ways for different systems (old BSD,
|
||||||
dnl Windows and Amiga).
|
dnl Windows and Amiga).
|
||||||
dnl
|
dnl
|
||||||
dnl There are two known platforms (AIX 3.x and SunOS 4.1.x) where the
|
dnl There are two known platforms (AIX 3.x and SunOS 4.1.x) where the
|
||||||
dnl O_NONBLOCK define is found but does not work. This condition is attempted
|
dnl O_NONBLOCK define is found but does not work. This condition is attempted
|
||||||
dnl to get caught in this script by using an excessive number of #ifdefs...
|
dnl to get caught in this script by using an excessive number of #ifdefs...
|
||||||
dnl
|
dnl
|
||||||
AC_DEFUN([CURL_CHECK_NONBLOCKING_SOCKET],
|
AC_DEFUN([CURL_CHECK_NONBLOCKING_SOCKET],
|
||||||
[
|
[
|
||||||
AC_MSG_CHECKING([non-blocking sockets style])
|
AC_MSG_CHECKING([non-blocking sockets style])
|
||||||
|
|
||||||
AC_TRY_COMPILE([
|
AC_TRY_COMPILE([
|
||||||
/* headers for O_NONBLOCK test */
|
/* headers for O_NONBLOCK test */
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
],[
|
],[
|
||||||
/* try to compile O_NONBLOCK */
|
/* try to compile O_NONBLOCK */
|
||||||
|
|
||||||
#if defined(sun) || defined(__sun__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
#if defined(sun) || defined(__sun__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
|
||||||
# if defined(__SVR4) || defined(__srv4__)
|
# if defined(__SVR4) || defined(__srv4__)
|
||||||
# define PLATFORM_SOLARIS
|
# define PLATFORM_SOLARIS
|
||||||
# else
|
# else
|
||||||
# define PLATFORM_SUNOS4
|
# define PLATFORM_SUNOS4
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
#if (defined(_AIX) || defined(__xlC__)) && !defined(_AIX4)
|
#if (defined(_AIX) || defined(__xlC__)) && !defined(_AIX4)
|
||||||
# define PLATFORM_AIX_V3
|
# define PLATFORM_AIX_V3
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(PLATFORM_SUNOS4) || defined(PLATFORM_AIX_V3) || defined(__BEOS__)
|
#if defined(PLATFORM_SUNOS4) || defined(PLATFORM_AIX_V3) || defined(__BEOS__)
|
||||||
#error "O_NONBLOCK does not work on this platform"
|
#error "O_NONBLOCK does not work on this platform"
|
||||||
#endif
|
#endif
|
||||||
int socket;
|
int socket;
|
||||||
int flags = fcntl(socket, F_SETFL, flags | O_NONBLOCK);
|
int flags = fcntl(socket, F_SETFL, flags | O_NONBLOCK);
|
||||||
],[
|
],[
|
||||||
dnl the O_NONBLOCK test was fine
|
dnl the O_NONBLOCK test was fine
|
||||||
nonblock="O_NONBLOCK"
|
nonblock="O_NONBLOCK"
|
||||||
AC_DEFINE(HAVE_O_NONBLOCK, 1, [use O_NONBLOCK for non-blocking sockets])
|
AC_DEFINE(HAVE_O_NONBLOCK, 1, [use O_NONBLOCK for non-blocking sockets])
|
||||||
],[
|
],[
|
||||||
dnl the code was bad, try a different program now, test 2
|
dnl the code was bad, try a different program now, test 2
|
||||||
|
|
||||||
AC_TRY_COMPILE([
|
AC_TRY_COMPILE([
|
||||||
/* headers for FIONBIO test */
|
/* headers for FIONBIO test */
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stropts.h>
|
#include <stropts.h>
|
||||||
],[
|
],[
|
||||||
/* FIONBIO source test (old-style unix) */
|
/* FIONBIO source test (old-style unix) */
|
||||||
int socket;
|
int socket;
|
||||||
int flags = ioctl(socket, FIONBIO, &flags);
|
int flags = ioctl(socket, FIONBIO, &flags);
|
||||||
],[
|
],[
|
||||||
dnl FIONBIO test was good
|
dnl FIONBIO test was good
|
||||||
nonblock="FIONBIO"
|
nonblock="FIONBIO"
|
||||||
AC_DEFINE(HAVE_FIONBIO, 1, [use FIONBIO for non-blocking sockets])
|
AC_DEFINE(HAVE_FIONBIO, 1, [use FIONBIO for non-blocking sockets])
|
||||||
],[
|
],[
|
||||||
dnl FIONBIO test was also bad
|
dnl FIONBIO test was also bad
|
||||||
dnl the code was bad, try a different program now, test 3
|
dnl the code was bad, try a different program now, test 3
|
||||||
|
|
||||||
AC_TRY_COMPILE([
|
AC_TRY_COMPILE([
|
||||||
/* headers for ioctlsocket test (cygwin?) */
|
/* headers for ioctlsocket test (cygwin?) */
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
],[
|
],[
|
||||||
/* ioctlsocket source code */
|
/* ioctlsocket source code */
|
||||||
int socket;
|
int socket;
|
||||||
unsigned long flags = ioctlsocket(socket, FIONBIO, &flags);
|
unsigned long flags = ioctlsocket(socket, FIONBIO, &flags);
|
||||||
],[
|
],[
|
||||||
dnl ioctlsocket test was good
|
dnl ioctlsocket test was good
|
||||||
nonblock="ioctlsocket"
|
nonblock="ioctlsocket"
|
||||||
AC_DEFINE(HAVE_IOCTLSOCKET, 1, [use ioctlsocket() for non-blocking sockets])
|
AC_DEFINE(HAVE_IOCTLSOCKET, 1, [use ioctlsocket() for non-blocking sockets])
|
||||||
],[
|
],[
|
||||||
dnl ioctlsocket didnt compile!, go to test 4
|
dnl ioctlsocket didnt compile!, go to test 4
|
||||||
|
|
||||||
AC_TRY_LINK([
|
AC_TRY_LINK([
|
||||||
/* headers for IoctlSocket test (Amiga?) */
|
/* headers for IoctlSocket test (Amiga?) */
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
],[
|
],[
|
||||||
/* IoctlSocket source code */
|
/* IoctlSocket source code */
|
||||||
int socket;
|
int socket;
|
||||||
int flags = IoctlSocket(socket, FIONBIO, (long)1);
|
int flags = IoctlSocket(socket, FIONBIO, (long)1);
|
||||||
],[
|
],[
|
||||||
dnl ioctlsocket test was good
|
dnl ioctlsocket test was good
|
||||||
nonblock="IoctlSocket"
|
nonblock="IoctlSocket"
|
||||||
AC_DEFINE(HAVE_IOCTLSOCKET_CASE, 1, [use Ioctlsocket() for non-blocking sockets])
|
AC_DEFINE(HAVE_IOCTLSOCKET_CASE, 1, [use Ioctlsocket() for non-blocking sockets])
|
||||||
],[
|
],[
|
||||||
dnl Ioctlsocket didnt compile, do test 5!
|
dnl Ioctlsocket didnt compile, do test 5!
|
||||||
AC_TRY_COMPILE([
|
AC_TRY_COMPILE([
|
||||||
/* headers for SO_NONBLOCK test (BeOS) */
|
/* headers for SO_NONBLOCK test (BeOS) */
|
||||||
#include <socket.h>
|
#include <socket.h>
|
||||||
],[
|
],[
|
||||||
/* SO_NONBLOCK source code */
|
/* SO_NONBLOCK source code */
|
||||||
long b = 1;
|
long b = 1;
|
||||||
int socket;
|
int socket;
|
||||||
int flags = setsockopt(socket, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
|
int flags = setsockopt(socket, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
|
||||||
],[
|
],[
|
||||||
dnl the SO_NONBLOCK test was good
|
dnl the SO_NONBLOCK test was good
|
||||||
nonblock="SO_NONBLOCK"
|
nonblock="SO_NONBLOCK"
|
||||||
AC_DEFINE(HAVE_SO_NONBLOCK, 1, [use SO_NONBLOCK for non-blocking sockets])
|
AC_DEFINE(HAVE_SO_NONBLOCK, 1, [use SO_NONBLOCK for non-blocking sockets])
|
||||||
],[
|
],[
|
||||||
dnl test 5 didnt compile!
|
dnl test 5 didnt compile!
|
||||||
nonblock="nada"
|
nonblock="nada"
|
||||||
AC_DEFINE(HAVE_DISABLED_NONBLOCKING, 1, [disabled non-blocking sockets])
|
AC_DEFINE(HAVE_DISABLED_NONBLOCKING, 1, [disabled non-blocking sockets])
|
||||||
])
|
])
|
||||||
dnl end of fifth test
|
dnl end of fifth test
|
||||||
|
|
||||||
])
|
])
|
||||||
dnl end of forth test
|
dnl end of forth test
|
||||||
|
|
||||||
])
|
])
|
||||||
dnl end of third test
|
dnl end of third test
|
||||||
|
|
||||||
])
|
])
|
||||||
dnl end of second test
|
dnl end of second test
|
||||||
|
|
||||||
])
|
])
|
||||||
dnl end of non-blocking try-compile test
|
dnl end of non-blocking try-compile test
|
||||||
AC_MSG_RESULT($nonblock)
|
AC_MSG_RESULT($nonblock)
|
||||||
|
|
||||||
if test "$nonblock" = "nada"; then
|
if test "$nonblock" = "nada"; then
|
||||||
AC_MSG_WARN([non-block sockets disabled])
|
AC_MSG_WARN([non-block sockets disabled])
|
||||||
fi
|
fi
|
||||||
])
|
])
|
||||||
|
|
||||||
dnl We create a function for detecting which compiler we use and then set as
|
dnl We create a function for detecting which compiler we use and then set as
|
||||||
dnl pendantic compiler options as possible for that particular compiler. The
|
dnl pendantic compiler options as possible for that particular compiler. The
|
||||||
dnl options are only used for debug-builds.
|
dnl options are only used for debug-builds.
|
||||||
|
|
||||||
dnl This is a copy of the original found in curl's configure script. Don't
|
dnl This is a copy of the original found in curl's configure script. Don't
|
||||||
dnl modify this one, edit the one in curl and copy it back here when that one
|
dnl modify this one, edit the one in curl and copy it back here when that one
|
||||||
dnl is changed.
|
dnl is changed.
|
||||||
|
|
||||||
AC_DEFUN([CURL_CC_DEBUG_OPTS],
|
AC_DEFUN([CURL_CC_DEBUG_OPTS],
|
||||||
[
|
[
|
||||||
if test "$GCC" = "yes"; then
|
if test "$GCC" = "yes"; then
|
||||||
|
|
||||||
dnl figure out gcc version!
|
dnl figure out gcc version!
|
||||||
AC_MSG_CHECKING([gcc version])
|
AC_MSG_CHECKING([gcc version])
|
||||||
gccver=`$CC -dumpversion`
|
gccver=`$CC -dumpversion`
|
||||||
num1=`echo $gccver | cut -d . -f1`
|
num1=`echo $gccver | cut -d . -f1`
|
||||||
num2=`echo $gccver | cut -d . -f2`
|
num2=`echo $gccver | cut -d . -f2`
|
||||||
gccnum=`(expr $num1 "*" 100 + $num2) 2>/dev/null`
|
gccnum=`(expr $num1 "*" 100 + $num2) 2>/dev/null`
|
||||||
AC_MSG_RESULT($gccver)
|
AC_MSG_RESULT($gccver)
|
||||||
|
|
||||||
AC_MSG_CHECKING([if this is icc in disguise])
|
AC_MSG_CHECKING([if this is icc in disguise])
|
||||||
AC_EGREP_CPP([^__INTEL_COMPILER], [__INTEL_COMPILER],
|
AC_EGREP_CPP([^__INTEL_COMPILER], [__INTEL_COMPILER],
|
||||||
dnl action if the text is found, this it has not been replaced by the
|
dnl action if the text is found, this it has not been replaced by the
|
||||||
dnl cpp
|
dnl cpp
|
||||||
ICC="no"
|
ICC="no"
|
||||||
AC_MSG_RESULT([no]),
|
AC_MSG_RESULT([no]),
|
||||||
dnl the text was not found, it was replaced by the cpp
|
dnl the text was not found, it was replaced by the cpp
|
||||||
ICC="yes"
|
ICC="yes"
|
||||||
AC_MSG_RESULT([yes])
|
AC_MSG_RESULT([yes])
|
||||||
)
|
)
|
||||||
|
|
||||||
if test "$ICC" = "yes"; then
|
if test "$ICC" = "yes"; then
|
||||||
dnl this is icc, not gcc.
|
dnl this is icc, not gcc.
|
||||||
|
|
||||||
dnl ICC warnings we ignore:
|
dnl ICC warnings we ignore:
|
||||||
dnl * 279 warns on static conditions in while expressions
|
dnl * 279 warns on static conditions in while expressions
|
||||||
dnl * 269 warns on our "%Od" printf formatters for curl_off_t output:
|
dnl * 269 warns on our "%Od" printf formatters for curl_off_t output:
|
||||||
dnl "invalid format string conversion"
|
dnl "invalid format string conversion"
|
||||||
|
|
||||||
WARN="-wd279,269"
|
WARN="-wd279,269"
|
||||||
|
|
||||||
if test "$gccnum" -gt "600"; then
|
if test "$gccnum" -gt "600"; then
|
||||||
dnl icc 6.0 and older doesn't have the -Wall flag
|
dnl icc 6.0 and older doesn't have the -Wall flag
|
||||||
WARN="-Wall $WARN"
|
WARN="-Wall $WARN"
|
||||||
fi
|
fi
|
||||||
else dnl $ICC = yes
|
else dnl $ICC = yes
|
||||||
dnl
|
dnl
|
||||||
WARN="-W -Wall -Wwrite-strings -pedantic -Wno-long-long -Wundef -Wpointer-arith -Wnested-externs -Winline -Wmissing-declarations -Wmissing-prototypes -Wsign-compare"
|
WARN="-W -Wall -Wwrite-strings -pedantic -Wno-long-long -Wundef -Wpointer-arith -Wnested-externs -Winline -Wmissing-declarations -Wmissing-prototypes -Wsign-compare"
|
||||||
|
|
||||||
dnl -Wcast-align is a bit too annoying ;-)
|
dnl -Wcast-align is a bit too annoying ;-)
|
||||||
|
|
||||||
if test "$gccnum" -ge "296"; then
|
if test "$gccnum" -ge "296"; then
|
||||||
dnl gcc 2.96 or later
|
dnl gcc 2.96 or later
|
||||||
WARN="$WARN -Wfloat-equal"
|
WARN="$WARN -Wfloat-equal"
|
||||||
|
|
||||||
if test "$gccnum" -gt "296"; then
|
if test "$gccnum" -gt "296"; then
|
||||||
dnl this option does not exist in 2.96
|
dnl this option does not exist in 2.96
|
||||||
WARN="$WARN -Wno-format-nonliteral"
|
WARN="$WARN -Wno-format-nonliteral"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dnl -Wunreachable-code seems totally unreliable on my gcc 3.3.2 on
|
dnl -Wunreachable-code seems totally unreliable on my gcc 3.3.2 on
|
||||||
dnl on i686-Linux as it gives us heaps with false positives
|
dnl on i686-Linux as it gives us heaps with false positives
|
||||||
if test "$gccnum" -ge "303"; then
|
if test "$gccnum" -ge "303"; then
|
||||||
dnl gcc 3.3 and later
|
dnl gcc 3.3 and later
|
||||||
WARN="$WARN -Wendif-labels -Wstrict-prototypes"
|
WARN="$WARN -Wendif-labels -Wstrict-prototypes"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for flag in $CPPFLAGS; do
|
for flag in $CPPFLAGS; do
|
||||||
case "$flag" in
|
case "$flag" in
|
||||||
-I*)
|
-I*)
|
||||||
dnl include path
|
dnl include path
|
||||||
add=`echo $flag | sed 's/^-I/-isystem /g'`
|
add=`echo $flag | sed 's/^-I/-isystem /g'`
|
||||||
WARN="$WARN $add"
|
WARN="$WARN $add"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
fi dnl $ICC = no
|
fi dnl $ICC = no
|
||||||
|
|
||||||
CFLAGS="$CFLAGS $WARN"
|
CFLAGS="$CFLAGS $WARN"
|
||||||
|
|
||||||
fi dnl $GCC = yes
|
fi dnl $GCC = yes
|
||||||
|
|
||||||
dnl strip off optimizer flags
|
dnl strip off optimizer flags
|
||||||
NEWFLAGS=""
|
NEWFLAGS=""
|
||||||
for flag in $CFLAGS; do
|
for flag in $CFLAGS; do
|
||||||
case "$flag" in
|
case "$flag" in
|
||||||
-O*)
|
-O*)
|
||||||
dnl echo "cut off $flag"
|
dnl echo "cut off $flag"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
NEWFLAGS="$NEWFLAGS $flag"
|
NEWFLAGS="$NEWFLAGS $flag"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
CFLAGS=$NEWFLAGS
|
CFLAGS=$NEWFLAGS
|
||||||
|
|
||||||
]) dnl end of AC_DEFUN()
|
]) dnl end of AC_DEFUN()
|
||||||
|
|
||||||
|
|
||||||
dnl This macro determines if the specified struct exists in the specified file
|
dnl This macro determines if the specified struct exists in the specified file
|
||||||
dnl Syntax:
|
dnl Syntax:
|
||||||
dnl CARES_CHECK_STRUCT(headers, struct name, if found, [if not found])
|
dnl CARES_CHECK_STRUCT(headers, struct name, if found, [if not found])
|
||||||
|
|
||||||
AC_DEFUN([CARES_CHECK_STRUCT], [
|
AC_DEFUN([CARES_CHECK_STRUCT], [
|
||||||
AC_MSG_CHECKING([for struct $2])
|
AC_MSG_CHECKING([for struct $2])
|
||||||
AC_TRY_COMPILE([$1],
|
AC_TRY_COMPILE([$1],
|
||||||
[
|
[
|
||||||
struct $2 struct_instance;
|
struct $2 struct_instance;
|
||||||
], ac_struct="yes", ac_found="no")
|
], ac_struct="yes", ac_found="no")
|
||||||
if test "$ac_struct" = "yes" ; then
|
if test "$ac_struct" = "yes" ; then
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
$3
|
$3
|
||||||
else
|
else
|
||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
$4
|
$4
|
||||||
fi
|
fi
|
||||||
])
|
])
|
||||||
|
|
||||||
dnl This macro determins if the specified struct contains a specific member.
|
dnl This macro determines if the specified constant exists in the specified file
|
||||||
dnl Syntax:
|
dnl Syntax:
|
||||||
dnl CARES_CHECK_STRUCT_MEMBER(headers, struct name, member name, if found, [if not found])
|
dnl CARES_CHECK_CONSTANT(headers, constant name, if found, [if not found])
|
||||||
|
|
||||||
AC_DEFUN([CARES_CHECK_STRUCT_MEMBER], [
|
AC_DEFUN([CARES_CHECK_CONSTANT], [
|
||||||
AC_MSG_CHECKING([if struct $2 has member $3])
|
AC_MSG_CHECKING([for $2])
|
||||||
AC_TRY_COMPILE([$1],
|
AC_EGREP_CPP(VARIABLEWASDEFINED,
|
||||||
[
|
[
|
||||||
struct $2 struct_instance;
|
$1
|
||||||
struct_instance.$3 = 0;
|
|
||||||
], ac_struct="yes", ac_found="no")
|
#ifdef $2
|
||||||
if test "$ac_struct" = "yes" ; then
|
VARIABLEWASDEFINED
|
||||||
AC_MSG_RESULT(yes)
|
#else
|
||||||
$4
|
NJET
|
||||||
else
|
#endif
|
||||||
AC_MSG_RESULT(no)
|
], ac_constant="yes", ac_constant="no"
|
||||||
$5
|
)
|
||||||
fi
|
if test "$ac_constant" = "yes" ; then
|
||||||
])
|
AC_MSG_RESULT(yes)
|
||||||
|
$3
|
||||||
dnl This macro determines if the specified constant exists in the specified file
|
else
|
||||||
dnl Syntax:
|
AC_MSG_RESULT(no)
|
||||||
dnl CARES_CHECK_CONSTANT(headers, constant name, if found, [if not found])
|
$4
|
||||||
|
fi
|
||||||
AC_DEFUN([CARES_CHECK_CONSTANT], [
|
])
|
||||||
AC_MSG_CHECKING([for $2])
|
|
||||||
AC_EGREP_CPP(VARIABLEWASDEFINED,
|
|
||||||
[
|
dnl This macro determines how many parameters getservbyport_r takes
|
||||||
$1
|
AC_DEFUN([CARES_CHECK_GETSERVBYPORT_R], [
|
||||||
|
AC_MSG_CHECKING([how many arguments getservbyport_r takes])
|
||||||
#ifdef $2
|
AC_TRY_COMPILE(
|
||||||
VARIABLEWASDEFINED
|
[#include <netdb.h>],
|
||||||
#else
|
[
|
||||||
NJET
|
int p1, p5;
|
||||||
#endif
|
char *p2, p4[4096];
|
||||||
], ac_constant="yes", ac_constant="no"
|
struct servent *p3, *p6;
|
||||||
)
|
getservbyport_r(p1, p2, p3, p4, p5, &p6);
|
||||||
if test "$ac_constant" = "yes" ; then
|
], ac_func_getservbyport_r=6,
|
||||||
AC_MSG_RESULT(yes)
|
[AC_TRY_COMPILE(
|
||||||
$3
|
[#include <netdb.h>],
|
||||||
else
|
[
|
||||||
AC_MSG_RESULT(no)
|
int p1, p5;
|
||||||
$4
|
char *p2, p4[4096];
|
||||||
fi
|
struct servent *p3;
|
||||||
])
|
getservbyport_r(p1, p2, p3, p4, p5);
|
||||||
|
], ac_func_getservbyport_r=5,
|
||||||
|
[AC_TRY_COMPILE(
|
||||||
|
[#include <netdb.h>],
|
||||||
|
[
|
||||||
|
int p1;
|
||||||
|
char *p2;
|
||||||
|
struct servent *p3;
|
||||||
|
struct servent_data p4;
|
||||||
|
getservbyport_r(p1, p2, p3, &p4);
|
||||||
|
], ac_func_getservbyport_r=4, ac_func_getservbyport_r=0
|
||||||
|
)]
|
||||||
|
)]
|
||||||
|
)
|
||||||
|
if test $ac_func_getservbyport_r != "0" ; then
|
||||||
|
AC_MSG_RESULT($ac_func_getservbyport_r)
|
||||||
|
AC_DEFINE(HAVE_GETSERVBYPORT_R, 1, [Specifies whether getservbyport_r is present])
|
||||||
|
AC_DEFINE_UNQUOTED(GETSERVBYPORT_R_ARGS, $ac_func_getservbyport_r, [Specifies the number of arguments to
|
||||||
|
getservbyport_r])
|
||||||
|
if test $ac_func_getservbyport_r = "4" ; then
|
||||||
|
AC_DEFINE(GETSERVBYPORT_R_BUFSIZE, sizeof(struct servent_data), [Specifies the size of the buffer to pass to
|
||||||
|
getservbyport_r])
|
||||||
|
else
|
||||||
|
AC_DEFINE(GETSERVBYPORT_R_BUFSIZE, 4096, [Specifies the size of the buffer to pass to getservbyport_r])
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([not found])
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
|
||||||
|
28
ares/ares.h
28
ares/ares.h
@@ -69,6 +69,10 @@ extern "C" {
|
|||||||
/* ares_getnameinfo error codes */
|
/* ares_getnameinfo error codes */
|
||||||
#define ARES_EBADFLAGS 18
|
#define ARES_EBADFLAGS 18
|
||||||
|
|
||||||
|
/* ares_getaddrinfo error codes */
|
||||||
|
#define ARES_ENONAME 19
|
||||||
|
#define ARES_EBADHINTS 20
|
||||||
|
|
||||||
/* Flag values */
|
/* Flag values */
|
||||||
#define ARES_FLAG_USEVC (1 << 0)
|
#define ARES_FLAG_USEVC (1 << 0)
|
||||||
#define ARES_FLAG_PRIMARY (1 << 1)
|
#define ARES_FLAG_PRIMARY (1 << 1)
|
||||||
@@ -104,9 +108,27 @@ extern "C" {
|
|||||||
#define ARES_NI_LOOKUPHOST (1 << 8)
|
#define ARES_NI_LOOKUPHOST (1 << 8)
|
||||||
#define ARES_NI_LOOKUPSERVICE (1 << 9)
|
#define ARES_NI_LOOKUPSERVICE (1 << 9)
|
||||||
/* Reserved for future use */
|
/* Reserved for future use */
|
||||||
#define ARES_NI_IDN (1 << 10)
|
#define ARES_NI_IDN (1 << 10)
|
||||||
#define ARES_NI_ALLOW_UNASSIGNED (1 << 11)
|
#define ARES_NI_IDN_ALLOW_UNASSIGNED (1 << 11)
|
||||||
#define ARES_NI_USE_STD3_ASCII_RULES (1 << 12)
|
#define ARES_NI_IDN_USE_STD3_ASCII_RULES (1 << 12)
|
||||||
|
|
||||||
|
/* Addrinfo flag values */
|
||||||
|
#define ARES_AI_CANONNAME (1 << 0)
|
||||||
|
#define ARES_AI_NUMERICHOST (1 << 1)
|
||||||
|
#define ARES_AI_PASSIVE (1 << 2)
|
||||||
|
#define ARES_AI_NUMERICSERV (1 << 3)
|
||||||
|
#define ARES_AI_V4MAPPED (1 << 4)
|
||||||
|
#define ARES_AI_ALL (1 << 5)
|
||||||
|
#define ARES_AI_ADDRCONFIG (1 << 6)
|
||||||
|
/* Reserved for future use */
|
||||||
|
#define ARES_AI_IDN (1 << 10)
|
||||||
|
#define ARES_AI_IDN_ALLOW_UNASSIGNED (1 << 11)
|
||||||
|
#define ARES_AI_IDN_USE_STD3_ASCII_RULES (1 << 12)
|
||||||
|
#define ARES_AI_CANONIDN (1 << 13)
|
||||||
|
|
||||||
|
#define ARES_AI_MASK (ARES_AI_CANONNAME|ARES_AI_NUMERICHOST|ARES_AI_PASSIVE| \
|
||||||
|
ARES_AI_NUMERICSERV|ARES_AI_V4MAPPED|ARES_AI_ALL| \
|
||||||
|
ARES_AI_ADDRCONFIG)
|
||||||
|
|
||||||
struct ares_options {
|
struct ares_options {
|
||||||
int flags;
|
int flags;
|
||||||
|
@@ -123,7 +123,7 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, socklen_t
|
|||||||
char *service = NULL;
|
char *service = NULL;
|
||||||
ipbuf[0] = 0;
|
ipbuf[0] = 0;
|
||||||
|
|
||||||
/* Specifying not to lookup a host, but then saying a host
|
/* Specifying not to lookup a host, but then saying a host
|
||||||
* is required has to be illegal.
|
* is required has to be illegal.
|
||||||
*/
|
*/
|
||||||
if (flags & ARES_NI_NAMEREQD)
|
if (flags & ARES_NI_NAMEREQD)
|
||||||
@@ -163,18 +163,18 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, socklen_t
|
|||||||
niquery->callback = callback;
|
niquery->callback = callback;
|
||||||
niquery->arg = arg;
|
niquery->arg = arg;
|
||||||
niquery->flags = flags;
|
niquery->flags = flags;
|
||||||
if (sa->sa_family == AF_INET)
|
if (sa->sa_family == AF_INET)
|
||||||
{
|
{
|
||||||
niquery->family = AF_INET;
|
niquery->family = AF_INET;
|
||||||
memcpy(&niquery->addr.addr4, addr, sizeof(addr));
|
memcpy(&niquery->addr.addr4, addr, sizeof(addr));
|
||||||
ares_gethostbyaddr(channel, &addr->sin_addr, sizeof(struct in_addr), AF_INET,
|
ares_gethostbyaddr(channel, &addr->sin_addr, sizeof(struct in_addr), AF_INET,
|
||||||
nameinfo_callback, niquery);
|
nameinfo_callback, niquery);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
niquery->family = AF_INET6;
|
niquery->family = AF_INET6;
|
||||||
memcpy(&niquery->addr.addr6, addr6, sizeof(addr6));
|
memcpy(&niquery->addr.addr6, addr6, sizeof(addr6));
|
||||||
ares_gethostbyaddr(channel, &addr6->sin6_addr, sizeof(struct in6_addr), AF_INET6,
|
ares_gethostbyaddr(channel, &addr6->sin6_addr, sizeof(struct in6_addr), AF_INET6,
|
||||||
nameinfo_callback, niquery);
|
nameinfo_callback, niquery);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -194,9 +194,11 @@ static void nameinfo_callback(void *arg, int status, struct hostent *host)
|
|||||||
if (niquery->flags & ARES_NI_LOOKUPSERVICE)
|
if (niquery->flags & ARES_NI_LOOKUPSERVICE)
|
||||||
{
|
{
|
||||||
if (niquery->family == AF_INET)
|
if (niquery->family == AF_INET)
|
||||||
service = lookup_service(niquery->addr.addr4.sin_port, niquery->flags, srvbuf);
|
service = lookup_service(niquery->addr.addr4.sin_port,
|
||||||
|
niquery->flags, srvbuf);
|
||||||
else
|
else
|
||||||
service = lookup_service(niquery->addr.addr6.sin6_port, niquery->flags, srvbuf);
|
service = lookup_service(niquery->addr.addr6.sin6_port,
|
||||||
|
niquery->flags, srvbuf);
|
||||||
}
|
}
|
||||||
/* NOFQDN means we have to strip off the domain name portion.
|
/* NOFQDN means we have to strip off the domain name portion.
|
||||||
We do this by determining our own domain name, then searching the string
|
We do this by determining our own domain name, then searching the string
|
||||||
@@ -212,7 +214,7 @@ static void nameinfo_callback(void *arg, int status, struct hostent *host)
|
|||||||
char *end = ares_striendstr(host->h_name, domain);
|
char *end = ares_striendstr(host->h_name, domain);
|
||||||
if (end)
|
if (end)
|
||||||
*end = 0;
|
*end = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
niquery->callback(niquery->arg, ARES_SUCCESS, host->h_name, service);
|
niquery->callback(niquery->arg, ARES_SUCCESS, host->h_name, service);
|
||||||
return;
|
return;
|
||||||
@@ -234,9 +236,11 @@ static void nameinfo_callback(void *arg, int status, struct hostent *host)
|
|||||||
if (niquery->flags & ARES_NI_LOOKUPSERVICE)
|
if (niquery->flags & ARES_NI_LOOKUPSERVICE)
|
||||||
{
|
{
|
||||||
if (niquery->family == AF_INET)
|
if (niquery->family == AF_INET)
|
||||||
service = lookup_service(niquery->addr.addr4.sin_port, niquery->flags, srvbuf);
|
service = lookup_service(niquery->addr.addr4.sin_port,
|
||||||
|
niquery->flags, srvbuf);
|
||||||
else
|
else
|
||||||
service = lookup_service(niquery->addr.addr6.sin6_port, niquery->flags, srvbuf);
|
service = lookup_service(niquery->addr.addr6.sin6_port,
|
||||||
|
niquery->flags, srvbuf);
|
||||||
}
|
}
|
||||||
niquery->callback(niquery->arg, ARES_SUCCESS, ipbuf, service);
|
niquery->callback(niquery->arg, ARES_SUCCESS, ipbuf, service);
|
||||||
return;
|
return;
|
||||||
@@ -245,7 +249,8 @@ static void nameinfo_callback(void *arg, int status, struct hostent *host)
|
|||||||
free(niquery);
|
free(niquery);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *lookup_service(unsigned short port, int flags, char *buf)
|
static char *lookup_service(unsigned short port, int flags,
|
||||||
|
char *buf) /* 33 bytes buffer */
|
||||||
{
|
{
|
||||||
if (port)
|
if (port)
|
||||||
{
|
{
|
||||||
@@ -256,7 +261,17 @@ static char *lookup_service(unsigned short port, int flags, char *buf)
|
|||||||
{
|
{
|
||||||
struct servent *se;
|
struct servent *se;
|
||||||
const char *proto;
|
const char *proto;
|
||||||
|
#if GETSERVBYPORT_R_ARGS == 6
|
||||||
|
struct servent ret;
|
||||||
|
char buf[4096];
|
||||||
|
int len = 4096;
|
||||||
|
#elif GETSERVBYPORT_R_ARGS == 5
|
||||||
|
char buf[4096];
|
||||||
|
int len = 4096;
|
||||||
|
#elif GETSERVBYPORT_R_ARGS == 4
|
||||||
|
struct servent ret;
|
||||||
|
struct servent_data sed;
|
||||||
|
#endif
|
||||||
if (flags & ARES_NI_UDP)
|
if (flags & ARES_NI_UDP)
|
||||||
proto = "udp";
|
proto = "udp";
|
||||||
else if (flags & ARES_NI_SCTP)
|
else if (flags & ARES_NI_SCTP)
|
||||||
@@ -265,9 +280,34 @@ static char *lookup_service(unsigned short port, int flags, char *buf)
|
|||||||
proto = "dccp";
|
proto = "dccp";
|
||||||
else
|
else
|
||||||
proto = "tcp";
|
proto = "tcp";
|
||||||
|
#ifdef HAVE_GETSERVBYPORT_R
|
||||||
|
#if GETSERVBYPORT_R_ARGS == 6
|
||||||
|
se = &ret;
|
||||||
|
if (getservbyport_r(port, proto, se, buf, len, &ret))
|
||||||
|
se = NULL;
|
||||||
|
#elif GETSERVBYPORT_R_ARGS == 5
|
||||||
|
se = getservbyport_r(port, proto, se, buf, len);
|
||||||
|
#elif GETSERVBYPORT_R_ARGS == 4
|
||||||
|
se = &ret;
|
||||||
|
if (getservbyport_r(port, proto, se, &sed) == -1)
|
||||||
|
se = NULL;
|
||||||
|
#else
|
||||||
|
/* Lets just hope the OS uses TLS! */
|
||||||
se = getservbyport(port, proto);
|
se = getservbyport(port, proto);
|
||||||
if (se && se->s_name)
|
#endif
|
||||||
strcpy(buf, se->s_name);
|
#else
|
||||||
|
/* Lets just hope the OS uses TLS! */
|
||||||
|
se = getservbyport(port, proto);
|
||||||
|
#endif
|
||||||
|
if (se && se->s_name) {
|
||||||
|
size_t len = strlen(se->s_name);
|
||||||
|
if(len < 33) {
|
||||||
|
strcpy(buf, se->s_name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
/* too big name to fit the buffer */
|
||||||
|
buf[0]=0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
sprintf(buf, "%u", ntohs(port));
|
sprintf(buf, "%u", ntohs(port));
|
||||||
}
|
}
|
||||||
@@ -277,14 +317,16 @@ static char *lookup_service(unsigned short port, int flags, char *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
|
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
|
||||||
static char *append_scopeid(struct sockaddr_in6 *addr6, unsigned int flags, char *buf)
|
static char *append_scopeid(struct sockaddr_in6 *addr6, unsigned int flags,
|
||||||
|
char *buf)
|
||||||
{
|
{
|
||||||
char tmpbuf[IF_NAMESIZE + 1];
|
char tmpbuf[IF_NAMESIZE + 1];
|
||||||
|
|
||||||
tmpbuf[0] = '%';
|
tmpbuf[0] = '%';
|
||||||
#ifdef HAVE_IF_INDEXTONAME
|
#ifdef HAVE_IF_INDEXTONAME
|
||||||
if ((flags & ARES_NI_NUMERICSCOPE) || (!IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr)
|
if ((flags & ARES_NI_NUMERICSCOPE) ||
|
||||||
&& !IN6_IS_ADDR_MC_LINKLOCAL(&addr6->sin6_addr)))
|
(!IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr)
|
||||||
|
&& !IN6_IS_ADDR_MC_LINKLOCAL(&addr6->sin6_addr)))
|
||||||
{
|
{
|
||||||
sprintf(&tmpbuf[1], "%u", addr6->sin6_scope_id);
|
sprintf(&tmpbuf[1], "%u", addr6->sin6_scope_id);
|
||||||
}
|
}
|
||||||
|
@@ -1,351 +1,359 @@
|
|||||||
dnl Process this file with autoconf to produce a configure script.
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
AC_INIT(ares_init.c)
|
AC_INIT(ares_init.c)
|
||||||
AM_CONFIG_HEADER(config.h)
|
AM_CONFIG_HEADER(config.h)
|
||||||
AM_MAINTAINER_MODE
|
AM_MAINTAINER_MODE
|
||||||
AM_INIT_AUTOMAKE(c-ares, CVS)
|
AM_INIT_AUTOMAKE(c-ares, CVS)
|
||||||
|
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
AC_PROG_INSTALL
|
AC_PROG_INSTALL
|
||||||
|
|
||||||
case $host_os in
|
case $host_os in
|
||||||
solaris*)
|
solaris*)
|
||||||
AC_DEFINE(ETC_INET, 1, [if a /etc/inet dir is being used])
|
AC_DEFINE(ETC_INET, 1, [if a /etc/inet dir is being used])
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# check for ssize_t
|
# check for ssize_t
|
||||||
AC_CHECK_TYPE(ssize_t, ,
|
AC_CHECK_TYPE(ssize_t, ,
|
||||||
AC_DEFINE(ssize_t, int, [the signed version of size_t]))
|
AC_DEFINE(ssize_t, int, [the signed version of size_t]))
|
||||||
|
|
||||||
AC_SEARCH_LIBS(gethostbyname, nsl)
|
AC_SEARCH_LIBS(gethostbyname, nsl)
|
||||||
AC_SEARCH_LIBS(socket, socket)
|
AC_SEARCH_LIBS(socket, socket)
|
||||||
|
|
||||||
dnl ************************************************************
|
dnl ************************************************************
|
||||||
dnl Option to switch on debug options. This makes an assumption that
|
dnl Option to switch on debug options. This makes an assumption that
|
||||||
dnl this is built as an 'ares' subdir in the curl source tree. Subject for
|
dnl this is built as an 'ares' subdir in the curl source tree. Subject for
|
||||||
dnl improval in the future!
|
dnl improval in the future!
|
||||||
dnl
|
dnl
|
||||||
AC_MSG_CHECKING([whether to enable debug options])
|
AC_MSG_CHECKING([whether to enable debug options])
|
||||||
AC_ARG_ENABLE(debug,
|
AC_ARG_ENABLE(debug,
|
||||||
AC_HELP_STRING([--enable-debug],[Enable pedantic debug options])
|
AC_HELP_STRING([--enable-debug],[Enable pedantic debug options])
|
||||||
AC_HELP_STRING([--disable-debug],[Disable debug options]),
|
AC_HELP_STRING([--disable-debug],[Disable debug options]),
|
||||||
[ case "$enableval" in
|
[ case "$enableval" in
|
||||||
no)
|
no)
|
||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
;;
|
;;
|
||||||
*) AC_MSG_RESULT(yes)
|
*) AC_MSG_RESULT(yes)
|
||||||
|
|
||||||
dnl when doing the debug stuff, use static library only
|
dnl when doing the debug stuff, use static library only
|
||||||
AC_DISABLE_SHARED
|
AC_DISABLE_SHARED
|
||||||
|
|
||||||
dnl Checks for standard header files, to make memdebug.h inclusions bettter
|
dnl Checks for standard header files, to make memdebug.h inclusions bettter
|
||||||
AC_HEADER_STDC
|
AC_HEADER_STDC
|
||||||
|
|
||||||
dnl the entire --enable-debug is a hack that lives and runs on top of
|
dnl the entire --enable-debug is a hack that lives and runs on top of
|
||||||
dnl libcurl stuff so this BUILDING_LIBCURL is not THAT much uglier
|
dnl libcurl stuff so this BUILDING_LIBCURL is not THAT much uglier
|
||||||
AC_DEFINE(BUILDING_LIBCURL, 1, [when building as static part of libcurl])
|
AC_DEFINE(BUILDING_LIBCURL, 1, [when building as static part of libcurl])
|
||||||
|
|
||||||
CPPFLAGS="$CPPFLAGS -DCURLDEBUG -I$srcdir/../include"
|
CPPFLAGS="$CPPFLAGS -DCURLDEBUG -I$srcdir/../include"
|
||||||
CFLAGS="$CFLAGS -g"
|
CFLAGS="$CFLAGS -g"
|
||||||
|
|
||||||
dnl set compiler "debug" options to become more picky, and remove
|
dnl set compiler "debug" options to become more picky, and remove
|
||||||
dnl optimize options from CFLAGS
|
dnl optimize options from CFLAGS
|
||||||
CURL_CC_DEBUG_OPTS
|
CURL_CC_DEBUG_OPTS
|
||||||
|
|
||||||
;;
|
;;
|
||||||
esac ],
|
esac ],
|
||||||
AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
)
|
)
|
||||||
|
|
||||||
AC_PROG_LIBTOOL
|
AC_PROG_LIBTOOL
|
||||||
|
|
||||||
dnl check for a few basic system headers we need
|
dnl check for a few basic system headers we need
|
||||||
AC_CHECK_HEADERS(
|
AC_CHECK_HEADERS(
|
||||||
sys/types.h \
|
sys/types.h \
|
||||||
sys/time.h \
|
sys/time.h \
|
||||||
sys/select.h \
|
sys/select.h \
|
||||||
sys/socket.h \
|
sys/socket.h \
|
||||||
sys/ioctl.h \
|
sys/ioctl.h \
|
||||||
winsock.h \
|
netdb.h \
|
||||||
netinet/in.h \
|
winsock.h \
|
||||||
net/if.h \
|
netinet/in.h \
|
||||||
arpa/nameser.h \
|
net/if.h \
|
||||||
arpa/nameser_compat.h \
|
arpa/nameser.h \
|
||||||
arpa/inet.h, , ,
|
arpa/nameser_compat.h \
|
||||||
[
|
arpa/inet.h, , ,
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
[
|
||||||
#include <sys/types.h>
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
#endif
|
#include <sys/types.h>
|
||||||
dnl We do this default-include simply to make sure that the nameser_compat.h
|
#endif
|
||||||
dnl header *REALLY* can be include after the new nameser.h. It seems AIX 5.1
|
dnl We do this default-include simply to make sure that the nameser_compat.h
|
||||||
dnl (and others?) is not designed to allow this.
|
dnl header *REALLY* can be include after the new nameser.h. It seems AIX 5.1
|
||||||
#ifdef HAVE_ARPA_NAMESER_H
|
dnl (and others?) is not designed to allow this.
|
||||||
#include <arpa/nameser.h>
|
#ifdef HAVE_ARPA_NAMESER_H
|
||||||
#endif
|
#include <arpa/nameser.h>
|
||||||
|
#endif
|
||||||
dnl *Sigh* these are needed in order for net/if.h to get properly detected.
|
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
dnl *Sigh* these are needed in order for net/if.h to get properly detected.
|
||||||
#include <sys/socket.h>
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#endif
|
#include <sys/socket.h>
|
||||||
#ifdef HAVE_WINSOCK_H
|
#endif
|
||||||
#include <winsock.h>
|
#ifdef HAVE_WINSOCK_H
|
||||||
#endif
|
#include <winsock.h>
|
||||||
]
|
#endif
|
||||||
)
|
]
|
||||||
|
)
|
||||||
AC_CHECK_TYPE(socklen_t, ,
|
|
||||||
AC_DEFINE(socklen_t, int, [the length of a socket address]),
|
AC_CHECK_TYPE(socklen_t, ,
|
||||||
[
|
AC_DEFINE(socklen_t, int, [the length of a socket address]),
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
[
|
||||||
#include <sys/types.h>
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
#endif
|
#include <sys/types.h>
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
#endif
|
||||||
#include <sys/socket.h>
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#endif
|
#include <sys/socket.h>
|
||||||
#ifdef HAVE_WINSOCK_H
|
#endif
|
||||||
#include <winsock.h>
|
#ifdef HAVE_WINSOCK_H
|
||||||
#endif
|
#include <winsock.h>
|
||||||
])
|
#endif
|
||||||
|
])
|
||||||
dnl check for AF_INET6
|
|
||||||
CARES_CHECK_CONSTANT(
|
dnl check for AF_INET6
|
||||||
[
|
CARES_CHECK_CONSTANT(
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
[
|
||||||
#include <sys/types.h>
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
#endif
|
#include <sys/types.h>
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
#endif
|
||||||
#include <sys/socket.h>
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#endif
|
#include <sys/socket.h>
|
||||||
#ifdef HAVE_WINSOCK_H
|
#endif
|
||||||
#include <winsock.h>
|
#ifdef HAVE_WINSOCK_H
|
||||||
#endif
|
#include <winsock.h>
|
||||||
|
#endif
|
||||||
], [PF_INET6],
|
|
||||||
AC_DEFINE_UNQUOTED(HAVE_PF_INET6,1,[Define to 1 if you have PF_INET6.])
|
], [PF_INET6],
|
||||||
)
|
AC_DEFINE_UNQUOTED(HAVE_PF_INET6,1,[Define to 1 if you have PF_INET6.])
|
||||||
|
)
|
||||||
dnl check for PF_INET6
|
|
||||||
CARES_CHECK_CONSTANT(
|
dnl check for PF_INET6
|
||||||
[
|
CARES_CHECK_CONSTANT(
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
[
|
||||||
#include <sys/types.h>
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
#endif
|
#include <sys/types.h>
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
#endif
|
||||||
#include <sys/socket.h>
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#endif
|
#include <sys/socket.h>
|
||||||
#ifdef HAVE_WINSOCK_H
|
#endif
|
||||||
#include <winsock.h>
|
#ifdef HAVE_WINSOCK_H
|
||||||
#endif
|
#include <winsock.h>
|
||||||
|
#endif
|
||||||
], [AF_INET6],
|
|
||||||
AC_DEFINE_UNQUOTED(HAVE_AF_INET6,1,[Define to 1 if you have AF_INET6.])
|
], [AF_INET6],
|
||||||
)
|
AC_DEFINE_UNQUOTED(HAVE_AF_INET6,1,[Define to 1 if you have AF_INET6.])
|
||||||
|
)
|
||||||
|
|
||||||
dnl check for the in6_addr structure
|
|
||||||
CARES_CHECK_STRUCT(
|
dnl check for the in6_addr structure
|
||||||
[
|
CARES_CHECK_STRUCT(
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
[
|
||||||
#include <sys/types.h>
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
#endif
|
#include <sys/types.h>
|
||||||
#ifdef HAVE_WINSOCK_H
|
#endif
|
||||||
#include <winsock.h>
|
#ifdef HAVE_WINSOCK_H
|
||||||
#endif
|
#include <winsock.h>
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#endif
|
||||||
#include <netinet/in.h>
|
#ifdef HAVE_NETINET_IN_H
|
||||||
#endif
|
#include <netinet/in.h>
|
||||||
], [in6_addr],
|
#endif
|
||||||
AC_DEFINE_UNQUOTED(HAVE_STRUCT_IN6_ADDR,1,[Define to 1 if you have struct in6_addr.])
|
], [in6_addr],
|
||||||
)
|
AC_DEFINE_UNQUOTED(HAVE_STRUCT_IN6_ADDR,1,[Define to 1 if you have struct in6_addr.])
|
||||||
|
)
|
||||||
dnl check for the sockaddr_in6 structure
|
|
||||||
CARES_CHECK_STRUCT(
|
dnl check for the sockaddr_in6 structure
|
||||||
[
|
CARES_CHECK_STRUCT(
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
[
|
||||||
#include <sys/types.h>
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
#endif
|
#include <sys/types.h>
|
||||||
#ifdef HAVE_WINSOCK_H
|
#endif
|
||||||
#include <winsock.h>
|
#ifdef HAVE_WINSOCK_H
|
||||||
#endif
|
#include <winsock.h>
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#endif
|
||||||
#include <netinet/in.h>
|
#ifdef HAVE_NETINET_IN_H
|
||||||
#endif
|
#include <netinet/in.h>
|
||||||
], [sockaddr_in6],
|
#endif
|
||||||
AC_DEFINE_UNQUOTED(HAVE_STRUCT_SOCKADDR_IN6,1,
|
], [sockaddr_in6],
|
||||||
[Define to 1 if you have struct sockaddr_in6.]) ac_have_sockaddr_in6=yes
|
AC_DEFINE_UNQUOTED(HAVE_STRUCT_SOCKADDR_IN6,1,
|
||||||
)
|
[Define to 1 if you have struct sockaddr_in6.]) ac_have_sockaddr_in6=yes
|
||||||
|
)
|
||||||
if test "$ac_have_sockaddr_in6" = "yes" ; then
|
|
||||||
CARES_CHECK_STRUCT_MEMBER(
|
AC_CHECK_MEMBER(struct sockaddr_in6.sin6_scope_id,
|
||||||
[
|
AC_DEFINE_UNQUOTED(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID,1,
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
[Define to 1 if your struct sockaddr_in6 has sin6_scope_id.])
|
||||||
#include <sys/types.h>
|
, ,
|
||||||
#endif
|
[
|
||||||
#ifdef HAVE_WINSOCK_H
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
#include <winsock.h>
|
#include <sys/types.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#ifdef HAVE_WINSOCK_H
|
||||||
#include <netinet/in.h>
|
#include <winsock.h>
|
||||||
#endif
|
#endif
|
||||||
], [sockaddr_in6], [sin6_scope_id],
|
#ifdef HAVE_NETINET_IN_H
|
||||||
AC_DEFINE_UNQUOTED(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID,1,
|
#include <netinet/in.h>
|
||||||
[Define to 1 if your struct sockaddr_in6 has sin6_scope_id.])
|
#endif
|
||||||
)
|
])
|
||||||
fi
|
|
||||||
|
dnl check for the addrinfo structure
|
||||||
dnl check for the addrinfo structure
|
AC_CHECK_MEMBER(struct addrinfo.ai_flags,
|
||||||
CARES_CHECK_STRUCT(
|
AC_DEFINE_UNQUOTED(HAVE_STRUCT_ADDRINFO,1,
|
||||||
[
|
[Define to 1 if you have struct addrinfo.]),,
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
[
|
||||||
#include <sys/types.h>
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
#endif
|
#include <sys/types.h>
|
||||||
#ifdef HAVE_WINSOCK_H
|
#endif
|
||||||
#include <winsock.h>
|
#ifdef HAVE_WINSOCK_H
|
||||||
#endif
|
#include <winsock.h>
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#endif
|
||||||
#include <netinet/in.h>
|
#ifdef HAVE_NETINET_IN_H
|
||||||
#endif
|
#include <netinet/in.h>
|
||||||
], [addrinfo],
|
#endif
|
||||||
AC_DEFINE_UNQUOTED(HAVE_STRUCT_ADDRINFO,1,
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
[Define to 1 if you have struct addrinfo.])
|
#include <sys/socket.h>
|
||||||
)
|
#endif
|
||||||
|
#ifdef HAVE_NETDB_H
|
||||||
dnl check for inet_pton
|
#include <netdb.h>
|
||||||
AC_CHECK_FUNCS(inet_pton)
|
#endif
|
||||||
dnl Some systems have it, but not IPv6
|
]
|
||||||
if test "$ac_cv_func_inet_pton" = "yes" ; then
|
)
|
||||||
AC_MSG_CHECKING(if inet_pton supports IPv6)
|
|
||||||
AC_TRY_RUN(
|
dnl check for inet_pton
|
||||||
[
|
AC_CHECK_FUNCS(inet_pton)
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
dnl Some systems have it, but not IPv6
|
||||||
#include <sys/types.h>
|
if test "$ac_cv_func_inet_pton" = "yes" ; then
|
||||||
#endif
|
AC_MSG_CHECKING(if inet_pton supports IPv6)
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
AC_TRY_RUN(
|
||||||
#include <sys/socket.h>
|
[
|
||||||
#endif
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
#ifdef HAVE_WINSOCK_H
|
#include <sys/types.h>
|
||||||
#include <winsock.h>
|
#endif
|
||||||
#endif
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#endif
|
||||||
#endif
|
#ifdef HAVE_WINSOCK_H
|
||||||
int main()
|
#include <winsock.h>
|
||||||
{
|
#endif
|
||||||
struct in6_addr addr6;
|
#ifdef HAVE_NETINET_IN_H
|
||||||
if (inet_pton(AF_INET6, "::1", &addr6) < 1)
|
#include <netinet/in.h>
|
||||||
exit(1);
|
#endif
|
||||||
else
|
int main()
|
||||||
exit(0);
|
{
|
||||||
}
|
struct in6_addr addr6;
|
||||||
], [
|
if (inet_pton(AF_INET6, "::1", &addr6) < 1)
|
||||||
AC_MSG_RESULT(yes)
|
exit(1);
|
||||||
AC_DEFINE_UNQUOTED(HAVE_INET_PTON_IPV6,1,[Define to 1 if inet_pton supports IPv6.])
|
else
|
||||||
], AC_MSG_RESULT(no),AC_MSG_RESULT(no))
|
exit(0);
|
||||||
fi
|
}
|
||||||
dnl Check for inet_net_pton
|
], [
|
||||||
AC_CHECK_FUNCS(inet_net_pton)
|
AC_MSG_RESULT(yes)
|
||||||
dnl Again, some systems have it, but not IPv6
|
AC_DEFINE_UNQUOTED(HAVE_INET_PTON_IPV6,1,[Define to 1 if inet_pton supports IPv6.])
|
||||||
if test "$ac_cv_func_inet_net_pton" = "yes" ; then
|
], AC_MSG_RESULT(no),AC_MSG_RESULT(no))
|
||||||
AC_MSG_CHECKING(if inet_net_pton supports IPv6)
|
fi
|
||||||
AC_TRY_RUN(
|
dnl Check for inet_net_pton
|
||||||
[
|
AC_CHECK_FUNCS(inet_net_pton)
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
dnl Again, some systems have it, but not IPv6
|
||||||
#include <sys/types.h>
|
if test "$ac_cv_func_inet_net_pton" = "yes" ; then
|
||||||
#endif
|
AC_MSG_CHECKING(if inet_net_pton supports IPv6)
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
AC_TRY_RUN(
|
||||||
#include <sys/socket.h>
|
[
|
||||||
#endif
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
#ifdef HAVE_WINSOCK_H
|
#include <sys/types.h>
|
||||||
#include <winsock.h>
|
#endif
|
||||||
#endif
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#endif
|
||||||
#endif
|
#ifdef HAVE_WINSOCK_H
|
||||||
int main()
|
#include <winsock.h>
|
||||||
{
|
#endif
|
||||||
struct in6_addr addr6;
|
#ifdef HAVE_NETINET_IN_H
|
||||||
if (inet_net_pton(AF_INET6, "::1", &addr6, sizeof(addr6)) < 1)
|
#include <netinet/in.h>
|
||||||
exit(1);
|
#endif
|
||||||
else
|
int main()
|
||||||
exit(0);
|
{
|
||||||
}
|
struct in6_addr addr6;
|
||||||
], [
|
if (inet_net_pton(AF_INET6, "::1", &addr6, sizeof(addr6)) < 1)
|
||||||
AC_MSG_RESULT(yes)
|
exit(1);
|
||||||
AC_DEFINE_UNQUOTED(HAVE_INET_NET_PTON_IPV6,1,[Define to 1 if inet_net_pton supports IPv6.])
|
else
|
||||||
], AC_MSG_RESULT(no),AC_MSG_RESULT(no))
|
exit(0);
|
||||||
fi
|
}
|
||||||
|
], [
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
dnl Check for inet_ntop
|
AC_DEFINE_UNQUOTED(HAVE_INET_NET_PTON_IPV6,1,[Define to 1 if inet_net_pton supports IPv6.])
|
||||||
AC_CHECK_FUNCS(inet_ntop)
|
], AC_MSG_RESULT(no),AC_MSG_RESULT(no))
|
||||||
dnl Again, some systems have it, but not IPv6
|
fi
|
||||||
if test "$ac_cv_func_inet_ntop" = "yes" ; then
|
|
||||||
AC_MSG_CHECKING(if inet_ntop supports IPv6)
|
|
||||||
AC_TRY_RUN(
|
dnl Check for inet_ntop
|
||||||
[
|
AC_CHECK_FUNCS(inet_ntop)
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
dnl Again, some systems have it, but not IPv6
|
||||||
#include <sys/types.h>
|
if test "$ac_cv_func_inet_ntop" = "yes" ; then
|
||||||
#endif
|
AC_MSG_CHECKING(if inet_ntop supports IPv6)
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
AC_TRY_RUN(
|
||||||
#include <sys/socket.h>
|
[
|
||||||
#endif
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
#ifdef HAVE_WINSOCK_H
|
#include <sys/types.h>
|
||||||
#include <winsock.h>
|
#endif
|
||||||
#endif
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#endif
|
||||||
#endif
|
#ifdef HAVE_WINSOCK_H
|
||||||
#include <errno.h>
|
#include <winsock.h>
|
||||||
int main()
|
#endif
|
||||||
{
|
#ifdef HAVE_NETINET_IN_H
|
||||||
struct in6_addr addr6;
|
#include <netinet/in.h>
|
||||||
char buf[128];
|
#endif
|
||||||
if (inet_ntop(AF_INET6, &addr6, buf, 128) == 0 && errno == EAFNOSUPPORT)
|
#include <errno.h>
|
||||||
exit(1);
|
int main()
|
||||||
else
|
{
|
||||||
exit(0);
|
struct in6_addr addr6;
|
||||||
}
|
char buf[128];
|
||||||
], [
|
if (inet_ntop(AF_INET6, &addr6, buf, 128) == 0 && errno == EAFNOSUPPORT)
|
||||||
AC_MSG_RESULT(yes)
|
exit(1);
|
||||||
AC_DEFINE_UNQUOTED(HAVE_INET_NTOP_IPV6,1,[Define to 1 if inet_ntop supports IPv6.])
|
else
|
||||||
], AC_MSG_RESULT(no),AC_MSG_RESULT(no))
|
exit(0);
|
||||||
fi
|
}
|
||||||
|
], [
|
||||||
AC_CHECK_SIZEOF(struct in6_addr, ,
|
AC_MSG_RESULT(yes)
|
||||||
[
|
AC_DEFINE_UNQUOTED(HAVE_INET_NTOP_IPV6,1,[Define to 1 if inet_ntop supports IPv6.])
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
], AC_MSG_RESULT(no),AC_MSG_RESULT(no))
|
||||||
#include <sys/types.h>
|
fi
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
AC_CHECK_SIZEOF(struct in6_addr, ,
|
||||||
#include <sys/socket.h>
|
[
|
||||||
#endif
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
#ifdef HAVE_WINSOCK_H
|
#include <sys/types.h>
|
||||||
#include <winsock.h>
|
#endif
|
||||||
#endif
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#endif
|
||||||
#endif
|
#ifdef HAVE_WINSOCK_H
|
||||||
]
|
#include <winsock.h>
|
||||||
)
|
#endif
|
||||||
AC_CHECK_SIZEOF(struct in_addr, ,
|
#ifdef HAVE_NETINET_IN_H
|
||||||
[
|
#include <netinet/in.h>
|
||||||
#ifdef HAVE_SYS_TYPES_H
|
#endif
|
||||||
#include <sys/types.h>
|
]
|
||||||
#endif
|
)
|
||||||
#ifdef HAVE_SYS_SOCKET_H
|
AC_CHECK_SIZEOF(struct in_addr, ,
|
||||||
#include <sys/socket.h>
|
[
|
||||||
#endif
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
#ifdef HAVE_WINSOCK_H
|
#include <sys/types.h>
|
||||||
#include <winsock.h>
|
#endif
|
||||||
#endif
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
#ifdef HAVE_NETINET_IN_H
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#endif
|
||||||
#endif
|
#ifdef HAVE_WINSOCK_H
|
||||||
]
|
#include <winsock.h>
|
||||||
)
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
AC_CHECK_FUNCS([bitncmp if_indextoname])
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
CURL_CHECK_NONBLOCKING_SOCKET
|
]
|
||||||
|
)
|
||||||
AC_OUTPUT(Makefile)
|
|
||||||
|
AC_CHECK_FUNCS([bitncmp if_indextoname])
|
||||||
|
|
||||||
|
dnl God bless non-standardized functions! We need to see which getservbyport_r variant is available
|
||||||
|
CARES_CHECK_GETSERVBYPORT_R
|
||||||
|
|
||||||
|
CURL_CHECK_NONBLOCKING_SOCKET
|
||||||
|
|
||||||
|
AC_OUTPUT(Makefile)
|
||||||
|
@@ -209,7 +209,7 @@ ${LIBTOOLIZE:-libtoolize} --copy --automake --force || die "The libtool command
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
echo "buildconf: running automake"
|
echo "buildconf: running automake"
|
||||||
${AUTOMAKE:-automake} -a || die "The automake command failed"
|
${AUTOMAKE:-automake} -a -c || die "The automake command failed"
|
||||||
|
|
||||||
echo "buildconf: OK"
|
echo "buildconf: OK"
|
||||||
exit 0
|
exit 0
|
||||||
|
25
configure.ac
25
configure.ac
@@ -122,13 +122,13 @@ case $host in
|
|||||||
*-*-mingw*)
|
*-*-mingw*)
|
||||||
AC_DEFINE(BUILDING_LIBCURL, 1, [when building libcurl itself])
|
AC_DEFINE(BUILDING_LIBCURL, 1, [when building libcurl itself])
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
<EFBFBD> <20>AC_MSG_CHECKING([if we need CURL_STATICLIB])
|
AC_MSG_CHECKING([if we need CURL_STATICLIB])
|
||||||
if test "X$enable_shared" = "Xno"
|
if test "X$enable_shared" = "Xno"
|
||||||
then
|
then
|
||||||
AC_DEFINE(CURL_STATICLIB, 1, [when not building a shared library])
|
AC_DEFINE(CURL_STATICLIB, 1, [when not building a shared library])
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
<EFBFBD> <20>else
|
else
|
||||||
<EFBFBD> <20> <20>AC_MSG_RESULT(no)
|
AC_MSG_RESULT(no)
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
@@ -251,6 +251,21 @@ AC_HELP_STRING([--disable-telnet],[Disable TELNET support]),
|
|||||||
esac ],
|
esac ],
|
||||||
AC_MSG_RESULT(yes)
|
AC_MSG_RESULT(yes)
|
||||||
)
|
)
|
||||||
|
AC_MSG_CHECKING([whether to support tftp])
|
||||||
|
AC_ARG_ENABLE(tftp,
|
||||||
|
AC_HELP_STRING([--enable-tftp],[Enable TFTP support])
|
||||||
|
AC_HELP_STRING([--disable-tftp],[Disable TFTP support]),
|
||||||
|
[ case "$enableval" in
|
||||||
|
no)
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
AC_DEFINE(CURL_DISABLE_TFTP, 1, [to disable TFTP])
|
||||||
|
AC_SUBST(CURL_DISABLE_TFTP, [1])
|
||||||
|
;;
|
||||||
|
*) AC_MSG_RESULT(yes)
|
||||||
|
;;
|
||||||
|
esac ],
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
)
|
||||||
|
|
||||||
dnl **********************************************************************
|
dnl **********************************************************************
|
||||||
dnl Check for built-in manual
|
dnl Check for built-in manual
|
||||||
@@ -1419,6 +1434,8 @@ AC_CHECK_HEADERS(
|
|||||||
libgen.h \
|
libgen.h \
|
||||||
locale.h \
|
locale.h \
|
||||||
errno.h \
|
errno.h \
|
||||||
|
arpa/tftp.h \
|
||||||
|
sys/filio.h \
|
||||||
setjmp.h,
|
setjmp.h,
|
||||||
dnl to do if not found
|
dnl to do if not found
|
||||||
[],
|
[],
|
||||||
@@ -1673,7 +1690,7 @@ AC_HELP_STRING([--disable-ares],[Disable ares for name lookups]),
|
|||||||
*) AC_MSG_RESULT(yes)
|
*) AC_MSG_RESULT(yes)
|
||||||
|
|
||||||
if test "x$IPV6_ENABLED" = "x1"; then
|
if test "x$IPV6_ENABLED" = "x1"; then
|
||||||
AC_MSG_ERROR([ares doesn't work with ipv6, disable ipv6 to use ares])
|
AC_MSG_NOTICE([ares may not work properly with ipv6])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_DEFINE(USE_ARES, 1, [Define if you want to enable ares support])
|
AC_DEFINE(USE_ARES, 1, [Define if you want to enable ares support])
|
||||||
|
@@ -116,6 +116,9 @@ while test $# -gt 0; do
|
|||||||
if test "@CURL_DISABLE_DICT@" != "1"; then
|
if test "@CURL_DISABLE_DICT@" != "1"; then
|
||||||
echo "DICT"
|
echo "DICT"
|
||||||
fi
|
fi
|
||||||
|
if test "@CURL_DISABLE_TFTP@" != "1"; then
|
||||||
|
echo "TFTP"
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
--version)
|
--version)
|
||||||
echo libcurl @VERSION@
|
echo libcurl @VERSION@
|
||||||
|
@@ -150,6 +150,11 @@ Scheme
|
|||||||
Bigloo binding written by Kirill Lisovsky
|
Bigloo binding written by Kirill Lisovsky
|
||||||
http://curl.haxx.se/libcurl/scheme/
|
http://curl.haxx.se/libcurl/scheme/
|
||||||
|
|
||||||
|
S-Lang
|
||||||
|
|
||||||
|
S-Lang binding written by John E Davis
|
||||||
|
http://www.jedsoft.org/slang/modules/curl.html
|
||||||
|
|
||||||
Tcl
|
Tcl
|
||||||
|
|
||||||
Tclcurl is written by Andr<64>s Garc<72>a
|
Tclcurl is written by Andr<64>s Garc<72>a
|
||||||
@@ -161,7 +166,7 @@ Visual Basic
|
|||||||
http://sourceforge.net/projects/libcurl-vb/
|
http://sourceforge.net/projects/libcurl-vb/
|
||||||
|
|
||||||
Q
|
Q
|
||||||
|
The libcurl module is part of the default install
|
||||||
http://q-lang.sourceforge.net/
|
http://q-lang.sourceforge.net/
|
||||||
|
|
||||||
wxWidgets
|
wxWidgets
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
Date: September 1, 2005
|
Date: September 30, 2005
|
||||||
Author: Daniel Stenberg <daniel@haxx.se>
|
Author: Daniel Stenberg <daniel@haxx.se>
|
||||||
URL: http://curl.haxx.se/legal/distro-dilemma.html
|
URL: http://curl.haxx.se/legal/distro-dilemma.html
|
||||||
|
|
||||||
Condition
|
Condition
|
||||||
|
|
||||||
This document is written to describe the sitution as it is right now. libcurl
|
This document is written to describe the situation as it is right
|
||||||
7.14.0 is currently the latest version available. Things may (or perhaps
|
now. libcurl 7.14.1 is currently the latest version available. Things may (or
|
||||||
will) of course change in the future.
|
perhaps will) of course change in the future.
|
||||||
|
|
||||||
This document reflects my view and understanding of these things. Please tell
|
This document reflects my view and understanding of these things. Please tell
|
||||||
me where and how you think I'm wrong, and I'll try to correct my mistakes.
|
me where and how you think I'm wrong, and I'll try to correct my mistakes.
|
||||||
@@ -16,7 +16,7 @@ Background
|
|||||||
The Free Software Foundation has deemed the Original BSD license[1] to be
|
The Free Software Foundation has deemed the Original BSD license[1] to be
|
||||||
"incompatible"[2] with GPL[3]. I'd rather say it is the other way around, but
|
"incompatible"[2] with GPL[3]. I'd rather say it is the other way around, but
|
||||||
the point is the same: if you distribute a binary version of a GPL program,
|
the point is the same: if you distribute a binary version of a GPL program,
|
||||||
it MUST NOT be linked with any Original BSD-licenced parts or
|
it MUST NOT be linked with any Original BSD-licensed parts or
|
||||||
libraries. Doing so will violate the GPL license. For a long time, very many
|
libraries. Doing so will violate the GPL license. For a long time, very many
|
||||||
GPL licensed programs have avoided this license mess by adding an
|
GPL licensed programs have avoided this license mess by adding an
|
||||||
exception[8] to their license. And many others have just closed their eyes
|
exception[8] to their license. And many others have just closed their eyes
|
||||||
@@ -38,7 +38,7 @@ Background
|
|||||||
Part of the Operating System
|
Part of the Operating System
|
||||||
|
|
||||||
This would not be a problem if the used lib would be considered part of the
|
This would not be a problem if the used lib would be considered part of the
|
||||||
uderlying operating system, as then the GPL license has an exception
|
underlying operating system, as then the GPL license has an exception
|
||||||
clause[6] that allows applications to use such libs without having to be
|
clause[6] that allows applications to use such libs without having to be
|
||||||
allowed to distribute it or its sources. Possibly some distros will claim
|
allowed to distribute it or its sources. Possibly some distros will claim
|
||||||
that OpenSSL is part of their operating system.
|
that OpenSSL is part of their operating system.
|
||||||
@@ -92,8 +92,13 @@ The Better License, Original BSD or LGPL?
|
|||||||
Instead, I think we should accept the fact that the SSL/TLS libraries and
|
Instead, I think we should accept the fact that the SSL/TLS libraries and
|
||||||
their different licenses will fit different applications and their authors
|
their different licenses will fit different applications and their authors
|
||||||
differently depending on the applications' licenses and their general usage
|
differently depending on the applications' licenses and their general usage
|
||||||
pattern (considering how LGPL libraries can be burdonsome for embedded
|
pattern (considering how LGPL libraries for example can be burdensome for
|
||||||
systems usage).
|
embedded systems usage).
|
||||||
|
|
||||||
|
In Debian land, there seems to be a common opinion that LGPL is "maximally
|
||||||
|
compatible" with apps while Original BSD is not. Like this:
|
||||||
|
|
||||||
|
http://lists.debian.org/debian-devel/2005/09/msg01417.html
|
||||||
|
|
||||||
More SSL Libraries
|
More SSL Libraries
|
||||||
|
|
||||||
@@ -116,6 +121,16 @@ Project cURL Angle of this Problem
|
|||||||
affects users - GPL application authors only - of our lib as it comes
|
affects users - GPL application authors only - of our lib as it comes
|
||||||
included and delivered on some distros.
|
included and delivered on some distros.
|
||||||
|
|
||||||
|
libcurl has different ABI when built with different SSL/TLS libraries due to
|
||||||
|
two reasons:
|
||||||
|
|
||||||
|
1. No one has worked on fixing this. The mutex/lock callbacks should be set
|
||||||
|
with a generic libcurl function that should use the proper underlying
|
||||||
|
functions.
|
||||||
|
|
||||||
|
2. The CURLOPT_SSL_CTX_FUNCTION option is not possible to "emulate" on GnuTLS
|
||||||
|
but simply requires OpenSSL.
|
||||||
|
|
||||||
Distro Angle of this Problem
|
Distro Angle of this Problem
|
||||||
|
|
||||||
A distro can provide separate libcurls built with different SSL/TLS libraries
|
A distro can provide separate libcurls built with different SSL/TLS libraries
|
||||||
@@ -170,6 +185,10 @@ When Will This Happen
|
|||||||
code like today (without the use of lib2), should you decide to ignore the
|
code like today (without the use of lib2), should you decide to ignore the
|
||||||
problems outlined in this document.
|
problems outlined in this document.
|
||||||
|
|
||||||
|
Update: Work on this has been initiated by Richard Atterer:
|
||||||
|
|
||||||
|
http://curl.haxx.se/mail/lib-2005-09/0066.html
|
||||||
|
|
||||||
Footnotes
|
Footnotes
|
||||||
|
|
||||||
[1] = http://www.xfree86.org/3.3.6/COPYRIGHT2.html#6
|
[1] = http://www.xfree86.org/3.3.6/COPYRIGHT2.html#6
|
||||||
|
@@ -145,3 +145,9 @@ August 2004:
|
|||||||
April 2005:
|
April 2005:
|
||||||
|
|
||||||
GnuTLS can now optionally be used for the secure layer when curl is built.
|
GnuTLS can now optionally be used for the secure layer when curl is built.
|
||||||
|
|
||||||
|
September 2005:
|
||||||
|
|
||||||
|
TFTP support was added.
|
||||||
|
|
||||||
|
More than 100,000 unique visitors of the curl web site. 25 mirrors.
|
||||||
|
@@ -3,6 +3,10 @@ join in and help us correct one or more of these! Also be sure to check the
|
|||||||
changelog of the current development status, as one or more of these problems
|
changelog of the current development status, as one or more of these problems
|
||||||
may have been fixed since this was written!
|
may have been fixed since this was written!
|
||||||
|
|
||||||
|
26. NTLM authentication using SSPI (on Windows) when (lib)curl is running in
|
||||||
|
"system context" will make it use wrong(?) user name - at least when compared
|
||||||
|
to what winhttp does. See http://curl.haxx.se/bug/view.cgi?id=1281867
|
||||||
|
|
||||||
25. When doing a CONNECT request with curl it doesn't properly handle if the
|
25. When doing a CONNECT request with curl it doesn't properly handle if the
|
||||||
proxy closes the connection within the authentication "negotiation phase".
|
proxy closes the connection within the authentication "negotiation phase".
|
||||||
Like if you do HTTPS or similar over a proxy and you use perhaps
|
Like if you do HTTPS or similar over a proxy and you use perhaps
|
||||||
@@ -23,7 +27,7 @@ may have been fixed since this was written!
|
|||||||
complaining on "unaligned file size" on completion. The problem is related
|
complaining on "unaligned file size" on completion. The problem is related
|
||||||
to VMS file structures and the perceived file sizes stat() returns. A
|
to VMS file structures and the perceived file sizes stat() returns. A
|
||||||
possible fix would involve sending a "STRU VMS" command.
|
possible fix would involve sending a "STRU VMS" command.
|
||||||
http://sourceforge.net/support/tracker.php?aid=1156287
|
http://curl.haxx.se/bug/view.cgi?id=1156287
|
||||||
|
|
||||||
21. FTP ASCII transfers do not follow RFC959. They don't convert the data
|
21. FTP ASCII transfers do not follow RFC959. They don't convert the data
|
||||||
accordingly (not for sending nor for receiving). RFC 959 section 3.1.1.1
|
accordingly (not for sending nor for receiving). RFC 959 section 3.1.1.1
|
||||||
@@ -69,11 +73,12 @@ may have been fixed since this was written!
|
|||||||
10. To get HTTP Negotiate authentication to work fine, you need to provide a
|
10. To get HTTP Negotiate authentication to work fine, you need to provide a
|
||||||
(fake) user name (this concerns both curl and the lib) because the code
|
(fake) user name (this concerns both curl and the lib) because the code
|
||||||
wrongly only considers authentication if there's a user name provided.
|
wrongly only considers authentication if there's a user name provided.
|
||||||
Bug report #1004841. How? http://curl.haxx.se/mail/lib-2004-08/0182.html
|
http://curl.haxx.se/bug/view.cgi?id=1004841. How?
|
||||||
|
http://curl.haxx.se/mail/lib-2004-08/0182.html
|
||||||
|
|
||||||
9. --limit-rate using -d or -F does not work. This is because the limit logic
|
9. --limit-rate using -d or -F does not work. This is because the limit logic
|
||||||
is provided by the curl app in its read/write callbacks, and when doing
|
is provided by the curl app in its read/write callbacks, and when doing
|
||||||
-d/-F the callbacks aren't used! Bug report #921395.
|
-d/-F the callbacks aren't used! http://curl.haxx.se/bug/view.cgi?id=921395
|
||||||
|
|
||||||
8. Doing resumed upload over HTTP does not work with '-C -', because curl
|
8. Doing resumed upload over HTTP does not work with '-C -', because curl
|
||||||
doesn't do a HEAD first to get the initial size. This needs to be done
|
doesn't do a HEAD first to get the initial size. This needs to be done
|
||||||
|
26
docs/THANKS
26
docs/THANKS
@@ -9,15 +9,14 @@ Alan Pinstein
|
|||||||
Albert Chin-A-Young
|
Albert Chin-A-Young
|
||||||
Albert Choy
|
Albert Choy
|
||||||
Aleksandar Milivojevic
|
Aleksandar Milivojevic
|
||||||
Alex aka WindEagle
|
|
||||||
Alex Neblett
|
Alex Neblett
|
||||||
Alex Suykov
|
Alex Suykov
|
||||||
|
Alex aka WindEagle
|
||||||
Alexander Kourakos
|
Alexander Kourakos
|
||||||
Alexander Krasnostavsky
|
Alexander Krasnostavsky
|
||||||
Alexander Zhuravlev
|
Alexander Zhuravlev
|
||||||
Alexis Carvalho
|
Alexis Carvalho
|
||||||
Andi Jahja
|
Andi Jahja
|
||||||
Andr<EFBFBD>s Garc<72>a
|
|
||||||
Andreas Damm
|
Andreas Damm
|
||||||
Andreas Olsson
|
Andreas Olsson
|
||||||
Andreas Rieke
|
Andreas Rieke
|
||||||
@@ -25,6 +24,7 @@ Andres Garcia
|
|||||||
Andrew Bushnell
|
Andrew Bushnell
|
||||||
Andrew Francis
|
Andrew Francis
|
||||||
Andrew Fuller
|
Andrew Fuller
|
||||||
|
Andr<EFBFBD>s Garc<72>a
|
||||||
Andy Cedilnik
|
Andy Cedilnik
|
||||||
Andy Serpa
|
Andy Serpa
|
||||||
Angus Mackay
|
Angus Mackay
|
||||||
@@ -36,8 +36,8 @@ Avery Fay
|
|||||||
Ben Greear
|
Ben Greear
|
||||||
Benjamin Gerard
|
Benjamin Gerard
|
||||||
Bertrand Demiddelaer
|
Bertrand Demiddelaer
|
||||||
Bj<EFBFBD>rn Stenberg
|
|
||||||
Bjorn Reese
|
Bjorn Reese
|
||||||
|
Bj<EFBFBD>rn Stenberg
|
||||||
Bob Schader
|
Bob Schader
|
||||||
Brad Burdick
|
Brad Burdick
|
||||||
Brent Beardsley
|
Brent Beardsley
|
||||||
@@ -75,8 +75,8 @@ Dan C
|
|||||||
Dan Fandrich
|
Dan Fandrich
|
||||||
Dan Torop
|
Dan Torop
|
||||||
Dan Zitter
|
Dan Zitter
|
||||||
Daniel at touchtunes
|
|
||||||
Daniel Stenberg
|
Daniel Stenberg
|
||||||
|
Daniel at touchtunes
|
||||||
Dave Dribin
|
Dave Dribin
|
||||||
Dave Halbakken
|
Dave Halbakken
|
||||||
Dave Hamilton
|
Dave Hamilton
|
||||||
@@ -138,8 +138,6 @@ Frank Ticheler
|
|||||||
Fred New
|
Fred New
|
||||||
Fred Noz
|
Fred Noz
|
||||||
Frederic Lepied
|
Frederic Lepied
|
||||||
G<EFBFBD>nter Knauf
|
|
||||||
G<EFBFBD>tz Babin-Ebell
|
|
||||||
Gautam Mani
|
Gautam Mani
|
||||||
Gaz Iqbal
|
Gaz Iqbal
|
||||||
Georg Horn
|
Georg Horn
|
||||||
@@ -162,6 +160,8 @@ Guenole Bescon
|
|||||||
Guillaume Arluison
|
Guillaume Arluison
|
||||||
Gustaf Hui
|
Gustaf Hui
|
||||||
Gwenole Beauchesne
|
Gwenole Beauchesne
|
||||||
|
G<EFBFBD>tz Babin-Ebell
|
||||||
|
G<EFBFBD>nter Knauf
|
||||||
Hamish Mackenzie
|
Hamish Mackenzie
|
||||||
Hanno Kranzhoff
|
Hanno Kranzhoff
|
||||||
Hans Steegers
|
Hans Steegers
|
||||||
@@ -174,11 +174,10 @@ Ian Ford
|
|||||||
Ian Gulliver
|
Ian Gulliver
|
||||||
Ian Wilkes
|
Ian Wilkes
|
||||||
Ignacio Vazquez-Abrams
|
Ignacio Vazquez-Abrams
|
||||||
|
Igor Polyakov
|
||||||
Ilguiz Latypov
|
Ilguiz Latypov
|
||||||
Ingo Ralf Blum
|
Ingo Ralf Blum
|
||||||
Ingo Wilken
|
Ingo Wilken
|
||||||
J<EFBFBD>rg Mueller-Tolk
|
|
||||||
J<EFBFBD>rn Hartroth
|
|
||||||
Jacky Lam
|
Jacky Lam
|
||||||
Jacob Meuser
|
Jacob Meuser
|
||||||
James Bursa
|
James Bursa
|
||||||
@@ -225,6 +224,8 @@ Jukka Pihl
|
|||||||
Julian Noble
|
Julian Noble
|
||||||
Jun-ichiro itojun Hagino
|
Jun-ichiro itojun Hagino
|
||||||
Jurij Smakov
|
Jurij Smakov
|
||||||
|
J<EFBFBD>rg Mueller-Tolk
|
||||||
|
J<EFBFBD>rn Hartroth
|
||||||
Kai Sommerfeld
|
Kai Sommerfeld
|
||||||
Kai-Uwe Rommel
|
Kai-Uwe Rommel
|
||||||
Kang-Jin Lee
|
Kang-Jin Lee
|
||||||
@@ -234,6 +235,7 @@ Keith McGuigan
|
|||||||
Ken Hirsch
|
Ken Hirsch
|
||||||
Ken Rastatter
|
Ken Rastatter
|
||||||
Kevin Fisk
|
Kevin Fisk
|
||||||
|
Kevin Lussier
|
||||||
Kevin Roth
|
Kevin Roth
|
||||||
Kimmo Kinnunen
|
Kimmo Kinnunen
|
||||||
Kjell Ericson
|
Kjell Ericson
|
||||||
@@ -312,8 +314,8 @@ Nicolas Berloquin
|
|||||||
Nicolas Croiset
|
Nicolas Croiset
|
||||||
Niels van Tongeren
|
Niels van Tongeren
|
||||||
Nikita Schmidt
|
Nikita Schmidt
|
||||||
nk
|
|
||||||
Nodak Sodak
|
Nodak Sodak
|
||||||
|
Norbert Novotny
|
||||||
Oren Tirosh
|
Oren Tirosh
|
||||||
P R Schaffner
|
P R Schaffner
|
||||||
Patrick Bihan-Faou
|
Patrick Bihan-Faou
|
||||||
@@ -376,7 +378,6 @@ Rosimildo da Silva
|
|||||||
Roy Shan
|
Roy Shan
|
||||||
Rune Kleveland
|
Rune Kleveland
|
||||||
Ryan Nelson
|
Ryan Nelson
|
||||||
S<EFBFBD>bastien Willemijns
|
|
||||||
S. Moonesamy
|
S. Moonesamy
|
||||||
Salvador D<>vila
|
Salvador D<>vila
|
||||||
Salvatore Sorrentino
|
Salvatore Sorrentino
|
||||||
@@ -392,6 +393,7 @@ Shard
|
|||||||
Shawn Poulson
|
Shawn Poulson
|
||||||
Siddhartha Prakash Jain
|
Siddhartha Prakash Jain
|
||||||
Simon Dick
|
Simon Dick
|
||||||
|
Simon Josefsson
|
||||||
Simon Liu
|
Simon Liu
|
||||||
Spiridonoff A.V
|
Spiridonoff A.V
|
||||||
Stadler Stephan
|
Stadler Stephan
|
||||||
@@ -408,7 +410,7 @@ Steven Bazyl
|
|||||||
Steven G. Johnson
|
Steven G. Johnson
|
||||||
Stoned Elipot
|
Stoned Elipot
|
||||||
Sven Neuhaus
|
Sven Neuhaus
|
||||||
swalkaus at yahoo.com
|
S<EFBFBD>bastien Willemijns
|
||||||
T. Bharath
|
T. Bharath
|
||||||
T. Yamada
|
T. Yamada
|
||||||
Thomas Schwinge
|
Thomas Schwinge
|
||||||
@@ -451,3 +453,5 @@ Wilfredo Sanchez
|
|||||||
Wojciech Zwiefka
|
Wojciech Zwiefka
|
||||||
Yarram Sunil
|
Yarram Sunil
|
||||||
Zvi Har'El
|
Zvi Har'El
|
||||||
|
nk
|
||||||
|
swalkaus at yahoo.com
|
||||||
|
@@ -31,7 +31,7 @@ TODO
|
|||||||
* Introduce a new error code indicating authentication problems (for proxy
|
* Introduce a new error code indicating authentication problems (for proxy
|
||||||
CONNECT error 407 for example). This cannot be an error code, we must not
|
CONNECT error 407 for example). This cannot be an error code, we must not
|
||||||
return informational stuff as errors, consider a new info returned by
|
return informational stuff as errors, consider a new info returned by
|
||||||
curl_easy_getinfo() #845941
|
curl_easy_getinfo() http://curl.haxx.se/bug/view.cgi?id=845941
|
||||||
|
|
||||||
* Use 'struct lifreq' and SIOCGLIFADDR instead of 'struct ifreq' and
|
* Use 'struct lifreq' and SIOCGLIFADDR instead of 'struct ifreq' and
|
||||||
SIOCGIFADDR on newer Solaris versions as they claim the latter is obsolete.
|
SIOCGIFADDR on newer Solaris versions as they claim the latter is obsolete.
|
||||||
|
27
docs/curl.1
27
docs/curl.1
@@ -21,7 +21,7 @@
|
|||||||
.\" * $Id$
|
.\" * $Id$
|
||||||
.\" **************************************************************************
|
.\" **************************************************************************
|
||||||
.\"
|
.\"
|
||||||
.TH curl 1 "12 Aug 2005" "Curl 7.14.1" "Curl Manual"
|
.TH curl 1 "4 Sep 2005" "Curl 7.14.2" "Curl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl \- transfer a URL
|
curl \- transfer a URL
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -30,8 +30,8 @@ curl \- transfer a URL
|
|||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.B curl
|
.B curl
|
||||||
is a tool to transfer data from or to a server, using one of the supported
|
is a tool to transfer data from or to a server, using one of the supported
|
||||||
protocols (HTTP, HTTPS, FTP, FTPS, GOPHER, DICT, TELNET, LDAP or FILE). The
|
protocols (HTTP, HTTPS, FTP, FTPS, TFTP, GOPHER, DICT, TELNET, LDAP or
|
||||||
command is designed to work without user interaction.
|
FILE). The command is designed to work without user interaction.
|
||||||
|
|
||||||
curl offers a busload of useful tricks like proxy support, user
|
curl offers a busload of useful tricks like proxy support, user
|
||||||
authentication, ftp upload, HTTP post, SSL (https:) connections, cookies, file
|
authentication, ftp upload, HTTP post, SSL (https:) connections, cookies, file
|
||||||
@@ -64,6 +64,11 @@ several ones next to each other:
|
|||||||
You can specify any amount of URLs on the command line. They will be fetched
|
You can specify any amount of URLs on the command line. They will be fetched
|
||||||
in a sequential manner in the specified order.
|
in a sequential manner in the specified order.
|
||||||
|
|
||||||
|
If you specify URL without protocol:// prefix, curl will attempt to guess what
|
||||||
|
protocol you might want. It will then default to HTTP but try other protocols
|
||||||
|
based on often-used host name prefixes. For example, for host names starting
|
||||||
|
with "ftp." curl will assume you want to speak FTP.
|
||||||
|
|
||||||
Curl will attempt to re-use connections for multiple file transfers, so that
|
Curl will attempt to re-use connections for multiple file transfers, so that
|
||||||
getting many files from the same server will not do multiple connects /
|
getting many files from the same server will not do multiple connects /
|
||||||
handshakes. This improves speed. Of course this is only done on files
|
handshakes. This improves speed. Of course this is only done on files
|
||||||
@@ -347,6 +352,15 @@ If this option is used twice, the second will again disable silent failure.
|
|||||||
using this option can be used to override a previous --ftp-port option. (Added
|
using this option can be used to override a previous --ftp-port option. (Added
|
||||||
in 7.11.0)
|
in 7.11.0)
|
||||||
|
|
||||||
|
If this option is used twice, the second will again disable silent failure.
|
||||||
|
.IP "--ftp-skip-pasv-ip"
|
||||||
|
(FTP) Tell curl to not use the IP address the server suggests in its response
|
||||||
|
to curl's PASV command when curl connects the data connection. Instead curl
|
||||||
|
will re-use the same IP address it already uses for the control
|
||||||
|
connection. (Added in 7.14.2)
|
||||||
|
|
||||||
|
This option has no effect if PORT, EPRT or EPSV is used instead of PASV.
|
||||||
|
|
||||||
If this option is used twice, the second will again disable silent failure.
|
If this option is used twice, the second will again disable silent failure.
|
||||||
.IP "--ftp-ssl"
|
.IP "--ftp-ssl"
|
||||||
(FTP) Make the FTP connection switch to use SSL/TLS. (Added in 7.11.0)
|
(FTP) Make the FTP connection switch to use SSL/TLS. (Added in 7.11.0)
|
||||||
@@ -579,8 +593,7 @@ this given limit. This concerns both FTP and HTTP transfers.
|
|||||||
.IP "-m/--max-time <seconds>"
|
.IP "-m/--max-time <seconds>"
|
||||||
Maximum time in seconds that you allow the whole operation to take. This is
|
Maximum time in seconds that you allow the whole operation to take. This is
|
||||||
useful for preventing your batch jobs from hanging for hours due to slow
|
useful for preventing your batch jobs from hanging for hours due to slow
|
||||||
networks or links going down. This doesn't work fully in win32 systems. See
|
networks or links going down. See also the \fI--connect-timeout\fP option.
|
||||||
also the \fI--connect-timeout\fP option.
|
|
||||||
|
|
||||||
If this option is used several times, the last one will be used.
|
If this option is used several times, the last one will be used.
|
||||||
.IP "-M/--manual"
|
.IP "-M/--manual"
|
||||||
@@ -599,7 +612,7 @@ directory.
|
|||||||
|
|
||||||
A quick and very simple example of how to setup a \fI.netrc\fP to allow curl
|
A quick and very simple example of how to setup a \fI.netrc\fP to allow curl
|
||||||
to ftp to the machine host.domain.com with user name \&'myself' and password
|
to ftp to the machine host.domain.com with user name \&'myself' and password
|
||||||
'secret' should look similar to:
|
\&'secret' should look similar to:
|
||||||
|
|
||||||
.B "machine host.domain.com login myself password secret"
|
.B "machine host.domain.com login myself password secret"
|
||||||
|
|
||||||
@@ -1171,7 +1184,7 @@ Sets proxy server to use for GOPHER.
|
|||||||
Sets proxy server to use if no protocol-specific proxy is set.
|
Sets proxy server to use if no protocol-specific proxy is set.
|
||||||
.IP "NO_PROXY <comma-separated list of hosts>"
|
.IP "NO_PROXY <comma-separated list of hosts>"
|
||||||
list of host names that shouldn't go through any proxy. If set to a asterisk
|
list of host names that shouldn't go through any proxy. If set to a asterisk
|
||||||
'*' only, it matches all hosts.
|
\&'*' only, it matches all hosts.
|
||||||
.SH EXIT CODES
|
.SH EXIT CODES
|
||||||
There exists a bunch of different error codes and their corresponding error
|
There exists a bunch of different error codes and their corresponding error
|
||||||
messages that may appear during bad conditions. At the time of this writing,
|
messages that may appear during bad conditions. At the time of this writing,
|
||||||
|
@@ -14,6 +14,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
#include <curl/types.h>
|
#include <curl/types.h>
|
||||||
@@ -93,5 +95,8 @@ int main(int argc, char **argv)
|
|||||||
* you're done with it, you should free() it as a nice application.
|
* you're done with it, you should free() it as a nice application.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if(chunk.memory)
|
||||||
|
free(chunk.memory);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -52,8 +52,7 @@ PDFPAGES = curl_easy_cleanup.pdf curl_easy_getinfo.pdf \
|
|||||||
|
|
||||||
CLEANFILES = $(HTMLPAGES) $(PDFPAGES)
|
CLEANFILES = $(HTMLPAGES) $(PDFPAGES)
|
||||||
|
|
||||||
EXTRA_DIST = $(man_MANS) $(HTMLPAGES) index.html $(PDFPAGES) libcurl.m4 \
|
EXTRA_DIST = $(man_MANS) $(HTMLPAGES) index.html $(PDFPAGES) libcurl.m4
|
||||||
getinfo-times
|
|
||||||
|
|
||||||
MAN2HTML= roffit --mandir=. < $< >$@
|
MAN2HTML= roffit --mandir=. < $< >$@
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
.\" nroff -man [file]
|
.\" nroff -man [file]
|
||||||
.\" $Id$
|
.\" $Id$
|
||||||
.\"
|
.\"
|
||||||
.TH curl_easy_getinfo 3 "22 Dec 2004" "libcurl 7.12.3" "libcurl Manual"
|
.TH curl_easy_getinfo 3 "6 Oct 2005" "libcurl 7.12.3" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_easy_getinfo - extract information from a curl handle
|
curl_easy_getinfo - extract information from a curl handle
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -141,6 +141,40 @@ cookies cURL knows (expired ones, too). Don't forget to
|
|||||||
cookies (cookies for the handle have not been enabled or simply none have been
|
cookies (cookies for the handle have not been enabled or simply none have been
|
||||||
received) 'struct curl_slist *' will be set to point to NULL. (Added in
|
received) 'struct curl_slist *' will be set to point to NULL. (Added in
|
||||||
7.14.1)
|
7.14.1)
|
||||||
|
.SH TIMES
|
||||||
|
.NF
|
||||||
|
An overview of the six time values available from curl_easy_getinfo()
|
||||||
|
|
||||||
|
curk_easy_perform()
|
||||||
|
|
|
||||||
|
|--NT
|
||||||
|
|--|--CT
|
||||||
|
|--|--|--PT
|
||||||
|
|--|--|--|--ST
|
||||||
|
|--|--|--TT
|
||||||
|
|--|--|--|--|--RT
|
||||||
|
.FI
|
||||||
|
.IP NT
|
||||||
|
\fICURLINFO_NAMELOOKUP_TIME\fP. The time it took from the start until the name
|
||||||
|
resolving was completed.
|
||||||
|
.IP CT
|
||||||
|
\fICURLINFO_CONNECT_TIME\fP. The time it took from the start until the connect
|
||||||
|
to the remote host (or proxy) was completed.
|
||||||
|
.IP PT
|
||||||
|
\fICURLINFO_PRETRANSFER_TIME\fP. The time it took from the start until the
|
||||||
|
file transfer is just about to begin. This includes all pre-transfer commands
|
||||||
|
and negotiations that are specific to the particular protocol(s) involved.
|
||||||
|
.IP ST
|
||||||
|
\fICURLINFO_STARTTRANSFER_TIME\fP. The time it took from the start until the
|
||||||
|
first byte is just about to be transferred.
|
||||||
|
.IP TT
|
||||||
|
\fICURLINFO_TOTAL_TIME\fP. Time of the previous transfer. This time does not
|
||||||
|
include the connect time (CT), so if you want the complete operation time, you
|
||||||
|
should add that.
|
||||||
|
.IP RT
|
||||||
|
\fICURLINFO_REDIRECT_TIME\fP. The time it took for all redirection steps
|
||||||
|
include name lookup, connect, pretransfer and transfer before final
|
||||||
|
transaction was started. So, this is zero if no redirection took place.
|
||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
If the operation was successful, CURLE_OK is returned. Otherwise an
|
If the operation was successful, CURLE_OK is returned. Otherwise an
|
||||||
appropriate error code will be returned.
|
appropriate error code will be returned.
|
||||||
|
@@ -21,7 +21,7 @@
|
|||||||
.\" * $Id$
|
.\" * $Id$
|
||||||
.\" **************************************************************************
|
.\" **************************************************************************
|
||||||
.\"
|
.\"
|
||||||
.TH curl_easy_setopt 3 "28 Jul 2005" "libcurl 7.14.1" "libcurl Manual"
|
.TH curl_easy_setopt 3 "22 Sep 2005" "libcurl 7.14.2" "libcurl Manual"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
curl_easy_setopt - set options for a curl easy handle
|
curl_easy_setopt - set options for a curl easy handle
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@@ -44,11 +44,11 @@ between transfers, so if you want subsequent transfers with different options,
|
|||||||
you must change them between the transfers. You can optionally reset all
|
you must change them between the transfers. You can optionally reset all
|
||||||
options back to internal default with \fIcurl_easy_reset(3)\fP.
|
options back to internal default with \fIcurl_easy_reset(3)\fP.
|
||||||
|
|
||||||
\fBNOTE:\fP strings passed to libcurl as 'char *' arguments, will not be
|
Strings passed to libcurl as 'char *' arguments, will not be copied by the
|
||||||
copied by the library. Instead you should keep them available until libcurl no
|
library. Instead you should keep them available until libcurl no longer needs
|
||||||
longer needs them. Failing to do so will cause very odd behavior or even
|
them. Failing to do so will cause very odd behavior or even crashes. libcurl
|
||||||
crashes. libcurl will need them until you call \fIcurl_easy_cleanup(3)\fP or
|
will need them until you call \fIcurl_easy_cleanup(3)\fP or you set the same
|
||||||
you set the same option again to use a different pointer.
|
option again to use a different pointer.
|
||||||
|
|
||||||
The \fIhandle\fP is the return code from a \fIcurl_easy_init(3)\fP or
|
The \fIhandle\fP is the return code from a \fIcurl_easy_init(3)\fP or
|
||||||
\fIcurl_easy_duphandle(3)\fP call.
|
\fIcurl_easy_duphandle(3)\fP call.
|
||||||
@@ -70,8 +70,8 @@ preceding the data (like HTTP).
|
|||||||
A non-zero parameter tells the library to shut off the built-in progress meter
|
A non-zero parameter tells the library to shut off the built-in progress meter
|
||||||
completely.
|
completely.
|
||||||
|
|
||||||
\fBNOTE:\fP future versions of libcurl is likely to not have any built-in
|
Future versions of libcurl is likely to not have any built-in progress meter
|
||||||
progress meter at all.
|
at all.
|
||||||
.IP CURLOPT_NOSIGNAL
|
.IP CURLOPT_NOSIGNAL
|
||||||
Pass a long. If it is non-zero, libcurl will not use any functions that
|
Pass a long. If it is non-zero, libcurl will not use any functions that
|
||||||
install signal handlers or any functions that cause signals to be sent to the
|
install signal handlers or any functions that cause signals to be sent to the
|
||||||
@@ -96,19 +96,26 @@ transfer and return \fICURLE_WRITE_ERROR\fP.
|
|||||||
This function may be called with zero bytes data if the transfered file is
|
This function may be called with zero bytes data if the transfered file is
|
||||||
empty.
|
empty.
|
||||||
|
|
||||||
|
Set this option to NULL to get the internal default function. The internal
|
||||||
|
default function will write the data to the FILE * given with
|
||||||
|
\fICURLOPT_WRITEDATA\fP.
|
||||||
|
|
||||||
Set the \fIstream\fP argument with the \fICURLOPT_WRITEDATA\fP option.
|
Set the \fIstream\fP argument with the \fICURLOPT_WRITEDATA\fP option.
|
||||||
|
|
||||||
\fBNOTE:\fP you will be passed as much data as possible in all invokes, but
|
The callback function will be passed as much data as possible in all invokes,
|
||||||
you cannot possibly make any assumptions. It may be one byte, it may be
|
but you cannot possibly make any assumptions. It may be one byte, it may be
|
||||||
thousands. The maximum amount of data that can be passed to the write callback
|
thousands. The maximum amount of data that can be passed to the write callback
|
||||||
is defined in the curl.h header file: CURL_MAX_WRITE_SIZE.
|
is defined in the curl.h header file: CURL_MAX_WRITE_SIZE.
|
||||||
.IP CURLOPT_WRITEDATA
|
.IP CURLOPT_WRITEDATA
|
||||||
Data pointer to pass to the file write function. Note that if you specify the
|
Data pointer to pass to the file write function. If you use the
|
||||||
\fICURLOPT_WRITEFUNCTION\fP, this is the pointer you'll get as input. If you
|
\fICURLOPT_WRITEFUNCTION\fP option, this is the pointer you'll get as
|
||||||
don't use a callback, you must pass a 'FILE *' as libcurl will pass this to
|
input. If you don't use a callback, you must pass a 'FILE *' as libcurl will
|
||||||
fwrite() when writing data.
|
pass this to fwrite() when writing data.
|
||||||
|
|
||||||
\fBNOTE:\fP If you're using libcurl as a win32 DLL, you MUST use the
|
The internal \fICURLOPT_WRITEFUNCTION\fP will write the data to the FILE *
|
||||||
|
given with this option, or to stdout if this option hasn't been set.
|
||||||
|
|
||||||
|
If you're using libcurl as a win32 DLL, you \fBMUST\fP use the
|
||||||
\fICURLOPT_WRITEFUNCTION\fP if you set this option or you will experience
|
\fICURLOPT_WRITEFUNCTION\fP if you set this option or you will experience
|
||||||
crashes.
|
crashes.
|
||||||
|
|
||||||
@@ -129,15 +136,20 @@ server expected it, like when you've told you will upload N bytes and you
|
|||||||
upload less than N bytes), you may experience that the server "hangs" waiting
|
upload less than N bytes), you may experience that the server "hangs" waiting
|
||||||
for the rest of the data that won't come.
|
for the rest of the data that won't come.
|
||||||
|
|
||||||
In libcurl 7.12.1 and later, the read callback may return
|
The read callback may return \fICURL_READFUNC_ABORT\fP to stop the current
|
||||||
\fICURL_READFUNC_ABORT\fP to stop the current operation at once, with a
|
operation immediately, resulting in a \fICURLE_ABORTED_BY_CALLBACK\fP error
|
||||||
\fICURLE_ABORTED_BY_CALLBACK\fP error code from the transfer.
|
code from the transfer (Added in 7.12.1)
|
||||||
.IP CURLOPT_READDATA
|
|
||||||
Data pointer to pass to the file read function. Note that if you specify the
|
|
||||||
\fICURLOPT_READFUNCTION\fP, this is the pointer you'll get as input. If you
|
|
||||||
don't specify a read callback, this must be a valid FILE *.
|
|
||||||
|
|
||||||
\fBNOTE:\fP If you're using libcurl as a win32 DLL, you MUST use a
|
If you set the callback pointer to NULL, or doesn't set it at all, the default
|
||||||
|
internal read function will be used. It is simply doing an fread() on the FILE
|
||||||
|
* stream set with \fICURLOPT_READDATA\fP.
|
||||||
|
.IP CURLOPT_READDATA
|
||||||
|
Data pointer to pass to the file read function. If you use the
|
||||||
|
\fICURLOPT_READFUNCTION\fP option, this is the pointer you'll get as input. If
|
||||||
|
you don't specify a read callback but instead rely on the default internal
|
||||||
|
read function, this data must be a valid readable FILE *.
|
||||||
|
|
||||||
|
If you're using libcurl as a win32 DLL, you MUST use a
|
||||||
\fICURLOPT_READFUNCTION\fP if you set this option.
|
\fICURLOPT_READFUNCTION\fP if you set this option.
|
||||||
|
|
||||||
This option is also known with the older name \fICURLOPT_INFILE\fP, the name
|
This option is also known with the older name \fICURLOPT_INFILE\fP, the name
|
||||||
@@ -163,8 +175,8 @@ data, the upload size will remain 0). Returning a non-zero value from this
|
|||||||
callback will cause libcurl to abort the transfer and return
|
callback will cause libcurl to abort the transfer and return
|
||||||
\fICURLE_ABORTED_BY_CALLBACK\fP.
|
\fICURLE_ABORTED_BY_CALLBACK\fP.
|
||||||
|
|
||||||
Also note that \fICURLOPT_NOPROGRESS\fP must be set to FALSE to make this
|
\fICURLOPT_NOPROGRESS\fP must be set to FALSE to make this function actually
|
||||||
function actually get called.
|
get called.
|
||||||
.IP CURLOPT_PROGRESSDATA
|
.IP CURLOPT_PROGRESSDATA
|
||||||
Pass a pointer that will be untouched by libcurl and passed as the first
|
Pass a pointer that will be untouched by libcurl and passed as the first
|
||||||
argument in the progress callback set with \fICURLOPT_PROGRESSFUNCTION\fP.
|
argument in the progress callback set with \fICURLOPT_PROGRESSFUNCTION\fP.
|
||||||
@@ -236,10 +248,10 @@ option was introduced in 7.11.0.
|
|||||||
This function will get called on all new connections made to a server, during
|
This function will get called on all new connections made to a server, during
|
||||||
the SSL negotiation. The SSL_CTX pointer will be a new one every time.
|
the SSL negotiation. The SSL_CTX pointer will be a new one every time.
|
||||||
|
|
||||||
\fBNOTE:\fP To use this properly, a non-trivial amount of knowledge of the
|
To use this properly, a non-trivial amount of knowledge of the openssl
|
||||||
openssl libraries is necessary. Using this function allows for example to use
|
libraries is necessary. Using this function allows for example to use openssl
|
||||||
openssl callbacks to add additional validation code for certificates, and even
|
callbacks to add additional validation code for certificates, and even to
|
||||||
to change the actual URI of an HTTPS request (example used in the lib509 test
|
change the actual URI of an HTTPS request (example used in the lib509 test
|
||||||
case). See also the example section for a replacement of the key, certificate
|
case). See also the example section for a replacement of the key, certificate
|
||||||
and trust file settings.
|
and trust file settings.
|
||||||
.IP CURLOPT_SSL_CTX_DATA
|
.IP CURLOPT_SSL_CTX_DATA
|
||||||
@@ -249,14 +261,21 @@ parameter, otherwise \fBNULL\fP. (Added in 7.11.0)
|
|||||||
.SH ERROR OPTIONS
|
.SH ERROR OPTIONS
|
||||||
.IP CURLOPT_ERRORBUFFER
|
.IP CURLOPT_ERRORBUFFER
|
||||||
Pass a char * to a buffer that the libcurl may store human readable error
|
Pass a char * to a buffer that the libcurl may store human readable error
|
||||||
messages in. This may be more helpful than just the return code from the
|
messages in. This may be more helpful than just the return code from
|
||||||
library. The buffer must be at least CURL_ERROR_SIZE big.
|
\fIcurl_easy_perform\fP. The buffer must be at least CURL_ERROR_SIZE big.
|
||||||
|
|
||||||
Use \fICURLOPT_VERBOSE\fP and \fICURLOPT_DEBUGFUNCTION\fP to better
|
Use \fICURLOPT_VERBOSE\fP and \fICURLOPT_DEBUGFUNCTION\fP to better
|
||||||
debug/trace why errors happen.
|
debug/trace why errors happen.
|
||||||
|
|
||||||
\fBNote:\fP if the library does not return an error, the buffer may not have
|
If the library does not return an error, the buffer may not have been
|
||||||
been touched. Do not rely on the contents in those cases.
|
touched. Do not rely on the contents in those cases.
|
||||||
|
|
||||||
|
In a few rare cases, there is no text string associated with the error in
|
||||||
|
libcurl and then you may not get a string in the buffer even though it returns
|
||||||
|
an error. This is considered a bug and we appreciate your reports about these
|
||||||
|
cases. Anyway, you can avoid problems with these cases in your program by
|
||||||
|
making sure to clear the first byte of the error buffer before you call
|
||||||
|
curl_easy_perform().
|
||||||
.IP CURLOPT_STDERR
|
.IP CURLOPT_STDERR
|
||||||
Pass a FILE * as parameter. Tell libcurl to use this stream instead of stderr
|
Pass a FILE * as parameter. Tell libcurl to use this stream instead of stderr
|
||||||
when showing the progress meter and displaying \fICURLOPT_VERBOSE\fP data.
|
when showing the progress meter and displaying \fICURLOPT_VERBOSE\fP data.
|
||||||
@@ -277,7 +296,7 @@ given protocol of the set URL is not supported, libcurl will return on error
|
|||||||
\fIcurl_multi_perform(3)\fP. Use \fIcurl_version_info(3)\fP for detailed info
|
\fIcurl_multi_perform(3)\fP. Use \fIcurl_version_info(3)\fP for detailed info
|
||||||
on which protocols that are supported.
|
on which protocols that are supported.
|
||||||
|
|
||||||
\fBNOTE:\fP \fICURLOPT_URL\fP is the only option that must be set before
|
\fICURLOPT_URL\fP is the only option that must be set before
|
||||||
\fIcurl_easy_perform(3)\fP is called.
|
\fIcurl_easy_perform(3)\fP is called.
|
||||||
.IP CURLOPT_PROXY
|
.IP CURLOPT_PROXY
|
||||||
Set HTTP proxy to use. The parameter should be a char * to a zero terminated
|
Set HTTP proxy to use. The parameter should be a char * to a zero terminated
|
||||||
@@ -310,9 +329,9 @@ this are \fICURLPROXY_HTTP\fP and \fICURLPROXY_SOCKS5\fP, with the HTTP one
|
|||||||
being default. (Added in 7.10)
|
being default. (Added in 7.10)
|
||||||
.IP CURLOPT_HTTPPROXYTUNNEL
|
.IP CURLOPT_HTTPPROXYTUNNEL
|
||||||
Set the parameter to non-zero to get the library to tunnel all operations
|
Set the parameter to non-zero to get the library to tunnel all operations
|
||||||
through a given HTTP proxy. Note that there is a big difference between using
|
through a given HTTP proxy. There is a big difference between using a proxy
|
||||||
a proxy and to tunnel through it. If you don't know what this means, you
|
and to tunnel through it. If you don't know what this means, you probably
|
||||||
probably don't want this tunneling option.
|
don't want this tunneling option.
|
||||||
.IP CURLOPT_INTERFACE
|
.IP CURLOPT_INTERFACE
|
||||||
Pass a char * as parameter. This set the interface name to use as outgoing
|
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
|
network interface. The name can be an interface name, an IP address or a host
|
||||||
@@ -331,10 +350,14 @@ thread-safe and this will use a global variable.
|
|||||||
to using the share interface instead! See \fICURLOPT_SHARE\fP and
|
to using the share interface instead! See \fICURLOPT_SHARE\fP and
|
||||||
\fIcurl_share_init(3)\fP.
|
\fIcurl_share_init(3)\fP.
|
||||||
.IP CURLOPT_BUFFERSIZE
|
.IP CURLOPT_BUFFERSIZE
|
||||||
Pass a long specifying your preferred size for the receive buffer in libcurl.
|
Pass a long specifying your preferred size (in bytes) for the receive buffer
|
||||||
The main point of this would be that the write callback gets called more often
|
in libcurl. The main point of this would be that the write callback gets
|
||||||
and with smaller chunks. This is just treated as a request, not an order. You
|
called more often and with smaller chunks. This is just treated as a request,
|
||||||
cannot be guaranteed to actually get the given size. (Added in 7.10)
|
not an order. You cannot be guaranteed to actually get the given size. (Added
|
||||||
|
in 7.10)
|
||||||
|
|
||||||
|
This size is by default set as big as possible (CURL_MAX_WRITE_SIZE), so it
|
||||||
|
only makse sense to use this option if you want it smaller.
|
||||||
.IP CURLOPT_PORT
|
.IP CURLOPT_PORT
|
||||||
Pass a long specifying what remote port number to connect to, instead of the
|
Pass a long specifying what remote port number to connect to, instead of the
|
||||||
one specified in the URL or the default port for the used protocol.
|
one specified in the URL or the default port for the used protocol.
|
||||||
@@ -360,9 +383,9 @@ This parameter controls the preference of libcurl between using user names and
|
|||||||
passwords from your \fI~/.netrc\fP file, relative to user names and passwords
|
passwords from your \fI~/.netrc\fP file, relative to user names and passwords
|
||||||
in the URL supplied with \fICURLOPT_URL\fP.
|
in the URL supplied with \fICURLOPT_URL\fP.
|
||||||
|
|
||||||
\fBNote:\fP libcurl uses a user name (and supplied or prompted password)
|
libcurl uses a user name (and supplied or prompted password) supplied with
|
||||||
supplied with \fICURLOPT_USERPWD\fP in preference to any of the options
|
\fICURLOPT_USERPWD\fP in preference to any of the options controlled by this
|
||||||
controlled by this parameter.
|
parameter.
|
||||||
|
|
||||||
Pass a long, set to one of the values described below.
|
Pass a long, set to one of the values described below.
|
||||||
.RS
|
.RS
|
||||||
@@ -386,9 +409,8 @@ and to search the file with the host only.
|
|||||||
Only machine name, user name and password are taken into account
|
Only machine name, user name and password are taken into account
|
||||||
(init macros and similar things aren't supported).
|
(init macros and similar things aren't supported).
|
||||||
|
|
||||||
\fBNote:\fP libcurl does not verify that the file has the correct properties
|
libcurl does not verify that the file has the correct properties set (as the
|
||||||
set (as the standard Unix ftp client does). It should only be readable by
|
standard Unix ftp client does). It should only be readable by user.
|
||||||
user.
|
|
||||||
.IP CURLOPT_NETRC_FILE
|
.IP CURLOPT_NETRC_FILE
|
||||||
Pass a char * as parameter, pointing to a zero terminated string containing
|
Pass a char * as parameter, pointing to a zero terminated string containing
|
||||||
the full path name to the file you want libcurl to use as .netrc file. If this
|
the full path name to the file you want libcurl to use as .netrc file. If this
|
||||||
@@ -413,9 +435,9 @@ Pass a long as parameter, which is set to a bitmask, to tell libcurl what
|
|||||||
authentication method(s) you want it to use. The available bits are listed
|
authentication method(s) you want it to use. The available bits are listed
|
||||||
below. If more than one bit is set, libcurl will first query the site to see
|
below. If more than one bit is set, libcurl will first query the site to see
|
||||||
what authentication methods it supports and then pick the best one you allow
|
what authentication methods it supports and then pick the best one you allow
|
||||||
it to use. Note that for some methods, this will induce an extra network
|
it to use. For some methods, this will induce an extra network round-trip. Set
|
||||||
round-trip. Set the actual name and password with the \fICURLOPT_USERPWD\fP
|
the actual name and password with the \fICURLOPT_USERPWD\fP option. (Added in
|
||||||
option. (Added in 7.10.6)
|
7.10.6)
|
||||||
.RS
|
.RS
|
||||||
.IP CURLAUTH_BASIC
|
.IP CURLAUTH_BASIC
|
||||||
HTTP Basic authentication. This is the default choice, and the only method
|
HTTP Basic authentication. This is the default choice, and the only method
|
||||||
@@ -433,15 +455,14 @@ applications. It is primarily meant as a support for Kerberos5 authentication
|
|||||||
but may be also used along with another authentication methods. For more
|
but may be also used along with another authentication methods. For more
|
||||||
information see IETF draft draft-brezak-spnego-http-04.txt.
|
information see IETF draft draft-brezak-spnego-http-04.txt.
|
||||||
|
|
||||||
\fBNOTE\fP that you need to build libcurl with a suitable GSS-API library for
|
You need to build libcurl with a suitable GSS-API library for this to work.
|
||||||
this to work.
|
|
||||||
.IP CURLAUTH_NTLM
|
.IP CURLAUTH_NTLM
|
||||||
HTTP NTLM authentication. A proprietary protocol invented and used by
|
HTTP NTLM authentication. A proprietary protocol invented and used by
|
||||||
Microsoft. It uses a challenge-response and hash concept similar to Digest, to
|
Microsoft. It uses a challenge-response and hash concept similar to Digest, to
|
||||||
prevent the password from being eavesdropped.
|
prevent the password from being eavesdropped.
|
||||||
|
|
||||||
\fBNOTE\fP that you need to build libcurl with SSL support for this option to
|
You need to build libcurl with OpenSSL support for this option to work, or
|
||||||
work.
|
build libcurl on Windows.
|
||||||
.IP CURLAUTH_ANY
|
.IP CURLAUTH_ANY
|
||||||
This is a convenience macro that sets all bits and thus makes libcurl pick any
|
This is a convenience macro that sets all bits and thus makes libcurl pick any
|
||||||
it finds suitable. libcurl will automatically select the one it finds most
|
it finds suitable. libcurl will automatically select the one it finds most
|
||||||
@@ -456,11 +477,11 @@ Pass a long as parameter, which is set to a bitmask, to tell libcurl what
|
|||||||
authentication method(s) you want it to use for your proxy authentication. If
|
authentication method(s) you want it to use for your proxy authentication. If
|
||||||
more than one bit is set, libcurl will first query the site to see what
|
more than one bit is set, libcurl will first query the site to see what
|
||||||
authentication methods it supports and then pick the best one you allow it to
|
authentication methods it supports and then pick the best one you allow it to
|
||||||
use. Note that for some methods, this will induce an extra network
|
use. For some methods, this will induce an extra network round-trip. Set the
|
||||||
round-trip. Set the actual name and password with the
|
actual name and password with the \fICURLOPT_PROXYUSERPWD\fP option. The
|
||||||
\fICURLOPT_PROXYUSERPWD\fP option. The bitmask can be constructed by or'ing
|
bitmask can be constructed by or'ing together the bits listed above for the
|
||||||
together the bits listed above for the \fICURLOPT_HTTPAUTH\fP option. As of
|
\fICURLOPT_HTTPAUTH\fP option. As of this writing, only Basic, Digest and NTLM
|
||||||
this writing, only Basic, Digest and NTLM work. (Added in 7.10.7)
|
work. (Added in 7.10.7)
|
||||||
.SH HTTP OPTIONS
|
.SH HTTP OPTIONS
|
||||||
.IP CURLOPT_AUTOREFERER
|
.IP CURLOPT_AUTOREFERER
|
||||||
Pass a non-zero parameter to enable this. When enabled, libcurl will
|
Pass a non-zero parameter to enable this. When enabled, libcurl will
|
||||||
@@ -483,14 +504,14 @@ lib/README.encoding for details.
|
|||||||
A non-zero parameter tells the library to follow any Location: header that the
|
A non-zero parameter tells the library to follow any Location: header that the
|
||||||
server sends as part of an HTTP header.
|
server sends as part of an HTTP header.
|
||||||
|
|
||||||
\fBNOTE:\fP this means that the library will re-send the same request on the
|
This means that the library will re-send the same request on the new location
|
||||||
new location and follow new Location: headers all the way until no more such
|
and follow new Location: headers all the way until no more such headers are
|
||||||
headers are returned. \fICURLOPT_MAXREDIRS\fP can be used to limit the number
|
returned. \fICURLOPT_MAXREDIRS\fP can be used to limit the number of redirects
|
||||||
of redirects libcurl will follow.
|
libcurl will follow.
|
||||||
.IP CURLOPT_UNRESTRICTED_AUTH
|
.IP CURLOPT_UNRESTRICTED_AUTH
|
||||||
A non-zero parameter tells the library it can continue to send authentication
|
A non-zero parameter tells the library it can continue to send authentication
|
||||||
(user+password) when following locations, even when hostname changed. Note
|
(user+password) when following locations, even when hostname changed. This
|
||||||
that this is meaningful only when setting \fICURLOPT_FOLLOWLOCATION\fP.
|
option is meaningful only when setting \fICURLOPT_FOLLOWLOCATION\fP.
|
||||||
.IP CURLOPT_MAXREDIRS
|
.IP CURLOPT_MAXREDIRS
|
||||||
Pass a long. The set number will be the redirection limit. If that many
|
Pass a long. The set number will be the redirection limit. If that many
|
||||||
redirections have been followed, the next redirect will cause an error
|
redirections have been followed, the next redirect will cause an error
|
||||||
@@ -549,8 +570,8 @@ commonly used one by HTML forms. See also the \fICURLOPT_POST\fP. Using
|
|||||||
Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header.
|
Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header.
|
||||||
You can disable this header with \fICURLOPT_HTTPHEADER\fP as usual.
|
You can disable this header with \fICURLOPT_HTTPHEADER\fP as usual.
|
||||||
|
|
||||||
\fBNote:\fP to make multipart/formdata posts (aka rfc1867-posts), check out
|
To make multipart/formdata posts (aka rfc1867-posts), check out the
|
||||||
the \fICURLOPT_HTTPPOST\fP option.
|
\fICURLOPT_HTTPPOST\fP option.
|
||||||
.IP CURLOPT_POSTFIELDSIZE
|
.IP CURLOPT_POSTFIELDSIZE
|
||||||
If you want to post data to the server without letting libcurl do a strlen()
|
If you want to post data to the server without letting libcurl do a strlen()
|
||||||
to measure the data size, this option must be used. When this option is used
|
to measure the data size, this option must be used. When this option is used
|
||||||
@@ -605,7 +626,7 @@ request-line are headers.
|
|||||||
|
|
||||||
Pass a NULL to this to reset back to no custom headers.
|
Pass a NULL to this to reset back to no custom headers.
|
||||||
|
|
||||||
\fBNOTE:\fP The most commonly replaced headers have "shortcuts" in the options
|
The most commonly replaced headers have "shortcuts" in the options
|
||||||
\fICURLOPT_COOKIE\fP, \fICURLOPT_USERAGENT\fP and \fICURLOPT_REFERER\fP.
|
\fICURLOPT_COOKIE\fP, \fICURLOPT_USERAGENT\fP and \fICURLOPT_REFERER\fP.
|
||||||
.IP CURLOPT_HTTP200ALIASES
|
.IP CURLOPT_HTTP200ALIASES
|
||||||
Pass a pointer to a linked list of aliases to be treated as valid HTTP 200
|
Pass a pointer to a linked list of aliases to be treated as valid HTTP 200
|
||||||
@@ -618,9 +639,9 @@ The linked list should be a fully valid list of struct curl_slist structs, and
|
|||||||
be properly filled in. Use \fIcurl_slist_append(3)\fP to create the list and
|
be properly filled in. Use \fIcurl_slist_append(3)\fP to create the list and
|
||||||
\fIcurl_slist_free_all(3)\fP to clean up an entire list.
|
\fIcurl_slist_free_all(3)\fP to clean up an entire list.
|
||||||
|
|
||||||
\fBNOTE:\fP The alias itself is not parsed for any version strings. So if your
|
The alias itself is not parsed for any version strings. So if your alias is
|
||||||
alias is "MYHTTP/9.9", Libcurl will not treat the server as responding with
|
\&"MYHTTP/9.9", Libcurl will not treat the server as responding with HTTP
|
||||||
HTTP version 9.9. Instead Libcurl will use the value set by option
|
version 9.9. Instead Libcurl will use the value set by option
|
||||||
\fICURLOPT_HTTP_VERSION\fP.
|
\fICURLOPT_HTTP_VERSION\fP.
|
||||||
.IP CURLOPT_COOKIE
|
.IP CURLOPT_COOKIE
|
||||||
Pass a pointer to a zero terminated string as parameter. It will be used to
|
Pass a pointer to a zero terminated string as parameter. It will be used to
|
||||||
@@ -655,7 +676,7 @@ instead have the cookies written to stdout. Using this option also enables
|
|||||||
cookies for this session, so if you for example follow a location it will make
|
cookies for this session, so if you for example follow a location it will make
|
||||||
matching cookies get sent accordingly.
|
matching cookies get sent accordingly.
|
||||||
|
|
||||||
\fBNOTE:\fP If the cookie jar file can't be created or written to (when the
|
If the cookie jar file can't be created or written to (when the
|
||||||
\fIcurl_easy_cleanup(3)\fP is called), libcurl will not and cannot report an
|
\fIcurl_easy_cleanup(3)\fP is called), libcurl will not and cannot report an
|
||||||
error for this. Using \fICURLOPT_VERBOSE\fP or \fICURLOPT_DEBUGFUNCTION\fP
|
error for this. Using \fICURLOPT_VERBOSE\fP or \fICURLOPT_DEBUGFUNCTION\fP
|
||||||
will get a warning to display, but that is the only visible feedback you get
|
will get a warning to display, but that is the only visible feedback you get
|
||||||
@@ -762,11 +783,19 @@ directory. (Added in 7.10.7)
|
|||||||
.IP CURLOPT_FTP_RESPONSE_TIMEOUT
|
.IP CURLOPT_FTP_RESPONSE_TIMEOUT
|
||||||
Pass a long. Causes curl to set a timeout period (in seconds) on the amount
|
Pass a long. Causes curl to set a timeout period (in seconds) on the amount
|
||||||
of time that the server is allowed to take in order to generate a response
|
of time that the server is allowed to take in order to generate a response
|
||||||
message for a command before the session is considered hung. Note that while
|
message for a command before the session is considered hung. While curl is
|
||||||
curl is waiting for a response, this value overrides \fICURLOPT_TIMEOUT\fP. It
|
waiting for a response, this value overrides \fICURLOPT_TIMEOUT\fP. It is
|
||||||
is recommended that if used in conjunction with \fICURLOPT_TIMEOUT\fP, you set
|
recommended that if used in conjunction with \fICURLOPT_TIMEOUT\fP, you set
|
||||||
\fICURLOPT_FTP_RESPONSE_TIMEOUT\fP to a value smaller than
|
\fICURLOPT_FTP_RESPONSE_TIMEOUT\fP to a value smaller than
|
||||||
\fICURLOPT_TIMEOUT\fP. (Added in 7.10.8)
|
\fICURLOPT_TIMEOUT\fP. (Added in 7.10.8)
|
||||||
|
.IP CURLOPT_FTP_SKIP_PASV_IP
|
||||||
|
Pass a long. If set to a non-zero value, it instructs libcurl to not use the
|
||||||
|
IP address the server suggests in its 227-response to libcurl's PASV command
|
||||||
|
when libcurl connects the data connection. Instead libcurl will re-use the
|
||||||
|
same IP address it already uses for the control connection. But it will use
|
||||||
|
the port number from the 227-response. (Added in 7.14.2)
|
||||||
|
|
||||||
|
This option has no effect if PORT, EPRT or EPSV is used instead of PASV.
|
||||||
.IP CURLOPT_FTP_SSL
|
.IP CURLOPT_FTP_SSL
|
||||||
Pass a long using one of the values from below, to make libcurl use your
|
Pass a long using one of the values from below, to make libcurl use your
|
||||||
desired level of SSL for the ftp transfer. (Added in 7.11.0)
|
desired level of SSL for the ftp transfer. (Added in 7.11.0)
|
||||||
@@ -816,10 +845,9 @@ stdout to binary mode. This option can be usable when transferring text data
|
|||||||
between systems with different views on certain characters, such as newlines
|
between systems with different views on certain characters, such as newlines
|
||||||
or similar.
|
or similar.
|
||||||
|
|
||||||
\fBNOTE:\fP libcurl does not do a complete ASCII conversion when doing ASCII
|
libcurl does not do a complete ASCII conversion when doing ASCII transfers
|
||||||
transfers over FTP. This is a known limitation/flaw that nobody has
|
over FTP. This is a known limitation/flaw that nobody has rectified. libcurl
|
||||||
rectified. libcurl simply sets the mode to ascii and performs a standard
|
simply sets the mode to ascii and performs a standard transfer.
|
||||||
transfer.
|
|
||||||
.IP CURLOPT_CRLF
|
.IP CURLOPT_CRLF
|
||||||
Convert Unix newlines to CRLF newlines on transfers.
|
Convert Unix newlines to CRLF newlines on transfers.
|
||||||
.IP CURLOPT_RANGE
|
.IP CURLOPT_RANGE
|
||||||
@@ -845,11 +873,11 @@ server supports the command first.
|
|||||||
|
|
||||||
Restore to the internal default by setting this to NULL.
|
Restore to the internal default by setting this to NULL.
|
||||||
|
|
||||||
\fBNOTE:\fP Many people have wrongly used this option to replace the entire
|
Many people have wrongly used this option to replace the entire request with
|
||||||
request with their own, including multiple headers and POST contents. While
|
their own, including multiple headers and POST contents. While that might work
|
||||||
that might work in many cases, it will cause libcurl to send invalid requests
|
in many cases, it will cause libcurl to send invalid requests and it could
|
||||||
and it could possibly confuse the remote server badly. Use \fICURLOPT_POST\fP
|
possibly confuse the remote server badly. Use \fICURLOPT_POST\fP and
|
||||||
and \fICURLOPT_POSTFIELDS\fP to set POST data. Use \fICURLOPT_HTTPHEADER\fP to
|
\fICURLOPT_POSTFIELDS\fP to set POST data. Use \fICURLOPT_HTTPHEADER\fP to
|
||||||
replace or extend the set of headers sent by libcurl. Use
|
replace or extend the set of headers sent by libcurl. Use
|
||||||
\fICURLOPT_HTTP_VERSION\fP to change HTTP version.
|
\fICURLOPT_HTTP_VERSION\fP to change HTTP version.
|
||||||
.IP CURLOPT_FILETIME
|
.IP CURLOPT_FILETIME
|
||||||
@@ -893,26 +921,26 @@ Pass a long as parameter. This allows you to specify the maximum size (in
|
|||||||
bytes) of a file to download. If the file requested is larger than this value,
|
bytes) of a file to download. If the file requested is larger than this value,
|
||||||
the transfer will not start and CURLE_FILESIZE_EXCEEDED will be returned.
|
the transfer will not start and CURLE_FILESIZE_EXCEEDED will be returned.
|
||||||
|
|
||||||
\fBNOTE:\fP The file size is not always known prior to download, and for such
|
The file size is not always known prior to download, and for such files this
|
||||||
files this option has no effect even if the file transfer ends up being larger
|
option has no effect even if the file transfer ends up being larger than this
|
||||||
than this given limit. This concerns both FTP and HTTP transfers.
|
given limit. This concerns both FTP and HTTP transfers.
|
||||||
.IP CURLOPT_MAXFILESIZE_LARGE
|
.IP CURLOPT_MAXFILESIZE_LARGE
|
||||||
Pass a curl_off_t as parameter. This allows you to specify the maximum size
|
Pass a curl_off_t as parameter. This allows you to specify the maximum size
|
||||||
(in bytes) of a file to download. If the file requested is larger than this
|
(in bytes) of a file to download. If the file requested is larger than this
|
||||||
value, the transfer will not start and \fICURLE_FILESIZE_EXCEEDED\fP will be
|
value, the transfer will not start and \fICURLE_FILESIZE_EXCEEDED\fP will be
|
||||||
returned. (Added in 7.11.0)
|
returned. (Added in 7.11.0)
|
||||||
|
|
||||||
\fBNOTE:\fP The file size is not always known prior to download, and for such
|
The file size is not always known prior to download, and for such files this
|
||||||
files this option has no effect even if the file transfer ends up being larger
|
option has no effect even if the file transfer ends up being larger than this
|
||||||
than this given limit. This concerns both FTP and HTTP transfers.
|
given limit. This concerns both FTP and HTTP transfers.
|
||||||
.IP CURLOPT_TIMECONDITION
|
.IP CURLOPT_TIMECONDITION
|
||||||
Pass a long as parameter. This defines how the \fICURLOPT_TIMEVALUE\fP time
|
Pass a long as parameter. This defines how the \fICURLOPT_TIMEVALUE\fP time
|
||||||
value is treated. You can set this parameter to \fICURL_TIMECOND_IFMODSINCE\fP
|
value is treated. You can set this parameter to \fICURL_TIMECOND_IFMODSINCE\fP
|
||||||
or \fICURL_TIMECOND_IFUNMODSINCE\fP. This feature applies to HTTP and FTP.
|
or \fICURL_TIMECOND_IFUNMODSINCE\fP. This feature applies to HTTP and FTP.
|
||||||
|
|
||||||
\fBNOTE:\fP The last modification time of a file is not always known and in such
|
The last modification time of a file is not always known and in such instances
|
||||||
instances this feature will have no effect even if the given time condition
|
this feature will have no effect even if the given time condition would have
|
||||||
would have not been met.
|
not been met.
|
||||||
.IP CURLOPT_TIMEVALUE
|
.IP CURLOPT_TIMEVALUE
|
||||||
Pass a long as parameter. This should be the time in seconds since 1 jan 1970,
|
Pass a long as parameter. This should be the time in seconds since 1 jan 1970,
|
||||||
and the time will be used in a condition as specified with
|
and the time will be used in a condition as specified with
|
||||||
@@ -925,8 +953,8 @@ considerable time and limiting operations to less than a few minutes risk
|
|||||||
aborting perfectly normal operations. This option will cause curl to use the
|
aborting perfectly normal operations. This option will cause curl to use the
|
||||||
SIGALRM to enable time-outing system calls.
|
SIGALRM to enable time-outing system calls.
|
||||||
|
|
||||||
\fBNOTE:\fP this is not recommended to use in unix multi-threaded programs, as
|
In unix-like systems, this might cause signals to be used unless
|
||||||
it uses signals unless \fICURLOPT_NOSIGNAL\fP (see above) is set.
|
\fICURLOPT_NOSIGNAL\fP is set.
|
||||||
.IP CURLOPT_LOW_SPEED_LIMIT
|
.IP CURLOPT_LOW_SPEED_LIMIT
|
||||||
Pass a long as parameter. It contains the transfer speed in bytes per second
|
Pass a long as parameter. It contains the transfer speed in bytes per second
|
||||||
that the transfer should be below during \fICURLOPT_LOW_SPEED_TIME\fP seconds
|
that the transfer should be below during \fICURLOPT_LOW_SPEED_TIME\fP seconds
|
||||||
@@ -947,9 +975,9 @@ When reaching the maximum limit, curl uses the \fICURLOPT_CLOSEPOLICY\fP to
|
|||||||
figure out which of the existing connections to close to prevent the number of
|
figure out which of the existing connections to close to prevent the number of
|
||||||
open connections to increase.
|
open connections to increase.
|
||||||
|
|
||||||
\fBNOTE:\fP if you already have performed transfers with this curl handle,
|
If you already have performed transfers with this curl handle, setting a
|
||||||
setting a smaller MAXCONNECTS than before may cause open connections to get
|
smaller MAXCONNECTS than before may cause open connections to get closed
|
||||||
closed unnecessarily.
|
unnecessarily.
|
||||||
.IP CURLOPT_CLOSEPOLICY
|
.IP CURLOPT_CLOSEPOLICY
|
||||||
Pass a long. This option sets what policy libcurl should use when the
|
Pass a long. This option sets what policy libcurl should use when the
|
||||||
connection cache is filled and one of the open connections has to be closed to
|
connection cache is filled and one of the open connections has to be closed to
|
||||||
@@ -981,8 +1009,8 @@ it has connected, this option is of no more use. Set to zero to disable
|
|||||||
connection timeout (it will then only timeout on the system's internal
|
connection timeout (it will then only timeout on the system's internal
|
||||||
timeouts). See also the \fICURLOPT_TIMEOUT\fP option.
|
timeouts). See also the \fICURLOPT_TIMEOUT\fP option.
|
||||||
|
|
||||||
\fBNOTE:\fP this is not recommended to use in unix multi-threaded programs, as
|
In unix-like systems, this might cause signals to be used unless
|
||||||
it uses signals unless \fICURLOPT_NOSIGNAL\fP (see above) is set.
|
\fICURLOPT_NOSIGNAL\fP is set.
|
||||||
.IP CURLOPT_IPRESOLVE
|
.IP CURLOPT_IPRESOLVE
|
||||||
Allows an application to select what kind of IP addresses to use when
|
Allows an application to select what kind of IP addresses to use when
|
||||||
resolving host names. This is only interesting when using host names that
|
resolving host names. This is only interesting when using host names that
|
||||||
@@ -1019,9 +1047,9 @@ changed with \fICURLOPT_SSLKEYTYPE\fP.
|
|||||||
Pass a pointer to a zero terminated string as parameter. The string should be
|
Pass a pointer to a zero terminated string as parameter. The string should be
|
||||||
the format of your private key. Supported formats are "PEM", "DER" and "ENG".
|
the format of your private key. Supported formats are "PEM", "DER" and "ENG".
|
||||||
|
|
||||||
\fBNOTE:\fP The format "ENG" enables you to load the private key from a crypto
|
The format "ENG" enables you to load the private key from a crypto engine. In
|
||||||
engine. In this case \fICURLOPT_SSLKEY\fP is used as an identifier passed to
|
this case \fICURLOPT_SSLKEY\fP is used as an identifier passed to the
|
||||||
the engine. You have to set the crypto engine with \fICURLOPT_SSLENGINE\fP.
|
engine. You have to set the crypto engine with \fICURLOPT_SSLENGINE\fP.
|
||||||
\&"DER" format key file currently does not work because of a bug in OpenSSL.
|
\&"DER" format key file currently does not work because of a bug in OpenSSL.
|
||||||
.IP CURLOPT_SSLKEYPASSWD
|
.IP CURLOPT_SSLKEYPASSWD
|
||||||
Pass a pointer to a zero terminated string as parameter. It will be used as
|
Pass a pointer to a zero terminated string as parameter. It will be used as
|
||||||
@@ -1031,14 +1059,14 @@ Pass a pointer to a zero terminated string as parameter. It will be used as
|
|||||||
the identifier for the crypto engine you want to use for your private
|
the identifier for the crypto engine you want to use for your private
|
||||||
key.
|
key.
|
||||||
|
|
||||||
\fBNOTE:\fP If the crypto device cannot be loaded,
|
If the crypto device cannot be loaded, \fICURLE_SSL_ENGINE_NOTFOUND\fP is
|
||||||
\fICURLE_SSL_ENGINE_NOTFOUND\fP is returned.
|
returned.
|
||||||
.IP CURLOPT_SSLENGINE_DEFAULT
|
.IP CURLOPT_SSLENGINE_DEFAULT
|
||||||
Sets the actual crypto engine as the default for (asymmetric) crypto
|
Sets the actual crypto engine as the default for (asymmetric) crypto
|
||||||
operations.
|
operations.
|
||||||
|
|
||||||
\fBNOTE:\fP If the crypto device cannot be set,
|
If the crypto device cannot be set, \fICURLE_SSL_ENGINE_SETFAILED\fP is
|
||||||
\fICURLE_SSL_ENGINE_SETFAILED\fP is returned.
|
returned.
|
||||||
.IP CURLOPT_SSLVERSION
|
.IP CURLOPT_SSLVERSION
|
||||||
Pass a long as parameter to control what version of SSL/TLS to attempt to use.
|
Pass a long as parameter to control what version of SSL/TLS to attempt to use.
|
||||||
The available options are:
|
The available options are:
|
||||||
|
@@ -23,4 +23,4 @@ You must curl_free() the returned string when you're done with it.
|
|||||||
.SH RETURN VALUE
|
.SH RETURN VALUE
|
||||||
A pointer to a zero terminated string or NULL if it failed.
|
A pointer to a zero terminated string or NULL if it failed.
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
.BR curl_unescape(3), curl_free(3), RFC 2396
|
.BR curl_unescape "(3), " curl_free "(3), " RFC 2396
|
||||||
|
@@ -243,7 +243,7 @@ where it'll store a human readable error message as well.
|
|||||||
If you then want to transfer another file, the handle is ready to be used
|
If you then want to transfer another file, the handle is ready to be used
|
||||||
again. Mind you, it is even preferred that you re-use an existing handle if
|
again. Mind you, it is even preferred that you re-use an existing handle if
|
||||||
you intend to make another transfer. libcurl will then attempt to re-use the
|
you intend to make another transfer. libcurl will then attempt to re-use the
|
||||||
previous
|
previous connection.
|
||||||
|
|
||||||
.SH "Multi-threading Issues"
|
.SH "Multi-threading Issues"
|
||||||
The first basic rule is that you must \fBnever\fP share a libcurl handle (be
|
The first basic rule is that you must \fBnever\fP share a libcurl handle (be
|
||||||
|
@@ -309,6 +309,13 @@ typedef enum {
|
|||||||
CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */
|
CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */
|
||||||
CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not
|
CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not
|
||||||
accepted and we failed to login */
|
accepted and we failed to login */
|
||||||
|
CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */
|
||||||
|
CURLE_TFTP_PERM, /* 69 - permission problem on server */
|
||||||
|
CURLE_TFTP_DISKFULL, /* 70 - out of disk space on server */
|
||||||
|
CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */
|
||||||
|
CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */
|
||||||
|
CURLE_TFTP_EXISTS, /* 73 - File already exists */
|
||||||
|
CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */
|
||||||
CURL_LAST /* never use! */
|
CURL_LAST /* never use! */
|
||||||
} CURLcode;
|
} CURLcode;
|
||||||
|
|
||||||
@@ -896,6 +903,12 @@ typedef enum {
|
|||||||
/* ignore Content-Length */
|
/* ignore Content-Length */
|
||||||
CINIT(IGNORE_CONTENT_LENGTH, LONG, 136),
|
CINIT(IGNORE_CONTENT_LENGTH, LONG, 136),
|
||||||
|
|
||||||
|
/* Set to non-zero to skip the IP address received in a 227 PASV FTP server
|
||||||
|
response. Typically used for FTP-SSL purposes but is not restricted to
|
||||||
|
that. libcurl will then instead use the same IP address it used for the
|
||||||
|
control connection. */
|
||||||
|
CINIT(FTP_SKIP_PASV_IP, LONG, 137),
|
||||||
|
|
||||||
CURLOPT_LASTENTRY /* the last unused */
|
CURLOPT_LASTENTRY /* the last unused */
|
||||||
} CURLoption;
|
} CURLoption;
|
||||||
|
|
||||||
|
@@ -28,7 +28,13 @@
|
|||||||
|
|
||||||
/* This is the version number of the libcurl package from which this header
|
/* This is the version number of the libcurl package from which this header
|
||||||
file origins: */
|
file origins: */
|
||||||
#define LIBCURL_VERSION "7.14.1-CVS"
|
#define LIBCURL_VERSION "7.15.0-CVS"
|
||||||
|
|
||||||
|
/* The numeric version number is also available "in parts" by using these
|
||||||
|
defines: */
|
||||||
|
#define LIBCURL_VERSION_MAJOR 7
|
||||||
|
#define LIBCURL_VERSION_MINOR 15
|
||||||
|
#define LIBCURL_VERSION_PATCH 0
|
||||||
|
|
||||||
/* This is the numeric version of the libcurl version number, meant for easier
|
/* This is the numeric version of the libcurl version number, meant for easier
|
||||||
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
|
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
|
||||||
@@ -37,19 +43,16 @@
|
|||||||
0xXXYYZZ
|
0xXXYYZZ
|
||||||
|
|
||||||
Where XX, YY and ZZ are the main version, release and patch numbers in
|
Where XX, YY and ZZ are the main version, release and patch numbers in
|
||||||
hexadecimal. All three numbers are always represented using two digits. 1.2
|
hexadecimal (using 8 bits each). All three numbers are always represented
|
||||||
would appear as "0x010200" while version 9.11.7 appears as "0x090b07".
|
using two digits. 1.2 would appear as "0x010200" while version 9.11.7
|
||||||
|
appears as "0x090b07".
|
||||||
|
|
||||||
This 6-digit hexadecimal number does not show pre-release number, and it is
|
This 6-digit (24 bits) hexadecimal number does not show pre-release number,
|
||||||
always a greater number in a more recent release. It makes comparisons with
|
and it is always a greater number in a more recent release. It makes
|
||||||
greater than and less than work.
|
comparisons with greater than and less than work.
|
||||||
*/
|
*/
|
||||||
#define LIBCURL_VERSION_NUM 0x070e01
|
#define LIBCURL_VERSION_NUM ((LIBCURL_VERSION_MAJOR << 16) | \
|
||||||
|
(LIBCURL_VERSION_MINOR << 8) | \
|
||||||
/* The numeric version number is also available "in parts" by using these
|
LIBCURL_VERSION_PATCH)
|
||||||
defines: */
|
|
||||||
#define LIBCURL_VERSION_MAJOR 7
|
|
||||||
#define LIBCURL_VERSION_MINOR 14
|
|
||||||
#define LIBCURL_VERSION_PATCH 1
|
|
||||||
|
|
||||||
#endif /* __CURL_CURLVER_H */
|
#endif /* __CURL_CURLVER_H */
|
||||||
|
@@ -44,7 +44,7 @@ OBJS = $(OBJ_DIR)\transfer.obj $(OBJ_DIR)\file.obj &
|
|||||||
$(OBJ_DIR)\hostip6.obj $(OBJ_DIR)\inet_ntop.obj &
|
$(OBJ_DIR)\hostip6.obj $(OBJ_DIR)\inet_ntop.obj &
|
||||||
$(OBJ_DIR)\hostsyn.obj $(OBJ_DIR)\parsedate.obj &
|
$(OBJ_DIR)\hostsyn.obj $(OBJ_DIR)\parsedate.obj &
|
||||||
$(OBJ_DIR)\select.obj $(OBJ_DIR)\sslgen.obj &
|
$(OBJ_DIR)\select.obj $(OBJ_DIR)\sslgen.obj &
|
||||||
$(OBJ_DIR)\gtls.obj
|
$(OBJ_DIR)\gtls.obj $(OBJ_DIR)\tftp.obj
|
||||||
|
|
||||||
RESOURCE = $(OBJ_DIR)\libcurl.res
|
RESOURCE = $(OBJ_DIR)\libcurl.res
|
||||||
|
|
||||||
@@ -362,3 +362,9 @@ $(OBJ_DIR)\gtls.obj: gtls.c setup.h config-win32.h
|
|||||||
$(OBJ_DIR)\sslgen.obj: sslgen.c setup.h config-win32.h urldata.h cookie.h &
|
$(OBJ_DIR)\sslgen.obj: sslgen.c setup.h config-win32.h urldata.h cookie.h &
|
||||||
formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h sslgen.h &
|
formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h sslgen.h &
|
||||||
ssluse.h gtls.h sendf.h strequal.h url.h memory.h memdebug.h
|
ssluse.h gtls.h sendf.h strequal.h url.h memory.h memdebug.h
|
||||||
|
|
||||||
|
$(OBJ_DIR)\tftp.obj: tftp.c setup.h config-win32.h urldata.h cookie.h &
|
||||||
|
..\include\curl\curl.h ..\include\curl\curlver.h ..\include\curl\easy.h &
|
||||||
|
..\include\curl\multi.h formdata.h http_chunks.h hostip.h hash.h llist.h &
|
||||||
|
transfer.h sendf.h tftp.h progress.h ..\include\curl\mprintf.h memory.h &
|
||||||
|
select.h memdebug.h
|
@@ -8,7 +8,7 @@ CSOURCES = file.c timeval.c base64.c hostip.c progress.c formdata.c \
|
|||||||
content_encoding.c share.c http_digest.c md5.c http_negotiate.c \
|
content_encoding.c share.c http_digest.c md5.c http_negotiate.c \
|
||||||
http_ntlm.c inet_pton.c strtoofft.c strerror.c hostares.c hostasyn.c \
|
http_ntlm.c inet_pton.c strtoofft.c strerror.c hostares.c hostasyn.c \
|
||||||
hostip4.c hostip6.c hostsyn.c hostthre.c inet_ntop.c parsedate.c \
|
hostip4.c hostip6.c hostsyn.c hostthre.c inet_ntop.c parsedate.c \
|
||||||
select.c gtls.c sslgen.c
|
select.c gtls.c sslgen.c tftp.c
|
||||||
|
|
||||||
HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h \
|
HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h \
|
||||||
progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \
|
progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \
|
||||||
@@ -18,5 +18,5 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h \
|
|||||||
share.h md5.h http_digest.h http_negotiate.h http_ntlm.h ca-bundle.h \
|
share.h md5.h http_digest.h http_negotiate.h http_ntlm.h ca-bundle.h \
|
||||||
inet_pton.h strtoofft.h strerror.h inet_ntop.h curlx.h memory.h \
|
inet_pton.h strtoofft.h strerror.h inet_ntop.h curlx.h memory.h \
|
||||||
setup.h transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h \
|
setup.h transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h \
|
||||||
gtls.h
|
gtls.h tftp.h
|
||||||
|
|
||||||
|
@@ -301,7 +301,7 @@ config.h: Makefile.netware
|
|||||||
@echo $(DL)*/$(DL) >> $@
|
@echo $(DL)*/$(DL) >> $@
|
||||||
@echo $(DL)#define OS "i586-pc-NetWare"$(DL) >> $@
|
@echo $(DL)#define OS "i586-pc-NetWare"$(DL) >> $@
|
||||||
@echo $(DL)#define VERSION "$(LIBCURL_VERSION_STR)"$(DL) >> $@
|
@echo $(DL)#define VERSION "$(LIBCURL_VERSION_STR)"$(DL) >> $@
|
||||||
@echo $(DL)#define PACKAGE_BUGREPORT "curl-bug@haxx.se"$(DL) >> $@
|
@echo $(DL)#define PACKAGE_BUGREPORT "a suitable curl mailing list => http://curl.haxx.se/mail/"$(DL) >> $@
|
||||||
@echo $(DL)#define HAVE_ARPA_INET_H 1$(DL) >> $@
|
@echo $(DL)#define HAVE_ARPA_INET_H 1$(DL) >> $@
|
||||||
@echo $(DL)#define HAVE_ASSERT_H 1$(DL) >> $@
|
@echo $(DL)#define HAVE_ASSERT_H 1$(DL) >> $@
|
||||||
@echo $(DL)#define HAVE_DLFCN_H 1$(DL) >> $@
|
@echo $(DL)#define HAVE_DLFCN_H 1$(DL) >> $@
|
||||||
|
@@ -469,6 +469,7 @@ X_OBJS= \
|
|||||||
$(DIROBJ)\strerror.obj \
|
$(DIROBJ)\strerror.obj \
|
||||||
$(DIROBJ)\select.obj \
|
$(DIROBJ)\select.obj \
|
||||||
$(DIROBJ)\content_encoding.obj \
|
$(DIROBJ)\content_encoding.obj \
|
||||||
|
$(DIROBJ)\tftp.obj \
|
||||||
$(RESOURCE)
|
$(RESOURCE)
|
||||||
|
|
||||||
all : $(TARGET)
|
all : $(TARGET)
|
||||||
|
@@ -631,8 +631,9 @@ singleipconnect(struct connectdata *conn,
|
|||||||
int error;
|
int error;
|
||||||
bool conected;
|
bool conected;
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
curl_socket_t sockfd = socket(ai->ai_family, ai->ai_socktype,
|
curl_socket_t sockfd;
|
||||||
ai->ai_protocol);
|
|
||||||
|
sockfd = socket(ai->ai_family, conn->socktype, ai->ai_protocol);
|
||||||
if (sockfd == CURL_SOCKET_BAD)
|
if (sockfd == CURL_SOCKET_BAD)
|
||||||
return CURL_SOCKET_BAD;
|
return CURL_SOCKET_BAD;
|
||||||
|
|
||||||
@@ -660,7 +661,11 @@ singleipconnect(struct connectdata *conn,
|
|||||||
/* set socket non-blocking */
|
/* set socket non-blocking */
|
||||||
Curl_nonblock(sockfd, TRUE);
|
Curl_nonblock(sockfd, TRUE);
|
||||||
|
|
||||||
rc = connect(sockfd, ai->ai_addr, (socklen_t)ai->ai_addrlen);
|
/* Connect TCP sockets, bind UDP */
|
||||||
|
if(conn->socktype == SOCK_STREAM)
|
||||||
|
rc = connect(sockfd, ai->ai_addr, (socklen_t)ai->ai_addrlen);
|
||||||
|
else
|
||||||
|
rc = 0;
|
||||||
|
|
||||||
if(-1 == rc) {
|
if(-1 == rc) {
|
||||||
error = Curl_ourerrno();
|
error = Curl_ourerrno();
|
||||||
|
67
lib/ftp.c
67
lib/ftp.c
@@ -174,13 +174,9 @@ static bool isBadFtpString(const char *string)
|
|||||||
* to us. This function will sit and wait here until the server has
|
* to us. This function will sit and wait here until the server has
|
||||||
* connected.
|
* connected.
|
||||||
*
|
*
|
||||||
* If FTP-SSL is used and SSL is requested for the data connection, this
|
|
||||||
* function will do that transport layer handshake too.
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
static CURLcode AllowServerConnect(struct connectdata *conn)
|
static CURLcode AllowServerConnect(struct connectdata *conn)
|
||||||
{
|
{
|
||||||
CURLcode result;
|
|
||||||
int timeout_ms;
|
int timeout_ms;
|
||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
curl_socket_t sock = conn->sock[SECONDARYSOCKET];
|
curl_socket_t sock = conn->sock[SECONDARYSOCKET];
|
||||||
@@ -235,17 +231,6 @@ static CURLcode AllowServerConnect(struct connectdata *conn)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If PASV is used, this is is made elsewhere */
|
|
||||||
if(conn->ssl[SECONDARYSOCKET].use) {
|
|
||||||
/* since we only have a plaintext TCP connection here, we must now
|
|
||||||
do the TLS stuff */
|
|
||||||
infof(data, "Doing the SSL/TLS handshake on the data stream\n");
|
|
||||||
/* BLOCKING */
|
|
||||||
result = Curl_ssl_connect(conn, SECONDARYSOCKET);
|
|
||||||
if(result)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -858,7 +843,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
|
|||||||
* Workaround for AIX5 getaddrinfo() problem (it doesn't set ai_socktype):
|
* Workaround for AIX5 getaddrinfo() problem (it doesn't set ai_socktype):
|
||||||
*/
|
*/
|
||||||
if (ai->ai_socktype == 0)
|
if (ai->ai_socktype == 0)
|
||||||
ai->ai_socktype = SOCK_STREAM;
|
ai->ai_socktype = conn->socktype;
|
||||||
|
|
||||||
portsock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
portsock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
|
||||||
if (portsock == CURL_SOCKET_BAD) {
|
if (portsock == CURL_SOCKET_BAD) {
|
||||||
@@ -1601,8 +1586,18 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
|||||||
return CURLE_FTP_WEIRD_227_FORMAT;
|
return CURLE_FTP_WEIRD_227_FORMAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(newhost, sizeof(newhost),
|
/* we got OK from server */
|
||||||
"%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
|
if(data->set.ftp_skip_ip) {
|
||||||
|
/* told to ignore the remotely given IP but instead use the one we used
|
||||||
|
for the control connection */
|
||||||
|
infof(data, "Skips %d.%d.%d.%d for data connection, uses %s instead\n",
|
||||||
|
ip[0], ip[1], ip[2], ip[3],
|
||||||
|
conn->ip_addr_str);
|
||||||
|
snprintf(newhost, sizeof(newhost), "%s", conn->ip_addr_str);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
snprintf(newhost, sizeof(newhost),
|
||||||
|
"%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
|
||||||
newport = (port[0]<<8) + port[1];
|
newport = (port[0]<<8) + port[1];
|
||||||
}
|
}
|
||||||
else if(ftp->count1 == 0) {
|
else if(ftp->count1 == 0) {
|
||||||
@@ -1622,8 +1617,6 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
|
|||||||
return CURLE_FTP_WEIRD_PASV_REPLY;
|
return CURLE_FTP_WEIRD_PASV_REPLY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we got OK from server */
|
|
||||||
|
|
||||||
if(data->change.proxy && *data->change.proxy) {
|
if(data->change.proxy && *data->change.proxy) {
|
||||||
/*
|
/*
|
||||||
* This is a tunnel through a http proxy and we need to connect to the
|
* This is a tunnel through a http proxy and we need to connect to the
|
||||||
@@ -1805,7 +1798,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
|
|||||||
switch(data->set.timecondition) {
|
switch(data->set.timecondition) {
|
||||||
case CURL_TIMECOND_IFMODSINCE:
|
case CURL_TIMECOND_IFMODSINCE:
|
||||||
default:
|
default:
|
||||||
if(data->info.filetime < data->set.timevalue) {
|
if(data->info.filetime <= data->set.timevalue) {
|
||||||
infof(data, "The requested document is not new enough\n");
|
infof(data, "The requested document is not new enough\n");
|
||||||
ftp->no_transfer = TRUE; /* mark this to not transfer data */
|
ftp->no_transfer = TRUE; /* mark this to not transfer data */
|
||||||
state(conn, FTP_STOP);
|
state(conn, FTP_STOP);
|
||||||
@@ -2032,6 +2025,16 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(conn->ssl[SECONDARYSOCKET].use) {
|
||||||
|
/* since we only have a plaintext TCP connection here, we must now
|
||||||
|
do the TLS stuff */
|
||||||
|
infof(data, "Doing the SSL/TLS handshake on the data stream\n");
|
||||||
|
/* BLOCKING */
|
||||||
|
result = Curl_ssl_connect(conn, SECONDARYSOCKET);
|
||||||
|
if(result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
*(ftp->bytecountp)=0;
|
*(ftp->bytecountp)=0;
|
||||||
|
|
||||||
/* When we know we're uploading a specified file, we can get the file
|
/* When we know we're uploading a specified file, we can get the file
|
||||||
@@ -2131,6 +2134,15 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(conn->ssl[SECONDARYSOCKET].use) {
|
||||||
|
/* since we only have a plaintext TCP connection here, we must now
|
||||||
|
do the TLS stuff */
|
||||||
|
infof(data, "Doing the SSL/TLS handshake on the data stream\n");
|
||||||
|
result = Curl_ssl_connect(conn, SECONDARYSOCKET);
|
||||||
|
if(result)
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
if(size > conn->maxdownload && conn->maxdownload > 0)
|
if(size > conn->maxdownload && conn->maxdownload > 0)
|
||||||
size = conn->size = conn->maxdownload;
|
size = conn->size = conn->maxdownload;
|
||||||
|
|
||||||
@@ -3092,18 +3104,6 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
|
|||||||
if(!ftp->no_transfer && !conn->bits.no_body) {
|
if(!ftp->no_transfer && !conn->bits.no_body) {
|
||||||
/* a transfer is about to take place */
|
/* a transfer is about to take place */
|
||||||
|
|
||||||
if(conn->ssl[SECONDARYSOCKET].use &&
|
|
||||||
!data->set.ftp_use_port) {
|
|
||||||
/* PASV is used and we just got the data connection connected, then
|
|
||||||
it is time to handshake the secure stuff. */
|
|
||||||
|
|
||||||
infof(data, "Doing the SSL/TLS handshake on the data stream\n");
|
|
||||||
/* BLOCKING */
|
|
||||||
result = Curl_ssl_connect(conn, SECONDARYSOCKET);
|
|
||||||
if(result)
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(data->set.upload) {
|
if(data->set.upload) {
|
||||||
NBFTPSENDF(conn, "TYPE %c", data->set.ftp_ascii?'A':'I');
|
NBFTPSENDF(conn, "TYPE %c", data->set.ftp_ascii?'A':'I');
|
||||||
state(conn, FTP_STOR_TYPE);
|
state(conn, FTP_STOR_TYPE);
|
||||||
@@ -3811,6 +3811,7 @@ static CURLcode ftp_dophase_done(struct connectdata *conn,
|
|||||||
/* Failure detected, close the second socket if it was created already */
|
/* Failure detected, close the second socket if it was created already */
|
||||||
sclose(conn->sock[SECONDARYSOCKET]);
|
sclose(conn->sock[SECONDARYSOCKET]);
|
||||||
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
|
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ftp->no_transfer)
|
if(ftp->no_transfer)
|
||||||
|
@@ -423,7 +423,11 @@ Curl_addrinfo *Curl_he2ai(struct hostent *he, int port)
|
|||||||
prevai->ai_next = ai;
|
prevai->ai_next = ai;
|
||||||
|
|
||||||
ai->ai_family = AF_INET; /* we only support this */
|
ai->ai_family = AF_INET; /* we only support this */
|
||||||
ai->ai_socktype = SOCK_STREAM; /* we only support this */
|
|
||||||
|
/* we return all names as STREAM, so when using this address for TFTP
|
||||||
|
the type must be ignored and conn->socktype be used instead! */
|
||||||
|
ai->ai_socktype = SOCK_STREAM;
|
||||||
|
|
||||||
ai->ai_addrlen = sizeof(struct sockaddr_in);
|
ai->ai_addrlen = sizeof(struct sockaddr_in);
|
||||||
/* make the ai_addr point to the address immediately following this struct
|
/* make the ai_addr point to the address immediately following this struct
|
||||||
and use that area to store the address */
|
and use that area to store the address */
|
||||||
|
@@ -202,6 +202,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
|||||||
struct addrinfo hints, *res;
|
struct addrinfo hints, *res;
|
||||||
int error;
|
int error;
|
||||||
char sbuf[NI_MAXSERV];
|
char sbuf[NI_MAXSERV];
|
||||||
|
char *sbufptr = NULL;
|
||||||
char addrbuf[128];
|
char addrbuf[128];
|
||||||
curl_socket_t s;
|
curl_socket_t s;
|
||||||
int pf;
|
int pf;
|
||||||
@@ -251,10 +252,15 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
|||||||
|
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_family = pf;
|
hints.ai_family = pf;
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
|
||||||
|
hints.ai_socktype = conn->socktype;
|
||||||
|
|
||||||
hints.ai_flags = ai_flags;
|
hints.ai_flags = ai_flags;
|
||||||
snprintf(sbuf, sizeof(sbuf), "%d", port);
|
if(port) {
|
||||||
error = getaddrinfo(hostname, sbuf, &hints, &res);
|
snprintf(sbuf, sizeof(sbuf), "%d", port);
|
||||||
|
sbufptr=sbuf;
|
||||||
|
}
|
||||||
|
error = getaddrinfo(hostname, sbufptr, &hints, &res);
|
||||||
if (error) {
|
if (error) {
|
||||||
infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port);
|
infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@@ -88,6 +88,10 @@
|
|||||||
/* The last #include file should be: */
|
/* The last #include file should be: */
|
||||||
#include "memdebug.h"
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && defined(CURL_NO__BEGINTHREADEX)
|
||||||
|
#pragma message ("No _beginthreadex() available in this RTL")
|
||||||
|
#endif
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* Only for Windows threaded name resolves builds
|
* Only for Windows threaded name resolves builds
|
||||||
**********************************************************************/
|
**********************************************************************/
|
||||||
@@ -289,7 +293,7 @@ static unsigned __stdcall gethostbyname_thread (void *arg)
|
|||||||
* This allows us to use it even after the container gets destroyed
|
* This allows us to use it even after the container gets destroyed
|
||||||
* due to a resolver timeout.
|
* due to a resolver timeout.
|
||||||
*/
|
*/
|
||||||
struct thread_sync_data tsd = {0};
|
struct thread_sync_data tsd = { 0,0,0,NULL };
|
||||||
if (!init_thread_sync_data(td, conn->async.hostname, &tsd)) {
|
if (!init_thread_sync_data(td, conn->async.hostname, &tsd)) {
|
||||||
/* thread synchronization data initialization failed */
|
/* thread synchronization data initialization failed */
|
||||||
return -1;
|
return -1;
|
||||||
@@ -356,7 +360,7 @@ static unsigned __stdcall getaddrinfo_thread (void *arg)
|
|||||||
* This allows us to use it even after the container gets destroyed
|
* This allows us to use it even after the container gets destroyed
|
||||||
* due to a resolver timeout.
|
* due to a resolver timeout.
|
||||||
*/
|
*/
|
||||||
struct thread_sync_data tsd = {0};
|
struct thread_sync_data tsd = { 0,0,0,NULL };
|
||||||
if (!init_thread_sync_data(td, conn->async.hostname, &tsd)) {
|
if (!init_thread_sync_data(td, conn->async.hostname, &tsd)) {
|
||||||
/* thread synchronization data initialization failed */
|
/* thread synchronization data initialization failed */
|
||||||
return -1;
|
return -1;
|
||||||
@@ -559,7 +563,10 @@ static bool init_resolve_thread (struct connectdata *conn,
|
|||||||
*/
|
*/
|
||||||
thread_and_event[0] = td->thread_hnd;
|
thread_and_event[0] = td->thread_hnd;
|
||||||
thread_and_event[1] = td->event_thread_started;
|
thread_and_event[1] = td->event_thread_started;
|
||||||
if (WaitForMultipleObjects(sizeof(thread_and_event) / sizeof(thread_and_event[0]), thread_and_event, FALSE, INFINITE) == WAIT_FAILED) {
|
if (WaitForMultipleObjects(sizeof(thread_and_event) /
|
||||||
|
sizeof(thread_and_event[0]),
|
||||||
|
thread_and_event, FALSE,
|
||||||
|
INFINITE) == WAIT_FAILED) {
|
||||||
/* The resolver thread has been created,
|
/* The resolver thread has been created,
|
||||||
* most probably it works now - ignoring this "minor" error
|
* most probably it works now - ignoring this "minor" error
|
||||||
*/
|
*/
|
||||||
@@ -804,7 +811,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
|
|||||||
|
|
||||||
memset(&hints, 0, sizeof(hints));
|
memset(&hints, 0, sizeof(hints));
|
||||||
hints.ai_family = pf;
|
hints.ai_family = pf;
|
||||||
hints.ai_socktype = SOCK_STREAM;
|
hints.ai_socktype = conn->socktype;
|
||||||
hints.ai_flags = AI_CANONNAME;
|
hints.ai_flags = AI_CANONNAME;
|
||||||
itoa(port, sbuf, 10);
|
itoa(port, sbuf, 10);
|
||||||
|
|
||||||
|
@@ -387,6 +387,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
|||||||
ULONG attrs;
|
ULONG attrs;
|
||||||
const char *user;
|
const char *user;
|
||||||
int domlen;
|
int domlen;
|
||||||
|
TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */
|
||||||
|
|
||||||
ntlm_sspi_cleanup(ntlm);
|
ntlm_sspi_cleanup(ntlm);
|
||||||
|
|
||||||
@@ -430,8 +431,8 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
|||||||
|
|
||||||
if (AcquireCredentialsHandle(
|
if (AcquireCredentialsHandle(
|
||||||
NULL, (char *)"NTLM", SECPKG_CRED_OUTBOUND, NULL, ntlm->p_identity,
|
NULL, (char *)"NTLM", SECPKG_CRED_OUTBOUND, NULL, ntlm->p_identity,
|
||||||
NULL, NULL, &ntlm->handle, NULL
|
NULL, NULL, &ntlm->handle, &tsDummy
|
||||||
) != SEC_E_OK) {
|
) != SEC_E_OK) {
|
||||||
return CURLE_OUT_OF_MEMORY;
|
return CURLE_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,12 +448,23 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
|||||||
ISC_REQ_REPLAY_DETECT |
|
ISC_REQ_REPLAY_DETECT |
|
||||||
ISC_REQ_CONNECTION,
|
ISC_REQ_CONNECTION,
|
||||||
0, SECURITY_NETWORK_DREP, NULL, 0,
|
0, SECURITY_NETWORK_DREP, NULL, 0,
|
||||||
&ntlm->c_handle, &desc, &attrs, NULL
|
&ntlm->c_handle, &desc, &attrs, &tsDummy
|
||||||
);
|
);
|
||||||
|
|
||||||
if (status == SEC_I_COMPLETE_AND_CONTINUE ||
|
if (status == SEC_I_COMPLETE_AND_CONTINUE ||
|
||||||
status == SEC_I_CONTINUE_NEEDED) {
|
status == SEC_I_CONTINUE_NEEDED) {
|
||||||
CompleteAuthToken(&ntlm->c_handle, &desc);
|
/* CompleteAuthToken() is not present in Win9x, so load it dynamically */
|
||||||
|
SECURITY_STATUS (__stdcall * pCompleteAuthToken)
|
||||||
|
(PCtxtHandle,PSecBufferDesc);
|
||||||
|
HMODULE hSecur32 = GetModuleHandle("secur32.dll");
|
||||||
|
if (hSecur32 != NULL) {
|
||||||
|
pCompleteAuthToken =
|
||||||
|
(SECURITY_STATUS (__stdcall *)(PCtxtHandle,PSecBufferDesc))
|
||||||
|
GetProcAddress(hSecur32, "CompleteAuthToken");
|
||||||
|
if( pCompleteAuthToken != NULL ) {
|
||||||
|
pCompleteAuthToken(&ntlm->c_handle, &desc);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (status != SEC_E_OK) {
|
else if (status != SEC_E_OK) {
|
||||||
FreeCredentialsHandle(&ntlm->handle);
|
FreeCredentialsHandle(&ntlm->handle);
|
||||||
@@ -553,6 +565,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
|||||||
SecBufferDesc type_2_desc, type_3_desc;
|
SecBufferDesc type_2_desc, type_3_desc;
|
||||||
SECURITY_STATUS status;
|
SECURITY_STATUS status;
|
||||||
ULONG attrs;
|
ULONG attrs;
|
||||||
|
TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */
|
||||||
|
|
||||||
type_2_desc.ulVersion = type_3_desc.ulVersion = SECBUFFER_VERSION;
|
type_2_desc.ulVersion = type_3_desc.ulVersion = SECBUFFER_VERSION;
|
||||||
type_2_desc.cBuffers = type_3_desc.cBuffers = 1;
|
type_2_desc.cBuffers = type_3_desc.cBuffers = 1;
|
||||||
@@ -573,7 +586,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
|||||||
ISC_REQ_CONNECTION,
|
ISC_REQ_CONNECTION,
|
||||||
0, SECURITY_NETWORK_DREP, &type_2_desc,
|
0, SECURITY_NETWORK_DREP, &type_2_desc,
|
||||||
0, &ntlm->c_handle, &type_3_desc,
|
0, &ntlm->c_handle, &type_3_desc,
|
||||||
&attrs, NULL);
|
&attrs, &tsDummy);
|
||||||
|
|
||||||
if (status != SEC_E_OK)
|
if (status != SEC_E_OK)
|
||||||
return CURLE_RECV_ERROR;
|
return CURLE_RECV_ERROR;
|
||||||
@@ -700,6 +713,13 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
|
|||||||
size=64;
|
size=64;
|
||||||
ntlmbuf[62]=ntlmbuf[63]=0;
|
ntlmbuf[62]=ntlmbuf[63]=0;
|
||||||
|
|
||||||
|
/* Make sure that the user and domain strings fit in the target buffer
|
||||||
|
before we copy them there. */
|
||||||
|
if(size + userlen + domlen >= sizeof(ntlmbuf)) {
|
||||||
|
failf(conn->data, "user + domain name too big");
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
memcpy(&ntlmbuf[size], domain, domlen);
|
memcpy(&ntlmbuf[size], domain, domlen);
|
||||||
size += domlen;
|
size += domlen;
|
||||||
|
|
||||||
|
@@ -130,8 +130,8 @@ static const struct tzinfo tz[]= {
|
|||||||
{"CET", -60}, /* Central European */
|
{"CET", -60}, /* Central European */
|
||||||
{"MET", -60}, /* Middle European */
|
{"MET", -60}, /* Middle European */
|
||||||
{"MEWT", -60}, /* Middle European Winter */
|
{"MEWT", -60}, /* Middle European Winter */
|
||||||
{"MEST", -120 tDAYZONE}, /* Middle European Summer */
|
{"MEST", -60 tDAYZONE}, /* Middle European Summer */
|
||||||
{"CEST", -120 tDAYZONE}, /* Central European Summer */
|
{"CEST", -60 tDAYZONE}, /* Central European Summer */
|
||||||
{"MESZ", -60 tDAYZONE}, /* Middle European Summer */
|
{"MESZ", -60 tDAYZONE}, /* Middle European Summer */
|
||||||
{"FWT", -60}, /* French Winter */
|
{"FWT", -60}, /* French Winter */
|
||||||
{"FST", -60 tDAYZONE}, /* French Summer */
|
{"FST", -60 tDAYZONE}, /* French Summer */
|
||||||
|
@@ -262,6 +262,14 @@ typedef int curl_socket_t;
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* "cl -ML" or "cl -MLd" implies a single-threaded runtime library where
|
||||||
|
_beginthreadex() is not available */
|
||||||
|
#if defined(_MSC_VER) && !defined(_MT) && !defined(USE_ARES)
|
||||||
|
#undef USE_THREADING_GETADDRINFO
|
||||||
|
#undef USE_THREADING_GETHOSTBYNAME
|
||||||
|
#define CURL_NO__BEGINTHREADEX
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef mpeix
|
#ifdef mpeix
|
||||||
#define IOCTL_3_ARGS
|
#define IOCTL_3_ARGS
|
||||||
#endif
|
#endif
|
||||||
|
@@ -245,6 +245,27 @@ curl_easy_strerror(CURLcode error)
|
|||||||
case CURLE_LOGIN_DENIED:
|
case CURLE_LOGIN_DENIED:
|
||||||
return "FTP: login denied";;
|
return "FTP: login denied";;
|
||||||
|
|
||||||
|
case CURLE_TFTP_NOTFOUND:
|
||||||
|
return "TFTP: File Not Found";;
|
||||||
|
|
||||||
|
case CURLE_TFTP_PERM:
|
||||||
|
return "TFTP: Access Violation";;
|
||||||
|
|
||||||
|
case CURLE_TFTP_DISKFULL:
|
||||||
|
return "TFTP: Disk full or allocation exceeded";;
|
||||||
|
|
||||||
|
case CURLE_TFTP_ILLEGAL:
|
||||||
|
return "TFTP: Illegal operation";;
|
||||||
|
|
||||||
|
case CURLE_TFTP_UNKNOWNID:
|
||||||
|
return "TFTP: Unknown transfer ID";;
|
||||||
|
|
||||||
|
case CURLE_TFTP_EXISTS:
|
||||||
|
return "TFTP: File already exists";;
|
||||||
|
|
||||||
|
case CURLE_TFTP_NOSUCHUSER:
|
||||||
|
return "TFTP: No such user";;
|
||||||
|
|
||||||
case CURLE_URL_MALFORMAT_USER: /* not used by current libcurl */
|
case CURLE_URL_MALFORMAT_USER: /* not used by current libcurl */
|
||||||
case CURLE_MALFORMAT_USER: /* not used by current libcurl */
|
case CURLE_MALFORMAT_USER: /* not used by current libcurl */
|
||||||
case CURLE_BAD_CALLING_ORDER: /* not used by current libcurl */
|
case CURLE_BAD_CALLING_ORDER: /* not used by current libcurl */
|
||||||
|
719
lib/tftp.c
Normal file
719
lib/tftp.c
Normal file
@@ -0,0 +1,719 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2005, 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
|
||||||
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#include "setup.h"
|
||||||
|
|
||||||
|
#ifndef CURL_DISABLE_TFTP
|
||||||
|
/* -- WIN32 approved -- */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_STAT_H
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
#include <time.h>
|
||||||
|
#include <io.h>
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#include <netdb.h>
|
||||||
|
#ifdef HAVE_ARPA_INET_H
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NET_IF_H
|
||||||
|
#include <net/if.h>
|
||||||
|
#endif
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_PARAM_H
|
||||||
|
#include <sys/param.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "urldata.h"
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#include "transfer.h"
|
||||||
|
#include "sendf.h"
|
||||||
|
#include "tftp.h"
|
||||||
|
#include "progress.h"
|
||||||
|
#include "connect.h"
|
||||||
|
#include "strerror.h"
|
||||||
|
|
||||||
|
#define _MPRINTF_REPLACE /* use our functions only */
|
||||||
|
#include <curl/mprintf.h>
|
||||||
|
|
||||||
|
#include "memory.h"
|
||||||
|
#include "select.h"
|
||||||
|
|
||||||
|
/* The last #include file should be: */
|
||||||
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
#ifndef MSG_NOSIGNAL
|
||||||
|
#define MSG_NOSIGNAL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TFTP_MODE_NETASCII=0,
|
||||||
|
TFTP_MODE_OCTET
|
||||||
|
} tftp_mode_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TFTP_STATE_START=0,
|
||||||
|
TFTP_STATE_RX,
|
||||||
|
TFTP_STATE_TX,
|
||||||
|
TFTP_STATE_FIN
|
||||||
|
} tftp_state_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TFTP_EVENT_INIT=0,
|
||||||
|
TFTP_EVENT_RRQ = 1,
|
||||||
|
TFTP_EVENT_WRQ = 2,
|
||||||
|
TFTP_EVENT_DATA = 3,
|
||||||
|
TFTP_EVENT_ACK = 4,
|
||||||
|
TFTP_EVENT_ERROR = 5,
|
||||||
|
TFTP_EVENT_TIMEOUT
|
||||||
|
} tftp_event_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
TFTP_ERR_UNDEF=0,
|
||||||
|
TFTP_ERR_NOTFOUND,
|
||||||
|
TFTP_ERR_PERM,
|
||||||
|
TFTP_ERR_DISKFULL,
|
||||||
|
TFTP_ERR_ILLEGAL,
|
||||||
|
TFTP_ERR_UNKNOWNID,
|
||||||
|
TFTP_ERR_EXISTS,
|
||||||
|
TFTP_ERR_NOSUCHUSER,
|
||||||
|
TFTP_ERR_TIMEOUT,
|
||||||
|
TFTP_ERR_NORESPONSE
|
||||||
|
} tftp_error_t;
|
||||||
|
|
||||||
|
typedef struct tftp_packet {
|
||||||
|
unsigned short event;
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
unsigned char data[512];
|
||||||
|
} request;
|
||||||
|
struct {
|
||||||
|
unsigned short block;
|
||||||
|
unsigned char data[512];
|
||||||
|
} data;
|
||||||
|
struct {
|
||||||
|
unsigned short block;
|
||||||
|
} ack;
|
||||||
|
struct {
|
||||||
|
unsigned short code;
|
||||||
|
unsigned char data[512];
|
||||||
|
} error;
|
||||||
|
} u;
|
||||||
|
} tftp_packet_t;
|
||||||
|
|
||||||
|
typedef struct tftp_state_data {
|
||||||
|
tftp_state_t state;
|
||||||
|
tftp_mode_t mode;
|
||||||
|
tftp_error_t error;
|
||||||
|
struct connectdata *conn;
|
||||||
|
curl_socket_t sockfd;
|
||||||
|
int retries;
|
||||||
|
int retry_time;
|
||||||
|
int retry_max;
|
||||||
|
time_t start_time;
|
||||||
|
time_t max_time;
|
||||||
|
unsigned short block;
|
||||||
|
struct sockaddr local_addr;
|
||||||
|
socklen_t local_addrlen;
|
||||||
|
struct sockaddr remote_addr;
|
||||||
|
socklen_t remote_addrlen;
|
||||||
|
int rbytes;
|
||||||
|
int sbytes;
|
||||||
|
tftp_packet_t rpacket;
|
||||||
|
tftp_packet_t spacket;
|
||||||
|
} tftp_state_data_t;
|
||||||
|
|
||||||
|
|
||||||
|
/* Forward declarations */
|
||||||
|
static void tftp_rx(tftp_state_data_t *state, tftp_event_t event) ;
|
||||||
|
static void tftp_tx(tftp_state_data_t *state, tftp_event_t event) ;
|
||||||
|
void tftp_set_timeouts(tftp_state_data_t *state) ;
|
||||||
|
|
||||||
|
/**********************************************************
|
||||||
|
*
|
||||||
|
* tftp_set_timeouts -
|
||||||
|
*
|
||||||
|
* Set timeouts based on state machine state.
|
||||||
|
* Use user provided connect timeouts until DATA or ACK
|
||||||
|
* packet is received, then use user-provided transfer timeouts
|
||||||
|
*
|
||||||
|
*
|
||||||
|
**********************************************************/
|
||||||
|
void tftp_set_timeouts(tftp_state_data_t *state)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct SessionHandle *data = state->conn->data;
|
||||||
|
time_t maxtime, timeout;
|
||||||
|
|
||||||
|
time(&state->start_time);
|
||||||
|
if(state->state == TFTP_STATE_START) {
|
||||||
|
/* Compute drop-dead time */
|
||||||
|
maxtime = (time_t)(data->set.connecttimeout?data->set.connecttimeout:30);
|
||||||
|
state->max_time = state->start_time+maxtime;
|
||||||
|
|
||||||
|
/* Set per-block timeout to total */
|
||||||
|
timeout = maxtime ;
|
||||||
|
|
||||||
|
/* Average restart after 5 seconds */
|
||||||
|
state->retry_max = timeout/5;
|
||||||
|
|
||||||
|
/* Compute the re-start interval to suit the timeout */
|
||||||
|
state->retry_time = timeout/state->retry_max;
|
||||||
|
if(state->retry_time<1) state->retry_time=1;
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
/* Compute drop-dead time */
|
||||||
|
maxtime = data->set.timeout?data->set.timeout:3600;
|
||||||
|
state->max_time = state->start_time+maxtime;
|
||||||
|
|
||||||
|
/* Set per-block timeout to 10% of total */
|
||||||
|
timeout = maxtime/10 ;
|
||||||
|
|
||||||
|
/* Average reposting an ACK after 15 seconds */
|
||||||
|
state->retry_max = timeout/15;
|
||||||
|
}
|
||||||
|
/* But bound the total number */
|
||||||
|
if(state->retry_max<3) state->retry_max=3;
|
||||||
|
if(state->retry_max>50) state->retry_max=50;
|
||||||
|
|
||||||
|
/* Compute the re-ACK interval to suit the timeout */
|
||||||
|
state->retry_time = timeout/state->retry_max;
|
||||||
|
if(state->retry_time<1) state->retry_time=1;
|
||||||
|
|
||||||
|
infof(data, "set timeouts for state %d; Total %d, retry %d maxtry %d\n",
|
||||||
|
state->state, (state->max_time-state->start_time),
|
||||||
|
state->retry_time, state->retry_max);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************
|
||||||
|
*
|
||||||
|
* tftp_set_send_first
|
||||||
|
*
|
||||||
|
* Event handler for the START state
|
||||||
|
*
|
||||||
|
**********************************************************/
|
||||||
|
|
||||||
|
static void tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
|
||||||
|
{
|
||||||
|
int sbytes;
|
||||||
|
const char *mode = "octet";
|
||||||
|
char *filename = state->conn->path;
|
||||||
|
struct SessionHandle *data = state->conn->data;
|
||||||
|
|
||||||
|
/* Set ascii mode if -B flag was used */
|
||||||
|
if(data->set.ftp_ascii)
|
||||||
|
mode = "netascii";
|
||||||
|
|
||||||
|
switch(event) {
|
||||||
|
|
||||||
|
case TFTP_EVENT_INIT: /* Send the first packet out */
|
||||||
|
case TFTP_EVENT_TIMEOUT: /* Resend the first packet out */
|
||||||
|
/* Increment the retry counter, quit if over the limit */
|
||||||
|
state->retries++;
|
||||||
|
if(state->retries>state->retry_max) {
|
||||||
|
state->error = TFTP_ERR_NORESPONSE;
|
||||||
|
state->state = TFTP_STATE_FIN;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data->set.upload) {
|
||||||
|
/* If we are uploading, send an WRQ */
|
||||||
|
state->spacket.event = htons(TFTP_EVENT_WRQ);
|
||||||
|
filename = curl_unescape(filename, strlen(filename));
|
||||||
|
state->conn->upload_fromhere = (char *)state->spacket.u.data.data;
|
||||||
|
if(data->set.infilesize != -1) {
|
||||||
|
Curl_pgrsSetUploadSize(data, data->set.infilesize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* If we are downloading, send an RRQ */
|
||||||
|
state->spacket.event = htons(TFTP_EVENT_RRQ);
|
||||||
|
}
|
||||||
|
sprintf((char *)state->spacket.u.request.data, "%s%c%s%c",
|
||||||
|
filename, '\0', mode, '\0');
|
||||||
|
sbytes = 4 + strlen(filename) + strlen(mode);
|
||||||
|
sbytes = sendto(state->sockfd, &state->spacket, sbytes, 0,
|
||||||
|
state->conn->ip_addr->ai_addr,
|
||||||
|
state->conn->ip_addr->ai_addrlen);
|
||||||
|
if(sbytes < 0) {
|
||||||
|
failf(data, "%s\n", strerror(errno));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TFTP_EVENT_ACK: /* Connected for transmit */
|
||||||
|
infof(data, "%s\n", "Connected for transmit");
|
||||||
|
state->state = TFTP_STATE_TX;
|
||||||
|
tftp_set_timeouts(state);
|
||||||
|
tftp_tx(state, event);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TFTP_EVENT_DATA: /* connected for receive */
|
||||||
|
infof(data, "%s\n", "Connected for receive");
|
||||||
|
state->state = TFTP_STATE_RX;
|
||||||
|
tftp_set_timeouts(state);
|
||||||
|
tftp_rx(state, event);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TFTP_EVENT_ERROR:
|
||||||
|
state->state = TFTP_STATE_FIN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
failf(state->conn->data, "tftp_send_first: internal error\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************
|
||||||
|
*
|
||||||
|
* tftp_rx
|
||||||
|
*
|
||||||
|
* Event handler for the RX state
|
||||||
|
*
|
||||||
|
**********************************************************/
|
||||||
|
static void tftp_rx(tftp_state_data_t *state, tftp_event_t event)
|
||||||
|
{
|
||||||
|
int sbytes;
|
||||||
|
int rblock;
|
||||||
|
struct SessionHandle *data = state->conn->data;
|
||||||
|
|
||||||
|
switch(event) {
|
||||||
|
|
||||||
|
case TFTP_EVENT_DATA:
|
||||||
|
|
||||||
|
/* Is this the block we expect? */
|
||||||
|
rblock = ntohs(state->rpacket.u.data.block);
|
||||||
|
if ((state->block+1) != rblock) {
|
||||||
|
/* No, log it, up the retry count and fail if over the limit */
|
||||||
|
infof(data,
|
||||||
|
"Received unexpected DATA packet block %d\n", rblock);
|
||||||
|
state->retries++;
|
||||||
|
if (state->retries>state->retry_max) {
|
||||||
|
failf(data, "tftp_rx: giving up waiting for block %d\n",
|
||||||
|
state->block+1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* This is the expected block. Reset counters and ACK it. */
|
||||||
|
state->block = rblock;
|
||||||
|
state->retries = 0;
|
||||||
|
state->spacket.event = htons(TFTP_EVENT_ACK);
|
||||||
|
state->spacket.u.ack.block = htons(state->block);
|
||||||
|
sbytes = sendto(state->sockfd, &state->spacket, 4, MSG_NOSIGNAL,
|
||||||
|
&state->remote_addr, state->remote_addrlen);
|
||||||
|
if(sbytes < 0) {
|
||||||
|
failf(data, "%s\n", strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if completed (That is, a less than full packet is recieved) */
|
||||||
|
if (state->rbytes < (int)sizeof(state->spacket)){
|
||||||
|
state->state = TFTP_STATE_FIN;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
state->state = TFTP_STATE_RX;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TFTP_EVENT_TIMEOUT:
|
||||||
|
/* Increment the retry count and fail if over the limit */
|
||||||
|
state->retries++;
|
||||||
|
infof(data,
|
||||||
|
"Timeout waiting for block %d ACK. Retries = %d\n", state->retries);
|
||||||
|
if(state->retries > state->retry_max) {
|
||||||
|
state->error = TFTP_ERR_TIMEOUT;
|
||||||
|
state->state = TFTP_STATE_FIN;
|
||||||
|
} else {
|
||||||
|
/* Resend the previous ACK */
|
||||||
|
sbytes = sendto(state->sockfd, &state->spacket,
|
||||||
|
4, MSG_NOSIGNAL,
|
||||||
|
&state->remote_addr, state->remote_addrlen);
|
||||||
|
/* Check all sbytes were sent */
|
||||||
|
if(sbytes<0) {
|
||||||
|
failf(data, "%s\n", strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TFTP_EVENT_ERROR:
|
||||||
|
state->state = TFTP_STATE_FIN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
failf(data, "%s\n", "tftp_rx: internal error");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Curl_pgrsSetDownloadCounter(data,
|
||||||
|
(curl_off_t) state->block*512);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************
|
||||||
|
*
|
||||||
|
* tftp_tx
|
||||||
|
*
|
||||||
|
* Event handler for the TX state
|
||||||
|
*
|
||||||
|
**********************************************************/
|
||||||
|
static void tftp_tx(tftp_state_data_t *state, tftp_event_t event)
|
||||||
|
{
|
||||||
|
struct SessionHandle *data = state->conn->data;
|
||||||
|
int sbytes;
|
||||||
|
int rblock;
|
||||||
|
|
||||||
|
switch(event) {
|
||||||
|
|
||||||
|
case TFTP_EVENT_ACK:
|
||||||
|
/* Ack the packet */
|
||||||
|
rblock = ntohs(state->rpacket.u.data.block);
|
||||||
|
|
||||||
|
if(rblock != state->block) {
|
||||||
|
/* This isn't the expected block. Log it and up the retry counter */
|
||||||
|
infof(data, "Received ACK for block %d, expecting %d\n",
|
||||||
|
rblock, state->block);
|
||||||
|
state->retries++;
|
||||||
|
/* Bail out if over the maximum */
|
||||||
|
if(state->retries>state->retry_max) {
|
||||||
|
failf(data, "%s\n",
|
||||||
|
"tftp_tx: giving up waiting for block %d ack",
|
||||||
|
state->block);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* This is the expected packet. Reset the counters and send the next
|
||||||
|
block */
|
||||||
|
state->block++;
|
||||||
|
state->retries = 0;
|
||||||
|
state->spacket.event = htons(TFTP_EVENT_DATA);
|
||||||
|
state->spacket.u.ack.block = htons(state->block);
|
||||||
|
if(state->block > 1 && state->sbytes < 512) {
|
||||||
|
state->state = TFTP_STATE_FIN;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Curl_fillreadbuffer(state->conn, 512, &state->sbytes);
|
||||||
|
sbytes = sendto(state->sockfd, &state->spacket,
|
||||||
|
4+state->sbytes, MSG_NOSIGNAL,
|
||||||
|
&state->remote_addr, state->remote_addrlen);
|
||||||
|
/* Check all sbytes were sent */
|
||||||
|
if(sbytes<0) {
|
||||||
|
failf(data, "%s\n", strerror(errno));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TFTP_EVENT_TIMEOUT:
|
||||||
|
/* Increment the retry counter and log the timeout */
|
||||||
|
state->retries++;
|
||||||
|
infof(data, "Timeout waiting for block %d ACK. "
|
||||||
|
" Retries = %d\n", state->retries);
|
||||||
|
/* Decide if we've had enough */
|
||||||
|
if(state->retries > state->retry_max) {
|
||||||
|
state->error = TFTP_ERR_TIMEOUT;
|
||||||
|
state->state = TFTP_STATE_FIN;
|
||||||
|
} else {
|
||||||
|
/* Re-send the data packet */
|
||||||
|
sbytes = sendto(state->sockfd, &state->spacket,
|
||||||
|
4+state->sbytes, MSG_NOSIGNAL,
|
||||||
|
&state->remote_addr, state->remote_addrlen);
|
||||||
|
/* Check all sbytes were sent */
|
||||||
|
if(sbytes<0) {
|
||||||
|
failf(data, "%s\n", strerror(errno));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TFTP_EVENT_ERROR:
|
||||||
|
state->state = TFTP_STATE_FIN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
failf(data, "%s\n", "tftp_tx: internal error");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the progress meter */
|
||||||
|
Curl_pgrsSetUploadCounter(data, (curl_off_t) state->block*512);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************
|
||||||
|
*
|
||||||
|
* tftp_state_machine
|
||||||
|
*
|
||||||
|
* The tftp state machine event dispatcher
|
||||||
|
*
|
||||||
|
**********************************************************/
|
||||||
|
static CURLcode tftp_state_machine(tftp_state_data_t *state,
|
||||||
|
tftp_event_t event)
|
||||||
|
{
|
||||||
|
struct SessionHandle *data = state->conn->data;
|
||||||
|
switch(state->state) {
|
||||||
|
case TFTP_STATE_START:
|
||||||
|
DEBUGF(infof(data, "TFTP_STATE_START\n"));
|
||||||
|
tftp_send_first(state, event);
|
||||||
|
break;
|
||||||
|
case TFTP_STATE_RX:
|
||||||
|
DEBUGF(infof(data, "TFTP_STATE_RX\n"));
|
||||||
|
tftp_rx(state, event);
|
||||||
|
break;
|
||||||
|
case TFTP_STATE_TX:
|
||||||
|
DEBUGF(infof(data, "TFTP_STATE_TX\n"));
|
||||||
|
tftp_tx(state, event);
|
||||||
|
break;
|
||||||
|
case TFTP_STATE_FIN:
|
||||||
|
infof(data, "%s\n", "TFTP finished");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DEBUGF(infof(data, "STATE: %d\n", state->state));
|
||||||
|
failf(data, "%s\n", "Internal state machine error");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************
|
||||||
|
*
|
||||||
|
* Curl_tftp_connect
|
||||||
|
*
|
||||||
|
* The connect callback
|
||||||
|
*
|
||||||
|
**********************************************************/
|
||||||
|
CURLcode Curl_tftp_connect(struct connectdata *conn, bool *done)
|
||||||
|
{
|
||||||
|
CURLcode code;
|
||||||
|
tftp_state_data_t *state;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if((state = conn->proto.tftp = calloc(sizeof(tftp_state_data_t), 1))==NULL) {
|
||||||
|
return CURLE_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
state->conn = conn;
|
||||||
|
state->sockfd = state->conn->sock[FIRSTSOCKET];
|
||||||
|
state->state = TFTP_STATE_START;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
/* AF_UNSPEC == 0 (from above calloc) doesn't work on Winsock */
|
||||||
|
state->local_addr.sa_family = conn->ip_addr->ai_family;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
tftp_set_timeouts(state);
|
||||||
|
|
||||||
|
/* Bind to any interface, random UDP port */
|
||||||
|
rc = bind(state->sockfd, &state->local_addr, sizeof(state->local_addr));
|
||||||
|
if(rc) {
|
||||||
|
failf(conn->data, "bind() failed; %s\n",
|
||||||
|
Curl_strerror(conn,Curl_ourerrno()));
|
||||||
|
return CURLE_COULDNT_CONNECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
Curl_pgrsStartNow(conn->data);
|
||||||
|
|
||||||
|
*done = TRUE;
|
||||||
|
code = CURLE_OK;
|
||||||
|
return(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**********************************************************
|
||||||
|
*
|
||||||
|
* Curl_tftp_done
|
||||||
|
*
|
||||||
|
* The done callback
|
||||||
|
*
|
||||||
|
**********************************************************/
|
||||||
|
CURLcode Curl_tftp_done(struct connectdata *conn, CURLcode status)
|
||||||
|
{
|
||||||
|
(void)status; /* unused */
|
||||||
|
|
||||||
|
free(conn->proto.tftp);
|
||||||
|
conn->proto.tftp = NULL;
|
||||||
|
Curl_pgrsDone(conn);
|
||||||
|
|
||||||
|
return CURLE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************
|
||||||
|
*
|
||||||
|
* Curl_tftp
|
||||||
|
*
|
||||||
|
* The do callback
|
||||||
|
*
|
||||||
|
* This callback handles the entire TFTP transfer
|
||||||
|
*
|
||||||
|
**********************************************************/
|
||||||
|
|
||||||
|
CURLcode Curl_tftp(struct connectdata *conn, bool *done)
|
||||||
|
{
|
||||||
|
struct SessionHandle *data = conn->data;
|
||||||
|
tftp_state_data_t *state = (tftp_state_data_t *)(conn->proto.tftp);
|
||||||
|
tftp_event_t event;
|
||||||
|
CURLcode code;
|
||||||
|
int rc;
|
||||||
|
struct sockaddr fromaddr;
|
||||||
|
socklen_t fromlen;
|
||||||
|
int check_time = 0;
|
||||||
|
|
||||||
|
(void)done; /* prevent compiler warning */
|
||||||
|
|
||||||
|
/* Run the TFTP State Machine */
|
||||||
|
for(tftp_state_machine(state, TFTP_EVENT_INIT);
|
||||||
|
state->state != TFTP_STATE_FIN;
|
||||||
|
tftp_state_machine(state, event) ) {
|
||||||
|
|
||||||
|
/* Wait until ready to read or timeout occurs */
|
||||||
|
rc=Curl_select(state->sockfd, CURL_SOCKET_BAD, state->retry_time * 1000);
|
||||||
|
|
||||||
|
if(rc == -1) {
|
||||||
|
/* bail out */
|
||||||
|
int error = Curl_ourerrno();
|
||||||
|
failf(data, "%s\n", Curl_strerror(conn, error));
|
||||||
|
event = TFTP_EVENT_ERROR;
|
||||||
|
}
|
||||||
|
else if (rc==0) {
|
||||||
|
/* A timeout occured */
|
||||||
|
event = TFTP_EVENT_TIMEOUT;
|
||||||
|
|
||||||
|
/* Force a look at transfer timeouts */
|
||||||
|
check_time = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
/* Receive the packet */
|
||||||
|
fromlen=sizeof(fromaddr);
|
||||||
|
state->rbytes = recvfrom(state->sockfd,
|
||||||
|
(void *)&state->rpacket, sizeof(state->rpacket),
|
||||||
|
0, &fromaddr, &fromlen);
|
||||||
|
if(state->remote_addrlen==0) {
|
||||||
|
memcpy(&state->remote_addr, &fromaddr, fromlen);
|
||||||
|
state->remote_addrlen = fromlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The event is given by the TFTP packet time */
|
||||||
|
event = (tftp_event_t)ntohs(state->rpacket.event);
|
||||||
|
|
||||||
|
switch(event) {
|
||||||
|
case TFTP_EVENT_DATA:
|
||||||
|
Curl_client_write(data, CLIENTWRITE_BODY,
|
||||||
|
(char *)state->rpacket.u.data.data, state->rbytes-4);
|
||||||
|
break;
|
||||||
|
case TFTP_EVENT_ERROR:
|
||||||
|
state->error = (tftp_error_t)ntohs(state->rpacket.u.error.code);
|
||||||
|
infof(conn->data, "%s\n", (char *)state->rpacket.u.error.data);
|
||||||
|
break;
|
||||||
|
case TFTP_EVENT_ACK:
|
||||||
|
break;
|
||||||
|
case TFTP_EVENT_RRQ:
|
||||||
|
case TFTP_EVENT_WRQ:
|
||||||
|
default:
|
||||||
|
failf(conn->data, "%s\n", "Internal error: Unexpected packet");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update the progress meter */
|
||||||
|
Curl_pgrsUpdate(conn);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for transfer timeout every 10 blocks, or after timeout */
|
||||||
|
if(check_time%10==0) {
|
||||||
|
time_t current;
|
||||||
|
time(¤t);
|
||||||
|
if(current>state->max_time) {
|
||||||
|
DEBUGF(infof(data, "timeout: %d > %d\n",
|
||||||
|
current, state->max_time));
|
||||||
|
state->error = TFTP_ERR_TIMEOUT;
|
||||||
|
state->state = TFTP_STATE_FIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tell curl we're done */
|
||||||
|
Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
|
||||||
|
|
||||||
|
/* If we have encountered an error */
|
||||||
|
if(state->error) {
|
||||||
|
|
||||||
|
/* Translate internal error codes to curl error codes */
|
||||||
|
switch(state->error) {
|
||||||
|
case TFTP_ERR_NOTFOUND:
|
||||||
|
code = CURLE_TFTP_NOTFOUND;
|
||||||
|
break;
|
||||||
|
case TFTP_ERR_PERM:
|
||||||
|
code = CURLE_TFTP_PERM;
|
||||||
|
break;
|
||||||
|
case TFTP_ERR_DISKFULL:
|
||||||
|
code = CURLE_TFTP_DISKFULL;
|
||||||
|
break;
|
||||||
|
case TFTP_ERR_ILLEGAL:
|
||||||
|
code = CURLE_TFTP_ILLEGAL;
|
||||||
|
break;
|
||||||
|
case TFTP_ERR_UNKNOWNID:
|
||||||
|
code = CURLE_TFTP_UNKNOWNID;
|
||||||
|
break;
|
||||||
|
case TFTP_ERR_EXISTS:
|
||||||
|
code = CURLE_TFTP_EXISTS;
|
||||||
|
break;
|
||||||
|
case TFTP_ERR_NOSUCHUSER:
|
||||||
|
code = CURLE_TFTP_NOSUCHUSER;
|
||||||
|
break;
|
||||||
|
case TFTP_ERR_TIMEOUT:
|
||||||
|
code = CURLE_OPERATION_TIMEOUTED;
|
||||||
|
break;
|
||||||
|
case TFTP_ERR_NORESPONSE:
|
||||||
|
code = CURLE_COULDNT_CONNECT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
code= CURLE_ABORTED_BY_CALLBACK;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
code = CURLE_OK;
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
#endif
|
31
lib/tftp.h
Normal file
31
lib/tftp.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#ifndef __TFTP_H
|
||||||
|
#define __TFTP_H
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* Copyright (C) 1998 - 2005, 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
|
||||||
|
* are also available at http://curl.haxx.se/docs/copyright.html.
|
||||||
|
*
|
||||||
|
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
||||||
|
* copies of the Software, and permit persons to whom the Software is
|
||||||
|
* furnished to do so, under the terms of the COPYING file.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
***************************************************************************/
|
||||||
|
#ifndef CURL_DISABLE_TFTP
|
||||||
|
CURLcode Curl_tftp_connect(struct connectdata *conn, bool *done);
|
||||||
|
CURLcode Curl_tftp(struct connectdata *conn, bool *done);
|
||||||
|
CURLcode Curl_tftp_done(struct connectdata *conn, CURLcode);
|
||||||
|
#endif
|
||||||
|
#endif
|
@@ -880,11 +880,11 @@ CURLcode Curl_readwrite(struct connectdata *conn,
|
|||||||
/* Content-Range: bytes [num]-
|
/* Content-Range: bytes [num]-
|
||||||
Content-Range: bytes: [num]-
|
Content-Range: bytes: [num]-
|
||||||
|
|
||||||
The second format was added August 1st 2000 by Igor
|
The second format was added since Sun's webserver
|
||||||
Khristophorov since Sun's webserver JavaWebServer/1.1.1
|
JavaWebServer/1.1.1 obviously sends the header this way!
|
||||||
obviously sends the header this way! :-( */
|
*/
|
||||||
|
|
||||||
char *ptr = strstr(k->p, "bytes");
|
char *ptr = Curl_strcasestr(k->p, "bytes");
|
||||||
ptr+=5;
|
ptr+=5;
|
||||||
|
|
||||||
if(*ptr == ':')
|
if(*ptr == ':')
|
||||||
@@ -1622,9 +1622,11 @@ Transfer(struct connectdata *conn)
|
|||||||
CURLcode Curl_pretransfer(struct SessionHandle *data)
|
CURLcode Curl_pretransfer(struct SessionHandle *data)
|
||||||
{
|
{
|
||||||
CURLcode res;
|
CURLcode res;
|
||||||
if(!data->change.url)
|
if(!data->change.url) {
|
||||||
/* we can't do anything wihout URL */
|
/* we can't do anything wihout URL */
|
||||||
|
failf(data, "No URL set!\n");
|
||||||
return CURLE_URL_MALFORMAT;
|
return CURLE_URL_MALFORMAT;
|
||||||
|
}
|
||||||
|
|
||||||
/* Init the SSL session ID cache here. We do it here since we want to do it
|
/* Init the SSL session ID cache here. We do it here since we want to do it
|
||||||
after the *_setopt() calls (that could change the size of the cache) but
|
after the *_setopt() calls (that could change the size of the cache) but
|
||||||
|
56
lib/url.c
56
lib/url.c
@@ -77,9 +77,7 @@
|
|||||||
#error "We can't compile without socket() support!"
|
#error "We can't compile without socket() support!"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_LIBIDN
|
#ifdef USE_LIBIDN
|
||||||
#include <idna.h>
|
#include <idna.h>
|
||||||
#include <tld.h>
|
#include <tld.h>
|
||||||
@@ -123,6 +121,7 @@ void idn_free (void *ptr); /* prototype from idn-free.h, not provided by
|
|||||||
#include "ftp.h"
|
#include "ftp.h"
|
||||||
#include "dict.h"
|
#include "dict.h"
|
||||||
#include "telnet.h"
|
#include "telnet.h"
|
||||||
|
#include "tftp.h"
|
||||||
#include "http.h"
|
#include "http.h"
|
||||||
#include "file.h"
|
#include "file.h"
|
||||||
#include "ldap.h"
|
#include "ldap.h"
|
||||||
@@ -966,6 +965,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||||||
data->set.ftp_use_epsv = va_arg(param, long)?TRUE:FALSE;
|
data->set.ftp_use_epsv = va_arg(param, long)?TRUE:FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CURLOPT_FTP_SKIP_PASV_IP:
|
||||||
|
/*
|
||||||
|
* Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
|
||||||
|
* bypass of the IP address in PASV responses.
|
||||||
|
*/
|
||||||
|
data->set.ftp_skip_ip = (bool)va_arg(param, long);
|
||||||
|
break;
|
||||||
|
|
||||||
case CURLOPT_INFILE:
|
case CURLOPT_INFILE:
|
||||||
/*
|
/*
|
||||||
* FILE pointer to read the file to be uploaded from. Or possibly
|
* FILE pointer to read the file to be uploaded from. Or possibly
|
||||||
@@ -1241,7 +1248,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
|
|||||||
/*
|
/*
|
||||||
* Set a SSL_CTX callback
|
* Set a SSL_CTX callback
|
||||||
*/
|
*/
|
||||||
data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
|
data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
|
||||||
break;
|
break;
|
||||||
case CURLOPT_SSL_CTX_DATA:
|
case CURLOPT_SSL_CTX_DATA:
|
||||||
/*
|
/*
|
||||||
@@ -1994,7 +2001,8 @@ static CURLcode ConnectPlease(struct connectdata *conn,
|
|||||||
struct SessionHandle *data = conn->data;
|
struct SessionHandle *data = conn->data;
|
||||||
char *hostname = data->change.proxy?conn->proxy.name:conn->host.name;
|
char *hostname = data->change.proxy?conn->proxy.name:conn->host.name;
|
||||||
|
|
||||||
infof(data, "About to connect() to %s port %d\n",
|
infof(data, "About to connect() to %s%s port %d\n",
|
||||||
|
data->change.proxy?"proxy ":"",
|
||||||
hostname, conn->port);
|
hostname, conn->port);
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
@@ -2722,6 +2730,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
* Setup internals depending on protocol
|
* Setup internals depending on protocol
|
||||||
*************************************************************/
|
*************************************************************/
|
||||||
|
|
||||||
|
conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
|
||||||
|
|
||||||
if (strequal(conn->protostr, "HTTP")) {
|
if (strequal(conn->protostr, "HTTP")) {
|
||||||
#ifndef CURL_DISABLE_HTTP
|
#ifndef CURL_DISABLE_HTTP
|
||||||
conn->port = PORT_HTTP;
|
conn->port = PORT_HTTP;
|
||||||
@@ -2915,6 +2925,44 @@ static CURLcode CreateConnection(struct SessionHandle *data,
|
|||||||
#else
|
#else
|
||||||
failf(data, LIBCURL_NAME
|
failf(data, LIBCURL_NAME
|
||||||
" was built with FILE disabled!");
|
" was built with FILE disabled!");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (strequal(conn->protostr, "TFTP")) {
|
||||||
|
#ifndef CURL_DISABLE_TFTP
|
||||||
|
char *type;
|
||||||
|
conn->socktype = SOCK_DGRAM; /* UDP datagram based */
|
||||||
|
conn->protocol |= PROT_TFTP;
|
||||||
|
conn->port = PORT_TFTP;
|
||||||
|
conn->remote_port = PORT_TFTP;
|
||||||
|
conn->curl_connect = Curl_tftp_connect;
|
||||||
|
conn->curl_do = Curl_tftp;
|
||||||
|
conn->curl_done = Curl_tftp_done;
|
||||||
|
/* TFTP URLs support an extension like ";mode=<typecode>" that
|
||||||
|
* we'll try to get now! */
|
||||||
|
type=strstr(conn->path, ";mode=");
|
||||||
|
if(!type) {
|
||||||
|
type=strstr(conn->host.rawalloc, ";mode=");
|
||||||
|
}
|
||||||
|
if(type) {
|
||||||
|
char command;
|
||||||
|
*type=0; /* it was in the middle of the hostname */
|
||||||
|
command = toupper((int)type[6]);
|
||||||
|
switch(command) {
|
||||||
|
case 'A': /* ASCII mode */
|
||||||
|
case 'N': /* NETASCII mode */
|
||||||
|
data->set.ftp_ascii = 1;
|
||||||
|
break;
|
||||||
|
case 'O': /* octet mode */
|
||||||
|
case 'I': /* binary mode */
|
||||||
|
default:
|
||||||
|
/* switch off ASCII */
|
||||||
|
data->set.ftp_ascii = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
failf(data, LIBCURL_NAME
|
||||||
|
" was built with TFTP disabled!");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
#define PORT_HTTPS 443
|
#define PORT_HTTPS 443
|
||||||
#define PORT_DICT 2628
|
#define PORT_DICT 2628
|
||||||
#define PORT_LDAP 389
|
#define PORT_LDAP 389
|
||||||
|
#define PORT_TFTP 69
|
||||||
|
|
||||||
#define DICT_MATCH "/MATCH:"
|
#define DICT_MATCH "/MATCH:"
|
||||||
#define DICT_MATCH2 "/M:"
|
#define DICT_MATCH2 "/M:"
|
||||||
@@ -540,6 +541,7 @@ struct connectdata {
|
|||||||
#define PROT_DICT (1<<6)
|
#define PROT_DICT (1<<6)
|
||||||
#define PROT_LDAP (1<<7)
|
#define PROT_LDAP (1<<7)
|
||||||
#define PROT_FILE (1<<8)
|
#define PROT_FILE (1<<8)
|
||||||
|
#define PROT_TFTP (1<<11)
|
||||||
#define PROT_FTPS (1<<9)
|
#define PROT_FTPS (1<<9)
|
||||||
#define PROT_SSL (1<<10) /* protocol requires SSL */
|
#define PROT_SSL (1<<10) /* protocol requires SSL */
|
||||||
|
|
||||||
@@ -560,6 +562,7 @@ struct connectdata {
|
|||||||
char *ip_addr_str;
|
char *ip_addr_str;
|
||||||
|
|
||||||
char protostr[16]; /* store the protocol string in this buffer */
|
char protostr[16]; /* store the protocol string in this buffer */
|
||||||
|
int socktype; /* SOCK_STREAM or SOCK_DGRAM */
|
||||||
|
|
||||||
struct hostname host;
|
struct hostname host;
|
||||||
struct hostname proxy;
|
struct hostname proxy;
|
||||||
@@ -695,6 +698,7 @@ struct connectdata {
|
|||||||
struct HTTP *gopher; /* alias, just for the sake of being more readable */
|
struct HTTP *gopher; /* alias, just for the sake of being more readable */
|
||||||
struct HTTP *https; /* alias, just for the sake of being more readable */
|
struct HTTP *https; /* alias, just for the sake of being more readable */
|
||||||
struct FTP *ftp;
|
struct FTP *ftp;
|
||||||
|
void *tftp; /* private for tftp.c-eyes only */
|
||||||
struct FILEPROTO *file;
|
struct FILEPROTO *file;
|
||||||
void *telnet; /* private for telnet.c-eyes only */
|
void *telnet; /* private for telnet.c-eyes only */
|
||||||
void *generic;
|
void *generic;
|
||||||
@@ -1069,8 +1073,9 @@ struct UserDefined {
|
|||||||
bool no_signal; /* do not use any signal/alarm handler */
|
bool no_signal; /* do not use any signal/alarm handler */
|
||||||
bool global_dns_cache; /* subject for future removal */
|
bool global_dns_cache; /* subject for future removal */
|
||||||
bool tcp_nodelay; /* whether to enable TCP_NODELAY or not */
|
bool tcp_nodelay; /* whether to enable TCP_NODELAY or not */
|
||||||
|
|
||||||
bool ignorecl; /* ignore content length */
|
bool ignorecl; /* ignore content length */
|
||||||
|
bool ftp_skip_ip; /* skip the IP address the FTP server passes on to
|
||||||
|
us */
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -81,6 +81,9 @@ char *curl_version(void)
|
|||||||
/* data for curl_version_info */
|
/* data for curl_version_info */
|
||||||
|
|
||||||
static const char * const protocols[] = {
|
static const char * const protocols[] = {
|
||||||
|
#ifndef CURL_DISABLE_TFTP
|
||||||
|
"tftp",
|
||||||
|
#endif
|
||||||
#ifndef CURL_DISABLE_FTP
|
#ifndef CURL_DISABLE_FTP
|
||||||
"ftp",
|
"ftp",
|
||||||
#endif
|
#endif
|
||||||
|
1
maketgz
1
maketgz
@@ -25,7 +25,6 @@ CHEADER=src/version.h
|
|||||||
|
|
||||||
# Replace version number in header file:
|
# Replace version number in header file:
|
||||||
sed -e 's/^#define LIBCURL_VERSION .*/#define LIBCURL_VERSION "'$libversion'"/g' \
|
sed -e 's/^#define LIBCURL_VERSION .*/#define LIBCURL_VERSION "'$libversion'"/g' \
|
||||||
-e 's/^#define LIBCURL_VERSION_NUM .*/#define LIBCURL_VERSION_NUM 0x'$numeric'/g' \
|
|
||||||
-e 's/^#define LIBCURL_VERSION_MAJOR .*/#define LIBCURL_VERSION_MAJOR '$major'/g' \
|
-e 's/^#define LIBCURL_VERSION_MAJOR .*/#define LIBCURL_VERSION_MAJOR '$major'/g' \
|
||||||
-e 's/^#define LIBCURL_VERSION_MINOR .*/#define LIBCURL_VERSION_MINOR '$minor'/g' \
|
-e 's/^#define LIBCURL_VERSION_MINOR .*/#define LIBCURL_VERSION_MINOR '$minor'/g' \
|
||||||
-e 's/^#define LIBCURL_VERSION_PATCH .*/#define LIBCURL_VERSION_PATCH '$patch'/g' \
|
-e 's/^#define LIBCURL_VERSION_PATCH .*/#define LIBCURL_VERSION_PATCH '$patch'/g' \
|
||||||
|
@@ -283,7 +283,7 @@ config.h: Makefile.netware
|
|||||||
@echo $(DL)*/$(DL) >> $@
|
@echo $(DL)*/$(DL) >> $@
|
||||||
@echo $(DL)#define OS "i586-pc-NetWare"$(DL) >> $@
|
@echo $(DL)#define OS "i586-pc-NetWare"$(DL) >> $@
|
||||||
@echo $(DL)#define VERSION "$(LIBCURL_VERSION_STR)"$(DL) >> $@
|
@echo $(DL)#define VERSION "$(LIBCURL_VERSION_STR)"$(DL) >> $@
|
||||||
@echo $(DL)#define PACKAGE_BUGREPORT "curl-bug@haxx.se"$(DL) >> $@
|
@echo $(DL)#define PACKAGE_BUGREPORT "a suitable curl mailing list => http://curl.haxx.se/mail/"$(DL) >> $@
|
||||||
@echo $(DL)#define USE_MANUAL 1$(DL) >> $@
|
@echo $(DL)#define USE_MANUAL 1$(DL) >> $@
|
||||||
@echo $(DL)#define HAVE_ARPA_INET_H 1$(DL) >> $@
|
@echo $(DL)#define HAVE_ARPA_INET_H 1$(DL) >> $@
|
||||||
@echo $(DL)#define HAVE_ASSERT_H 1$(DL) >> $@
|
@echo $(DL)#define HAVE_ASSERT_H 1$(DL) >> $@
|
||||||
|
18
src/main.c
18
src/main.c
@@ -315,6 +315,7 @@ struct Configurable {
|
|||||||
bool insecure_ok; /* set TRUE to allow insecure SSL connects */
|
bool insecure_ok; /* set TRUE to allow insecure SSL connects */
|
||||||
bool create_dirs;
|
bool create_dirs;
|
||||||
bool ftp_create_dirs;
|
bool ftp_create_dirs;
|
||||||
|
bool ftp_skip_ip;
|
||||||
bool proxyntlm;
|
bool proxyntlm;
|
||||||
bool proxydigest;
|
bool proxydigest;
|
||||||
bool proxybasic;
|
bool proxybasic;
|
||||||
@@ -508,7 +509,8 @@ static void help(void)
|
|||||||
" --crlf Convert LF to CRLF in upload",
|
" --crlf Convert LF to CRLF in upload",
|
||||||
" -f/--fail Fail silently (no output at all) on errors (H)",
|
" -f/--fail Fail silently (no output at all) on errors (H)",
|
||||||
" --ftp-create-dirs Create the remote dirs if not present (F)",
|
" --ftp-create-dirs Create the remote dirs if not present (F)",
|
||||||
" --ftp-pasv Use PASV instead of PORT (F)",
|
" --ftp-pasv Use PASV/EPSV instead of PORT (F)",
|
||||||
|
" --ftp-skip-pasv-ip Skip the IP address for PASV (F)\n"
|
||||||
" --ftp-ssl Enable SSL/TLS for the ftp transfer (F)",
|
" --ftp-ssl Enable SSL/TLS for the ftp transfer (F)",
|
||||||
" -F/--form <name=content> Specify HTTP multipart POST data (H)",
|
" -F/--form <name=content> Specify HTTP multipart POST data (H)",
|
||||||
" --form-string <name=string> Specify HTTP multipart POST data (H)",
|
" --form-string <name=string> Specify HTTP multipart POST data (H)",
|
||||||
@@ -1313,6 +1315,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
{"$n", "proxy-anyauth", FALSE},
|
{"$n", "proxy-anyauth", FALSE},
|
||||||
{"$o", "trace-time", FALSE},
|
{"$o", "trace-time", FALSE},
|
||||||
{"$p", "ignore-content-length", FALSE},
|
{"$p", "ignore-content-length", FALSE},
|
||||||
|
{"$q", "ftp-skip-pasv-ip", FALSE},
|
||||||
|
|
||||||
{"0", "http1.0", FALSE},
|
{"0", "http1.0", FALSE},
|
||||||
{"1", "tlsv1", FALSE},
|
{"1", "tlsv1", FALSE},
|
||||||
@@ -1709,6 +1712,9 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
|
|||||||
case 'p': /* --ignore-content-length */
|
case 'p': /* --ignore-content-length */
|
||||||
config->ignorecl ^= TRUE;
|
config->ignorecl ^= TRUE;
|
||||||
break;
|
break;
|
||||||
|
case 'q': /* --ftp-skip-pasv-ip */
|
||||||
|
config->ftp_skip_ip ^= TRUE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '#': /* --progress-bar */
|
case '#': /* --progress-bar */
|
||||||
@@ -3905,6 +3911,10 @@ operate(struct Configurable *config, int argc, char *argv[])
|
|||||||
|
|
||||||
curl_easy_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl);
|
curl_easy_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl);
|
||||||
|
|
||||||
|
/* curl 7.14.2 */
|
||||||
|
curl_easy_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP,
|
||||||
|
config->ftp_skip_ip);
|
||||||
|
|
||||||
retry_numretries = config->req_retry;
|
retry_numretries = config->req_retry;
|
||||||
|
|
||||||
retrystart = curlx_tvnow();
|
retrystart = curlx_tvnow();
|
||||||
@@ -4149,15 +4159,15 @@ quit_curl:
|
|||||||
if (config->engine)
|
if (config->engine)
|
||||||
free(config->engine);
|
free(config->engine);
|
||||||
|
|
||||||
|
/* cleanup the curl handle! */
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
|
||||||
if(config->headerfile && !headerfilep && heads.stream)
|
if(config->headerfile && !headerfilep && heads.stream)
|
||||||
fclose(heads.stream);
|
fclose(heads.stream);
|
||||||
|
|
||||||
if(allocuseragent)
|
if(allocuseragent)
|
||||||
free(config->useragent);
|
free(config->useragent);
|
||||||
|
|
||||||
/* cleanup the curl handle! */
|
|
||||||
curl_easy_cleanup(curl);
|
|
||||||
|
|
||||||
if(config->trace_fopened && config->trace_stream)
|
if(config->trace_fopened && config->trace_stream)
|
||||||
fclose(config->trace_stream);
|
fclose(config->trace_stream);
|
||||||
|
|
||||||
|
@@ -5,7 +5,7 @@
|
|||||||
* | (__| |_| | _ <| |___
|
* | (__| |_| | _ <| |___
|
||||||
* \___|\___/|_| \_\_____|
|
* \___|\___/|_| \_\_____|
|
||||||
*
|
*
|
||||||
* Copyright (C) 1998 - 2004, Daniel Stenberg, <daniel@haxx.se>, et al.
|
* Copyright (C) 1998 - 2005, Daniel Stenberg, <daniel@haxx.se>, et al.
|
||||||
*
|
*
|
||||||
* This software is licensed as described in the file COPYING, which
|
* This software is licensed as described in the file COPYING, which
|
||||||
* you should have received as part of this distribution. The terms
|
* you should have received as part of this distribution. The terms
|
||||||
@@ -112,11 +112,13 @@ void ourWriteOut(CURL *curl, char *writeinfo)
|
|||||||
char keepit;
|
char keepit;
|
||||||
int i;
|
int i;
|
||||||
if(('{' == ptr[1]) && (end=strchr(ptr, '}'))) {
|
if(('{' == ptr[1]) && (end=strchr(ptr, '}'))) {
|
||||||
|
bool match = FALSE;
|
||||||
ptr+=2; /* pass the % and the { */
|
ptr+=2; /* pass the % and the { */
|
||||||
keepit=*end;
|
keepit=*end;
|
||||||
*end=0; /* zero terminate */
|
*end=0; /* zero terminate */
|
||||||
for(i=0; replacements[i].name; i++) {
|
for(i=0; replacements[i].name; i++) {
|
||||||
if(curl_strequal(ptr, replacements[i].name)) {
|
if(curl_strequal(ptr, replacements[i].name)) {
|
||||||
|
match = TRUE;
|
||||||
switch(replacements[i].id) {
|
switch(replacements[i].id) {
|
||||||
case VAR_EFFECTIVE_URL:
|
case VAR_EFFECTIVE_URL:
|
||||||
if((CURLE_OK ==
|
if((CURLE_OK ==
|
||||||
@@ -217,6 +219,9 @@ void ourWriteOut(CURL *curl, char *writeinfo)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(!match) {
|
||||||
|
fprintf(stderr, "curl: unknown --writeout variable: '%s'\n", ptr);
|
||||||
|
}
|
||||||
ptr=end+1; /* pass the end */
|
ptr=end+1; /* pass the end */
|
||||||
*end = keepit;
|
*end = keepit;
|
||||||
}
|
}
|
||||||
|
@@ -81,6 +81,7 @@ RETRWEIRDO
|
|||||||
RETRNOSIZE
|
RETRNOSIZE
|
||||||
NOSAVE
|
NOSAVE
|
||||||
SLOWDOWN
|
SLOWDOWN
|
||||||
|
PASVBADIP - makes PASV send back an illegal IP in its 227 response
|
||||||
|
|
||||||
For HTTP, one specified command is supported:
|
For HTTP, one specified command is supported:
|
||||||
"auth_required" - if this is set and a POST/PUT is made without auth, the
|
"auth_required" - if this is set and a POST/PUT is made without auth, the
|
||||||
|
@@ -33,4 +33,4 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \
|
|||||||
test237 test238 test239 test243 test245 test246 test247 test248 test249 \
|
test237 test238 test239 test243 test245 test246 test247 test248 test249 \
|
||||||
test250 test251 test252 test253 test254 test255 test521 test522 test523 \
|
test250 test251 test252 test253 test254 test255 test521 test522 test523 \
|
||||||
test256 test257 test258 test259 test260 test261 test262 test263 test264 \
|
test256 test257 test258 test259 test260 test261 test262 test263 test264 \
|
||||||
test265 test266 test267 test268 test269
|
test265 test266 test267 test268 test269 test270 test271 test272
|
||||||
|
48
tests/data/test270
Normal file
48
tests/data/test270
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
FTP
|
||||||
|
PASV
|
||||||
|
RETR
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data>
|
||||||
|
data
|
||||||
|
to
|
||||||
|
see
|
||||||
|
that FTP
|
||||||
|
works
|
||||||
|
so does it?
|
||||||
|
</data>
|
||||||
|
<servercmd>
|
||||||
|
PASVBADIP
|
||||||
|
</servercmd>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
ftp
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
FTP RETR PASV --ftp-skip-pasv-ip
|
||||||
|
</name>
|
||||||
|
<command>
|
||||||
|
ftp://%HOSTIP:%FTPPORT/270 --ftp-skip-pasv-ip --disable-epsv
|
||||||
|
</command>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<protocol>
|
||||||
|
USER anonymous
|
||||||
|
PASS curl_by_daniel@haxx.se
|
||||||
|
PWD
|
||||||
|
PASV
|
||||||
|
TYPE I
|
||||||
|
SIZE 270
|
||||||
|
RETR 270
|
||||||
|
QUIT
|
||||||
|
</protocol>
|
||||||
|
</verify>
|
41
tests/data/test271
Normal file
41
tests/data/test271
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
TFTP
|
||||||
|
TFTP RRQ
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<data>
|
||||||
|
a chunk of
|
||||||
|
data
|
||||||
|
returned
|
||||||
|
to client
|
||||||
|
</data>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
tftp
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
TFTP retrieve
|
||||||
|
</name>
|
||||||
|
<command>
|
||||||
|
tftp://%HOSTIP:%TFTPPORT/271 --trace-ascii log/traceit
|
||||||
|
</command>
|
||||||
|
</client>
|
||||||
|
|
||||||
|
#
|
||||||
|
# Verify pseudo protocol after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<protocol>
|
||||||
|
opcode: 1
|
||||||
|
filename: /271
|
||||||
|
mode: octet
|
||||||
|
</protocol>
|
||||||
|
</verify>
|
38
tests/data/test272
Normal file
38
tests/data/test272
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<info>
|
||||||
|
<keywords>
|
||||||
|
FTP
|
||||||
|
PASV
|
||||||
|
RETR
|
||||||
|
</keywords>
|
||||||
|
</info>
|
||||||
|
# Server-side
|
||||||
|
<reply>
|
||||||
|
<mdtm>
|
||||||
|
213 20040101121212
|
||||||
|
</mdtm>
|
||||||
|
</reply>
|
||||||
|
|
||||||
|
# Client-side
|
||||||
|
<client>
|
||||||
|
<server>
|
||||||
|
ftp
|
||||||
|
</server>
|
||||||
|
<name>
|
||||||
|
FTP timed conditioned get file with identical time stamp
|
||||||
|
</name>
|
||||||
|
<command>
|
||||||
|
ftp://%HOSTIP:%FTPPORT/272 -z "2004 jan 1 12:12:12 UTC"
|
||||||
|
</command>
|
||||||
|
|
||||||
|
</client>
|
||||||
|
|
||||||
|
# Verify data after the test has been "shot"
|
||||||
|
<verify>
|
||||||
|
<protocol>
|
||||||
|
USER anonymous
|
||||||
|
PASS curl_by_daniel@haxx.se
|
||||||
|
PWD
|
||||||
|
MDTM 272
|
||||||
|
QUIT
|
||||||
|
</protocol>
|
||||||
|
</verify>
|
@@ -70,6 +70,7 @@ sub ftpmsg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
my $verbose=0; # set to 1 for debugging
|
my $verbose=0; # set to 1 for debugging
|
||||||
|
my $pasvbadip=0;
|
||||||
my $retrweirdo=0;
|
my $retrweirdo=0;
|
||||||
my $retrnosize=0;
|
my $retrnosize=0;
|
||||||
my $srcdir=".";
|
my $srcdir=".";
|
||||||
@@ -564,7 +565,11 @@ sub PASV_command {
|
|||||||
|
|
||||||
if($cmd ne "EPSV") {
|
if($cmd ne "EPSV") {
|
||||||
# PASV reply
|
# PASV reply
|
||||||
sendcontrol sprintf("227 Entering Passive Mode (127,0,0,1,%d,%d)\n",
|
my $p="127,0,0,1";
|
||||||
|
if($pasvbadip) {
|
||||||
|
$p="1,2,3,4";
|
||||||
|
}
|
||||||
|
sendcontrol sprintf("227 Entering Passive Mode ($p,%d,%d)\n",
|
||||||
($pasvport/256), ($pasvport%256));
|
($pasvport/256), ($pasvport%256));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -703,6 +708,10 @@ sub customize {
|
|||||||
logmsg "FTPD: instructed to use RETRNOSIZE\n";
|
logmsg "FTPD: instructed to use RETRNOSIZE\n";
|
||||||
$retrnosize=1;
|
$retrnosize=1;
|
||||||
}
|
}
|
||||||
|
elsif($_ =~ /PASVBADIP/) {
|
||||||
|
logmsg "FTPD: instructed to use PASVBADIP\n";
|
||||||
|
$pasvbadip=1;
|
||||||
|
}
|
||||||
elsif($_ =~ /NOSAVE/) {
|
elsif($_ =~ /NOSAVE/) {
|
||||||
# don't actually store the file we upload - to be used when
|
# don't actually store the file we upload - to be used when
|
||||||
# uploading insanely huge amounts
|
# uploading insanely huge amounts
|
||||||
|
@@ -46,6 +46,8 @@ my $FTPPORT; # FTP server port
|
|||||||
my $FTP2PORT; # FTP server 2 port
|
my $FTP2PORT; # FTP server 2 port
|
||||||
my $FTPSPORT; # FTPS server port
|
my $FTPSPORT; # FTPS server port
|
||||||
my $FTP6PORT; # FTP IPv6 server port
|
my $FTP6PORT; # FTP IPv6 server port
|
||||||
|
my $TFTPPORT; # TFTP
|
||||||
|
my $TFTP6PORT; # TFTP
|
||||||
|
|
||||||
my $CURL="../src/curl"; # what curl executable to run on the tests
|
my $CURL="../src/curl"; # what curl executable to run on the tests
|
||||||
my $DBGCURL=$CURL; #"../src/.libs/curl"; # alternative for debugging
|
my $DBGCURL=$CURL; #"../src/.libs/curl"; # alternative for debugging
|
||||||
@@ -75,6 +77,8 @@ my $FTPPIDFILE=".ftp.pid";
|
|||||||
my $FTP6PIDFILE=".ftp6.pid";
|
my $FTP6PIDFILE=".ftp6.pid";
|
||||||
my $FTP2PIDFILE=".ftp2.pid";
|
my $FTP2PIDFILE=".ftp2.pid";
|
||||||
my $FTPSPIDFILE=".ftps.pid";
|
my $FTPSPIDFILE=".ftps.pid";
|
||||||
|
my $TFTPPIDFILE=".tftpd.pid";
|
||||||
|
my $TFTP6PIDFILE=".tftp6.pid";
|
||||||
|
|
||||||
# invoke perl like this:
|
# invoke perl like this:
|
||||||
my $perl="perl -I$srcdir";
|
my $perl="perl -I$srcdir";
|
||||||
@@ -128,6 +132,7 @@ my $large_file; # set if libcurl is built with large file support
|
|||||||
my $has_idn; # set if libcurl is built with IDN support
|
my $has_idn; # set if libcurl is built with IDN support
|
||||||
my $http_ipv6; # set if HTTP server has IPv6 support
|
my $http_ipv6; # set if HTTP server has IPv6 support
|
||||||
my $ftp_ipv6; # set if FTP server has IPv6 support
|
my $ftp_ipv6; # set if FTP server has IPv6 support
|
||||||
|
my $tftp_ipv6; # set if TFTP server has IPv6 support
|
||||||
my $has_ipv6; # set if libcurl is built with IPv6 support
|
my $has_ipv6; # set if libcurl is built with IPv6 support
|
||||||
my $has_libz; # set if libcurl is built with libz support
|
my $has_libz; # set if libcurl is built with libz support
|
||||||
my $has_getrlimit; # set if system has getrlimit()
|
my $has_getrlimit; # set if system has getrlimit()
|
||||||
@@ -489,7 +494,8 @@ sub verifyftp {
|
|||||||
|
|
||||||
my %protofunc = ('http' => \&verifyhttp,
|
my %protofunc = ('http' => \&verifyhttp,
|
||||||
'https' => \&verifyhttp,
|
'https' => \&verifyhttp,
|
||||||
'ftp' => \&verifyftp);
|
'ftp' => \&verifyftp,
|
||||||
|
'tftp' => \&verifyftp);
|
||||||
|
|
||||||
sub verifyserver {
|
sub verifyserver {
|
||||||
my ($proto, $ip, $port) = @_;
|
my ($proto, $ip, $port) = @_;
|
||||||
@@ -691,6 +697,72 @@ sub runftpserver {
|
|||||||
return ($pid2, $ftppid);
|
return ($pid2, $ftppid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#######################################################################
|
||||||
|
# start the tftp server
|
||||||
|
#
|
||||||
|
sub runtftpserver {
|
||||||
|
my ($id, $verbose, $ipv6) = @_;
|
||||||
|
my $STATUS;
|
||||||
|
my $RUNNING;
|
||||||
|
my $port = $TFTPPORT;
|
||||||
|
# check for pidfile
|
||||||
|
my $pidfile = $TFTPPIDFILE;
|
||||||
|
my $ip=$HOSTIP;
|
||||||
|
my $nameext;
|
||||||
|
my $cmd;
|
||||||
|
|
||||||
|
if($ipv6) {
|
||||||
|
# if IPv6, use a different setup
|
||||||
|
$pidfile = $TFTP6PIDFILE;
|
||||||
|
$port = $TFTP6PORT;
|
||||||
|
$ip = $HOST6IP;
|
||||||
|
$nameext="-ipv6";
|
||||||
|
}
|
||||||
|
|
||||||
|
my $pid = checkserver($pidfile);
|
||||||
|
if($pid >= 0) {
|
||||||
|
stopserver($pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
# start our server:
|
||||||
|
my $flag=$debugprotocol?"-v ":"";
|
||||||
|
$flag .= "-s \"$srcdir\" ";
|
||||||
|
if($id) {
|
||||||
|
$flag .="--id $id ";
|
||||||
|
}
|
||||||
|
if($ipv6) {
|
||||||
|
$flag .="--ipv6 ";
|
||||||
|
}
|
||||||
|
$cmd="./server/tftpd --pidfile $pidfile $flag $port";
|
||||||
|
|
||||||
|
unlink($pidfile);
|
||||||
|
|
||||||
|
my ($tftppid, $pid2) = startnew($cmd, $pidfile);
|
||||||
|
|
||||||
|
if(!$tftppid || !kill(0, $tftppid)) {
|
||||||
|
# it is NOT alive
|
||||||
|
logmsg "RUN: failed to start the FTP$id$nameext server!\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Server is up. Verify that we can speak to it.
|
||||||
|
if(!verifyserver("tftp", $ip, $port)) {
|
||||||
|
logmsg "RUN: TFTP$id$nameext server failed verification\n";
|
||||||
|
# failed to talk to it properly. Kill the server and return failure
|
||||||
|
stopserver("$tftppid $pid2");
|
||||||
|
return (0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if($verbose) {
|
||||||
|
logmsg "RUN: TFTP$id$nameext server is now running PID $tftppid\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep(1);
|
||||||
|
|
||||||
|
return ($pid2, $tftppid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# Remove all files in the specified directory
|
# Remove all files in the specified directory
|
||||||
#
|
#
|
||||||
@@ -946,6 +1018,10 @@ sub checksystem {
|
|||||||
if($ftp_ipv6) {
|
if($ftp_ipv6) {
|
||||||
logmsg sprintf("* FTP IPv6 port: %d\n", $FTP6PORT);
|
logmsg sprintf("* FTP IPv6 port: %d\n", $FTP6PORT);
|
||||||
}
|
}
|
||||||
|
logmsg sprintf("* TFTP port: %d\n", $TFTPPORT);
|
||||||
|
if($tftp_ipv6) {
|
||||||
|
logmsg sprintf("* TFTP IPv6 port: %d\n", $TFTP6PORT);
|
||||||
|
}
|
||||||
|
|
||||||
if($ssl_version) {
|
if($ssl_version) {
|
||||||
logmsg sprintf("* SSL library: %s\n",
|
logmsg sprintf("* SSL library: %s\n",
|
||||||
@@ -974,6 +1050,8 @@ sub subVariables {
|
|||||||
$$thing =~ s/%FTPSPORT/$FTPSPORT/g;
|
$$thing =~ s/%FTPSPORT/$FTPSPORT/g;
|
||||||
$$thing =~ s/%SRCDIR/$srcdir/g;
|
$$thing =~ s/%SRCDIR/$srcdir/g;
|
||||||
$$thing =~ s/%PWD/$pwd/g;
|
$$thing =~ s/%PWD/$pwd/g;
|
||||||
|
$$thing =~ s/%TFTPPORT/$TFTPPORT/g;
|
||||||
|
$$thing =~ s/%TFTP6PORT/$TFTP6PORT/g;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub fixarray {
|
sub fixarray {
|
||||||
@@ -1760,6 +1838,26 @@ sub startservers {
|
|||||||
$run{'https'}="$pid $pid2";
|
$run{'https'}="$pid $pid2";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
elsif($what eq "tftp") {
|
||||||
|
if(!$run{'tftp'}) {
|
||||||
|
($pid, $pid2) = runtftpserver("", $verbose);
|
||||||
|
if($pid <= 0) {
|
||||||
|
return "failed starting TFTP server";
|
||||||
|
}
|
||||||
|
printf ("* pid tftp => %d %d\n", $pid, $pid2) if($verbose);
|
||||||
|
$run{'tftp'}="$pid $pid2";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elsif($what eq "tftp-ipv6") {
|
||||||
|
if(!$run{'tftp-ipv6'}) {
|
||||||
|
($pid, $pid2) = runtftpserver("", $verbose, "IPv6");
|
||||||
|
if($pid <= 0) {
|
||||||
|
return "failed starting TFTP-IPv6 server";
|
||||||
|
}
|
||||||
|
printf("* pid tftp-ipv6 => %d %d\n", $pid, $pid2) if($verbose);
|
||||||
|
$run{'tftp-ipv6'}="$pid $pid2";
|
||||||
|
}
|
||||||
|
}
|
||||||
elsif($what eq "none") {
|
elsif($what eq "none") {
|
||||||
logmsg "* starts no server\n" if ($verbose);
|
logmsg "* starts no server\n" if ($verbose);
|
||||||
}
|
}
|
||||||
@@ -1920,6 +2018,8 @@ $HTTP6PORT = $base + 4; # HTTP IPv6 server port (different IP protocol
|
|||||||
# but we follow the same port scheme anyway)
|
# but we follow the same port scheme anyway)
|
||||||
$FTP2PORT = $base + 5; # FTP server 2 port
|
$FTP2PORT = $base + 5; # FTP server 2 port
|
||||||
$FTP6PORT = $base + 6; # FTP IPv6 port
|
$FTP6PORT = $base + 6; # FTP IPv6 port
|
||||||
|
$TFTPPORT = $base + 7; # TFTP (UDP) port
|
||||||
|
$TFTP6PORT = $base + 8; # TFTP IPv6 (UDP) port
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# Output curl version and host info being tested
|
# Output curl version and host info being tested
|
||||||
|
@@ -8,3 +8,4 @@ Makefile
|
|||||||
getpart
|
getpart
|
||||||
sockfilt
|
sockfilt
|
||||||
resolve
|
resolve
|
||||||
|
tftpd
|
||||||
|
@@ -25,7 +25,7 @@ AUTOMAKE_OPTIONS = foreign
|
|||||||
|
|
||||||
INCLUDES = -I$(top_srcdir)/lib -I$(top_srcdir)/include
|
INCLUDES = -I$(top_srcdir)/lib -I$(top_srcdir)/include
|
||||||
|
|
||||||
noinst_PROGRAMS = sws getpart sockfilt resolve
|
noinst_PROGRAMS = sws getpart sockfilt resolve tftpd
|
||||||
|
|
||||||
useful = getpart.c getpart.h $(top_srcdir)/lib/strequal.c \
|
useful = getpart.c getpart.h $(top_srcdir)/lib/strequal.c \
|
||||||
$(top_srcdir)/lib/base64.c $(top_srcdir)/lib/mprintf.c \
|
$(top_srcdir)/lib/base64.c $(top_srcdir)/lib/mprintf.c \
|
||||||
@@ -36,5 +36,7 @@ sws_SOURCES= sws.c util.c util.h $(useful)
|
|||||||
sockfilt_SOURCES = sockfilt.c util.c util.h $(useful) \
|
sockfilt_SOURCES = sockfilt.c util.c util.h $(useful) \
|
||||||
$(top_srcdir)/lib/inet_pton.c
|
$(top_srcdir)/lib/inet_pton.c
|
||||||
getpart_SOURCES= testpart.c $(useful)
|
getpart_SOURCES= testpart.c $(useful)
|
||||||
|
tftpd_SOURCES = tftpd.c util.c util.h $(useful)
|
||||||
|
|
||||||
extra_DIST = base64.pl
|
extra_DIST = base64.pl
|
||||||
|
|
||||||
|
@@ -105,8 +105,6 @@ const char *serverlogfile = DEFAULT_LOGFILE;
|
|||||||
#define REQUEST_DUMP "log/server.input"
|
#define REQUEST_DUMP "log/server.input"
|
||||||
#define RESPONSE_DUMP "log/server.response"
|
#define RESPONSE_DUMP "log/server.response"
|
||||||
|
|
||||||
#define TEST_DATA_PATH "%s/data/test%ld"
|
|
||||||
|
|
||||||
/* very-big-path support */
|
/* very-big-path support */
|
||||||
#define MAXDOCNAMELEN 140000
|
#define MAXDOCNAMELEN 140000
|
||||||
#define MAXDOCNAMELEN_TXT "139999"
|
#define MAXDOCNAMELEN_TXT "139999"
|
||||||
@@ -117,9 +115,6 @@ const char *serverlogfile = DEFAULT_LOGFILE;
|
|||||||
|
|
||||||
#define END_OF_HEADERS "\r\n\r\n"
|
#define END_OF_HEADERS "\r\n\r\n"
|
||||||
|
|
||||||
/* global variable, where to find the 'data' dir */
|
|
||||||
const char *path=".";
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
DOCNUMBER_NOTHING = -7,
|
DOCNUMBER_NOTHING = -7,
|
||||||
DOCNUMBER_QUIT = -6,
|
DOCNUMBER_QUIT = -6,
|
||||||
@@ -169,14 +164,6 @@ static void sigpipe_handler(int sig)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static char *test2file(long testno)
|
|
||||||
{
|
|
||||||
static char filename[256];
|
|
||||||
sprintf(filename, TEST_DATA_PATH, path, testno);
|
|
||||||
return filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int ProcessRequest(struct httprequest *req)
|
int ProcessRequest(struct httprequest *req)
|
||||||
{
|
{
|
||||||
char *line=req->reqbuf;
|
char *line=req->reqbuf;
|
||||||
@@ -338,7 +325,7 @@ int ProcessRequest(struct httprequest *req)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(chunked) {
|
if(chunked) {
|
||||||
if(strstr(req->reqbuf, "\r\n0\r\n"))
|
if(strstr(req->reqbuf, "\r\n0\r\n\r\n"))
|
||||||
/* end of chunks reached */
|
/* end of chunks reached */
|
||||||
return 1; /* done */
|
return 1; /* done */
|
||||||
else
|
else
|
||||||
@@ -642,7 +629,8 @@ int main(int argc, char *argv[])
|
|||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
struct sockaddr_in6 me6;
|
struct sockaddr_in6 me6;
|
||||||
#endif /* ENABLE_IPV6 */
|
#endif /* ENABLE_IPV6 */
|
||||||
int sock, msgsock, flag;
|
curl_socket_t sock, msgsock;
|
||||||
|
int flag;
|
||||||
unsigned short port = DEFAULT_PORT;
|
unsigned short port = DEFAULT_PORT;
|
||||||
FILE *pidfile;
|
FILE *pidfile;
|
||||||
char *pidname= (char *)".http.pid";
|
char *pidname= (char *)".http.pid";
|
||||||
|
900
tests/server/tftpd.c
Normal file
900
tests/server/tftpd.c
Normal file
@@ -0,0 +1,900 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
* _ _ ____ _
|
||||||
|
* Project ___| | | | _ \| |
|
||||||
|
* / __| | | | |_) | |
|
||||||
|
* | (__| |_| | _ <| |___
|
||||||
|
* \___|\___/|_| \_\_____|
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Trivial file transfer protocol server.
|
||||||
|
*
|
||||||
|
* This code includes many modifications by Jim Guyton <guyton@rand-unix>
|
||||||
|
*
|
||||||
|
* This source file was started based on netkit-tftpd 0.17
|
||||||
|
* Heavily modified for curl's test suite
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1983 Regents of the University of California.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by the University of
|
||||||
|
* California, Berkeley and its contributors.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "setup.h" /* portability help from the lib directory */
|
||||||
|
#ifdef HAVE_SYS_TYPES_H
|
||||||
|
#include <sys/types.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_IOCTL_H
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_STAT_H
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_FCNTL_H
|
||||||
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_SOCKET_H
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETINET_IN_H
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ARPA_TFTP_H
|
||||||
|
#include <arpa/tftp.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_NETDB_H
|
||||||
|
#include <netdb.h>
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_SYS_FILIO_H
|
||||||
|
/* FIONREAD on Solaris 7 */
|
||||||
|
#include <sys/filio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <setjmp.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <grp.h>
|
||||||
|
|
||||||
|
#define ENABLE_CURLX_PRINTF
|
||||||
|
/* make the curlx header define all printf() functions to use the curlx_*
|
||||||
|
versions instead */
|
||||||
|
#include "curlx.h" /* from the private lib dir */
|
||||||
|
#include "getpart.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
/* include memdebug.h last */
|
||||||
|
#include "memdebug.h"
|
||||||
|
|
||||||
|
struct testcase {
|
||||||
|
char *buffer; /* holds the file data to send to the client */
|
||||||
|
size_t bufsize; /* size of the data in buffer */
|
||||||
|
char *rptr; /* read pointer into the buffer */
|
||||||
|
size_t rcount; /* amount of data left to read of the file */
|
||||||
|
long num; /* test case number */
|
||||||
|
int ofile; /* file descriptor for output file when uploading to us */
|
||||||
|
FILE *server; /* write input "protocol" there for client verification */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int synchnet(int);
|
||||||
|
static struct tftphdr *r_init(void);
|
||||||
|
static struct tftphdr *w_init(void);
|
||||||
|
static int readit(struct testcase *test, struct tftphdr **dpp, int convert);
|
||||||
|
static int writeit(struct testcase *test, struct tftphdr **dpp, int ct,
|
||||||
|
int convert);
|
||||||
|
static void mysignal(int, void (*func)(int));
|
||||||
|
|
||||||
|
|
||||||
|
#define TIMEOUT 5
|
||||||
|
|
||||||
|
#define PKTSIZE SEGSIZE+4
|
||||||
|
|
||||||
|
struct formats;
|
||||||
|
static int tftp(struct testcase *test, struct tftphdr *tp, int size);
|
||||||
|
static void nak(int error);
|
||||||
|
static void sendtftp(struct testcase *test, struct formats *pf);
|
||||||
|
static void recvtftp(struct testcase *test, struct formats *pf);
|
||||||
|
static int validate_access(struct testcase *test, const char *, int);
|
||||||
|
|
||||||
|
static curl_socket_t peer;
|
||||||
|
static int rexmtval = TIMEOUT;
|
||||||
|
static int maxtimeout = 5*TIMEOUT;
|
||||||
|
|
||||||
|
static char buf[PKTSIZE];
|
||||||
|
static char ackbuf[PKTSIZE];
|
||||||
|
static struct sockaddr_in from;
|
||||||
|
static socklen_t fromlen;
|
||||||
|
|
||||||
|
struct bf {
|
||||||
|
int counter; /* size of data in buffer, or flag */
|
||||||
|
char buf[PKTSIZE]; /* room for data packet */
|
||||||
|
} bfs[2];
|
||||||
|
|
||||||
|
/* Values for bf.counter */
|
||||||
|
#define BF_ALLOC -3 /* alloc'd but not yet filled */
|
||||||
|
#define BF_FREE -2 /* free */
|
||||||
|
/* [-1 .. SEGSIZE] = size of data in the data buffer */
|
||||||
|
|
||||||
|
static int nextone; /* index of next buffer to use */
|
||||||
|
static int current; /* index of buffer in use */
|
||||||
|
|
||||||
|
/* control flags for crlf conversions */
|
||||||
|
int newline = 0; /* fillbuf: in middle of newline expansion */
|
||||||
|
int prevchar = -1; /* putbuf: previous char (cr check) */
|
||||||
|
|
||||||
|
static void read_ahead(struct testcase *test,
|
||||||
|
int convert /* if true, convert to ascii */);
|
||||||
|
static int write_behind(struct testcase *test, int convert);
|
||||||
|
static struct tftphdr *rw_init(int);
|
||||||
|
static struct tftphdr *w_init(void) { return rw_init(0); } /* write-behind */
|
||||||
|
static struct tftphdr *r_init(void) { return rw_init(1); } /* read-ahead */
|
||||||
|
|
||||||
|
static struct tftphdr *
|
||||||
|
rw_init(int x) /* init for either read-ahead or write-behind */
|
||||||
|
{ /* zero for write-behind, one for read-head */
|
||||||
|
newline = 0; /* init crlf flag */
|
||||||
|
prevchar = -1;
|
||||||
|
bfs[0].counter = BF_ALLOC; /* pass out the first buffer */
|
||||||
|
current = 0;
|
||||||
|
bfs[1].counter = BF_FREE;
|
||||||
|
nextone = x; /* ahead or behind? */
|
||||||
|
return (struct tftphdr *)bfs[0].buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Have emptied current buffer by sending to net and getting ack.
|
||||||
|
Free it and return next buffer filled with data.
|
||||||
|
*/
|
||||||
|
static int readit(struct testcase *test, struct tftphdr **dpp,
|
||||||
|
int convert /* if true, convert to ascii */)
|
||||||
|
{
|
||||||
|
struct bf *b;
|
||||||
|
|
||||||
|
bfs[current].counter = BF_FREE; /* free old one */
|
||||||
|
current = !current; /* "incr" current */
|
||||||
|
|
||||||
|
b = &bfs[current]; /* look at new buffer */
|
||||||
|
if (b->counter == BF_FREE) /* if it's empty */
|
||||||
|
read_ahead(test, convert); /* fill it */
|
||||||
|
|
||||||
|
*dpp = (struct tftphdr *)b->buf; /* set caller's ptr */
|
||||||
|
return b->counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef MIN /* some systems have this defined already, some don't */
|
||||||
|
#define MIN(x,y) ((x)<(y)?(x):(y));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fill the input buffer, doing ascii conversions if requested
|
||||||
|
* conversions are lf -> cr,lf and cr -> cr, nul
|
||||||
|
*/
|
||||||
|
static void read_ahead(struct testcase *test,
|
||||||
|
int convert /* if true, convert to ascii */)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *p;
|
||||||
|
int c;
|
||||||
|
struct bf *b;
|
||||||
|
struct tftphdr *dp;
|
||||||
|
|
||||||
|
b = &bfs[nextone]; /* look at "next" buffer */
|
||||||
|
if (b->counter != BF_FREE) /* nop if not free */
|
||||||
|
return;
|
||||||
|
nextone = !nextone; /* "incr" next buffer ptr */
|
||||||
|
|
||||||
|
dp = (struct tftphdr *)b->buf;
|
||||||
|
|
||||||
|
if (convert == 0) {
|
||||||
|
/* The former file reading code did this:
|
||||||
|
b->counter = read(fileno(file), dp->th_data, SEGSIZE); */
|
||||||
|
int copy_n = MIN(SEGSIZE, test->rcount);
|
||||||
|
memcpy(dp->th_data, test->rptr, copy_n);
|
||||||
|
|
||||||
|
/* decrease amount, advance pointer */
|
||||||
|
test->rcount -= copy_n;
|
||||||
|
test->rptr += copy_n;
|
||||||
|
b->counter = copy_n;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = dp->th_data;
|
||||||
|
for (i = 0 ; i < SEGSIZE; i++) {
|
||||||
|
if (newline) {
|
||||||
|
if (prevchar == '\n')
|
||||||
|
c = '\n'; /* lf to cr,lf */
|
||||||
|
else
|
||||||
|
c = '\0'; /* cr to cr,nul */
|
||||||
|
newline = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(test->rcount) {
|
||||||
|
c=test->rptr[0];
|
||||||
|
test->rptr++;
|
||||||
|
test->rcount--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
if (c == '\n' || c == '\r') {
|
||||||
|
prevchar = c;
|
||||||
|
c = '\r';
|
||||||
|
newline = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*p++ = c;
|
||||||
|
}
|
||||||
|
b->counter = (int)(p - dp->th_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update count associated with the buffer, get new buffer from the queue.
|
||||||
|
Calls write_behind only if next buffer not available.
|
||||||
|
*/
|
||||||
|
static int writeit(struct testcase *test, struct tftphdr **dpp,
|
||||||
|
int ct, int convert)
|
||||||
|
{
|
||||||
|
bfs[current].counter = ct; /* set size of data to write */
|
||||||
|
current = !current; /* switch to other buffer */
|
||||||
|
if (bfs[current].counter != BF_FREE) /* if not free */
|
||||||
|
write_behind(test, convert); /* flush it */
|
||||||
|
bfs[current].counter = BF_ALLOC; /* mark as alloc'd */
|
||||||
|
*dpp = (struct tftphdr *)bfs[current].buf;
|
||||||
|
return ct; /* this is a lie of course */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Output a buffer to a file, converting from netascii if requested.
|
||||||
|
* CR,NUL -> CR and CR,LF => LF.
|
||||||
|
* Note spec is undefined if we get CR as last byte of file or a
|
||||||
|
* CR followed by anything else. In this case we leave it alone.
|
||||||
|
*/
|
||||||
|
static int write_behind(struct testcase *test, int convert)
|
||||||
|
{
|
||||||
|
char *buf;
|
||||||
|
int count;
|
||||||
|
int ct;
|
||||||
|
char *p;
|
||||||
|
int c; /* current character */
|
||||||
|
struct bf *b;
|
||||||
|
struct tftphdr *dp;
|
||||||
|
|
||||||
|
b = &bfs[nextone];
|
||||||
|
if (b->counter < -1) /* anything to flush? */
|
||||||
|
return 0; /* just nop if nothing to do */
|
||||||
|
|
||||||
|
if(!test->ofile) {
|
||||||
|
char outfile[256];
|
||||||
|
snprintf(outfile, sizeof(outfile), "log/upload.%ld", test->num);
|
||||||
|
test->ofile=open(outfile, O_CREAT|O_RDWR, 0777);
|
||||||
|
if(test->ofile == -1) {
|
||||||
|
logmsg("Couldn't create and/or open file %s for upload!", outfile);
|
||||||
|
return -1; /* failure! */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
count = b->counter; /* remember byte count */
|
||||||
|
b->counter = BF_FREE; /* reset flag */
|
||||||
|
dp = (struct tftphdr *)b->buf;
|
||||||
|
nextone = !nextone; /* incr for next time */
|
||||||
|
buf = dp->th_data;
|
||||||
|
|
||||||
|
if (count <= 0)
|
||||||
|
return -1; /* nak logic? */
|
||||||
|
|
||||||
|
if (convert == 0)
|
||||||
|
return write(test->ofile, buf, count);
|
||||||
|
|
||||||
|
p = buf;
|
||||||
|
ct = count;
|
||||||
|
while (ct--) { /* loop over the buffer */
|
||||||
|
c = *p++; /* pick up a character */
|
||||||
|
if (prevchar == '\r') { /* if prev char was cr */
|
||||||
|
if (c == '\n') /* if have cr,lf then just */
|
||||||
|
lseek(test->ofile, -1, SEEK_CUR); /* smash lf on top of the cr */
|
||||||
|
else
|
||||||
|
if (c == '\0') /* if have cr,nul then */
|
||||||
|
goto skipit; /* just skip over the putc */
|
||||||
|
/* else just fall through and allow it */
|
||||||
|
}
|
||||||
|
/* formerly
|
||||||
|
putc(c, file); */
|
||||||
|
write(test->ofile, &c, 1);
|
||||||
|
skipit:
|
||||||
|
prevchar = c;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* When an error has occurred, it is possible that the two sides are out of
|
||||||
|
* synch. Ie: that what I think is the other side's response to packet N is
|
||||||
|
* really their response to packet N-1.
|
||||||
|
*
|
||||||
|
* So, to try to prevent that, we flush all the input queued up for us on the
|
||||||
|
* network connection on our host.
|
||||||
|
*
|
||||||
|
* We return the number of packets we flushed (mostly for reporting when trace
|
||||||
|
* is active).
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int synchnet(curl_socket_t f /* socket to flush */)
|
||||||
|
{
|
||||||
|
int i, j = 0;
|
||||||
|
char rbuf[PKTSIZE];
|
||||||
|
struct sockaddr_in from;
|
||||||
|
socklen_t fromlen;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
(void) ioctl(f, FIONREAD, &i);
|
||||||
|
if (i) {
|
||||||
|
j++;
|
||||||
|
fromlen = sizeof from;
|
||||||
|
(void) recvfrom(f, rbuf, sizeof (rbuf), 0,
|
||||||
|
(struct sockaddr *)&from, &fromlen);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Like signal(), but with well-defined semantics.
|
||||||
|
*/
|
||||||
|
static void mysignal(int sig, void (*handler)(int))
|
||||||
|
{
|
||||||
|
struct sigaction sa;
|
||||||
|
memset(&sa, 0, sizeof(sa));
|
||||||
|
sa.sa_handler = handler;
|
||||||
|
sigaction(sig, &sa, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef DEFAULT_LOGFILE
|
||||||
|
#define DEFAULT_LOGFILE "log/tftpd.log"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DEFAULT_PORT 8999 /* UDP */
|
||||||
|
const char *serverlogfile = DEFAULT_LOGFILE;
|
||||||
|
|
||||||
|
#define REQUEST_DUMP "log/server.input"
|
||||||
|
|
||||||
|
char use_ipv6=FALSE;
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sockaddr_in me;
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
struct sockaddr_in6 me6;
|
||||||
|
#endif /* ENABLE_IPV6 */
|
||||||
|
|
||||||
|
struct tftphdr *tp;
|
||||||
|
int n = 0;
|
||||||
|
int arg = 1;
|
||||||
|
FILE *pidfile;
|
||||||
|
char *pidname= (char *)".tftpd.pid";
|
||||||
|
unsigned short port = DEFAULT_PORT;
|
||||||
|
curl_socket_t sock;
|
||||||
|
int flag;
|
||||||
|
int rc;
|
||||||
|
struct testcase test;
|
||||||
|
|
||||||
|
while(argc>arg) {
|
||||||
|
if(!strcmp("--version", argv[arg])) {
|
||||||
|
printf("tftpd IPv4%s\n",
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
"/IPv6"
|
||||||
|
#else
|
||||||
|
""
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if(!strcmp("--pidfile", argv[arg])) {
|
||||||
|
arg++;
|
||||||
|
if(argc>arg)
|
||||||
|
pidname = argv[arg++];
|
||||||
|
}
|
||||||
|
else if(!strcmp("--ipv6", argv[arg])) {
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
use_ipv6=TRUE;
|
||||||
|
#endif
|
||||||
|
arg++;
|
||||||
|
}
|
||||||
|
else if(argc>arg) {
|
||||||
|
|
||||||
|
if(atoi(argv[arg]))
|
||||||
|
port = (unsigned short)atoi(argv[arg++]);
|
||||||
|
|
||||||
|
if(argc>arg)
|
||||||
|
path = argv[arg++];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(WIN32) && !defined(__GNUC__) || defined(__MINGW32__)
|
||||||
|
win32_init();
|
||||||
|
atexit(win32_cleanup);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
if(!use_ipv6)
|
||||||
|
#endif
|
||||||
|
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
else
|
||||||
|
sock = socket(AF_INET6, SOCK_DGRAM, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (sock < 0) {
|
||||||
|
perror("opening stream socket");
|
||||||
|
logmsg("Error opening socket");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
flag = 1;
|
||||||
|
if (setsockopt
|
||||||
|
(sock, SOL_SOCKET, SO_REUSEADDR, (const void *) &flag,
|
||||||
|
sizeof(int)) < 0) {
|
||||||
|
perror("setsockopt(SO_REUSEADDR)");
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
if(!use_ipv6) {
|
||||||
|
#endif
|
||||||
|
me.sin_family = AF_INET;
|
||||||
|
me.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
me.sin_port = htons(port);
|
||||||
|
rc = bind(sock, (struct sockaddr *) &me, sizeof(me));
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memset(&me6, 0, sizeof(struct sockaddr_in6));
|
||||||
|
me6.sin6_family = AF_INET6;
|
||||||
|
me6.sin6_addr = in6addr_any;
|
||||||
|
me6.sin6_port = htons(port);
|
||||||
|
rc = bind(sock, (struct sockaddr *) &me6, sizeof(me6));
|
||||||
|
}
|
||||||
|
#endif /* ENABLE_IPV6 */
|
||||||
|
if(rc < 0) {
|
||||||
|
perror("binding stream socket");
|
||||||
|
logmsg("Error binding socket");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pidfile = fopen(pidname, "w");
|
||||||
|
if(pidfile) {
|
||||||
|
fprintf(pidfile, "%d\n", (int)getpid());
|
||||||
|
fclose(pidfile);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fprintf(stderr, "Couldn't write pid file\n");
|
||||||
|
|
||||||
|
logmsg("Running IPv%d version on port UDP/%d",
|
||||||
|
#ifdef ENABLE_IPV6
|
||||||
|
(use_ipv6?6:4)
|
||||||
|
#else
|
||||||
|
4
|
||||||
|
#endif
|
||||||
|
, port );
|
||||||
|
|
||||||
|
do {
|
||||||
|
FILE *server;
|
||||||
|
|
||||||
|
fromlen = sizeof(from);
|
||||||
|
n = recvfrom(sock, buf, sizeof (buf), 0,
|
||||||
|
(struct sockaddr *)&from, &fromlen);
|
||||||
|
if (n < 0) {
|
||||||
|
logmsg("recvfrom:\n");
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
from.sin_family = AF_INET;
|
||||||
|
|
||||||
|
peer = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (peer < 0) {
|
||||||
|
logmsg("socket:\n");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (connect(peer, (struct sockaddr *)&from, sizeof(from)) < 0) {
|
||||||
|
logmsg("connect: fail\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
maxtimeout = 5*TIMEOUT;
|
||||||
|
|
||||||
|
tp = (struct tftphdr *)buf;
|
||||||
|
tp->th_opcode = ntohs(tp->th_opcode);
|
||||||
|
if (tp->th_opcode == RRQ || tp->th_opcode == WRQ) {
|
||||||
|
memset(&test, 0, sizeof(test));
|
||||||
|
server = fopen(REQUEST_DUMP, "ab");
|
||||||
|
if(!server)
|
||||||
|
break;
|
||||||
|
test.server = server;
|
||||||
|
tftp(&test, tp, n);
|
||||||
|
if(test.buffer)
|
||||||
|
free(test.buffer);
|
||||||
|
}
|
||||||
|
fclose(server);
|
||||||
|
sclose(peer);
|
||||||
|
} while(1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct formats {
|
||||||
|
const char *f_mode;
|
||||||
|
int f_convert;
|
||||||
|
} formats[] = {
|
||||||
|
{ "netascii", 1 },
|
||||||
|
{ "octet", 0 },
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Handle initial connection protocol.
|
||||||
|
*/
|
||||||
|
static int tftp(struct testcase *test, struct tftphdr *tp, int size)
|
||||||
|
{
|
||||||
|
char *cp;
|
||||||
|
int first = 1, ecode;
|
||||||
|
struct formats *pf;
|
||||||
|
char *filename, *mode = NULL;
|
||||||
|
|
||||||
|
/* store input protocol */
|
||||||
|
fprintf(test->server, "opcode: %x\n", tp->th_opcode);
|
||||||
|
|
||||||
|
cp = (char *)&tp->th_stuff;
|
||||||
|
filename = cp;
|
||||||
|
again:
|
||||||
|
while (cp < buf + size) {
|
||||||
|
if (*cp == '\0')
|
||||||
|
break;
|
||||||
|
cp++;
|
||||||
|
}
|
||||||
|
if (*cp) {
|
||||||
|
nak(EBADOP);
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
if (first) {
|
||||||
|
mode = ++cp;
|
||||||
|
first = 0;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
/* store input protocol */
|
||||||
|
fprintf(test->server, "filename: %s\n", filename);
|
||||||
|
|
||||||
|
for (cp = mode; *cp; cp++)
|
||||||
|
if (isupper((int)*cp))
|
||||||
|
*cp = tolower((int)*cp);
|
||||||
|
|
||||||
|
/* store input protocol */
|
||||||
|
fprintf(test->server, "mode: %s\n", mode);
|
||||||
|
|
||||||
|
for (pf = formats; pf->f_mode; pf++)
|
||||||
|
if (strcmp(pf->f_mode, mode) == 0)
|
||||||
|
break;
|
||||||
|
if (!pf->f_mode) {
|
||||||
|
nak(EBADOP);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
ecode = validate_access(test, filename, tp->th_opcode);
|
||||||
|
if (ecode) {
|
||||||
|
nak(ecode);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (tp->th_opcode == WRQ)
|
||||||
|
recvtftp(test, pf);
|
||||||
|
else
|
||||||
|
sendtftp(test, pf);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Validate file access.
|
||||||
|
*/
|
||||||
|
static int validate_access(struct testcase *test,
|
||||||
|
const char *filename, int mode)
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
long testno;
|
||||||
|
|
||||||
|
logmsg("trying to get file: %s mode %x", filename, mode);
|
||||||
|
|
||||||
|
if(!strncmp("/verifiedserver", filename, 15)) {
|
||||||
|
char weare[128];
|
||||||
|
size_t count = sprintf(weare, "WE ROOLZ: %d\r\n", (int)getpid());
|
||||||
|
|
||||||
|
logmsg("Are-we-friendly question received");
|
||||||
|
test->buffer = strdup(weare);
|
||||||
|
test->rptr = test->buffer; /* set read pointer */
|
||||||
|
test->bufsize = count; /* set total count */
|
||||||
|
test->rcount = count; /* set data left to read */
|
||||||
|
return 0; /* fine */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find the last slash */
|
||||||
|
ptr = strrchr(filename, '/');
|
||||||
|
|
||||||
|
if(ptr) {
|
||||||
|
char *file;
|
||||||
|
|
||||||
|
ptr++; /* skip the slash */
|
||||||
|
|
||||||
|
/* skip all non-numericals following the slash */
|
||||||
|
while(*ptr && !isdigit((int)*ptr))
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
/* get the number */
|
||||||
|
testno = strtol(ptr, &ptr, 10);
|
||||||
|
|
||||||
|
logmsg("requested test number %d", testno);
|
||||||
|
|
||||||
|
test->num = testno;
|
||||||
|
|
||||||
|
file = test2file(testno);
|
||||||
|
|
||||||
|
if(file) {
|
||||||
|
FILE *stream=fopen(file, "rb");
|
||||||
|
if(!stream) {
|
||||||
|
logmsg("Couldn't open test file: %s", file);
|
||||||
|
return EACCESS;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
size_t count;
|
||||||
|
test->buffer = (char *)spitout(stream, "reply", "data", &count);
|
||||||
|
fclose(stream);
|
||||||
|
if(test->buffer) {
|
||||||
|
test->rptr = test->buffer; /* set read pointer */
|
||||||
|
test->bufsize = count; /* set total count */
|
||||||
|
test->rcount = count; /* set data left to read */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return EACCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return EACCESS;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
logmsg("no slash found in path");
|
||||||
|
return EACCESS; /* failure */
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int timeout;
|
||||||
|
sigjmp_buf timeoutbuf;
|
||||||
|
|
||||||
|
static void timer(int signum)
|
||||||
|
{
|
||||||
|
(void)signum;
|
||||||
|
|
||||||
|
logmsg("alarm!");
|
||||||
|
|
||||||
|
timeout += rexmtval;
|
||||||
|
if (timeout >= maxtimeout)
|
||||||
|
exit(1);
|
||||||
|
siglongjmp(timeoutbuf, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send the requested file.
|
||||||
|
*/
|
||||||
|
static void sendtftp(struct testcase *test, struct formats *pf)
|
||||||
|
{
|
||||||
|
struct tftphdr *dp;
|
||||||
|
struct tftphdr *ap; /* ack packet */
|
||||||
|
unsigned short block = 1;
|
||||||
|
int size, n;
|
||||||
|
|
||||||
|
mysignal(SIGALRM, timer);
|
||||||
|
dp = r_init();
|
||||||
|
ap = (struct tftphdr *)ackbuf;
|
||||||
|
do {
|
||||||
|
size = readit(test, &dp, pf->f_convert);
|
||||||
|
if (size < 0) {
|
||||||
|
nak(errno + 100);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dp->th_opcode = htons((u_short)DATA);
|
||||||
|
dp->th_block = htons((u_short)block);
|
||||||
|
timeout = 0;
|
||||||
|
(void) sigsetjmp(timeoutbuf, 1);
|
||||||
|
|
||||||
|
send_data:
|
||||||
|
if (send(peer, dp, size + 4, 0) != size + 4) {
|
||||||
|
logmsg("write\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
read_ahead(test, pf->f_convert);
|
||||||
|
for ( ; ; ) {
|
||||||
|
alarm(rexmtval); /* read the ack */
|
||||||
|
n = recv(peer, ackbuf, sizeof (ackbuf), 0);
|
||||||
|
alarm(0);
|
||||||
|
if (n < 0) {
|
||||||
|
logmsg("read: fail\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ap->th_opcode = ntohs((u_short)ap->th_opcode);
|
||||||
|
ap->th_block = ntohs((u_short)ap->th_block);
|
||||||
|
|
||||||
|
if (ap->th_opcode == ERROR) {
|
||||||
|
logmsg("got ERROR");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ap->th_opcode == ACK) {
|
||||||
|
if (ap->th_block == block) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Re-synchronize with the other side */
|
||||||
|
(void) synchnet(peer);
|
||||||
|
if (ap->th_block == (block -1)) {
|
||||||
|
goto send_data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
block++;
|
||||||
|
} while (size == SEGSIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void justquit(int signum)
|
||||||
|
{
|
||||||
|
(void)signum;
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Receive a file.
|
||||||
|
*/
|
||||||
|
static void recvtftp(struct testcase *test, struct formats *pf)
|
||||||
|
{
|
||||||
|
struct tftphdr *dp;
|
||||||
|
struct tftphdr *ap; /* ack buffer */
|
||||||
|
unsigned short block = 0;
|
||||||
|
int n, size;
|
||||||
|
|
||||||
|
mysignal(SIGALRM, timer);
|
||||||
|
dp = w_init();
|
||||||
|
ap = (struct tftphdr *)ackbuf;
|
||||||
|
do {
|
||||||
|
timeout = 0;
|
||||||
|
ap->th_opcode = htons((u_short)ACK);
|
||||||
|
ap->th_block = htons((u_short)block);
|
||||||
|
block++;
|
||||||
|
(void) sigsetjmp(timeoutbuf, 1);
|
||||||
|
send_ack:
|
||||||
|
if (send(peer, ackbuf, 4, 0) != 4) {
|
||||||
|
logmsg("write: fail\n");
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
write_behind(test, pf->f_convert);
|
||||||
|
for ( ; ; ) {
|
||||||
|
alarm(rexmtval);
|
||||||
|
n = recv(peer, dp, PKTSIZE, 0);
|
||||||
|
alarm(0);
|
||||||
|
if (n < 0) { /* really? */
|
||||||
|
logmsg("read: fail\n");
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
dp->th_opcode = ntohs((u_short)dp->th_opcode);
|
||||||
|
dp->th_block = ntohs((u_short)dp->th_block);
|
||||||
|
if (dp->th_opcode == ERROR)
|
||||||
|
goto abort;
|
||||||
|
if (dp->th_opcode == DATA) {
|
||||||
|
if (dp->th_block == block) {
|
||||||
|
break; /* normal */
|
||||||
|
}
|
||||||
|
/* Re-synchronize with the other side */
|
||||||
|
(void) synchnet(peer);
|
||||||
|
if (dp->th_block == (block-1))
|
||||||
|
goto send_ack; /* rexmit */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size = writeit(test, &dp, n - 4, pf->f_convert);
|
||||||
|
if (size != (n-4)) { /* ahem */
|
||||||
|
if (size < 0)
|
||||||
|
nak(errno + 100);
|
||||||
|
else
|
||||||
|
nak(ENOSPACE);
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
} while (size == SEGSIZE);
|
||||||
|
write_behind(test, pf->f_convert);
|
||||||
|
|
||||||
|
ap->th_opcode = htons((u_short)ACK); /* send the "final" ack */
|
||||||
|
ap->th_block = htons((u_short)(block));
|
||||||
|
(void) send(peer, ackbuf, 4, 0);
|
||||||
|
|
||||||
|
mysignal(SIGALRM, justquit); /* just quit on timeout */
|
||||||
|
alarm(rexmtval);
|
||||||
|
n = recv(peer, buf, sizeof (buf), 0); /* normally times out and quits */
|
||||||
|
alarm(0);
|
||||||
|
if (n >= 4 && /* if read some data */
|
||||||
|
dp->th_opcode == DATA && /* and got a data block */
|
||||||
|
block == dp->th_block) { /* then my last ack was lost */
|
||||||
|
(void) send(peer, ackbuf, 4, 0); /* resend final ack */
|
||||||
|
}
|
||||||
|
abort:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct errmsg {
|
||||||
|
int e_code;
|
||||||
|
const char *e_msg;
|
||||||
|
} errmsgs[] = {
|
||||||
|
{ EUNDEF, "Undefined error code" },
|
||||||
|
{ ENOTFOUND, "File not found" },
|
||||||
|
{ EACCESS, "Access violation" },
|
||||||
|
{ ENOSPACE, "Disk full or allocation exceeded" },
|
||||||
|
{ EBADOP, "Illegal TFTP operation" },
|
||||||
|
{ EBADID, "Unknown transfer ID" },
|
||||||
|
{ EEXISTS, "File already exists" },
|
||||||
|
{ ENOUSER, "No such user" },
|
||||||
|
{ -1, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send a nak packet (error message). Error code passed in is one of the
|
||||||
|
* standard TFTP codes, or a UNIX errno offset by 100.
|
||||||
|
*/
|
||||||
|
static void nak(int error)
|
||||||
|
{
|
||||||
|
struct tftphdr *tp;
|
||||||
|
int length;
|
||||||
|
struct errmsg *pe;
|
||||||
|
|
||||||
|
tp = (struct tftphdr *)buf;
|
||||||
|
tp->th_opcode = htons((u_short)ERROR);
|
||||||
|
tp->th_code = htons((u_short)error);
|
||||||
|
for (pe = errmsgs; pe->e_code >= 0; pe++)
|
||||||
|
if (pe->e_code == error)
|
||||||
|
break;
|
||||||
|
if (pe->e_code < 0) {
|
||||||
|
pe->e_msg = strerror(error - 100);
|
||||||
|
tp->th_code = EUNDEF; /* set 'undef' errorcode */
|
||||||
|
}
|
||||||
|
strcpy(tp->th_msg, pe->e_msg);
|
||||||
|
length = strlen(pe->e_msg);
|
||||||
|
tp->th_msg[length] = '\0';
|
||||||
|
length += 5;
|
||||||
|
if (send(peer, buf, length, 0) != length)
|
||||||
|
logmsg("nak: fail\n");
|
||||||
|
}
|
@@ -144,3 +144,13 @@ void win32_cleanup(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* set by the main code to point to where the test dir is */
|
||||||
|
const char *path=".";
|
||||||
|
|
||||||
|
char *test2file(long testno)
|
||||||
|
{
|
||||||
|
static char filename[256];
|
||||||
|
snprintf(filename, sizeof(filename), TEST_DATA_PATH, path, testno);
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -33,6 +33,11 @@ void logmsg(const char *msg, ...);
|
|||||||
#define TRUE 1
|
#define TRUE 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define TEST_DATA_PATH "%s/data/test%ld"
|
||||||
|
|
||||||
|
/* global variable, where to find the 'data' dir */
|
||||||
|
extern const char *path;
|
||||||
|
|
||||||
#if defined(WIN32) && !defined(__CYGWIN__)
|
#if defined(WIN32) && !defined(__CYGWIN__)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
@@ -60,3 +65,6 @@ const struct in6_addr in6addr_any = {{ IN6ADDR_ANY_INIT }};
|
|||||||
|
|
||||||
void win32_init(void);
|
void win32_init(void);
|
||||||
void win32_cleanup(void);
|
void win32_cleanup(void);
|
||||||
|
|
||||||
|
/* returns the path name to the test case file */
|
||||||
|
char *test2file(long testno);
|
||||||
|
@@ -568,8 +568,8 @@ if ($configurebuild && !$crosscompile) {
|
|||||||
if($runtestopts) {
|
if($runtestopts) {
|
||||||
$o = "TEST_F=\"$runtestopts\" ";
|
$o = "TEST_F=\"$runtestopts\" ";
|
||||||
}
|
}
|
||||||
logit "$make ${o}test-full";
|
logit "$make -k ${o}test-full";
|
||||||
open(F, "$make ${o}test-full 2>&1 |") or die;
|
open(F, "$make -k ${o}test-full 2>&1 |") or die;
|
||||||
open(LOG, ">$buildlog") or die;
|
open(LOG, ">$buildlog") or die;
|
||||||
while (<F>) {
|
while (<F>) {
|
||||||
s/$pwd//g;
|
s/$pwd//g;
|
||||||
|
Reference in New Issue
Block a user