diff -Naur busybox.orig/include/applets.h busybox/include/applets.h --- busybox.orig/include/applets.h 2008-02-27 17:46:30 +0000 +++ busybox/include/applets.h 2008-03-04 23:43:37 +0000 @@ -356,6 +356,7 @@ #if ENABLE_FEATURE_TFTP_GET || ENABLE_FEATURE_TFTP_PUT USE_TFTP(APPLET(tftp, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) #endif +USE_TFTPD(APPLET(tftpd, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) USE_TIME(APPLET(time, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) USE_TOP(APPLET(top, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) USE_TOUCH(APPLET_NOFORK(touch, touch, _BB_DIR_BIN, _BB_SUID_NEVER, touch)) diff -Naur busybox.orig/include/usage.h busybox/include/usage.h --- busybox.orig/include/usage.h 2008-02-27 17:46:30 +0000 +++ busybox/include/usage.h 2008-03-04 23:43:37 +0000 @@ -3916,6 +3916,13 @@ USE_FEATURE_TFTP_BLOCKSIZE( \ "\n -b SIZE Transfer blocks of SIZE octets" \ ) + +#define tftpd_trivial_usage +#define tftpd_full_usage \ + "Trivial File Transfer Protocol Daemon" \ + "\n\nExample:" \ + "\n udpsvd -E 0 69 softlimit -m 99999 tftpd" + #define time_trivial_usage \ "[OPTION]... COMMAND [ARGS...]" #define time_full_usage \ diff -Naur busybox.orig/networking/Config.in busybox/networking/Config.in --- busybox.orig/networking/Config.in 2008-02-27 13:19:56 +0000 +++ busybox/networking/Config.in 2008-03-04 23:43:37 +0000 @@ -806,6 +806,12 @@ into problems with tftp as the protocol doesn't help you much when you run into problems. +config TFTPD + bool "tftpd" + default n + help + Bare bones TFTP Daemon. + config TRACEROUTE bool "traceroute" default n diff -Naur busybox.orig/networking/Kbuild busybox/networking/Kbuild --- busybox.orig/networking/Kbuild 2008-02-26 23:33:24 +0000 +++ busybox/networking/Kbuild 2008-03-04 23:43:37 +0000 @@ -35,6 +35,7 @@ lib-$(CONFIG_TELNET) += telnet.o lib-$(CONFIG_TELNETD) += telnetd.o lib-$(CONFIG_TFTP) += tftp.o +lib-$(CONFIG_TFTPD) += tftpd.o lib-$(CONFIG_TRACEROUTE) += traceroute.o lib-$(CONFIG_VCONFIG) += vconfig.o lib-$(CONFIG_WGET) += wget.o diff -Naur busybox.orig/networking/tftpd.c busybox/networking/tftpd.c --- busybox.orig/networking/tftpd.c 1970-01-01 00:00:00 +0000 +++ busybox/networking/tftpd.c 2008-03-04 23:43:37 +0000 @@ -0,0 +1,88 @@ +/* vi: set sw=4 ts=4: */ +/* + * bare bones TFTP daemon + * + * Copyright (C) 2008 by Vladimir Dronnikov + * + * Licensed under GPLv2, see file LICENSE in this tarball for details. + */ +#include "libbb.h" + +int tftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; +int tftpd_main(int argc, char **argv) +{ + // stdin, stdout -- network + int fd = -1; + unsigned seq = 0; + ssize_t len; + uint16_t cmd; + char buf[512+4]; + + // read packets + // packets of length < 5 indicate terminal condition + while ((len = safe_read(STDIN_FILENO, buf, sizeof(buf))) >= 4) { + cmd = *((uint16_t *)buf); + // read requested? + if (0x0100 == cmd) { + // ... open requested file + fd = open_or_warn(buf+2, O_RDONLY); + if (fd < 0) { + // send error packet + *((uint32_t *)(buf)) = 0x01000500; + bad: + *((uint16_t *)(buf+4)) = 0; + full_write(STDOUT_FILENO, buf, 5); + xfunc_die(); + } + // RRQ should be acknowledged with data packet of seq num 1 + goto send_data; + } + // write requested? + if (0x0200 == cmd) { + // ... create requested file + fd = open_or_warn(buf+2, O_CREAT | O_WRONLY | O_TRUNC | O_EXCL); + if (fd < 0) { + *((uint32_t *)(buf)) = 0x06000500; + goto bad; + } + // WRQ should be acknowledged with seq num 0 + *((uint16_t *)(buf+2)) = 0; + // ack + goto send_ack; + } + // data packet? + if (0x0300 == cmd) { + // ... dump contents to the file being written + if (full_write(fd, buf+4, len-4) < 0) { + *((uint32_t *)(buf)) = 0x03000500; + goto bad; + } + send_ack: + // send ACK + buf[1] = 4; + len = 0; + goto send; + } + // ack packet? + if (0x0400 == cmd) { + send_data: + // ... send next data chunk + len = safe_read(fd, buf+4, 512); + if (len < 0) { + *((uint32_t *)(buf)) = 0x04000500; + goto bad; + } + // send DATA + buf[1] = 3; + *((uint16_t *)(buf+2)) = htons(++seq); + send: + xwrite(STDOUT_FILENO, buf, len+4); + } + // bad packet! + *((uint32_t *)(buf)) = 0x03000500; + goto bad; + } + close(fd); + + return EXIT_SUCCESS; +}