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