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 Changelog
Version 7.15.0 (13 October 2005)
Daniel (12 October 2005)
- Michael Sutton of iDEFENSE reported and I fixed a securitfy flaw in the NTLM
code that would overflow a buffer if given a too long user name or domain
name. This would happen if you enable NTLM authentication and either
A - pass in a user name and domain name to libcurl that together are longer
than 192 bytes
B - allow (lib)curl to follow HTTP "redirects" (Location: and the
appropriate HTTP 30x response code) and the new URL contains a URL with
a user name and domain name that together are longer than 192 bytes
See http://curl.haxx.se/docs/security.html for further details and updates
Daniel (5 October 2005)
- Darryl House reported a problem with using -z to download files from FTP.
It turned out that if the given time stamp was exact the same as the remote
time stamp, the file would still wrongly be downloaded. Added test case 272
to verify.
Daniel (4 October 2005)
- Domenico Andreoli fixed a man page malformat and removed odd (0xa0) bytes
from the configure script.
- Michael Wallner reported that the date parser had wrong offset stored for
the MEST and CEST time zones.
Daniel (27 September 2005)
- David Yan filed bug #1299181 (http://curl.haxx.se/bug/view.cgi?id=1299181)
that identified a silly problem with Content-Range: headers with the 'bytes'
keyword written in a different case than all lowercase! It would cause a
segfault!
- TJ Saunders of the proftpd project identified and pointed out problems with
the modified FTPS negotiation change of August 19 2005. Thus, we revert the
change back to pre-7.14.1 status.
Daniel (21 September 2005)
- Fixed "cut off" sentence in the libcurl-tutorial man page:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=329305
- Clarified in the curl_easy_setopt man page what the default
CURLOPT_WRITEFUNCTION and CURLOPT_WRITEDATA mean:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=329311
- Clarified in the curl_easy_setopt man page that CURLOPT_ERRORBUFFER
sometimes doesn't fill in the buffer even though it is supposed to:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=329313
- When CURLE_URL_MALFORMAT is returned due to a missing URL, it now has an
error string set.
Daniel (19 September 2005)
- Dmitry Bartsevich made the SSPI support work on Windows 9x as well.
Daniel (15 September 2005)
- Added a TFTP server to the test suite and made the test suite capable of
using it.
Daniel (7 September 2005)
- Ben Madsen's detailed reports that funnily enough only occurred with certain
glibc versions turned out to be curl using an already closed file handle
during certain conditions (like when saving FTP server "headers").
- Scott Davis helped me track down a problem in the test HTTP server that made
test case 56 wrongly fail at times. It turned out it was due to the server
finding the end of a chunked-encoded POST too early.
Daniel (6 September 2005)
- Now curl warns if an unknown variable is used in the -w/--writeout argument.
Daniel (4 September 2005)
- I applied Nicolas Fran<61>ois' man page patch he posted to the Debian bug
tracker. It corrected two lines that started with apostrophes, which isn't
legal nroff format. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=326511
- Added --ftp-skip-pasv-ip to the command line tool, that sets the new
CURLOPT_FTP_SKIP_PASV_IP option. It makes libcurl re-use the control
connection's IP address when setting up the data connection instead of
extractting the IP address from the PASV response. It has turned out this
feature is frequently needed by people to circumvent silly servers and silly
firewalls, especially when FTPS is used and the PASV command-response is
sent encrtyped.
Sponsored by CU*Answers
Daniel (1 September 2005)
- John Kelly added TFTP support to libcurl. A bunch of new error codes was
added. TODO: add them to docs. add TFTP server to test suite. add TFTP to
list of protocols whereever those are mentioned.
Version 7.14.1 (1 September 2005) Version 7.14.1 (1 September 2005)
Daniel (29 August 2005) Daniel (29 August 2005)
@@ -93,10 +187,11 @@ Daniel (9 August 2005)
zone names thus limiting the effect of this bug. zone names thus limiting the effect of this bug.
Daniel (8 August 2005) Daniel (8 August 2005)
- Jon Grubbs filed bug report #1249962 which identified a problem with NTLM on - Jon Grubbs filed bug report #1249962
a HTTP proxy if an FTP URL was given. libcurl now properly switches to pure (http://curl.haxx.se/bug/view.cgi?id=1249962) which identified a problem
HTTP internally when an HTTP proxy is used, even for FTP URLs. The problem with NTLM on a HTTP proxy if an FTP URL was given. libcurl now properly
would also occur with other multi-pass auth methods. switches to pure HTTP internally when an HTTP proxy is used, even for FTP
URLs. The problem would also occur with other multi-pass auth methods.
Daniel (7 August 2005) Daniel (7 August 2005)
- When curl is built with GnuTLS, curl-config didn't include "SSL" when - When curl is built with GnuTLS, curl-config didn't include "SSL" when
@@ -125,11 +220,11 @@ Daniel (12 July 2005)
contains a flawed chunked encoding stream that still works the same. contains a flawed chunked encoding stream that still works the same.
Daniel (5 July 2005) Daniel (5 July 2005)
- Gisle Vanem came up with a nice little work-around for bug #1230118. It - Gisle Vanem came up with a nice little work-around for bug #1230118
seems the Windows (MSVC) libc time functions may return data one hour off if (http://curl.haxx.se/bug/view.cgi?id=1230118). It seems the Windows (MSVC)
TZ is not set and automatic DST adjustment is enabled. This made libc time functions may return data one hour off if TZ is not set and
curl_getdate() return wrong value, and it also concerned internal cookie automatic DST adjustment is enabled. This made curl_getdate() return wrong
expirations etc. value, and it also concerned internal cookie expirations etc.
Daniel (4 July 2005) Daniel (4 July 2005)
- Andrew Bushnell provided enough info for me to tell that we badly needed to - Andrew Bushnell provided enough info for me to tell that we badly needed to
@@ -165,8 +260,9 @@ Daniel (22 June 2005)
- David Shaw updated libcurl.m4 - David Shaw updated libcurl.m4
Daniel (14 June 2005) Daniel (14 June 2005)
- Gisle Vanem fixed a potential thread handle leak. Bug report #1216500. - Gisle Vanem fixed a potential thread handle leak. Bug report #1216500
Comment in http://curl.haxx.se/mail/lib-2005-06/0059.html (http://curl.haxx.se/bug/view.cgi?id=1216500). Comment in
http://curl.haxx.se/mail/lib-2005-06/0059.html
Daniel (13 June 2005) Daniel (13 June 2005)
- Made buildconf run libtoolize in the ares dir too (inspired by Tupone's - Made buildconf run libtoolize in the ares dir too (inspired by Tupone's
@@ -202,7 +298,7 @@ Daniel (3 June 2005)
Daniel (1 June 2005) Daniel (1 June 2005)
- The configure check for c-ares now adds the cares lib before the other libs, - The configure check for c-ares now adds the cares lib before the other libs,
to make it build fine with mingw. Inspired by Tupone Alfredo's bug report to make it build fine with mingw. Inspired by Tupone Alfredo's bug report
(and patch) #1212940 and patch: http://curl.haxx.se/bug/view.cgi?id=1212940
Daniel (31 May 2005) Daniel (31 May 2005)
- Todd Kulesza reported a flaw in the proxy option, since a numerical IPv6 - Todd Kulesza reported a flaw in the proxy option, since a numerical IPv6
@@ -214,7 +310,7 @@ Daniel (30 May 2005)
- Eric Cooper reported about a problem with HTTP servers that responds with - Eric Cooper reported about a problem with HTTP servers that responds with
binary zeroes within the headers. They confused libcurl to do wrong so the binary zeroes within the headers. They confused libcurl to do wrong so the
downloaded headers become incomplete. The fix is now verified with test case downloaded headers become incomplete. The fix is now verified with test case
262. 262. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=310948
Daniel (25 May 2005) Daniel (25 May 2005)
- Fixed problems with the test suite, and in particular the FTP test cases - Fixed problems with the test suite, and in particular the FTP test cases
@@ -236,9 +332,10 @@ Daniel (20 May 2005)
docs. docs.
Daniel (18 May 2005) Daniel (18 May 2005)
- John McGowan identified a problem in bug report #1204435 with malformed URLs - John McGowan identified a problem in bug report #1204435
like "http://somehost?data" as it added a slash too much in the request (http://curl.haxx.se/bug/view.cgi?id=1204435) with malformed URLs like
("GET /?data/"...). Added test case 260 to verify. "http://somehost?data" as it added a slash too much in the request ("GET
/?data/"...). Added test case 260 to verify.
- The configure check for strerror_r() failed to detect the proper API at - The configure check for strerror_r() failed to detect the proper API at
times, like on HP-UX 10.20. Then lib/strerror.c badly assumed the glibc times, like on HP-UX 10.20. Then lib/strerror.c badly assumed the glibc
@@ -261,8 +358,9 @@ Daniel (12 May 2005)
- When doing a second request (after a disconnect) using the same easy handle, - When doing a second request (after a disconnect) using the same easy handle,
over a proxy that uses NTLM authentication, libcurl failed to use NTLM again over a proxy that uses NTLM authentication, libcurl failed to use NTLM again
properly (the auth method was accidentally reset to the same as had been set properly (the auth method was accidentally reset to the same as had been set
for host auth, which defaults to Basic). Bug report #1200661 identified the for host auth, which defaults to Basic). Bug report #1200661
the problem and the fix. (http://curl.haxx.se/bug/view.cgi?id=1200661) identified the the problem and
the fix.
- If -z/--time-cond is used with an invalid date syntax, this is no longer - If -z/--time-cond is used with an invalid date syntax, this is no longer
silently discarded. Instead a proper warning message is diplayed that silently discarded. Instead a proper warning message is diplayed that

View File

@@ -1,74 +1,46 @@
Curl and libcurl 7.14.1 Curl and libcurl 7.15.0
Public curl release number: 89 Public curl release number: 90
Releases counted from the very beginning: 116 Releases counted from the very beginning: 117
Available command line options: 108 Available command line options: 109
Available curl_easy_setopt() options: 123 Available curl_easy_setopt() options: 124
Number of public functions in libcurl: 46 Number of public functions in libcurl: 46
Amount of public web site mirrors: 25 Amount of public web site mirrors: 24
Number of known libcurl bindings: 31 Number of known libcurl bindings: 32
Number of contributors: 447 Number of contributors: 451
This release includes the following changes: This release includes the following changes:
o GNU GSS support o --ftp-skip-pasv-ip / CURLOPT_FTP_SKIP_PASV_IP (sponsored by CU*Answers)
o --ignore-content-length and CURLOPT_IGNORE_CONTENT_LENGTH added o TFTP support added
o negotiates data connection SSL earlier when doing FTPS with PASV
o CURLOPT_COOKIELIST and CURLINFO_COOKIELIST
o trailer support for chunked encoded data streams
o -x/CURL_PROXY strings may now contain user+password
o --trace-time now outputs the full microsecond, all 6 digits
This release includes the following bugfixes: This release includes the following bugfixes:
o MSVC build problem with the DSP file o user+domain name buffer overflow in the NTLM code (security flaw)
o windows threaded resolver access violation with multi interface o -z over FTP now considers equal timestamps "not modified since"
o test suite works with valgrind 3 o Weird characters removed from the configure script
o CA cert verification with GnuTLS builds o Fixed time zone offsets for MEST and CEST for the time parser
o handles expiry times in cookie files that go beyond 32 bits in size o HTTP Content-Range header parser crash
o several client problems with files, such as doing -d @file when the file o FTPS negotiation timeouts/errors
isn't readable now gets a warning displayed o SSPI works even for Windows 9x
o write callback abort didn't always "take" o crash in --dump-header on FTP
o the curl -z "bad syntax" warning is now hidden when -s is used o test 56 runs better
o curl -d @nonexisting no longer makes a GET
o minor debug callback data size
o date parsing of dates including daylight savings time zone names
o using NTLM over proxy with an FTP URL
o curl-config --features now displays SSL when built with GnuTLS too
o CURLOPT_HTTPGET, CURLOPT_POST and CURLOPT_HTTPPOST reset CURLOPT_NOBODY
o builds fine on AmigaOS again
o corrected date parsing on Windows with auto-DST-adjust enabled
o treats CONNECT 407 responses with bodies better during Digest/NTLM auth
o improved strerror_r() API guessing when cross-compiling
o debug builds work on Tru64
o improved libcurl.m4
o possible memory leak in windows name resolves
o c-ares enabled build with mingw
o proxy host set with numerical IPv6 address
o better treatment of binary zeroes in HTTP response headers
o fixed the notorious FTP server failure in the test suite
o better checking of text output in the test suite on windows
o FTP servers' TYPE command response check made less strict
o URL-without-slash as in http://somehost?data
o strerror_r() configure check for HP-UX 10.20 (and others)
o time parse work-around on HP-UX 10.20 since its gmtime_r() is broken
Other curl-related news since the previous public release: Other curl-related news since the previous public release:
o cURLpp 0.5.2 was released at http://rrette.com/curlpp.html o http://curl.freemirror.de/ is a new German mirror
o Rexx/CURL 1.3 was released at http://rexxcurl.sf.net/ o All curl relatd mailing list information and subscribers on cool.haxx.se
o http://curl.miscellaneousmirror.org is a new German curl mirror were lost due to a malicious user exploiting a security hole on the
o LuaCURL by Alexander Marinov at http://luacurl.luaforge.net/ server. Attempts have been made to put back susbcribers on the lists, but
o http://curl.hostingzero.com/ is a new US curl mirror many have been lost: http://curl.haxx.se/mail/lost.html
o ocurl 0.2.1 was released at http://sourceforge.net/projects/ocurl o New S-Lang binding: http://curl.haxx.se/libcurl/slang/
o TclCurl 0.14.1: http://personal1.iddeo.es/andresgarci/tclcurl/english/
o pycurl 7.14.1: http://pycurl.sf.net/
This release would not have looked like this without help, code, reports and This release would not have looked like this without help, code, reports and
advice from friends like these: advice from friends like these:
John McGowan, Georg Wicherski, Andres Garcia, Eric Cooper, Todd Kulesza, o John Kelly, Nicolas Fran<61>ois, Scott Davis, Ben Madsen, Dmitry Bartsevich,
Tupone Alfredo, Gisle Vanem, David Shaw, Andrew Bushnell, Dan Fandrich, David Yan, Michael Wallner, Domenico Andreoli, Darryl House
Adrian Schuur, Diego Casorran, Peteris Krumins, Jon Grubbs, Christopher
R. Palmer, Mario Schroeder, Richard Clayton, James Bursa, Jeff Pohlmeyer,
Norbert Novotny, Toby Peterson, Simon Josefsson, Igor Polyakov, Kevin Lussier
Thanks! (and sorry if I forgot to mention someone) Thanks! (and sorry if I forgot to mention someone)

View File

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

View File

@@ -1,5 +1,17 @@
Changelog for the c-ares project Changelog for the c-ares project
* September 18
- Added constants that will be used by ares_getaddrinfo
- Made ares_getnameinfo use the reentrant getservbyport (getservbyport_r) if it is
available to ensure it works properly in a threaded environment.
* September 10
- configure fix for detecting a member in the sockaddr_in6 struct which failed
on ipv6-enabled HP-UX 11.00
Version 1.3.0 (August 29, 2004) Version 1.3.0 (August 29, 2004)
* August 21 * August 21

View File

@@ -1,291 +1,318 @@
dnl Check for how to set a socket to non-blocking state. There seems to exist dnl Check for how to set a socket to non-blocking state. There seems to exist
dnl four known different ways, with the one used almost everywhere being POSIX dnl four known different ways, with the one used almost everywhere being POSIX
dnl and XPG3, while the other different ways for different systems (old BSD, dnl and XPG3, while the other different ways for different systems (old BSD,
dnl Windows and Amiga). dnl Windows and Amiga).
dnl dnl
dnl There are two known platforms (AIX 3.x and SunOS 4.1.x) where the dnl There are two known platforms (AIX 3.x and SunOS 4.1.x) where the
dnl O_NONBLOCK define is found but does not work. This condition is attempted dnl O_NONBLOCK define is found but does not work. This condition is attempted
dnl to get caught in this script by using an excessive number of #ifdefs... dnl to get caught in this script by using an excessive number of #ifdefs...
dnl dnl
AC_DEFUN([CURL_CHECK_NONBLOCKING_SOCKET], AC_DEFUN([CURL_CHECK_NONBLOCKING_SOCKET],
[ [
AC_MSG_CHECKING([non-blocking sockets style]) AC_MSG_CHECKING([non-blocking sockets style])
AC_TRY_COMPILE([ AC_TRY_COMPILE([
/* headers for O_NONBLOCK test */ /* headers for O_NONBLOCK test */
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
],[ ],[
/* try to compile O_NONBLOCK */ /* try to compile O_NONBLOCK */
#if defined(sun) || defined(__sun__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) #if defined(sun) || defined(__sun__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
# if defined(__SVR4) || defined(__srv4__) # if defined(__SVR4) || defined(__srv4__)
# define PLATFORM_SOLARIS # define PLATFORM_SOLARIS
# else # else
# define PLATFORM_SUNOS4 # define PLATFORM_SUNOS4
# endif # endif
#endif #endif
#if (defined(_AIX) || defined(__xlC__)) && !defined(_AIX4) #if (defined(_AIX) || defined(__xlC__)) && !defined(_AIX4)
# define PLATFORM_AIX_V3 # define PLATFORM_AIX_V3
#endif #endif
#if defined(PLATFORM_SUNOS4) || defined(PLATFORM_AIX_V3) || defined(__BEOS__) #if defined(PLATFORM_SUNOS4) || defined(PLATFORM_AIX_V3) || defined(__BEOS__)
#error "O_NONBLOCK does not work on this platform" #error "O_NONBLOCK does not work on this platform"
#endif #endif
int socket; int socket;
int flags = fcntl(socket, F_SETFL, flags | O_NONBLOCK); int flags = fcntl(socket, F_SETFL, flags | O_NONBLOCK);
],[ ],[
dnl the O_NONBLOCK test was fine dnl the O_NONBLOCK test was fine
nonblock="O_NONBLOCK" nonblock="O_NONBLOCK"
AC_DEFINE(HAVE_O_NONBLOCK, 1, [use O_NONBLOCK for non-blocking sockets]) AC_DEFINE(HAVE_O_NONBLOCK, 1, [use O_NONBLOCK for non-blocking sockets])
],[ ],[
dnl the code was bad, try a different program now, test 2 dnl the code was bad, try a different program now, test 2
AC_TRY_COMPILE([ AC_TRY_COMPILE([
/* headers for FIONBIO test */ /* headers for FIONBIO test */
#include <unistd.h> #include <unistd.h>
#include <stropts.h> #include <stropts.h>
],[ ],[
/* FIONBIO source test (old-style unix) */ /* FIONBIO source test (old-style unix) */
int socket; int socket;
int flags = ioctl(socket, FIONBIO, &flags); int flags = ioctl(socket, FIONBIO, &flags);
],[ ],[
dnl FIONBIO test was good dnl FIONBIO test was good
nonblock="FIONBIO" nonblock="FIONBIO"
AC_DEFINE(HAVE_FIONBIO, 1, [use FIONBIO for non-blocking sockets]) AC_DEFINE(HAVE_FIONBIO, 1, [use FIONBIO for non-blocking sockets])
],[ ],[
dnl FIONBIO test was also bad dnl FIONBIO test was also bad
dnl the code was bad, try a different program now, test 3 dnl the code was bad, try a different program now, test 3
AC_TRY_COMPILE([ AC_TRY_COMPILE([
/* headers for ioctlsocket test (cygwin?) */ /* headers for ioctlsocket test (cygwin?) */
#include <windows.h> #include <windows.h>
],[ ],[
/* ioctlsocket source code */ /* ioctlsocket source code */
int socket; int socket;
unsigned long flags = ioctlsocket(socket, FIONBIO, &flags); unsigned long flags = ioctlsocket(socket, FIONBIO, &flags);
],[ ],[
dnl ioctlsocket test was good dnl ioctlsocket test was good
nonblock="ioctlsocket" nonblock="ioctlsocket"
AC_DEFINE(HAVE_IOCTLSOCKET, 1, [use ioctlsocket() for non-blocking sockets]) AC_DEFINE(HAVE_IOCTLSOCKET, 1, [use ioctlsocket() for non-blocking sockets])
],[ ],[
dnl ioctlsocket didnt compile!, go to test 4 dnl ioctlsocket didnt compile!, go to test 4
AC_TRY_LINK([ AC_TRY_LINK([
/* headers for IoctlSocket test (Amiga?) */ /* headers for IoctlSocket test (Amiga?) */
#include <sys/ioctl.h> #include <sys/ioctl.h>
],[ ],[
/* IoctlSocket source code */ /* IoctlSocket source code */
int socket; int socket;
int flags = IoctlSocket(socket, FIONBIO, (long)1); int flags = IoctlSocket(socket, FIONBIO, (long)1);
],[ ],[
dnl ioctlsocket test was good dnl ioctlsocket test was good
nonblock="IoctlSocket" nonblock="IoctlSocket"
AC_DEFINE(HAVE_IOCTLSOCKET_CASE, 1, [use Ioctlsocket() for non-blocking sockets]) AC_DEFINE(HAVE_IOCTLSOCKET_CASE, 1, [use Ioctlsocket() for non-blocking sockets])
],[ ],[
dnl Ioctlsocket didnt compile, do test 5! dnl Ioctlsocket didnt compile, do test 5!
AC_TRY_COMPILE([ AC_TRY_COMPILE([
/* headers for SO_NONBLOCK test (BeOS) */ /* headers for SO_NONBLOCK test (BeOS) */
#include <socket.h> #include <socket.h>
],[ ],[
/* SO_NONBLOCK source code */ /* SO_NONBLOCK source code */
long b = 1; long b = 1;
int socket; int socket;
int flags = setsockopt(socket, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b)); int flags = setsockopt(socket, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b));
],[ ],[
dnl the SO_NONBLOCK test was good dnl the SO_NONBLOCK test was good
nonblock="SO_NONBLOCK" nonblock="SO_NONBLOCK"
AC_DEFINE(HAVE_SO_NONBLOCK, 1, [use SO_NONBLOCK for non-blocking sockets]) AC_DEFINE(HAVE_SO_NONBLOCK, 1, [use SO_NONBLOCK for non-blocking sockets])
],[ ],[
dnl test 5 didnt compile! dnl test 5 didnt compile!
nonblock="nada" nonblock="nada"
AC_DEFINE(HAVE_DISABLED_NONBLOCKING, 1, [disabled non-blocking sockets]) AC_DEFINE(HAVE_DISABLED_NONBLOCKING, 1, [disabled non-blocking sockets])
]) ])
dnl end of fifth test dnl end of fifth test
]) ])
dnl end of forth test dnl end of forth test
]) ])
dnl end of third test dnl end of third test
]) ])
dnl end of second test dnl end of second test
]) ])
dnl end of non-blocking try-compile test dnl end of non-blocking try-compile test
AC_MSG_RESULT($nonblock) AC_MSG_RESULT($nonblock)
if test "$nonblock" = "nada"; then if test "$nonblock" = "nada"; then
AC_MSG_WARN([non-block sockets disabled]) AC_MSG_WARN([non-block sockets disabled])
fi fi
]) ])
dnl We create a function for detecting which compiler we use and then set as dnl We create a function for detecting which compiler we use and then set as
dnl pendantic compiler options as possible for that particular compiler. The dnl pendantic compiler options as possible for that particular compiler. The
dnl options are only used for debug-builds. dnl options are only used for debug-builds.
dnl This is a copy of the original found in curl's configure script. Don't dnl This is a copy of the original found in curl's configure script. Don't
dnl modify this one, edit the one in curl and copy it back here when that one dnl modify this one, edit the one in curl and copy it back here when that one
dnl is changed. dnl is changed.
AC_DEFUN([CURL_CC_DEBUG_OPTS], AC_DEFUN([CURL_CC_DEBUG_OPTS],
[ [
if test "$GCC" = "yes"; then if test "$GCC" = "yes"; then
dnl figure out gcc version! dnl figure out gcc version!
AC_MSG_CHECKING([gcc version]) AC_MSG_CHECKING([gcc version])
gccver=`$CC -dumpversion` gccver=`$CC -dumpversion`
num1=`echo $gccver | cut -d . -f1` num1=`echo $gccver | cut -d . -f1`
num2=`echo $gccver | cut -d . -f2` num2=`echo $gccver | cut -d . -f2`
gccnum=`(expr $num1 "*" 100 + $num2) 2>/dev/null` gccnum=`(expr $num1 "*" 100 + $num2) 2>/dev/null`
AC_MSG_RESULT($gccver) AC_MSG_RESULT($gccver)
AC_MSG_CHECKING([if this is icc in disguise]) AC_MSG_CHECKING([if this is icc in disguise])
AC_EGREP_CPP([^__INTEL_COMPILER], [__INTEL_COMPILER], AC_EGREP_CPP([^__INTEL_COMPILER], [__INTEL_COMPILER],
dnl action if the text is found, this it has not been replaced by the dnl action if the text is found, this it has not been replaced by the
dnl cpp dnl cpp
ICC="no" ICC="no"
AC_MSG_RESULT([no]), AC_MSG_RESULT([no]),
dnl the text was not found, it was replaced by the cpp dnl the text was not found, it was replaced by the cpp
ICC="yes" ICC="yes"
AC_MSG_RESULT([yes]) AC_MSG_RESULT([yes])
) )
if test "$ICC" = "yes"; then if test "$ICC" = "yes"; then
dnl this is icc, not gcc. dnl this is icc, not gcc.
dnl ICC warnings we ignore: dnl ICC warnings we ignore:
dnl * 279 warns on static conditions in while expressions dnl * 279 warns on static conditions in while expressions
dnl * 269 warns on our "%Od" printf formatters for curl_off_t output: dnl * 269 warns on our "%Od" printf formatters for curl_off_t output:
dnl "invalid format string conversion" dnl "invalid format string conversion"
WARN="-wd279,269" WARN="-wd279,269"
if test "$gccnum" -gt "600"; then if test "$gccnum" -gt "600"; then
dnl icc 6.0 and older doesn't have the -Wall flag dnl icc 6.0 and older doesn't have the -Wall flag
WARN="-Wall $WARN" WARN="-Wall $WARN"
fi fi
else dnl $ICC = yes else dnl $ICC = yes
dnl dnl
WARN="-W -Wall -Wwrite-strings -pedantic -Wno-long-long -Wundef -Wpointer-arith -Wnested-externs -Winline -Wmissing-declarations -Wmissing-prototypes -Wsign-compare" WARN="-W -Wall -Wwrite-strings -pedantic -Wno-long-long -Wundef -Wpointer-arith -Wnested-externs -Winline -Wmissing-declarations -Wmissing-prototypes -Wsign-compare"
dnl -Wcast-align is a bit too annoying ;-) dnl -Wcast-align is a bit too annoying ;-)
if test "$gccnum" -ge "296"; then if test "$gccnum" -ge "296"; then
dnl gcc 2.96 or later dnl gcc 2.96 or later
WARN="$WARN -Wfloat-equal" WARN="$WARN -Wfloat-equal"
if test "$gccnum" -gt "296"; then if test "$gccnum" -gt "296"; then
dnl this option does not exist in 2.96 dnl this option does not exist in 2.96
WARN="$WARN -Wno-format-nonliteral" WARN="$WARN -Wno-format-nonliteral"
fi fi
dnl -Wunreachable-code seems totally unreliable on my gcc 3.3.2 on dnl -Wunreachable-code seems totally unreliable on my gcc 3.3.2 on
dnl on i686-Linux as it gives us heaps with false positives dnl on i686-Linux as it gives us heaps with false positives
if test "$gccnum" -ge "303"; then if test "$gccnum" -ge "303"; then
dnl gcc 3.3 and later dnl gcc 3.3 and later
WARN="$WARN -Wendif-labels -Wstrict-prototypes" WARN="$WARN -Wendif-labels -Wstrict-prototypes"
fi fi
fi fi
for flag in $CPPFLAGS; do for flag in $CPPFLAGS; do
case "$flag" in case "$flag" in
-I*) -I*)
dnl include path dnl include path
add=`echo $flag | sed 's/^-I/-isystem /g'` add=`echo $flag | sed 's/^-I/-isystem /g'`
WARN="$WARN $add" WARN="$WARN $add"
;; ;;
esac esac
done done
fi dnl $ICC = no fi dnl $ICC = no
CFLAGS="$CFLAGS $WARN" CFLAGS="$CFLAGS $WARN"
fi dnl $GCC = yes fi dnl $GCC = yes
dnl strip off optimizer flags dnl strip off optimizer flags
NEWFLAGS="" NEWFLAGS=""
for flag in $CFLAGS; do for flag in $CFLAGS; do
case "$flag" in case "$flag" in
-O*) -O*)
dnl echo "cut off $flag" dnl echo "cut off $flag"
;; ;;
*) *)
NEWFLAGS="$NEWFLAGS $flag" NEWFLAGS="$NEWFLAGS $flag"
;; ;;
esac esac
done done
CFLAGS=$NEWFLAGS CFLAGS=$NEWFLAGS
]) dnl end of AC_DEFUN() ]) dnl end of AC_DEFUN()
dnl This macro determines if the specified struct exists in the specified file dnl This macro determines if the specified struct exists in the specified file
dnl Syntax: dnl Syntax:
dnl CARES_CHECK_STRUCT(headers, struct name, if found, [if not found]) dnl CARES_CHECK_STRUCT(headers, struct name, if found, [if not found])
AC_DEFUN([CARES_CHECK_STRUCT], [ AC_DEFUN([CARES_CHECK_STRUCT], [
AC_MSG_CHECKING([for struct $2]) AC_MSG_CHECKING([for struct $2])
AC_TRY_COMPILE([$1], AC_TRY_COMPILE([$1],
[ [
struct $2 struct_instance; struct $2 struct_instance;
], ac_struct="yes", ac_found="no") ], ac_struct="yes", ac_found="no")
if test "$ac_struct" = "yes" ; then if test "$ac_struct" = "yes" ; then
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
$3 $3
else else
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
$4 $4
fi fi
]) ])
dnl This macro determins if the specified struct contains a specific member. dnl This macro determines if the specified constant exists in the specified file
dnl Syntax: dnl Syntax:
dnl CARES_CHECK_STRUCT_MEMBER(headers, struct name, member name, if found, [if not found]) dnl CARES_CHECK_CONSTANT(headers, constant name, if found, [if not found])
AC_DEFUN([CARES_CHECK_STRUCT_MEMBER], [ AC_DEFUN([CARES_CHECK_CONSTANT], [
AC_MSG_CHECKING([if struct $2 has member $3]) AC_MSG_CHECKING([for $2])
AC_TRY_COMPILE([$1], AC_EGREP_CPP(VARIABLEWASDEFINED,
[ [
struct $2 struct_instance; $1
struct_instance.$3 = 0;
], ac_struct="yes", ac_found="no") #ifdef $2
if test "$ac_struct" = "yes" ; then VARIABLEWASDEFINED
AC_MSG_RESULT(yes) #else
$4 NJET
else #endif
AC_MSG_RESULT(no) ], ac_constant="yes", ac_constant="no"
$5 )
fi if test "$ac_constant" = "yes" ; then
]) AC_MSG_RESULT(yes)
$3
dnl This macro determines if the specified constant exists in the specified file else
dnl Syntax: AC_MSG_RESULT(no)
dnl CARES_CHECK_CONSTANT(headers, constant name, if found, [if not found]) $4
fi
AC_DEFUN([CARES_CHECK_CONSTANT], [ ])
AC_MSG_CHECKING([for $2])
AC_EGREP_CPP(VARIABLEWASDEFINED,
[ dnl This macro determines how many parameters getservbyport_r takes
$1 AC_DEFUN([CARES_CHECK_GETSERVBYPORT_R], [
AC_MSG_CHECKING([how many arguments getservbyport_r takes])
#ifdef $2 AC_TRY_COMPILE(
VARIABLEWASDEFINED [#include <netdb.h>],
#else [
NJET int p1, p5;
#endif char *p2, p4[4096];
], ac_constant="yes", ac_constant="no" struct servent *p3, *p6;
) getservbyport_r(p1, p2, p3, p4, p5, &p6);
if test "$ac_constant" = "yes" ; then ], ac_func_getservbyport_r=6,
AC_MSG_RESULT(yes) [AC_TRY_COMPILE(
$3 [#include <netdb.h>],
else [
AC_MSG_RESULT(no) int p1, p5;
$4 char *p2, p4[4096];
fi struct servent *p3;
]) getservbyport_r(p1, p2, p3, p4, p5);
], ac_func_getservbyport_r=5,
[AC_TRY_COMPILE(
[#include <netdb.h>],
[
int p1;
char *p2;
struct servent *p3;
struct servent_data p4;
getservbyport_r(p1, p2, p3, &p4);
], ac_func_getservbyport_r=4, ac_func_getservbyport_r=0
)]
)]
)
if test $ac_func_getservbyport_r != "0" ; then
AC_MSG_RESULT($ac_func_getservbyport_r)
AC_DEFINE(HAVE_GETSERVBYPORT_R, 1, [Specifies whether getservbyport_r is present])
AC_DEFINE_UNQUOTED(GETSERVBYPORT_R_ARGS, $ac_func_getservbyport_r, [Specifies the number of arguments to
getservbyport_r])
if test $ac_func_getservbyport_r = "4" ; then
AC_DEFINE(GETSERVBYPORT_R_BUFSIZE, sizeof(struct servent_data), [Specifies the size of the buffer to pass to
getservbyport_r])
else
AC_DEFINE(GETSERVBYPORT_R_BUFSIZE, 4096, [Specifies the size of the buffer to pass to getservbyport_r])
fi
else
AC_MSG_RESULT([not found])
fi
])

View File

@@ -69,6 +69,10 @@ extern "C" {
/* ares_getnameinfo error codes */ /* ares_getnameinfo error codes */
#define ARES_EBADFLAGS 18 #define ARES_EBADFLAGS 18
/* ares_getaddrinfo error codes */
#define ARES_ENONAME 19
#define ARES_EBADHINTS 20
/* Flag values */ /* Flag values */
#define ARES_FLAG_USEVC (1 << 0) #define ARES_FLAG_USEVC (1 << 0)
#define ARES_FLAG_PRIMARY (1 << 1) #define ARES_FLAG_PRIMARY (1 << 1)
@@ -104,9 +108,27 @@ extern "C" {
#define ARES_NI_LOOKUPHOST (1 << 8) #define ARES_NI_LOOKUPHOST (1 << 8)
#define ARES_NI_LOOKUPSERVICE (1 << 9) #define ARES_NI_LOOKUPSERVICE (1 << 9)
/* Reserved for future use */ /* Reserved for future use */
#define ARES_NI_IDN (1 << 10) #define ARES_NI_IDN (1 << 10)
#define ARES_NI_ALLOW_UNASSIGNED (1 << 11) #define ARES_NI_IDN_ALLOW_UNASSIGNED (1 << 11)
#define ARES_NI_USE_STD3_ASCII_RULES (1 << 12) #define ARES_NI_IDN_USE_STD3_ASCII_RULES (1 << 12)
/* Addrinfo flag values */
#define ARES_AI_CANONNAME (1 << 0)
#define ARES_AI_NUMERICHOST (1 << 1)
#define ARES_AI_PASSIVE (1 << 2)
#define ARES_AI_NUMERICSERV (1 << 3)
#define ARES_AI_V4MAPPED (1 << 4)
#define ARES_AI_ALL (1 << 5)
#define ARES_AI_ADDRCONFIG (1 << 6)
/* Reserved for future use */
#define ARES_AI_IDN (1 << 10)
#define ARES_AI_IDN_ALLOW_UNASSIGNED (1 << 11)
#define ARES_AI_IDN_USE_STD3_ASCII_RULES (1 << 12)
#define ARES_AI_CANONIDN (1 << 13)
#define ARES_AI_MASK (ARES_AI_CANONNAME|ARES_AI_NUMERICHOST|ARES_AI_PASSIVE| \
ARES_AI_NUMERICSERV|ARES_AI_V4MAPPED|ARES_AI_ALL| \
ARES_AI_ADDRCONFIG)
struct ares_options { struct ares_options {
int flags; int flags;

View File

@@ -123,7 +123,7 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, socklen_t
char *service = NULL; char *service = NULL;
ipbuf[0] = 0; ipbuf[0] = 0;
/* Specifying not to lookup a host, but then saying a host /* Specifying not to lookup a host, but then saying a host
* is required has to be illegal. * is required has to be illegal.
*/ */
if (flags & ARES_NI_NAMEREQD) if (flags & ARES_NI_NAMEREQD)
@@ -163,18 +163,18 @@ void ares_getnameinfo(ares_channel channel, const struct sockaddr *sa, socklen_t
niquery->callback = callback; niquery->callback = callback;
niquery->arg = arg; niquery->arg = arg;
niquery->flags = flags; niquery->flags = flags;
if (sa->sa_family == AF_INET) if (sa->sa_family == AF_INET)
{ {
niquery->family = AF_INET; niquery->family = AF_INET;
memcpy(&niquery->addr.addr4, addr, sizeof(addr)); memcpy(&niquery->addr.addr4, addr, sizeof(addr));
ares_gethostbyaddr(channel, &addr->sin_addr, sizeof(struct in_addr), AF_INET, ares_gethostbyaddr(channel, &addr->sin_addr, sizeof(struct in_addr), AF_INET,
nameinfo_callback, niquery); nameinfo_callback, niquery);
} }
else else
{ {
niquery->family = AF_INET6; niquery->family = AF_INET6;
memcpy(&niquery->addr.addr6, addr6, sizeof(addr6)); memcpy(&niquery->addr.addr6, addr6, sizeof(addr6));
ares_gethostbyaddr(channel, &addr6->sin6_addr, sizeof(struct in6_addr), AF_INET6, ares_gethostbyaddr(channel, &addr6->sin6_addr, sizeof(struct in6_addr), AF_INET6,
nameinfo_callback, niquery); nameinfo_callback, niquery);
} }
} }
@@ -194,9 +194,11 @@ static void nameinfo_callback(void *arg, int status, struct hostent *host)
if (niquery->flags & ARES_NI_LOOKUPSERVICE) if (niquery->flags & ARES_NI_LOOKUPSERVICE)
{ {
if (niquery->family == AF_INET) if (niquery->family == AF_INET)
service = lookup_service(niquery->addr.addr4.sin_port, niquery->flags, srvbuf); service = lookup_service(niquery->addr.addr4.sin_port,
niquery->flags, srvbuf);
else else
service = lookup_service(niquery->addr.addr6.sin6_port, niquery->flags, srvbuf); service = lookup_service(niquery->addr.addr6.sin6_port,
niquery->flags, srvbuf);
} }
/* NOFQDN means we have to strip off the domain name portion. /* NOFQDN means we have to strip off the domain name portion.
We do this by determining our own domain name, then searching the string We do this by determining our own domain name, then searching the string
@@ -212,7 +214,7 @@ static void nameinfo_callback(void *arg, int status, struct hostent *host)
char *end = ares_striendstr(host->h_name, domain); char *end = ares_striendstr(host->h_name, domain);
if (end) if (end)
*end = 0; *end = 0;
} }
} }
niquery->callback(niquery->arg, ARES_SUCCESS, host->h_name, service); niquery->callback(niquery->arg, ARES_SUCCESS, host->h_name, service);
return; return;
@@ -234,9 +236,11 @@ static void nameinfo_callback(void *arg, int status, struct hostent *host)
if (niquery->flags & ARES_NI_LOOKUPSERVICE) if (niquery->flags & ARES_NI_LOOKUPSERVICE)
{ {
if (niquery->family == AF_INET) if (niquery->family == AF_INET)
service = lookup_service(niquery->addr.addr4.sin_port, niquery->flags, srvbuf); service = lookup_service(niquery->addr.addr4.sin_port,
niquery->flags, srvbuf);
else else
service = lookup_service(niquery->addr.addr6.sin6_port, niquery->flags, srvbuf); service = lookup_service(niquery->addr.addr6.sin6_port,
niquery->flags, srvbuf);
} }
niquery->callback(niquery->arg, ARES_SUCCESS, ipbuf, service); niquery->callback(niquery->arg, ARES_SUCCESS, ipbuf, service);
return; return;
@@ -245,7 +249,8 @@ static void nameinfo_callback(void *arg, int status, struct hostent *host)
free(niquery); free(niquery);
} }
static char *lookup_service(unsigned short port, int flags, char *buf) static char *lookup_service(unsigned short port, int flags,
char *buf) /* 33 bytes buffer */
{ {
if (port) if (port)
{ {
@@ -256,7 +261,17 @@ static char *lookup_service(unsigned short port, int flags, char *buf)
{ {
struct servent *se; struct servent *se;
const char *proto; const char *proto;
#if GETSERVBYPORT_R_ARGS == 6
struct servent ret;
char buf[4096];
int len = 4096;
#elif GETSERVBYPORT_R_ARGS == 5
char buf[4096];
int len = 4096;
#elif GETSERVBYPORT_R_ARGS == 4
struct servent ret;
struct servent_data sed;
#endif
if (flags & ARES_NI_UDP) if (flags & ARES_NI_UDP)
proto = "udp"; proto = "udp";
else if (flags & ARES_NI_SCTP) else if (flags & ARES_NI_SCTP)
@@ -265,9 +280,34 @@ static char *lookup_service(unsigned short port, int flags, char *buf)
proto = "dccp"; proto = "dccp";
else else
proto = "tcp"; proto = "tcp";
#ifdef HAVE_GETSERVBYPORT_R
#if GETSERVBYPORT_R_ARGS == 6
se = &ret;
if (getservbyport_r(port, proto, se, buf, len, &ret))
se = NULL;
#elif GETSERVBYPORT_R_ARGS == 5
se = getservbyport_r(port, proto, se, buf, len);
#elif GETSERVBYPORT_R_ARGS == 4
se = &ret;
if (getservbyport_r(port, proto, se, &sed) == -1)
se = NULL;
#else
/* Lets just hope the OS uses TLS! */
se = getservbyport(port, proto); se = getservbyport(port, proto);
if (se && se->s_name) #endif
strcpy(buf, se->s_name); #else
/* Lets just hope the OS uses TLS! */
se = getservbyport(port, proto);
#endif
if (se && se->s_name) {
size_t len = strlen(se->s_name);
if(len < 33) {
strcpy(buf, se->s_name);
}
else
/* too big name to fit the buffer */
buf[0]=0;
}
else else
sprintf(buf, "%u", ntohs(port)); sprintf(buf, "%u", ntohs(port));
} }
@@ -277,14 +317,16 @@ static char *lookup_service(unsigned short port, int flags, char *buf)
} }
#ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID #ifdef HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID
static char *append_scopeid(struct sockaddr_in6 *addr6, unsigned int flags, char *buf) static char *append_scopeid(struct sockaddr_in6 *addr6, unsigned int flags,
char *buf)
{ {
char tmpbuf[IF_NAMESIZE + 1]; char tmpbuf[IF_NAMESIZE + 1];
tmpbuf[0] = '%'; tmpbuf[0] = '%';
#ifdef HAVE_IF_INDEXTONAME #ifdef HAVE_IF_INDEXTONAME
if ((flags & ARES_NI_NUMERICSCOPE) || (!IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr) if ((flags & ARES_NI_NUMERICSCOPE) ||
&& !IN6_IS_ADDR_MC_LINKLOCAL(&addr6->sin6_addr))) (!IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr)
&& !IN6_IS_ADDR_MC_LINKLOCAL(&addr6->sin6_addr)))
{ {
sprintf(&tmpbuf[1], "%u", addr6->sin6_scope_id); sprintf(&tmpbuf[1], "%u", addr6->sin6_scope_id);
} }

View File

@@ -1,351 +1,359 @@
dnl Process this file with autoconf to produce a configure script. dnl Process this file with autoconf to produce a configure script.
AC_INIT(ares_init.c) AC_INIT(ares_init.c)
AM_CONFIG_HEADER(config.h) AM_CONFIG_HEADER(config.h)
AM_MAINTAINER_MODE AM_MAINTAINER_MODE
AM_INIT_AUTOMAKE(c-ares, CVS) AM_INIT_AUTOMAKE(c-ares, CVS)
AC_PROG_CC AC_PROG_CC
AC_PROG_INSTALL AC_PROG_INSTALL
case $host_os in case $host_os in
solaris*) solaris*)
AC_DEFINE(ETC_INET, 1, [if a /etc/inet dir is being used]) AC_DEFINE(ETC_INET, 1, [if a /etc/inet dir is being used])
;; ;;
esac esac
# check for ssize_t # check for ssize_t
AC_CHECK_TYPE(ssize_t, , AC_CHECK_TYPE(ssize_t, ,
AC_DEFINE(ssize_t, int, [the signed version of size_t])) AC_DEFINE(ssize_t, int, [the signed version of size_t]))
AC_SEARCH_LIBS(gethostbyname, nsl) AC_SEARCH_LIBS(gethostbyname, nsl)
AC_SEARCH_LIBS(socket, socket) AC_SEARCH_LIBS(socket, socket)
dnl ************************************************************ dnl ************************************************************
dnl Option to switch on debug options. This makes an assumption that dnl Option to switch on debug options. This makes an assumption that
dnl this is built as an 'ares' subdir in the curl source tree. Subject for dnl this is built as an 'ares' subdir in the curl source tree. Subject for
dnl improval in the future! dnl improval in the future!
dnl dnl
AC_MSG_CHECKING([whether to enable debug options]) AC_MSG_CHECKING([whether to enable debug options])
AC_ARG_ENABLE(debug, AC_ARG_ENABLE(debug,
AC_HELP_STRING([--enable-debug],[Enable pedantic debug options]) AC_HELP_STRING([--enable-debug],[Enable pedantic debug options])
AC_HELP_STRING([--disable-debug],[Disable debug options]), AC_HELP_STRING([--disable-debug],[Disable debug options]),
[ case "$enableval" in [ case "$enableval" in
no) no)
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
;; ;;
*) AC_MSG_RESULT(yes) *) AC_MSG_RESULT(yes)
dnl when doing the debug stuff, use static library only dnl when doing the debug stuff, use static library only
AC_DISABLE_SHARED AC_DISABLE_SHARED
dnl Checks for standard header files, to make memdebug.h inclusions bettter dnl Checks for standard header files, to make memdebug.h inclusions bettter
AC_HEADER_STDC AC_HEADER_STDC
dnl the entire --enable-debug is a hack that lives and runs on top of dnl the entire --enable-debug is a hack that lives and runs on top of
dnl libcurl stuff so this BUILDING_LIBCURL is not THAT much uglier dnl libcurl stuff so this BUILDING_LIBCURL is not THAT much uglier
AC_DEFINE(BUILDING_LIBCURL, 1, [when building as static part of libcurl]) AC_DEFINE(BUILDING_LIBCURL, 1, [when building as static part of libcurl])
CPPFLAGS="$CPPFLAGS -DCURLDEBUG -I$srcdir/../include" CPPFLAGS="$CPPFLAGS -DCURLDEBUG -I$srcdir/../include"
CFLAGS="$CFLAGS -g" CFLAGS="$CFLAGS -g"
dnl set compiler "debug" options to become more picky, and remove dnl set compiler "debug" options to become more picky, and remove
dnl optimize options from CFLAGS dnl optimize options from CFLAGS
CURL_CC_DEBUG_OPTS CURL_CC_DEBUG_OPTS
;; ;;
esac ], esac ],
AC_MSG_RESULT(no) AC_MSG_RESULT(no)
) )
AC_PROG_LIBTOOL AC_PROG_LIBTOOL
dnl check for a few basic system headers we need dnl check for a few basic system headers we need
AC_CHECK_HEADERS( AC_CHECK_HEADERS(
sys/types.h \ sys/types.h \
sys/time.h \ sys/time.h \
sys/select.h \ sys/select.h \
sys/socket.h \ sys/socket.h \
sys/ioctl.h \ sys/ioctl.h \
winsock.h \ netdb.h \
netinet/in.h \ winsock.h \
net/if.h \ netinet/in.h \
arpa/nameser.h \ net/if.h \
arpa/nameser_compat.h \ arpa/nameser.h \
arpa/inet.h, , , arpa/nameser_compat.h \
[ arpa/inet.h, , ,
#ifdef HAVE_SYS_TYPES_H [
#include <sys/types.h> #ifdef HAVE_SYS_TYPES_H
#endif #include <sys/types.h>
dnl We do this default-include simply to make sure that the nameser_compat.h #endif
dnl header *REALLY* can be include after the new nameser.h. It seems AIX 5.1 dnl We do this default-include simply to make sure that the nameser_compat.h
dnl (and others?) is not designed to allow this. dnl header *REALLY* can be include after the new nameser.h. It seems AIX 5.1
#ifdef HAVE_ARPA_NAMESER_H dnl (and others?) is not designed to allow this.
#include <arpa/nameser.h> #ifdef HAVE_ARPA_NAMESER_H
#endif #include <arpa/nameser.h>
#endif
dnl *Sigh* these are needed in order for net/if.h to get properly detected.
#ifdef HAVE_SYS_SOCKET_H dnl *Sigh* these are needed in order for net/if.h to get properly detected.
#include <sys/socket.h> #ifdef HAVE_SYS_SOCKET_H
#endif #include <sys/socket.h>
#ifdef HAVE_WINSOCK_H #endif
#include <winsock.h> #ifdef HAVE_WINSOCK_H
#endif #include <winsock.h>
] #endif
) ]
)
AC_CHECK_TYPE(socklen_t, ,
AC_DEFINE(socklen_t, int, [the length of a socket address]), AC_CHECK_TYPE(socklen_t, ,
[ AC_DEFINE(socklen_t, int, [the length of a socket address]),
#ifdef HAVE_SYS_TYPES_H [
#include <sys/types.h> #ifdef HAVE_SYS_TYPES_H
#endif #include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H #endif
#include <sys/socket.h> #ifdef HAVE_SYS_SOCKET_H
#endif #include <sys/socket.h>
#ifdef HAVE_WINSOCK_H #endif
#include <winsock.h> #ifdef HAVE_WINSOCK_H
#endif #include <winsock.h>
]) #endif
])
dnl check for AF_INET6
CARES_CHECK_CONSTANT( dnl check for AF_INET6
[ CARES_CHECK_CONSTANT(
#ifdef HAVE_SYS_TYPES_H [
#include <sys/types.h> #ifdef HAVE_SYS_TYPES_H
#endif #include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H #endif
#include <sys/socket.h> #ifdef HAVE_SYS_SOCKET_H
#endif #include <sys/socket.h>
#ifdef HAVE_WINSOCK_H #endif
#include <winsock.h> #ifdef HAVE_WINSOCK_H
#endif #include <winsock.h>
#endif
], [PF_INET6],
AC_DEFINE_UNQUOTED(HAVE_PF_INET6,1,[Define to 1 if you have PF_INET6.]) ], [PF_INET6],
) AC_DEFINE_UNQUOTED(HAVE_PF_INET6,1,[Define to 1 if you have PF_INET6.])
)
dnl check for PF_INET6
CARES_CHECK_CONSTANT( dnl check for PF_INET6
[ CARES_CHECK_CONSTANT(
#ifdef HAVE_SYS_TYPES_H [
#include <sys/types.h> #ifdef HAVE_SYS_TYPES_H
#endif #include <sys/types.h>
#ifdef HAVE_SYS_SOCKET_H #endif
#include <sys/socket.h> #ifdef HAVE_SYS_SOCKET_H
#endif #include <sys/socket.h>
#ifdef HAVE_WINSOCK_H #endif
#include <winsock.h> #ifdef HAVE_WINSOCK_H
#endif #include <winsock.h>
#endif
], [AF_INET6],
AC_DEFINE_UNQUOTED(HAVE_AF_INET6,1,[Define to 1 if you have AF_INET6.]) ], [AF_INET6],
) AC_DEFINE_UNQUOTED(HAVE_AF_INET6,1,[Define to 1 if you have AF_INET6.])
)
dnl check for the in6_addr structure
CARES_CHECK_STRUCT( dnl check for the in6_addr structure
[ CARES_CHECK_STRUCT(
#ifdef HAVE_SYS_TYPES_H [
#include <sys/types.h> #ifdef HAVE_SYS_TYPES_H
#endif #include <sys/types.h>
#ifdef HAVE_WINSOCK_H #endif
#include <winsock.h> #ifdef HAVE_WINSOCK_H
#endif #include <winsock.h>
#ifdef HAVE_NETINET_IN_H #endif
#include <netinet/in.h> #ifdef HAVE_NETINET_IN_H
#endif #include <netinet/in.h>
], [in6_addr], #endif
AC_DEFINE_UNQUOTED(HAVE_STRUCT_IN6_ADDR,1,[Define to 1 if you have struct in6_addr.]) ], [in6_addr],
) AC_DEFINE_UNQUOTED(HAVE_STRUCT_IN6_ADDR,1,[Define to 1 if you have struct in6_addr.])
)
dnl check for the sockaddr_in6 structure
CARES_CHECK_STRUCT( dnl check for the sockaddr_in6 structure
[ CARES_CHECK_STRUCT(
#ifdef HAVE_SYS_TYPES_H [
#include <sys/types.h> #ifdef HAVE_SYS_TYPES_H
#endif #include <sys/types.h>
#ifdef HAVE_WINSOCK_H #endif
#include <winsock.h> #ifdef HAVE_WINSOCK_H
#endif #include <winsock.h>
#ifdef HAVE_NETINET_IN_H #endif
#include <netinet/in.h> #ifdef HAVE_NETINET_IN_H
#endif #include <netinet/in.h>
], [sockaddr_in6], #endif
AC_DEFINE_UNQUOTED(HAVE_STRUCT_SOCKADDR_IN6,1, ], [sockaddr_in6],
[Define to 1 if you have struct sockaddr_in6.]) ac_have_sockaddr_in6=yes AC_DEFINE_UNQUOTED(HAVE_STRUCT_SOCKADDR_IN6,1,
) [Define to 1 if you have struct sockaddr_in6.]) ac_have_sockaddr_in6=yes
)
if test "$ac_have_sockaddr_in6" = "yes" ; then
CARES_CHECK_STRUCT_MEMBER( AC_CHECK_MEMBER(struct sockaddr_in6.sin6_scope_id,
[ AC_DEFINE_UNQUOTED(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID,1,
#ifdef HAVE_SYS_TYPES_H [Define to 1 if your struct sockaddr_in6 has sin6_scope_id.])
#include <sys/types.h> , ,
#endif [
#ifdef HAVE_WINSOCK_H #ifdef HAVE_SYS_TYPES_H
#include <winsock.h> #include <sys/types.h>
#endif #endif
#ifdef HAVE_NETINET_IN_H #ifdef HAVE_WINSOCK_H
#include <netinet/in.h> #include <winsock.h>
#endif #endif
], [sockaddr_in6], [sin6_scope_id], #ifdef HAVE_NETINET_IN_H
AC_DEFINE_UNQUOTED(HAVE_SOCKADDR_IN6_SIN6_SCOPE_ID,1, #include <netinet/in.h>
[Define to 1 if your struct sockaddr_in6 has sin6_scope_id.]) #endif
) ])
fi
dnl check for the addrinfo structure
dnl check for the addrinfo structure AC_CHECK_MEMBER(struct addrinfo.ai_flags,
CARES_CHECK_STRUCT( AC_DEFINE_UNQUOTED(HAVE_STRUCT_ADDRINFO,1,
[ [Define to 1 if you have struct addrinfo.]),,
#ifdef HAVE_SYS_TYPES_H [
#include <sys/types.h> #ifdef HAVE_SYS_TYPES_H
#endif #include <sys/types.h>
#ifdef HAVE_WINSOCK_H #endif
#include <winsock.h> #ifdef HAVE_WINSOCK_H
#endif #include <winsock.h>
#ifdef HAVE_NETINET_IN_H #endif
#include <netinet/in.h> #ifdef HAVE_NETINET_IN_H
#endif #include <netinet/in.h>
], [addrinfo], #endif
AC_DEFINE_UNQUOTED(HAVE_STRUCT_ADDRINFO,1, #ifdef HAVE_SYS_SOCKET_H
[Define to 1 if you have struct addrinfo.]) #include <sys/socket.h>
) #endif
#ifdef HAVE_NETDB_H
dnl check for inet_pton #include <netdb.h>
AC_CHECK_FUNCS(inet_pton) #endif
dnl Some systems have it, but not IPv6 ]
if test "$ac_cv_func_inet_pton" = "yes" ; then )
AC_MSG_CHECKING(if inet_pton supports IPv6)
AC_TRY_RUN( dnl check for inet_pton
[ AC_CHECK_FUNCS(inet_pton)
#ifdef HAVE_SYS_TYPES_H dnl Some systems have it, but not IPv6
#include <sys/types.h> if test "$ac_cv_func_inet_pton" = "yes" ; then
#endif AC_MSG_CHECKING(if inet_pton supports IPv6)
#ifdef HAVE_SYS_SOCKET_H AC_TRY_RUN(
#include <sys/socket.h> [
#endif #ifdef HAVE_SYS_TYPES_H
#ifdef HAVE_WINSOCK_H #include <sys/types.h>
#include <winsock.h> #endif
#endif #ifdef HAVE_SYS_SOCKET_H
#ifdef HAVE_NETINET_IN_H #include <sys/socket.h>
#include <netinet/in.h> #endif
#endif #ifdef HAVE_WINSOCK_H
int main() #include <winsock.h>
{ #endif
struct in6_addr addr6; #ifdef HAVE_NETINET_IN_H
if (inet_pton(AF_INET6, "::1", &addr6) < 1) #include <netinet/in.h>
exit(1); #endif
else int main()
exit(0); {
} struct in6_addr addr6;
], [ if (inet_pton(AF_INET6, "::1", &addr6) < 1)
AC_MSG_RESULT(yes) exit(1);
AC_DEFINE_UNQUOTED(HAVE_INET_PTON_IPV6,1,[Define to 1 if inet_pton supports IPv6.]) else
], AC_MSG_RESULT(no),AC_MSG_RESULT(no)) exit(0);
fi }
dnl Check for inet_net_pton ], [
AC_CHECK_FUNCS(inet_net_pton) AC_MSG_RESULT(yes)
dnl Again, some systems have it, but not IPv6 AC_DEFINE_UNQUOTED(HAVE_INET_PTON_IPV6,1,[Define to 1 if inet_pton supports IPv6.])
if test "$ac_cv_func_inet_net_pton" = "yes" ; then ], AC_MSG_RESULT(no),AC_MSG_RESULT(no))
AC_MSG_CHECKING(if inet_net_pton supports IPv6) fi
AC_TRY_RUN( dnl Check for inet_net_pton
[ AC_CHECK_FUNCS(inet_net_pton)
#ifdef HAVE_SYS_TYPES_H dnl Again, some systems have it, but not IPv6
#include <sys/types.h> if test "$ac_cv_func_inet_net_pton" = "yes" ; then
#endif AC_MSG_CHECKING(if inet_net_pton supports IPv6)
#ifdef HAVE_SYS_SOCKET_H AC_TRY_RUN(
#include <sys/socket.h> [
#endif #ifdef HAVE_SYS_TYPES_H
#ifdef HAVE_WINSOCK_H #include <sys/types.h>
#include <winsock.h> #endif
#endif #ifdef HAVE_SYS_SOCKET_H
#ifdef HAVE_NETINET_IN_H #include <sys/socket.h>
#include <netinet/in.h> #endif
#endif #ifdef HAVE_WINSOCK_H
int main() #include <winsock.h>
{ #endif
struct in6_addr addr6; #ifdef HAVE_NETINET_IN_H
if (inet_net_pton(AF_INET6, "::1", &addr6, sizeof(addr6)) < 1) #include <netinet/in.h>
exit(1); #endif
else int main()
exit(0); {
} struct in6_addr addr6;
], [ if (inet_net_pton(AF_INET6, "::1", &addr6, sizeof(addr6)) < 1)
AC_MSG_RESULT(yes) exit(1);
AC_DEFINE_UNQUOTED(HAVE_INET_NET_PTON_IPV6,1,[Define to 1 if inet_net_pton supports IPv6.]) else
], AC_MSG_RESULT(no),AC_MSG_RESULT(no)) exit(0);
fi }
], [
AC_MSG_RESULT(yes)
dnl Check for inet_ntop AC_DEFINE_UNQUOTED(HAVE_INET_NET_PTON_IPV6,1,[Define to 1 if inet_net_pton supports IPv6.])
AC_CHECK_FUNCS(inet_ntop) ], AC_MSG_RESULT(no),AC_MSG_RESULT(no))
dnl Again, some systems have it, but not IPv6 fi
if test "$ac_cv_func_inet_ntop" = "yes" ; then
AC_MSG_CHECKING(if inet_ntop supports IPv6)
AC_TRY_RUN( dnl Check for inet_ntop
[ AC_CHECK_FUNCS(inet_ntop)
#ifdef HAVE_SYS_TYPES_H dnl Again, some systems have it, but not IPv6
#include <sys/types.h> if test "$ac_cv_func_inet_ntop" = "yes" ; then
#endif AC_MSG_CHECKING(if inet_ntop supports IPv6)
#ifdef HAVE_SYS_SOCKET_H AC_TRY_RUN(
#include <sys/socket.h> [
#endif #ifdef HAVE_SYS_TYPES_H
#ifdef HAVE_WINSOCK_H #include <sys/types.h>
#include <winsock.h> #endif
#endif #ifdef HAVE_SYS_SOCKET_H
#ifdef HAVE_NETINET_IN_H #include <sys/socket.h>
#include <netinet/in.h> #endif
#endif #ifdef HAVE_WINSOCK_H
#include <errno.h> #include <winsock.h>
int main() #endif
{ #ifdef HAVE_NETINET_IN_H
struct in6_addr addr6; #include <netinet/in.h>
char buf[128]; #endif
if (inet_ntop(AF_INET6, &addr6, buf, 128) == 0 && errno == EAFNOSUPPORT) #include <errno.h>
exit(1); int main()
else {
exit(0); struct in6_addr addr6;
} char buf[128];
], [ if (inet_ntop(AF_INET6, &addr6, buf, 128) == 0 && errno == EAFNOSUPPORT)
AC_MSG_RESULT(yes) exit(1);
AC_DEFINE_UNQUOTED(HAVE_INET_NTOP_IPV6,1,[Define to 1 if inet_ntop supports IPv6.]) else
], AC_MSG_RESULT(no),AC_MSG_RESULT(no)) exit(0);
fi }
], [
AC_CHECK_SIZEOF(struct in6_addr, , AC_MSG_RESULT(yes)
[ AC_DEFINE_UNQUOTED(HAVE_INET_NTOP_IPV6,1,[Define to 1 if inet_ntop supports IPv6.])
#ifdef HAVE_SYS_TYPES_H ], AC_MSG_RESULT(no),AC_MSG_RESULT(no))
#include <sys/types.h> fi
#endif
#ifdef HAVE_SYS_SOCKET_H AC_CHECK_SIZEOF(struct in6_addr, ,
#include <sys/socket.h> [
#endif #ifdef HAVE_SYS_TYPES_H
#ifdef HAVE_WINSOCK_H #include <sys/types.h>
#include <winsock.h> #endif
#endif #ifdef HAVE_SYS_SOCKET_H
#ifdef HAVE_NETINET_IN_H #include <sys/socket.h>
#include <netinet/in.h> #endif
#endif #ifdef HAVE_WINSOCK_H
] #include <winsock.h>
) #endif
AC_CHECK_SIZEOF(struct in_addr, , #ifdef HAVE_NETINET_IN_H
[ #include <netinet/in.h>
#ifdef HAVE_SYS_TYPES_H #endif
#include <sys/types.h> ]
#endif )
#ifdef HAVE_SYS_SOCKET_H AC_CHECK_SIZEOF(struct in_addr, ,
#include <sys/socket.h> [
#endif #ifdef HAVE_SYS_TYPES_H
#ifdef HAVE_WINSOCK_H #include <sys/types.h>
#include <winsock.h> #endif
#endif #ifdef HAVE_SYS_SOCKET_H
#ifdef HAVE_NETINET_IN_H #include <sys/socket.h>
#include <netinet/in.h> #endif
#endif #ifdef HAVE_WINSOCK_H
] #include <winsock.h>
) #endif
#ifdef HAVE_NETINET_IN_H
AC_CHECK_FUNCS([bitncmp if_indextoname]) #include <netinet/in.h>
#endif
CURL_CHECK_NONBLOCKING_SOCKET ]
)
AC_OUTPUT(Makefile)
AC_CHECK_FUNCS([bitncmp if_indextoname])
dnl God bless non-standardized functions! We need to see which getservbyport_r variant is available
CARES_CHECK_GETSERVBYPORT_R
CURL_CHECK_NONBLOCKING_SOCKET
AC_OUTPUT(Makefile)

View File

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

View File

@@ -122,13 +122,13 @@ case $host in
*-*-mingw*) *-*-mingw*)
AC_DEFINE(BUILDING_LIBCURL, 1, [when building libcurl itself]) AC_DEFINE(BUILDING_LIBCURL, 1, [when building libcurl itself])
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
<EFBFBD> <20>AC_MSG_CHECKING([if we need CURL_STATICLIB]) AC_MSG_CHECKING([if we need CURL_STATICLIB])
if test "X$enable_shared" = "Xno" if test "X$enable_shared" = "Xno"
then then
AC_DEFINE(CURL_STATICLIB, 1, [when not building a shared library]) AC_DEFINE(CURL_STATICLIB, 1, [when not building a shared library])
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
<EFBFBD> <20>else else
<EFBFBD> <20> <20>AC_MSG_RESULT(no) AC_MSG_RESULT(no)
fi fi
;; ;;
*) *)
@@ -251,6 +251,21 @@ AC_HELP_STRING([--disable-telnet],[Disable TELNET support]),
esac ], esac ],
AC_MSG_RESULT(yes) AC_MSG_RESULT(yes)
) )
AC_MSG_CHECKING([whether to support tftp])
AC_ARG_ENABLE(tftp,
AC_HELP_STRING([--enable-tftp],[Enable TFTP support])
AC_HELP_STRING([--disable-tftp],[Disable TFTP support]),
[ case "$enableval" in
no)
AC_MSG_RESULT(no)
AC_DEFINE(CURL_DISABLE_TFTP, 1, [to disable TFTP])
AC_SUBST(CURL_DISABLE_TFTP, [1])
;;
*) AC_MSG_RESULT(yes)
;;
esac ],
AC_MSG_RESULT(yes)
)
dnl ********************************************************************** dnl **********************************************************************
dnl Check for built-in manual dnl Check for built-in manual
@@ -1419,6 +1434,8 @@ AC_CHECK_HEADERS(
libgen.h \ libgen.h \
locale.h \ locale.h \
errno.h \ errno.h \
arpa/tftp.h \
sys/filio.h \
setjmp.h, setjmp.h,
dnl to do if not found dnl to do if not found
[], [],
@@ -1673,7 +1690,7 @@ AC_HELP_STRING([--disable-ares],[Disable ares for name lookups]),
*) AC_MSG_RESULT(yes) *) AC_MSG_RESULT(yes)
if test "x$IPV6_ENABLED" = "x1"; then if test "x$IPV6_ENABLED" = "x1"; then
AC_MSG_ERROR([ares doesn't work with ipv6, disable ipv6 to use ares]) AC_MSG_NOTICE([ares may not work properly with ipv6])
fi fi
AC_DEFINE(USE_ARES, 1, [Define if you want to enable ares support]) AC_DEFINE(USE_ARES, 1, [Define if you want to enable ares support])

View File

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

View File

@@ -150,6 +150,11 @@ Scheme
Bigloo binding written by Kirill Lisovsky Bigloo binding written by Kirill Lisovsky
http://curl.haxx.se/libcurl/scheme/ http://curl.haxx.se/libcurl/scheme/
S-Lang
S-Lang binding written by John E Davis
http://www.jedsoft.org/slang/modules/curl.html
Tcl Tcl
Tclcurl is written by Andr<64>s Garc<72>a Tclcurl is written by Andr<64>s Garc<72>a
@@ -161,7 +166,7 @@ Visual Basic
http://sourceforge.net/projects/libcurl-vb/ http://sourceforge.net/projects/libcurl-vb/
Q Q
The libcurl module is part of the default install
http://q-lang.sourceforge.net/ http://q-lang.sourceforge.net/
wxWidgets wxWidgets

View File

@@ -1,12 +1,12 @@
Date: September 1, 2005 Date: September 30, 2005
Author: Daniel Stenberg <daniel@haxx.se> Author: Daniel Stenberg <daniel@haxx.se>
URL: http://curl.haxx.se/legal/distro-dilemma.html URL: http://curl.haxx.se/legal/distro-dilemma.html
Condition Condition
This document is written to describe the sitution as it is right now. libcurl This document is written to describe the situation as it is right
7.14.0 is currently the latest version available. Things may (or perhaps now. libcurl 7.14.1 is currently the latest version available. Things may (or
will) of course change in the future. perhaps will) of course change in the future.
This document reflects my view and understanding of these things. Please tell This document reflects my view and understanding of these things. Please tell
me where and how you think I'm wrong, and I'll try to correct my mistakes. me where and how you think I'm wrong, and I'll try to correct my mistakes.
@@ -16,7 +16,7 @@ Background
The Free Software Foundation has deemed the Original BSD license[1] to be The Free Software Foundation has deemed the Original BSD license[1] to be
"incompatible"[2] with GPL[3]. I'd rather say it is the other way around, but "incompatible"[2] with GPL[3]. I'd rather say it is the other way around, but
the point is the same: if you distribute a binary version of a GPL program, the point is the same: if you distribute a binary version of a GPL program,
it MUST NOT be linked with any Original BSD-licenced parts or it MUST NOT be linked with any Original BSD-licensed parts or
libraries. Doing so will violate the GPL license. For a long time, very many libraries. Doing so will violate the GPL license. For a long time, very many
GPL licensed programs have avoided this license mess by adding an GPL licensed programs have avoided this license mess by adding an
exception[8] to their license. And many others have just closed their eyes exception[8] to their license. And many others have just closed their eyes
@@ -38,7 +38,7 @@ Background
Part of the Operating System Part of the Operating System
This would not be a problem if the used lib would be considered part of the This would not be a problem if the used lib would be considered part of the
uderlying operating system, as then the GPL license has an exception underlying operating system, as then the GPL license has an exception
clause[6] that allows applications to use such libs without having to be clause[6] that allows applications to use such libs without having to be
allowed to distribute it or its sources. Possibly some distros will claim allowed to distribute it or its sources. Possibly some distros will claim
that OpenSSL is part of their operating system. that OpenSSL is part of their operating system.
@@ -92,8 +92,13 @@ The Better License, Original BSD or LGPL?
Instead, I think we should accept the fact that the SSL/TLS libraries and Instead, I think we should accept the fact that the SSL/TLS libraries and
their different licenses will fit different applications and their authors their different licenses will fit different applications and their authors
differently depending on the applications' licenses and their general usage differently depending on the applications' licenses and their general usage
pattern (considering how LGPL libraries can be burdonsome for embedded pattern (considering how LGPL libraries for example can be burdensome for
systems usage). embedded systems usage).
In Debian land, there seems to be a common opinion that LGPL is "maximally
compatible" with apps while Original BSD is not. Like this:
http://lists.debian.org/debian-devel/2005/09/msg01417.html
More SSL Libraries More SSL Libraries
@@ -116,6 +121,16 @@ Project cURL Angle of this Problem
affects users - GPL application authors only - of our lib as it comes affects users - GPL application authors only - of our lib as it comes
included and delivered on some distros. included and delivered on some distros.
libcurl has different ABI when built with different SSL/TLS libraries due to
two reasons:
1. No one has worked on fixing this. The mutex/lock callbacks should be set
with a generic libcurl function that should use the proper underlying
functions.
2. The CURLOPT_SSL_CTX_FUNCTION option is not possible to "emulate" on GnuTLS
but simply requires OpenSSL.
Distro Angle of this Problem Distro Angle of this Problem
A distro can provide separate libcurls built with different SSL/TLS libraries A distro can provide separate libcurls built with different SSL/TLS libraries
@@ -170,6 +185,10 @@ When Will This Happen
code like today (without the use of lib2), should you decide to ignore the code like today (without the use of lib2), should you decide to ignore the
problems outlined in this document. problems outlined in this document.
Update: Work on this has been initiated by Richard Atterer:
http://curl.haxx.se/mail/lib-2005-09/0066.html
Footnotes Footnotes
[1] = http://www.xfree86.org/3.3.6/COPYRIGHT2.html#6 [1] = http://www.xfree86.org/3.3.6/COPYRIGHT2.html#6

View File

@@ -145,3 +145,9 @@ August 2004:
April 2005: April 2005:
GnuTLS can now optionally be used for the secure layer when curl is built. GnuTLS can now optionally be used for the secure layer when curl is built.
September 2005:
TFTP support was added.
More than 100,000 unique visitors of the curl web site. 25 mirrors.

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 changelog of the current development status, as one or more of these problems
may have been fixed since this was written! may have been fixed since this was written!
26. NTLM authentication using SSPI (on Windows) when (lib)curl is running in
"system context" will make it use wrong(?) user name - at least when compared
to what winhttp does. See http://curl.haxx.se/bug/view.cgi?id=1281867
25. When doing a CONNECT request with curl it doesn't properly handle if the 25. When doing a CONNECT request with curl it doesn't properly handle if the
proxy closes the connection within the authentication "negotiation phase". proxy closes the connection within the authentication "negotiation phase".
Like if you do HTTPS or similar over a proxy and you use perhaps Like if you do HTTPS or similar over a proxy and you use perhaps
@@ -23,7 +27,7 @@ may have been fixed since this was written!
complaining on "unaligned file size" on completion. The problem is related complaining on "unaligned file size" on completion. The problem is related
to VMS file structures and the perceived file sizes stat() returns. A to VMS file structures and the perceived file sizes stat() returns. A
possible fix would involve sending a "STRU VMS" command. possible fix would involve sending a "STRU VMS" command.
http://sourceforge.net/support/tracker.php?aid=1156287 http://curl.haxx.se/bug/view.cgi?id=1156287
21. FTP ASCII transfers do not follow RFC959. They don't convert the data 21. FTP ASCII transfers do not follow RFC959. They don't convert the data
accordingly (not for sending nor for receiving). RFC 959 section 3.1.1.1 accordingly (not for sending nor for receiving). RFC 959 section 3.1.1.1
@@ -69,11 +73,12 @@ may have been fixed since this was written!
10. To get HTTP Negotiate authentication to work fine, you need to provide a 10. To get HTTP Negotiate authentication to work fine, you need to provide a
(fake) user name (this concerns both curl and the lib) because the code (fake) user name (this concerns both curl and the lib) because the code
wrongly only considers authentication if there's a user name provided. wrongly only considers authentication if there's a user name provided.
Bug report #1004841. How? http://curl.haxx.se/mail/lib-2004-08/0182.html http://curl.haxx.se/bug/view.cgi?id=1004841. How?
http://curl.haxx.se/mail/lib-2004-08/0182.html
9. --limit-rate using -d or -F does not work. This is because the limit logic 9. --limit-rate using -d or -F does not work. This is because the limit logic
is provided by the curl app in its read/write callbacks, and when doing is provided by the curl app in its read/write callbacks, and when doing
-d/-F the callbacks aren't used! Bug report #921395. -d/-F the callbacks aren't used! http://curl.haxx.se/bug/view.cgi?id=921395
8. Doing resumed upload over HTTP does not work with '-C -', because curl 8. Doing resumed upload over HTTP does not work with '-C -', because curl
doesn't do a HEAD first to get the initial size. This needs to be done doesn't do a HEAD first to get the initial size. This needs to be done

View File

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

View File

@@ -31,7 +31,7 @@ TODO
* Introduce a new error code indicating authentication problems (for proxy * Introduce a new error code indicating authentication problems (for proxy
CONNECT error 407 for example). This cannot be an error code, we must not CONNECT error 407 for example). This cannot be an error code, we must not
return informational stuff as errors, consider a new info returned by return informational stuff as errors, consider a new info returned by
curl_easy_getinfo() #845941 curl_easy_getinfo() http://curl.haxx.se/bug/view.cgi?id=845941
* Use 'struct lifreq' and SIOCGLIFADDR instead of 'struct ifreq' and * Use 'struct lifreq' and SIOCGLIFADDR instead of 'struct ifreq' and
SIOCGIFADDR on newer Solaris versions as they claim the latter is obsolete. SIOCGIFADDR on newer Solaris versions as they claim the latter is obsolete.

View File

@@ -21,7 +21,7 @@
.\" * $Id$ .\" * $Id$
.\" ************************************************************************** .\" **************************************************************************
.\" .\"
.TH curl 1 "12 Aug 2005" "Curl 7.14.1" "Curl Manual" .TH curl 1 "4 Sep 2005" "Curl 7.14.2" "Curl Manual"
.SH NAME .SH NAME
curl \- transfer a URL curl \- transfer a URL
.SH SYNOPSIS .SH SYNOPSIS
@@ -30,8 +30,8 @@ curl \- transfer a URL
.SH DESCRIPTION .SH DESCRIPTION
.B curl .B curl
is a tool to transfer data from or to a server, using one of the supported is a tool to transfer data from or to a server, using one of the supported
protocols (HTTP, HTTPS, FTP, FTPS, GOPHER, DICT, TELNET, LDAP or FILE). The protocols (HTTP, HTTPS, FTP, FTPS, TFTP, GOPHER, DICT, TELNET, LDAP or
command is designed to work without user interaction. FILE). The command is designed to work without user interaction.
curl offers a busload of useful tricks like proxy support, user curl offers a busload of useful tricks like proxy support, user
authentication, ftp upload, HTTP post, SSL (https:) connections, cookies, file authentication, ftp upload, HTTP post, SSL (https:) connections, cookies, file
@@ -64,6 +64,11 @@ several ones next to each other:
You can specify any amount of URLs on the command line. They will be fetched You can specify any amount of URLs on the command line. They will be fetched
in a sequential manner in the specified order. in a sequential manner in the specified order.
If you specify URL without protocol:// prefix, curl will attempt to guess what
protocol you might want. It will then default to HTTP but try other protocols
based on often-used host name prefixes. For example, for host names starting
with "ftp." curl will assume you want to speak FTP.
Curl will attempt to re-use connections for multiple file transfers, so that Curl will attempt to re-use connections for multiple file transfers, so that
getting many files from the same server will not do multiple connects / getting many files from the same server will not do multiple connects /
handshakes. This improves speed. Of course this is only done on files handshakes. This improves speed. Of course this is only done on files
@@ -347,6 +352,15 @@ If this option is used twice, the second will again disable silent failure.
using this option can be used to override a previous --ftp-port option. (Added using this option can be used to override a previous --ftp-port option. (Added
in 7.11.0) in 7.11.0)
If this option is used twice, the second will again disable silent failure.
.IP "--ftp-skip-pasv-ip"
(FTP) Tell curl to not use the IP address the server suggests in its response
to curl's PASV command when curl connects the data connection. Instead curl
will re-use the same IP address it already uses for the control
connection. (Added in 7.14.2)
This option has no effect if PORT, EPRT or EPSV is used instead of PASV.
If this option is used twice, the second will again disable silent failure. If this option is used twice, the second will again disable silent failure.
.IP "--ftp-ssl" .IP "--ftp-ssl"
(FTP) Make the FTP connection switch to use SSL/TLS. (Added in 7.11.0) (FTP) Make the FTP connection switch to use SSL/TLS. (Added in 7.11.0)
@@ -579,8 +593,7 @@ this given limit. This concerns both FTP and HTTP transfers.
.IP "-m/--max-time <seconds>" .IP "-m/--max-time <seconds>"
Maximum time in seconds that you allow the whole operation to take. This is Maximum time in seconds that you allow the whole operation to take. This is
useful for preventing your batch jobs from hanging for hours due to slow useful for preventing your batch jobs from hanging for hours due to slow
networks or links going down. This doesn't work fully in win32 systems. See networks or links going down. See also the \fI--connect-timeout\fP option.
also the \fI--connect-timeout\fP option.
If this option is used several times, the last one will be used. If this option is used several times, the last one will be used.
.IP "-M/--manual" .IP "-M/--manual"
@@ -599,7 +612,7 @@ directory.
A quick and very simple example of how to setup a \fI.netrc\fP to allow curl A quick and very simple example of how to setup a \fI.netrc\fP to allow curl
to ftp to the machine host.domain.com with user name \&'myself' and password to ftp to the machine host.domain.com with user name \&'myself' and password
'secret' should look similar to: \&'secret' should look similar to:
.B "machine host.domain.com login myself password secret" .B "machine host.domain.com login myself password secret"
@@ -1171,7 +1184,7 @@ Sets proxy server to use for GOPHER.
Sets proxy server to use if no protocol-specific proxy is set. Sets proxy server to use if no protocol-specific proxy is set.
.IP "NO_PROXY <comma-separated list of hosts>" .IP "NO_PROXY <comma-separated list of hosts>"
list of host names that shouldn't go through any proxy. If set to a asterisk list of host names that shouldn't go through any proxy. If set to a asterisk
'*' only, it matches all hosts. \&'*' only, it matches all hosts.
.SH EXIT CODES .SH EXIT CODES
There exists a bunch of different error codes and their corresponding error There exists a bunch of different error codes and their corresponding error
messages that may appear during bad conditions. At the time of this writing, messages that may appear during bad conditions. At the time of this writing,

View File

@@ -14,6 +14,8 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h> #include <curl/curl.h>
#include <curl/types.h> #include <curl/types.h>
@@ -93,5 +95,8 @@ int main(int argc, char **argv)
* you're done with it, you should free() it as a nice application. * you're done with it, you should free() it as a nice application.
*/ */
if(chunk.memory)
free(chunk.memory);
return 0; return 0;
} }

View File

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

View File

@@ -2,7 +2,7 @@
.\" nroff -man [file] .\" nroff -man [file]
.\" $Id$ .\" $Id$
.\" .\"
.TH curl_easy_getinfo 3 "22 Dec 2004" "libcurl 7.12.3" "libcurl Manual" .TH curl_easy_getinfo 3 "6 Oct 2005" "libcurl 7.12.3" "libcurl Manual"
.SH NAME .SH NAME
curl_easy_getinfo - extract information from a curl handle curl_easy_getinfo - extract information from a curl handle
.SH SYNOPSIS .SH SYNOPSIS
@@ -141,6 +141,40 @@ cookies cURL knows (expired ones, too). Don't forget to
cookies (cookies for the handle have not been enabled or simply none have been cookies (cookies for the handle have not been enabled or simply none have been
received) 'struct curl_slist *' will be set to point to NULL. (Added in received) 'struct curl_slist *' will be set to point to NULL. (Added in
7.14.1) 7.14.1)
.SH TIMES
.NF
An overview of the six time values available from curl_easy_getinfo()
curk_easy_perform()
|
|--NT
|--|--CT
|--|--|--PT
|--|--|--|--ST
|--|--|--TT
|--|--|--|--|--RT
.FI
.IP NT
\fICURLINFO_NAMELOOKUP_TIME\fP. The time it took from the start until the name
resolving was completed.
.IP CT
\fICURLINFO_CONNECT_TIME\fP. The time it took from the start until the connect
to the remote host (or proxy) was completed.
.IP PT
\fICURLINFO_PRETRANSFER_TIME\fP. The time it took from the start until the
file transfer is just about to begin. This includes all pre-transfer commands
and negotiations that are specific to the particular protocol(s) involved.
.IP ST
\fICURLINFO_STARTTRANSFER_TIME\fP. The time it took from the start until the
first byte is just about to be transferred.
.IP TT
\fICURLINFO_TOTAL_TIME\fP. Time of the previous transfer. This time does not
include the connect time (CT), so if you want the complete operation time, you
should add that.
.IP RT
\fICURLINFO_REDIRECT_TIME\fP. The time it took for all redirection steps
include name lookup, connect, pretransfer and transfer before final
transaction was started. So, this is zero if no redirection took place.
.SH RETURN VALUE .SH RETURN VALUE
If the operation was successful, CURLE_OK is returned. Otherwise an If the operation was successful, CURLE_OK is returned. Otherwise an
appropriate error code will be returned. appropriate error code will be returned.

View File

@@ -21,7 +21,7 @@
.\" * $Id$ .\" * $Id$
.\" ************************************************************************** .\" **************************************************************************
.\" .\"
.TH curl_easy_setopt 3 "28 Jul 2005" "libcurl 7.14.1" "libcurl Manual" .TH curl_easy_setopt 3 "22 Sep 2005" "libcurl 7.14.2" "libcurl Manual"
.SH NAME .SH NAME
curl_easy_setopt - set options for a curl easy handle curl_easy_setopt - set options for a curl easy handle
.SH SYNOPSIS .SH SYNOPSIS
@@ -44,11 +44,11 @@ between transfers, so if you want subsequent transfers with different options,
you must change them between the transfers. You can optionally reset all you must change them between the transfers. You can optionally reset all
options back to internal default with \fIcurl_easy_reset(3)\fP. options back to internal default with \fIcurl_easy_reset(3)\fP.
\fBNOTE:\fP strings passed to libcurl as 'char *' arguments, will not be Strings passed to libcurl as 'char *' arguments, will not be copied by the
copied by the library. Instead you should keep them available until libcurl no library. Instead you should keep them available until libcurl no longer needs
longer needs them. Failing to do so will cause very odd behavior or even them. Failing to do so will cause very odd behavior or even crashes. libcurl
crashes. libcurl will need them until you call \fIcurl_easy_cleanup(3)\fP or will need them until you call \fIcurl_easy_cleanup(3)\fP or you set the same
you set the same option again to use a different pointer. option again to use a different pointer.
The \fIhandle\fP is the return code from a \fIcurl_easy_init(3)\fP or The \fIhandle\fP is the return code from a \fIcurl_easy_init(3)\fP or
\fIcurl_easy_duphandle(3)\fP call. \fIcurl_easy_duphandle(3)\fP call.
@@ -70,8 +70,8 @@ preceding the data (like HTTP).
A non-zero parameter tells the library to shut off the built-in progress meter A non-zero parameter tells the library to shut off the built-in progress meter
completely. completely.
\fBNOTE:\fP future versions of libcurl is likely to not have any built-in Future versions of libcurl is likely to not have any built-in progress meter
progress meter at all. at all.
.IP CURLOPT_NOSIGNAL .IP CURLOPT_NOSIGNAL
Pass a long. If it is non-zero, libcurl will not use any functions that Pass a long. If it is non-zero, libcurl will not use any functions that
install signal handlers or any functions that cause signals to be sent to the install signal handlers or any functions that cause signals to be sent to the
@@ -96,19 +96,26 @@ transfer and return \fICURLE_WRITE_ERROR\fP.
This function may be called with zero bytes data if the transfered file is This function may be called with zero bytes data if the transfered file is
empty. empty.
Set this option to NULL to get the internal default function. The internal
default function will write the data to the FILE * given with
\fICURLOPT_WRITEDATA\fP.
Set the \fIstream\fP argument with the \fICURLOPT_WRITEDATA\fP option. Set the \fIstream\fP argument with the \fICURLOPT_WRITEDATA\fP option.
\fBNOTE:\fP you will be passed as much data as possible in all invokes, but The callback function will be passed as much data as possible in all invokes,
you cannot possibly make any assumptions. It may be one byte, it may be but you cannot possibly make any assumptions. It may be one byte, it may be
thousands. The maximum amount of data that can be passed to the write callback thousands. The maximum amount of data that can be passed to the write callback
is defined in the curl.h header file: CURL_MAX_WRITE_SIZE. is defined in the curl.h header file: CURL_MAX_WRITE_SIZE.
.IP CURLOPT_WRITEDATA .IP CURLOPT_WRITEDATA
Data pointer to pass to the file write function. Note that if you specify the Data pointer to pass to the file write function. If you use the
\fICURLOPT_WRITEFUNCTION\fP, this is the pointer you'll get as input. If you \fICURLOPT_WRITEFUNCTION\fP option, this is the pointer you'll get as
don't use a callback, you must pass a 'FILE *' as libcurl will pass this to input. If you don't use a callback, you must pass a 'FILE *' as libcurl will
fwrite() when writing data. pass this to fwrite() when writing data.
\fBNOTE:\fP If you're using libcurl as a win32 DLL, you MUST use the The internal \fICURLOPT_WRITEFUNCTION\fP will write the data to the FILE *
given with this option, or to stdout if this option hasn't been set.
If you're using libcurl as a win32 DLL, you \fBMUST\fP use the
\fICURLOPT_WRITEFUNCTION\fP if you set this option or you will experience \fICURLOPT_WRITEFUNCTION\fP if you set this option or you will experience
crashes. crashes.
@@ -129,15 +136,20 @@ server expected it, like when you've told you will upload N bytes and you
upload less than N bytes), you may experience that the server "hangs" waiting upload less than N bytes), you may experience that the server "hangs" waiting
for the rest of the data that won't come. for the rest of the data that won't come.
In libcurl 7.12.1 and later, the read callback may return The read callback may return \fICURL_READFUNC_ABORT\fP to stop the current
\fICURL_READFUNC_ABORT\fP to stop the current operation at once, with a operation immediately, resulting in a \fICURLE_ABORTED_BY_CALLBACK\fP error
\fICURLE_ABORTED_BY_CALLBACK\fP error code from the transfer. code from the transfer (Added in 7.12.1)
.IP CURLOPT_READDATA
Data pointer to pass to the file read function. Note that if you specify the
\fICURLOPT_READFUNCTION\fP, this is the pointer you'll get as input. If you
don't specify a read callback, this must be a valid FILE *.
\fBNOTE:\fP If you're using libcurl as a win32 DLL, you MUST use a If you set the callback pointer to NULL, or doesn't set it at all, the default
internal read function will be used. It is simply doing an fread() on the FILE
* stream set with \fICURLOPT_READDATA\fP.
.IP CURLOPT_READDATA
Data pointer to pass to the file read function. If you use the
\fICURLOPT_READFUNCTION\fP option, this is the pointer you'll get as input. If
you don't specify a read callback but instead rely on the default internal
read function, this data must be a valid readable FILE *.
If you're using libcurl as a win32 DLL, you MUST use a
\fICURLOPT_READFUNCTION\fP if you set this option. \fICURLOPT_READFUNCTION\fP if you set this option.
This option is also known with the older name \fICURLOPT_INFILE\fP, the name This option is also known with the older name \fICURLOPT_INFILE\fP, the name
@@ -163,8 +175,8 @@ data, the upload size will remain 0). Returning a non-zero value from this
callback will cause libcurl to abort the transfer and return callback will cause libcurl to abort the transfer and return
\fICURLE_ABORTED_BY_CALLBACK\fP. \fICURLE_ABORTED_BY_CALLBACK\fP.
Also note that \fICURLOPT_NOPROGRESS\fP must be set to FALSE to make this \fICURLOPT_NOPROGRESS\fP must be set to FALSE to make this function actually
function actually get called. get called.
.IP CURLOPT_PROGRESSDATA .IP CURLOPT_PROGRESSDATA
Pass a pointer that will be untouched by libcurl and passed as the first Pass a pointer that will be untouched by libcurl and passed as the first
argument in the progress callback set with \fICURLOPT_PROGRESSFUNCTION\fP. argument in the progress callback set with \fICURLOPT_PROGRESSFUNCTION\fP.
@@ -236,10 +248,10 @@ option was introduced in 7.11.0.
This function will get called on all new connections made to a server, during This function will get called on all new connections made to a server, during
the SSL negotiation. The SSL_CTX pointer will be a new one every time. the SSL negotiation. The SSL_CTX pointer will be a new one every time.
\fBNOTE:\fP To use this properly, a non-trivial amount of knowledge of the To use this properly, a non-trivial amount of knowledge of the openssl
openssl libraries is necessary. Using this function allows for example to use libraries is necessary. Using this function allows for example to use openssl
openssl callbacks to add additional validation code for certificates, and even callbacks to add additional validation code for certificates, and even to
to change the actual URI of an HTTPS request (example used in the lib509 test change the actual URI of an HTTPS request (example used in the lib509 test
case). See also the example section for a replacement of the key, certificate case). See also the example section for a replacement of the key, certificate
and trust file settings. and trust file settings.
.IP CURLOPT_SSL_CTX_DATA .IP CURLOPT_SSL_CTX_DATA
@@ -249,14 +261,21 @@ parameter, otherwise \fBNULL\fP. (Added in 7.11.0)
.SH ERROR OPTIONS .SH ERROR OPTIONS
.IP CURLOPT_ERRORBUFFER .IP CURLOPT_ERRORBUFFER
Pass a char * to a buffer that the libcurl may store human readable error Pass a char * to a buffer that the libcurl may store human readable error
messages in. This may be more helpful than just the return code from the messages in. This may be more helpful than just the return code from
library. The buffer must be at least CURL_ERROR_SIZE big. \fIcurl_easy_perform\fP. The buffer must be at least CURL_ERROR_SIZE big.
Use \fICURLOPT_VERBOSE\fP and \fICURLOPT_DEBUGFUNCTION\fP to better Use \fICURLOPT_VERBOSE\fP and \fICURLOPT_DEBUGFUNCTION\fP to better
debug/trace why errors happen. debug/trace why errors happen.
\fBNote:\fP if the library does not return an error, the buffer may not have If the library does not return an error, the buffer may not have been
been touched. Do not rely on the contents in those cases. touched. Do not rely on the contents in those cases.
In a few rare cases, there is no text string associated with the error in
libcurl and then you may not get a string in the buffer even though it returns
an error. This is considered a bug and we appreciate your reports about these
cases. Anyway, you can avoid problems with these cases in your program by
making sure to clear the first byte of the error buffer before you call
curl_easy_perform().
.IP CURLOPT_STDERR .IP CURLOPT_STDERR
Pass a FILE * as parameter. Tell libcurl to use this stream instead of stderr Pass a FILE * as parameter. Tell libcurl to use this stream instead of stderr
when showing the progress meter and displaying \fICURLOPT_VERBOSE\fP data. when showing the progress meter and displaying \fICURLOPT_VERBOSE\fP data.
@@ -277,7 +296,7 @@ given protocol of the set URL is not supported, libcurl will return on error
\fIcurl_multi_perform(3)\fP. Use \fIcurl_version_info(3)\fP for detailed info \fIcurl_multi_perform(3)\fP. Use \fIcurl_version_info(3)\fP for detailed info
on which protocols that are supported. on which protocols that are supported.
\fBNOTE:\fP \fICURLOPT_URL\fP is the only option that must be set before \fICURLOPT_URL\fP is the only option that must be set before
\fIcurl_easy_perform(3)\fP is called. \fIcurl_easy_perform(3)\fP is called.
.IP CURLOPT_PROXY .IP CURLOPT_PROXY
Set HTTP proxy to use. The parameter should be a char * to a zero terminated Set HTTP proxy to use. The parameter should be a char * to a zero terminated
@@ -310,9 +329,9 @@ this are \fICURLPROXY_HTTP\fP and \fICURLPROXY_SOCKS5\fP, with the HTTP one
being default. (Added in 7.10) being default. (Added in 7.10)
.IP CURLOPT_HTTPPROXYTUNNEL .IP CURLOPT_HTTPPROXYTUNNEL
Set the parameter to non-zero to get the library to tunnel all operations Set the parameter to non-zero to get the library to tunnel all operations
through a given HTTP proxy. Note that there is a big difference between using through a given HTTP proxy. There is a big difference between using a proxy
a proxy and to tunnel through it. If you don't know what this means, you and to tunnel through it. If you don't know what this means, you probably
probably don't want this tunneling option. don't want this tunneling option.
.IP CURLOPT_INTERFACE .IP CURLOPT_INTERFACE
Pass a char * as parameter. This set the interface name to use as outgoing Pass a char * as parameter. This set the interface name to use as outgoing
network interface. The name can be an interface name, an IP address or a host network interface. The name can be an interface name, an IP address or a host
@@ -331,10 +350,14 @@ thread-safe and this will use a global variable.
to using the share interface instead! See \fICURLOPT_SHARE\fP and to using the share interface instead! See \fICURLOPT_SHARE\fP and
\fIcurl_share_init(3)\fP. \fIcurl_share_init(3)\fP.
.IP CURLOPT_BUFFERSIZE .IP CURLOPT_BUFFERSIZE
Pass a long specifying your preferred size for the receive buffer in libcurl. Pass a long specifying your preferred size (in bytes) for the receive buffer
The main point of this would be that the write callback gets called more often in libcurl. The main point of this would be that the write callback gets
and with smaller chunks. This is just treated as a request, not an order. You called more often and with smaller chunks. This is just treated as a request,
cannot be guaranteed to actually get the given size. (Added in 7.10) not an order. You cannot be guaranteed to actually get the given size. (Added
in 7.10)
This size is by default set as big as possible (CURL_MAX_WRITE_SIZE), so it
only makse sense to use this option if you want it smaller.
.IP CURLOPT_PORT .IP CURLOPT_PORT
Pass a long specifying what remote port number to connect to, instead of the Pass a long specifying what remote port number to connect to, instead of the
one specified in the URL or the default port for the used protocol. one specified in the URL or the default port for the used protocol.
@@ -360,9 +383,9 @@ This parameter controls the preference of libcurl between using user names and
passwords from your \fI~/.netrc\fP file, relative to user names and passwords passwords from your \fI~/.netrc\fP file, relative to user names and passwords
in the URL supplied with \fICURLOPT_URL\fP. in the URL supplied with \fICURLOPT_URL\fP.
\fBNote:\fP libcurl uses a user name (and supplied or prompted password) libcurl uses a user name (and supplied or prompted password) supplied with
supplied with \fICURLOPT_USERPWD\fP in preference to any of the options \fICURLOPT_USERPWD\fP in preference to any of the options controlled by this
controlled by this parameter. parameter.
Pass a long, set to one of the values described below. Pass a long, set to one of the values described below.
.RS .RS
@@ -386,9 +409,8 @@ and to search the file with the host only.
Only machine name, user name and password are taken into account Only machine name, user name and password are taken into account
(init macros and similar things aren't supported). (init macros and similar things aren't supported).
\fBNote:\fP libcurl does not verify that the file has the correct properties libcurl does not verify that the file has the correct properties set (as the
set (as the standard Unix ftp client does). It should only be readable by standard Unix ftp client does). It should only be readable by user.
user.
.IP CURLOPT_NETRC_FILE .IP CURLOPT_NETRC_FILE
Pass a char * as parameter, pointing to a zero terminated string containing Pass a char * as parameter, pointing to a zero terminated string containing
the full path name to the file you want libcurl to use as .netrc file. If this the full path name to the file you want libcurl to use as .netrc file. If this
@@ -413,9 +435,9 @@ Pass a long as parameter, which is set to a bitmask, to tell libcurl what
authentication method(s) you want it to use. The available bits are listed authentication method(s) you want it to use. The available bits are listed
below. If more than one bit is set, libcurl will first query the site to see below. If more than one bit is set, libcurl will first query the site to see
what authentication methods it supports and then pick the best one you allow what authentication methods it supports and then pick the best one you allow
it to use. Note that for some methods, this will induce an extra network it to use. For some methods, this will induce an extra network round-trip. Set
round-trip. Set the actual name and password with the \fICURLOPT_USERPWD\fP the actual name and password with the \fICURLOPT_USERPWD\fP option. (Added in
option. (Added in 7.10.6) 7.10.6)
.RS .RS
.IP CURLAUTH_BASIC .IP CURLAUTH_BASIC
HTTP Basic authentication. This is the default choice, and the only method HTTP Basic authentication. This is the default choice, and the only method
@@ -433,15 +455,14 @@ applications. It is primarily meant as a support for Kerberos5 authentication
but may be also used along with another authentication methods. For more but may be also used along with another authentication methods. For more
information see IETF draft draft-brezak-spnego-http-04.txt. information see IETF draft draft-brezak-spnego-http-04.txt.
\fBNOTE\fP that you need to build libcurl with a suitable GSS-API library for You need to build libcurl with a suitable GSS-API library for this to work.
this to work.
.IP CURLAUTH_NTLM .IP CURLAUTH_NTLM
HTTP NTLM authentication. A proprietary protocol invented and used by HTTP NTLM authentication. A proprietary protocol invented and used by
Microsoft. It uses a challenge-response and hash concept similar to Digest, to Microsoft. It uses a challenge-response and hash concept similar to Digest, to
prevent the password from being eavesdropped. prevent the password from being eavesdropped.
\fBNOTE\fP that you need to build libcurl with SSL support for this option to You need to build libcurl with OpenSSL support for this option to work, or
work. build libcurl on Windows.
.IP CURLAUTH_ANY .IP CURLAUTH_ANY
This is a convenience macro that sets all bits and thus makes libcurl pick any This is a convenience macro that sets all bits and thus makes libcurl pick any
it finds suitable. libcurl will automatically select the one it finds most it finds suitable. libcurl will automatically select the one it finds most
@@ -456,11 +477,11 @@ Pass a long as parameter, which is set to a bitmask, to tell libcurl what
authentication method(s) you want it to use for your proxy authentication. If authentication method(s) you want it to use for your proxy authentication. If
more than one bit is set, libcurl will first query the site to see what more than one bit is set, libcurl will first query the site to see what
authentication methods it supports and then pick the best one you allow it to authentication methods it supports and then pick the best one you allow it to
use. Note that for some methods, this will induce an extra network use. For some methods, this will induce an extra network round-trip. Set the
round-trip. Set the actual name and password with the actual name and password with the \fICURLOPT_PROXYUSERPWD\fP option. The
\fICURLOPT_PROXYUSERPWD\fP option. The bitmask can be constructed by or'ing bitmask can be constructed by or'ing together the bits listed above for the
together the bits listed above for the \fICURLOPT_HTTPAUTH\fP option. As of \fICURLOPT_HTTPAUTH\fP option. As of this writing, only Basic, Digest and NTLM
this writing, only Basic, Digest and NTLM work. (Added in 7.10.7) work. (Added in 7.10.7)
.SH HTTP OPTIONS .SH HTTP OPTIONS
.IP CURLOPT_AUTOREFERER .IP CURLOPT_AUTOREFERER
Pass a non-zero parameter to enable this. When enabled, libcurl will Pass a non-zero parameter to enable this. When enabled, libcurl will
@@ -483,14 +504,14 @@ lib/README.encoding for details.
A non-zero parameter tells the library to follow any Location: header that the A non-zero parameter tells the library to follow any Location: header that the
server sends as part of an HTTP header. server sends as part of an HTTP header.
\fBNOTE:\fP this means that the library will re-send the same request on the This means that the library will re-send the same request on the new location
new location and follow new Location: headers all the way until no more such and follow new Location: headers all the way until no more such headers are
headers are returned. \fICURLOPT_MAXREDIRS\fP can be used to limit the number returned. \fICURLOPT_MAXREDIRS\fP can be used to limit the number of redirects
of redirects libcurl will follow. libcurl will follow.
.IP CURLOPT_UNRESTRICTED_AUTH .IP CURLOPT_UNRESTRICTED_AUTH
A non-zero parameter tells the library it can continue to send authentication A non-zero parameter tells the library it can continue to send authentication
(user+password) when following locations, even when hostname changed. Note (user+password) when following locations, even when hostname changed. This
that this is meaningful only when setting \fICURLOPT_FOLLOWLOCATION\fP. option is meaningful only when setting \fICURLOPT_FOLLOWLOCATION\fP.
.IP CURLOPT_MAXREDIRS .IP CURLOPT_MAXREDIRS
Pass a long. The set number will be the redirection limit. If that many Pass a long. The set number will be the redirection limit. If that many
redirections have been followed, the next redirect will cause an error redirections have been followed, the next redirect will cause an error
@@ -549,8 +570,8 @@ commonly used one by HTML forms. See also the \fICURLOPT_POST\fP. Using
Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header. Using POST with HTTP 1.1 implies the use of a "Expect: 100-continue" header.
You can disable this header with \fICURLOPT_HTTPHEADER\fP as usual. You can disable this header with \fICURLOPT_HTTPHEADER\fP as usual.
\fBNote:\fP to make multipart/formdata posts (aka rfc1867-posts), check out To make multipart/formdata posts (aka rfc1867-posts), check out the
the \fICURLOPT_HTTPPOST\fP option. \fICURLOPT_HTTPPOST\fP option.
.IP CURLOPT_POSTFIELDSIZE .IP CURLOPT_POSTFIELDSIZE
If you want to post data to the server without letting libcurl do a strlen() If you want to post data to the server without letting libcurl do a strlen()
to measure the data size, this option must be used. When this option is used to measure the data size, this option must be used. When this option is used
@@ -605,7 +626,7 @@ request-line are headers.
Pass a NULL to this to reset back to no custom headers. Pass a NULL to this to reset back to no custom headers.
\fBNOTE:\fP The most commonly replaced headers have "shortcuts" in the options The most commonly replaced headers have "shortcuts" in the options
\fICURLOPT_COOKIE\fP, \fICURLOPT_USERAGENT\fP and \fICURLOPT_REFERER\fP. \fICURLOPT_COOKIE\fP, \fICURLOPT_USERAGENT\fP and \fICURLOPT_REFERER\fP.
.IP CURLOPT_HTTP200ALIASES .IP CURLOPT_HTTP200ALIASES
Pass a pointer to a linked list of aliases to be treated as valid HTTP 200 Pass a pointer to a linked list of aliases to be treated as valid HTTP 200
@@ -618,9 +639,9 @@ The linked list should be a fully valid list of struct curl_slist structs, and
be properly filled in. Use \fIcurl_slist_append(3)\fP to create the list and be properly filled in. Use \fIcurl_slist_append(3)\fP to create the list and
\fIcurl_slist_free_all(3)\fP to clean up an entire list. \fIcurl_slist_free_all(3)\fP to clean up an entire list.
\fBNOTE:\fP The alias itself is not parsed for any version strings. So if your The alias itself is not parsed for any version strings. So if your alias is
alias is "MYHTTP/9.9", Libcurl will not treat the server as responding with \&"MYHTTP/9.9", Libcurl will not treat the server as responding with HTTP
HTTP version 9.9. Instead Libcurl will use the value set by option version 9.9. Instead Libcurl will use the value set by option
\fICURLOPT_HTTP_VERSION\fP. \fICURLOPT_HTTP_VERSION\fP.
.IP CURLOPT_COOKIE .IP CURLOPT_COOKIE
Pass a pointer to a zero terminated string as parameter. It will be used to Pass a pointer to a zero terminated string as parameter. It will be used to
@@ -655,7 +676,7 @@ instead have the cookies written to stdout. Using this option also enables
cookies for this session, so if you for example follow a location it will make cookies for this session, so if you for example follow a location it will make
matching cookies get sent accordingly. matching cookies get sent accordingly.
\fBNOTE:\fP If the cookie jar file can't be created or written to (when the If the cookie jar file can't be created or written to (when the
\fIcurl_easy_cleanup(3)\fP is called), libcurl will not and cannot report an \fIcurl_easy_cleanup(3)\fP is called), libcurl will not and cannot report an
error for this. Using \fICURLOPT_VERBOSE\fP or \fICURLOPT_DEBUGFUNCTION\fP error for this. Using \fICURLOPT_VERBOSE\fP or \fICURLOPT_DEBUGFUNCTION\fP
will get a warning to display, but that is the only visible feedback you get will get a warning to display, but that is the only visible feedback you get
@@ -762,11 +783,19 @@ directory. (Added in 7.10.7)
.IP CURLOPT_FTP_RESPONSE_TIMEOUT .IP CURLOPT_FTP_RESPONSE_TIMEOUT
Pass a long. Causes curl to set a timeout period (in seconds) on the amount Pass a long. Causes curl to set a timeout period (in seconds) on the amount
of time that the server is allowed to take in order to generate a response of time that the server is allowed to take in order to generate a response
message for a command before the session is considered hung. Note that while message for a command before the session is considered hung. While curl is
curl is waiting for a response, this value overrides \fICURLOPT_TIMEOUT\fP. It waiting for a response, this value overrides \fICURLOPT_TIMEOUT\fP. It is
is recommended that if used in conjunction with \fICURLOPT_TIMEOUT\fP, you set recommended that if used in conjunction with \fICURLOPT_TIMEOUT\fP, you set
\fICURLOPT_FTP_RESPONSE_TIMEOUT\fP to a value smaller than \fICURLOPT_FTP_RESPONSE_TIMEOUT\fP to a value smaller than
\fICURLOPT_TIMEOUT\fP. (Added in 7.10.8) \fICURLOPT_TIMEOUT\fP. (Added in 7.10.8)
.IP CURLOPT_FTP_SKIP_PASV_IP
Pass a long. If set to a non-zero value, it instructs libcurl to not use the
IP address the server suggests in its 227-response to libcurl's PASV command
when libcurl connects the data connection. Instead libcurl will re-use the
same IP address it already uses for the control connection. But it will use
the port number from the 227-response. (Added in 7.14.2)
This option has no effect if PORT, EPRT or EPSV is used instead of PASV.
.IP CURLOPT_FTP_SSL .IP CURLOPT_FTP_SSL
Pass a long using one of the values from below, to make libcurl use your Pass a long using one of the values from below, to make libcurl use your
desired level of SSL for the ftp transfer. (Added in 7.11.0) desired level of SSL for the ftp transfer. (Added in 7.11.0)
@@ -816,10 +845,9 @@ stdout to binary mode. This option can be usable when transferring text data
between systems with different views on certain characters, such as newlines between systems with different views on certain characters, such as newlines
or similar. or similar.
\fBNOTE:\fP libcurl does not do a complete ASCII conversion when doing ASCII libcurl does not do a complete ASCII conversion when doing ASCII transfers
transfers over FTP. This is a known limitation/flaw that nobody has over FTP. This is a known limitation/flaw that nobody has rectified. libcurl
rectified. libcurl simply sets the mode to ascii and performs a standard simply sets the mode to ascii and performs a standard transfer.
transfer.
.IP CURLOPT_CRLF .IP CURLOPT_CRLF
Convert Unix newlines to CRLF newlines on transfers. Convert Unix newlines to CRLF newlines on transfers.
.IP CURLOPT_RANGE .IP CURLOPT_RANGE
@@ -845,11 +873,11 @@ server supports the command first.
Restore to the internal default by setting this to NULL. Restore to the internal default by setting this to NULL.
\fBNOTE:\fP Many people have wrongly used this option to replace the entire Many people have wrongly used this option to replace the entire request with
request with their own, including multiple headers and POST contents. While their own, including multiple headers and POST contents. While that might work
that might work in many cases, it will cause libcurl to send invalid requests in many cases, it will cause libcurl to send invalid requests and it could
and it could possibly confuse the remote server badly. Use \fICURLOPT_POST\fP possibly confuse the remote server badly. Use \fICURLOPT_POST\fP and
and \fICURLOPT_POSTFIELDS\fP to set POST data. Use \fICURLOPT_HTTPHEADER\fP to \fICURLOPT_POSTFIELDS\fP to set POST data. Use \fICURLOPT_HTTPHEADER\fP to
replace or extend the set of headers sent by libcurl. Use replace or extend the set of headers sent by libcurl. Use
\fICURLOPT_HTTP_VERSION\fP to change HTTP version. \fICURLOPT_HTTP_VERSION\fP to change HTTP version.
.IP CURLOPT_FILETIME .IP CURLOPT_FILETIME
@@ -893,26 +921,26 @@ Pass a long as parameter. This allows you to specify the maximum size (in
bytes) of a file to download. If the file requested is larger than this value, bytes) of a file to download. If the file requested is larger than this value,
the transfer will not start and CURLE_FILESIZE_EXCEEDED will be returned. the transfer will not start and CURLE_FILESIZE_EXCEEDED will be returned.
\fBNOTE:\fP The file size is not always known prior to download, and for such The file size is not always known prior to download, and for such files this
files this option has no effect even if the file transfer ends up being larger option has no effect even if the file transfer ends up being larger than this
than this given limit. This concerns both FTP and HTTP transfers. given limit. This concerns both FTP and HTTP transfers.
.IP CURLOPT_MAXFILESIZE_LARGE .IP CURLOPT_MAXFILESIZE_LARGE
Pass a curl_off_t as parameter. This allows you to specify the maximum size Pass a curl_off_t as parameter. This allows you to specify the maximum size
(in bytes) of a file to download. If the file requested is larger than this (in bytes) of a file to download. If the file requested is larger than this
value, the transfer will not start and \fICURLE_FILESIZE_EXCEEDED\fP will be value, the transfer will not start and \fICURLE_FILESIZE_EXCEEDED\fP will be
returned. (Added in 7.11.0) returned. (Added in 7.11.0)
\fBNOTE:\fP The file size is not always known prior to download, and for such The file size is not always known prior to download, and for such files this
files this option has no effect even if the file transfer ends up being larger option has no effect even if the file transfer ends up being larger than this
than this given limit. This concerns both FTP and HTTP transfers. given limit. This concerns both FTP and HTTP transfers.
.IP CURLOPT_TIMECONDITION .IP CURLOPT_TIMECONDITION
Pass a long as parameter. This defines how the \fICURLOPT_TIMEVALUE\fP time Pass a long as parameter. This defines how the \fICURLOPT_TIMEVALUE\fP time
value is treated. You can set this parameter to \fICURL_TIMECOND_IFMODSINCE\fP value is treated. You can set this parameter to \fICURL_TIMECOND_IFMODSINCE\fP
or \fICURL_TIMECOND_IFUNMODSINCE\fP. This feature applies to HTTP and FTP. or \fICURL_TIMECOND_IFUNMODSINCE\fP. This feature applies to HTTP and FTP.
\fBNOTE:\fP The last modification time of a file is not always known and in such The last modification time of a file is not always known and in such instances
instances this feature will have no effect even if the given time condition this feature will have no effect even if the given time condition would have
would have not been met. not been met.
.IP CURLOPT_TIMEVALUE .IP CURLOPT_TIMEVALUE
Pass a long as parameter. This should be the time in seconds since 1 jan 1970, Pass a long as parameter. This should be the time in seconds since 1 jan 1970,
and the time will be used in a condition as specified with and the time will be used in a condition as specified with
@@ -925,8 +953,8 @@ considerable time and limiting operations to less than a few minutes risk
aborting perfectly normal operations. This option will cause curl to use the aborting perfectly normal operations. This option will cause curl to use the
SIGALRM to enable time-outing system calls. SIGALRM to enable time-outing system calls.
\fBNOTE:\fP this is not recommended to use in unix multi-threaded programs, as In unix-like systems, this might cause signals to be used unless
it uses signals unless \fICURLOPT_NOSIGNAL\fP (see above) is set. \fICURLOPT_NOSIGNAL\fP is set.
.IP CURLOPT_LOW_SPEED_LIMIT .IP CURLOPT_LOW_SPEED_LIMIT
Pass a long as parameter. It contains the transfer speed in bytes per second Pass a long as parameter. It contains the transfer speed in bytes per second
that the transfer should be below during \fICURLOPT_LOW_SPEED_TIME\fP seconds that the transfer should be below during \fICURLOPT_LOW_SPEED_TIME\fP seconds
@@ -947,9 +975,9 @@ When reaching the maximum limit, curl uses the \fICURLOPT_CLOSEPOLICY\fP to
figure out which of the existing connections to close to prevent the number of figure out which of the existing connections to close to prevent the number of
open connections to increase. open connections to increase.
\fBNOTE:\fP if you already have performed transfers with this curl handle, If you already have performed transfers with this curl handle, setting a
setting a smaller MAXCONNECTS than before may cause open connections to get smaller MAXCONNECTS than before may cause open connections to get closed
closed unnecessarily. unnecessarily.
.IP CURLOPT_CLOSEPOLICY .IP CURLOPT_CLOSEPOLICY
Pass a long. This option sets what policy libcurl should use when the Pass a long. This option sets what policy libcurl should use when the
connection cache is filled and one of the open connections has to be closed to connection cache is filled and one of the open connections has to be closed to
@@ -981,8 +1009,8 @@ it has connected, this option is of no more use. Set to zero to disable
connection timeout (it will then only timeout on the system's internal connection timeout (it will then only timeout on the system's internal
timeouts). See also the \fICURLOPT_TIMEOUT\fP option. timeouts). See also the \fICURLOPT_TIMEOUT\fP option.
\fBNOTE:\fP this is not recommended to use in unix multi-threaded programs, as In unix-like systems, this might cause signals to be used unless
it uses signals unless \fICURLOPT_NOSIGNAL\fP (see above) is set. \fICURLOPT_NOSIGNAL\fP is set.
.IP CURLOPT_IPRESOLVE .IP CURLOPT_IPRESOLVE
Allows an application to select what kind of IP addresses to use when Allows an application to select what kind of IP addresses to use when
resolving host names. This is only interesting when using host names that resolving host names. This is only interesting when using host names that
@@ -1019,9 +1047,9 @@ changed with \fICURLOPT_SSLKEYTYPE\fP.
Pass a pointer to a zero terminated string as parameter. The string should be Pass a pointer to a zero terminated string as parameter. The string should be
the format of your private key. Supported formats are "PEM", "DER" and "ENG". the format of your private key. Supported formats are "PEM", "DER" and "ENG".
\fBNOTE:\fP The format "ENG" enables you to load the private key from a crypto The format "ENG" enables you to load the private key from a crypto engine. In
engine. In this case \fICURLOPT_SSLKEY\fP is used as an identifier passed to this case \fICURLOPT_SSLKEY\fP is used as an identifier passed to the
the engine. You have to set the crypto engine with \fICURLOPT_SSLENGINE\fP. engine. You have to set the crypto engine with \fICURLOPT_SSLENGINE\fP.
\&"DER" format key file currently does not work because of a bug in OpenSSL. \&"DER" format key file currently does not work because of a bug in OpenSSL.
.IP CURLOPT_SSLKEYPASSWD .IP CURLOPT_SSLKEYPASSWD
Pass a pointer to a zero terminated string as parameter. It will be used as Pass a pointer to a zero terminated string as parameter. It will be used as
@@ -1031,14 +1059,14 @@ Pass a pointer to a zero terminated string as parameter. It will be used as
the identifier for the crypto engine you want to use for your private the identifier for the crypto engine you want to use for your private
key. key.
\fBNOTE:\fP If the crypto device cannot be loaded, If the crypto device cannot be loaded, \fICURLE_SSL_ENGINE_NOTFOUND\fP is
\fICURLE_SSL_ENGINE_NOTFOUND\fP is returned. returned.
.IP CURLOPT_SSLENGINE_DEFAULT .IP CURLOPT_SSLENGINE_DEFAULT
Sets the actual crypto engine as the default for (asymmetric) crypto Sets the actual crypto engine as the default for (asymmetric) crypto
operations. operations.
\fBNOTE:\fP If the crypto device cannot be set, If the crypto device cannot be set, \fICURLE_SSL_ENGINE_SETFAILED\fP is
\fICURLE_SSL_ENGINE_SETFAILED\fP is returned. returned.
.IP CURLOPT_SSLVERSION .IP CURLOPT_SSLVERSION
Pass a long as parameter to control what version of SSL/TLS to attempt to use. Pass a long as parameter to control what version of SSL/TLS to attempt to use.
The available options are: The available options are:

View File

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

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 If you then want to transfer another file, the handle is ready to be used
again. Mind you, it is even preferred that you re-use an existing handle if again. Mind you, it is even preferred that you re-use an existing handle if
you intend to make another transfer. libcurl will then attempt to re-use the you intend to make another transfer. libcurl will then attempt to re-use the
previous previous connection.
.SH "Multi-threading Issues" .SH "Multi-threading Issues"
The first basic rule is that you must \fBnever\fP share a libcurl handle (be The first basic rule is that you must \fBnever\fP share a libcurl handle (be

View File

@@ -309,6 +309,13 @@ typedef enum {
CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */ CURLE_SSL_ENGINE_INITFAILED, /* 66 - failed to initialise ENGINE */
CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not CURLE_LOGIN_DENIED, /* 67 - user, password or similar was not
accepted and we failed to login */ accepted and we failed to login */
CURLE_TFTP_NOTFOUND, /* 68 - file not found on server */
CURLE_TFTP_PERM, /* 69 - permission problem on server */
CURLE_TFTP_DISKFULL, /* 70 - out of disk space on server */
CURLE_TFTP_ILLEGAL, /* 71 - Illegal TFTP operation */
CURLE_TFTP_UNKNOWNID, /* 72 - Unknown transfer ID */
CURLE_TFTP_EXISTS, /* 73 - File already exists */
CURLE_TFTP_NOSUCHUSER, /* 74 - No such user */
CURL_LAST /* never use! */ CURL_LAST /* never use! */
} CURLcode; } CURLcode;
@@ -896,6 +903,12 @@ typedef enum {
/* ignore Content-Length */ /* ignore Content-Length */
CINIT(IGNORE_CONTENT_LENGTH, LONG, 136), CINIT(IGNORE_CONTENT_LENGTH, LONG, 136),
/* Set to non-zero to skip the IP address received in a 227 PASV FTP server
response. Typically used for FTP-SSL purposes but is not restricted to
that. libcurl will then instead use the same IP address it used for the
control connection. */
CINIT(FTP_SKIP_PASV_IP, LONG, 137),
CURLOPT_LASTENTRY /* the last unused */ CURLOPT_LASTENTRY /* the last unused */
} CURLoption; } CURLoption;

View File

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

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)\hostip6.obj $(OBJ_DIR)\inet_ntop.obj &
$(OBJ_DIR)\hostsyn.obj $(OBJ_DIR)\parsedate.obj & $(OBJ_DIR)\hostsyn.obj $(OBJ_DIR)\parsedate.obj &
$(OBJ_DIR)\select.obj $(OBJ_DIR)\sslgen.obj & $(OBJ_DIR)\select.obj $(OBJ_DIR)\sslgen.obj &
$(OBJ_DIR)\gtls.obj $(OBJ_DIR)\gtls.obj $(OBJ_DIR)\tftp.obj
RESOURCE = $(OBJ_DIR)\libcurl.res RESOURCE = $(OBJ_DIR)\libcurl.res
@@ -362,3 +362,9 @@ $(OBJ_DIR)\gtls.obj: gtls.c setup.h config-win32.h
$(OBJ_DIR)\sslgen.obj: sslgen.c setup.h config-win32.h urldata.h cookie.h & $(OBJ_DIR)\sslgen.obj: sslgen.c setup.h config-win32.h urldata.h cookie.h &
formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h sslgen.h & formdata.h timeval.h http_chunks.h hostip.h hash.h llist.h sslgen.h &
ssluse.h gtls.h sendf.h strequal.h url.h memory.h memdebug.h ssluse.h gtls.h sendf.h strequal.h url.h memory.h memdebug.h
$(OBJ_DIR)\tftp.obj: tftp.c setup.h config-win32.h urldata.h cookie.h &
..\include\curl\curl.h ..\include\curl\curlver.h ..\include\curl\easy.h &
..\include\curl\multi.h formdata.h http_chunks.h hostip.h hash.h llist.h &
transfer.h sendf.h tftp.h progress.h ..\include\curl\mprintf.h memory.h &
select.h memdebug.h

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 \ content_encoding.c share.c http_digest.c md5.c http_negotiate.c \
http_ntlm.c inet_pton.c strtoofft.c strerror.c hostares.c hostasyn.c \ http_ntlm.c inet_pton.c strtoofft.c strerror.c hostares.c hostasyn.c \
hostip4.c hostip6.c hostsyn.c hostthre.c inet_ntop.c parsedate.c \ hostip4.c hostip6.c hostsyn.c hostthre.c inet_ntop.c parsedate.c \
select.c gtls.c sslgen.c select.c gtls.c sslgen.c tftp.c
HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h \ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h \
progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \ progress.h formdata.h cookie.h http.h sendf.h ftp.h url.h dict.h \
@@ -18,5 +18,5 @@ HHEADERS = arpa_telnet.h netrc.h file.h timeval.h base64.h hostip.h \
share.h md5.h http_digest.h http_negotiate.h http_ntlm.h ca-bundle.h \ share.h md5.h http_digest.h http_negotiate.h http_ntlm.h ca-bundle.h \
inet_pton.h strtoofft.h strerror.h inet_ntop.h curlx.h memory.h \ inet_pton.h strtoofft.h strerror.h inet_ntop.h curlx.h memory.h \
setup.h transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h \ setup.h transfer.h select.h easyif.h multiif.h parsedate.h sslgen.h \
gtls.h gtls.h tftp.h

View File

@@ -301,7 +301,7 @@ config.h: Makefile.netware
@echo $(DL)*/$(DL) >> $@ @echo $(DL)*/$(DL) >> $@
@echo $(DL)#define OS "i586-pc-NetWare"$(DL) >> $@ @echo $(DL)#define OS "i586-pc-NetWare"$(DL) >> $@
@echo $(DL)#define VERSION "$(LIBCURL_VERSION_STR)"$(DL) >> $@ @echo $(DL)#define VERSION "$(LIBCURL_VERSION_STR)"$(DL) >> $@
@echo $(DL)#define PACKAGE_BUGREPORT "curl-bug@haxx.se"$(DL) >> $@ @echo $(DL)#define PACKAGE_BUGREPORT "a suitable curl mailing list => http://curl.haxx.se/mail/"$(DL) >> $@
@echo $(DL)#define HAVE_ARPA_INET_H 1$(DL) >> $@ @echo $(DL)#define HAVE_ARPA_INET_H 1$(DL) >> $@
@echo $(DL)#define HAVE_ASSERT_H 1$(DL) >> $@ @echo $(DL)#define HAVE_ASSERT_H 1$(DL) >> $@
@echo $(DL)#define HAVE_DLFCN_H 1$(DL) >> $@ @echo $(DL)#define HAVE_DLFCN_H 1$(DL) >> $@

View File

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

View File

@@ -631,8 +631,9 @@ singleipconnect(struct connectdata *conn,
int error; int error;
bool conected; bool conected;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
curl_socket_t sockfd = socket(ai->ai_family, ai->ai_socktype, curl_socket_t sockfd;
ai->ai_protocol);
sockfd = socket(ai->ai_family, conn->socktype, ai->ai_protocol);
if (sockfd == CURL_SOCKET_BAD) if (sockfd == CURL_SOCKET_BAD)
return CURL_SOCKET_BAD; return CURL_SOCKET_BAD;
@@ -660,7 +661,11 @@ singleipconnect(struct connectdata *conn,
/* set socket non-blocking */ /* set socket non-blocking */
Curl_nonblock(sockfd, TRUE); Curl_nonblock(sockfd, TRUE);
rc = connect(sockfd, ai->ai_addr, (socklen_t)ai->ai_addrlen); /* Connect TCP sockets, bind UDP */
if(conn->socktype == SOCK_STREAM)
rc = connect(sockfd, ai->ai_addr, (socklen_t)ai->ai_addrlen);
else
rc = 0;
if(-1 == rc) { if(-1 == rc) {
error = Curl_ourerrno(); error = Curl_ourerrno();

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 * to us. This function will sit and wait here until the server has
* connected. * connected.
* *
* If FTP-SSL is used and SSL is requested for the data connection, this
* function will do that transport layer handshake too.
*
*/ */
static CURLcode AllowServerConnect(struct connectdata *conn) static CURLcode AllowServerConnect(struct connectdata *conn)
{ {
CURLcode result;
int timeout_ms; int timeout_ms;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
curl_socket_t sock = conn->sock[SECONDARYSOCKET]; curl_socket_t sock = conn->sock[SECONDARYSOCKET];
@@ -235,17 +231,6 @@ static CURLcode AllowServerConnect(struct connectdata *conn)
break; break;
} }
/* If PASV is used, this is is made elsewhere */
if(conn->ssl[SECONDARYSOCKET].use) {
/* since we only have a plaintext TCP connection here, we must now
do the TLS stuff */
infof(data, "Doing the SSL/TLS handshake on the data stream\n");
/* BLOCKING */
result = Curl_ssl_connect(conn, SECONDARYSOCKET);
if(result)
return result;
}
return CURLE_OK; return CURLE_OK;
} }
@@ -858,7 +843,7 @@ static CURLcode ftp_state_use_port(struct connectdata *conn,
* Workaround for AIX5 getaddrinfo() problem (it doesn't set ai_socktype): * Workaround for AIX5 getaddrinfo() problem (it doesn't set ai_socktype):
*/ */
if (ai->ai_socktype == 0) if (ai->ai_socktype == 0)
ai->ai_socktype = SOCK_STREAM; ai->ai_socktype = conn->socktype;
portsock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); portsock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (portsock == CURL_SOCKET_BAD) { if (portsock == CURL_SOCKET_BAD) {
@@ -1601,8 +1586,18 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
return CURLE_FTP_WEIRD_227_FORMAT; return CURLE_FTP_WEIRD_227_FORMAT;
} }
snprintf(newhost, sizeof(newhost), /* we got OK from server */
"%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); if(data->set.ftp_skip_ip) {
/* told to ignore the remotely given IP but instead use the one we used
for the control connection */
infof(data, "Skips %d.%d.%d.%d for data connection, uses %s instead\n",
ip[0], ip[1], ip[2], ip[3],
conn->ip_addr_str);
snprintf(newhost, sizeof(newhost), "%s", conn->ip_addr_str);
}
else
snprintf(newhost, sizeof(newhost),
"%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
newport = (port[0]<<8) + port[1]; newport = (port[0]<<8) + port[1];
} }
else if(ftp->count1 == 0) { else if(ftp->count1 == 0) {
@@ -1622,8 +1617,6 @@ static CURLcode ftp_state_pasv_resp(struct connectdata *conn,
return CURLE_FTP_WEIRD_PASV_REPLY; return CURLE_FTP_WEIRD_PASV_REPLY;
} }
/* we got OK from server */
if(data->change.proxy && *data->change.proxy) { if(data->change.proxy && *data->change.proxy) {
/* /*
* This is a tunnel through a http proxy and we need to connect to the * This is a tunnel through a http proxy and we need to connect to the
@@ -1805,7 +1798,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
switch(data->set.timecondition) { switch(data->set.timecondition) {
case CURL_TIMECOND_IFMODSINCE: case CURL_TIMECOND_IFMODSINCE:
default: default:
if(data->info.filetime < data->set.timevalue) { if(data->info.filetime <= data->set.timevalue) {
infof(data, "The requested document is not new enough\n"); infof(data, "The requested document is not new enough\n");
ftp->no_transfer = TRUE; /* mark this to not transfer data */ ftp->no_transfer = TRUE; /* mark this to not transfer data */
state(conn, FTP_STOP); state(conn, FTP_STOP);
@@ -2032,6 +2025,16 @@ static CURLcode ftp_state_stor_resp(struct connectdata *conn,
return result; return result;
} }
if(conn->ssl[SECONDARYSOCKET].use) {
/* since we only have a plaintext TCP connection here, we must now
do the TLS stuff */
infof(data, "Doing the SSL/TLS handshake on the data stream\n");
/* BLOCKING */
result = Curl_ssl_connect(conn, SECONDARYSOCKET);
if(result)
return result;
}
*(ftp->bytecountp)=0; *(ftp->bytecountp)=0;
/* When we know we're uploading a specified file, we can get the file /* When we know we're uploading a specified file, we can get the file
@@ -2131,6 +2134,15 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
return result; return result;
} }
if(conn->ssl[SECONDARYSOCKET].use) {
/* since we only have a plaintext TCP connection here, we must now
do the TLS stuff */
infof(data, "Doing the SSL/TLS handshake on the data stream\n");
result = Curl_ssl_connect(conn, SECONDARYSOCKET);
if(result)
return result;
}
if(size > conn->maxdownload && conn->maxdownload > 0) if(size > conn->maxdownload && conn->maxdownload > 0)
size = conn->size = conn->maxdownload; size = conn->size = conn->maxdownload;
@@ -3092,18 +3104,6 @@ CURLcode Curl_ftp_nextconnect(struct connectdata *conn)
if(!ftp->no_transfer && !conn->bits.no_body) { if(!ftp->no_transfer && !conn->bits.no_body) {
/* a transfer is about to take place */ /* a transfer is about to take place */
if(conn->ssl[SECONDARYSOCKET].use &&
!data->set.ftp_use_port) {
/* PASV is used and we just got the data connection connected, then
it is time to handshake the secure stuff. */
infof(data, "Doing the SSL/TLS handshake on the data stream\n");
/* BLOCKING */
result = Curl_ssl_connect(conn, SECONDARYSOCKET);
if(result)
return result;
}
if(data->set.upload) { if(data->set.upload) {
NBFTPSENDF(conn, "TYPE %c", data->set.ftp_ascii?'A':'I'); NBFTPSENDF(conn, "TYPE %c", data->set.ftp_ascii?'A':'I');
state(conn, FTP_STOR_TYPE); state(conn, FTP_STOR_TYPE);
@@ -3811,6 +3811,7 @@ static CURLcode ftp_dophase_done(struct connectdata *conn,
/* Failure detected, close the second socket if it was created already */ /* Failure detected, close the second socket if it was created already */
sclose(conn->sock[SECONDARYSOCKET]); sclose(conn->sock[SECONDARYSOCKET]);
conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD; conn->sock[SECONDARYSOCKET] = CURL_SOCKET_BAD;
return result;
} }
if(ftp->no_transfer) if(ftp->no_transfer)

View File

@@ -423,7 +423,11 @@ Curl_addrinfo *Curl_he2ai(struct hostent *he, int port)
prevai->ai_next = ai; prevai->ai_next = ai;
ai->ai_family = AF_INET; /* we only support this */ ai->ai_family = AF_INET; /* we only support this */
ai->ai_socktype = SOCK_STREAM; /* we only support this */
/* we return all names as STREAM, so when using this address for TFTP
the type must be ignored and conn->socktype be used instead! */
ai->ai_socktype = SOCK_STREAM;
ai->ai_addrlen = sizeof(struct sockaddr_in); ai->ai_addrlen = sizeof(struct sockaddr_in);
/* make the ai_addr point to the address immediately following this struct /* make the ai_addr point to the address immediately following this struct
and use that area to store the address */ and use that area to store the address */

View File

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

View File

@@ -88,6 +88,10 @@
/* The last #include file should be: */ /* The last #include file should be: */
#include "memdebug.h" #include "memdebug.h"
#if defined(_MSC_VER) && defined(CURL_NO__BEGINTHREADEX)
#pragma message ("No _beginthreadex() available in this RTL")
#endif
/*********************************************************************** /***********************************************************************
* Only for Windows threaded name resolves builds * Only for Windows threaded name resolves builds
**********************************************************************/ **********************************************************************/
@@ -289,7 +293,7 @@ static unsigned __stdcall gethostbyname_thread (void *arg)
* This allows us to use it even after the container gets destroyed * This allows us to use it even after the container gets destroyed
* due to a resolver timeout. * due to a resolver timeout.
*/ */
struct thread_sync_data tsd = {0}; struct thread_sync_data tsd = { 0,0,0,NULL };
if (!init_thread_sync_data(td, conn->async.hostname, &tsd)) { if (!init_thread_sync_data(td, conn->async.hostname, &tsd)) {
/* thread synchronization data initialization failed */ /* thread synchronization data initialization failed */
return -1; return -1;
@@ -356,7 +360,7 @@ static unsigned __stdcall getaddrinfo_thread (void *arg)
* This allows us to use it even after the container gets destroyed * This allows us to use it even after the container gets destroyed
* due to a resolver timeout. * due to a resolver timeout.
*/ */
struct thread_sync_data tsd = {0}; struct thread_sync_data tsd = { 0,0,0,NULL };
if (!init_thread_sync_data(td, conn->async.hostname, &tsd)) { if (!init_thread_sync_data(td, conn->async.hostname, &tsd)) {
/* thread synchronization data initialization failed */ /* thread synchronization data initialization failed */
return -1; return -1;
@@ -559,7 +563,10 @@ static bool init_resolve_thread (struct connectdata *conn,
*/ */
thread_and_event[0] = td->thread_hnd; thread_and_event[0] = td->thread_hnd;
thread_and_event[1] = td->event_thread_started; thread_and_event[1] = td->event_thread_started;
if (WaitForMultipleObjects(sizeof(thread_and_event) / sizeof(thread_and_event[0]), thread_and_event, FALSE, INFINITE) == WAIT_FAILED) { if (WaitForMultipleObjects(sizeof(thread_and_event) /
sizeof(thread_and_event[0]),
thread_and_event, FALSE,
INFINITE) == WAIT_FAILED) {
/* The resolver thread has been created, /* The resolver thread has been created,
* most probably it works now - ignoring this "minor" error * most probably it works now - ignoring this "minor" error
*/ */
@@ -804,7 +811,7 @@ Curl_addrinfo *Curl_getaddrinfo(struct connectdata *conn,
memset(&hints, 0, sizeof(hints)); memset(&hints, 0, sizeof(hints));
hints.ai_family = pf; hints.ai_family = pf;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = conn->socktype;
hints.ai_flags = AI_CANONNAME; hints.ai_flags = AI_CANONNAME;
itoa(port, sbuf, 10); itoa(port, sbuf, 10);

View File

@@ -387,6 +387,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
ULONG attrs; ULONG attrs;
const char *user; const char *user;
int domlen; int domlen;
TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */
ntlm_sspi_cleanup(ntlm); ntlm_sspi_cleanup(ntlm);
@@ -430,8 +431,8 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
if (AcquireCredentialsHandle( if (AcquireCredentialsHandle(
NULL, (char *)"NTLM", SECPKG_CRED_OUTBOUND, NULL, ntlm->p_identity, NULL, (char *)"NTLM", SECPKG_CRED_OUTBOUND, NULL, ntlm->p_identity,
NULL, NULL, &ntlm->handle, NULL NULL, NULL, &ntlm->handle, &tsDummy
) != SEC_E_OK) { ) != SEC_E_OK) {
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
@@ -447,12 +448,23 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
ISC_REQ_REPLAY_DETECT | ISC_REQ_REPLAY_DETECT |
ISC_REQ_CONNECTION, ISC_REQ_CONNECTION,
0, SECURITY_NETWORK_DREP, NULL, 0, 0, SECURITY_NETWORK_DREP, NULL, 0,
&ntlm->c_handle, &desc, &attrs, NULL &ntlm->c_handle, &desc, &attrs, &tsDummy
); );
if (status == SEC_I_COMPLETE_AND_CONTINUE || if (status == SEC_I_COMPLETE_AND_CONTINUE ||
status == SEC_I_CONTINUE_NEEDED) { status == SEC_I_CONTINUE_NEEDED) {
CompleteAuthToken(&ntlm->c_handle, &desc); /* CompleteAuthToken() is not present in Win9x, so load it dynamically */
SECURITY_STATUS (__stdcall * pCompleteAuthToken)
(PCtxtHandle,PSecBufferDesc);
HMODULE hSecur32 = GetModuleHandle("secur32.dll");
if (hSecur32 != NULL) {
pCompleteAuthToken =
(SECURITY_STATUS (__stdcall *)(PCtxtHandle,PSecBufferDesc))
GetProcAddress(hSecur32, "CompleteAuthToken");
if( pCompleteAuthToken != NULL ) {
pCompleteAuthToken(&ntlm->c_handle, &desc);
}
}
} }
else if (status != SEC_E_OK) { else if (status != SEC_E_OK) {
FreeCredentialsHandle(&ntlm->handle); FreeCredentialsHandle(&ntlm->handle);
@@ -553,6 +565,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
SecBufferDesc type_2_desc, type_3_desc; SecBufferDesc type_2_desc, type_3_desc;
SECURITY_STATUS status; SECURITY_STATUS status;
ULONG attrs; ULONG attrs;
TimeStamp tsDummy; /* For Windows 9x compatibility of SPPI calls */
type_2_desc.ulVersion = type_3_desc.ulVersion = SECBUFFER_VERSION; type_2_desc.ulVersion = type_3_desc.ulVersion = SECBUFFER_VERSION;
type_2_desc.cBuffers = type_3_desc.cBuffers = 1; type_2_desc.cBuffers = type_3_desc.cBuffers = 1;
@@ -573,7 +586,7 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
ISC_REQ_CONNECTION, ISC_REQ_CONNECTION,
0, SECURITY_NETWORK_DREP, &type_2_desc, 0, SECURITY_NETWORK_DREP, &type_2_desc,
0, &ntlm->c_handle, &type_3_desc, 0, &ntlm->c_handle, &type_3_desc,
&attrs, NULL); &attrs, &tsDummy);
if (status != SEC_E_OK) if (status != SEC_E_OK)
return CURLE_RECV_ERROR; return CURLE_RECV_ERROR;
@@ -700,6 +713,13 @@ CURLcode Curl_output_ntlm(struct connectdata *conn,
size=64; size=64;
ntlmbuf[62]=ntlmbuf[63]=0; ntlmbuf[62]=ntlmbuf[63]=0;
/* Make sure that the user and domain strings fit in the target buffer
before we copy them there. */
if(size + userlen + domlen >= sizeof(ntlmbuf)) {
failf(conn->data, "user + domain name too big");
return CURLE_OUT_OF_MEMORY;
}
memcpy(&ntlmbuf[size], domain, domlen); memcpy(&ntlmbuf[size], domain, domlen);
size += domlen; size += domlen;

View File

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

View File

@@ -262,6 +262,14 @@ typedef int curl_socket_t;
#endif #endif
#endif #endif
/* "cl -ML" or "cl -MLd" implies a single-threaded runtime library where
_beginthreadex() is not available */
#if defined(_MSC_VER) && !defined(_MT) && !defined(USE_ARES)
#undef USE_THREADING_GETADDRINFO
#undef USE_THREADING_GETHOSTBYNAME
#define CURL_NO__BEGINTHREADEX
#endif
#ifdef mpeix #ifdef mpeix
#define IOCTL_3_ARGS #define IOCTL_3_ARGS
#endif #endif

View File

@@ -245,6 +245,27 @@ curl_easy_strerror(CURLcode error)
case CURLE_LOGIN_DENIED: case CURLE_LOGIN_DENIED:
return "FTP: login denied";; return "FTP: login denied";;
case CURLE_TFTP_NOTFOUND:
return "TFTP: File Not Found";;
case CURLE_TFTP_PERM:
return "TFTP: Access Violation";;
case CURLE_TFTP_DISKFULL:
return "TFTP: Disk full or allocation exceeded";;
case CURLE_TFTP_ILLEGAL:
return "TFTP: Illegal operation";;
case CURLE_TFTP_UNKNOWNID:
return "TFTP: Unknown transfer ID";;
case CURLE_TFTP_EXISTS:
return "TFTP: File already exists";;
case CURLE_TFTP_NOSUCHUSER:
return "TFTP: No such user";;
case CURLE_URL_MALFORMAT_USER: /* not used by current libcurl */ case CURLE_URL_MALFORMAT_USER: /* not used by current libcurl */
case CURLE_MALFORMAT_USER: /* not used by current libcurl */ case CURLE_MALFORMAT_USER: /* not used by current libcurl */
case CURLE_BAD_CALLING_ORDER: /* not used by current libcurl */ case CURLE_BAD_CALLING_ORDER: /* not used by current libcurl */

719
lib/tftp.c Normal file
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]-
Content-Range: bytes: [num]- Content-Range: bytes: [num]-
The second format was added August 1st 2000 by Igor The second format was added since Sun's webserver
Khristophorov since Sun's webserver JavaWebServer/1.1.1 JavaWebServer/1.1.1 obviously sends the header this way!
obviously sends the header this way! :-( */ */
char *ptr = strstr(k->p, "bytes"); char *ptr = Curl_strcasestr(k->p, "bytes");
ptr+=5; ptr+=5;
if(*ptr == ':') if(*ptr == ':')
@@ -1622,9 +1622,11 @@ Transfer(struct connectdata *conn)
CURLcode Curl_pretransfer(struct SessionHandle *data) CURLcode Curl_pretransfer(struct SessionHandle *data)
{ {
CURLcode res; CURLcode res;
if(!data->change.url) if(!data->change.url) {
/* we can't do anything wihout URL */ /* we can't do anything wihout URL */
failf(data, "No URL set!\n");
return CURLE_URL_MALFORMAT; return CURLE_URL_MALFORMAT;
}
/* Init the SSL session ID cache here. We do it here since we want to do it /* Init the SSL session ID cache here. We do it here since we want to do it
after the *_setopt() calls (that could change the size of the cache) but after the *_setopt() calls (that could change the size of the cache) but

View File

@@ -77,9 +77,7 @@
#error "We can't compile without socket() support!" #error "We can't compile without socket() support!"
#endif #endif
#endif #endif
#ifdef USE_LIBIDN #ifdef USE_LIBIDN
#include <idna.h> #include <idna.h>
#include <tld.h> #include <tld.h>
@@ -123,6 +121,7 @@ void idn_free (void *ptr); /* prototype from idn-free.h, not provided by
#include "ftp.h" #include "ftp.h"
#include "dict.h" #include "dict.h"
#include "telnet.h" #include "telnet.h"
#include "tftp.h"
#include "http.h" #include "http.h"
#include "file.h" #include "file.h"
#include "ldap.h" #include "ldap.h"
@@ -966,6 +965,14 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
data->set.ftp_use_epsv = va_arg(param, long)?TRUE:FALSE; data->set.ftp_use_epsv = va_arg(param, long)?TRUE:FALSE;
break; break;
case CURLOPT_FTP_SKIP_PASV_IP:
/*
* Enable or disable FTP_SKIP_PASV_IP, which will disable/enable the
* bypass of the IP address in PASV responses.
*/
data->set.ftp_skip_ip = (bool)va_arg(param, long);
break;
case CURLOPT_INFILE: case CURLOPT_INFILE:
/* /*
* FILE pointer to read the file to be uploaded from. Or possibly * FILE pointer to read the file to be uploaded from. Or possibly
@@ -1241,7 +1248,7 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option,
/* /*
* Set a SSL_CTX callback * Set a SSL_CTX callback
*/ */
data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback); data->set.ssl.fsslctx = va_arg(param, curl_ssl_ctx_callback);
break; break;
case CURLOPT_SSL_CTX_DATA: case CURLOPT_SSL_CTX_DATA:
/* /*
@@ -1994,7 +2001,8 @@ static CURLcode ConnectPlease(struct connectdata *conn,
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
char *hostname = data->change.proxy?conn->proxy.name:conn->host.name; char *hostname = data->change.proxy?conn->proxy.name:conn->host.name;
infof(data, "About to connect() to %s port %d\n", infof(data, "About to connect() to %s%s port %d\n",
data->change.proxy?"proxy ":"",
hostname, conn->port); hostname, conn->port);
/************************************************************* /*************************************************************
@@ -2722,6 +2730,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
* Setup internals depending on protocol * Setup internals depending on protocol
*************************************************************/ *************************************************************/
conn->socktype = SOCK_STREAM; /* most of them are TCP streams */
if (strequal(conn->protostr, "HTTP")) { if (strequal(conn->protostr, "HTTP")) {
#ifndef CURL_DISABLE_HTTP #ifndef CURL_DISABLE_HTTP
conn->port = PORT_HTTP; conn->port = PORT_HTTP;
@@ -2915,6 +2925,44 @@ static CURLcode CreateConnection(struct SessionHandle *data,
#else #else
failf(data, LIBCURL_NAME failf(data, LIBCURL_NAME
" was built with FILE disabled!"); " was built with FILE disabled!");
#endif
}
else if (strequal(conn->protostr, "TFTP")) {
#ifndef CURL_DISABLE_TFTP
char *type;
conn->socktype = SOCK_DGRAM; /* UDP datagram based */
conn->protocol |= PROT_TFTP;
conn->port = PORT_TFTP;
conn->remote_port = PORT_TFTP;
conn->curl_connect = Curl_tftp_connect;
conn->curl_do = Curl_tftp;
conn->curl_done = Curl_tftp_done;
/* TFTP URLs support an extension like ";mode=<typecode>" that
* we'll try to get now! */
type=strstr(conn->path, ";mode=");
if(!type) {
type=strstr(conn->host.rawalloc, ";mode=");
}
if(type) {
char command;
*type=0; /* it was in the middle of the hostname */
command = toupper((int)type[6]);
switch(command) {
case 'A': /* ASCII mode */
case 'N': /* NETASCII mode */
data->set.ftp_ascii = 1;
break;
case 'O': /* octet mode */
case 'I': /* binary mode */
default:
/* switch off ASCII */
data->set.ftp_ascii = 0;
break;
}
}
#else
failf(data, LIBCURL_NAME
" was built with TFTP disabled!");
#endif #endif
} }
else { else {

View File

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

View File

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

View File

@@ -25,7 +25,6 @@ CHEADER=src/version.h
# Replace version number in header file: # Replace version number in header file:
sed -e 's/^#define LIBCURL_VERSION .*/#define LIBCURL_VERSION "'$libversion'"/g' \ sed -e 's/^#define LIBCURL_VERSION .*/#define LIBCURL_VERSION "'$libversion'"/g' \
-e 's/^#define LIBCURL_VERSION_NUM .*/#define LIBCURL_VERSION_NUM 0x'$numeric'/g' \
-e 's/^#define LIBCURL_VERSION_MAJOR .*/#define LIBCURL_VERSION_MAJOR '$major'/g' \ -e 's/^#define LIBCURL_VERSION_MAJOR .*/#define LIBCURL_VERSION_MAJOR '$major'/g' \
-e 's/^#define LIBCURL_VERSION_MINOR .*/#define LIBCURL_VERSION_MINOR '$minor'/g' \ -e 's/^#define LIBCURL_VERSION_MINOR .*/#define LIBCURL_VERSION_MINOR '$minor'/g' \
-e 's/^#define LIBCURL_VERSION_PATCH .*/#define LIBCURL_VERSION_PATCH '$patch'/g' \ -e 's/^#define LIBCURL_VERSION_PATCH .*/#define LIBCURL_VERSION_PATCH '$patch'/g' \

View File

@@ -283,7 +283,7 @@ config.h: Makefile.netware
@echo $(DL)*/$(DL) >> $@ @echo $(DL)*/$(DL) >> $@
@echo $(DL)#define OS "i586-pc-NetWare"$(DL) >> $@ @echo $(DL)#define OS "i586-pc-NetWare"$(DL) >> $@
@echo $(DL)#define VERSION "$(LIBCURL_VERSION_STR)"$(DL) >> $@ @echo $(DL)#define VERSION "$(LIBCURL_VERSION_STR)"$(DL) >> $@
@echo $(DL)#define PACKAGE_BUGREPORT "curl-bug@haxx.se"$(DL) >> $@ @echo $(DL)#define PACKAGE_BUGREPORT "a suitable curl mailing list => http://curl.haxx.se/mail/"$(DL) >> $@
@echo $(DL)#define USE_MANUAL 1$(DL) >> $@ @echo $(DL)#define USE_MANUAL 1$(DL) >> $@
@echo $(DL)#define HAVE_ARPA_INET_H 1$(DL) >> $@ @echo $(DL)#define HAVE_ARPA_INET_H 1$(DL) >> $@
@echo $(DL)#define HAVE_ASSERT_H 1$(DL) >> $@ @echo $(DL)#define HAVE_ASSERT_H 1$(DL) >> $@

View File

@@ -315,6 +315,7 @@ struct Configurable {
bool insecure_ok; /* set TRUE to allow insecure SSL connects */ bool insecure_ok; /* set TRUE to allow insecure SSL connects */
bool create_dirs; bool create_dirs;
bool ftp_create_dirs; bool ftp_create_dirs;
bool ftp_skip_ip;
bool proxyntlm; bool proxyntlm;
bool proxydigest; bool proxydigest;
bool proxybasic; bool proxybasic;
@@ -508,7 +509,8 @@ static void help(void)
" --crlf Convert LF to CRLF in upload", " --crlf Convert LF to CRLF in upload",
" -f/--fail Fail silently (no output at all) on errors (H)", " -f/--fail Fail silently (no output at all) on errors (H)",
" --ftp-create-dirs Create the remote dirs if not present (F)", " --ftp-create-dirs Create the remote dirs if not present (F)",
" --ftp-pasv Use PASV instead of PORT (F)", " --ftp-pasv Use PASV/EPSV instead of PORT (F)",
" --ftp-skip-pasv-ip Skip the IP address for PASV (F)\n"
" --ftp-ssl Enable SSL/TLS for the ftp transfer (F)", " --ftp-ssl Enable SSL/TLS for the ftp transfer (F)",
" -F/--form <name=content> Specify HTTP multipart POST data (H)", " -F/--form <name=content> Specify HTTP multipart POST data (H)",
" --form-string <name=string> Specify HTTP multipart POST data (H)", " --form-string <name=string> Specify HTTP multipart POST data (H)",
@@ -1313,6 +1315,7 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
{"$n", "proxy-anyauth", FALSE}, {"$n", "proxy-anyauth", FALSE},
{"$o", "trace-time", FALSE}, {"$o", "trace-time", FALSE},
{"$p", "ignore-content-length", FALSE}, {"$p", "ignore-content-length", FALSE},
{"$q", "ftp-skip-pasv-ip", FALSE},
{"0", "http1.0", FALSE}, {"0", "http1.0", FALSE},
{"1", "tlsv1", FALSE}, {"1", "tlsv1", FALSE},
@@ -1709,6 +1712,9 @@ static ParameterError getparameter(char *flag, /* f or -long-flag */
case 'p': /* --ignore-content-length */ case 'p': /* --ignore-content-length */
config->ignorecl ^= TRUE; config->ignorecl ^= TRUE;
break; break;
case 'q': /* --ftp-skip-pasv-ip */
config->ftp_skip_ip ^= TRUE;
break;
} }
break; break;
case '#': /* --progress-bar */ case '#': /* --progress-bar */
@@ -3905,6 +3911,10 @@ operate(struct Configurable *config, int argc, char *argv[])
curl_easy_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl); curl_easy_setopt(curl, CURLOPT_IGNORE_CONTENT_LENGTH, config->ignorecl);
/* curl 7.14.2 */
curl_easy_setopt(curl, CURLOPT_FTP_SKIP_PASV_IP,
config->ftp_skip_ip);
retry_numretries = config->req_retry; retry_numretries = config->req_retry;
retrystart = curlx_tvnow(); retrystart = curlx_tvnow();
@@ -4149,15 +4159,15 @@ quit_curl:
if (config->engine) if (config->engine)
free(config->engine); free(config->engine);
/* cleanup the curl handle! */
curl_easy_cleanup(curl);
if(config->headerfile && !headerfilep && heads.stream) if(config->headerfile && !headerfilep && heads.stream)
fclose(heads.stream); fclose(heads.stream);
if(allocuseragent) if(allocuseragent)
free(config->useragent); free(config->useragent);
/* cleanup the curl handle! */
curl_easy_cleanup(curl);
if(config->trace_fopened && config->trace_stream) if(config->trace_fopened && config->trace_stream)
fclose(config->trace_stream); fclose(config->trace_stream);

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

View File

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

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 \ test237 test238 test239 test243 test245 test246 test247 test248 test249 \
test250 test251 test252 test253 test254 test255 test521 test522 test523 \ test250 test251 test252 test253 test254 test255 test521 test522 test523 \
test256 test257 test258 test259 test260 test261 test262 test263 test264 \ test256 test257 test258 test259 test260 test261 test262 test263 test264 \
test265 test266 test267 test268 test269 test265 test266 test267 test268 test269 test270 test271 test272

48
tests/data/test270 Normal file
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 $verbose=0; # set to 1 for debugging
my $pasvbadip=0;
my $retrweirdo=0; my $retrweirdo=0;
my $retrnosize=0; my $retrnosize=0;
my $srcdir="."; my $srcdir=".";
@@ -564,7 +565,11 @@ sub PASV_command {
if($cmd ne "EPSV") { if($cmd ne "EPSV") {
# PASV reply # PASV reply
sendcontrol sprintf("227 Entering Passive Mode (127,0,0,1,%d,%d)\n", my $p="127,0,0,1";
if($pasvbadip) {
$p="1,2,3,4";
}
sendcontrol sprintf("227 Entering Passive Mode ($p,%d,%d)\n",
($pasvport/256), ($pasvport%256)); ($pasvport/256), ($pasvport%256));
} }
else { else {
@@ -703,6 +708,10 @@ sub customize {
logmsg "FTPD: instructed to use RETRNOSIZE\n"; logmsg "FTPD: instructed to use RETRNOSIZE\n";
$retrnosize=1; $retrnosize=1;
} }
elsif($_ =~ /PASVBADIP/) {
logmsg "FTPD: instructed to use PASVBADIP\n";
$pasvbadip=1;
}
elsif($_ =~ /NOSAVE/) { elsif($_ =~ /NOSAVE/) {
# don't actually store the file we upload - to be used when # don't actually store the file we upload - to be used when
# uploading insanely huge amounts # uploading insanely huge amounts

View File

@@ -46,6 +46,8 @@ my $FTPPORT; # FTP server port
my $FTP2PORT; # FTP server 2 port my $FTP2PORT; # FTP server 2 port
my $FTPSPORT; # FTPS server port my $FTPSPORT; # FTPS server port
my $FTP6PORT; # FTP IPv6 server port my $FTP6PORT; # FTP IPv6 server port
my $TFTPPORT; # TFTP
my $TFTP6PORT; # TFTP
my $CURL="../src/curl"; # what curl executable to run on the tests my $CURL="../src/curl"; # what curl executable to run on the tests
my $DBGCURL=$CURL; #"../src/.libs/curl"; # alternative for debugging my $DBGCURL=$CURL; #"../src/.libs/curl"; # alternative for debugging
@@ -75,6 +77,8 @@ my $FTPPIDFILE=".ftp.pid";
my $FTP6PIDFILE=".ftp6.pid"; my $FTP6PIDFILE=".ftp6.pid";
my $FTP2PIDFILE=".ftp2.pid"; my $FTP2PIDFILE=".ftp2.pid";
my $FTPSPIDFILE=".ftps.pid"; my $FTPSPIDFILE=".ftps.pid";
my $TFTPPIDFILE=".tftpd.pid";
my $TFTP6PIDFILE=".tftp6.pid";
# invoke perl like this: # invoke perl like this:
my $perl="perl -I$srcdir"; my $perl="perl -I$srcdir";
@@ -128,6 +132,7 @@ my $large_file; # set if libcurl is built with large file support
my $has_idn; # set if libcurl is built with IDN support my $has_idn; # set if libcurl is built with IDN support
my $http_ipv6; # set if HTTP server has IPv6 support my $http_ipv6; # set if HTTP server has IPv6 support
my $ftp_ipv6; # set if FTP server has IPv6 support my $ftp_ipv6; # set if FTP server has IPv6 support
my $tftp_ipv6; # set if TFTP server has IPv6 support
my $has_ipv6; # set if libcurl is built with IPv6 support my $has_ipv6; # set if libcurl is built with IPv6 support
my $has_libz; # set if libcurl is built with libz support my $has_libz; # set if libcurl is built with libz support
my $has_getrlimit; # set if system has getrlimit() my $has_getrlimit; # set if system has getrlimit()
@@ -489,7 +494,8 @@ sub verifyftp {
my %protofunc = ('http' => \&verifyhttp, my %protofunc = ('http' => \&verifyhttp,
'https' => \&verifyhttp, 'https' => \&verifyhttp,
'ftp' => \&verifyftp); 'ftp' => \&verifyftp,
'tftp' => \&verifyftp);
sub verifyserver { sub verifyserver {
my ($proto, $ip, $port) = @_; my ($proto, $ip, $port) = @_;
@@ -691,6 +697,72 @@ sub runftpserver {
return ($pid2, $ftppid); return ($pid2, $ftppid);
} }
#######################################################################
# start the tftp server
#
sub runtftpserver {
my ($id, $verbose, $ipv6) = @_;
my $STATUS;
my $RUNNING;
my $port = $TFTPPORT;
# check for pidfile
my $pidfile = $TFTPPIDFILE;
my $ip=$HOSTIP;
my $nameext;
my $cmd;
if($ipv6) {
# if IPv6, use a different setup
$pidfile = $TFTP6PIDFILE;
$port = $TFTP6PORT;
$ip = $HOST6IP;
$nameext="-ipv6";
}
my $pid = checkserver($pidfile);
if($pid >= 0) {
stopserver($pid);
}
# start our server:
my $flag=$debugprotocol?"-v ":"";
$flag .= "-s \"$srcdir\" ";
if($id) {
$flag .="--id $id ";
}
if($ipv6) {
$flag .="--ipv6 ";
}
$cmd="./server/tftpd --pidfile $pidfile $flag $port";
unlink($pidfile);
my ($tftppid, $pid2) = startnew($cmd, $pidfile);
if(!$tftppid || !kill(0, $tftppid)) {
# it is NOT alive
logmsg "RUN: failed to start the FTP$id$nameext server!\n";
return -1;
}
# Server is up. Verify that we can speak to it.
if(!verifyserver("tftp", $ip, $port)) {
logmsg "RUN: TFTP$id$nameext server failed verification\n";
# failed to talk to it properly. Kill the server and return failure
stopserver("$tftppid $pid2");
return (0,0);
}
if($verbose) {
logmsg "RUN: TFTP$id$nameext server is now running PID $tftppid\n";
}
sleep(1);
return ($pid2, $tftppid);
}
####################################################################### #######################################################################
# Remove all files in the specified directory # Remove all files in the specified directory
# #
@@ -946,6 +1018,10 @@ sub checksystem {
if($ftp_ipv6) { if($ftp_ipv6) {
logmsg sprintf("* FTP IPv6 port: %d\n", $FTP6PORT); logmsg sprintf("* FTP IPv6 port: %d\n", $FTP6PORT);
} }
logmsg sprintf("* TFTP port: %d\n", $TFTPPORT);
if($tftp_ipv6) {
logmsg sprintf("* TFTP IPv6 port: %d\n", $TFTP6PORT);
}
if($ssl_version) { if($ssl_version) {
logmsg sprintf("* SSL library: %s\n", logmsg sprintf("* SSL library: %s\n",
@@ -974,6 +1050,8 @@ sub subVariables {
$$thing =~ s/%FTPSPORT/$FTPSPORT/g; $$thing =~ s/%FTPSPORT/$FTPSPORT/g;
$$thing =~ s/%SRCDIR/$srcdir/g; $$thing =~ s/%SRCDIR/$srcdir/g;
$$thing =~ s/%PWD/$pwd/g; $$thing =~ s/%PWD/$pwd/g;
$$thing =~ s/%TFTPPORT/$TFTPPORT/g;
$$thing =~ s/%TFTP6PORT/$TFTP6PORT/g;
} }
sub fixarray { sub fixarray {
@@ -1760,6 +1838,26 @@ sub startservers {
$run{'https'}="$pid $pid2"; $run{'https'}="$pid $pid2";
} }
} }
elsif($what eq "tftp") {
if(!$run{'tftp'}) {
($pid, $pid2) = runtftpserver("", $verbose);
if($pid <= 0) {
return "failed starting TFTP server";
}
printf ("* pid tftp => %d %d\n", $pid, $pid2) if($verbose);
$run{'tftp'}="$pid $pid2";
}
}
elsif($what eq "tftp-ipv6") {
if(!$run{'tftp-ipv6'}) {
($pid, $pid2) = runtftpserver("", $verbose, "IPv6");
if($pid <= 0) {
return "failed starting TFTP-IPv6 server";
}
printf("* pid tftp-ipv6 => %d %d\n", $pid, $pid2) if($verbose);
$run{'tftp-ipv6'}="$pid $pid2";
}
}
elsif($what eq "none") { elsif($what eq "none") {
logmsg "* starts no server\n" if ($verbose); logmsg "* starts no server\n" if ($verbose);
} }
@@ -1920,6 +2018,8 @@ $HTTP6PORT = $base + 4; # HTTP IPv6 server port (different IP protocol
# but we follow the same port scheme anyway) # but we follow the same port scheme anyway)
$FTP2PORT = $base + 5; # FTP server 2 port $FTP2PORT = $base + 5; # FTP server 2 port
$FTP6PORT = $base + 6; # FTP IPv6 port $FTP6PORT = $base + 6; # FTP IPv6 port
$TFTPPORT = $base + 7; # TFTP (UDP) port
$TFTP6PORT = $base + 8; # TFTP IPv6 (UDP) port
####################################################################### #######################################################################
# Output curl version and host info being tested # Output curl version and host info being tested

View File

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

View File

@@ -25,7 +25,7 @@ AUTOMAKE_OPTIONS = foreign
INCLUDES = -I$(top_srcdir)/lib -I$(top_srcdir)/include INCLUDES = -I$(top_srcdir)/lib -I$(top_srcdir)/include
noinst_PROGRAMS = sws getpart sockfilt resolve noinst_PROGRAMS = sws getpart sockfilt resolve tftpd
useful = getpart.c getpart.h $(top_srcdir)/lib/strequal.c \ useful = getpart.c getpart.h $(top_srcdir)/lib/strequal.c \
$(top_srcdir)/lib/base64.c $(top_srcdir)/lib/mprintf.c \ $(top_srcdir)/lib/base64.c $(top_srcdir)/lib/mprintf.c \
@@ -36,5 +36,7 @@ sws_SOURCES= sws.c util.c util.h $(useful)
sockfilt_SOURCES = sockfilt.c util.c util.h $(useful) \ sockfilt_SOURCES = sockfilt.c util.c util.h $(useful) \
$(top_srcdir)/lib/inet_pton.c $(top_srcdir)/lib/inet_pton.c
getpart_SOURCES= testpart.c $(useful) getpart_SOURCES= testpart.c $(useful)
tftpd_SOURCES = tftpd.c util.c util.h $(useful)
extra_DIST = base64.pl extra_DIST = base64.pl

View File

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

900
tests/server/tftpd.c Normal file
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 #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 #define TRUE 1
#endif #endif
#define TEST_DATA_PATH "%s/data/test%ld"
/* global variable, where to find the 'data' dir */
extern const char *path;
#if defined(WIN32) && !defined(__CYGWIN__) #if defined(WIN32) && !defined(__CYGWIN__)
#include <windows.h> #include <windows.h>
#include <winsock2.h> #include <winsock2.h>
@@ -60,3 +65,6 @@ const struct in6_addr in6addr_any = {{ IN6ADDR_ANY_INIT }};
void win32_init(void); void win32_init(void);
void win32_cleanup(void); void win32_cleanup(void);
/* returns the path name to the test case file */
char *test2file(long testno);

View File

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