Import atftp-0.7

Atftp is a client/server implementation of the TFTP protocol that
implements RFCs 1350, 2090, 2347, 2348, and 2349. The server is
multi-threaded and the client presents a friendly interface using
libreadline. The current server implementation lacks IPv6 support.
This commit is contained in:
Kevin Lo 2010-10-05 06:23:11 +00:00
parent dfde640557
commit fe9dc20c2a
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/head/; revision=262417
19 changed files with 841 additions and 0 deletions

View file

@ -4,6 +4,7 @@
COMMENT = FTP client and server utilities
SUBDIR += IglooFTP
SUBDIR += atftp
SUBDIR += axel
SUBDIR += axyftp
SUBDIR += bareftp

29
ftp/atftp/Makefile Normal file
View file

@ -0,0 +1,29 @@
# New ports collection makefile for: atftp
# Date created: 5 October 2010
# Whom: kevlo
#
# $FreeBSD$
#
PORTNAME= atftp
PORTVERSION= 0.7
CATEGORIES= ftp
MASTER_SITES= ${MASTER_SITE_DEBIAN}
MASTER_SITE_SUBDIR= pool/main/a/${PORTNAME}
DISTNAME= ${PORTNAME}_${PORTVERSION}.dfsg.orig
MAINTAINER= kevlo@FreeBSD.org
COMMENT= Advanced tftp server and client
WRKSRC= ${WRKDIR}/${PORTNAME}-${PORTVERSION}.dfsg
USE_RC_SUBR= atftpd
GNU_CONFIGURE= yes
PLIST_FILES= bin/atftp \
sbin/atftpd
MAN1= atftp.1
MAN8= atftpd.8
.include <bsd.port.mk>

6
ftp/atftp/distinfo Normal file
View file

@ -0,0 +1,6 @@
MD5 (atftp_0.7.dfsg.orig.tar.gz) = aa269044a6f992eca78fee2f6119643c
SHA256 (atftp_0.7.dfsg.orig.tar.gz) = 18815f5b67290fac087c6b9da28dfa5e0feb722096f5c5de52e59b46026da559
SIZE (atftp_0.7.dfsg.orig.tar.gz) = 186849
MD5 (atftp_0.7.dfsg-9.diff.gz) = 9ca540e022432ea72157102fd2fddf3b
SHA256 (atftp_0.7.dfsg-9.diff.gz) = 9ce4654b312d19cb797d5d99b9ca3e1ff38551980430af02f9d2cd7cb87d5ca4
SIZE (atftp_0.7.dfsg-9.diff.gz) = 52300

44
ftp/atftp/files/atftpd.in Normal file
View file

@ -0,0 +1,44 @@
#!/bin/sh
# PROVIDE: atftpd
# REQUIRE: DAEMON
# BEFORE: LOGIN
# KEYWORD: shutdown
#
# Add the following lines to /etc/rc.conf.local or /etc/rc.conf
# to enable this service:
#
# atftpd_enable (bool): Set to "NO" by default.
# atftpd_flags (str): Default to "--daemon".
# Extra flags passed to start command.
#
. /etc/rc.subr
name="atftpd"
rcvar=`set_rcvar`
command=%%PREFIX%%/sbin/${name}
pidfile=/var/run/${name}.pid
logfile=/var/log/${name}.log
load_rc_config $name
[ -z "$atftpd_enable" ] && atftpd_enable="NO"
[ -z "$atftpd_flags" ] && atftpd_flags="--daemon --verbose=5 --pidfile ${pidfile} --logfile ${logfile} /tftpboot"
start_precmd="start_precmd"
stop_postcmd="stop_postcmd"
start_precmd()
{
touch ${logfile}
chown nobody ${logfile}
}
stop_postcmd()
{
rm -f ${pidfile}
}
run_rc_command "$1"

View file

@ -0,0 +1,29 @@
--- Makefile.in.orig 2010-10-04 18:38:26.000000000 +0800
+++ Makefile.in 2010-10-04 18:39:02.000000000 +0800
@@ -789,11 +789,11 @@
install-data-am: install-man
@$(NORMAL_INSTALL)
- $(MAKE) $(AM_MAKEFLAGS) install-data-hook
+ $(MAKE) $(AM_MAKEFLAGS)
install-exec-am: install-binPROGRAMS install-sbinPROGRAMS
@$(NORMAL_INSTALL)
- $(MAKE) $(AM_MAKEFLAGS) install-exec-hook
+ $(MAKE) $(AM_MAKEFLAGS)
install-info: install-info-recursive
@@ -847,12 +847,6 @@
uninstall-sbinPROGRAMS
-install-exec-hook:
- (cd $(DESTDIR)$(sbindir) && ln -s atftpd in.tftpd)
-
-install-data-hook:
- (cd $(DESTDIR)$(mandir)/man8 && ln -s atftpd.8 in.tftpd.8)
-
uninstall-local:
rm -f $(DESTDIR)$(sbindir)/in.tftpd $(DESTDIR)$(mandir)/man8/in.tftpd.8

View file

@ -0,0 +1,155 @@
--- argz.h.orig 2010-10-04 18:31:14.000000000 +0800
+++ argz.h 2010-10-04 18:32:03.000000000 +0800
@@ -38,7 +38,9 @@
#ifndef _ARGZ_H
#define _ARGZ_H 1
+#ifdef HAVE_FEATURES_H
#include <features.h>
+#endif
#define __need_error_t
#include <errno.h>
@@ -55,109 +57,28 @@
__BEGIN_DECLS
-/* Make a '\0' separated arg vector from a unix argv vector, returning it in
- ARGZ, and the total length in LEN. If a memory allocation error occurs,
- ENOMEM is returned, otherwise 0. The result can be destroyed using free. */
-extern error_t __argz_create (char *__const __argv[], char **__restrict __argz,
- size_t *__restrict __len) __THROW;
-extern error_t argz_create (char *__const __argv[], char **__restrict __argz,
- size_t *__restrict __len) __THROW;
-
/* Make a '\0' separated arg vector from a SEP separated list in
STRING, returning it in ARGZ, and the total length in LEN. If a
memory allocation error occurs, ENOMEM is returned, otherwise 0.
The result can be destroyed using free. */
extern error_t __argz_create_sep (__const char *__restrict __string,
int __sep, char **__restrict __argz,
- size_t *__restrict __len) __THROW;
+ size_t *__restrict __len);
extern error_t argz_create_sep (__const char *__restrict __string,
int __sep, char **__restrict __argz,
- size_t *__restrict __len) __THROW;
+ size_t *__restrict __len);
/* Returns the number of strings in ARGZ. */
-extern size_t __argz_count (__const char *__argz, size_t __len)
- __THROW __attribute_pure__;
-extern size_t argz_count (__const char *__argz, size_t __len)
- __THROW __attribute_pure__;
+extern size_t __argz_count (__const char *__argz, size_t __len);
+extern size_t argz_count (__const char *__argz, size_t __len);
/* Puts pointers to each string in ARGZ into ARGV, which must be large enough
to hold them all. */
extern void __argz_extract (__const char *__restrict __argz, size_t __len,
- char **__restrict __argv) __THROW;
+ char **__restrict __argv);
extern void argz_extract (__const char *__restrict __argz, size_t __len,
- char **__restrict __argv) __THROW;
+ char **__restrict __argv);
-/* Make '\0' separated arg vector ARGZ printable by converting all the '\0's
- except the last into the character SEP. */
-extern void __argz_stringify (char *__argz, size_t __len, int __sep) __THROW;
-extern void argz_stringify (char *__argz, size_t __len, int __sep) __THROW;
-
-/* Append BUF, of length BUF_LEN to the argz vector in ARGZ & ARGZ_LEN. */
-extern error_t __argz_append (char **__restrict __argz,
- size_t *__restrict __argz_len,
- __const char *__restrict __buf, size_t _buf_len)
- __THROW;
-extern error_t argz_append (char **__restrict __argz,
- size_t *__restrict __argz_len,
- __const char *__restrict __buf, size_t __buf_len)
- __THROW;
-
-/* Append STR to the argz vector in ARGZ & ARGZ_LEN. */
-extern error_t __argz_add (char **__restrict __argz,
- size_t *__restrict __argz_len,
- __const char *__restrict __str) __THROW;
-extern error_t argz_add (char **__restrict __argz,
- size_t *__restrict __argz_len,
- __const char *__restrict __str) __THROW;
-
-/* Append SEP separated list in STRING to the argz vector in ARGZ &
- ARGZ_LEN. */
-extern error_t __argz_add_sep (char **__restrict __argz,
- size_t *__restrict __argz_len,
- __const char *__restrict __string, int __delim)
- __THROW;
-extern error_t argz_add_sep (char **__restrict __argz,
- size_t *__restrict __argz_len,
- __const char *__restrict __string, int __delim)
- __THROW;
-
-/* Delete ENTRY from ARGZ & ARGZ_LEN, if it appears there. */
-extern void __argz_delete (char **__restrict __argz,
- size_t *__restrict __argz_len,
- char *__restrict __entry) __THROW;
-extern void argz_delete (char **__restrict __argz,
- size_t *__restrict __argz_len,
- char *__restrict __entry) __THROW;
-
-/* Insert ENTRY into ARGZ & ARGZ_LEN before BEFORE, which should be an
- existing entry in ARGZ; if BEFORE is NULL, ENTRY is appended to the end.
- Since ARGZ's first entry is the same as ARGZ, argz_insert (ARGZ, ARGZ_LEN,
- ARGZ, ENTRY) will insert ENTRY at the beginning of ARGZ. If BEFORE is not
- in ARGZ, EINVAL is returned, else if memory can't be allocated for the new
- ARGZ, ENOMEM is returned, else 0. */
-extern error_t __argz_insert (char **__restrict __argz,
- size_t *__restrict __argz_len,
- char *__restrict __before,
- __const char *__restrict __entry) __THROW;
-extern error_t argz_insert (char **__restrict __argz,
- size_t *__restrict __argz_len,
- char *__restrict __before,
- __const char *__restrict __entry) __THROW;
-
-/* Replace any occurrences of the string STR in ARGZ with WITH, reallocating
- ARGZ as necessary. If REPLACE_COUNT is non-zero, *REPLACE_COUNT will be
- incremented by number of replacements performed. */
-extern error_t __argz_replace (char **__restrict __argz,
- size_t *__restrict __argz_len,
- __const char *__restrict __str,
- __const char *__restrict __with,
- unsigned int *__restrict __replace_count);
-extern error_t argz_replace (char **__restrict __argz,
- size_t *__restrict __argz_len,
- __const char *__restrict __str,
- __const char *__restrict __with,
- unsigned int *__restrict __replace_count);
-
/* Returns the next entry in ARGZ & ARGZ_LEN after ENTRY, or NULL if there
are no more. If entry is NULL, then the first entry is returned. This
behavior allows two convenient iteration styles:
@@ -173,14 +94,14 @@
...;
*/
extern char *__argz_next (__const char *__restrict __argz, size_t __argz_len,
- __const char *__restrict __entry) __THROW;
+ __const char *__restrict __entry);
extern char *argz_next (__const char *__restrict __argz, size_t __argz_len,
- __const char *__restrict __entry) __THROW;
+ __const char *__restrict __entry);
#ifdef __USE_EXTERN_INLINES
extern inline char *
__argz_next (__const char *__argz, size_t __argz_len,
- __const char *__entry) __THROW
+ __const char *__entry)
{
if (__entry)
{
@@ -194,7 +115,7 @@
}
extern inline char *
argz_next (__const char *__argz, size_t __argz_len,
- __const char *__entry) __THROW
+ __const char *__entry)
{
return __argz_next (__argz, __argz_len, __entry);
}

View file

@ -0,0 +1,57 @@
--- logger.c.orig 2004-02-27 10:05:26.000000000 +0800
+++ logger.c 2010-10-05 12:34:41.000000000 +0800
@@ -3,7 +3,7 @@
* logger.c
* functions for logging messages.
*
- * $Id: logger.c,v 1.12 2004/02/27 02:05:26 jp Exp $
+ * $Id: logger.c 1769 2010-09-29 08:46:26Z kevlo $
*
* Copyright (c) 2000 Jean-Pierre Lefebvre <helix@step.polymtl.ca>
* and Remi Lefebvre <remi@debian.org>
@@ -27,6 +27,7 @@
#include <time.h>
#include <unistd.h>
#include <netdb.h>
+#include <pthread.h>
#include "logger.h"
#define MAXLEN 128
@@ -56,7 +57,15 @@
log_ident = "unset";
if (filename)
+ {
log_filename = strdup(filename);
+ if (!strcmp(filename, "-"))
+ {
+ log_fd = STDOUT_FILENO;
+ log_fp = fdopen(log_fd, "a");
+ return;
+ }
+ }
else
{
openlog(log_ident, LOG_PID, LOG_DAEMON);
@@ -105,15 +114,17 @@
if (log_fp)
{
- fprintf(log_fp, "%s %s %s[%d.%d]: %s\n", time_buf, hostname,
- log_ident, getpid(), pthread_self(), message);
+ fprintf(log_fp, "%s %s %s[%ld.%ld]: %s\n", time_buf, hostname,
+ log_ident, (long)getpid(), (long)pthread_self(),
+ message);
fflush(log_fp);
}
else if (log_syslog_is_open)
syslog(severity, "%s", message);
else
- fprintf(stderr, "%s %s %s[%d.%d]: %s\n", time_buf, hostname,
- log_ident, getpid(), pthread_self(), message);
+ fprintf(stderr, "%s %s %s[%ld.%ld]: %s\n", time_buf, hostname,
+ log_ident, (long)getpid(), (long)pthread_self(),
+ message);
}
va_end(args);
}

View file

@ -0,0 +1,13 @@
--- stats.c.orig 2002-03-27 11:02:12.000000000 +0800
+++ stats.c 2010-10-05 09:56:08.000000000 +0800
@@ -157,8 +157,8 @@
logger(LOG_INFO, " Load measurements:");
logger(LOG_INFO, " User: %8.3fs Sys:%8.3fs",
- (double)(s_stats.tms.tms_utime) / CLK_TCK,
- (double)(s_stats.tms.tms_stime) / CLK_TCK);
+ (double)(s_stats.tms.tms_utime) / CLOCKS_PER_SEC,
+ (double)(s_stats.tms.tms_stime) / CLOCKS_PER_SEC);
logger(LOG_INFO, " Total:%8.3fs CPU:%8.3f%%",
(double)(tmp.tv_sec + tmp.tv_usec * 1e-6),
(double)(s_stats.tms.tms_utime + s_stats.tms.tms_stime) /

View file

@ -0,0 +1,69 @@
--- tftp.c.orig 2010-10-05 09:35:38.000000000 +0800
+++ tftp.c 2010-10-05 09:42:03.000000000 +0800
@@ -354,7 +354,7 @@
void make_arg(char *string, int *argc, char ***argv)
{
static char *tmp = NULL;
- int argz_len;
+ size_t argz_len;
/* split the string to an argz vector */
if (argz_create_sep(string, ' ', &tmp, &argz_len) != 0)
@@ -608,9 +608,16 @@
exit(ERR);
}
memset(&data.sa_local, 0, sizeof(data.sa_local));
- bind(data.sockfd, (struct sockaddr *)&data.sa_local,
- sizeof(data.sa_local));
- getsockname(data.sockfd, (struct sockaddr *)&data.sa_local, &len);
+ if (bind(data.sockfd, (struct sockaddr *)&data.sa_local,
+ sizeof(data.sa_local)) < 0) {
+ perror("bind");
+ exit(ERR);
+ }
+ if (getsockname(data.sockfd, (struct sockaddr *)&data.sa_local, &len) < 0)
+ {
+ perror("getsockname");
+ exit(ERR);
+ }
/* do the transfer */
gettimeofday(&data.start_time, NULL);
@@ -621,7 +628,7 @@
fsync(data.sockfd);
close(data.sockfd);
- return OK;
+ return tftp_result;
}
/*
@@ -712,9 +719,16 @@
exit(ERR);
}
memset(&data.sa_local, 0, sizeof(data.sa_local));
- bind(data.sockfd, (struct sockaddr *)&data.sa_local,
- sizeof(data.sa_local));
- getsockname(data.sockfd, (struct sockaddr *)&data.sa_local, &len);
+ if (bind(data.sockfd, (struct sockaddr *)&data.sa_local,
+ sizeof(data.sa_local)) < 0) {
+ perror("bind");
+ exit(ERR);
+ }
+ if (getsockname(data.sockfd, (struct sockaddr *)&data.sa_local, &len) < 0)
+ {
+ perror("getsockname");
+ exit(ERR);
+ }
/* do the transfer */
gettimeofday(&data.start_time, NULL);
@@ -731,7 +745,7 @@
fsync(data.sockfd);
close(data.sockfd);
- return OK;
+ return tftp_result;
}
#ifdef HAVE_MTFTP

View file

@ -0,0 +1,15 @@
--- tftp_def.c.orig 2010-10-05 09:43:06.000000000 +0800
+++ tftp_def.c 2010-10-05 09:43:53.000000000 +0800
@@ -140,8 +140,10 @@
*/
inline char *Strncpy(char *to, const char *from, size_t size)
{
- to[size-1] = '\000';
- return strncpy(to, from, size - 1);
+ strncpy(to, from, size);
+ if (size > 0)
+ to[size-1] = '\000';
+ return to;
}

View file

@ -0,0 +1,10 @@
--- tftp_def.h.orig 2004-02-13 11:16:09.000000000 +0800
+++ tftp_def.h 2010-10-05 12:36:29.000000000 +0800
@@ -19,6 +19,7 @@
#include <sys/time.h>
#include <sys/times.h>
+#include <netinet/in.h>
#include <netdb.h>
/* standard return value */

View file

@ -0,0 +1,66 @@
--- tftp_file.c.orig 2004-02-13 11:16:09.000000000 +0800
+++ tftp_file.c 2010-10-04 18:46:54.000000000 +0800
@@ -59,7 +59,7 @@
unsigned int next_word;
/* initial stuff */
- next_hole = prev_hole + 1;
+ next_hole = 0; /*prev_hole + 1;*/
next_word_no = next_hole / 32;
next_bit_no = next_hole % 32;
next_word = bitmap[next_word_no];
@@ -150,7 +150,8 @@
memset(&file_bitmap, 0, sizeof(file_bitmap));
/* make sure the socket is not connected */
- sa.sin_family = AF_UNSPEC;
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
connect(sockfd, (struct sockaddr *)&sa, sizeof(sa));
connected = 0;
@@ -238,9 +239,13 @@
tftp_find_bitmap_hole(prev_bitmap_hole, file_bitmap);
block_number = prev_bitmap_hole;
}
- if (data->trace)
- fprintf(stderr, "sent ACK <block: %d>\n", block_number);
- tftp_send_ack(sockfd, &sa, block_number);
+ result = tftp_send_ack(sockfd, &sa, block_number);
+ if (result == OK)
+ {
+ if (data->trace)
+ fprintf(stderr, "sent ACK <block: %d>\n",
+ block_number);
+ }
/* if we just ACK the last block we are done */
if (block_number == last_block_number)
state = S_END;
@@ -627,7 +632,8 @@
from.sin_addr.s_addr = 0;
/* make sure the socket is not connected */
- sa.sin_family = AF_UNSPEC;
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
connect(sockfd, (struct sockaddr *)&sa, sizeof(sa));
connected = 0;
@@ -761,7 +767,7 @@
/* if the socket if not connected, connect it */
if (!connected)
{
- //connect(sockfd, (struct sockaddr *)&sa, sizeof(sa));
+ connect(sockfd, (struct sockaddr *)&sa, sizeof(sa));
connected = 1;
}
block_number = ntohs(tftphdr->th_block);
@@ -780,7 +786,7 @@
/* if the socket if not connected, connect it */
if (!connected)
{
- //connect(sockfd, (struct sockaddr *)&sa, sizeof(sa));
+ connect(sockfd, (struct sockaddr *)&sa, sizeof(sa));
connected = 1;
}
state = S_OACK_RECEIVED;

View file

@ -0,0 +1,60 @@
--- tftp_io.c.orig 2004-02-19 09:30:00.000000000 +0800
+++ tftp_io.c 2010-10-04 18:45:56.000000000 +0800
@@ -102,8 +102,8 @@
tftphdr.th_opcode = htons(ACK);
tftphdr.th_block = htons(block_number);
- result = sendto(socket, &tftphdr, 4, 0, (struct sockaddr *)sa,
- sizeof(*sa));
+ result = write(socket, &tftphdr, 4);
+
if (result < 0)
return ERR;
return OK;
@@ -141,8 +141,8 @@
}
}
/* send the buffer */
- result = sendto(socket, buffer, index, 0, (struct sockaddr *)sa,
- sizeof(*sa));
+ result = write(socket, buffer, index);
+
if (result < 0)
return ERR;
return OK;
@@ -191,8 +191,8 @@
tftphdr->th_opcode = htons(DATA);
tftphdr->th_block = htons(block_number);
- result = sendto(socket, data, size, 0, (struct sockaddr *)sa,
- sizeof(*sa));
+ result = write(socket, data, size);
+
if (result < 0)
return ERR;
return OK;
@@ -214,7 +214,6 @@
struct msghdr msg; /* used to get client's packet info */
struct cmsghdr *cmsg;
- struct in_pktinfo *pktinfo;
struct iovec iov;
char cbuf[1024];
@@ -284,11 +283,12 @@
cmsg != NULL && cmsg->cmsg_len >= sizeof(*cmsg);
cmsg = CMSG_NXTHDR(&msg, cmsg))
{
- if (cmsg->cmsg_level == SOL_IP
- && cmsg->cmsg_type == IP_PKTINFO)
+ if (cmsg->cmsg_level == IPPROTO_IP
+ && cmsg->cmsg_type == IP_RECVDSTADDR)
{
- pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
- sa_to->sin_addr = pktinfo->ipi_addr;
+ struct in_addr *pktinfo;
+ pktinfo = (struct in_addr *)CMSG_DATA(cmsg);
+ sa_to->sin_addr = *pktinfo;
}
break;
}

View file

@ -0,0 +1,12 @@
--- tftp_mtftp.c.orig 2010-10-05 14:12:47.000000000 +0800
+++ tftp_mtftp.c 2010-10-05 14:13:19.000000000 +0800
@@ -138,7 +138,8 @@
memset(&file_bitmap, 0, sizeof(file_bitmap));
/* make sure the socket is not connected */
- sa.sin_family = AF_UNSPEC;
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
connect(sockfd, (struct sockaddr *)&sa, sizeof(sa));
/* copy sa_peer structure */

View file

@ -0,0 +1,159 @@
--- tftpd.c.orig 2010-10-04 18:26:05.000000000 +0800
+++ tftpd.c 2010-10-04 18:30:20.000000000 +0800
@@ -60,6 +60,9 @@
char directory[MAXLEN] = "/tftpboot/";
int retry_timeout = S_TIMEOUT;
+int on = 1;
+int listen_local = 0;
+
int tftpd_daemon = 0; /* By default we are started by inetd */
int tftpd_daemon_no_fork = 0; /* For who want a false daemon mode */
short tftpd_port = 0; /* Port atftpd listen to */
@@ -157,6 +160,7 @@
struct servent *serv;
struct passwd *user;
struct group *group;
+ pthread_t tid;
#ifdef HAVE_MTFTP
pthread_t mtftp_thread;
@@ -253,7 +257,7 @@
else
sa.sin_addr.s_addr = htonl(INADDR_ANY);
/* open the socket */
- if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == 0)
+ if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
{
logger(LOG_ERR, "atftpd: can't open socket");
exit(1);
@@ -301,7 +305,7 @@
}
/* We need to retieve some information from incomming packets */
- if (setsockopt(0, SOL_IP, IP_PKTINFO, &one, sizeof(one)) != 0)
+ if (setsockopt(0, IPPROTO_IP, IP_RECVDSTADDR, &one, sizeof(one)) != 0)
{
logger(LOG_WARNING, "Failed to set socket option: %s", strerror(errno));
}
@@ -387,10 +391,18 @@
packets */
if (!tftpd_cancel)
{
+ int rv;
+
if ((tftpd_timeout == 0) || (tftpd_daemon))
- select(FD_SETSIZE, &rfds, NULL, NULL, NULL);
+ rv = select(FD_SETSIZE, &rfds, NULL, NULL, NULL);
else
- select(FD_SETSIZE, &rfds, NULL, NULL, &tv);
+ rv = select(FD_SETSIZE, &rfds, NULL, NULL, &tv);
+ if (rv < 0) {
+ logger(LOG_ERR, "%s: %d: select: %s",
+ __FILE__, __LINE__, strerror(errno));
+ /* Clear the bits, they are undefined! */
+ FD_ZERO(&rfds);
+ }
}
#ifdef RATE_CONTROL
@@ -466,7 +478,7 @@
new->client_info->next = NULL;
/* Start a new server thread. */
- if (pthread_create(&new->tid, NULL, tftpd_receive_request,
+ if (pthread_create(&tid, NULL, tftpd_receive_request,
(void *)new) != 0)
{
logger(LOG_ERR, "Failed to start new thread");
@@ -567,7 +579,8 @@
/* Detach ourself. That way the main thread does not have to
* wait for us with pthread_join. */
- pthread_detach(pthread_self());
+ data->tid = pthread_self();
+ pthread_detach(data->tid);
/* Read the first packet from stdin. */
data_size = data->data_buffer_size;
@@ -615,7 +628,25 @@
data->sockfd = socket(PF_INET, SOCK_DGRAM, 0);
to.sin_family = AF_INET;
to.sin_port = 0;
- if (data->sockfd > 0)
+ /* Force socket to listen on local address. Do not listen on broadcast address 255.255.255.255.
+ If the socket listens on the broadcast address, Linux tells the remote client the port
+ is unreachable. This happens even if SO_BROADCAST is set in setsockopt for this socket.
+ I was unable to find a kernel option or /proc/sys flag to make the kernel pay attention to
+ these requests, so the workaround is to force listening on the local address. */
+ if (listen_local == 1)
+ {
+ to.sin_addr.s_addr = INADDR_ANY;
+ logger(LOG_INFO, "forcing socket to listen on local address");
+ if (setsockopt(data->sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) != 0) {
+ logger(LOG_ERR, "setsockopt: %s", strerror(errno));
+ }
+ }
+ else
+ {
+ logger(LOG_INFO, "socket may listen on any address, including broadcast");
+ }
+
+ if (data->sockfd != -1)
{
/* bind the socket to the interface */
if (bind(data->sockfd, (struct sockaddr *)&to, len) == -1)
@@ -732,8 +763,8 @@
tftpd_clientlist_free(data);
/* free the thread structure */
- free(data);
-
+ free(data);
+
logger(LOG_INFO, "Server thread exiting");
pthread_exit(NULL);
}
@@ -811,6 +842,7 @@
{ "no-multicast", 0, NULL, 'M' },
{ "logfile", 1, NULL, 'L' },
{ "pidfile", 1, NULL, 'I'},
+ { "listen-local", 0, NULL, 'F'},
{ "daemon", 0, NULL, 'D' },
{ "no-fork", 0, NULL, 'N'},
{ "user", 1, NULL, 'U'},
@@ -888,6 +920,9 @@
case 'I':
pidfile = strdup(optarg);
break;
+ case 'F':
+ listen_local = 1;
+ break;
case 'D':
tftpd_daemon = 1;
break;
@@ -1015,6 +1050,10 @@
logger(LOG_INFO, " log file: %s", (log_file==NULL) ? "syslog":log_file);
if (pidfile)
logger(LOG_INFO, " pid file: %s", pidfile);
+ if (listen_local == 1)
+ logger(LOG_INFO, " forcing to listen on local interfaces: on.");
+ else
+ logger(LOG_INFO, " not forcing to listen on local interfaces.");
if (tftpd_daemon == 1)
logger(LOG_INFO, " server timeout: Not used");
else
@@ -1111,11 +1150,12 @@
" output messages\n"
" --trace : log all sent and received packets\n"
" --no-timeout : disable 'timeout' from RFC2349\n"
- " --no-tisize : disable 'tsize' from RFC2349\n"
+ " --no-tsize : disable 'tsize' from RFC2349\n"
" --no-blksize : disable 'blksize' from RFC2348\n"
" --no-multicast : disable 'multicast' from RFC2090\n"
" --logfile <file> : logfile to log logs to ;-)\n"
" --pidfile <file> : write PID to this file\n"
+ " --listen-local : force listen on local network address\n"
" --daemon : run atftpd standalone (no inetd)\n"
" --no-fork : run as a daemon, don't fork\n"
" --user <user[.group]> : default is nobody\n"

View file

@ -0,0 +1,87 @@
--- tftpd_file.c.orig 2010-10-04 18:33:31.000000000 +0800
+++ tftpd_file.c 2010-10-04 18:37:08.000000000 +0800
@@ -240,9 +240,13 @@
break;
case S_SEND_ACK:
timeout_state = state;
- tftp_send_ack(sockfd, sa, block_number);
- if (data->trace)
- logger(LOG_DEBUG, "sent ACK <block: %d>", block_number);
+ result = tftp_send_ack(sockfd, sa, block_number);
+ if (result == OK)
+ {
+ if (data->trace)
+ logger(LOG_DEBUG, "sent ACK <block: %d>",
+ block_number);
+ }
if (all_blocks_received)
state = S_END;
else
@@ -660,8 +664,12 @@
data->mc_port, 1);
/* the socket must be unconnected for multicast */
+#ifdef __linux__
sa->sin_family = AF_UNSPEC;
- connect(sockfd, (struct sockaddr *)sa, sizeof(sa));
+#else
+ sa->sin_family = AF_INET;
+#endif
+ connect(sockfd, (struct sockaddr *)sa, sizeof(*sa));
/* set multicast flag */
multicast = 1;
@@ -706,10 +714,14 @@
case S_SEND_OACK:
timeout_state = state;
opt_options_to_string(data->tftp_options, string, MAXLEN);
- if (data->trace)
- logger(LOG_DEBUG, "sent OACK <%s>", string);
- tftp_send_oack(sockfd, sa, data->tftp_options,
- data->data_buffer, data->data_buffer_size);
+ result = tftp_send_oack(sockfd, sa, data->tftp_options,
+ data->data_buffer,
+ data->data_buffer_size);
+ if (result == OK)
+ {
+ if (data->trace)
+ logger(LOG_DEBUG, "sent OACK <%s>", string);
+ }
state = S_WAIT_PACKET;
break;
case S_SEND_DATA:
@@ -725,19 +737,25 @@
if (multicast)
{
- tftp_send_data(sockfd, &data->sa_mcast,
- block_number + 1, data_size,
- data->data_buffer);
+ result = tftp_send_data(sockfd, &data->sa_mcast,
+ block_number + 1, data_size,
+ data->data_buffer);
}
else
{
- tftp_send_data(sockfd, sa, block_number + 1,
- data_size, data->data_buffer);
+ result = tftp_send_data(sockfd, sa, block_number + 1,
+ data_size, data->data_buffer);
+ }
+
+ if (result == ERR)
+ state = S_ABORT;
+ else
+ {
+ if (data->trace)
+ logger(LOG_DEBUG, "sent DATA <block: %d, size %d>",
+ block_number + 1, data_size - 4);
+ state = S_WAIT_PACKET;
}
- if (data->trace)
- logger(LOG_DEBUG, "sent DATA <block: %d, size %d>",
- block_number + 1, data_size - 4);
- state = S_WAIT_PACKET;
break;
case S_WAIT_PACKET:
data_size = data->data_buffer_size;

View file

@ -0,0 +1,11 @@
--- tftpd_list.c.orig 2010-10-05 13:11:12.000000000 +0800
+++ tftpd_list.c 2010-10-05 13:18:09.000000000 +0800
@@ -149,7 +149,7 @@
opt_request_to_string(tftp_options, options, MAXLEN);
index = strstr(options, "multicast");
- len = (int)index - (int)options;
+ len = strlen(options) - strlen(index);
/* lock the whole list before walking it */
pthread_mutex_lock(&thread_list_mutex);

View file

@ -0,0 +1,14 @@
--- tftpd_pcre.c.orig 2010-10-04 18:24:43.000000000 +0800
+++ tftpd_pcre.c 2010-10-04 18:25:23.000000000 +0800
@@ -211,9 +211,9 @@
chp++; /* point to value indicating substring */
rc = pcre_get_substring(str, ovector, matches, *chp - 0x30, &tmpstr);
/* found string */
- if (rc > 0)
+ if (rc > 0 && outchp - outstr + rc+1 < outsize)
{
- Strncpy(outchp, tmpstr, rc);
+ Strncpy(outchp, tmpstr, rc+1);
outchp += rc;
pcre_free_substring(tmpstr);
continue;

4
ftp/atftp/pkg-descr Normal file
View file

@ -0,0 +1,4 @@
Atftp is a client/server implementation of the TFTP protocol that
implements RFCs 1350, 2090, 2347, 2348, and 2349. The server is
multi-threaded and the client presents a friendly interface using
libreadline. The current server implementation lacks IPv6 support.