TFTP: net/tftp.c: add server mode receive
authorLuca Ceresoli <luca.ceresoli@comelit.it>
Tue, 17 May 2011 00:03:39 +0000 (00:03 +0000)
committerWolfgang Denk <wd@denx.de>
Thu, 19 May 2011 19:38:26 +0000 (21:38 +0200)
Signed-off-by: Luca Ceresoli <luca.ceresoli@comelit.it>
Cc: Wolfgang Denk <wd@denx.de>
Acked-by: Detlev Zundel <dzu@denx.de>
net/tftp.c
net/tftp.h

index 6386740b1d684d904f4433235f4b061b62cc4fcc..6d44298878857aaecf765879c1291c1d2267d691 100644 (file)
@@ -2,6 +2,8 @@
  * Copyright 1994, 1995, 2000 Neil Russell.
  * (See License)
  * Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de
+ * Copyright 2011 Comelit Group SpA,
+ *                Luca Ceresoli <luca.ceresoli@comelit.it>
  */
 
 #include <common.h>
@@ -85,6 +87,7 @@ static short  TftpNumchars;
 #define STATE_TOO_LARGE        3
 #define STATE_BAD_MAGIC        4
 #define STATE_OACK     5
+#define STATE_RECV_WRQ 6
 
 /* default TFTP block size */
 #define TFTP_BLOCK_SIZE                512
@@ -257,6 +260,8 @@ TftpSend(void)
                                                            (Mapsize*8), 0);
                /*..falling..*/
 #endif
+
+       case STATE_RECV_WRQ:
        case STATE_DATA:
                xp = pkt;
                s = (ushort *)pkt;
@@ -309,7 +314,8 @@ TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
 #endif
                        return;
        }
-       if (TftpState != STATE_SEND_RRQ && src != TftpRemotePort)
+       if (TftpState != STATE_SEND_RRQ && src != TftpRemotePort &&
+           TftpState != STATE_RECV_WRQ)
                return;
 
        if (len < 2)
@@ -322,12 +328,24 @@ TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
        switch (ntohs(proto)) {
 
        case TFTP_RRQ:
-       case TFTP_WRQ:
        case TFTP_ACK:
                break;
        default:
                break;
 
+#ifdef CONFIG_CMD_TFTPSRV
+       case TFTP_WRQ:
+               debug("Got WRQ\n");
+               TftpRemoteIP = sip;
+               TftpRemotePort = src;
+               TftpOurPort = 1024 + (get_timer(0) % 3072);
+               TftpLastBlock = 0;
+               TftpBlockWrap = 0;
+               TftpBlockWrapOffset = 0;
+               TftpSend(); /* Send ACK(0) */
+               break;
+#endif
+
        case TFTP_OACK:
                debug("Got OACK: %s %s\n",
                        pkt,
@@ -402,7 +420,8 @@ TftpHandler(uchar *pkt, unsigned dest, IPaddr_t sip, unsigned src,
                if (TftpState == STATE_SEND_RRQ)
                        debug("Server did not acknowledge timeout option!\n");
 
-               if (TftpState == STATE_SEND_RRQ || TftpState == STATE_OACK) {
+               if (TftpState == STATE_SEND_RRQ || TftpState == STATE_OACK ||
+                   TftpState == STATE_RECV_WRQ) {
                        /* first block received */
                        TftpState = STATE_DATA;
                        TftpRemotePort = src;
@@ -537,7 +556,8 @@ TftpTimeout(void)
        } else {
                puts("T ");
                NetSetTimeout(TftpTimeoutMSecs, TftpTimeout);
-               TftpSend();
+               if (TftpState != STATE_RECV_WRQ)
+                       TftpSend();
        }
 }
 
@@ -661,6 +681,40 @@ TftpStart(void)
        TftpSend();
 }
 
+#ifdef CONFIG_CMD_TFTPSRV
+void
+TftpStartServer(void)
+{
+       tftp_filename[0] = 0;
+
+#if defined(CONFIG_NET_MULTI)
+       printf("Using %s device\n", eth_get_name());
+#endif
+       printf("Listening for TFTP transfer on %pI4\n", &NetOurIP);
+       printf("Load address: 0x%lx\n", load_addr);
+
+       puts("Loading: *\b");
+
+       TftpTimeoutCountMax = TIMEOUT_COUNT;
+       TftpTimeoutCount = 0;
+       TftpTimeoutMSecs = TIMEOUT;
+       NetSetTimeout(TftpTimeoutMSecs, TftpTimeout);
+
+       /* Revert TftpBlkSize to dflt */
+       TftpBlkSize = TFTP_BLOCK_SIZE;
+       TftpBlock = 0;
+       TftpOurPort = WELL_KNOWN_PORT;
+
+#ifdef CONFIG_TFTP_TSIZE
+       TftpTsize = 0;
+       TftpNumchars = 0;
+#endif
+
+       TftpState = STATE_RECV_WRQ;
+       NetSetHandler(TftpHandler);
+}
+#endif /* CONFIG_CMD_TFTPSRV */
+
 #ifdef CONFIG_MCAST_TFTP
 /* Credits: atftp project.
  */
index e3dfb2628aa51bf140d2df6b2e32995aa53fce01..3abdf7bc267f3b7219f4af7512eb13d077cfcbbf 100644 (file)
@@ -2,6 +2,8 @@
  *     LiMon - BOOTP/TFTP.
  *
  *     Copyright 1994, 1995, 2000 Neil Russell.
+ *     Copyright 2011 Comelit Group SpA
+ *                    Luca Ceresoli <luca.ceresoli@comelit.it>
  *     (See License)
  */
 
 /* tftp.c */
 extern void    TftpStart (void);       /* Begin TFTP get */
 
+#ifdef CONFIG_CMD_TFTPSRV
+extern void    TftpStartServer(void);  /* Wait for incoming TFTP put */
+#endif
+
 /**********************************************************************/
 
 #endif /* __TFTP_H__ */