TFTP: add option to suppress TFTP option requests (Part 1)
Some TFTP server implementations ignore the "TFTP Option extension" (RFC 1782-1784, 2347-2349), or implement it in a flawed way, causing problems with libcurl. Another switch for curl_easy_setopt "CURLOPT_TFTP_NO_OPTIONS" is introduced which prevents libcurl from sending TFTP option requests to a server, avoiding many problems caused by faulty implementations. Bug: https://github.com/curl/curl/issues/481
This commit is contained in:
		 Michael Koenig
					Michael Koenig
				
			
				
					committed by
					
						 Jay Satiro
						Jay Satiro
					
				
			
			
				
	
			
			
			 Jay Satiro
						Jay Satiro
					
				
			
						parent
						
							527e86b054
						
					
				
				
					commit
					9dc3eaee29
				
			| @@ -314,6 +314,8 @@ Authentication address. See \fICURLOPT_MAIL_AUTH(3)\fP | |||||||
| .SH TFTP OPTIONS | .SH TFTP OPTIONS | ||||||
| .IP CURLOPT_TFTP_BLKSIZE | .IP CURLOPT_TFTP_BLKSIZE | ||||||
| TFTP block size. See \fICURLOPT_TFTP_BLKSIZE(3)\fP | TFTP block size. See \fICURLOPT_TFTP_BLKSIZE(3)\fP | ||||||
|  | .IP CURLOPT_TFTP_NO_OPTIONS | ||||||
|  | Prevents TFTP options to be send with RRQs/WRQs. See \fICURLOPT_TFTP_NO_OPTIONS(3)\fP | ||||||
| .SH FTP OPTIONS | .SH FTP OPTIONS | ||||||
| .IP CURLOPT_FTPPORT | .IP CURLOPT_FTPPORT | ||||||
| Use active FTP. See \fICURLOPT_FTPPORT(3)\fP | Use active FTP. See \fICURLOPT_FTPPORT(3)\fP | ||||||
|   | |||||||
							
								
								
									
										44
									
								
								docs/libcurl/opts/CURLOPT_TFTP_NO_OPTIONS.3
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								docs/libcurl/opts/CURLOPT_TFTP_NO_OPTIONS.3
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | |||||||
|  | .\" ************************************************************************** | ||||||
|  | .\" *                                  _   _ ____  _ | ||||||
|  | .\" *  Project                     ___| | | |  _ \| | | ||||||
|  | .\" *                             / __| | | | |_) | | | ||||||
|  | .\" *                            | (__| |_| |  _ <| |___ | ||||||
|  | .\" *                             \___|\___/|_| \_\_____| | ||||||
|  | .\" * | ||||||
|  | .\" * Copyright (C) 1998 - 2014, 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. | ||||||
|  | .\" * | ||||||
|  | .\" ************************************************************************** | ||||||
|  | .\" | ||||||
|  | .TH CURLOPT_TFTP_NO_OPTIONS 3 "19 Jun 2014" "libcurl 7.37.0" "curl_easy_setopt options" | ||||||
|  | .SH NAME | ||||||
|  | CURLOPT_TFTP_NO_OPTIONS \- Prevents TFTP options to be send with RRQs/WRQs | ||||||
|  | .SH SYNOPSIS | ||||||
|  | #include <curl/curl.h> | ||||||
|  |  | ||||||
|  | CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TFTP_NO_OPTIONS, long sendoptions); | ||||||
|  | .SH DESCRIPTION | ||||||
|  | Set \fIsendoptions\fP to 1 to exclude all TFTP options defined in RFC2347, | ||||||
|  | RFC2348, RFC2349 from read and write requests. | ||||||
|  | libcurl will behave like a client implementing only RFC1350, ignoring any | ||||||
|  | protocol extensions. | ||||||
|  | .SH DEFAULT | ||||||
|  | 0 | ||||||
|  | .SH PROTOCOLS | ||||||
|  | TFTP | ||||||
|  | .SH EXAMPLE | ||||||
|  | TODO | ||||||
|  | .SH AVAILABILITY | ||||||
|  | Added in 7.48.0 | ||||||
|  | .SH RETURN VALUE | ||||||
|  | Returns CURLE_OK if the option is supported, and CURLE_UNKNOWN_OPTION if not. | ||||||
| @@ -537,6 +537,7 @@ CURLOPT_TCP_KEEPINTVL           7.25.0 | |||||||
| CURLOPT_TCP_NODELAY             7.11.2 | CURLOPT_TCP_NODELAY             7.11.2 | ||||||
| CURLOPT_TELNETOPTIONS           7.7 | CURLOPT_TELNETOPTIONS           7.7 | ||||||
| CURLOPT_TFTP_BLKSIZE            7.19.4 | CURLOPT_TFTP_BLKSIZE            7.19.4 | ||||||
|  | CURLOPT_TFTP_NO_OPTIONS         7.48.0 | ||||||
| CURLOPT_TIMECONDITION           7.1 | CURLOPT_TIMECONDITION           7.1 | ||||||
| CURLOPT_TIMEOUT                 7.1 | CURLOPT_TIMEOUT                 7.1 | ||||||
| CURLOPT_TIMEOUT_MS              7.16.2 | CURLOPT_TIMEOUT_MS              7.16.2 | ||||||
|   | |||||||
| @@ -1673,6 +1673,9 @@ typedef enum { | |||||||
|   /* Set E-xclusive stream dependency on another CURL handle */ |   /* Set E-xclusive stream dependency on another CURL handle */ | ||||||
|   CINIT(STREAM_DEPENDS_E, OBJECTPOINT, 241), |   CINIT(STREAM_DEPENDS_E, OBJECTPOINT, 241), | ||||||
|  |  | ||||||
|  |   /* Do not send any tftp option requests to the server */ | ||||||
|  |   CINIT(TFTP_NO_OPTIONS, LONG, 242), | ||||||
|  |  | ||||||
|   CURLOPT_LASTENTRY /* the last unused */ |   CURLOPT_LASTENTRY /* the last unused */ | ||||||
| } CURLoption; | } CURLoption; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -494,6 +494,8 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event) | |||||||
|              "%s%c%s%c", filename, '\0',  mode, '\0'); |              "%s%c%s%c", filename, '\0',  mode, '\0'); | ||||||
|     sbytes = 4 + strlen(filename) + strlen(mode); |     sbytes = 4 + strlen(filename) + strlen(mode); | ||||||
|  |  | ||||||
|  |     /* optional addition of TFTP options */ | ||||||
|  |     if(!data->set.tftp_no_options) { | ||||||
|       /* add tsize option */ |       /* add tsize option */ | ||||||
|       if(data->set.upload && (data->state.infilesize != -1)) |       if(data->set.upload && (data->state.infilesize != -1)) | ||||||
|         snprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T, |         snprintf(buf, sizeof(buf), "%" CURL_FORMAT_CURL_OFF_T, | ||||||
| @@ -507,7 +509,7 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event) | |||||||
|       sbytes += tftp_option_add(state, sbytes, |       sbytes += tftp_option_add(state, sbytes, | ||||||
|                                 (char *)state->spacket.data+sbytes, buf); |                                 (char *)state->spacket.data+sbytes, buf); | ||||||
|       /* add blksize option */ |       /* add blksize option */ | ||||||
|     snprintf( buf, sizeof(buf), "%d", state->requested_blksize ); |       snprintf(buf, sizeof(buf), "%d", state->requested_blksize); | ||||||
|       sbytes += tftp_option_add(state, sbytes, |       sbytes += tftp_option_add(state, sbytes, | ||||||
|                                 (char *)state->spacket.data+sbytes, |                                 (char *)state->spacket.data+sbytes, | ||||||
|                                 TFTP_OPTION_BLKSIZE); |                                 TFTP_OPTION_BLKSIZE); | ||||||
| @@ -515,12 +517,13 @@ static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event) | |||||||
|                                 (char *)state->spacket.data+sbytes, buf ); |                                 (char *)state->spacket.data+sbytes, buf ); | ||||||
|  |  | ||||||
|       /* add timeout option */ |       /* add timeout option */ | ||||||
|     snprintf( buf, sizeof(buf), "%d", state->retry_time); |       snprintf(buf, sizeof(buf), "%d", state->retry_time); | ||||||
|       sbytes += tftp_option_add(state, sbytes, |       sbytes += tftp_option_add(state, sbytes, | ||||||
|                                 (char *)state->spacket.data+sbytes, |                                 (char *)state->spacket.data+sbytes, | ||||||
|                                 TFTP_OPTION_INTERVAL); |                                 TFTP_OPTION_INTERVAL); | ||||||
|       sbytes += tftp_option_add(state, sbytes, |       sbytes += tftp_option_add(state, sbytes, | ||||||
|                                 (char *)state->spacket.data+sbytes, buf ); |                                 (char *)state->spacket.data+sbytes, buf ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /* the typecase for the 3rd argument is mostly for systems that do |     /* the typecase for the 3rd argument is mostly for systems that do | ||||||
|        not have a size_t argument, like older unixes that want an 'int' */ |        not have a size_t argument, like older unixes that want an 'int' */ | ||||||
|   | |||||||
| @@ -843,9 +843,16 @@ CURLcode Curl_setopt(struct SessionHandle *data, CURLoption option, | |||||||
|      */ |      */ | ||||||
|     data->set.server_response_timeout = va_arg( param , long ) * 1000; |     data->set.server_response_timeout = va_arg( param , long ) * 1000; | ||||||
|     break; |     break; | ||||||
|  |   case CURLOPT_TFTP_NO_OPTIONS: | ||||||
|  |     /* | ||||||
|  |      * Option that prevents libcurl from sending TFTP option requests to the | ||||||
|  |      * server. | ||||||
|  |      */ | ||||||
|  |     data->set.tftp_no_options = va_arg(param, long) != 0; | ||||||
|  |     break; | ||||||
|   case CURLOPT_TFTP_BLKSIZE: |   case CURLOPT_TFTP_BLKSIZE: | ||||||
|     /* |     /* | ||||||
|      * TFTP option that specifies the block size to use for data transmission |      * TFTP option that specifies the block size to use for data transmission. | ||||||
|      */ |      */ | ||||||
|     data->set.tftp_blksize = va_arg(param, long); |     data->set.tftp_blksize = va_arg(param, long); | ||||||
|     break; |     break; | ||||||
|   | |||||||
| @@ -1499,7 +1499,8 @@ struct UserDefined { | |||||||
|   long connecttimeout;  /* in milliseconds, 0 means no timeout */ |   long connecttimeout;  /* in milliseconds, 0 means no timeout */ | ||||||
|   long accepttimeout;   /* in milliseconds, 0 means no timeout */ |   long accepttimeout;   /* in milliseconds, 0 means no timeout */ | ||||||
|   long server_response_timeout; /* in milliseconds, 0 means no timeout */ |   long server_response_timeout; /* in milliseconds, 0 means no timeout */ | ||||||
|   long tftp_blksize ; /* in bytes, 0 means use default */ |   long tftp_blksize;    /* in bytes, 0 means use default */ | ||||||
|  |   bool tftp_no_options; /* do not send TFTP options requests */ | ||||||
|   curl_off_t filesize;  /* size of file to upload, -1 means unknown */ |   curl_off_t filesize;  /* size of file to upload, -1 means unknown */ | ||||||
|   long low_speed_limit; /* bytes/second */ |   long low_speed_limit; /* bytes/second */ | ||||||
|   long low_speed_time;  /* number of seconds */ |   long low_speed_time;  /* number of seconds */ | ||||||
|   | |||||||
| @@ -1242,6 +1242,8 @@ | |||||||
|      d                 c                   10240 |      d                 c                   10240 | ||||||
|      d  CURLOPT_STREAM_DEPENDS_E... |      d  CURLOPT_STREAM_DEPENDS_E... | ||||||
|      d                 c                   10241 |      d                 c                   10241 | ||||||
|  |      d  CURLOPT_TFTP_NO_OPTIONS... | ||||||
|  |      d                 c                   10242 | ||||||
|       * |       * | ||||||
|       /if not defined(CURL_NO_OLDIES) |       /if not defined(CURL_NO_OLDIES) | ||||||
|      d  CURLOPT_FILE   c                   10001 |      d  CURLOPT_FILE   c                   10001 | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user