尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

curl 的 `--tftp-no-options` 选项:彻底禁用 TFTP 选项协商以兼容老旧服务器

curl 的 `--tftp-no-options` 选项:彻底禁用 TFTP 选项协商以兼容老旧服务器 curl 的--tftp-no-options选项彻底禁用 TFTP 选项协商以兼容老旧服务器【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl--tftp-no-options是 curl 命令行工具中用于 TFTP 协议的开关选项自 7.48.0 起提供它让客户端在发送 RRQ读请求与 WRQ写请求时完全不携带任何 TFTP 扩展选项从而绕开部分老旧服务器对选项协商支持不完整导致的传输失败。本文以 tftp-no-options.md 文档为骨架结合 lib/tftp.c 的实现、CURLOPT_TFTP_NO_OPTIONS编程接口以及 tests/data/test1242、tests/data/test1243 测试用例说明该选项的使用方法、底层原理与适用场景。选项速览在 curl 的命令行手册中--tftp-no-options的元数据定义如下摘自 docs/cmdline-opts/tftp-no-options.md长选项名--tftp-no-options帮助文本Do not send any TFTP options不发送任何 TFTP 选项适用协议仅 TFTP引入版本7.48.0参数类型boolean布尔开关不需要携带值取值语义Multiboolean即使用一次即生效重复指定不改变行为使用方式非常简单直接在 TFTP URL 前加上该开关即可curl --tftp-no-options tftp://192.168.0.1/与--tftp-blksize不同它不需要跟随任何数值参数因为它表达的是一个关闭某能力的语义而不是设置某个值。该选项解决什么问题TFTP 协议RFC 1350的报文格式非常精简RRQ/WRQ 请求包由opcode 文件名 0 传输模式(octet/netascii) 0构成。在此基础上RFC 2347、RFC 2348、RFC 2349 引入了选项协商机制客户端可以在请求包中追加形如option\0value\0的键值对常见的选项包括选项名来源 RFC作用blksizeRFC 2348协商数据块大小默认 512 字节可增大以减少包数tsizeRFC 2349协商传输文件大小下载时用于进度显示timeoutRFC 2349协商重传超时时间秒这些选项的实现可见于 lib/tftp.c 中的宏定义#define TFTP_OPTION_BLKSIZE blksize #define TFTP_OPTION_TSIZE tsize #define TFTP_OPTION_INTERVAL timeout问题在于并非所有 TFTP 服务器都完整实现了选项协商。一些老旧的嵌入式设备固件或最小化实现的服务端要么不返回 OACKOption Acknowledgment选项确认包要么对未知选项返回 ERROR 包导致本来可以正常完成的文件传输直接失败。--tftp-no-options正是为应对这类互操作性问题而生关闭选项发送让 curl 退回到最朴素的、所有 TFTP 服务器都支持的 RFC 1350 基础行为。与--tftp-blksize的联动关系两个选项高度相关且官方文档明确指出了它们的优先级关系When this option is used --tftp-blksize is ignored. 使用本选项时--tftp-blksize将被忽略。也就是说# 即便同时指定了 blksize由于 tftp-no-options 存在blksize 不生效 curl --tftp-no-options --tftp-blksize 1024 tftp://example.com/file此时 curl 仍会以默认的 512 字节块大小进行传输。这符合逻辑既然请求包中不带任何选项包括blksize那么客户端必须按 RFC 1350 的默认值 512 字节收发数据服务器端也不会通过 OACK 告知新的块大小。关于--tftp-blksize本身的约束必须大于等于 512参见 docs/cmdline-opts/tftp-blksize.md。源码实现选项是如何被跳过的curl 的 TFTP 协议实现在 lib/tftp.c 中首次请求包的构造位于tftp_send_first()函数lib/tftp.c#L651-L742。关键逻辑在第 713 行/* optional addition of TFTP options */ if(!data-set.tftp_no_options) { char buf[64]; /* add tsize option */ ... result tftp_option_add(state, sbytes, sbytes, TFTP_OPTION_TSIZE); ... /* add blksize option */ ... /* add timeout option */ ... }从源码结构可以清晰看到无论是否禁用选项请求包的基础部分opcode、文件名、octet/netascii模式都会先被构造出来只有当data-set.tftp_no_options为假即未指定该选项时才会依次调用tftp_option_add()lib/tftp.c#L332-L345追加tsize、blksize、timeout三组选项指定--tftp-no-options后这段代码整体被跳过发出的就是一个最原始的 RRQ/WRQ 包。tftp_option_add()的实现也值得注意它会校验剩余缓冲空间是否足够容纳选项名与值长度不足时返回CURLE_TFTP_ILLEGAL这正是选项协商需要额外缓冲区的根源——禁用选项后请求包体积固定为最小形态天然规避了缓冲区过小这类边界问题。另外即便关闭了客户端侧发送选项tftp_parse_option_ack()lib/tftp.c#L259-L329仍保留了 OACK 解析能力它会把blksize复位为默认值 512state-blksize TFTP_BLKSIZE_DEFAULT;并校验服务器返回的blksize不超过客户端请求值、tsize用于下载进度等。这表明该开关的语义是客户端不主动发起协商而非完全拒绝理解选项报文。命令行层面的解析--tftp-no-options在命令行工具中的注册位于 src/tool_getparam.c{tftp-no-options, ARG_BOOL, , C_TFTP_NO_OPTIONS},ARG_BOOL表示这是一个布尔型开关不需要额外取值。其处理分支在 src/tool_getparam.ccase C_TFTP_NO_OPTIONS: /* --tftp-no-options */ config-tftp_no_options toggle;布尔型参数支持--tftp-no-options与--no-tftp-no-options两种写法后者用于显式关闭该行为对应 curl 布尔选项的通用约定。解析得到的值随后在运行时被传递到 libcurl 的CURLOPT_TFTP_NO_OPTIONS选项参见 lib/setopt.c 的s-tftp_no_options enabled;最终被 lib/tftp.c 消费。libcurl 编程接口CURLOPT_TFTP_NO_OPTIONS对于使用 libcurl 库的开发者对应的接口是CURLOPT_TFTP_NO_OPTIONS其完整说明见 docs/libcurl/opts/CURLOPT_TFTP_NO_OPTIONS.md。函数原型#include curl/curl.h CURLcode curl_easy_setopt(CURL *handle, CURLOPT_TFTP_NO_OPTIONS, long onoff);参数语义设置onoff为1L时从读写请求中排除 RFC 2347、RFC 2348 与 RFC 2349 定义的所有 TFTP 选项设置为0L默认值时恢复选项协商。默认值0即默认开启选项协商。官方文档给出了一段完整的下载示例整理如下static size_t write_callback(char *ptr, size_t size, size_t nmemb, void *fp) { return fwrite(ptr, size, nmemb, (FILE *)fp); } int main(void) { CURL *curl curl_easy_init(); if(curl) { CURLcode result CURLE_OK; FILE *fp fopen(foo.bin, wb); if(fp) { curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)fp); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback); curl_easy_setopt(curl, CURLOPT_URL, tftp://example.com/foo.bin); /* do not send TFTP options requests */ curl_easy_setopt(curl, CURLOPT_TFTP_NO_OPTIONS, 1L); /* Perform the request */ result curl_easy_perform(curl); fclose(fp); } curl_easy_cleanup(curl); } }返回值与所有curl_easy_setopt一致CURLE_OK (0)表示设置成功非零表示出错错误码含义见 docs/libcurl/curl_easy_setopt.md。该选项在include/curl/curl.h与 lib/easyoptions.c 中均有注册属于稳定的公共 API。测试用例验证curl 自带的集成测试直接验证了该选项的行为测试数据位于 tests/data/test1242下载场景与 tests/data/test1243上传场景。test1242 —— 不带选项的 RRQ下载command tftp://%HOSTIP:%TFTPPORT//%TESTNUMBER --tftp-no-options /command ... protocol opcode 1 mode octet filename /%TESTNUMBER /protocol验证伪协议明确要求请求包中只有opcode 1RRQ、mode octet、文件名三项内容没有任何选项键值对。test1243 —— 不带选项的 WRQ上传command -T %LOGDIR/test%TESTNUMBER.txt tftp://%HOSTIP:%TFTPPORT// --tftp-no-options /command ... protocol opcode 2 mode octet filename /test%TESTNUMBER.txt /protocol同样要求opcode 2WRQ报文中不携带任何选项。这两个用例从下载与上传两个方向共同保证了--tftp-no-options的行为契约请求包退化为纯 RFC 1350 形态。使用建议与注意事项什么时候该用当连接某些老旧 TFTP 服务器出现握手后无响应、服务器返回 ERROR或超时重传等异常且排除了网络原因时可优先尝试--tftp-no-options。它牺牲的是块大小、超时、文件大小等优化能力换来的是最大化的兼容性。代价禁用选项后块大小固定为 512 字节大文件传输的包数量显著增加传输效率会下降同时--tftp-blksize的设置会被忽略。与进度显示的关系tsize选项被禁用后下载侧无法在传输前获知文件大小源码中Curl_pgrsSetDownloadSize()仅在 OACK 携带tsize时被调用因此进度条可能无法显示总字节数。适用范围该选项仅对 TFTP 协议有意义对其他协议HTTP、FTP 等无效在非 TFTP 请求中指定会被忽略。延伸阅读命令行选项完整说明docs/cmdline-opts/tftp-no-options.md、docs/cmdline-opts/tftp-blksize.mdlibcurl 编程接口docs/libcurl/opts/CURLOPT_TFTP_NO_OPTIONS.md、docs/libcurl/curl_easy_setopt.md核心实现lib/tftp.c请求构造tftp_send_first、选项追加tftp_option_add、OACK 解析tftp_parse_option_ack选项注册src/tool_getparam.c、lib/setopt.c集成测试tests/data/test1242、tests/data/test1243【免费下载链接】curlA command line tool and library for transferring data with URL syntax, supporting DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. libcurl offers a myriad of powerful features项目地址: https://gitcode.com/GitHub_Trending/cu/curl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表