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,12 +19,12 @@
  * 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 2016 Nexenta Systems, Inc.  All rights reserved.
  */
 
 /*      Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T     */
 /*        All Rights Reserved   */
 
@@ -61,10 +61,11 @@
 #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,10 +87,11 @@
 #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,12 +129,19 @@
 
 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;
 
+/*
+ * 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,29 +151,190 @@
 } 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)
 {
-        int     doorfd = -1;
         uint_t  darg;
+        uint_t  flags = (DOOR_PRIVATE | DOOR_NO_CANCEL | DOOR_REFUSE_DESC);
 #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");
+        /* 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,11 +341,11 @@
          * 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);
+                (void) close(auth_door);
                 exit(11);
         }
 
         /*
          * Clean up any stale namespace associations
@@ -183,26 +353,33 @@
         (void) fdetach(MOUNTD_DOOR);
 
         /*
          * Register in namespace to pass to the kernel to door_ki_open
          */
-        if (fattach(doorfd, MOUNTD_DOOR) == -1) {
+        if (fattach(auth_door, MOUNTD_DOOR) == -1) {
                 syslog(LOG_ERR, "Unable to fattach door: %m\n");
                 (void) close(dfd);
-                (void) close(doorfd);
+                (void) close(auth_door);
                 exit(12);
         }
         (void) close(dfd);
 #endif
 
         /*
          * Must pass the doorfd down to the kernel.
          */
-        darg = doorfd;
+        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,30 +392,40 @@
 /*
  * 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;
+        uint_t  flags = (DOOR_PRIVATE | DOOR_NO_CANCEL | DOOR_REFUSE_DESC);
 
-        if ((doorfd = door_create(nfscmd_func, NULL,
-            DOOR_REFUSE_DESC | DOOR_NO_CANCEL)) == -1) {
+        /* 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 doorfd down to the kernel.
+         * Must pass the cmd_door down to the kernel.
          */
-        darg = doorfd;
+        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,10 +436,12 @@
 }
 
 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,10 +459,12 @@
 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,10 +485,12 @@
 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,10 +522,12 @@
 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,11 +704,11 @@
         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) {
+        while ((c = getopt(argc, argv, "dvrm:p:A")) != EOF) {
                 switch (c) {
                 case 'd':
                         debug++;
                         break;
                 case 'v':
@@ -529,10 +724,12 @@
                                     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,12 +793,14 @@
                 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,10 +838,11 @@
         default:
                 /* daemon was already running */
                 exit(0);
         }
 
+        if (mountd_bsm_audit)
         audit_mountd_setup();   /* BSM */
 
         /*
          * Get required system variables
          */
@@ -699,14 +899,18 @@
 
         /*
          * 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)) {
+        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,10 +921,22 @@
          */
         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,14 +963,17 @@
          * 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"));
+        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,12 +1069,10 @@
         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
@@ -1076,10 +1293,12 @@
     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,11 +1372,10 @@
         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)
 {
@@ -1168,15 +1386,34 @@
         } else {
                 cln->netid = netid;
                 cln->nbuf = nbuf;
         }
 
-        cln->nconf = NULL;
         cln->clnames = NULL;
-        cln->host = 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,12 +1432,10 @@
         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)
 {
@@ -1209,83 +1444,26 @@
 
 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)
+                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
@@ -1328,21 +1506,12 @@
          * 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;
+                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,36 +1712,36 @@
 
                 audit_status = mountres3.fhs_status;
                 break;
         }
 
-        if (cln_havehost(&cln))
+        if (host == NULL)
                 host = cln_gethost(&cln);
 
         if (verbose)
-                syslog(LOG_NOTICE, "MOUNT: %s %s %s",
-                    (host == NULL) ? "unknown host" : host,
+                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) {
-                if (host == NULL) {
-                        DTRACE_PROBE(mountd, name_by_in_thread);
-                        host = cln_gethost(&cln);
-                }
 
+                if (enqueued == FALSE) {
                 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 (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,10 +2142,17 @@
 
                         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,22 +3399,15 @@
         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);
 
+        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,14 +3446,10 @@
         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);