Compare commits

...

91 Commits

Author SHA1 Message Date
Daniel Stenberg
96cec4dfd7 7.15.0 time 2005-10-13 08:19:09 +00:00
Daniel Stenberg
943aea6267 Make sure that the user and domain strings fit in the target buffer before we
copy them there.
2005-10-13 07:57:51 +00:00
Daniel Stenberg
b433e4a1e7 NTLM requires windows or OpenSSL. If you build with GnuTLS for example you
do not get NTLM support enabled.
2005-10-13 06:20:43 +00:00
Daniel Stenberg
20f1966c0e 7.15.0 in november? 2005-10-11 12:54:44 +00:00
Daniel Stenberg
ab1f5c3edd make it compile warning-free and free() the memory before exit 2005-10-10 20:58:18 +00:00
Daniel Stenberg
b2be6799f2 pass a NULL pointer in the service argument (the second) if the port number
was 0 as it seems at least some AIX versions don't like a "0" string there
2005-10-10 18:28:05 +00:00
Gisle Vanem
ea2618fc6f Added tftp.obj. 2005-10-06 18:47:05 +00:00
Daniel Stenberg
62fdf8eaed we all the next version 7.15.0 due to the new TFTP support 2005-10-06 12:56:13 +00:00
Daniel Stenberg
d3569a3572 remove getinfo-times from the dist archive since the info is now in the
curl_easy_getinfo man page
2005-10-06 09:05:08 +00:00
Daniel Stenberg
89df76e449 end the .nf section, mark the option names properly so that they end up
as links in the html version
2005-10-06 09:03:36 +00:00
Daniel Stenberg
e5b2f33b4f Added the info from getinfo-times as it really belongs in this man page. 2005-10-06 08:58:44 +00:00
Daniel Stenberg
934d312f50 mention the recent fixes 2005-10-05 09:15:20 +00:00
Daniel Stenberg
68917eb517 added test case 272 for -z download over FTP when the timestamp is identical
to the remote one
2005-10-05 06:23:45 +00:00
Daniel Stenberg
3beb2f6b5d CURL_TIMECOND_IFMODSINCE actually requires that the remote document has been
modded since the given time, so we should compare <= and not just <.
2005-10-05 06:09:20 +00:00
Daniel Stenberg
b29017f15b Domenico Andreoli's patch that removes a few 0xa0(!) bytes 2005-10-04 20:32:17 +00:00
Daniel Stenberg
db83a0ebbc Michael Wallner reported that the date parser had wrong offset stored for
the MEST and CEST time zones.
2005-10-04 18:15:33 +00:00
Daniel Stenberg
6d9fddb95d Domenico Andreoli's SEE ALSO patch 2005-10-04 10:58:14 +00:00
Daniel Stenberg
4284190cc4 Ok, based on the online docs for AIX'es getservbyport_r() I adjusted to code
to do (what I believe is) "right". See docs on:
http://publib.boulder.ibm.com/infocenter/pseries/index.jsp?topic=/com.ibm.aix.doc/libs/commtrf2/getservbyport_r.htm
2005-10-03 10:12:06 +00:00
Daniel Stenberg
5e4cbd2d24 recent action 2005-10-03 08:38:07 +00:00
Gisle Vanem
06c3bec65d Avoid gcc warning "dereferencing type-punned pointer
will break strict-aliasing rules".
2005-10-02 18:22:45 +00:00
Gisle Vanem
e8c3bb45ba Fix for building with MS Visual-C and single-threaded
runtime libs.
2005-10-02 16:52:07 +00:00
Daniel Stenberg
4ec55a964d fixed the proper path to the tftpd server 2005-09-30 14:25:50 +00:00
Daniel Stenberg
b9420864c0 a new mirror, but we don't increase the amount since one of the former ones
are now officially no longer considered a mirror... ;-)
2005-09-30 08:59:33 +00:00
Daniel Stenberg
bf6588b6a7 Update in the "which license is best" section as it seems Debian people have
made up their mind. Spell-checked as well.
2005-09-30 08:34:51 +00:00
Daniel Stenberg
e43217e664 Starting now, the verbose text that goes like "About to connect() to" will
now contain the word "proxy" is the hostname is in fact a proxy. This will
help users detect situations when they mistakenly use a proxy.
2005-09-29 11:37:52 +00:00
Daniel Stenberg
e19ee2d102 David Yan brought the Content-Range report 2005-09-27 20:22:13 +00:00
Daniel Stenberg
b4c53e2cfd An anonymous submitter 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!
2005-09-27 09:13:39 +00:00
Daniel Stenberg
a2902de67c 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.
2005-09-27 08:46:54 +00:00
Daniel Stenberg
da192f7955 clarify what the default read callback does and how it uses the READDATA
option
2005-09-22 10:15:10 +00:00
Daniel Stenberg
a2210d23c3 three debian bug reports addressed 2005-09-21 11:29:03 +00:00
Daniel Stenberg
bd5a622400 stricter type usage for time variables to avoid picky compiler warnings 2005-09-21 11:28:40 +00:00
Daniel Stenberg
b9494cb0d6 1 - attempted fix of uninitialized variable
2 - indented and edited to fit better within 80 columns
3 - fixed possible buffer overflow in the service name lookup function
2005-09-21 10:45:25 +00:00
Daniel Stenberg
0f73af4470 simplified the sin6_scope_id test and removed some left-overs from the previous
way of detecting it
2005-09-21 09:10:17 +00:00
Daniel Stenberg
45e26b5c02 fixed the check for the addrinfo struct 2005-09-21 09:01:44 +00:00
Daniel Stenberg
6af5ea38ce clarified ERRORBUFFER - some errors just don't write a string even though
they should. And I removed all uses 'Note' (as they are pretty useless) and
did some other language and phrasing cleanups.
2005-09-21 06:59:01 +00:00
Daniel Stenberg
b6f0aa4394 return an error string for the missing URL case 2005-09-21 06:38:33 +00:00
Daniel Stenberg
774dab58f6 mention what WRITEFUNCTION and WRITEDATA do by default 2005-09-21 06:12:41 +00:00
Daniel Stenberg
e3bdb98f7a oops, broken sentence fixed:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=329305
2005-09-21 06:07:41 +00:00
Daniel Stenberg
58d628c9f8 Uses __stdcall instead of SEC_ENTRY since it seems (at least) mingw doesn't
define SEC_ENTRY and thus fails unless this is done!
2005-09-20 08:29:56 +00:00
Daniel Stenberg
1e69394545 Since newer ares versions should work with ipv6, I modified the error message
to a warning message as a first step. We should persue to make curl use
c-ares properly even when built with ipv6 support.
2005-09-20 07:53:44 +00:00
Daniel Stenberg
1cf798ad14 typecasts added in an attempt to please the picky compilers 2005-09-20 06:51:23 +00:00
Daniel Stenberg
da3992d2e9 added test 271 2005-09-19 22:04:14 +00:00
Daniel Stenberg
48908e4633 test 271, the first ever TFTP test 2005-09-19 22:04:06 +00:00
Daniel Stenberg
f5ae149338 seems to work for test 271 on Linux now! 2005-09-19 22:03:16 +00:00
Daniel Stenberg
3fe5311967 Dmitry Bartsevich made the SSPI support work on Windows 9x as well 2005-09-19 21:45:16 +00:00
Dominick Meglio
6a48639c68 Added constants that will be used by ares_getaddrinfo. Made ares_getnameinfo use the reentrant getservbyport (getservbyport_r) if it isavailable to ensure it works properly in a threaded environment 2005-09-18 16:44:49 +00:00
Daniel Stenberg
e7093b3ca8 keep 'socktype' in the connectdata struct and make sure we use that for all
protocol sockets even if the resolved address may say otherwise
2005-09-16 21:30:08 +00:00
Daniel Stenberg
d0a4104c0c recent changes 2005-09-16 21:03:26 +00:00
Daniel Stenberg
90559bed53 renamed sendfile() since some systems have a system call named like this -
now the functions are named sendtftp() and recvtftp() instead.
2005-09-16 10:52:38 +00:00
Daniel Stenberg
973a18cf03 In the Solaris 7 header files for tftp, the th_stuff struct member is an
unsigned short. Trying a typecast here to fix.
2005-09-16 10:50:43 +00:00
Daniel Stenberg
3c666ce57a prevent warnings on re-defining MIN 2005-09-16 07:19:54 +00:00
Daniel Stenberg
a1287ec64f added URLs to bug reports 2005-09-16 07:18:25 +00:00
Daniel Stenberg
5fbfa1bfa8 Added known bugs #26, started using my new "bounce URL" that jumps to the
correct (and overly complicated) sourceforge bug tracker URL given the bug
report ID number.
2005-09-16 07:09:07 +00:00
Daniel Stenberg
da3ecc91f8 use int "subscripts" to prevent warnings from picky compilers 2005-09-16 06:14:30 +00:00
Daniel Stenberg
09c8f558f7 use internal *printf() clones 2005-09-16 05:49:53 +00:00
Daniel Stenberg
528a149def ifdef for includes, added checking for two not previously checked files (one
being necessary for solaris builds)
2005-09-15 21:50:50 +00:00
Daniel Stenberg
29e36afb6b use make -k when running the tests 2005-09-15 21:49:26 +00:00
Daniel Stenberg
0e39543d35 ignore this too 2005-09-15 20:36:58 +00:00
Daniel Stenberg
0de20d8ee6 build tftpd too! 2005-09-15 20:36:28 +00:00
Daniel Stenberg
cd5de5c0e5 First version of the TFTP server. Basic functionality is there. 2005-09-15 20:32:59 +00:00
Daniel Stenberg
bd5afc26bd added TFTP and TFTP-ipv6 support 2005-09-15 20:25:02 +00:00
Daniel Stenberg
9542dfdcdc moved test2file() to util.c 2005-09-15 20:22:43 +00:00
Daniel Stenberg
97a6d7b1a8 minor changes, the biggest one being using Curl_select() 2005-09-15 20:21:27 +00:00
Daniel Stenberg
209b9d4374 mention the configure change 2005-09-15 19:23:31 +00:00
Daniel Stenberg
0b8ccd0ae7 oops, return error if an error did occur! 2005-09-14 15:04:01 +00:00
Daniel Stenberg
0b7f5ad508 CURLOPT_BUFFERSIZE clarification 2005-09-12 20:36:17 +00:00
Daniel Stenberg
8a38805e82 Use the AC_CHECK_MEMBER() function for check struct members instead of
inventing and providing our own. Hopefully this solves a HP-UX 11.00 problem.
2005-09-10 21:09:44 +00:00
Daniel Stenberg
836d88a4b8 --max-time should work just as good on win32 these days 2005-09-08 20:21:52 +00:00
Daniel Stenberg
d5268ed511 mention the protocol-guessing when no protocol part is given in the URL
added TFTP to the list of supported protocols
2005-09-08 06:16:46 +00:00
Daniel Stenberg
0e7d93858d added tftp.c 2005-09-07 14:42:15 +00:00
Daniel Stenberg
2164d760b7 Ben Madsen reported a problem that only seemed to occur with certain specific
glibc versions, and with this patch applied it no longer shows up to me. The
problem was indeed a flaw that made curl use a file handle already closed.
2005-09-07 11:05:34 +00:00
Daniel Stenberg
b9c8de598b Thanks to Scott Davis' detailed reports, I found this premature detection
of the end of a chunked-encoded POST request.
2005-09-07 10:51:37 +00:00
Gisle Vanem
9889a811db Fix warning about missing initializers. 2005-09-06 15:58:09 +00:00
Gisle Vanem
9e38d882b9 Fix for bind() on Winsock; AF_UNSPEC (0) is illegal.
Should we do this for all targets?
2005-09-06 15:43:14 +00:00
Daniel Stenberg
e8635044b5 Now curl warns if an unknown variable is used in the -w/--writeout argument. 2005-09-06 13:27:18 +00:00
Daniel Stenberg
56dea0ac9a binding updates 2005-09-06 11:53:24 +00:00
Daniel Stenberg
e8b77477c7 sockets are curl_socket_t to build cleaner 2005-09-06 10:39:01 +00:00
Daniel Stenberg
64298e528d Use SOCK_DGRAM for TFTP. Consider setting this up at one central place, we
have this check done on far too many places by now...
2005-09-06 10:37:57 +00:00
Gunter Knauf
4f1465e7c7 minor Makefile fixes. 2005-09-06 00:39:41 +00:00
Daniel Stenberg
6120041b69 Added the people from the 7.14.1 release announcement. 2005-09-05 14:22:01 +00:00
Daniel Stenberg
8c1213627d new release, work has been "initiated" 2005-09-05 06:03:06 +00:00
Daniel Stenberg
3e6ae6eeb8 mention the recent improvements 2005-09-04 22:10:03 +00:00
Daniel Stenberg
291e9aeabd don't start lines with apostrophes! 2005-09-04 21:53:10 +00:00
Daniel Stenberg
a3d776187a check that bind() returns success 2005-09-04 18:33:20 +00:00
Daniel Stenberg
e55f502e2f --protocols now supports TFTP 2005-09-04 18:15:24 +00:00
Daniel Stenberg
e369270f88 7.14.2 actually 2005-09-04 05:23:08 +00:00
Daniel Stenberg
7e845e7cfd Added FTP_SKIP_PASV_IP and --ftp-skip-pasv-ip 2005-09-04 05:16:06 +00:00
Daniel Stenberg
56d9624b56 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.
2005-09-02 15:11:08 +00:00
Daniel Stenberg
911d135deb explain why the ABI depends on the SSL libs 2005-09-02 13:40:07 +00:00
Daniel Stenberg
8107b90678 use -c to automake to copy the new files 2005-09-01 21:41:35 +00:00
Daniel Stenberg
7722452b98 work on 7.14.2 starts now 2005-09-01 21:08:56 +00:00
63 changed files with 3377 additions and 1000 deletions

134
CHANGES
View File

@@ -7,6 +7,100 @@
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)
Daniel (29 August 2005)
@@ -93,10 +187,11 @@ Daniel (9 August 2005)
zone names thus limiting the effect of this bug.
Daniel (8 August 2005)
- Jon Grubbs filed bug report #1249962 which identified a problem with NTLM on
a HTTP proxy if an FTP URL was given. libcurl now properly 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.
- Jon Grubbs filed bug report #1249962
(http://curl.haxx.se/bug/view.cgi?id=1249962) which identified a problem
with NTLM on a HTTP proxy if an FTP URL was given. libcurl now properly
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)
- 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.
Daniel (5 July 2005)
- Gisle Vanem came up with a nice little work-around for bug #1230118. It
seems the Windows (MSVC) libc time functions may return data one hour off if
TZ is not set and automatic DST adjustment is enabled. This made
curl_getdate() return wrong value, and it also concerned internal cookie
expirations etc.
- Gisle Vanem came up with a nice little work-around for bug #1230118
(http://curl.haxx.se/bug/view.cgi?id=1230118). It seems the Windows (MSVC)
libc time functions may return data one hour off if TZ is not set and
automatic DST adjustment is enabled. This made curl_getdate() return wrong
value, and it also concerned internal cookie expirations etc.
Daniel (4 July 2005)
- 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
Daniel (14 June 2005)
- Gisle Vanem fixed a potential thread handle leak. Bug report #1216500.
Comment in http://curl.haxx.se/mail/lib-2005-06/0059.html
- Gisle Vanem fixed a potential thread handle leak. Bug report #1216500
(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)
- 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)
- 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
(and patch) #1212940
and patch: http://curl.haxx.se/bug/view.cgi?id=1212940
Daniel (31 May 2005)
- 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
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
262.
262. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=310948
Daniel (25 May 2005)
- Fixed problems with the test suite, and in particular the FTP test cases
@@ -236,9 +332,10 @@ Daniel (20 May 2005)
docs.
Daniel (18 May 2005)
- John McGowan identified a problem in bug report #1204435 with malformed URLs
like "http://somehost?data" as it added a slash too much in the request
("GET /?data/"...). Added test case 260 to verify.
- John McGowan identified a problem in bug report #1204435
(http://curl.haxx.se/bug/view.cgi?id=1204435) with malformed URLs like
"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
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,
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
for host auth, which defaults to Basic). Bug report #1200661 identified the
the problem and the fix.
for host auth, which defaults to Basic). Bug report #1200661
(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
silently discarded. Instead a proper warning message is diplayed that

View File

@@ -1,74 +1,46 @@
Curl and libcurl 7.14.1
Curl and libcurl 7.15.0
Public curl release number: 89
Releases counted from the very beginning: 116
Available command line options: 108
Available curl_easy_setopt() options: 123
Public curl release number: 90
Releases counted from the very beginning: 117
Available command line options: 109
Available curl_easy_setopt() options: 124
Number of public functions in libcurl: 46
Amount of public web site mirrors: 25
Number of known libcurl bindings: 31
Number of contributors: 447
Amount of public web site mirrors: 24
Number of known libcurl bindings: 32
Number of contributors: 451
This release includes the following changes:
o GNU GSS support
o --ignore-content-length and CURLOPT_IGNORE_CONTENT_LENGTH 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
o --ftp-skip-pasv-ip / CURLOPT_FTP_SKIP_PASV_IP (sponsored by CU*Answers)
o TFTP support added
This release includes the following bugfixes:
o MSVC build problem with the DSP file
o windows threaded resolver access violation with multi interface
o test suite works with valgrind 3
o CA cert verification with GnuTLS builds
o handles expiry times in cookie files that go beyond 32 bits in size
o several client problems with files, such as doing -d @file when the file
isn't readable now gets a warning displayed
o write callback abort didn't always "take"
o the curl -z "bad syntax" warning is now hidden when -s is used
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
o user+domain name buffer overflow in the NTLM code (security flaw)
o -z over FTP now considers equal timestamps "not modified since"
o Weird characters removed from the configure script
o Fixed time zone offsets for MEST and CEST for the time parser
o HTTP Content-Range header parser crash
o FTPS negotiation timeouts/errors
o SSPI works even for Windows 9x
o crash in --dump-header on FTP
o test 56 runs better
Other curl-related news since the previous public release:
o cURLpp 0.5.2 was released at http://rrette.com/curlpp.html
o Rexx/CURL 1.3 was released at http://rexxcurl.sf.net/
o http://curl.miscellaneousmirror.org is a new German curl mirror
o LuaCURL by Alexander Marinov at http://luacurl.luaforge.net/
o http://curl.hostingzero.com/ is a new US curl mirror
o ocurl 0.2.1 was released at http://sourceforge.net/projects/ocurl
o http://curl.freemirror.de/ is a new German mirror
o All curl relatd mailing list information and subscribers on cool.haxx.se
were lost due to a malicious user exploiting a security hole on the
server. Attempts have been made to put back susbcribers on the lists, but
many have been lost: http://curl.haxx.se/mail/lost.html
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
advice from friends like these:
John McGowan, Georg Wicherski, Andres Garcia, Eric Cooper, Todd Kulesza,
Tupone Alfredo, Gisle Vanem, David Shaw, Andrew Bushnell, Dan Fandrich,
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
o John Kelly, Nicolas Fran<61>ois, Scott Davis, Ben Madsen, Dmitry Bartsevich,
David Yan, Michael Wallner, Domenico Andreoli, Darryl House
Thanks! (and sorry if I forgot to mention someone)

View File

@@ -1,12 +1,7 @@
Issues not sorted in any particular order.
To get fixed in 7.14.1 (planned release: August 2005)
To get fixed in 7.15.0 (planned release: November 2005)
======================
To get fixed in 7.14.2 (planned release: October 2005)
======================
60 - CONNECT 407 responses that kills the connection
60 - CONNECT 407 responses that kills the connection (not very likely though)
63 -

View File

@@ -1,5 +1,17 @@
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)
* August 21

View File

@@ -242,26 +242,6 @@ AC_DEFUN([CARES_CHECK_STRUCT], [
fi
])
dnl This macro determins if the specified struct contains a specific member.
dnl Syntax:
dnl CARES_CHECK_STRUCT_MEMBER(headers, struct name, member name, if found, [if not found])
AC_DEFUN([CARES_CHECK_STRUCT_MEMBER], [
AC_MSG_CHECKING([if struct $2 has member $3])
AC_TRY_COMPILE([$1],
[
struct $2 struct_instance;
struct_instance.$3 = 0;
], ac_struct="yes", ac_found="no")
if test "$ac_struct" = "yes" ; then
AC_MSG_RESULT(yes)
$4
else
AC_MSG_RESULT(no)
$5
fi
])
dnl This macro determines if the specified constant exists in the specified file
dnl Syntax:
dnl CARES_CHECK_CONSTANT(headers, constant name, if found, [if not found])
@@ -289,3 +269,50 @@ AC_DEFUN([CARES_CHECK_CONSTANT], [
])
dnl This macro determines how many parameters getservbyport_r takes
AC_DEFUN([CARES_CHECK_GETSERVBYPORT_R], [
AC_MSG_CHECKING([how many arguments getservbyport_r takes])
AC_TRY_COMPILE(
[#include <netdb.h>],
[
int p1, p5;
char *p2, p4[4096];
struct servent *p3, *p6;
getservbyport_r(p1, p2, p3, p4, p5, &p6);
], ac_func_getservbyport_r=6,
[AC_TRY_COMPILE(
[#include <netdb.h>],
[
int p1, p5;
char *p2, p4[4096];
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
])

View File

@@ -69,6 +69,10 @@ extern "C" {
/* ares_getnameinfo error codes */
#define ARES_EBADFLAGS 18
/* ares_getaddrinfo error codes */
#define ARES_ENONAME 19
#define ARES_EBADHINTS 20
/* Flag values */
#define ARES_FLAG_USEVC (1 << 0)
#define ARES_FLAG_PRIMARY (1 << 1)
@@ -104,9 +108,27 @@ extern "C" {
#define ARES_NI_LOOKUPHOST (1 << 8)
#define ARES_NI_LOOKUPSERVICE (1 << 9)
/* Reserved for future use */
#define ARES_NI_IDN (1 << 10)
#define ARES_NI_ALLOW_UNASSIGNED (1 << 11)
#define ARES_NI_USE_STD3_ASCII_RULES (1 << 12)
#define ARES_NI_IDN (1 << 10)
#define ARES_NI_IDN_ALLOW_UNASSIGNED (1 << 11)
#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 {
int flags;

View File

@@ -194,9 +194,11 @@ static void nameinfo_callback(void *arg, int status, struct hostent *host)
if (niquery->flags & ARES_NI_LOOKUPSERVICE)
{
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
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.
We do this by determining our own domain name, then searching the string
@@ -234,9 +236,11 @@ static void nameinfo_callback(void *arg, int status, struct hostent *host)
if (niquery->flags & ARES_NI_LOOKUPSERVICE)
{
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
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);
return;
@@ -245,7 +249,8 @@ static void nameinfo_callback(void *arg, int status, struct hostent *host)
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)
{
@@ -256,7 +261,17 @@ static char *lookup_service(unsigned short port, int flags, char *buf)
{
struct servent *se;
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)
proto = "udp";
else if (flags & ARES_NI_SCTP)
@@ -265,9 +280,34 @@ static char *lookup_service(unsigned short port, int flags, char *buf)
proto = "dccp";
else
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);
if (se && se->s_name)
strcpy(buf, se->s_name);
#endif
#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
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
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];
tmpbuf[0] = '%';
#ifdef HAVE_IF_INDEXTONAME
if ((flags & ARES_NI_NUMERICSCOPE) || (!IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr)
&& !IN6_IS_ADDR_MC_LINKLOCAL(&addr6->sin6_addr)))
if ((flags & ARES_NI_NUMERICSCOPE) ||
(!IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr)
&& !IN6_IS_ADDR_MC_LINKLOCAL(&addr6->sin6_addr)))
{
sprintf(&tmpbuf[1], "%u", addr6->sin6_scope_id);
}

View File

@@ -66,6 +66,7 @@ AC_CHECK_HEADERS(
sys/select.h \
sys/socket.h \
sys/ioctl.h \
netdb.h \
winsock.h \
netinet/in.h \
net/if.h \
@@ -175,8 +176,10 @@ CARES_CHECK_STRUCT(
[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,
[Define to 1 if your struct sockaddr_in6 has sin6_scope_id.])
, ,
[
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -187,14 +190,12 @@ CARES_CHECK_STRUCT_MEMBER(
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
], [sockaddr_in6], [sin6_scope_id],
AC_DEFINE_UNQUOTED(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID,1,
[Define to 1 if your struct sockaddr_in6 has sin6_scope_id.])
)
fi
])
dnl check for the addrinfo structure
CARES_CHECK_STRUCT(
AC_CHECK_MEMBER(struct addrinfo.ai_flags,
AC_DEFINE_UNQUOTED(HAVE_STRUCT_ADDRINFO,1,
[Define to 1 if you have struct addrinfo.]),,
[
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -205,9 +206,13 @@ CARES_CHECK_STRUCT(
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
], [addrinfo],
AC_DEFINE_UNQUOTED(HAVE_STRUCT_ADDRINFO,1,
[Define to 1 if you have struct addrinfo.])
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_NETDB_H
#include <netdb.h>
#endif
]
)
dnl check for inet_pton
@@ -346,6 +351,9 @@ AC_CHECK_SIZEOF(struct in_addr, ,
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)

View File

@@ -209,7 +209,7 @@ ${LIBTOOLIZE:-libtoolize} --copy --automake --force || die "The libtool command
fi
echo "buildconf: running automake"
${AUTOMAKE:-automake} -a || die "The automake command failed"
${AUTOMAKE:-automake} -a -c || die "The automake command failed"
echo "buildconf: OK"
exit 0

View File

@@ -122,13 +122,13 @@ case $host in
*-*-mingw*)
AC_DEFINE(BUILDING_LIBCURL, 1, [when building libcurl itself])
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"
then
AC_DEFINE(CURL_STATICLIB, 1, [when not building a shared library])
AC_MSG_RESULT(yes)
<EFBFBD> <20>else
<EFBFBD> <20> <20>AC_MSG_RESULT(no)
else
AC_MSG_RESULT(no)
fi
;;
*)
@@ -251,6 +251,21 @@ AC_HELP_STRING([--disable-telnet],[Disable TELNET support]),
esac ],
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 Check for built-in manual
@@ -1419,6 +1434,8 @@ AC_CHECK_HEADERS(
libgen.h \
locale.h \
errno.h \
arpa/tftp.h \
sys/filio.h \
setjmp.h,
dnl to do if not found
[],
@@ -1673,7 +1690,7 @@ AC_HELP_STRING([--disable-ares],[Disable ares for name lookups]),
*) AC_MSG_RESULT(yes)
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
AC_DEFINE(USE_ARES, 1, [Define if you want to enable ares support])

View File

@@ -116,6 +116,9 @@ while test $# -gt 0; do
if test "@CURL_DISABLE_DICT@" != "1"; then
echo "DICT"
fi
if test "@CURL_DISABLE_TFTP@" != "1"; then
echo "TFTP"
fi
;;
--version)
echo libcurl @VERSION@

View File

@@ -150,6 +150,11 @@ Scheme
Bigloo binding written by Kirill Lisovsky
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
Tclcurl is written by Andr<64>s Garc<72>a
@@ -161,7 +166,7 @@ Visual Basic
http://sourceforge.net/projects/libcurl-vb/
Q
The libcurl module is part of the default install
http://q-lang.sourceforge.net/
wxWidgets

View File

@@ -1,12 +1,12 @@
Date: September 1, 2005
Author: Daniel Stenberg <daniel@haxx.se>
URL: http://curl.haxx.se/legal/distro-dilemma.html
Date: September 30, 2005
Author: Daniel Stenberg <daniel@haxx.se>
URL: http://curl.haxx.se/legal/distro-dilemma.html
Condition
This document is written to describe the sitution as it is right now. libcurl
7.14.0 is currently the latest version available. Things may (or perhaps
will) of course change in the future.
This document is written to describe the situation as it is right
now. libcurl 7.14.1 is currently the latest version available. Things may (or
perhaps will) of course change in the future.
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.
@@ -16,7 +16,7 @@ Background
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
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
GPL licensed programs have avoided this license mess by adding an
exception[8] to their license. And many others have just closed their eyes
@@ -38,7 +38,7 @@ Background
Part of the Operating System
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
allowed to distribute it or its sources. Possibly some distros will claim
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
their different licenses will fit different applications and their authors
differently depending on the applications' licenses and their general usage
pattern (considering how LGPL libraries can be burdonsome for embedded
systems usage).
pattern (considering how LGPL libraries for example can be burdensome for
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
@@ -116,6 +121,16 @@ Project cURL Angle of this Problem
affects users - GPL application authors only - of our lib as it comes
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
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
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
[1] = http://www.xfree86.org/3.3.6/COPYRIGHT2.html#6

View File

@@ -145,3 +145,9 @@ August 2004:
April 2005:
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.

View File

@@ -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
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
proxy closes the connection within the authentication "negotiation phase".
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
to VMS file structures and the perceived file sizes stat() returns. A
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
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
(fake) user name (this concerns both curl and the lib) because the code
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
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
doesn't do a HEAD first to get the initial size. This needs to be done

View File

@@ -9,15 +9,14 @@ Alan Pinstein
Albert Chin-A-Young
Albert Choy
Aleksandar Milivojevic
Alex aka WindEagle
Alex Neblett
Alex Suykov
Alex aka WindEagle
Alexander Kourakos
Alexander Krasnostavsky
Alexander Zhuravlev
Alexis Carvalho
Andi Jahja
Andr<EFBFBD>s Garc<72>a
Andreas Damm
Andreas Olsson
Andreas Rieke
@@ -25,6 +24,7 @@ Andres Garcia
Andrew Bushnell
Andrew Francis
Andrew Fuller
Andr<EFBFBD>s Garc<72>a
Andy Cedilnik
Andy Serpa
Angus Mackay
@@ -36,8 +36,8 @@ Avery Fay
Ben Greear
Benjamin Gerard
Bertrand Demiddelaer
Bj<EFBFBD>rn Stenberg
Bjorn Reese
Bj<EFBFBD>rn Stenberg
Bob Schader
Brad Burdick
Brent Beardsley
@@ -75,8 +75,8 @@ Dan C
Dan Fandrich
Dan Torop
Dan Zitter
Daniel at touchtunes
Daniel Stenberg
Daniel at touchtunes
Dave Dribin
Dave Halbakken
Dave Hamilton
@@ -138,8 +138,6 @@ Frank Ticheler
Fred New
Fred Noz
Frederic Lepied
G<EFBFBD>nter Knauf
G<EFBFBD>tz Babin-Ebell
Gautam Mani
Gaz Iqbal
Georg Horn
@@ -162,6 +160,8 @@ Guenole Bescon
Guillaume Arluison
Gustaf Hui
Gwenole Beauchesne
G<EFBFBD>tz Babin-Ebell
G<EFBFBD>nter Knauf
Hamish Mackenzie
Hanno Kranzhoff
Hans Steegers
@@ -174,11 +174,10 @@ Ian Ford
Ian Gulliver
Ian Wilkes
Ignacio Vazquez-Abrams
Igor Polyakov
Ilguiz Latypov
Ingo Ralf Blum
Ingo Wilken
J<EFBFBD>rg Mueller-Tolk
J<EFBFBD>rn Hartroth
Jacky Lam
Jacob Meuser
James Bursa
@@ -225,6 +224,8 @@ Jukka Pihl
Julian Noble
Jun-ichiro itojun Hagino
Jurij Smakov
J<EFBFBD>rg Mueller-Tolk
J<EFBFBD>rn Hartroth
Kai Sommerfeld
Kai-Uwe Rommel
Kang-Jin Lee
@@ -234,6 +235,7 @@ Keith McGuigan
Ken Hirsch
Ken Rastatter
Kevin Fisk
Kevin Lussier
Kevin Roth
Kimmo Kinnunen
Kjell Ericson
@@ -312,8 +314,8 @@ Nicolas Berloquin
Nicolas Croiset
Niels van Tongeren
Nikita Schmidt
nk
Nodak Sodak
Norbert Novotny
Oren Tirosh
P R Schaffner
Patrick Bihan-Faou
@@ -376,7 +378,6 @@ Rosimildo da Silva
Roy Shan
Rune Kleveland
Ryan Nelson
S<EFBFBD>bastien Willemijns
S. Moonesamy
Salvador D<>vila
Salvatore Sorrentino
@@ -392,6 +393,7 @@ Shard
Shawn Poulson
Siddhartha Prakash Jain
Simon Dick
Simon Josefsson
Simon Liu
Spiridonoff A.V
Stadler Stephan
@@ -408,7 +410,7 @@ Steven Bazyl
Steven G. Johnson
Stoned Elipot
Sven Neuhaus
swalkaus at yahoo.com
S<EFBFBD>bastien Willemijns
T. Bharath
T. Yamada
Thomas Schwinge
@@ -451,3 +453,5 @@ Wilfredo Sanchez
Wojciech Zwiefka
Yarram Sunil
Zvi Har'El
nk
swalkaus at yahoo.com

View File

@@ -31,7 +31,7 @@ TODO
* Introduce a new error code indicating authentication problems (for proxy
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
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
SIOCGIFADDR on newer Solaris versions as they claim the latter is obsolete.

View File

@@ -21,7 +21,7 @@
.\" * $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
curl \- transfer a URL
.SH SYNOPSIS
@@ -30,8 +30,8 @@ curl \- transfer a URL
.SH DESCRIPTION
.B curl
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
command is designed to work without user interaction.
protocols (HTTP, HTTPS, FTP, FTPS, TFTP, GOPHER, DICT, TELNET, LDAP or
FILE). The command is designed to work without user interaction.
curl offers a busload of useful tricks like proxy support, user
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
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
getting many files from the same server will not do multiple connects /
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
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.
.IP "--ftp-ssl"
(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>"
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
networks or links going down. This doesn't work fully in win32 systems. See
also the \fI--connect-timeout\fP option.
networks or links going down. See also the \fI--connect-timeout\fP option.
If this option is used several times, the last one will be used.
.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
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"
@@ -1171,7 +1184,7 @@ Sets proxy server to use for GOPHER.
Sets proxy server to use if no protocol-specific proxy is set.
.IP "NO_PROXY <comma-separated list of hosts>"
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
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,

View File

@@ -14,6 +14,8 @@
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.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.
*/
if(chunk.memory)
free(chunk.memory);
return 0;
}

View File

@@ -52,8 +52,7 @@ PDFPAGES = curl_easy_cleanup.pdf curl_easy_getinfo.pdf \
CLEANFILES = $(HTMLPAGES) $(PDFPAGES)
EXTRA_DIST = $(man_MANS) $(HTMLPAGES) index.html $(PDFPAGES) libcurl.m4 \
getinfo-times
EXTRA_DIST = $(man_MANS) $(HTMLPAGES) index.html $(PDFPAGES) libcurl.m4
MAN2HTML= roffit --mandir=. < $< >$@

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file]
.\" $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
curl_easy_getinfo - extract information from a curl handle
.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
received) 'struct curl_slist *' will be set to point to NULL. (Added in
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
If the operation was successful, CURLE_OK is returned. Otherwise an
appropriate error code will be returned.

View File

@@ -21,7 +21,7 @@
.\" * $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
curl_easy_setopt - set options for a curl easy handle
.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
options back to internal default with \fIcurl_easy_reset(3)\fP.
\fBNOTE:\fP strings passed to libcurl as 'char *' arguments, will not be
copied by the library. Instead you should keep them available until libcurl no
longer needs them. Failing to do so will cause very odd behavior or even
crashes. libcurl will need them until you call \fIcurl_easy_cleanup(3)\fP or
you set the same option again to use a different pointer.
Strings passed to libcurl as 'char *' arguments, will not be copied by the
library. Instead you should keep them available until libcurl no longer needs
them. Failing to do so will cause very odd behavior or even crashes. libcurl
will need them until you call \fIcurl_easy_cleanup(3)\fP or you set the same
option again to use a different pointer.
The \fIhandle\fP is the return code from a \fIcurl_easy_init(3)\fP or
\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
completely.
\fBNOTE:\fP future versions of libcurl is likely to not have any built-in
progress meter at all.
Future versions of libcurl is likely to not have any built-in progress meter
at all.
.IP CURLOPT_NOSIGNAL
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
@@ -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
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.
\fBNOTE:\fP you will be passed as much data as possible in all invokes, but
you cannot possibly make any assumptions. It may be one byte, it may be
The callback function will be passed as much data as possible in all invokes,
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
is defined in the curl.h header file: CURL_MAX_WRITE_SIZE.
.IP CURLOPT_WRITEDATA
Data pointer to pass to the file write function. Note that if you specify the
\fICURLOPT_WRITEFUNCTION\fP, this is the pointer you'll get as input. If you
don't use a callback, you must pass a 'FILE *' as libcurl will pass this to
fwrite() when writing data.
Data pointer to pass to the file write function. If you use the
\fICURLOPT_WRITEFUNCTION\fP option, this is the pointer you'll get as
input. If you don't use a callback, you must pass a 'FILE *' as libcurl will
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
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
for the rest of the data that won't come.
In libcurl 7.12.1 and later, the read callback may return
\fICURL_READFUNC_ABORT\fP to stop the current operation at once, with a
\fICURLE_ABORTED_BY_CALLBACK\fP error code from the transfer.
.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 *.
The read callback may return \fICURL_READFUNC_ABORT\fP to stop the current
operation immediately, resulting in a \fICURLE_ABORTED_BY_CALLBACK\fP error
code from the transfer (Added in 7.12.1)
\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.
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
\fICURLE_ABORTED_BY_CALLBACK\fP.
Also note that \fICURLOPT_NOPROGRESS\fP must be set to FALSE to make this
function actually get called.
\fICURLOPT_NOPROGRESS\fP must be set to FALSE to make this function actually
get called.
.IP CURLOPT_PROGRESSDATA
Pass a pointer that will be untouched by libcurl and passed as the first
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
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
openssl libraries is necessary. Using this function allows for example to use
openssl callbacks to add additional validation code for certificates, and even
to change the actual URI of an HTTPS request (example used in the lib509 test
To use this properly, a non-trivial amount of knowledge of the openssl
libraries is necessary. Using this function allows for example to use openssl
callbacks to add additional validation code for certificates, and even to
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
and trust file settings.
.IP CURLOPT_SSL_CTX_DATA
@@ -249,14 +261,21 @@ parameter, otherwise \fBNULL\fP. (Added in 7.11.0)
.SH ERROR OPTIONS
.IP CURLOPT_ERRORBUFFER
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
library. The buffer must be at least CURL_ERROR_SIZE big.
messages in. This may be more helpful than just the return code from
\fIcurl_easy_perform\fP. The buffer must be at least CURL_ERROR_SIZE big.
Use \fICURLOPT_VERBOSE\fP and \fICURLOPT_DEBUGFUNCTION\fP to better
debug/trace why errors happen.
\fBNote:\fP if the library does not return an error, the buffer may not have
been touched. Do not rely on the contents in those cases.
If the library does not return an error, the buffer may not have been
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
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.
@@ -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
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.
.IP CURLOPT_PROXY
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)
.IP CURLOPT_HTTPPROXYTUNNEL
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
a proxy and to tunnel through it. If you don't know what this means, you
probably don't want this tunneling option.
through a given HTTP proxy. There is a big difference between using a proxy
and to tunnel through it. If you don't know what this means, you probably
don't want this tunneling option.
.IP CURLOPT_INTERFACE
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
@@ -331,10 +350,14 @@ thread-safe and this will use a global variable.
to using the share interface instead! See \fICURLOPT_SHARE\fP and
\fIcurl_share_init(3)\fP.
.IP CURLOPT_BUFFERSIZE
Pass a long specifying your preferred size for the receive buffer in libcurl.
The main point of this would be that the write callback gets called more often
and with smaller chunks. This is just treated as a request, not an order. You
cannot be guaranteed to actually get the given size. (Added in 7.10)
Pass a long specifying your preferred size (in bytes) for the receive buffer
in libcurl. The main point of this would be that the write callback gets
called more often and with smaller chunks. This is just treated as a request,
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
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.
@@ -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
in the URL supplied with \fICURLOPT_URL\fP.
\fBNote:\fP libcurl uses a user name (and supplied or prompted password)
supplied with \fICURLOPT_USERPWD\fP in preference to any of the options
controlled by this parameter.
libcurl uses a user name (and supplied or prompted password) supplied with
\fICURLOPT_USERPWD\fP in preference to any of the options controlled by this
parameter.
Pass a long, set to one of the values described below.
.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
(init macros and similar things aren't supported).
\fBNote:\fP libcurl does not verify that the file has the correct properties
set (as the standard Unix ftp client does). It should only be readable by
user.
libcurl does not verify that the file has the correct properties set (as the
standard Unix ftp client does). It should only be readable by user.
.IP CURLOPT_NETRC_FILE
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
@@ -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
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
it to use. Note that for some methods, this will induce an extra network
round-trip. Set the actual name and password with the \fICURLOPT_USERPWD\fP
option. (Added in 7.10.6)
it to use. For some methods, this will induce an extra network round-trip. Set
the actual name and password with the \fICURLOPT_USERPWD\fP option. (Added in
7.10.6)
.RS
.IP CURLAUTH_BASIC
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
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
this to work.
You need to build libcurl with a suitable GSS-API library for this to work.
.IP CURLAUTH_NTLM
HTTP NTLM authentication. A proprietary protocol invented and used by
Microsoft. It uses a challenge-response and hash concept similar to Digest, to
prevent the password from being eavesdropped.
\fBNOTE\fP that you need to build libcurl with SSL support for this option to
work.
You need to build libcurl with OpenSSL support for this option to work, or
build libcurl on Windows.
.IP CURLAUTH_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
@@ -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
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
use. Note that for some methods, this will induce an extra network
round-trip. Set the actual name and password with the
\fICURLOPT_PROXYUSERPWD\fP option. The bitmask can be constructed by or'ing
together the bits listed above for the \fICURLOPT_HTTPAUTH\fP option. As of
this writing, only Basic, Digest and NTLM work. (Added in 7.10.7)
use. For some methods, this will induce an extra network round-trip. Set the
actual name and password with the \fICURLOPT_PROXYUSERPWD\fP option. The
bitmask can be constructed by or'ing together the bits listed above for the
\fICURLOPT_HTTPAUTH\fP option. As of this writing, only Basic, Digest and NTLM
work. (Added in 7.10.7)
.SH HTTP OPTIONS
.IP CURLOPT_AUTOREFERER
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
server sends as part of an HTTP header.
\fBNOTE:\fP this means that the library will re-send the same request on the
new location and follow new Location: headers all the way until no more such
headers are returned. \fICURLOPT_MAXREDIRS\fP can be used to limit the number
of redirects libcurl will follow.
This means that the library will re-send the same request on the new location
and follow new Location: headers all the way until no more such headers are
returned. \fICURLOPT_MAXREDIRS\fP can be used to limit the number of redirects
libcurl will follow.
.IP CURLOPT_UNRESTRICTED_AUTH
A non-zero parameter tells the library it can continue to send authentication
(user+password) when following locations, even when hostname changed. Note
that this is meaningful only when setting \fICURLOPT_FOLLOWLOCATION\fP.
(user+password) when following locations, even when hostname changed. This
option is meaningful only when setting \fICURLOPT_FOLLOWLOCATION\fP.
.IP CURLOPT_MAXREDIRS
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
@@ -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.
You can disable this header with \fICURLOPT_HTTPHEADER\fP as usual.
\fBNote:\fP to make multipart/formdata posts (aka rfc1867-posts), check out
the \fICURLOPT_HTTPPOST\fP option.
To make multipart/formdata posts (aka rfc1867-posts), check out the
\fICURLOPT_HTTPPOST\fP option.
.IP CURLOPT_POSTFIELDSIZE
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
@@ -605,7 +626,7 @@ request-line are 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.
.IP CURLOPT_HTTP200ALIASES
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
\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
alias is "MYHTTP/9.9", Libcurl will not treat the server as responding with
HTTP version 9.9. Instead Libcurl will use the value set by option
The alias itself is not parsed for any version strings. So if your alias is
\&"MYHTTP/9.9", Libcurl will not treat the server as responding with HTTP
version 9.9. Instead Libcurl will use the value set by option
\fICURLOPT_HTTP_VERSION\fP.
.IP CURLOPT_COOKIE
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
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
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
@@ -762,11 +783,19 @@ directory. (Added in 7.10.7)
.IP CURLOPT_FTP_RESPONSE_TIMEOUT
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
message for a command before the session is considered hung. Note that while
curl is waiting for a response, this value overrides \fICURLOPT_TIMEOUT\fP. It
is recommended that if used in conjunction with \fICURLOPT_TIMEOUT\fP, you set
message for a command before the session is considered hung. While curl is
waiting for a response, this value overrides \fICURLOPT_TIMEOUT\fP. It is
recommended that if used in conjunction with \fICURLOPT_TIMEOUT\fP, you set
\fICURLOPT_FTP_RESPONSE_TIMEOUT\fP to a value smaller than
\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
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)
@@ -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
or similar.
\fBNOTE:\fP libcurl does not do a complete ASCII conversion when doing ASCII
transfers over FTP. This is a known limitation/flaw that nobody has
rectified. libcurl simply sets the mode to ascii and performs a standard
transfer.
libcurl does not do a complete ASCII conversion when doing ASCII transfers
over FTP. This is a known limitation/flaw that nobody has rectified. libcurl
simply sets the mode to ascii and performs a standard transfer.
.IP CURLOPT_CRLF
Convert Unix newlines to CRLF newlines on transfers.
.IP CURLOPT_RANGE
@@ -845,11 +873,11 @@ server supports the command first.
Restore to the internal default by setting this to NULL.
\fBNOTE:\fP Many people have wrongly used this option to replace the entire
request with their own, including multiple headers and POST contents. While
that might work in many cases, it will cause libcurl to send invalid requests
and it could possibly confuse the remote server badly. Use \fICURLOPT_POST\fP
and \fICURLOPT_POSTFIELDS\fP to set POST data. Use \fICURLOPT_HTTPHEADER\fP to
Many people have wrongly used this option to replace the entire request with
their own, including multiple headers and POST contents. While that might work
in many cases, it will cause libcurl to send invalid requests and it could
possibly confuse the remote server badly. Use \fICURLOPT_POST\fP and
\fICURLOPT_POSTFIELDS\fP to set POST data. Use \fICURLOPT_HTTPHEADER\fP to
replace or extend the set of headers sent by libcurl. Use
\fICURLOPT_HTTP_VERSION\fP to change HTTP version.
.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,
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
files this option has no effect even if the file transfer ends up being larger
than this given limit. This concerns both FTP and HTTP transfers.
The file size is not always known prior to download, and for such files this
option has no effect even if the file transfer ends up being larger than this
given limit. This concerns both FTP and HTTP transfers.
.IP CURLOPT_MAXFILESIZE_LARGE
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
value, the transfer will not start and \fICURLE_FILESIZE_EXCEEDED\fP will be
returned. (Added in 7.11.0)
\fBNOTE:\fP The file size is not always known prior to download, and for such
files this option has no effect even if the file transfer ends up being larger
than this given limit. This concerns both FTP and HTTP transfers.
The file size is not always known prior to download, and for such files this
option has no effect even if the file transfer ends up being larger than this
given limit. This concerns both FTP and HTTP transfers.
.IP CURLOPT_TIMECONDITION
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
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
instances this feature will have no effect even if the given time condition
would have not been met.
The last modification time of a file is not always known and in such instances
this feature will have no effect even if the given time condition would have
not been met.
.IP CURLOPT_TIMEVALUE
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
@@ -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
SIGALRM to enable time-outing system calls.
\fBNOTE:\fP this is not recommended to use in unix multi-threaded programs, as
it uses signals unless \fICURLOPT_NOSIGNAL\fP (see above) is set.
In unix-like systems, this might cause signals to be used unless
\fICURLOPT_NOSIGNAL\fP is set.
.IP CURLOPT_LOW_SPEED_LIMIT
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
@@ -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
open connections to increase.
\fBNOTE:\fP if you already have performed transfers with this curl handle,
setting a smaller MAXCONNECTS than before may cause open connections to get
closed unnecessarily.
If you already have performed transfers with this curl handle, setting a
smaller MAXCONNECTS than before may cause open connections to get closed
unnecessarily.
.IP CURLOPT_CLOSEPOLICY
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
@@ -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
timeouts). See also the \fICURLOPT_TIMEOUT\fP option.
\fBNOTE:\fP this is not recommended to use in unix multi-threaded programs, as
it uses signals unless \fICURLOPT_NOSIGNAL\fP (see above) is set.
In unix-like systems, this might cause signals to be used unless
\fICURLOPT_NOSIGNAL\fP is set.
.IP CURLOPT_IPRESOLVE
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
@@ -1019,9 +1047,9 @@ changed with \fICURLOPT_SSLKEYTYPE\fP.
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".
\fBNOTE:\fP The format "ENG" enables you to load the private key from a crypto
engine. In this case \fICURLOPT_SSLKEY\fP is used as an identifier passed to
the engine. You have to set the crypto engine with \fICURLOPT_SSLENGINE\fP.
The format "ENG" enables you to load the private key from a crypto engine. In
this case \fICURLOPT_SSLKEY\fP is used as an identifier passed to the
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.
.IP CURLOPT_SSLKEYPASSWD
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
key.
\fBNOTE:\fP If the crypto device cannot be loaded,
\fICURLE_SSL_ENGINE_NOTFOUND\fP is returned.
If the crypto device cannot be loaded, \fICURLE_SSL_ENGINE_NOTFOUND\fP is
returned.
.IP CURLOPT_SSLENGINE_DEFAULT
Sets the actual crypto engine as the default for (asymmetric) crypto
operations.
\fBNOTE:\fP If the crypto device cannot be set,
\fICURLE_SSL_ENGINE_SETFAILED\fP is returned.
If the crypto device cannot be set, \fICURLE_SSL_ENGINE_SETFAILED\fP is
returned.
.IP CURLOPT_SSLVERSION
Pass a long as parameter to control what version of SSL/TLS to attempt to use.
The available options are:

View File

@@ -23,4 +23,4 @@ You must curl_free() the returned string when you're done with it.
.SH RETURN VALUE
A pointer to a zero terminated string or NULL if it failed.
.SH "SEE ALSO"
.BR curl_unescape(3), curl_free(3), RFC 2396
.BR curl_unescape "(3), " curl_free "(3), " RFC 2396

View File

@@ -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
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
previous
previous connection.
.SH "Multi-threading Issues"
The first basic rule is that you must \fBnever\fP share a libcurl handle (be

View File

@@ -309,6 +309,13 @@ typedef enum {
CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */
CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not
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! */
} CURLcode;
@@ -896,6 +903,12 @@ typedef enum {
/* ignore Content-Length */
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 */
} CURLoption;

View File

@@ -28,7 +28,13 @@
/* This is the version number of the libcurl package from which this header
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
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
@@ -37,19 +43,16 @@
0xXXYYZZ
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
would appear as "0x010200" while version 9.11.7 appears as "0x090b07".
hexadecimal (using 8 bits each). All three numbers are always represented
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
always a greater number in a more recent release. It makes comparisons with
greater than and less than work.
This 6-digit (24 bits) hexadecimal number does not show pre-release number,
and it is always a greater number in a more recent release. It makes
comparisons with greater than and less than work.
*/
#define LIBCURL_VERSION_NUM 0x070e01
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 14
#define LIBCURL_VERSION_PATCH 1
#define LIBCURL_VERSION_NUM ((LIBCURL_VERSION_MAJOR << 16) | \
(LIBCURL_VERSION_MINOR << 8) | \
LIBCURL_VERSION_PATCH)
#endif /* __CURL_CURLVER_H */

View File

@@ -44,7 +44,7 @@ OBJS = $(OBJ_DIR)\transfer.obj $(OBJ_DIR)\file.obj &
$(OBJ_DIR)\hostip6.obj $(OBJ_DIR)\inet_ntop.obj &
$(OBJ_DIR)\hostsyn.obj $(OBJ_DIR)\parsedate.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
@@ -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 &
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
$(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

View File

@@ -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 \
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 \
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 \
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 \
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 \
gtls.h
gtls.h tftp.h

View File

@@ -301,7 +301,7 @@ config.h: Makefile.netware
@echo $(DL)*/$(DL) >> $@
@echo $(DL)#define OS "i586-pc-NetWare"$(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_ASSERT_H 1$(DL) >> $@
@echo $(DL)#define HAVE_DLFCN_H 1$(DL) >> $@

View File

@@ -469,6 +469,7 @@ X_OBJS= \
$(DIROBJ)\strerror.obj \
$(DIROBJ)\select.obj \
$(DIROBJ)\content_encoding.obj \
$(DIROBJ)\tftp.obj \
$(RESOURCE)
all : $(TARGET)

View File

@@ -631,8 +631,9 @@ singleipconnect(struct connectdata *conn,
int error;
bool conected;
struct SessionHandle *data = conn->data;
curl_socket_t sockfd = socket(ai->ai_family, ai->ai_socktype,
ai->ai_protocol);
curl_socket_t sockfd;
sockfd = socket(ai->ai_family, conn->socktype, ai->ai_protocol);
if (sockfd == CURL_SOCKET_BAD)
return CURL_SOCKET_BAD;
@@ -660,7 +661,11 @@ singleipconnect(struct connectdata *conn,
/* set socket non-blocking */
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) {
error = Curl_ourerrno();

View File

@@ -174,13 +174,9 @@ static bool isBadFtpString(const char *string)
* to us. This function will sit and wait here until the server has
* 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)
{
CURLcode result;
int timeout_ms;
struct SessionHandle *data = conn->data;
curl_socket_t sock = conn->sock[SECONDARYSOCKET];
@@ -235,17 +231,6 @@ static CURLcode AllowServerConnect(struct connectdata *conn)
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;
}
@@ -858,7 +843,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
* Workaround for AIX5 getaddrinfo() problem (it doesn't set ai_socktype):
*/
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);
if (portsock == CURL_SOCKET_BAD) {
@@ -1601,8 +1586,18 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
return CURLE_FTP_WEIRD_227_FORMAT;
}
snprintf(newhost, sizeof(newhost),
"%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
/* we got OK from server */
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];
}
else if(ftp->count1 == 0) {
@@ -1622,8 +1617,6 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
return CURLE_FTP_WEIRD_PASV_REPLY;
}
/* we got OK from server */
if(data->change.proxy && *data->change.proxy) {
/*
* 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) {
case CURL_TIMECOND_IFMODSINCE:
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");
ftp->no_transfer = TRUE; /* mark this to not transfer data */
state(conn, FTP_STOP);
@@ -2032,6 +2025,16 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn,
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;
/* 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;
}
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)
size = conn->size = conn->maxdownload;
@@ -3092,18 +3104,6 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
if(!ftp->no_transfer && !conn->bits.no_body) {
/* 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) {
NBFTPSENDF(conn, "TYPE %c", data->set.ftp_ascii?'A':'I');
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 */
sclose(conn->sock[SECONDARYSOCKET]);
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
return result;
}
if(ftp->no_transfer)

View File

@@ -423,7 +423,11 @@ Curl_addrinfo *Curl_he2ai(struct hostent *he, int port)
prevai->ai_next = ai;
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);
/* make the ai_addr point to the address immediately following this struct
and use that area to store the address */

View File

@@ -202,6 +202,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
struct addrinfo hints, *res;
int error;
char sbuf[NI_MAXSERV];
char *sbufptr = NULL;
char addrbuf[128];
curl_socket_t s;
int pf;
@@ -251,10 +252,15 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
memset(&hints, 0, sizeof(hints));
hints.ai_family = pf;
hints.ai_socktype = SOCK_STREAM;
hints.ai_socktype = conn->socktype;
hints.ai_flags = ai_flags;
snprintf(sbuf, sizeof(sbuf), "%d", port);
error = getaddrinfo(hostname, sbuf, &hints, &res);
if(port) {
snprintf(sbuf, sizeof(sbuf), "%d", port);
sbufptr=sbuf;
}
error = getaddrinfo(hostname, sbufptr, &hints, &res);
if (error) {
infof(data, "getaddrinfo(3) failed for %s:%d\n", hostname, port);
return NULL;

View File

@@ -88,6 +88,10 @@
/* The last #include file should be: */
#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
**********************************************************************/
@@ -289,7 +293,7 @@ static unsigned __stdcall gethostbyname_thread (void *arg)
* This allows us to use it even after the container gets destroyed
* 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)) {
/* thread synchronization data initialization failed */
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
* 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)) {
/* thread synchronization data initialization failed */
return -1;
@@ -559,7 +563,10 @@ static bool init_resolve_thread (struct connectdata *conn,
*/
thread_and_event[0] = td->thread_hnd;
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,
* 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));
hints.ai_family = pf;
hints.ai_socktype = SOCK_STREAM;
hints.ai_socktype = conn->socktype;
hints.ai_flags = AI_CANONNAME;
itoa(port, sbuf, 10);

View File

@@ -387,6 +387,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
ULONG attrs;
const char *user;
int domlen;
TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */
ntlm_sspi_cleanup(ntlm);
@@ -430,8 +431,8 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
if (AcquireCredentialsHandle(
NULL, (char *)"NTLM", SECPKG_CRED_OUTBOUND, NULL, ntlm->p_identity,
NULL, NULL, &ntlm->handle, NULL
) != SEC_E_OK) {
NULL, NULL, &ntlm->handle, &tsDummy
) != SEC_E_OK) {
return CURLE_OUT_OF_MEMORY;
}
@@ -447,12 +448,23 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
ISC_REQ_REPLAY_DETECT |
ISC_REQ_CONNECTION,
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 ||
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) {
FreeCredentialsHandle(&ntlm->handle);
@@ -553,6 +565,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
SecBufferDesc type_2_desc, type_3_desc;
SECURITY_STATUS status;
ULONG attrs;
TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */
type_2_desc.ulVersion = type_3_desc.ulVersion = SECBUFFER_VERSION;
type_2_desc.cBuffers = type_3_desc.cBuffers = 1;
@@ -573,7 +586,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
ISC_REQ_CONNECTION,
0, SECURITY_NETWORK_DREP, &type_2_desc,
0, &ntlm->c_handle, &type_3_desc,
&attrs, NULL);
&attrs, &tsDummy);
if (status != SEC_E_OK)
return CURLE_RECV_ERROR;
@@ -700,6 +713,13 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
size=64;
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);
size += domlen;

View File

@@ -130,8 +130,8 @@ static const struct tzinfo tz[]= {
{"CET", -60}, /* Central European */
{"MET", -60}, /* Middle European */
{"MEWT", -60}, /* Middle European Winter */
{"MEST", -120 tDAYZONE}, /* Middle European Summer */
{"CEST", -120 tDAYZONE}, /* Central European Summer */
{"MEST", -60 tDAYZONE}, /* Middle European Summer */
{"CEST", -60 tDAYZONE}, /* Central European Summer */
{"MESZ", -60 tDAYZONE}, /* Middle European Summer */
{"FWT", -60}, /* French Winter */
{"FST", -60 tDAYZONE}, /* French Summer */

View File

@@ -262,6 +262,14 @@ typedef int curl_socket_t;
#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
#define IOCTL_3_ARGS
#endif

View File

@@ -245,6 +245,27 @@ curl_easy_strerror(CURLcode error)
case CURLE_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_MALFORMAT_USER: /* not used by current libcurl */
case CURLE_BAD_CALLING_ORDER: /* not used by current libcurl */

719
lib/tftp.c Normal file
View 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(&current);
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
View 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

View File

@@ -880,11 +880,11 @@ CURLcode Curl_readwrite(struct connectdata *conn,
/* Content-Range: bytes [num]-
Content-Range: bytes: [num]-
The second format was added August 1st 2000 by Igor
Khristophorov since Sun's webserver JavaWebServer/1.1.1
obviously sends the header this way! :-( */
The second format was added since Sun's webserver
JavaWebServer/1.1.1 obviously sends the header this way!
*/
char *ptr = strstr(k->p, "bytes");
char *ptr = Curl_strcasestr(k->p, "bytes");
ptr+=5;
if(*ptr == ':')
@@ -1622,9 +1622,11 @@ Transfer(struct connectdata *conn)
CURLcode Curl_pretransfer(struct SessionHandle *data)
{
CURLcode res;
if(!data->change.url)
if(!data->change.url) {
/* we can't do anything wihout URL */
failf(data, "No URL set!\n");
return CURLE_URL_MALFORMAT;
}
/* 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

View File

@@ -77,9 +77,7 @@
#error "We can't compile without socket() support!"
#endif
#endif
#ifdef USE_LIBIDN
#include <idna.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 "dict.h"
#include "telnet.h"
#include "tftp.h"
#include "http.h"
#include "file.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;
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:
/*
* 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
*/
data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
break;
case CURLOPT_SSL_CTX_DATA:
/*
@@ -1994,7 +2001,8 @@ static CURLcode ConnectPlease(struct connectdata *conn,
struct SessionHandle *data = conn->data;
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);
/*************************************************************
@@ -2722,6 +2730,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
* Setup internals depending on protocol
*************************************************************/
conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
if (strequal(conn->protostr, "HTTP")) {
#ifndef CURL_DISABLE_HTTP
conn->port = PORT_HTTP;
@@ -2915,6 +2925,44 @@ static CURLcode CreateConnection(struct SessionHandle *data,
#else
failf(data, LIBCURL_NAME
" 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
}
else {

View File

@@ -35,6 +35,7 @@
#define PORT_HTTPS 443
#define PORT_DICT 2628
#define PORT_LDAP 389
#define PORT_TFTP 69
#define DICT_MATCH "/MATCH:"
#define DICT_MATCH2 "/M:"
@@ -540,6 +541,7 @@ struct connectdata {
#define PROT_DICT (1<<6)
#define PROT_LDAP (1<<7)
#define PROT_FILE (1<<8)
#define PROT_TFTP (1<<11)
#define PROT_FTPS (1<<9)
#define PROT_SSL (1<<10) /* protocol requires SSL */
@@ -560,6 +562,7 @@ struct connectdata {
char *ip_addr_str;
char protostr[16]; /* store the protocol string in this buffer */
int socktype; /* SOCK_STREAM or SOCK_DGRAM */
struct hostname host;
struct hostname proxy;
@@ -695,6 +698,7 @@ struct connectdata {
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 FTP *ftp;
void *tftp; /* private for tftp.c-eyes only */
struct FILEPROTO *file;
void *telnet; /* private for telnet.c-eyes only */
void *generic;
@@ -1069,8 +1073,9 @@ struct UserDefined {
bool no_signal; /* do not use any signal/alarm handler */
bool global_dns_cache; /* subject for future removal */
bool tcp_nodelay; /* whether to enable TCP_NODELAY or not */
bool ignorecl; /* ignore content length */
bool ftp_skip_ip; /* skip the IP address the FTP server passes on to
us */
};
/*

View File

@@ -81,6 +81,9 @@ char *curl_version(void)
/* data for curl_version_info */
static const char * const protocols[] = {
#ifndef CURL_DISABLE_TFTP
"tftp",
#endif
#ifndef CURL_DISABLE_FTP
"ftp",
#endif

View File

@@ -25,7 +25,6 @@ CHEADER=src/version.h
# Replace version number in header file:
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_MINOR .*/#define LIBCURL_VERSION_MINOR '$minor'/g' \
-e 's/^#define LIBCURL_VERSION_PATCH .*/#define LIBCURL_VERSION_PATCH '$patch'/g' \

View File

@@ -283,7 +283,7 @@ config.h: Makefile.netware
@echo $(DL)*/$(DL) >> $@
@echo $(DL)#define OS "i586-pc-NetWare"$(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 HAVE_ARPA_INET_H 1$(DL) >> $@
@echo $(DL)#define HAVE_ASSERT_H 1$(DL) >> $@

View File

@@ -315,6 +315,7 @@ struct Configurable {
bool insecure_ok; /* set TRUE to allow insecure SSL connects */
bool create_dirs;
bool ftp_create_dirs;
bool ftp_skip_ip;
bool proxyntlm;
bool proxydigest;
bool proxybasic;
@@ -508,7 +509,8 @@ static void help(void)
" --crlf Convert LF to CRLF in upload",
" -f/--fail Fail silently (no output at all) on errors (H)",
" --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)",
" -F/--form <name=content> 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},
{"$o", "trace-time", FALSE},
{"$p", "ignore-content-length", FALSE},
{"$q", "ftp-skip-pasv-ip", FALSE},
{"0", "http1.0", FALSE},
{"1", "tlsv1", FALSE},
@@ -1709,6 +1712,9 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
case 'p': /* --ignore-content-length */
config->ignorecl ^= TRUE;
break;
case 'q': /* --ftp-skip-pasv-ip */
config->ftp_skip_ip ^= TRUE;
break;
}
break;
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 7.14.2 */
curl_easy_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP,
config->ftp_skip_ip);
retry_numretries = config->req_retry;
retrystart = curlx_tvnow();
@@ -4149,15 +4159,15 @@ quit_curl:
if (config->engine)
free(config->engine);
/* cleanup the curl handle! */
curl_easy_cleanup(curl);
if(config->headerfile && !headerfilep && heads.stream)
fclose(heads.stream);
if(allocuseragent)
free(config->useragent);
/* cleanup the curl handle! */
curl_easy_cleanup(curl);
if(config->trace_fopened && config->trace_stream)
fclose(config->trace_stream);

View File

@@ -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
* you should have received as part of this distribution. The terms
@@ -112,11 +112,13 @@ void ourWriteOut(CURL *curl, char *writeinfo)
char keepit;
int i;
if(('{' == ptr[1]) && (end=strchr(ptr, '}'))) {
bool match = FALSE;
ptr+=2; /* pass the % and the { */
keepit=*end;
*end=0; /* zero terminate */
for(i=0; replacements[i].name; i++) {
if(curl_strequal(ptr, replacements[i].name)) {
match = TRUE;
switch(replacements[i].id) {
case VAR_EFFECTIVE_URL:
if((CURLE_OK ==
@@ -217,6 +219,9 @@ void ourWriteOut(CURL *curl, char *writeinfo)
break;
}
}
if(!match) {
fprintf(stderr, "curl: unknown --writeout variable: '%s'\n", ptr);
}
ptr=end+1; /* pass the end */
*end = keepit;
}

View File

@@ -81,6 +81,7 @@ RETRWEIRDO
RETRNOSIZE
NOSAVE
SLOWDOWN
PASVBADIP - makes PASV send back an illegal IP in its 227 response
For HTTP, one specified command is supported:
"auth_required" - if this is set and a POST/PUT is made without auth, the

View File

@@ -33,4 +33,4 @@ EXTRA_DIST = test1 test108 test117 test127 test20 test27 test34 test46 \
test237 test238 test239 test243 test245 test246 test247 test248 test249 \
test250 test251 test252 test253 test254 test255 test521 test522 test523 \
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
View 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
View 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
View 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>

View File

@@ -70,6 +70,7 @@ sub ftpmsg {
}
my $verbose=0; # set to 1 for debugging
my $pasvbadip=0;
my $retrweirdo=0;
my $retrnosize=0;
my $srcdir=".";
@@ -564,7 +565,11 @@ sub PASV_command {
if($cmd ne "EPSV") {
# 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));
}
else {
@@ -703,6 +708,10 @@ sub customize {
logmsg "FTPD: instructed to use RETRNOSIZE\n";
$retrnosize=1;
}
elsif($_ =~ /PASVBADIP/) {
logmsg "FTPD: instructed to use PASVBADIP\n";
$pasvbadip=1;
}
elsif($_ =~ /NOSAVE/) {
# don't actually store the file we upload - to be used when
# uploading insanely huge amounts

View File

@@ -46,6 +46,8 @@ my $FTPPORT; # FTP server port
my $FTP2PORT; # FTP server 2 port
my $FTPSPORT; # FTPS 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 $DBGCURL=$CURL; #"../src/.libs/curl"; # alternative for debugging
@@ -75,6 +77,8 @@ my $FTPPIDFILE=".ftp.pid";
my $FTP6PIDFILE=".ftp6.pid";
my $FTP2PIDFILE=".ftp2.pid";
my $FTPSPIDFILE=".ftps.pid";
my $TFTPPIDFILE=".tftpd.pid";
my $TFTP6PIDFILE=".tftp6.pid";
# invoke perl like this:
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 $http_ipv6; # set if HTTP 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_libz; # set if libcurl is built with libz support
my $has_getrlimit; # set if system has getrlimit()
@@ -489,7 +494,8 @@ sub verifyftp {
my %protofunc = ('http' => \&verifyhttp,
'https' => \&verifyhttp,
'ftp' => \&verifyftp);
'ftp' => \&verifyftp,
'tftp' => \&verifyftp);
sub verifyserver {
my ($proto, $ip, $port) = @_;
@@ -691,6 +697,72 @@ sub runftpserver {
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
#
@@ -946,6 +1018,10 @@ sub checksystem {
if($ftp_ipv6) {
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) {
logmsg sprintf("* SSL library: %s\n",
@@ -974,6 +1050,8 @@ sub subVariables {
$$thing =~ s/%FTPSPORT/$FTPSPORT/g;
$$thing =~ s/%SRCDIR/$srcdir/g;
$$thing =~ s/%PWD/$pwd/g;
$$thing =~ s/%TFTPPORT/$TFTPPORT/g;
$$thing =~ s/%TFTP6PORT/$TFTP6PORT/g;
}
sub fixarray {
@@ -1760,6 +1838,26 @@ sub startservers {
$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") {
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)
$FTP2PORT = $base + 5; # FTP server 2 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

View File

@@ -8,3 +8,4 @@ Makefile
getpart
sockfilt
resolve
tftpd

View File

@@ -25,7 +25,7 @@ AUTOMAKE_OPTIONS = foreign
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 \
$(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) \
$(top_srcdir)/lib/inet_pton.c
getpart_SOURCES= testpart.c $(useful)
tftpd_SOURCES = tftpd.c util.c util.h $(useful)
extra_DIST = base64.pl

View File

@@ -105,8 +105,6 @@ const char *serverlogfile = DEFAULT_LOGFILE;
#define REQUEST_DUMP "log/server.input"
#define RESPONSE_DUMP "log/server.response"
#define TEST_DATA_PATH "%s/data/test%ld"
/* very-big-path support */
#define MAXDOCNAMELEN 140000
#define MAXDOCNAMELEN_TXT "139999"
@@ -117,9 +115,6 @@ const char *serverlogfile = DEFAULT_LOGFILE;
#define END_OF_HEADERS "\r\n\r\n"
/* global variable, where to find the 'data' dir */
const char *path=".";
enum {
DOCNUMBER_NOTHING = -7,
DOCNUMBER_QUIT = -6,
@@ -169,14 +164,6 @@ static void sigpipe_handler(int sig)
}
#endif
static char *test2file(long testno)
{
static char filename[256];
sprintf(filename, TEST_DATA_PATH, path, testno);
return filename;
}
int ProcessRequest(struct httprequest *req)
{
char *line=req->reqbuf;
@@ -338,7 +325,7 @@ int ProcessRequest(struct httprequest *req)
}
if(chunked) {
if(strstr(req->reqbuf, "\r\n0\r\n"))
if(strstr(req->reqbuf, "\r\n0\r\n\r\n"))
/* end of chunks reached */
return 1; /* done */
else
@@ -642,7 +629,8 @@ int main(int argc, char *argv[])
#ifdef ENABLE_IPV6
struct sockaddr_in6 me6;
#endif /* ENABLE_IPV6 */
int sock, msgsock, flag;
curl_socket_t sock, msgsock;
int flag;
unsigned short port = DEFAULT_PORT;
FILE *pidfile;
char *pidname= (char *)".http.pid";

900
tests/server/tftpd.c Normal file
View 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");
}

View File

@@ -144,3 +144,13 @@ void win32_cleanup(void)
}
#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;
}

View File

@@ -33,6 +33,11 @@ void logmsg(const char *msg, ...);
#define TRUE 1
#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__)
#include <windows.h>
#include <winsock2.h>
@@ -60,3 +65,6 @@ const struct in6_addr in6addr_any = {{ IN6ADDR_ANY_INIT }};
void win32_init(void);
void win32_cleanup(void);
/* returns the path name to the test case file */
char *test2file(long testno);

View File

@@ -568,8 +568,8 @@ if ($configurebuild && !$crosscompile) {
if($runtestopts) {
$o = "TEST_F=\"$runtestopts\" ";
}
logit "$make ${o}test-full";
open(F, "$make ${o}test-full 2>&1 |") or die;
logit "$make -k ${o}test-full";
open(F, "$make -k ${o}test-full 2>&1 |") or die;
open(LOG, ">$buildlog") or die;
while (<F>) {
s/$pwd//g;