Home | History | Annotate | Line # | Download | only in libamu
      1 /*	$NetBSD: mount_fs.c,v 1.3 2015/01/17 17:46:31 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1997-2014 Erez Zadok
      5  * Copyright (c) 1990 Jan-Simon Pendry
      6  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
      7  * Copyright (c) 1990 The Regents of the University of California.
      8  * All rights reserved.
      9  *
     10  * This code is derived from software contributed to Berkeley by
     11  * Jan-Simon Pendry at Imperial College, London.
     12  *
     13  * Redistribution and use in source and binary forms, with or without
     14  * modification, are permitted provided that the following conditions
     15  * are met:
     16  * 1. Redistributions of source code must retain the above copyright
     17  *    notice, this list of conditions and the following disclaimer.
     18  * 2. Redistributions in binary form must reproduce the above copyright
     19  *    notice, this list of conditions and the following disclaimer in the
     20  *    documentation and/or other materials provided with the distribution.
     21  * 3. Neither the name of the University nor the names of its contributors
     22  *    may be used to endorse or promote products derived from this software
     23  *    without specific prior written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     35  * SUCH DAMAGE.
     36  *
     37  *
     38  * File: am-utils/libamu/mount_fs.c
     39  *
     40  */
     41 
     42 #ifdef HAVE_CONFIG_H
     43 # include <config.h>
     44 #endif /* HAVE_CONFIG_H */
     45 #include <am_defs.h>
     46 #include <amu.h>
     47 #include <nfs_common.h>
     48 
     49 
     50 /* ensure that mount table options are delimited by a comma */
     51 #define append_opts(old, l, new) { \
     52 	if (*(old) != '\0') \
     53 	  xstrlcat(old, ",", l); \
     54 	xstrlcat(old, new, l); }
     55 
     56 /*
     57  * Standard mount flags
     58  */
     59 struct opt_tab mnt_flags[] =
     60 {
     61 #if defined(MNT2_GEN_OPT_RDONLY) && defined(MNTTAB_OPT_RO)
     62   {MNTTAB_OPT_RO, MNT2_GEN_OPT_RDONLY},
     63 #endif /* defined(MNT2_GEN_OPT_RDONLY) && defined(MNTTAB_OPT_RO) */
     64 
     65 #if defined(MNT2_GEN_OPT_NOCACHE) && defined(MNTTAB_OPT_NOCACHE)
     66   {MNTTAB_OPT_NOCACHE, MNT2_GEN_OPT_NOCACHE},
     67 #endif /* defined(MNT2_GEN_OPT_NOCACHE) && defined(MNTTAB_OPT_NOCACHE) */
     68 
     69   /* the "grpid" mount option can be offered as generic of NFS */
     70 #ifdef MNTTAB_OPT_GRPID
     71 # ifdef MNT2_GEN_OPT_GRPID
     72   {MNTTAB_OPT_GRPID, MNT2_GEN_OPT_GRPID},
     73 # endif /* MNT2_GEN_OPT_GRPID */
     74 # ifdef MNT2_NFS_OPT_GRPID
     75   {MNTTAB_OPT_GRPID, MNT2_NFS_OPT_GRPID},
     76 # endif /* MNT2_NFS_OPT_GRPID */
     77 #endif /* MNTTAB_OPT_GRPID */
     78 
     79 #if defined(MNT2_GEN_OPT_MULTI) && defined(MNTTAB_OPT_MULTI)
     80   {MNTTAB_OPT_MULTI, MNT2_GEN_OPT_MULTI},
     81 #endif /* defined(MNT2_GEN_OPT_MULTI) && defined(MNTTAB_OPT_MULTI) */
     82 
     83 #if defined(MNT2_GEN_OPT_NODEV) && defined(MNTTAB_OPT_NODEV)
     84   {MNTTAB_OPT_NODEV, MNT2_GEN_OPT_NODEV},
     85 #endif /* defined(MNT2_GEN_OPT_NODEV) && defined(MNTTAB_OPT_NODEV) */
     86 
     87 #if defined(MNT2_GEN_OPT_NOEXEC) && defined(MNTTAB_OPT_NOEXEC)
     88   {MNTTAB_OPT_NOEXEC, MNT2_GEN_OPT_NOEXEC},
     89 #endif /* defined(MNT2_GEN_OPT_NOEXEC) && defined(MNTTAB_OPT_NOEXEC) */
     90 
     91 #if defined(MNT2_GEN_OPT_NOSUB) && defined(MNTTAB_OPT_NOSUB)
     92   {MNTTAB_OPT_NOSUB, MNT2_GEN_OPT_NOSUB},
     93 #endif /* defined(MNT2_GEN_OPT_NOSUB) && defined(MNTTAB_OPT_NOSUB) */
     94 
     95 #if defined(MNT2_GEN_OPT_NOSUID) && defined(MNTTAB_OPT_NOSUID)
     96   {MNTTAB_OPT_NOSUID, MNT2_GEN_OPT_NOSUID},
     97 #endif /* defined(MNT2_GEN_OPT_NOSUID) && defined(MNTTAB_OPT_NOSUID) */
     98 
     99 #if defined(MNT2_GEN_OPT_SYNC) && defined(MNTTAB_OPT_SYNC)
    100   {MNTTAB_OPT_SYNC, MNT2_GEN_OPT_SYNC},
    101 #endif /* defined(MNT2_GEN_OPT_SYNC) && defined(MNTTAB_OPT_SYNC) */
    102 
    103 #if defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY)
    104   {MNTTAB_OPT_OVERLAY, MNT2_GEN_OPT_OVERLAY},
    105 #endif /* defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY) */
    106 
    107 #if defined(MNT2_GEN_OPT_LOG) && defined(MNTTAB_OPT_LOG)
    108   {MNTTAB_OPT_LOG, MNT2_GEN_OPT_LOG},
    109 #endif /* defined(MNT2_GEN_OPT_LOG) && defined(MNTTAB_OPT_LOG) */
    110 
    111 #if defined(MNT2_GEN_OPT_NOATIME) && defined(MNTTAB_OPT_NOATIME)
    112   {MNTTAB_OPT_NOATIME, MNT2_GEN_OPT_NOATIME},
    113 #endif /* defined(MNT2_GEN_OPT_NOATIME) && defined(MNTTAB_OPT_NOATIME) */
    114 
    115 #if defined(MNT2_GEN_OPT_NODEVMTIME) && defined(MNTTAB_OPT_NODEVMTIME)
    116   {MNTTAB_OPT_NODEVMTIME, MNT2_GEN_OPT_NODEVMTIME},
    117 #endif /* defined(MNT2_GEN_OPT_NODEVMTIME) && defined(MNTTAB_OPT_NODEVMTIME) */
    118 
    119 #if defined(MNT2_GEN_OPT_SOFTDEP) && defined(MNTTAB_OPT_SOFTDEP)
    120   {MNTTAB_OPT_SOFTDEP, MNT2_GEN_OPT_SOFTDEP},
    121 #endif /* defined(MNT2_GEN_OPT_SOFTDEP) && defined(MNTTAB_OPT_SOFTDEP) */
    122 
    123 #if defined(MNT2_GEN_OPT_SYMPERM) && defined(MNTTAB_OPT_SYMPERM)
    124   {MNTTAB_OPT_SYMPERM, MNT2_GEN_OPT_SYMPERM},
    125 #endif /* defined(MNT2_GEN_OPT_SYMPERM) && defined(MNTTAB_OPT_SYMPERM) */
    126 
    127 #if defined(MNT2_GEN_OPT_UNION) && defined(MNTTAB_OPT_UNION)
    128   {MNTTAB_OPT_UNION, MNT2_GEN_OPT_UNION},
    129 #endif /* defined(MNT2_GEN_OPT_UNION) && defined(MNTTAB_OPT_UNION) */
    130 
    131   /*
    132    * Do not define MNT2_NFS_OPT_* entries here!  This is for generic
    133    * mount(2) options only, not for NFS mount options.  If you need to put
    134    * something here, it's probably not the right place: see
    135    * include/am_compat.h.
    136    */
    137 
    138   {0, 0}
    139 };
    140 
    141 
    142 /* compute generic mount flags */
    143 int
    144 compute_mount_flags(mntent_t *mntp)
    145 {
    146   struct opt_tab *opt;
    147   int flags = 0;
    148 
    149 #ifdef MNT2_GEN_OPT_NEWTYPE
    150   flags |= MNT2_GEN_OPT_NEWTYPE;
    151 #endif /* MNT2_GEN_OPT_NEWTYPE */
    152 #ifdef MNT2_GEN_OPT_AUTOMOUNTED
    153   flags |= MNT2_GEN_OPT_AUTOMOUNTED;
    154 #endif /* not MNT2_GEN_OPT_AUTOMOUNTED */
    155 
    156   /*
    157    * Crack basic mount options
    158    */
    159   for (opt = mnt_flags; opt->opt; opt++) {
    160     flags |= amu_hasmntopt(mntp, opt->opt) ? opt->flag : 0;
    161   }
    162 
    163   return flags;
    164 }
    165 
    166 
    167 /* compute generic mount flags for automounter mounts */
    168 int
    169 compute_automounter_mount_flags(mntent_t *mntp)
    170 {
    171   int flags = 0;
    172 
    173 #ifdef MNT2_GEN_OPT_IGNORE
    174   flags |= MNT2_GEN_OPT_IGNORE;
    175 #endif /* not MNT2_GEN_OPT_IGNORE */
    176 #ifdef MNT2_GEN_OPT_AUTOMNTFS
    177   flags |= MNT2_GEN_OPT_AUTOMNTFS;
    178 #endif /* not MNT2_GEN_OPT_AUTOMNTFS */
    179 
    180   return flags;
    181 }
    182 
    183 
    184 #if defined(MOUNT_TABLE_ON_FILE) && defined(MNTTAB_OPT_VERS)
    185 /*
    186  * add the extra vers={2,3} field to the mount table,
    187  * unless already specified by user
    188  */
    189 static void
    190 addvers(char *zopts, size_t l, mntent_t *mnt, u_long have_vers,
    191   u_long want_vers)
    192 {
    193   if (have_vers == want_vers &&
    194       hasmntval(mnt, MNTTAB_OPT_VERS) != want_vers) {
    195     char optsbuf[48];
    196     xsnprintf(optsbuf, sizeof(optsbuf),
    197 	      "%s=%d", MNTTAB_OPT_VERS, want_vers);
    198     append_opts(zopts, l, optsbuf);
    199   }
    200 }
    201 #endif /* MOUNT_TABLE_ON_FILE && MNTTAB_OPT_VERS */
    202 
    203 int
    204 mount_fs(mntent_t *mnt, int flags, caddr_t mnt_data, int retry, MTYPE_TYPE type, u_long nfs_version, const char *nfs_proto, const char *mnttabname, int on_autofs)
    205 {
    206   int error = 0;
    207 #ifdef MOUNT_TABLE_ON_FILE
    208   char *zopts = NULL, *xopts = NULL;
    209   size_t l;
    210 #endif /* MOUNT_TABLE_ON_FILE */
    211   char *mnt_dir = NULL;
    212 
    213 #ifdef NEED_AUTOFS_SPACE_HACK
    214   char *old_mnt_dir = NULL;
    215   /* perform space hack */
    216   if (on_autofs) {
    217     old_mnt_dir = mnt->mnt_dir;
    218     mnt->mnt_dir = mnt_dir = autofs_strdup_space_hack(old_mnt_dir);
    219   } else
    220 #endif /* NEED_AUTOFS_SPACE_HACK */
    221     mnt_dir = xstrdup(mnt->mnt_dir);
    222 
    223   dlog("'%s' fstype " MTYPE_PRINTF_TYPE " (%s) flags %#x (%s)",
    224        mnt_dir, type, mnt->mnt_type, flags, mnt->mnt_opts);
    225 
    226 again:
    227   error = MOUNT_TRAP(type, mnt, flags, mnt_data);
    228 
    229   if (error < 0) {
    230     plog(XLOG_ERROR, "'%s': mount: %m", mnt_dir);
    231     /*
    232      * The following code handles conditions which shouldn't
    233      * occur.  They are possible either because amd screws up
    234      * in preparing for the mount, or because some human
    235      * messed with the mount point.  Both have been known to
    236      * happen. -- stolcke 2/22/95
    237      */
    238     if (errno == EBUSY) {
    239       /*
    240        * Also, sometimes unmount isn't called, e.g., because
    241        * our mountlist is garbled.  This leaves old mount
    242        * points around which need to be removed before we
    243        * can mount something new in their place.
    244        */
    245       errno = umount_fs(mnt_dir, mnttabname, on_autofs);
    246       if (errno != 0)
    247 	plog(XLOG_ERROR, "'%s': umount: %m", mnt_dir);
    248       else {
    249 	plog(XLOG_WARNING, "extra umount required for '%s'", mnt_dir);
    250 	error = MOUNT_TRAP(type, mnt, flags, mnt_data);
    251       }
    252     }
    253   }
    254 
    255   if (error < 0 && --retry > 0) {
    256     sleep(1);
    257     goto again;
    258   }
    259 
    260 #ifdef NEED_AUTOFS_SPACE_HACK
    261   /* Undo space hack */
    262   if (on_autofs)
    263     mnt->mnt_dir = old_mnt_dir;
    264 #endif /* NEED_AUTOFS_SPACE_HACK */
    265 
    266   if (error < 0) {
    267     error = errno;
    268     goto out;
    269   }
    270 
    271 #ifdef MOUNT_TABLE_ON_FILE
    272   /*
    273    * Allocate memory for options:
    274    *        dev=..., vers={2,3}, proto={tcp,udp}
    275    */
    276   l = strlen(mnt->mnt_opts) + 48;
    277   zopts = (char *) xmalloc(l);
    278 
    279   /* copy standard options */
    280   xopts = mnt->mnt_opts;
    281 
    282   xstrlcpy(zopts, xopts, l);
    283 
    284 # ifdef MNTTAB_OPT_DEV
    285   {
    286     /* add the extra dev= field to the mount table */
    287     struct stat stb;
    288     if (lstat(mnt_dir, &stb) == 0) {
    289       char optsbuf[48];
    290       if (sizeof(stb.st_dev) == 2) /* e.g. SunOS 4.1 */
    291 	xsnprintf(optsbuf, sizeof(optsbuf), "%s=%04lx",
    292 		  MNTTAB_OPT_DEV, (u_long) stb.st_dev & 0xffff);
    293       else			/* e.g. System Vr4 */
    294 	xsnprintf(optsbuf, sizeof(optsbuf), "%s=%08lx",
    295 		  MNTTAB_OPT_DEV, (u_long) stb.st_dev);
    296       append_opts(zopts, l, optsbuf);
    297     }
    298   }
    299 # endif /* MNTTAB_OPT_DEV */
    300 
    301 # if defined(HAVE_FS_NFS4) && defined(MNTTAB_OPT_VERS)
    302   addvers(zopts, l, mnt, nfs_version, NFS_VERSION4);
    303 # endif /* defined(HAVE_FS_NFS4) && defined(MNTTAB_OPT_VERS) */
    304 # if defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)
    305   addvers(zopts, l, mnt, nfs_version, NFS_VERSION3);
    306 # endif /* defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS) */
    307 # ifdef MNTTAB_OPT_VERS
    308   addvers(zopts, l, mnt, nfs_version, NFS_VERSION2);
    309 # endif /* MNTTAB_OPT_VERS */
    310 
    311 # ifdef MNTTAB_OPT_PROTO
    312   /*
    313    * add the extra proto={tcp,udp} field to the mount table,
    314    * unless already specified by user.
    315    */
    316   if (nfs_proto && !amu_hasmntopt(mnt, MNTTAB_OPT_PROTO)) {
    317     char optsbuf[48];
    318     xsnprintf(optsbuf, sizeof(optsbuf), "%s=%s", MNTTAB_OPT_PROTO, nfs_proto);
    319     append_opts(zopts, l, optsbuf);
    320   }
    321 # endif /* MNTTAB_OPT_PROTO */
    322 
    323   /* finally, store the options into the mount table structure */
    324   mnt->mnt_opts = zopts;
    325 
    326   /*
    327    * Additional fields in mntent_t
    328    * are fixed up here
    329    */
    330 # ifdef HAVE_MNTENT_T_MNT_CNODE
    331   mnt->mnt_cnode = 0;
    332 # endif /* HAVE_MNTENT_T_MNT_CNODE */
    333 
    334 # ifdef HAVE_MNTENT_T_MNT_RO
    335   mnt->mnt_ro = (amu_hasmntopt(mnt, MNTTAB_OPT_RO) != NULL);
    336 # endif /* HAVE_MNTENT_T_MNT_RO */
    337 
    338 # ifdef HAVE_MNTENT_T_MNT_TIME
    339 #  ifdef HAVE_MNTENT_T_MNT_TIME_STRING
    340   {				/* allocate enough space for a long */
    341     size_t l = 13 * sizeof(char);
    342     char *str = (char *) xmalloc(l);
    343     xsnprintf(str, l, "%ld", time((time_t *) NULL));
    344     mnt->mnt_time = str;
    345   }
    346 #  else /* not HAVE_MNTENT_T_MNT_TIME_STRING */
    347   mnt->mnt_time = time((time_t *) NULL);
    348 #  endif /* not HAVE_MNTENT_T_MNT_TIME_STRING */
    349 # endif /* HAVE_MNTENT_T_MNT_TIME */
    350 
    351   write_mntent(mnt, mnttabname);
    352 
    353 # ifdef MNTTAB_OPT_DEV
    354   if (xopts) {
    355     XFREE(mnt->mnt_opts);
    356     mnt->mnt_opts = xopts;
    357   }
    358 # endif /* MNTTAB_OPT_DEV */
    359 #endif /* MOUNT_TABLE_ON_FILE */
    360 
    361  out:
    362   XFREE(mnt_dir);
    363   return error;
    364 }
    365 
    366 
    367 /*
    368  * Compute all NFS attribute cache related flags separately.  Note that this
    369  * function now computes attribute-cache flags for both Amd's automount
    370  * points (NFS) as well as any normal NFS mount that Amd performs.  Edit
    371  * with caution.
    372  */
    373 static void
    374 compute_nfs_attrcache_flags(struct nfs_common_args *nap, mntent_t *mntp)
    375 {
    376   int acval = 0;
    377   int err_acval = 1;		/* 1 means we found no 'actimeo' value */
    378 #if defined(HAVE_NFS_ARGS_T_ACREGMIN) || defined(HAVE_NFS_ARGS_T_ACREGMAX) || defined(HAVE_NFS_ARGS_T_ACDIRMIN) || defined(HAVE_NFS_ARGS_T_ACDIRMAX)
    379   int err_acrdmm;		/* for ac{reg,dir}{min,max} */
    380 #endif /* HAVE_NFS_ARGS_T_AC{REG,DIR}{MIN,MAX} */
    381 
    382   /************************************************************************/
    383   /***	ATTRIBUTE CACHES						***/
    384   /************************************************************************/
    385   /*
    386    * acval is set to 0 at the top of the function.  If actimeo mount option
    387    * exists and defined in mntopts, then its acval is set to it.
    388    * If the value is non-zero, then we set all attribute cache fields to it.
    389    * If acval is zero, it means it was never defined in mntopts or the
    390    * actimeo mount option does not exist, in which case we check for
    391    * individual mount options per attribute cache.
    392    * Regardless of the value of acval, mount flags are set based directly
    393    * on the values of the attribute caches.
    394    */
    395 #ifdef MNTTAB_OPT_ACTIMEO
    396   err_acval = hasmntvalerr(mntp, MNTTAB_OPT_ACTIMEO, &acval);	/* attr cache timeout (sec) */
    397 #endif /* MNTTAB_OPT_ACTIMEO */
    398 
    399   /*** acregmin ***/
    400 #ifdef HAVE_NFS_ARGS_T_ACREGMIN
    401   err_acrdmm = 1;		/* 1 means we found no acregmin value */
    402   if (!err_acval) {
    403     nap->acregmin = acval;	/* min ac timeout for reg files (sec) */
    404   } else {
    405 # ifdef MNTTAB_OPT_ACREGMIN
    406     int tmp;
    407     err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMIN, &tmp);
    408     nap->acregmin = tmp;
    409 # else /* not MNTTAB_OPT_ACREGMIN */
    410     nap->acregmin = 0;
    411 # endif /* not MNTTAB_OPT_ACREGMIN */
    412   }
    413   /* set this flag iff we changed acregmin (possibly to zero) */
    414 # ifdef MNT2_NFS_OPT_ACREGMIN
    415   if (!err_acval || !err_acrdmm)
    416     nap->flags |= MNT2_NFS_OPT_ACREGMIN;
    417 # endif /* MNT2_NFS_OPT_ACREGMIN */
    418 #endif /* HAVE_NFS_ARGS_T_ACREGMIN */
    419 
    420   /*** acregmax ***/
    421 #ifdef HAVE_NFS_ARGS_T_ACREGMAX
    422   err_acrdmm = 1;		/* 1 means we found no acregmax value */
    423   if (!err_acval) {
    424     nap->acregmax = acval;	/* max ac timeout for reg files (sec) */
    425   } else {
    426 # ifdef MNTTAB_OPT_ACREGMAX
    427     int tmp;
    428     err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMAX, &tmp);
    429     nap->acregmax = tmp;
    430 # else /* not MNTTAB_OPT_ACREGMAX */
    431     nap->acregmax = 0;
    432 # endif /* not MNTTAB_OPT_ACREGMAX */
    433   }
    434   /* set this flag iff we changed acregmax (possibly to zero) */
    435 # ifdef MNT2_NFS_OPT_ACREGMAX
    436   if (!err_acval || !err_acrdmm)
    437     nap->flags |= MNT2_NFS_OPT_ACREGMAX;
    438 # endif /* MNT2_NFS_OPT_ACREGMAX */
    439 #endif /* HAVE_NFS_ARGS_T_ACREGMAX */
    440 
    441   /*** acdirmin ***/
    442 #ifdef HAVE_NFS_ARGS_T_ACDIRMIN
    443   err_acrdmm = 1;		/* 1 means we found no acdirmin value */
    444   if (!err_acval) {
    445     nap->acdirmin = acval;	/* min ac timeout for dirs (sec) */
    446   } else {
    447 # ifdef MNTTAB_OPT_ACDIRMIN
    448     int tmp;
    449     err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMIN, &tmp);
    450     nap->acdirmin = tmp;
    451 # else /* not MNTTAB_OPT_ACDIRMIN */
    452     nap->acdirmin = 0;
    453 # endif /* not MNTTAB_OPT_ACDIRMIN */
    454   }
    455   /* set this flag iff we changed acdirmin (possibly to zero) */
    456 # ifdef MNT2_NFS_OPT_ACDIRMIN
    457   if (!err_acval || !err_acrdmm)
    458     nap->flags |= MNT2_NFS_OPT_ACDIRMIN;
    459 # endif /* MNT2_NFS_OPT_ACDIRMIN */
    460 #endif /* HAVE_NFS_ARGS_T_ACDIRMIN */
    461 
    462   /*** acdirmax ***/
    463 #ifdef HAVE_NFS_ARGS_T_ACDIRMAX
    464   err_acrdmm = 1;		/* 1 means we found no acdirmax value */
    465   if (!err_acval) {
    466     nap->acdirmax = acval;	/* max ac timeout for dirs (sec) */
    467   } else {
    468 # ifdef MNTTAB_OPT_ACDIRMAX
    469     int tmp;
    470     err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMAX, &tmp);
    471     nap->acdirmax = tmp;
    472 # else /* not MNTTAB_OPT_ACDIRMAX */
    473     nap->acdirmax = 0;
    474 # endif /* not MNTTAB_OPT_ACDIRMAX */
    475   }
    476   /* set this flag iff we changed acdirmax (possibly to zero) */
    477 # ifdef MNT2_NFS_OPT_ACDIRMAX
    478   if (!err_acval || !err_acrdmm)
    479     nap->flags |= MNT2_NFS_OPT_ACDIRMAX;
    480 # endif /* MNT2_NFS_OPT_ACDIRMAX */
    481 #endif /* HAVE_NFS_ARGS_T_ACDIRMAX */
    482 
    483 
    484   /* don't cache attributes */
    485 #if defined(MNTTAB_OPT_NOAC) && defined(MNT2_NFS_OPT_NOAC)
    486   if (amu_hasmntopt(mntp, MNTTAB_OPT_NOAC) != NULL)
    487     nap->flags |= MNT2_NFS_OPT_NOAC;
    488 #endif /* defined(MNTTAB_OPT_NOAC) && defined(MNT2_NFS_OPT_NOAC) */
    489   (void)err_acval;
    490 }
    491 
    492 
    493 
    494 static void
    495 compute_nfs_common_args(struct nfs_common_args *nap, mntent_t *mntp,
    496     const char *nfs_proto, u_long nfs_version)
    497 {
    498 #ifdef MNT2_NFS_OPT_TCP
    499   if (nfs_proto && STREQ(nfs_proto, "tcp"))
    500     nap->flags |= MNT2_NFS_OPT_TCP;
    501 #endif /* MNT2_NFS_OPT_TCP */
    502 
    503 #ifdef MNT2_NFS_OPT_NOCONN
    504   /* check if user specified to use unconnected or connected sockets */
    505   if (amu_hasmntopt(mntp, MNTTAB_OPT_NOCONN) != NULL)
    506     nap->flags |= MNT2_NFS_OPT_NOCONN;
    507   else if (amu_hasmntopt(mntp, MNTTAB_OPT_CONN) != NULL)
    508     nap->flags &= ~MNT2_NFS_OPT_NOCONN;
    509   else {
    510     /*
    511      * Some OSs want you to set noconn always.  Some want you to always turn
    512      * it off.  Others want you to turn it on/off only if NFS V.3 is used.
    513      * And all of that changes from revision to another.  This is
    514      * particularly true of OpenBSD, NetBSD, and FreeBSD.  So, rather than
    515      * attempt to auto-detect this, I'm forced to "fix" it in the individual
    516      * conf/nfs_prot/nfs_prot_*.h files.
    517      */
    518 # ifdef USE_UNCONNECTED_NFS_SOCKETS
    519     if (!(nap->flags & MNT2_NFS_OPT_NOCONN)) {
    520       nap->flags |= MNT2_NFS_OPT_NOCONN;
    521       plog(XLOG_WARNING, "noconn option not specified, and was just turned ON (OS override)! (May cause NFS hangs on some systems...)");
    522     }
    523 # endif /* USE_UNCONNECTED_NFS_SOCKETS */
    524 # ifdef USE_CONNECTED_NFS_SOCKETS
    525     if (nap->flags & MNT2_NFS_OPT_NOCONN) {
    526       nap->flags &= ~MNT2_NFS_OPT_NOCONN;
    527       plog(XLOG_WARNING, "noconn option specified, and was just turned OFF (OS override)! (May cause NFS hangs on some systems...)");
    528     }
    529 # endif /* USE_CONNECTED_NFS_SOCKETS */
    530   }
    531 #endif /* MNT2_NFS_OPT_NOCONN */
    532 
    533 #ifdef MNT2_NFS_OPT_RESVPORT
    534 # ifdef MNTTAB_OPT_RESVPORT
    535   if (amu_hasmntopt(mntp, MNTTAB_OPT_RESVPORT) != NULL)
    536     nap->flags |= MNT2_NFS_OPT_RESVPORT;
    537 # else /* not MNTTAB_OPT_RESVPORT */
    538   nap->flags |= MNT2_NFS_OPT_RESVPORT;
    539 # endif /* not MNTTAB_OPT_RESVPORT */
    540 #endif /* MNT2_NFS_OPT_RESVPORT */
    541 
    542   nap->rsize = hasmntval(mntp, MNTTAB_OPT_RSIZE);
    543 #ifdef MNT2_NFS_OPT_RSIZE
    544   if (nap->rsize)
    545     nap->flags |= MNT2_NFS_OPT_RSIZE;
    546 #endif /* MNT2_NFS_OPT_RSIZE */
    547   if (nfs_version == NFS_VERSION && nap->rsize > 8192)
    548     nap->rsize = 8192;
    549 
    550   nap->wsize = hasmntval(mntp, MNTTAB_OPT_WSIZE);
    551 #ifdef MNT2_NFS_OPT_WSIZE
    552   if (nap->wsize)
    553     nap->flags |= MNT2_NFS_OPT_WSIZE;
    554 #endif /* MNT2_NFS_OPT_WSIZE */
    555   if (nfs_version == NFS_VERSION && nap->wsize > 8192)
    556     nap->wsize = 8192;
    557 
    558   nap->timeo = hasmntval(mntp, MNTTAB_OPT_TIMEO);
    559 #ifdef MNT2_NFS_OPT_TIMEO
    560   if (nap->timeo)
    561     nap->flags |= MNT2_NFS_OPT_TIMEO;
    562 #endif /* MNT2_NFS_OPT_TIMEO */
    563 
    564   nap->retrans = hasmntval(mntp, MNTTAB_OPT_RETRANS);
    565 #ifdef MNT2_NFS_OPT_RETRANS
    566   if (nap->retrans)
    567     nap->flags |= MNT2_NFS_OPT_RETRANS;
    568 #endif /* MNT2_NFS_OPT_RETRANS */
    569 
    570 #ifdef MNT2_NFS_OPT_SOFT
    571   if (amu_hasmntopt(mntp, MNTTAB_OPT_SOFT) != NULL)
    572     nap->flags |= MNT2_NFS_OPT_SOFT;
    573 #endif /* MNT2_NFS_OPT_SOFT */
    574 
    575 #ifdef MNT2_NFS_OPT_SPONGY
    576   if (amu_hasmntopt(mntp, MNTTAB_OPT_SPONGY) != NULL) {
    577     nap->flags |= MNT2_NFS_OPT_SPONGY;
    578     if (*flags & MNT2_NFS_OPT_SOFT) {
    579       plog(XLOG_USER, "Mount opts soft and spongy are incompatible - soft ignored");
    580       nap->flags &= ~MNT2_NFS_OPT_SOFT;
    581     }
    582   }
    583 #endif /* MNT2_NFS_OPT_SPONGY */
    584 
    585 #if defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY)
    586   /* Ultrix has separate generic and NFS ro flags */
    587   if (genflags & MNT2_GEN_OPT_RONLY)
    588     nap->flags |= MNT2_NFS_OPT_RONLY;
    589 #endif /* defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY) */
    590 
    591 #ifdef MNTTAB_OPT_INTR
    592   if (amu_hasmntopt(mntp, MNTTAB_OPT_INTR) != NULL)
    593     /*
    594      * Either turn on the "allow interrupts" option, or
    595      * turn off the "disallow interrupts" option"
    596      */
    597 # ifdef MNT2_NFS_OPT_INTR
    598     nap->flags |= MNT2_NFS_OPT_INTR;
    599 # endif /* MNT2_NFS_OPT_INTR */
    600 # ifdef MNT2_NFS_OPT_NOINTR
    601     nap->flags &= ~MNT2_NFS_OPT_NOINTR;
    602 # endif /* MNT2_NFS_OPT_NOINTR */
    603 # ifdef MNT2_NFS_OPT_INT
    604     nap->flags |= MNT2_NFS_OPT_INT;
    605 # endif /* MNT2_NFS_OPT_INT */
    606 # ifdef MNT2_NFS_OPT_NOINT
    607     nap->flags &= ~MNT2_NFS_OPT_NOINT;
    608 # endif /* MNT2_NFS_OPT_NOINT */
    609 #endif /* MNTTAB_OPT_INTR */
    610 
    611 #ifdef MNT2_NFS_OPT_NOACL
    612   if (amu_hasmntopt(mntp, MNTTAB_OPT_NOACL) != NULL)
    613     nap->flags |= MNT2_NFS_OPT_NOACL;
    614 #endif /* MNT2_NFS_OPT_NOACL */
    615 
    616 #ifdef MNTTAB_OPT_NODEVS
    617   if (amu_hasmntopt(mntp, MNTTAB_OPT_NODEVS) != NULL)
    618     nap->flags |= MNT2_NFS_OPT_NODEVS;
    619 #endif /* MNTTAB_OPT_NODEVS */
    620 
    621 #ifdef MNTTAB_OPT_COMPRESS
    622   if (amu_hasmntopt(mntp, MNTTAB_OPT_COMPRESS) != NULL)
    623     nap->flags |= MNT2_NFS_OPT_COMPRESS;
    624 #endif /* MNTTAB_OPT_COMPRESS */
    625 
    626 #ifdef MNTTAB_OPT_PRIVATE	/* mount private, single-client tree */
    627   if (amu_hasmntopt(mntp, MNTTAB_OPT_PRIVATE) != NULL)
    628     nap->flags |= MNT2_NFS_OPT_PRIVATE;
    629 #endif /* MNTTAB_OPT_PRIVATE */
    630 
    631 
    632 #if defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO)
    633   if (amu_hasmntopt(mntp, MNTTAB_OPT_NOCTO) != NULL)
    634     nap->flags |= MNT2_NFS_OPT_NOCTO;
    635 #endif /* defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO) */
    636 
    637 #if defined(MNT2_NFS_OPT_PROPLIST) && defined(MNTTAB_OPT_PROPLIST)
    638   if (amu_hasmntopt(mntp, MNTTAB_OPT_PROPLIST) != NULL)
    639     nap->flags |= MNT2_NFS_OPT_PROPLIST;
    640 #endif /* defined(MNT2_NFS_OPT_PROPLIST) && defined(MNTTAB_OPT_PROPLIST) */
    641 
    642 #if defined(MNT2_NFS_OPT_NONLM) && defined(MNTTAB_OPT_NOLOCK)
    643   if (amu_hasmntopt(mntp, MNTTAB_OPT_NOLOCK) != NULL)
    644     nap->flags |= MNT2_NFS_OPT_NONLM;
    645 #endif /* defined(MNT2_NFS_OPT_NONLM) && defined(MNTTAB_OPT_NOLOCK) */
    646 
    647 #if defined(MNT2_NFS_OPT_XLATECOOKIE) && defined(MNTTAB_OPT_XLATECOOKIE)
    648   if (amu_hasmntopt(mntp, MNTTAB_OPT_XLATECOOKIE) != NULL)
    649     nap->flags |= MNT2_NFS_OPT_XLATECOOKIE;
    650 #endif /* defined(MNT2_NFS_OPT_XLATECOOKIE) && defined(MNTTAB_OPT_XLATECOOKIE) */
    651 }
    652 
    653 #ifdef DEBUG
    654 static void
    655 print_nfs_common_args(const struct nfs_common_args *a)
    656 {
    657   plog(XLOG_DEBUG, "NA->flags = 0x%lx", a->flags);
    658 
    659   plog(XLOG_DEBUG, "NA->rsize = %lu", a->rsize);
    660   plog(XLOG_DEBUG, "NA->wsize = %lu", a->wsize);
    661   plog(XLOG_DEBUG, "NA->timeo = %lu", a->timeo);
    662   plog(XLOG_DEBUG, "NA->retrans = %lu", a->retrans);
    663 
    664 #ifdef HAVE_NFS_ARGS_T_ACREGMIN
    665   plog(XLOG_DEBUG, "NA->acregmin = %lu", a->acregmin);
    666   plog(XLOG_DEBUG, "NA->acregmax = %lu", a->acregmax);
    667   plog(XLOG_DEBUG, "NA->acdirmin = %lu", a->acdirmin);
    668   plog(XLOG_DEBUG, "NA->acdirmax = %lu", a->acdirmax);
    669 #endif /* HAVE_NFS_ARGS_T_ACREGMIN */
    670 }
    671 #endif
    672 
    673 static void
    674 discard_nfs23_args(nfs_args_t *nap)
    675 {
    676 #ifdef HAVE_TRANSPORT_TYPE_TLI
    677   free_knetconfig(nap->knconf);
    678   if (nap->addr)
    679     XFREE(nap->addr);	/* allocated in compute_nfs_args() */
    680 #endif /* HAVE_TRANSPORT_TYPE_TLI */
    681 }
    682 
    683 #ifdef DEBUG
    684 /* get string version (in hex) of identifier */
    685 static char *
    686 get_hex_string(u_int len, const char *fhdata)
    687 {
    688   u_int i;
    689   static u_int xlen;
    690   static char *buf;
    691   static u_short *arr;
    692   char str[16];
    693 
    694   if (!fhdata || len == 0 || len > 10240)
    695     return NULL;
    696   i = len * 4 + 1;
    697   if (xlen < i) {
    698     buf = xrealloc(buf, i);
    699     arr = xrealloc(arr, len * sizeof(*arr));
    700     xlen = i;
    701   }
    702 
    703   buf[0] = '\0';
    704   memset(arr, 0, len * sizeof(*arr));
    705   memcpy(arr, fhdata, len);
    706   len /= sizeof(*arr);
    707   for (i = 0; i < len; i++) {
    708     xsnprintf(str, sizeof(str), "%04x", ntohs(arr[i]));
    709     xstrlcat(buf, str, xlen);
    710   }
    711   return buf;
    712 }
    713 
    714 static void
    715 print_nfs_sockaddr_in(const char *tag, const struct sockaddr_in *sap)
    716 {
    717   char name[64];
    718   plog(XLOG_DEBUG, "NA->%s.sin_family = %d", tag, sap->sin_family);
    719   plog(XLOG_DEBUG, "NA->%s.sin_port = %d", tag, ntohs(sap->sin_port));
    720   if (inet_ntop(AF_INET, &sap->sin_addr, name, sizeof(name)) == NULL)
    721     return;
    722   plog(XLOG_DEBUG, "NA->%s.sin_addr = \"%s\"", tag, name);
    723 }
    724 
    725 /*
    726  * print a subset of fields from "struct nfs_args" that are otherwise
    727  * not being provided anywhere else.
    728  */
    729 static void
    730 print_nfs23_args(const nfs_args_t *nap, u_long nfs_version)
    731 {
    732   int fhlen = 32;	/* default: NFS V.2 file handle length is 32 */
    733 #ifdef HAVE_TRANSPORT_TYPE_TLI
    734   struct netbuf *nbp;
    735   struct knetconfig *kncp;
    736 #else /* not HAVE_TRANSPORT_TYPE_TLI */
    737   struct sockaddr_in *sap;
    738 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
    739   struct nfs_common_args a;
    740 
    741   if (!nap) {
    742     plog(XLOG_DEBUG, "NULL nfs_args!");
    743     return;
    744   }
    745 
    746   /* override default file handle size */
    747 #ifdef FHSIZE
    748    fhlen = FHSIZE;
    749 #endif /* FHSIZE */
    750 #ifdef NFS_FHSIZE
    751    fhlen = NFS_FHSIZE;
    752 #endif /* NFS_FHSIZE */
    753 
    754 #ifdef HAVE_TRANSPORT_TYPE_TLI
    755   nbp = nap->addr;
    756   plog(XLOG_DEBUG, "NA->addr {netbuf} (maxlen=%d, len=%d) = \"%s\"",
    757        nbp->maxlen, nbp->len,
    758        get_hex_string(nbp->len, nbp->buf));
    759   nbp = nap->syncaddr;
    760   plog(XLOG_DEBUG, "NA->syncaddr {netbuf} %p", nbp);
    761   kncp = nap->knconf;
    762   plog(XLOG_DEBUG, "NA->knconf->semantics %lu", (u_long) kncp->knc_semantics);
    763   plog(XLOG_DEBUG, "NA->knconf->protofmly \"%s\"", kncp->knc_protofmly);
    764   plog(XLOG_DEBUG, "NA->knconf->proto \"%s\"", kncp->knc_proto);
    765   plog(XLOG_DEBUG, "NA->knconf->rdev %lu", (u_long) kncp->knc_rdev);
    766   /* don't print knconf->unused field */
    767 #else /* not HAVE_TRANSPORT_TYPE_TLI */
    768 # ifdef NFS_ARGS_T_ADDR_IS_POINTER
    769     sap = (struct sockaddr_in *) nap->addr;
    770 # else /* not NFS_ARGS_T_ADDR_IS_POINTER */
    771     sap = (struct sockaddr_in *) &nap->addr;
    772 # endif /* not NFS_ARGS_T_ADDR_IS_POINTER */
    773 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
    774   /* as per POSIX, sin_len need not be set (used internally by kernel) */
    775   plog(XLOG_DEBUG, "NA->addr.sin_len = %d", sap->sin_len);
    776 #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
    777   print_nfs_sockaddr_in("addr", sap);
    778 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
    779 #ifdef HAVE_NFS_ARGS_T_ADDRLEN
    780   plog(XLOG_DEBUG, "NA->addrlen = %d", nap->addrlen);
    781 #endif /* ifdef HAVE_NFS_ARGS_T_ADDRLEN */
    782 
    783   plog(XLOG_DEBUG, "NA->hostname = \"%s\"", nap->hostname ? nap->hostname : "null");
    784 #ifdef HAVE_NFS_ARGS_T_NAMLEN
    785   plog(XLOG_DEBUG, "NA->namlen = %d", nap->namlen);
    786 #endif /* HAVE_NFS_ARGS_T_NAMLEN */
    787 
    788 #ifdef MNT2_NFS_OPT_FSNAME
    789   plog(XLOG_DEBUG, "NA->fsname = \"%s\"", nap->fsname ? nap->fsname : "null");
    790 #endif /* MNT2_NFS_OPT_FSNAME */
    791 
    792 #ifdef HAVE_NFS_ARGS_T_FHSIZE
    793   plog(XLOG_DEBUG, "NA->fhsize = %d", nap->fhsize);
    794   fhlen = nap->fhsize;
    795 #endif /* HAVE_NFS_ARGS_T_FHSIZE */
    796 #ifdef HAVE_NFS_ARGS_T_FH_LEN
    797   plog(XLOG_DEBUG, "NA->fh_len = %d", nap->fh_len);
    798   fhlen = nap->fh_len;
    799 #endif /* HAVE_NFS_ARGS_T_FH_LEN */
    800 
    801   /*
    802    * XXX: need to figure out how to correctly print file handles,
    803    * since some times they are pointers, and sometimes the real structure
    804    * is stored in nfs_args.  Even if it is a pointer, it can be the actual
    805    * char[] array, or a structure containing multiple fields.
    806    */
    807   plog(XLOG_DEBUG, "NA->filehandle = \"%s\"",
    808        get_hex_string(fhlen, (const char *) &nap->NFS_FH_FIELD));
    809 
    810 #ifdef HAVE_NFS_ARGS_T_SOTYPE
    811   plog(XLOG_DEBUG, "NA->sotype = %d", nap->sotype);
    812 #endif /* HAVE_NFS_ARGS_T_SOTYPE */
    813 #ifdef HAVE_NFS_ARGS_T_PROTO
    814   plog(XLOG_DEBUG, "NA->proto = %d", (int) nap->proto);
    815 #endif /* HAVE_NFS_ARGS_T_PROTO */
    816 #ifdef HAVE_NFS_ARGS_T_VERSION
    817   plog(XLOG_DEBUG, "NA->version = %d", nap->version);
    818 #endif /* HAVE_NFS_ARGS_T_VERSION */
    819 
    820   put_nfs_common_args(nap, a);
    821   print_nfs_common_args(&a);
    822 
    823 #ifdef HAVE_NFS_ARGS_T_BSIZE
    824   plog(XLOG_DEBUG, "NA->bsize = %d", nap->bsize);
    825 #endif /* HAVE_NFS_ARGS_T_BSIZE */
    826 
    827 #ifdef MNTTAB_OPT_SYMTTL
    828   plog(XLOG_DEBUG, "NA->symttl = %d", nap->symttl);
    829 #endif /* MNTTAB_OPT_SYMTTL */
    830 #ifdef MNTTAB_OPT_PG_THRESH
    831   plog(XLOG_DEBUG, "NA->pg_thresh = %d", nap->pg_thresh);
    832 #endif /* MNTTAB_OPT_PG_THRESH */
    833 
    834 #ifdef MNT2_NFS_OPT_BIODS
    835   plog(XLOG_DEBUG, "NA->biods = %d", nap->biods);
    836 #endif /* MNT2_NFS_OPT_BIODS */
    837 
    838 }
    839 #endif /* DEBUG */
    840 
    841 /*
    842  * Fill in the many possible fields and flags of struct nfs_args.
    843  *
    844  * nap:		pre-allocated structure to fill in.
    845  * mntp:	mount entry structure (includes options)
    846  * genflags:	generic mount flags already determined
    847  * nfsncp:	(TLI only) netconfig entry for this NFS mount
    848  * ip_addr:	IP address of file server
    849  * nfs_version:	2, 3, or 0 if unknown
    850  * nfs_proto:	"udp", "tcp", or NULL.
    851  * fhp:		file handle structure pointer
    852  * host_name:	name of remote NFS host
    853  * fs_name:	remote file system name to mount
    854  */
    855 static void
    856 compute_nfs23_args(nfs_args_t *nap,
    857 		   mntent_t *mntp,
    858 		   int genflags,
    859 		   struct netconfig *nfsncp,
    860 		   struct sockaddr_in *ip_addr,
    861 		   u_long nfs_version,
    862 		   char *nfs_proto,
    863 		   am_nfs_handle_t *fhp,
    864 		   char *host_name,
    865 		   char *fs_name)
    866 {
    867   struct nfs_common_args a;
    868   /* initialize just in case */
    869   memset((voidp) nap, 0, sizeof(nfs_args_t));
    870 
    871   /* compute all of the NFS attribute-cache flags */
    872   memset(&a, 0, sizeof(a));
    873   compute_nfs_attrcache_flags(&a, mntp);
    874   compute_nfs_common_args(&a, mntp, nfs_proto, nfs_version);
    875   get_nfs_common_args(nap, a);
    876 
    877   /************************************************************************/
    878   /***	FILEHANDLE DATA AND LENGTH					***/
    879   /************************************************************************/
    880 #ifdef HAVE_FS_NFS3
    881   if (nfs_version == NFS_VERSION3) {
    882     if (fhp == NULL) {
    883       plog(XLOG_FATAL, "cannot pass NULL fh for NFSv%lu", nfs_version);
    884       going_down(1);
    885       return;
    886     }
    887 
    888 # if defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN)
    889     /*
    890      * Some systems (Irix/bsdi3) have a separate field in nfs_args for
    891      * the length of the file handle for NFS V3.  They insist that
    892      * the file handle set in nfs_args be plain bytes, and not
    893      * include the length field.
    894      */
    895     NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v3.am_fh3_data);
    896 # else /* not defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN) */
    897     NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v3);
    898 # endif /* not defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN) */
    899 # ifdef MNT2_NFS_OPT_NFSV3
    900     nap->flags |= MNT2_NFS_OPT_NFSV3;
    901 # endif /* MNT2_NFS_OPT_NFSV3 */
    902 # ifdef MNT2_NFS_OPT_VER3
    903     nap->flags |= MNT2_NFS_OPT_VER3;
    904 # endif /* MNT2_NFS_OPT_VER3 */
    905   } else
    906 #endif /* HAVE_FS_NFS3 */
    907   {
    908     if (fhp == NULL) {
    909       plog(XLOG_FATAL, "cannot pass NULL fh for NFSv%lu", nfs_version);
    910       going_down(1);
    911       return;
    912     }
    913     NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v2);
    914   }
    915 
    916 #ifdef HAVE_NFS_ARGS_T_FHSIZE
    917 # ifdef HAVE_FS_NFS3
    918   if (nfs_version == NFS_VERSION3)
    919     nap->fhsize = fhp->v3.am_fh3_length;
    920   else
    921 # endif /* HAVE_FS_NFS3 */
    922     nap->fhsize = FHSIZE;
    923 #endif /* HAVE_NFS_ARGS_T_FHSIZE */
    924 
    925   /* this is the version of the nfs_args structure, not of NFS! */
    926 #ifdef HAVE_NFS_ARGS_T_FH_LEN
    927 # ifdef HAVE_FS_NFS3
    928   if (nfs_version == NFS_VERSION3)
    929     nap->fh_len = fhp->v3.am_fh3_length;
    930   else
    931 # endif /* HAVE_FS_NFS3 */
    932     nap->fh_len = FHSIZE;
    933 #endif /* HAVE_NFS_ARGS_T_FH_LEN */
    934 
    935   /************************************************************************/
    936   /***	HOST NAME							***/
    937   /************************************************************************/
    938   /*
    939    * XXX: warning, using xstrlcpy in NFS_HN_DREF, which may corrupt a
    940    * struct nfs_args, or truncate our concocted "hostname:/path"
    941    * string prematurely.
    942    */
    943   NFS_HN_DREF(nap->hostname, host_name);
    944 #ifdef MNT2_NFS_OPT_HOSTNAME
    945   nap->flags |= MNT2_NFS_OPT_HOSTNAME;
    946 #endif /* MNT2_NFS_OPT_HOSTNAME */
    947 
    948   /************************************************************************/
    949   /***	IP ADDRESS OF REMOTE HOST					***/
    950   /************************************************************************/
    951   if (ip_addr) {
    952 #ifdef HAVE_TRANSPORT_TYPE_TLI
    953     nap->addr = ALLOC(struct netbuf); /* free()'ed at end of mount_nfs_fh() */
    954 #endif /* HAVE_TRANSPORT_TYPE_TLI */
    955     NFS_SA_DREF(nap, ip_addr);
    956   }
    957 
    958   /************************************************************************/
    959   /***	NFS PROTOCOL (UDP, TCP) AND VERSION				***/
    960   /************************************************************************/
    961 #ifdef HAVE_NFS_ARGS_T_SOTYPE
    962   /* bsdi3 uses this */
    963   if (nfs_proto) {
    964     if (STREQ(nfs_proto, "tcp"))
    965       nap->sotype = SOCK_STREAM;
    966     else if (STREQ(nfs_proto, "udp"))
    967       nap->sotype = SOCK_DGRAM;
    968   }
    969 #endif /* HAVE_NFS_ARGS_T_SOTYPE */
    970 
    971 #ifdef HAVE_NFS_ARGS_T_PROTO
    972   nap->proto = 0;		/* bsdi3 sets this field to zero  */
    973 # ifdef IPPROTO_TCP
    974   if (nfs_proto) {
    975     if (STREQ(nfs_proto, "tcp"))	/* AIX 4.2.x needs this */
    976       nap->proto = IPPROTO_TCP;
    977     else if (STREQ(nfs_proto, "udp"))
    978       nap->proto = IPPROTO_UDP;
    979   }
    980 # endif /* IPPROTO_TCP */
    981 #endif /* HAVE_NFS_ARGS_T_SOTYPE */
    982 
    983 #ifdef HAVE_NFS_ARGS_T_VERSION
    984 # ifdef NFS_ARGSVERSION
    985   nap->version = NFS_ARGSVERSION; /* BSDI 3.0 and OpenBSD 2.2 */
    986 # endif /* NFS_ARGSVERSION */
    987 # ifdef DG_MOUNT_NFS_VERSION
    988   nap->version = DG_MOUNT_NFS_VERSION; /* dg-ux */
    989 # endif /* DG_MOUNT_NFS_VERSION */
    990 #endif /* HAVE_NFS_ARGS_VERSION */
    991 
    992   /************************************************************************/
    993   /***	OTHER NFS SOCKET RELATED OPTIONS AND FLAGS			***/
    994   /************************************************************************/
    995 
    996   /************************************************************************/
    997   /***	OTHER FLAGS AND OPTIONS						***/
    998   /************************************************************************/
    999 
   1000 #ifdef MNT2_NFS_OPT_BIODS
   1001   if ((nap->biods = hasmntval(mntp, MNTTAB_OPT_BIODS)))
   1002     nap->flags |= MNT2_NFS_OPT_BIODS;
   1003 #endif /* MNT2_NFS_OPT_BIODS */
   1004 
   1005 #ifdef MNTTAB_OPT_SYMTTL	/* symlink cache time-to-live */
   1006   if ((nap->symttl = hasmntval(mntp, MNTTAB_OPT_SYMTTL)))
   1007     nap->args.flags |= MNT2_NFS_OPT_SYMTTL;
   1008 #endif /* MNTTAB_OPT_SYMTTL */
   1009 
   1010 #ifdef MNT2_NFS_OPT_PGTHRESH	/* paging threshold */
   1011   if ((nap->pg_thresh = hasmntval(mntp, MNTTAB_OPT_PGTHRESH)))
   1012     nap->args.flags |= MNT2_NFS_OPT_PGTHRESH;
   1013 #endif /* MNT2_NFS_OPT_PGTHRESH */
   1014 
   1015 #if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX)
   1016   if (amu_hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) {
   1017     nap->flags |= MNT2_NFS_OPT_POSIX;
   1018 # ifdef HAVE_NFS_ARGS_T_PATHCONF
   1019     nap->pathconf = NULL;
   1020 # endif /* HAVE_NFS_ARGS_T_PATHCONF */
   1021   }
   1022 #endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */
   1023 
   1024 #ifdef HAVE_TRANSPORT_TYPE_TLI
   1025   /* set up syncaddr field */
   1026   nap->syncaddr = (struct netbuf *) NULL;
   1027 
   1028   /* set up knconf field */
   1029   if (get_knetconfig(&nap->knconf, nfsncp, nfs_proto) < 0) {
   1030     plog(XLOG_FATAL, "cannot fill knetconfig structure for nfs_args");
   1031     going_down(1);
   1032     return;
   1033   }
   1034   /* update the flags field for knconf */
   1035   nap->args.flags |= MNT2_NFS_OPT_KNCONF;
   1036 #endif /* HAVE_TRANSPORT_TYPE_TLI */
   1037 
   1038 #ifdef MNT2_NFS_OPT_FSNAME
   1039   nap->fsname = fs_name;
   1040   nap->args.flags |= MNT2_NFS_OPT_FSNAME;
   1041 #endif /* MNT2_NFS_OPT_FSNAME */
   1042 
   1043 
   1044 #ifdef HAVE_NFS_ARGS_T_OPTSTR
   1045   nap->optstr = mntp->mnt_opts;
   1046 #endif /* HAVE_NFS_ARGS_T_OPTSTR */
   1047 
   1048 #if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS)
   1049   nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS);
   1050   if (nap->maxgrouplist != 0)
   1051     nap->flags |= MNT2_NFS_OPT_MAXGRPS;
   1052 #endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */
   1053 
   1054   /************************************************************************/
   1055   /***	FINAL ACTIONS							***/
   1056   /************************************************************************/
   1057 
   1058 #ifdef HAVE_NFS_ARGS_T_GFS_FLAGS
   1059   /* Ultrix stores generic flags in nfs_args.gfs_flags. */
   1060   nap->gfs_flags = genflags;
   1061 #endif /* HAVE_NFS_ARGS_T_FLAGS */
   1062 
   1063   return;			/* end of compute_nfs_args() function */
   1064 }
   1065 
   1066 #ifdef HAVE_FS_NFS4
   1067 
   1068 #define RPC_AUTH_GSS_KRB5       390003
   1069 #define RPC_AUTH_GSS_KRB5I      390004
   1070 #define RPC_AUTH_GSS_KRB5P      390005
   1071 #define RPC_AUTH_GSS_LKEY       390006
   1072 #define RPC_AUTH_GSS_LKEYI      390007
   1073 #define RPC_AUTH_GSS_LKEYP      390008
   1074 #define RPC_AUTH_GSS_SPKM       390009
   1075 #define RPC_AUTH_GSS_SPKMI      390010
   1076 #define RPC_AUTH_GSS_SPKMP      390011
   1077 
   1078 struct {
   1079   const char *name;
   1080   int num;
   1081 } flavours[] = {
   1082   { "unix",	AUTH_UNIX },
   1083   { "krb5",	RPC_AUTH_GSS_KRB5 },
   1084   { "krb5i",	RPC_AUTH_GSS_KRB5I },
   1085   { "krb5p",	RPC_AUTH_GSS_KRB5P },
   1086   { "lkey",	RPC_AUTH_GSS_LKEY },
   1087   { "lkeyi",	RPC_AUTH_GSS_LKEYI },
   1088   { "lkeyp",	RPC_AUTH_GSS_LKEYP },
   1089   { "spkm",	RPC_AUTH_GSS_SPKM },
   1090   { "spkmi",	RPC_AUTH_GSS_SPKMI },
   1091   { "spkmp",	RPC_AUTH_GSS_SPKMP },
   1092 };
   1093 
   1094 static char *
   1095 set_nfs4_security(nfs4_args_t *nap, mntent_t *mntp)
   1096 {
   1097   const char *o = hasmnteq(mntp, MNTTAB_OPT_SEC);
   1098   char *q, *s, *ss;
   1099   size_t l, i;
   1100 
   1101   if (o == NULL)
   1102     o = "unix";
   1103 
   1104   for (l = 1, q = strchr(o, ','); q; q = strchr(q + 1, ','))
   1105     l++;
   1106 
   1107   nap->auth_flavours = xmalloc(l * sizeof(*nap->auth_flavours));
   1108 
   1109   s = ss = xstrdup(o);
   1110   for (;;) {
   1111     q = strchr(s, ',');
   1112     if (q)
   1113 	*q = '\0';
   1114 
   1115     for (l = 0, i = 0; i < sizeof(flavours) / sizeof(flavours[0]); i++)
   1116       if (strcmp(flavours[i].name, s) == 0) {
   1117 	nap->auth_flavours[l++] = flavours[i].num;
   1118 	break;
   1119       }
   1120 
   1121     if (i == sizeof(flavours) / sizeof(flavours[0]))
   1122       plog(XLOG_ERROR, "Unknown NFSv4 security mechanism %s\n", s);
   1123 
   1124     if (q == NULL)
   1125       break;
   1126 
   1127     *q = ':';
   1128     s = ++q;
   1129   }
   1130 
   1131   nap->auth_flavourlen = l;
   1132   return ss;
   1133 }
   1134 
   1135 static int
   1136 get_my_ipv4addr(struct nfs_string *ns)
   1137 {
   1138   struct hostent *hp;
   1139   char myname[MAXHOSTNAMELEN];
   1140 
   1141   if (gethostname(myname, sizeof(myname)) == -1)
   1142     return -1;
   1143   if ((hp = gethostbyname(myname)) == NULL)
   1144     return -1;
   1145   if (inet_ntop(AF_INET, hp->h_addr, myname, sizeof(myname)) == NULL)
   1146     return -1;
   1147   ns->len = strlen(myname);
   1148   ns->data = xmalloc(ns->len + 1);
   1149   memcpy(ns->data, myname, ns->len + 1);
   1150   return 0;
   1151 }
   1152 
   1153 static void
   1154 add_nfs4_mntopts(const nfs4_args_t *nap, mntent_t *mntp, char *sec)
   1155 {
   1156   char *opts = mntp->mnt_opts;
   1157   char buf[1024], addr[128];
   1158   size_t len = strlen(mntp->mnt_opts);
   1159 
   1160   if (inet_ntop(AF_INET,
   1161       &((const struct sockaddr_in *)nap->host_addr)->sin_addr,
   1162       addr, sizeof(addr)) == NULL)
   1163     return;
   1164 
   1165   xsnprintf(buf, sizeof(buf), ",clientaddr=%s,addr=%s", nap->client_addr.data,
   1166 	    addr);
   1167 
   1168   len += strlen(buf) + 1;
   1169 
   1170   if (sec && strcmp(sec, "unix") != 0) {
   1171     len += strlen(sec) + strlen(MNTTAB_OPT_SEC) + 2; /* 2 = ",=" */
   1172   } else
   1173     sec = NULL;
   1174 
   1175   opts = xrealloc(mntp->mnt_opts, len);
   1176   xstrlcat(opts, buf, len);
   1177 
   1178   if (sec) {
   1179     xstrlcat(opts, ",", len);
   1180     xstrlcat(opts, MNTTAB_OPT_SEC, len);
   1181     xstrlcat(opts, "=", len);
   1182     xstrlcat(opts, sec, len);
   1183   }
   1184 
   1185   mntp->mnt_opts = opts;
   1186 }
   1187 
   1188 static void
   1189 print_nfs4_security(const nfs4_args_t *nap)
   1190 {
   1191   char buf[1024];
   1192   char num[64];
   1193   size_t i, j;
   1194 
   1195   buf[0] = '\0';
   1196 
   1197   for (i = 0; i < nap->auth_flavourlen; i++) {
   1198 
   1199     for (j = 0; j < sizeof(flavours) / sizeof(flavours[0]); j++)
   1200       if (flavours[j].num == nap->auth_flavours[i]) {
   1201 	xstrlcpy(num, flavours[j].name, sizeof(num));
   1202 	break;
   1203       }
   1204 
   1205     if (j == sizeof(flavours) / sizeof(flavours[0])) {
   1206       plog(XLOG_ERROR, "Unknown NFSv4 security mechanism %d\n",
   1207            nap->auth_flavours[i]);
   1208       xsnprintf(num, sizeof(num), "*%d*", nap->auth_flavours[i]);
   1209     }
   1210 
   1211     if (buf[0])
   1212       xstrlcat(buf, ":", sizeof(buf));
   1213 
   1214     xstrlcat(buf, num, sizeof(buf));
   1215   }
   1216 
   1217   plog(XLOG_DEBUG, "NA->auth_flavours \"%s\"\n", buf);
   1218 }
   1219 
   1220 static void
   1221 discard_nfs4_args(nfs4_args_t *nap)
   1222 {
   1223   if (nap->client_addr.data)
   1224     free(nap->client_addr.data);
   1225   if (nap->hostname.data)
   1226     free(nap->hostname.data);
   1227   if (nap->mnt_path.data)
   1228     free(nap->mnt_path.data);
   1229   if (nap->host_addr)
   1230     free(nap->host_addr);
   1231   if (nap->auth_flavours)
   1232     free(nap->auth_flavours);
   1233 }
   1234 
   1235 /*
   1236  * Fill in the many possible fields and flags of struct nfs4_args.
   1237  *
   1238  * nap:		pre-allocated structure to fill in.
   1239  * mntp:	mount entry structure (includes options)
   1240  * genflags:	generic mount flags already determined
   1241  * nfsncp:	(TLI only) netconfig entry for this NFS mount
   1242  * ip_addr:	IP address of file server
   1243  * nfs_version:	4, or 0 if unknown
   1244  * nfs_proto:	"udp", "tcp", or NULL.
   1245  * fhp:		file handle structure pointer
   1246  * host_name:	name of remote NFS host
   1247  * fs_name:	remote file system name to mount
   1248  */
   1249 static void
   1250 compute_nfs4_args(nfs4_args_t *nap,
   1251                   mntent_t *mntp,
   1252                   int genflags,
   1253                   struct netconfig *nfsncp,
   1254                   struct sockaddr_in *ip_addr,
   1255                   u_long nfs_version,
   1256                   char *nfs_proto,
   1257                   am_nfs_handle_t *fhp,
   1258                   char *host_name,
   1259                   char *fs_name)
   1260 {
   1261   char *s;
   1262   struct nfs_common_args a;
   1263   uint16_t nfs_port;
   1264 
   1265   /* initialize just in case */
   1266   memset((voidp) nap, 0, sizeof(nfs4_args_t));
   1267 
   1268   /* compute all of the NFS attribute-cache flags */
   1269   memset(&a, 0, sizeof(a));
   1270   compute_nfs_attrcache_flags(&a, mntp);
   1271   compute_nfs_common_args(&a, mntp, nfs_proto, nfs_version);
   1272   get_nfs_common_args(nap, a);
   1273 
   1274   get_my_ipv4addr(&nap->client_addr);
   1275 
   1276   /************************************************************************/
   1277   /***	HOST NAME							***/
   1278   /************************************************************************/
   1279   nap->hostname.len = strlen(host_name);
   1280   nap->hostname.data = xmalloc(nap->hostname.len + 1);
   1281   memcpy(nap->hostname.data, host_name, nap->hostname.len + 1);
   1282 
   1283   if ((s = strchr(fs_name, ':')) != NULL)
   1284     s++;
   1285   else
   1286     s = fs_name;
   1287 
   1288   nap->mnt_path.len = strlen(s);
   1289   nap->mnt_path.data = xmalloc(nap->mnt_path.len + 1);
   1290   memcpy(nap->mnt_path.data, s, nap->mnt_path.len + 1);
   1291   plog(XLOG_DEBUG, "dir name %s\n", nap->mnt_path.data);
   1292 
   1293   /************************************************************************/
   1294   /***  IP ADDRESS OF REMOTE HOST                                       ***/
   1295   /************************************************************************/
   1296   nap->host_addrlen = sizeof(*ip_addr);
   1297   nap->host_addr = xmalloc(nap->host_addrlen);
   1298   memcpy(nap->host_addr, ip_addr, nap->host_addrlen);
   1299 
   1300   nfs_port = hasmntval(mntp, MNTTAB_OPT_PORT);
   1301   if (nfs_port == 0)
   1302     nfs_port = htons(NFS_PORT);
   1303   else
   1304     nfs_port = htons(nfs_port);
   1305 
   1306   ((struct sockaddr_in *)nap->host_addr)->sin_port = nfs_port;
   1307 
   1308   nap->proto = 0;               /* bsdi3 sets this field to zero  */
   1309   if (nfs_proto) {
   1310     if (STREQ(nfs_proto, "tcp"))        /* AIX 4.2.x needs this */
   1311       nap->proto = IPPROTO_TCP;
   1312     else if (STREQ(nfs_proto, "udp"))
   1313       nap->proto = IPPROTO_UDP;
   1314   }
   1315 
   1316   nap->version = NFS4_MOUNT_VERSION; /* BSDI 3.0 and OpenBSD 2.2 */
   1317 
   1318   /************************************************************************/
   1319   /***  OTHER NFS SOCKET RELATED OPTIONS AND FLAGS                      ***/
   1320   /************************************************************************/
   1321 
   1322 
   1323   /************************************************************************/
   1324   /***  OTHER FLAGS AND OPTIONS                                         ***/
   1325   /************************************************************************/
   1326 
   1327 #if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX)
   1328   if (amu_hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) {
   1329     nap->args.flags |= MNT2_NFS_OPT_POSIX;
   1330 # ifdef HAVE_NFS_ARGS_T_PATHCONF
   1331     nap->pathconf = NULL;
   1332 # endif /* HAVE_NFS_ARGS_T_PATHCONF */
   1333   }
   1334 #endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */
   1335 
   1336 #if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS)
   1337   nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS);
   1338   if (nap->maxgrouplist != 0)
   1339     nap->args.flags |= MNT2_NFS_OPT_MAXGRPS;
   1340 #endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */
   1341 
   1342 #ifdef HAVE_NFS_ARGS_T_OPTSTR
   1343   nap->optstr = mntp->mnt_opts;
   1344 #endif /* HAVE_NFS_ARGS_T_OPTSTR */
   1345 
   1346   /************************************************************************/
   1347   /***  FINAL ACTIONS                                                   ***/
   1348   /************************************************************************/
   1349 
   1350 #ifdef HAVE_NFS_ARGS_T_GFS_FLAGS
   1351   /* Ultrix stores generic flags in nfs_args.gfs_flags. */
   1352   nap->gfs_flags = genflags;
   1353 #endif /* HAVE_NFS_ARGS_T_FLAGS */
   1354 
   1355   s = set_nfs4_security(nap, mntp);
   1356 
   1357   /* Add addresses to the mount options */
   1358   add_nfs4_mntopts(nap, mntp, s);
   1359 
   1360   return;                       /* end of compute_nfs4_args() function */
   1361 }
   1362 
   1363 #ifdef DEBUG
   1364 static void
   1365 print_nfs4_args(const nfs4_args_t *nap, u_long nfs_version)
   1366 {
   1367   struct sockaddr_in *sap;
   1368   struct nfs_common_args a;
   1369 
   1370   if (!nap) {
   1371     plog(XLOG_DEBUG, "NULL nfs_args!");
   1372     return;
   1373   }
   1374 
   1375   plog(XLOG_DEBUG, "NA->client_addr \"%s\"\n", nap->client_addr.data);
   1376   plog(XLOG_DEBUG, "NA->mnt_path = \"%s\"", nap->mnt_path.data);
   1377   plog(XLOG_DEBUG, "NA->hostname = \"%s\"", nap->hostname.data);
   1378   sap = (struct sockaddr_in *) nap->host_addr;
   1379   print_nfs_sockaddr_in("host_addr", sap);
   1380   plog(XLOG_DEBUG, "NA->proto = %d", (int) nap->proto);
   1381 #ifdef HAVE_NFS_ARGS_T_VERSION
   1382   plog(XLOG_DEBUG, "NA->version = %d", nap->version);
   1383 #endif /* HAVE_NFS_ARGS_T_VERSION */
   1384   print_nfs4_security(nap);
   1385 
   1386   put_nfs_common_args(nap, a);
   1387   print_nfs_common_args(&a);
   1388 }
   1389 #endif
   1390 #endif /* HAVE_FS_NFS4 */
   1391 
   1392 void
   1393 compute_nfs_args(void *nap,
   1394                  mntent_t *mntp,
   1395                  int genflags,
   1396                  struct netconfig *nfsncp,
   1397                  struct sockaddr_in *ip_addr,
   1398                  u_long nfs_version,
   1399                  char *nfs_proto,
   1400                  am_nfs_handle_t *fhp,
   1401                  char *host_name,
   1402                  char *fs_name)
   1403 {
   1404 #ifdef HAVE_FS_NFS4
   1405   if (nfs_version == NFS_VERSION4)
   1406     compute_nfs4_args(nap, mntp, genflags, nfsncp, ip_addr, nfs_version,
   1407 		      nfs_proto, fhp, host_name, fs_name);
   1408   else
   1409 #endif /* HAVE_FS_NFS4 */
   1410     compute_nfs23_args(nap, mntp, genflags, nfsncp, ip_addr, nfs_version,
   1411 		       nfs_proto, fhp, host_name, fs_name);
   1412 }
   1413 
   1414 void
   1415 discard_nfs_args(void *nap, u_long nfs_version)
   1416 {
   1417 #ifdef HAVE_FS_NFS4
   1418   if (nfs_version == NFS_VERSION4)
   1419     discard_nfs4_args(nap);
   1420   else
   1421 #endif /* HAVE_FS_NFS4 */
   1422     discard_nfs23_args(nap);
   1423 }
   1424 
   1425 #ifdef DEBUG
   1426 void
   1427 print_nfs_args(const void *nap, u_long nfs_version)
   1428 {
   1429 #ifdef HAVE_FS_NFS4
   1430   if (nfs_version == NFS_VERSION4)
   1431     print_nfs4_args(nap, nfs_version);
   1432   else
   1433 #endif /* HAVE_FS_NFS4 */
   1434     print_nfs23_args(nap, nfs_version);
   1435 }
   1436 #endif
   1437 
   1438 
   1439 /*
   1440  * Fill in special values for flags and fields of nfs_args, for an
   1441  * automounter NFS mount.
   1442  */
   1443 void
   1444 compute_automounter_nfs_args(nfs_args_t *nap, mntent_t *mntp)
   1445 {
   1446   struct nfs_common_args a;
   1447 
   1448 #ifdef MNT2_NFS_OPT_SYMTTL
   1449   /*
   1450    * Don't let the kernel cache symbolic links we generate, or else lookups
   1451    * will bypass amd and fail to remount stuff as needed.
   1452    */
   1453   plog(XLOG_INFO, "turning on NFS option symttl and setting value to 0");
   1454   nap->flags |= MNT2_NFS_OPT_SYMTTL;
   1455   nap->symttl = 0;
   1456 #endif /* MNT2_NFS_OPT_SYMTTL */
   1457 
   1458   /*
   1459    * This completes the flags for the HIDE_MOUNT_TYPE  code in the
   1460    * mount_amfs_toplvl() function in amd/amfs_toplvl.c.
   1461    * Some systems don't have a mount type, but a mount flag.
   1462    */
   1463 #ifdef MNT2_NFS_OPT_AUTO
   1464   nap->flags |= MNT2_NFS_OPT_AUTO;
   1465 #endif /* MNT2_NFS_OPT_AUTO */
   1466 #ifdef MNT2_NFS_OPT_IGNORE
   1467   nap->flags |= MNT2_NFS_OPT_IGNORE;
   1468 #endif /* MNT2_NFS_OPT_IGNORE */
   1469 #ifdef MNT2_GEN_OPT_AUTOMNTFS
   1470   nap->flags |= MNT2_GEN_OPT_AUTOMNTFS;
   1471 #endif /* not MNT2_GEN_OPT_AUTOMNTFS */
   1472 
   1473 #ifdef MNT2_NFS_OPT_DUMBTIMR
   1474   /*
   1475    * Don't let the kernel start computing throughput of Amd.  The numbers
   1476    * will be meaningless because of the way Amd does mount retries.
   1477    */
   1478   plog(XLOG_INFO, "%s: disabling nfs congestion window", mntp->mnt_dir);
   1479   nap->flags |= MNT2_NFS_OPT_DUMBTIMR;
   1480 #endif /* MNT2_NFS_OPT_DUMBTIMR */
   1481 
   1482   /* compute all of the NFS attribute-cache flags */
   1483   memset(&a, 0, sizeof(a));
   1484   a.flags = nap->flags;
   1485   compute_nfs_attrcache_flags(&a, mntp);
   1486   get_nfs_common_args(nap, a);
   1487 
   1488   /*
   1489    * Provide a slight bit more security by requiring the kernel to use
   1490    * reserved ports.
   1491    */
   1492 #ifdef MNT2_NFS_OPT_RESVPORT
   1493   nap->flags |= MNT2_NFS_OPT_RESVPORT;
   1494 #endif /* MNT2_NFS_OPT_RESVPORT */
   1495 }
   1496 
   1497 int
   1498 nfs_valid_version(u_long v)
   1499 {
   1500   return v >= NFS_VERS_MIN && v <= NFS_VERS_MAX;
   1501 }
   1502