diff options
Diffstat (limited to 'net/tftp.c')
-rw-r--r-- | net/tftp.c | 103 |
1 files changed, 75 insertions, 28 deletions
diff --git a/net/tftp.c b/net/tftp.c index dea9c25ffd8..39421f8daa7 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -708,44 +708,91 @@ static int tftp_init_load_addr(void) return 0; } +static int saved_tftp_block_size_option; +static void sanitize_tftp_block_size_option(enum proto_t protocol) +{ + int cap, max_defrag; + + switch (protocol) { + case TFTPGET: + max_defrag = config_opt_enabled(CONFIG_IP_DEFRAG, CONFIG_NET_MAXDEFRAG, 0); + if (max_defrag) { + /* Account for IP, UDP and TFTP headers. */ + cap = max_defrag - (20 + 8 + 4); + /* RFC2348 sets a hard upper limit. */ + cap = min(cap, 65464); + break; + } + /* + * If not CONFIG_IP_DEFRAG, cap at the same value as + * for tftp put, namely normal MTU minus protocol + * overhead. + */ + fallthrough; + case TFTPPUT: + default: + /* + * U-Boot does not support IP fragmentation on TX, so + * this must be small enough that it fits normal MTU + * (and small enough that it fits net_tx_packet which + * has room for PKTSIZE_ALIGN bytes). + */ + cap = 1468; + } + if (tftp_block_size_option > cap) { + printf("Capping tftp block size option to %d (was %d)\n", + cap, tftp_block_size_option); + saved_tftp_block_size_option = tftp_block_size_option; + tftp_block_size_option = cap; + } +} + void tftp_start(enum proto_t protocol) { -#if CONFIG_NET_TFTP_VARS - char *ep; /* Environment pointer */ + __maybe_unused char *ep; /* Environment pointer */ - /* - * Allow the user to choose TFTP blocksize and timeout. - * TFTP protocol has a minimal timeout of 1 second. - */ + if (saved_tftp_block_size_option) { + tftp_block_size_option = saved_tftp_block_size_option; + saved_tftp_block_size_option = 0; + } - ep = env_get("tftpblocksize"); - if (ep != NULL) - tftp_block_size_option = simple_strtol(ep, NULL, 10); + if (IS_ENABLED(CONFIG_NET_TFTP_VARS)) { - ep = env_get("tftpwindowsize"); - if (ep != NULL) - tftp_window_size_option = simple_strtol(ep, NULL, 10); + /* + * Allow the user to choose TFTP blocksize and timeout. + * TFTP protocol has a minimal timeout of 1 second. + */ - ep = env_get("tftptimeout"); - if (ep != NULL) - timeout_ms = simple_strtol(ep, NULL, 10); + ep = env_get("tftpblocksize"); + if (ep != NULL) + tftp_block_size_option = simple_strtol(ep, NULL, 10); - if (timeout_ms < 1000) { - printf("TFTP timeout (%ld ms) too low, set min = 1000 ms\n", - timeout_ms); - timeout_ms = 1000; - } + ep = env_get("tftpwindowsize"); + if (ep != NULL) + tftp_window_size_option = simple_strtol(ep, NULL, 10); - ep = env_get("tftptimeoutcountmax"); - if (ep != NULL) - tftp_timeout_count_max = simple_strtol(ep, NULL, 10); + ep = env_get("tftptimeout"); + if (ep != NULL) + timeout_ms = simple_strtol(ep, NULL, 10); + + if (timeout_ms < 1000) { + printf("TFTP timeout (%ld ms) too low, set min = 1000 ms\n", + timeout_ms); + timeout_ms = 1000; + } + + ep = env_get("tftptimeoutcountmax"); + if (ep != NULL) + tftp_timeout_count_max = simple_strtol(ep, NULL, 10); - if (tftp_timeout_count_max < 0) { - printf("TFTP timeout count max (%d ms) negative, set to 0\n", - tftp_timeout_count_max); - tftp_timeout_count_max = 0; + if (tftp_timeout_count_max < 0) { + printf("TFTP timeout count max (%d ms) negative, set to 0\n", + tftp_timeout_count_max); + tftp_timeout_count_max = 0; + } } -#endif + + sanitize_tftp_block_size_option(protocol); debug("TFTP blocksize = %i, TFTP windowsize = %d timeout = %ld ms\n", tftp_block_size_option, tftp_window_size_option, timeout_ms); |