Compare commits

..

No commits in common. "master" and "tftp-hpa-5.1" have entirely different histories.

50 changed files with 902 additions and 1318 deletions

View file

@ -1,11 +0,0 @@
root = true
[*]
end_of_line = lf
trim_trailing_whitespace = true
insert_final_newline = true
[{*.c,*.h}]
indent_style = space
indent_size = 4
tab_width = 8

11
.gitignore vendored
View file

@ -1,9 +1,6 @@
/config/MCONFIG
/config/config.h
/config/config.h.in
/autoconf/aclocal.m4
/autoconf/clean.sh
/autoconf/helpers/
/MCONFIG
/aconfig.h
/aconfig.h.in
/autom4te.cache
/config.log
/config.status
@ -15,7 +12,5 @@
*.8
*.a
*.o
*.i
*.s
*~
\#*

View file

@ -1,8 +1,3 @@
Changes in 5.2:
Fix breakage on newer Linux when a single interface has
multiple IP addresses.
Changes in 5.1:
Add -P option to write a PID file. Patch by Ferenc Wagner.

View file

@ -3,10 +3,10 @@
SUB = lib common tftp tftpd
%.build: config/MCONFIG config/config.h version.h
%.build: MCONFIG aconfig.h version.h
$(MAKE) -C $(patsubst %.build, %, $@)
%.install: config/MCONFIG config/config.h version.h
%.install: MCONFIG aconfig.h version.h
$(MAKE) -C $(patsubst %.install, %, $@) install
%.clean:
@ -15,12 +15,12 @@ SUB = lib common tftp tftpd
%.distclean:
$(MAKE) -C $(patsubst %.distclean, %, $@) distclean
all: config/MCONFIG $(patsubst %, %.build, $(SUB))
all: MCONFIG $(patsubst %, %.build, $(SUB))
tftp.build: lib.build common.build
tftpd.build: lib.build common.build
install: config/MCONFIG $(patsubst %, %.install, $(SUB))
install: MCONFIG $(patsubst %, %.install, $(SUB))
clean: localclean $(patsubst %, %.clean, $(SUB))
@ -30,40 +30,46 @@ localclean:
distclean: localdistclean $(patsubst %, %.distclean, $(SUB))
localdistclean: localclean
rm -f config/config/MCONFIG config.status config.log config/config.h *~ \#*
rm -f MCONFIG config.status config.log aconfig.h *~ \#*
rm -rf *.cache
find . -type f \( -name \*.orig -o -name \*.rej \) | xargs rm -f
spotless: distclean
rm -f configure config/config.h.in tftp.spec
rm -f configure aconfig.h.in tftp.spec
autoconf: configure config/config.h.in
autoconf: configure aconfig.h.in
config: config/MCONFIG config/config.h
config: MCONFIG aconfig.h
release:
$(MAKE) autoconf
$(MAKE) tftp.spec
$(MAKE) distclean
config/MCONFIG: configure config/MCONFIG.in config/config.h.in
MCONFIG: configure MCONFIG.in aconfig.h.in
if test -x config.status; then \
./config.status --recheck && ./config.status ; \
else \
./configure ; \
fi
config/config.h: config/MCONFIG
aconfig.h: MCONFIG
: Generated by side effect
configure: configure.ac
sh autogen.sh
# Adding "configure" to the dependencies serializes this with running
# autoconf, because there are apparently race conditions between
# autoconf and autoheader.
aconfig.h.in: configure.in configure aclocal.m4
rm -f aconfig.h.in aconfig.h
autoheader
config/config.h.in: configure
: Generated by side effect
configure: configure.in aclocal.m4
rm -rf MCONFIG configure config.log aconfig.h *.cache
autoconf
version.h: version
echo \#define VERSION \"tftp-hpa `cat version`\" > version.h
tftp.spec: tftp.spec.in version
sed -e "s/@@VERSION@@/`cat version`/g" < $< > $@ || rm -f $@

280
aclocal.m4 vendored Normal file
View file

@ -0,0 +1,280 @@
dnl -----------------------------------------------------------------------
dnl
dnl Copyright 1999-2008 H. Peter Anvin - All Rights Reserved
dnl
dnl This program is free software; you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
dnl the Free Software Foundation, Inc., 53 Temple Place Ste 330,
dnl Bostom MA 02111-1307, USA; either version 2 of the License, or
dnl (at your option) any later version; incorporated herein by reference.
dnl
dnl -----------------------------------------------------------------------
dnl --------------------------------------------------------------------------
dnl PA_ADD_CFLAGS()
dnl
dnl Attempt to add the given option to CFLAGS, if it doesn't break compilation
dnl --------------------------------------------------------------------------
AC_DEFUN(PA_ADD_CFLAGS,
[AC_MSG_CHECKING([if $CC accepts $1])
pa_add_cflags__old_cflags="$CFLAGS"
CFLAGS="$CFLAGS $1"
AC_TRY_LINK([#include <stdio.h>],
[printf("Hello, World!\n");],
AC_MSG_RESULT([yes]),
AC_MSG_RESULT([no])
CFLAGS="$pa_add_cflags__old_cflags")])
dnl --------------------------------------------------------------------------
dnl PA_SIGSETJMP
dnl
dnl Do we have sigsetjmp/siglongjmp? (AC_CHECK_FUNCS doesn't seem to work
dnl for these particular functions.)
dnl --------------------------------------------------------------------------
AC_DEFUN(PA_SIGSETJMP,
[AC_MSG_CHECKING([for sigsetjmp])
AC_TRY_LINK([
#ifdef HAVE_SETJMP_H
#include <setjmp.h>
#endif],
[sigjmp_buf buf;
sigsetjmp(buf,1);
siglongjmp(buf,2);],
AC_MSG_RESULT([yes])
$1,
AC_MSG_RESULT([no])
$2)])
dnl --------------------------------------------------------------------------
dnl PA_MSGHDR_MSG_CONTROL
dnl
dnl Does struct msghdr have the msg_control field?
dnl --------------------------------------------------------------------------
AH_TEMPLATE([HAVE_MSGHDR_MSG_CONTROL],
[Define if struct msghdr has the msg_control field.])
AC_DEFUN(PA_MSGHDR_MSG_CONTROL,
[AC_CHECK_MEMBER(struct msghdr.msg_control,
[AC_DEFINE(HAVE_MSGHDR_MSG_CONTROL)],
[],
[
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
])])
dnl ------------------------------------------------------------------------
dnl PA_STRUCT_IN_PKTINFO
dnl
dnl Look for definition of struct in_pktinfo, which at least has an
dnl ipi_addr member. Some versions of glibc lack struct in_pktinfo;
dnl if so we need to include the definition ourselves -- but we only
dnl want to do that if absolutely necessary!
dnl ------------------------------------------------------------------------
AH_TEMPLATE([HAVE_STRUCT_IN_PKTINFO],
[Define if struct in_pktinfo is defined.])
AC_DEFUN(PA_STRUCT_IN_PKTINFO,
[AC_CHECK_MEMBER(struct in_pktinfo.ipi_addr,
[AC_DEFINE(HAVE_STRUCT_IN_PKTINFO)],
[],
[
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <sys/uio.h>
])])
dnl ------------------------------------------------------------------------
dnl PA_STRUCT_SOCKADDR_IN6
dnl
dnl Look for definition of struct sockaddr_in6, which at least has an
dnl sin6_addr member
dnl
AH_TEMPLATE([HAVE_STRUCT_SOCKADDR_IN6],
[Define if struct sockaddr_in6 is defined.])
AC_DEFUN(PA_STRUCT_SOCKADDR_IN6,
[AC_CHECK_MEMBER(struct sockaddr_in6.sin6_addr,
[
AC_DEFINE(HAVE_STRUCT_SOCKADDR_IN6)
HAVE_INET6=true;
],
[
HAVE_INET6=false;
],
[
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
])])
dnl ------------------------------------------------------------------------
dnl PA_STRUCT_ADDRINFO
dnl
dnl Look for definition of struct addrinfo, which at least has an
dnl ai_addr member
dnl
AH_TEMPLATE([HAVE_STRUCT_ADDRINFO],
[Define if struct addrinfo is defined.])
AC_DEFUN(PA_STRUCT_ADDRINFO,
[AC_CHECK_MEMBER(struct addrinfo.ai_addr,
[AC_DEFINE(HAVE_STRUCT_ADDRINFO)],
[],
[
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
])])
dnl ------------------------------------------------------------------------
dnl PA_STRUCT_IN6_PKTINFO
dnl
dnl Look for definition of struct in6_pktinfo, which at least has an
dnl ipi6_addr member
dnl
AH_TEMPLATE([HAVE_STRUCT_IN6_PKTINFO],
[Define if struct in6_pktinfo is defined.])
AC_DEFUN(PA_STRUCT_IN6_PKTINFO,
[AC_CHECK_MEMBER(struct in6_pktinfo.ipi6_addr,
[AC_DEFINE(HAVE_STRUCT_IN6_PKTINFO)],
[],
[
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
])])
dnl --------------------------------------------------------------------------
dnl PA_HAVE_TCPWRAPPERS
dnl
dnl Do we have the tcpwrappers -lwrap? This can't be done using AC_CHECK_LIBS
dnl due to the need to provide "allow_severity" and "deny_severity" variables
dnl --------------------------------------------------------------------------
AH_TEMPLATE([HAVE_TCPWRAPPERS],
[Define if we have tcpwrappers (-lwrap) and <tcpd.h>.])
AC_DEFUN(PA_HAVE_TCPWRAPPERS,
[AC_CHECK_LIB([wrap], [main])
AC_MSG_CHECKING([for tcpwrappers])
AC_TRY_LINK(
[
#include <tcpd.h>
int allow_severity = 0;
int deny_severity = 0;
],
[
hosts_ctl("sample_daemon", STRING_UNKNOWN, STRING_UNKNOWN, STRING_UNKNOWN);
],
[
AC_DEFINE(HAVE_TCPWRAPPERS)
AC_MSG_RESULT([yes])
],
[
AC_MSG_RESULT([no])
])])
dnl ------------------------------------------------------------------------
dnl PA_CHECK_INTTYPES_H_SANE
dnl
dnl At least some versions of AIX 4 have <inttypes.h> macros which are
dnl completely broken. Try to detect those.
dnl --------------------------------------------------------------------------
AH_TEMPLATE([INTTYPES_H_IS_SANE],
[Define if the macros in <inttypes.h> are usable])
AC_DEFUN(PA_CHECK_INTTYPES_H_SANE,
[AC_CHECK_HEADERS(inttypes.h,
[
AC_MSG_CHECKING([if inttypes.h is sane])
AC_TRY_LINK(
[
#include <inttypes.h>
#include <stdio.h>
],
[uintmax_t max = UINTMAX_C(0);
printf("%"PRIuMAX"\n", max);],
AC_MSG_RESULT([yes])
AC_DEFINE(INTTYPES_H_IS_SANE),
AC_MSG_RESULT([no (AIX, eh?)]))
])
])
dnl ------------------------------------------------------------------------
dnl PA_WITH_BOOL
dnl
dnl PA_WITH_BOOL(option, default, help, enable, disable)
dnl
dnl Provides a more convenient way to specify --with-option and
dnl --without-option, with a default. default should be either 0 or 1.
dnl ------------------------------------------------------------------------
AC_DEFUN(PA_WITH_BOOL,
[AC_ARG_WITH([$1], [$3],
if test ["$withval"] != no; then
[$4]
else
[$5]
fi,
if test [$2] -ne 0; then
[$4]
else
[$5]
fi)])
dnl --------------------------------------------------------------------------
dnl PA_HEADER_DEFINES
dnl
dnl PA_HEADER_DEFINES(header, type, value)
dnl --------------------------------------------------------------------------
AC_DEFUN(PA_HEADER_DEFINES,
[AC_MSG_CHECKING([if $1 defines $3])
AH_TEMPLATE([HAVE_$3_DEFINITION], [Define if $1 defines $3])
AC_TRY_COMPILE([
#include <$1>
],
[
int main()
{
$2 dummy = $3;
return 0;
}
],
[
pa_header_define=`echo HAVE_$3_DEFINITION | tr '[a-z]' '[A-Z]'`
AC_DEFINE_UNQUOTED($pa_header_define)
AC_MSG_RESULT(yes)
],
[
AC_MSG_RESULT(no)
])])
dnl --------------------------------------------------------------------------
dnl PA_SEARCH_LIBS_AND_ADD
dnl
dnl PA_SEARCH_LIBS_AND_ADD(function, libraries [,function to add])
dnl --------------------------------------------------------------------------
AC_DEFUN(PA_SEARCH_LIBS_AND_ADD,
[
AH_TEMPLATE(AS_TR_CPP(HAVE_$1), [Define if $1 function was found])
AC_SEARCH_LIBS($1, $2,
[
AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$1))
pa_add_$1=false;
],
[
XTRA=true;
if test $# -eq 3; then
AC_LIBOBJ($3)
else
AC_LIBOBJ($1)
fi
pa_add_$1=true;
])])

View file

@ -1,9 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_ADD_CFLAGS(variable, flag [,actual_flag [,success [,failure]]]])
dnl
dnl Attempt to add the given option to xFLAGS, if it doesn't break
dnl compilation. If the option to be tested is different than the
dnl option that should actually be added, add the option to be
dnl actually added as a second argument.
dnl --------------------------------------------------------------------------
AC_DEFUN([PA_ADD_CFLAGS], [PA_ADD_FLAGS(CFLAGS, [$1], [$2], [$3], [$4])])

View file

@ -1,39 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_ADD_FLAGS(flagvar, flags)
dnl
dnl Add [flags] to the variable [flagvar] if and only if it is accepted
dnl by all languages affected by [flagvar], if those languages have
dnl been previously seen in the script.
dnl --------------------------------------------------------------------------
AC_DEFUN([PA_ADD_FLAGS],
[
AS_VAR_PUSHDEF([old], [_$0_$1_orig])
AS_VAR_PUSHDEF([ok], [_$0_$1_ok])
AS_VAR_PUSHDEF([flags], [$1])
AS_VAR_COPY([old], [flags])
AS_VAR_SET([flags], ["$flags $2"])
AS_VAR_SET([ok], [yes])
PA_LANG_FOREACH(PA_FLAGS_LANGLIST($1),
[AS_VAR_IF([ok], [yes],
[AC_MSG_CHECKING([if $]_AC_CC[ accepts $2])
PA_BUILD_IFELSE([],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])
AS_VAR_SET([ok], [no])])])
])
AS_VAR_IF([ok], [yes],
[m4_ifnblank([$3],[AS_VAR_SET([flags], ["$old $3"])])
m4_foreach_w([_pa_add_flags_flag], [m4_ifblank([$3],[$2],[$3])],
[AC_DEFINE(PA_SYM([$1_]_pa_add_flags_flag), 1,
[Define to 1 if compiled with the ]_pa_add_flags_flag[ compiler flag])])
$4],
[AS_VAR_SET([flags], ["$old"])
$5])
AS_VAR_POPDEF([flags])
AS_VAR_POPDEF([ok])
AS_VAR_POPDEF([old])
])

View file

@ -1,13 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_ADD_HEADERS(headers...)
dnl
dnl Call AC_CHECK_HEADERS(), and add to ac_includes_default if found
dnl --------------------------------------------------------------------------
AC_DEFUN([_PA_ADD_HEADER],
[AC_CHECK_HEADERS([$1],[ac_includes_default="$ac_includes_default
#include <$1>"
])
])
AC_DEFUN([PA_ADD_HEADERS],
[m4_map_args_w([$1],[_PA_ADD_HEADER(],[)])])

View file

@ -1,27 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_ADD_LANGFLAGS(flag...)
dnl
dnl Attempt to add the option in the given list to each compiler flags
dnl (CFLAGS, CXXFLAGS, ...), if it doesn't break compilation.
dnl --------------------------------------------------------------------------
m4_defun([_PA_LANGFLAG_VAR],
[m4_case([$1],
[C], [CFLAGS],
[C++], [CXXFLAGS],
[Fortran 77], [FFLAGS],
[Fortran], [FCFLAGS],
[Erlang], [ERLCFLAGS],
[Objective C], [OBJCFLAGS],
[Objective C++], [OBJCXXFLAGS],
[Go], [GOFLAGS],
[m4_fatal([PA_ADD_LANGFLAGS: Unknown language: $1])])])
AC_DEFUN([PA_ADD_LANGFLAGS],
[m4_pushdef([_pa_langflags],m4_dquote($1))dnl
m4_set_foreach(_PA_LANG_SEEN_SET,[_pa_lang],dnl
[_pa_flag_found=no
m4_foreach_w([_pa_flag], _pa_langflags,
[AS_IF([test $_pa_flag_found = no],
[PA_ADD_FLAGS(_PA_LANGFLAG_VAR(_pa_lang),_pa_flag,[],[_pa_flag_found=yes])])
])])
m4_popdef([_pa_langflags])])

View file

@ -1,19 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_ARG_BOOL(option,helptext,default,enabled_action,disabled_action)
dnl
dnl The last three arguments are optional; default can be yes or no.
dnl
dnl Simpler-to-use versions of AC_ARG_ENABLED, that include the
dnl test for $enableval and the AS_HELP_STRING definition. This is only
dnl to be used for boolean options.
dnl --------------------------------------------------------------------------
AC_DEFUN([PA_ARG_BOOL],
[m4_pushdef([pa_default],m4_default(m4_normalize([$3]),[no]))
m4_pushdef([pa_option],m4_case(pa_default,[yes],[disable],[enable]))
AC_ARG_ENABLE([$1],
[AS_HELP_STRING([--]m4_defn([pa_option])[-$1],[$2])],
[pa_arg_bool_enableval="$enableval"],
[pa_arg_bool_enableval="]m4_defn([pa_default])["])
m4_popdef([pa_option], [pa_default])
AS_IF([test x"$pa_arg_bool_enableval" != xno], [$4], [$5])
])

View file

@ -1,4 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_ARG_DISABLED(option,helptext,disabled_action,enabled_action)
dnl --------------------------------------------------------------------------
AC_DEFUN([PA_ARG_DISABLED],[PA_ARG_BOOL([$1],[$2],yes,[$4],[$3])])

View file

@ -1,4 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_ARG_ENABLED(option,helptext,enabled_action,disabled_action)
dnl --------------------------------------------------------------------------
AC_DEFUN([PA_ARG_ENABLED],[PA_ARG_BOOL([$1],[$2],no,[$3],[$4])])

View file

@ -1,16 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_BUILD_IFELSE(input [,success [,failure]])
dnl
dnl Same as AC_LINK_IFELSE for languages where linking is applicable,
dnl otherwise AC_COMPILE_IFELSE.
dnl
dnl If the first argument is empty, use _AC_LANG_IO_PROGRAM.
dnl --------------------------------------------------------------------------
m4_defun([_PA_BUILD_IFELSE],
[m4_case(_AC_LANG,
[Erlang], [AC_COMPILE_IFELSE($@)],
[AC_LINK_IFELSE($@)])])
AC_DEFUN([PA_BUILD_IFELSE],
[_PA_BUILD_IFELSE([m4_ifblank([$1],[AC_LANG_SOURCE(_AC_LANG_IO_PROGRAM)],
[$1])],[$2],[$3])])

View file

@ -1,32 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_C_TYPEOF
dnl
dnl Find if typeof() exists, or an equivalent (__typeof__, decltype,
dnl __decltype__)
dnl --------------------------------------------------------------------------
AC_DEFUN([PA_C_TYPEOF],
[AC_CACHE_CHECK([if $CC supports typeof], [pa_cv_typeof],
[pa_cv_typeof=no
for pa_typeof_try in typeof __typeof __typeof__ decltype __decltype __decltype__ _Decltype
do
AS_IF([test $pa_cv_typeof = no],
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([
AC_INCLUDES_DEFAULT
int testme(int x);
int testme(int x)
{
$pa_typeof_try(x) y = x*x;
return y;
}
])],
[pa_cv_typeof=$pa_typeof_try])])
done
])
AS_IF([test $pa_cv_typeof = no],
[],
[AC_DEFINE([HAVE_TYPEOF], 1,
[Define to 1 if you have some version of the typeof operator.])
AS_IF([test $pa_cv_typeof = typeof],
[],
[AC_DEFINE_UNQUOTED([typeof], [$pa_cv_typeof],
[Define if your typeof operator is not named `typeof'.])])])])

View file

@ -1,26 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_CHECK_BAD_STDC_INLINE
dnl
dnl Some versions of gcc seem to apply -Wmissing-prototypes to C99
dnl inline functions, which means we need to use GNU inline syntax
dnl --------------------------------------------------------------------------
AC_DEFUN([PA_CHECK_BAD_STDC_INLINE],
[AC_MSG_CHECKING([if $CC supports C99 external inlines])
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
AC_INCLUDES_DEFAULT
/* Don't mistake GNU inlines for c99 */
#if defined(__GNUC__) && !defined(__GNUC_STDC_INLINE__)
# error "Using gnu inline standard"
#endif
inline int foo(int x)
{
return x+1;
}
])],
[AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_STDC_INLINE], 1,
[Define to 1 if your compiler supports C99 extern inline])],
[AC_MSG_RESULT([no])
PA_ADD_CFLAGS([-fgnu89-inline])])])

View file

@ -1,17 +0,0 @@
dnl ------------------------------------------------------------------------
dnl PA_CHECK_INTTYPES_H_SANE
dnl
dnl At least some versions of AIX 4 have <inttypes.h> macros which are
dnl completely broken. Try to detect those.
dnl --------------------------------------------------------------------------
AC_DEFUN([PA_CHECK_INTTYPES_H_SANE],
[AC_CHECK_HEADERS_ONCE(inttypes.h)
AS_IF([test "x$ac_cv_header_inttypes_h" = xyes],[
AC_MSG_CHECKING([if inttypes.h is sane])
AC_LINK_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT],
[uintmax_t max = UINTMAX_C(0);
printf("%"PRIuMAX"\n", max);])],
[AC_MSG_RESULT([yes])
AC_DEFINE(INTTYPES_H_IS_SANE, 1,
[Define if the macros in <inttypes.h> are usable])],
[AC_MSG_RESULT([no (AIX, eh?)])])])])

View file

@ -1,41 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_CROSS_COMPILE
dnl
dnl Get the canonical name for the build and host (runtime) systems;
dnl then figure out if this is cross-compilation. Specifically, this
dnl disables invoking WINE on non-Windows systems which are configured
dnl to run WINE automatically.
dnl
dnl Use PA_CROSS_COMPILE_TOOL if the target system (output of a code-
dnl generation tool) is applicable.
dnl
dnl This doesn't explicitly print any messages as that is automatically
dnl done elsewhere.
dnl --------------------------------------------------------------------------
AC_DEFUN_ONCE([PA_CROSS_COMPILE],
[
AC_BEFORE([$0], [AC_LANG_COMPILER])
AC_BEFORE([$0], [AC_LANG])
AC_BEFORE([$0], [AC_PROG_CC])
AC_BEFORE([$0], [AC_PROG_CPP])
AC_BEFORE([$0], [AC_PROG_CXX])
AC_BEFORE([$0], [AC_PROG_CXXCPP])
AC_BEFORE([$0], [AC_PROG_OBJC])
AC_BEFORE([$0], [AC_PROG_OBJCPP])
AC_BEFORE([$0], [AC_PROG_OBJCXX])
AC_BEFORE([$0], [AC_PROG_OBJCXXCPP])
AC_BEFORE([$0], [AC_PROG_F77])
AC_BEFORE([$0], [AC_PROG_FC])
AC_BEFORE([$0], [AC_PROG_GO])
# Disable WINE
WINELOADER=/dev/null
export WINELOADER
WINESERVER=/dev/null
export WINESERVER
WINEPREFIX=/dev/null
export WINEPREFIX
AC_CANONICAL_BUILD
AC_CANONICAL_HOST
])

View file

@ -1,19 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_FLAGS_LANGLIST(flagvar)
dnl
dnl Return a list of languages affected by the variable flagvar.
dnl If flagvar is unknown, assume it affects the current language.
dnl --------------------------------------------------------------------------
AC_DEFUN([PA_FLAGS_LANGLIST],
[m4_dquote(m4_case([$1],
[CPPFLAGS], [[C],[C++],[Objective C],[Objective C++]],
[CFLAGS], [[C]],
[CXXFLAGS], [[C++]],
[FFLAGS], [[Fortran 77]],
[FCFLAGS], [[Fortran]],
[ERLCFLAGS], [[Erlang]],
[OBJCFLAGS], [[Objective C]],
[OBJCXXFLAGS], [[Objective C++]],
[GOFLAGS], [[Go]],
[LDFLAGS], [[C],[C++],[Fortran 77],[Fortran],[Objective C],[Objective C++],[Go]],
m4_dquote(_AC_LANG)))])

View file

@ -1,26 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_HAVE_TCPWRAPPERS
dnl
dnl Do we have the tcpwrappers -lwrap? This can't be done using AC_CHECK_LIBS
dnl due to the need to provide "allow_severity" and "deny_severity" variables
dnl --------------------------------------------------------------------------
AC_DEFUN([PA_HAVE_TCPWRAPPERS],
[AC_CHECK_LIB([wrap], [main])
AC_MSG_CHECKING([for tcpwrappers])
AC_LINK_IFELSE([AC_LANG_PROGRAM(
[[
#include <tcpd.h>
int allow_severity = 0;
int deny_severity = 0;
]],
[[
hosts_ctl("sample_daemon", STRING_UNKNOWN, STRING_UNKNOWN, STRING_UNKNOWN);
]])],
[
AC_DEFINE(HAVE_TCPWRAPPERS, 1,
[Define if we have tcpwrappers (-lwrap) and <tcpd.h>.])
AC_MSG_RESULT([yes])
],
[
AC_MSG_RESULT([no])
])])

View file

@ -1,15 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_LANG_FOREACH(subset, body)
dnl
dnl Expand [body] for each language encountered in the configure script also
dnl present in [subset], or all if [subset] is empty
dnl --------------------------------------------------------------------------
AC_DEFUN([_PA_LANG_DO],dnl
[AC_LANG([$2])dnl
$1])
AC_DEFUN([PA_LANG_FOREACH],dnl
[m4_pushdef([_pa_lang_foreach_current],[_AC_LANG])dnl
m4_map_args([m4_curry([_PA_LANG_DO],[$2])],m4_unquote(PA_LANG_SEEN_LIST($1)))dnl
AC_LANG(_pa_lang_foreach_current)dnl
m4_popdef([_pa_lang_foreach_current])])

View file

@ -1,20 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_LANG_SEEN_LIST(subset)
dnl
dnl List of the language lang has been used in the configuration
dnl script so far, possibly subset by [subset].
dnl
dnl This relies on overriding _AC_LANG_SET(from, to),
dnl the internal implementation of _AC_LANG.
dnl --------------------------------------------------------------------------
m4_ifndef([_PA_LANG_SET],
[m4_rename([_AC_LANG_SET], [_PA_LANG_SET])dnl
m4_defun([_AC_LANG_SET], [m4_set_add([_PA_LANG_SEEN_SET],[$2])dnl
_PA_LANG_SET($@)])])
AC_DEFUN([PA_LANG_SEEN_LIST],
[m4_set_delete([_pa_lang_seen_subset])dnl
m4_pushdef([_pa_lang_seen_subset_list],m4_ifnblank([$1],[$1],m4_dquote(m4_set_list([_PA_LANG_SEEN_SET]))))dnl
m4_set_add_all([_pa_lang_seen_subset],_pa_lang_seen_subset_list)dnl
m4_cdr(m4_set_intersection([_pa_lang_seen_subset],[_PA_LANG_SEEN_SET]))dnl
m4_popdef([_pa_lang_seen_subset_list])])

View file

@ -1,13 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_OPTION_DEBUG(with_debug, without_debug)
dnl
dnl Set debug flags and optimization flags depending on if
dnl --enable-debug is set or not. Some flags are set regardless...
dnl --------------------------------------------------------------------------
AC_DEFUN([PA_OPTION_DEBUG],
[PA_ARG_DISABLED([gdb], [disable gdb debug extensions],
[PA_ADD_LANGFLAGS([-g3])], [PA_ADD_LANGFLAGS([-ggdb3 -g3])])
PA_ARG_ENABLED([debug], [optimize for debugging],
[PA_ADD_LANGFLAGS([-Og -O0])
$1],
[$2])])

View file

@ -1,8 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_OPTION_PROFILING(with_profiling, without_profiling)
dnl
dnl Try to enable profiling if --enable-profiling is set.
dnl --------------------------------------------------------------------------
AC_DEFUN([PA_OPTION_PROFILING],
[PA_ARG_ENABLED([profiling], [compile with profiling (-pg option)],
[PA_ADD_LANGFLAGS([-pg])])])

View file

@ -1,13 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_PROG_CC()
dnl
dnl Similar to AC_PROG_CC, but add a prototype for main() to
dnl AC_INCLUDES_DEFAULT to avoid -Werror from breaking compilation.
dnl --------------------------------------------------------------------------
AC_DEFUN([PA_PROG_CC],
[AC_PROG_CC
AS_IF([test x$ac_cv_prog != xno],
[ac_includes_default="$ac_includes_default
#ifndef __cplusplus
extern int main(void);
#endif"])])

View file

@ -1,22 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_SEARCH_LIBS_AND_ADD
dnl
dnl PA_SEARCH_LIBS_AND_ADD(function, libraries [,function to add])
dnl --------------------------------------------------------------------------
AC_DEFUN([PA_SEARCH_LIBS_AND_ADD],
[
AH_TEMPLATE(AS_TR_CPP(HAVE_$1), [Define if $1 function was found])
AC_SEARCH_LIBS($1, $2,
[
AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$1))
pa_add_$1=false;
],
[
XTRA=true;
if test $# -eq 3; then
AC_LIBOBJ($3)
else
AC_LIBOBJ($1)
fi
pa_add_$1=true;
])])

View file

@ -1,25 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_SIGSETJMP
dnl
dnl Do we have sigsetjmp/siglongjmp? (AC_CHECK_FUNCS doesn't seem to work
dnl for these particular functions.)
dnl --------------------------------------------------------------------------
AC_DEFUN([PA_SIGSETJMP],
[AC_MSG_CHECKING([for sigsetjmp])
AC_LINK_IFELSE([AC_LANG_SOURCE(
[
AC_INCLUDES_DEFAULT
#include <setjmp.h>
int main(void) {
sigjmp_buf buf;
if (sigsetjmp(buf,1))
return 0;
siglongjmp(buf,2);
return 1;
}
])],
[AC_MSG_RESULT([yes])
AC_DEFINE([HAVE_SIGSETJMP], 1,
[Define to 1 if your system has sigsetjmp/siglongjmp])],
[AC_MSG_RESULT([no])])])

View file

@ -1,11 +0,0 @@
dnl --------------------------------------------------------------------------
dnl PA_SYM(prefix, string)
dnl
dnl Convert a (semi-) arbitrary string to a CPP symbol
dnl Compact underscores and convert non-C characters to underscore,
dnl except + which is converted to X (so C++ -> CXX).
dnl --------------------------------------------------------------------------
AC_DEFUN([PA_SYM],
[m4_bpatsubsts(m4_quote(m4_toupper([$*])),
[,],[],[\+],[X],[[^ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]+],[_],dnl
[^._?\(.*\)_.$],[[\1]])])

View file

@ -1,83 +1,2 @@
#!/bin/sh -x
#
# Run this script to regenerate autoconf files
#
recheck=false
for arg; do
case x"$arg" in
x--recheck)
recheck=true
config=$(sh config.status --config 2>/dev/null)
;;
x--clearenv)
unset AUTOCONF AUTOMAKE ACLOCAL AUTOHEADER ACLOCAL_PATH
;;
*)
echo "$0: unknown option: $arg" 1>&2
;;
esac
done
# This allows for overriding the default autoconf programs
AUTOCONF="${AUTOCONF:-${AUTOTOOLS_PREFIX}autoconf}"
AUTOMAKE="${AUTOMAKE:-${AUTOTOOLS_PREFIX}automake}"
ACLOCAL="${ACLOCAL:-${AUTOTOOLS_PREFIX}aclocal}"
AUTOHEADER="${AUTOHEADER:-${AUTOTOOLS_PREFIX}autoheader}"
mkdir -p autoconf autoconf/helpers config
autolib="`"$AUTOMAKE" --print-libdir`"
if test ! x"$autolib" = x; then
for prg in install-sh compile config.guess config.sub; do
# Update autoconf helpers if and only if newer ones are available
if test -f "$autolib"/"$prg" && \
( set -e ; \
test -f autoconf/helpers/"$prg" && sed -n \
-e 's/^scriptver=/scriptversion=/' \
-e 's/^timestamp=/scriptversion=/' \
-e 's/^scriptversion=['\''"]?\([^'\''"]*\).*$/\1/p' \
"$autolib"/"$prg" autoconf/helpers/"$prg" | \
sort -c 2>/dev/null ; \
test $? -ne 0 )
then
cp -f "$autolib"/"$prg" autoconf/helpers
fi
done
fi
mv -f autoconf/aclocal.m4 autoconf/aclocal.m4.old
mkdir -p autoconf/m4.old autoconf/m4
mv -f autoconf/m4/*.m4 autoconf/m4.old/ 2>/dev/null || true
ACLOCAL_PATH="${ACLOCAL_PATH}${ACLOCAL_PATH:+:}`pwd`/autoconf/m4.old"
export ACLOCAL_PATH
"$ACLOCAL" --install --output=autoconf/aclocal.m4 -I autoconf/m4
if test ! -f autoconf/aclocal.m4; then
# aclocal failed, revert to previous files
mv -f autoconf/m4.old/*.m4 autoconf/m4/
mv -f autoconf/aclocal.m4.old autoconf/aclocal.m4
exit 1
fi
rm -rf autoconf/*m4.old
"$AUTOHEADER" -B autoconf
"$AUTOCONF" -B autoconf
(
echo '#!/bin/sh'
"$AUTOCONF" -B autoconf \
-t AC_CONFIG_HEADERS:'rm -f $*' \
-t AC_CONFIG_FILES:'rm -f $*'
echo 'rm -f config.log config.status'
echo 'rm -rf autom4te.cache'
) > autoconf/clean.sh
chmod +x autoconf/clean.sh
sh autoconf/clean.sh
rm -f configure~ || true
# Try to regenerate unconfig.h if Perl is available and unconfig.pl
# is present in the autoconf directory.
if [ -n "$(which perl)" -a -f autoconf/unconfig.pl ]; then
perl autoconf/unconfig.pl . config/config.h.in config/unconfig.h
fi
if $recheck; then
# This bizarre statement has to do with how config.status quotes its output
echo exec sh configure $config | sh -
fi
#!/bin/sh
make autoconf

View file

@ -1,10 +1,10 @@
SRCROOT = ..
VERSION = $(shell cat ../version)
-include ../config/MCONFIG
-include ../MCONFIG
include ../MRULES
OBJS = tftpsubs.$(O) signal.$(O)
OBJS = tftpsubs.$(O)
LIB = libcommon.a
all: $(LIB)

View file

@ -1,19 +0,0 @@
/*
* signal.c
*
* User-friendly wrapper around sigaction().
*/
#include "config.h"
int tftp_signal(int signum, sighandler_t handler, int flags)
{
struct sigaction sa;
memset(&sa, 0, sizeof sa);
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = flags;
return sigaction(signum, &sa, NULL);
}

View file

@ -1,6 +1,6 @@
/* -*- c -*- ------------------------------------------------------------- *
*
* Copyright 2001-2024 H. Peter Anvin - All Rights Reserved
* Copyright 2001-2006 H. Peter Anvin - All Rights Reserved
*
* This program is free software available under the same license
* as the "OpenBSD" operating system, distributed at
@ -17,23 +17,12 @@
#ifndef CONFIG_H
#define CONFIG_H 1
/* Feature enables for specific environments */
#ifdef __APPLE__
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1070
#define __APPLE_USE_RFC_3542 1
#endif
#endif
/* Must be included before we include any system headers! */
#include "config/config.h" /* autogenerated configuration header */
#include "aconfig.h" /* autogenerated configuration header */
/* Standard includes */
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@ -43,6 +32,21 @@
#include <sys/stat.h>
#endif
#ifdef STDC_HEADERS
#include <stdlib.h>
#include <stddef.h>
#else
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_MEMORY_H
#ifndef STDC_HEADERS
#include <memory.h>
#endif
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
@ -69,8 +73,15 @@
#include <setjmp.h>
#endif
#ifdef HAVE_SYS_TIME_H
#ifdef TIME_WITH_SYS_TIME
#include <sys/time.h>
#include <time.h>
#else
#if HAVE_SYS_TIME_H
#include <sys/time.h>
#else
#include <time.h>
#endif
#endif
#ifdef HAVE_GRP_H
@ -81,6 +92,9 @@
#include <fcntl.h>
#endif
#include <errno.h>
#include <signal.h>
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#else
@ -115,10 +129,10 @@
/* Some broken systems care about text versus binary, but
real Unix systems don't... */
#if !HAVE_DECL_O_TEXT
#ifndef HAVE_O_TEXT_DEFINITION
#define O_TEXT 0
#endif
#if !HAVE_DECL_O_BINARY
#ifndef HAVE_O_BINARY_DEFINITION
#define O_BINARY 0
#endif
@ -253,9 +267,11 @@ typedef int socklen_t;
#include <netinet/in.h>
#if !HAVE_DECL_IPPORT_TFTP && !defined(IPPORT_TFTP)
#ifndef HAVE_IPPORT_TFTP_DEFINITION
#ifndef IPPORT_TFTP
#define IPPORT_TFTP 69
#endif
#endif
/* arpa/{inet,tftp}.h, and possible missing pieces */
@ -277,11 +293,9 @@ typedef int socklen_t;
void *xmalloc(size_t);
char *xstrdup(const char *);
#ifndef HAVE_SIGHANDLER_T
typedef void (*sighandler_t)(int);
#ifndef HAVE_BSD_SIGNAL
void (*bsd_signal(int, void (*)(int))) (int);
#endif
int tftp_signal(int, sighandler_t, int);
#ifndef HAVE_DUP2
int dup2(int, int);
#endif

View file

@ -1,283 +0,0 @@
dnl Process this file with autoconf 2.71 or later to produce
dnl a configure script.
AC_PREREQ([2.71])
AC_INIT
AC_CONFIG_SRCDIR([MRULES])
AC_PREFIX_DEFAULT([/usr])
AC_CONFIG_AUX_DIR([autoconf/helpers])
dnl This prevents us from running Wine and thinking we are not
dnl cross-compiling when in fact we are; running Wine here is at
dnl the best very slow and doesn't buy us a single thing at all.
PA_CROSS_COMPILE
dnl Enable any available C extensions
PA_PROG_CC
AC_USE_SYSTEM_EXTENSIONS
dnl Options for debugging and profiling
PA_OPTION_DEBUG
PA_OPTION_PROFILING
dnl LLVM doesn't error out on invalid -W options unless this option is
dnl specified first. Enable this so this script can actually discover
dnl which -W options are possible for this compiler.
PA_ADD_CFLAGS([-Werror=unknown-warning-option])
dnl Force gcc and gcc-compatible compilers treat signed integers
dnl as 2's complement
PA_ADD_CFLAGS([-fwrapv])
dnl Force clang to behave in a predictable manner, in order to make bugs
dnl possible to track down. gcc appears to have this behavior by default.
PA_ADD_CFLAGS([-ftrivial-auto-var-init=zero])
dnl Some environments abuse __STRICT_ANSI__ to disable some
dnl function declarations
PA_ADD_CFLAGS([-U__STRICT_ANSI__])
dnl Don't put things in common if we can avoid it. We don't want to
dnl assume all compilers support common, and this will help find those
dnl problems. This also works around an OSX linker problem.
PA_ADD_CFLAGS([-fno-common])
dnl Tests which may trigger warnings on some compilers
AC_C_CONST
AC_C_INLINE
AC_C_RESTRICT
dnl Checks for header files.
AC_CHECK_INCLUDES_DEFAULT
dnl See if we need extra libraries
XTRA=false
AC_SEARCH_LIBS([strerror],[cposix])
AC_CHECK_HEADERS_ONCE(inttypes.h)
AC_CHECK_HEADERS_ONCE(stdint.h)
AC_CHECK_HEADERS_ONCE(grp.h)
AC_CHECK_HEADERS_ONCE(libgen.h)
AC_CHECK_HEADERS_ONCE(setjmp.h)
AC_CHECK_HEADERS_ONCE(strings.h)
AC_CHECK_HEADERS_ONCE(sysexits.h)
AC_CHECK_HEADERS_ONCE(unistd.h)
AC_CHECK_HEADERS_ONCE(sys/filio.h)
AC_CHECK_HEADERS_ONCE(sys/stat.h)
AC_CHECK_HEADERS_ONCE(sys/time.h)
PA_CHECK_INTTYPES_H_SANE
dnl This is needed on some versions of FreeBSD...
AC_CHECK_HEADERS_ONCE(machine/param.h)
dnl Windows...
PA_ADD_HEADERS(windows.h)
PA_ADD_HEADERS(winsock2.h)
AS_IF([test "x$ac_cv_header_winsock2_h" != xyes],
[PA_ADD_HEADERS(winsock.h)])
PA_ADD_HEADERS(fcntl.h)
PA_ADD_HEADERS(sys/types.h)
PA_ADD_HEADERS(arpa/inet.h)
PA_ADD_HEADERS(sys/socket.h)
PA_ADD_HEADERS(sys/file.h)
PA_ADD_HEADERS(netinet/in.h)
PA_ADD_HEADERS(sys/uio.h)
PA_ADD_HEADERS(netdb.h)
AC_TYPE_OFF_T
AC_TYPE_PID_T
AC_TYPE_MODE_T
AC_TYPE_SIZE_T
AC_CHECK_TYPES(intmax_t)
AC_CHECK_TYPES(long long)
AC_CHECK_TYPES(uint16_t)
AC_CHECK_TYPES(uint32_t)
AC_CHECK_TYPES(u_short)
AC_CHECK_TYPES(u_long)
AC_CHECK_TYPES(socklen_t)
AC_SEARCH_LIBS(socket, [socket ws2_32 wsock32], ,
[AC_MSG_ERROR(socket library not found)])
AC_CHECK_FUNCS(fcntl)
AC_CHECK_FUNCS(flock)
AC_CHECK_FUNCS(setsid)
AC_CHECK_FUNCS(recvmsg)
AC_CHECK_FUNCS(ftruncate)
AC_CHECK_FUNCS(setresuid)
AC_CHECK_FUNCS(setreuid)
AC_CHECK_FUNCS(setresgid)
AC_CHECK_FUNCS(setregid)
AC_CHECK_FUNCS(initgroups)
AC_CHECK_FUNCS(setgroups)
AC_CHECK_TYPES(sighandler_t)
dnl Solaris 8 has [u]intmax_t but not strtoumax(). How utterly braindamaged.
AC_CHECK_FUNCS(strtoumax)
AC_CHECK_FUNCS(strtoull)
AC_CHECK_MEMBERS(struct msghdr.msg_control)
AC_CHECK_MEMBERS(struct in_pktinfo.ipi_addr)
AC_CHECK_MEMBERS(struct addrinfo.ai_addr)
AC_CHECK_DECLS([O_NONBLOCK, O_BINARY, O_TEXT])
AC_CHECK_DECLS([F_SETLK])
AC_CHECK_DECLS([LOCK_SH, LOCK_EX])
PA_SIGSETJMP
dnl
dnl Get common paths
dnl
SRCROOT=`cd $srcdir && pwd`
OBJROOT=`pwd`
PA_SEARCH_LIBS_AND_ADD(xmalloc, iberty)
PA_SEARCH_LIBS_AND_ADD(xstrdup, iberty)
PA_SEARCH_LIBS_AND_ADD(getopt_long, getopt, getopt_long)
PA_SEARCH_LIBS_AND_ADD(getaddrinfo, [nsl resolv])
AS_IF([$pa_add_getaddrinfo],
[AC_SEARCH_LIBS(gethostbyname, [nsl resolv],
[AC_SEARCH_LIBS(herror, [nsl resolv], ,
[AC_MSG_ERROR(herror not found)])],
[AC_MSG_ERROR(gethostbyname not found)])],
[AC_SEARCH_LIBS(freeaddrinfo, [nsl resolv], ,
[AC_MSG_ERROR(getaddrinfo but not freeaddrinfo found)])
AC_SEARCH_LIBS(gai_strerror, [nsl resolv], ,
[AC_MSG_ERROR(getaddrinfo but not gai_strerror found)])])
PA_SEARCH_LIBS_AND_ADD(inet_ntop, [nsl resolv])
AS_IF([$pa_add_inet_ntop],
[AC_SEARCH_LIBS(inet_ntoa, [nsl resolv], ,
[AC_MSG_ERROR(inet_ntoa not found)])])
AC_SEARCH_LIBS(inet_aton, [nsl resolv], ,[AC_MSG_ERROR(inet_aton not found)])
PA_SEARCH_LIBS_AND_ADD(daemon)
PA_SEARCH_LIBS_AND_ADD(dup2)
AS_IF([$XTRA], [XTRALIBS="$OBJROOT/lib/libxtra.a $XTRALIBS"])
dnl
dnl These libraries apply to the server only
dnl
common_libs="$LIBS"
AC_CHECK_DECLS(IPPORT_TFTP)
PA_ARG_DISABLED([tcpwrappers],
[disable tcpwrapper permissions checking], [],
[
AC_SEARCH_LIBS(yp_get_default_domain, [nsl resolv])
PA_HAVE_TCPWRAPPERS
])
AC_CHECK_HEADERS_ONCE([regex.h])
PA_ARG_DISABLED([remap],
[disable regex-based filename remapping], [],
[AS_IF([test x"$ac_cv_header_regex_h" = xyes],
[AC_SEARCH_LIBS(regcomp, [regex rx],
[AC_DEFINE([WITH_REGEX], 1,
[Define if we are compiling with regex filename remapping.])
TFTPDOBJS="remap.\$(O) $TFTPOBJS"])])])
TFTPD_LIBS="$LIBS $XTRALIBS"
LIBS="$common_libs"
dnl
dnl These libraries apply to the client only
dnl
AH_TEMPLATE([WITH_READLINE],
[Define if we are compiling with readline/editline command-line editing.])
PA_ARG_DISABLED([readline],
[disable the use of readline command-line editing], [],
[
AC_CHECK_HEADER([readline/readline.h],
[
dnl readline may need libtermcap or somesuch...
AC_SEARCH_LIBS(tputs, [termcap terminfo])
AC_SEARCH_LIBS(readline, [readline history],
[AC_DEFINE(WITH_READLINE)])
AC_CHECK_HEADERS(readline/history.h)
],
[AC_CHECK_HEADER([editline/readline.h],
[
dnl editline may need libtermcap or somesuch...
AC_SEARCH_LIBS(tputs, [termcap terminfo])
AC_SEARCH_LIBS(editline, [edit],
[AC_DEFINE(WITH_READLINE)])
])])
],:)
TFTP_LIBS="$LIBS $XTRALIBS"
LIBS="$common_libs"
dnl
dnl Check for IPV6 and disable-ipv6
dnl
AC_CHECK_MEMBERS(struct sockaddr_in6.sin6_addr)
AC_MSG_CHECKING([for IPv6 support])
PA_ARG_DISABLED([ipv6],
[disable support for IPv6],
[AC_MSG_RESULT(disabled)],
[AS_IF([test x"$ac_cv_member_struct_sockaddr_in6_sin6_addr$ac_cv_member_struct_addrinfo_ai_addr" = xyesyes],
[AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_IPV6, 1, [define if IPv6 support is enabled])],
[AC_MSG_RESULT(no)
AC_MSG_WARN([*** we do not have required IPv6 structs - IPv6 will be disabled])])])
AC_SUBST(SRCROOT)
AC_SUBST(OBJROOT)
AC_SUBST(TFTP_LIBS)
AC_SUBST(TFTPD_LIBS)
AC_SUBST(TFTPDOBJS)
AC_PROG_LN_S
AC_PROG_RANLIB
dnl
dnl Make sure the install program has an absolute path if it
dnl has a path at all. autoconf doesn't do this "in order
dnl to not pollute the cache." Sigh.
dnl Note: the $ needs to be double-quoted for reasons unknown.
dnl
AC_PROG_INSTALL
[if echo "$INSTALL" | grep '^[^/].*/' > /dev/null 2>&1; then
INSTALL='\${SRCROOT}'/"$INSTALL"
fi]
PA_ADD_CFLAGS(-W)
PA_ADD_CFLAGS(-Wall)
PA_ADD_CFLAGS(-Wpointer-arith)
PA_ADD_CFLAGS(-Wbad-function-cast)
PA_ADD_CFLAGS(-Wcast-equal)
PA_ADD_CFLAGS(-Wstrict-prototypes)
PA_ADD_CFLAGS(-Wmissing-prototypes)
PA_ADD_CFLAGS(-Wmissing-declarations)
PA_ADD_CFLAGS(-Wnested-externs)
PA_ADD_CFLAGS(-Winline)
PA_ADD_CFLAGS(-Wwrite-strings)
PA_ADD_CFLAGS(-Wundef)
PA_ADD_CFLAGS(-Wshadow)
PA_ADD_CFLAGS(-Wsign-compare)
PA_ADD_CFLAGS(-fno-strict-aliasing)
dnl
dnl Test compiler features. On some compilers, this can be affected
dnl by -Werror options, so run this *after* those options are added.
dnl
PA_CHECK_BAD_STDC_INLINE
PA_C_TYPEOF
AC_CONFIG_HEADERS([config/config.h])
AC_CONFIG_FILES([config/MCONFIG])
AC_OUTPUT

303
configure.in Normal file
View file

@ -0,0 +1,303 @@
dnl
dnl autoconf input file to generate MCONFIG
dnl
AC_PREREQ(2.61)
AC_INIT(MCONFIG.in)
AC_PREFIX_DEFAULT(/usr)
AC_USE_SYSTEM_EXTENSIONS
AC_ISC_POSIX
AC_PROG_CC
AC_C_CONST
AC_C_INLINE
PA_ADD_CFLAGS(-W)
PA_ADD_CFLAGS(-Wall)
PA_ADD_CFLAGS(-Wpointer-arith)
PA_ADD_CFLAGS(-Wbad-function-cast)
PA_ADD_CFLAGS(-Wcast-equal)
PA_ADD_CFLAGS(-Wstrict-prototypes)
PA_ADD_CFLAGS(-Wmissing-prototypes)
PA_ADD_CFLAGS(-Wmissing-declarations)
PA_ADD_CFLAGS(-Wnested-externs)
PA_ADD_CFLAGS(-Winline)
PA_ADD_CFLAGS(-Wwrite-strings)
PA_ADD_CFLAGS(-Wundef)
PA_ADD_CFLAGS(-Wshadow)
PA_ADD_CFLAGS(-Wsign-compare)
PA_ADD_CFLAGS(-pipe)
PA_ADD_CFLAGS(-fno-strict-aliasing)
AC_HEADER_STDC
AC_CHECK_HEADERS(inttypes.h)
AC_CHECK_HEADERS(stdint.h)
PA_CHECK_INTTYPES_H_SANE
AC_CHECK_HEADERS(fcntl.h)
AC_CHECK_HEADERS(grp.h)
AC_CHECK_HEADERS(libgen.h)
AC_CHECK_HEADERS(memory.h)
AC_CHECK_HEADERS(setjmp.h)
AC_CHECK_HEADERS(stddef.h)
AC_CHECK_HEADERS(stdlib.h)
AC_CHECK_HEADERS(string.h)
AC_CHECK_HEADERS(strings.h)
AC_CHECK_HEADERS(sysexits.h)
AC_CHECK_HEADERS(time.h)
AC_CHECK_HEADERS(unistd.h)
AC_CHECK_HEADERS(sys/file.h)
AC_CHECK_HEADERS(sys/filio.h)
AC_CHECK_HEADERS(sys/stat.h)
AC_CHECK_HEADERS(sys/time.h)
AC_CHECK_HEADERS(sys/types.h)
AC_CHECK_HEADERS(arpa/inet.h)
AC_CHECK_HEADERS(netdb.h)
AC_HEADER_TIME
dnl This is needed on some versions of FreeBSD...
AC_CHECK_HEADERS(machine/param.h)
AC_CHECK_HEADERS(sys/socket.h)
AC_CHECK_HEADERS(winsock2.h)
AC_CHECK_HEADERS(winsock.h)
AC_SYS_LARGEFILE
AC_TYPE_OFF_T
AC_TYPE_PID_T
AC_TYPE_MODE_T
AC_TYPE_SIZE_T
AC_CHECK_TYPES(intmax_t)
AC_CHECK_TYPES(long long)
AC_CHECK_TYPES(uint16_t)
AC_CHECK_TYPES(uint32_t)
AC_CHECK_TYPES(u_short)
AC_CHECK_TYPES(u_long)
dnl
dnl <sys/socket.h> isn't among the list of standard headers that autoconf checks,
dnl but POSIX requires <sys/socket.h> for socklen_t to be defined.
dnl
AC_CHECK_TYPES(socklen_t,,,
[
#include <stdio.h>
#if HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#if HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#if STDC_HEADERS
# include <stdlib.h>
# include <stddef.h>
#else
# if HAVE_STDLIB_H
# include <stdlib.h>
# endif
#endif
#if HAVE_STRING_H
# if !STDC_HEADERS && HAVE_MEMORY_H
# include <memory.h>
# endif
# include <string.h>
#endif
#if HAVE_STRINGS_H
# include <strings.h>
#endif
#if HAVE_INTTYPES_H
# include <inttypes.h>
#else
# if HAVE_STDINT_H
# include <stdint.h>
# endif
#endif
#if HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
])
AC_SEARCH_LIBS(socket, [socket ws2_32 wsock32], , [AC_MSG_ERROR(socket library not found)])
AC_CHECK_FUNCS(fcntl)
AC_CHECK_FUNCS(setsid)
AC_CHECK_FUNCS(recvmsg)
AC_CHECK_FUNCS(ftruncate)
AC_CHECK_FUNCS(setreuid)
AC_CHECK_FUNCS(setregid)
AC_CHECK_FUNCS(initgroups)
AC_CHECK_FUNCS(setgroups)
dnl Solaris 8 has [u]intmax_t but not strtoumax(). How utterly braindamaged.
AC_CHECK_FUNCS(strtoumax)
AC_CHECK_FUNCS(strtoull)
PA_MSGHDR_MSG_CONTROL
PA_STRUCT_IN_PKTINFO
PA_STRUCT_ADDRINFO
PA_HEADER_DEFINES(fcntl.h, int, O_NONBLOCK)
PA_HEADER_DEFINES(fcntl.h, int, O_BINARY)
PA_HEADER_DEFINES(fcntl.h, int, O_TEXT)
PA_HEADER_DEFINES(fcntl.h, int, F_SETLK)
PA_HEADER_DEFINES(sys/file.h, int, LOCK_SH)
PA_HEADER_DEFINES(sys/file.h, int, LOCK_EX)
AH_TEMPLATE([HAVE_SIGSETJMP],
[Define if we have sigsetjmp, siglongjmp and sigjmp_buf.])
PA_SIGSETJMP([AC_DEFINE(HAVE_SIGSETJMP)])
dnl
dnl Get common paths
dnl
SRCROOT=`cd $srcdir && pwd`
OBJROOT=`pwd`
XTRA=false
PA_SEARCH_LIBS_AND_ADD(xmalloc, iberty)
PA_SEARCH_LIBS_AND_ADD(xstrdup, iberty)
PA_SEARCH_LIBS_AND_ADD(bsd_signal, bsd, bsdsignal)
PA_SEARCH_LIBS_AND_ADD(getopt_long, getopt, getopt_long)
PA_SEARCH_LIBS_AND_ADD(getaddrinfo, [nsl resolv])
if $pa_add_getaddrinfo
then
AC_SEARCH_LIBS(gethostbyname, [nsl resolv],
[AC_SEARCH_LIBS(herror, [nsl resolv], ,
[AC_MSG_ERROR(herror not found)])],
[AC_MSG_ERROR(gethostbyname not found)])
else
AC_SEARCH_LIBS(freeaddrinfo, [nsl resolv], ,
[AC_MSG_ERROR(getaddrinfo but not freeaddrinfo found)])
AC_SEARCH_LIBS(gai_strerror, [nsl resolv], ,
[AC_MSG_ERROR(getaddrinfo but not gai_strerror found)])
fi
PA_SEARCH_LIBS_AND_ADD(inet_ntop, [nsl resolv])
if $pa_add_inet_ntop
then
AC_SEARCH_LIBS(inet_ntoa, [nsl resolv], ,
[AC_MSG_ERROR(inet_ntoa not found)])
fi
AC_SEARCH_LIBS(inet_aton, [nsl resolv], ,[AC_MSG_ERROR(inet_aton not found)])
AC_CHECK_FUNCS(daemon, , [XTRA=true; AC_LIBOBJ(daemon)])
AC_CHECK_FUNCS(dup2, , [XTRA=true; AC_LIBOBJ(dup2)])
if $XTRA
then
XTRALIBS="$OBJROOT/lib/libxtra.a $XTRALIBS"
fi
dnl
dnl These libraries apply to the server only
dnl
common_libs="$LIBS"
PA_HEADER_DEFINES(netinet/in.h, int, IPPORT_TFTP)
PA_WITH_BOOL(tcpwrappers, 1,
[ --without-tcpwrappers disable tcpwrapper permissions checking],
[
AC_SEARCH_LIBS(yp_get_default_domain, [nsl resolv])
PA_HAVE_TCPWRAPPERS
],:)
AH_TEMPLATE([WITH_REGEX],
[Define if we are compiling with regex filename remapping.])
PA_WITH_BOOL(remap, 1,
[ --without-remap disable regex-based filename remapping],
[
AC_CHECK_HEADER(regex.h,
[
AC_SEARCH_LIBS(regcomp, [regex rx],
[
AC_DEFINE(WITH_REGEX)
TFTPDOBJS="remap.${OBJEXT} $TFTPDOBJS"
])
])
],:)
TFTPD_LIBS="$LIBS $XTRALIBS"
LIBS="$common_libs"
dnl
dnl These libraries apply to the client only
dnl
AH_TEMPLATE([WITH_READLINE],
[Define if we are compiling with readline/editline command-line editing.])
PA_WITH_BOOL(readline, 1,
[ --without-readline disable the use of readline command-line editing],
[
AC_CHECK_HEADER(readline/readline.h,
[
dnl readline may need libtermcap or somesuch...
AC_SEARCH_LIBS(tputs, [termcap terminfo])
AC_SEARCH_LIBS(readline, [readline history],
[AC_DEFINE(WITH_READLINE)])
AC_CHECK_HEADERS(readline/history.h)
],
[AC_CHECK_HEADER(editline/readline.h,
[
dnl editline may need libtermcap or somesuch...
AC_SEARCH_LIBS(tputs, [termcap terminfo])
AC_SEARCH_LIBS(editline, [edit],
[AC_DEFINE(WITH_READLINE)])
])])
],:)
TFTP_LIBS="$LIBS $XTRALIBS"
LIBS="$common_libs"
dnl
dnl Check for IPV6 and disable-ipv6
dnl
PA_STRUCT_SOCKADDR_IN6
AC_MSG_CHECKING([for IPv6 support])
PA_WITH_BOOL(ipv6, 1,
[ --without-ipv6 disable the support for IPv6],
[
if $HAVE_INET6
then
AC_MSG_RESULT(yes)
AC_DEFINE(HAVE_IPV6, 1, [Define if IPv6 support is enabled.])
PA_STRUCT_IN6_PKTINFO
else
AC_MSG_RESULT(no)
AC_MSG_WARN([*** we do not have required IPv6 structs - IPv6 will be disabled])
fi
],
[AC_MSG_RESULT(disabled)])
AC_SUBST(SRCROOT)
AC_SUBST(OBJROOT)
AC_SUBST(TFTP_LIBS)
AC_SUBST(TFTPD_LIBS)
AC_SUBST(TFTPDOBJS)
AC_PROG_LN_S
AC_PROG_RANLIB
dnl
dnl Make sure the install program has an absolute path if it
dnl has a path at all. autoconf doesn't do this "in order
dnl to not pollute the cache." Sigh.
dnl Note: the $ needs to be double-quoted for reasons unknown.
dnl
AC_PROG_INSTALL
[if echo "$INSTALL" | grep '^[^/].*/' > /dev/null 2>&1; then
INSTALL='\${SRCROOT}'/"$INSTALL"
fi]
AC_CONFIG_HEADERS(aconfig.h)
AC_OUTPUT(MCONFIG)

View file

@ -4,7 +4,7 @@
SRCROOT = ..
-include ../config/MCONFIG
-include ../MCONFIG
include ../MRULES
ifeq ($(LIBOBJS),)
@ -25,3 +25,5 @@ libxtra.a: $(LIBOBJS)
-rm -f libxtra.a
$(AR) libxtra.a $(LIBOBJS)
$(RANLIB) libxtra.a

27
lib/bsdsignal.c Normal file
View file

@ -0,0 +1,27 @@
/*
* bsdsignal.c
*
* Use sigaction() to simulate BSD signal()
*/
#include "config.h"
void (*bsd_signal(int signum, void (*handler) (int))) (int) {
struct sigaction action, oldaction;
memset(&action, 0, sizeof action);
action.sa_handler = handler;
sigemptyset(&action.sa_mask);
sigaddset(&action.sa_mask, signum);
action.sa_flags = SA_RESTART;
if (sigaction(signum, &action, &oldaction) == -1) {
#ifdef SIG_ERR
return SIG_ERR;
#else
return NULL;
#endif
}
return oldaction.sa_handler;
}

View file

@ -1,7 +1,7 @@
SRCROOT = ..
VERSION = $(shell cat ../version)
-include ../config/MCONFIG
-include ../MCONFIG
include ../MRULES
OBJS = tftp.$(O) main.$(O)

View file

@ -31,13 +31,10 @@
* SUCH DAMAGE.
*/
#ifndef EXTERN_H
#define EXTERN_H
#include "config.h"
#ifndef RECVFILE_H
#define RECVFILE_H
void tftp_recvfile(int, const char *, const char *);
void tftp_sendfile(int, const char *, const char *);
extern sigjmp_buf toplevel;
#endif

View file

@ -188,7 +188,7 @@ char *xstrdup(const char *);
const char *program;
static void usage(int errcode)
static inline void usage(int errcode)
{
fprintf(stderr,
#ifdef HAVE_IPV6
@ -305,7 +305,7 @@ int main(int argc, char *argv[])
sp->s_proto = (char *)"udp";
}
tftp_signal(SIGINT, intr, 0);
bsd_signal(SIGINT, intr);
if (peerargc) {
/* Set peer */
@ -768,8 +768,8 @@ void intr(int sig)
{
(void)sig; /* Quiet unused warning */
bsd_signal(SIGALRM, SIG_IGN);
alarm(0);
tftp_signal(SIGALRM, SIG_DFL, 0);
siglongjmp(toplevel, -1);
}

View file

@ -48,7 +48,8 @@ extern int maxtimeout;
#define PKTSIZE SEGSIZE+4
char ackbuf[PKTSIZE];
int timeout;
static sigjmp_buf timeoutbuf;
sigjmp_buf toplevel;
sigjmp_buf timeoutbuf;
static void nak(int, const char *);
static int makerequest(int, const char *, struct tftphdr *, const char *);
@ -84,7 +85,7 @@ void tftp_sendfile(int fd, const char *name, const char *mode)
is_request = 1; /* First packet is the actual WRQ */
amount = 0;
tftp_signal(SIGALRM, timer, 0);
bsd_signal(SIGALRM, timer);
do {
if (is_request) {
size = makerequest(WRQ, name, dp, mode) - 4;
@ -190,7 +191,7 @@ void tftp_recvfile(int fd, const char *name, const char *mode)
firsttrip = 1;
amount = 0;
tftp_signal(SIGALRM, timer, 0);
bsd_signal(SIGALRM, timer);
do {
if (firsttrip) {
size = makerequest(RRQ, name, ap, mode);

View file

@ -1,7 +1,7 @@
SRCROOT = ..
VERSION = $(shell cat ../version)
-include ../config/MCONFIG
-include ../MCONFIG
include ../MRULES
OBJS = tftpd.$(O) recvfrom.$(O) misc.$(O) $(TFTPDOBJS)

View file

@ -19,11 +19,19 @@
#include "tftpd.h"
/*
* Set the signal handler and flags, and error out on failure.
* Set the signal handler and flags. Basically a user-friendly
* wrapper around sigaction().
*/
void set_signal(int signum, sighandler_t handler, int flags)
void set_signal(int signum, void (*handler) (int), int flags)
{
if (tftp_signal(signum, handler, flags)) {
struct sigaction sa;
memset(&sa, 0, sizeof sa);
sa.sa_handler = handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = flags;
if (sigaction(signum, &sa, NULL)) {
syslog(LOG_ERR, "sigaction: %m");
exit(EX_OSERR);
}

View file

@ -26,12 +26,10 @@
#if defined(HAVE_RECVMSG) && defined(HAVE_MSGHDR_MSG_CONTROL)
#ifdef HAVE_SYS_UIO_H
# include <sys/uio.h>
#endif
#include <sys/uio.h>
#ifdef IP_PKTINFO
# ifndef HAVE_STRUCT_IN_PKTINFO_IPI_ADDR
# ifndef HAVE_STRUCT_IN_PKTINFO
# ifdef __linux__
/* Assume this version of glibc simply lacks the definition */
struct in_pktinfo {
@ -53,59 +51,52 @@ struct in_pktinfo {
#endif
/*
* Check to see if this is a valid local address, meaning that we can
* legally bind to it.
* Check to see if this is a valid local address. If so, we should
* end up having the same local and remote address when trying to
* bind to it.
*/
static int address_is_local(const union sock_addr *addr)
{
union sock_addr sa1, sa2;
union sock_addr sa;
int sockfd = -1;
int e;
int rv = 0;
socklen_t addrlen;
memcpy(&sa1, addr, sizeof sa1);
/* Multicast or universal broadcast address? */
if (sa1.sa.sa_family == AF_INET) {
if (ntohl(sa1.si.sin_addr.s_addr) >= (224UL << 24))
if (addr->sa.sa_family == AF_INET) {
if (ntohl(addr->si.sin_addr.s_addr) >= (224UL << 24))
return 0;
sa1.si.sin_port = 0; /* Any port */
}
#ifdef HAVE_IPV6
else if (sa1.sa.sa_family == AF_INET6) {
if (IN6_IS_ADDR_MULTICAST(&sa1.s6.sin6_addr))
else if (addr->sa.sa_family == AF_INET6) {
if (IN6_IS_ADDR_MULTICAST(&addr->s6.sin6_addr))
return 0;
sa1.s6.sin6_port = 0; /* Any port */
}
#endif
else
return 0;
sockfd = socket(sa1.sa.sa_family, SOCK_DGRAM, 0);
sockfd = socket(addr->sa.sa_family, SOCK_DGRAM, 0);
if (sockfd < 0)
goto err;
if (bind(sockfd, &sa1.sa, SOCKLEN(&sa1)))
if (connect(sockfd, &addr->sa, SOCKLEN(addr)))
goto err;
addrlen = SOCKLEN(addr);
if (getsockname(sockfd, (struct sockaddr *)&sa2, &addrlen))
if (getsockname(sockfd, (struct sockaddr *)&sa, &addrlen))
goto err;
if (sa1.sa.sa_family != sa2.sa.sa_family)
goto err;
if (sa2.sa.sa_family == AF_INET)
rv = sa1.si.sin_addr.s_addr == sa2.si.sin_addr.s_addr;
if (addr->sa.sa_family == AF_INET)
rv = sa.si.sin_addr.s_addr == addr->si.sin_addr.s_addr;
#ifdef HAVE_IPV6
else if (sa2.sa.sa_family == AF_INET6)
rv = IN6_ARE_ADDR_EQUAL(&sa1.s6.sin6_addr, &sa2.s6.sin6_addr);
else if (addr->sa.sa_family == AF_INET6)
rv = IN6_ARE_ADDR_EQUAL(&sa.s6.sin6_addr, &addr->s6.sin6_addr);
#endif
else
rv = 0;
err:
err:
e = errno;
if (sockfd >= 0)
@ -115,31 +106,10 @@ err:
return rv;
}
static void normalize_ip6_compat(union sock_addr *myaddr)
{
#ifdef HAVE_IPV6
static const uint8_t ip6_compat_prefix[12] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff };
struct sockaddr_in in;
if (myaddr->sa.sa_family == AF_INET6 &&
!memcmp(&myaddr->s6.sin6_addr, ip6_compat_prefix,
sizeof ip6_compat_prefix)) {
bzero(&in, sizeof in);
in.sin_family = AF_INET;
in.sin_port = myaddr->s6.sin6_port;
memcpy(&in.sin_addr, (const char *)&myaddr->s6.sin6_addr +
sizeof ip6_compat_prefix, sizeof in.sin_addr);
memcpy(&myaddr->si, &in, sizeof in);
}
#else
(void)myaddr;
#endif
}
int
myrecvfrom(int s, void *buf, int len, unsigned int flags,
union sock_addr *from, union sock_addr *myaddr)
struct sockaddr *from, socklen_t * fromlen,
union sock_addr *myaddr)
{
struct msghdr msg;
struct iovec iov;
@ -172,16 +142,16 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
/* Try to enable getting the return address */
#ifdef IP_RECVDSTADDR
if (from->sa.sa_family == AF_INET)
if (from->sa_family == AF_INET)
setsockopt(s, IPPROTO_IP, IP_RECVDSTADDR, &on, sizeof(on));
#endif
#ifdef IP_PKTINFO
if (from->sa.sa_family == AF_INET)
if (from->sa_family == AF_INET)
setsockopt(s, IPPROTO_IP, IP_PKTINFO, &on, sizeof(on));
#endif
#ifdef HAVE_IPV6
#ifdef IPV6_RECVPKTINFO
if (from->sa.sa_family == AF_INET6)
if (from->sa_family == AF_INET6)
setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on));
#endif
#endif
@ -190,8 +160,8 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
msg.msg_controllen = sizeof(control_un);
msg.msg_flags = 0;
msg.msg_name = &from->sa;
msg.msg_namelen = sizeof(*from);
msg.msg_name = from;
msg.msg_namelen = *fromlen;
iov.iov_base = buf;
iov.iov_len = len;
msg.msg_iov = &iov;
@ -200,9 +170,11 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
if ((n = recvmsg(s, &msg, flags)) < 0)
return n; /* Error */
*fromlen = msg.msg_namelen;
if (myaddr) {
bzero(myaddr, sizeof(*myaddr));
myaddr->sa.sa_family = from->sa.sa_family;
myaddr->sa.sa_family = from->sa_family;
if (msg.msg_controllen < sizeof(struct cmsghdr) ||
(msg.msg_flags & MSG_CTRUNC))
@ -211,7 +183,7 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL;
cmptr = CMSG_NXTHDR(&msg, cmptr)) {
if (from->sa.sa_family == AF_INET) {
if (from->sa_family == AF_INET) {
myaddr->sa.sa_family = AF_INET;
#ifdef IP_RECVDSTADDR
if (cmptr->cmsg_level == IPPROTO_IP &&
@ -232,7 +204,7 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
#endif
}
#ifdef HAVE_IPV6
else if (from->sa.sa_family == AF_INET6) {
else if (from->sa_family == AF_INET6) {
myaddr->sa.sa_family = AF_INET6;
#ifdef IP6_RECVDSTADDR
if (cmptr->cmsg_level == IPPROTO_IPV6 &&
@ -243,23 +215,17 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
#ifdef HAVE_STRUCT_IN6_PKTINFO
if (cmptr->cmsg_level == IPPROTO_IPV6 &&
(
#ifdef IPV6_RECVPKTINFO
cmptr->cmsg_type == IPV6_RECVPKTINFO ||
#endif
(cmptr->cmsg_type == IPV6_RECVPKTINFO ||
cmptr->cmsg_type == IPV6_PKTINFO)) {
memcpy(&pktinfo6, CMSG_DATA(cmptr),
sizeof(struct in6_pktinfo));
memcpy(&myaddr->s6.sin6_addr, &pktinfo6.ipi6_addr,
sizeof(struct in6_addr));
memcpy(&pktinfo6, CMSG_DATA(cmptr),
sizeof(struct in6_pktinfo));
memcpy(&myaddr->s6.sin6_addr, &pktinfo6.ipi6_addr,
sizeof(struct in6_addr));
}
#endif
}
#endif
}
normalize_ip6_compat(myaddr);
/* If the address is not a valid local address,
* then bind to any address...
*/
@ -272,9 +238,6 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
#endif
}
}
normalize_ip6_compat(from);
return n;
}
@ -282,16 +245,16 @@ myrecvfrom(int s, void *buf, int len, unsigned int flags,
int
myrecvfrom(int s, void *buf, int len, unsigned int flags,
union sock_addr *from, union sock_addr *myaddr)
struct sockaddr *from, socklen_t * fromlen,
union sock_addr *myaddr)
{
/* There is no way we can get the local address, fudge it */
socklen_t fromlen = sizeof(*from);
bzero(myaddr, sizeof(*myaddr));
myaddr->sa.sa_family = from->sa.sa_family;
myaddr->sa.sa_family = from->sa_family;
sa_set_port(myaddr, htons(IPPORT_TFTP));
return recvfrom(s, buf, len, flags, &from->sa, &fromlen);
return recvfrom(s, buf, len, flags, from, fromlen);
}
#endif

View file

@ -19,4 +19,5 @@
int
myrecvfrom(int s, void *buf, int len, unsigned int flags,
union sock_addr *from, union sock_addr *myaddr);
struct sockaddr *from, socklen_t *fromlen,
union sock_addr *myaddr);

View file

@ -1,6 +1,6 @@
/* ----------------------------------------------------------------------- *
*
* Copyright 2001-2024 H. Peter Anvin - All Rights Reserved
* Copyright 2001-2007 H. Peter Anvin - All Rights Reserved
*
* This program is free software available under the same license
* as the "OpenBSD" operating system, distributed at
@ -22,7 +22,7 @@
#include "tftpd.h"
#include "remap.h"
#define DEADMAN_MAX_STEPS 4096 /* Timeout after this many steps */
#define DEADMAN_MAX_STEPS 1024 /* Timeout after this many steps */
#define MAXLINE 16384 /* Truncate a line at this many bytes */
#define RULE_REWRITE 0x01 /* This is a rewrite rule */
@ -31,20 +31,12 @@
#define RULE_RESTART 0x08 /* Restart at the top after matching this rule */
#define RULE_ABORT 0x10 /* Terminate processing with an error */
#define RULE_INVERSE 0x20 /* Execute if regex *doesn't* match */
#define RULE_IPV4 0x40 /* IPv4 only */
#define RULE_IPV6 0x80 /* IPv6 only */
#define RULE_HASFILE 0x100 /* Valid if rule results in a valid filename */
#define RULE_RRQ 0x200 /* Get (read) only */
#define RULE_WRQ 0x400 /* Put (write) only */
#define RULE_SEDG 0x800 /* sed-style global */
int deadman_max_steps = DEADMAN_MAX_STEPS;
struct rule {
struct rule *next;
int nrule;
unsigned int rule_flags;
int rule_flags;
char rule_mode;
regex_t rx;
const char *pattern;
};
@ -64,30 +56,22 @@ static int xform_tolower(int c)
return tolower(c);
}
/*
* Do \-substitution. Call with string == NULL to get length only.
* "start" indicates an offset into the input buffer where the pattern
* match was started.
*/
static int do_genmatchstring(char *string, const char *pattern,
const char *ibuf,
const regmatch_t * pmatch,
match_pattern_callback macrosub,
int start, int *nextp)
/* Do \-substitution. Call with string == NULL to get length only. */
static int genmatchstring(char *string, const char *pattern,
const char *input, const regmatch_t * pmatch,
match_pattern_callback macrosub)
{
int (*xform) (int) = xform_null;
int len = 0;
int n, mlen, sublen;
int endbytes;
const char *input = ibuf + start;
/* Get section before match; note pmatch[0] is the whole match */
endbytes = strlen(input) - pmatch[0].rm_eo;
len = start + pmatch[0].rm_so;
len = pmatch[0].rm_so + endbytes;
if (string) {
/* Copy the prefix before "start" as well! */
memcpy(string, ibuf, start + pmatch[0].rm_so);
string += start + pmatch[0].rm_so;
memcpy(string, input, pmatch[0].rm_so);
string += pmatch[0].rm_so;
}
/* Transform matched section */
@ -113,7 +97,7 @@ static int do_genmatchstring(char *string, const char *pattern,
mlen = pmatch[n].rm_eo - pmatch[n].rm_so;
len += mlen;
if (string) {
const char *p = input + start + pmatch[n].rm_so;
const char *p = input + pmatch[n].rm_so;
while (mlen--)
*string++ = xform(*p++);
}
@ -156,12 +140,7 @@ static int do_genmatchstring(char *string, const char *pattern,
}
}
/* Pointer to post-substitution tail */
if (nextp)
*nextp = len;
/* Copy section after match */
len += endbytes;
if (string) {
memcpy(string, input + pmatch[0].rm_eo, endbytes);
string[endbytes] = '\0';
@ -170,26 +149,6 @@ static int do_genmatchstring(char *string, const char *pattern,
return len;
}
/*
* Ditto, but allocate the string in a new buffer
*/
static int genmatchstring(char **string, const char *pattern,
const char *ibuf,
const regmatch_t * pmatch,
match_pattern_callback macrosub,
int start, int *nextp)
{
int len;
char *buf;
len = do_genmatchstring(NULL, pattern, ibuf, pmatch,
macrosub, start, NULL);
*string = buf = tfmalloc(len + 1);
return do_genmatchstring(buf, pattern, ibuf, pmatch,
macrosub, start, nextp);
}
/*
* Extract a string terminated by non-escaped whitespace; ignoring
* leading whitespace. Consider an unescaped # to be a comment marker,
@ -247,17 +206,11 @@ static int parseline(char *line, struct rule *r, int lineno)
r->rule_flags |= RULE_REWRITE;
break;
case 'g':
if (r->rule_flags & RULE_GLOBAL)
r->rule_flags |= RULE_SEDG;
else
r->rule_flags |= RULE_GLOBAL;
r->rule_flags |= RULE_GLOBAL;
break;
case 'e':
r->rule_flags |= RULE_EXIT;
break;
case 'E':
r->rule_flags |= RULE_HASFILE;
break;
case 's':
r->rule_flags |= RULE_RESTART;
break;
@ -270,17 +223,9 @@ static int parseline(char *line, struct rule *r, int lineno)
case '~':
r->rule_flags |= RULE_INVERSE;
break;
case '4':
r->rule_flags |= RULE_IPV4;
break;
case '6':
r->rule_flags |= RULE_IPV6;
break;
case 'G':
r->rule_flags |= RULE_RRQ;
break;
case 'P':
r->rule_flags |= RULE_WRQ;
case 'G':
case 'P':
r->rule_mode = *p;
break;
default:
syslog(LOG_ERR,
@ -291,21 +236,15 @@ static int parseline(char *line, struct rule *r, int lineno)
}
}
if (r->rule_flags & RULE_REWRITE) {
if (r->rule_flags & RULE_INVERSE) {
syslog(LOG_ERR, "r rules cannot be inverted, line %d: %s\n",
lineno, line);
return -1; /* Error */
}
if ((r->rule_flags & (RULE_GLOBAL|RULE_SEDG|RULE_HASFILE))
== (RULE_GLOBAL|RULE_HASFILE)) {
syslog(LOG_ERR, "E rules cannot be combined with g (but gg is OK), line %d: %s\n",
lineno, line);
return -1; /* Error */
}
} else {
/* RULE_GLOBAL and RULE_SEDG are meaningless without RULE_REWRITE */
r->rule_flags &= ~(RULE_GLOBAL|RULE_SEDG);
/* RULE_GLOBAL only applies when RULE_REWRITE specified */
if (!(r->rule_flags & RULE_REWRITE))
r->rule_flags &= ~RULE_GLOBAL;
if ((r->rule_flags & (RULE_INVERSE | RULE_REWRITE)) ==
(RULE_INVERSE | RULE_REWRITE)) {
syslog(LOG_ERR, "r rules cannot be inverted, line %d: %s\n",
lineno, line);
return -1; /* Error */
}
/* Read and compile the regex */
@ -386,24 +325,17 @@ void freerules(struct rule *r)
}
/* Execute a rule set on a string; returns a malloc'd new string. */
char *rewrite_string(const struct formats *pf,
const char *input, const struct rule *rules,
int mode, int af, match_pattern_callback macrosub,
char *rewrite_string(const char *input, const struct rule *rules,
char mode, match_pattern_callback macrosub,
const char **errmsg)
{
char *current = tfstrdup(input);
char *newstr, *newerstr;
const char *accerr;
char *newstr;
const struct rule *ruleptr = rules;
regmatch_t pmatch[10];
int i;
int len;
int was_match = 0;
int deadman = deadman_max_steps;
int matchsense;
int pmatches;
unsigned int bad_flags;
int ggoffset;
int deadman = DEADMAN_MAX_STEPS;
/* Default error */
*errmsg = "Remap table failure";
@ -412,121 +344,86 @@ char *rewrite_string(const struct formats *pf,
syslog(LOG_INFO, "remap: input: %s", current);
}
bad_flags = 0;
if (mode != RRQ) bad_flags |= RULE_RRQ;
if (mode != WRQ) bad_flags |= RULE_WRQ;
if (af != AF_INET) bad_flags |= RULE_IPV4;
if (af != AF_INET6) bad_flags |= RULE_IPV6;
for (ruleptr = rules; ruleptr; ruleptr = ruleptr->next) {
if (ruleptr->rule_flags & bad_flags)
continue; /* This rule is excluded by flags */
if (ruleptr->rule_mode && ruleptr->rule_mode != mode)
continue; /* Rule not applicable, try next */
matchsense = ruleptr->rule_flags & RULE_INVERSE ? REG_NOMATCH : 0;
pmatches = ruleptr->rule_flags & RULE_INVERSE ? 0 : 10;
/* Clear the pmatch[] array */
for (i = 0; i < 10; i++)
pmatch[i].rm_so = pmatch[i].rm_eo = -1;
was_match = 0;
if (!deadman--) {
syslog(LOG_WARNING,
"remap: Breaking loop, input = %s, last = %s", input,
current);
free(current);
return NULL; /* Did not terminate! */
}
do {
if (!deadman--)
goto dead;
if (regexec(&ruleptr->rx, current, 10, pmatch, 0) ==
(ruleptr->rule_flags & RULE_INVERSE ? REG_NOMATCH : 0)) {
/* Match on this rule */
was_match = 1;
if (regexec(&ruleptr->rx, current, pmatches, pmatch, 0)
!= matchsense)
break; /* No match, break out of do loop */
/* Match on this rule */
was_match = 1;
if (ruleptr->rule_flags & RULE_ABORT) {
if (verbosity >= 3) {
syslog(LOG_INFO, "remap: rule %d: abort: %s",
ruleptr->nrule, current);
}
if (ruleptr->pattern[0]) {
/* Custom error message */
genmatchstring(&newstr, ruleptr->pattern, current,
pmatch, macrosub, 0, NULL);
*errmsg = newstr;
} else {
*errmsg = NULL;
}
free(current);
return (NULL);
}
if (ruleptr->rule_flags & RULE_REWRITE) {
len = genmatchstring(&newstr, ruleptr->pattern, current,
pmatch, macrosub, 0, &ggoffset);
if (ruleptr->rule_flags & RULE_SEDG) {
/* sed-style partial-matching global */
while (ggoffset < len &&
regexec(&ruleptr->rx, newstr + ggoffset,
pmatches, pmatch,
ggoffset ? REG_NOTBOL : 0)
== matchsense) {
if (!deadman--) {
free(current);
current = newstr;
goto dead;
}
len = genmatchstring(&newerstr, ruleptr->pattern,
newstr, pmatch, macrosub,
ggoffset, &ggoffset);
free(newstr);
newstr = newerstr;
}
if (ruleptr->rule_flags & RULE_INVERSE) {
/* No actual match, so clear out the pmatch array */
int i;
for (i = 0; i < 10; i++)
pmatch[i].rm_so = pmatch[i].rm_eo = -1;
}
if ((ruleptr->rule_flags & RULE_HASFILE) &&
pf->f_validate(newstr, mode, pf, &accerr)) {
if (ruleptr->rule_flags & RULE_ABORT) {
if (verbosity >= 3) {
syslog(LOG_INFO, "remap: rule %d: ignored rewrite (%s): %s",
ruleptr->nrule, accerr, newstr);
syslog(LOG_INFO, "remap: rule %d: abort: %s",
ruleptr->nrule, current);
}
free(newstr);
was_match = 0;
break;
if (ruleptr->pattern[0]) {
/* Custom error message */
len =
genmatchstring(NULL, ruleptr->pattern, current,
pmatch, macrosub);
newstr = tfmalloc(len + 1);
genmatchstring(newstr, ruleptr->pattern, current,
pmatch, macrosub);
*errmsg = newstr;
} else {
*errmsg = NULL;
}
free(current);
return (NULL);
}
free(current);
current = newstr;
if (verbosity >= 3) {
syslog(LOG_INFO, "remap: rule %d: rewrite: %s",
ruleptr->nrule, current);
}
} else if (ruleptr->rule_flags & RULE_HASFILE) {
if (pf->f_validate(current, mode, pf, &accerr)) {
if (ruleptr->rule_flags & RULE_REWRITE) {
len = genmatchstring(NULL, ruleptr->pattern, current,
pmatch, macrosub);
newstr = tfmalloc(len + 1);
genmatchstring(newstr, ruleptr->pattern, current,
pmatch, macrosub);
free(current);
current = newstr;
if (verbosity >= 3) {
syslog(LOG_INFO, "remap: rule %d: not exiting (%s)\n",
ruleptr->nrule, accerr);
syslog(LOG_INFO, "remap: rule %d: rewrite: %s",
ruleptr->nrule, current);
}
was_match = 0;
break;
}
} else {
break; /* No match, terminate unconditionally */
}
/* If the rule is (old-style) global, keep going until no match */
} while ((ruleptr->rule_flags & (RULE_GLOBAL|RULE_SEDG)) == RULE_GLOBAL);
/* If the rule is global, keep going until no match */
} while (ruleptr->rule_flags & RULE_GLOBAL);
if (!was_match)
continue; /* Next rule */
if (was_match) {
was_match = 0;
if (ruleptr->rule_flags & (RULE_EXIT|RULE_HASFILE)) {
if (verbosity >= 3) {
syslog(LOG_INFO, "remap: rule %d: exit",
ruleptr->nrule);
}
return current; /* Exit here, we're done */
} else if (ruleptr->rule_flags & RULE_RESTART) {
ruleptr = rules; /* Start from the top */
if (verbosity >= 3) {
syslog(LOG_INFO, "remap: rule %d: restart",
ruleptr->nrule);
if (ruleptr->rule_flags & RULE_EXIT) {
if (verbosity >= 3) {
syslog(LOG_INFO, "remap: rule %d: exit",
ruleptr->nrule);
}
return current; /* Exit here, we're done */
} else if (ruleptr->rule_flags & RULE_RESTART) {
ruleptr = rules; /* Start from the top */
if (verbosity >= 3) {
syslog(LOG_INFO, "remap: rule %d: restart",
ruleptr->nrule);
}
}
}
}
@ -535,11 +432,4 @@ char *rewrite_string(const struct formats *pf,
syslog(LOG_INFO, "remap: done");
}
return current;
dead: /* Deadman expired */
syslog(LOG_ERR,
"remap: Breaking loop after %d steps, input = %s, last = %s",
deadman_max_steps, input, current);
free(current);
return NULL; /* Did not terminate! */
}

View file

@ -35,13 +35,8 @@ struct rule *parserulefile(FILE *);
void freerules(struct rule *);
/* Execute a rule set on a string; returns a malloc'd new string. */
struct formats;
char *rewrite_string(const struct formats *, const char *,
const struct rule *, int, int,
char *rewrite_string(const char *, const struct rule *, char,
match_pattern_callback, const char **);
/* Remapping deadman counter */
extern int deadman_max_steps;
#endif /* WITH_REGEX */
#endif /* TFTPD_REMAP_H */

View file

@ -1,5 +1,5 @@
.\" -*- nroff -*- --------------------------------------------------------- *
.\"
.\"
.\" Copyright (c) 1990, 1993, 1994
.\" The Regents of the University of California. All rights reserved.
.\"
@ -30,7 +30,7 @@
.\" SUCH DAMAGE.
.\"
.\"----------------------------------------------------------------------- */
.TH TFTPD 8 "7 June 2014" "tftp-hpa @@VERSION@@" "System Manager's Manual"
.TH TFTPD 8 "14 September 2009" "tftp-hpa @@VERSION@@" "System Manager's Manual"
.SH NAME
.B tftpd
\- Trivial File Transfer Protocol server
@ -155,7 +155,7 @@ or
.B utimeout
option is negotiated. The default is 1000000 (1 second.)
.TP
\fB\-\-map-file\fP \fIremap-file\fP, \fB\-m\fP \fIremap-file\fP
\fB\-\-mapfile\fP \fIremap-file\fP, \fB\-m\fP \fIremap-file\fP
Specify the use of filename remapping. The
.I remap-file
is a file containing the remapping rules. See the section on filename
@ -163,10 +163,6 @@ remapping below. This option may not be compiled in, see the output of
.B "in.tftpd \-V"
to verify whether or not it is available.
.TP
.\fB\-\-map-steps\fP \fIsteps\fP
Specify the number of remapping rules that may be executed before the
filename mapping fails. The default is 4096.
.TP
\fB\-\-verbose\fP, \fB\-v\fP
Increase the logging verbosity of
.BR tftpd .
@ -242,7 +238,7 @@ option, but crash with an error if they actually get the option
accepted by the server.
.SH "FILENAME REMAPPING"
The
.B \-\-map-file
.B \-\-mapfile
option specifies a file which contains filename remapping rules. Each
non-comment line (comments begin with hash marks,
.BR # )
@ -274,18 +270,7 @@ by the
The replacement pattern may contain escape sequences; see below.
.TP
.B g
Repeat this rule until it no longer matches. This is always used with
.BR r .
.TP
.B gg
Repeat this rule until it no longer matches, but only on the portion
of the string that has not yet been matched, similar to how the
.B s
command with the
.B g
option works in
.BR sed (1).
This is always used with
Repeat this rule until it no longer matches. This is always used with
.BR r .
.TP
.B i
@ -296,17 +281,6 @@ case-insensitively. By default it is case sensitive.
.B e
If this rule matches, end rule processing after executing the rule.
.TP
.B E
If this rule matches,
\fIand the result matches a filename that can be transferred\fP,
end rule processing after executing the rule. If this is combined with
.BR r ,
then if the substitution does \fInot\fP result in a valid filename,
the substitution is undone. This cannot be combined with
.BR g ,
but \fIcan\fP be combined with
.BR gg .
.TP
.B s
If this rule matches, start rule processing over from the very first
rule after executing this rule.
@ -321,22 +295,16 @@ This rule applies to GET (RRQ) requests only.
.B P
This rule applies to PUT (WRQ) requests only.
.TP
.B 4
This rule applies to IPv4 sessions only.
.TP
.B 6
This rule applies to IPv6 sessions only.
.TP
.B ~
Inverse the sense of this rule, i.e. execute the
.I operation
only if the
.I regex
.I doesn't
match. Cannot used together with
match. Cannot used together with
.BR r .
.PP
The following escape sequences are recognized as part of a
The following escape sequences are recognized as part of the
.IR "replacement pattern" :
.TP
\fB\\0\fP
@ -350,14 +318,12 @@ subexpressions, \\( ... \\), of the
pattern.
.TP
\fB\\i\fP
The IP address of the requesting host, in dotted-quad notation for
IPv4 (e.g. 192.0.2.169) or conventional colon form for IPv6
(e.g. 2001:db8::1).
The IP address of the requesting host, in dotted-quad notation
(e.g. 192.0.2.169).
.TP
\fB\\x\fP
The IP address of the requesting host, in expanded hexadecimal
notation (e.g. C00002A9 for IPv4, or 20010DB8000000000000000000000001
for IPv6).
The IP address of the requesting host, in hexadecimal notation
(e.g. C00002A9).
.TP
\fB\\\\\fP
Literal backslash.
@ -417,14 +383,14 @@ Access to files can, and should, be restricted by invoking
.B tftpd
with a list of directories by including pathnames as server program
arguments on the command line. In this case access is restricted to
files whose names are prefixed by one of the given directories. If
files whole names are prefixed by one of the given directories. If
possible, it is recommended that the
.B \-\-secure
flag is used to set up a chroot() environment for the server to run in
once a connection has been set up.
.PP
Finally, the filename remapping
.RB ( \-\-map-file
.RB ( \-\-mapfile
flag) support can be used to provide a limited amount of additional
access control.
.SH "CONFORMING TO"

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 1983 Regents of the University of California.
* Copyright (c) 1999-2009 H. Peter Anvin
* Copyright (c) 2011-2014 Intel Corporation; author: H. Peter Anvin
* Copyright (c) 2011 Intel Corporation; author: H. Peter Anvin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -76,7 +76,7 @@ static int ai_fam = AF_INET;
#define TRIES 6 /* Number of attempts to send each packet */
#define TIMEOUT_LIMIT ((1 << TRIES)-1)
const char *tftpd_progname;
const char *__progname;
static int peer;
static unsigned long timeout = TIMEOUT; /* Current timeout value */
static unsigned long rexmtval = TIMEOUT; /* Basic timeout value */
@ -93,6 +93,7 @@ static unsigned int max_blksize = MAX_SEGSIZE;
static char tmpbuf[INET6_ADDRSTRLEN], *tmp_p;
static union sock_addr from;
static socklen_t fromlen;
static off_t tsize;
static int tsize_ok;
@ -106,12 +107,11 @@ int portrange = 0;
unsigned int portrange_from, portrange_to;
int verbosity = 0;
struct formats;
#ifdef WITH_REGEX
static struct rule *rewrite_rules = NULL;
#endif
static FILE *file;
int tftp(struct tftphdr *, int);
static void nak(int, const char *);
static void timer(int);
@ -153,7 +153,7 @@ static void handle_exit(int sig)
}
/* Handle timeout signal or timeout event */
static void timer(int sig)
void timer(int sig)
{
(void)sig; /* Suppress unused warning */
timeout <<= 1;
@ -163,14 +163,14 @@ static void timer(int sig)
}
#ifdef WITH_REGEX
static struct rule *read_remap_rules(const char *rulefile)
static struct rule *read_remap_rules(const char *file)
{
FILE *f;
struct rule *rulep;
f = fopen(rulefile, "rt");
f = fopen(file, "rt");
if (!f) {
syslog(LOG_ERR, "Cannot open map file: %s: %m", rulefile);
syslog(LOG_ERR, "Cannot open map file: %s: %m", file);
exit(EX_NOINPUT);
}
rulep = parserulefile(f);
@ -185,8 +185,7 @@ static struct rule *read_remap_rules(const char *rulefile)
*/
static int lock_file(int fd, int lock_write)
{
(void)lock_write;
#if defined(HAVE_FCNTL) && HAVE_DECL_F_SETLK
#if defined(HAVE_FCNTL) && defined(HAVE_F_SETLK_DEFINITION)
struct flock fl;
fl.l_type = lock_write ? F_WRLCK : F_RDLCK;
@ -194,7 +193,7 @@ static int lock_file(int fd, int lock_write)
fl.l_start = 0;
fl.l_len = 0; /* Whole file */
return fcntl(fd, F_SETLK, &fl);
#elif defined(HAVE_FLOCK) && HAVE_DECL_LOCK_SH && HAVE_DECL_LOCK_EX
#elif defined(HAVE_LOCK_SH_DEFINITION)
return flock(fd, lock_write ? LOCK_EX|LOCK_NB : LOCK_SH|LOCK_NB);
#else
return 0; /* Hope & pray... */
@ -325,9 +324,8 @@ static int split_port(char **ap, char **pp)
enum long_only_options {
OPT_VERBOSITY = 256,
OPT_MAP_STEPS
};
static struct option long_options[] = {
{ "ipv4", 0, NULL, '4' },
{ "ipv6", 0, NULL, '6' },
@ -348,7 +346,6 @@ static struct option long_options[] = {
{ "retransmit", 1, NULL, 'T' },
{ "port-range", 1, NULL, 'R' },
{ "map-file", 1, NULL, 'm' },
{ "map-steps", 1, NULL, OPT_MAP_STEPS },
{ "pidfile", 1, NULL, 'P' },
{ NULL, 0, NULL, 0 }
};
@ -378,7 +375,6 @@ int main(int argc, char **argv)
int spec_umask = 0;
int c;
int setrv;
int die;
int waittime = 900; /* Default time to wait for a connect */
const char *user = "nobody"; /* Default user */
char *p, *ep;
@ -391,9 +387,9 @@ int main(int argc, char **argv)
/* basename() is way too much of a pain from a portability standpoint */
p = strrchr(argv[0], '/');
tftpd_progname = (p && p[1]) ? p + 1 : argv[0];
__progname = (p && p[1]) ? p + 1 : argv[0];
openlog(tftpd_progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
srand(time(NULL) ^ getpid());
@ -497,17 +493,6 @@ int main(int argc, char **argv)
}
rewrite_file = optarg;
break;
case OPT_MAP_STEPS:
{
unsigned long steps = strtoul(optarg, &ep, 0);
if (*optarg && *ep && steps > 0 && steps <= INT_MAX) {
deadman_max_steps = steps;
} else {
syslog(LOG_ERR, "Bad --map-steps option: %s", optarg);
exit(EX_USAGE);
}
break;
}
#endif
case 'v':
verbosity++;
@ -889,7 +874,9 @@ int main(int argc, char **argv)
set_socket_nonblock(fd, 0);
#endif
n = myrecvfrom(fd, buf, sizeof(buf), 0, &from, &myaddr);
fromlen = sizeof(from);
n = myrecvfrom(fd, buf, sizeof(buf), 0,
(struct sockaddr *)&from, &fromlen, &myaddr);
if (n < 0) {
if (E_WOULD_BLOCK(errno) || errno == EINTR) {
@ -951,14 +938,14 @@ int main(int argc, char **argv)
syslog daemon gets restarted by the time we get here. */
if (secure && standalone) {
closelog();
openlog(tftpd_progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
openlog(__progname, LOG_PID | LOG_NDELAY, LOG_DAEMON);
}
#ifdef HAVE_TCPWRAPPERS
/* Verify if this was a legal request for us. This has to be
done before the chroot, while /etc is still accessible. */
request_init(&wrap_request,
RQ_DAEMON, tftpd_progname,
RQ_DAEMON, __progname,
RQ_FILE, fd,
RQ_CLIENT_SIN, &from, RQ_SERVER_SIN, &myaddr, 0);
sock_methods(&wrap_request);
@ -990,29 +977,21 @@ int main(int argc, char **argv)
exit(EX_IOERR);
}
/* Set up the supplementary group access list if possible
/etc/group still need to be accessible at this point.
If we get EPERM, this is already a restricted process, e.g.
using user namespaces on Linux. */
die = 0;
#ifdef HAVE_SETGROUPS
setrv = setgroups(0, NULL);
if (setrv && errno != EPERM) {
syslog(LOG_ERR, "cannot clear group list");
die = EX_OSERR;
}
#endif
/* Set up the supplementary group access list if possible */
/* /etc/group still need to be accessible at this point */
#ifdef HAVE_INITGROUPS
setrv = initgroups(user, pw->pw_gid);
if (!setrv) {
die = 0;
} else if (errno != EPERM) {
if (setrv) {
syslog(LOG_ERR, "cannot set groups for user %s", user);
die = EX_OSERR;
exit(EX_OSERR);
}
#else
#ifdef HAVE_SETGROUPS
if (setgroups(0, NULL)) {
syslog(LOG_ERR, "cannot clear group list");
}
#endif
if (die)
exit(die);
#endif
/* Chroot and drop privileges */
if (secure) {
@ -1024,30 +1003,19 @@ int main(int argc, char **argv)
chdir("/"); /* Cygwin chroot() bug workaround */
#endif
}
#ifdef HAVE_SETRESGID
setrv = setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid);
#elif defined(HAVE_SETREGID)
#ifdef HAVE_SETREGID
setrv = setregid(pw->pw_gid, pw->pw_gid);
#else
setrv = setegid(pw->pw_gid) || setgid(pw->pw_gid);
#endif
if (setrv && errno == EPERM) {
setrv = 0; /* Assume already restricted by system policy */
}
#ifdef HAVE_SETRESUID
setrv = setrv || setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid);
#elif defined(HAVE_SETREUID)
#ifdef HAVE_SETREUID
setrv = setrv || setreuid(pw->pw_uid, pw->pw_uid);
#else
/* Important: setuid() must come first */
setrv = setrv || setuid(pw->pw_uid) ||
(geteuid() != pw->pw_uid && seteuid(pw->pw_uid));
#endif
if (setrv && errno == EPERM) {
setrv = 0; /* Assume already restricted by system policy */
}
if (setrv) {
syslog(LOG_ERR, "cannot drop privileges: %m");
@ -1071,16 +1039,23 @@ int main(int argc, char **argv)
tp = (struct tftphdr *)buf;
tp_opcode = ntohs(tp->th_opcode);
if (tp_opcode == RRQ || tp_opcode == WRQ)
tftp(tp, n);
tftp(tp, n);
exit(0);
}
static char *rewrite_access(const struct formats *,
char *, int, int, const char **);
static char *rewrite_access(char *, int, const char **);
static int validate_access(char *, int, const struct formats *, const char **);
static void tftp_sendfile(const struct formats *, struct tftphdr *, int);
static void tftp_recvfile(const struct formats *, struct tftphdr *, int);
struct formats {
const char *f_mode;
char *(*f_rewrite) (char *, int, const char **);
int (*f_validate) (char *, int, const struct formats *, const char **);
void (*f_send) (const struct formats *, struct tftphdr *, int);
void (*f_recv) (const struct formats *, struct tftphdr *, int);
int f_convert;
};
static const struct formats formats[] = {
{
"netascii", rewrite_access, validate_access, tftp_sendfile,
@ -1137,9 +1112,9 @@ int tftp(struct tftphdr *tp, int size)
nak(EBADOP, "Unknown mode");
exit(0);
}
file = NULL;
if (!(filename = (*pf->f_rewrite)
(pf, origfilename, tp_opcode, from.sa.sa_family, &errmsgptr))) {
if (!(filename =
(*pf->f_rewrite) (origfilename, tp_opcode,
&errmsgptr))) {
nak(EACCESS, errmsgptr); /* File denied by mapping rule */
exit(0);
}
@ -1162,18 +1137,12 @@ int tftp(struct tftphdr *tp, int size)
tmp_p, origfilename,
filename);
}
/*
* If "file" is already set, then a file was already validated
* and opened during remap processing.
*/
if (!file) {
ecode =
(*pf->f_validate) (filename, tp_opcode, pf, &errmsgptr);
if (ecode) {
nak(ecode, errmsgptr);
exit(0);
}
}
ecode =
(*pf->f_validate) (filename, tp_opcode, pf, &errmsgptr);
if (ecode) {
nak(ecode, errmsgptr);
exit(0);
}
opt = ++cp;
} else if (argn & 1) {
val = ++cp;
@ -1260,7 +1229,7 @@ static int set_blksize2(uintmax_t *vp)
static int set_rollover(uintmax_t *vp)
{
uintmax_t ro = *vp;
if (ro > 65535)
return 0;
@ -1359,7 +1328,7 @@ static void do_opt(const char *opt, const char *val, char **ap)
nak(EOPTNEG, "Insufficient space for options");
exit(0);
}
memcpy(p, opt, optlen+1);
p += optlen+1;
memcpy(p, retbuf, retlen+1);
@ -1429,12 +1398,12 @@ static int rewrite_macros(char macro, char *output)
/*
* Modify the filename, if applicable. If it returns NULL, deny the access.
*/
static char *rewrite_access(const struct formats *pf, char *filename,
int mode, int af, const char **msg)
static char *rewrite_access(char *filename, int mode, const char **msg)
{
if (rewrite_rules) {
char *newname =
rewrite_string(pf, filename, rewrite_rules, mode, af,
rewrite_string(filename, rewrite_rules,
mode != RRQ ? 'P' : 'G',
rewrite_macros, msg);
filename = newname;
}
@ -1442,17 +1411,15 @@ static char *rewrite_access(const struct formats *pf, char *filename,
}
#else
static char *rewrite_access(const struct formats *pf, char *filename,
int mode, int af, const char **msg)
static char *rewrite_access(char *filename, int mode, const char **msg)
{
(void)pf;
(void)mode; /* Avoid warning */
(void)msg;
(void)af;
return filename;
}
#endif
static FILE *file;
/*
* Validate file access. Since we
* have no uid or gid, for now require
@ -1677,21 +1644,17 @@ static void tftp_sendfile(const struct formats *pf, struct tftphdr *oap, int oac
/*
* Receive a file.
*/
static void tftp_recvfile(const struct formats *pf,
struct tftphdr *oack, int oacklen)
static void tftp_recvfile(const struct formats *pf, struct tftphdr *oap, int oacklen)
{
struct tftphdr *dp;
int n, size;
/* These are "static" to avoid longjmp funnies */
static struct tftphdr *oap;
static struct tftphdr *ap; /* ack buffer */
static u_short block = 0;
static int acksize;
u_short dp_opcode, dp_block;
unsigned long r_timeout;
oap = oack;
dp = w_init();
do {
timeout = rexmtval;

View file

@ -23,13 +23,4 @@ char *tfstrdup(const char *);
extern int verbosity;
struct formats {
const char *f_mode;
char *(*f_rewrite) (const struct formats *, char *, int, int, const char **);
int (*f_validate) (char *, int, const struct formats *, const char **);
void (*f_send) (const struct formats *, struct tftphdr *, int);
void (*f_recv) (const struct formats *, struct tftphdr *, int);
int f_convert;
};
#endif

View file

@ -1 +1 @@
5.3
5.1