Updated to latest upstream version: 1.1.5
This commit is contained in:
parent
a4989af149
commit
f76c8ecabe
@ -14,3 +14,4 @@ nfs-utils-1.1.1.tar.bz2
|
||||
nfs-utils-1.1.2.tar.bz2
|
||||
nfs-utils-1.1.3.tar.bz2
|
||||
nfs-utils-1.1.4.tar.bz2
|
||||
nfs-utils-1.1.5.tar.bz2
|
||||
|
@ -1,142 +0,0 @@
|
||||
commit aee8b1ab778f8e07b30305f10d4f9427023e314d
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Wed Jan 7 12:06:14 2009 -0500
|
||||
|
||||
configure: Remove inet_ntop(3) check from configure.ac
|
||||
|
||||
nfs-utils no longer uses inet_ntop(3) so remove checks for it from
|
||||
configure.ac.
|
||||
|
||||
commit ba05418f589c2d01f4e7e44c70d4844f43511927
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Wed Jan 7 12:18:11 2009 -0500
|
||||
|
||||
configure: Add new build option "--enable-tirpc"
|
||||
|
||||
Allow easier testing of nfs-utils in legacy environments by providing
|
||||
a "configure" option to force the build not to use libtirpc, even if
|
||||
it's present on the build system. This can also be tried as a
|
||||
fallback if problems are found with the new TI-RPC-based nfs-utils
|
||||
code.
|
||||
|
||||
The new option is:
|
||||
|
||||
--enable-tirpc enable use of TI-RPC [default=no]
|
||||
|
||||
Build option matrix:
|
||||
|
||||
--disable-tirpc --disable-ipv6 Default; IPv4 only, glibc RPC
|
||||
--disable-tirpc --enable-ipv6 'configure' will fail
|
||||
--enable-tirpc --disable-ipv6 IPv4 only, TI-RPC
|
||||
--enable-tirpc --enable-ipv6 IPv4 and IPv6, TI-RPC
|
||||
|
||||
commit 29ac873f9024c8fcbca38ab09ba54cda3765b746
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Wed Jan 7 12:33:09 2009 -0500
|
||||
|
||||
showmount command: Quiesce warning when TI-RPC is disabled
|
||||
|
||||
Make sure nfs_sm_pgmtbl is not compiled if TI-RPC functions are not
|
||||
available. This quiesces the following compiler warning:
|
||||
|
||||
showmount.c:53: warning: nfs_sm_pgmtbl defined but not used
|
||||
|
||||
diff -up nfs-utils-1.1.4/configure.ac.save nfs-utils-1.1.4/configure.ac
|
||||
--- nfs-utils-1.1.4/configure.ac.save 2009-01-07 12:52:29.000000000 -0500
|
||||
+++ nfs-utils-1.1.4/configure.ac 2009-01-07 12:52:50.000000000 -0500
|
||||
@@ -131,6 +131,14 @@ AC_ARG_ENABLE(ipv6,
|
||||
AC_SUBST(enable_ipv6)
|
||||
AM_CONDITIONAL(CONFIG_IPV6, [test "$enable_ipv6" = "yes"])
|
||||
|
||||
+AC_ARG_ENABLE(tirpc,
|
||||
+ [AC_HELP_STRING([--enable-tirpc],
|
||||
+ [enable use of TI-RPC @<:@default=no@:>@])],
|
||||
+ enable_tirpc=$enableval,
|
||||
+ enable_tirpc=no)
|
||||
+ AC_SUBST(enable_tirpc)
|
||||
+ AM_CONDITIONAL(CONFIG_TIRPC, [test "$enable_tirpc" = "yes"])
|
||||
+
|
||||
# Check whether user wants TCP wrappers support
|
||||
AC_TCP_WRAPPERS
|
||||
|
||||
@@ -251,15 +259,22 @@ AC_CHECK_DECL([AI_ADDRCONFIG],
|
||||
[Define this to 1 if AI_ADDRCONFIG macro is defined]), ,
|
||||
[ #include <netdb.h> ] )
|
||||
|
||||
+if test "$enable_tirpc" = yes; then
|
||||
+ AC_CHECK_LIB(tirpc, clnt_tli_create, ,
|
||||
+ AC_MSG_ERROR([libtirpc not found.]))
|
||||
+ AC_CHECK_HEADERS(tirpc/netconfig.h, ,
|
||||
+ AC_MSG_ERROR([libtirpc headers not found.]))
|
||||
+ AC_CHECK_FUNCS([bindresvport_sa getnetconfig \
|
||||
+ clnt_create clnt_create_timed \
|
||||
+ clnt_vc_create clnt_dg_create xdr_rpcb])
|
||||
+fi
|
||||
+
|
||||
if test "$enable_ipv6" = yes; then
|
||||
- AC_CHECK_FUNC(inet_ntop, , ,
|
||||
- AC_MSG_ERROR(Function 'inet_ntop' not found.))
|
||||
+ if test "$enable_tirpc" = no; then
|
||||
+ AC_MSG_ERROR('--enable-ipv6' requires '--enable-tirpc'.)
|
||||
+ fi
|
||||
AC_CHECK_FUNC(getnameinfo, , ,
|
||||
AC_MSG_ERROR(Function 'getnameinfo' not found.))
|
||||
- AC_CHECK_LIB(tirpc, clnt_tli_create, ,
|
||||
- AC_MSG_ERROR([libtirpc needed for IPv6 support]))
|
||||
- AC_CHECK_HEADERS(tirpc/netconfig.h, ,
|
||||
- AC_MSG_ERROR([libtirpc headers needed for IPv6 support]))
|
||||
AC_CHECK_DECL([AI_ADDRCONFIG], ,
|
||||
AC_MSG_ERROR([full getaddrinfo(3) implementation needed for IPv6 support]),
|
||||
[ #include <netdb.h> ] )
|
||||
@@ -273,7 +288,7 @@ AC_CHECK_HEADERS([arpa/inet.h fcntl.h li
|
||||
stdlib.h string.h sys/file.h sys/ioctl.h sys/mount.h \
|
||||
sys/param.h sys/socket.h sys/time.h sys/vfs.h \
|
||||
syslog.h unistd.h com_err.h et/com_err.h \
|
||||
- ifaddrs.h tirpc/netconfig.h])
|
||||
+ ifaddrs.h])
|
||||
|
||||
dnl *************************************************************
|
||||
dnl Checks for typedefs, structures, and compiler characteristics
|
||||
@@ -309,10 +324,7 @@ AC_FUNC_STAT
|
||||
AC_FUNC_VPRINTF
|
||||
AC_CHECK_FUNCS([alarm atexit dup2 fdatasync ftruncate getcwd \
|
||||
gethostbyaddr gethostbyname gethostname getmntent \
|
||||
- inet_ntop getnameinfo getrpcbyname \
|
||||
- bindresvport_sa getnetconfig \
|
||||
- clnt_create clnt_create_timed \
|
||||
- clnt_tli_create clnt_vc_create clnt_dg_create xdr_rpcb \
|
||||
+ getnameinfo getrpcbyname \
|
||||
gettimeofday hasmntopt inet_ntoa innetgr memset mkdir pathconf \
|
||||
realpath rmdir select socket strcasecmp strchr strdup \
|
||||
strerror strrchr strtol strtoul sigprocmask])
|
||||
diff -up nfs-utils-1.1.4/utils/showmount/showmount.c.save nfs-utils-1.1.4/utils/showmount/showmount.c
|
||||
--- nfs-utils-1.1.4/utils/showmount/showmount.c.save 2009-01-07 12:53:26.000000000 -0500
|
||||
+++ nfs-utils-1.1.4/utils/showmount/showmount.c 2009-01-07 12:53:37.000000000 -0500
|
||||
@@ -50,13 +50,6 @@ static int aflag = 0;
|
||||
static int dflag = 0;
|
||||
static int eflag = 0;
|
||||
|
||||
-static const char *nfs_sm_pgmtbl[] = {
|
||||
- "showmount",
|
||||
- "mount",
|
||||
- "mountd",
|
||||
- NULL,
|
||||
-};
|
||||
-
|
||||
static struct option longopts[] =
|
||||
{
|
||||
{ "all", 0, 0, 'a' },
|
||||
@@ -87,6 +80,13 @@ static void usage(FILE *fp, int n)
|
||||
|
||||
#ifdef HAVE_CLNT_CREATE
|
||||
|
||||
+static const char *nfs_sm_pgmtbl[] = {
|
||||
+ "showmount",
|
||||
+ "mount",
|
||||
+ "mountd",
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
/*
|
||||
* Generate an RPC client handle connected to the mountd service
|
||||
* at @hostname, or die trying.
|
@ -1,11 +0,0 @@
|
||||
--- nfs-utils-1.1.4/configure.ac.orig 2009-01-06 12:27:23.944023000 -0500
|
||||
+++ nfs-utils-1.1.4/configure.ac 2009-01-06 12:29:43.128014000 -0500
|
||||
@@ -109,7 +109,7 @@ AC_ARG_WITH(rpcgen,
|
||||
AC_SUBST(RPCGEN_PATH)
|
||||
AM_CONDITIONAL(CONFIG_RPCGEN, [test "$RPCGEN_PATH" == ""])
|
||||
AC_ARG_ENABLE(uuid,
|
||||
- [AC_HELP_STRING([--without-uuid], [Exclude uuid support and so avoid possibly buggy libblkid])],
|
||||
+ [AC_HELP_STRING([--disable-uuid], [Exclude uuid support to avoid buggy libblkid])],
|
||||
if test "$enableval" = "yes" ; then choose_blkid=yes; else choose_blkid=no; fi,
|
||||
choose_blkid=default)
|
||||
AC_ARG_ENABLE(mount,
|
@ -1,64 +0,0 @@
|
||||
commit 38667906c89d6944faaced7fbcda027643dc10ad
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Wed Mar 4 15:54:39 2009 -0500
|
||||
|
||||
configure: fix AC_CACHE_VAL warnings on Fedora 10
|
||||
|
||||
Autoconf 2.63 (and maybe earlier releases) complains about the cache
|
||||
variable name used in aclocal/libblkid.m4:
|
||||
|
||||
configure.ac:217: warning: AC_CACHE_VAL(libblkid_is_recent, ...):
|
||||
suspicious cache-id, must contain _cv_ to be cached
|
||||
../../lib/autoconf/general.m4:1974: AC_CACHE_VAL is expanded from...
|
||||
aclocal/libblkid.m4:2: AC_BLKID_VERS is expanded from...
|
||||
configure.ac:217: the top level
|
||||
|
||||
This addresses
|
||||
https://bugzilla.redhat.com/attachment.cgi?bugid=481386 .
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff --git a/aclocal/libblkid.m4 b/aclocal/libblkid.m4
|
||||
index d751a8c..10824e9 100644
|
||||
--- a/aclocal/libblkid.m4
|
||||
+++ b/aclocal/libblkid.m4
|
||||
@@ -1,7 +1,7 @@
|
||||
dnl *************************** libblkid needs version 1.40 or later ***********************
|
||||
AC_DEFUN([AC_BLKID_VERS], [
|
||||
AC_MSG_CHECKING(for suitable libblkid version)
|
||||
- AC_CACHE_VAL(libblkid_is_recent,
|
||||
+ AC_CACHE_VAL([libblkid_cv_is_recent],
|
||||
[
|
||||
saved_LIBS="$LIBS"
|
||||
LIBS=-lblkid
|
||||
@@ -12,9 +12,8 @@ AC_DEFUN([AC_BLKID_VERS], [
|
||||
int vers = blkid_get_library_version(0, 0);
|
||||
return vers >= 140 ? 0 : 1;
|
||||
}
|
||||
- ], libblkid_is_recent=yes, libblkid_is_recent=no,
|
||||
- libblkid_is_recent=unknown)
|
||||
- LIBS="$saved_LIBS"
|
||||
- ])dnl
|
||||
- AC_MSG_RESULT($libblkid_is_recent)
|
||||
+ ], [libblkid_cv_is_recent=yes], [libblkid_cv_is_recent=no],
|
||||
+ [libblkid_cv_is_recent=unknown])
|
||||
+ LIBS="$saved_LIBS"])
|
||||
+ AC_MSG_RESULT($libblkid_cv_is_recent)
|
||||
])dnl
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index c8508f1..4fd111f 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -219,9 +219,9 @@ if test "$choose_blkid" != no; then
|
||||
AC_BLKID_VERS
|
||||
if test $choose_blkid = yes; then
|
||||
use_blkid=1
|
||||
- test $libblkid_is_recent = no && AC_MSG_WARN([libblkid is old and may cause mountd to leak memory])
|
||||
+ test $libblkid_cv_is_recent = no && AC_MSG_WARN([libblkid is old and may cause mountd to leak memory])
|
||||
else
|
||||
- if test $libblkid_is_recent = yes
|
||||
+ if test $libblkid_cv_is_recent = yes
|
||||
then use_blkid=1
|
||||
else use_blkid=0
|
||||
AC_MSG_WARN([uuid support disabled as libblkid is too old])
|
@ -1,357 +0,0 @@
|
||||
commit 4cacc965afc4fb03a465ffcc6cb3078aeadc3818
|
||||
Author: Tomas Richter <krik3t@gmail.com>
|
||||
Date: Wed Feb 18 13:33:27 2009 -0500
|
||||
|
||||
Exportfs and rpc.mountd optimalization
|
||||
|
||||
There were some problems with exportfs and rpc.mountd for long export
|
||||
lists - see https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=76643
|
||||
I do optimalization as my bachelors thesis (Facuulty of informatics,
|
||||
Masaryk's university Brno, Czech Republic), under lead of Yenya
|
||||
Kasprzak.
|
||||
|
||||
Both exportfs and rpc.mount build linked list of exports (shared
|
||||
functions in export.c). Every time they are inserting new export into
|
||||
list, they search for same export in list.
|
||||
I replaced linked list by hash table and functions export_add and
|
||||
export_lookup by functions hash_export_add and hash_export_lookup
|
||||
(export.c).
|
||||
|
||||
Because some other functions required exportlist as linked list, hash
|
||||
table has some implementation modification im comparison with ordinary
|
||||
hash table. It also keeps exports in linked list and has pointer to
|
||||
head of the list. So there's no need of implementation function
|
||||
<for_all_in_hash_table>.
|
||||
|
||||
Signed-off-by: Tomas Richter <krik3t@gmail.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff -up nfs-utils-1.1.4/support/export/export.c.orig nfs-utils-1.1.4/support/export/export.c
|
||||
--- nfs-utils-1.1.4/support/export/export.c.orig 2008-10-17 10:20:09.000000000 -0400
|
||||
+++ nfs-utils-1.1.4/support/export/export.c 2009-02-18 19:42:13.000000000 -0500
|
||||
@@ -19,7 +19,8 @@
|
||||
#include "nfslib.h"
|
||||
#include "exportfs.h"
|
||||
|
||||
-nfs_export *exportlist[MCL_MAXTYPES] = { NULL, };
|
||||
+exp_hash_table exportlist[MCL_MAXTYPES] = {{NULL, {{NULL,NULL}, }}, };
|
||||
+static int export_hash(char *);
|
||||
|
||||
static void export_init(nfs_export *exp, nfs_client *clp,
|
||||
struct exportent *nep);
|
||||
@@ -125,22 +126,35 @@ export_dup(nfs_export *exp, struct hoste
|
||||
|
||||
return new;
|
||||
}
|
||||
-
|
||||
-void
|
||||
+/*
|
||||
+ * Add export entry to hash table
|
||||
+ */
|
||||
+void
|
||||
export_add(nfs_export *exp)
|
||||
{
|
||||
- nfs_export **epp;
|
||||
- int type = exp->m_client->m_type;
|
||||
- int slen = strlen(exp->m_export.e_path);
|
||||
-
|
||||
- if (type < 0 || type >= MCL_MAXTYPES)
|
||||
- xlog(L_FATAL, "unknown client type in export_add");
|
||||
-
|
||||
- epp = exportlist + type;
|
||||
- while (*epp && slen <= strlen((*epp)->m_export.e_path))
|
||||
- epp = &((*epp)->m_next);
|
||||
- exp->m_next = *epp;
|
||||
- *epp = exp;
|
||||
+ exp_hash_table *p_tbl;
|
||||
+ exp_hash_entry *p_hen;
|
||||
+ nfs_export *p_next;
|
||||
+
|
||||
+ int type = exp->m_client->m_type;
|
||||
+ int pos;
|
||||
+
|
||||
+ pos = export_hash(exp->m_export.e_path);
|
||||
+ p_tbl = &(exportlist[type]); /* pointer to hash table */
|
||||
+ p_hen = &(p_tbl->entries[pos]); /* pointer to hash table entry */
|
||||
+
|
||||
+ if (!(p_hen->p_first)) { /* hash table entry is empty */
|
||||
+ p_hen->p_first = exp;
|
||||
+ p_hen->p_last = exp;
|
||||
+
|
||||
+ exp->m_next = p_tbl->p_head;
|
||||
+ p_tbl->p_head = exp;
|
||||
+ } else { /* hash table entry is NOT empty */
|
||||
+ p_next = p_hen->p_last->m_next;
|
||||
+ p_hen->p_last->m_next = exp;
|
||||
+ exp->m_next = p_next;
|
||||
+ p_hen->p_last = exp;
|
||||
+ }
|
||||
}
|
||||
|
||||
nfs_export *
|
||||
@@ -150,7 +164,7 @@ export_find(struct hostent *hp, char *pa
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MCL_MAXTYPES; i++) {
|
||||
- for (exp = exportlist[i]; exp; exp = exp->m_next) {
|
||||
+ for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
|
||||
if (!export_check(exp, hp, path))
|
||||
continue;
|
||||
if (exp->m_client->m_type == MCL_FQDN)
|
||||
@@ -169,7 +183,7 @@ export_allowed_internal (struct hostent
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MCL_MAXTYPES; i++) {
|
||||
- for (exp = exportlist[i]; exp; exp = exp->m_next) {
|
||||
+ for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
|
||||
if (!exp->m_mayexport ||
|
||||
!export_check(exp, hp, path))
|
||||
continue;
|
||||
@@ -207,17 +221,30 @@ export_allowed(struct hostent *hp, char
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Search hash table for export entry.
|
||||
+ */
|
||||
nfs_export *
|
||||
-export_lookup(char *hname, char *path, int canonical)
|
||||
+export_lookup(char *hname, char *path, int canonical)
|
||||
{
|
||||
- nfs_client *clp;
|
||||
- nfs_export *exp;
|
||||
+ nfs_client *clp;
|
||||
+ nfs_export *exp;
|
||||
+ exp_hash_entry *p_hen;
|
||||
+
|
||||
+ int pos;
|
||||
|
||||
- if (!(clp = client_lookup(hname, canonical)))
|
||||
+ clp = client_lookup(hname, canonical);
|
||||
+ if(clp == NULL)
|
||||
return NULL;
|
||||
- for (exp = exportlist[clp->m_type]; exp; exp = exp->m_next)
|
||||
- if (exp->m_client == clp && !strcmp(exp->m_export.e_path, path))
|
||||
- return exp;
|
||||
+
|
||||
+ pos = export_hash(path);
|
||||
+ p_hen = &(exportlist[clp->m_type].entries[pos]);
|
||||
+ for(exp = p_hen->p_first; exp && (exp != p_hen->p_last->m_next);
|
||||
+ exp = exp->m_next) {
|
||||
+ if (exp->m_client == clp && !strcmp(exp->m_export.e_path, path)) {
|
||||
+ return exp;
|
||||
+ }
|
||||
+ }
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -234,10 +261,10 @@ void
|
||||
export_freeall(void)
|
||||
{
|
||||
nfs_export *exp, *nxt;
|
||||
- int i;
|
||||
+ int i, j;
|
||||
|
||||
for (i = 0; i < MCL_MAXTYPES; i++) {
|
||||
- for (exp = exportlist[i]; exp; exp = nxt) {
|
||||
+ for (exp = exportlist[i].p_head; exp; exp = nxt) {
|
||||
nxt = exp->m_next;
|
||||
client_release(exp->m_client);
|
||||
if (exp->m_export.e_squids)
|
||||
@@ -251,7 +278,40 @@ export_freeall(void)
|
||||
xfree(exp->m_export.e_hostname);
|
||||
xfree(exp);
|
||||
}
|
||||
- exportlist[i] = NULL;
|
||||
+ for(j = 0; j < HASH_TABLE_SIZE; j++) {
|
||||
+ exportlist[i].entries[j].p_first = NULL;
|
||||
+ exportlist[i].entries[j].p_last = NULL;
|
||||
+ }
|
||||
+ exportlist[i].p_head = NULL;
|
||||
}
|
||||
client_freeall();
|
||||
}
|
||||
+
|
||||
+/*
|
||||
+ * Compute and returns integer from string.
|
||||
+ * Note: Its understood the smae integers can be same for
|
||||
+ * different strings, but it should not matter.
|
||||
+ */
|
||||
+static unsigned int
|
||||
+strtoint(char *str)
|
||||
+{
|
||||
+ int i = 0;
|
||||
+ unsigned int n = 0;
|
||||
+
|
||||
+ while ( str[i] != '\0') {
|
||||
+ n+=((int)str[i])*i;
|
||||
+ i++;
|
||||
+ }
|
||||
+ return n;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Hash function
|
||||
+ */
|
||||
+static int
|
||||
+export_hash(char *str)
|
||||
+{
|
||||
+ int num = strtoint(str);
|
||||
+
|
||||
+ return num % HASH_TABLE_SIZE;
|
||||
+}
|
||||
diff -up nfs-utils-1.1.4/support/export/xtab.c.orig nfs-utils-1.1.4/support/export/xtab.c
|
||||
--- nfs-utils-1.1.4/support/export/xtab.c.orig 2008-10-17 10:20:09.000000000 -0400
|
||||
+++ nfs-utils-1.1.4/support/export/xtab.c 2009-02-18 19:42:13.000000000 -0500
|
||||
@@ -100,7 +100,7 @@ xtab_write(char *xtab, char *xtabtmp, in
|
||||
setexportent(xtabtmp, "w");
|
||||
|
||||
for (i = 0; i < MCL_MAXTYPES; i++) {
|
||||
- for (exp = exportlist[i]; exp; exp = exp->m_next) {
|
||||
+ for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
|
||||
if (is_export && !exp->m_xtabent)
|
||||
continue;
|
||||
if (!is_export && ! exp->m_exported)
|
||||
diff -up nfs-utils-1.1.4/support/include/exportfs.h.orig nfs-utils-1.1.4/support/include/exportfs.h
|
||||
--- nfs-utils-1.1.4/support/include/exportfs.h.orig 2008-10-17 10:20:09.000000000 -0400
|
||||
+++ nfs-utils-1.1.4/support/include/exportfs.h 2009-02-18 19:42:13.000000000 -0500
|
||||
@@ -52,8 +52,21 @@ typedef struct mexport {
|
||||
* matching one client */
|
||||
} nfs_export;
|
||||
|
||||
+#define HASH_TABLE_SIZE 1021
|
||||
+
|
||||
+typedef struct _exp_hash_entry {
|
||||
+ nfs_export * p_first;
|
||||
+ nfs_export * p_last;
|
||||
+} exp_hash_entry;
|
||||
+
|
||||
+typedef struct _exp_hash_table {
|
||||
+ nfs_export * p_head;
|
||||
+ exp_hash_entry entries[HASH_TABLE_SIZE];
|
||||
+} exp_hash_table;
|
||||
+
|
||||
+extern exp_hash_table exportlist[MCL_MAXTYPES];
|
||||
+
|
||||
extern nfs_client * clientlist[MCL_MAXTYPES];
|
||||
-extern nfs_export * exportlist[MCL_MAXTYPES];
|
||||
|
||||
nfs_client * client_lookup(char *hname, int canonical);
|
||||
nfs_client * client_find(struct hostent *);
|
||||
@@ -69,7 +82,7 @@ struct hostent * client_resolve(struct
|
||||
int client_member(char *client, char *name);
|
||||
|
||||
int export_read(char *fname);
|
||||
-void export_add(nfs_export *);
|
||||
+void export_add(nfs_export *);
|
||||
void export_reset(nfs_export *);
|
||||
nfs_export * export_lookup(char *hname, char *path, int caconical);
|
||||
nfs_export * export_find(struct hostent *, char *path);
|
||||
diff -up nfs-utils-1.1.4/support/misc/tcpwrapper.c.orig nfs-utils-1.1.4/support/misc/tcpwrapper.c
|
||||
--- nfs-utils-1.1.4/support/misc/tcpwrapper.c.orig 2009-02-17 16:45:04.000000000 -0500
|
||||
+++ nfs-utils-1.1.4/support/misc/tcpwrapper.c 2009-02-18 19:42:13.000000000 -0500
|
||||
@@ -91,7 +91,7 @@ inline unsigned int strtoint(char *str)
|
||||
|
||||
return n;
|
||||
}
|
||||
-inline int hashint(unsigned int num)
|
||||
+static inline int hashint(unsigned int num)
|
||||
{
|
||||
return num % HASH_TABLE_SIZE;
|
||||
}
|
||||
diff -up nfs-utils-1.1.4/utils/exportfs/exportfs.c.orig nfs-utils-1.1.4/utils/exportfs/exportfs.c
|
||||
--- nfs-utils-1.1.4/utils/exportfs/exportfs.c.orig 2008-10-17 10:20:09.000000000 -0400
|
||||
+++ nfs-utils-1.1.4/utils/exportfs/exportfs.c 2009-02-18 19:42:13.000000000 -0500
|
||||
@@ -111,7 +111,6 @@ main(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
-
|
||||
if (f_export && ! f_ignore)
|
||||
export_read(_PATH_EXPORTS);
|
||||
if (f_export) {
|
||||
@@ -193,10 +192,10 @@ exports_update(int verbose)
|
||||
{
|
||||
nfs_export *exp;
|
||||
|
||||
- for (exp = exportlist[MCL_FQDN]; exp; exp=exp->m_next) {
|
||||
+ for (exp = exportlist[MCL_FQDN].p_head; exp; exp=exp->m_next) {
|
||||
exports_update_one(exp, verbose);
|
||||
}
|
||||
- for (exp = exportlist[MCL_GSS]; exp; exp=exp->m_next) {
|
||||
+ for (exp = exportlist[MCL_GSS].p_head; exp; exp=exp->m_next) {
|
||||
exports_update_one(exp, verbose);
|
||||
}
|
||||
}
|
||||
@@ -212,7 +211,7 @@ export_all(int verbose)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MCL_MAXTYPES; i++) {
|
||||
- for (exp = exportlist[i]; exp; exp = exp->m_next) {
|
||||
+ for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
|
||||
if (verbose)
|
||||
printf("exporting %s:%s\n",
|
||||
exp->m_client->m_hostname,
|
||||
@@ -308,7 +307,7 @@ unexportfs(char *arg, int verbose)
|
||||
}
|
||||
}
|
||||
|
||||
- for (exp = exportlist[htype]; exp; exp = exp->m_next) {
|
||||
+ for (exp = exportlist[htype].p_head; exp; exp = exp->m_next) {
|
||||
if (path && strcmp(path, exp->m_export.e_path))
|
||||
continue;
|
||||
if (htype != exp->m_client->m_type)
|
||||
@@ -453,7 +452,7 @@ dump(int verbose)
|
||||
char *hname, c;
|
||||
|
||||
for (htype = 0; htype < MCL_MAXTYPES; htype++) {
|
||||
- for (exp = exportlist[htype]; exp; exp = exp->m_next) {
|
||||
+ for (exp = exportlist[htype].p_head; exp; exp = exp->m_next) {
|
||||
ep = &exp->m_export;
|
||||
if (!exp->m_xtabent)
|
||||
continue; /* neilb */
|
||||
diff -up nfs-utils-1.1.4/utils/mountd/auth.c.orig nfs-utils-1.1.4/utils/mountd/auth.c
|
||||
--- nfs-utils-1.1.4/utils/mountd/auth.c.orig 2008-10-17 10:20:09.000000000 -0400
|
||||
+++ nfs-utils-1.1.4/utils/mountd/auth.c 2009-02-18 19:42:13.000000000 -0500
|
||||
@@ -142,7 +142,7 @@ auth_authenticate_internal(char *what, s
|
||||
|
||||
exp = NULL;
|
||||
for (i = 0; !exp && i < MCL_MAXTYPES; i++)
|
||||
- for (exp = exportlist[i]; exp; exp = exp->m_next) {
|
||||
+ for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
|
||||
if (strcmp(path, exp->m_export.e_path))
|
||||
continue;
|
||||
if (!use_ipaddr && !client_member(my_client.m_hostname, exp->m_client->m_hostname))
|
||||
diff -up nfs-utils-1.1.4/utils/mountd/cache.c.orig nfs-utils-1.1.4/utils/mountd/cache.c
|
||||
--- nfs-utils-1.1.4/utils/mountd/cache.c.orig 2008-10-17 10:20:09.000000000 -0400
|
||||
+++ nfs-utils-1.1.4/utils/mountd/cache.c 2009-02-18 19:42:13.000000000 -0500
|
||||
@@ -394,7 +394,7 @@ void nfsd_fh(FILE *f)
|
||||
/* Now determine export point for this fsid/domain */
|
||||
for (i=0 ; i < MCL_MAXTYPES; i++) {
|
||||
nfs_export *next_exp;
|
||||
- for (exp = exportlist[i]; exp; exp = next_exp) {
|
||||
+ for (exp = exportlist[i].p_head; exp; exp = next_exp) {
|
||||
struct stat stb;
|
||||
char u[16];
|
||||
char *path;
|
||||
@@ -654,7 +654,7 @@ void nfsd_export(FILE *f)
|
||||
|
||||
/* now find flags for this export point in this domain */
|
||||
for (i=0 ; i < MCL_MAXTYPES; i++) {
|
||||
- for (exp = exportlist[i]; exp; exp = exp->m_next) {
|
||||
+ for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
|
||||
if (!use_ipaddr && !client_member(dom, exp->m_client->m_hostname))
|
||||
continue;
|
||||
if (exp->m_export.e_flags & NFSEXP_CROSSMOUNT) {
|
||||
diff -up nfs-utils-1.1.4/utils/mountd/mountd.c.orig nfs-utils-1.1.4/utils/mountd/mountd.c
|
||||
--- nfs-utils-1.1.4/utils/mountd/mountd.c.orig 2008-10-17 10:20:09.000000000 -0400
|
||||
+++ nfs-utils-1.1.4/utils/mountd/mountd.c 2009-02-18 19:42:13.000000000 -0500
|
||||
@@ -521,7 +521,7 @@ get_exportlist(void)
|
||||
elist = NULL;
|
||||
|
||||
for (i = 0; i < MCL_MAXTYPES; i++) {
|
||||
- for (exp = exportlist[i]; exp; exp = exp->m_next) {
|
||||
+ for (exp = exportlist[i].p_head; exp; exp = exp->m_next) {
|
||||
for (e = elist; e != NULL; e = e->ex_next) {
|
||||
if (!strcmp(exp->m_export.e_path, e->ex_dir))
|
||||
break;
|
@ -1,48 +0,0 @@
|
||||
commit 068ea89e7d335d381276a2fff73d5abbb2b0a04d
|
||||
Author: Neil Brown <neilb@suse.de>
|
||||
Date: Wed Nov 26 08:48:03 2008 -0500
|
||||
|
||||
gssd: unblock DNOTIFY_SIGNAL in case it was blocked.
|
||||
|
||||
I have a situation where rpc.gssd appears to not be working.
|
||||
Mount attempts which need to communicate with it block.
|
||||
|
||||
I've narrowed down the problem to that fact that all realtime signals
|
||||
have been blocked. This means that DNOTIFY_SIGNAL (which is a
|
||||
realtime signal) is never delivered, so gssd never rescans the
|
||||
rpc_pipe/nfs directory.
|
||||
|
||||
It seems start_kde (or whatever it is called) and all descendants have
|
||||
these
|
||||
signals blocked. xfce seems to do the same thing. gnome doesn't.
|
||||
|
||||
So if you start rpc.gssd from a terminal window while logged in via
|
||||
KDE, it doesn't behave as expected.
|
||||
|
||||
Signed-off-by: Neil Brown <neilb@suse.de>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff --git a/utils/gssd/gssd_main_loop.c b/utils/gssd/gssd_main_loop.c
|
||||
index 84f04e9..b9f3a06 100644
|
||||
--- a/utils/gssd/gssd_main_loop.c
|
||||
+++ b/utils/gssd/gssd_main_loop.c
|
||||
@@ -99,6 +99,7 @@ gssd_run()
|
||||
int ret;
|
||||
struct sigaction dn_act;
|
||||
int fd;
|
||||
+ sigset_t set;
|
||||
|
||||
/* Taken from linux/Documentation/dnotify.txt: */
|
||||
dn_act.sa_sigaction = dir_notify_handler;
|
||||
@@ -106,6 +107,11 @@ gssd_run()
|
||||
dn_act.sa_flags = SA_SIGINFO;
|
||||
sigaction(DNOTIFY_SIGNAL, &dn_act, NULL);
|
||||
|
||||
+ /* just in case the signal is blocked... */
|
||||
+ sigemptyset(&set);
|
||||
+ sigaddset(&set, DNOTIFY_SIGNAL);
|
||||
+ sigprocmask(SIG_UNBLOCK, &set, NULL);
|
||||
+
|
||||
if ((fd = open(pipefs_nfsdir, O_RDONLY)) == -1) {
|
||||
printerr(0, "ERROR: failed to open %s: %s\n",
|
||||
pipefs_nfsdir, strerror(errno));
|
@ -1,136 +0,0 @@
|
||||
commit 09c7ad1cd9c5ca2fc46631a0057d47309abc8706
|
||||
Author: Kevin Coffman <kwc@citi.umich.edu>
|
||||
Date: Mon Jan 5 14:07:05 2009 -0500
|
||||
|
||||
gssd: By default, don't spam syslog when users' credentials expire
|
||||
|
||||
Change the priority of "common" log messages so that syslog doesn't get
|
||||
slammed/spammed when users' credentials expire, or there is another
|
||||
common
|
||||
problem which would cause error messages for all context creation
|
||||
requests.
|
||||
|
||||
Note that this will now require that gssd or svcgssd option "-v" is used
|
||||
to
|
||||
debug these common cases.
|
||||
|
||||
Original patch from Andrew Pollock <apollock@google.com>.
|
||||
|
||||
Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
CC: Andrew Pollock <apollock@google.com>
|
||||
|
||||
diff --git a/utils/gssd/gss_util.c b/utils/gssd/gss_util.c
|
||||
index 8a7bcaa..2d66be9 100644
|
||||
--- a/utils/gssd/gss_util.c
|
||||
+++ b/utils/gssd/gss_util.c
|
||||
@@ -216,7 +216,7 @@ gssd_acquire_cred(char *server_name)
|
||||
ignore_maj_stat = gss_display_name(&ignore_min_stat,
|
||||
target_name, &pbuf, NULL);
|
||||
if (ignore_maj_stat == GSS_S_COMPLETE) {
|
||||
- printerr(0, "Unable to obtain credentials for '%.*s'\n",
|
||||
+ printerr(1, "Unable to obtain credentials for '%.*s'\n",
|
||||
pbuf.length, pbuf.value);
|
||||
ignore_maj_stat = gss_release_buffer(&ignore_min_stat,
|
||||
&pbuf);
|
||||
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
|
||||
index cb14d45..91fc8d2 100644
|
||||
--- a/utils/gssd/gssd_proc.c
|
||||
+++ b/utils/gssd/gssd_proc.c
|
||||
@@ -448,7 +448,7 @@ do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
|
||||
return 0;
|
||||
out_err:
|
||||
if (buf) free(buf);
|
||||
- printerr(0, "Failed to write downcall!\n");
|
||||
+ printerr(1, "Failed to write downcall!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -741,14 +741,14 @@ handle_krb5_upcall(struct clnt_info *clp)
|
||||
}
|
||||
gssd_free_krb5_machine_cred_list(credlist);
|
||||
if (!success) {
|
||||
- printerr(0, "WARNING: Failed to create krb5 context "
|
||||
+ printerr(1, "WARNING: Failed to create krb5 context "
|
||||
"for user with uid %d with any "
|
||||
"credentials cache for server %s\n",
|
||||
uid, clp->servername);
|
||||
goto out_return_error;
|
||||
}
|
||||
} else {
|
||||
- printerr(0, "WARNING: Failed to create krb5 context "
|
||||
+ printerr(1, "WARNING: Failed to create krb5 context "
|
||||
"for user with uid %d for server %s\n",
|
||||
uid, clp->servername);
|
||||
goto out_return_error;
|
||||
@@ -756,7 +756,7 @@ handle_krb5_upcall(struct clnt_info *clp)
|
||||
}
|
||||
|
||||
if (!authgss_get_private_data(auth, &pd)) {
|
||||
- printerr(0, "WARNING: Failed to obtain authentication "
|
||||
+ printerr(1, "WARNING: Failed to obtain authentication "
|
||||
"data for user with uid %d for server %s\n",
|
||||
uid, clp->servername);
|
||||
goto out_return_error;
|
||||
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
|
||||
index 77814bc..d4ee631 100644
|
||||
--- a/utils/gssd/krb5_util.c
|
||||
+++ b/utils/gssd/krb5_util.c
|
||||
@@ -399,7 +399,7 @@ gssd_get_single_krb5_cred(krb5_context context,
|
||||
goto out;
|
||||
}
|
||||
if (krb5_get_init_creds_opt_set_addressless(context, init_opts, 1))
|
||||
- printerr(0, "WARNING: Unable to set option for addressless "
|
||||
+ printerr(1, "WARNING: Unable to set option for addressless "
|
||||
"tickets. May have problems behind a NAT.\n");
|
||||
#ifdef TEST_SHORT_LIFETIME
|
||||
/* set a short lifetime (for debugging only!) */
|
||||
@@ -422,7 +422,7 @@ gssd_get_single_krb5_cred(krb5_context context,
|
||||
|
||||
if ((code = krb5_get_init_creds_keytab(context, &my_creds, ple->princ,
|
||||
kt, 0, NULL, opts))) {
|
||||
- printerr(0, "WARNING: %s while getting initial ticket for "
|
||||
+ printerr(1, "WARNING: %s while getting initial ticket for "
|
||||
"principal '%s' using keytab '%s'\n",
|
||||
gssd_k5_err_msg(context, code),
|
||||
pname ? pname : "<unparsable>", kt_name);
|
||||
@@ -632,7 +632,7 @@ get_full_hostname(const char *inhost, char *outhost, int outhostlen)
|
||||
/* Get full target hostname */
|
||||
retval = getaddrinfo(inhost, NULL, &hints, &addrs);
|
||||
if (retval) {
|
||||
- printerr(0, "%s while getting full hostname for '%s'\n",
|
||||
+ printerr(1, "%s while getting full hostname for '%s'\n",
|
||||
gai_strerror(retval), inhost);
|
||||
goto out;
|
||||
}
|
||||
diff --git a/utils/gssd/svcgssd_proc.c b/utils/gssd/svcgssd_proc.c
|
||||
index f162152..1d13532 100644
|
||||
--- a/utils/gssd/svcgssd_proc.c
|
||||
+++ b/utils/gssd/svcgssd_proc.c
|
||||
@@ -108,7 +108,7 @@ do_svc_downcall(gss_buffer_desc *out_handle, struct svc_cred *cred,
|
||||
fclose(f);
|
||||
return err;
|
||||
out_err:
|
||||
- printerr(0, "WARNING: downcall failed\n");
|
||||
+ printerr(1, "WARNING: downcall failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ get_ids(gss_name_t client_name, gss_OID mech, struct svc_cred *cred)
|
||||
res = 0;
|
||||
goto out_free;
|
||||
}
|
||||
- printerr(0, "WARNING: get_ids: failed to map name '%s' "
|
||||
+ printerr(1, "WARNING: get_ids: failed to map name '%s' "
|
||||
"to uid/gid: %s\n", sname, strerror(-res));
|
||||
goto out_free;
|
||||
}
|
||||
@@ -380,7 +380,7 @@ handle_nullreq(FILE *f) {
|
||||
goto continue_needed;
|
||||
}
|
||||
else if (maj_stat != GSS_S_COMPLETE) {
|
||||
- printerr(0, "WARNING: gss_accept_sec_context failed\n");
|
||||
+ printerr(1, "WARNING: gss_accept_sec_context failed\n");
|
||||
pgsserr("handle_nullreq: gss_accept_sec_context",
|
||||
maj_stat, min_stat, mech);
|
||||
goto out_err;
|
@ -1,646 +0,0 @@
|
||||
commit 162cbdd19830abaf6a3fd64a22839023ce99185d
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Mon Nov 17 16:08:03 2008 -0500
|
||||
|
||||
Add AF_INET6-capable API to acquire an RPC CLIENT *
|
||||
|
||||
Provide a simple interface that any component of nfs-utils can use to acquire
|
||||
an RPC CLIENT *. This is an AF_INET6-enabled API, and can also handle
|
||||
PF_LOCAL sockets if libtirpc is present on the system.
|
||||
|
||||
When libtirpc is not available, legacy RPC services will be used instead,
|
||||
and an attempt to connect to an AF_INET6 address will fail.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
--- nfs-utils-1.1.4/support/nfs/Makefile.am.orig 2008-10-17 10:20:09.000000000 -0400
|
||||
+++ nfs-utils-1.1.4/support/nfs/Makefile.am 2008-11-18 14:59:08.894659000 -0500
|
||||
@@ -3,7 +3,7 @@
|
||||
noinst_LIBRARIES = libnfs.a
|
||||
libnfs_a_SOURCES = exports.c rmtab.c xio.c rpcmisc.c rpcdispatch.c \
|
||||
xlog.c xcommon.c wildmat.c nfssvc.c nfsclient.c \
|
||||
- nfsexport.c getfh.c nfsctl.c \
|
||||
+ nfsexport.c getfh.c nfsctl.c rpc_socket.c \
|
||||
svc_socket.c cacheio.c closeall.c nfs_mntent.c
|
||||
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
--- /dev/null 2008-11-18 08:07:41.940431098 -0500
|
||||
+++ nfs-utils-1.1.4/support/nfs/rpc_socket.c 2008-11-18 14:59:08.904660000 -0500
|
||||
@@ -0,0 +1,528 @@
|
||||
+/*
|
||||
+ * Generic RPC client socket-level APIs for nfs-utils
|
||||
+ *
|
||||
+ * Copyright (C) 2008 Oracle Corporation. All rights reserved.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public
|
||||
+ * License as published by the Free Software Foundation; either
|
||||
+ * version 2 of the License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public
|
||||
+ * License along with this program; if not, write to the
|
||||
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
+ * Boston, MA 021110-1307, USA.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#ifdef HAVE_CONFIG_H
|
||||
+#include <config.h>
|
||||
+#endif
|
||||
+
|
||||
+#include <sys/types.h>
|
||||
+#include <sys/time.h>
|
||||
+#include <unistd.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <errno.h>
|
||||
+
|
||||
+#include <sys/socket.h>
|
||||
+#include <netinet/in.h>
|
||||
+#include <netdb.h>
|
||||
+#include <arpa/inet.h>
|
||||
+
|
||||
+#include <rpc/rpc.h>
|
||||
+#include <rpc/pmap_prot.h>
|
||||
+
|
||||
+#include "nfsrpc.h"
|
||||
+
|
||||
+#ifdef HAVE_TIRPC_NETCONFIG_H
|
||||
+
|
||||
+/*
|
||||
+ * Most of the headers under /usr/include/tirpc are currently
|
||||
+ * unusable for various reasons. We statically define the bits
|
||||
+ * we need here until the official headers are fixed.
|
||||
+ *
|
||||
+ * The commonly used RPC calls such as CLNT_CALL and CLNT_DESTROY
|
||||
+ * are actually virtual functions in both the legacy and TI-RPC
|
||||
+ * implementations. The proper _CALL or _DESTROY will be invoked
|
||||
+ * no matter if we used a legacy clnt_create() or clnt_tli_create()
|
||||
+ * from libtirpc.
|
||||
+ */
|
||||
+
|
||||
+#include <tirpc/netconfig.h>
|
||||
+#include <tirpc/rpc/rpcb_prot.h>
|
||||
+
|
||||
+/* definitions from tirpc/rpc/types.h */
|
||||
+
|
||||
+/*
|
||||
+ * The netbuf structure is used for transport-independent address storage.
|
||||
+ */
|
||||
+struct netbuf {
|
||||
+ unsigned int maxlen;
|
||||
+ unsigned int len;
|
||||
+ void *buf;
|
||||
+};
|
||||
+
|
||||
+/* definitions from tirpc/rpc/clnt.h */
|
||||
+
|
||||
+/*
|
||||
+ * Low level clnt create routine for connectionless transports, e.g. udp.
|
||||
+ */
|
||||
+extern CLIENT *clnt_dg_create(const int, const struct netbuf *,
|
||||
+ const rpcprog_t, const rpcvers_t,
|
||||
+ const u_int, const u_int);
|
||||
+
|
||||
+/*
|
||||
+ * Low level clnt create routine for connectionful transports, e.g. tcp.
|
||||
+ */
|
||||
+extern CLIENT *clnt_vc_create(const int, const struct netbuf *,
|
||||
+ const rpcprog_t, const rpcvers_t,
|
||||
+ u_int, u_int);
|
||||
+
|
||||
+#endif /* HAVE_TIRPC_NETCONFIG_H */
|
||||
+
|
||||
+/*
|
||||
+ * If "-1" is specified in the tv_sec field, use these defaults instead.
|
||||
+ */
|
||||
+#define NFSRPC_TIMEOUT_UDP (3)
|
||||
+#define NFSRPC_TIMEOUT_TCP (10)
|
||||
+
|
||||
+/*
|
||||
+ * Set up an RPC client for communicating via a AF_LOCAL socket.
|
||||
+ *
|
||||
+ * @timeout is initialized upon return
|
||||
+ *
|
||||
+ * Returns a pointer to a prepared RPC client if successful; caller
|
||||
+ * must destroy a non-NULL returned RPC client. Otherwise NULL, and
|
||||
+ * rpc_createerr.cf_stat is set to reflect the error.
|
||||
+ */
|
||||
+static CLIENT *nfs_get_localclient(const struct sockaddr *sap,
|
||||
+ const socklen_t salen,
|
||||
+ const rpcprog_t program,
|
||||
+ const rpcvers_t version,
|
||||
+ struct timeval *timeout)
|
||||
+{
|
||||
+#ifdef HAVE_CLNT_VC_CREATE
|
||||
+ struct sockaddr_storage address;
|
||||
+ const struct netbuf nbuf = {
|
||||
+ .maxlen = sizeof(struct sockaddr_un),
|
||||
+ .len = (size_t)salen,
|
||||
+ .buf = &address,
|
||||
+ };
|
||||
+#endif /* HAVE_CLNT_VC_CREATE */
|
||||
+ CLIENT *client;
|
||||
+ int sock;
|
||||
+
|
||||
+ sock = socket(AF_LOCAL, SOCK_STREAM, 0);
|
||||
+ if (sock == -1) {
|
||||
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||||
+ rpc_createerr.cf_error.re_errno = errno;
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (timeout->tv_sec == -1)
|
||||
+ timeout->tv_sec = NFSRPC_TIMEOUT_TCP;
|
||||
+
|
||||
+#ifdef HAVE_CLNT_VC_CREATE
|
||||
+ memcpy(nbuf.buf, sap, (size_t)salen);
|
||||
+ client = clnt_vc_create(sock, &nbuf, program, version, 0, 0);
|
||||
+#else /* HAVE_CLNT_VC_CREATE */
|
||||
+ client = clntunix_create((struct sockaddr_un *)sap,
|
||||
+ program, version, &sock, 0, 0);
|
||||
+#endif /* HAVE_CLNT_VC_CREATE */
|
||||
+ if (client != NULL)
|
||||
+ CLNT_CONTROL(client, CLSET_FD_CLOSE, NULL);
|
||||
+ else
|
||||
+ (void)close(sock);
|
||||
+
|
||||
+ return client;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Bind a socket using an unused ephemeral source port.
|
||||
+ *
|
||||
+ * Returns zero on success, or returns -1 on error. errno is
|
||||
+ * set to reflect the nature of the error.
|
||||
+ */
|
||||
+static int nfs_bind(const int sock, const sa_family_t family)
|
||||
+{
|
||||
+ struct sockaddr_in sin = {
|
||||
+ .sin_family = AF_INET,
|
||||
+ .sin_addr.s_addr = htonl(INADDR_ANY),
|
||||
+ };
|
||||
+ struct sockaddr_in6 sin6 = {
|
||||
+ .sin6_family = AF_INET6,
|
||||
+ .sin6_addr = IN6ADDR_ANY_INIT,
|
||||
+ };
|
||||
+
|
||||
+ switch (family) {
|
||||
+ case AF_INET:
|
||||
+ return bind(sock, (struct sockaddr *)&sin,
|
||||
+ (socklen_t)sizeof(sin));
|
||||
+ case AF_INET6:
|
||||
+ return bind(sock, (struct sockaddr *)&sin6,
|
||||
+ (socklen_t)sizeof(sin6));
|
||||
+ }
|
||||
+
|
||||
+ errno = EAFNOSUPPORT;
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Perform a non-blocking connect on the socket fd.
|
||||
+ *
|
||||
+ * @timeout is modified to contain the time remaining (i.e. time provided
|
||||
+ * minus time elasped).
|
||||
+ *
|
||||
+ * Returns zero on success, or returns -1 on error. errno is
|
||||
+ * set to reflect the nature of the error.
|
||||
+ */
|
||||
+static int nfs_connect_nb(const int fd, const struct sockaddr *sap,
|
||||
+ const socklen_t salen, struct timeval *timeout)
|
||||
+{
|
||||
+ int flags, ret;
|
||||
+ fd_set rset;
|
||||
+
|
||||
+ flags = fcntl(fd, F_GETFL, 0);
|
||||
+ if (flags < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ ret = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
|
||||
+ if (ret < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ /*
|
||||
+ * From here on subsequent sys calls could change errno so
|
||||
+ * we set ret = -errno to capture it in case we decide to
|
||||
+ * use it later.
|
||||
+ */
|
||||
+ ret = connect(fd, sap, salen);
|
||||
+ if (ret < 0 && errno != EINPROGRESS) {
|
||||
+ ret = -1;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (ret == 0)
|
||||
+ goto done;
|
||||
+
|
||||
+ /* now wait */
|
||||
+ FD_ZERO(&rset);
|
||||
+ FD_SET(fd, &rset);
|
||||
+
|
||||
+ ret = select(fd + 1, NULL, &rset, NULL, timeout);
|
||||
+ if (ret <= 0) {
|
||||
+ if (ret == 0)
|
||||
+ errno = ETIMEDOUT;
|
||||
+ ret = -1;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ if (FD_ISSET(fd, &rset)) {
|
||||
+ int status;
|
||||
+ socklen_t len = (socklen_t)sizeof(ret);
|
||||
+
|
||||
+ status = getsockopt(fd, SOL_SOCKET, SO_ERROR, &ret, &len);
|
||||
+ if (status < 0) {
|
||||
+ ret = -1;
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ /* Oops - something wrong with connect */
|
||||
+ if (ret != 0) {
|
||||
+ errno = ret;
|
||||
+ ret = -1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+done:
|
||||
+ (void)fcntl(fd, F_SETFL, flags);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Set up an RPC client for communicating via a datagram socket.
|
||||
+ * A connected UDP socket is used to detect a missing remote
|
||||
+ * listener as quickly as possible.
|
||||
+ *
|
||||
+ * @timeout is initialized upon return
|
||||
+ *
|
||||
+ * Returns a pointer to a prepared RPC client if successful; caller
|
||||
+ * must destroy a non-NULL returned RPC client. Otherwise NULL, and
|
||||
+ * rpc_createerr.cf_stat is set to reflect the error.
|
||||
+ */
|
||||
+static CLIENT *nfs_get_udpclient(const struct sockaddr *sap,
|
||||
+ const socklen_t salen,
|
||||
+ const rpcprog_t program,
|
||||
+ const rpcvers_t version,
|
||||
+ struct timeval *timeout)
|
||||
+{
|
||||
+#ifdef HAVE_CLNT_DG_CREATE
|
||||
+ struct sockaddr_storage address;
|
||||
+ const struct netbuf nbuf = {
|
||||
+ .maxlen = salen,
|
||||
+ .len = salen,
|
||||
+ .buf = &address,
|
||||
+ };
|
||||
+#endif /* HAVE_CLNT_DG_CREATE */
|
||||
+ CLIENT *client;
|
||||
+ int ret, sock;
|
||||
+
|
||||
+#ifndef HAVE_CLNT_DG_CREATE
|
||||
+ if (sap->sa_family != AF_INET) {
|
||||
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
|
||||
+ return NULL;
|
||||
+ }
|
||||
+#endif /* !HAVE_CLNT_DG_CREATE */
|
||||
+
|
||||
+ sock = socket((int)sap->sa_family, SOCK_DGRAM, IPPROTO_UDP);
|
||||
+ if (sock == -1) {
|
||||
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||||
+ rpc_createerr.cf_error.re_errno = errno;
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ ret = nfs_bind(sock, sap->sa_family);
|
||||
+ if (ret < 0) {
|
||||
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||||
+ rpc_createerr.cf_error.re_errno = errno;
|
||||
+ (void)close(sock);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (timeout->tv_sec == -1)
|
||||
+ timeout->tv_sec = NFSRPC_TIMEOUT_UDP;
|
||||
+
|
||||
+ ret = nfs_connect_nb(sock, sap, salen, timeout);
|
||||
+ if (ret != 0) {
|
||||
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||||
+ rpc_createerr.cf_error.re_errno = errno;
|
||||
+ (void)close(sock);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+#ifdef HAVE_CLNT_DG_CREATE
|
||||
+ memcpy(nbuf.buf, sap, (size_t)salen);
|
||||
+ client = clnt_dg_create(sock, &nbuf, program, version, 0, 0);
|
||||
+#else /* HAVE_CLNT_DG_CREATE */
|
||||
+ client = clntudp_create((struct sockaddr_in *)sap, program,
|
||||
+ version, *timeout, &sock);
|
||||
+#endif /* HAVE_CLNT_DG_CREATE */
|
||||
+ if (client != NULL) {
|
||||
+ CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)timeout);
|
||||
+ CLNT_CONTROL(client, CLSET_FD_CLOSE, NULL);
|
||||
+ } else
|
||||
+ (void)close(sock);
|
||||
+
|
||||
+ return client;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Set up and connect an RPC client for communicating via a stream socket.
|
||||
+ *
|
||||
+ * @timeout is initialized upon return
|
||||
+ *
|
||||
+ * Returns a pointer to a prepared and connected RPC client if
|
||||
+ * successful; caller must destroy a non-NULL returned RPC client.
|
||||
+ * Otherwise NULL, and rpc_createerr.cf_stat is set to reflect the
|
||||
+ * error.
|
||||
+ */
|
||||
+static CLIENT *nfs_get_tcpclient(const struct sockaddr *sap,
|
||||
+ const socklen_t salen,
|
||||
+ const rpcprog_t program,
|
||||
+ const rpcvers_t version,
|
||||
+ struct timeval *timeout)
|
||||
+{
|
||||
+#ifdef HAVE_CLNT_VC_CREATE
|
||||
+ struct sockaddr_storage address;
|
||||
+ const struct netbuf nbuf = {
|
||||
+ .maxlen = salen,
|
||||
+ .len = salen,
|
||||
+ .buf = &address,
|
||||
+ };
|
||||
+#endif /* HAVE_CLNT_VC_CREATE */
|
||||
+ CLIENT *client;
|
||||
+ int ret, sock;
|
||||
+
|
||||
+#ifndef HAVE_CLNT_VC_CREATE
|
||||
+ if (sap->sa_family != AF_INET) {
|
||||
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
|
||||
+ return NULL;
|
||||
+ }
|
||||
+#endif /* !HAVE_CLNT_VC_CREATE */
|
||||
+
|
||||
+ sock = socket((int)sap->sa_family, SOCK_STREAM, IPPROTO_TCP);
|
||||
+ if (sock == -1) {
|
||||
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||||
+ rpc_createerr.cf_error.re_errno = errno;
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ ret = nfs_bind(sock, sap->sa_family);
|
||||
+ if (ret < 0) {
|
||||
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||||
+ rpc_createerr.cf_error.re_errno = errno;
|
||||
+ (void)close(sock);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ if (timeout->tv_sec == -1)
|
||||
+ timeout->tv_sec = NFSRPC_TIMEOUT_TCP;
|
||||
+
|
||||
+ ret = nfs_connect_nb(sock, sap, salen, timeout);
|
||||
+ if (ret != 0) {
|
||||
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||||
+ rpc_createerr.cf_error.re_errno = errno;
|
||||
+ (void)close(sock);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+#ifdef HAVE_CLNT_VC_CREATE
|
||||
+ memcpy(nbuf.buf, sap, (size_t)salen);
|
||||
+ client = clnt_vc_create(sock, &nbuf, program, version, 0, 0);
|
||||
+#else /* HAVE_CLNT_VC_CREATE */
|
||||
+ client = clnttcp_create((struct sockaddr_in *)sap,
|
||||
+ program, version, &sock, 0, 0);
|
||||
+#endif /* HAVE_CLNT_VC_CREATE */
|
||||
+ if (client != NULL)
|
||||
+ CLNT_CONTROL(client, CLSET_FD_CLOSE, NULL);
|
||||
+ else
|
||||
+ (void)close(sock);
|
||||
+
|
||||
+ return client;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * nfs_get_rpcclient - acquire an RPC client
|
||||
+ * @sap: pointer to socket address of RPC server
|
||||
+ * @salen: length of socket address
|
||||
+ * @transport: IPPROTO_ value of transport protocol to use
|
||||
+ * @program: RPC program number
|
||||
+ * @version: RPC version number
|
||||
+ * @timeout: pointer to request timeout (must not be NULL)
|
||||
+ *
|
||||
+ * Set up an RPC client for communicating with an RPC program @program
|
||||
+ * and @version on the server @sap over @transport.
|
||||
+ *
|
||||
+ * Returns a pointer to a prepared RPC client if successful, and
|
||||
+ * @timeout is initialized; caller must destroy a non-NULL returned RPC
|
||||
+ * client. Otherwise returns NULL, and rpc_createerr.cf_stat is set to
|
||||
+ * reflect the error.
|
||||
+ */
|
||||
+CLIENT *nfs_get_rpcclient(const struct sockaddr *sap,
|
||||
+ const socklen_t salen,
|
||||
+ const unsigned short transport,
|
||||
+ const rpcprog_t program,
|
||||
+ const rpcvers_t version,
|
||||
+ struct timeval *timeout)
|
||||
+{
|
||||
+ struct sockaddr_in *sin = (struct sockaddr_in *)sap;
|
||||
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
|
||||
+
|
||||
+ switch (sap->sa_family) {
|
||||
+ case AF_LOCAL:
|
||||
+ return nfs_get_localclient(sap, salen, program,
|
||||
+ version, timeout);
|
||||
+ case AF_INET:
|
||||
+ if (sin->sin_port == 0) {
|
||||
+ rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ break;
|
||||
+ case AF_INET6:
|
||||
+ if (sin6->sin6_port == 0) {
|
||||
+ rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ break;
|
||||
+ default:
|
||||
+ rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ switch (transport) {
|
||||
+ case IPPROTO_TCP:
|
||||
+ return nfs_get_tcpclient(sap, salen, program, version, timeout);
|
||||
+ case 0:
|
||||
+ case IPPROTO_UDP:
|
||||
+ return nfs_get_udpclient(sap, salen, program, version, timeout);
|
||||
+ }
|
||||
+
|
||||
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * nfs_getrpcbyname - convert an RPC program name to a rpcprog_t
|
||||
+ * @program: default program number to use if names not found in db
|
||||
+ * @table: pointer to table of 'char *' names to try to find
|
||||
+ *
|
||||
+ * Returns program number of first name to be successfully looked
|
||||
+ * up, or the default program number if all lookups fail.
|
||||
+ */
|
||||
+rpcprog_t nfs_getrpcbyname(const rpcprog_t program, const char *table[])
|
||||
+{
|
||||
+#ifdef HAVE_GETRPCBYNAME
|
||||
+ struct rpcent *entry;
|
||||
+ unsigned int i;
|
||||
+
|
||||
+ if (table != NULL)
|
||||
+ for (i = 0; table[i] != NULL; i++) {
|
||||
+ entry = getrpcbyname(table[i]);
|
||||
+ if (entry)
|
||||
+ return (rpcprog_t)entry->r_number;
|
||||
+ }
|
||||
+#endif /* HAVE_GETRPCBYNAME */
|
||||
+
|
||||
+ return program;
|
||||
+}
|
||||
+
|
||||
+static unsigned short nfs_tryportbyname(const char *name,
|
||||
+ const char *protocol)
|
||||
+{
|
||||
+ struct servent *servp = NULL;
|
||||
+
|
||||
+ servp = getservbyname(name, protocol);
|
||||
+ if (servp != NULL)
|
||||
+ return (unsigned short)ntohl((uint32_t)servp->s_port);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * nfs_getportbynumber - convert an RPC program number to a port
|
||||
+ * @program: RPC program number to look up
|
||||
+ * @transport: IPPROTO_ value of transport protocol to use
|
||||
+ *
|
||||
+ * Returns a non-zero port number, in host byte order, on success;
|
||||
+ * otherwise zero if some problem occurred.
|
||||
+ */
|
||||
+unsigned short nfs_getportbynumber(const rpcprog_t program,
|
||||
+ const unsigned short transport)
|
||||
+{
|
||||
+ char *protocol = (transport == IPPROTO_TCP) ? "tcp" : "udp";
|
||||
+ struct rpcent *rpcp;
|
||||
+ unsigned short port = 0;
|
||||
+
|
||||
+ rpcp = getrpcbynumber((int)program);
|
||||
+ if (rpcp == NULL)
|
||||
+ return port;
|
||||
+
|
||||
+ port = nfs_tryportbyname(rpcp->r_name, protocol);
|
||||
+ if (port != 0)
|
||||
+ return port;
|
||||
+
|
||||
+ if (rpcp->r_aliases) {
|
||||
+ int i;
|
||||
+ for (i = 0; rpcp->r_aliases[i] != NULL; i++) {
|
||||
+ port = nfs_tryportbyname(rpcp->r_aliases[i], protocol);
|
||||
+ if (port != 0)
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return port;
|
||||
+}
|
||||
--- /dev/null 2008-11-18 08:07:41.940431098 -0500
|
||||
+++ nfs-utils-1.1.4/support/include/nfsrpc.h 2008-11-18 14:59:08.888662000 -0500
|
||||
@@ -0,0 +1,70 @@
|
||||
+/*
|
||||
+ * nfsrpc.h -- RPC client APIs provided by support/nfs
|
||||
+ *
|
||||
+ * Copyright (C) 2008 Oracle Corporation. All rights reserved.
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public
|
||||
+ * License as published by the Free Software Foundation; either
|
||||
+ * version 2 of the License, or (at your option) any later version.
|
||||
+ *
|
||||
+ * This program is distributed in the hope that it will be useful,
|
||||
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
+ * General Public License for more details.
|
||||
+ *
|
||||
+ * You should have received a copy of the GNU General Public
|
||||
+ * License along with this program; if not, write to the
|
||||
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
+ * Boston, MA 021110-1307, USA.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#ifndef __NFS_UTILS_NFSRPC_H
|
||||
+#define __NFS_UTILS_NFSRPC_H
|
||||
+
|
||||
+#include <rpc/types.h>
|
||||
+
|
||||
+/*
|
||||
+ * Conventional RPC program numbers
|
||||
+ */
|
||||
+#ifndef RPCBPROG
|
||||
+#define RPCBPROG ((rpcprog_t)100000)
|
||||
+#endif
|
||||
+#ifndef PMAPPROG
|
||||
+#define PMAPPROG ((rpcprog_t)100000)
|
||||
+#endif
|
||||
+
|
||||
+#ifndef NFSPROG
|
||||
+#define NFSPROG ((rpcprog_t)100003)
|
||||
+#endif
|
||||
+#ifndef MOUNTPROG
|
||||
+#define MOUNTPROG ((rpcprog_t)100005)
|
||||
+#endif
|
||||
+#ifndef NLMPROG
|
||||
+#define NLMPROG ((rpcprog_t)100021)
|
||||
+#endif
|
||||
+#ifndef NSMPROG
|
||||
+#define NSMPROG ((rpcprog_t)100024)
|
||||
+#endif
|
||||
+
|
||||
+/*
|
||||
+ * Look up an RPC program name in /etc/rpc
|
||||
+ */
|
||||
+extern rpcprog_t nfs_getrpcbyname(const rpcprog_t, const char *table[]);
|
||||
+
|
||||
+/*
|
||||
+ * Look up a port number in /etc/services for an RPC program
|
||||
+ */
|
||||
+extern unsigned short nfs_getportbynumber(const rpcprog_t program,
|
||||
+ const unsigned short transport);
|
||||
+
|
||||
+/*
|
||||
+ * Acquire an RPC CLIENT *
|
||||
+ */
|
||||
+extern CLIENT *nfs_get_rpcclient(const struct sockaddr *,
|
||||
+ const socklen_t, const unsigned short,
|
||||
+ const rpcprog_t, const rpcvers_t,
|
||||
+ struct timeval *);
|
||||
+
|
||||
+#endif /* __NFS_UTILS_NFSRPC_H */
|
||||
--- nfs-utils-1.1.4/configure.ac.orig 2008-10-17 10:20:09.000000000 -0400
|
||||
+++ nfs-utils-1.1.4/configure.ac 2008-11-18 14:59:08.884659000 -0500
|
||||
@@ -178,6 +178,12 @@ AC_CHECK_FUNC(connect, ,
|
||||
AC_CHECK_FUNC(getaddrinfo, , ,
|
||||
AC_MSG_ERROR(Function 'getaddrinfo' not found.))
|
||||
|
||||
+AC_CHECK_FUNC(getrpcbynumber, , ,
|
||||
+ AC_MSG_ERROR(Function 'getrpcbynumber' not found.))
|
||||
+
|
||||
+AC_CHECK_FUNC(getservbyname, , ,
|
||||
+ AC_MSG_ERROR(Function 'getservbyname' not found.))
|
||||
+
|
||||
AC_CHECK_LIB(crypt, crypt, [LIBCRYPT="-lcrypt"])
|
||||
if test "$enable_nfsv4" = yes; then
|
||||
AC_CHECK_LIB(event, event_dispatch, [libevent=1], AC_MSG_ERROR([libevent needed for nfsv4 support]))
|
File diff suppressed because it is too large
Load Diff
@ -1,227 +0,0 @@
|
||||
--- nfs-utils-1.1.4/support/nfs/getport.c.save 2009-01-06 12:22:33.100864000 -0500
|
||||
+++ nfs-utils-1.1.4/support/nfs/getport.c 2009-01-06 12:23:04.885428000 -0500
|
||||
@@ -73,6 +73,60 @@ static const char *nfs_gp_rpcb_pgmtbl[]
|
||||
NULL,
|
||||
};
|
||||
|
||||
+#ifdef HAVE_DECL_AI_ADDRCONFIG
|
||||
+/*
|
||||
+ * getaddrinfo(3) generates a usable loopback address based on how the
|
||||
+ * local network interfaces are configured. RFC 3484 requires that the
|
||||
+ * results are sorted so that the first result has the best likelihood
|
||||
+ * of working, so we try just that first result.
|
||||
+ *
|
||||
+ * Returns TRUE on success.
|
||||
+ */
|
||||
+static int nfs_gp_loopback_address(struct sockaddr *sap, socklen_t *salen)
|
||||
+{
|
||||
+ struct addrinfo *gai_results;
|
||||
+ struct addrinfo gai_hint = {
|
||||
+ .ai_flags = AI_ADDRCONFIG,
|
||||
+ };
|
||||
+ socklen_t len = *salen;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ if (getaddrinfo(NULL, "sunrpc", &gai_hint, &gai_results))
|
||||
+ return 0;
|
||||
+
|
||||
+ switch (gai_results->ai_addr->sa_family) {
|
||||
+ case AF_INET:
|
||||
+ case AF_INET6:
|
||||
+ if (len >= gai_results->ai_addrlen) {
|
||||
+ memcpy(sap, gai_results->ai_addr,
|
||||
+ gai_results->ai_addrlen);
|
||||
+ *salen = gai_results->ai_addrlen;
|
||||
+ ret = 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ freeaddrinfo(gai_results);
|
||||
+ return ret;
|
||||
+}
|
||||
+#else
|
||||
+/*
|
||||
+ * Old versions of getaddrinfo(3) don't support AI_ADDRCONFIG, so we
|
||||
+ * have a fallback for building on legacy systems.
|
||||
+ */
|
||||
+static int nfs_gp_loopback_address(struct sockaddr *sap, socklen_t *salen)
|
||||
+{
|
||||
+ struct sockaddr_in *sin = (struct sockaddr_in *)sap;
|
||||
+
|
||||
+ memset(sin, 0, sizeof(*sin));
|
||||
+
|
||||
+ sin->sin_family = AF_INET;
|
||||
+ sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
+ *salen = sizeof(*sin);
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
/*
|
||||
* Discover the port number that should be used to contact an
|
||||
* rpcbind service. This will detect if the port has a local
|
||||
@@ -780,12 +834,10 @@ unsigned short nfs_getlocalport(const rp
|
||||
const rpcvers_t version,
|
||||
const unsigned short protocol)
|
||||
{
|
||||
- struct addrinfo *gai_results;
|
||||
- struct addrinfo gai_hint = {
|
||||
- .ai_flags = AI_ADDRCONFIG,
|
||||
- };
|
||||
+ struct sockaddr_storage address;
|
||||
+ struct sockaddr *lb_addr = (struct sockaddr *)&address;
|
||||
+ socklen_t lb_len = sizeof(lb_addr);
|
||||
unsigned short port = 0;
|
||||
- int error;
|
||||
|
||||
#ifdef NFS_GP_LOCAL
|
||||
const struct sockaddr_un sun = {
|
||||
@@ -811,12 +863,9 @@ unsigned short nfs_getlocalport(const rp
|
||||
#endif /* NFS_GP_LOCAL */
|
||||
|
||||
if (port == 0) {
|
||||
- error = getaddrinfo(NULL, "sunrpc", &gai_hint, &gai_results);
|
||||
- if (error == 0) {
|
||||
- port = nfs_getport(gai_results->ai_addr,
|
||||
- gai_results->ai_addrlen,
|
||||
+ if (nfs_gp_loopback_address(lb_addr, &lb_len)) {
|
||||
+ port = nfs_getport(lb_addr, lb_len,
|
||||
program, version, protocol);
|
||||
- freeaddrinfo(gai_results);
|
||||
} else
|
||||
rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
|
||||
}
|
||||
--- nfs-utils-1.1.4/utils/mount/network.c.save 2009-01-06 12:22:12.950764000 -0500
|
||||
+++ nfs-utils-1.1.4/utils/mount/network.c 2009-01-06 12:23:10.432801000 -0500
|
||||
@@ -50,24 +50,6 @@
|
||||
#include "nfsrpc.h"
|
||||
#include "network.h"
|
||||
|
||||
-/*
|
||||
- * Earlier versions of glibc's /usr/include/netdb.h exclude these
|
||||
- * definitions because it was thought they were not part of a stable
|
||||
- * POSIX standard. However, they are defined by RFC 2553 and 3493
|
||||
- * and in POSIX 1003.1-2001, so these definitions were added in later
|
||||
- * versions of netdb.h.
|
||||
- */
|
||||
-#ifndef AI_V4MAPPED
|
||||
-#define AI_V4MAPPED 0x0008 /* IPv4-mapped addresses are acceptable. */
|
||||
-#endif /* AI_V4MAPPED */
|
||||
-#ifndef AI_ALL
|
||||
-#define AI_ALL 0x0010 /* Return both IPv4 and IPv6 addresses. */
|
||||
-#endif /* AI_ALL */
|
||||
-#ifndef AI_ADDRCONFIG
|
||||
-#define AI_ADDRCONFIG 0x0020 /* Use configuration of this host to choose \
|
||||
- returned address type. */
|
||||
-#endif /* AI_ADDRCONFIG */
|
||||
-
|
||||
#define PMAP_TIMEOUT (10)
|
||||
#define CONNECT_TIMEOUT (20)
|
||||
#define MOUNT_TIMEOUT (30)
|
||||
@@ -175,9 +157,11 @@ static void nfs_set_port(struct sockaddr
|
||||
}
|
||||
}
|
||||
|
||||
+#ifdef HAVE_DECL_AI_ADDRCONFIG
|
||||
/**
|
||||
* nfs_name_to_address - resolve hostname to an IPv4 or IPv6 socket address
|
||||
* @hostname: pointer to C string containing DNS hostname to resolve
|
||||
+ * @af_hint: hint to restrict resolution to one address family
|
||||
* @sap: pointer to buffer to fill with socket address
|
||||
* @len: IN: size of buffer to fill; OUT: size of socket address
|
||||
*
|
||||
@@ -228,11 +212,66 @@ int nfs_name_to_address(const char *host
|
||||
freeaddrinfo(gai_results);
|
||||
return ret;
|
||||
}
|
||||
+#else /* HAVE_DECL_AI_ADDRCONFIG */
|
||||
+/**
|
||||
+ * nfs_name_to_address - resolve hostname to an IPv4 socket address
|
||||
+ * @hostname: pointer to C string containing DNS hostname to resolve
|
||||
+ * @af_hint: hint to restrict resolution to one address family
|
||||
+ * @sap: pointer to buffer to fill with socket address
|
||||
+ * @len: IN: size of buffer to fill; OUT: size of socket address
|
||||
+ *
|
||||
+ * Returns 1 and places a socket address at @sap if successful;
|
||||
+ * otherwise zero.
|
||||
+ *
|
||||
+ * Some older getaddrinfo(3) implementations don't support
|
||||
+ * AI_ADDRCONFIG or AI_V4MAPPED properly. For those cases, a DNS
|
||||
+ * resolver based on the traditional gethostbyname(3) is provided.
|
||||
+ */
|
||||
+int nfs_name_to_address(const char *hostname,
|
||||
+ const sa_family_t af_hint,
|
||||
+ struct sockaddr *sap, socklen_t *salen)
|
||||
+{
|
||||
+ struct sockaddr_in *sin = (struct sockaddr_in *)sap;
|
||||
+ socklen_t len = *salen;
|
||||
+ struct hostent *hp;
|
||||
+
|
||||
+ *salen = 0;
|
||||
+
|
||||
+ if (af_hint != AF_INET) {
|
||||
+ nfs_error(_("%s: address family not supported by DNS resolver\n"),
|
||||
+ progname, hostname);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ sin->sin_family = AF_INET;
|
||||
+ if (inet_aton(hostname, &sin->sin_addr)) {
|
||||
+ *salen = sizeof(*sin);
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ hp = gethostbyname(hostname);
|
||||
+ if (hp == NULL) {
|
||||
+ nfs_error(_("%s: DNS resolution failed for %s: %s"),
|
||||
+ progname, hostname, hstrerror(h_errno));
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ if (hp->h_length > len) {
|
||||
+ nfs_error(_("%s: DNS resolution results too long for buffer\n"),
|
||||
+ progname);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(&sin->sin_addr, hp->h_addr, hp->h_length);
|
||||
+ *salen = hp->h_length;
|
||||
+ return 1;
|
||||
+}
|
||||
+#endif /* HAVE_DECL_AI_ADDRCONFIG */
|
||||
|
||||
/**
|
||||
* nfs_gethostbyname - resolve a hostname to an IPv4 address
|
||||
* @hostname: pointer to a C string containing a DNS hostname
|
||||
- * @saddr: returns an IPv4 address
|
||||
+ * @sin: returns an IPv4 address
|
||||
*
|
||||
* Returns 1 if successful, otherwise zero.
|
||||
*/
|
||||
--- nfs-utils-1.1.4/configure.ac.save 2009-01-06 12:22:41.437331000 -0500
|
||||
+++ nfs-utils-1.1.4/configure.ac 2009-01-06 12:23:10.424809000 -0500
|
||||
@@ -246,6 +246,11 @@ if test "$enable_gss" = yes; then
|
||||
|
||||
fi
|
||||
|
||||
+AC_CHECK_DECL([AI_ADDRCONFIG],
|
||||
+ AC_DEFINE([HAVE_DECL_AI_ADDRCONFIG], 1,
|
||||
+ [Define this to 1 if AI_ADDRCONFIG macro is defined]), ,
|
||||
+ [ #include <netdb.h> ] )
|
||||
+
|
||||
if test "$enable_ipv6" = yes; then
|
||||
AC_CHECK_FUNC(inet_ntop, , ,
|
||||
AC_MSG_ERROR(Function 'inet_ntop' not found.))
|
||||
@@ -254,7 +259,10 @@ if test "$enable_ipv6" = yes; then
|
||||
AC_CHECK_LIB(tirpc, clnt_tli_create, ,
|
||||
AC_MSG_ERROR([libtirpc needed for IPv6 support]))
|
||||
AC_CHECK_HEADERS(tirpc/netconfig.h, ,
|
||||
- AC_MSG_ERROR([libtirpc-devel needed for IPv6 support]))
|
||||
+ AC_MSG_ERROR([libtirpc headers needed for IPv6 support]))
|
||||
+ AC_CHECK_DECL([AI_ADDRCONFIG], ,
|
||||
+ AC_MSG_ERROR([full getaddrinfo(3) implementation needed for IPv6 support]),
|
||||
+ [ #include <netdb.h> ] )
|
||||
fi
|
||||
|
||||
dnl *************************************************************
|
@ -1,407 +0,0 @@
|
||||
commit 71433fbcb0e3142e2b555727197f480d24761d7e
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Thu Dec 11 10:27:34 2008 -0500
|
||||
|
||||
mount command: full support for AF_INET6 addresses in probe_port()
|
||||
|
||||
Now that probe_port() uses an AF_INET6-capable rpcbind query and RPC ping,
|
||||
finish updating probe_port() to support AF_INET6 addresses fully.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
commit 299a990de1b16ff769201fa0ed38249853254497
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Thu Dec 11 10:28:57 2008 -0500
|
||||
|
||||
mount command: support AF_INET6 in probe_nfsport() and probe_mntport()
|
||||
|
||||
Flesh out support for AF_INET6 in the intermediate helper functions
|
||||
probe_nfsport() and probe_mntport().
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
commit 8a5ef964599438ea45f849a0cd1431a0c26bf054
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Thu Dec 11 10:30:20 2008 -0500
|
||||
|
||||
mount command: AF_INET6 support for probe_bothports()
|
||||
|
||||
Introduce an AF_INET6 capable probe_bothports() API. This means replacing
|
||||
"struct sockaddr_in *" arguments with a "struct sockaddr *" and a socklen_t
|
||||
arguments.
|
||||
|
||||
These functions often combine a "struct sockaddr_in" and a "struct pmap" into
|
||||
a single "clnt_addr_t" argument. Instead of modifying "clnt_addr_t" and all
|
||||
the legacy code that uses it, I'm going to create a new probe_bothports() API
|
||||
for the text-based mount command that takes a "struct sockaddr *" and
|
||||
sockaddr length, and leave the existing probe_bothports() interface, which
|
||||
takes "clnt_addr_t" arguments, for legacy use.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff --git a/utils/mount/network.c b/utils/mount/network.c
|
||||
index 0c68993..e50bc28 100644
|
||||
--- a/utils/mount/network.c
|
||||
+++ b/utils/mount/network.c
|
||||
@@ -160,6 +160,21 @@ static const unsigned long probe_mnt3_first[] = {
|
||||
0,
|
||||
};
|
||||
|
||||
+static void nfs_set_port(struct sockaddr *sap, const unsigned short port)
|
||||
+{
|
||||
+ switch (sap->sa_family) {
|
||||
+ case AF_INET:
|
||||
+ ((struct sockaddr_in *)sap)->sin_port = htons(port);
|
||||
+ break;
|
||||
+ case AF_INET6:
|
||||
+ ((struct sockaddr_in6 *)sap)->sin6_port = htons(port);
|
||||
+ break;
|
||||
+ default:
|
||||
+ nfs_error(_("%s: unrecognized address family in %s"),
|
||||
+ progname, __func__);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* nfs_name_to_address - resolve hostname to an IPv4 or IPv6 socket address
|
||||
* @hostname: pointer to C string containing DNS hostname to resolve
|
||||
@@ -474,27 +489,38 @@ static void nfs_pp_debug(const struct sockaddr *sap, const socklen_t salen,
|
||||
* Use the portmapper to discover whether or not the service we want is
|
||||
* available. The lists 'versions' and 'protos' define ordered sequences
|
||||
* of service versions and udp/tcp protocols to probe for.
|
||||
+ *
|
||||
+ * Returns 1 if the requested service port is unambiguous and pingable;
|
||||
+ * @pmap is filled in with the version, port, and transport protocol used
|
||||
+ * during the successful ping. Note that if a port is already specified
|
||||
+ * in @pmap and it matches the rpcbind query result, nfs_probe_port() does
|
||||
+ * not perform an RPC ping.
|
||||
+ *
|
||||
+ * If an error occurs or the requested service isn't available, zero is
|
||||
+ * returned; rpccreateerr.cf_stat is set to reflect the nature of the error.
|
||||
*/
|
||||
-static int probe_port(clnt_addr_t *server, const unsigned long *versions,
|
||||
- const unsigned int *protos)
|
||||
+static int nfs_probe_port(const struct sockaddr *sap, const socklen_t salen,
|
||||
+ struct pmap *pmap, const unsigned long *versions,
|
||||
+ const unsigned int *protos)
|
||||
{
|
||||
- const struct sockaddr *saddr = (struct sockaddr *)&server->saddr;
|
||||
- const socklen_t salen = sizeof(server->saddr);
|
||||
- struct pmap *pmap = &server->pmap;
|
||||
+ struct sockaddr_storage address;
|
||||
+ struct sockaddr *saddr = (struct sockaddr *)&address;
|
||||
const unsigned long prog = pmap->pm_prog, *p_vers;
|
||||
const unsigned int prot = (u_int)pmap->pm_prot, *p_prot;
|
||||
const u_short port = (u_short) pmap->pm_port;
|
||||
unsigned long vers = pmap->pm_vers;
|
||||
unsigned short p_port;
|
||||
|
||||
+ memcpy(saddr, sap, salen);
|
||||
p_prot = prot ? &prot : protos;
|
||||
p_vers = vers ? &vers : versions;
|
||||
rpc_createerr.cf_stat = 0;
|
||||
+
|
||||
for (;;) {
|
||||
p_port = nfs_getport(saddr, salen, prog, *p_vers, *p_prot);
|
||||
if (p_port) {
|
||||
if (!port || port == p_port) {
|
||||
- server->saddr.sin_port = htons(p_port);
|
||||
+ nfs_set_port(saddr, p_port);
|
||||
nfs_pp_debug(saddr, salen, prog, *p_vers,
|
||||
*p_prot, p_port);
|
||||
if (nfs_rpc_ping(saddr, salen, prog,
|
||||
@@ -537,28 +563,36 @@ out_ok:
|
||||
|
||||
static int probe_nfsport(clnt_addr_t *nfs_server)
|
||||
{
|
||||
+ struct sockaddr *sap = (struct sockaddr *)&nfs_server->saddr;
|
||||
+ socklen_t salen = sizeof(nfs_server->saddr);
|
||||
struct pmap *pmap = &nfs_server->pmap;
|
||||
|
||||
if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
|
||||
return 1;
|
||||
|
||||
if (nfs_mount_data_version >= 4)
|
||||
- return probe_port(nfs_server, probe_nfs3_first, probe_tcp_first);
|
||||
+ return nfs_probe_port(sap, salen, pmap,
|
||||
+ probe_nfs3_first, probe_tcp_first);
|
||||
else
|
||||
- return probe_port(nfs_server, probe_nfs2_only, probe_udp_only);
|
||||
+ return nfs_probe_port(sap, salen, pmap,
|
||||
+ probe_nfs2_only, probe_udp_only);
|
||||
}
|
||||
|
||||
static int probe_mntport(clnt_addr_t *mnt_server)
|
||||
{
|
||||
+ struct sockaddr *sap = (struct sockaddr *)&mnt_server->saddr;
|
||||
+ socklen_t salen = sizeof(mnt_server->saddr);
|
||||
struct pmap *pmap = &mnt_server->pmap;
|
||||
|
||||
if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
|
||||
return 1;
|
||||
|
||||
if (nfs_mount_data_version >= 4)
|
||||
- return probe_port(mnt_server, probe_mnt3_first, probe_udp_first);
|
||||
+ return nfs_probe_port(sap, salen, pmap,
|
||||
+ probe_mnt3_first, probe_udp_first);
|
||||
else
|
||||
- return probe_port(mnt_server, probe_mnt1_first, probe_udp_only);
|
||||
+ return nfs_probe_port(sap, salen, pmap,
|
||||
+ probe_mnt1_first, probe_udp_only);
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/utils/mount/network.c b/utils/mount/network.c
|
||||
index e50bc28..55b2cab 100644
|
||||
--- a/utils/mount/network.c
|
||||
+++ b/utils/mount/network.c
|
||||
@@ -561,12 +561,22 @@ out_ok:
|
||||
return 1;
|
||||
}
|
||||
|
||||
-static int probe_nfsport(clnt_addr_t *nfs_server)
|
||||
+/*
|
||||
+ * Probe a server's NFS service to determine which versions and
|
||||
+ * transport protocols are supported.
|
||||
+ *
|
||||
+ * Returns 1 if the requested service port is unambiguous and pingable;
|
||||
+ * @pmap is filled in with the version, port, and transport protocol used
|
||||
+ * during the successful ping. If all three are already specified, simply
|
||||
+ * return success without an rpcbind query or RPC ping (we may be trying
|
||||
+ * to mount an NFS service that is not advertised via rpcbind).
|
||||
+ *
|
||||
+ * If an error occurs or the requested service isn't available, zero is
|
||||
+ * returned; rpccreateerr.cf_stat is set to reflect the nature of the error.
|
||||
+ */
|
||||
+static int nfs_probe_nfsport(const struct sockaddr *sap, const socklen_t salen,
|
||||
+ struct pmap *pmap)
|
||||
{
|
||||
- struct sockaddr *sap = (struct sockaddr *)&nfs_server->saddr;
|
||||
- socklen_t salen = sizeof(nfs_server->saddr);
|
||||
- struct pmap *pmap = &nfs_server->pmap;
|
||||
-
|
||||
if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
|
||||
return 1;
|
||||
|
||||
@@ -578,12 +588,22 @@ static int probe_nfsport(clnt_addr_t *nfs_server)
|
||||
probe_nfs2_only, probe_udp_only);
|
||||
}
|
||||
|
||||
-static int probe_mntport(clnt_addr_t *mnt_server)
|
||||
+/*
|
||||
+ * Probe a server's mountd service to determine which versions and
|
||||
+ * transport protocols are supported.
|
||||
+ *
|
||||
+ * Returns 1 if the requested service port is unambiguous and pingable;
|
||||
+ * @pmap is filled in with the version, port, and transport protocol used
|
||||
+ * during the successful ping. If all three are already specified, simply
|
||||
+ * return success without an rpcbind query or RPC ping (we may be trying
|
||||
+ * to mount an NFS service that is not advertised via rpcbind).
|
||||
+ *
|
||||
+ * If an error occurs or the requested service isn't available, zero is
|
||||
+ * returned; rpccreateerr.cf_stat is set to reflect the nature of the error.
|
||||
+ */
|
||||
+static int nfs_probe_mntport(const struct sockaddr *sap, const socklen_t salen,
|
||||
+ struct pmap *pmap)
|
||||
{
|
||||
- struct sockaddr *sap = (struct sockaddr *)&mnt_server->saddr;
|
||||
- socklen_t salen = sizeof(mnt_server->saddr);
|
||||
- struct pmap *pmap = &mnt_server->pmap;
|
||||
-
|
||||
if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
|
||||
return 1;
|
||||
|
||||
@@ -607,10 +627,13 @@ static int probe_mntport(clnt_addr_t *mnt_server)
|
||||
*/
|
||||
int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
|
||||
{
|
||||
+ struct sockaddr *nfs_saddr = (struct sockaddr *)&nfs_server->saddr;
|
||||
+ socklen_t nfs_salen = sizeof(nfs_server->saddr);
|
||||
+ struct sockaddr *mnt_saddr = (struct sockaddr *)&mnt_server->saddr;
|
||||
+ socklen_t mnt_salen = sizeof(mnt_server->saddr);
|
||||
struct pmap *nfs_pmap = &nfs_server->pmap;
|
||||
struct pmap *mnt_pmap = &mnt_server->pmap;
|
||||
struct pmap save_nfs, save_mnt;
|
||||
- int res;
|
||||
const unsigned long *probe_vers;
|
||||
|
||||
if (mnt_pmap->pm_vers && !nfs_pmap->pm_vers)
|
||||
@@ -627,9 +650,9 @@ int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
|
||||
|
||||
for (; *probe_vers; probe_vers++) {
|
||||
nfs_pmap->pm_vers = mntvers_to_nfs(*probe_vers);
|
||||
- if ((res = probe_nfsport(nfs_server) != 0)) {
|
||||
+ if (nfs_probe_nfsport(nfs_saddr, nfs_salen, nfs_pmap) != 0) {
|
||||
mnt_pmap->pm_vers = *probe_vers;
|
||||
- if ((res = probe_mntport(mnt_server)) != 0)
|
||||
+ if (nfs_probe_mntport(mnt_saddr, mnt_salen, mnt_pmap) != 0)
|
||||
return 1;
|
||||
memcpy(mnt_pmap, &save_mnt, sizeof(*mnt_pmap));
|
||||
}
|
||||
@@ -647,9 +670,9 @@ out_bad:
|
||||
return 0;
|
||||
|
||||
version_fixed:
|
||||
- if (!probe_nfsport(nfs_server))
|
||||
+ if (!nfs_probe_nfsport(nfs_saddr, nfs_salen, nfs_pmap))
|
||||
goto out_bad;
|
||||
- return probe_mntport(mnt_server);
|
||||
+ return nfs_probe_mntport(mnt_saddr, mnt_salen, mnt_pmap);
|
||||
}
|
||||
|
||||
static int nfs_probe_statd(void)
|
||||
@@ -716,11 +739,14 @@ int start_statd(void)
|
||||
*/
|
||||
int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp)
|
||||
{
|
||||
+ struct sockaddr *sap = (struct sockaddr *)&mnt_server->saddr;
|
||||
+ socklen_t salen = sizeof(mnt_server->saddr);
|
||||
+ struct pmap *pmap = &mnt_server->pmap;
|
||||
CLIENT *clnt;
|
||||
enum clnt_stat res = 0;
|
||||
int msock;
|
||||
|
||||
- if (!probe_mntport(mnt_server))
|
||||
+ if (!nfs_probe_mntport(sap, salen, pmap))
|
||||
return 0;
|
||||
clnt = mnt_openclnt(mnt_server, &msock);
|
||||
if (!clnt)
|
||||
diff --git a/utils/mount/network.c b/utils/mount/network.c
|
||||
index 55b2cab..6a9a41a 100644
|
||||
--- a/utils/mount/network.c
|
||||
+++ b/utils/mount/network.c
|
||||
@@ -615,24 +615,49 @@ static int nfs_probe_mntport(const struct sockaddr *sap, const socklen_t salen,
|
||||
probe_mnt1_first, probe_udp_only);
|
||||
}
|
||||
|
||||
-/**
|
||||
- * probe_bothports - discover the RPC endpoints of mountd and NFS server
|
||||
- * @mnt_server: pointer to address and pmap argument for mountd results
|
||||
- * @nfs_server: pointer to address and pmap argument for NFS server
|
||||
+/*
|
||||
+ * Probe a server's mountd service to determine which versions and
|
||||
+ * transport protocols are supported. Invoked when the protocol
|
||||
+ * version is already known for both the NFS and mountd service.
|
||||
*
|
||||
- * Returns 1 if successful, otherwise zero if some error occurred.
|
||||
- * Note that the arguments are both input and output arguments.
|
||||
+ * Returns 1 and fills in both @pmap structs if the requested service
|
||||
+ * ports are unambiguous and pingable. Otherwise zero is returned;
|
||||
+ * rpccreateerr.cf_stat is set to reflect the nature of the error.
|
||||
+ */
|
||||
+static int nfs_probe_version_fixed(const struct sockaddr *mnt_saddr,
|
||||
+ const socklen_t mnt_salen,
|
||||
+ struct pmap *mnt_pmap,
|
||||
+ const struct sockaddr *nfs_saddr,
|
||||
+ const socklen_t nfs_salen,
|
||||
+ struct pmap *nfs_pmap)
|
||||
+{
|
||||
+ if (!nfs_probe_nfsport(nfs_saddr, nfs_salen, nfs_pmap))
|
||||
+ return 0;
|
||||
+ return nfs_probe_mntport(mnt_saddr, mnt_salen, mnt_pmap);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * nfs_probe_bothports - discover the RPC endpoints of mountd and NFS server
|
||||
+ * @mnt_saddr: pointer to socket address of mountd server
|
||||
+ * @mnt_salen: length of mountd server's address
|
||||
+ * @mnt_pmap: IN: partially filled-in mountd RPC service tuple;
|
||||
+ * OUT: fully filled-in mountd RPC service tuple
|
||||
+ * @nfs_saddr: pointer to socket address of NFS server
|
||||
+ * @nfs_salen: length of NFS server's address
|
||||
+ * @nfs_pmap: IN: partially filled-in NFS RPC service tuple;
|
||||
+ * OUT: fully filled-in NFS RPC service tuple
|
||||
*
|
||||
- * A side effect of calling this function is that rpccreateerr is set.
|
||||
+ * Returns 1 and fills in both @pmap structs if the requested service
|
||||
+ * ports are unambiguous and pingable. Otherwise zero is returned;
|
||||
+ * rpccreateerr.cf_stat is set to reflect the nature of the error.
|
||||
*/
|
||||
-int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
|
||||
+int nfs_probe_bothports(const struct sockaddr *mnt_saddr,
|
||||
+ const socklen_t mnt_salen,
|
||||
+ struct pmap *mnt_pmap,
|
||||
+ const struct sockaddr *nfs_saddr,
|
||||
+ const socklen_t nfs_salen,
|
||||
+ struct pmap *nfs_pmap)
|
||||
{
|
||||
- struct sockaddr *nfs_saddr = (struct sockaddr *)&nfs_server->saddr;
|
||||
- socklen_t nfs_salen = sizeof(nfs_server->saddr);
|
||||
- struct sockaddr *mnt_saddr = (struct sockaddr *)&mnt_server->saddr;
|
||||
- socklen_t mnt_salen = sizeof(mnt_server->saddr);
|
||||
- struct pmap *nfs_pmap = &nfs_server->pmap;
|
||||
- struct pmap *mnt_pmap = &mnt_server->pmap;
|
||||
struct pmap save_nfs, save_mnt;
|
||||
const unsigned long *probe_vers;
|
||||
|
||||
@@ -640,8 +665,10 @@ int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
|
||||
nfs_pmap->pm_vers = mntvers_to_nfs(mnt_pmap->pm_vers);
|
||||
else if (nfs_pmap->pm_vers && !mnt_pmap->pm_vers)
|
||||
mnt_pmap->pm_vers = nfsvers_to_mnt(nfs_pmap->pm_vers);
|
||||
+
|
||||
if (nfs_pmap->pm_vers)
|
||||
- goto version_fixed;
|
||||
+ return nfs_probe_version_fixed(mnt_saddr, mnt_salen, mnt_pmap,
|
||||
+ nfs_saddr, nfs_salen, nfs_pmap);
|
||||
|
||||
memcpy(&save_nfs, nfs_pmap, sizeof(save_nfs));
|
||||
memcpy(&save_mnt, mnt_pmap, sizeof(save_mnt));
|
||||
@@ -661,18 +688,35 @@ int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
|
||||
case RPC_PROGNOTREGISTERED:
|
||||
break;
|
||||
default:
|
||||
- goto out_bad;
|
||||
+ return 0;
|
||||
}
|
||||
memcpy(nfs_pmap, &save_nfs, sizeof(*nfs_pmap));
|
||||
}
|
||||
|
||||
-out_bad:
|
||||
return 0;
|
||||
+}
|
||||
|
||||
-version_fixed:
|
||||
- if (!nfs_probe_nfsport(nfs_saddr, nfs_salen, nfs_pmap))
|
||||
- goto out_bad;
|
||||
- return nfs_probe_mntport(mnt_saddr, mnt_salen, mnt_pmap);
|
||||
+/**
|
||||
+ * probe_bothports - discover the RPC endpoints of mountd and NFS server
|
||||
+ * @mnt_server: pointer to address and pmap argument for mountd results
|
||||
+ * @nfs_server: pointer to address and pmap argument for NFS server
|
||||
+ *
|
||||
+ * This is the legacy API that takes "clnt_addr_t" for both servers,
|
||||
+ * but supports only AF_INET addresses.
|
||||
+ *
|
||||
+ * Returns 1 and fills in the pmap field in both clnt_addr_t structs
|
||||
+ * if the requested service ports are unambiguous and pingable.
|
||||
+ * Otherwise zero is returned; rpccreateerr.cf_stat is set to reflect
|
||||
+ * the nature of the error.
|
||||
+ */
|
||||
+int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
|
||||
+{
|
||||
+ return nfs_probe_bothports((struct sockaddr *)&mnt_server->saddr,
|
||||
+ sizeof(mnt_server->saddr),
|
||||
+ &mnt_server->pmap,
|
||||
+ (struct sockaddr *)&nfs_server->saddr,
|
||||
+ sizeof(nfs_server->saddr),
|
||||
+ &nfs_server->pmap);
|
||||
}
|
||||
|
||||
static int nfs_probe_statd(void)
|
||||
diff --git a/utils/mount/network.h b/utils/mount/network.h
|
||||
index a4dba1b..075093d 100644
|
||||
--- a/utils/mount/network.h
|
||||
+++ b/utils/mount/network.h
|
||||
@@ -40,6 +40,9 @@ static const struct timeval TIMEOUT = { 20, 0 };
|
||||
static const struct timeval RETRY_TIMEOUT = { 3, 0 };
|
||||
|
||||
int probe_bothports(clnt_addr_t *, clnt_addr_t *);
|
||||
+int nfs_probe_bothports(const struct sockaddr *, const socklen_t,
|
||||
+ struct pmap *, const struct sockaddr *,
|
||||
+ const socklen_t, struct pmap *);
|
||||
int nfs_gethostbyname(const char *, struct sockaddr_in *);
|
||||
int nfs_name_to_address(const char *, const sa_family_t,
|
||||
struct sockaddr *, socklen_t *);
|
@ -1,276 +0,0 @@
|
||||
commit b8711a0665b9ecff9d59ee36d756f50823242f64
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Tue Dec 2 07:43:54 2008 -0500
|
||||
|
||||
mount command: remove local getport() implementation
|
||||
|
||||
Eliminate local getport() implementation from utils/mount/network.c, as
|
||||
it is no longer used.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
commit cc58ba0c98b2f687810a5af9e6185bcc5e855fb0
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Tue Dec 2 07:43:01 2008 -0500
|
||||
|
||||
mount command: Replace clnt_ping() and getport() calls in probe_port()
|
||||
|
||||
Update the mount command's probe_port() function to call the new shared
|
||||
rpcbind query and RPC ping functions. This provides immediate support
|
||||
for
|
||||
rpcbind v3/v4 queries, and paves the way for supporting AF_INET6 in the
|
||||
probe_bothports() path.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
commit 14b0dae49afae3fcf05c19ae84829aeef2f6876e
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Tue Dec 2 07:40:16 2008 -0500
|
||||
|
||||
mount command: Use nfs_error() instead of perror()
|
||||
|
||||
So we can ensure that error output is directed appropriately, use
|
||||
nfs_error() instead of perror() in start_statd().
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
commit ea0473feffd8071216c96217df3202a8deed2c65
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Tue Dec 2 07:39:06 2008 -0500
|
||||
|
||||
mount command: Use nfs_pmap_getport() in probe_statd()
|
||||
|
||||
Repace the getport() and clnt_ping() calls in probe_statd() with their
|
||||
new shared equivalents.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff -up nfs-utils-1.1.4/utils/mount/network.c.orig nfs-utils-1.1.4/utils/mount/network.c
|
||||
--- nfs-utils-1.1.4/utils/mount/network.c.orig 2008-12-01 09:14:24.000000000 -0500
|
||||
+++ nfs-utils-1.1.4/utils/mount/network.c 2008-12-02 08:32:00.000000000 -0500
|
||||
@@ -47,6 +47,7 @@
|
||||
#include "nls.h"
|
||||
#include "nfs_mount.h"
|
||||
#include "mount_constants.h"
|
||||
+#include "nfsrpc.h"
|
||||
#include "network.h"
|
||||
|
||||
/*
|
||||
@@ -79,6 +80,11 @@ extern int nfs_mount_data_version;
|
||||
extern char *progname;
|
||||
extern int verbose;
|
||||
|
||||
+static const char *nfs_ns_pgmtbl[] = {
|
||||
+ "status",
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
static const unsigned long nfs_to_mnt[] = {
|
||||
0,
|
||||
0,
|
||||
@@ -443,76 +449,25 @@ err_connect:
|
||||
return RPC_ANYSOCK;
|
||||
}
|
||||
|
||||
-/*
|
||||
- * getport() is very similar to pmap_getport() with the exception that
|
||||
- * this version tries to use an ephemeral port, since reserved ports are
|
||||
- * not needed for GETPORT queries. This conserves the very limited
|
||||
- * reserved port space, which helps reduce failed socket binds
|
||||
- * during mount storms.
|
||||
- *
|
||||
- * A side effect of calling this function is that rpccreateerr is set.
|
||||
- */
|
||||
-static unsigned short getport(struct sockaddr_in *saddr,
|
||||
- unsigned long program,
|
||||
- unsigned long version,
|
||||
- unsigned int proto)
|
||||
-{
|
||||
- struct sockaddr_in bind_saddr;
|
||||
- unsigned short port = 0;
|
||||
- int socket;
|
||||
- CLIENT *clnt = NULL;
|
||||
- enum clnt_stat stat;
|
||||
-
|
||||
- bind_saddr = *saddr;
|
||||
- bind_saddr.sin_port = htons(PMAPPORT);
|
||||
-
|
||||
- socket = get_socket(&bind_saddr, proto, PMAP_TIMEOUT, FALSE, TRUE);
|
||||
- if (socket == RPC_ANYSOCK) {
|
||||
- if (proto == IPPROTO_TCP &&
|
||||
- rpc_createerr.cf_error.re_errno == ETIMEDOUT)
|
||||
- rpc_createerr.cf_stat = RPC_TIMEDOUT;
|
||||
- return 0;
|
||||
- }
|
||||
+static void nfs_pp_debug(const struct sockaddr *sap, const socklen_t salen,
|
||||
+ const rpcprog_t program, const rpcvers_t version,
|
||||
+ const unsigned short protocol,
|
||||
+ const unsigned short port)
|
||||
+{
|
||||
+ char buf[NI_MAXHOST];
|
||||
|
||||
- switch (proto) {
|
||||
- case IPPROTO_UDP:
|
||||
- clnt = clntudp_bufcreate(&bind_saddr,
|
||||
- PMAPPROG, PMAPVERS,
|
||||
- RETRY_TIMEOUT, &socket,
|
||||
- RPCSMALLMSGSIZE,
|
||||
- RPCSMALLMSGSIZE);
|
||||
- break;
|
||||
- case IPPROTO_TCP:
|
||||
- clnt = clnttcp_create(&bind_saddr,
|
||||
- PMAPPROG, PMAPVERS,
|
||||
- &socket,
|
||||
- RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
|
||||
- break;
|
||||
- }
|
||||
- if (clnt != NULL) {
|
||||
- struct pmap parms = {
|
||||
- .pm_prog = program,
|
||||
- .pm_vers = version,
|
||||
- .pm_prot = proto,
|
||||
- };
|
||||
-
|
||||
- stat = clnt_call(clnt, PMAPPROC_GETPORT,
|
||||
- (xdrproc_t)xdr_pmap, (caddr_t)&parms,
|
||||
- (xdrproc_t)xdr_u_short, (caddr_t)&port,
|
||||
- TIMEOUT);
|
||||
- if (stat) {
|
||||
- clnt_geterr(clnt, &rpc_createerr.cf_error);
|
||||
- rpc_createerr.cf_stat = stat;
|
||||
- }
|
||||
- clnt_destroy(clnt);
|
||||
- if (stat != RPC_SUCCESS)
|
||||
- port = 0;
|
||||
- else if (port == 0)
|
||||
- rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
|
||||
+ if (!verbose)
|
||||
+ return;
|
||||
+
|
||||
+ if (nfs_present_sockaddr(sap, salen, buf, sizeof(buf)) == 0) {
|
||||
+ buf[0] = '\0';
|
||||
+ strcat(buf, "unknown host");
|
||||
}
|
||||
- close(socket);
|
||||
|
||||
- return port;
|
||||
+ fprintf(stderr, _("%s: trying %s prog %ld vers %ld prot %s port %d\n"),
|
||||
+ progname, buf, program, version,
|
||||
+ (protocol == IPPROTO_UDP ? _("UDP") : _("TCP")),
|
||||
+ port);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -523,7 +478,8 @@ static unsigned short getport(struct soc
|
||||
static int probe_port(clnt_addr_t *server, const unsigned long *versions,
|
||||
const unsigned int *protos)
|
||||
{
|
||||
- struct sockaddr_in *saddr = &server->saddr;
|
||||
+ const struct sockaddr *saddr = (struct sockaddr *)&server->saddr;
|
||||
+ const socklen_t salen = sizeof(server->saddr);
|
||||
struct pmap *pmap = &server->pmap;
|
||||
const unsigned long prog = pmap->pm_prog, *p_vers;
|
||||
const unsigned int prot = (u_int)pmap->pm_prot, *p_prot;
|
||||
@@ -535,21 +491,14 @@ static int probe_port(clnt_addr_t *serve
|
||||
p_vers = vers ? &vers : versions;
|
||||
rpc_createerr.cf_stat = 0;
|
||||
for (;;) {
|
||||
- p_port = getport(saddr, prog, *p_vers, *p_prot);
|
||||
+ p_port = nfs_getport(saddr, salen, prog, *p_vers, *p_prot);
|
||||
if (p_port) {
|
||||
if (!port || port == p_port) {
|
||||
- saddr->sin_port = htons(p_port);
|
||||
- if (verbose) {
|
||||
- printf(_("%s: trying %s prog %ld vers "
|
||||
- "%ld prot %s port %d\n"),
|
||||
- progname,
|
||||
- inet_ntoa(saddr->sin_addr),
|
||||
- prog, *p_vers,
|
||||
- *p_prot == IPPROTO_UDP ?
|
||||
- _("UDP") : _("TCP"),
|
||||
- p_port);
|
||||
- }
|
||||
- if (clnt_ping(saddr, prog, *p_vers, *p_prot, NULL))
|
||||
+ server->saddr.sin_port = htons(p_port);
|
||||
+ nfs_pp_debug(saddr, salen, prog, *p_vers,
|
||||
+ *p_prot, p_port);
|
||||
+ if (nfs_rpc_ping(saddr, salen, prog,
|
||||
+ *p_vers, *p_prot, NULL))
|
||||
goto out_ok;
|
||||
}
|
||||
}
|
||||
@@ -669,24 +618,16 @@ version_fixed:
|
||||
return probe_mntport(mnt_server);
|
||||
}
|
||||
|
||||
-static int probe_statd(void)
|
||||
+static int nfs_probe_statd(void)
|
||||
{
|
||||
- struct sockaddr_in addr;
|
||||
- unsigned short port;
|
||||
-
|
||||
- memset(&addr, 0, sizeof(addr));
|
||||
- addr.sin_family = AF_INET;
|
||||
- addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
- port = getport(&addr, 100024, 1, IPPROTO_UDP);
|
||||
-
|
||||
- if (port == 0)
|
||||
- return 0;
|
||||
- addr.sin_port = htons(port);
|
||||
-
|
||||
- if (clnt_ping(&addr, 100024, 1, IPPROTO_UDP, NULL) <= 0)
|
||||
- return 0;
|
||||
+ struct sockaddr_in addr = {
|
||||
+ .sin_family = AF_INET,
|
||||
+ .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
|
||||
+ };
|
||||
+ rpcprog_t program = nfs_getrpcbyname(NSMPROG, nfs_ns_pgmtbl);
|
||||
|
||||
- return 1;
|
||||
+ return nfs_getport_ping((struct sockaddr *)&addr, sizeof(addr),
|
||||
+ program, (rpcvers_t)1, IPPROTO_UDP);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -700,7 +641,7 @@ int start_statd(void)
|
||||
struct stat stb;
|
||||
#endif
|
||||
|
||||
- if (probe_statd())
|
||||
+ if (nfs_probe_statd())
|
||||
return 1;
|
||||
|
||||
#ifdef START_STATD
|
||||
@@ -712,13 +653,14 @@ int start_statd(void)
|
||||
execl(START_STATD, START_STATD, NULL);
|
||||
exit(1);
|
||||
case -1: /* error */
|
||||
- perror("Fork failed");
|
||||
+ nfs_error(_("fork failed: %s"),
|
||||
+ strerror(errno));
|
||||
break;
|
||||
default: /* parent */
|
||||
waitpid(pid, NULL,0);
|
||||
break;
|
||||
}
|
||||
- if (probe_statd())
|
||||
+ if (nfs_probe_statd())
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -829,9 +771,9 @@ void mnt_closeclnt(CLIENT *clnt, int mso
|
||||
* @prot: target RPC protocol
|
||||
* @caddr: filled in with our network address
|
||||
*
|
||||
- * Sigh... getport() doesn't actually check the version number.
|
||||
+ * Sigh... GETPORT queries don't actually check the version number.
|
||||
* In order to make sure that the server actually supports the service
|
||||
- * we're requesting, we open and RPC client, and fire off a NULL
|
||||
+ * we're requesting, we open an RPC client, and fire off a NULL
|
||||
* RPC call.
|
||||
*
|
||||
* caddr is the network address that the server will use to call us back.
|
@ -1,139 +0,0 @@
|
||||
commit e7ec5e745e851ad10c56d579463ee7e1b85c9c21
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Tue Feb 17 15:19:58 2009 -0500
|
||||
|
||||
text-based mount command: fix return value from po_rightmost()
|
||||
|
||||
Recently commit 0dcb83a8 changed the po_rightmost() function to
|
||||
distinguish among several possible mount options by taking a table
|
||||
containing the alternatives, and returning the table index of the
|
||||
entry which is rightmost in the mount option string.
|
||||
|
||||
If it didn't find any mount option that matches an entry from the
|
||||
passed-in table, it returned zero. This was the same behavior it had
|
||||
before, when it only checked for two options at a time. It returned
|
||||
PO_NEITHER_FOUND, which was zero.
|
||||
|
||||
Since this is C, however, zero also happens to be a valid index into
|
||||
the passed-in array of options.
|
||||
|
||||
Modify the po_rightmost() function to return -1 if the entry wasn't
|
||||
found, and fix up the callers to look for a C-style array index that
|
||||
starts at zero.
|
||||
|
||||
Thanks to Steve Dickson for troubleshooting the problem. His solution
|
||||
was merely to bump the return value, as callers already expected an
|
||||
ordinal index instead of a C-style index.
|
||||
|
||||
I prefer this equivalent but slightly more extensive change because it
|
||||
makes the behavior of po_rightmost() more closely match how humans
|
||||
understand C arrays to work. Let's address some of the confusion that
|
||||
caused this bug, as well as fixing the run-time behavior.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff -up nfs-utils-1.1.4/utils/mount/network.c.orig nfs-utils-1.1.4/utils/mount/network.c
|
||||
--- nfs-utils-1.1.4/utils/mount/network.c.orig 2009-02-17 15:51:27.000000000 -0500
|
||||
+++ nfs-utils-1.1.4/utils/mount/network.c 2009-02-17 15:52:13.000000000 -0500
|
||||
@@ -1168,16 +1168,16 @@ static rpcvers_t nfs_nfs_version(struct
|
||||
long tmp;
|
||||
|
||||
switch (po_rightmost(options, nfs_version_opttbl)) {
|
||||
- case 1: /* v2 */
|
||||
+ case 0: /* v2 */
|
||||
return 2;
|
||||
- case 2: /* v3 */
|
||||
+ case 1: /* v3 */
|
||||
return 3;
|
||||
- case 3: /* vers */
|
||||
+ case 2: /* vers */
|
||||
if (po_get_numeric(options, "vers", &tmp) == PO_FOUND)
|
||||
if (tmp >= 2 && tmp <= 3)
|
||||
return tmp;
|
||||
break;
|
||||
- case 4: /* nfsvers */
|
||||
+ case 3: /* nfsvers */
|
||||
if (po_get_numeric(options, "nfsvers", &tmp) == PO_FOUND)
|
||||
if (tmp >= 2 && tmp <= 3)
|
||||
return tmp;
|
||||
@@ -1198,11 +1198,9 @@ static unsigned short nfs_nfs_protocol(s
|
||||
char *option;
|
||||
|
||||
switch (po_rightmost(options, nfs_transport_opttbl)) {
|
||||
- case 1: /* udp */
|
||||
- return IPPROTO_UDP;
|
||||
- case 2: /* tcp */
|
||||
+ case 1: /* tcp */
|
||||
return IPPROTO_TCP;
|
||||
- case 3: /* proto */
|
||||
+ case 2: /* proto */
|
||||
option = po_get(options, "proto");
|
||||
if (option) {
|
||||
if (strcmp(option, "tcp") == 0)
|
||||
@@ -1211,6 +1209,7 @@ static unsigned short nfs_nfs_protocol(s
|
||||
return IPPROTO_UDP;
|
||||
}
|
||||
}
|
||||
+
|
||||
return IPPROTO_UDP;
|
||||
}
|
||||
|
||||
diff -up nfs-utils-1.1.4/utils/mount/parse_opt.c.orig nfs-utils-1.1.4/utils/mount/parse_opt.c
|
||||
--- nfs-utils-1.1.4/utils/mount/parse_opt.c.orig 2009-02-17 15:51:27.000000000 -0500
|
||||
+++ nfs-utils-1.1.4/utils/mount/parse_opt.c 2009-02-17 15:52:13.000000000 -0500
|
||||
@@ -437,9 +437,10 @@ po_found_t po_get_numeric(struct mount_o
|
||||
* as "proto=," "udp" and "tcp."
|
||||
*
|
||||
* Returns the index into @keys of the option that is rightmost.
|
||||
- * If none of the options are present, returns zero.
|
||||
+ * If none of the options listed in @keys is present in @options, or
|
||||
+ * if @options is NULL, returns -1.
|
||||
*/
|
||||
-unsigned int po_rightmost(struct mount_options *options, const char *keys[])
|
||||
+int po_rightmost(struct mount_options *options, const char *keys[])
|
||||
{
|
||||
struct mount_option *option;
|
||||
unsigned int i;
|
||||
@@ -452,7 +453,7 @@ unsigned int po_rightmost(struct mount_o
|
||||
}
|
||||
}
|
||||
|
||||
- return 0;
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
diff -up nfs-utils-1.1.4/utils/mount/parse_opt.h.orig nfs-utils-1.1.4/utils/mount/parse_opt.h
|
||||
--- nfs-utils-1.1.4/utils/mount/parse_opt.h.orig 2009-02-17 15:51:27.000000000 -0500
|
||||
+++ nfs-utils-1.1.4/utils/mount/parse_opt.h 2009-02-17 15:52:13.000000000 -0500
|
||||
@@ -47,7 +47,7 @@ po_found_t po_contains(struct mount_opt
|
||||
char * po_get(struct mount_options *, char *);
|
||||
po_found_t po_get_numeric(struct mount_options *,
|
||||
char *, long *);
|
||||
-unsigned int po_rightmost(struct mount_options *,
|
||||
+int po_rightmost(struct mount_options *,
|
||||
const char *keys[]);
|
||||
po_found_t po_remove_all(struct mount_options *, char *);
|
||||
void po_destroy(struct mount_options *);
|
||||
diff -up nfs-utils-1.1.4/utils/mount/stropts.c.orig nfs-utils-1.1.4/utils/mount/stropts.c
|
||||
--- nfs-utils-1.1.4/utils/mount/stropts.c.orig 2009-02-17 15:51:27.000000000 -0500
|
||||
+++ nfs-utils-1.1.4/utils/mount/stropts.c 2009-02-17 15:52:13.000000000 -0500
|
||||
@@ -232,7 +232,7 @@ static const char *nfs_lock_opttbl[] = {
|
||||
|
||||
static int nfs_verify_lock_option(struct mount_options *options)
|
||||
{
|
||||
- if (po_rightmost(options, nfs_lock_opttbl) == 1)
|
||||
+ if (po_rightmost(options, nfs_lock_opttbl) == 0)
|
||||
return 1;
|
||||
|
||||
if (!start_statd()) {
|
||||
@@ -756,7 +756,7 @@ static int nfsmount_start(struct nfsmoun
|
||||
if (!nfs_validate_options(mi))
|
||||
return EX_FAIL;
|
||||
|
||||
- if (po_rightmost(mi->options, nfs_background_opttbl) == 1)
|
||||
+ if (po_rightmost(mi->options, nfs_background_opttbl) == 0)
|
||||
return nfsmount_bg(mi);
|
||||
else
|
||||
return nfsmount_fg(mi);
|
@ -1,153 +0,0 @@
|
||||
commit b5009d23525181846777349f2fc0e4a72b89d24d
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Wed Dec 17 14:21:10 2008 -0500
|
||||
|
||||
text-based mount command: add function to parse numeric mount options
|
||||
|
||||
Introduce a function that is especially for parsing keyword mount options
|
||||
that take a numeric value.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff --git a/utils/mount/parse_opt.c b/utils/mount/parse_opt.c
|
||||
index cb398bd..f61d0dd 100644
|
||||
--- a/utils/mount/parse_opt.c
|
||||
+++ b/utils/mount/parse_opt.c
|
||||
@@ -36,6 +36,10 @@
|
||||
*/
|
||||
|
||||
|
||||
+#ifdef HAVE_CONFIG_H
|
||||
+#include <config.h>
|
||||
+#endif
|
||||
+
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
@@ -366,6 +370,57 @@ char *po_get(struct mount_options *options, char *keyword)
|
||||
}
|
||||
|
||||
/**
|
||||
+ * po_get_numeric - return numeric value of rightmost instance of keyword option
|
||||
+ * @options: pointer to mount options
|
||||
+ * @keyword: pointer to a C string containing option keyword for which to search
|
||||
+ * @value: OUT: set to the value of the keyword
|
||||
+ *
|
||||
+ * This is specifically for parsing keyword options that take only a numeric
|
||||
+ * value. If multiple instances of the same option are present in a mount
|
||||
+ * option list, the rightmost instance is always the effective one.
|
||||
+ *
|
||||
+ * Returns:
|
||||
+ * * PO_FOUND if the keyword was found and the value is numeric; @value is
|
||||
+ * set to the keyword's value
|
||||
+ * * PO_NOT_FOUND if the keyword was not found
|
||||
+ * * PO_BAD_VALUE if the keyword was found, but the value is not numeric
|
||||
+ *
|
||||
+ * These last two are separate in case the caller wants to warn about bad mount
|
||||
+ * options instead of silently using a default.
|
||||
+ */
|
||||
+#ifdef HAVE_STRTOL
|
||||
+po_found_t po_get_numeric(struct mount_options *options, char *keyword, long *value)
|
||||
+{
|
||||
+ char *option, *endptr;
|
||||
+ long tmp;
|
||||
+
|
||||
+ option = po_get(options, keyword);
|
||||
+ if (option == NULL)
|
||||
+ return PO_NOT_FOUND;
|
||||
+
|
||||
+ errno = 0;
|
||||
+ tmp = strtol(option, &endptr, 10);
|
||||
+ if (errno == 0 && endptr != option) {
|
||||
+ *value = tmp;
|
||||
+ return PO_FOUND;
|
||||
+ }
|
||||
+ return PO_BAD_VALUE;
|
||||
+}
|
||||
+#else /* HAVE_STRTOL */
|
||||
+po_found_t po_get_numeric(struct mount_options *options, char *keyword, long *value)
|
||||
+{
|
||||
+ char *option;
|
||||
+
|
||||
+ option = po_get(options, keyword);
|
||||
+ if (option == NULL)
|
||||
+ return PO_NOT_FOUND;
|
||||
+
|
||||
+ *value = atoi(option);
|
||||
+ return PO_FOUND;
|
||||
+}
|
||||
+#endif /* HAVE_STRTOL */
|
||||
+
|
||||
+/**
|
||||
* po_rightmost - determine the relative position of two options
|
||||
* @options: pointer to mount options
|
||||
* @key1: pointer to a C string containing an option keyword
|
||||
diff --git a/utils/mount/parse_opt.h b/utils/mount/parse_opt.h
|
||||
index fb003c3..199630f 100644
|
||||
--- a/utils/mount/parse_opt.h
|
||||
+++ b/utils/mount/parse_opt.h
|
||||
@@ -32,6 +32,7 @@ typedef enum {
|
||||
typedef enum {
|
||||
PO_NOT_FOUND = 0,
|
||||
PO_FOUND = 1,
|
||||
+ PO_BAD_VALUE = 2,
|
||||
} po_found_t;
|
||||
|
||||
typedef enum {
|
||||
@@ -50,6 +51,8 @@ po_return_t po_join(struct mount_options *, char **);
|
||||
po_return_t po_append(struct mount_options *, char *);
|
||||
po_found_t po_contains(struct mount_options *, char *);
|
||||
char * po_get(struct mount_options *, char *);
|
||||
+po_found_t po_get_numeric(struct mount_options *,
|
||||
+ char *, long *);
|
||||
po_rightmost_t po_rightmost(struct mount_options *, char *, char *);
|
||||
po_found_t po_remove_all(struct mount_options *, char *);
|
||||
void po_destroy(struct mount_options *);
|
||||
commit 3f23f712477df48fd1d57376b65c44bb2a19ec16
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Wed Dec 17 14:23:43 2008 -0500
|
||||
|
||||
text-based mount command: use po_get_numeric() for handling retry
|
||||
|
||||
Replace the logic in nfs_parse_retry_option() with a call to the new
|
||||
po_get_numeric() function.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
|
||||
index 09fca86..43791e6 100644
|
||||
--- a/utils/mount/stropts.c
|
||||
+++ b/utils/mount/stropts.c
|
||||
@@ -99,19 +99,21 @@ struct nfsmount_info {
|
||||
static time_t nfs_parse_retry_option(struct mount_options *options,
|
||||
unsigned int timeout_minutes)
|
||||
{
|
||||
- char *retry_option, *endptr;
|
||||
+ long tmp;
|
||||
|
||||
- retry_option = po_get(options, "retry");
|
||||
- if (retry_option) {
|
||||
- long tmp;
|
||||
-
|
||||
- errno = 0;
|
||||
- tmp = strtol(retry_option, &endptr, 10);
|
||||
- if (errno == 0 && endptr != retry_option && tmp >= 0)
|
||||
+ switch (po_get_numeric(options, "retry", &tmp)) {
|
||||
+ case PO_NOT_FOUND:
|
||||
+ break;
|
||||
+ case PO_FOUND:
|
||||
+ if (tmp >= 0) {
|
||||
timeout_minutes = tmp;
|
||||
- else if (verbose)
|
||||
+ break;
|
||||
+ }
|
||||
+ case PO_BAD_VALUE:
|
||||
+ if (verbose)
|
||||
nfs_error(_("%s: invalid retry timeout was specified; "
|
||||
"using default timeout"), progname);
|
||||
+ break;
|
||||
}
|
||||
|
||||
return time(NULL) + (time_t)(timeout_minutes * 60);
|
@ -1,821 +0,0 @@
|
||||
text-based mount command: make po_rightmost() work for N options
|
||||
|
||||
Sometimes we need to choose the rightmost option among multiple
|
||||
different mount options. For example, we want to find the rightmost
|
||||
of "proto," "tcp," and "udp". Or, the rightmost of "vers," "nfsvers,"
|
||||
"v2," and "v3".
|
||||
|
||||
Update po_rightmost() to choose among N options instead of just two.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
---
|
||||
|
||||
utils/mount/parse_opt.c | 28 ++++++++++++++++------------
|
||||
utils/mount/parse_opt.h | 9 ++-------
|
||||
utils/mount/stropts.c | 28 +++++++++++++++++++++++-----
|
||||
3 files changed, 41 insertions(+), 24 deletions(-)
|
||||
|
||||
diff --git a/utils/mount/parse_opt.c b/utils/mount/parse_opt.c
|
||||
index f61d0dd..4934508 100644
|
||||
--- a/utils/mount/parse_opt.c
|
||||
+++ b/utils/mount/parse_opt.c
|
||||
@@ -421,34 +421,38 @@ po_found_t po_get_numeric(struct mount_options *options, char *keyword, long *va
|
||||
#endif /* HAVE_STRTOL */
|
||||
|
||||
/**
|
||||
- * po_rightmost - determine the relative position of two options
|
||||
+ * po_rightmost - determine the relative position of several options
|
||||
* @options: pointer to mount options
|
||||
- * @key1: pointer to a C string containing an option keyword
|
||||
- * @key2: pointer to a C string containing another option keyword
|
||||
+ * @keys: pointer to an array of C strings containing option keywords
|
||||
+ *
|
||||
+ * This function can be used to determine which of several similar
|
||||
+ * options will be the one to take effect.
|
||||
*
|
||||
* The kernel parses the mount option string from left to right.
|
||||
* If an option is specified more than once (for example, "intr"
|
||||
* and "nointr", the rightmost option is the last to be parsed,
|
||||
* and it therefore takes precedence over previous similar options.
|
||||
*
|
||||
- * This function can be used to determine which of two similar
|
||||
- * options will be the one to take effect.
|
||||
+ * This can also distinguish among multiple synonymous options, such
|
||||
+ * as "proto=," "udp" and "tcp."
|
||||
+ *
|
||||
+ * Returns the index into @keys of the option that is rightmost.
|
||||
+ * If none of the options are present, returns zero.
|
||||
*/
|
||||
-po_rightmost_t po_rightmost(struct mount_options *options,
|
||||
- char *key1, char *key2)
|
||||
+unsigned int po_rightmost(struct mount_options *options, const char *keys[])
|
||||
{
|
||||
struct mount_option *option;
|
||||
+ unsigned int i;
|
||||
|
||||
if (options) {
|
||||
for (option = options->tail; option; option = option->prev) {
|
||||
- if (key2 && strcmp(option->keyword, key2) == 0)
|
||||
- return PO_KEY2_RIGHTMOST;
|
||||
- if (key1 && strcmp(option->keyword, key1) == 0)
|
||||
- return PO_KEY1_RIGHTMOST;
|
||||
+ for (i = 0; keys[i] != NULL; i++)
|
||||
+ if (strcmp(option->keyword, keys[i]) == 0)
|
||||
+ return i;
|
||||
}
|
||||
}
|
||||
|
||||
- return PO_NEITHER_FOUND;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
diff --git a/utils/mount/parse_opt.h b/utils/mount/parse_opt.h
|
||||
index 199630f..e132b1c 100644
|
||||
--- a/utils/mount/parse_opt.h
|
||||
+++ b/utils/mount/parse_opt.h
|
||||
@@ -35,12 +35,6 @@ typedef enum {
|
||||
PO_BAD_VALUE = 2,
|
||||
} po_found_t;
|
||||
|
||||
-typedef enum {
|
||||
- PO_KEY1_RIGHTMOST = -1,
|
||||
- PO_NEITHER_FOUND = 0,
|
||||
- PO_KEY2_RIGHTMOST = 1,
|
||||
-} po_rightmost_t;
|
||||
-
|
||||
struct mount_options;
|
||||
|
||||
struct mount_options * po_split(char *);
|
||||
@@ -53,7 +47,8 @@ po_found_t po_contains(struct mount_options *, char *);
|
||||
char * po_get(struct mount_options *, char *);
|
||||
po_found_t po_get_numeric(struct mount_options *,
|
||||
char *, long *);
|
||||
-po_rightmost_t po_rightmost(struct mount_options *, char *, char *);
|
||||
+unsigned int po_rightmost(struct mount_options *,
|
||||
+ const char *keys[]);
|
||||
po_found_t po_remove_all(struct mount_options *, char *);
|
||||
void po_destroy(struct mount_options *);
|
||||
|
||||
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
|
||||
index 43791e6..bd127ab 100644
|
||||
--- a/utils/mount/stropts.c
|
||||
+++ b/utils/mount/stropts.c
|
||||
@@ -224,9 +224,15 @@ static int nfs_fix_mounthost_option(const sa_family_t family,
|
||||
* Returns zero if the "lock" option is in effect, but statd
|
||||
* can't be started. Otherwise, returns 1.
|
||||
*/
|
||||
+static const char *nfs_lock_opttbl[] = {
|
||||
+ "nolock",
|
||||
+ "lock",
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
static int nfs_verify_lock_option(struct mount_options *options)
|
||||
{
|
||||
- if (po_rightmost(options, "nolock", "lock") == PO_KEY1_RIGHTMOST)
|
||||
+ if (po_rightmost(options, nfs_lock_opttbl) == 1)
|
||||
return 1;
|
||||
|
||||
if (!start_statd()) {
|
||||
@@ -316,6 +322,12 @@ static int nfs_is_permanent_error(int error)
|
||||
* Returns a new group of mount options if successful; otherwise
|
||||
* NULL is returned if some failure occurred.
|
||||
*/
|
||||
+static const char *nfs_transport_opttbl[] = {
|
||||
+ "udp",
|
||||
+ "tcp",
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
static struct mount_options *nfs_rewrite_mount_options(char *str)
|
||||
{
|
||||
struct mount_options *options;
|
||||
@@ -395,12 +407,12 @@ static struct mount_options *nfs_rewrite_mount_options(char *str)
|
||||
po_remove_all(options, "proto");
|
||||
}
|
||||
}
|
||||
- p = po_rightmost(options, "tcp", "udp");
|
||||
+ p = po_rightmost(options, nfs_transport_opttbl);
|
||||
switch (p) {
|
||||
- case PO_KEY2_RIGHTMOST:
|
||||
+ case 1:
|
||||
nfs_server.pmap.pm_prot = IPPROTO_UDP;
|
||||
break;
|
||||
- case PO_KEY1_RIGHTMOST:
|
||||
+ case 2:
|
||||
nfs_server.pmap.pm_prot = IPPROTO_TCP;
|
||||
break;
|
||||
}
|
||||
@@ -722,12 +734,18 @@ static int nfsmount_bg(struct nfsmount_info *mi)
|
||||
*
|
||||
* Returns a valid mount command exit code.
|
||||
*/
|
||||
+static const char *nfs_background_opttbl[] = {
|
||||
+ "bg",
|
||||
+ "fg",
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
static int nfsmount_start(struct nfsmount_info *mi)
|
||||
{
|
||||
if (!nfs_validate_options(mi))
|
||||
return EX_FAIL;
|
||||
|
||||
- if (po_rightmost(mi->options, "bg", "fg") == PO_KEY1_RIGHTMOST)
|
||||
+ if (po_rightmost(mi->options, nfs_background_opttbl) == 1)
|
||||
return nfsmount_bg(mi);
|
||||
else
|
||||
return nfsmount_fg(mi);
|
||||
|
||||
text-based mount command: Function to stuff "struct pmap" from mount options
|
||||
|
||||
Both the text-based mount.nfs command and the umount.nfs command need
|
||||
to fill in a pmap structure based on string mount options. Introduce
|
||||
a shared function that can do this.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
---
|
||||
|
||||
utils/mount/network.c | 214 +++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
utils/mount/network.h | 5 +
|
||||
2 files changed, 219 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/utils/mount/network.c b/utils/mount/network.c
|
||||
index d262e94..91a005c 100644
|
||||
--- a/utils/mount/network.c
|
||||
+++ b/utils/mount/network.c
|
||||
@@ -48,6 +48,7 @@
|
||||
#include "nfs_mount.h"
|
||||
#include "mount_constants.h"
|
||||
#include "nfsrpc.h"
|
||||
+#include "parse_opt.h"
|
||||
#include "network.h"
|
||||
|
||||
#define PMAP_TIMEOUT (10)
|
||||
@@ -67,6 +68,33 @@ static const char *nfs_ns_pgmtbl[] = {
|
||||
NULL,
|
||||
};
|
||||
|
||||
+static const char *nfs_mnt_pgmtbl[] = {
|
||||
+ "mount",
|
||||
+ "mountd",
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static const char *nfs_nfs_pgmtbl[] = {
|
||||
+ "nfs",
|
||||
+ "nfsprog",
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static const char *nfs_transport_opttbl[] = {
|
||||
+ "udp",
|
||||
+ "tcp",
|
||||
+ "proto",
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static const char *nfs_version_opttbl[] = {
|
||||
+ "v2",
|
||||
+ "v3",
|
||||
+ "vers",
|
||||
+ "nfsvers",
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
static const unsigned long nfs_to_mnt[] = {
|
||||
0,
|
||||
0,
|
||||
@@ -1111,3 +1139,189 @@ out_failed:
|
||||
return 0;
|
||||
|
||||
}
|
||||
+
|
||||
+/*
|
||||
+ * "nfsprog" is only supported by the legacy mount command. The
|
||||
+ * kernel mount client does not support this option.
|
||||
+ *
|
||||
+ * Returns the value set by the nfsprog= option, the value of
|
||||
+ * the RPC NFS program specified in /etc/rpc, or a baked-in
|
||||
+ * default program number, if all fails.
|
||||
+ */
|
||||
+static rpcprog_t nfs_nfs_program(struct mount_options *options)
|
||||
+{
|
||||
+ long tmp;
|
||||
+
|
||||
+ if (po_get_numeric(options, "nfsprog", &tmp) == PO_FOUND)
|
||||
+ if (tmp >= 0)
|
||||
+ return tmp;
|
||||
+ return nfs_getrpcbyname(NFSPROG, nfs_nfs_pgmtbl);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Returns the RPC version number specified by the given mount
|
||||
+ * options for the NFS service, or zero if all fails.
|
||||
+ */
|
||||
+static rpcvers_t nfs_nfs_version(struct mount_options *options)
|
||||
+{
|
||||
+ long tmp;
|
||||
+
|
||||
+ switch (po_rightmost(options, nfs_version_opttbl)) {
|
||||
+ case 1: /* v2 */
|
||||
+ return 2;
|
||||
+ case 2: /* v3 */
|
||||
+ return 3;
|
||||
+ case 3: /* vers */
|
||||
+ if (po_get_numeric(options, "vers", &tmp) == PO_FOUND)
|
||||
+ if (tmp >= 2 && tmp <= 3)
|
||||
+ return tmp;
|
||||
+ break;
|
||||
+ case 4: /* nfsvers */
|
||||
+ if (po_get_numeric(options, "nfsvers", &tmp) == PO_FOUND)
|
||||
+ if (tmp >= 2 && tmp <= 3)
|
||||
+ return tmp;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Returns the NFS transport protocol specified by the given mount options
|
||||
+ *
|
||||
+ * Returns the IPPROTO_ value specified by the given mount options, or
|
||||
+ * IPPROTO_UDP if all fails.
|
||||
+ */
|
||||
+static unsigned short nfs_nfs_protocol(struct mount_options *options)
|
||||
+{
|
||||
+ char *option;
|
||||
+
|
||||
+ switch (po_rightmost(options, nfs_transport_opttbl)) {
|
||||
+ case 1: /* udp */
|
||||
+ return IPPROTO_UDP;
|
||||
+ case 2: /* tcp */
|
||||
+ return IPPROTO_TCP;
|
||||
+ case 3: /* proto */
|
||||
+ option = po_get(options, "proto");
|
||||
+ if (option) {
|
||||
+ if (strcmp(option, "tcp") == 0)
|
||||
+ return IPPROTO_TCP;
|
||||
+ if (strcmp(option, "udp") == 0)
|
||||
+ return IPPROTO_UDP;
|
||||
+ }
|
||||
+ }
|
||||
+ return IPPROTO_UDP;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Returns the NFS server's port number specified by the given
|
||||
+ * mount options, or zero if all fails. Zero results in a portmap
|
||||
+ * query to discover the server's mountd service port.
|
||||
+ *
|
||||
+ * port=0 will guarantee an rpcbind request precedes the first
|
||||
+ * NFS RPC so the client can determine the server's port number.
|
||||
+ */
|
||||
+static unsigned short nfs_nfs_port(struct mount_options *options)
|
||||
+{
|
||||
+ long tmp;
|
||||
+
|
||||
+ if (po_get_numeric(options, "port", &tmp) == PO_FOUND)
|
||||
+ if (tmp >= 0 && tmp <= 65535)
|
||||
+ return tmp;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * "mountprog" is only supported by the legacy mount command. The
|
||||
+ * kernel mount client does not support this option.
|
||||
+ *
|
||||
+ * Returns the value set by the mountprog= option, the value of
|
||||
+ * the RPC mount program specified in /etc/rpc, or a baked-in
|
||||
+ * default program number, if all fails.
|
||||
+ */
|
||||
+static rpcprog_t nfs_mount_program(struct mount_options *options)
|
||||
+{
|
||||
+ long tmp;
|
||||
+
|
||||
+ if (po_get_numeric(options, "mountprog", &tmp) == PO_FOUND)
|
||||
+ if (tmp >= 0)
|
||||
+ return tmp;
|
||||
+ return nfs_getrpcbyname(MOUNTPROG, nfs_mnt_pgmtbl);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Returns the RPC version number specified by the given mount options,
|
||||
+ * or the version "3" if all fails.
|
||||
+ */
|
||||
+static rpcvers_t nfs_mount_version(struct mount_options *options)
|
||||
+{
|
||||
+ long tmp;
|
||||
+
|
||||
+ if (po_get_numeric(options, "mountvers", &tmp) == PO_FOUND)
|
||||
+ if (tmp >= 1 && tmp <= 4)
|
||||
+ return tmp;
|
||||
+
|
||||
+ return nfsvers_to_mnt(nfs_nfs_version(options));
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Returns the transport protocol to use for the mount service
|
||||
+ *
|
||||
+ * Returns the IPPROTO_ value specified by the mountproto option, or
|
||||
+ * if that doesn't exist, the IPPROTO_ value specified for NFS
|
||||
+ * itself.
|
||||
+ */
|
||||
+static unsigned short nfs_mount_protocol(struct mount_options *options)
|
||||
+{
|
||||
+ char *option;
|
||||
+
|
||||
+ option = po_get(options, "mountproto");
|
||||
+ if (option) {
|
||||
+ if (strcmp(option, "tcp") == 0)
|
||||
+ return IPPROTO_TCP;
|
||||
+ if (strcmp(option, "udp") == 0)
|
||||
+ return IPPROTO_UDP;
|
||||
+ }
|
||||
+
|
||||
+ return nfs_nfs_version(options);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Returns the mountd server's port number specified by the given
|
||||
+ * mount options, or zero if all fails. Zero results in a portmap
|
||||
+ * query to discover the server's mountd service port.
|
||||
+ *
|
||||
+ * port=0 will guarantee an rpcbind request precedes the mount
|
||||
+ * RPC so the client can determine the server's port number.
|
||||
+ */
|
||||
+static unsigned short nfs_mount_port(struct mount_options *options)
|
||||
+{
|
||||
+ long tmp;
|
||||
+
|
||||
+ if (po_get_numeric(options, "mountport", &tmp) == PO_FOUND)
|
||||
+ if (tmp >= 0 && tmp <= 65535)
|
||||
+ return tmp;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * nfs_options2pmap - set up pmap structs based on mount options
|
||||
+ * @options: pointer to mount options
|
||||
+ * @nfs_pmap: OUT: pointer to pmap arguments for NFS server
|
||||
+ * @mnt_pmap: OUT: pointer to pmap arguments for mountd server
|
||||
+ *
|
||||
+ */
|
||||
+void nfs_options2pmap(struct mount_options *options,
|
||||
+ struct pmap *nfs_pmap, struct pmap *mnt_pmap)
|
||||
+{
|
||||
+ nfs_pmap->pm_prog = nfs_nfs_program(options);
|
||||
+ nfs_pmap->pm_vers = nfs_nfs_version(options);
|
||||
+ nfs_pmap->pm_prot = nfs_nfs_protocol(options);
|
||||
+ nfs_pmap->pm_port = nfs_nfs_port(options);
|
||||
+
|
||||
+ mnt_pmap->pm_prog = nfs_mount_program(options);
|
||||
+ mnt_pmap->pm_vers = nfs_mount_version(options);
|
||||
+ mnt_pmap->pm_prot = nfs_mount_protocol(options);
|
||||
+ mnt_pmap->pm_port = nfs_mount_port(options);
|
||||
+}
|
||||
diff --git a/utils/mount/network.h b/utils/mount/network.h
|
||||
index 075093d..25060ab 100644
|
||||
--- a/utils/mount/network.h
|
||||
+++ b/utils/mount/network.h
|
||||
@@ -57,6 +57,11 @@ int clnt_ping(struct sockaddr_in *, const unsigned long,
|
||||
const unsigned long, const unsigned int,
|
||||
struct sockaddr_in *);
|
||||
|
||||
+struct mount_options;
|
||||
+
|
||||
+void nfs_options2pmap(struct mount_options *,
|
||||
+ struct pmap *, struct pmap *);
|
||||
+
|
||||
int start_statd(void);
|
||||
|
||||
unsigned long nfsvers_to_mnt(const unsigned long);
|
||||
|
||||
text-based mount options: Use new pmap stuffer when rewriting mount options
|
||||
|
||||
all nfs_options2pmap() in nfs_rewrite_mount_options() instead of
|
||||
open-coding the logic to convert mount options to a pmap struct.
|
||||
The new nfs_options2pmap() function is more careful about avoiding
|
||||
invalid mount option values, and handles multiply-specified transport
|
||||
protocol options correctly.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
---
|
||||
|
||||
utils/mount/stropts.c | 68 ++++---------------------------------------------
|
||||
1 files changed, 5 insertions(+), 63 deletions(-)
|
||||
|
||||
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
|
||||
index bd127ab..99be0f3 100644
|
||||
--- a/utils/mount/stropts.c
|
||||
+++ b/utils/mount/stropts.c
|
||||
@@ -322,19 +322,12 @@ static int nfs_is_permanent_error(int error)
|
||||
* Returns a new group of mount options if successful; otherwise
|
||||
* NULL is returned if some failure occurred.
|
||||
*/
|
||||
-static const char *nfs_transport_opttbl[] = {
|
||||
- "udp",
|
||||
- "tcp",
|
||||
- NULL,
|
||||
-};
|
||||
-
|
||||
static struct mount_options *nfs_rewrite_mount_options(char *str)
|
||||
{
|
||||
struct mount_options *options;
|
||||
char *option, new_option[64];
|
||||
clnt_addr_t mnt_server = { };
|
||||
clnt_addr_t nfs_server = { };
|
||||
- int p;
|
||||
|
||||
options = po_split(str);
|
||||
if (!options) {
|
||||
@@ -360,64 +353,13 @@ static struct mount_options *nfs_rewrite_mount_options(char *str)
|
||||
memcpy(&mnt_server.saddr, &nfs_server.saddr,
|
||||
sizeof(mnt_server.saddr));
|
||||
|
||||
- option = po_get(options, "mountport");
|
||||
- if (option)
|
||||
- mnt_server.pmap.pm_port = atoi(option);
|
||||
- mnt_server.pmap.pm_prog = MOUNTPROG;
|
||||
- option = po_get(options, "mountvers");
|
||||
- if (option)
|
||||
- mnt_server.pmap.pm_vers = atoi(option);
|
||||
- option = po_get(options, "mountproto");
|
||||
- if (option) {
|
||||
- if (strcmp(option, "tcp") == 0) {
|
||||
- mnt_server.pmap.pm_prot = IPPROTO_TCP;
|
||||
- po_remove_all(options, "mountproto");
|
||||
- }
|
||||
- if (strcmp(option, "udp") == 0) {
|
||||
- mnt_server.pmap.pm_prot = IPPROTO_UDP;
|
||||
- po_remove_all(options, "mountproto");
|
||||
- }
|
||||
- }
|
||||
+ nfs_options2pmap(options, &nfs_server.pmap, &mnt_server.pmap);
|
||||
|
||||
- option = po_get(options, "port");
|
||||
- if (option) {
|
||||
- nfs_server.pmap.pm_port = atoi(option);
|
||||
- po_remove_all(options, "port");
|
||||
- }
|
||||
+ /* The kernel NFS client doesn't support changing the RPC program
|
||||
+ * number for these services, so reset these fields before probing
|
||||
+ * the server's ports. */
|
||||
nfs_server.pmap.pm_prog = NFS_PROGRAM;
|
||||
-
|
||||
- option = po_get(options, "nfsvers");
|
||||
- if (option) {
|
||||
- nfs_server.pmap.pm_vers = atoi(option);
|
||||
- po_remove_all(options, "nfsvers");
|
||||
- }
|
||||
- option = po_get(options, "vers");
|
||||
- if (option) {
|
||||
- nfs_server.pmap.pm_vers = atoi(option);
|
||||
- po_remove_all(options, "vers");
|
||||
- }
|
||||
- option = po_get(options, "proto");
|
||||
- if (option) {
|
||||
- if (strcmp(option, "tcp") == 0) {
|
||||
- nfs_server.pmap.pm_prot = IPPROTO_TCP;
|
||||
- po_remove_all(options, "proto");
|
||||
- }
|
||||
- if (strcmp(option, "udp") == 0) {
|
||||
- nfs_server.pmap.pm_prot = IPPROTO_UDP;
|
||||
- po_remove_all(options, "proto");
|
||||
- }
|
||||
- }
|
||||
- p = po_rightmost(options, nfs_transport_opttbl);
|
||||
- switch (p) {
|
||||
- case 1:
|
||||
- nfs_server.pmap.pm_prot = IPPROTO_UDP;
|
||||
- break;
|
||||
- case 2:
|
||||
- nfs_server.pmap.pm_prot = IPPROTO_TCP;
|
||||
- break;
|
||||
- }
|
||||
- po_remove_all(options, "tcp");
|
||||
- po_remove_all(options, "udp");
|
||||
+ mnt_server.pmap.pm_prog = MOUNTPROG;
|
||||
|
||||
if (!probe_bothports(&mnt_server, &nfs_server)) {
|
||||
errno = ESPIPE;
|
||||
|
||||
text-based mount command: fix mount option rewriting logic
|
||||
|
||||
Fix a bunch of corner cases in the text-based mount option rewriting logic.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
---
|
||||
|
||||
utils/mount/stropts.c | 113 ++++++++++++++++++++++++++++++++++---------------
|
||||
1 files changed, 79 insertions(+), 34 deletions(-)
|
||||
|
||||
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
|
||||
index 99be0f3..319be71 100644
|
||||
--- a/utils/mount/stropts.c
|
||||
+++ b/utils/mount/stropts.c
|
||||
@@ -309,6 +309,81 @@ static int nfs_is_permanent_error(int error)
|
||||
}
|
||||
}
|
||||
|
||||
+static int nfs_construct_new_options(struct mount_options *options,
|
||||
+ struct pmap *nfs_pmap,
|
||||
+ struct pmap *mnt_pmap)
|
||||
+{
|
||||
+ char new_option[64];
|
||||
+
|
||||
+ po_remove_all(options, "nfsprog");
|
||||
+ po_remove_all(options, "mountprog");
|
||||
+
|
||||
+ po_remove_all(options, "v2");
|
||||
+ po_remove_all(options, "v3");
|
||||
+ po_remove_all(options, "vers");
|
||||
+ po_remove_all(options, "nfsvers");
|
||||
+ snprintf(new_option, sizeof(new_option) - 1,
|
||||
+ "vers=%lu", nfs_pmap->pm_vers);
|
||||
+ if (po_append(options, new_option) == PO_FAILED)
|
||||
+ return 0;
|
||||
+
|
||||
+ po_remove_all(options, "proto");
|
||||
+ po_remove_all(options, "udp");
|
||||
+ po_remove_all(options, "tcp");
|
||||
+ switch (nfs_pmap->pm_prot) {
|
||||
+ case IPPROTO_TCP:
|
||||
+ snprintf(new_option, sizeof(new_option) - 1,
|
||||
+ "proto=tcp");
|
||||
+ if (po_append(options, new_option) == PO_FAILED)
|
||||
+ return 0;
|
||||
+ break;
|
||||
+ case IPPROTO_UDP:
|
||||
+ snprintf(new_option, sizeof(new_option) - 1,
|
||||
+ "proto=udp");
|
||||
+ if (po_append(options, new_option) == PO_FAILED)
|
||||
+ return 0;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ po_remove_all(options, "port");
|
||||
+ if (nfs_pmap->pm_port != NFS_PORT) {
|
||||
+ snprintf(new_option, sizeof(new_option) - 1,
|
||||
+ "port=%lu", nfs_pmap->pm_port);
|
||||
+ if (po_append(options, new_option) == PO_FAILED)
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ po_remove_all(options, "mountvers");
|
||||
+ snprintf(new_option, sizeof(new_option) - 1,
|
||||
+ "mountvers=%lu", mnt_pmap->pm_vers);
|
||||
+ if (po_append(options, new_option) == PO_FAILED)
|
||||
+ return 0;
|
||||
+
|
||||
+ po_remove_all(options, "mountproto");
|
||||
+ switch (mnt_pmap->pm_prot) {
|
||||
+ case IPPROTO_TCP:
|
||||
+ snprintf(new_option, sizeof(new_option) - 1,
|
||||
+ "mountproto=tcp");
|
||||
+ if (po_append(options, new_option) == PO_FAILED)
|
||||
+ return 0;
|
||||
+ break;
|
||||
+ case IPPROTO_UDP:
|
||||
+ snprintf(new_option, sizeof(new_option) - 1,
|
||||
+ "mountproto=udp");
|
||||
+ if (po_append(options, new_option) == PO_FAILED)
|
||||
+ return 0;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ po_remove_all(options, "mountport");
|
||||
+ snprintf(new_option, sizeof(new_option) - 1,
|
||||
+ "mountport=%lu", mnt_pmap->pm_port);
|
||||
+ if (po_append(options, new_option) == PO_FAILED)
|
||||
+ return 0;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Reconstruct the mount option string based on a portmapper probe
|
||||
* of the server. Returns one if the server's portmapper returned
|
||||
@@ -325,7 +400,7 @@ static int nfs_is_permanent_error(int error)
|
||||
static struct mount_options *nfs_rewrite_mount_options(char *str)
|
||||
{
|
||||
struct mount_options *options;
|
||||
- char *option, new_option[64];
|
||||
+ char *option;
|
||||
clnt_addr_t mnt_server = { };
|
||||
clnt_addr_t nfs_server = { };
|
||||
|
||||
@@ -366,42 +441,12 @@ static struct mount_options *nfs_rewrite_mount_options(char *str)
|
||||
goto err;
|
||||
}
|
||||
|
||||
- snprintf(new_option, sizeof(new_option) - 1,
|
||||
- "nfsvers=%lu", nfs_server.pmap.pm_vers);
|
||||
- if (po_append(options, new_option) == PO_FAILED)
|
||||
+ if (!nfs_construct_new_options(options,
|
||||
+ &nfs_server.pmap, &mnt_server.pmap)) {
|
||||
+ errno = EINVAL;
|
||||
goto err;
|
||||
-
|
||||
- if (nfs_server.pmap.pm_prot == IPPROTO_TCP)
|
||||
- snprintf(new_option, sizeof(new_option) - 1,
|
||||
- "proto=tcp");
|
||||
- else
|
||||
- snprintf(new_option, sizeof(new_option) - 1,
|
||||
- "proto=udp");
|
||||
- if (po_append(options, new_option) == PO_FAILED)
|
||||
- goto err;
|
||||
-
|
||||
- if (nfs_server.pmap.pm_port != NFS_PORT) {
|
||||
- snprintf(new_option, sizeof(new_option) - 1,
|
||||
- "port=%lu", nfs_server.pmap.pm_port);
|
||||
- if (po_append(options, new_option) == PO_FAILED)
|
||||
- goto err;
|
||||
-
|
||||
}
|
||||
|
||||
- if (mnt_server.pmap.pm_prot == IPPROTO_TCP)
|
||||
- snprintf(new_option, sizeof(new_option) - 1,
|
||||
- "mountproto=tcp");
|
||||
- else
|
||||
- snprintf(new_option, sizeof(new_option) - 1,
|
||||
- "mountproto=udp");
|
||||
- if (po_append(options, new_option) == PO_FAILED)
|
||||
- goto err;
|
||||
-
|
||||
- snprintf(new_option, sizeof(new_option) - 1,
|
||||
- "mountport=%lu", mnt_server.pmap.pm_port);
|
||||
- if (po_append(options, new_option) == PO_FAILED)
|
||||
- goto err;
|
||||
-
|
||||
errno = 0;
|
||||
return options;
|
||||
|
||||
|
||||
text-based mount command: support AF_INET6 in rewrite_mount_options()
|
||||
|
||||
Now that we have an AF_INET6-capable probe_bothports(), we can support
|
||||
AF_INET6 when rewriting text-based NFS mount options. This should be
|
||||
adequate to support NFS transport protocol and version negotiation with
|
||||
AF_INET6 NFS servers.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
---
|
||||
|
||||
utils/mount/stropts.c | 74 ++++++++++++++++++++++++++++++++-----------------
|
||||
1 files changed, 49 insertions(+), 25 deletions(-)
|
||||
|
||||
diff --git a/utils/mount/stropts.c b/utils/mount/stropts.c
|
||||
index 319be71..6d44bb7 100644
|
||||
--- a/utils/mount/stropts.c
|
||||
+++ b/utils/mount/stropts.c
|
||||
@@ -309,6 +309,37 @@ static int nfs_is_permanent_error(int error)
|
||||
}
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Get NFS/mnt server addresses from mount options
|
||||
+ *
|
||||
+ * Returns 1 and fills in @nfs_saddr, @nfs_salen, @mnt_saddr, and @mnt_salen
|
||||
+ * if all goes well; otherwise zero.
|
||||
+ */
|
||||
+static int nfs_extract_server_addresses(struct mount_options *options,
|
||||
+ struct sockaddr *nfs_saddr,
|
||||
+ socklen_t *nfs_salen,
|
||||
+ struct sockaddr *mnt_saddr,
|
||||
+ socklen_t *mnt_salen)
|
||||
+{
|
||||
+ char *option;
|
||||
+
|
||||
+ option = po_get(options, "addr");
|
||||
+ if (option == NULL)
|
||||
+ return 0;
|
||||
+ if (!nfs_string_to_sockaddr(option, strlen(option),
|
||||
+ nfs_saddr, nfs_salen))
|
||||
+ return 0;
|
||||
+
|
||||
+ option = po_get(options, "mountaddr");
|
||||
+ if (option == NULL)
|
||||
+ memcpy(mnt_saddr, nfs_saddr, *nfs_salen);
|
||||
+ else if (!nfs_string_to_sockaddr(option, strlen(option),
|
||||
+ mnt_saddr, mnt_salen))
|
||||
+ return 0;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
static int nfs_construct_new_options(struct mount_options *options,
|
||||
struct pmap *nfs_pmap,
|
||||
struct pmap *mnt_pmap)
|
||||
@@ -400,9 +431,14 @@ static int nfs_construct_new_options(struct mount_options *options,
|
||||
static struct mount_options *nfs_rewrite_mount_options(char *str)
|
||||
{
|
||||
struct mount_options *options;
|
||||
- char *option;
|
||||
- clnt_addr_t mnt_server = { };
|
||||
- clnt_addr_t nfs_server = { };
|
||||
+ struct sockaddr_storage nfs_address;
|
||||
+ struct sockaddr *nfs_saddr = (struct sockaddr *)&nfs_address;
|
||||
+ socklen_t nfs_salen;
|
||||
+ struct pmap nfs_pmap;
|
||||
+ struct sockaddr_storage mnt_address;
|
||||
+ struct sockaddr *mnt_saddr = (struct sockaddr *)&mnt_address;
|
||||
+ socklen_t mnt_salen;
|
||||
+ struct pmap mnt_pmap;
|
||||
|
||||
options = po_split(str);
|
||||
if (!options) {
|
||||
@@ -410,39 +446,27 @@ static struct mount_options *nfs_rewrite_mount_options(char *str)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
- errno = EINVAL;
|
||||
- option = po_get(options, "addr");
|
||||
- if (option) {
|
||||
- nfs_server.saddr.sin_family = AF_INET;
|
||||
- if (!inet_aton((const char *)option, &nfs_server.saddr.sin_addr))
|
||||
- goto err;
|
||||
- } else
|
||||
+ if (!nfs_extract_server_addresses(options, nfs_saddr, &nfs_salen,
|
||||
+ mnt_saddr, &mnt_salen)) {
|
||||
+ errno = EINVAL;
|
||||
goto err;
|
||||
+ }
|
||||
|
||||
- option = po_get(options, "mountaddr");
|
||||
- if (option) {
|
||||
- mnt_server.saddr.sin_family = AF_INET;
|
||||
- if (!inet_aton((const char *)option, &mnt_server.saddr.sin_addr))
|
||||
- goto err;
|
||||
- } else
|
||||
- memcpy(&mnt_server.saddr, &nfs_server.saddr,
|
||||
- sizeof(mnt_server.saddr));
|
||||
-
|
||||
- nfs_options2pmap(options, &nfs_server.pmap, &mnt_server.pmap);
|
||||
+ nfs_options2pmap(options, &nfs_pmap, &mnt_pmap);
|
||||
|
||||
/* The kernel NFS client doesn't support changing the RPC program
|
||||
* number for these services, so reset these fields before probing
|
||||
* the server's ports. */
|
||||
- nfs_server.pmap.pm_prog = NFS_PROGRAM;
|
||||
- mnt_server.pmap.pm_prog = MOUNTPROG;
|
||||
+ nfs_pmap.pm_prog = NFS_PROGRAM;
|
||||
+ mnt_pmap.pm_prog = MOUNTPROG;
|
||||
|
||||
- if (!probe_bothports(&mnt_server, &nfs_server)) {
|
||||
+ if (!nfs_probe_bothports(mnt_saddr, mnt_salen, &mnt_pmap,
|
||||
+ nfs_saddr, nfs_salen, &nfs_pmap)) {
|
||||
errno = ESPIPE;
|
||||
goto err;
|
||||
}
|
||||
|
||||
- if (!nfs_construct_new_options(options,
|
||||
- &nfs_server.pmap, &mnt_server.pmap)) {
|
||||
+ if (!nfs_construct_new_options(options, &nfs_pmap, &mnt_pmap)) {
|
||||
errno = EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
commit 52ec1b5fceece8f63b97afc6d6b78bfabff12669
|
||||
Author: Steve Dickson <steved@redhat.com>
|
||||
Date: Tue Feb 17 15:33:58 2009 -0500
|
||||
|
||||
The mount sockaddr len (mnt_salen) is not be set in
|
||||
nfs_extract_server_addresses() which causes the mount.nfs
|
||||
command to segmentation fault when a NFS server only
|
||||
supports UDP mounts.
|
||||
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff -up nfs-utils-1.1.4/utils/mount/stropts.c.orig nfs-utils-1.1.4/utils/mount/stropts.c
|
||||
--- nfs-utils-1.1.4/utils/mount/stropts.c.orig 2009-02-17 15:55:53.000000000 -0500
|
||||
+++ nfs-utils-1.1.4/utils/mount/stropts.c 2009-02-17 15:58:15.000000000 -0500
|
||||
@@ -331,9 +331,10 @@ static int nfs_extract_server_addresses(
|
||||
return 0;
|
||||
|
||||
option = po_get(options, "mountaddr");
|
||||
- if (option == NULL)
|
||||
+ if (option == NULL) {
|
||||
memcpy(mnt_saddr, nfs_saddr, *nfs_salen);
|
||||
- else if (!nfs_string_to_sockaddr(option, strlen(option),
|
||||
+ *mnt_salen = *nfs_salen;
|
||||
+ } else if (!nfs_string_to_sockaddr(option, strlen(option),
|
||||
mnt_saddr, mnt_salen))
|
||||
return 0;
|
||||
|
@ -1,349 +0,0 @@
|
||||
commit bb3e50bd5c4f6bf94221ef69d4dc87e73d0e474b
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Tue Nov 25 08:15:51 2008 -0500
|
||||
|
||||
showmount command: call nfs_getport instead of local getport
|
||||
|
||||
Have the showmount command invoke the shared nfs_getport() function
|
||||
instead of its own local version. This gives the showmount command
|
||||
immediate support for querying via rpcbindv3/v4 in addition to
|
||||
portmapper, and sets the stage for AF_INET6 support in showmount.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
commit e358039c9ffa8a4ead342e8a0cf0ff51a3a21af4
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Tue Nov 25 08:35:10 2008 -0500
|
||||
|
||||
showmount command: Remove unused local getport() implementation
|
||||
|
||||
Clean up: remove showmount.c's local getport() implementation, now that
|
||||
the showmount command uses the shared one.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
commit 1c96846ba3adeb59a61e0cf33cf4c94c0678853f
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Tue Nov 25 08:38:01 2008 -0500
|
||||
|
||||
showmount command: move logic to acquire RPC client handle out of main()
|
||||
|
||||
In preparation to support IPv6 in the showmount command, extract the
|
||||
logic that parses/acquires the target hostname and converts it into an RPC
|
||||
client handle to contact the remote mountd service, and move it into its
|
||||
own function.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
commit f7020bd5d3ffca280690c6beba5fecdeb4d305f7
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Tue Nov 25 08:39:47 2008 -0500
|
||||
|
||||
showmount command: support querying IPv6 servers
|
||||
|
||||
Introduce a version of nfs_get_mount_client() that supports AF_INET6 and
|
||||
AF_INET server addresses. If the TI-RPC library is not available when
|
||||
the showmount command is built, fall back to the legacy RPC user-space
|
||||
API.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff -up nfs-utils-1.1.4/utils/showmount/showmount.c.save nfs-utils-1.1.4/utils/showmount/showmount.c
|
||||
--- nfs-utils-1.1.4/utils/showmount/showmount.c.save 2008-11-25 11:16:03.000000000 -0500
|
||||
+++ nfs-utils-1.1.4/utils/showmount/showmount.c 2008-11-25 11:16:28.000000000 -0500
|
||||
@@ -37,8 +37,9 @@
|
||||
#include <mount.h>
|
||||
#include <unistd.h>
|
||||
|
||||
+#include "nfsrpc.h"
|
||||
+
|
||||
#define TIMEOUT_UDP 3
|
||||
-#define TIMEOUT_TCP 10
|
||||
#define TOTAL_TIMEOUT 20
|
||||
|
||||
static char * version = "showmount for " VERSION;
|
||||
@@ -49,6 +50,13 @@ static int aflag = 0;
|
||||
static int dflag = 0;
|
||||
static int eflag = 0;
|
||||
|
||||
+static const char *nfs_sm_pgmtbl[] = {
|
||||
+ "showmount",
|
||||
+ "mount",
|
||||
+ "mountd",
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
static struct option longopts[] =
|
||||
{
|
||||
{ "all", 0, 0, 'a' },
|
||||
@@ -77,6 +85,33 @@ static void usage(FILE *fp, int n)
|
||||
exit(n);
|
||||
}
|
||||
|
||||
+#ifdef HAVE_CLNT_CREATE
|
||||
+
|
||||
+/*
|
||||
+ * Generate an RPC client handle connected to the mountd service
|
||||
+ * at @hostname, or die trying.
|
||||
+ *
|
||||
+ * Supports both AF_INET and AF_INET6 server addresses.
|
||||
+ */
|
||||
+static CLIENT *nfs_get_mount_client(const char *hostname)
|
||||
+{
|
||||
+ rpcprog_t program = nfs_getrpcbyname(MOUNTPROG, nfs_sm_pgmtbl);
|
||||
+ CLIENT *client;
|
||||
+
|
||||
+ client = clnt_create(hostname, program, MOUNTVERS, "tcp");
|
||||
+ if (client)
|
||||
+ return client;
|
||||
+
|
||||
+ client = clnt_create(hostname, program, MOUNTVERS, "udp");
|
||||
+ if (client)
|
||||
+ return client;
|
||||
+
|
||||
+ clnt_pcreateerror("clnt_create");
|
||||
+ exit(1);
|
||||
+}
|
||||
+
|
||||
+#else /* HAVE_CLNT_CREATE */
|
||||
+
|
||||
/*
|
||||
* Perform a non-blocking connect on the socket fd.
|
||||
*
|
||||
@@ -149,120 +184,77 @@ done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static unsigned short getport(struct sockaddr_in *addr,
|
||||
- unsigned long prog, unsigned long vers, int prot)
|
||||
+/*
|
||||
+ * Generate an RPC client handle connected to the mountd service
|
||||
+ * at @hostname, or die trying.
|
||||
+ *
|
||||
+ * Supports only AF_INET server addresses.
|
||||
+ */
|
||||
+static CLIENT *nfs_get_mount_client(const char *hostname)
|
||||
{
|
||||
- CLIENT *client;
|
||||
- enum clnt_stat status;
|
||||
- struct pmap parms;
|
||||
- int ret, sock;
|
||||
- struct sockaddr_in laddr, saddr;
|
||||
- struct timeval tout = {0, 0};
|
||||
- socklen_t len;
|
||||
- unsigned int send_sz = 0;
|
||||
- unsigned int recv_sz = 0;
|
||||
- unsigned short port;
|
||||
-
|
||||
- memset(&laddr, 0, sizeof(laddr));
|
||||
- memset(&saddr, 0, sizeof(saddr));
|
||||
- memset(&parms, 0, sizeof(parms));
|
||||
-
|
||||
- memcpy(&saddr, addr, sizeof(saddr));
|
||||
- saddr.sin_port = htons(PMAPPORT);
|
||||
+ struct hostent *hp;
|
||||
+ struct sockaddr_in server_addr;
|
||||
+ struct timeval pertry_timeout;
|
||||
+ CLIENT *mclient = NULL;
|
||||
+ int ret, msock;
|
||||
|
||||
- if (prot == IPPROTO_TCP) {
|
||||
- sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
- if (sock == -1) {
|
||||
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||||
- rpc_createerr.cf_error.re_errno = errno;
|
||||
- return 0;
|
||||
+ if (inet_aton(hostname, &server_addr.sin_addr)) {
|
||||
+ server_addr.sin_family = AF_INET;
|
||||
+ }
|
||||
+ else {
|
||||
+ if ((hp = gethostbyname(hostname)) == NULL) {
|
||||
+ fprintf(stderr, "%s: can't get address for %s\n",
|
||||
+ program_name, hostname);
|
||||
+ exit(1);
|
||||
}
|
||||
+ server_addr.sin_family = AF_INET;
|
||||
+ memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
|
||||
+ }
|
||||
|
||||
- tout.tv_sec = TIMEOUT_TCP;
|
||||
-
|
||||
- ret = connect_nb(sock, &saddr, &tout);
|
||||
- if (ret != 0) {
|
||||
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||||
- rpc_createerr.cf_error.re_errno = errno;
|
||||
- close(sock);
|
||||
- return 0;
|
||||
- }
|
||||
- client = clnttcp_create(&saddr,
|
||||
- PMAPPROG, PMAPVERS, &sock,
|
||||
- 0, 0);
|
||||
- } else {
|
||||
- /*
|
||||
- * bind to any unused port. If we left this up to the rpc
|
||||
- * layer, it would bind to a reserved port, which has been shown
|
||||
- * to exhaust the reserved port range in some situations.
|
||||
- */
|
||||
- sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
- if (sock == -1) {
|
||||
- rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||||
- rpc_createerr.cf_error.re_errno = errno;
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- laddr.sin_family = AF_INET;
|
||||
- laddr.sin_port = 0;
|
||||
- laddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
-
|
||||
- tout.tv_sec = TIMEOUT_UDP;
|
||||
-
|
||||
- send_sz = RPCSMALLMSGSIZE;
|
||||
- recv_sz = RPCSMALLMSGSIZE;
|
||||
-
|
||||
- len = sizeof(struct sockaddr_in);
|
||||
- if (bind(sock, (struct sockaddr *)&laddr, len) < 0) {
|
||||
- close(sock);
|
||||
- sock = RPC_ANYSOCK;
|
||||
- /* FALLTHROUGH */
|
||||
- }
|
||||
- client = clntudp_bufcreate(&saddr, PMAPPROG, PMAPVERS,
|
||||
- tout, &sock, send_sz, recv_sz);
|
||||
- }
|
||||
-
|
||||
- if (!client) {
|
||||
- close(sock);
|
||||
- rpc_createerr.cf_stat = RPC_RPCBFAILURE;
|
||||
- return 0;
|
||||
- }
|
||||
-
|
||||
- clnt_control(client, CLSET_FD_CLOSE, NULL);
|
||||
-
|
||||
- parms.pm_prog = prog;
|
||||
- parms.pm_vers = vers;
|
||||
- parms.pm_prot = prot;
|
||||
-
|
||||
- status = clnt_call(client, PMAPPROC_GETPORT,
|
||||
- (xdrproc_t) xdr_pmap, (caddr_t) &parms,
|
||||
- (xdrproc_t) xdr_u_short, (caddr_t) &port,
|
||||
- tout);
|
||||
-
|
||||
- if (status != RPC_SUCCESS) {
|
||||
- clnt_geterr(client, &rpc_createerr.cf_error);
|
||||
- rpc_createerr.cf_stat = status;
|
||||
- clnt_destroy(client);
|
||||
- return 0;
|
||||
- } else if (port == 0) {
|
||||
- rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
|
||||
+ msock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
+ if (msock != -1) {
|
||||
+ if (nfs_getport_ping((struct sockaddr *)&server_addr,
|
||||
+ sizeof(server_addr), MOUNTPROG,
|
||||
+ MOUNTVERS, IPPROTO_TCP)) {
|
||||
+ ret = connect_nb(msock, &server_addr, 0);
|
||||
+ if (ret == 0)
|
||||
+ mclient = clnttcp_create(&server_addr,
|
||||
+ MOUNTPROG, MOUNTVERS, &msock,
|
||||
+ 0, 0);
|
||||
+ else
|
||||
+ close(msock);
|
||||
+ } else
|
||||
+ close(msock);
|
||||
}
|
||||
|
||||
- clnt_destroy(client);
|
||||
+ if (!mclient) {
|
||||
+ if (nfs_getport_ping((struct sockaddr *)&server_addr,
|
||||
+ sizeof(server_addr), MOUNTPROG,
|
||||
+ MOUNTVERS, IPPROTO_UDP)) {
|
||||
+ clnt_pcreateerror("showmount");
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ msock = RPC_ANYSOCK;
|
||||
+ pertry_timeout.tv_sec = TIMEOUT_UDP;
|
||||
+ pertry_timeout.tv_usec = 0;
|
||||
+ if ((mclient = clntudp_create(&server_addr,
|
||||
+ MOUNTPROG, MOUNTVERS, pertry_timeout, &msock)) == NULL) {
|
||||
+ clnt_pcreateerror("mount clntudp_create");
|
||||
+ exit(1);
|
||||
+ }
|
||||
+ }
|
||||
|
||||
- return htons(port);
|
||||
+ return mclient;
|
||||
}
|
||||
|
||||
+#endif /* HAVE_CLNT_CREATE */
|
||||
+
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char hostname_buf[MAXHOSTLEN];
|
||||
char *hostname;
|
||||
enum clnt_stat clnt_stat;
|
||||
- struct hostent *hp;
|
||||
- struct sockaddr_in server_addr;
|
||||
- int ret, msock;
|
||||
struct timeval total_timeout;
|
||||
- struct timeval pertry_timeout;
|
||||
int c;
|
||||
CLIENT *mclient;
|
||||
groups grouplist;
|
||||
@@ -334,54 +326,7 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
}
|
||||
|
||||
- if (inet_aton(hostname, &server_addr.sin_addr)) {
|
||||
- server_addr.sin_family = AF_INET;
|
||||
- }
|
||||
- else {
|
||||
- if ((hp = gethostbyname(hostname)) == NULL) {
|
||||
- fprintf(stderr, "%s: can't get address for %s\n",
|
||||
- program_name, hostname);
|
||||
- exit(1);
|
||||
- }
|
||||
- server_addr.sin_family = AF_INET;
|
||||
- memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
|
||||
- }
|
||||
-
|
||||
- /* create mount deamon client */
|
||||
-
|
||||
- mclient = NULL;
|
||||
- msock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
- if (msock != -1) {
|
||||
- server_addr.sin_port = getport(&server_addr,
|
||||
- MOUNTPROG, MOUNTVERS, IPPROTO_TCP);
|
||||
- if (server_addr.sin_port) {
|
||||
- ret = connect_nb(msock, &server_addr, 0);
|
||||
- if (ret == 0) /* success */
|
||||
- mclient = clnttcp_create(&server_addr,
|
||||
- MOUNTPROG, MOUNTVERS, &msock,
|
||||
- 0, 0);
|
||||
- else
|
||||
- close(msock);
|
||||
- } else
|
||||
- close(msock);
|
||||
- }
|
||||
-
|
||||
- if (!mclient) {
|
||||
- server_addr.sin_port = getport(&server_addr,
|
||||
- MOUNTPROG, MOUNTVERS, IPPROTO_UDP);
|
||||
- if (!server_addr.sin_port) {
|
||||
- clnt_pcreateerror("showmount");
|
||||
- exit(1);
|
||||
- }
|
||||
- msock = RPC_ANYSOCK;
|
||||
- pertry_timeout.tv_sec = TIMEOUT_UDP;
|
||||
- pertry_timeout.tv_usec = 0;
|
||||
- if ((mclient = clntudp_create(&server_addr,
|
||||
- MOUNTPROG, MOUNTVERS, pertry_timeout, &msock)) == NULL) {
|
||||
- clnt_pcreateerror("mount clntudp_create");
|
||||
- exit(1);
|
||||
- }
|
||||
- }
|
||||
+ mclient = nfs_get_mount_client(hostname);
|
||||
mclient->cl_auth = authunix_create_default();
|
||||
total_timeout.tv_sec = TOTAL_TIMEOUT;
|
||||
total_timeout.tv_usec = 0;
|
@ -1,57 +0,0 @@
|
||||
diff -up nfs-utils-1.1.4/utils/statd/sm-notify.c.orig nfs-utils-1.1.4/utils/statd/sm-notify.c
|
||||
--- nfs-utils-1.1.4/utils/statd/sm-notify.c.orig 2008-12-17 15:09:13.000000000 -0500
|
||||
+++ nfs-utils-1.1.4/utils/statd/sm-notify.c 2008-12-17 15:11:07.000000000 -0500
|
||||
@@ -133,6 +133,17 @@ static struct addrinfo *smn_lookup(const
|
||||
return ai;
|
||||
}
|
||||
|
||||
+static void smn_forget_host(struct nsm_host *host)
|
||||
+{
|
||||
+ unlink(host->path);
|
||||
+ free(host->path);
|
||||
+ free(host->name);
|
||||
+ if (host->ai)
|
||||
+ freeaddrinfo(host->ai);
|
||||
+
|
||||
+ free(host);
|
||||
+}
|
||||
+
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@@ -342,13 +353,8 @@ notify(void)
|
||||
hp = hosts;
|
||||
hosts = hp->next;
|
||||
|
||||
- if (notify_host(sock, hp)){
|
||||
- unlink(hp->path);
|
||||
- free(hp->name);
|
||||
- free(hp->path);
|
||||
- free(hp);
|
||||
+ if (notify_host(sock, hp))
|
||||
continue;
|
||||
- }
|
||||
|
||||
/* Set the timeout for this call, using an
|
||||
exponential timeout strategy */
|
||||
@@ -403,6 +409,7 @@ notify_host(int sock, struct nsm_host *h
|
||||
nsm_log(LOG_WARNING,
|
||||
"%s doesn't seem to be a valid address,"
|
||||
" skipped", host->name);
|
||||
+ smn_forget_host(host);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -547,11 +554,7 @@ recv_reply(int sock)
|
||||
if (p <= end) {
|
||||
nsm_log(LOG_DEBUG, "Host %s notified successfully",
|
||||
hp->name);
|
||||
- unlink(hp->path);
|
||||
- free(hp->name);
|
||||
- free(hp->path);
|
||||
- free(hp);
|
||||
- freeaddrinfo(hp->ai);
|
||||
+ smn_forget_host(hp);
|
||||
return;
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
commit 5d8b800b8438222a55c4698c86b558b15717aa21
|
||||
Author: Steve Dickson <steved@redhat.com>
|
||||
Date: Sat Dec 6 08:31:29 2008 -0500
|
||||
|
||||
sm-notify: always exiting without any notification
|
||||
|
||||
Added curly brackets around the record_pid() check which
|
||||
stop sm-notify from exiting when a pid file does not
|
||||
exist.
|
||||
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff --git a/utils/statd/sm-notify.c b/utils/statd/sm-notify.c
|
||||
index 7a7ae1a..d8e2c01 100644
|
||||
--- a/utils/statd/sm-notify.c
|
||||
+++ b/utils/statd/sm-notify.c
|
||||
@@ -193,10 +193,11 @@ usage: fprintf(stderr,
|
||||
openlog("sm-notify", LOG_PID, LOG_DAEMON);
|
||||
|
||||
if (strcmp(_SM_BASE_PATH, BASEDIR) == 0) {
|
||||
- if (record_pid() == 0 && force == 0 && opt_update_state == 1)
|
||||
+ if (record_pid() == 0 && force == 0 && opt_update_state == 1) {
|
||||
/* already run, don't try again */
|
||||
nsm_log(LOG_NOTICE, "Already notifying clients; Exiting!");
|
||||
exit(0);
|
||||
+ }
|
||||
}
|
||||
|
||||
if (opt_srcaddr) {
|
@ -1,72 +0,0 @@
|
||||
commit 33bbeabb40d11a59266e0702adaa6a2e0acb6382
|
||||
Author: Neil Brown <neilb@suse.de>
|
||||
Date: Wed Nov 26 12:01:06 2008 -0500
|
||||
|
||||
Ensure statd gets started if required when non-root
|
||||
user mounts an NFS filesystem.
|
||||
|
||||
The first time an NFS filesystem is mounted, we start statd from
|
||||
/sbin/mount.nfs. If this first time is a non-root user doing the
|
||||
mount, (thanks to e.g. the 'users' option in /etc/fstab)
|
||||
then we need to be sure that the 'setuid' status from mount.nfs
|
||||
is inherited through to rpc.statd so that it runs as root.
|
||||
|
||||
There are two places where we loose our setuid status due to the shell
|
||||
(/bin/sh) discarding.
|
||||
|
||||
1/ mount.nfs uses "system" to run /usr/sbin/start-statd. This runs a
|
||||
shell which is likely to drop privileges. So change that code to use
|
||||
'fork' and 'execl' explicitly.
|
||||
2/ start-statd is a shell script. To convince the shell to allow the
|
||||
program to run in privileged mode, we need to add a "-p" flag.
|
||||
|
||||
We could just call setuid(getuid()) at some appropriate time, and it
|
||||
might be worth doing that as well, however I think that getting
|
||||
rid of 'system()' is a good idea and once that is done, the
|
||||
adding of '-p' is trivial and sufficient.
|
||||
|
||||
Signed-off-by: Neil Brown <neilb@suse.de>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff --git a/utils/mount/network.c b/utils/mount/network.c
|
||||
index 2db694d..806344c 100644
|
||||
--- a/utils/mount/network.c
|
||||
+++ b/utils/mount/network.c
|
||||
@@ -36,6 +36,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
+#include <sys/wait.h>
|
||||
#include <netinet/in.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/pmap_prot.h>
|
||||
@@ -705,7 +706,18 @@ int start_statd(void)
|
||||
#ifdef START_STATD
|
||||
if (stat(START_STATD, &stb) == 0) {
|
||||
if (S_ISREG(stb.st_mode) && (stb.st_mode & S_IXUSR)) {
|
||||
- system(START_STATD);
|
||||
+ pid_t pid = fork();
|
||||
+ switch (pid) {
|
||||
+ case 0: /* child */
|
||||
+ execl(START_STATD, START_STATD, NULL);
|
||||
+ exit(1);
|
||||
+ case -1: /* error */
|
||||
+ perror("Fork failed");
|
||||
+ break;
|
||||
+ default: /* parent */
|
||||
+ waitpid(pid, NULL,0);
|
||||
+ break;
|
||||
+ }
|
||||
if (probe_statd())
|
||||
return 1;
|
||||
}
|
||||
diff --git a/utils/statd/start-statd b/utils/statd/start-statd
|
||||
index 6e7ea04..c7805ee 100644
|
||||
--- a/utils/statd/start-statd
|
||||
+++ b/utils/statd/start-statd
|
||||
@@ -1,4 +1,4 @@
|
||||
-#!/bin/sh
|
||||
+#!/bin/sh -p
|
||||
# nfsmount calls this script when mounting a filesystem with locking
|
||||
# enabled, but when statd does not seem to be running (based on
|
||||
# /var/run/rpc.statd.pid).
|
@ -1,98 +0,0 @@
|
||||
commit bc870150cc2116584aee288d15ac2b9a2f825ff5
|
||||
Author: Steve Dickson <steved@redhat.com>
|
||||
Date: Wed Dec 17 16:41:35 2008 -0500
|
||||
|
||||
statd: not unlinking host files
|
||||
|
||||
Statd is not unlinking host files during SM_UNMON and
|
||||
SM_UNMON_ALL calls because the given host is still on the run-time
|
||||
notify list (rtnl) and the check flag is set when xunlink() is
|
||||
called. But the next thing the caller of xunlink() does is
|
||||
remove the host from the rtnl list which means the
|
||||
unlink will never happen.
|
||||
|
||||
So this patch removes the check flag from xunlink() since
|
||||
its not needed and correctly allocates and frees memory
|
||||
used by xunlink().
|
||||
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff --git a/utils/statd/misc.c b/utils/statd/misc.c
|
||||
index fd201b4..7256291 100644
|
||||
--- a/utils/statd/misc.c
|
||||
+++ b/utils/statd/misc.c
|
||||
@@ -53,23 +53,25 @@ xstrdup (const char *string)
|
||||
|
||||
|
||||
/*
|
||||
- * Call with check=1 to verify that this host is not still on the rtnl
|
||||
- * before unlinking file.
|
||||
+ * Unlinking a file.
|
||||
*/
|
||||
void
|
||||
-xunlink (char *path, char *host, short int check)
|
||||
+xunlink (char *path, char *host)
|
||||
{
|
||||
- char *tozap;
|
||||
+ char *tozap;
|
||||
|
||||
- tozap=alloca (strlen(path)+strlen(host)+2);
|
||||
- sprintf (tozap, "%s/%s", path, host);
|
||||
+ tozap = malloc(strlen(path)+strlen(host)+2);
|
||||
+ if (tozap == NULL) {
|
||||
+ note(N_ERROR, "xunlink: malloc failed: errno %d (%s)",
|
||||
+ errno, strerror(errno));
|
||||
+ return;
|
||||
+ }
|
||||
+ sprintf (tozap, "%s/%s", path, host);
|
||||
|
||||
- if (!check || !nlist_gethost(rtnl, host, 0)) {
|
||||
- if (unlink (tozap) == -1)
|
||||
- note (N_ERROR, "unlink (%s): %s", tozap, strerror (errno));
|
||||
- else
|
||||
- dprintf (N_DEBUG, "Unlinked %s", tozap);
|
||||
- }
|
||||
- else
|
||||
- dprintf (N_DEBUG, "Not unlinking %s--host still monitored.", tozap);
|
||||
+ if (unlink (tozap) == -1)
|
||||
+ note(N_ERROR, "unlink (%s): %s", tozap, strerror (errno));
|
||||
+ else
|
||||
+ dprintf (N_DEBUG, "Unlinked %s", tozap);
|
||||
+
|
||||
+ free(tozap);
|
||||
}
|
||||
diff --git a/utils/statd/monitor.c b/utils/statd/monitor.c
|
||||
index a6a1d9c..24c2531 100644
|
||||
--- a/utils/statd/monitor.c
|
||||
+++ b/utils/statd/monitor.c
|
||||
@@ -352,7 +352,7 @@ sm_unmon_1_svc(struct mon_id *argp, struct svc_req *rqstp)
|
||||
/* PRC: do the HA callout: */
|
||||
ha_callout("del-client", mon_name, my_name, -1);
|
||||
|
||||
- xunlink(SM_DIR, clnt->dns_name, 1);
|
||||
+ xunlink(SM_DIR, clnt->dns_name);
|
||||
nlist_free(&rtnl, clnt);
|
||||
|
||||
return (&result);
|
||||
@@ -404,7 +404,7 @@ sm_unmon_all_1_svc(struct my_id *argp, struct svc_req *rqstp)
|
||||
temp = NL_NEXT(clnt);
|
||||
/* PRC: do the HA callout: */
|
||||
ha_callout("del-client", mon_name, my_name, -1);
|
||||
- xunlink(SM_DIR, clnt->dns_name, 1);
|
||||
+ xunlink(SM_DIR, clnt->dns_name);
|
||||
nlist_free(&rtnl, clnt);
|
||||
++count;
|
||||
clnt = temp;
|
||||
diff --git a/utils/statd/statd.h b/utils/statd/statd.h
|
||||
index 5a6e289..88ba208 100644
|
||||
--- a/utils/statd/statd.h
|
||||
+++ b/utils/statd/statd.h
|
||||
@@ -53,7 +53,7 @@ extern int process_notify_list(void);
|
||||
extern int process_reply(FD_SET_TYPE *);
|
||||
extern char * xstrdup(const char *);
|
||||
extern void * xmalloc(size_t);
|
||||
-extern void xunlink (char *, char *, short int);
|
||||
+extern void xunlink (char *, char *);
|
||||
extern void load_state(void);
|
||||
|
||||
/*
|
@ -1,304 +0,0 @@
|
||||
commit a4f1386224310b6797f083826fc4b6751e91f9b6
|
||||
Author: Kevin Coffman <kwc@citi.umich.edu>
|
||||
Date: Thu Dec 11 11:39:38 2008 -0500
|
||||
|
||||
gssd/svcgssd: add support to retrieve actual context expiration
|
||||
|
||||
Add some plumbing so that the context expiration can be returned while
|
||||
serializing the information. Later patch(es) will actually get the
|
||||
expiration and pass it down to the kernel.
|
||||
|
||||
Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff --git a/utils/gssd/context.c b/utils/gssd/context.c
|
||||
index 4bab3e7..0ca7079 100644
|
||||
--- a/utils/gssd/context.c
|
||||
+++ b/utils/gssd/context.c
|
||||
@@ -43,13 +43,14 @@
|
||||
int
|
||||
serialize_context_for_kernel(gss_ctx_id_t ctx,
|
||||
gss_buffer_desc *buf,
|
||||
- gss_OID mech)
|
||||
+ gss_OID mech,
|
||||
+ int32_t *endtime)
|
||||
{
|
||||
if (g_OID_equal(&krb5oid, mech))
|
||||
- return serialize_krb5_ctx(ctx, buf);
|
||||
+ return serialize_krb5_ctx(ctx, buf, endtime);
|
||||
#ifdef HAVE_SPKM3_H
|
||||
else if (g_OID_equal(&spkm3oid, mech))
|
||||
- return serialize_spkm3_ctx(ctx, buf);
|
||||
+ return serialize_spkm3_ctx(ctx, buf, endtime);
|
||||
#endif
|
||||
else {
|
||||
printerr(0, "ERROR: attempting to serialize context with "
|
||||
diff --git a/utils/gssd/context.h b/utils/gssd/context.h
|
||||
index 67ed3bb..be47f9c 100644
|
||||
--- a/utils/gssd/context.h
|
||||
+++ b/utils/gssd/context.h
|
||||
@@ -38,8 +38,10 @@
|
||||
|
||||
|
||||
int serialize_context_for_kernel(gss_ctx_id_t ctx, gss_buffer_desc *buf,
|
||||
- gss_OID mech);
|
||||
-int serialize_spkm3_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf);
|
||||
-int serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf);
|
||||
+ gss_OID mech, int32_t *endtime);
|
||||
+int serialize_spkm3_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf,
|
||||
+ int32_t *endtime);
|
||||
+int serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf,
|
||||
+ int32_t *endtime);
|
||||
|
||||
#endif /* _CONTEXT_H_ */
|
||||
diff --git a/utils/gssd/context_heimdal.c b/utils/gssd/context_heimdal.c
|
||||
index 6fb8fbd..fc241e3 100644
|
||||
--- a/utils/gssd/context_heimdal.c
|
||||
+++ b/utils/gssd/context_heimdal.c
|
||||
@@ -198,7 +198,7 @@ int write_heimdal_seq_key(char **p, char *end, gss_ctx_id_t ctx)
|
||||
*/
|
||||
|
||||
int
|
||||
-serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
|
||||
+serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf, int32_t *endtime)
|
||||
{
|
||||
|
||||
char *p, *end;
|
||||
@@ -239,6 +239,9 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
|
||||
/* endtime */
|
||||
if (WRITE_BYTES(&p, end, ctx->lifetime)) goto out_err;
|
||||
|
||||
+ if (endtime)
|
||||
+ *endtime = ctx->lifetime;
|
||||
+
|
||||
/* seq_send */
|
||||
if (WRITE_BYTES(&p, end, ctx->auth_context->local_seqnumber))
|
||||
goto out_err;
|
||||
diff --git a/utils/gssd/context_lucid.c b/utils/gssd/context_lucid.c
|
||||
index 3550762..94403af 100644
|
||||
--- a/utils/gssd/context_lucid.c
|
||||
+++ b/utils/gssd/context_lucid.c
|
||||
@@ -66,7 +66,7 @@ write_lucid_keyblock(char **p, char *end, gss_krb5_lucid_key_t *key)
|
||||
|
||||
static int
|
||||
prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx,
|
||||
- gss_buffer_desc *buf)
|
||||
+ gss_buffer_desc *buf, int32_t *endtime)
|
||||
{
|
||||
char *p, *end;
|
||||
static int constant_zero = 0;
|
||||
@@ -101,6 +101,8 @@ prepare_krb5_rfc1964_buffer(gss_krb5_lucid_context_v1_t *lctx,
|
||||
if (WRITE_BYTES(&p, end, lctx->rfc1964_kd.sign_alg)) goto out_err;
|
||||
if (WRITE_BYTES(&p, end, lctx->rfc1964_kd.seal_alg)) goto out_err;
|
||||
if (WRITE_BYTES(&p, end, lctx->endtime)) goto out_err;
|
||||
+ if (endtime)
|
||||
+ *endtime = lctx->endtime;
|
||||
word_send_seq = lctx->send_seq; /* XXX send_seq is 64-bit */
|
||||
if (WRITE_BYTES(&p, end, word_send_seq)) goto out_err;
|
||||
if (write_oid(&p, end, &krb5oid)) goto out_err;
|
||||
@@ -154,7 +156,7 @@ out_err:
|
||||
|
||||
static int
|
||||
prepare_krb5_rfc_cfx_buffer(gss_krb5_lucid_context_v1_t *lctx,
|
||||
- gss_buffer_desc *buf)
|
||||
+ gss_buffer_desc *buf, int32_t *endtime)
|
||||
{
|
||||
printerr(0, "ERROR: prepare_krb5_rfc_cfx_buffer: not implemented\n");
|
||||
return -1;
|
||||
@@ -162,7 +164,7 @@ prepare_krb5_rfc_cfx_buffer(gss_krb5_lucid_context_v1_t *lctx,
|
||||
|
||||
|
||||
int
|
||||
-serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
|
||||
+serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf, int32_t *endtime)
|
||||
{
|
||||
OM_uint32 maj_stat, min_stat;
|
||||
void *return_ctx = 0;
|
||||
@@ -194,9 +196,9 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
|
||||
|
||||
/* Now lctx points to a lucid context that we can send down to kernel */
|
||||
if (lctx->protocol == 0)
|
||||
- retcode = prepare_krb5_rfc1964_buffer(lctx, buf);
|
||||
+ retcode = prepare_krb5_rfc1964_buffer(lctx, buf, endtime);
|
||||
else
|
||||
- retcode = prepare_krb5_rfc_cfx_buffer(lctx, buf);
|
||||
+ retcode = prepare_krb5_rfc_cfx_buffer(lctx, buf, endtime);
|
||||
|
||||
maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, return_ctx);
|
||||
if (maj_stat != GSS_S_COMPLETE) {
|
||||
diff --git a/utils/gssd/context_mit.c b/utils/gssd/context_mit.c
|
||||
index 94b2266..e76a8b1 100644
|
||||
--- a/utils/gssd/context_mit.c
|
||||
+++ b/utils/gssd/context_mit.c
|
||||
@@ -150,7 +150,7 @@ typedef struct gss_union_ctx_id_t {
|
||||
} gss_union_ctx_id_desc, *gss_union_ctx_id_t;
|
||||
|
||||
int
|
||||
-serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
|
||||
+serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf, int32_t *endtime)
|
||||
{
|
||||
krb5_gss_ctx_id_t kctx = ((gss_union_ctx_id_t)ctx)->internal_ctx_id;
|
||||
char *p, *end;
|
||||
@@ -180,6 +180,8 @@ serialize_krb5_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
|
||||
if (WRITE_BYTES(&p, end, kctx->signalg)) goto out_err;
|
||||
if (WRITE_BYTES(&p, end, kctx->sealalg)) goto out_err;
|
||||
if (WRITE_BYTES(&p, end, kctx->endtime)) goto out_err;
|
||||
+ if (endtime)
|
||||
+ *endtime = kctx->endtime;
|
||||
word_seq_send = kctx->seq_send;
|
||||
if (WRITE_BYTES(&p, end, word_seq_send)) goto out_err;
|
||||
if (write_oid(&p, end, kctx->mech_used)) goto out_err;
|
||||
diff --git a/utils/gssd/context_spkm3.c b/utils/gssd/context_spkm3.c
|
||||
index 4f41ee3..5b387bd 100644
|
||||
--- a/utils/gssd/context_spkm3.c
|
||||
+++ b/utils/gssd/context_spkm3.c
|
||||
@@ -139,7 +139,7 @@ out_err:
|
||||
* and only export those fields to the kernel.
|
||||
*/
|
||||
int
|
||||
-serialize_spkm3_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
|
||||
+serialize_spkm3_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf, int32_t *endtime)
|
||||
{
|
||||
OM_uint32 vers, ret, maj_stat, min_stat;
|
||||
void *ret_ctx = 0;
|
||||
@@ -162,6 +162,9 @@ serialize_spkm3_ctx(gss_ctx_id_t ctx, gss_buffer_desc *buf)
|
||||
}
|
||||
ret = prepare_spkm3_ctx_buffer(lctx, buf);
|
||||
|
||||
+ if (endtime)
|
||||
+ *endtime = lctx->endtime;
|
||||
+
|
||||
maj_stat = gss_free_lucid_sec_context(&min_stat, ctx, ret_ctx);
|
||||
|
||||
if (maj_stat != GSS_S_COMPLETE)
|
||||
diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c
|
||||
index f415a10..cb14d45 100644
|
||||
--- a/utils/gssd/gssd_proc.c
|
||||
+++ b/utils/gssd/gssd_proc.c
|
||||
@@ -762,7 +762,7 @@ handle_krb5_upcall(struct clnt_info *clp)
|
||||
goto out_return_error;
|
||||
}
|
||||
|
||||
- if (serialize_context_for_kernel(pd.pd_ctx, &token, &krb5oid)) {
|
||||
+ if (serialize_context_for_kernel(pd.pd_ctx, &token, &krb5oid, NULL)) {
|
||||
printerr(0, "WARNING: Failed to serialize krb5 context for "
|
||||
"user with uid %d for server %s\n",
|
||||
uid, clp->servername);
|
||||
@@ -824,7 +824,7 @@ handle_spkm3_upcall(struct clnt_info *clp)
|
||||
goto out_return_error;
|
||||
}
|
||||
|
||||
- if (serialize_context_for_kernel(pd.pd_ctx, &token, &spkm3oid)) {
|
||||
+ if (serialize_context_for_kernel(pd.pd_ctx, &token, &spkm3oid, NULL)) {
|
||||
printerr(0, "WARNING: Failed to serialize spkm3 context for "
|
||||
"user with uid %d for server\n",
|
||||
uid, clp->servername);
|
||||
diff --git a/utils/gssd/svcgssd_proc.c b/utils/gssd/svcgssd_proc.c
|
||||
index 794c2f4..d021d49 100644
|
||||
--- a/utils/gssd/svcgssd_proc.c
|
||||
+++ b/utils/gssd/svcgssd_proc.c
|
||||
@@ -396,7 +396,7 @@ handle_nullreq(FILE *f) {
|
||||
|
||||
/* kernel needs ctx to calculate verifier on null response, so
|
||||
* must give it context before doing null call: */
|
||||
- if (serialize_context_for_kernel(ctx, &ctx_token, mech)) {
|
||||
+ if (serialize_context_for_kernel(ctx, &ctx_token, mech, NULL)) {
|
||||
printerr(0, "WARNING: handle_nullreq: "
|
||||
"serialize_context_for_kernel failed\n");
|
||||
maj_stat = GSS_S_FAILURE;
|
||||
commit eb3a145789b9eedd39b56e1d76f412435abaa747
|
||||
Author: Kevin Coffman <kwc@citi.umich.edu>
|
||||
Date: Thu Dec 11 11:43:31 2008 -0500
|
||||
|
||||
svcgssd: use the actual context expiration for cache
|
||||
|
||||
Instead of sending down an infinite expiration value for the rsi(init) and
|
||||
rsc(context) cache entries, use a reasonable value for the rsi cache, and
|
||||
the actual context expiration value for the rsc cache.
|
||||
|
||||
Prompted by a proposal from Neil Brown as a result of a complaint of a
|
||||
server running out of kernel memory when under heavy load of rpcsec_gss
|
||||
traffic. Neil's original patch used one minute for the init cache and one
|
||||
hour for the context cache. Using the actual expiration time prevents
|
||||
unnecessary context re-negotiation.
|
||||
|
||||
Signed-off-by: Kevin Coffman <kwc@citi.umich.edu>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff --git a/utils/gssd/svcgssd_proc.c b/utils/gssd/svcgssd_proc.c
|
||||
index d021d49..f162152 100644
|
||||
--- a/utils/gssd/svcgssd_proc.c
|
||||
+++ b/utils/gssd/svcgssd_proc.c
|
||||
@@ -46,6 +46,7 @@
|
||||
#include <errno.h>
|
||||
#include <nfsidmap.h>
|
||||
#include <nfslib.h>
|
||||
+#include <time.h>
|
||||
|
||||
#include "svcgssd.h"
|
||||
#include "gss_util.h"
|
||||
@@ -67,7 +68,8 @@ struct svc_cred {
|
||||
|
||||
static int
|
||||
do_svc_downcall(gss_buffer_desc *out_handle, struct svc_cred *cred,
|
||||
- gss_OID mech, gss_buffer_desc *context_token)
|
||||
+ gss_OID mech, gss_buffer_desc *context_token,
|
||||
+ int32_t endtime)
|
||||
{
|
||||
FILE *f;
|
||||
int i;
|
||||
@@ -86,13 +88,15 @@ do_svc_downcall(gss_buffer_desc *out_handle, struct svc_cred *cred,
|
||||
}
|
||||
qword_printhex(f, out_handle->value, out_handle->length);
|
||||
/* XXX are types OK for the rest of this? */
|
||||
- qword_printint(f, 0x7fffffff); /*XXX need a better timeout */
|
||||
+ /* For context cache, use the actual context endtime */
|
||||
+ qword_printint(f, endtime);
|
||||
qword_printint(f, cred->cr_uid);
|
||||
qword_printint(f, cred->cr_gid);
|
||||
qword_printint(f, cred->cr_ngroups);
|
||||
- printerr(2, "mech: %s, hndl len: %d, ctx len %d, timeout: %d, "
|
||||
+ printerr(2, "mech: %s, hndl len: %d, ctx len %d, timeout: %d (%d from now), "
|
||||
"uid: %d, gid: %d, num aux grps: %d:\n",
|
||||
- fname, out_handle->length, context_token->length, 0x7fffffff,
|
||||
+ fname, out_handle->length, context_token->length,
|
||||
+ endtime, endtime - time(0),
|
||||
cred->cr_uid, cred->cr_gid, cred->cr_ngroups);
|
||||
for (i=0; i < cred->cr_ngroups; i++) {
|
||||
qword_printint(f, cred->cr_groups[i]);
|
||||
@@ -130,7 +134,8 @@ send_response(FILE *f, gss_buffer_desc *in_handle, gss_buffer_desc *in_token,
|
||||
|
||||
qword_addhex(&bp, &blen, in_handle->value, in_handle->length);
|
||||
qword_addhex(&bp, &blen, in_token->value, in_token->length);
|
||||
- qword_addint(&bp, &blen, 0x7fffffff); /*XXX need a better timeout */
|
||||
+ /* For init cache, only needed for a short time */
|
||||
+ qword_addint(&bp, &blen, time(0) + 60);
|
||||
qword_adduint(&bp, &blen, maj_stat);
|
||||
qword_adduint(&bp, &blen, min_stat);
|
||||
qword_addhex(&bp, &blen, out_handle->value, out_handle->length);
|
||||
@@ -320,6 +325,7 @@ handle_nullreq(FILE *f) {
|
||||
static char *lbuf = NULL;
|
||||
static int lbuflen = 0;
|
||||
static char *cp;
|
||||
+ int32_t ctx_endtime;
|
||||
|
||||
printerr(1, "handling null request\n");
|
||||
|
||||
@@ -396,7 +402,7 @@ handle_nullreq(FILE *f) {
|
||||
|
||||
/* kernel needs ctx to calculate verifier on null response, so
|
||||
* must give it context before doing null call: */
|
||||
- if (serialize_context_for_kernel(ctx, &ctx_token, mech, NULL)) {
|
||||
+ if (serialize_context_for_kernel(ctx, &ctx_token, mech, &ctx_endtime)) {
|
||||
printerr(0, "WARNING: handle_nullreq: "
|
||||
"serialize_context_for_kernel failed\n");
|
||||
maj_stat = GSS_S_FAILURE;
|
||||
@@ -405,7 +411,7 @@ handle_nullreq(FILE *f) {
|
||||
/* We no longer need the gss context */
|
||||
gss_delete_sec_context(&ignore_min_stat, &ctx, &ignore_out_tok);
|
||||
|
||||
- do_svc_downcall(&out_handle, &cred, mech, &ctx_token);
|
||||
+ do_svc_downcall(&out_handle, &cred, mech, &ctx_token, ctx_endtime);
|
||||
continue_needed:
|
||||
send_response(f, &in_handle, &in_tok, maj_stat, min_stat,
|
||||
&out_handle, &out_tok);
|
@ -1,194 +0,0 @@
|
||||
Author: Steve Dickson <steved@redhat.com>
|
||||
Date: Sat Jan 31 06:17:18 2009 -0500
|
||||
|
||||
General clean up. Removed unused routines. Reworked syslog
|
||||
message to (hopefully) make it more sensible. Move
|
||||
"#ifdef HAVE_LIBWRAP" around so nothing will be defined
|
||||
when tcp wrapper is not configured.
|
||||
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff -up nfs-utils-1.1.4/support/misc/tcpwrapper.c.orig nfs-utils-1.1.4/support/misc/tcpwrapper.c
|
||||
--- nfs-utils-1.1.4/support/misc/tcpwrapper.c.orig 2009-01-31 06:27:54.000000000 -0500
|
||||
+++ nfs-utils-1.1.4/support/misc/tcpwrapper.c 2009-01-31 06:31:32.000000000 -0500
|
||||
@@ -34,6 +34,7 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
+#ifdef HAVE_LIBWRAP
|
||||
#include <tcpwrapper.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
@@ -57,40 +58,10 @@
|
||||
|
||||
static void logit(int severity, struct sockaddr_in *addr,
|
||||
u_long procnum, u_long prognum, char *text);
|
||||
-static void toggle_verboselog(int sig);
|
||||
-int verboselog = 0;
|
||||
-int allow_severity = LOG_INFO;
|
||||
-int deny_severity = LOG_WARNING;
|
||||
-
|
||||
-/* A handful of macros for "readability". */
|
||||
-
|
||||
-#ifdef HAVE_LIBWRAP
|
||||
-/* coming from libwrap.a (tcp_wrappers) */
|
||||
-extern int hosts_ctl(char *daemon, char *name, char *addr, char *user);
|
||||
-#else
|
||||
-int hosts_ctl(char *daemon, char *name, char *addr, char *user)
|
||||
-{
|
||||
- return 0;
|
||||
-}
|
||||
-#endif
|
||||
-
|
||||
-#define legal_port(a,p) \
|
||||
- (ntohs((a)->sin_port) < IPPORT_RESERVED || (p) >= IPPORT_RESERVED)
|
||||
-
|
||||
-#define log_bad_port(addr, proc, prog) \
|
||||
- logit(deny_severity, addr, proc, prog, ": request from unprivileged port")
|
||||
+static int check_files(void);
|
||||
|
||||
#define log_bad_host(addr, proc, prog) \
|
||||
- logit(deny_severity, addr, proc, prog, ": request from unauthorized host")
|
||||
-
|
||||
-#define log_bad_owner(addr, proc, prog) \
|
||||
- logit(deny_severity, addr, proc, prog, ": request from non-local host")
|
||||
-
|
||||
-#define log_no_forward(addr, proc, prog) \
|
||||
- logit(deny_severity, addr, proc, prog, ": request not forwarded")
|
||||
-
|
||||
-#define log_client(addr, proc, prog) \
|
||||
- logit(allow_severity, addr, proc, prog, "")
|
||||
+ logit(LOG_WARNING, addr, proc, prog, "request from unauthorized host")
|
||||
|
||||
#define ALLOW 1
|
||||
#define DENY 0
|
||||
@@ -180,46 +151,9 @@ struct sockaddr_in *addr;
|
||||
return DENY;
|
||||
}
|
||||
|
||||
-/* check_startup - additional startup code */
|
||||
-
|
||||
-void check_startup(void)
|
||||
-{
|
||||
-
|
||||
- /*
|
||||
- * Give up root privileges so that we can never allocate a privileged
|
||||
- * port when forwarding an rpc request.
|
||||
- *
|
||||
- * Fix 8/3/00 Philipp Knirsch: First lookup our rpc user. If we find it,
|
||||
- * switch to that uid, otherwise simply resue the old bin user and print
|
||||
- * out a warning in syslog.
|
||||
- */
|
||||
-
|
||||
- struct passwd *pwent;
|
||||
-
|
||||
- pwent = getpwnam("rpc");
|
||||
- if (pwent == NULL) {
|
||||
- syslog(LOG_WARNING, "user rpc not found, reverting to user bin");
|
||||
- if (setuid(1) == -1) {
|
||||
- syslog(LOG_ERR, "setuid(1) failed: %m");
|
||||
- exit(1);
|
||||
- }
|
||||
- }
|
||||
- else {
|
||||
- if (setuid(pwent->pw_uid) == -1) {
|
||||
- syslog(LOG_WARNING, "setuid() to rpc user failed: %m");
|
||||
- if (setuid(1) == -1) {
|
||||
- syslog(LOG_ERR, "setuid(1) failed: %m");
|
||||
- exit(1);
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- (void) signal(SIGINT, toggle_verboselog);
|
||||
-}
|
||||
-
|
||||
/* check_files - check to see if either access files have changed */
|
||||
|
||||
-int check_files()
|
||||
+static int check_files()
|
||||
{
|
||||
static time_t allow_mtime, deny_mtime;
|
||||
struct stat astat, dstat;
|
||||
@@ -268,78 +202,21 @@ u_long prog;
|
||||
haccess_add(addr, prog, FALSE);
|
||||
return (FALSE);
|
||||
}
|
||||
- if (verboselog)
|
||||
- log_client(addr, proc, prog);
|
||||
|
||||
if (acc)
|
||||
acc->access = TRUE;
|
||||
else
|
||||
haccess_add(addr, prog, TRUE);
|
||||
- return (TRUE);
|
||||
-}
|
||||
|
||||
-/* check_privileged_port - additional checks for privileged-port updates */
|
||||
-int
|
||||
-check_privileged_port(struct sockaddr_in *addr,
|
||||
- u_long proc, u_long prog, u_long port)
|
||||
-{
|
||||
-#ifdef CHECK_PORT
|
||||
- if (!legal_port(addr, port)) {
|
||||
- log_bad_port(addr, proc, prog);
|
||||
- return (FALSE);
|
||||
- }
|
||||
-#endif
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
-/* toggle_verboselog - toggle verbose logging flag */
|
||||
-
|
||||
-static void toggle_verboselog(int sig)
|
||||
-{
|
||||
- (void) signal(sig, toggle_verboselog);
|
||||
- verboselog = !verboselog;
|
||||
-}
|
||||
-
|
||||
/* logit - report events of interest via the syslog daemon */
|
||||
|
||||
static void logit(int severity, struct sockaddr_in *addr,
|
||||
u_long procnum, u_long prognum, char *text)
|
||||
{
|
||||
- char *procname;
|
||||
- char procbuf[16 + 4 * sizeof(u_long)];
|
||||
- char *progname;
|
||||
- char progbuf[16 + 4 * sizeof(u_long)];
|
||||
- struct rpcent *rpc;
|
||||
-
|
||||
- /*
|
||||
- * Fork off a process or the portmap daemon might hang while
|
||||
- * getrpcbynumber() or syslog() does its thing.
|
||||
- *
|
||||
- * Don't forget to wait for the children, too...
|
||||
- */
|
||||
-
|
||||
- if (fork() == 0) {
|
||||
-
|
||||
- /* Try to map program number to name. */
|
||||
-
|
||||
- if (prognum == 0) {
|
||||
- progname = "";
|
||||
- } else if ((rpc = getrpcbynumber((int) prognum))) {
|
||||
- progname = rpc->r_name;
|
||||
- } else {
|
||||
- snprintf(progname = progbuf, sizeof (progbuf),
|
||||
- "prog (%lu)", prognum);
|
||||
- }
|
||||
-
|
||||
- /* Try to map procedure number to name. */
|
||||
-
|
||||
- snprintf(procname = procbuf, sizeof (procbuf),
|
||||
- "proc (%lu)", (u_long) procnum);
|
||||
-
|
||||
- /* Write syslog record. */
|
||||
-
|
||||
- syslog(severity, "connect from %s to %s in %s%s",
|
||||
- inet_ntoa(addr->sin_addr), procname, progname, text);
|
||||
- exit(0);
|
||||
- }
|
||||
+ syslog(severity, "connect from %s denied: %s",
|
||||
+ inet_ntoa(addr->sin_addr), text);
|
||||
}
|
||||
+#endif
|
@ -1,89 +0,0 @@
|
||||
Author: Steve Dickson <steved@redhat.com>
|
||||
Date: Sat Jan 31 05:30:13 2009 -0500
|
||||
|
||||
Only hash on IP address and Program number. Including the Procedure
|
||||
number only creates needles extra hash entries.
|
||||
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff -up nfs-utils-1.1.4/support/misc/tcpwrapper.c.orig nfs-utils-1.1.4/support/misc/tcpwrapper.c
|
||||
--- nfs-utils-1.1.4/support/misc/tcpwrapper.c.orig 2009-01-31 06:22:35.000000000 -0500
|
||||
+++ nfs-utils-1.1.4/support/misc/tcpwrapper.c 2009-01-31 06:23:22.000000000 -0500
|
||||
@@ -106,8 +106,8 @@ typedef struct _hash_head {
|
||||
TAILQ_HEAD(host_list, _haccess_t) h_head;
|
||||
} hash_head;
|
||||
hash_head haccess_tbl[HASH_TABLE_SIZE];
|
||||
-static haccess_t *haccess_lookup(struct sockaddr_in *addr, u_long, u_long);
|
||||
-static void haccess_add(struct sockaddr_in *addr, u_long, u_long, int);
|
||||
+static haccess_t *haccess_lookup(struct sockaddr_in *addr, u_long);
|
||||
+static void haccess_add(struct sockaddr_in *addr, u_long, int);
|
||||
|
||||
inline unsigned int strtoint(char *str)
|
||||
{
|
||||
@@ -124,11 +124,10 @@ inline int hashint(unsigned int num)
|
||||
{
|
||||
return num % HASH_TABLE_SIZE;
|
||||
}
|
||||
-#define HASH(_addr, _proc, _prog) \
|
||||
- hashint((strtoint((_addr))+(_proc)+(_prog)))
|
||||
+#define HASH(_addr, _prog) \
|
||||
+ hashint((strtoint((_addr))+(_prog)))
|
||||
|
||||
-void haccess_add(struct sockaddr_in *addr, u_long proc,
|
||||
- u_long prog, int access)
|
||||
+void haccess_add(struct sockaddr_in *addr, u_long prog, int access)
|
||||
{
|
||||
hash_head *head;
|
||||
haccess_t *hptr;
|
||||
@@ -138,7 +137,7 @@ void haccess_add(struct sockaddr_in *add
|
||||
if (hptr == NULL)
|
||||
return;
|
||||
|
||||
- hash = HASH(inet_ntoa(addr->sin_addr), proc, prog);
|
||||
+ hash = HASH(inet_ntoa(addr->sin_addr), prog);
|
||||
head = &(haccess_tbl[hash]);
|
||||
|
||||
hptr->access = access;
|
||||
@@ -149,13 +148,13 @@ void haccess_add(struct sockaddr_in *add
|
||||
else
|
||||
TAILQ_INSERT_TAIL(&head->h_head, hptr, list);
|
||||
}
|
||||
-haccess_t *haccess_lookup(struct sockaddr_in *addr, u_long proc, u_long prog)
|
||||
+haccess_t *haccess_lookup(struct sockaddr_in *addr, u_long prog)
|
||||
{
|
||||
hash_head *head;
|
||||
haccess_t *hptr;
|
||||
int hash;
|
||||
|
||||
- hash = HASH(inet_ntoa(addr->sin_addr), proc, prog);
|
||||
+ hash = HASH(inet_ntoa(addr->sin_addr), prog);
|
||||
head = &(haccess_tbl[hash]);
|
||||
|
||||
TAILQ_FOREACH(hptr, &head->h_head, list) {
|
||||
@@ -300,7 +299,7 @@ u_long prog;
|
||||
haccess_t *acc = NULL;
|
||||
int changed = check_files();
|
||||
|
||||
- acc = haccess_lookup(addr, proc, prog);
|
||||
+ acc = haccess_lookup(addr, prog);
|
||||
if (acc && changed == 0)
|
||||
return (acc->access);
|
||||
|
||||
@@ -309,7 +308,7 @@ u_long prog;
|
||||
if (acc)
|
||||
acc->access = FALSE;
|
||||
else
|
||||
- haccess_add(addr, proc, prog, FALSE);
|
||||
+ haccess_add(addr, prog, FALSE);
|
||||
return (FALSE);
|
||||
}
|
||||
if (verboselog)
|
||||
@@ -318,7 +317,7 @@ u_long prog;
|
||||
if (acc)
|
||||
acc->access = TRUE;
|
||||
else
|
||||
- haccess_add(addr, proc, prog, TRUE);
|
||||
+ haccess_add(addr, prog, TRUE);
|
||||
return (TRUE);
|
||||
}
|
||||
|
@ -1,106 +0,0 @@
|
||||
Author: Steve Dickson <steved@redhat.com>
|
||||
Date: Sat Jan 31 05:50:51 2009 -0500
|
||||
|
||||
Converted good_client() to correctly use the tcp wrapper
|
||||
interface and added a note to the mountd man page saying
|
||||
hostnames will be ignored when they can not be looked up.
|
||||
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff -up nfs-utils-1.1.4/support/misc/tcpwrapper.c.orig nfs-utils-1.1.4/support/misc/tcpwrapper.c
|
||||
--- nfs-utils-1.1.4/support/misc/tcpwrapper.c.orig 2009-01-31 06:25:16.000000000 -0500
|
||||
+++ nfs-utils-1.1.4/support/misc/tcpwrapper.c 2009-01-31 06:26:27.000000000 -0500
|
||||
@@ -46,7 +46,7 @@
|
||||
#include <sys/signal.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/stat.h>
|
||||
-#include <unistd.h>
|
||||
+#include <tcpd.h>
|
||||
|
||||
#include "xlog.h"
|
||||
|
||||
@@ -169,58 +169,15 @@ good_client(daemon, addr)
|
||||
char *daemon;
|
||||
struct sockaddr_in *addr;
|
||||
{
|
||||
- struct hostent *hp;
|
||||
- char **sp;
|
||||
- char *tmpname;
|
||||
-
|
||||
- /* First check the address. */
|
||||
- if (hosts_ctl(daemon, "", inet_ntoa(addr->sin_addr), "") == DENY)
|
||||
- return DENY;
|
||||
-
|
||||
- /* Now do the hostname lookup */
|
||||
- hp = gethostbyaddr ((const char *) &(addr->sin_addr),
|
||||
- sizeof (addr->sin_addr), AF_INET);
|
||||
- if (!hp) {
|
||||
- xlog(L_WARNING,
|
||||
- "Warning: Client IP address '%s' not found in host lookup",
|
||||
- inet_ntoa(addr->sin_addr));
|
||||
- return DENY; /* never heard of it. misconfigured DNS? */
|
||||
- }
|
||||
-
|
||||
- /* Make sure the hostent is authorative. */
|
||||
- tmpname = strdup(hp->h_name);
|
||||
- if (!tmpname) {
|
||||
- xlog(L_WARNING, "Warning: No memory for Host access check");
|
||||
- return DENY;
|
||||
- }
|
||||
- hp = gethostbyname(tmpname);
|
||||
- if (!hp) {
|
||||
- xlog(L_WARNING,
|
||||
- "Warning: Client hostname '%s' not found in host lookup", tmpname);
|
||||
- free(tmpname);
|
||||
- return DENY; /* never heard of it. misconfigured DNS? */
|
||||
- }
|
||||
- free(tmpname);
|
||||
+ struct request_info req;
|
||||
|
||||
- /* Now make sure the address is on the list */
|
||||
- for (sp = hp->h_addr_list ; *sp ; sp++) {
|
||||
- if (memcmp(*sp, &(addr->sin_addr), hp->h_length) == 0)
|
||||
- break;
|
||||
- }
|
||||
- if (!*sp)
|
||||
- return DENY; /* it was a FAKE. */
|
||||
+ request_init(&req, RQ_DAEMON, daemon, RQ_CLIENT_SIN, addr, 0);
|
||||
+ sock_methods(&req);
|
||||
|
||||
- /* Check the official name and address. */
|
||||
- if (hosts_ctl(daemon, hp->h_name, inet_ntoa(addr->sin_addr), "") == DENY)
|
||||
- return DENY;
|
||||
-
|
||||
- /* Now check aliases. */
|
||||
- for (sp = hp->h_aliases; *sp ; sp++) {
|
||||
- if (hosts_ctl(daemon, *sp, inet_ntoa(addr->sin_addr), "") == DENY)
|
||||
- return DENY;
|
||||
- }
|
||||
+ if (hosts_access(&req))
|
||||
+ return ALLOW;
|
||||
|
||||
- return ALLOW;
|
||||
+ return DENY;
|
||||
}
|
||||
|
||||
/* check_startup - additional startup code */
|
||||
diff -up nfs-utils-1.1.4/utils/mountd/mountd.man.orig nfs-utils-1.1.4/utils/mountd/mountd.man
|
||||
--- nfs-utils-1.1.4/utils/mountd/mountd.man.orig 2008-10-17 10:20:09.000000000 -0400
|
||||
+++ nfs-utils-1.1.4/utils/mountd/mountd.man 2009-01-31 06:26:27.000000000 -0500
|
||||
@@ -181,13 +181,15 @@ mountd: .bar.com
|
||||
You have to use the daemon name
|
||||
.B mountd
|
||||
for the daemon name (even if the binary has a different name).
|
||||
+.B Note:
|
||||
+hostnames used in either access file will be ignored when
|
||||
+they can not be resolved into IP addresses.
|
||||
|
||||
For further information please have a look at the
|
||||
.BR tcpd (8)
|
||||
and
|
||||
.BR hosts_access (5)
|
||||
manual pages.
|
||||
-
|
||||
.SH SEE ALSO
|
||||
.BR rpc.nfsd (8),
|
||||
.BR exportfs (8),
|
@ -1,55 +0,0 @@
|
||||
commit 6e3f696e788a56f30b5b3f8250647fe4cd63c884
|
||||
Author: Steve Dickson <steved@redhat.com>
|
||||
Date: Sat Jan 3 14:08:25 2009 -0500
|
||||
|
||||
Now that the TCP wrapper actually works, mounts will
|
||||
be denied with misconfigured DNS configurations. Warnings
|
||||
will be logged when these types of configurations are
|
||||
detected.
|
||||
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff -up nfs-utils-1.1.4/support/misc/tcpwrapper.c.orig nfs-utils-1.1.4/support/misc/tcpwrapper.c
|
||||
--- nfs-utils-1.1.4/support/misc/tcpwrapper.c.orig 2009-01-03 13:02:15.000000000 -0500
|
||||
+++ nfs-utils-1.1.4/support/misc/tcpwrapper.c 2009-01-03 14:05:42.000000000 -0500
|
||||
@@ -48,6 +48,8 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
+#include "xlog.h"
|
||||
+
|
||||
#ifdef SYSV40
|
||||
#include <netinet/in.h>
|
||||
#include <rpc/rpcent.h>
|
||||
@@ -179,17 +181,27 @@ struct sockaddr_in *addr;
|
||||
/* Now do the hostname lookup */
|
||||
hp = gethostbyaddr ((const char *) &(addr->sin_addr),
|
||||
sizeof (addr->sin_addr), AF_INET);
|
||||
- if (!hp)
|
||||
+ if (!hp) {
|
||||
+ xlog(L_WARNING,
|
||||
+ "Warning: Client IP address '%s' not found in host lookup",
|
||||
+ inet_ntoa(addr->sin_addr));
|
||||
return DENY; /* never heard of it. misconfigured DNS? */
|
||||
+ }
|
||||
|
||||
/* Make sure the hostent is authorative. */
|
||||
tmpname = strdup(hp->h_name);
|
||||
- if (!tmpname)
|
||||
+ if (!tmpname) {
|
||||
+ xlog(L_WARNING, "Warning: No memory for Host access check");
|
||||
return DENY;
|
||||
+ }
|
||||
hp = gethostbyname(tmpname);
|
||||
- free(tmpname);
|
||||
- if (!hp)
|
||||
+ if (!hp) {
|
||||
+ xlog(L_WARNING,
|
||||
+ "Warning: Client hostname '%s' not found in host lookup", tmpname);
|
||||
+ free(tmpname);
|
||||
return DENY; /* never heard of it. misconfigured DNS? */
|
||||
+ }
|
||||
+ free(tmpname);
|
||||
|
||||
/* Now make sure the address is on the list */
|
||||
for (sp = hp->h_addr_list ; *sp ; sp++) {
|
@ -1,280 +0,0 @@
|
||||
commit 71f9f61517bf301f723b79651d53590ef97c3556
|
||||
Author: Steve Dickson <steved@redhat.com>
|
||||
Date: Fri Dec 19 14:20:14 2008 -0500
|
||||
|
||||
To ensure the hash table of clients has valid
|
||||
access rights, check the modification times on
|
||||
both access files. If one of them have change,
|
||||
update the hash entry instead of creating a
|
||||
new entry.
|
||||
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
commit 58e0a308fec476361dd21f7d3856faceb6e308ee
|
||||
Author: Steve Dickson <steved@redhat.com>
|
||||
Date: Fri Dec 19 14:11:09 2008 -0500
|
||||
|
||||
Clients IP address and host names are check on
|
||||
every RPC request, to both mountd and statd
|
||||
when TCP wrappers are enabled. To help this
|
||||
process scale better the access rights are stored
|
||||
in a hash table, which are hashed per IP address,
|
||||
RPC program and procudure numbers.
|
||||
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
commit e47da19d63ea50a4e15f6ab491535d54097744de
|
||||
Author: Steve Dickson <steved@redhat.com>
|
||||
Date: Fri Dec 19 14:09:59 2008 -0500
|
||||
|
||||
When clients are define as IP addresses in /etc/hosts.deny,
|
||||
access is allow due to misinterpreting the return value of
|
||||
hosts_ctl(). This patch reworks that logic which closes
|
||||
that hole.
|
||||
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff -up nfs-utils-1.1.4/support/misc/tcpwrapper.c.save nfs-utils-1.1.4/support/misc/tcpwrapper.c
|
||||
--- nfs-utils-1.1.4/support/misc/tcpwrapper.c.save 2008-12-19 15:44:05.000000000 -0500
|
||||
+++ nfs-utils-1.1.4/support/misc/tcpwrapper.c 2008-12-19 15:46:15.000000000 -0500
|
||||
@@ -44,6 +44,10 @@
|
||||
#include <pwd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/signal.h>
|
||||
+#include <sys/queue.h>
|
||||
+#include <sys/stat.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
#ifdef SYSV40
|
||||
#include <netinet/in.h>
|
||||
#include <rpc/rpcent.h>
|
||||
@@ -86,6 +90,79 @@ int hosts_ctl(char *daemon, char *name,
|
||||
#define log_client(addr, proc, prog) \
|
||||
logit(allow_severity, addr, proc, prog, "")
|
||||
|
||||
+#define ALLOW 1
|
||||
+#define DENY 0
|
||||
+
|
||||
+typedef struct _haccess_t {
|
||||
+ TAILQ_ENTRY(_haccess_t) list;
|
||||
+ int access;
|
||||
+ struct in_addr addr;
|
||||
+} haccess_t;
|
||||
+
|
||||
+#define HASH_TABLE_SIZE 1021
|
||||
+typedef struct _hash_head {
|
||||
+ TAILQ_HEAD(host_list, _haccess_t) h_head;
|
||||
+} hash_head;
|
||||
+hash_head haccess_tbl[HASH_TABLE_SIZE];
|
||||
+static haccess_t *haccess_lookup(struct sockaddr_in *addr, u_long, u_long);
|
||||
+static void haccess_add(struct sockaddr_in *addr, u_long, u_long, int);
|
||||
+
|
||||
+inline unsigned int strtoint(char *str)
|
||||
+{
|
||||
+ unsigned int n = 0;
|
||||
+ int len = strlen(str);
|
||||
+ int i;
|
||||
+
|
||||
+ for (i=0; i < len; i++)
|
||||
+ n+=((int)str[i])*i;
|
||||
+
|
||||
+ return n;
|
||||
+}
|
||||
+inline int hashint(unsigned int num)
|
||||
+{
|
||||
+ return num % HASH_TABLE_SIZE;
|
||||
+}
|
||||
+#define HASH(_addr, _proc, _prog) \
|
||||
+ hashint((strtoint((_addr))+(_proc)+(_prog)))
|
||||
+
|
||||
+void haccess_add(struct sockaddr_in *addr, u_long proc,
|
||||
+ u_long prog, int access)
|
||||
+{
|
||||
+ hash_head *head;
|
||||
+ haccess_t *hptr;
|
||||
+ int hash;
|
||||
+
|
||||
+ hptr = (haccess_t *)malloc(sizeof(haccess_t));
|
||||
+ if (hptr == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ hash = HASH(inet_ntoa(addr->sin_addr), proc, prog);
|
||||
+ head = &(haccess_tbl[hash]);
|
||||
+
|
||||
+ hptr->access = access;
|
||||
+ hptr->addr.s_addr = addr->sin_addr.s_addr;
|
||||
+
|
||||
+ if (TAILQ_EMPTY(&head->h_head))
|
||||
+ TAILQ_INSERT_HEAD(&head->h_head, hptr, list);
|
||||
+ else
|
||||
+ TAILQ_INSERT_TAIL(&head->h_head, hptr, list);
|
||||
+}
|
||||
+haccess_t *haccess_lookup(struct sockaddr_in *addr, u_long proc, u_long prog)
|
||||
+{
|
||||
+ hash_head *head;
|
||||
+ haccess_t *hptr;
|
||||
+ int hash;
|
||||
+
|
||||
+ hash = HASH(inet_ntoa(addr->sin_addr), proc, prog);
|
||||
+ head = &(haccess_tbl[hash]);
|
||||
+
|
||||
+ TAILQ_FOREACH(hptr, &head->h_head, list) {
|
||||
+ if (hptr->addr.s_addr == addr->sin_addr.s_addr)
|
||||
+ return hptr;
|
||||
+ }
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
int
|
||||
good_client(daemon, addr)
|
||||
char *daemon;
|
||||
@@ -95,47 +172,44 @@ struct sockaddr_in *addr;
|
||||
char **sp;
|
||||
char *tmpname;
|
||||
|
||||
- /* Check the IP address first. */
|
||||
- if (hosts_ctl(daemon, "", inet_ntoa(addr->sin_addr), ""))
|
||||
- return 1;
|
||||
-
|
||||
- /* Check the hostname. */
|
||||
- hp = gethostbyaddr ((const char *) &(addr->sin_addr),
|
||||
- sizeof (addr->sin_addr), AF_INET);
|
||||
+ /* First check the address. */
|
||||
+ if (hosts_ctl(daemon, "", inet_ntoa(addr->sin_addr), "") == DENY)
|
||||
+ return DENY;
|
||||
+
|
||||
+ /* Now do the hostname lookup */
|
||||
+ hp = gethostbyaddr ((const char *) &(addr->sin_addr),
|
||||
+ sizeof (addr->sin_addr), AF_INET);
|
||||
+ if (!hp)
|
||||
+ return DENY; /* never heard of it. misconfigured DNS? */
|
||||
+
|
||||
+ /* Make sure the hostent is authorative. */
|
||||
+ tmpname = strdup(hp->h_name);
|
||||
+ if (!tmpname)
|
||||
+ return DENY;
|
||||
+ hp = gethostbyname(tmpname);
|
||||
+ free(tmpname);
|
||||
+ if (!hp)
|
||||
+ return DENY; /* never heard of it. misconfigured DNS? */
|
||||
|
||||
- if (!hp)
|
||||
- return 0;
|
||||
-
|
||||
- /* must make sure the hostent is authorative. */
|
||||
- tmpname = alloca (strlen (hp->h_name) + 1);
|
||||
- strcpy (tmpname, hp->h_name);
|
||||
- hp = gethostbyname(tmpname);
|
||||
- if (hp) {
|
||||
- /* now make sure the "addr->sin_addr" is on the list */
|
||||
+ /* Now make sure the address is on the list */
|
||||
for (sp = hp->h_addr_list ; *sp ; sp++) {
|
||||
- if (memcmp(*sp, &(addr->sin_addr), hp->h_length)==0)
|
||||
- break;
|
||||
+ if (memcmp(*sp, &(addr->sin_addr), hp->h_length) == 0)
|
||||
+ break;
|
||||
}
|
||||
if (!*sp)
|
||||
- /* it was a FAKE. */
|
||||
- return 0;
|
||||
- }
|
||||
- else
|
||||
- /* never heard of it. misconfigured DNS? */
|
||||
- return 0;
|
||||
-
|
||||
- /* Check the official name first. */
|
||||
- if (hosts_ctl(daemon, hp->h_name, "", ""))
|
||||
- return 1;
|
||||
-
|
||||
- /* Check aliases. */
|
||||
- for (sp = hp->h_aliases; *sp ; sp++) {
|
||||
- if (hosts_ctl(daemon, *sp, "", ""))
|
||||
- return 1;
|
||||
- }
|
||||
+ return DENY; /* it was a FAKE. */
|
||||
+
|
||||
+ /* Check the official name and address. */
|
||||
+ if (hosts_ctl(daemon, hp->h_name, inet_ntoa(addr->sin_addr), "") == DENY)
|
||||
+ return DENY;
|
||||
+
|
||||
+ /* Now check aliases. */
|
||||
+ for (sp = hp->h_aliases; *sp ; sp++) {
|
||||
+ if (hosts_ctl(daemon, *sp, inet_ntoa(addr->sin_addr), "") == DENY)
|
||||
+ return DENY;
|
||||
+ }
|
||||
|
||||
- /* No match */
|
||||
- return 0;
|
||||
+ return ALLOW;
|
||||
}
|
||||
|
||||
/* check_startup - additional startup code */
|
||||
@@ -175,6 +249,33 @@ void check_startup(void)
|
||||
(void) signal(SIGINT, toggle_verboselog);
|
||||
}
|
||||
|
||||
+/* check_files - check to see if either access files have changed */
|
||||
+
|
||||
+int check_files()
|
||||
+{
|
||||
+ static time_t allow_mtime, deny_mtime;
|
||||
+ struct stat astat, dstat;
|
||||
+ int changed = 0;
|
||||
+
|
||||
+ if (stat("/etc/hosts.allow", &astat) < 0)
|
||||
+ astat.st_mtime = 0;
|
||||
+ if (stat("/etc/hosts.deny", &dstat) < 0)
|
||||
+ dstat.st_mtime = 0;
|
||||
+
|
||||
+ if(!astat.st_mtime || !dstat.st_mtime)
|
||||
+ return changed;
|
||||
+
|
||||
+ if (astat.st_mtime != allow_mtime)
|
||||
+ changed = 1;
|
||||
+ else if (dstat.st_mtime != deny_mtime)
|
||||
+ changed = 1;
|
||||
+
|
||||
+ allow_mtime = astat.st_mtime;
|
||||
+ deny_mtime = dstat.st_mtime;
|
||||
+
|
||||
+ return changed;
|
||||
+}
|
||||
+
|
||||
/* check_default - additional checks for NULL, DUMP, GETPORT and unknown */
|
||||
|
||||
int
|
||||
@@ -184,12 +285,28 @@ struct sockaddr_in *addr;
|
||||
u_long proc;
|
||||
u_long prog;
|
||||
{
|
||||
- if (!(from_local(addr) || good_client(daemon, addr))) {
|
||||
- log_bad_host(addr, proc, prog);
|
||||
- return (FALSE);
|
||||
- }
|
||||
- if (verboselog)
|
||||
- log_client(addr, proc, prog);
|
||||
+ haccess_t *acc = NULL;
|
||||
+ int changed = check_files();
|
||||
+
|
||||
+ acc = haccess_lookup(addr, proc, prog);
|
||||
+ if (acc && changed == 0)
|
||||
+ return (acc->access);
|
||||
+
|
||||
+ if (!(from_local(addr) || good_client(daemon, addr))) {
|
||||
+ log_bad_host(addr, proc, prog);
|
||||
+ if (acc)
|
||||
+ acc->access = FALSE;
|
||||
+ else
|
||||
+ haccess_add(addr, proc, prog, FALSE);
|
||||
+ return (FALSE);
|
||||
+ }
|
||||
+ if (verboselog)
|
||||
+ log_client(addr, proc, prog);
|
||||
+
|
||||
+ if (acc)
|
||||
+ acc->access = TRUE;
|
||||
+ else
|
||||
+ haccess_add(addr, proc, prog, TRUE);
|
||||
return (TRUE);
|
||||
}
|
||||
|
@ -1,343 +0,0 @@
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Tue Feb 17 16:27:43 2009 -0500
|
||||
|
||||
umount command: remove do_nfs_umount23 function
|
||||
|
||||
Remove do_nfs_umount23() now that it is unused.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
commit c735a8331b082038a0e83ec4187c2656b0804eea
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Tue Feb 17 16:26:31 2009 -0500
|
||||
|
||||
umount.nfs command: Support AF_INET6 server addresses
|
||||
|
||||
Replace existing mount option parser in nfsumount.c with the new pmap
|
||||
stuffer
|
||||
function nfs_options2pmap(). Mount option parsing for umount.nfs now
|
||||
works
|
||||
the same as it does for mount option rewriting in the text-based
|
||||
mount.nfs
|
||||
command.
|
||||
|
||||
This adds a number of new features:
|
||||
|
||||
1. The new logic supports resolving AF_INET6 server addresses
|
||||
2. Support is added for the recently introduced "mountaddr" option.
|
||||
3. Parsing numeric option values is much more careful
|
||||
4. Option parsing no longer uses xmalloc/xstrdup, so it won't fail
|
||||
silently if memory can't be allocated
|
||||
5. Mount program number set in /etc/rpc is respected
|
||||
6. Mount doesn't exit with EX_USAGE if the hostname lookup fails
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
commit 97de03f8c866b9d3e790d64f4e9ac24011aaa5b1
|
||||
Author: Chuck Lever <chuck.lever@oracle.com>
|
||||
Date: Tue Feb 17 16:25:27 2009 -0500
|
||||
|
||||
umount.nfs command: Add an AF_INET6-capable version of nfs_call_unmount()
|
||||
|
||||
We need an AF_INET6-capable version of nfs_call_unmount() to allow the
|
||||
umount.nfs command to support unmounting NFS servers over IPv6. The
|
||||
legacy
|
||||
mount.nfs command still likes to use nfs_call_umount(), so we leave it
|
||||
in
|
||||
place and introduce a new API that can take a "struct sockaddr *".
|
||||
|
||||
The umount.nfs command will invoke this new API, but we'll leave the
|
||||
legacy
|
||||
mount.nfs command and the umount.nfs4 command alone. The umount.nfs4
|
||||
command does not need this support because NFSv4 unmount operations are
|
||||
entirely local.
|
||||
|
||||
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
|
||||
Signed-off-by: Steve Dickson <steved@redhat.com>
|
||||
|
||||
diff -up nfs-utils-1.1.4/utils/mount/network.c.save nfs-utils-1.1.4/utils/mount/network.c
|
||||
--- nfs-utils-1.1.4/utils/mount/network.c.save 2009-02-17 16:37:18.000000000 -0500
|
||||
+++ nfs-utils-1.1.4/utils/mount/network.c 2009-02-17 16:38:10.000000000 -0500
|
||||
@@ -838,6 +838,59 @@ int start_statd(void)
|
||||
}
|
||||
|
||||
/**
|
||||
+ * nfs_advise_umount - ask the server to remove a share from it's rmtab
|
||||
+ * @sap: pointer to IP address of server to call
|
||||
+ * @salen: length of server address
|
||||
+ * @pmap: partially filled-in mountd RPC service tuple
|
||||
+ * @argp: directory path of share to "unmount"
|
||||
+ *
|
||||
+ * Returns one if the unmount call succeeded; zero if the unmount
|
||||
+ * failed for any reason; rpccreateerr.cf_stat is set to reflect
|
||||
+ * the nature of the error.
|
||||
+ *
|
||||
+ * We use a fast timeout since this call is advisory only.
|
||||
+ */
|
||||
+int nfs_advise_umount(const struct sockaddr *sap, const socklen_t salen,
|
||||
+ const struct pmap *pmap, const dirpath *argp)
|
||||
+{
|
||||
+ struct sockaddr_storage address;
|
||||
+ struct sockaddr *saddr = (struct sockaddr *)&address;
|
||||
+ struct pmap mnt_pmap = *pmap;
|
||||
+ struct timeval timeout = {
|
||||
+ .tv_sec = MOUNT_TIMEOUT >> 3,
|
||||
+ };
|
||||
+ CLIENT *client;
|
||||
+ enum clnt_stat res = 0;
|
||||
+
|
||||
+ if (nfs_probe_mntport(sap, salen, &mnt_pmap) == 0)
|
||||
+ return 0;
|
||||
+
|
||||
+ memcpy(saddr, sap, salen);
|
||||
+ nfs_set_port(saddr, mnt_pmap.pm_port);
|
||||
+
|
||||
+ client = nfs_get_rpcclient(saddr, salen, mnt_pmap.pm_prot,
|
||||
+ mnt_pmap.pm_prog, mnt_pmap.pm_vers,
|
||||
+ &timeout);
|
||||
+ if (client == NULL)
|
||||
+ return 0;
|
||||
+
|
||||
+ client->cl_auth = authunix_create_default();
|
||||
+
|
||||
+ res = CLNT_CALL(client, MOUNTPROC_UMNT,
|
||||
+ (xdrproc_t)xdr_dirpath, (caddr_t)argp,
|
||||
+ (xdrproc_t)xdr_void, NULL,
|
||||
+ timeout);
|
||||
+
|
||||
+ auth_destroy(client->cl_auth);
|
||||
+ CLNT_DESTROY(client);
|
||||
+
|
||||
+ if (res != RPC_SUCCESS)
|
||||
+ return 0;
|
||||
+
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
* nfs_call_umount - ask the server to remove a share from it's rmtab
|
||||
* @mnt_server: address of RPC MNT program server
|
||||
* @argp: directory path of share to "unmount"
|
||||
diff -up nfs-utils-1.1.4/utils/mount/network.h.save nfs-utils-1.1.4/utils/mount/network.h
|
||||
--- nfs-utils-1.1.4/utils/mount/network.h.save 2009-02-17 16:37:26.000000000 -0500
|
||||
+++ nfs-utils-1.1.4/utils/mount/network.h 2009-02-17 16:38:10.000000000 -0500
|
||||
@@ -52,7 +52,6 @@ int nfs_present_sockaddr(const struct so
|
||||
const socklen_t, char *, const size_t);
|
||||
int nfs_callback_address(const struct sockaddr *, const socklen_t,
|
||||
struct sockaddr *, socklen_t *);
|
||||
-int nfs_call_umount(clnt_addr_t *, dirpath *);
|
||||
int clnt_ping(struct sockaddr_in *, const unsigned long,
|
||||
const unsigned long, const unsigned int,
|
||||
struct sockaddr_in *);
|
||||
@@ -66,6 +65,9 @@ int start_statd(void);
|
||||
|
||||
unsigned long nfsvers_to_mnt(const unsigned long);
|
||||
|
||||
+int nfs_call_umount(clnt_addr_t *, dirpath *);
|
||||
+int nfs_advise_umount(const struct sockaddr *, const socklen_t,
|
||||
+ const struct pmap *, const dirpath *);
|
||||
CLIENT *mnt_openclnt(clnt_addr_t *, int *);
|
||||
void mnt_closeclnt(CLIENT *, int);
|
||||
|
||||
diff -up nfs-utils-1.1.4/utils/mount/nfsumount.c.save nfs-utils-1.1.4/utils/mount/nfsumount.c
|
||||
--- nfs-utils-1.1.4/utils/mount/nfsumount.c.save 2009-02-17 16:37:42.000000000 -0500
|
||||
+++ nfs-utils-1.1.4/utils/mount/nfsumount.c 2009-02-17 16:38:29.000000000 -0500
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "mount.h"
|
||||
#include "error.h"
|
||||
#include "network.h"
|
||||
+#include "parse_opt.h"
|
||||
#include "parse_dev.h"
|
||||
|
||||
#if !defined(MNT_FORCE)
|
||||
@@ -134,6 +135,64 @@ static int del_mtab(const char *spec, co
|
||||
}
|
||||
|
||||
/*
|
||||
+ * Discover mount server's hostname/address by examining mount options
|
||||
+ *
|
||||
+ * Returns a pointer to a string that the caller must free, on
|
||||
+ * success; otherwise NULL is returned.
|
||||
+ */
|
||||
+static char *nfs_umount_hostname(struct mount_options *options,
|
||||
+ char *hostname)
|
||||
+{
|
||||
+ char *option;
|
||||
+
|
||||
+ option = po_get(options, "mountaddr");
|
||||
+ if (option)
|
||||
+ goto out;
|
||||
+ option = po_get(options, "mounthost");
|
||||
+ if (option)
|
||||
+ goto out;
|
||||
+ option = po_get(options, "addr");
|
||||
+ if (option)
|
||||
+ goto out;
|
||||
+
|
||||
+ return hostname;
|
||||
+
|
||||
+out:
|
||||
+ free(hostname);
|
||||
+ return strdup(option);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Returns EX_SUCCESS if mount options and device name have been
|
||||
+ * parsed successfully; otherwise EX_FAIL.
|
||||
+ */
|
||||
+static int nfs_umount_do_umnt(struct mount_options *options,
|
||||
+ char **hostname, char **dirname)
|
||||
+{
|
||||
+ struct sockaddr_storage address;
|
||||
+ struct sockaddr *sap = (struct sockaddr *)&address;
|
||||
+ socklen_t salen = sizeof(address);
|
||||
+ struct pmap nfs_pmap, mnt_pmap;
|
||||
+
|
||||
+ nfs_options2pmap(options, &nfs_pmap, &mnt_pmap);
|
||||
+
|
||||
+ *hostname = nfs_umount_hostname(options, *hostname);
|
||||
+ if (!*hostname) {
|
||||
+ nfs_error(_("%s: out of memory"), progname);
|
||||
+ return EX_FAIL;
|
||||
+ }
|
||||
+
|
||||
+ if (nfs_name_to_address(*hostname, AF_UNSPEC, sap, &salen)) {
|
||||
+ if (nfs_advise_umount(sap, salen, &mnt_pmap, dirname) != 0)
|
||||
+ return EX_SUCCESS;
|
||||
+ else
|
||||
+ nfs_error(_("%s: Server failed to unmount '%s:%s'"),
|
||||
+ progname, *hostname, *dirname);
|
||||
+ }
|
||||
+ return EX_FAIL;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
* Pick up certain mount options used during the original mount
|
||||
* from /etc/mtab. The basics include the server's IP address and
|
||||
* the server pathname of the share to unregister.
|
||||
@@ -142,85 +201,28 @@ static int del_mtab(const char *spec, co
|
||||
* version, and transport protocol used to punch through a firewall.
|
||||
* We will need this information to get through the firewall again
|
||||
* to do the umount.
|
||||
+ *
|
||||
+ * Note that option parsing failures won't necessarily cause the
|
||||
+ * umount request to fail. Those values will be left zero in the
|
||||
+ * pmap tuple. If the GETPORT call later fails to disambiguate them,
|
||||
+ * then we fail.
|
||||
*/
|
||||
-static int do_nfs_umount23(const char *spec, char *opts)
|
||||
+static int nfs_umount23(const char *devname, char *string)
|
||||
{
|
||||
- char *hostname;
|
||||
- char *dirname;
|
||||
- clnt_addr_t mnt_server = { &hostname, };
|
||||
- struct mntent mnt = { .mnt_opts = opts };
|
||||
- struct pmap *pmap = &mnt_server.pmap;
|
||||
- char *p;
|
||||
- int result = EX_USAGE;
|
||||
-
|
||||
- if (!nfs_parse_devname(spec, &hostname, &dirname))
|
||||
- return result;
|
||||
-
|
||||
-#ifdef NFS_MOUNT_DEBUG
|
||||
- printf(_("host: %s, directory: %s\n"), hostname, dirname);
|
||||
-#endif
|
||||
-
|
||||
- if (opts && (p = strstr(opts, "addr="))) {
|
||||
- char *q;
|
||||
+ char *hostname, *dirname;
|
||||
+ struct mount_options *options;
|
||||
+ int result = EX_FAIL;
|
||||
|
||||
- free(hostname);
|
||||
- p += 5;
|
||||
- q = p;
|
||||
- while (*q && *q != ',') q++;
|
||||
- hostname = xstrndup(p,q-p);
|
||||
- }
|
||||
-
|
||||
- if (opts && (p = strstr(opts, "mounthost="))) {
|
||||
- char *q;
|
||||
-
|
||||
- free(hostname);
|
||||
- p += 10;
|
||||
- q = p;
|
||||
- while (*q && *q != ',') q++;
|
||||
- hostname = xstrndup(p,q-p);
|
||||
- }
|
||||
-
|
||||
- pmap->pm_prog = MOUNTPROG;
|
||||
- pmap->pm_vers = 0; /* unknown */
|
||||
- if (opts && (p = strstr(opts, "mountprog=")) && isdigit(*(p+10)))
|
||||
- pmap->pm_prog = atoi(p+10);
|
||||
- if (opts && (p = strstr(opts, "mountport=")) && isdigit(*(p+10)))
|
||||
- pmap->pm_port = atoi(p+10);
|
||||
- if (opts && hasmntopt(&mnt, "v2"))
|
||||
- pmap->pm_vers = nfsvers_to_mnt(2);
|
||||
- if (opts && hasmntopt(&mnt, "v3"))
|
||||
- pmap->pm_vers = nfsvers_to_mnt(3);
|
||||
- if (opts && (p = strstr(opts, "vers=")) && isdigit(*(p+5)))
|
||||
- pmap->pm_vers = nfsvers_to_mnt(atoi(p+5));
|
||||
- if (opts && (p = strstr(opts, "mountvers=")) && isdigit(*(p+10)))
|
||||
- pmap->pm_vers = atoi(p+10);
|
||||
- if (opts && (hasmntopt(&mnt, "udp")
|
||||
- || hasmntopt(&mnt, "proto=udp")
|
||||
- || hasmntopt(&mnt, "mountproto=udp")
|
||||
- ))
|
||||
- pmap->pm_prot = IPPROTO_UDP;
|
||||
- if (opts && (hasmntopt(&mnt, "tcp")
|
||||
- || hasmntopt(&mnt, "proto=tcp")
|
||||
- || hasmntopt(&mnt, "mountproto=tcp")
|
||||
- ))
|
||||
- pmap->pm_prot = IPPROTO_TCP;
|
||||
-
|
||||
- if (!nfs_gethostbyname(hostname, &mnt_server.saddr)) {
|
||||
- nfs_error(_("%s: DNS resolution of '%s' failed"),
|
||||
- progname, hostname);
|
||||
- goto out;
|
||||
- }
|
||||
-
|
||||
- if (!nfs_call_umount(&mnt_server, &dirname)) {
|
||||
- nfs_error(_("%s: Server failed to unmount '%s'"),
|
||||
- progname, spec);
|
||||
- result = EX_FAIL;
|
||||
- goto out;
|
||||
- }
|
||||
+ if (!nfs_parse_devname(devname, &hostname, &dirname))
|
||||
+ return EX_USAGE;
|
||||
|
||||
- result = EX_SUCCESS;
|
||||
+ options = po_split(string);
|
||||
+ if (options) {
|
||||
+ result = nfs_umount_do_umnt(options, &hostname, &dirname);
|
||||
+ po_destroy(options);
|
||||
+ } else
|
||||
+ nfs_error(_("%s: option parsing error"), progname);
|
||||
|
||||
-out:
|
||||
free(hostname);
|
||||
free(dirname);
|
||||
return result;
|
||||
@@ -350,16 +352,16 @@ int nfsumount(int argc, char *argv[])
|
||||
ret = 0;
|
||||
if (mc) {
|
||||
if (!lazy && strcmp(mc->m.mnt_type, "nfs4") != 0)
|
||||
- /* We ignore the error from do_nfs_umount23.
|
||||
+ /* We ignore the error from nfs_umount23.
|
||||
* If the actual umount succeeds (in del_mtab),
|
||||
* we don't want to signal an error, as that
|
||||
* could cause /sbin/mount to retry!
|
||||
*/
|
||||
- do_nfs_umount23(mc->m.mnt_fsname, mc->m.mnt_opts);
|
||||
- ret = del_mtab(mc->m.mnt_fsname, mc->m.mnt_dir);
|
||||
+ nfs_umount23(mc->m.mnt_fsname, mc->m.mnt_opts);
|
||||
+ ret = del_mtab(mc->m.mnt_fsname, mc->m.mnt_dir) ?: ret;
|
||||
} else if (*spec != '/') {
|
||||
if (!lazy)
|
||||
- ret = do_nfs_umount23(spec, "tcp,v3");
|
||||
+ ret = nfs_umount23(spec, "tcp,v3");
|
||||
} else
|
||||
ret = del_mtab(NULL, spec);
|
||||
|
@ -1,8 +1,8 @@
|
||||
Summary: NFS utilities and supporting clients and daemons for the kernel NFS server
|
||||
Name: nfs-utils
|
||||
URL: http://sourceforge.net/projects/nfs
|
||||
Version: 1.1.4
|
||||
Release: 21%{?dist}
|
||||
Version: 1.1.5
|
||||
Release: 1%{?dist}
|
||||
Epoch: 1
|
||||
|
||||
# group all 32bit related archs
|
||||
@ -26,34 +26,6 @@ Patch00: nfs-utils-1.0.5-statdpath.patch
|
||||
Patch01: nfs-utils-1.1.0-smnotify-path.patch
|
||||
Patch02: nfs-utils-1.1.0-exp-subtree-warn-off.patch
|
||||
|
||||
Patch100: nfs-utils-1.1.4-inet6-capable-api.patch
|
||||
Patch101: nfs-utils-1.1.4-inet6-rpcbind-util-funcs.patch
|
||||
Patch102: nfs-utils-1.1.4-showmount-rpcbind.patch
|
||||
Patch103: nfs-utils-1.1.4-gssd-dnotify.patch
|
||||
Patch104: nfs-utils-1.1.4-statd-setuid.patch
|
||||
Patch105: nfs-utils-1.1.4-mount-nfs_getport.patch
|
||||
Patch106: nfs-utils-1.1.4-sm-notify-typo.patch
|
||||
Patch107: nfs-utils-1.1.4-mount-inet6-support.patch
|
||||
Patch108: nfs-utils-1.1.4-svcgssd-expiration.patch
|
||||
Patch109: nfs-utils-1.1.4-mount-po_get_numeric.patch
|
||||
Patch110: nfs-utils-1.1.4-sm-notify-freeaddrinfo.patch
|
||||
Patch111: nfs-utils-1.1.4-statd-xunlink.patch
|
||||
Patch112: nfs-utils-1.1.4-tcpwrapper-update.patch
|
||||
Patch113: nfs-utils-1.1.4-tcpwrap-warn.patch
|
||||
Patch114: nfs-utils-1.1.4-gssd-verbosity.patch
|
||||
Patch115: nfs-utils-1.1.4-mount-addrconfig.patch
|
||||
Patch116: nfs-utils-1.1.4-configure-uuid.patch
|
||||
Patch117: nfs-utils-1.1.4-configure-tirpc.patch
|
||||
Patch118: nfs-utils-1.1.4-tcpwrap-hash.patch
|
||||
Patch119: nfs-utils-1.1.4-tcpwrap-newrules.patch
|
||||
Patch120: nfs-utils-1.1.4-tcpwrap-cleanup.patch
|
||||
Patch121: nfs-utils-1.1.4-mount-textbased.patch
|
||||
Patch122: nfs-utils-1.1.4-mount-nolock.patch
|
||||
Patch123: nfs-utils-1.1.4-mount-udponly.patch
|
||||
Patch124: nfs-utils-1.1.4-umount-ipv6.patch
|
||||
Patch125: nfs-utils-1.1.4-export-hash.patch
|
||||
Patch126: nfs-utils-1.1.4-configure.patch
|
||||
|
||||
%if %{enablefscache}
|
||||
Patch90: nfs-utils-1.1.0-mount-fsc.patch
|
||||
%endif
|
||||
@ -107,34 +79,6 @@ This package also contains the mount.nfs and umount.nfs program.
|
||||
%patch01 -p1
|
||||
%patch02 -p1
|
||||
|
||||
%patch100 -p1
|
||||
%patch101 -p1
|
||||
%patch102 -p1
|
||||
%patch103 -p1
|
||||
%patch104 -p1
|
||||
%patch105 -p1
|
||||
%patch106 -p1
|
||||
%patch107 -p1
|
||||
%patch108 -p1
|
||||
%patch109 -p1
|
||||
%patch110 -p1
|
||||
%patch111 -p1
|
||||
%patch112 -p1
|
||||
%patch113 -p1
|
||||
%patch114 -p1
|
||||
%patch115 -p1
|
||||
%patch116 -p1
|
||||
%patch117 -p1
|
||||
%patch118 -p1
|
||||
%patch119 -p1
|
||||
%patch120 -p1
|
||||
%patch121 -p1
|
||||
%patch122 -p1
|
||||
%patch123 -p1
|
||||
%patch124 -p1
|
||||
%patch125 -p1
|
||||
%patch126 -p1
|
||||
|
||||
%if %{enablefscache}
|
||||
%patch90 -p1
|
||||
%endif
|
||||
@ -297,6 +241,9 @@ fi
|
||||
%attr(4755,root,root) /sbin/umount.nfs4
|
||||
|
||||
%changelog
|
||||
* Thu Mar 5 2009 Steve Dickson <steved@redhat.com> 1.1.5-1
|
||||
- Updated to latest upstream version: 1.1.5
|
||||
|
||||
* Wed Mar 4 2009 Steve Dickson <steved@redhat.com> 1.1.4-21
|
||||
- configure: fix AC_CACHE_VAL warnings
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user