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
compute_mount_flags(mntent_t * mntp)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
compute_automounter_mount_flags(mntent_t * mntp)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
addvers(char * zopts,size_t l,mntent_t * mnt,u_long have_vers,u_long want_vers)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
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)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
compute_nfs_attrcache_flags(struct nfs_common_args * nap,mntent_t * mntp)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
compute_nfs_common_args(struct nfs_common_args * nap,mntent_t * mntp,const char * nfs_proto,u_long nfs_version)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
print_nfs_common_args(const struct nfs_common_args * a)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
discard_nfs23_args(nfs_args_t * nap)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 *
get_hex_string(u_int len,const char * fhdata)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
print_nfs_sockaddr_in(const char * tag,const struct sockaddr_in * sap)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
print_nfs23_args(const nfs_args_t * nap,u_long nfs_version)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
compute_nfs23_args(nfs_args_t * nap,mntent_t * mntp,int genflags,struct netconfig * nfsncp,struct sockaddr_in * ip_addr,u_long nfs_version,char * nfs_proto,am_nfs_handle_t * fhp,char * host_name,char * fs_name)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 *
set_nfs4_security(nfs4_args_t * nap,mntent_t * mntp)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
get_my_ipv4addr(struct nfs_string * ns)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
add_nfs4_mntopts(const nfs4_args_t * nap,mntent_t * mntp,char * sec)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
print_nfs4_security(const nfs4_args_t * nap)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
discard_nfs4_args(nfs4_args_t * nap)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
compute_nfs4_args(nfs4_args_t * nap,mntent_t * mntp,int genflags,struct netconfig * nfsncp,struct sockaddr_in * ip_addr,u_long nfs_version,char * nfs_proto,am_nfs_handle_t * fhp,char * host_name,char * fs_name)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
print_nfs4_args(const nfs4_args_t * nap,u_long nfs_version)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
compute_nfs_args(void * nap,mntent_t * mntp,int genflags,struct netconfig * nfsncp,struct sockaddr_in * ip_addr,u_long nfs_version,char * nfs_proto,am_nfs_handle_t * fhp,char * host_name,char * fs_name)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
discard_nfs_args(void * nap,u_long nfs_version)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
print_nfs_args(const void * nap,u_long nfs_version)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
compute_automounter_nfs_args(nfs_args_t * nap,mntent_t * mntp)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
nfs_valid_version(u_long v)1498 nfs_valid_version(u_long v)
1499 {
1500   return v >= NFS_VERS_MIN && v <= NFS_VERS_MAX;
1501 }
1502