Print this page
7569 statd support to run on a fixed port
Portions contributed by: Paul Dagnelie <pcd@delphix.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sebastien Roy <sebastien.roy@delphix.com>
*** 18,29 ****
*
* CDDL HEADER END
*/
/*
- * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
--- 18,30 ----
*
* CDDL HEADER END
*/
/*
* 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 */
/* All Rights Reserved */
*** 35,59 ****
* University Acknowledgment- Portions of this document are derived from
* software developed by the University of California, Berkeley, and its
* contributors.
*/
- /*
- * Copyright (c) 2012 by Delphix. All rights reserved.
- */
-
#include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <ftw.h>
#include <signal.h>
#include <string.h>
#include <syslog.h>
#include <netconfig.h>
#include <unistd.h>
#include <netdb.h>
#include <rpc/rpc.h>
#include <netinet/in.h>
#include <sys/param.h>
#include <sys/resource.h>
#include <sys/file.h>
#include <sys/types.h>
--- 36,58 ----
* University Acknowledgment- Portions of this document are derived from
* software developed by the University of California, Berkeley, and its
* contributors.
*/
#include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h>
#include <ftw.h>
#include <signal.h>
#include <string.h>
#include <syslog.h>
#include <netconfig.h>
+ #include <netdir.h>
#include <unistd.h>
#include <netdb.h>
#include <rpc/rpc.h>
+ #include <rpc/svc.h>
#include <netinet/in.h>
#include <sys/param.h>
#include <sys/resource.h>
#include <sys/file.h>
#include <sys/types.h>
*** 67,76 ****
--- 66,76 ----
#include <synch.h>
#include <net/if.h>
#include <limits.h>
#include <rpcsvc/daemon_utils.h>
#include <priv_utils.h>
+ #include "smfcfg.h"
#include "sm_statd.h"
#define home0 "/var/statmon"
#define current0 "/var/statmon/sm"
*** 97,106 ****
--- 97,107 ----
char STATE[MAXPATHLEN], CURRENT[MAXPATHLEN], BACKUP[MAXPATHLEN];
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];
/*
* These variables will be used to store all the
* alias names for the host, as well as the -a
*** 455,464 ****
--- 456,537 ----
in_merges = B_FALSE;
(void) cond_broadcast(&merges_cond);
(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[])
{
int c;
int ppid;
*** 466,485 ****
int choice = 0;
struct rlimit rl;
int mode;
int sz;
int pipe_fd = -1;
int connmaxrec = RPC_MAXDATASIZE;
addrix = 0;
pathix = 0;
(void) gethostname(hostname, MAXHOSTNAMELEN);
if (init_hostname() < 0)
exit(1);
! while ((c = getopt(argc, argv, "Dd:a:G:p:rU:")) != EOF)
switch (c) {
case 'd':
(void) sscanf(optarg, "%d", &debug);
break;
case 'D':
--- 539,568 ----
int choice = 0;
struct rlimit rl;
int mode;
int sz;
int pipe_fd = -1;
+ int ret;
int connmaxrec = RPC_MAXDATASIZE;
+ struct netconfig *nconf;
+ NCONF_HANDLE *nc;
addrix = 0;
pathix = 0;
(void) gethostname(hostname, MAXHOSTNAMELEN);
if (init_hostname() < 0)
exit(1);
! 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);
break;
case 'D':
*** 540,549 ****
--- 623,640 ----
} else {
(void) fprintf(stderr,
"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':
regfiles_only = 1;
break;
default:
(void) fprintf(stderr,
*** 634,653 ****
*/
if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &connmaxrec)) {
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);
}
! 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.");
}
/*
* Make sure /var/statmon and any alternate (-p) statmon
* directories exist and are owned by daemon. Then change our uid
* to daemon. The uid change is to prevent attacks against local
--- 725,757 ----
*/
if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &connmaxrec)) {
syslog(LOG_INFO, "unable to set maximum RPC record size");
}
! /*
! * 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;
!
! sm_svc_tp_create(nconf);
}
+ (void) endnetconfig(nc);
/*
* Make sure /var/statmon and any alternate (-p) statmon
* directories exist and are owned by daemon. Then change our uid
* to daemon. The uid change is to prevent attacks against local