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>

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/fs.d/nfs/statd/sm_svc.c
          +++ new/usr/src/cmd/fs.d/nfs/statd/sm_svc.c
↓ open down ↓ 12 lines elided ↑ open up ↑
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23      - * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  24   23   * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
       24 + * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
       25 + * Copyright 2016 Nexenta Systems, Inc.  All rights reserved.
  25   26   */
  26   27  
  27   28  /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  28   29  /*        All Rights Reserved   */
  29   30  
  30   31  /*
  31   32   * University Copyright- Copyright (c) 1982, 1986, 1988
  32   33   * The Regents of the University of California
  33   34   * All Rights Reserved
  34   35   *
  35   36   * University Acknowledgment- Portions of this document are derived from
  36   37   * software developed by the University of California, Berkeley, and its
  37   38   * contributors.
  38   39   */
  39   40  
  40      -/*
  41      - * Copyright (c) 2012 by Delphix. All rights reserved.
  42      - */
  43      -
  44   41  #include <stdio.h>
  45   42  #include <stdio_ext.h>
  46   43  #include <stdlib.h>
  47   44  #include <ftw.h>
  48   45  #include <signal.h>
  49   46  #include <string.h>
  50   47  #include <syslog.h>
  51   48  #include <netconfig.h>
       49 +#include <netdir.h>
  52   50  #include <unistd.h>
  53   51  #include <netdb.h>
  54   52  #include <rpc/rpc.h>
       53 +#include <rpc/svc.h>
  55   54  #include <netinet/in.h>
  56   55  #include <sys/param.h>
  57   56  #include <sys/resource.h>
  58   57  #include <sys/file.h>
  59   58  #include <sys/types.h>
  60   59  #include <sys/stat.h>
  61   60  #include <sys/sockio.h>
  62   61  #include <dirent.h>
  63   62  #include <errno.h>
  64   63  #include <rpcsvc/sm_inter.h>
  65   64  #include <rpcsvc/nsm_addr.h>
  66   65  #include <thread.h>
  67   66  #include <synch.h>
  68   67  #include <net/if.h>
  69   68  #include <limits.h>
  70   69  #include <rpcsvc/daemon_utils.h>
  71   70  #include <priv_utils.h>
       71 +#include "smfcfg.h"
  72   72  #include "sm_statd.h"
  73   73  
  74   74  
  75   75  #define home0           "/var/statmon"
  76   76  #define current0        "/var/statmon/sm"
  77   77  #define backup0         "/var/statmon/sm.bak"
  78   78  #define state0          "/var/statmon/state"
  79   79  
  80   80  #define home1           "statmon"
  81   81  #define current1        "statmon/sm/"
↓ open down ↓ 10 lines elided ↑ open up ↑
  92   92   * files.
  93   93   */
  94   94  uid_t   daemon_uid = DAEMON_UID;
  95   95  gid_t   daemon_gid = DAEMON_GID;
  96   96  
  97   97  char STATE[MAXPATHLEN], CURRENT[MAXPATHLEN], BACKUP[MAXPATHLEN];
  98   98  static char statd_home[MAXPATHLEN];
  99   99  
 100  100  int debug;
 101  101  int regfiles_only = 0;          /* 1 => use symlinks in statmon, 0 => don't */
      102 +int statd_port = 0;
 102  103  char hostname[MAXHOSTNAMELEN];
 103  104  
 104  105  /*
 105  106   * These variables will be used to store all the
 106  107   * alias names for the host, as well as the -a
 107  108   * command line hostnames.
 108  109   */
 109  110  int host_name_count;
 110  111  char **host_name; /* store -a opts */
 111  112  int  addrix; /* # of -a entries */
↓ open down ↓ 338 lines elided ↑ open up ↑
 450  451  
 451  452          /*
 452  453           * Notify the waiters.
 453  454           */
 454  455          (void) mutex_lock(&merges_lock);
 455  456          in_merges = B_FALSE;
 456  457          (void) cond_broadcast(&merges_cond);
 457  458          (void) mutex_unlock(&merges_lock);
 458  459  }
 459  460  
      461 +/*
      462 + * This function is called for each configured network type to
      463 + * bind and register our RPC service programs.
      464 + *
      465 + * On TCP or UDP, we may want to bind SM_PROG on a specific port
      466 + * (when statd_port is specified) in which case we'll use the
      467 + * variant of svc_tp_create() that lets us pass a bind address.
      468 + */
      469 +static void
      470 +sm_svc_tp_create(struct netconfig *nconf)
      471 +{
      472 +        char port_str[8];
      473 +        struct nd_hostserv hs;
      474 +        struct nd_addrlist *al = NULL;
      475 +        SVCXPRT *xprt = NULL;
      476 +
      477 +        /*
      478 +         * If statd_port is set and this is an inet transport,
      479 +         * bind this service on the specified port.  The TLI way
      480 +         * to create such a bind address is netdir_getbyname()
      481 +         * with the special "host" HOST_SELF_BIND.  This builds
      482 +         * an all-zeros IP address with the specified port.
      483 +         */
      484 +        if (statd_port != 0 &&
      485 +            (strcmp(nconf->nc_protofmly, NC_INET) == 0 ||
      486 +            strcmp(nconf->nc_protofmly, NC_INET6) == 0)) {
      487 +                int err;
      488 +
      489 +                snprintf(port_str, sizeof (port_str), "%u",
      490 +                    (unsigned short)statd_port);
      491 +
      492 +                hs.h_host = HOST_SELF_BIND;
      493 +                hs.h_serv = port_str;
      494 +                err = netdir_getbyname((struct netconfig *)nconf, &hs, &al);
      495 +                if (err == 0 && al != NULL) {
      496 +                        xprt = svc_tp_create_addr(sm_prog_1, SM_PROG, SM_VERS,
      497 +                            nconf, al->n_addrs);
      498 +                        netdir_free(al, ND_ADDRLIST);
      499 +                }
      500 +                if (xprt == NULL) {
      501 +                        syslog(LOG_ERR, "statd: unable to create "
      502 +                            "(SM_PROG, SM_VERS) on transport %s (port %d)",
      503 +                            nconf->nc_netid, statd_port);
      504 +                }
      505 +                /* fall-back to default bind */
      506 +        }
      507 +        if (xprt == NULL) {
      508 +                /*
      509 +                 * Had statd_port=0, or non-inet transport,
      510 +                 * or the bind to a specific port failed.
      511 +                 * Do a default bind.
      512 +                 */
      513 +                xprt = svc_tp_create(sm_prog_1, SM_PROG, SM_VERS, nconf);
      514 +        }
      515 +        if (xprt == NULL) {
      516 +                syslog(LOG_ERR, "statd: unable to create "
      517 +                    "(SM_PROG, SM_VERS) for transport %s",
      518 +                    nconf->nc_netid);
      519 +                return;
      520 +        }
      521 +
      522 +        /*
      523 +         * Also register the NSM_ADDR program on this
      524 +         * transport handle (same dispatch function).
      525 +         */
      526 +        if (!svc_reg(xprt, NSM_ADDR_PROGRAM, NSM_ADDR_V1, sm_prog_1, nconf)) {
      527 +                syslog(LOG_ERR, "statd: failed to register "
      528 +                    "(NSM_ADDR_PROGRAM, NSM_ADDR_V1) for "
      529 +                    "netconfig %s", nconf->nc_netid);
      530 +        }
      531 +}
      532 +
 460  533  int
 461  534  main(int argc, char *argv[])
 462  535  {
 463  536          int c;
 464  537          int ppid;
 465  538          extern char *optarg;
 466  539          int choice = 0;
 467  540          struct rlimit rl;
 468  541          int mode;
 469  542          int sz;
 470  543          int pipe_fd = -1;
      544 +        int ret;
 471  545          int connmaxrec = RPC_MAXDATASIZE;
      546 +        struct netconfig *nconf;
      547 +        NCONF_HANDLE *nc;
 472  548  
 473  549          addrix = 0;
 474  550          pathix = 0;
 475  551  
 476  552          (void) gethostname(hostname, MAXHOSTNAMELEN);
 477  553          if (init_hostname() < 0)
 478  554                  exit(1);
 479  555  
 480      -        while ((c = getopt(argc, argv, "Dd:a:G:p:rU:")) != EOF)
      556 +        ret = nfs_smf_get_iprop("statd_port", &statd_port,
      557 +            DEFAULT_INSTANCE, SCF_TYPE_INTEGER, STATD);
      558 +        if (ret != SA_OK) {
      559 +                syslog(LOG_ERR, "Reading of statd_port from SMF "
      560 +                    "failed, using default value");
      561 +        }
      562 +
      563 +        while ((c = getopt(argc, argv, "Dd:a:G:p:P:rU:")) != EOF)
 481  564                  switch (c) {
 482  565                  case 'd':
 483  566                          (void) sscanf(optarg, "%d", &debug);
 484  567                          break;
 485  568                  case 'D':
 486  569                          choice = 1;
 487  570                          break;
 488  571                  case 'a':
 489  572                          if (addrix < host_name_count) {
 490  573                                  if (strcmp(hostname, optarg) != 0) {
↓ open down ↓ 41 lines elided ↑ open up ↑
 532  615                                                  (void) fprintf(stderr,
 533  616                                                  "statd: malloc failed\n");
 534  617                                                  exit(1);
 535  618                                          }
 536  619                                          (void) memset(path_name, 0, sz);
 537  620                                  }
 538  621                                  path_name[pathix] = optarg;
 539  622                                  pathix++;
 540  623                          } else {
 541  624                                  (void) fprintf(stderr,
 542      -                                "statd: -p pathname is too long.\n");
      625 +                                    "statd: -p pathname is too long.\n");
 543  626                          }
 544  627                          break;
      628 +                case 'P':
      629 +                        (void) sscanf(optarg, "%d", &statd_port);
      630 +                        if (statd_port < 1 || statd_port > UINT16_MAX) {
      631 +                                (void) fprintf(stderr,
      632 +                                    "statd: -P port invalid.\n");
      633 +                                statd_port = 0;
      634 +                        }
      635 +                        break;
 545  636                  case 'r':
 546  637                          regfiles_only = 1;
 547  638                          break;
 548  639                  default:
 549  640                          (void) fprintf(stderr,
 550      -                        "statd [-d level] [-D]\n");
      641 +                            "statd [-d level] [-D]\n");
 551  642                          return (1);
 552  643                  }
 553  644  
 554  645          if (choice == 0) {
 555  646                  (void) strcpy(statd_home, home0);
 556  647                  (void) strcpy(CURRENT, current0);
 557  648                  (void) strcpy(BACKUP, backup0);
 558  649                  (void) strcpy(STATE, state0);
 559  650          } else {
 560  651                  (void) strcpy(statd_home, home1);
↓ open down ↓ 68 lines elided ↑ open up ↑
 629  720          }
 630  721  
 631  722          /*
 632  723           * Set non-blocking mode and maximum record size for
 633  724           * connection oriented RPC transports.
 634  725           */
 635  726          if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &connmaxrec)) {
 636  727                  syslog(LOG_INFO, "unable to set maximum RPC record size");
 637  728          }
 638  729  
 639      -        if (!svc_create(sm_prog_1, SM_PROG, SM_VERS, "netpath")) {
 640      -                syslog(LOG_ERR, "statd: unable to create (SM_PROG, SM_VERS) "
 641      -                    "for netpath.");
 642      -                exit(1);
      730 +        /*
      731 +         * Enumerate network transports and create service listeners
      732 +         * as appropriate for each.
      733 +         */
      734 +        if ((nc = setnetconfig()) == NULL) {
      735 +                syslog(LOG_ERR, "setnetconfig failed: %m");
      736 +                return (-1);
 643  737          }
      738 +        while ((nconf = getnetconfig(nc)) != NULL) {
 644  739  
 645      -        if (!svc_create(sm_prog_1, NSM_ADDR_PROGRAM, NSM_ADDR_V1, "netpath")) {
 646      -                syslog(LOG_ERR, "statd: unable to create (NSM_ADDR_PROGRAM, "
 647      -                    "NSM_ADDR_V1) for netpath.");
      740 +                /*
      741 +                 * Skip things like tpi_raw, invisible...
      742 +                 */
      743 +                if ((nconf->nc_flag & NC_VISIBLE) == 0)
      744 +                        continue;
      745 +                if (nconf->nc_semantics != NC_TPI_CLTS &&
      746 +                    nconf->nc_semantics != NC_TPI_COTS &&
      747 +                    nconf->nc_semantics != NC_TPI_COTS_ORD)
      748 +                        continue;
      749 +
      750 +                sm_svc_tp_create(nconf);
 648  751          }
      752 +        (void) endnetconfig(nc);
 649  753  
 650  754          /*
 651  755           * Make sure /var/statmon and any alternate (-p) statmon
 652  756           * directories exist and are owned by daemon.  Then change our uid
 653  757           * to daemon.  The uid change is to prevent attacks against local
 654  758           * daemons that trust any call from a local root process.
 655  759           */
 656  760  
 657  761          set_statmon_owner();
 658  762  
↓ open down ↓ 159 lines elided ↑ open up ↑
 818  922  /*
 819  923   * Set the user and group to daemon for the given file or directory.  If
 820  924   * it's a directory, also makes sure that it is mode 755.
 821  925   * Generates a syslog message but does not return an error if there were
 822  926   * problems.
 823  927   */
 824  928  
 825  929  /*ARGSUSED3*/
 826  930  static int
 827  931  nftw_owner(const char *path, const struct stat *statp, int info,
 828      -        struct FTW *ftw)
      932 +    struct FTW *ftw)
 829  933  {
 830  934          if (!(info == FTW_F || info == FTW_D))
 831  935                  return (0);
 832  936  
 833  937          /*
 834  938           * Some older systems might have mode 777 directories.  Fix that.
 835  939           */
 836  940  
 837  941          if (info == FTW_D && (statp->st_mode & (S_IWGRP | S_IWOTH)) != 0) {
 838  942                  mode_t newmode = (statp->st_mode & ~(S_IWGRP | S_IWOTH)) &
↓ open down ↓ 32 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX