3499 lines
107 KiB
Diff
3499 lines
107 KiB
Diff
|
diff -up nfs-utils-1.2.1/support/include/ha-callout.h.orig nfs-utils-1.2.1/support/include/ha-callout.h
|
||
|
--- nfs-utils-1.2.1/support/include/ha-callout.h.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/support/include/ha-callout.h 2009-12-14 11:36:12.961824114 -0500
|
||
|
@@ -53,11 +53,7 @@ ha_callout(char *event, char *arg1, char
|
||
|
default: pid = waitpid(pid, &ret, 0);
|
||
|
}
|
||
|
sigaction(SIGCHLD, &oldact, &newact);
|
||
|
-#ifdef dprintf
|
||
|
- dprintf(N_DEBUG, "ha callout returned %d\n", WEXITSTATUS(ret));
|
||
|
-#else
|
||
|
xlog(D_GENERAL, "ha callout returned %d\n", WEXITSTATUS(ret));
|
||
|
-#endif
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
diff -up nfs-utils-1.2.1/support/include/nfsrpc.h.orig nfs-utils-1.2.1/support/include/nfsrpc.h
|
||
|
--- nfs-utils-1.2.1/support/include/nfsrpc.h.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/support/include/nfsrpc.h 2009-12-14 11:36:12.962825032 -0500
|
||
|
@@ -90,6 +90,18 @@ extern CLIENT *nfs_get_priv_rpcclient(
|
||
|
struct timeval *);
|
||
|
|
||
|
/*
|
||
|
+ * Convert a netid to a protocol number and protocol family
|
||
|
+ */
|
||
|
+extern int nfs_get_proto(const char *netid, sa_family_t *family,
|
||
|
+ unsigned long *protocol);
|
||
|
+
|
||
|
+/*
|
||
|
+ * Convert a protocol family and protocol name to a netid
|
||
|
+ */
|
||
|
+extern char *nfs_get_netid(const sa_family_t family,
|
||
|
+ const unsigned long protocol);
|
||
|
+
|
||
|
+/*
|
||
|
* Convert a socket address to a universal address
|
||
|
*/
|
||
|
extern char *nfs_sockaddr2universal(const struct sockaddr *);
|
||
|
diff -up nfs-utils-1.2.1/support/nfs/getport.c.orig nfs-utils-1.2.1/support/nfs/getport.c
|
||
|
--- nfs-utils-1.2.1/support/nfs/getport.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/support/nfs/getport.c 2009-12-14 11:36:12.962825032 -0500
|
||
|
@@ -199,7 +199,63 @@ static CLIENT *nfs_gp_get_rpcbclient(str
|
||
|
return clnt;
|
||
|
}
|
||
|
|
||
|
-/*
|
||
|
+/**
|
||
|
+ * nfs_get_proto - Convert a netid to an address family and protocol number
|
||
|
+ * @netid: C string containing a netid
|
||
|
+ * @family: OUT: address family
|
||
|
+ * @protocol: OUT: protocol number
|
||
|
+ *
|
||
|
+ * Returns 1 and fills in @protocol if the netid was recognized;
|
||
|
+ * otherwise zero is returned.
|
||
|
+ */
|
||
|
+#ifdef HAVE_LIBTIRPC
|
||
|
+int
|
||
|
+nfs_get_proto(const char *netid, sa_family_t *family, unsigned long *protocol)
|
||
|
+{
|
||
|
+ struct netconfig *nconf;
|
||
|
+ struct protoent *proto;
|
||
|
+
|
||
|
+ nconf = getnetconfigent(netid);
|
||
|
+ if (nconf == NULL)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ proto = getprotobyname(nconf->nc_proto);
|
||
|
+ if (proto == NULL) {
|
||
|
+ freenetconfigent(nconf);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+
|
||
|
+ *family = AF_UNSPEC;
|
||
|
+ if (strcmp(nconf->nc_protofmly, NC_INET) == 0)
|
||
|
+ *family = AF_INET;
|
||
|
+ if (strcmp(nconf->nc_protofmly, NC_INET6) == 0)
|
||
|
+ *family = AF_INET6;
|
||
|
+ freenetconfigent(nconf);
|
||
|
+
|
||
|
+ *protocol = (unsigned long)proto->p_proto;
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+#else /* !HAVE_LIBTIRPC */
|
||
|
+int
|
||
|
+nfs_get_proto(const char *netid, sa_family_t *family, unsigned long *protocol)
|
||
|
+{
|
||
|
+ struct protoent *proto;
|
||
|
+
|
||
|
+ proto = getprotobyname(netid);
|
||
|
+ if (proto == NULL)
|
||
|
+ return 0;
|
||
|
+
|
||
|
+ *family = AF_INET;
|
||
|
+ *protocol = (unsigned long)proto->p_proto;
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+#endif /* !HAVE_LIBTIRPC */
|
||
|
+
|
||
|
+/**
|
||
|
+ * nfs_get_netid - Convert a protocol family and protocol name to a netid
|
||
|
+ * @family: protocol family
|
||
|
+ * @protocol: protocol number
|
||
|
+ *
|
||
|
* One of the arguments passed when querying remote rpcbind services
|
||
|
* via rpcbind v3 or v4 is a netid string. This replaces the pm_prot
|
||
|
* field used in legacy PMAP_GETPORT calls.
|
||
|
@@ -213,13 +269,12 @@ static CLIENT *nfs_gp_get_rpcbclient(str
|
||
|
* first entry that matches @family and @protocol and whose netid string
|
||
|
* fits in the provided buffer.
|
||
|
*
|
||
|
- * Returns a '\0'-terminated string if successful; otherwise NULL.
|
||
|
+ * Returns a '\0'-terminated string if successful. Caller must
|
||
|
+ * free the returned string. Otherwise NULL is returned, and
|
||
|
* rpc_createerr.cf_stat is set to reflect the error.
|
||
|
*/
|
||
|
#ifdef HAVE_LIBTIRPC
|
||
|
-
|
||
|
-static char *nfs_gp_get_netid(const sa_family_t family,
|
||
|
- const unsigned short protocol)
|
||
|
+char *nfs_get_netid(const sa_family_t family, const unsigned long protocol)
|
||
|
{
|
||
|
char *nc_protofmly, *nc_proto, *nc_netid;
|
||
|
struct netconfig *nconf;
|
||
|
@@ -255,6 +310,9 @@ static char *nfs_gp_get_netid(const sa_f
|
||
|
|
||
|
nc_netid = strdup(nconf->nc_netid);
|
||
|
endnetconfig(handle);
|
||
|
+
|
||
|
+ if (nc_netid == NULL)
|
||
|
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||
|
return nc_netid;
|
||
|
}
|
||
|
endnetconfig(handle);
|
||
|
@@ -263,8 +321,28 @@ out:
|
||
|
rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
|
||
|
return NULL;
|
||
|
}
|
||
|
+#else /* !HAVE_LIBTIRPC */
|
||
|
+char *nfs_get_netid(const sa_family_t family, const unsigned long protocol)
|
||
|
+{
|
||
|
+ struct protoent *proto;
|
||
|
+ char *netid;
|
||
|
|
||
|
-#endif /* HAVE_LIBTIRPC */
|
||
|
+ if (family != AF_INET)
|
||
|
+ goto out;
|
||
|
+ proto = getprotobynumber((int)protocol);
|
||
|
+ if (proto == NULL)
|
||
|
+ goto out;
|
||
|
+
|
||
|
+ netid = strdup(proto->p_name);
|
||
|
+ if (netid == NULL)
|
||
|
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||
|
+ return netid;
|
||
|
+
|
||
|
+out:
|
||
|
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+#endif /* !HAVE_LIBTIRPC */
|
||
|
|
||
|
/*
|
||
|
* Extract a port number from a universal address, and terminate the
|
||
|
@@ -421,7 +499,7 @@ static int nfs_gp_init_rpcb_parms(const
|
||
|
{
|
||
|
char *netid, *addr;
|
||
|
|
||
|
- netid = nfs_gp_get_netid(sap->sa_family, protocol);
|
||
|
+ netid = nfs_get_netid(sap->sa_family, protocol);
|
||
|
if (netid == NULL)
|
||
|
return 0;
|
||
|
|
||
|
diff -up nfs-utils-1.2.1/utils/gssd/gssd.c.orig nfs-utils-1.2.1/utils/gssd/gssd.c
|
||
|
--- nfs-utils-1.2.1/utils/gssd/gssd.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/gssd/gssd.c 2009-12-14 11:36:12.963824196 -0500
|
||
|
@@ -56,7 +56,6 @@
|
||
|
#include "krb5_util.h"
|
||
|
|
||
|
char pipefs_dir[PATH_MAX] = GSSD_PIPEFS_DIR;
|
||
|
-char pipefs_nfsdir[PATH_MAX] = GSSD_PIPEFS_DIR;
|
||
|
char keytabfile[PATH_MAX] = GSSD_DEFAULT_KEYTAB_FILE;
|
||
|
char ccachedir[PATH_MAX] = GSSD_DEFAULT_CRED_DIR;
|
||
|
char *ccachesearch[GSSD_MAX_CCACHE_SEARCH + 1];
|
||
|
@@ -159,11 +158,6 @@ main(int argc, char *argv[])
|
||
|
if (preferred_realm == NULL)
|
||
|
gssd_k5_get_default_realm(&preferred_realm);
|
||
|
|
||
|
- snprintf(pipefs_nfsdir, sizeof(pipefs_nfsdir), "%s/%s",
|
||
|
- pipefs_dir, GSSD_SERVICE_NAME);
|
||
|
- if (pipefs_nfsdir[sizeof(pipefs_nfsdir)-1] != '\0')
|
||
|
- errx(1, "pipefs_nfsdir path name too long");
|
||
|
-
|
||
|
if ((progname = strrchr(argv[0], '/')))
|
||
|
progname++;
|
||
|
else
|
||
|
diff -up nfs-utils-1.2.1/utils/gssd/gssd.h.orig nfs-utils-1.2.1/utils/gssd/gssd.h
|
||
|
--- nfs-utils-1.2.1/utils/gssd/gssd.h.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/gssd/gssd.h 2009-12-14 11:36:12.963824196 -0500
|
||
|
@@ -60,7 +60,6 @@ enum {AUTHTYPE_KRB5, AUTHTYPE_SPKM3, AUT
|
||
|
|
||
|
|
||
|
extern char pipefs_dir[PATH_MAX];
|
||
|
-extern char pipefs_nfsdir[PATH_MAX];
|
||
|
extern char keytabfile[PATH_MAX];
|
||
|
extern char *ccachesearch[];
|
||
|
extern int use_memcache;
|
||
|
@@ -83,13 +82,24 @@ struct clnt_info {
|
||
|
int krb5_poll_index;
|
||
|
int spkm3_fd;
|
||
|
int spkm3_poll_index;
|
||
|
+ int gssd_fd;
|
||
|
+ int gssd_poll_index;
|
||
|
struct sockaddr_storage addr;
|
||
|
};
|
||
|
|
||
|
+TAILQ_HEAD(topdirs_list_head, topdirs_info) topdirs_list;
|
||
|
+
|
||
|
+struct topdirs_info {
|
||
|
+ TAILQ_ENTRY(topdirs_info) list;
|
||
|
+ char *dirname;
|
||
|
+ int fd;
|
||
|
+};
|
||
|
+
|
||
|
void init_client_list(void);
|
||
|
int update_client_list(void);
|
||
|
void handle_krb5_upcall(struct clnt_info *clp);
|
||
|
void handle_spkm3_upcall(struct clnt_info *clp);
|
||
|
+void handle_gssd_upcall(struct clnt_info *clp);
|
||
|
int gssd_acquire_cred(char *server_name);
|
||
|
void gssd_run(void);
|
||
|
|
||
|
diff -up nfs-utils-1.2.1/utils/gssd/gssd_main_loop.c.orig nfs-utils-1.2.1/utils/gssd/gssd_main_loop.c
|
||
|
--- nfs-utils-1.2.1/utils/gssd/gssd_main_loop.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/gssd/gssd_main_loop.c 2009-12-14 11:36:12.963824196 -0500
|
||
|
@@ -49,6 +49,7 @@
|
||
|
#include <fcntl.h>
|
||
|
#include <signal.h>
|
||
|
#include <unistd.h>
|
||
|
+#include <dirent.h>
|
||
|
|
||
|
#include "gssd.h"
|
||
|
#include "err_util.h"
|
||
|
@@ -73,6 +74,17 @@ scan_poll_results(int ret)
|
||
|
|
||
|
for (clp = clnt_list.tqh_first; clp != NULL; clp = clp->list.tqe_next)
|
||
|
{
|
||
|
+ i = clp->gssd_poll_index;
|
||
|
+ if (i >= 0 && pollarray[i].revents) {
|
||
|
+ if (pollarray[i].revents & POLLHUP)
|
||
|
+ dir_changed = 1;
|
||
|
+ if (pollarray[i].revents & POLLIN)
|
||
|
+ handle_gssd_upcall(clp);
|
||
|
+ pollarray[clp->gssd_poll_index].revents = 0;
|
||
|
+ ret--;
|
||
|
+ if (!ret)
|
||
|
+ break;
|
||
|
+ }
|
||
|
i = clp->krb5_poll_index;
|
||
|
if (i >= 0 && pollarray[i].revents) {
|
||
|
if (pollarray[i].revents & POLLHUP)
|
||
|
@@ -98,12 +110,85 @@ scan_poll_results(int ret)
|
||
|
}
|
||
|
};
|
||
|
|
||
|
+static int
|
||
|
+topdirs_add_entry(struct dirent *dent)
|
||
|
+{
|
||
|
+ struct topdirs_info *tdi;
|
||
|
+
|
||
|
+ tdi = calloc(sizeof(struct topdirs_info), 1);
|
||
|
+ if (tdi == NULL) {
|
||
|
+ printerr(0, "ERROR: Couldn't allocate struct topdirs_info\n");
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+ tdi->dirname = malloc(PATH_MAX);
|
||
|
+ if (tdi->dirname == NULL) {
|
||
|
+ printerr(0, "ERROR: Couldn't allocate directory name\n");
|
||
|
+ free(tdi);
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+ snprintf(tdi->dirname, PATH_MAX, "%s/%s", pipefs_dir, dent->d_name);
|
||
|
+ tdi->fd = open(tdi->dirname, O_RDONLY);
|
||
|
+ if (tdi->fd != -1) {
|
||
|
+ fcntl(tdi->fd, F_SETSIG, DNOTIFY_SIGNAL);
|
||
|
+ fcntl(tdi->fd, F_NOTIFY,
|
||
|
+ DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT);
|
||
|
+ }
|
||
|
+
|
||
|
+ TAILQ_INSERT_HEAD(&topdirs_list, tdi, list);
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+topdirs_free_list(void)
|
||
|
+{
|
||
|
+ struct topdirs_info *tdi;
|
||
|
+
|
||
|
+ TAILQ_FOREACH(tdi, &topdirs_list, list) {
|
||
|
+ free(tdi->dirname);
|
||
|
+ if (tdi->fd != -1)
|
||
|
+ close(tdi->fd);
|
||
|
+ TAILQ_REMOVE(&topdirs_list, tdi, list);
|
||
|
+ free(tdi);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+topdirs_init_list(void)
|
||
|
+{
|
||
|
+ DIR *pipedir;
|
||
|
+ struct dirent *dent;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ TAILQ_INIT(&topdirs_list);
|
||
|
+
|
||
|
+ pipedir = opendir(pipefs_dir);
|
||
|
+ if (pipedir == NULL) {
|
||
|
+ printerr(0, "ERROR: could not open rpc_pipefs directory '%s': "
|
||
|
+ "%s\n", pipefs_dir, strerror(errno));
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+ for (dent = readdir(pipedir); dent != NULL; dent = readdir(pipedir)) {
|
||
|
+ if (dent->d_type != DT_DIR ||
|
||
|
+ strcmp(dent->d_name, ".") == 0 ||
|
||
|
+ strcmp(dent->d_name, "..") == 0) {
|
||
|
+ continue;
|
||
|
+ }
|
||
|
+ ret = topdirs_add_entry(dent);
|
||
|
+ if (ret)
|
||
|
+ goto out_err;
|
||
|
+ }
|
||
|
+ closedir(pipedir);
|
||
|
+ return 0;
|
||
|
+out_err:
|
||
|
+ topdirs_free_list();
|
||
|
+ return -1;
|
||
|
+}
|
||
|
+
|
||
|
void
|
||
|
gssd_run()
|
||
|
{
|
||
|
int ret;
|
||
|
struct sigaction dn_act;
|
||
|
- int fd;
|
||
|
sigset_t set;
|
||
|
|
||
|
/* Taken from linux/Documentation/dnotify.txt: */
|
||
|
@@ -117,13 +202,8 @@ gssd_run()
|
||
|
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));
|
||
|
- exit(1);
|
||
|
- }
|
||
|
- fcntl(fd, F_SETSIG, DNOTIFY_SIGNAL);
|
||
|
- fcntl(fd, F_NOTIFY, DN_CREATE|DN_DELETE|DN_MODIFY|DN_MULTISHOT);
|
||
|
+ if (topdirs_init_list() != 0)
|
||
|
+ return;
|
||
|
|
||
|
init_client_list();
|
||
|
|
||
|
@@ -132,8 +212,7 @@ gssd_run()
|
||
|
while (dir_changed) {
|
||
|
dir_changed = 0;
|
||
|
if (update_client_list()) {
|
||
|
- printerr(0, "ERROR: couldn't update "
|
||
|
- "client list\n");
|
||
|
+ /* Error msg is already printed */
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
@@ -151,6 +230,7 @@ gssd_run()
|
||
|
scan_poll_results(ret);
|
||
|
}
|
||
|
}
|
||
|
- close(fd);
|
||
|
+ topdirs_free_list();
|
||
|
+
|
||
|
return;
|
||
|
}
|
||
|
diff -up nfs-utils-1.2.1/utils/gssd/gssd_proc.c.orig nfs-utils-1.2.1/utils/gssd/gssd_proc.c
|
||
|
--- nfs-utils-1.2.1/utils/gssd/gssd_proc.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/gssd/gssd_proc.c 2009-12-14 11:36:12.964824203 -0500
|
||
|
@@ -73,6 +73,7 @@
|
||
|
#include "krb5_util.h"
|
||
|
#include "context.h"
|
||
|
#include "nfsrpc.h"
|
||
|
+#include "nfslib.h"
|
||
|
|
||
|
/*
|
||
|
* pollarray:
|
||
|
@@ -83,20 +84,22 @@
|
||
|
* linked list of struct clnt_info which associates a clntXXX directory
|
||
|
* with an index into pollarray[], and other basic data about that client.
|
||
|
*
|
||
|
- * Directory structure: created by the kernel nfs client
|
||
|
- * {pipefs_nfsdir}/clntXX : one per rpc_clnt struct in the kernel
|
||
|
- * {pipefs_nfsdir}/clntXX/krb5 : read uid for which kernel wants
|
||
|
+ * Directory structure: created by the kernel
|
||
|
+ * {rpc_pipefs}/{dir}/clntXX : one per rpc_clnt struct in the kernel
|
||
|
+ * {rpc_pipefs}/{dir}/clntXX/krb5 : read uid for which kernel wants
|
||
|
* a context, write the resulting context
|
||
|
- * {pipefs_nfsdir}/clntXX/info : stores info such as server name
|
||
|
+ * {rpc_pipefs}/{dir}/clntXX/info : stores info such as server name
|
||
|
+ * {rpc_pipefs}/{dir}/clntXX/gssd : pipe for all gss mechanisms using
|
||
|
+ * a text-based string of parameters
|
||
|
*
|
||
|
* Algorithm:
|
||
|
- * Poll all {pipefs_nfsdir}/clntXX/krb5 files. When ready, data read
|
||
|
- * is a uid; performs rpcsec_gss context initialization protocol to
|
||
|
+ * Poll all {rpc_pipefs}/{dir}/clntXX/YYYY files. When data is ready,
|
||
|
+ * read and process; performs rpcsec_gss context initialization protocol to
|
||
|
* get a cred for that user. Writes result to corresponding krb5 file
|
||
|
* in a form the kernel code will understand.
|
||
|
* In addition, we make sure we are notified whenever anything is
|
||
|
- * created or destroyed in {pipefs_nfsdir} or in an of the clntXX directories,
|
||
|
- * and rescan the whole {pipefs_nfsdir} when this happens.
|
||
|
+ * created or destroyed in {rpc_pipefs} or in any of the clntXX directories,
|
||
|
+ * and rescan the whole {rpc_pipefs} when this happens.
|
||
|
*/
|
||
|
|
||
|
struct pollfd * pollarray;
|
||
|
@@ -105,7 +108,7 @@ int pollsize; /* the size of pollaray (
|
||
|
|
||
|
/*
|
||
|
* convert a presentation address string to a sockaddr_storage struct. Returns
|
||
|
- * true on success and false on failure.
|
||
|
+ * true on success or false on failure.
|
||
|
*
|
||
|
* Note that we do not populate the sin6_scope_id field here for IPv6 addrs.
|
||
|
* gssd nececessarily relies on hostname resolution and DNS AAAA records
|
||
|
@@ -117,26 +120,43 @@ int pollsize; /* the size of pollaray (
|
||
|
* not really feasible at present.
|
||
|
*/
|
||
|
static int
|
||
|
-addrstr_to_sockaddr(struct sockaddr *sa, const char *addr, const int port)
|
||
|
+addrstr_to_sockaddr(struct sockaddr *sa, const char *node, const char *port)
|
||
|
{
|
||
|
- struct sockaddr_in *s4 = (struct sockaddr_in *) sa;
|
||
|
-#ifdef IPV6_SUPPORTED
|
||
|
- struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sa;
|
||
|
-#endif /* IPV6_SUPPORTED */
|
||
|
+ int rc;
|
||
|
+ struct addrinfo *res;
|
||
|
+ struct addrinfo hints = { .ai_flags = AI_NUMERICHOST | AI_NUMERICSERV };
|
||
|
|
||
|
- if (inet_pton(AF_INET, addr, &s4->sin_addr)) {
|
||
|
- s4->sin_family = AF_INET;
|
||
|
- s4->sin_port = htons(port);
|
||
|
-#ifdef IPV6_SUPPORTED
|
||
|
- } else if (inet_pton(AF_INET6, addr, &s6->sin6_addr)) {
|
||
|
- s6->sin6_family = AF_INET6;
|
||
|
- s6->sin6_port = htons(port);
|
||
|
+#ifndef IPV6_SUPPORTED
|
||
|
+ hints.ai_family = AF_INET;
|
||
|
#endif /* IPV6_SUPPORTED */
|
||
|
- } else {
|
||
|
- printerr(0, "ERROR: unable to convert %s to address\n", addr);
|
||
|
+
|
||
|
+ rc = getaddrinfo(node, port, &hints, &res);
|
||
|
+ if (rc) {
|
||
|
+ printerr(0, "ERROR: unable to convert %s|%s to sockaddr: %s\n",
|
||
|
+ node, port, rc == EAI_SYSTEM ? strerror(errno) :
|
||
|
+ gai_strerror(rc));
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+#ifdef IPV6_SUPPORTED
|
||
|
+ /*
|
||
|
+ * getnameinfo ignores the scopeid. If the address turns out to have
|
||
|
+ * a non-zero scopeid, we can't use it -- the resolved host might be
|
||
|
+ * completely different from the one intended.
|
||
|
+ */
|
||
|
+ if (res->ai_addr->sa_family == AF_INET6) {
|
||
|
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)res->ai_addr;
|
||
|
+ if (sin6->sin6_scope_id) {
|
||
|
+ printerr(0, "ERROR: address %s has non-zero "
|
||
|
+ "sin6_scope_id!\n", node);
|
||
|
+ freeaddrinfo(res);
|
||
|
+ return 0;
|
||
|
+ }
|
||
|
+ }
|
||
|
+#endif /* IPV6_SUPPORTED */
|
||
|
+
|
||
|
+ memcpy(sa, res->ai_addr, res->ai_addrlen);
|
||
|
+ freeaddrinfo(res);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
@@ -194,11 +214,10 @@ read_service_info(char *info_file_name,
|
||
|
char program[16];
|
||
|
char version[16];
|
||
|
char protoname[16];
|
||
|
- char cb_port[128];
|
||
|
+ char port[128];
|
||
|
char *p;
|
||
|
int fd = -1;
|
||
|
int numfields;
|
||
|
- int port = 0;
|
||
|
|
||
|
*servicename = *servername = *protocol = NULL;
|
||
|
|
||
|
@@ -227,20 +246,22 @@ read_service_info(char *info_file_name,
|
||
|
goto fail;
|
||
|
}
|
||
|
|
||
|
- cb_port[0] = '\0';
|
||
|
+ port[0] = '\0';
|
||
|
if ((p = strstr(buf, "port")) != NULL)
|
||
|
- sscanf(p, "port: %127s\n", cb_port);
|
||
|
+ sscanf(p, "port: %127s\n", port);
|
||
|
|
||
|
/* check service, program, and version */
|
||
|
- if(memcmp(service, "nfs", 3)) return -1;
|
||
|
+ if (memcmp(service, "nfs", 3) != 0)
|
||
|
+ return -1;
|
||
|
*prog = atoi(program + 1); /* skip open paren */
|
||
|
*vers = atoi(version);
|
||
|
- if((*prog != 100003) || ((*vers != 2) && (*vers != 3) && (*vers != 4)))
|
||
|
- goto fail;
|
||
|
|
||
|
- if (cb_port[0] != '\0') {
|
||
|
- port = atoi(cb_port);
|
||
|
- if (port < 0 || port > 65535)
|
||
|
+ if (strlen(service) == 3 ) {
|
||
|
+ if ((*prog != 100003) || ((*vers != 2) && (*vers != 3) &&
|
||
|
+ (*vers != 4)))
|
||
|
+ goto fail;
|
||
|
+ } else if (memcmp(service, "nfs4_cb", 7) == 0) {
|
||
|
+ if (*vers != 1)
|
||
|
goto fail;
|
||
|
}
|
||
|
|
||
|
@@ -281,9 +302,13 @@ destroy_client(struct clnt_info *clp)
|
||
|
if (clp->spkm3_poll_index != -1)
|
||
|
memset(&pollarray[clp->spkm3_poll_index], 0,
|
||
|
sizeof(struct pollfd));
|
||
|
+ if (clp->gssd_poll_index != -1)
|
||
|
+ memset(&pollarray[clp->gssd_poll_index], 0,
|
||
|
+ sizeof(struct pollfd));
|
||
|
if (clp->dir_fd != -1) close(clp->dir_fd);
|
||
|
if (clp->krb5_fd != -1) close(clp->krb5_fd);
|
||
|
if (clp->spkm3_fd != -1) close(clp->spkm3_fd);
|
||
|
+ if (clp->gssd_fd != -1) close(clp->gssd_fd);
|
||
|
free(clp->dirname);
|
||
|
free(clp->servicename);
|
||
|
free(clp->servername);
|
||
|
@@ -303,8 +328,10 @@ insert_new_clnt(void)
|
||
|
}
|
||
|
clp->krb5_poll_index = -1;
|
||
|
clp->spkm3_poll_index = -1;
|
||
|
+ clp->gssd_poll_index = -1;
|
||
|
clp->krb5_fd = -1;
|
||
|
clp->spkm3_fd = -1;
|
||
|
+ clp->gssd_fd = -1;
|
||
|
clp->dir_fd = -1;
|
||
|
|
||
|
TAILQ_INSERT_HEAD(&clnt_list, clp, list);
|
||
|
@@ -315,19 +342,43 @@ out:
|
||
|
static int
|
||
|
process_clnt_dir_files(struct clnt_info * clp)
|
||
|
{
|
||
|
- char kname[32];
|
||
|
- char sname[32];
|
||
|
- char info_file_name[32];
|
||
|
-
|
||
|
- if (clp->krb5_fd == -1) {
|
||
|
- snprintf(kname, sizeof(kname), "%s/krb5", clp->dirname);
|
||
|
- clp->krb5_fd = open(kname, O_RDWR);
|
||
|
- }
|
||
|
- if (clp->spkm3_fd == -1) {
|
||
|
- snprintf(sname, sizeof(sname), "%s/spkm3", clp->dirname);
|
||
|
- clp->spkm3_fd = open(sname, O_RDWR);
|
||
|
+ char name[PATH_MAX];
|
||
|
+ char gname[PATH_MAX];
|
||
|
+ char info_file_name[PATH_MAX];
|
||
|
+
|
||
|
+ if (clp->gssd_fd == -1) {
|
||
|
+ snprintf(gname, sizeof(gname), "%s/gssd", clp->dirname);
|
||
|
+ clp->gssd_fd = open(gname, O_RDWR);
|
||
|
+ }
|
||
|
+ if (clp->gssd_fd == -1) {
|
||
|
+ if (clp->krb5_fd == -1) {
|
||
|
+ snprintf(name, sizeof(name), "%s/krb5", clp->dirname);
|
||
|
+ clp->krb5_fd = open(name, O_RDWR);
|
||
|
+ }
|
||
|
+ if (clp->spkm3_fd == -1) {
|
||
|
+ snprintf(name, sizeof(name), "%s/spkm3", clp->dirname);
|
||
|
+ clp->spkm3_fd = open(name, O_RDWR);
|
||
|
+ }
|
||
|
+
|
||
|
+ /* If we opened a gss-specific pipe, let's try opening
|
||
|
+ * the new upcall pipe again. If we succeed, close
|
||
|
+ * gss-specific pipe(s).
|
||
|
+ */
|
||
|
+ if (clp->krb5_fd != -1 || clp->spkm3_fd != -1) {
|
||
|
+ clp->gssd_fd = open(gname, O_RDWR);
|
||
|
+ if (clp->gssd_fd != -1) {
|
||
|
+ if (clp->krb5_fd != -1)
|
||
|
+ close(clp->krb5_fd);
|
||
|
+ clp->krb5_fd = -1;
|
||
|
+ if (clp->spkm3_fd != -1)
|
||
|
+ close(clp->spkm3_fd);
|
||
|
+ clp->spkm3_fd = -1;
|
||
|
+ }
|
||
|
+ }
|
||
|
}
|
||
|
- if((clp->krb5_fd == -1) && (clp->spkm3_fd == -1))
|
||
|
+
|
||
|
+ if ((clp->krb5_fd == -1) && (clp->spkm3_fd == -1) &&
|
||
|
+ (clp->gssd_fd == -1))
|
||
|
return -1;
|
||
|
snprintf(info_file_name, sizeof(info_file_name), "%s/info",
|
||
|
clp->dirname);
|
||
|
@@ -362,6 +413,15 @@ get_poll_index(int *ind)
|
||
|
static int
|
||
|
insert_clnt_poll(struct clnt_info *clp)
|
||
|
{
|
||
|
+ if ((clp->gssd_fd != -1) && (clp->gssd_poll_index == -1)) {
|
||
|
+ if (get_poll_index(&clp->gssd_poll_index)) {
|
||
|
+ printerr(0, "ERROR: Too many gssd clients\n");
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+ pollarray[clp->gssd_poll_index].fd = clp->gssd_fd;
|
||
|
+ pollarray[clp->gssd_poll_index].events |= POLLIN;
|
||
|
+ }
|
||
|
+
|
||
|
if ((clp->krb5_fd != -1) && (clp->krb5_poll_index == -1)) {
|
||
|
if (get_poll_index(&clp->krb5_poll_index)) {
|
||
|
printerr(0, "ERROR: Too many krb5 clients\n");
|
||
|
@@ -384,17 +444,18 @@ insert_clnt_poll(struct clnt_info *clp)
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
-process_clnt_dir(char *dir)
|
||
|
+process_clnt_dir(char *dir, char *pdir)
|
||
|
{
|
||
|
struct clnt_info * clp;
|
||
|
|
||
|
if (!(clp = insert_new_clnt()))
|
||
|
goto fail_destroy_client;
|
||
|
|
||
|
- if (!(clp->dirname = calloc(strlen(dir) + 1, 1))) {
|
||
|
+ /* An extra for the '/', and an extra for the null */
|
||
|
+ if (!(clp->dirname = calloc(strlen(dir) + strlen(pdir) + 2, 1))) {
|
||
|
goto fail_destroy_client;
|
||
|
}
|
||
|
- memcpy(clp->dirname, dir, strlen(dir));
|
||
|
+ sprintf(clp->dirname, "%s/%s", pdir, dir);
|
||
|
if ((clp->dir_fd = open(clp->dirname, O_RDONLY)) == -1) {
|
||
|
printerr(0, "ERROR: can't open %s: %s\n",
|
||
|
clp->dirname, strerror(errno));
|
||
|
@@ -438,16 +499,24 @@ init_client_list(void)
|
||
|
* directories, since the DNOTIFY could have been in there.
|
||
|
*/
|
||
|
static void
|
||
|
-update_old_clients(struct dirent **namelist, int size)
|
||
|
+update_old_clients(struct dirent **namelist, int size, char *pdir)
|
||
|
{
|
||
|
struct clnt_info *clp;
|
||
|
void *saveprev;
|
||
|
int i, stillhere;
|
||
|
+ char fname[PATH_MAX];
|
||
|
|
||
|
for (clp = clnt_list.tqh_first; clp != NULL; clp = clp->list.tqe_next) {
|
||
|
+ /* only compare entries in the global list that are from the
|
||
|
+ * same pipefs parent directory as "pdir"
|
||
|
+ */
|
||
|
+ if (strncmp(clp->dirname, pdir, strlen(pdir)) != 0) continue;
|
||
|
+
|
||
|
stillhere = 0;
|
||
|
for (i=0; i < size; i++) {
|
||
|
- if (!strcmp(clp->dirname, namelist[i]->d_name)) {
|
||
|
+ snprintf(fname, sizeof(fname), "%s/%s",
|
||
|
+ pdir, namelist[i]->d_name);
|
||
|
+ if (strcmp(clp->dirname, fname) == 0) {
|
||
|
stillhere = 1;
|
||
|
break;
|
||
|
}
|
||
|
@@ -468,48 +537,69 @@ update_old_clients(struct dirent **namel
|
||
|
|
||
|
/* Search for a client by directory name, return 1 if found, 0 otherwise */
|
||
|
static int
|
||
|
-find_client(char *dirname)
|
||
|
+find_client(char *dirname, char *pdir)
|
||
|
{
|
||
|
struct clnt_info *clp;
|
||
|
+ char fname[PATH_MAX];
|
||
|
|
||
|
- for (clp = clnt_list.tqh_first; clp != NULL; clp = clp->list.tqe_next)
|
||
|
- if (!strcmp(clp->dirname, dirname))
|
||
|
+ for (clp = clnt_list.tqh_first; clp != NULL; clp = clp->list.tqe_next) {
|
||
|
+ snprintf(fname, sizeof(fname), "%s/%s", pdir, dirname);
|
||
|
+ if (strcmp(clp->dirname, fname) == 0)
|
||
|
return 1;
|
||
|
+ }
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
-/* Used to read (and re-read) list of clients, set up poll array. */
|
||
|
-int
|
||
|
-update_client_list(void)
|
||
|
+static int
|
||
|
+process_pipedir(char *pipe_name)
|
||
|
{
|
||
|
struct dirent **namelist;
|
||
|
int i, j;
|
||
|
|
||
|
- if (chdir(pipefs_nfsdir) < 0) {
|
||
|
+ if (chdir(pipe_name) < 0) {
|
||
|
printerr(0, "ERROR: can't chdir to %s: %s\n",
|
||
|
- pipefs_nfsdir, strerror(errno));
|
||
|
+ pipe_name, strerror(errno));
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
- j = scandir(pipefs_nfsdir, &namelist, NULL, alphasort);
|
||
|
+ j = scandir(pipe_name, &namelist, NULL, alphasort);
|
||
|
if (j < 0) {
|
||
|
printerr(0, "ERROR: can't scandir %s: %s\n",
|
||
|
- pipefs_nfsdir, strerror(errno));
|
||
|
+ pipe_name, strerror(errno));
|
||
|
return -1;
|
||
|
}
|
||
|
- update_old_clients(namelist, j);
|
||
|
+
|
||
|
+ update_old_clients(namelist, j, pipe_name);
|
||
|
for (i=0; i < j; i++) {
|
||
|
if (i < FD_ALLOC_BLOCK
|
||
|
&& !strncmp(namelist[i]->d_name, "clnt", 4)
|
||
|
- && !find_client(namelist[i]->d_name))
|
||
|
- process_clnt_dir(namelist[i]->d_name);
|
||
|
+ && !find_client(namelist[i]->d_name, pipe_name))
|
||
|
+ process_clnt_dir(namelist[i]->d_name, pipe_name);
|
||
|
free(namelist[i]);
|
||
|
}
|
||
|
|
||
|
free(namelist);
|
||
|
+
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+/* Used to read (and re-read) list of clients, set up poll array. */
|
||
|
+int
|
||
|
+update_client_list(void)
|
||
|
+{
|
||
|
+ int retval = -1;
|
||
|
+ struct topdirs_info *tdi;
|
||
|
+
|
||
|
+ TAILQ_FOREACH(tdi, &topdirs_list, list) {
|
||
|
+ retval = process_pipedir(tdi->dirname);
|
||
|
+ if (retval)
|
||
|
+ printerr(1, "WARNING: error processing %s\n",
|
||
|
+ tdi->dirname);
|
||
|
+
|
||
|
+ }
|
||
|
+ return retval;
|
||
|
+}
|
||
|
+
|
||
|
static int
|
||
|
do_downcall(int k5_fd, uid_t uid, struct authgss_private_data *pd,
|
||
|
gss_buffer_desc *context_token)
|
||
|
@@ -798,15 +888,14 @@ int create_auth_rpc_client(struct clnt_i
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
-
|
||
|
/*
|
||
|
* this code uses the userland rpcsec gss library to create a krb5
|
||
|
* context on behalf of the kernel
|
||
|
*/
|
||
|
-void
|
||
|
-handle_krb5_upcall(struct clnt_info *clp)
|
||
|
+static void
|
||
|
+process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname,
|
||
|
+ char *service)
|
||
|
{
|
||
|
- uid_t uid;
|
||
|
CLIENT *rpc_clnt = NULL;
|
||
|
AUTH *auth = NULL;
|
||
|
struct authgss_private_data pd;
|
||
|
@@ -816,19 +905,43 @@ handle_krb5_upcall(struct clnt_info *clp
|
||
|
char **dirname;
|
||
|
int create_resp = -1;
|
||
|
|
||
|
- printerr(1, "handling krb5 upcall\n");
|
||
|
+ printerr(1, "handling krb5 upcall (%s)\n", clp->dirname);
|
||
|
|
||
|
+ if (tgtname) {
|
||
|
+ if (clp->servicename) {
|
||
|
+ free(clp->servicename);
|
||
|
+ clp->servicename = strdup(tgtname);
|
||
|
+ }
|
||
|
+ }
|
||
|
token.length = 0;
|
||
|
token.value = NULL;
|
||
|
memset(&pd, 0, sizeof(struct authgss_private_data));
|
||
|
|
||
|
- if (read(clp->krb5_fd, &uid, sizeof(uid)) < sizeof(uid)) {
|
||
|
- printerr(0, "WARNING: failed reading uid from krb5 "
|
||
|
- "upcall pipe: %s\n", strerror(errno));
|
||
|
- goto out;
|
||
|
- }
|
||
|
-
|
||
|
- if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0)) {
|
||
|
+ /*
|
||
|
+ * If "service" is specified, then the kernel is indicating that
|
||
|
+ * we must use machine credentials for this request. (Regardless
|
||
|
+ * of the uid value or the setting of root_uses_machine_creds.)
|
||
|
+ * If the service value is "*", then any service name can be used.
|
||
|
+ * Otherwise, it specifies the service name that should be used.
|
||
|
+ * (For now, the values of service will only be "*" or "nfs".)
|
||
|
+ *
|
||
|
+ * Restricting gssd to use "nfs" service name is needed for when
|
||
|
+ * the NFS server is doing a callback to the NFS client. In this
|
||
|
+ * case, the NFS server has to authenticate itself as "nfs" --
|
||
|
+ * even if there are other service keys such as "host" or "root"
|
||
|
+ * in the keytab.
|
||
|
+ *
|
||
|
+ * Another case when the kernel may specify the service attribute
|
||
|
+ * is when gssd is being asked to create the context for a
|
||
|
+ * SETCLIENT_ID operation. In this case, machine credentials
|
||
|
+ * must be used for the authentication. However, the service name
|
||
|
+ * used for this case is not important.
|
||
|
+ *
|
||
|
+ */
|
||
|
+ printerr(2, "%s: service is '%s'\n", __func__,
|
||
|
+ service ? service : "<null>");
|
||
|
+ if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0 &&
|
||
|
+ service == NULL)) {
|
||
|
/* Tell krb5 gss which credentials cache to use */
|
||
|
for (dirname = ccachesearch; *dirname != NULL; dirname++) {
|
||
|
if (gssd_setup_krb5_user_gss_ccache(uid, clp->servername, *dirname) == 0)
|
||
|
@@ -839,12 +952,13 @@ handle_krb5_upcall(struct clnt_info *clp
|
||
|
}
|
||
|
}
|
||
|
if (create_resp != 0) {
|
||
|
- if (uid == 0 && root_uses_machine_creds == 1) {
|
||
|
+ if (uid == 0 && (root_uses_machine_creds == 1 ||
|
||
|
+ service != NULL)) {
|
||
|
int nocache = 0;
|
||
|
int success = 0;
|
||
|
do {
|
||
|
gssd_refresh_krb5_machine_credential(clp->servername,
|
||
|
- NULL, nocache);
|
||
|
+ NULL, service);
|
||
|
/*
|
||
|
* Get a list of credential cache names and try each
|
||
|
* of them until one works or we've tried them all
|
||
|
@@ -904,7 +1018,7 @@ handle_krb5_upcall(struct clnt_info *clp
|
||
|
goto out_return_error;
|
||
|
}
|
||
|
|
||
|
- do_downcall(clp->krb5_fd, uid, &pd, &token);
|
||
|
+ do_downcall(fd, uid, &pd, &token);
|
||
|
|
||
|
out:
|
||
|
if (token.value)
|
||
|
@@ -920,7 +1034,7 @@ out:
|
||
|
return;
|
||
|
|
||
|
out_return_error:
|
||
|
- do_error_downcall(clp->krb5_fd, uid, -1);
|
||
|
+ do_error_downcall(fd, uid, -1);
|
||
|
goto out;
|
||
|
}
|
||
|
|
||
|
@@ -928,26 +1042,19 @@ out_return_error:
|
||
|
* this code uses the userland rpcsec gss library to create an spkm3
|
||
|
* context on behalf of the kernel
|
||
|
*/
|
||
|
-void
|
||
|
-handle_spkm3_upcall(struct clnt_info *clp)
|
||
|
+static void
|
||
|
+process_spkm3_upcall(struct clnt_info *clp, uid_t uid, int fd)
|
||
|
{
|
||
|
- uid_t uid;
|
||
|
CLIENT *rpc_clnt = NULL;
|
||
|
AUTH *auth = NULL;
|
||
|
struct authgss_private_data pd;
|
||
|
gss_buffer_desc token;
|
||
|
|
||
|
- printerr(2, "handling spkm3 upcall\n");
|
||
|
+ printerr(2, "handling spkm3 upcall (%s)\n", clp->dirname);
|
||
|
|
||
|
token.length = 0;
|
||
|
token.value = NULL;
|
||
|
|
||
|
- if (read(clp->spkm3_fd, &uid, sizeof(uid)) < sizeof(uid)) {
|
||
|
- printerr(0, "WARNING: failed reading uid from spkm3 "
|
||
|
- "upcall pipe: %s\n", strerror(errno));
|
||
|
- goto out;
|
||
|
- }
|
||
|
-
|
||
|
if (create_auth_rpc_client(clp, &rpc_clnt, &auth, uid, AUTHTYPE_SPKM3)) {
|
||
|
printerr(0, "WARNING: Failed to create spkm3 context for "
|
||
|
"user with uid %d\n", uid);
|
||
|
@@ -968,7 +1075,7 @@ handle_spkm3_upcall(struct clnt_info *cl
|
||
|
goto out_return_error;
|
||
|
}
|
||
|
|
||
|
- do_downcall(clp->spkm3_fd, uid, &pd, &token);
|
||
|
+ do_downcall(fd, uid, &pd, &token);
|
||
|
|
||
|
out:
|
||
|
if (token.value)
|
||
|
@@ -980,6 +1087,139 @@ out:
|
||
|
return;
|
||
|
|
||
|
out_return_error:
|
||
|
- do_error_downcall(clp->spkm3_fd, uid, -1);
|
||
|
+ do_error_downcall(fd, uid, -1);
|
||
|
goto out;
|
||
|
}
|
||
|
+
|
||
|
+void
|
||
|
+handle_krb5_upcall(struct clnt_info *clp)
|
||
|
+{
|
||
|
+ uid_t uid;
|
||
|
+
|
||
|
+ if (read(clp->krb5_fd, &uid, sizeof(uid)) < sizeof(uid)) {
|
||
|
+ printerr(0, "WARNING: failed reading uid from krb5 "
|
||
|
+ "upcall pipe: %s\n", strerror(errno));
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ return process_krb5_upcall(clp, uid, clp->krb5_fd, NULL, NULL);
|
||
|
+}
|
||
|
+
|
||
|
+void
|
||
|
+handle_spkm3_upcall(struct clnt_info *clp)
|
||
|
+{
|
||
|
+ uid_t uid;
|
||
|
+
|
||
|
+ if (read(clp->spkm3_fd, &uid, sizeof(uid)) < sizeof(uid)) {
|
||
|
+ printerr(0, "WARNING: failed reading uid from spkm3 "
|
||
|
+ "upcall pipe: %s\n", strerror(errno));
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ return process_spkm3_upcall(clp, uid, clp->spkm3_fd);
|
||
|
+}
|
||
|
+
|
||
|
+void
|
||
|
+handle_gssd_upcall(struct clnt_info *clp)
|
||
|
+{
|
||
|
+ uid_t uid;
|
||
|
+ char *lbuf = NULL;
|
||
|
+ int lbuflen = 0;
|
||
|
+ char *p;
|
||
|
+ char *mech = NULL;
|
||
|
+ char *target = NULL;
|
||
|
+ char *service = NULL;
|
||
|
+
|
||
|
+ printerr(1, "handling gssd upcall (%s)\n", clp->dirname);
|
||
|
+
|
||
|
+ if (readline(clp->gssd_fd, &lbuf, &lbuflen) != 1) {
|
||
|
+ printerr(0, "WARNING: handle_gssd_upcall: "
|
||
|
+ "failed reading request\n");
|
||
|
+ return;
|
||
|
+ }
|
||
|
+ printerr(2, "%s: '%s'\n", __func__, lbuf);
|
||
|
+
|
||
|
+ /* find the mechanism name */
|
||
|
+ if ((p = strstr(lbuf, "mech=")) != NULL) {
|
||
|
+ mech = malloc(lbuflen);
|
||
|
+ if (!mech)
|
||
|
+ goto out;
|
||
|
+ if (sscanf(p, "mech=%s", mech) != 1) {
|
||
|
+ printerr(0, "WARNING: handle_gssd_upcall: "
|
||
|
+ "failed to parse gss mechanism name "
|
||
|
+ "in upcall string '%s'\n", lbuf);
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+ } else {
|
||
|
+ printerr(0, "WARNING: handle_gssd_upcall: "
|
||
|
+ "failed to find gss mechanism name "
|
||
|
+ "in upcall string '%s'\n", lbuf);
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* read uid */
|
||
|
+ if ((p = strstr(lbuf, "uid=")) != NULL) {
|
||
|
+ if (sscanf(p, "uid=%d", &uid) != 1) {
|
||
|
+ printerr(0, "WARNING: handle_gssd_upcall: "
|
||
|
+ "failed to parse uid "
|
||
|
+ "in upcall string '%s'\n", lbuf);
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+ } else {
|
||
|
+ printerr(0, "WARNING: handle_gssd_upcall: "
|
||
|
+ "failed to find uid "
|
||
|
+ "in upcall string '%s'\n", lbuf);
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* read target name */
|
||
|
+ if ((p = strstr(lbuf, "target=")) != NULL) {
|
||
|
+ target = malloc(lbuflen);
|
||
|
+ if (!target)
|
||
|
+ goto out;
|
||
|
+ if (sscanf(p, "target=%s", target) != 1) {
|
||
|
+ printerr(0, "WARNING: handle_gssd_upcall: "
|
||
|
+ "failed to parse target name "
|
||
|
+ "in upcall string '%s'\n", lbuf);
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ /*
|
||
|
+ * read the service name
|
||
|
+ *
|
||
|
+ * The presence of attribute "service=" indicates that machine
|
||
|
+ * credentials should be used for this request. If the value
|
||
|
+ * is "*", then any machine credentials available can be used.
|
||
|
+ * If the value is anything else, then machine credentials for
|
||
|
+ * the specified service name (always "nfs" for now) should be
|
||
|
+ * used.
|
||
|
+ */
|
||
|
+ if ((p = strstr(lbuf, "service=")) != NULL) {
|
||
|
+ service = malloc(lbuflen);
|
||
|
+ if (!service)
|
||
|
+ goto out;
|
||
|
+ if (sscanf(p, "service=%s", service) != 1) {
|
||
|
+ printerr(0, "WARNING: handle_gssd_upcall: "
|
||
|
+ "failed to parse service type "
|
||
|
+ "in upcall string '%s'\n", lbuf);
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (strcmp(mech, "krb5") == 0)
|
||
|
+ process_krb5_upcall(clp, uid, clp->gssd_fd, target, service);
|
||
|
+ else if (strcmp(mech, "spkm3") == 0)
|
||
|
+ process_spkm3_upcall(clp, uid, clp->gssd_fd);
|
||
|
+ else
|
||
|
+ printerr(0, "WARNING: handle_gssd_upcall: "
|
||
|
+ "received unknown gss mech '%s'\n", mech);
|
||
|
+
|
||
|
+out:
|
||
|
+ free(lbuf);
|
||
|
+ free(mech);
|
||
|
+ free(target);
|
||
|
+ free(service);
|
||
|
+ return;
|
||
|
+}
|
||
|
+
|
||
|
diff -up nfs-utils-1.2.1/utils/gssd/krb5_util.c.orig nfs-utils-1.2.1/utils/gssd/krb5_util.c
|
||
|
--- nfs-utils-1.2.1/utils/gssd/krb5_util.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/gssd/krb5_util.c 2009-12-14 11:36:12.965824348 -0500
|
||
|
@@ -797,10 +797,9 @@ gssd_search_krb5_keytab(krb5_context con
|
||
|
*/
|
||
|
static int
|
||
|
find_keytab_entry(krb5_context context, krb5_keytab kt, const char *hostname,
|
||
|
- krb5_keytab_entry *kte)
|
||
|
+ krb5_keytab_entry *kte, const char **svcnames)
|
||
|
{
|
||
|
krb5_error_code code;
|
||
|
- const char *svcnames[] = { "root", "nfs", "host", NULL };
|
||
|
char **realmnames = NULL;
|
||
|
char myhostname[NI_MAXHOST], targethostname[NI_MAXHOST];
|
||
|
int i, j, retval;
|
||
|
@@ -1096,7 +1095,8 @@ gssd_get_krb5_machine_cred_list(char ***
|
||
|
for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) {
|
||
|
if (ple->ccname) {
|
||
|
/* Make sure cred is up-to-date before returning it */
|
||
|
- retval = gssd_refresh_krb5_machine_credential(NULL, ple, 0);
|
||
|
+ retval = gssd_refresh_krb5_machine_credential(NULL, ple,
|
||
|
+ NULL);
|
||
|
if (retval)
|
||
|
continue;
|
||
|
if (i + 1 > listsize) {
|
||
|
@@ -1186,14 +1186,24 @@ gssd_destroy_krb5_machine_creds(void)
|
||
|
*/
|
||
|
int
|
||
|
gssd_refresh_krb5_machine_credential(char *hostname,
|
||
|
- struct gssd_k5_kt_princ *ple, int nocache)
|
||
|
+ struct gssd_k5_kt_princ *ple,
|
||
|
+ char *service)
|
||
|
{
|
||
|
krb5_error_code code = 0;
|
||
|
krb5_context context;
|
||
|
krb5_keytab kt = NULL;;
|
||
|
int retval = 0;
|
||
|
char *k5err = NULL;
|
||
|
+ const char *svcnames[4] = { "root", "nfs", "host", NULL };
|
||
|
|
||
|
+ /*
|
||
|
+ * If a specific service name was specified, use it.
|
||
|
+ * Otherwise, use the default list.
|
||
|
+ */
|
||
|
+ if (service != NULL && strcmp(service, "*") != 0) {
|
||
|
+ svcnames[0] = service;
|
||
|
+ svcnames[1] = NULL;
|
||
|
+ }
|
||
|
if (hostname == NULL && ple == NULL)
|
||
|
return EINVAL;
|
||
|
|
||
|
@@ -1216,7 +1226,7 @@ gssd_refresh_krb5_machine_credential(cha
|
||
|
if (ple == NULL) {
|
||
|
krb5_keytab_entry kte;
|
||
|
|
||
|
- code = find_keytab_entry(context, kt, hostname, &kte);
|
||
|
+ code = find_keytab_entry(context, kt, hostname, &kte, svcnames);
|
||
|
if (code) {
|
||
|
printerr(0, "ERROR: %s: no usable keytab entry found "
|
||
|
"in keytab %s for connection with host %s\n",
|
||
|
@@ -1241,7 +1251,7 @@ gssd_refresh_krb5_machine_credential(cha
|
||
|
goto out;
|
||
|
}
|
||
|
}
|
||
|
- retval = gssd_get_single_krb5_cred(context, kt, ple, nocache);
|
||
|
+ retval = gssd_get_single_krb5_cred(context, kt, ple, 0);
|
||
|
out:
|
||
|
if (kt)
|
||
|
krb5_kt_close(context, kt);
|
||
|
diff -up nfs-utils-1.2.1/utils/gssd/krb5_util.h.orig nfs-utils-1.2.1/utils/gssd/krb5_util.h
|
||
|
--- nfs-utils-1.2.1/utils/gssd/krb5_util.h.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/gssd/krb5_util.h 2009-12-14 11:36:12.965824348 -0500
|
||
|
@@ -30,7 +30,8 @@ void gssd_free_krb5_machine_cred_list(ch
|
||
|
void gssd_setup_krb5_machine_gss_ccache(char *servername);
|
||
|
void gssd_destroy_krb5_machine_creds(void);
|
||
|
int gssd_refresh_krb5_machine_credential(char *hostname,
|
||
|
- struct gssd_k5_kt_princ *ple, int nocache);
|
||
|
+ struct gssd_k5_kt_princ *ple,
|
||
|
+ char *service);
|
||
|
char *gssd_k5_err_msg(krb5_context context, krb5_error_code code);
|
||
|
void gssd_k5_get_default_realm(char **def_realm);
|
||
|
|
||
|
diff -up nfs-utils-1.2.1/utils/gssd/svcgssd_proc.c.orig nfs-utils-1.2.1/utils/gssd/svcgssd_proc.c
|
||
|
--- nfs-utils-1.2.1/utils/gssd/svcgssd_proc.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/gssd/svcgssd_proc.c 2009-12-14 11:36:12.966824102 -0500
|
||
|
@@ -56,6 +56,7 @@
|
||
|
#include "gss_util.h"
|
||
|
#include "err_util.h"
|
||
|
#include "context.h"
|
||
|
+#include "gss_oids.h"
|
||
|
|
||
|
extern char * mech2file(gss_OID mech);
|
||
|
#define SVCGSSD_CONTEXT_CHANNEL "/proc/net/rpc/auth.rpcsec.context/channel"
|
||
|
@@ -73,7 +74,7 @@ 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,
|
||
|
- int32_t endtime)
|
||
|
+ int32_t endtime, char *client_name)
|
||
|
{
|
||
|
FILE *f;
|
||
|
int i;
|
||
|
@@ -98,9 +99,10 @@ do_svc_downcall(gss_buffer_desc *out_han
|
||
|
qword_printint(f, cred->cr_gid);
|
||
|
qword_printint(f, cred->cr_ngroups);
|
||
|
printerr(2, "mech: %s, hndl len: %d, ctx len %d, timeout: %d (%d from now), "
|
||
|
- "uid: %d, gid: %d, num aux grps: %d:\n",
|
||
|
+ "clnt: %s, uid: %d, gid: %d, num aux grps: %d:\n",
|
||
|
fname, out_handle->length, context_token->length,
|
||
|
endtime, endtime - time(0),
|
||
|
+ client_name ? client_name : "<null>",
|
||
|
cred->cr_uid, cred->cr_gid, cred->cr_ngroups);
|
||
|
for (i=0; i < cred->cr_ngroups; i++) {
|
||
|
qword_printint(f, cred->cr_groups[i]);
|
||
|
@@ -108,6 +110,8 @@ do_svc_downcall(gss_buffer_desc *out_han
|
||
|
}
|
||
|
qword_print(f, fname);
|
||
|
qword_printhex(f, context_token->value, context_token->length);
|
||
|
+ if (client_name)
|
||
|
+ qword_print(f, client_name);
|
||
|
err = qword_eol(f);
|
||
|
if (err) {
|
||
|
printerr(1, "WARNING: error writing to downcall channel "
|
||
|
@@ -307,6 +311,75 @@ print_hexl(const char *description, unsi
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
+static int
|
||
|
+get_krb5_hostbased_name (gss_buffer_desc *name, char **hostbased_name)
|
||
|
+{
|
||
|
+ char *p, *sname = NULL;
|
||
|
+ if (strchr(name->value, '@') && strchr(name->value, '/')) {
|
||
|
+ if ((sname = calloc(name->length, 1)) == NULL) {
|
||
|
+ printerr(0, "ERROR: get_krb5_hostbased_name failed "
|
||
|
+ "to allocate %d bytes\n", name->length);
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+ /* read in name and instance and replace '/' with '@' */
|
||
|
+ sscanf(name->value, "%[^@]", sname);
|
||
|
+ p = strrchr(sname, '/');
|
||
|
+ if (p == NULL) { /* The '@' preceeded the '/' */
|
||
|
+ free(sname);
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+ *p = '@';
|
||
|
+ }
|
||
|
+ *hostbased_name = sname;
|
||
|
+ return 0;
|
||
|
+}
|
||
|
+
|
||
|
+static int
|
||
|
+get_hostbased_client_name(gss_name_t client_name, gss_OID mech,
|
||
|
+ char **hostbased_name)
|
||
|
+{
|
||
|
+ u_int32_t maj_stat, min_stat;
|
||
|
+ gss_buffer_desc name;
|
||
|
+ gss_OID name_type = GSS_C_NO_OID;
|
||
|
+ char *cname;
|
||
|
+ int res = -1;
|
||
|
+
|
||
|
+ *hostbased_name = NULL; /* preset in case we fail */
|
||
|
+
|
||
|
+ /* Get the client's gss authenticated name */
|
||
|
+ maj_stat = gss_display_name(&min_stat, client_name, &name, &name_type);
|
||
|
+ if (maj_stat != GSS_S_COMPLETE) {
|
||
|
+ pgsserr("get_hostbased_client_name: gss_display_name",
|
||
|
+ maj_stat, min_stat, mech);
|
||
|
+ goto out_err;
|
||
|
+ }
|
||
|
+ if (name.length >= 0xffff) { /* don't overflow */
|
||
|
+ printerr(0, "ERROR: get_hostbased_client_name: "
|
||
|
+ "received gss_name is too long (%d bytes)\n",
|
||
|
+ name.length);
|
||
|
+ goto out_rel_buf;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* For Kerberos, transform the NT_KRB5_PRINCIPAL name to
|
||
|
+ * an NT_HOSTBASED_SERVICE name */
|
||
|
+ if (g_OID_equal(&krb5oid, mech)) {
|
||
|
+ if (get_krb5_hostbased_name(&name, &cname) == 0)
|
||
|
+ *hostbased_name = cname;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* No support for SPKM3, just print a warning (for now) */
|
||
|
+ if (g_OID_equal(&spkm3oid, mech)) {
|
||
|
+ printerr(1, "WARNING: get_hostbased_client_name: "
|
||
|
+ "no hostbased_name support for SPKM3\n");
|
||
|
+ }
|
||
|
+
|
||
|
+ res = 0;
|
||
|
+out_rel_buf:
|
||
|
+ gss_release_buffer(&min_stat, &name);
|
||
|
+out_err:
|
||
|
+ return res;
|
||
|
+}
|
||
|
+
|
||
|
void
|
||
|
handle_nullreq(FILE *f) {
|
||
|
/* XXX initialize to a random integer to reduce chances of unnecessary
|
||
|
@@ -325,7 +398,7 @@ handle_nullreq(FILE *f) {
|
||
|
null_token = {.value = NULL};
|
||
|
u_int32_t ret_flags;
|
||
|
gss_ctx_id_t ctx = GSS_C_NO_CONTEXT;
|
||
|
- gss_name_t client_name;
|
||
|
+ gss_name_t client_name = NULL;
|
||
|
gss_OID mech = GSS_C_NO_OID;
|
||
|
u_int32_t maj_stat = GSS_S_FAILURE, min_stat = 0;
|
||
|
u_int32_t ignore_min_stat;
|
||
|
@@ -334,6 +407,7 @@ handle_nullreq(FILE *f) {
|
||
|
static int lbuflen = 0;
|
||
|
static char *cp;
|
||
|
int32_t ctx_endtime;
|
||
|
+ char *hostbased_name = NULL;
|
||
|
|
||
|
printerr(1, "handling null request\n");
|
||
|
|
||
|
@@ -396,11 +470,13 @@ handle_nullreq(FILE *f) {
|
||
|
if (get_ids(client_name, mech, &cred)) {
|
||
|
/* get_ids() prints error msg */
|
||
|
maj_stat = GSS_S_BAD_NAME; /* XXX ? */
|
||
|
- gss_release_name(&ignore_min_stat, &client_name);
|
||
|
goto out_err;
|
||
|
}
|
||
|
- gss_release_name(&ignore_min_stat, &client_name);
|
||
|
-
|
||
|
+ if (get_hostbased_client_name(client_name, mech, &hostbased_name)) {
|
||
|
+ /* get_hostbased_client_name() prints error msg */
|
||
|
+ maj_stat = GSS_S_BAD_NAME; /* XXX ? */
|
||
|
+ goto out_err;
|
||
|
+ }
|
||
|
|
||
|
/* Context complete. Pass handle_seq in out_handle to use
|
||
|
* for context lookup in the kernel. */
|
||
|
@@ -419,7 +495,8 @@ 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, ctx_endtime);
|
||
|
+ do_svc_downcall(&out_handle, &cred, mech, &ctx_token, ctx_endtime,
|
||
|
+ hostbased_name);
|
||
|
continue_needed:
|
||
|
send_response(f, &in_handle, &in_tok, maj_stat, min_stat,
|
||
|
&out_handle, &out_tok);
|
||
|
@@ -428,6 +505,9 @@ out:
|
||
|
free(ctx_token.value);
|
||
|
if (out_tok.value != NULL)
|
||
|
gss_release_buffer(&ignore_min_stat, &out_tok);
|
||
|
+ if (client_name)
|
||
|
+ gss_release_name(&ignore_min_stat, &client_name);
|
||
|
+ free(hostbased_name);
|
||
|
printerr(1, "finished handling null request\n");
|
||
|
return;
|
||
|
|
||
|
diff -up nfs-utils-1.2.1/utils/mountd/auth.c.orig nfs-utils-1.2.1/utils/mountd/auth.c
|
||
|
--- nfs-utils-1.2.1/utils/mountd/auth.c.orig 2009-12-14 11:35:16.315699404 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/mountd/auth.c 2009-12-14 11:36:12.970736039 -0500
|
||
|
@@ -172,8 +172,7 @@ auth_authenticate_internal(char *what, s
|
||
|
}
|
||
|
}
|
||
|
if (!(exp->m_export.e_flags & NFSEXP_INSECURE_PORT) &&
|
||
|
- (ntohs(caller->sin_port) < IPPORT_RESERVED/2 ||
|
||
|
- ntohs(caller->sin_port) >= IPPORT_RESERVED)) {
|
||
|
+ ntohs(caller->sin_port) >= IPPORT_RESERVED) {
|
||
|
*error = illegal_port;
|
||
|
return NULL;
|
||
|
}
|
||
|
diff -up nfs-utils-1.2.1/utils/mount/mount.c.orig nfs-utils-1.2.1/utils/mount/mount.c
|
||
|
--- nfs-utils-1.2.1/utils/mount/mount.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/mount/mount.c 2009-12-14 11:36:12.966824102 -0500
|
||
|
@@ -593,6 +593,9 @@ int main(int argc, char *argv[])
|
||
|
if (mnt_err == EX_BG) {
|
||
|
printf(_("%s: backgrounding \"%s\"\n"),
|
||
|
progname, spec);
|
||
|
+ printf(_("%s: mount options: \"%s\"\n"),
|
||
|
+ progname, extra_opts);
|
||
|
+
|
||
|
fflush(stdout);
|
||
|
|
||
|
/*
|
||
|
diff -up nfs-utils-1.2.1/utils/mount/network.c.orig nfs-utils-1.2.1/utils/mount/network.c
|
||
|
--- nfs-utils-1.2.1/utils/mount/network.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/mount/network.c 2009-12-14 11:36:12.967824334 -0500
|
||
|
@@ -193,8 +193,18 @@ static const unsigned int *nfs_default_p
|
||
|
}
|
||
|
#endif /* MOUNT_CONFIG */
|
||
|
|
||
|
-static int nfs_lookup(const char *hostname, const sa_family_t family,
|
||
|
- struct sockaddr *sap, socklen_t *salen)
|
||
|
+/**
|
||
|
+ * nfs_lookup - resolve hostname to an IPv4 or IPv6 socket address
|
||
|
+ * @hostname: pointer to C string containing DNS hostname to resolve
|
||
|
+ * @family: address family hint
|
||
|
+ * @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.
|
||
|
+ */
|
||
|
+int nfs_lookup(const char *hostname, const sa_family_t family,
|
||
|
+ struct sockaddr *sap, socklen_t *salen)
|
||
|
{
|
||
|
struct addrinfo *gai_results;
|
||
|
struct addrinfo gai_hint = {
|
||
|
@@ -243,25 +253,6 @@ static int nfs_lookup(const char *hostna
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
- * nfs_name_to_address - resolve hostname to an IPv4 or IPv6 socket address
|
||
|
- * @hostname: pointer to C string containing DNS hostname to resolve
|
||
|
- * @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.
|
||
|
- */
|
||
|
-int nfs_name_to_address(const char *hostname,
|
||
|
- struct sockaddr *sap, socklen_t *salen)
|
||
|
-{
|
||
|
-#ifdef IPV6_SUPPORTED
|
||
|
- return nfs_lookup(hostname, AF_UNSPEC, sap, salen);
|
||
|
-#else /* !IPV6_SUPPORTED */
|
||
|
- return nfs_lookup(hostname, AF_INET, sap, salen);
|
||
|
-#endif /* !IPV6_SUPPORTED */
|
||
|
-}
|
||
|
-
|
||
|
-/**
|
||
|
* nfs_gethostbyname - resolve a hostname to an IPv4 address
|
||
|
* @hostname: pointer to a C string containing a DNS hostname
|
||
|
* @sin: returns an IPv4 address
|
||
|
@@ -283,8 +274,8 @@ int nfs_gethostbyname(const char *hostna
|
||
|
* OUT: length of converted socket address
|
||
|
*
|
||
|
* Convert a presentation format address string to a socket address.
|
||
|
- * Similar to nfs_name_to_address(), but the DNS query is squelched,
|
||
|
- * and won't make any noise if the getaddrinfo() call fails.
|
||
|
+ * Similar to nfs_lookup(), but the DNS query is squelched, and it
|
||
|
+ * won't make any noise if the getaddrinfo() call fails.
|
||
|
*
|
||
|
* Returns 1 and fills in @sap and @salen if successful; otherwise zero.
|
||
|
*
|
||
|
@@ -1289,6 +1280,7 @@ nfs_nfs_version(struct mount_options *op
|
||
|
int
|
||
|
nfs_nfs_protocol(struct mount_options *options, unsigned long *protocol)
|
||
|
{
|
||
|
+ sa_family_t family;
|
||
|
char *option;
|
||
|
|
||
|
switch (po_rightmost(options, nfs_transport_opttbl)) {
|
||
|
@@ -1300,17 +1292,8 @@ nfs_nfs_protocol(struct mount_options *o
|
||
|
return 1;
|
||
|
case 2: /* proto */
|
||
|
option = po_get(options, "proto");
|
||
|
- if (option) {
|
||
|
- if (strcmp(option, "tcp") == 0) {
|
||
|
- *protocol = IPPROTO_TCP;
|
||
|
- return 1;
|
||
|
- }
|
||
|
- if (strcmp(option, "udp") == 0) {
|
||
|
- *protocol = IPPROTO_UDP;
|
||
|
- return 1;
|
||
|
- }
|
||
|
- return 0;
|
||
|
- }
|
||
|
+ if (option != NULL)
|
||
|
+ return nfs_get_proto(option, &family, protocol);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
@@ -1352,6 +1335,40 @@ nfs_nfs_port(struct mount_options *optio
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
+ * Returns TRUE and fills in @family if a valid NFS protocol option
|
||
|
+ * is found, or FALSE if the option was specified with an invalid value.
|
||
|
+ */
|
||
|
+int nfs_nfs_proto_family(struct mount_options *options,
|
||
|
+ sa_family_t *family)
|
||
|
+{
|
||
|
+ unsigned long protocol;
|
||
|
+ char *option;
|
||
|
+
|
||
|
+#ifdef HAVE_LIBTIRPC
|
||
|
+ *family = AF_UNSPEC;
|
||
|
+#else
|
||
|
+ *family = AF_INET;
|
||
|
+#endif
|
||
|
+
|
||
|
+ switch (po_rightmost(options, nfs_transport_opttbl)) {
|
||
|
+ case 0: /* udp */
|
||
|
+ return 1;
|
||
|
+ case 1: /* tcp */
|
||
|
+ return 1;
|
||
|
+ case 2: /* proto */
|
||
|
+ option = po_get(options, "proto");
|
||
|
+ if (option != NULL)
|
||
|
+ return nfs_get_proto(option, family, &protocol);
|
||
|
+ }
|
||
|
+
|
||
|
+ /*
|
||
|
+ * NFS transport protocol wasn't specified. Return the
|
||
|
+ * default address family.
|
||
|
+ */
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+
|
||
|
+/*
|
||
|
* "mountprog" is supported only by the legacy mount command. The
|
||
|
* kernel mount client does not support this option.
|
||
|
*
|
||
|
@@ -1419,20 +1436,12 @@ nfs_mount_version(struct mount_options *
|
||
|
static int
|
||
|
nfs_mount_protocol(struct mount_options *options, unsigned long *protocol)
|
||
|
{
|
||
|
+ sa_family_t family;
|
||
|
char *option;
|
||
|
|
||
|
option = po_get(options, "mountproto");
|
||
|
- if (option) {
|
||
|
- if (strcmp(option, "tcp") == 0) {
|
||
|
- *protocol = IPPROTO_TCP;
|
||
|
- return 1;
|
||
|
- }
|
||
|
- if (strcmp(option, "udp") == 0) {
|
||
|
- *protocol = IPPROTO_UDP;
|
||
|
- return 1;
|
||
|
- }
|
||
|
- return 0;
|
||
|
- }
|
||
|
+ if (option != NULL)
|
||
|
+ return nfs_get_proto(option, &family, protocol);
|
||
|
|
||
|
/*
|
||
|
* MNT transport protocol wasn't specified. If the NFS
|
||
|
@@ -1472,6 +1481,35 @@ nfs_mount_port(struct mount_options *opt
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
+/*
|
||
|
+ * Returns TRUE and fills in @family if a valid MNT protocol option
|
||
|
+ * is found, or FALSE if the option was specified with an invalid value.
|
||
|
+ */
|
||
|
+int nfs_mount_proto_family(struct mount_options *options,
|
||
|
+ sa_family_t *family)
|
||
|
+{
|
||
|
+ unsigned long protocol;
|
||
|
+ char *option;
|
||
|
+
|
||
|
+#ifdef HAVE_LIBTIRPC
|
||
|
+ *family = AF_UNSPEC;
|
||
|
+#else
|
||
|
+ *family = AF_INET;
|
||
|
+#endif
|
||
|
+
|
||
|
+ option = po_get(options, "mountproto");
|
||
|
+ if (option != NULL)
|
||
|
+ return nfs_get_proto(option, family, &protocol);
|
||
|
+
|
||
|
+ /*
|
||
|
+ * MNT transport protocol wasn't specified. If the NFS
|
||
|
+ * transport protocol was specified, derive the family
|
||
|
+ * from that; otherwise, return the default family for
|
||
|
+ * NFS.
|
||
|
+ */
|
||
|
+ return nfs_nfs_proto_family(options, family);
|
||
|
+}
|
||
|
+
|
||
|
/**
|
||
|
* nfs_options2pmap - set up pmap structs based on mount options
|
||
|
* @options: pointer to mount options
|
||
|
diff -up nfs-utils-1.2.1/utils/mount/network.h.orig nfs-utils-1.2.1/utils/mount/network.h
|
||
|
--- nfs-utils-1.2.1/utils/mount/network.h.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/mount/network.h 2009-12-14 11:36:12.967824334 -0500
|
||
|
@@ -44,7 +44,8 @@ int nfs_probe_bothports(const struct soc
|
||
|
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 *, struct sockaddr *, socklen_t *);
|
||
|
+int nfs_lookup(const char *hostname, const sa_family_t family,
|
||
|
+ struct sockaddr *sap, socklen_t *salen);
|
||
|
int nfs_string_to_sockaddr(const char *, struct sockaddr *, socklen_t *);
|
||
|
int nfs_present_sockaddr(const struct sockaddr *,
|
||
|
const socklen_t, char *, const size_t);
|
||
|
@@ -56,6 +57,8 @@ int clnt_ping(struct sockaddr_in *, cons
|
||
|
|
||
|
struct mount_options;
|
||
|
|
||
|
+int nfs_nfs_proto_family(struct mount_options *options, sa_family_t *family);
|
||
|
+int nfs_mount_proto_family(struct mount_options *options, sa_family_t *family);
|
||
|
int nfs_nfs_version(struct mount_options *options, unsigned long *version);
|
||
|
int nfs_nfs_protocol(struct mount_options *options, unsigned long *protocol);
|
||
|
|
||
|
diff -up nfs-utils-1.2.1/utils/mount/nfs4mount.c.orig nfs-utils-1.2.1/utils/mount/nfs4mount.c
|
||
|
--- nfs-utils-1.2.1/utils/mount/nfs4mount.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/mount/nfs4mount.c 2009-12-14 11:36:12.969718447 -0500
|
||
|
@@ -217,8 +217,11 @@ int nfs4mount(const char *spec, const ch
|
||
|
progname);
|
||
|
goto fail;
|
||
|
}
|
||
|
- snprintf(new_opts, sizeof(new_opts), "%s%saddr=%s",
|
||
|
- old_opts, *old_opts ? "," : "", s);
|
||
|
+ if (running_bg)
|
||
|
+ strncpy(new_opts, old_opts, sizeof(new_opts));
|
||
|
+ else
|
||
|
+ snprintf(new_opts, sizeof(new_opts), "%s%saddr=%s",
|
||
|
+ old_opts, *old_opts ? "," : "", s);
|
||
|
*extra_opts = xstrdup(new_opts);
|
||
|
|
||
|
/* Set default options.
|
||
|
@@ -434,15 +437,17 @@ int nfs4mount(const char *spec, const ch
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
- switch(rpc_createerr.cf_stat){
|
||
|
- case RPC_TIMEDOUT:
|
||
|
- break;
|
||
|
- case RPC_SYSTEMERROR:
|
||
|
- if (errno == ETIMEDOUT)
|
||
|
+ if (!bg) {
|
||
|
+ switch(rpc_createerr.cf_stat) {
|
||
|
+ case RPC_TIMEDOUT:
|
||
|
break;
|
||
|
- default:
|
||
|
- rpc_mount_errors(hostname, 0, bg);
|
||
|
- goto fail;
|
||
|
+ case RPC_SYSTEMERROR:
|
||
|
+ if (errno == ETIMEDOUT)
|
||
|
+ break;
|
||
|
+ default:
|
||
|
+ rpc_mount_errors(hostname, 0, bg);
|
||
|
+ goto fail;
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
if (bg && !running_bg) {
|
||
|
diff -up nfs-utils-1.2.1/utils/mount/nfs.man.orig nfs-utils-1.2.1/utils/mount/nfs.man
|
||
|
--- nfs-utils-1.2.1/utils/mount/nfs.man.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/mount/nfs.man 2009-12-14 11:36:12.968700507 -0500
|
||
|
@@ -58,9 +58,17 @@ The server's hostname and export pathnam
|
||
|
are separated by a colon, while
|
||
|
the mount options are separated by commas. The remaining fields
|
||
|
are separated by blanks or tabs.
|
||
|
+.P
|
||
|
The server's hostname can be an unqualified hostname,
|
||
|
a fully qualified domain name,
|
||
|
-or a dotted quad IPv4 address.
|
||
|
+a dotted quad IPv4 address, or
|
||
|
+an IPv6 address enclosed in square brackets.
|
||
|
+Link-local and site-local IPv6 addresses must be accompanied by an
|
||
|
+interface identifier.
|
||
|
+See
|
||
|
+.BR ipv6 (7)
|
||
|
+for details on specifying raw IPv6 addresses.
|
||
|
+.P
|
||
|
The
|
||
|
.I fstype
|
||
|
field contains either "nfs" (for version 2 or version 3 NFS mounts)
|
||
|
@@ -470,32 +478,38 @@ for mounting the
|
||
|
.B nfs
|
||
|
file system type.
|
||
|
.TP 1.5i
|
||
|
-.BI proto= transport
|
||
|
-The transport the NFS client uses
|
||
|
+.BI proto= netid
|
||
|
+The transport protocol name and protocol family the NFS client uses
|
||
|
to transmit requests to the NFS server for this mount point.
|
||
|
-.I transport
|
||
|
-can be either
|
||
|
-.B udp
|
||
|
-or
|
||
|
-.BR tcp .
|
||
|
-Each transport uses different default
|
||
|
+If an NFS server has both an IPv4 and an IPv6 address, using a specific
|
||
|
+netid will force the use of IPv4 or IPv6 networking to communicate
|
||
|
+with that server.
|
||
|
+.IP
|
||
|
+If support for TI-RPC is built into the
|
||
|
+.B mount.nfs
|
||
|
+command,
|
||
|
+.I netid
|
||
|
+is a valid netid listed in
|
||
|
+.IR /etc/netconfig .
|
||
|
+Otherwise,
|
||
|
+.I netid
|
||
|
+is one of "tcp," "udp," or "rdma," and only IPv4 may be used.
|
||
|
+.IP
|
||
|
+Each transport protocol uses different default
|
||
|
.B retrans
|
||
|
and
|
||
|
.B timeo
|
||
|
-settings; refer to the description of these two mount options for details.
|
||
|
+settings.
|
||
|
+Refer to the description of these two mount options for details.
|
||
|
.IP
|
||
|
In addition to controlling how the NFS client transmits requests to
|
||
|
the server, this mount option also controls how the
|
||
|
.BR mount (8)
|
||
|
command communicates with the server's rpcbind and mountd services.
|
||
|
-Specifying
|
||
|
-.B proto=tcp
|
||
|
-forces all traffic from the
|
||
|
+Specifying a netid that uses TCP forces all traffic from the
|
||
|
.BR mount (8)
|
||
|
command and the NFS client to use TCP.
|
||
|
-Specifying
|
||
|
-.B proto=udp
|
||
|
-forces all traffic types to use UDP.
|
||
|
+Specifying a netid that uses UDP forces all traffic types to use UDP.
|
||
|
.IP
|
||
|
If the
|
||
|
.B proto
|
||
|
@@ -548,15 +562,20 @@ or the server's mountd service is not av
|
||
|
This option can be used when mounting an NFS server
|
||
|
through a firewall that blocks the rpcbind protocol.
|
||
|
.TP 1.5i
|
||
|
-.BI mountproto= transport
|
||
|
-The transport the NFS client uses
|
||
|
+.BI mountproto= netid
|
||
|
+The transport protocol name and protocol family the NFS client uses
|
||
|
to transmit requests to the NFS server's mountd service when performing
|
||
|
this mount request, and when later unmounting this mount point.
|
||
|
-.I transport
|
||
|
-can be either
|
||
|
-.B udp
|
||
|
-or
|
||
|
-.BR tcp .
|
||
|
+.IP
|
||
|
+If support for TI-RPC is built into the
|
||
|
+.B mount.nfs
|
||
|
+command,
|
||
|
+.I netid
|
||
|
+is a valid netid listed in
|
||
|
+.IR /etc/netconfig .
|
||
|
+Otherwise,
|
||
|
+.I netid
|
||
|
+is one of "tcp" or "udp," and only IPv4 may be used.
|
||
|
.IP
|
||
|
This option can be used when mounting an NFS server
|
||
|
through a firewall that blocks a particular transport.
|
||
|
@@ -566,6 +585,7 @@ option, different transports for mountd
|
||
|
can be specified.
|
||
|
If the server's mountd service is not available via the specified
|
||
|
transport, the mount request fails.
|
||
|
+.IP
|
||
|
Refer to the TRANSPORT METHODS section for more on how the
|
||
|
.B mountproto
|
||
|
mount option interacts with the
|
||
|
@@ -709,17 +729,26 @@ for mounting the
|
||
|
.B nfs4
|
||
|
file system type.
|
||
|
.TP 1.5i
|
||
|
-.BI proto= transport
|
||
|
-The transport the NFS client uses
|
||
|
+.BI proto= netid
|
||
|
+The transport protocol name and protocol family the NFS client uses
|
||
|
to transmit requests to the NFS server for this mount point.
|
||
|
-.I transport
|
||
|
-can be either
|
||
|
-.B udp
|
||
|
-or
|
||
|
-.BR tcp .
|
||
|
+If an NFS server has both an IPv4 and an IPv6 address, using a specific
|
||
|
+netid will force the use of IPv4 or IPv6 networking to communicate
|
||
|
+with that server.
|
||
|
+.IP
|
||
|
+If support for TI-RPC is built into the
|
||
|
+.B mount.nfs
|
||
|
+command,
|
||
|
+.I netid
|
||
|
+is a valid netid listed in
|
||
|
+.IR /etc/netconfig .
|
||
|
+Otherwise,
|
||
|
+.I netid
|
||
|
+is one of "tcp" or "udp," and only IPv4 may be used.
|
||
|
+.IP
|
||
|
All NFS version 4 servers are required to support TCP,
|
||
|
so if this mount option is not specified, the NFS version 4 client
|
||
|
-uses the TCP transport protocol.
|
||
|
+uses the TCP protocol.
|
||
|
Refer to the TRANSPORT METHODS section for more details.
|
||
|
.TP 1.5i
|
||
|
.BI port= n
|
||
|
@@ -779,7 +808,8 @@ The DATA AND METADATA COHERENCE section
|
||
|
the behavior of this option in more detail.
|
||
|
.TP 1.5i
|
||
|
.BI clientaddr= n.n.n.n
|
||
|
-Specifies a single IPv4 address (in dotted-quad form)
|
||
|
+Specifies a single IPv4 address (in dotted-quad form),
|
||
|
+or a non-link-local IPv6 address,
|
||
|
that the NFS client advertises to allow servers
|
||
|
to perform NFS version 4 callback requests against
|
||
|
files on this mount point. If the server is unable to
|
||
|
@@ -855,6 +885,14 @@ This example can be used to mount /usr o
|
||
|
.TA 2.5i +0.7i +0.7i +.7i
|
||
|
server:/export /usr nfs ro,nolock,nocto,actimeo=3600 0 0
|
||
|
.FI
|
||
|
+.P
|
||
|
+This example shows how to mount an NFS server
|
||
|
+using a raw IPv6 link-local address.
|
||
|
+.P
|
||
|
+.NF
|
||
|
+.TA 2.5i +0.7i +0.7i +.7i
|
||
|
+ [fe80::215:c5ff:fb3e:e2b1%eth0]:/export /mnt nfs defaults 0 0
|
||
|
+.FI
|
||
|
.SH "TRANSPORT METHODS"
|
||
|
NFS clients send requests to NFS servers via
|
||
|
Remote Procedure Calls, or
|
||
|
@@ -1498,6 +1536,8 @@ such as security negotiation, server ref
|
||
|
.BR mount.nfs (5),
|
||
|
.BR umount.nfs (5),
|
||
|
.BR exports (5),
|
||
|
+.BR netconfig (5),
|
||
|
+.BR ipv6 (7),
|
||
|
.BR nfsd (8),
|
||
|
.BR sm-notify (8),
|
||
|
.BR rpc.statd (8),
|
||
|
diff -up nfs-utils-1.2.1/utils/mount/nfsmount.c.orig nfs-utils-1.2.1/utils/mount/nfsmount.c
|
||
|
--- nfs-utils-1.2.1/utils/mount/nfsmount.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/mount/nfsmount.c 2009-12-14 11:36:12.969718447 -0500
|
||
|
@@ -170,7 +170,7 @@ parse_options(char *old_opts, struct nfs
|
||
|
struct pmap *mnt_pmap = &mnt_server->pmap;
|
||
|
struct pmap *nfs_pmap = &nfs_server->pmap;
|
||
|
int len;
|
||
|
- char *opt, *opteq, *p, *opt_b;
|
||
|
+ char *opt, *opteq, *p, *opt_b, *tmp_opts;
|
||
|
char *mounthost = NULL;
|
||
|
char cbuf[128];
|
||
|
int open_quote = 0;
|
||
|
@@ -179,7 +179,8 @@ parse_options(char *old_opts, struct nfs
|
||
|
*bg = 0;
|
||
|
|
||
|
len = strlen(new_opts);
|
||
|
- for (p=old_opts, opt_b=NULL; p && *p; p++) {
|
||
|
+ tmp_opts = xstrdup(old_opts);
|
||
|
+ for (p=tmp_opts, opt_b=NULL; p && *p; p++) {
|
||
|
if (!opt_b)
|
||
|
opt_b = p; /* begin of the option item */
|
||
|
if (*p == '"')
|
||
|
@@ -457,10 +458,12 @@ parse_options(char *old_opts, struct nfs
|
||
|
goto out_bad;
|
||
|
*mnt_server->hostname = mounthost;
|
||
|
}
|
||
|
+ free(tmp_opts);
|
||
|
return 1;
|
||
|
bad_parameter:
|
||
|
nfs_error(_("%s: Bad nfs mount parameter: %s\n"), progname, opt);
|
||
|
out_bad:
|
||
|
+ free(tmp_opts);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
diff -up nfs-utils-1.2.1/utils/mount/nfsumount.c.orig nfs-utils-1.2.1/utils/mount/nfsumount.c
|
||
|
--- nfs-utils-1.2.1/utils/mount/nfsumount.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/mount/nfsumount.c 2009-12-14 11:36:12.970736039 -0500
|
||
|
@@ -169,10 +169,15 @@ out:
|
||
|
static int nfs_umount_do_umnt(struct mount_options *options,
|
||
|
char **hostname, char **dirname)
|
||
|
{
|
||
|
- struct sockaddr_storage address;
|
||
|
- struct sockaddr *sap = (struct sockaddr *)&address;
|
||
|
+ union {
|
||
|
+ struct sockaddr sa;
|
||
|
+ struct sockaddr_in s4;
|
||
|
+ struct sockaddr_in6 s6;
|
||
|
+ } address;
|
||
|
+ struct sockaddr *sap = &address.sa;
|
||
|
socklen_t salen = sizeof(address);
|
||
|
struct pmap nfs_pmap, mnt_pmap;
|
||
|
+ sa_family_t family;
|
||
|
|
||
|
if (!nfs_options2pmap(options, &nfs_pmap, &mnt_pmap)) {
|
||
|
nfs_error(_("%s: bad mount options"), progname);
|
||
|
@@ -189,8 +194,10 @@ static int nfs_umount_do_umnt(struct mou
|
||
|
return EX_FAIL;
|
||
|
}
|
||
|
|
||
|
- if (nfs_name_to_address(*hostname, sap, &salen) == 0)
|
||
|
- /* nfs_name_to_address reports any errors */
|
||
|
+ if (!nfs_mount_proto_family(options, &family))
|
||
|
+ return 0;
|
||
|
+ if (!nfs_lookup(*hostname, family, sap, &salen))
|
||
|
+ /* nfs_lookup reports any errors */
|
||
|
return EX_FAIL;
|
||
|
|
||
|
if (nfs_advise_umount(sap, salen, &mnt_pmap, dirname) == 0)
|
||
|
diff -up nfs-utils-1.2.1/utils/mount/stropts.c.orig nfs-utils-1.2.1/utils/mount/stropts.c
|
||
|
--- nfs-utils-1.2.1/utils/mount/stropts.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/mount/stropts.c 2009-12-14 11:36:12.970736039 -0500
|
||
|
@@ -38,6 +38,7 @@
|
||
|
#include "xcommon.h"
|
||
|
#include "mount.h"
|
||
|
#include "nls.h"
|
||
|
+#include "nfsrpc.h"
|
||
|
#include "mount_constants.h"
|
||
|
#include "stropts.h"
|
||
|
#include "error.h"
|
||
|
@@ -76,12 +77,18 @@ extern char *progname;
|
||
|
extern int verbose;
|
||
|
extern int sloppy;
|
||
|
|
||
|
+union nfs_sockaddr {
|
||
|
+ struct sockaddr sa;
|
||
|
+ struct sockaddr_in s4;
|
||
|
+ struct sockaddr_in6 s6;
|
||
|
+};
|
||
|
+
|
||
|
struct nfsmount_info {
|
||
|
const char *spec, /* server:/path */
|
||
|
*node, /* mounted-on dir */
|
||
|
*type; /* "nfs" or "nfs4" */
|
||
|
char *hostname; /* server's hostname */
|
||
|
- struct sockaddr_storage address; /* server's address */
|
||
|
+ union nfs_sockaddr address;
|
||
|
socklen_t salen; /* size of server's address */
|
||
|
|
||
|
struct mount_options *options; /* parsed mount options */
|
||
|
@@ -204,9 +211,9 @@ static int nfs_append_clientaddr_option(
|
||
|
socklen_t salen,
|
||
|
struct mount_options *options)
|
||
|
{
|
||
|
- struct sockaddr_storage dummy;
|
||
|
- struct sockaddr *my_addr = (struct sockaddr *)&dummy;
|
||
|
- socklen_t my_len = sizeof(dummy);
|
||
|
+ union nfs_sockaddr address;
|
||
|
+ struct sockaddr *my_addr = &address.sa;
|
||
|
+ socklen_t my_len = sizeof(address);
|
||
|
|
||
|
if (po_contains(options, "clientaddr") == PO_FOUND)
|
||
|
return 1;
|
||
|
@@ -218,21 +225,33 @@ static int nfs_append_clientaddr_option(
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
- * Resolve the 'mounthost=' hostname and append a new option using
|
||
|
- * the resulting address.
|
||
|
+ * Determine whether to append a 'mountaddr=' option. The option is needed if:
|
||
|
+ *
|
||
|
+ * 1. "mounthost=" was specified, or
|
||
|
+ * 2. The address families for proto= and mountproto= are different.
|
||
|
*/
|
||
|
-static int nfs_fix_mounthost_option(struct mount_options *options)
|
||
|
+static int nfs_fix_mounthost_option(struct mount_options *options,
|
||
|
+ const char *nfs_hostname)
|
||
|
{
|
||
|
- struct sockaddr_storage dummy;
|
||
|
- struct sockaddr *sap = (struct sockaddr *)&dummy;
|
||
|
- socklen_t salen = sizeof(dummy);
|
||
|
+ union nfs_sockaddr address;
|
||
|
+ struct sockaddr *sap = &address.sa;
|
||
|
+ socklen_t salen = sizeof(address);
|
||
|
+ sa_family_t nfs_family, mnt_family;
|
||
|
char *mounthost;
|
||
|
|
||
|
+ if (!nfs_nfs_proto_family(options, &nfs_family))
|
||
|
+ return 0;
|
||
|
+ if (!nfs_mount_proto_family(options, &mnt_family))
|
||
|
+ return 0;
|
||
|
+
|
||
|
mounthost = po_get(options, "mounthost");
|
||
|
- if (!mounthost)
|
||
|
- return 1;
|
||
|
+ if (mounthost == NULL) {
|
||
|
+ if (nfs_family == mnt_family)
|
||
|
+ return 1;
|
||
|
+ mounthost = (char *)nfs_hostname;
|
||
|
+ }
|
||
|
|
||
|
- if (!nfs_name_to_address(mounthost, sap, &salen)) {
|
||
|
+ if (!nfs_lookup(mounthost, mnt_family, sap, &salen)) {
|
||
|
nfs_error(_("%s: unable to determine mount server's address"),
|
||
|
progname);
|
||
|
return 0;
|
||
|
@@ -319,13 +338,16 @@ static int nfs_set_version(struct nfsmou
|
||
|
*/
|
||
|
static int nfs_validate_options(struct nfsmount_info *mi)
|
||
|
{
|
||
|
- struct sockaddr *sap = (struct sockaddr *)&mi->address;
|
||
|
+ struct sockaddr *sap = &mi->address.sa;
|
||
|
+ sa_family_t family;
|
||
|
|
||
|
if (!nfs_parse_devname(mi->spec, &mi->hostname, NULL))
|
||
|
return 0;
|
||
|
|
||
|
+ if (!nfs_nfs_proto_family(mi->options, &family))
|
||
|
+ return 0;
|
||
|
mi->salen = sizeof(mi->address);
|
||
|
- if (!nfs_name_to_address(mi->hostname, sap, &mi->salen))
|
||
|
+ if (!nfs_lookup(mi->hostname, family, sap, &mi->salen))
|
||
|
return 0;
|
||
|
|
||
|
if (!nfs_set_version(mi))
|
||
|
@@ -371,10 +393,13 @@ static int nfs_extract_server_addresses(
|
||
|
}
|
||
|
|
||
|
static int nfs_construct_new_options(struct mount_options *options,
|
||
|
+ struct sockaddr *nfs_saddr,
|
||
|
struct pmap *nfs_pmap,
|
||
|
+ struct sockaddr *mnt_saddr,
|
||
|
struct pmap *mnt_pmap)
|
||
|
{
|
||
|
char new_option[64];
|
||
|
+ char *netid;
|
||
|
|
||
|
po_remove_all(options, "nfsprog");
|
||
|
po_remove_all(options, "mountprog");
|
||
|
@@ -391,20 +416,14 @@ static int nfs_construct_new_options(str
|
||
|
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;
|
||
|
- }
|
||
|
+ netid = nfs_get_netid(nfs_saddr->sa_family, nfs_pmap->pm_prot);
|
||
|
+ if (netid == NULL)
|
||
|
+ return 0;
|
||
|
+ snprintf(new_option, sizeof(new_option) - 1,
|
||
|
+ "proto=%s", netid);
|
||
|
+ free(netid);
|
||
|
+ if (po_append(options, new_option) == PO_FAILED)
|
||
|
+ return 0;
|
||
|
|
||
|
po_remove_all(options, "port");
|
||
|
if (nfs_pmap->pm_port != NFS_PORT) {
|
||
|
@@ -421,20 +440,14 @@ static int nfs_construct_new_options(str
|
||
|
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;
|
||
|
- }
|
||
|
+ netid = nfs_get_netid(mnt_saddr->sa_family, mnt_pmap->pm_prot);
|
||
|
+ if (netid == NULL)
|
||
|
+ return 0;
|
||
|
+ snprintf(new_option, sizeof(new_option) - 1,
|
||
|
+ "mountproto=%s", netid);
|
||
|
+ free(netid);
|
||
|
+ if (po_append(options, new_option) == PO_FAILED)
|
||
|
+ return 0;
|
||
|
|
||
|
po_remove_all(options, "mountport");
|
||
|
snprintf(new_option, sizeof(new_option) - 1,
|
||
|
@@ -461,12 +474,12 @@ static int nfs_construct_new_options(str
|
||
|
static int
|
||
|
nfs_rewrite_pmap_mount_options(struct mount_options *options)
|
||
|
{
|
||
|
- struct sockaddr_storage nfs_address;
|
||
|
- struct sockaddr *nfs_saddr = (struct sockaddr *)&nfs_address;
|
||
|
+ union nfs_sockaddr nfs_address;
|
||
|
+ struct sockaddr *nfs_saddr = &nfs_address.sa;
|
||
|
socklen_t nfs_salen = sizeof(nfs_address);
|
||
|
struct pmap nfs_pmap;
|
||
|
- struct sockaddr_storage mnt_address;
|
||
|
- struct sockaddr *mnt_saddr = (struct sockaddr *)&mnt_address;
|
||
|
+ union nfs_sockaddr mnt_address;
|
||
|
+ struct sockaddr *mnt_saddr = &mnt_address.sa;
|
||
|
socklen_t mnt_salen = sizeof(mnt_address);
|
||
|
struct pmap mnt_pmap;
|
||
|
char *option;
|
||
|
@@ -510,7 +523,8 @@ nfs_rewrite_pmap_mount_options(struct mo
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
- if (!nfs_construct_new_options(options, &nfs_pmap, &mnt_pmap)) {
|
||
|
+ if (!nfs_construct_new_options(options, nfs_saddr, &nfs_pmap,
|
||
|
+ mnt_saddr, &mnt_pmap)) {
|
||
|
errno = EINVAL;
|
||
|
return 0;
|
||
|
}
|
||
|
@@ -566,7 +580,7 @@ static int nfs_try_mount_v3v2(struct nfs
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
- if (!nfs_fix_mounthost_option(options)) {
|
||
|
+ if (!nfs_fix_mounthost_option(options, mi->hostname)) {
|
||
|
errno = EINVAL;
|
||
|
goto out_fail;
|
||
|
}
|
||
|
@@ -601,7 +615,7 @@ out_fail:
|
||
|
*/
|
||
|
static int nfs_try_mount_v4(struct nfsmount_info *mi)
|
||
|
{
|
||
|
- struct sockaddr *sap = (struct sockaddr *)&mi->address;
|
||
|
+ struct sockaddr *sap = &mi->address.sa;
|
||
|
struct mount_options *options = po_dup(mi->options);
|
||
|
int result = 0;
|
||
|
|
||
|
@@ -611,6 +625,18 @@ static int nfs_try_mount_v4(struct nfsmo
|
||
|
}
|
||
|
|
||
|
if (mi->version == 0) {
|
||
|
+ if (po_contains(options, "mounthost") ||
|
||
|
+ po_contains(options, "mountaddr") ||
|
||
|
+ po_contains(options, "mountvers") ||
|
||
|
+ po_contains(options, "mountproto")) {
|
||
|
+ /*
|
||
|
+ * Since these mountd options are set assume version 3
|
||
|
+ * is wanted so error out with EPROTONOSUPPORT so the
|
||
|
+ * protocol negation starts with v3.
|
||
|
+ */
|
||
|
+ errno = EPROTONOSUPPORT;
|
||
|
+ goto out_fail;
|
||
|
+ }
|
||
|
if (po_append(options, "vers=4") == PO_FAILED) {
|
||
|
errno = EINVAL;
|
||
|
goto out_fail;
|
||
|
@@ -656,9 +682,10 @@ static int nfs_try_mount(struct nfsmount
|
||
|
/*
|
||
|
* To deal with legacy Linux servers that don't
|
||
|
* automatically export a pseudo root, retry
|
||
|
- * ENOENT errors using version 3
|
||
|
+ * ENOENT errors using version 3. And for
|
||
|
+ * Linux servers prior to 2.6.25, retry EPERM
|
||
|
*/
|
||
|
- if (errno != ENOENT)
|
||
|
+ if (errno != ENOENT && errno != EPERM)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
diff -up nfs-utils-1.2.1/utils/nfsd/nfssvc.c.orig nfs-utils-1.2.1/utils/nfsd/nfssvc.c
|
||
|
--- nfs-utils-1.2.1/utils/nfsd/nfssvc.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/nfsd/nfssvc.c 2009-12-14 11:36:12.971751874 -0500
|
||
|
@@ -212,7 +212,7 @@ int
|
||
|
nfssvc_set_sockets(const int family, const unsigned int protobits,
|
||
|
const char *host, const char *port)
|
||
|
{
|
||
|
- struct addrinfo hints = { .ai_flags = AI_PASSIVE | AI_ADDRCONFIG };
|
||
|
+ struct addrinfo hints = { .ai_flags = AI_PASSIVE };
|
||
|
|
||
|
hints.ai_family = family;
|
||
|
|
||
|
diff -up nfs-utils-1.2.1/utils/statd/callback.c.orig nfs-utils-1.2.1/utils/statd/callback.c
|
||
|
--- nfs-utils-1.2.1/utils/statd/callback.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/statd/callback.c 2009-12-14 11:36:12.971751874 -0500
|
||
|
@@ -35,12 +35,12 @@ sm_notify_1_svc(struct stat_chge *argp,
|
||
|
struct sockaddr_in *sin = nfs_getrpccaller_in(rqstp->rq_xprt);
|
||
|
char *ip_addr = xstrdup(inet_ntoa(sin->sin_addr));
|
||
|
|
||
|
- dprintf(N_DEBUG, "Received SM_NOTIFY from %s, state: %d",
|
||
|
+ xlog(D_CALL, "Received SM_NOTIFY from %s, state: %d",
|
||
|
argp->mon_name, argp->state);
|
||
|
|
||
|
/* quick check - don't bother if we're not monitoring anyone */
|
||
|
if (rtnl == NULL) {
|
||
|
- note(N_WARNING, "SM_NOTIFY from %s while not monitoring any hosts.",
|
||
|
+ xlog_warn("SM_NOTIFY from %s while not monitoring any hosts",
|
||
|
argp->mon_name);
|
||
|
return ((void *) &result);
|
||
|
}
|
||
|
diff -up nfs-utils-1.2.1/utils/statd/Makefile.am.orig nfs-utils-1.2.1/utils/statd/Makefile.am
|
||
|
--- nfs-utils-1.2.1/utils/statd/Makefile.am.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/statd/Makefile.am 2009-12-14 11:36:12.971751874 -0500
|
||
|
@@ -13,9 +13,9 @@ RPCPREFIX = rpc.
|
||
|
KPREFIX = @kprefix@
|
||
|
sbin_PROGRAMS = statd sm-notify
|
||
|
dist_sbin_SCRIPTS = start-statd
|
||
|
-statd_SOURCES = callback.c notlist.c log.c misc.c monitor.c \
|
||
|
+statd_SOURCES = callback.c notlist.c misc.c monitor.c \
|
||
|
simu.c stat.c statd.c svc_run.c rmtcall.c \
|
||
|
- sm_inter_clnt.c sm_inter_svc.c sm_inter_xdr.c log.h \
|
||
|
+ sm_inter_clnt.c sm_inter_svc.c sm_inter_xdr.c \
|
||
|
notlist.h statd.h system.h version.h sm_inter.h
|
||
|
sm_notify_SOURCES = sm-notify.c
|
||
|
|
||
|
@@ -24,7 +24,8 @@ statd_LDADD = ../../support/export/libex
|
||
|
../../support/nfs/libnfs.a \
|
||
|
../../support/misc/libmisc.a \
|
||
|
$(LIBWRAP) $(LIBNSL)
|
||
|
-sm_notify_LDADD = $(LIBNSL)
|
||
|
+sm_notify_LDADD = ../../support/nfs/libnfs.a \
|
||
|
+ $(LIBNSL)
|
||
|
|
||
|
EXTRA_DIST = sim_sm_inter.x sm_inter.x $(man8_MANS) COPYRIGHT simulate.c
|
||
|
|
||
|
diff -up nfs-utils-1.2.1/utils/statd/misc.c.orig nfs-utils-1.2.1/utils/statd/misc.c
|
||
|
--- nfs-utils-1.2.1/utils/statd/misc.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/statd/misc.c 2009-12-14 11:36:12.972709739 -0500
|
||
|
@@ -29,8 +29,7 @@ xmalloc (size_t size)
|
||
|
return ((void *)NULL);
|
||
|
|
||
|
if (!(ptr = malloc (size)))
|
||
|
- /* SHIT! SHIT! SHIT! */
|
||
|
- die ("malloc failed");
|
||
|
+ xlog_err ("malloc failed");
|
||
|
|
||
|
return (ptr);
|
||
|
}
|
||
|
@@ -46,7 +45,7 @@ xstrdup (const char *string)
|
||
|
|
||
|
/* Will only fail if underlying malloc() fails (ENOMEM). */
|
||
|
if (!(result = strdup (string)))
|
||
|
- die ("strdup failed");
|
||
|
+ xlog_err ("strdup failed");
|
||
|
|
||
|
return (result);
|
||
|
}
|
||
|
@@ -62,16 +61,15 @@ xunlink (char *path, char *host)
|
||
|
|
||
|
tozap = malloc(strlen(path)+strlen(host)+2);
|
||
|
if (tozap == NULL) {
|
||
|
- note(N_ERROR, "xunlink: malloc failed: errno %d (%s)",
|
||
|
- errno, strerror(errno));
|
||
|
+ xlog(L_ERROR, "xunlink: malloc failed: errno %d (%m)", errno);
|
||
|
return;
|
||
|
}
|
||
|
sprintf (tozap, "%s/%s", path, host);
|
||
|
|
||
|
if (unlink (tozap) == -1)
|
||
|
- note(N_ERROR, "unlink (%s): %s", tozap, strerror (errno));
|
||
|
+ xlog(L_ERROR, "unlink (%s): %m", tozap);
|
||
|
else
|
||
|
- dprintf (N_DEBUG, "Unlinked %s", tozap);
|
||
|
+ xlog(D_GENERAL, "Unlinked %s", tozap);
|
||
|
|
||
|
free(tozap);
|
||
|
}
|
||
|
diff -up nfs-utils-1.2.1/utils/statd/monitor.c.orig nfs-utils-1.2.1/utils/statd/monitor.c
|
||
|
--- nfs-utils-1.2.1/utils/statd/monitor.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/statd/monitor.c 2009-12-14 11:36:12.973788317 -0500
|
||
|
@@ -43,8 +43,7 @@ caller_is_localhost(struct svc_req *rqst
|
||
|
|
||
|
caller = sin->sin_addr;
|
||
|
if (caller.s_addr != htonl(INADDR_LOOPBACK)) {
|
||
|
- note(N_WARNING,
|
||
|
- "Call to statd from non-local host %s",
|
||
|
+ xlog_warn("Call to statd from non-local host %s",
|
||
|
inet_ntoa(caller));
|
||
|
return 0;
|
||
|
}
|
||
|
@@ -69,6 +68,8 @@ sm_mon_1_svc(struct mon *argp, struct sv
|
||
|
char *dnsname;
|
||
|
struct hostent *hostinfo = NULL;
|
||
|
|
||
|
+ xlog(D_CALL, "Received SM_MON for %s from %s", mon_name, my_name);
|
||
|
+
|
||
|
/* Assume that we'll fail. */
|
||
|
result.res_stat = STAT_FAIL;
|
||
|
result.state = -1; /* State is undefined for STAT_FAIL. */
|
||
|
@@ -92,8 +93,7 @@ sm_mon_1_svc(struct mon *argp, struct sv
|
||
|
if (id->my_prog != 100021 ||
|
||
|
(id->my_proc != 16 && id->my_proc != 24))
|
||
|
{
|
||
|
- note(N_WARNING,
|
||
|
- "Attempt to register callback to %d/%d",
|
||
|
+ xlog_warn("Attempt to register callback to %d/%d",
|
||
|
id->my_prog, id->my_proc);
|
||
|
goto failure;
|
||
|
}
|
||
|
@@ -105,12 +105,12 @@ sm_mon_1_svc(struct mon *argp, struct sv
|
||
|
|
||
|
/* must check for /'s in hostname! See CERT's CA-96.09 for details. */
|
||
|
if (strchr(mon_name, '/') || mon_name[0] == '.') {
|
||
|
- note(N_CRIT, "SM_MON request for hostname containing '/' "
|
||
|
+ xlog(L_ERROR, "SM_MON request for hostname containing '/' "
|
||
|
"or starting '.': %s", mon_name);
|
||
|
- note(N_CRIT, "POSSIBLE SPOOF/ATTACK ATTEMPT!");
|
||
|
+ xlog(L_ERROR, "POSSIBLE SPOOF/ATTACK ATTEMPT!");
|
||
|
goto failure;
|
||
|
} else if ((hostinfo = gethostbyname(mon_name)) == NULL) {
|
||
|
- note(N_WARNING, "gethostbyname error for %s", mon_name);
|
||
|
+ xlog_warn("gethostbyname error for %s", mon_name);
|
||
|
goto failure;
|
||
|
}
|
||
|
|
||
|
@@ -152,7 +152,7 @@ sm_mon_1_svc(struct mon *argp, struct sv
|
||
|
NL_MY_VERS(clnt) == id->my_vers &&
|
||
|
memcmp(NL_PRIV(clnt), argp->priv, SM_PRIV_SIZE) == 0) {
|
||
|
/* Hey! We already know you guys! */
|
||
|
- dprintf(N_DEBUG,
|
||
|
+ xlog(D_GENERAL,
|
||
|
"Duplicate SM_MON request for %s "
|
||
|
"from procedure on %s",
|
||
|
mon_name, my_name);
|
||
|
@@ -168,7 +168,7 @@ sm_mon_1_svc(struct mon *argp, struct sv
|
||
|
* doesn't fail. (I should probably fix this assumption.)
|
||
|
*/
|
||
|
if (!(clnt = nlist_new(my_name, mon_name, 0))) {
|
||
|
- note(N_WARNING, "out of memory");
|
||
|
+ xlog_warn("out of memory");
|
||
|
goto failure;
|
||
|
}
|
||
|
|
||
|
@@ -188,7 +188,7 @@ sm_mon_1_svc(struct mon *argp, struct sv
|
||
|
if ((fd = open(path, O_WRONLY|O_SYNC|O_CREAT|O_APPEND,
|
||
|
S_IRUSR|S_IWUSR)) < 0) {
|
||
|
/* Didn't fly. We won't monitor. */
|
||
|
- note(N_ERROR, "creat(%s) failed: %s", path, strerror (errno));
|
||
|
+ xlog(L_ERROR, "creat(%s) failed: %m", path);
|
||
|
nlist_free(NULL, clnt);
|
||
|
free(path);
|
||
|
goto failure;
|
||
|
@@ -205,7 +205,7 @@ sm_mon_1_svc(struct mon *argp, struct sv
|
||
|
if (e+1-buf != LINELEN) abort();
|
||
|
e += sprintf(e, " %s %s\n", mon_name, my_name);
|
||
|
if (write(fd, buf, e-buf) != (e-buf)) {
|
||
|
- note(N_WARNING, "writing to %s failed: errno %d (%s)",
|
||
|
+ xlog_warn("writing to %s failed: errno %d (%s)",
|
||
|
path, errno, strerror(errno));
|
||
|
}
|
||
|
}
|
||
|
@@ -215,7 +215,7 @@ sm_mon_1_svc(struct mon *argp, struct sv
|
||
|
ha_callout("add-client", mon_name, my_name, -1);
|
||
|
nlist_insert(&rtnl, clnt);
|
||
|
close(fd);
|
||
|
- dprintf(N_DEBUG, "MONITORING %s for %s", mon_name, my_name);
|
||
|
+ xlog(D_GENERAL, "MONITORING %s for %s", mon_name, my_name);
|
||
|
success:
|
||
|
result.res_stat = STAT_SUCC;
|
||
|
/* SUN's sm_inter.x says this should be "state number of local site".
|
||
|
@@ -232,7 +232,7 @@ sm_mon_1_svc(struct mon *argp, struct sv
|
||
|
return (&result);
|
||
|
|
||
|
failure:
|
||
|
- note(N_WARNING, "STAT_FAIL to %s for SM_MON of %s", my_name, mon_name);
|
||
|
+ xlog_warn("STAT_FAIL to %s for SM_MON of %s", my_name, mon_name);
|
||
|
return (&result);
|
||
|
}
|
||
|
|
||
|
@@ -320,6 +320,8 @@ sm_unmon_1_svc(struct mon_id *argp, stru
|
||
|
struct my_id *id = &argp->my_id;
|
||
|
char *cp;
|
||
|
|
||
|
+ xlog(D_CALL, "Received SM_UNMON for %s from %s", mon_name, my_name);
|
||
|
+
|
||
|
result.state = MY_STATE;
|
||
|
|
||
|
if (!caller_is_localhost(rqstp))
|
||
|
@@ -333,9 +335,8 @@ sm_unmon_1_svc(struct mon_id *argp, stru
|
||
|
|
||
|
/* Check if we're monitoring anyone. */
|
||
|
if (rtnl == NULL) {
|
||
|
- note(N_WARNING,
|
||
|
- "Received SM_UNMON request from %s for %s while not "
|
||
|
- "monitoring any hosts.", my_name, argp->mon_name);
|
||
|
+ xlog_warn("Received SM_UNMON request from %s for %s while not "
|
||
|
+ "monitoring any hosts", my_name, argp->mon_name);
|
||
|
return (&result);
|
||
|
}
|
||
|
clnt = rtnl;
|
||
|
@@ -352,7 +353,7 @@ sm_unmon_1_svc(struct mon_id *argp, stru
|
||
|
NL_MY_PROG(clnt) == id->my_prog &&
|
||
|
NL_MY_VERS(clnt) == id->my_vers) {
|
||
|
/* Match! */
|
||
|
- dprintf(N_DEBUG, "UNMONITORING %s for %s",
|
||
|
+ xlog(D_GENERAL, "UNMONITORING %s for %s",
|
||
|
mon_name, my_name);
|
||
|
|
||
|
/* PRC: do the HA callout: */
|
||
|
@@ -367,7 +368,7 @@ sm_unmon_1_svc(struct mon_id *argp, stru
|
||
|
}
|
||
|
|
||
|
failure:
|
||
|
- note(N_WARNING, "Received erroneous SM_UNMON request from %s for %s",
|
||
|
+ xlog_warn("Received erroneous SM_UNMON request from %s for %s",
|
||
|
my_name, mon_name);
|
||
|
return (&result);
|
||
|
}
|
||
|
@@ -381,13 +382,15 @@ sm_unmon_all_1_svc(struct my_id *argp, s
|
||
|
notify_list *clnt;
|
||
|
char *my_name = argp->my_name;
|
||
|
|
||
|
+ xlog(D_CALL, "Received SM_UNMON_ALL for %s", my_name);
|
||
|
+
|
||
|
if (!caller_is_localhost(rqstp))
|
||
|
goto failure;
|
||
|
|
||
|
result.state = MY_STATE;
|
||
|
|
||
|
if (rtnl == NULL) {
|
||
|
- note(N_WARNING, "Received SM_UNMON_ALL request from %s "
|
||
|
+ xlog_warn("Received SM_UNMON_ALL request from %s "
|
||
|
"while not monitoring any hosts", my_name);
|
||
|
return (&result);
|
||
|
}
|
||
|
@@ -401,7 +404,7 @@ sm_unmon_all_1_svc(struct my_id *argp, s
|
||
|
char mon_name[SM_MAXSTRLEN + 1];
|
||
|
notify_list *temp;
|
||
|
|
||
|
- dprintf(N_DEBUG,
|
||
|
+ xlog(D_GENERAL,
|
||
|
"UNMONITORING (SM_UNMON_ALL) %s for %s",
|
||
|
NL_MON_NAME(clnt), NL_MY_NAME(clnt));
|
||
|
strncpy(mon_name, NL_MON_NAME(clnt),
|
||
|
@@ -419,8 +422,8 @@ sm_unmon_all_1_svc(struct my_id *argp, s
|
||
|
}
|
||
|
|
||
|
if (!count) {
|
||
|
- dprintf(N_DEBUG, "SM_UNMON_ALL request from %s with no "
|
||
|
- "SM_MON requests from it.", my_name);
|
||
|
+ xlog(D_GENERAL, "SM_UNMON_ALL request from %s with no "
|
||
|
+ "SM_MON requests from it", my_name);
|
||
|
}
|
||
|
|
||
|
failure:
|
||
|
diff -up nfs-utils-1.2.1/utils/statd/rmtcall.c.orig nfs-utils-1.2.1/utils/statd/rmtcall.c
|
||
|
--- nfs-utils-1.2.1/utils/statd/rmtcall.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/statd/rmtcall.c 2009-12-14 11:36:12.973788317 -0500
|
||
|
@@ -43,7 +43,6 @@
|
||
|
#include "sm_inter.h"
|
||
|
#include "statd.h"
|
||
|
#include "notlist.h"
|
||
|
-#include "log.h"
|
||
|
#include "ha-callout.h"
|
||
|
|
||
|
#if SIZEOF_SOCKLEN_T - 0 == 0
|
||
|
@@ -81,7 +80,7 @@ statd_get_socket(void)
|
||
|
if (sockfd >= 0) close(sockfd);
|
||
|
|
||
|
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
|
||
|
- note(N_CRIT, "%s: Can't create socket: %m", __func__);
|
||
|
+ xlog(L_ERROR, "%s: Can't create socket: %m", __func__);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
@@ -91,7 +90,7 @@ statd_get_socket(void)
|
||
|
sin.sin_addr.s_addr = INADDR_ANY;
|
||
|
|
||
|
if (bindresvport(sockfd, &sin) < 0) {
|
||
|
- dprintf(N_WARNING, "%s: can't bind to reserved port",
|
||
|
+ xlog(D_GENERAL, "%s: can't bind to reserved port",
|
||
|
__func__);
|
||
|
break;
|
||
|
}
|
||
|
@@ -150,7 +149,7 @@ xmit_call(struct sockaddr_in *sin,
|
||
|
|
||
|
/* Encode the RPC header part and payload */
|
||
|
if (!xdr_callmsg(xdrs, &mesg) || !func(xdrs, obj)) {
|
||
|
- dprintf(N_WARNING, "%s: can't encode RPC message!", __func__);
|
||
|
+ xlog(D_GENERAL, "%s: can't encode RPC message!", __func__);
|
||
|
xdr_destroy(xdrs);
|
||
|
return 0;
|
||
|
}
|
||
|
@@ -160,9 +159,9 @@ xmit_call(struct sockaddr_in *sin,
|
||
|
|
||
|
if ((err = sendto(sockfd, msgbuf, msglen, 0,
|
||
|
(struct sockaddr *) sin, sizeof(*sin))) < 0) {
|
||
|
- dprintf(N_WARNING, "%s: sendto failed: %m", __func__);
|
||
|
+ xlog_warn("%s: sendto failed: %m", __func__);
|
||
|
} else if (err != msglen) {
|
||
|
- dprintf(N_WARNING, "%s: short write: %m", __func__);
|
||
|
+ xlog_warn("%s: short write: %m", __func__);
|
||
|
}
|
||
|
|
||
|
xdr_destroy(xdrs);
|
||
|
@@ -182,7 +181,7 @@ recv_rply(struct sockaddr_in *sin, u_lon
|
||
|
/* Receive message */
|
||
|
if ((msglen = recvfrom(sockfd, msgbuf, sizeof(msgbuf), 0,
|
||
|
(struct sockaddr *) sin, &alen)) < 0) {
|
||
|
- dprintf(N_WARNING, "%s: recvfrom failed: %m", __func__);
|
||
|
+ xlog_warn("%s: recvfrom failed: %m", __func__);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
@@ -194,19 +193,19 @@ recv_rply(struct sockaddr_in *sin, u_lon
|
||
|
mesg.rm_reply.rp_acpt.ar_results.proc = (xdrproc_t) xdr_void;
|
||
|
|
||
|
if (!xdr_replymsg(xdrs, &mesg)) {
|
||
|
- note(N_WARNING, "%s: can't decode RPC message!", __func__);
|
||
|
+ xlog_warn("%s: can't decode RPC message!", __func__);
|
||
|
goto done;
|
||
|
}
|
||
|
|
||
|
if (mesg.rm_reply.rp_stat != 0) {
|
||
|
- note(N_WARNING, "%s: [%s] RPC status %d",
|
||
|
+ xlog_warn("%s: [%s] RPC status %d",
|
||
|
__func__,
|
||
|
inet_ntoa(sin->sin_addr),
|
||
|
mesg.rm_reply.rp_stat);
|
||
|
goto done;
|
||
|
}
|
||
|
if (mesg.rm_reply.rp_acpt.ar_stat != 0) {
|
||
|
- note(N_WARNING, "%s: [%s] RPC status %d",
|
||
|
+ xlog_warn("%s: [%s] RPC status %d",
|
||
|
__func__,
|
||
|
inet_ntoa(sin->sin_addr),
|
||
|
mesg.rm_reply.rp_acpt.ar_stat);
|
||
|
@@ -224,14 +223,13 @@ recv_rply(struct sockaddr_in *sin, u_lon
|
||
|
strncpy (addr, inet_ntoa(lp->addr),
|
||
|
sizeof (addr) - 1);
|
||
|
addr [sizeof (addr) - 1] = '\0';
|
||
|
- dprintf(N_WARNING, "%s: address mismatch: "
|
||
|
+ xlog_warn("%s: address mismatch: "
|
||
|
"expected %s, got %s", __func__,
|
||
|
addr, inet_ntoa(sin->sin_addr));
|
||
|
}
|
||
|
if (lp->port == 0) {
|
||
|
if (!xdr_u_long(xdrs, portp)) {
|
||
|
- note(N_WARNING,
|
||
|
- "%s: [%s] can't decode reply body!",
|
||
|
+ xlog_warn("%s: [%s] can't decode reply body!",
|
||
|
__func__,
|
||
|
inet_ntoa(sin->sin_addr));
|
||
|
lp = NULL;
|
||
|
@@ -260,7 +258,7 @@ process_entry(notify_list *lp)
|
||
|
/* __u32 proc, vers, prog; */
|
||
|
|
||
|
if (NL_TIMES(lp) == 0) {
|
||
|
- note(N_DEBUG, "%s: Cannot notify %s, giving up.",
|
||
|
+ xlog(D_GENERAL, "%s: Cannot notify %s, giving up",
|
||
|
__func__, inet_ntoa(NL_ADDR(lp)));
|
||
|
return 0;
|
||
|
}
|
||
|
@@ -286,7 +284,7 @@ process_entry(notify_list *lp)
|
||
|
|
||
|
lp->xid = xmit_call(&sin, prog, vers, proc, func, objp);
|
||
|
if (!lp->xid) {
|
||
|
- note(N_WARNING, "%s: failed to notify port %d",
|
||
|
+ xlog_warn("%s: failed to notify port %d",
|
||
|
__func__, ntohs(lp->port));
|
||
|
}
|
||
|
NL_TIMES(lp) -= 1;
|
||
|
@@ -319,10 +317,10 @@ process_reply(FD_SET_TYPE *rfds)
|
||
|
nlist_insert_timer(¬ify, lp);
|
||
|
return 1;
|
||
|
}
|
||
|
- note(N_WARNING, "%s: [%s] service %d not registered",
|
||
|
+ xlog_warn("%s: [%s] service %d not registered",
|
||
|
__func__, inet_ntoa(lp->addr), NL_MY_PROG(lp));
|
||
|
} else {
|
||
|
- dprintf(N_DEBUG, "%s: Callback to %s (for %d) succeeded.",
|
||
|
+ xlog(D_GENERAL, "%s: Callback to %s (for %d) succeeded",
|
||
|
__func__, NL_MY_NAME(lp), NL_MON_NAME(lp));
|
||
|
}
|
||
|
nlist_free(¬ify, lp);
|
||
|
@@ -346,8 +344,8 @@ process_notify_list(void)
|
||
|
nlist_remove(¬ify, entry);
|
||
|
nlist_insert_timer(¬ify, entry);
|
||
|
} else {
|
||
|
- note(N_ERROR,
|
||
|
- "%s: Can't callback %s (%d,%d), giving up.",
|
||
|
+ xlog(L_ERROR,
|
||
|
+ "%s: Can't callback %s (%d,%d), giving up",
|
||
|
__func__,
|
||
|
NL_MY_NAME(entry),
|
||
|
NL_MY_PROG(entry),
|
||
|
diff -up nfs-utils-1.2.1/utils/statd/simu.c.orig nfs-utils-1.2.1/utils/statd/simu.c
|
||
|
--- nfs-utils-1.2.1/utils/statd/simu.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/statd/simu.c 2009-12-14 11:36:12.973788317 -0500
|
||
|
@@ -27,24 +27,26 @@ sm_simu_crash_1_svc (void *argp, struct
|
||
|
static char *result = NULL;
|
||
|
struct in_addr caller;
|
||
|
|
||
|
+ xlog(D_CALL, "Received SM_SIMU_CRASH");
|
||
|
+
|
||
|
if (sin->sin_family != AF_INET) {
|
||
|
- note(N_WARNING, "Call to statd from non-AF_INET address");
|
||
|
+ xlog_warn("Call to statd from non-AF_INET address");
|
||
|
goto failure;
|
||
|
}
|
||
|
|
||
|
caller = sin->sin_addr;
|
||
|
if (caller.s_addr != htonl(INADDR_LOOPBACK)) {
|
||
|
- note(N_WARNING, "Call to statd from non-local host %s",
|
||
|
+ xlog_warn("Call to statd from non-local host %s",
|
||
|
inet_ntoa(caller));
|
||
|
goto failure;
|
||
|
}
|
||
|
|
||
|
if (ntohs(sin->sin_port) >= 1024) {
|
||
|
- note(N_WARNING, "Call to statd-simu-crash from unprivileged port");
|
||
|
+ xlog_warn("Call to statd-simu-crash from unprivileged port");
|
||
|
goto failure;
|
||
|
}
|
||
|
|
||
|
- note (N_WARNING, "*** SIMULATING CRASH! ***");
|
||
|
+ xlog_warn("*** SIMULATING CRASH! ***");
|
||
|
my_svc_exit ();
|
||
|
|
||
|
if (rtnl)
|
||
|
diff -up nfs-utils-1.2.1/utils/statd/simulate.c.orig nfs-utils-1.2.1/utils/statd/simulate.c
|
||
|
--- nfs-utils-1.2.1/utils/statd/simulate.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/statd/simulate.c 2009-12-14 11:36:12.974804690 -0500
|
||
|
@@ -38,7 +38,9 @@ extern void svc_exit (void);
|
||
|
void
|
||
|
simulator (int argc, char **argv)
|
||
|
{
|
||
|
- log_enable (1);
|
||
|
+ xlog_stderr (1);
|
||
|
+ xlog_syslog (0);
|
||
|
+ xlog_open ("statd simulator");
|
||
|
|
||
|
if (argc == 2)
|
||
|
if (!strcasecmp (*argv, "crash"))
|
||
|
@@ -61,7 +63,7 @@ simulator (int argc, char **argv)
|
||
|
simulate_mon (*(&argv[1]), *(&argv[2]), *(&argv[3]), *(&argv[4]),
|
||
|
*(&argv[5]));
|
||
|
}
|
||
|
- die ("WTF? Give me something I can use!");
|
||
|
+ xlog_err ("WTF? Give me something I can use!");
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
@@ -72,11 +74,11 @@ simulate_mon (char *calling, char *monit
|
||
|
sm_stat_res *result;
|
||
|
mon mon;
|
||
|
|
||
|
- dprintf (N_DEBUG, "Calling %s (as %s) to monitor %s", calling, as,
|
||
|
+ xlog (D_GENERAL, "Calling %s (as %s) to monitor %s", calling, as,
|
||
|
monitoring);
|
||
|
|
||
|
if ((client = clnt_create (calling, SM_PROG, SM_VERS, "udp")) == NULL)
|
||
|
- die ("%s", clnt_spcreateerror ("clnt_create"));
|
||
|
+ xlog_err ("%s", clnt_spcreateerror ("clnt_create"));
|
||
|
|
||
|
memcpy (mon.priv, fool, SM_PRIV_SIZE);
|
||
|
mon.mon_id.my_id.my_name = xstrdup (as);
|
||
|
@@ -87,16 +89,15 @@ simulate_mon (char *calling, char *monit
|
||
|
mon.mon_id.mon_name = monitoring;
|
||
|
|
||
|
if (!(result = sm_mon_1 (&mon, client)))
|
||
|
- die ("%s", clnt_sperror (client, "sm_mon_1"));
|
||
|
+ xlog_err ("%s", clnt_sperror (client, "sm_mon_1"));
|
||
|
|
||
|
free (mon.mon_id.my_id.my_name);
|
||
|
|
||
|
if (result->res_stat != STAT_SUCC) {
|
||
|
- note (N_FATAL, "SM_MON request failed, state: %d", result->state);
|
||
|
- exit (0);
|
||
|
+ xlog_err ("SM_MON request failed, state: %d", result->state);
|
||
|
} else {
|
||
|
- dprintf (N_DEBUG, "SM_MON result successful, state: %d\n", result->state);
|
||
|
- dprintf (N_DEBUG, "Waiting for callback.");
|
||
|
+ xlog (D_GENERAL, "SM_MON result successful, state: %d\n", result->state);
|
||
|
+ xlog (D_GENERAL, "Waiting for callback");
|
||
|
daemon_simulator ();
|
||
|
exit (0);
|
||
|
}
|
||
|
@@ -109,11 +110,11 @@ simulate_unmon (char *calling, char *unm
|
||
|
sm_stat *result;
|
||
|
mon_id mon_id;
|
||
|
|
||
|
- dprintf (N_DEBUG, "Calling %s (as %s) to unmonitor %s", calling, as,
|
||
|
+ xlog (D_GENERAL, "Calling %s (as %s) to unmonitor %s", calling, as,
|
||
|
unmonitoring);
|
||
|
|
||
|
if ((client = clnt_create (calling, SM_PROG, SM_VERS, "udp")) == NULL)
|
||
|
- die ("%s", clnt_spcreateerror ("clnt_create"));
|
||
|
+ xlog_err ("%s", clnt_spcreateerror ("clnt_create"));
|
||
|
|
||
|
mon_id.my_id.my_name = xstrdup (as);
|
||
|
mon_id.my_id.my_prog = atoi (proggy) * SIM_SM_PROG;
|
||
|
@@ -122,10 +123,10 @@ simulate_unmon (char *calling, char *unm
|
||
|
mon_id.mon_name = unmonitoring;
|
||
|
|
||
|
if (!(result = sm_unmon_1 (&mon_id, client)))
|
||
|
- die ("%s", clnt_sperror (client, "sm_unmon_1"));
|
||
|
+ xlog_err ("%s", clnt_sperror (client, "sm_unmon_1"));
|
||
|
|
||
|
free (mon_id.my_id.my_name);
|
||
|
- dprintf (N_DEBUG, "SM_UNMON request returned state: %d\n", result->state);
|
||
|
+ xlog (D_GENERAL, "SM_UNMON request returned state: %d\n", result->state);
|
||
|
exit (0);
|
||
|
}
|
||
|
|
||
|
@@ -136,10 +137,10 @@ simulate_unmon_all (char *calling, char
|
||
|
sm_stat *result;
|
||
|
my_id my_id;
|
||
|
|
||
|
- dprintf (N_DEBUG, "Calling %s (as %s) to unmonitor all hosts", calling, as);
|
||
|
+ xlog (D_GENERAL, "Calling %s (as %s) to unmonitor all hosts", calling, as);
|
||
|
|
||
|
if ((client = clnt_create (calling, SM_PROG, SM_VERS, "udp")) == NULL)
|
||
|
- die ("%s", clnt_spcreateerror ("clnt_create"));
|
||
|
+ xlog_err ("%s", clnt_spcreateerror ("clnt_create"));
|
||
|
|
||
|
my_id.my_name = xstrdup (as);
|
||
|
my_id.my_prog = atoi (proggy) * SIM_SM_PROG;
|
||
|
@@ -147,10 +148,10 @@ simulate_unmon_all (char *calling, char
|
||
|
my_id.my_proc = SIM_SM_MON;
|
||
|
|
||
|
if (!(result = sm_unmon_all_1 (&my_id, client)))
|
||
|
- die ("%s", clnt_sperror (client, "sm_unmon_all_1"));
|
||
|
+ xlog_err ("%s", clnt_sperror (client, "sm_unmon_all_1"));
|
||
|
|
||
|
free (my_id.my_name);
|
||
|
- dprintf (N_DEBUG, "SM_UNMON_ALL request returned state: %d\n", result->state);
|
||
|
+ xlog (D_GENERAL, "SM_UNMON_ALL request returned state: %d\n", result->state);
|
||
|
exit (0);
|
||
|
}
|
||
|
|
||
|
@@ -160,10 +161,10 @@ simulate_crash (char *host)
|
||
|
CLIENT *client;
|
||
|
|
||
|
if ((client = clnt_create (host, SM_PROG, SM_VERS, "udp")) == NULL)
|
||
|
- die ("%s", clnt_spcreateerror ("clnt_create"));
|
||
|
+ xlog_err ("%s", clnt_spcreateerror ("clnt_create"));
|
||
|
|
||
|
if (!sm_simu_crash_1 (NULL, client))
|
||
|
- die ("%s", clnt_sperror (client, "sm_simu_crash_1"));
|
||
|
+ xlog_err ("%s", clnt_sperror (client, "sm_simu_crash_1"));
|
||
|
|
||
|
exit (0);
|
||
|
}
|
||
|
@@ -176,18 +177,18 @@ simulate_stat (char *calling, char *moni
|
||
|
sm_stat_res *result;
|
||
|
|
||
|
if ((client = clnt_create (calling, SM_PROG, SM_VERS, "udp")) == NULL)
|
||
|
- die ("%s", clnt_spcreateerror ("clnt_create"));
|
||
|
+ xlog_err ("%s", clnt_spcreateerror ("clnt_create"));
|
||
|
|
||
|
checking.mon_name = monitoring;
|
||
|
|
||
|
if (!(result = sm_stat_1 (&checking, client)))
|
||
|
- die ("%s", clnt_sperror (client, "sm_stat_1"));
|
||
|
+ xlog_err ("%s", clnt_sperror (client, "sm_stat_1"));
|
||
|
|
||
|
if (result->res_stat == STAT_SUCC)
|
||
|
- dprintf (N_DEBUG, "STAT_SUCC from %s for %s, state: %d", calling,
|
||
|
+ xlog (D_GENERAL, "STAT_SUCC from %s for %s, state: %d", calling,
|
||
|
monitoring, result->state);
|
||
|
else
|
||
|
- dprintf (N_DEBUG, "STAT_FAIL from %s for %s, state: %d", calling,
|
||
|
+ xlog (D_GENERAL, "STAT_FAIL from %s for %s, state: %d", calling,
|
||
|
monitoring, result->state);
|
||
|
|
||
|
exit (0);
|
||
|
@@ -196,9 +197,8 @@ simulate_stat (char *calling, char *moni
|
||
|
static void
|
||
|
sim_killer (int sig)
|
||
|
{
|
||
|
- note (N_FATAL, "Simulator caught signal %d, un-registering and exiting.", sig);
|
||
|
pmap_unset (sim_port, SIM_SM_VERS);
|
||
|
- exit (0);
|
||
|
+ xlog_err ("Simulator caught signal %d, un-registering and exiting", sig);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
@@ -219,7 +219,7 @@ sim_sm_mon_1_svc (struct status *argp, s
|
||
|
{
|
||
|
static char *result;
|
||
|
|
||
|
- dprintf (N_DEBUG, "Recieved state %d for mon_name %s (opaque \"%s\")",
|
||
|
+ xlog (D_GENERAL, "Recieved state %d for mon_name %s (opaque \"%s\")",
|
||
|
argp->state, argp->mon_name, argp->priv);
|
||
|
svc_exit ();
|
||
|
return ((void *)&result);
|
||
|
diff -up nfs-utils-1.2.1/utils/statd/sm-notify.c.orig nfs-utils-1.2.1/utils/statd/sm-notify.c
|
||
|
--- nfs-utils-1.2.1/utils/statd/sm-notify.c.orig 2009-12-14 11:35:16.308700575 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/statd/sm-notify.c 2009-12-14 11:36:12.975820742 -0500
|
||
|
@@ -30,6 +30,9 @@
|
||
|
|
||
|
#define STATD_PATH_XTN "statd/"
|
||
|
|
||
|
+#include "xlog.h"
|
||
|
+#include "nfsrpc.h"
|
||
|
+
|
||
|
#ifndef BASEDIR
|
||
|
# ifdef NFS_STATEDIR
|
||
|
# define BASEDIR NFS_STATEDIR "/" STATD_PATH_XTN
|
||
|
@@ -71,12 +74,10 @@ struct nsm_host {
|
||
|
static char nsm_hostname[256];
|
||
|
static uint32_t nsm_state;
|
||
|
static int opt_debug = 0;
|
||
|
-static int opt_quiet = 0;
|
||
|
static int opt_update_state = 1;
|
||
|
static unsigned int opt_max_retry = 15 * 60;
|
||
|
static char * opt_srcaddr = 0;
|
||
|
static uint16_t opt_srcport = 0;
|
||
|
-static int log_syslog = 0;
|
||
|
|
||
|
static unsigned int nsm_get_state(int);
|
||
|
static void notify(void);
|
||
|
@@ -86,40 +87,12 @@ static void backup_hosts(const char *,
|
||
|
static void get_hosts(const char *);
|
||
|
static void insert_host(struct nsm_host *);
|
||
|
static struct nsm_host *find_host(uint32_t);
|
||
|
-static void nsm_log(int fac, const char *fmt, ...);
|
||
|
static int record_pid(void);
|
||
|
static void drop_privs(void);
|
||
|
static void set_kernel_nsm_state(int state);
|
||
|
|
||
|
static struct nsm_host * hosts = NULL;
|
||
|
|
||
|
-/*
|
||
|
- * Address handling utilities
|
||
|
- */
|
||
|
-
|
||
|
-static unsigned short smn_get_port(const struct sockaddr *sap)
|
||
|
-{
|
||
|
- switch (sap->sa_family) {
|
||
|
- case AF_INET:
|
||
|
- return ntohs(((struct sockaddr_in *)sap)->sin_port);
|
||
|
- case AF_INET6:
|
||
|
- return ntohs(((struct sockaddr_in6 *)sap)->sin6_port);
|
||
|
- }
|
||
|
- return 0;
|
||
|
-}
|
||
|
-
|
||
|
-static void smn_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;
|
||
|
- }
|
||
|
-}
|
||
|
-
|
||
|
static struct addrinfo *smn_lookup(const char *name)
|
||
|
{
|
||
|
struct addrinfo *ai, hint = {
|
||
|
@@ -132,21 +105,12 @@ static struct addrinfo *smn_lookup(const
|
||
|
int error;
|
||
|
|
||
|
error = getaddrinfo(name, NULL, &hint, &ai);
|
||
|
- switch (error) {
|
||
|
- case 0:
|
||
|
- return ai;
|
||
|
- case EAI_SYSTEM:
|
||
|
- if (opt_debug)
|
||
|
- nsm_log(LOG_ERR, "getaddrinfo(3): %s",
|
||
|
- strerror(errno));
|
||
|
- break;
|
||
|
- default:
|
||
|
- if (opt_debug)
|
||
|
- nsm_log(LOG_ERR, "getaddrinfo(3): %s",
|
||
|
- gai_strerror(error));
|
||
|
+ if (error) {
|
||
|
+ xlog(D_GENERAL, "getaddrinfo(3): %s", gai_strerror(error));
|
||
|
+ return NULL;
|
||
|
}
|
||
|
|
||
|
- return NULL;
|
||
|
+ return ai;
|
||
|
}
|
||
|
|
||
|
static void smn_forget_host(struct nsm_host *host)
|
||
|
@@ -165,8 +129,15 @@ main(int argc, char **argv)
|
||
|
{
|
||
|
int c;
|
||
|
int force = 0;
|
||
|
+ char * progname;
|
||
|
+
|
||
|
+ progname = strrchr(argv[0], '/');
|
||
|
+ if (progname != NULL)
|
||
|
+ progname++;
|
||
|
+ else
|
||
|
+ progname = argv[0];
|
||
|
|
||
|
- while ((c = getopt(argc, argv, "dm:np:v:qP:f")) != -1) {
|
||
|
+ while ((c = getopt(argc, argv, "dm:np:v:P:f")) != -1) {
|
||
|
switch (c) {
|
||
|
case 'f':
|
||
|
force = 1;
|
||
|
@@ -186,9 +157,6 @@ main(int argc, char **argv)
|
||
|
case 'v':
|
||
|
opt_srcaddr = optarg;
|
||
|
break;
|
||
|
- case 'q':
|
||
|
- opt_quiet = 1;
|
||
|
- break;
|
||
|
case 'P':
|
||
|
_SM_BASE_PATH = strdup(optarg);
|
||
|
_SM_STATE_PATH = malloc(strlen(optarg)+1+sizeof("state"));
|
||
|
@@ -198,7 +166,7 @@ main(int argc, char **argv)
|
||
|
_SM_STATE_PATH == NULL ||
|
||
|
_SM_DIR_PATH == NULL ||
|
||
|
_SM_BAK_PATH == NULL) {
|
||
|
- nsm_log(LOG_ERR, "unable to allocate memory");
|
||
|
+ fprintf(stderr, "unable to allocate memory");
|
||
|
exit(1);
|
||
|
}
|
||
|
strcat(strcpy(_SM_STATE_PATH, _SM_BASE_PATH), "/state");
|
||
|
@@ -213,18 +181,26 @@ main(int argc, char **argv)
|
||
|
|
||
|
if (optind < argc) {
|
||
|
usage: fprintf(stderr,
|
||
|
- "Usage: sm-notify [-dfq] [-m max-retry-minutes] [-p srcport]\n"
|
||
|
- " [-P /path/to/state/directory] [-v my_host_name]\n");
|
||
|
+ "Usage: %s -notify [-dfq] [-m max-retry-minutes] [-p srcport]\n"
|
||
|
+ " [-P /path/to/state/directory] [-v my_host_name]\n",
|
||
|
+ progname);
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
- log_syslog = 1;
|
||
|
- openlog("sm-notify", LOG_PID, LOG_DAEMON);
|
||
|
+ xlog_syslog(1);
|
||
|
+ if (opt_debug) {
|
||
|
+ xlog_stderr(1);
|
||
|
+ xlog_config(D_ALL, 1);
|
||
|
+ } else
|
||
|
+ xlog_stderr(0);
|
||
|
+
|
||
|
+ xlog_open(progname);
|
||
|
+ xlog(L_NOTICE, "Version " VERSION " starting");
|
||
|
|
||
|
if (strcmp(_SM_BASE_PATH, BASEDIR) == 0) {
|
||
|
if (record_pid() == 0 && force == 0 && opt_update_state == 1) {
|
||
|
/* already run, don't try again */
|
||
|
- nsm_log(LOG_NOTICE, "Already notifying clients; Exiting!");
|
||
|
+ xlog(L_NOTICE, "Already notifying clients; Exiting!");
|
||
|
exit(0);
|
||
|
}
|
||
|
}
|
||
|
@@ -233,8 +209,7 @@ usage: fprintf(stderr,
|
||
|
strncpy(nsm_hostname, opt_srcaddr, sizeof(nsm_hostname)-1);
|
||
|
} else
|
||
|
if (gethostname(nsm_hostname, sizeof(nsm_hostname)) < 0) {
|
||
|
- nsm_log(LOG_ERR, "Failed to obtain name of local host: %s",
|
||
|
- strerror(errno));
|
||
|
+ xlog(L_ERROR, "Failed to obtain name of local host: %m");
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
@@ -243,7 +218,7 @@ usage: fprintf(stderr,
|
||
|
|
||
|
/* If there are not hosts to notify, just exit */
|
||
|
if (!hosts) {
|
||
|
- nsm_log(LOG_DEBUG, "No hosts to notify; exiting");
|
||
|
+ xlog(D_GENERAL, "No hosts to notify; exiting");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@@ -252,12 +227,10 @@ usage: fprintf(stderr,
|
||
|
set_kernel_nsm_state(nsm_state);
|
||
|
|
||
|
if (!opt_debug) {
|
||
|
- if (!opt_quiet)
|
||
|
- printf("Backgrounding to notify hosts...\n");
|
||
|
+ xlog(L_NOTICE, "Backgrounding to notify hosts...\n");
|
||
|
|
||
|
if (daemon(0, 0) < 0) {
|
||
|
- nsm_log(LOG_ERR, "unable to background: %s",
|
||
|
- strerror(errno));
|
||
|
+ xlog(L_ERROR, "unable to background: %m");
|
||
|
exit(1);
|
||
|
}
|
||
|
|
||
|
@@ -273,8 +246,7 @@ usage: fprintf(stderr,
|
||
|
|
||
|
while ((hp = hosts) != 0) {
|
||
|
hosts = hp->next;
|
||
|
- nsm_log(LOG_NOTICE,
|
||
|
- "Unable to notify %s, giving up",
|
||
|
+ xlog(L_NOTICE, "Unable to notify %s, giving up",
|
||
|
hp->name);
|
||
|
}
|
||
|
exit(1);
|
||
|
@@ -298,8 +270,7 @@ notify(void)
|
||
|
retry:
|
||
|
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||
|
if (sock < 0) {
|
||
|
- nsm_log(LOG_ERR, "Failed to create RPC socket: %s",
|
||
|
- strerror(errno));
|
||
|
+ xlog(L_ERROR, "Failed to create RPC socket: %m");
|
||
|
exit(1);
|
||
|
}
|
||
|
fcntl(sock, F_SETFL, O_NONBLOCK);
|
||
|
@@ -311,7 +282,7 @@ notify(void)
|
||
|
if (opt_srcaddr) {
|
||
|
struct addrinfo *ai = smn_lookup(opt_srcaddr);
|
||
|
if (!ai) {
|
||
|
- nsm_log(LOG_ERR,
|
||
|
+ xlog(L_ERROR,
|
||
|
"Not a valid hostname or address: \"%s\"",
|
||
|
opt_srcaddr);
|
||
|
exit(1);
|
||
|
@@ -326,10 +297,9 @@ notify(void)
|
||
|
/* Use source port if provided on the command line,
|
||
|
* otherwise use bindresvport */
|
||
|
if (opt_srcport) {
|
||
|
- smn_set_port(local_addr, opt_srcport);
|
||
|
+ nfs_set_port(local_addr, opt_srcport);
|
||
|
if (bind(sock, local_addr, sizeof(struct sockaddr_in)) < 0) {
|
||
|
- nsm_log(LOG_ERR, "Failed to bind RPC socket: %s",
|
||
|
- strerror(errno));
|
||
|
+ xlog(L_ERROR, "Failed to bind RPC socket: %m");
|
||
|
exit(1);
|
||
|
}
|
||
|
} else {
|
||
|
@@ -385,7 +355,7 @@ notify(void)
|
||
|
if (hosts == NULL)
|
||
|
return;
|
||
|
|
||
|
- nsm_log(LOG_DEBUG, "Host %s due in %ld seconds",
|
||
|
+ xlog(D_GENERAL, "Host %s due in %ld seconds",
|
||
|
hosts->name, wait);
|
||
|
|
||
|
pfd.fd = sock;
|
||
|
@@ -422,8 +392,7 @@ notify_host(int sock, struct nsm_host *h
|
||
|
if (host->ai == NULL) {
|
||
|
host->ai = smn_lookup(host->name);
|
||
|
if (host->ai == NULL) {
|
||
|
- nsm_log(LOG_WARNING,
|
||
|
- "DNS resolution of %s failed; "
|
||
|
+ xlog_warn("DNS resolution of %s failed; "
|
||
|
"retrying later", host->name);
|
||
|
return 0;
|
||
|
}
|
||
|
@@ -462,16 +431,16 @@ notify_host(int sock, struct nsm_host *h
|
||
|
first->ai_addrlen);
|
||
|
}
|
||
|
|
||
|
- smn_set_port((struct sockaddr *)&host->addr, 0);
|
||
|
+ nfs_set_port((struct sockaddr *)&host->addr, 0);
|
||
|
host->retries = 0;
|
||
|
}
|
||
|
|
||
|
memcpy(dest, &host->addr, destlen);
|
||
|
- if (smn_get_port(dest) == 0) {
|
||
|
+ if (nfs_get_port(dest) == 0) {
|
||
|
/* Build a PMAP packet */
|
||
|
- nsm_log(LOG_DEBUG, "Sending portmap query to %s", host->name);
|
||
|
+ xlog(D_GENERAL, "Sending portmap query to %s", host->name);
|
||
|
|
||
|
- smn_set_port(dest, 111);
|
||
|
+ nfs_set_port(dest, 111);
|
||
|
*p++ = htonl(100000);
|
||
|
*p++ = htonl(2);
|
||
|
*p++ = htonl(3);
|
||
|
@@ -486,7 +455,7 @@ notify_host(int sock, struct nsm_host *h
|
||
|
*p++ = 0;
|
||
|
} else {
|
||
|
/* Build an SM_NOTIFY packet */
|
||
|
- nsm_log(LOG_DEBUG, "Sending SM_NOTIFY to %s", host->name);
|
||
|
+ xlog(D_GENERAL, "Sending SM_NOTIFY to %s", host->name);
|
||
|
|
||
|
*p++ = htonl(NSM_PROGRAM);
|
||
|
*p++ = htonl(NSM_VERSION);
|
||
|
@@ -506,8 +475,8 @@ notify_host(int sock, struct nsm_host *h
|
||
|
len = (p - msgbuf) << 2;
|
||
|
|
||
|
if (sendto(sock, msgbuf, len, 0, dest, destlen) < 0)
|
||
|
- nsm_log(LOG_WARNING, "Sending Reboot Notification to "
|
||
|
- "'%s' failed: errno %d (%s)", host->name, errno, strerror(errno));
|
||
|
+ xlog_warn("Sending Reboot Notification to "
|
||
|
+ "'%s' failed: errno %d (%m)", host->name, errno);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
@@ -528,7 +497,7 @@ recv_reply(int sock)
|
||
|
if (res < 0)
|
||
|
return;
|
||
|
|
||
|
- nsm_log(LOG_DEBUG, "Received packet...");
|
||
|
+ xlog(D_GENERAL, "Received packet...");
|
||
|
|
||
|
p = msgbuf;
|
||
|
end = p + (res >> 2);
|
||
|
@@ -547,7 +516,7 @@ recv_reply(int sock)
|
||
|
return;
|
||
|
sap = (struct sockaddr *)&hp->addr;
|
||
|
|
||
|
- if (smn_get_port(sap) == 0) {
|
||
|
+ if (nfs_get_port(sap) == 0) {
|
||
|
/* This was a portmap request */
|
||
|
unsigned int port;
|
||
|
|
||
|
@@ -559,11 +528,11 @@ recv_reply(int sock)
|
||
|
if (port == 0) {
|
||
|
/* No binding for statd. Delay the next
|
||
|
* portmap query for max timeout */
|
||
|
- nsm_log(LOG_DEBUG, "No statd on %s", hp->name);
|
||
|
+ xlog(D_GENERAL, "No statd on %s", hp->name);
|
||
|
hp->timeout = NSM_MAX_TIMEOUT;
|
||
|
hp->send_next += NSM_MAX_TIMEOUT;
|
||
|
} else {
|
||
|
- smn_set_port(sap, port);
|
||
|
+ nfs_set_port(sap, port);
|
||
|
if (hp->timeout >= NSM_MAX_TIMEOUT / 4)
|
||
|
hp->timeout = NSM_MAX_TIMEOUT / 4;
|
||
|
}
|
||
|
@@ -575,7 +544,7 @@ recv_reply(int sock)
|
||
|
* packet)
|
||
|
*/
|
||
|
if (p <= end) {
|
||
|
- nsm_log(LOG_DEBUG, "Host %s notified successfully",
|
||
|
+ xlog(D_GENERAL, "Host %s notified successfully",
|
||
|
hp->name);
|
||
|
smn_forget_host(hp);
|
||
|
return;
|
||
|
@@ -596,8 +565,7 @@ backup_hosts(const char *dirname, const
|
||
|
DIR *dir;
|
||
|
|
||
|
if (!(dir = opendir(dirname))) {
|
||
|
- nsm_log(LOG_WARNING,
|
||
|
- "Failed to open %s: %s", dirname, strerror(errno));
|
||
|
+ xlog_warn("Failed to open %s: %m", dirname);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
@@ -609,11 +577,8 @@ backup_hosts(const char *dirname, const
|
||
|
|
||
|
snprintf(src, sizeof(src), "%s/%s", dirname, de->d_name);
|
||
|
snprintf(dst, sizeof(dst), "%s/%s", bakname, de->d_name);
|
||
|
- if (rename(src, dst) < 0) {
|
||
|
- nsm_log(LOG_WARNING,
|
||
|
- "Failed to rename %s -> %s: %m",
|
||
|
- src, dst);
|
||
|
- }
|
||
|
+ if (rename(src, dst) < 0)
|
||
|
+ xlog_warn("Failed to rename %s -> %s: %m", src, dst);
|
||
|
}
|
||
|
closedir(dir);
|
||
|
}
|
||
|
@@ -629,8 +594,7 @@ get_hosts(const char *dirname)
|
||
|
DIR *dir;
|
||
|
|
||
|
if (!(dir = opendir(dirname))) {
|
||
|
- nsm_log(LOG_WARNING,
|
||
|
- "Failed to open %s: %s", dirname, strerror(errno));
|
||
|
+ xlog_warn("Failed to open %s: %m", dirname);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
@@ -644,7 +608,7 @@ get_hosts(const char *dirname)
|
||
|
if (host == NULL)
|
||
|
host = calloc(1, sizeof(*host));
|
||
|
if (host == NULL) {
|
||
|
- nsm_log(LOG_WARNING, "Unable to allocate memory");
|
||
|
+ xlog_warn("Unable to allocate memory");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
@@ -725,17 +689,14 @@ nsm_get_state(int update)
|
||
|
int fd, state;
|
||
|
|
||
|
if ((fd = open(_SM_STATE_PATH, O_RDONLY)) < 0) {
|
||
|
- if (!opt_quiet) {
|
||
|
- nsm_log(LOG_WARNING, "%s: %m", _SM_STATE_PATH);
|
||
|
- nsm_log(LOG_WARNING, "Creating %s, set initial state 1",
|
||
|
- _SM_STATE_PATH);
|
||
|
- }
|
||
|
+ xlog_warn("%s: %m", _SM_STATE_PATH);
|
||
|
+ xlog_warn("Creating %s, set initial state 1",
|
||
|
+ _SM_STATE_PATH);
|
||
|
state = 1;
|
||
|
update = 1;
|
||
|
} else {
|
||
|
if (read(fd, &state, sizeof(state)) != sizeof(state)) {
|
||
|
- nsm_log(LOG_WARNING,
|
||
|
- "%s: bad file size, setting state = 1",
|
||
|
+ xlog_warn("%s: bad file size, setting state = 1",
|
||
|
_SM_STATE_PATH);
|
||
|
state = 1;
|
||
|
update = 1;
|
||
|
@@ -751,17 +712,17 @@ nsm_get_state(int update)
|
||
|
snprintf(newfile, sizeof(newfile),
|
||
|
"%s.new", _SM_STATE_PATH);
|
||
|
if ((fd = open(newfile, O_CREAT|O_WRONLY, 0644)) < 0) {
|
||
|
- nsm_log(LOG_ERR, "Cannot create %s: %m", newfile);
|
||
|
+ xlog(L_ERROR, "Cannot create %s: %m", newfile);
|
||
|
exit(1);
|
||
|
}
|
||
|
if (write(fd, &state, sizeof(state)) != sizeof(state)) {
|
||
|
- nsm_log(LOG_ERR,
|
||
|
+ xlog(L_ERROR,
|
||
|
"Failed to write state to %s", newfile);
|
||
|
exit(1);
|
||
|
}
|
||
|
close(fd);
|
||
|
if (rename(newfile, _SM_STATE_PATH) < 0) {
|
||
|
- nsm_log(LOG_ERR,
|
||
|
+ xlog(L_ERROR,
|
||
|
"Cannot create %s: %m", _SM_STATE_PATH);
|
||
|
exit(1);
|
||
|
}
|
||
|
@@ -772,27 +733,6 @@ nsm_get_state(int update)
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
- * Log a message
|
||
|
- */
|
||
|
-static void
|
||
|
-nsm_log(int fac, const char *fmt, ...)
|
||
|
-{
|
||
|
- va_list ap;
|
||
|
-
|
||
|
- if (fac == LOG_DEBUG && !opt_debug)
|
||
|
- return;
|
||
|
-
|
||
|
- va_start(ap, fmt);
|
||
|
- if (log_syslog)
|
||
|
- vsyslog(fac, fmt, ap);
|
||
|
- else {
|
||
|
- vfprintf(stderr, fmt, ap);
|
||
|
- fputs("\n", stderr);
|
||
|
- }
|
||
|
- va_end(ap);
|
||
|
-}
|
||
|
-
|
||
|
-/*
|
||
|
* Record pid in /var/run/sm-notify.pid
|
||
|
* This file should remain until a reboot, even if the
|
||
|
* program exits.
|
||
|
@@ -801,17 +741,21 @@ nsm_log(int fac, const char *fmt, ...)
|
||
|
static int record_pid(void)
|
||
|
{
|
||
|
char pid[20];
|
||
|
+ ssize_t len;
|
||
|
int fd;
|
||
|
|
||
|
- snprintf(pid, 20, "%d\n", getpid());
|
||
|
+ (void)snprintf(pid, sizeof(pid), "%d\n", (int)getpid());
|
||
|
fd = open("/var/run/sm-notify.pid", O_CREAT|O_EXCL|O_WRONLY, 0600);
|
||
|
if (fd < 0)
|
||
|
return 0;
|
||
|
- if (write(fd, pid, strlen(pid)) != strlen(pid)) {
|
||
|
- nsm_log(LOG_WARNING, "Writing to pid file failed: errno %d(%s)",
|
||
|
- errno, strerror(errno));
|
||
|
+
|
||
|
+ len = write(fd, pid, strlen(pid));
|
||
|
+ if ((len < 0) || ((size_t)len != strlen(pid))) {
|
||
|
+ xlog_warn("Writing to pid file failed: errno %d (%m)",
|
||
|
+ errno);
|
||
|
}
|
||
|
- close(fd);
|
||
|
+
|
||
|
+ (void)close(fd);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
@@ -829,16 +773,15 @@ static void drop_privs(void)
|
||
|
}
|
||
|
|
||
|
if (st.st_uid == 0) {
|
||
|
- nsm_log(LOG_WARNING,
|
||
|
- "sm-notify running as root. chown %s to choose different user",
|
||
|
- _SM_DIR_PATH);
|
||
|
+ xlog_warn("Running as 'root'. "
|
||
|
+ "chown %s to choose different user", _SM_DIR_PATH);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
setgroups(0, NULL);
|
||
|
if (setgid(st.st_gid) == -1
|
||
|
|| setuid(st.st_uid) == -1) {
|
||
|
- nsm_log(LOG_ERR, "Fail to drop privileges");
|
||
|
+ xlog(L_ERROR, "Fail to drop privileges");
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
@@ -853,8 +796,8 @@ static void set_kernel_nsm_state(int sta
|
||
|
char buf[20];
|
||
|
snprintf(buf, sizeof(buf), "%d", state);
|
||
|
if (write(fd, buf, strlen(buf)) != strlen(buf)) {
|
||
|
- nsm_log(LOG_WARNING, "Writing to '%s' failed: errno %d (%s)",
|
||
|
- file, errno, strerror(errno));
|
||
|
+ xlog_warn("Writing to '%s' failed: errno %d (%m)",
|
||
|
+ file, errno);
|
||
|
}
|
||
|
close(fd);
|
||
|
}
|
||
|
diff -up nfs-utils-1.2.1/utils/statd/sm-notify.man.orig nfs-utils-1.2.1/utils/statd/sm-notify.man
|
||
|
--- nfs-utils-1.2.1/utils/statd/sm-notify.man.orig 2009-12-14 11:35:16.308700575 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/statd/sm-notify.man 2009-12-14 11:36:12.975820742 -0500
|
||
|
@@ -6,7 +6,7 @@
|
||
|
.SH NAME
|
||
|
sm-notify \- Send out NSM reboot notifications
|
||
|
.SH SYNOPSIS
|
||
|
-.BI "/sbin/sm-notify [-dfq] [-m " time "] [-p " port "] [-P " path "] [-v " my_name " ]
|
||
|
+.BI "/sbin/sm-notify [-df] [-m " time "] [-p " port "] [-P " path "] [-v " my_name " ]
|
||
|
.SH DESCRIPTION
|
||
|
File locking over NFS (v2 and v3) requires a facility to notify peers in
|
||
|
case of a reboot, so that clients can reclaim locks after
|
||
|
@@ -101,10 +101,6 @@ to bind to the indicated IP
|
||
|
number. If this option is not given, it will try to bind to
|
||
|
a randomly chosen privileged port below 1024.
|
||
|
.TP
|
||
|
-.B -q
|
||
|
-Be quiet. This suppresses all messages except error
|
||
|
-messages while collecting the list of hosts.
|
||
|
-.TP
|
||
|
.BI -P " /path/to/state/directory
|
||
|
If
|
||
|
.B sm-notify
|
||
|
diff -up nfs-utils-1.2.1/utils/statd/stat.c.orig nfs-utils-1.2.1/utils/statd/stat.c
|
||
|
--- nfs-utils-1.2.1/utils/statd/stat.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/statd/stat.c 2009-12-14 11:36:12.976836745 -0500
|
||
|
@@ -42,13 +42,15 @@ sm_stat_1_svc (struct sm_name *argp, str
|
||
|
{
|
||
|
static sm_stat_res result;
|
||
|
|
||
|
+ xlog(D_CALL, "Received SM_STAT from %s", argp->mon_name);
|
||
|
+
|
||
|
if (gethostbyname (argp->mon_name) == NULL) {
|
||
|
- note (N_WARNING, "gethostbyname error for %s", argp->mon_name);
|
||
|
+ xlog_warn ("gethostbyname error for %s", argp->mon_name);
|
||
|
result.res_stat = STAT_FAIL;
|
||
|
- dprintf (N_DEBUG, "STAT_FAIL for %s", argp->mon_name);
|
||
|
+ xlog (D_GENERAL, "STAT_FAIL for %s", argp->mon_name);
|
||
|
} else {
|
||
|
result.res_stat = STAT_SUCC;
|
||
|
- dprintf (N_DEBUG, "STAT_SUCC for %s", argp->mon_name);
|
||
|
+ xlog (D_GENERAL, "STAT_SUCC for %s", argp->mon_name);
|
||
|
}
|
||
|
result.state = MY_STATE;
|
||
|
return(&result);
|
||
|
diff -up nfs-utils-1.2.1/utils/statd/statd.c.orig nfs-utils-1.2.1/utils/statd/statd.c
|
||
|
--- nfs-utils-1.2.1/utils/statd/statd.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/statd/statd.c 2009-12-14 11:36:12.976836745 -0500
|
||
|
@@ -26,7 +26,6 @@
|
||
|
#include <sys/wait.h>
|
||
|
#include <grp.h>
|
||
|
#include "statd.h"
|
||
|
-#include "version.h"
|
||
|
#include "nfslib.h"
|
||
|
|
||
|
/* Socket operations */
|
||
|
@@ -50,8 +49,7 @@ int run_mode = 0; /* foreground logging
|
||
|
/* LH - I had these local to main, but it seemed silly to have
|
||
|
* two copies of each - one in main(), one static in log.c...
|
||
|
* It also eliminates the 256-char static in log.c */
|
||
|
-char *name_p = NULL;
|
||
|
-const char *version_p = NULL;
|
||
|
+static char *name_p = NULL;
|
||
|
|
||
|
/* PRC: a high-availability callout program can be specified with -H
|
||
|
* When this is done, the program will receive callouts whenever clients
|
||
|
@@ -109,17 +107,15 @@ sm_prog_1_wrapper (struct svc_req *rqstp
|
||
|
static void
|
||
|
killer (int sig)
|
||
|
{
|
||
|
- note (N_FATAL, "Caught signal %d, un-registering and exiting.", sig);
|
||
|
pmap_unset (SM_PROG, SM_VERS);
|
||
|
-
|
||
|
- exit (0);
|
||
|
+ xlog_err ("Caught signal %d, un-registering and exiting", sig);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
sigusr (int sig)
|
||
|
{
|
||
|
extern void my_svc_exit (void);
|
||
|
- dprintf (N_DEBUG, "Caught signal %d, re-notifying (state %d).", sig,
|
||
|
+ xlog(D_GENERAL, "Caught signal %d, re-notifying (state %d)", sig,
|
||
|
MY_STATE);
|
||
|
my_svc_exit();
|
||
|
}
|
||
|
@@ -141,7 +137,7 @@ static void log_modes(void)
|
||
|
if (run_mode & MODE_LOG_STDERR)
|
||
|
strcat(buf,"Log-STDERR ");
|
||
|
|
||
|
- note(N_WARNING,buf);
|
||
|
+ xlog_warn(buf);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
@@ -175,13 +171,12 @@ static void create_pidfile(void)
|
||
|
unlink(pidfile);
|
||
|
fp = fopen(pidfile, "w");
|
||
|
if (!fp)
|
||
|
- die("Opening %s failed: %s\n",
|
||
|
- pidfile, strerror(errno));
|
||
|
+ xlog_err("Opening %s failed: %m\n", pidfile);
|
||
|
fprintf(fp, "%d\n", getpid());
|
||
|
pidfd = dup(fileno(fp));
|
||
|
if (fclose(fp) < 0) {
|
||
|
- note(N_WARNING, "Flushing pid file failed: errno %d (%s)\n",
|
||
|
- errno, strerror(errno));
|
||
|
+ xlog_warn("Flushing pid file failed: errno %d (%m)\n",
|
||
|
+ errno);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@@ -189,8 +184,8 @@ static void truncate_pidfile(void)
|
||
|
{
|
||
|
if (pidfd >= 0) {
|
||
|
if (ftruncate(pidfd, 0) < 0) {
|
||
|
- note(N_WARNING, "truncating pid file failed: errno %d (%s)\n",
|
||
|
- errno, strerror(errno));
|
||
|
+ xlog_warn("truncating pid file failed: errno %d (%m)\n",
|
||
|
+ errno);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
@@ -206,8 +201,8 @@ static void drop_privs(void)
|
||
|
}
|
||
|
|
||
|
if (st.st_uid == 0) {
|
||
|
- note(N_WARNING, "statd running as root. chown %s to choose different user\n",
|
||
|
- SM_DIR);
|
||
|
+ xlog_warn("Running as 'root'. "
|
||
|
+ "chown %s to choose different user\n", SM_DIR);
|
||
|
return;
|
||
|
}
|
||
|
/* better chown the pid file before dropping, as if it
|
||
|
@@ -215,14 +210,14 @@ static void drop_privs(void)
|
||
|
*/
|
||
|
if (pidfd >= 0) {
|
||
|
if (fchown(pidfd, st.st_uid, st.st_gid) < 0) {
|
||
|
- note(N_ERROR, "Unable to change owner of %s: %d (%s)",
|
||
|
+ xlog(L_ERROR, "Unable to change owner of %s: %d (%s)",
|
||
|
SM_DIR, strerror (errno));
|
||
|
}
|
||
|
}
|
||
|
setgroups(0, NULL);
|
||
|
if (setgid(st.st_gid) == -1
|
||
|
|| setuid(st.st_uid) == -1) {
|
||
|
- note(N_ERROR, "Fail to drop privileges");
|
||
|
+ xlog(L_ERROR, "Fail to drop privileges");
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
@@ -266,6 +261,8 @@ int main (int argc, char **argv)
|
||
|
|
||
|
/* Default: daemon mode, no other options */
|
||
|
run_mode = 0;
|
||
|
+ xlog_stderr(0);
|
||
|
+ xlog_syslog(1);
|
||
|
|
||
|
/* Set the basename */
|
||
|
if ((name_p = strrchr(argv[0],'/')) != NULL) {
|
||
|
@@ -274,13 +271,6 @@ int main (int argc, char **argv)
|
||
|
name_p = argv[0];
|
||
|
}
|
||
|
|
||
|
- /* Get the version */
|
||
|
- if ((version_p = strrchr(VERSION,' ')) != NULL) {
|
||
|
- version_p++;
|
||
|
- } else {
|
||
|
- version_p = VERSION;
|
||
|
- }
|
||
|
-
|
||
|
/* Set hostname */
|
||
|
MY_NAME = NULL;
|
||
|
|
||
|
@@ -289,7 +279,7 @@ int main (int argc, char **argv)
|
||
|
switch (arg) {
|
||
|
case 'V': /* Version */
|
||
|
case 'v':
|
||
|
- printf("%s version %s\n",name_p,version_p);
|
||
|
+ printf("%s version " VERSION "\n",name_p);
|
||
|
exit(0);
|
||
|
case 'F': /* Foreground/nodaemon mode */
|
||
|
run_mode |= MODE_NODAEMON;
|
||
|
@@ -383,7 +373,6 @@ int main (int argc, char **argv)
|
||
|
run_sm_notify(out_port);
|
||
|
}
|
||
|
|
||
|
-
|
||
|
if (!(run_mode & MODE_NODAEMON)) {
|
||
|
run_mode &= ~MODE_LOG_STDERR; /* Never log to console in
|
||
|
daemon mode. */
|
||
|
@@ -455,7 +444,13 @@ int main (int argc, char **argv)
|
||
|
|
||
|
/* Child. */
|
||
|
|
||
|
- log_init (/*name_p,version_p*/);
|
||
|
+ if (run_mode & MODE_LOG_STDERR) {
|
||
|
+ xlog_syslog(0);
|
||
|
+ xlog_stderr(1);
|
||
|
+ xlog_config(D_ALL, 1);
|
||
|
+ }
|
||
|
+ xlog_open(name_p);
|
||
|
+ xlog(L_NOTICE, "Version " VERSION " starting");
|
||
|
|
||
|
log_modes();
|
||
|
|
||
|
@@ -505,7 +500,7 @@ int main (int argc, char **argv)
|
||
|
if (pipefds[1] > 0) {
|
||
|
status = 0;
|
||
|
if (write(pipefds[1], &status, 1) != 1) {
|
||
|
- note(N_WARNING, "writing to parent pipe failed: errno %d (%s)\n",
|
||
|
+ xlog_warn("writing to parent pipe failed: errno %d (%s)\n",
|
||
|
errno, strerror(errno));
|
||
|
}
|
||
|
close(pipefds[1]);
|
||
|
@@ -552,7 +547,7 @@ load_state_number(void)
|
||
|
return;
|
||
|
|
||
|
if (read(fd, &MY_STATE, sizeof(MY_STATE)) != sizeof(MY_STATE)) {
|
||
|
- note(N_WARNING, "Unable to read state from '%s': errno %d (%s)",
|
||
|
+ xlog_warn("Unable to read state from '%s': errno %d (%s)",
|
||
|
SM_STAT_PATH, errno, strerror(errno));
|
||
|
}
|
||
|
close(fd);
|
||
|
@@ -561,7 +556,7 @@ load_state_number(void)
|
||
|
char buf[20];
|
||
|
snprintf(buf, sizeof(buf), "%d", MY_STATE);
|
||
|
if (write(fd, buf, strlen(buf)) != strlen(buf))
|
||
|
- note(N_WARNING, "Writing to '%s' failed: errno %d (%s)",
|
||
|
+ xlog_warn("Writing to '%s' failed: errno %d (%s)",
|
||
|
file, errno, strerror(errno));
|
||
|
close(fd);
|
||
|
}
|
||
|
diff -up nfs-utils-1.2.1/utils/statd/statd.h.orig nfs-utils-1.2.1/utils/statd/statd.h
|
||
|
--- nfs-utils-1.2.1/utils/statd/statd.h.orig 2009-12-14 11:35:16.304699406 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/statd/statd.h 2009-12-14 11:36:12.976836745 -0500
|
||
|
@@ -11,7 +11,7 @@
|
||
|
|
||
|
#include "sm_inter.h"
|
||
|
#include "system.h"
|
||
|
-#include "log.h"
|
||
|
+#include "xlog.h"
|
||
|
|
||
|
/*
|
||
|
* Paths and filenames.
|
||
|
@@ -85,10 +85,3 @@ extern int run_mode;
|
||
|
* another host.... */
|
||
|
#define STATIC_HOSTNAME 8 /* Always use the hostname set by -n */
|
||
|
#define MODE_NO_NOTIFY 16 /* Don't notify peers of a reboot */
|
||
|
-/*
|
||
|
- * Program name and version pointers -- See statd.c for the reasoning
|
||
|
- * as to why they're global.
|
||
|
- */
|
||
|
-extern char *name_p; /* program basename */
|
||
|
-extern const char *version_p; /* program version */
|
||
|
-
|
||
|
diff -up nfs-utils-1.2.1/utils/statd/svc_run.c.orig nfs-utils-1.2.1/utils/statd/svc_run.c
|
||
|
--- nfs-utils-1.2.1/utils/statd/svc_run.c.orig 2009-11-04 06:13:56.000000000 -0500
|
||
|
+++ nfs-utils-1.2.1/utils/statd/svc_run.c 2009-12-14 11:36:12.977852736 -0500
|
||
|
@@ -101,12 +101,12 @@ my_svc_run(void)
|
||
|
|
||
|
tv.tv_sec = NL_WHEN(notify) - now;
|
||
|
tv.tv_usec = 0;
|
||
|
- dprintf(N_DEBUG, "Waiting for reply... (timeo %d)",
|
||
|
+ xlog(D_GENERAL, "Waiting for reply... (timeo %d)",
|
||
|
tv.tv_sec);
|
||
|
selret = select(FD_SETSIZE, &readfds,
|
||
|
(void *) 0, (void *) 0, &tv);
|
||
|
} else {
|
||
|
- dprintf(N_DEBUG, "Waiting for client connections.");
|
||
|
+ xlog(D_GENERAL, "Waiting for client connections");
|
||
|
selret = select(FD_SETSIZE, &readfds,
|
||
|
(void *) 0, (void *) 0, (struct timeval *) 0);
|
||
|
}
|
||
|
@@ -116,8 +116,7 @@ my_svc_run(void)
|
||
|
if (errno == EINTR || errno == ECONNREFUSED
|
||
|
|| errno == ENETUNREACH || errno == EHOSTUNREACH)
|
||
|
continue;
|
||
|
- note(N_ERROR, "my_svc_run() - select: %s",
|
||
|
- strerror (errno));
|
||
|
+ xlog(L_ERROR, "my_svc_run() - select: %m");
|
||
|
return;
|
||
|
|
||
|
case 0:
|