Conditionally enable TFTP block rollover hack
authorJoseph C. Lehner <joseph.c.lehner@gmail.com>
Thu, 2 May 2019 10:18:22 +0000 (12:18 +0200)
committerJoseph C. Lehner <joseph.c.lehner@gmail.com>
Thu, 2 May 2019 10:25:08 +0000 (12:25 +0200)
tftp.c

diff --git a/tftp.c b/tftp.c
index f81f877938309fc9d2e6611832b2b0aaf7b057f4..1e0dd736801769e2716dee164161ea396f2d5dce 100644 (file)
--- a/tftp.c
+++ b/tftp.c
@@ -314,6 +314,7 @@ int tftp_put(struct nmrpd_args *args)
        char rx[2048], tx[2048];
        const char *file_remote = args->file_remote;
        char *val, *end;
+       bool freeze_block = false;
 
        sock = -1;
        ret = -1;
@@ -400,7 +401,7 @@ int tftp_put(struct nmrpd_args *args)
 
                if (timeouts || ackblock == block) {
                        if (!timeouts) {
-                               if (block < UINT16_MAX) {
+                               if (!freeze_block) {
                                        ++block;
                                }
 
@@ -432,9 +433,20 @@ int tftp_put(struct nmrpd_args *args)
                        }
 
                        if (ackblock != -1 && ++errors > 5) {
-                               fprintf(stderr, "Protocol error; bailing out.\n");
-                               ret = -1;
-                               goto cleanup;
+                               if (ackblock == UINT16_MAX && block == 0 && !freeze_block) {
+                                       /* work around the 32 MiB limit if block rollover is not
+                                        * supported, by transmitting all remaining packets as
+                                        * block #65535 - reported working on a Netgear D7000.
+                                        */
+                                       block = UINT16_MAX;
+                                       freeze_block = true;
+                                       errors = 0;
+                                       printf("Transmitting rest of file as block %d.\n", block);
+                               } else {
+                                       fprintf(stderr, "Protocol error; bailing out.\n");
+                                       ret = -1;
+                                       goto cleanup;
+                               }
                        }
                }