diff options
Diffstat (limited to '')
-rw-r--r-- | utils/mountd/Makefile.am | 70 | ||||
-rw-r--r-- | utils/mountd/Makefile.in | 941 | ||||
-rw-r--r-- | utils/mountd/mount_dispatch.c | 84 | ||||
-rw-r--r-- | utils/mountd/mountd.c | 887 | ||||
-rw-r--r-- | utils/mountd/mountd.h | 54 | ||||
-rw-r--r-- | utils/mountd/mountd.man | 362 | ||||
-rw-r--r-- | utils/mountd/rmtab.c | 254 | ||||
-rw-r--r-- | utils/mountd/svc_run.c | 109 |
8 files changed, 2761 insertions, 0 deletions
diff --git a/utils/mountd/Makefile.am b/utils/mountd/Makefile.am new file mode 100644 index 0000000..197ef29 --- /dev/null +++ b/utils/mountd/Makefile.am @@ -0,0 +1,70 @@ +## Process this file with automake to produce Makefile.in + +OPTLIBS = +if CONFIG_JUNCTION +OPTLIBS += ../../support/junction/libjunction.la $(LIBXML2) +endif + +man8_MANS = mountd.man +EXTRA_DIST = $(man8_MANS) + +RPCPREFIX = rpc. +KPREFIX = @kprefix@ +sbin_PROGRAMS = mountd + +mountd_SOURCES = mountd.c mount_dispatch.c rmtab.c \ + svc_run.c mountd.h +mountd_LDADD = ../../support/export/libexport.a \ + ../../support/nfs/libnfs.la \ + ../../support/misc/libmisc.a \ + ../../support/reexport/libreexport.a \ + $(OPTLIBS) \ + $(LIBBSD) $(LIBWRAP) $(LIBNSL) $(LIBBLKID) -luuid $(LIBTIRPC) \ + $(LIBPTHREAD) + +mountd_CPPFLAGS = $(AM_CPPFLAGS) $(CPPFLAGS) \ + -I$(top_builddir)/support/include \ + -I$(top_srcdir)/support/export + +MAINTAINERCLEANFILES = Makefile.in + +####################################################################### +# The following allows the current practice of having +# daemons renamed during the install to include RPCPREFIX +# and the KPREFIX +# This could all be done much easier with program_transform_name +# ( program_transform_name = s/^/$(RPCPREFIX)$(KPREFIX)/ ) +# but that also renames the man pages, which the current +# practice does not do. +install-exec-hook: + (cd $(DESTDIR)$(sbindir) && \ + for p in $(sbin_PROGRAMS); do \ + mv -f $$p$(EXEEXT) $(RPCPREFIX)$(KPREFIX)$$p$(EXEEXT) ;\ + done) +uninstall-hook: + (cd $(DESTDIR)$(sbindir) && \ + for p in $(sbin_PROGRAMS); do \ + rm -f $(RPCPREFIX)$(KPREFIX)$$p$(EXEEXT) ;\ + done) + + +# XXX This makes some assumptions about what automake does. +# XXX But there is no install-man-hook or install-man-local. +install-man: install-man8 install-man-links +uninstall-man: uninstall-man8 uninstall-man-links + +install-man-links: + (cd $(DESTDIR)$(man8dir) && \ + for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \ + inst=`echo $$m | sed -e 's/man$$/8/'`; \ + rm -f $(RPCPREFIX)$$inst ; \ + $(LN_S) $$inst $(RPCPREFIX)$$inst ; \ + done) + +uninstall-man-links: + (cd $(DESTDIR)$(man8dir) && \ + for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \ + inst=`echo $$m | sed -e 's/man$$/8/'`; \ + rm -f $(RPCPREFIX)$$inst ; \ + done) + diff --git a/utils/mountd/Makefile.in b/utils/mountd/Makefile.in new file mode 100644 index 0000000..7754575 --- /dev/null +++ b/utils/mountd/Makefile.in @@ -0,0 +1,941 @@ +# Makefile.in generated by automake 1.16.5 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994-2021 Free Software Foundation, Inc. + +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ + +VPATH = @srcdir@ +am__is_gnu_make = { \ + if test -z '$(MAKELEVEL)'; then \ + false; \ + elif test -n '$(MAKE_HOST)'; then \ + true; \ + elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \ + true; \ + else \ + false; \ + fi; \ +} +am__make_running_with_option = \ + case $${target_option-} in \ + ?) ;; \ + *) echo "am__make_running_with_option: internal error: invalid" \ + "target option '$${target_option-}' specified" >&2; \ + exit 1;; \ + esac; \ + has_opt=no; \ + sane_makeflags=$$MAKEFLAGS; \ + if $(am__is_gnu_make); then \ + sane_makeflags=$$MFLAGS; \ + else \ + case $$MAKEFLAGS in \ + *\\[\ \ ]*) \ + bs=\\; \ + sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ + | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ + esac; \ + fi; \ + skip_next=no; \ + strip_trailopt () \ + { \ + flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ + }; \ + for flg in $$sane_makeflags; do \ + test $$skip_next = yes && { skip_next=no; continue; }; \ + case $$flg in \ + *=*|--*) continue;; \ + -*I) strip_trailopt 'I'; skip_next=yes;; \ + -*I?*) strip_trailopt 'I';; \ + -*O) strip_trailopt 'O'; skip_next=yes;; \ + -*O?*) strip_trailopt 'O';; \ + -*l) strip_trailopt 'l'; skip_next=yes;; \ + -*l?*) strip_trailopt 'l';; \ + -[dEDm]) skip_next=yes;; \ + -[JT]) skip_next=yes;; \ + esac; \ + case $$flg in \ + *$$target_option*) has_opt=yes; break;; \ + esac; \ + done; \ + test $$has_opt = yes +am__make_dryrun = (target_option=n; $(am__make_running_with_option)) +am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_HEADER = $(INSTALL_DATA) +transform = $(program_transform_name) +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +build_triplet = @build@ +host_triplet = @host@ +@CONFIG_JUNCTION_TRUE@am__append_1 = ../../support/junction/libjunction.la $(LIBXML2) +sbin_PROGRAMS = mountd$(EXEEXT) +subdir = utils/mountd +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +am__aclocal_m4_deps = $(top_srcdir)/aclocal/ax_gcc_func_attribute.m4 \ + $(top_srcdir)/aclocal/bsdsignals.m4 \ + $(top_srcdir)/aclocal/getrandom.m4 \ + $(top_srcdir)/aclocal/ipv6.m4 \ + $(top_srcdir)/aclocal/kerberos5.m4 \ + $(top_srcdir)/aclocal/keyutils.m4 \ + $(top_srcdir)/aclocal/libblkid.m4 \ + $(top_srcdir)/aclocal/libcap.m4 \ + $(top_srcdir)/aclocal/libevent.m4 \ + $(top_srcdir)/aclocal/libpthread.m4 \ + $(top_srcdir)/aclocal/libsqlite3.m4 \ + $(top_srcdir)/aclocal/libtirpc.m4 \ + $(top_srcdir)/aclocal/libxml2.m4 \ + $(top_srcdir)/aclocal/nfs-utils.m4 \ + $(top_srcdir)/aclocal/rpcsec_vers.m4 \ + $(top_srcdir)/aclocal/tcp-wrappers.m4 \ + $(top_srcdir)/configure.ac +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/support/include/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)" +PROGRAMS = $(sbin_PROGRAMS) +am_mountd_OBJECTS = mountd-mountd.$(OBJEXT) \ + mountd-mount_dispatch.$(OBJEXT) mountd-rmtab.$(OBJEXT) \ + mountd-svc_run.$(OBJEXT) +mountd_OBJECTS = $(am_mountd_OBJECTS) +am__DEPENDENCIES_1 = +@CONFIG_JUNCTION_TRUE@am__DEPENDENCIES_2 = \ +@CONFIG_JUNCTION_TRUE@ ../../support/junction/libjunction.la \ +@CONFIG_JUNCTION_TRUE@ $(am__DEPENDENCIES_1) +am__DEPENDENCIES_3 = $(am__DEPENDENCIES_2) +mountd_DEPENDENCIES = ../../support/export/libexport.a \ + ../../support/nfs/libnfs.la ../../support/misc/libmisc.a \ + ../../support/reexport/libreexport.a $(am__DEPENDENCIES_3) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +AM_V_lt = $(am__v_lt_@AM_V@) +am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) +am__v_lt_0 = --silent +am__v_lt_1 = +AM_V_P = $(am__v_P_@AM_V@) +am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) +am__v_P_0 = false +am__v_P_1 = : +AM_V_GEN = $(am__v_GEN_@AM_V@) +am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) +am__v_GEN_0 = @echo " GEN " $@; +am__v_GEN_1 = +AM_V_at = $(am__v_at_@AM_V@) +am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) +am__v_at_0 = @ +am__v_at_1 = +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/support/include +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__maybe_remake_depfiles = depfiles +am__depfiles_remade = ./$(DEPDIR)/mountd-mount_dispatch.Po \ + ./$(DEPDIR)/mountd-mountd.Po ./$(DEPDIR)/mountd-rmtab.Po \ + ./$(DEPDIR)/mountd-svc_run.Po +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_@AM_V@) +am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) +am__v_CC_0 = @echo " CC " $@; +am__v_CC_1 = +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_@AM_V@) +am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) +am__v_CCLD_0 = @echo " CCLD " $@; +am__v_CCLD_1 = +SOURCES = $(mountd_SOURCES) +DIST_SOURCES = $(mountd_SOURCES) +am__can_run_installinfo = \ + case $$AM_UPDATE_INFO_DIR in \ + n|no|NO) false;; \ + *) (install-info --version) >/dev/null 2>&1;; \ + esac +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +am__uninstall_files_from_dir = { \ + test -z "$$files" \ + || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ + || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ + $(am__cd) "$$dir" && rm -f $$files; }; \ + } +man8dir = $(mandir)/man8 +NROFF = nroff +MANS = $(man8_MANS) +am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) +# Read a list of newline-separated strings from the standard input, +# and print each of them once, without duplicates. Input order is +# *not* preserved. +am__uniquify_input = $(AWK) '\ + BEGIN { nonempty = 0; } \ + { items[$$0] = 1; nonempty = 1; } \ + END { if (nonempty) { for (i in items) print i; }; } \ +' +# Make sure the list of sources is unique. This is necessary because, +# e.g., the same source file might be shared among _SOURCES variables +# for different programs/libraries. +am__define_uniq_tagged_files = \ + list='$(am__tagged_files)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | $(am__uniquify_input)` +am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ +ALLOCA = @ALLOCA@ +AMTAR = @AMTAR@ +AM_CFLAGS = @AM_CFLAGS@ +AM_CPPFLAGS = @AM_CPPFLAGS@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CC_FOR_BUILD = @CC_FOR_BUILD@ +CFLAGS = @CFLAGS@ +CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@ +CSCOPE = @CSCOPE@ +CTAGS = @CTAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CXXFLAGS_FOR_BUILD = @CXXFLAGS_FOR_BUILD@ +CYGPATH_W = @CYGPATH_W@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +ETAGS = @ETAGS@ +EXEEXT = @EXEEXT@ +FGREP = @FGREP@ +FILECMD = @FILECMD@ +GREP = @GREP@ +GSSAPI_CFLAGS = @GSSAPI_CFLAGS@ +GSSAPI_LIBS = @GSSAPI_LIBS@ +GSSD = @GSSD@ +GSSGLUE_CFLAGS = @GSSGLUE_CFLAGS@ +GSSGLUE_LIBS = @GSSGLUE_LIBS@ +GSSKRB_CFLAGS = @GSSKRB_CFLAGS@ +GSSKRB_LIBS = @GSSKRB_LIBS@ +HAVE_GETRANDOM = @HAVE_GETRANDOM@ +HAVE_LIBWRAP = @HAVE_LIBWRAP@ +HAVE_TCP_WRAPPER = @HAVE_TCP_WRAPPER@ +IDMAPD = @IDMAPD@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +K5VERS = @K5VERS@ +KRBCFLAGS = @KRBCFLAGS@ +KRBDIR = @KRBDIR@ +KRBLDFLAGS = @KRBLDFLAGS@ +KRBLIBS = @KRBLIBS@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@ +LIBBLKID = @LIBBLKID@ +LIBBSD = @LIBBSD@ +LIBCAP = @LIBCAP@ +LIBCRYPT = @LIBCRYPT@ +LIBEVENT = @LIBEVENT@ +LIBKEYUTILS = @LIBKEYUTILS@ +LIBMOUNT = @LIBMOUNT@ +LIBMOUNT_CFLAGS = @LIBMOUNT_CFLAGS@ +LIBMOUNT_LIBS = @LIBMOUNT_LIBS@ +LIBNSL = @LIBNSL@ +LIBOBJS = @LIBOBJS@ +LIBPTHREAD = @LIBPTHREAD@ +LIBS = @LIBS@ +LIBSOCKET = @LIBSOCKET@ +LIBSQLITE = @LIBSQLITE@ +LIBTIRPC = @LIBTIRPC@ +LIBTOOL = @LIBTOOL@ +LIBWRAP = @LIBWRAP@ +LIBXML2 = @LIBXML2@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_SYS_LIBRARY_PATH = @LT_SYS_LIBRARY_PATH@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MANIFEST_TOOL = @MANIFEST_TOOL@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +PACKAGE = @PACKAGE@ +PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_STRING = @PACKAGE_STRING@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ +PACKAGE_URL = @PACKAGE_URL@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +PATH_PLUGINS = @PATH_PLUGINS@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +PKG_CONFIG = @PKG_CONFIG@ +PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ +PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ +RANLIB = @RANLIB@ +RELEASE = @RELEASE@ +RPCGEN_PATH = @RPCGEN_PATH@ +RPCSECGSS_CFLAGS = @RPCSECGSS_CFLAGS@ +RPCSECGSS_LIBS = @RPCSECGSS_LIBS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +SVCGSSD = @SVCGSSD@ +TIRPC_CFLAGS = @TIRPC_CFLAGS@ +TIRPC_LIBS = @TIRPC_LIBS@ +VERSION = @VERSION@ +XML2_CFLAGS = @XML2_CFLAGS@ +XML2_LIBS = @XML2_LIBS@ +_rpc_pipefsmount = @_rpc_pipefsmount@ +_statedir = @_statedir@ +_sysconfdir = @_sysconfdir@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +am__include = @am__include@ +am__leading_dot = @am__leading_dot@ +am__quote = @am__quote@ +am__tar = @am__tar@ +am__untar = @am__untar@ +bindir = @bindir@ +build = @build@ +build_alias = @build_alias@ +build_cpu = @build_cpu@ +build_os = @build_os@ +build_vendor = @build_vendor@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +enable_gss = @enable_gss@ +enable_ipv6 = @enable_ipv6@ +enable_mountconfig = @enable_mountconfig@ +enable_nfsv4 = @enable_nfsv4@ +enable_nfsv41 = @enable_nfsv41@ +enable_svcgss = @enable_svcgss@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +kprefix = @kprefix@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +mountfile = @mountfile@ +nfsconfig = @nfsconfig@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +rpc_pipefsmount = @rpc_pipefsmount@ +runstatedir = @runstatedir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +startstatd = @startstatd@ +statdpath = @statdpath@ +statduser = @statduser@ +statedir = @statedir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +unitdir = @unitdir@ +OPTLIBS = $(am__append_1) +man8_MANS = mountd.man +EXTRA_DIST = $(man8_MANS) +RPCPREFIX = rpc. +KPREFIX = @kprefix@ +mountd_SOURCES = mountd.c mount_dispatch.c rmtab.c \ + svc_run.c mountd.h + +mountd_LDADD = ../../support/export/libexport.a \ + ../../support/nfs/libnfs.la \ + ../../support/misc/libmisc.a \ + ../../support/reexport/libreexport.a \ + $(OPTLIBS) \ + $(LIBBSD) $(LIBWRAP) $(LIBNSL) $(LIBBLKID) -luuid $(LIBTIRPC) \ + $(LIBPTHREAD) + +mountd_CPPFLAGS = $(AM_CPPFLAGS) $(CPPFLAGS) \ + -I$(top_builddir)/support/include \ + -I$(top_srcdir)/support/export + +MAINTAINERCLEANFILES = Makefile.in +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) + @for dep in $?; do \ + case '$(am__configure_deps)' in \ + *$$dep*) \ + ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu utils/mountd/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu utils/mountd/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + @case '$?' in \ + *config.status*) \ + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ + *) \ + echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \ + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \ + esac; + +$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh + +$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) + cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +$(am__aclocal_m4_deps): +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + if test -n "$$list"; then \ + echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ + fi; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p \ + || test -f $$p1 \ + ; then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' \ + -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' \ + `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(sbindir)" && rm -f $$files + +clean-sbinPROGRAMS: + @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list + +mountd$(EXEEXT): $(mountd_OBJECTS) $(mountd_DEPENDENCIES) $(EXTRA_mountd_DEPENDENCIES) + @rm -f mountd$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(mountd_OBJECTS) $(mountd_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mountd-mount_dispatch.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mountd-mountd.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mountd-rmtab.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mountd-svc_run.Po@am__quote@ # am--include-marker + +$(am__depfiles_remade): + @$(MKDIR_P) $(@D) + @echo '# dummy' >$@-t && $(am__mv) $@-t $@ + +am--depfiles: $(am__depfiles_remade) + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< + +.c.obj: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` + +.c.lo: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< + +mountd-mountd.o: mountd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mountd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mountd-mountd.o -MD -MP -MF $(DEPDIR)/mountd-mountd.Tpo -c -o mountd-mountd.o `test -f 'mountd.c' || echo '$(srcdir)/'`mountd.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mountd-mountd.Tpo $(DEPDIR)/mountd-mountd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mountd.c' object='mountd-mountd.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mountd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mountd-mountd.o `test -f 'mountd.c' || echo '$(srcdir)/'`mountd.c + +mountd-mountd.obj: mountd.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mountd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mountd-mountd.obj -MD -MP -MF $(DEPDIR)/mountd-mountd.Tpo -c -o mountd-mountd.obj `if test -f 'mountd.c'; then $(CYGPATH_W) 'mountd.c'; else $(CYGPATH_W) '$(srcdir)/mountd.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mountd-mountd.Tpo $(DEPDIR)/mountd-mountd.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mountd.c' object='mountd-mountd.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mountd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mountd-mountd.obj `if test -f 'mountd.c'; then $(CYGPATH_W) 'mountd.c'; else $(CYGPATH_W) '$(srcdir)/mountd.c'; fi` + +mountd-mount_dispatch.o: mount_dispatch.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mountd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mountd-mount_dispatch.o -MD -MP -MF $(DEPDIR)/mountd-mount_dispatch.Tpo -c -o mountd-mount_dispatch.o `test -f 'mount_dispatch.c' || echo '$(srcdir)/'`mount_dispatch.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mountd-mount_dispatch.Tpo $(DEPDIR)/mountd-mount_dispatch.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mount_dispatch.c' object='mountd-mount_dispatch.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mountd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mountd-mount_dispatch.o `test -f 'mount_dispatch.c' || echo '$(srcdir)/'`mount_dispatch.c + +mountd-mount_dispatch.obj: mount_dispatch.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mountd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mountd-mount_dispatch.obj -MD -MP -MF $(DEPDIR)/mountd-mount_dispatch.Tpo -c -o mountd-mount_dispatch.obj `if test -f 'mount_dispatch.c'; then $(CYGPATH_W) 'mount_dispatch.c'; else $(CYGPATH_W) '$(srcdir)/mount_dispatch.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mountd-mount_dispatch.Tpo $(DEPDIR)/mountd-mount_dispatch.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mount_dispatch.c' object='mountd-mount_dispatch.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mountd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mountd-mount_dispatch.obj `if test -f 'mount_dispatch.c'; then $(CYGPATH_W) 'mount_dispatch.c'; else $(CYGPATH_W) '$(srcdir)/mount_dispatch.c'; fi` + +mountd-rmtab.o: rmtab.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mountd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mountd-rmtab.o -MD -MP -MF $(DEPDIR)/mountd-rmtab.Tpo -c -o mountd-rmtab.o `test -f 'rmtab.c' || echo '$(srcdir)/'`rmtab.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mountd-rmtab.Tpo $(DEPDIR)/mountd-rmtab.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rmtab.c' object='mountd-rmtab.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mountd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mountd-rmtab.o `test -f 'rmtab.c' || echo '$(srcdir)/'`rmtab.c + +mountd-rmtab.obj: rmtab.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mountd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mountd-rmtab.obj -MD -MP -MF $(DEPDIR)/mountd-rmtab.Tpo -c -o mountd-rmtab.obj `if test -f 'rmtab.c'; then $(CYGPATH_W) 'rmtab.c'; else $(CYGPATH_W) '$(srcdir)/rmtab.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mountd-rmtab.Tpo $(DEPDIR)/mountd-rmtab.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rmtab.c' object='mountd-rmtab.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mountd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mountd-rmtab.obj `if test -f 'rmtab.c'; then $(CYGPATH_W) 'rmtab.c'; else $(CYGPATH_W) '$(srcdir)/rmtab.c'; fi` + +mountd-svc_run.o: svc_run.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mountd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mountd-svc_run.o -MD -MP -MF $(DEPDIR)/mountd-svc_run.Tpo -c -o mountd-svc_run.o `test -f 'svc_run.c' || echo '$(srcdir)/'`svc_run.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mountd-svc_run.Tpo $(DEPDIR)/mountd-svc_run.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='svc_run.c' object='mountd-svc_run.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mountd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mountd-svc_run.o `test -f 'svc_run.c' || echo '$(srcdir)/'`svc_run.c + +mountd-svc_run.obj: svc_run.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mountd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mountd-svc_run.obj -MD -MP -MF $(DEPDIR)/mountd-svc_run.Tpo -c -o mountd-svc_run.obj `if test -f 'svc_run.c'; then $(CYGPATH_W) 'svc_run.c'; else $(CYGPATH_W) '$(srcdir)/svc_run.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/mountd-svc_run.Tpo $(DEPDIR)/mountd-svc_run.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='svc_run.c' object='mountd-svc_run.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(mountd_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mountd-svc_run.obj `if test -f 'svc_run.c'; then $(CYGPATH_W) 'svc_run.c'; else $(CYGPATH_W) '$(srcdir)/svc_run.c'; fi` + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs +install-man8: $(man8_MANS) + @$(NORMAL_INSTALL) + @list1='$(man8_MANS)'; \ + list2=''; \ + test -n "$(man8dir)" \ + && test -n "`echo $$list1$$list2`" \ + || exit 0; \ + echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ + $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ + { for i in $$list1; do echo "$$i"; done; \ + if test -n "$$list2"; then \ + for i in $$list2; do echo "$$i"; done \ + | sed -n '/\.8[a-z]*$$/p'; \ + fi; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ + done; } + +uninstall-man8: + @$(NORMAL_UNINSTALL) + @list='$(man8_MANS)'; test -n "$(man8dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) + +ID: $(am__tagged_files) + $(am__define_uniq_tagged_files); mkid -fID $$unique +tags: tags-am +TAGS: tags + +tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + set x; \ + here=`pwd`; \ + $(am__define_uniq_tagged_files); \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: ctags-am + +CTAGS: ctags +ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) + $(am__define_uniq_tagged_files); \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" +cscopelist: cscopelist-am + +cscopelist-am: $(am__tagged_files) + list='$(am__tagged_files)'; \ + case "$(srcdir)" in \ + [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ + *) sdir=$(subdir)/$(srcdir) ;; \ + esac; \ + for i in $$list; do \ + if test -f "$$i"; then \ + echo "$(subdir)/$$i"; \ + else \ + echo "$$sdir/$$i"; \ + fi; \ + done >> $(top_builddir)/cscope.files + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags +distdir: $(BUILT_SOURCES) + $(MAKE) $(AM_MAKEFLAGS) distdir-am + +distdir-am: $(DISTFILES) + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(MANS) +installdirs: + for dir in "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(man8dir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + if test -z '$(STRIP)'; then \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + install; \ + else \ + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ + "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ + fi +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." + -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) +clean: clean-am + +clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \ + mostlyclean-am + +distclean: distclean-am + -rm -f ./$(DEPDIR)/mountd-mount_dispatch.Po + -rm -f ./$(DEPDIR)/mountd-mountd.Po + -rm -f ./$(DEPDIR)/mountd-rmtab.Po + -rm -f ./$(DEPDIR)/mountd-svc_run.Po + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-sbinPROGRAMS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-exec-hook +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -f ./$(DEPDIR)/mountd-mount_dispatch.Po + -rm -f ./$(DEPDIR)/mountd-mountd.Po + -rm -f ./$(DEPDIR)/mountd-rmtab.Po + -rm -f ./$(DEPDIR)/mountd-svc_run.Po + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-man uninstall-sbinPROGRAMS + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-hook +.MAKE: install-am install-exec-am install-strip uninstall-am + +.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \ + clean-generic clean-libtool clean-sbinPROGRAMS cscopelist-am \ + ctags ctags-am distclean distclean-compile distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am html \ + html-am info info-am install install-am install-data \ + install-data-am install-dvi install-dvi-am install-exec \ + install-exec-am install-exec-hook install-html install-html-am \ + install-info install-info-am install-man install-man8 \ + install-pdf install-pdf-am install-ps install-ps-am \ + install-sbinPROGRAMS install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags tags-am uninstall uninstall-am uninstall-hook \ + uninstall-man uninstall-man8 uninstall-sbinPROGRAMS + +.PRECIOUS: Makefile + + +####################################################################### +# The following allows the current practice of having +# daemons renamed during the install to include RPCPREFIX +# and the KPREFIX +# This could all be done much easier with program_transform_name +# ( program_transform_name = s/^/$(RPCPREFIX)$(KPREFIX)/ ) +# but that also renames the man pages, which the current +# practice does not do. +install-exec-hook: + (cd $(DESTDIR)$(sbindir) && \ + for p in $(sbin_PROGRAMS); do \ + mv -f $$p$(EXEEXT) $(RPCPREFIX)$(KPREFIX)$$p$(EXEEXT) ;\ + done) +uninstall-hook: + (cd $(DESTDIR)$(sbindir) && \ + for p in $(sbin_PROGRAMS); do \ + rm -f $(RPCPREFIX)$(KPREFIX)$$p$(EXEEXT) ;\ + done) + +# XXX This makes some assumptions about what automake does. +# XXX But there is no install-man-hook or install-man-local. +install-man: install-man8 install-man-links +uninstall-man: uninstall-man8 uninstall-man-links + +install-man-links: + (cd $(DESTDIR)$(man8dir) && \ + for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \ + inst=`echo $$m | sed -e 's/man$$/8/'`; \ + rm -f $(RPCPREFIX)$$inst ; \ + $(LN_S) $$inst $(RPCPREFIX)$$inst ; \ + done) + +uninstall-man-links: + (cd $(DESTDIR)$(man8dir) && \ + for m in $(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS); do \ + inst=`echo $$m | sed -e 's/man$$/8/'`; \ + rm -f $(RPCPREFIX)$$inst ; \ + done) + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/utils/mountd/mount_dispatch.c b/utils/mountd/mount_dispatch.c new file mode 100644 index 0000000..ba6981d --- /dev/null +++ b/utils/mountd/mount_dispatch.c @@ -0,0 +1,84 @@ +/* + * mount_dispatch This file contains the function dispatch table. + * + * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de> + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_TCP_WRAPPER +#include "tcpwrapper.h" +#endif + +#include "mountd.h" +#include "rpcmisc.h" + +/* + * Procedures for MNTv1 + */ +static struct rpc_dentry mnt_1_dtable[] = { + dtable_ent(mount_null,1,void,void), /* NULL */ + dtable_ent(mount_mnt,1,dirpath,fhstatus), /* MNT */ + dtable_ent(mount_dump,1,void,mountlist), /* DUMP */ + dtable_ent(mount_umnt,1,dirpath,void), /* UMNT */ + dtable_ent(mount_umntall,1,void,void), /* UMNTALL */ + dtable_ent(mount_export,1,void,exports), /* EXPORT */ + dtable_ent(mount_exportall,1,void,exports), /* EXPORTALL */ +}; + +/* + * Procedures for MNTv2 + */ +static struct rpc_dentry mnt_2_dtable[] = { + dtable_ent(mount_null,1,void,void), /* NULL */ + dtable_ent(mount_mnt,1,dirpath,fhstatus), /* MNT */ + dtable_ent(mount_dump,1,void,mountlist), /* DUMP */ + dtable_ent(mount_umnt,1,dirpath,void), /* UMNT */ + dtable_ent(mount_umntall,1,void,void), /* UMNTALL */ + dtable_ent(mount_export,1,void,exports), /* EXPORT */ + dtable_ent(mount_exportall,1,void,exports), /* EXPORTALL */ + dtable_ent(mount_pathconf,2,dirpath,ppathcnf), /* PATHCONF */ +}; + +/* + * Procedures for MNTv3 + */ +static struct rpc_dentry mnt_3_dtable[] = { + dtable_ent(mount_null,1,void,void), /* NULL */ + dtable_ent(mount_mnt,3,dirpath,mountres3), /* MNT */ + dtable_ent(mount_dump,1,void,mountlist), /* DUMP */ + dtable_ent(mount_umnt,1,dirpath,void), /* UMNT */ + dtable_ent(mount_umntall,1,void,void), /* UMNTALL */ + dtable_ent(mount_export,1,void,exports), /* EXPORT */ +}; + +#define number_of(x) (sizeof(x)/sizeof(x[0])) + +static struct rpc_dtable dtable[] = { + { mnt_1_dtable, number_of(mnt_1_dtable) }, + { mnt_2_dtable, number_of(mnt_2_dtable) }, + { mnt_3_dtable, number_of(mnt_3_dtable) }, +}; + +/* + * The main dispatch routine. + */ +void +mount_dispatch(struct svc_req *rqstp, SVCXPRT *transp) +{ + union mountd_arguments argument; + union mountd_results result; + +#ifdef HAVE_TCP_WRAPPER + /* remote host authorization check */ + if (!check_default("mountd", nfs_getrpccaller(transp), MOUNTPROG)) { + svcerr_auth (transp, AUTH_FAILED); + return; + } +#endif + + rpc_dispatch(rqstp, transp, dtable, number_of(dtable), + &argument, &result); +} diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c new file mode 100644 index 0000000..dbd5546 --- /dev/null +++ b/utils/mountd/mountd.c @@ -0,0 +1,887 @@ +/* + * utils/mountd/mountd.c + * + * Authenticate mount requests and retrieve file handle. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <signal.h> +#include <sys/stat.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> +#include <errno.h> +#include <fcntl.h> +#include <sys/resource.h> + +#include "conffile.h" +#include "xmalloc.h" +#include "misc.h" +#include "mountd.h" +#include "rpcmisc.h" +#include "pseudoflavors.h" +#include "nfsd_path.h" +#include "nfslib.h" +#include "export.h" + +extern void my_svc_run(void); + +static void usage(const char *, int exitcode); +static exports get_exportlist(void); +static struct nfs_fh_len *get_rootfh(struct svc_req *, dirpath *, nfs_export **, mountstat3 *, int v3); + +int reverse_resolve = 0; +int manage_gids; +int use_ipaddr = -1; + +/* PRC: a high-availability callout program can be specified with -H + * When this is done, the program will receive callouts whenever clients + * send mount or unmount requests -- the callout is not needed for 2.6 kernel */ +char *ha_callout_prog = NULL; + +/* Number of mountd threads to start. Default is 1 and + * that's probably enough unless you need hundreds of + * clients to be able to mount at once. */ +static int num_threads = 1; +/* Arbitrary limit on number of threads */ +#define MAX_THREADS 64 + +static struct option longopts[] = +{ + { "foreground", 0, 0, 'F' }, + { "descriptors", 1, 0, 'o' }, + { "debug", 1, 0, 'd' }, + { "help", 0, 0, 'h' }, + { "nfs-version", 1, 0, 'V' }, + { "no-nfs-version", 1, 0, 'N' }, + { "version", 0, 0, 'v' }, + { "port", 1, 0, 'p' }, + { "no-tcp", 0, 0, 'n' }, + { "ha-callout", 1, 0, 'H' }, + { "state-directory-path", 1, 0, 's' }, + { "num-threads", 1, 0, 't' }, + { "reverse-lookup", 0, 0, 'r' }, + { "manage-gids", 0, 0, 'g' }, + { "no-udp", 0, 0, 'u' }, + { "log-auth", 0, 0, 'l'}, + { "cache-use-ipaddr", 0, 0, 'i'}, + { "ttl", 1, 0, 'T'}, + { NULL, 0, 0, 0 } +}; +static char shortopts[] = "o:nFd:p:P:hH:N:V:vurs:t:gliT:"; + +#define NFSVERSBIT(vers) (0x1 << (vers - 1)) +#define NFSVERSBIT_ALL (NFSVERSBIT(2) | NFSVERSBIT(3) | NFSVERSBIT(4)) + +static int nfs_version = NFSVERSBIT_ALL; + +static int version2(void) +{ + return nfs_version & NFSVERSBIT(2); +} + +static int version3(void) +{ + return nfs_version & NFSVERSBIT(3); +} + +static int version23(void) +{ + return nfs_version & (NFSVERSBIT(2) | NFSVERSBIT(3)); +} + +static int version_any(void) +{ + return nfs_version & NFSVERSBIT_ALL; +} + +static void +unregister_services (void) +{ + nfs_svc_unregister(MOUNTPROG, MOUNTVERS); + nfs_svc_unregister(MOUNTPROG, MOUNTVERS_POSIX); + nfs_svc_unregister(MOUNTPROG, MOUNTVERS_NFSV3); +} + +static void +cleanup_lockfiles (void) +{ + unlink(etab.lockfn); + unlink(rmtab.lockfn); +} + +/* + * Signal handler. + */ +static void +killer (int sig) +{ + unregister_services(); + if (num_threads > 1) { + /* play Kronos and eat our children */ + kill(0, SIGTERM); + cache_wait_for_workers("mountd"); + } + cleanup_lockfiles(); + free_state_path_names(&etab); + free_state_path_names(&rmtab); + xlog (L_NOTICE, "Caught signal %d, un-registering and exiting.", sig); + exit(0); +} + +static void +sig_hup (int UNUSED(sig)) +{ + /* don't exit on SIGHUP */ + xlog (L_NOTICE, "Received SIGHUP... Ignoring.\n"); + return; +} + +bool_t +mount_null_1_svc(struct svc_req *rqstp, void *UNUSED(argp), + void *UNUSED(resp)) +{ + struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); + char buf[INET6_ADDRSTRLEN]; + + xlog(D_CALL, "Received NULL request from %s", + host_ntop(sap, buf, sizeof(buf))); + + return 1; +} + +bool_t +mount_mnt_1_svc(struct svc_req *rqstp, dirpath *path, fhstatus *res) +{ + struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); + char buf[INET6_ADDRSTRLEN]; + struct nfs_fh_len *fh; + + xlog(D_CALL, "Received MNT1(%s) request from %s", *path, + host_ntop(sap, buf, sizeof(buf))); + + fh = get_rootfh(rqstp, path, NULL, &res->fhs_status, 0); + if (fh) + memcpy(&res->fhstatus_u.fhs_fhandle, fh->fh_handle, 32); + return 1; +} + +bool_t +mount_dump_1_svc(struct svc_req *rqstp, void *UNUSED(argp), mountlist *res) +{ + struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); + char buf[INET6_ADDRSTRLEN]; + + xlog(D_CALL, "Received DUMP request from %s", + host_ntop(sap, buf, sizeof(buf))); + + *res = mountlist_list(); + + return 1; +} + +bool_t +mount_umnt_1_svc(struct svc_req *rqstp, dirpath *argp, void *UNUSED(resp)) +{ + struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); + nfs_export *exp; + char *p = *argp; + char rpath[MAXPATHLEN+1]; + char buf[INET6_ADDRSTRLEN]; + + if (*p == '\0') + p = "/"; + + if (nfsd_realpath(p, rpath) != NULL) { + rpath[sizeof (rpath) - 1] = '\0'; + p = rpath; + } + + xlog(D_CALL, "Received UMNT(%s) request from %s", p, + host_ntop(sap, buf, sizeof(buf))); + + exp = auth_authenticate("unmount", sap, p); + if (exp == NULL) + return 1; + + mountlist_del(host_ntop(sap, buf, sizeof(buf)), p); + return 1; +} + +bool_t +mount_umntall_1_svc(struct svc_req *rqstp, void *UNUSED(argp), + void *UNUSED(resp)) +{ + struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); + char buf[INET6_ADDRSTRLEN]; + + xlog(D_CALL, "Received UMNTALL request from %s", + host_ntop(sap, buf, sizeof(buf))); + + /* Reload /etc/exports if necessary */ + auth_reload(); + + mountlist_del_all(nfs_getrpccaller(rqstp->rq_xprt)); + return 1; +} + +bool_t +mount_export_1_svc(struct svc_req *rqstp, void *UNUSED(argp), exports *resp) +{ + struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); + char buf[INET6_ADDRSTRLEN]; + + xlog(D_CALL, "Received EXPORT request from %s.", + host_ntop(sap, buf, sizeof(buf))); + + *resp = get_exportlist(); + + return 1; +} + +bool_t +mount_exportall_1_svc(struct svc_req *rqstp, void *UNUSED(argp), exports *resp) +{ + struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); + char buf[INET6_ADDRSTRLEN]; + + xlog(D_CALL, "Received EXPORTALL request from %s.", + host_ntop(sap, buf, sizeof(buf))); + + *resp = get_exportlist(); + + return 1; +} + +/* + * MNTv2 pathconf procedure + * + * The protocol doesn't include a status field, so Sun apparently considers + * it good practice to let anyone snoop on your system, even if it's + * pretty harmless data such as pathconf. We don't. + * + * Besides, many of the pathconf values don't make much sense on NFS volumes. + * FIFOs and tty device files represent devices on the *client*, so there's + * no point in getting the server's buffer sizes etc. + */ +bool_t +mount_pathconf_2_svc(struct svc_req *rqstp, dirpath *path, ppathcnf *res) +{ + struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); + struct stat stb; + nfs_export *exp; + char rpath[MAXPATHLEN+1]; + char *p = *path; + char buf[INET6_ADDRSTRLEN]; + + memset(res, 0, sizeof(*res)); + + if (*p == '\0') + p = "/"; + + /* Reload /etc/exports if necessary */ + auth_reload(); + + /* Resolve symlinks */ + if (nfsd_realpath(p, rpath) != NULL) { + rpath[sizeof (rpath) - 1] = '\0'; + p = rpath; + } + + xlog(D_CALL, "Received PATHCONF(%s) request from %s", p, + host_ntop(sap, buf, sizeof(buf))); + + /* Now authenticate the intruder... */ + exp = auth_authenticate("pathconf", sap, p); + if (exp == NULL) + return 1; + else if (nfsd_path_stat(p, &stb) < 0) { + xlog(L_WARNING, "can't stat exported dir %s: %s", + p, strerror(errno)); + return 1; + } + + res->pc_link_max = pathconf(p, _PC_LINK_MAX); + res->pc_max_canon = pathconf(p, _PC_MAX_CANON); + res->pc_max_input = pathconf(p, _PC_MAX_INPUT); + res->pc_name_max = pathconf(p, _PC_NAME_MAX); + res->pc_path_max = pathconf(p, _PC_PATH_MAX); + res->pc_pipe_buf = pathconf(p, _PC_PIPE_BUF); + res->pc_vdisable = pathconf(p, _PC_VDISABLE); + + /* Can't figure out what to do with pc_mask */ + res->pc_mask[0] = 0; + res->pc_mask[1] = 0; + + return 1; +} + +/* + * We should advertise the preferred flavours first. (See RFC 2623 + * section 2.7.) We leave that to the administrator, by advertising + * flavours in the order they were listed in /etc/exports. AUTH_NULL is + * dropped from the list to avoid backward compatibility issue with + * older Linux clients, who inspect the list in reversed order. + * + * XXX: It might be more helpful to rearrange these so that flavors + * giving more access (as determined from readonly and id-squashing + * options) come first. (If we decide to do that we should probably do + * that when reading the exports rather than here.) + */ +static void set_authflavors(struct mountres3_ok *ok, nfs_export *exp) +{ + struct sec_entry *s; + static int flavors[SECFLAVOR_COUNT]; + int i = 0; + + for (s = exp->m_export.e_secinfo; s->flav; s++) { + if (s->flav->fnum == AUTH_NULL) + continue; + flavors[i] = s->flav->fnum; + i++; + } + if (i == 0) { + /* default when there is no sec= option: */ + i = 1; + flavors[0] = AUTH_UNIX; + } + ok->auth_flavors.auth_flavors_val = flavors; + ok->auth_flavors.auth_flavors_len = i; +} + +/* + * NFSv3 MOUNT procedure + */ +bool_t +mount_mnt_3_svc(struct svc_req *rqstp, dirpath *path, mountres3 *res) +{ + struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); + struct mountres3_ok *ok = &res->mountres3_u.mountinfo; + char buf[INET6_ADDRSTRLEN]; + nfs_export *exp; + struct nfs_fh_len *fh; + + xlog(D_CALL, "Received MNT3(%s) request from %s", *path, + host_ntop(sap, buf, sizeof(buf))); + + fh = get_rootfh(rqstp, path, &exp, &res->fhs_status, 1); + if (!fh) + return 1; + + ok->fhandle.fhandle3_len = fh->fh_size; + ok->fhandle.fhandle3_val = (char *)fh->fh_handle; + set_authflavors(ok, exp); + return 1; +} + +static struct nfs_fh_len * +get_rootfh(struct svc_req *rqstp, dirpath *path, nfs_export **expret, + mountstat3 *error, int v3) +{ + struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); + struct stat stb, estb; + nfs_export *exp; + struct nfs_fh_len *fh; + char rpath[MAXPATHLEN+1]; + char *p = *path; + char buf[INET6_ADDRSTRLEN]; + + if (*p == '\0') + p = "/"; + + /* Reload /var/lib/nfs/etab if necessary */ + auth_reload(); + + /* Resolve symlinks */ + if (nfsd_realpath(p, rpath) != NULL) { + rpath[sizeof (rpath) - 1] = '\0'; + p = rpath; + } + + /* Now authenticate the intruder... */ + exp = auth_authenticate("mount", sap, p); + if (exp == NULL) { + *error = MNT3ERR_ACCES; + return NULL; + } + if (nfsd_path_stat(p, &stb) < 0) { + xlog(L_WARNING, "can't stat exported dir %s: %s", + p, strerror(errno)); + if (errno == ENOENT) + *error = MNT3ERR_NOENT; + else + *error = MNT3ERR_ACCES; + return NULL; + } + if (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode)) { + xlog(L_WARNING, "%s is not a directory or regular file", p); + *error = MNT3ERR_NOTDIR; + return NULL; + } + if (nfsd_path_stat(exp->m_export.e_path, &estb) < 0) { + xlog(L_WARNING, "can't stat export point %s: %s", + p, strerror(errno)); + *error = MNT3ERR_NOENT; + return NULL; + } + if (estb.st_dev != stb.st_dev + && !(exp->m_export.e_flags & NFSEXP_CROSSMOUNT)) { + xlog(L_WARNING, "request to export directory %s below nearest filesystem %s", + p, exp->m_export.e_path); + *error = MNT3ERR_ACCES; + return NULL; + } + if (exp->m_export.e_mountpoint && + !check_is_mountpoint(exp->m_export.e_mountpoint[0]? + exp->m_export.e_mountpoint: + exp->m_export.e_path, + nfsd_path_lstat)) { + xlog(L_WARNING, "request to export an unmounted filesystem: %s", + p); + *error = MNT3ERR_NOENT; + return NULL; + } + + /* This will be a static private nfs_export with just one + * address. We feed it to kernel then extract the filehandle, + */ + + if (cache_export(exp, p)) { + *error = MNT3ERR_ACCES; + return NULL; + } + fh = cache_get_filehandle(exp, v3?64:32, p); + if (fh == NULL) { + *error = MNT3ERR_ACCES; + return NULL; + } + *error = MNT_OK; + mountlist_add(host_ntop(sap, buf, sizeof(buf)), p); + if (expret) + *expret = exp; + return fh; +} + +static void remove_all_clients(exportnode *e) +{ + struct groupnode *g, *ng; + + for (g = e->ex_groups; g; g = ng) { + ng = g->gr_next; + xfree(g->gr_name); + xfree(g); + } + e->ex_groups = NULL; +} + +static void free_exportlist(exports *elist) +{ + struct exportnode *e, *ne; + + for (e = *elist; e != NULL; e = ne) { + ne = e->ex_next; + remove_all_clients(e); + xfree(e->ex_dir); + xfree(e); + } + *elist = NULL; +} + +static void prune_clients(nfs_export *exp, struct exportnode *e) +{ + struct addrinfo *ai = NULL; + struct groupnode *c, **cp; + + cp = &e->ex_groups; + while ((c = *cp) != NULL) { + if (client_gettype(c->gr_name) == MCL_FQDN + && (ai = host_addrinfo(c->gr_name))) { + if (client_check(exp->m_client, ai)) { + *cp = c->gr_next; + xfree(c->gr_name); + xfree(c); + nfs_freeaddrinfo(ai); + continue; + } + nfs_freeaddrinfo(ai); + } + cp = &(c->gr_next); + } +} + +static exportnode *lookup_or_create_elist_entry(exports *elist, nfs_export *exp) +{ + exportnode *e; + + for (e = *elist; e != NULL; e = e->ex_next) { + if (!strcmp(exp->m_export.e_path, e->ex_dir)) + return e; + } + e = xmalloc(sizeof(*e)); + e->ex_next = *elist; + e->ex_groups = NULL; + e->ex_dir = xstrdup(exp->m_export.e_path); + *elist = e; + return e; +} + +static void insert_group(struct exportnode *e, char *newname) +{ + struct groupnode *g; + + for (g = e->ex_groups; g; g = g->gr_next) + if (!strcmp(g->gr_name, newname)) + return; + + g = xmalloc(sizeof(*g)); + g->gr_name = xstrdup(newname); + g->gr_next = e->ex_groups; + e->ex_groups = g; +} + +static exports +get_exportlist(void) +{ + static exports elist = NULL; + struct exportnode *e; + nfs_export *exp; + int i; + static unsigned int ecounter; + unsigned int acounter; + + acounter = auth_reload(); + if (elist && acounter == ecounter) + return elist; + + ecounter = acounter; + + free_exportlist(&elist); + + for (i = 0; i < MCL_MAXTYPES; i++) { + for (exp = exportlist[i].p_head; exp; exp = exp->m_next) { + /* Don't show pseudo exports */ + if (exp->m_export.e_flags & NFSEXP_V4ROOT) + continue; + e = lookup_or_create_elist_entry(&elist, exp); + + /* exports to "*" absorb any others */ + if (i == MCL_ANONYMOUS && e->ex_groups) { + remove_all_clients(e); + continue; + } + /* non-FQDN's absorb FQDN's they contain: */ + if (i != MCL_FQDN && e->ex_groups) + prune_clients(exp, e); + + if (exp->m_export.e_hostname[0] != '\0') + insert_group(e, exp->m_export.e_hostname); + } + } + + return elist; +} + +int vers; +int port = 0; +int descriptors = 0; + +inline static void +read_mountd_conf(char **argv) +{ + char *s; + int ttl; + + conf_init_file(NFS_CONFFILE); + + xlog_set_debug("mountd"); + manage_gids = conf_get_bool("mountd", "manage-gids", manage_gids); + descriptors = conf_get_num("mountd", "descriptors", descriptors); + port = conf_get_num("mountd", "port", port); + num_threads = conf_get_num("mountd", "threads", num_threads); + reverse_resolve = conf_get_bool("mountd", "reverse-lookup", reverse_resolve); + ha_callout_prog = conf_get_str("mountd", "ha-callout"); + if (conf_get_bool("mountd", "cache-use-ipaddr", 0)) + use_ipaddr = 2; + + s = conf_get_str("mountd", "state-directory-path"); + if (s && !state_setup_basedir(argv[0], s)) + exit(1); + + /* NOTE: following uses "nfsd" section of nfs.conf !!!! */ + if (conf_get_bool("nfsd", "udp", NFSCTL_UDPISSET(_rpcprotobits))) + NFSCTL_UDPSET(_rpcprotobits); + else + NFSCTL_UDPUNSET(_rpcprotobits); + if (conf_get_bool("nfsd", "tcp", NFSCTL_TCPISSET(_rpcprotobits))) + NFSCTL_TCPSET(_rpcprotobits); + else + NFSCTL_TCPUNSET(_rpcprotobits); + for (vers = 2; vers <= 4; vers++) { + char tag[20]; + sprintf(tag, "vers%d", vers); + if (conf_get_bool("nfsd", tag, NFSCTL_VERISSET(nfs_version, vers))) + NFSCTL_VERSET(nfs_version, vers); + else + NFSCTL_VERUNSET(nfs_version, vers); + } + + ttl = conf_get_num("mountd", "ttl", default_ttl); + if (ttl > 0) + default_ttl = ttl; +} + +int +main(int argc, char **argv) +{ + char *progname; + unsigned int listeners = 0; + int foreground = 0; + int c; + int ttl; + struct sigaction sa; + struct rlimit rlim; + + /* Set the basename */ + if ((progname = strrchr(argv[0], '/')) != NULL) + progname++; + else + progname = argv[0]; + + /* Initialize logging. */ + xlog_open(progname); + + /* Read in config setting */ + read_mountd_conf(argv); + + /* Parse the command line options and arguments. */ + opterr = 0; + while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != EOF) + switch (c) { + case 'g': + manage_gids = 1; + break; + case 'o': + descriptors = atoi(optarg); + if (descriptors <= 0) { + fprintf(stderr, "%s: bad descriptors: %s\n", + progname, optarg); + usage(progname, 1); + } + break; + case 'F': + foreground = 1; + break; + case 'd': + xlog_sconfig(optarg, 1); + break; + case 'H': /* PRC: specify a high-availability callout program */ + ha_callout_prog = optarg; + break; + case 'h': + usage(progname, 0); + break; + case 'P': /* XXX for nfs-server compatibility */ + case 'p': + port = atoi(optarg); + if (port <= 0 || port > 65535) { + fprintf(stderr, "%s: bad port number: %s\n", + progname, optarg); + usage(progname, 1); + } + break; + case 'N': + vers = atoi(optarg); + if (vers < 2 || vers > 4) { + fprintf(stderr, "%s: bad version number: %s\n", + argv[0], optarg); + usage(argv[0], 1); + } + nfs_version &= ~NFSVERSBIT(vers); + break; + case 'n': + NFSCTL_TCPUNSET(_rpcprotobits); + break; + case 'r': + reverse_resolve = 1; + break; + case 's': + if (!state_setup_basedir(argv[0], optarg)) + exit(1); + break; + case 't': + num_threads = atoi (optarg); + break; + case 'V': + vers = atoi(optarg); + if (vers < 2 || vers > 4) { + fprintf(stderr, "%s: bad version number: %s\n", + argv[0], optarg); + usage(argv[0], 1); + } + nfs_version |= NFSVERSBIT(vers); + break; + case 'v': + printf("%s version " VERSION "\n", progname); + exit(0); + case 'u': + NFSCTL_UDPUNSET(_rpcprotobits); + break; + case 'l': + xlog_sconfig("auth", 1); + break; + case 'i': + use_ipaddr = 2; + break; + case 'T': + ttl = atoi(optarg); + if (ttl <= 0) { + fprintf(stderr, "%s: bad ttl number of seconds: %s\n", + argv[0], optarg); + usage(argv[0], 1); + } + default_ttl = ttl; + break; + case 0: + break; + case '?': + default: + usage(progname, 1); + } + + /* No more arguments allowed. */ + if (optind != argc || !version_any()) { + fprintf(stderr, "%s: No protocol versions specified!\n", progname); + usage(progname, 1); + } + if (!setup_state_path_names(progname, ETAB, ETABTMP, ETABLCK, &etab)) + return 1; + if (!setup_state_path_names(progname, RMTAB, RMTABTMP, RMTABLCK, &rmtab)) + return 1; + + if (getrlimit (RLIMIT_NOFILE, &rlim) != 0) + fprintf(stderr, "%s: getrlimit (RLIMIT_NOFILE) failed: %s\n", + progname, strerror(errno)); + else { + /* glibc sunrpc code dies if getdtablesize > FD_SETSIZE */ + if ((descriptors == 0 && rlim.rlim_cur > FD_SETSIZE) || + descriptors > FD_SETSIZE) + descriptors = FD_SETSIZE; + if (descriptors) { + rlim.rlim_cur = descriptors; + if (setrlimit (RLIMIT_NOFILE, &rlim) != 0) { + fprintf(stderr, "%s: setrlimit (RLIMIT_NOFILE) failed: %s\n", + progname, strerror(errno)); + exit(1); + } + } + } + if (!foreground) xlog_stderr(0); + + sa.sa_handler = SIG_IGN; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + sigaction(SIGHUP, &sa, NULL); + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + sigaction(SIGPIPE, &sa, NULL); + /* WARNING: the following works on Linux and SysV, but not BSD! */ + sigaction(SIGCHLD, &sa, NULL); + + unregister_services(); + if (version2()) { + listeners += nfs_svc_create("mountd", MOUNTPROG, + MOUNTVERS, mount_dispatch, port); + listeners += nfs_svc_create("mountd", MOUNTPROG, + MOUNTVERS_POSIX, mount_dispatch, port); + } + if (version3()) + listeners += nfs_svc_create("mountd", MOUNTPROG, + MOUNTVERS_NFSV3, mount_dispatch, port); + if (version23() && listeners == 0) + xlog(L_WARNING, "mountd: No V2 or V3 listeners created!"); + + sa.sa_handler = killer; + sigaction(SIGINT, &sa, NULL); + sigaction(SIGTERM, &sa, NULL); + sa.sa_handler = sig_hup; + sigaction(SIGHUP, &sa, NULL); + + if (!foreground) { + /* We first fork off a child. */ + if ((c = fork()) > 0) + exit(0); + if (c < 0) { + xlog(L_FATAL, "mountd: cannot fork: %s\n", + strerror(errno)); + } + /* Now we remove ourselves from the foreground. + Redirect stdin/stdout/stderr first. */ + { + int fd = open("/dev/null", O_RDWR); + (void) dup2(fd, 0); + (void) dup2(fd, 1); + (void) dup2(fd, 2); + if (fd > 2) (void) close(fd); + } + setsid(); + } + + /* silently bounds check num_threads */ + if (foreground) + num_threads = 1; + else if (num_threads < 1) + num_threads = 1; + else if (num_threads > MAX_THREADS) + num_threads = MAX_THREADS; + + /* Open cache channel files BEFORE forking so each upcall is + * only handled by one thread. Kernel provides locking for both + * read and write. + */ + cache_open(); + + if (cache_fork_workers("mountd", num_threads) == 0) { + /* We forked, waited, and now need to clean up */ + unregister_services(); + cleanup_lockfiles(); + free_state_path_names(&etab); + free_state_path_names(&rmtab); + xlog(L_NOTICE, "mountd: no more workers, exiting\n"); + exit(0); + } + + nfsd_path_init(); + v4clients_init(); + + xlog(L_NOTICE, "Version " VERSION " starting"); + my_svc_run(); + + xlog(L_ERROR, "RPC service loop terminated unexpectedly. Exiting...\n"); + unregister_services(); + free_state_path_names(&etab); + free_state_path_names(&rmtab); + exit(1); +} + +static void +usage(const char *prog, int n) +{ + fprintf(stderr, +"Usage: %s [-F|--foreground] [-h|--help] [-v|--version] [-d kind|--debug kind]\n" +" [-l|--log-auth] [-i|--cache-use-ipaddr] [-T|--ttl ttl]\n" +" [-o num|--descriptors num]\n" +" [-p|--port port] [-V version|--nfs-version version]\n" +" [-N version|--no-nfs-version version] [-n|--no-tcp]\n" +" [-H prog |--ha-callout prog] [-r |--reverse-lookup]\n" +" [-s|--state-directory-path path] [-g|--manage-gids]\n" +" [-t num|--num-threads=num] [-u|--no-udp]\n", prog); + exit(n); +} diff --git a/utils/mountd/mountd.h b/utils/mountd/mountd.h new file mode 100644 index 0000000..bd5c957 --- /dev/null +++ b/utils/mountd/mountd.h @@ -0,0 +1,54 @@ +/* + * utils/mountd/mountd.h + * + * Declarations for mountd. + * + * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> + */ + +#ifndef MOUNTD_H +#define MOUNTD_H + +#include <rpc/rpc.h> +#include <rpc/svc.h> +#include "nfslib.h" +#include "exportfs.h" +#include "mount.h" + +union mountd_arguments { + dirpath dirpath; +}; + +union mountd_results { + fhstatus fstatus; + mountlist mountlist; + exports exports; +}; + +/* + * Global Function prototypes. + */ +bool_t mount_null_1_svc(struct svc_req *, void *, void *); +bool_t mount_mnt_1_svc(struct svc_req *, dirpath *, fhstatus *); +bool_t mount_dump_1_svc(struct svc_req *, void *, mountlist *); +bool_t mount_umnt_1_svc(struct svc_req *, dirpath *, void *); +bool_t mount_umntall_1_svc(struct svc_req *, void *, void *); +bool_t mount_export_1_svc(struct svc_req *, void *, exports *); +bool_t mount_exportall_1_svc(struct svc_req *, void *, exports *); +bool_t mount_pathconf_2_svc(struct svc_req *, dirpath *, ppathcnf *); +bool_t mount_mnt_3_svc(struct svc_req *, dirpath *, mountres3 *); + +void mount_dispatch(struct svc_req *, SVCXPRT *); +void auth_init(void); +unsigned int auth_reload(void); +nfs_export * auth_authenticate(const char *what, + const struct sockaddr *caller, + const char *path); +void auth_export(nfs_export *exp); + +void mountlist_add(char *host, const char *path); +void mountlist_del(char *host, const char *path); +void mountlist_del_all(const struct sockaddr *sap); +mountlist mountlist_list(void); + +#endif /* MOUNTD_H */ diff --git a/utils/mountd/mountd.man b/utils/mountd/mountd.man new file mode 100644 index 0000000..a206a3e --- /dev/null +++ b/utils/mountd/mountd.man @@ -0,0 +1,362 @@ +.\"@(#)rpc.mountd.8" +.\" +.\" Copyright (C) 1999 Olaf Kirch <okir@monad.swb.de> +.\" Modified by Paul Clements, 2004. +.\" +.TH rpc.mountd 8 "31 Dec 2009" +.SH NAME +rpc.mountd \- NFS mount daemon +.SH SYNOPSIS +.BI "/usr/sbin/rpc.mountd [" options "]" +.SH DESCRIPTION +The +.B rpc.mountd +daemon implements the server side of the NFS MOUNT protocol, +an NFS side protocol used by NFS version 2 [RFC1094] and NFS version 3 [RFC1813]. +It also responds to requests from the Linux kernel to authenticate +clients and provides details of access permissions. +.PP +The NFS server +.RI ( nfsd ) +maintains a cache of authentication and authorization information which +is used to identify the source of each request, and then what access +permissions that source has to any local filesystem. When required +information is not found in the cache, the server sends a request to +.B mountd +to fill in the missing information. Mountd uses a table of information +stored in +.B /var/lib/nfs/etab +and maintained by +.BR exportfs (8), +possibly based on the contents of +.BR exports (5), +to respond to each request. +.SS Mounting exported NFS File Systems +The NFS MOUNT protocol has several procedures. +The most important of these are +MNT (mount an export) and +UMNT (unmount an export). +.PP +A MNT request has two arguments: an explicit argument that +contains the pathname of the root directory of the export to be mounted, +and an implicit argument that is the sender's IP address. +.PP +When receiving a MNT request from an NFS client, +.B rpc.mountd +checks both the pathname and the sender's IP address against its export table. +If the sender is permitted to access the requested export, +.B rpc.mountd +returns an NFS file handle for the export's root directory to the client. +The client can then use the root file handle and NFS LOOKUP requests +to navigate the directory structure of the export. +.SS The rmtab File +The +.B rpc.mountd +daemon registers every successful MNT request by adding an entry to the +.I /var/lib/nfs/rmtab +file. +When receivng a UMNT request from an NFS client, +.B rpc.mountd +simply removes the matching entry from +.IR /var/lib/nfs/rmtab , +as long as the access control list for that export allows that sender +to access the export. +.PP +Clients can discover the list of file systems an NFS server is +currently exporting, or the list of other clients that have mounted +its exports, by using the +.BR showmount (8) +command. +.BR showmount (8) +uses other procedures in the NFS MOUNT protocol to report information +about the server's exported file systems. +.PP +Note, however, that there is little to guarantee that the contents of +.I /var/lib/nfs/rmtab +are accurate. +A client may continue accessing an export even after invoking UMNT. +If the client reboots without sending a UMNT request, stale entries +remain for that client in +.IR /var/lib/nfs/rmtab . +.SS Mounting File Systems with NFSv4 +Version 4 (and later) of NFS does not use a separate NFS MOUNT +protocol. Instead mounting is performed using regular NFS requests +handled by the NFS server in the Linux kernel +.RI ( nfsd ). +Consequently +.I /var/lib/nfs/rmtab +is not updated to reflect any NFSv4 activity. +.SH OPTIONS +.TP +.B \-d kind " or " \-\-debug kind +Turn on debugging. Valid kinds are: all, auth, call, general and parse. +.TP +.BR \-l " or " \-\-log\-auth +Enable logging of responses to authentication and access requests from +nfsd. Each response is then cached by the kernel for 30 minutes (or as set by +.B \-\-ttl +below), and will be refreshed after 15 minutes (half the ttl time) if +the relevant client remains active. +Note that +.B -l +is equivalent to +.B "-d auth" +and so can be enabled in +.B /etc/nfs.conf +with +.B "\[dq]debug = auth\[dq]" +in the +.B "[mountd]" +section. +.IP +.B rpc.mountd +will always log authentication responses to MOUNT requests when NFSv3 is +used, but to get similar logs for NFSv4, this option is required. +.TP +.BR \-i " or " \-\-cache\-use\-ipaddr +Normally each client IP address is matched against each host identifier +(name, wildcard, netgroup etc) found in +.B /etc/exports +and a combined identity is formed from all matching identifiers. +Often many clients will map to the same combined identity so performing +this mapping reduces the number of distinct access details that the +kernel needs to store. +Specifying the +.B \-i +option suppresses this mapping so that access to each filesystem is +requested and cached separately for each client IP address. Doing this +can increase the burden of updating the cache slightly, but can make the +log messages produced by the +.B -l +option easier to read. +.TP +.B \-T " or " \-\-ttl +Provide a time-to-live (TTL) for cached information given to the kernel. +The kernel will normally request an update if the information is needed +after half of this time has expired. Increasing the provided number, +which is in seconds, reduces the rate of cache update requests, and this +is particularly noticeable when these requests are logged with +.BR \-l . +However increasing also means that changes to hostname to address +mappings can take longer to be noticed. +The default TTL is 1800 (30 minutes). +.TP +.B \-F " or " \-\-foreground +Run in foreground (do not daemonize) +.TP +.B \-h " or " \-\-help +Display usage message. +.TP +.B \-o num " or " \-\-descriptors num +Set the limit of the number of open file descriptors to num. The +default is to leave the limit unchanged. +.TP +.B \-N mountd-version " or " \-\-no-nfs-version mountd-version +This option can be used to request that +.B rpc.mountd +do not offer certain versions of NFS. The current version of +.B rpc.mountd +can support both NFS version 2, 3 and 4. If the +either one of these version should not be offered, +.B rpc.mountd +must be invoked with the option +.B "\-\-no-nfs-version <vers>" . +.TP +.B \-n " or " \-\-no-tcp +Don't advertise TCP for mount. +.TP +.B \-p num " or " \-P num " or " \-\-port num +Specifies the port number used for RPC listener sockets. +If this option is not specified, +.B rpc.mountd +will try to consult +.IR /etc/services , +if gets port succeed, set the same port for all listener socket, +otherwise chooses a random ephemeral port for each listener socket. +.IP +This option can be used to fix the port value of +.BR rpc.mountd 's +listeners when NFS MOUNT requests must traverse a firewall +between clients and servers. +.TP +.B \-H " prog or " \-\-ha-callout prog +Specify a high availability callout program. +This program receives callouts for all MOUNT and UNMOUNT requests. +This allows +.B rpc.mountd +to be used in a High Availability NFS (HA-NFS) environment. +.IP +The callout program is run with 4 arguments. +The first is +.B mount +or +.B unmount +depending on the reason for the callout. +The second will be the name of the client performing the mount. +The third will be the path that the client is mounting. +The last is the number of concurrent mounts that we believe the client +has of that path. +.IP +This callout is not needed with 2.6 and later kernels. +Instead, mount the nfsd filesystem on +.IR /proc/fs/nfsd . +.TP +.BI "\-s," "" " \-\-state\-directory\-path " directory +Specify a directory in which to place state information (etab and rmtab). +If this option is not specified the default of +.I /var/lib/nfs +is used. +.TP +.BI "\-r," "" " \-\-reverse\-lookup" +.B rpc.mountd +tracks IP addresses in the +.I rmtab +file. When a DUMP request is made (by +someone running +.BR "showmount -a" , +for instance), it returns IP addresses instead +of hostnames by default. This option causes +.B rpc.mountd +to perform a reverse lookup on each IP address and return that hostname instead. +Enabling this can have a substantial negative effect on performance +in some situations. +.TP +.BR "\-t N" " or " "\-\-num\-threads=N " or " \-\-num\-threads N " +This option specifies the number of worker threads that rpc.mountd +spawns. The default is 1 thread, which is probably enough. More +threads are usually only needed for NFS servers which need to handle +mount storms of hundreds of NFS mounts in a few seconds, or when +your DNS server is slow or unreliable. +.TP +.B \-u " or " \-\-no-udp +Don't advertise UDP for mounting +.TP +.B \-V version " or " \-\-nfs-version version +This option can be used to request that +.B rpc.mountd +offer certain versions of NFS. The current version of +.B rpc.mountd +can support both NFS version 2 and the newer version 3. +.TP +.B \-v " or " \-\-version +Print the version of +.B rpc.mountd +and exit. +.TP +.B \-g " or " \-\-manage-gids +Accept requests from the kernel to map user id numbers into lists of +group id numbers for use in access control. An NFS request will +normally (except when using Kerberos or other cryptographic +authentication) contains a user-id and a list of group-ids. Due to a +limitation in the NFS protocol, at most 16 groups ids can be listed. +If you use the +.B \-g +flag, then the list of group ids received from the client will be +replaced by a list of group ids determined by an appropriate lookup on +the server. Note that the 'primary' group id is not affected so a +.B newgroup +command on the client will still be effective. This function requires +a Linux Kernel with version at least 2.6.21. + +.SH CONFIGURATION FILE +Many of the options that can be set on the command line can also be +controlled through values set in the +.B [mountd] +or, in some cases, the +.B [nfsd] +sections of the +.I /etc/nfs.conf +configuration file. +Values recognized in the +.B [mountd] +section include +.BR manage-gids , +.BR cache\-use\-ipaddr , +.BR descriptors , +.BR port , +.BR threads , +.BR ttl , +.BR reverse-lookup ", and" +.BR state-directory-path , +.B ha-callout +which each have the same effect as the option with the same name. + +The values recognized in the +.B [nfsd] +section include +.BR TCP , +.BR UDP , +.BR vers3 ", and" +.B vers4 +which each have the same meaning as given by +.BR rpc.nfsd (8). + +.SH TCP_WRAPPERS SUPPORT +You can protect your +.B rpc.mountd +listeners using the +.B tcp_wrapper +library or +.BR iptables (8). +.PP +Note that the +.B tcp_wrapper +library supports only IPv4 networking. +.PP +Add the hostnames of NFS peers that are allowed to access +.B rpc.mountd +to +.IR /etc/hosts.allow . +Use the daemon name +.B mountd +even if the +.B rpc.mountd +binary has a different name. +.PP +Hostnames used in either access file will be ignored when +they can not be resolved into IP addresses. +For further information see the +.BR tcpd (8) +and +.BR hosts_access (5) +man pages. +.SS IPv6 and TI-RPC support +TI-RPC is a pre-requisite for supporting NFS on IPv6. +If TI-RPC support is built into +.BR rpc.mountd , +it attempts to start listeners on network transports marked 'visible' in +.IR /etc/netconfig . +As long as at least one network transport listener starts successfully, +.B rpc.mountd +will operate. +.SH FILES +.TP 2.5i +.I /etc/exports +input file for +.BR exportfs , +listing exports, export options, and access control lists +.TP 2.5i +.I /var/lib/nfs/rmtab +table of clients accessing server's exports +.SH SEE ALSO +.BR exportfs (8), +.BR exports (5), +.BR showmount (8), +.BR rpc.nfsd (8), +.BR rpc.rquotad (8), +.BR nfs (5), +.BR nfs.conf (5), +.BR tcpd (8), +.BR hosts_access (5), +.BR iptables (8), +.BR netconfig (5) +.sp +RFC 1094 - "NFS: Network File System Protocol Specification" +.br +RFC 1813 - "NFS Version 3 Protocol Specification" +.br +RFC 7530 - "Network File System (NFS) Version 4 Protocol" +.br +RFC 8881 - "Network File System (NFS) Version 4 Minor Version 1 Protocol" +.SH AUTHOR +Olaf Kirch, H. J. Lu, G. Allan Morris III, and a host of others. diff --git a/utils/mountd/rmtab.c b/utils/mountd/rmtab.c new file mode 100644 index 0000000..752fdb6 --- /dev/null +++ b/utils/mountd/rmtab.c @@ -0,0 +1,254 @@ +/* + * utils/mountd/rmtab.c + * + * Manage the rmtab file for mountd. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> + +#include "misc.h" +#include "exportfs.h" +#include "xio.h" +#include "mountd.h" +#include "ha-callout.h" + +#include <limits.h> /* PATH_MAX */ +#include <errno.h> + +extern int reverse_resolve; + +/* If new path is a link do not destroy it but place the + * file where the link points. + */ + +static int +slink_safe_rename(const char * oldpath, const char * newpath) +{ + int r; + struct stat s; + char slink_path[PATH_MAX]; + const char *real_newpath = newpath; + + if ((lstat(newpath, &s) == 0) && S_ISLNK(s.st_mode)) { + /* New path is a symbolic link, do not destroy but follow */ + if ((r = readlink(newpath, slink_path, PATH_MAX - 1)) == -1) + return -1; + slink_path[r] = '\0'; + real_newpath = slink_path; + } + + return rename(oldpath, real_newpath); +} + +void +mountlist_add(char *host, const char *path) +{ + struct rmtabent xe; + struct rmtabent *rep; + int lockid; + long pos; + + if ((lockid = xflock(rmtab.lockfn, "a")) < 0) + return; + setrmtabent("r+"); + while ((rep = getrmtabent(1, &pos)) != NULL) { + if (strcmp (rep->r_client, + host) == 0 + && strcmp(rep->r_path, path) == 0) { + rep->r_count++; + /* PRC: do the HA callout: */ + ha_callout("mount", rep->r_client, rep->r_path, rep->r_count); + putrmtabent(rep, &pos); + endrmtabent(); + xfunlock(lockid); + return; + } + } + endrmtabent(); + strncpy(xe.r_client, host, + sizeof (xe.r_client) - 1); + xe.r_client [sizeof (xe.r_client) - 1] = '\0'; + strncpy(xe.r_path, path, sizeof (xe.r_path) - 1); + xe.r_path [sizeof (xe.r_path) - 1] = '\0'; + xe.r_count = 1; + if (setrmtabent("a")) { + /* PRC: do the HA callout: */ + ha_callout("mount", xe.r_client, xe.r_path, xe.r_count); + putrmtabent(&xe, NULL); + endrmtabent(); + } + xfunlock(lockid); +} + +void +mountlist_del(char *hname, const char *path) +{ + struct rmtabent *rep; + FILE *fp; + int lockid; + int match; + + if ((lockid = xflock(rmtab.lockfn, "w")) < 0) + return; + if (!setrmtabent("r")) { + xfunlock(lockid); + return; + } + if (!(fp = fsetrmtabent(rmtab.tmpfn, "w"))) { + endrmtabent(); + xfunlock(lockid); + return; + } + while ((rep = getrmtabent(1, NULL)) != NULL) { + match = !strcmp (rep->r_client, hname) + && !strcmp(rep->r_path, path); + if (match) { + rep->r_count--; + /* PRC: do the HA callout: */ + ha_callout("unmount", rep->r_client, rep->r_path, rep->r_count); + } + if (!match || rep->r_count) + fputrmtabent(fp, rep, NULL); + } + if (slink_safe_rename(rmtab.tmpfn, rmtab.statefn) < 0) { + xlog(L_ERROR, "couldn't rename %s to %s", + rmtab.tmpfn, rmtab.statefn); + } + endrmtabent(); /* close & unlink */ + fendrmtabent(fp); + xfunlock(lockid); +} + +void +mountlist_del_all(const struct sockaddr *sap) +{ + char *hostname; + struct rmtabent *rep; + FILE *fp; + int lockid; + + if ((lockid = xflock(rmtab.lockfn, "w")) < 0) + return; + hostname = host_canonname(sap); + if (hostname == NULL) { + char buf[INET6_ADDRSTRLEN]; + xlog(L_ERROR, "can't get hostname of %s", + host_ntop(sap, buf, sizeof(buf))); + goto out_unlock; + } + + if (!setrmtabent("r")) + goto out_free; + + if (!(fp = fsetrmtabent(rmtab.tmpfn, "w"))) + goto out_close; + + while ((rep = getrmtabent(1, NULL)) != NULL) { + if (strcmp(rep->r_client, hostname) == 0 && + auth_authenticate("umountall", sap, rep->r_path) != NULL) + continue; + fputrmtabent(fp, rep, NULL); + } + if (slink_safe_rename(rmtab.tmpfn, rmtab.statefn) < 0) { + xlog(L_ERROR, "couldn't rename %s to %s", + rmtab.tmpfn, rmtab.statefn); + } + fendrmtabent(fp); +out_close: + endrmtabent(); /* close & unlink */ +out_free: + free(hostname); +out_unlock: + xfunlock(lockid); +} + +static void +mountlist_freeall(mountlist list) +{ + while (list != NULL) { + mountlist m = list; + list = m->ml_next; + free(m->ml_hostname); + free(m->ml_directory); + free(m); + } +} + +mountlist +mountlist_list(void) +{ + static mountlist mlist = NULL; + static time_t last_mtime = 0; + mountlist m; + struct rmtabent *rep; + struct stat stb; + int lockid; + + if ((lockid = xflock(rmtab.lockfn, "r")) < 0) + return NULL; + if (stat(rmtab.statefn, &stb) < 0) { + xlog(L_ERROR, "can't stat %s: %s", + rmtab.statefn, strerror(errno)); + xfunlock(lockid); + return NULL; + } + if (stb.st_mtime != last_mtime) { + mountlist_freeall(mlist); + mlist = NULL; + last_mtime = stb.st_mtime; + + setrmtabent("r"); + while ((rep = getrmtabent(1, NULL)) != NULL) { + m = calloc(1, sizeof(*m)); + if (m == NULL) { + mountlist_freeall(mlist); + mlist = NULL; + xlog(L_ERROR, "%s: memory allocation failed", + __func__); + break; + } + + if (reverse_resolve) { + struct addrinfo *ai; + ai = host_pton(rep->r_client); + if (ai != NULL) { + m->ml_hostname = host_canonname(ai->ai_addr); + nfs_freeaddrinfo(ai); + } + } + if (m->ml_hostname == NULL) + m->ml_hostname = strdup(rep->r_client); + + m->ml_directory = strdup(rep->r_path); + + if (m->ml_hostname == NULL || m->ml_directory == NULL) { + free(m->ml_hostname); + free(m->ml_directory); + free(m); + mountlist_freeall(mlist); + mlist = NULL; + xlog(L_ERROR, "%s: memory allocation failed", + __func__); + break; + } + + m->ml_next = mlist; + mlist = m; + } + endrmtabent(); + } + xfunlock(lockid); + + return mlist; +} diff --git a/utils/mountd/svc_run.c b/utils/mountd/svc_run.c new file mode 100644 index 0000000..2aaf375 --- /dev/null +++ b/utils/mountd/svc_run.c @@ -0,0 +1,109 @@ +/* + * Copyright (C) 1984 Sun Microsystems, Inc. + * Based on svc_run.c from statd which claimed: + * Modified by Jeffrey A. Uphoff, 1995, 1997-1999. + * Modified by Olaf Kirch, 1996. + * + */ + +/* + * Copyright (c) 2009, Sun Microsystems, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * - Neither the name of Sun Microsystems, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Allow svc_run to listen to other file descriptors as well + */ + +/* + * This is the RPC server side idle loop. + * Wait for input, call server program. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <sys/types.h> +#include <rpc/rpc.h> +#include "xlog.h" +#include <errno.h> +#include <time.h> + +#ifdef HAVE_LIBTIRPC +#include <rpc/rpc_com.h> +#endif +#include "export.h" + +void my_svc_run(void); + +#if defined(__GLIBC__) && LONG_MAX != INT_MAX +/* bug in glibc 2.3.6 and earlier, we need + * our own svc_getreqset + */ +static void +my_svc_getreqset (fd_set *readfds) +{ + fd_mask mask; + fd_mask *maskp; + int setsize; + int sock; + int bit; + + setsize = _rpc_dtablesize (); + if (setsize > FD_SETSIZE) + setsize = FD_SETSIZE; + maskp = readfds->fds_bits; + for (sock = 0; sock < setsize; sock += NFDBITS) + for (mask = *maskp++; + (bit = ffsl (mask)); + mask ^= (1L << (bit - 1))) + svc_getreq_common (sock + bit - 1); +} +#define svc_getreqset my_svc_getreqset + +#endif + +/* + * The heart of the server. A crib from libc for the most part... + */ +void +my_svc_run(void) +{ + fd_set readfds; + int selret; + + for (;;) { + readfds = svc_fdset; + selret = cache_process(&readfds); + if (selret < 0) { + xlog(L_ERROR, "my_svc_run() - select: %m"); + return; + } + if (selret) + svc_getreqset(&readfds); + } +} |