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