tftp: optional tftp-hpa compat
authorDenys Vlasenko <vda.linux@googlemail.com>
Sun, 9 Jun 2019 09:12:02 +0000 (11:12 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Sun, 9 Jun 2019 09:12:02 +0000 (11:12 +0200)
function                                             old     new   delta
tftp_main                                            276     394    +118

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
libbb/xconnect.c
networking/tftp.c

index ea5fe173f984132bcd6e7938ee40f468129c5073..eb2871cb10c6ff8b7c9ec109a72215e67b5c4ff3 100644 (file)
@@ -133,6 +133,7 @@ unsigned FAST_FUNC bb_lookup_port(const char *port, const char *protocol, unsign
                        port_nr = default_port;
                        if (tserv)
                                port_nr = ntohs(tserv->s_port);
+//FIXME: else: port string was garbage, but we don't report that???
                }
                errno = old_errno;
        }
index 5ebd221059f8b4782ba3b922d8ade21f2f4ca089..30232ef8e54d31e0c365f7298fdf47d41de22d4a 100644 (file)
 //config:      default y
 //config:      depends on TFTP
 //config:
+//config:config FEATURE_TFTP_HPA_COMPAT
+//config:      bool "tftp-hpa compat (support -c get/put FILE)"
+//config:      default y
+//config:      depends on TFTP
+//config:
 //config:config TFTPD
 //config:      bool "tftpd (10 kb)"
 //config:      default y
 //usage:       IF_FEATURE_TFTP_BLOCKSIZE(
 //usage:     "\n       -b SIZE Transfer blocks of SIZE octets"
 //usage:       )
+///////:     "\n       -m STR  Accepted and ignored ('-m binary' compat with tftp-hpa 5.2)"
 //usage:
 //usage:#define tftpd_trivial_usage
-//usage:       "[-cr] [-u USER] [DIR]"
+//usage:       "[-crl] [-u USER] [DIR]"
 //usage:#define tftpd_full_usage "\n\n"
 //usage:       "Transfer a file on tftp client's request\n"
 //usage:       "\n"
@@ -759,15 +765,46 @@ int tftp_main(int argc UNUSED_PARAM, char **argv)
 
        INIT_G();
 
+       if (ENABLE_FEATURE_TFTP_HPA_COMPAT) {
+               /* As of 2019, common tftp client in Linux distros
+                * is one maintained by H. Peter Anvin:
+                * I've seen "tftp-hpa 5.2" version.
+                * Make the following command work:
+                *  "tftp HOST [PORT] -m binary -c get/put FILE"
+                * by mangling it into "....... -g/-p -r FILE"
+                * and accepting and ignoring -m STR option.
+                */
+               unsigned i = 1;
+               while (argv[i]) {
+                       if (strcmp(argv[i], "-c") == 0) {
+                               if (!argv[++i])
+                                       break;
+                               if (strcmp(argv[i], "get") == 0) {
+                                       argv[i-1] = (char*)"-g";
+                                       argv[i] = (char*)"-r";
+                                       break;
+                               }
+                               if (strcmp(argv[i], "put") == 0) {
+                                       argv[i-1] = (char*)"-p";
+                                       argv[i] = (char*)"-r";
+                                       break;
+                               }
+                       }
+                       i++;
+               }
+       }
+
        IF_GETPUT(opt =) getopt32(argv, "^"
                        IF_FEATURE_TFTP_GET("g") IF_FEATURE_TFTP_PUT("p")
                        "l:r:" IF_FEATURE_TFTP_BLOCKSIZE("b:")
+                       IF_FEATURE_TFTP_HPA_COMPAT("m:")
                        "\0"
                        /* -p or -g is mandatory, and they are mutually exclusive */
                        IF_FEATURE_TFTP_GET("g:") IF_FEATURE_TFTP_PUT("p:")
                        IF_GETPUT("g--p:p--g:"),
                        &local_file, &remote_file
                        IF_FEATURE_TFTP_BLOCKSIZE(, &blksize_str)
+                       IF_FEATURE_TFTP_HPA_COMPAT(, NULL)
        );
        argv += optind;
 
@@ -851,7 +888,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
        peer_lsa->len = our_lsa->len;
 
        /* Shifting to not collide with TFTP_OPTs */
-       opt = option_mask32 = TFTPD_OPT | (getopt32(argv, "rcu:l", &user_opt) << 8);
+       opt = option_mask32 = TFTPD_OPT | (getopt32(argv, "rcu:lm:", &user_opt, NULL) << 8);
        argv += optind;
        if (opt & TFTPD_OPT_l) {
                openlog(applet_name, LOG_PID, LOG_DAEMON);
@@ -897,6 +934,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
        mode = local_file + strlen(local_file) + 1;
        /* RFC 1350 says mode string is case independent */
        if (mode >= G.block_buf + result || strcasecmp(mode, "octet") != 0) {
+               error_msg = "mode is not 'octet'";
                goto err;
        }
 # if ENABLE_FEATURE_TFTP_BLOCKSIZE
@@ -944,7 +982,8 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv)
        /* tftp_protocol() will create new one, bound to particular local IP */
        result = tftp_protocol(
                our_lsa, peer_lsa,
-               local_file IF_TFTP(, NULL /*remote_file*/)
+               local_file
+               IF_TFTP(, NULL /*remote_file*/)
                IF_FEATURE_TFTP_BLOCKSIZE(, want_transfer_size)
                IF_FEATURE_TFTP_BLOCKSIZE(, blksize)
        );