Updated to latest upstream version: 1.1.5

This commit is contained in:
Steve Dickson 2009-03-05 12:57:02 +00:00
parent a4989af149
commit f76c8ecabe
30 changed files with 7 additions and 6591 deletions

View File

@ -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

View File

@ -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.

View File

@ -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,

View File

@ -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])

View File

@ -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;

View File

@ -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));

View File

@ -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;

View File

@ -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

View File

@ -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 *************************************************************

View File

@ -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 *);

View File

@ -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.

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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) {

View File

@ -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).

View File

@ -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);
/*

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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),

View File

@ -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++) {

View File

@ -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);
}

View File

@ -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);

View File

@ -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

View File

@ -1,2 +1,2 @@
ae7db9c61c5ad04f83bb99e5caed73da nfs.doc.tar.gz
3ed5b9cb73fd1c9b358c7bfa7a6ae150 nfs-utils-1.1.4.tar.bz2
2848072a5e53840b9bc520fbb6782b57 nfs-utils-1.1.5.tar.bz2