aboutsummaryrefslogtreecommitdiffstats
path: root/ftp/atftp
diff options
context:
space:
mode:
authorkevlo <kevlo@FreeBSD.org>2010-10-05 14:23:11 +0800
committerkevlo <kevlo@FreeBSD.org>2010-10-05 14:23:11 +0800
commitbad4ceacc6e91ff6dc1c30331408af5468347ba6 (patch)
treed3ac69ab3049ed151eb10a3a4c1b32907794aa20 /ftp/atftp
parent2b45102f80404546d4dc7516f1cfe204ea344593 (diff)
downloadfreebsd-ports-gnome-bad4ceacc6e91ff6dc1c30331408af5468347ba6.tar.gz
freebsd-ports-gnome-bad4ceacc6e91ff6dc1c30331408af5468347ba6.tar.zst
freebsd-ports-gnome-bad4ceacc6e91ff6dc1c30331408af5468347ba6.zip
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.
Diffstat (limited to 'ftp/atftp')
-rw-r--r--ftp/atftp/Makefile29
-rw-r--r--ftp/atftp/distinfo6
-rw-r--r--ftp/atftp/files/atftpd.in44
-rw-r--r--ftp/atftp/files/patch-Makefile.in29
-rw-r--r--ftp/atftp/files/patch-argz.h155
-rw-r--r--ftp/atftp/files/patch-logger.c57
-rw-r--r--ftp/atftp/files/patch-stats.c13
-rw-r--r--ftp/atftp/files/patch-tftp.c69
-rw-r--r--ftp/atftp/files/patch-tftp_def.c15
-rw-r--r--ftp/atftp/files/patch-tftp_def.h10
-rw-r--r--ftp/atftp/files/patch-tftp_file.c66
-rw-r--r--ftp/atftp/files/patch-tftp_io.c60
-rw-r--r--ftp/atftp/files/patch-tftp_mtftp.c12
-rw-r--r--ftp/atftp/files/patch-tftpd.c159
-rw-r--r--ftp/atftp/files/patch-tftpd_file.c87
-rw-r--r--ftp/atftp/files/patch-tftpd_list.c11
-rw-r--r--ftp/atftp/files/patch-tftpd_pcre.c14
-rw-r--r--ftp/atftp/pkg-descr4
18 files changed, 840 insertions, 0 deletions
diff --git a/ftp/atftp/Makefile b/ftp/atftp/Makefile
new file mode 100644
index 000000000000..54c63e43cd5d
--- /dev/null
+++ b/ftp/atftp/Makefile
@@ -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>
diff --git a/ftp/atftp/distinfo b/ftp/atftp/distinfo
new file mode 100644
index 000000000000..19ed997ac497
--- /dev/null
+++ b/ftp/atftp/distinfo
@@ -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
diff --git a/ftp/atftp/files/atftpd.in b/ftp/atftp/files/atftpd.in
new file mode 100644
index 000000000000..505536f0851b
--- /dev/null
+++ b/ftp/atftp/files/atftpd.in
@@ -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"
diff --git a/ftp/atftp/files/patch-Makefile.in b/ftp/atftp/files/patch-Makefile.in
new file mode 100644
index 000000000000..e4c216fcf9f0
--- /dev/null
+++ b/ftp/atftp/files/patch-Makefile.in
@@ -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
+
diff --git a/ftp/atftp/files/patch-argz.h b/ftp/atftp/files/patch-argz.h
new file mode 100644
index 000000000000..3148ffe8c4e0
--- /dev/null
+++ b/ftp/atftp/files/patch-argz.h
@@ -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);
+ }
diff --git a/ftp/atftp/files/patch-logger.c b/ftp/atftp/files/patch-logger.c
new file mode 100644
index 000000000000..e04fda6b6db3
--- /dev/null
+++ b/ftp/atftp/files/patch-logger.c
@@ -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);
+ }
diff --git a/ftp/atftp/files/patch-stats.c b/ftp/atftp/files/patch-stats.c
new file mode 100644
index 000000000000..9a7a5c67c0a0
--- /dev/null
+++ b/ftp/atftp/files/patch-stats.c
@@ -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) /
diff --git a/ftp/atftp/files/patch-tftp.c b/ftp/atftp/files/patch-tftp.c
new file mode 100644
index 000000000000..3b1a356e38e1
--- /dev/null
+++ b/ftp/atftp/files/patch-tftp.c
@@ -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
diff --git a/ftp/atftp/files/patch-tftp_def.c b/ftp/atftp/files/patch-tftp_def.c
new file mode 100644
index 000000000000..a56e5ee84709
--- /dev/null
+++ b/ftp/atftp/files/patch-tftp_def.c
@@ -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;
+ }
+
+
diff --git a/ftp/atftp/files/patch-tftp_def.h b/ftp/atftp/files/patch-tftp_def.h
new file mode 100644
index 000000000000..5f75fe4cdf92
--- /dev/null
+++ b/ftp/atftp/files/patch-tftp_def.h
@@ -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 */
diff --git a/ftp/atftp/files/patch-tftp_file.c b/ftp/atftp/files/patch-tftp_file.c
new file mode 100644
index 000000000000..59b08f467396
--- /dev/null
+++ b/ftp/atftp/files/patch-tftp_file.c
@@ -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;
diff --git a/ftp/atftp/files/patch-tftp_io.c b/ftp/atftp/files/patch-tftp_io.c
new file mode 100644
index 000000000000..1c2672e978f1
--- /dev/null
+++ b/ftp/atftp/files/patch-tftp_io.c
@@ -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;
+ }
diff --git a/ftp/atftp/files/patch-tftp_mtftp.c b/ftp/atftp/files/patch-tftp_mtftp.c
new file mode 100644
index 000000000000..1a1557b67a7c
--- /dev/null
+++ b/ftp/atftp/files/patch-tftp_mtftp.c
@@ -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 */
diff --git a/ftp/atftp/files/patch-tftpd.c b/ftp/atftp/files/patch-tftpd.c
new file mode 100644
index 000000000000..00d8c2a57689
--- /dev/null
+++ b/ftp/atftp/files/patch-tftpd.c
@@ -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"
diff --git a/ftp/atftp/files/patch-tftpd_file.c b/ftp/atftp/files/patch-tftpd_file.c
new file mode 100644
index 000000000000..e11ad6aac6b9
--- /dev/null
+++ b/ftp/atftp/files/patch-tftpd_file.c
@@ -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;
diff --git a/ftp/atftp/files/patch-tftpd_list.c b/ftp/atftp/files/patch-tftpd_list.c
new file mode 100644
index 000000000000..1a087d64a2d3
--- /dev/null
+++ b/ftp/atftp/files/patch-tftpd_list.c
@@ -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);
diff --git a/ftp/atftp/files/patch-tftpd_pcre.c b/ftp/atftp/files/patch-tftpd_pcre.c
new file mode 100644
index 000000000000..e50626e7cb1c
--- /dev/null
+++ b/ftp/atftp/files/patch-tftpd_pcre.c
@@ -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;
diff --git a/ftp/atftp/pkg-descr b/ftp/atftp/pkg-descr
new file mode 100644
index 000000000000..fbaafbcde461
--- /dev/null
+++ b/ftp/atftp/pkg-descr
@@ -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.