From e72ff08d3b44e4e2f89e0ec84680f40062be00d5 Mon Sep 17 00:00:00 2001 From: Gordon Ross Date: Mon, 14 Nov 2016 20:35:12 -0500 Subject: [PATCH] 7569 statd support to run on a fixed port Portions contributed by: Paul Dagnelie Reviewed by: Evan Layton Reviewed by: Sebastien Roy Approved by: Prakash Surya --- usr/src/cmd/fs.d/nfs/statd/Makefile | 14 +++- usr/src/cmd/fs.d/nfs/statd/sm_svc.c | 136 ++++++++++++++++++++++++++++---- usr/src/cmd/fs.d/nfs/svc/status.xml | 12 ++- usr/src/lib/libshare/nfs/libshare_nfs.c | 5 ++ usr/src/man/man4/nfs.4 | 9 ++- 5 files changed, 152 insertions(+), 24 deletions(-) diff --git a/usr/src/cmd/fs.d/nfs/statd/Makefile b/usr/src/cmd/fs.d/nfs/statd/Makefile index 8a74b8860b..ad7559a035 100644 --- a/usr/src/cmd/fs.d/nfs/statd/Makefile +++ b/usr/src/cmd/fs.d/nfs/statd/Makefile @@ -28,6 +28,8 @@ # Copyright 1990-2003 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # +# Copyright (c) 2016 by Delphix. All rights reserved. +# FSTYPE= nfs TYPEPROG= statd @@ -37,15 +39,18 @@ include ../../Makefile.fstype CPPFLAGS += -D_REENTRANT -DSUN_THREADS CERRWARN += -_gcc=-Wno-unused-variable +CERRWARN += -_gcc=-Wno-switch CERRWARN += -_gcc=-Wno-parentheses CERRWARN += -_gcc=-Wno-uninitialized LOCAL= sm_svc.o sm_proc.o sm_statd.o -OBJS= $(LOCAL) selfcheck.o daemon.o +OBJS= $(LOCAL) selfcheck.o daemon.o smfcfg.o -SRCS= $(LOCAL:%.o=%.c) ../lib/selfcheck.c ../lib/daemon.c +SRCS= $(LOCAL:%.o=%.c) ../lib/selfcheck.c ../lib/daemon.c \ + ../lib/smfcfg.c -LDLIBS += -lsocket -lrpcsvc -lnsl +LDLIBS += -lsocket -lrpcsvc -lnsl -lscf +CPPFLAGS += -I../lib $(TYPEPROG): $(OBJS) $(LINK.c) -o $@ $(OBJS) $(LDLIBS) @@ -58,6 +63,9 @@ selfcheck.o: ../lib/selfcheck.c daemon.o: ../lib/daemon.c $(COMPILE.c) ../lib/daemon.c +smfcfg.o: ../lib/smfcfg.c + $(COMPILE.c) ../lib/smfcfg.c + lint: lint_SRCS clean: diff --git a/usr/src/cmd/fs.d/nfs/statd/sm_svc.c b/usr/src/cmd/fs.d/nfs/statd/sm_svc.c index 37ef788f50..8f19764116 100644 --- a/usr/src/cmd/fs.d/nfs/statd/sm_svc.c +++ b/usr/src/cmd/fs.d/nfs/statd/sm_svc.c @@ -20,8 +20,9 @@ */ /* - * Copyright 2015 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 by Delphix. All rights reserved. + * Copyright 2016 Nexenta Systems, Inc. All rights reserved. */ /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ @@ -37,10 +38,6 @@ * contributors. */ -/* - * Copyright (c) 2012 by Delphix. All rights reserved. - */ - #include #include #include @@ -49,9 +46,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -69,6 +68,7 @@ #include #include #include +#include "smfcfg.h" #include "sm_statd.h" @@ -99,6 +99,7 @@ static char statd_home[MAXPATHLEN]; int debug; int regfiles_only = 0; /* 1 => use symlinks in statmon, 0 => don't */ +int statd_port = 0; char hostname[MAXHOSTNAMELEN]; /* @@ -457,6 +458,78 @@ thr_statd_merges(void) (void) mutex_unlock(&merges_lock); } +/* + * This function is called for each configured network type to + * bind and register our RPC service programs. + * + * On TCP or UDP, we may want to bind SM_PROG on a specific port + * (when statd_port is specified) in which case we'll use the + * variant of svc_tp_create() that lets us pass a bind address. + */ +static void +sm_svc_tp_create(struct netconfig *nconf) +{ + char port_str[8]; + struct nd_hostserv hs; + struct nd_addrlist *al = NULL; + SVCXPRT *xprt = NULL; + + /* + * If statd_port is set and this is an inet transport, + * bind this service on the specified port. The TLI way + * to create such a bind address is netdir_getbyname() + * with the special "host" HOST_SELF_BIND. This builds + * an all-zeros IP address with the specified port. + */ + if (statd_port != 0 && + (strcmp(nconf->nc_protofmly, NC_INET) == 0 || + strcmp(nconf->nc_protofmly, NC_INET6) == 0)) { + int err; + + snprintf(port_str, sizeof (port_str), "%u", + (unsigned short)statd_port); + + hs.h_host = HOST_SELF_BIND; + hs.h_serv = port_str; + err = netdir_getbyname((struct netconfig *)nconf, &hs, &al); + if (err == 0 && al != NULL) { + xprt = svc_tp_create_addr(sm_prog_1, SM_PROG, SM_VERS, + nconf, al->n_addrs); + netdir_free(al, ND_ADDRLIST); + } + if (xprt == NULL) { + syslog(LOG_ERR, "statd: unable to create " + "(SM_PROG, SM_VERS) on transport %s (port %d)", + nconf->nc_netid, statd_port); + } + /* fall-back to default bind */ + } + if (xprt == NULL) { + /* + * Had statd_port=0, or non-inet transport, + * or the bind to a specific port failed. + * Do a default bind. + */ + xprt = svc_tp_create(sm_prog_1, SM_PROG, SM_VERS, nconf); + } + if (xprt == NULL) { + syslog(LOG_ERR, "statd: unable to create " + "(SM_PROG, SM_VERS) for transport %s", + nconf->nc_netid); + return; + } + + /* + * Also register the NSM_ADDR program on this + * transport handle (same dispatch function). + */ + if (!svc_reg(xprt, NSM_ADDR_PROGRAM, NSM_ADDR_V1, sm_prog_1, nconf)) { + syslog(LOG_ERR, "statd: failed to register " + "(NSM_ADDR_PROGRAM, NSM_ADDR_V1) for " + "netconfig %s", nconf->nc_netid); + } +} + int main(int argc, char *argv[]) { @@ -468,7 +541,10 @@ main(int argc, char *argv[]) int mode; int sz; int pipe_fd = -1; + int ret; int connmaxrec = RPC_MAXDATASIZE; + struct netconfig *nconf; + NCONF_HANDLE *nc; addrix = 0; pathix = 0; @@ -477,7 +553,14 @@ main(int argc, char *argv[]) if (init_hostname() < 0) exit(1); - while ((c = getopt(argc, argv, "Dd:a:G:p:rU:")) != EOF) + ret = nfs_smf_get_iprop("statd_port", &statd_port, + DEFAULT_INSTANCE, SCF_TYPE_INTEGER, STATD); + if (ret != SA_OK) { + syslog(LOG_ERR, "Reading of statd_port from SMF " + "failed, using default value"); + } + + while ((c = getopt(argc, argv, "Dd:a:G:p:P:rU:")) != EOF) switch (c) { case 'd': (void) sscanf(optarg, "%d", &debug); @@ -539,7 +622,15 @@ main(int argc, char *argv[]) pathix++; } else { (void) fprintf(stderr, - "statd: -p pathname is too long.\n"); + "statd: -p pathname is too long.\n"); + } + break; + case 'P': + (void) sscanf(optarg, "%d", &statd_port); + if (statd_port < 1 || statd_port > UINT16_MAX) { + (void) fprintf(stderr, + "statd: -P port invalid.\n"); + statd_port = 0; } break; case 'r': @@ -547,7 +638,7 @@ main(int argc, char *argv[]) break; default: (void) fprintf(stderr, - "statd [-d level] [-D]\n"); + "statd [-d level] [-D]\n"); return (1); } @@ -636,16 +727,29 @@ main(int argc, char *argv[]) syslog(LOG_INFO, "unable to set maximum RPC record size"); } - if (!svc_create(sm_prog_1, SM_PROG, SM_VERS, "netpath")) { - syslog(LOG_ERR, "statd: unable to create (SM_PROG, SM_VERS) " - "for netpath."); - exit(1); + /* + * Enumerate network transports and create service listeners + * as appropriate for each. + */ + if ((nc = setnetconfig()) == NULL) { + syslog(LOG_ERR, "setnetconfig failed: %m"); + return (-1); } + while ((nconf = getnetconfig(nc)) != NULL) { + + /* + * Skip things like tpi_raw, invisible... + */ + if ((nconf->nc_flag & NC_VISIBLE) == 0) + continue; + if (nconf->nc_semantics != NC_TPI_CLTS && + nconf->nc_semantics != NC_TPI_COTS && + nconf->nc_semantics != NC_TPI_COTS_ORD) + continue; - if (!svc_create(sm_prog_1, NSM_ADDR_PROGRAM, NSM_ADDR_V1, "netpath")) { - syslog(LOG_ERR, "statd: unable to create (NSM_ADDR_PROGRAM, " - "NSM_ADDR_V1) for netpath."); + sm_svc_tp_create(nconf); } + (void) endnetconfig(nc); /* * Make sure /var/statmon and any alternate (-p) statmon @@ -825,7 +929,7 @@ one_statmon_owner(const char *dir) /*ARGSUSED3*/ static int nftw_owner(const char *path, const struct stat *statp, int info, - struct FTW *ftw) + struct FTW *ftw) { if (!(info == FTW_F || info == FTW_D)) return (0); diff --git a/usr/src/cmd/fs.d/nfs/svc/status.xml b/usr/src/cmd/fs.d/nfs/svc/status.xml index 8412fd8bac..dce8cba446 100644 --- a/usr/src/cmd/fs.d/nfs/svc/status.xml +++ b/usr/src/cmd/fs.d/nfs/svc/status.xml @@ -33,6 +33,8 @@ $SRC/head/rpcsvc/daemon_utils.h and libnsl:open_daemon_lock(). --> + + - - - - + + + + + +