fa00e1e
From f5339378fc8357c8c07c9c548e8e878fe7872449 Mon Sep 17 00:00:00 2001
5544c1b
From: =?UTF-8?q?Herv=C3=A9=20Poussineau?= <hpoussin@reactos.org>
5544c1b
Date: Thu, 13 Sep 2012 12:39:36 +0200
5544c1b
Subject: [PATCH] slirp: Handle more than 65535 blocks in TFTP transfers
5544c1b
MIME-Version: 1.0
5544c1b
Content-Type: text/plain; charset=UTF-8
5544c1b
Content-Transfer-Encoding: 8bit
5544c1b
5544c1b
RFC 1350 does not mention block count roll-over. However, a lot of TFTP servers
5544c1b
implement it to be able to transmit big files, so do it also.
5544c1b
5544c1b
Current block size is 512 bytes, so TFTP files were limited to 32 MB.
5544c1b
5544c1b
Signed-off-by: Hervé Poussineau <hpoussin@reactos.org>
5544c1b
Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
5544c1b
(cherry picked from commit 4aa401f39e048e71020cceb59f126ab941095a42)
5544c1b
5544c1b
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
5544c1b
---
5544c1b
 slirp/tftp.c | 24 ++++++++++--------------
5544c1b
 slirp/tftp.h |  1 +
5544c1b
 2 files changed, 11 insertions(+), 14 deletions(-)
5544c1b
5544c1b
diff --git a/slirp/tftp.c b/slirp/tftp.c
5544c1b
index 520dbd6..c6a5df2 100644
5544c1b
--- a/slirp/tftp.c
5544c1b
+++ b/slirp/tftp.c
5544c1b
@@ -97,7 +97,7 @@ static int tftp_session_find(Slirp *slirp, struct tftp_t *tp)
5544c1b
   return -1;
5544c1b
 }
5544c1b
 
5544c1b
-static int tftp_read_data(struct tftp_session *spt, uint16_t block_nr,
5544c1b
+static int tftp_read_data(struct tftp_session *spt, uint32_t block_nr,
5544c1b
                           uint8_t *buf, int len)
5544c1b
 {
5544c1b
     int bytes_read = 0;
5544c1b
@@ -197,19 +197,14 @@ out:
5544c1b
   tftp_session_terminate(spt);
5544c1b
 }
5544c1b
 
5544c1b
-static int tftp_send_data(struct tftp_session *spt,
5544c1b
-                          uint16_t block_nr,
5544c1b
-			  struct tftp_t *recv_tp)
5544c1b
+static int tftp_send_next_block(struct tftp_session *spt,
5544c1b
+                                struct tftp_t *recv_tp)
5544c1b
 {
5544c1b
   struct sockaddr_in saddr, daddr;
5544c1b
   struct mbuf *m;
5544c1b
   struct tftp_t *tp;
5544c1b
   int nobytes;
5544c1b
 
5544c1b
-  if (block_nr < 1) {
5544c1b
-    return -1;
5544c1b
-  }
5544c1b
-
5544c1b
   m = m_get(spt->slirp);
5544c1b
 
5544c1b
   if (!m) {
5544c1b
@@ -223,7 +218,7 @@ static int tftp_send_data(struct tftp_session *spt,
5544c1b
   m->m_data += sizeof(struct udpiphdr);
5544c1b
 
5544c1b
   tp->tp_op = htons(TFTP_DATA);
5544c1b
-  tp->x.tp_data.tp_block_nr = htons(block_nr);
5544c1b
+  tp->x.tp_data.tp_block_nr = htons((spt->block_nr + 1) & 0xffff);
5544c1b
 
5544c1b
   saddr.sin_addr = recv_tp->ip.ip_dst;
5544c1b
   saddr.sin_port = recv_tp->udp.uh_dport;
5544c1b
@@ -231,7 +226,7 @@ static int tftp_send_data(struct tftp_session *spt,
5544c1b
   daddr.sin_addr = spt->client_ip;
5544c1b
   daddr.sin_port = spt->client_port;
5544c1b
 
5544c1b
-  nobytes = tftp_read_data(spt, block_nr - 1, tp->x.tp_data.tp_buf, 512);
5544c1b
+  nobytes = tftp_read_data(spt, spt->block_nr, tp->x.tp_data.tp_buf, 512);
5544c1b
 
5544c1b
   if (nobytes < 0) {
5544c1b
     m_free(m);
5544c1b
@@ -255,6 +250,7 @@ static int tftp_send_data(struct tftp_session *spt,
5544c1b
     tftp_session_terminate(spt);
5544c1b
   }
5544c1b
 
5544c1b
+  spt->block_nr++;
5544c1b
   return 0;
5544c1b
 }
5544c1b
 
5544c1b
@@ -373,7 +369,8 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen)
5544c1b
       }
5544c1b
   }
5544c1b
 
5544c1b
-  tftp_send_data(spt, 1, tp);
5544c1b
+  spt->block_nr = 0;
5544c1b
+  tftp_send_next_block(spt, tp);
5544c1b
 }
5544c1b
 
5544c1b
 static void tftp_handle_ack(Slirp *slirp, struct tftp_t *tp, int pktlen)
5544c1b
@@ -386,9 +383,8 @@ static void tftp_handle_ack(Slirp *slirp, struct tftp_t *tp, int pktlen)
5544c1b
     return;
5544c1b
   }
5544c1b
 
5544c1b
-  if (tftp_send_data(&slirp->tftp_sessions[s],
5544c1b
-		     ntohs(tp->x.tp_data.tp_block_nr) + 1,
5544c1b
-		     tp) < 0) {
5544c1b
+  if (tftp_send_next_block(&slirp->tftp_sessions[s],
5544c1b
+                           tp) < 0) {
5544c1b
     return;
5544c1b
   }
5544c1b
 }
5544c1b
diff --git a/slirp/tftp.h b/slirp/tftp.h
5544c1b
index 9c364ea..51704e4 100644
5544c1b
--- a/slirp/tftp.h
5544c1b
+++ b/slirp/tftp.h
5544c1b
@@ -37,6 +37,7 @@ struct tftp_session {
5544c1b
 
5544c1b
     struct in_addr client_ip;
5544c1b
     uint16_t client_port;
5544c1b
+    uint32_t block_nr;
5544c1b
 
5544c1b
     int timestamp;
5544c1b
 };