Print this page
NEX-6532 allow specifying individual IP addresses without @ prefix in NFS access lists
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Alex Deiter <alex.deiter@nexenta.com>
NEX-6673 possible NULL pointer dereference in mountd`mount
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Alex Deiter <alex.deiter@nexenta.com>
NEX-4116 mountd: The IP to name translation is usually not needed in nfsauth_access()
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-4603 mountd: Compile warnings cleanup
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-2614 Add non-interactive mode for ypinit
NEX-2394 mountd() door services are sub-optimal in large... (redux)
NEX-1974 Support for more than 16 groups with AUTH_SYS
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
NEX-2394 mountd() door services are sub-optimal in large scale deployments
NEX-2526 mountd consumes an inordinate amount of memory
NEX-2502 4.0.3 RC4 Unable to mount NFS shares
Revert "NEX-2394 mountd() door services are sub-optimal in large scale deployments".
This reverts commit c6e1673e3a4b8ba866c77dee7b8f03f858be07d6.
The fix for NEX-2394 worked fine when putting the mountd binary in 4.0.2,
but needs additional work in a 4.0.3 environment
NEX-2394 mountd() door services are sub-optimal in large scale deployments
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Ryuji Masuda <ryuji.masuda@nexenta.com>
Reviewed by: Kirill Davydychev <kirill.davydychev@nexenta.com>
NEX-1128 NFS server: Generic uid and gid remapping for AUTH_SYS
Reviewed by: Jan Kryl <jan.kryl@nexenta.com>
OS-141 mountd(1m) needs to be able to set listen backlog
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
OS-134 mountd(1m): Remove limit of FDs in RPC server
Reviewed by: Michael Tsymbalyuk <michael.tsymbalyuk@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
OS-133 mountd: Busy do_logging_queue() eats memory
Reviewed by: Michael Tsymbalyuk <michael.tsymbalyuk@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
OS-131 mountd(1m) leaks nd_hostservlist in do_logging_queue()
Reviewed by: Ilya Usvyatsky <ilya.usvyatsky@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
OS-20 share_nfs(1m) charset handling is unreliable
OS-22 Page fault at nfscmd_dropped_entrysize+0x1e()
OS-23 NFSv2/3/4: READDIR responses are inconsistent when charset conversion fails
OS-24 rfs3_readdir(): Issues related to nfscmd_convdirent()
Reviewed by: Jan Kryl <jan.kryl@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
        
*** 19,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) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T     */
  /*        All Rights Reserved   */
  
--- 19,30 ----
   * CDDL HEADER END
   */
  
  /*
   * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
+  * Copyright 2016 Nexenta Systems, Inc.
   * Copyright (c) 2012, 2016 by Delphix. All rights reserved.
   */
  
  /*      Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T     */
  /*        All Rights Reserved   */
  
*** 61,70 ****
--- 61,71 ----
  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <arpa/inet.h>
  #include <netdb.h>
  #include <thread.h>
+ #include <pthread.h>
  #include <assert.h>
  #include <priv_utils.h>
  #include <nfs/auth.h>
  #include <nfs/nfssys.h>
  #include <nfs/nfs.h>
*** 86,95 ****
--- 87,97 ----
  #include <attr.h>
  #include "smfcfg.h"
  #include <pwd.h>
  #include <grp.h>
  #include <alloca.h>
+ #include <atomic.h>
  
  extern int daemonize_init(void);
  extern void daemonize_fini(int);
  
  extern int _nfssys(int, void *);
*** 127,138 ****
  
  extern void nfscmd_func(void *, char *, size_t, door_desc_t *, uint_t);
  
  thread_t        nfsauth_thread;
  thread_t        cmd_thread;
- thread_t        logging_thread;
  
  typedef struct logging_data {
          char                    *ld_host;
          char                    *ld_path;
          char                    *ld_rpath;
          int                     ld_status;
--- 129,147 ----
  
  extern void nfscmd_func(void *, char *, size_t, door_desc_t *, uint_t);
  
  thread_t        nfsauth_thread;
  thread_t        cmd_thread;
  
+ /*
+  * The following logging and BSM related data structs
+  * are only used when mountd_bsm_audit is TRUE; this
+  * is done by specifying the undocumented -A flag to
+  * mountd(1m).
+  */
+ static bool_t   mountd_bsm_audit = FALSE;
+ 
  typedef struct logging_data {
          char                    *ld_host;
          char                    *ld_path;
          char                    *ld_rpath;
          int                     ld_status;
*** 142,170 ****
  } logging_data;
  
  static logging_data *logging_head = NULL;
  static logging_data *logging_tail = NULL;
  
  /*
   * Our copy of some system variables obtained using sysconf(3c)
   */
  static long ngroups_max;        /* _SC_NGROUPS_MAX */
  static long pw_size;            /* _SC_GETPW_R_SIZE_MAX */
  
  /* ARGSUSED */
  static void *
  nfsauth_svc(void *arg)
  {
-         int     doorfd = -1;
          uint_t  darg;
  #ifdef DEBUG
          int     dfd;
  #endif
  
!         if ((doorfd = door_create(nfsauth_func, NULL,
!             DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) == -1) {
!                 syslog(LOG_ERR, "Unable to create door: %m\n");
                  exit(10);
          }
  
  #ifdef DEBUG
          /*
--- 151,340 ----
  } logging_data;
  
  static logging_data *logging_head = NULL;
  static logging_data *logging_tail = NULL;
  
+ #define MOUNTD_STKSZ    (16 * 1024)     /* 16KB Stacks */
+ static  uint32_t        nm_thrds = 0;
+ static  uint32_t        mx_thrds = 2;   /* fallback default: see main() */
+ 
+ static  thread_key_t    door_key;
+ static  mutex_t         door_lock;
+ static  int             cmd_door = -1;
+ static  cond_t          cdoor_cv;
+ static  int             auth_door = -1;
+ static  cond_t          adoor_cv;
+ 
+ typedef enum {
+         UNKNOWN_FUNC    = 0,
+         NFSAUTH_FUNC    = 1,
+         NFSCMD_FUNC     = 2
+ } dr_cmd_t;
+ 
  /*
   * Our copy of some system variables obtained using sysconf(3c)
   */
  static long ngroups_max;        /* _SC_NGROUPS_MAX */
  static long pw_size;            /* _SC_GETPW_R_SIZE_MAX */
  
+ static char *
+ cmd2str(dr_cmd_t t)
+ {
+         switch (t) {
+         case NFSAUTH_FUNC:
+                 return ("NFSAUTH_FUNC");
+ 
+         case NFSCMD_FUNC:
+                 return ("NFSCMD_FUNC");
+ 
+         case UNKNOWN_FUNC:
+         default:
+                 return ("UNKNOWN_FUNC");
+         }
+ }
+ 
+ void *
+ mntd_thr_start(void *arg)
+ {
+         dr_cmd_t        *cp = (dr_cmd_t *)arg;
+         dr_cmd_t         cmd = *cp;
+         static void     *value;
+         int              dfd = 0;
+ 
+         value = (nm_thrds >= mx_thrds) ? (void *)1 : (void *)0;
+         (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+         (void) thr_setspecific(door_key, value);
+ 
+         switch (cmd) {
+         case NFSAUTH_FUNC:
+                 (void) mutex_lock(&door_lock);
+                 while (auth_door == -1)
+                         cond_wait(&adoor_cv, &door_lock);
+                 dfd = auth_door;
+                 (void) mutex_unlock(&door_lock);
+                 break;
+ 
+         case NFSCMD_FUNC:
+                 (void) mutex_lock(&door_lock);
+                 while (cmd_door == -1)
+                         cond_wait(&cdoor_cv, &door_lock);
+                 dfd = cmd_door;
+                 (void) mutex_unlock(&door_lock);
+                 break;
+ 
+         default:
+                 syslog(LOG_NOTICE, "mntd_thr_start: %s", cmd2str(cmd));
+                 free(cp);
+                 thr_exit(NULL);
+         }
+ 
+         if (door_bind(dfd) < 0) {
+                 syslog(LOG_ERR, "Unable to bind door for %s: %m", cmd2str(cmd));
+                 exit(20);
+         }
+ #ifdef  DEBUG
+         syslog(LOG_NOTICE, "%s Door Bound Successfully", cmd2str(cmd));
+ #endif
+         free(cp);
+         door_return(NULL, 0, NULL, 0);
+ 
+         /* NOTREACHED */
+         return (NULL);
+ }
+ 
+ /*
+  * Manages stacksize and threadpool
+  */
+ static void
+ mntd_thr_create(door_info_t *dp)
+ {
+         thread_t         tid;
+         int              num = 0;
+         int              rc = 0;
+         size_t           stksz = MOUNTD_STKSZ;
+         long             flags = THR_DETACHED;
+         void            *proc;
+         dr_cmd_t        *cp;
+ #ifdef  DEBUG
+         char             func[1024] = {0};
+ #endif
+ 
+         if (dp == NULL) {
+                 syslog(LOG_NOTICE, "mntd_thr_create: dp == NULL");
+                 return;
+         }
+         proc = (void *)(uintptr_t)dp->di_proc;
+ 
+         if ((cp = (dr_cmd_t *)malloc(sizeof (dr_cmd_t))) == (dr_cmd_t *)NULL) {
+                 syslog(LOG_ERR, "mntd_thr_create: %m");
+                 return;
+         }
+ 
+ #ifdef  DEBUG
+         (void) addrtosymstr(proc, func, sizeof (func));
+         syslog(LOG_NOTICE, "mntd_thr_create: func = %s", func);
+ #endif
+ 
+         if (proc == (void *)nfsauth_func)
+                 *cp = NFSAUTH_FUNC;
+         else if (proc == (void *)nfscmd_func)
+                 *cp = NFSCMD_FUNC;
+         else {
+                 free(cp);
+                 return;
+         }
+ 
+         if ((num = atomic_inc_32_nv(&nm_thrds)) > mx_thrds) {
+                 atomic_dec_32(&nm_thrds);
+                 num -= 1;
+ #ifdef  DEBUG
+                 syslog(LOG_ERR,
+                     "mntd_thr_create: %d threads already active", num);
+ #endif
+                 free(cp);
+                 return;
+         }
+ 
+         rc = thr_create(NULL, stksz, mntd_thr_start, (void *)cp, flags, &tid);
+         if (rc != 0) {
+                 atomic_dec_32(&nm_thrds);
+                 syslog(LOG_ERR, "mntd_thr_create: %m");
+                 free(cp);
+                 return;
+         }
+ #ifdef  DEBUG
+         syslog(LOG_NOTICE,
+             "mntd_thr_create: tid %d created (nm_thrds = %d)", tid, nm_thrds);
+ #endif
+ }
+ 
+ static void
+ mntd_thr_destroy(void *arg)
+ {
+         atomic_dec_32(&nm_thrds);
+ #ifdef  DEBUG
+         syslog(LOG_NOTICE, "mntd_thr_destroy: (nm_thrds = %d)", nm_thrds);
+ #endif
+ }
+ 
  /* ARGSUSED */
  static void *
  nfsauth_svc(void *arg)
  {
          uint_t  darg;
+         uint_t  flags = (DOOR_PRIVATE | DOOR_NO_CANCEL | DOOR_REFUSE_DESC);
  #ifdef DEBUG
          int     dfd;
  #endif
  
!         /* register 'nfsauth_func' as the new door service */
!         (void) mutex_lock(&door_lock);
!         auth_door = door_create(nfsauth_func, NULL, flags);
!         (void) mutex_unlock(&door_lock);
! 
!         if (auth_door < 0) {
!                 syslog(LOG_ERR, "nfsauth_svc: %m");
                  exit(10);
          }
  
  #ifdef DEBUG
          /*
*** 171,181 ****
           * Create a file system path for the door
           */
          if ((dfd = open(MOUNTD_DOOR, O_RDWR|O_CREAT|O_TRUNC,
              S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1) {
                  syslog(LOG_ERR, "Unable to open %s: %m\n", MOUNTD_DOOR);
!                 (void) close(doorfd);
                  exit(11);
          }
  
          /*
           * Clean up any stale namespace associations
--- 341,351 ----
           * Create a file system path for the door
           */
          if ((dfd = open(MOUNTD_DOOR, O_RDWR|O_CREAT|O_TRUNC,
              S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) == -1) {
                  syslog(LOG_ERR, "Unable to open %s: %m\n", MOUNTD_DOOR);
!                 (void) close(auth_door);
                  exit(11);
          }
  
          /*
           * Clean up any stale namespace associations
*** 183,208 ****
          (void) fdetach(MOUNTD_DOOR);
  
          /*
           * Register in namespace to pass to the kernel to door_ki_open
           */
!         if (fattach(doorfd, MOUNTD_DOOR) == -1) {
                  syslog(LOG_ERR, "Unable to fattach door: %m\n");
                  (void) close(dfd);
!                 (void) close(doorfd);
                  exit(12);
          }
          (void) close(dfd);
  #endif
  
          /*
           * Must pass the doorfd down to the kernel.
           */
!         darg = doorfd;
          (void) _nfssys(MOUNTD_ARGS, &darg);
  
          /*
           * Wait for incoming calls
           */
          /*CONSTCOND*/
          for (;;)
                  (void) pause();
--- 353,385 ----
          (void) fdetach(MOUNTD_DOOR);
  
          /*
           * Register in namespace to pass to the kernel to door_ki_open
           */
!         if (fattach(auth_door, MOUNTD_DOOR) == -1) {
                  syslog(LOG_ERR, "Unable to fattach door: %m\n");
                  (void) close(dfd);
!                 (void) close(auth_door);
                  exit(12);
          }
          (void) close(dfd);
  #endif
  
          /*
           * Must pass the doorfd down to the kernel.
           */
!         darg = auth_door;
          (void) _nfssys(MOUNTD_ARGS, &darg);
  
          /*
+          * Signal thread that kernel has door descriptor
+          */
+         (void) mutex_lock(&door_lock);
+         cond_signal(&adoor_cv);
+         (void) mutex_unlock(&door_lock);
+ 
+         /*
           * Wait for incoming calls
           */
          /*CONSTCOND*/
          for (;;)
                  (void) pause();
*** 215,244 ****
  /*
   * NFS command service thread code for setup and handling of the
   * nfs_cmd requests for character set conversion and other future
   * events.
   */
- 
  static void *
  cmd_svc(void *arg)
  {
-         int     doorfd = -1;
          uint_t  darg;
  
!         if ((doorfd = door_create(nfscmd_func, NULL,
!             DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) == -1) {
                  syslog(LOG_ERR, "Unable to create cmd door: %m\n");
                  exit(10);
          }
  
          /*
!          * Must pass the doorfd down to the kernel.
           */
!         darg = doorfd;
          (void) _nfssys(NFSCMD_ARGS, &darg);
  
          /*
           * Wait for incoming calls
           */
          /*CONSTCOND*/
          for (;;)
                  (void) pause();
--- 392,431 ----
  /*
   * NFS command service thread code for setup and handling of the
   * nfs_cmd requests for character set conversion and other future
   * events.
   */
  static void *
  cmd_svc(void *arg)
  {
          uint_t  darg;
+         uint_t  flags = (DOOR_PRIVATE | DOOR_NO_CANCEL | DOOR_REFUSE_DESC);
  
!         /* register 'nfscmd_func' as the new door service */
!         (void) mutex_lock(&door_lock);
!         cmd_door = door_create(nfscmd_func, NULL, flags);
!         (void) mutex_unlock(&door_lock);
! 
!         if (cmd_door < 0) {
                  syslog(LOG_ERR, "Unable to create cmd door: %m\n");
                  exit(10);
          }
  
          /*
!          * Must pass the cmd_door down to the kernel.
           */
!         darg = cmd_door;
          (void) _nfssys(NFSCMD_ARGS, &darg);
  
          /*
+          * Signal thread that kernel has door descriptor
+          */
+         (void) mutex_lock(&door_lock);
+         cond_signal(&cdoor_cv);
+         (void) mutex_unlock(&door_lock);
+ 
+         /*
           * Wait for incoming calls
           */
          /*CONSTCOND*/
          for (;;)
                  (void) pause();
*** 249,258 ****
--- 436,447 ----
  }
  
  static void
  free_logging_data(logging_data *lq)
  {
+         assert(mountd_bsm_audit == TRUE);
+ 
          if (lq != NULL) {
                  free(lq->ld_host);
                  free(lq->ld_netid);
  
                  if (lq->ld_nb != NULL) {
*** 270,279 ****
--- 459,470 ----
  static logging_data *
  remove_head_of_queue(void)
  {
          logging_data    *lq;
  
+         assert(mountd_bsm_audit == TRUE);
+ 
          /*
           * Pull it off the queue.
           */
          lq = logging_head;
          if (lq) {
*** 294,303 ****
--- 485,496 ----
  do_logging_queue(logging_data *lq)
  {
          int             cleared = 0;
          char            *host;
  
+         assert(mountd_bsm_audit == TRUE);
+ 
          while (lq) {
                  struct cln cln;
  
                  if (lq->ld_host == NULL) {
                          DTRACE_PROBE(mountd, name_by_lazy);
*** 329,338 ****
--- 522,533 ----
  static void *
  logging_svc(void *arg)
  {
          logging_data    *lq;
  
+         assert(mountd_bsm_audit == TRUE);
+ 
          for (;;) {
                  (void) mutex_lock(&logging_queue_lock);
                  while (logging_head == NULL) {
                          (void) cond_wait(&logging_queue_cv,
                              &logging_queue_lock);
*** 509,519 ****
          if (ret != SA_OK) {
                  syslog(LOG_ERR, "Reading of mountd_port from SMF "
                      "failed, using default value");
          }
  
!         while ((c = getopt(argc, argv, "dvrm:p:")) != EOF) {
                  switch (c) {
                  case 'd':
                          debug++;
                          break;
                  case 'v':
--- 704,714 ----
          if (ret != SA_OK) {
                  syslog(LOG_ERR, "Reading of mountd_port from SMF "
                      "failed, using default value");
          }
  
!         while ((c = getopt(argc, argv, "dvrm:p:A")) != EOF) {
                  switch (c) {
                  case 'd':
                          debug++;
                          break;
                  case 'v':
*** 529,538 ****
--- 724,735 ----
                                      argv[0]);
                                  break;
                          }
                          max_threads = tmp;
                          break;
+                 case 'A':
+                         mountd_bsm_audit = TRUE;
                  case 'p':
                          if (convert_int(&tmp, optarg) != 0 || tmp < 1 ||
                              tmp > UINT16_MAX) {
                                  (void) fprintf(stderr, "%s: invalid port "
                                      "number\n", argv[0]);
*** 596,607 ****
--- 793,806 ----
                  mount_vers_max = mount_vers_min;
          }
          (void) setlocale(LC_ALL, "");
          (void) rwlock_init(&sharetab_lock, USYNC_THREAD, NULL);
          (void) mutex_init(&mnttab_lock, USYNC_THREAD, NULL);
+         if (mountd_bsm_audit) {
                  (void) mutex_init(&logging_queue_lock, USYNC_THREAD, NULL);
                  (void) cond_init(&logging_queue_cv, USYNC_THREAD, NULL);
+         }
  
          netgroup_init();
  
  #if !defined(TEXT_DOMAIN)
  #define TEXT_DOMAIN "SYS_TEST"
*** 639,648 ****
--- 838,848 ----
          default:
                  /* daemon was already running */
                  exit(0);
          }
  
+         if (mountd_bsm_audit)
                  audit_mountd_setup();   /* BSM */
  
          /*
           * Get required system variables
           */
*** 699,712 ****
  
          /*
           * If max_threads was specified, then set the
           * maximum number of threads to the value specified.
           */
!         if (max_threads > 0 && !rpc_control(RPC_SVC_THRMAX_SET, &max_threads)) {
                  fprintf(stderr, "unable to set max_threads\n");
                  exit(1);
          }
  
          if (mountd_port < 0 || mountd_port > UINT16_MAX) {
                  fprintf(stderr, "unable to use specified port\n");
                  exit(1);
          }
--- 899,916 ----
  
          /*
           * If max_threads was specified, then set the
           * maximum number of threads to the value specified.
           */
!         if (max_threads > 0) {
!                 if (!rpc_control(RPC_SVC_THRMAX_SET, &max_threads)) {
                          fprintf(stderr, "unable to set max_threads\n");
                          exit(1);
                  }
+                 /* Default to one fourth of all threads */
+                 mx_thrds = (uint32_t)(max_threads / 4);
+         }
  
          if (mountd_port < 0 || mountd_port > UINT16_MAX) {
                  fprintf(stderr, "unable to use specified port\n");
                  exit(1);
          }
*** 717,726 ****
--- 921,942 ----
           */
          svc_unreg(MOUNTPROG, MOUNTVERS);
          svc_unreg(MOUNTPROG, MOUNTVERS_POSIX);
          svc_unreg(MOUNTPROG, MOUNTVERS3);
  
+         (void) mutex_init(&door_lock, USYNC_THREAD, NULL);
+         (void) cond_init(&adoor_cv, USYNC_THREAD, NULL);
+         (void) cond_init(&cdoor_cv, USYNC_THREAD, NULL);
+ 
+         /* server function to create/optimize door threads */
+         (void) door_server_create(mntd_thr_create);
+         if (thr_keycreate(&door_key, mntd_thr_destroy) != 0) {
+                 fprintf(stderr, "thr_keycreate (server thread): %s\n",
+                     strerror(errno));
+                 exit(3);
+         }
+ 
          /*
           * Create the nfsauth thread with same signal disposition
           * as the main thread. We need to create a separate thread
           * since mountd() will be both an RPC server (for remote
           * traffic) _and_ a doors server (for kernel upcalls).
*** 747,760 ****
           * audit_mountd_mount logging for mount requests. Use the same
           * signal disposition as the main thread. We create
           * a separate thread to allow the mount request threads to
           * clear as soon as possible.
           */
!         if (thr_create(NULL, 0, logging_svc, 0, thr_flags, &logging_thread)) {
!                 syslog(LOG_ERR, gettext("Failed to create LOGGING svc thread"));
                  exit(2);
          }
  
          /*
           * Enumerate network transports and create service listeners
           * as appropriate for each.
           */
--- 963,979 ----
           * audit_mountd_mount logging for mount requests. Use the same
           * signal disposition as the main thread. We create
           * a separate thread to allow the mount request threads to
           * clear as soon as possible.
           */
!         if (mountd_bsm_audit) {
!                 if (thr_create(NULL, 0, logging_svc, 0, thr_flags, NULL)) {
!                         syslog(LOG_ERR,
!                             gettext("Failed to create LOGGING svc thread"));
                          exit(2);
                  }
+         }
  
          /*
           * Enumerate network transports and create service listeners
           * as appropriate for each.
           */
*** 850,861 ****
          char *host;
  
          saverrno = errno;       /* save error code */
  
          host = cln_gethost(cln);
-         if (host == NULL)
-                 return;
  
          errno = saverrno;
          if (errno == 0)
                  syslog(LOG_ERR, "couldn't send reply to %s", host);
          else
--- 1069,1078 ----
*** 1076,1085 ****
--- 1293,1304 ----
      char *rpath, int status, int error)
  {
          logging_data    *lq;
          struct netbuf   *nb;
  
+         assert(mountd_bsm_audit == TRUE);
+ 
          lq = (logging_data *)calloc(1, sizeof (logging_data));
          if (lq == NULL)
                  goto cleanup;
  
          /*
*** 1153,1163 ****
          return (FALSE);
  }
  
  
  #define CLN_CLNAMES     (1 << 0)
- #define CLN_HOST        (1 << 1)
  
  static void
  cln_init_common(struct cln *cln, SVCXPRT *transp, char *netid,
      struct netbuf *nbuf)
  {
--- 1372,1381 ----
*** 1168,1182 ****
          } else {
                  cln->netid = netid;
                  cln->nbuf = nbuf;
          }
  
-         cln->nconf = NULL;
          cln->clnames = NULL;
-         cln->host = NULL;
- 
          cln->flags = 0;
  }
  
  void
  cln_init(struct cln *cln, SVCXPRT *transp)
  {
--- 1386,1419 ----
          } else {
                  cln->netid = netid;
                  cln->nbuf = nbuf;
          }
  
          cln->clnames = NULL;
          cln->flags = 0;
+ 
+         bzero(cln->host, sizeof (cln->host));
+ 
+         if (cln->netid != NULL && cln->nbuf != NULL &&
+             (cln->nconf = getnetconfigent(cln->netid)) != NULL) {
+                 if (strcmp(cln->nconf->nc_protofmly, NC_INET) == 0) {
+                         struct sockaddr_in *sa;
+                         /* LINTED pointer alignment */
+                         sa = (struct sockaddr_in *)(cln->nbuf->buf);
+                         (void) inet_ntop(AF_INET, &sa->sin_addr.s_addr,
+                             cln->host, sizeof (cln->host));
+                 } else if (strcmp(cln->nconf->nc_protofmly, NC_INET6) == 0) {
+                         struct sockaddr_in6 *sa;
+                         /* LINTED pointer alignment */
+                         sa = (struct sockaddr_in6 *)(cln->nbuf->buf);
+                         (void) inet_ntop(AF_INET6, &sa->sin6_addr.s6_addr,
+                             cln->host, sizeof (cln->host));
+                 }
+         }
+ 
+         if (strlen(cln->host) == 0)
+                 (void) strlcpy(cln->host, "(unknown)", sizeof (cln->host));
  }
  
  void
  cln_init(struct cln *cln, SVCXPRT *transp)
  {
*** 1195,1206 ****
          if (cln->nconf != NULL)
                  freenetconfigent(cln->nconf);
  
          if (cln->clnames != NULL)
                  netdir_free(cln->clnames, ND_HOSTSERVLIST);
- 
-         free(cln->host);
  }
  
  struct netbuf *
  cln_getnbuf(struct cln *cln)
  {
--- 1432,1441 ----
*** 1209,1291 ****
  
  struct nd_hostservlist *
  cln_getclientsnames(struct cln *cln)
  {
          if ((cln->flags & CLN_CLNAMES) == 0) {
!                 /*
!                  * nconf is not needed if we do not have nbuf (see
!                  * cln_gethost() too), so we check for nbuf and in a case it is
!                  * NULL we do not try to get nconf.
!                  */
!                 if (cln->netid != NULL && cln->nbuf != NULL) {
!                         cln->nconf = getnetconfigent(cln->netid);
!                         if (cln->nconf == NULL)
!                                 syslog(LOG_ERR, "%s: getnetconfigent failed",
!                                     cln->netid);
!                 }
! 
!                 if (cln->nconf != NULL && cln->nbuf != NULL)
                          (void) __netdir_getbyaddr_nosrv(cln->nconf,
                              &cln->clnames, cln->nbuf);
! 
                  cln->flags |= CLN_CLNAMES;
          }
  
          return (cln->clnames);
  }
  
- /*
-  * Return B_TRUE if the host is already available at no cost
-  */
- boolean_t
- cln_havehost(struct cln *cln)
- {
-         return ((cln->flags & (CLN_CLNAMES | CLN_HOST)) != 0);
- }
- 
  char *
  cln_gethost(struct cln *cln)
  {
          if (cln_getclientsnames(cln) != NULL)
                  return (cln->clnames->h_hostservs[0].h_host);
  
-         if ((cln->flags & CLN_HOST) == 0) {
-                 if (cln->nconf == NULL || cln->nbuf == NULL) {
-                         cln->host = strdup("(anon)");
-                 } else {
-                         char host[MAXIPADDRLEN];
- 
-                         if (strcmp(cln->nconf->nc_protofmly, NC_INET) == 0) {
-                                 struct sockaddr_in *sa;
- 
-                                 /* LINTED pointer alignment */
-                                 sa = (struct sockaddr_in *)(cln->nbuf->buf);
-                                 (void) inet_ntoa_r(sa->sin_addr, host);
- 
-                                 cln->host = strdup(host);
-                         } else if (strcmp(cln->nconf->nc_protofmly,
-                             NC_INET6) == 0) {
-                                 struct sockaddr_in6 *sa;
- 
-                                 /* LINTED pointer alignment */
-                                 sa = (struct sockaddr_in6 *)(cln->nbuf->buf);
-                                 (void) inet_ntop(AF_INET6,
-                                     sa->sin6_addr.s6_addr,
-                                     host, INET6_ADDRSTRLEN);
- 
-                                 cln->host = strdup(host);
-                         } else {
-                                 syslog(LOG_ERR, gettext("Client's address is "
-                                     "neither IPv4 nor IPv6"));
- 
-                                 cln->host = strdup("(anon)");
-                         }
-                 }
- 
-                 cln->flags |= CLN_HOST;
-         }
- 
          return (cln->host);
  }
  
  /*
   * Check mount requests, add to mounted list if ok
--- 1444,1469 ----
  
  struct nd_hostservlist *
  cln_getclientsnames(struct cln *cln)
  {
          if ((cln->flags & CLN_CLNAMES) == 0) {
!                 if (cln->nconf != NULL && cln->nbuf != NULL) {
                          (void) __netdir_getbyaddr_nosrv(cln->nconf,
                              &cln->clnames, cln->nbuf);
!                 }
                  cln->flags |= CLN_CLNAMES;
          }
  
          return (cln->clnames);
  }
  
  char *
  cln_gethost(struct cln *cln)
  {
          if (cln_getclientsnames(cln) != NULL)
                  return (cln->clnames->h_hostservs[0].h_host);
  
          return (cln->host);
  }
  
  /*
   * Check mount requests, add to mounted list if ok
*** 1328,1348 ****
           * get the host name now in case we need to spit out an
           * error message.
           */
          if (verbose) {
                  DTRACE_PROBE(mountd, name_by_verbose);
!                 if ((host = cln_gethost(&cln)) == NULL) {
!                         /*
!                          * We failed to get a name for the client, even
!                          * 'anon', probably because we ran out of memory.
!                          * In this situation it doesn't make sense to
!                          * allow the mount to succeed.
!                          */
!                         error = EACCES;
!                         goto reply;
                  }
-         }
  
          /*
           * If the version being used is less than the minimum version,
           * the filehandle translation should not be provided to the
           * client.
--- 1506,1517 ----
           * get the host name now in case we need to spit out an
           * error message.
           */
          if (verbose) {
                  DTRACE_PROBE(mountd, name_by_verbose);
!                 host = cln_gethost(&cln);
          }
  
          /*
           * If the version being used is less than the minimum version,
           * the filehandle translation should not be provided to the
           * client.
*** 1543,1578 ****
  
                  audit_status = mountres3.fhs_status;
                  break;
          }
  
!         if (cln_havehost(&cln))
                  host = cln_gethost(&cln);
  
          if (verbose)
!                 syslog(LOG_NOTICE, "MOUNT: %s %s %s",
!                     (host == NULL) ? "unknown host" : host,
                      error ? "denied" : "mounted", path);
  
          /*
           * If we can not create a queue entry, go ahead and do it
           * in the context of this thread.
           */
          enqueued = enqueue_logging_data(host, transp, path, rpath,
              audit_status, error);
-         if (enqueued == FALSE) {
-                 if (host == NULL) {
-                         DTRACE_PROBE(mountd, name_by_in_thread);
-                         host = cln_gethost(&cln);
-                 }
  
                  DTRACE_PROBE(mountd, logged_in_thread);
                  audit_mountd_mount(host, path, audit_status); /* BSM */
-                 if (!error)
-                         mntlist_new(host, rpath); /* add entry to mount list */
          }
  
          if (path != NULL)
                  svc_freeargs(transp, xdr_dirpath, (caddr_t)&path);
  
          if (sh)
                  sharefree(sh);
--- 1712,1747 ----
  
                  audit_status = mountres3.fhs_status;
                  break;
          }
  
!         if (host == NULL)
                  host = cln_gethost(&cln);
  
          if (verbose)
!                 syslog(LOG_NOTICE, "MOUNT: %s %s %s", host,
                      error ? "denied" : "mounted", path);
  
+         if (mountd_bsm_audit) {
                  /*
                   * If we can not create a queue entry, go ahead and do it
                   * in the context of this thread.
                   */
                  enqueued = enqueue_logging_data(host, transp, path, rpath,
                      audit_status, error);
  
+                 if (enqueued == FALSE) {
                          DTRACE_PROBE(mountd, logged_in_thread);
                          audit_mountd_mount(host, path, audit_status); /* BSM */
                  }
+         }
  
+         if (enqueued == FALSE && !error) {
+                 /* Add entry to mount list */
+                 mntlist_new(host, rpath);
+         }
+ 
          if (path != NULL)
                  svc_freeargs(transp, xdr_dirpath, (caddr_t)&path);
  
          if (sh)
                  sharefree(sh);
*** 1973,1982 ****
--- 2142,2158 ----
  
                          goto next;
                  }
  
                  /*
+                  * Before doing clients names lookup, check if it's individual
+                  * IP address specified without @ prefix.
+                  */
+                 if (strcmp(gr, cln->host) == 0)
+                         return (response);
+ 
+                 /*
                   * No other checks can be performed if client address
                   * can't be resolved.
                   */
                  if ((clnames = cln_getclientsnames(cln)) == NULL)
                          goto next;
*** 3223,3244 ****
          errno = 0;
          if (!svc_sendreply(transp, xdr_void, (char *)NULL))
                  log_cant_reply_cln(&cln);
  
          host = cln_gethost(&cln);
-         if (host == NULL) {
-                 /*
-                  * Without the hostname we can't do audit or delete
-                  * this host from the mount entries.
-                  */
-                 svc_freeargs(transp, xdr_dirpath, (caddr_t)&path);
-                 return;
-         }
  
          if (verbose)
                  syslog(LOG_NOTICE, "UNMOUNT: %s unmounted %s", host, path);
  
          audit_mountd_umount(host, path);
  
          remove_path = rpath;    /* assume we will use the cannonical path */
          if (realpath(path, rpath) == NULL) {
                  if (verbose)
--- 3399,3413 ----
          errno = 0;
          if (!svc_sendreply(transp, xdr_void, (char *)NULL))
                  log_cant_reply_cln(&cln);
  
          host = cln_gethost(&cln);
  
          if (verbose)
                  syslog(LOG_NOTICE, "UNMOUNT: %s unmounted %s", host, path);
  
+         if (mountd_bsm_audit)
                  audit_mountd_umount(host, path);
  
          remove_path = rpath;    /* assume we will use the cannonical path */
          if (realpath(path, rpath) == NULL) {
                  if (verbose)
*** 3277,3290 ****
          svcerr_systemerr(transp);
  
          cln_init(&cln, transp);
  
          host = cln_gethost(&cln);
-         if (host == NULL) {
-                 /* Can't do anything without the name of the client */
-                 return;
-         }
  
          /*
           * Remove all hosts entries from mount list
           */
          mntlist_delete_all(host);
--- 3446,3455 ----