2 * Copyright (c) 1997-2014 Erez Zadok
3 * Copyright (c) 1990 Jan-Simon Pendry
4 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
5 * Copyright (c) 1990 The Regents of the University of California.
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * File: am-utils/libamu/mount_fs.c
42 #endif /* HAVE_CONFIG_H */
45 #include <nfs_common.h>
48 /* ensure that mount table options are delimited by a comma */
49 #define append_opts(old, l, new) { \
51 xstrlcat(old, ",", l); \
52 xstrlcat(old, new, l); }
55 * Standard mount flags
57 struct opt_tab mnt_flags[] =
59 #if defined(MNT2_GEN_OPT_RDONLY) && defined(MNTTAB_OPT_RO)
60 {MNTTAB_OPT_RO, MNT2_GEN_OPT_RDONLY},
61 #endif /* defined(MNT2_GEN_OPT_RDONLY) && defined(MNTTAB_OPT_RO) */
63 #if defined(MNT2_GEN_OPT_NOCACHE) && defined(MNTTAB_OPT_NOCACHE)
64 {MNTTAB_OPT_NOCACHE, MNT2_GEN_OPT_NOCACHE},
65 #endif /* defined(MNT2_GEN_OPT_NOCACHE) && defined(MNTTAB_OPT_NOCACHE) */
67 /* the "grpid" mount option can be offered as generic of NFS */
68 #ifdef MNTTAB_OPT_GRPID
69 # ifdef MNT2_GEN_OPT_GRPID
70 {MNTTAB_OPT_GRPID, MNT2_GEN_OPT_GRPID},
71 # endif /* MNT2_GEN_OPT_GRPID */
72 # ifdef MNT2_NFS_OPT_GRPID
73 {MNTTAB_OPT_GRPID, MNT2_NFS_OPT_GRPID},
74 # endif /* MNT2_NFS_OPT_GRPID */
75 #endif /* MNTTAB_OPT_GRPID */
77 #if defined(MNT2_GEN_OPT_MULTI) && defined(MNTTAB_OPT_MULTI)
78 {MNTTAB_OPT_MULTI, MNT2_GEN_OPT_MULTI},
79 #endif /* defined(MNT2_GEN_OPT_MULTI) && defined(MNTTAB_OPT_MULTI) */
81 #if defined(MNT2_GEN_OPT_NODEV) && defined(MNTTAB_OPT_NODEV)
82 {MNTTAB_OPT_NODEV, MNT2_GEN_OPT_NODEV},
83 #endif /* defined(MNT2_GEN_OPT_NODEV) && defined(MNTTAB_OPT_NODEV) */
85 #if defined(MNT2_GEN_OPT_NOEXEC) && defined(MNTTAB_OPT_NOEXEC)
86 {MNTTAB_OPT_NOEXEC, MNT2_GEN_OPT_NOEXEC},
87 #endif /* defined(MNT2_GEN_OPT_NOEXEC) && defined(MNTTAB_OPT_NOEXEC) */
89 #if defined(MNT2_GEN_OPT_NOSUB) && defined(MNTTAB_OPT_NOSUB)
90 {MNTTAB_OPT_NOSUB, MNT2_GEN_OPT_NOSUB},
91 #endif /* defined(MNT2_GEN_OPT_NOSUB) && defined(MNTTAB_OPT_NOSUB) */
93 #if defined(MNT2_GEN_OPT_NOSUID) && defined(MNTTAB_OPT_NOSUID)
94 {MNTTAB_OPT_NOSUID, MNT2_GEN_OPT_NOSUID},
95 #endif /* defined(MNT2_GEN_OPT_NOSUID) && defined(MNTTAB_OPT_NOSUID) */
97 #if defined(MNT2_GEN_OPT_SYNC) && defined(MNTTAB_OPT_SYNC)
98 {MNTTAB_OPT_SYNC, MNT2_GEN_OPT_SYNC},
99 #endif /* defined(MNT2_GEN_OPT_SYNC) && defined(MNTTAB_OPT_SYNC) */
101 #if defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY)
102 {MNTTAB_OPT_OVERLAY, MNT2_GEN_OPT_OVERLAY},
103 #endif /* defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY) */
105 #if defined(MNT2_GEN_OPT_LOG) && defined(MNTTAB_OPT_LOG)
106 {MNTTAB_OPT_LOG, MNT2_GEN_OPT_LOG},
107 #endif /* defined(MNT2_GEN_OPT_LOG) && defined(MNTTAB_OPT_LOG) */
109 #if defined(MNT2_GEN_OPT_NOATIME) && defined(MNTTAB_OPT_NOATIME)
110 {MNTTAB_OPT_NOATIME, MNT2_GEN_OPT_NOATIME},
111 #endif /* defined(MNT2_GEN_OPT_NOATIME) && defined(MNTTAB_OPT_NOATIME) */
113 #if defined(MNT2_GEN_OPT_NODEVMTIME) && defined(MNTTAB_OPT_NODEVMTIME)
114 {MNTTAB_OPT_NODEVMTIME, MNT2_GEN_OPT_NODEVMTIME},
115 #endif /* defined(MNT2_GEN_OPT_NODEVMTIME) && defined(MNTTAB_OPT_NODEVMTIME) */
117 #if defined(MNT2_GEN_OPT_SOFTDEP) && defined(MNTTAB_OPT_SOFTDEP)
118 {MNTTAB_OPT_SOFTDEP, MNT2_GEN_OPT_SOFTDEP},
119 #endif /* defined(MNT2_GEN_OPT_SOFTDEP) && defined(MNTTAB_OPT_SOFTDEP) */
121 #if defined(MNT2_GEN_OPT_SYMPERM) && defined(MNTTAB_OPT_SYMPERM)
122 {MNTTAB_OPT_SYMPERM, MNT2_GEN_OPT_SYMPERM},
123 #endif /* defined(MNT2_GEN_OPT_SYMPERM) && defined(MNTTAB_OPT_SYMPERM) */
125 #if defined(MNT2_GEN_OPT_UNION) && defined(MNTTAB_OPT_UNION)
126 {MNTTAB_OPT_UNION, MNT2_GEN_OPT_UNION},
127 #endif /* defined(MNT2_GEN_OPT_UNION) && defined(MNTTAB_OPT_UNION) */
130 * Do not define MNT2_NFS_OPT_* entries here! This is for generic
131 * mount(2) options only, not for NFS mount options. If you need to put
132 * something here, it's probably not the right place: see
133 * include/am_compat.h.
140 /* compute generic mount flags */
142 compute_mount_flags(mntent_t *mntp)
147 #ifdef MNT2_GEN_OPT_NEWTYPE
148 flags |= MNT2_GEN_OPT_NEWTYPE;
149 #endif /* MNT2_GEN_OPT_NEWTYPE */
150 #ifdef MNT2_GEN_OPT_AUTOMOUNTED
151 flags |= MNT2_GEN_OPT_AUTOMOUNTED;
152 #endif /* not MNT2_GEN_OPT_AUTOMOUNTED */
155 * Crack basic mount options
157 for (opt = mnt_flags; opt->opt; opt++) {
158 flags |= amu_hasmntopt(mntp, opt->opt) ? opt->flag : 0;
165 /* compute generic mount flags for automounter mounts */
167 compute_automounter_mount_flags(mntent_t *mntp)
171 #ifdef MNT2_GEN_OPT_IGNORE
172 flags |= MNT2_GEN_OPT_IGNORE;
173 #endif /* not MNT2_GEN_OPT_IGNORE */
174 #ifdef MNT2_GEN_OPT_AUTOMNTFS
175 flags |= MNT2_GEN_OPT_AUTOMNTFS;
176 #endif /* not MNT2_GEN_OPT_AUTOMNTFS */
182 #if defined(MOUNT_TABLE_ON_FILE) && defined(MNTTAB_OPT_VERS)
184 * add the extra vers={2,3} field to the mount table,
185 * unless already specified by user
188 addvers(char *zopts, size_t l, mntent_t *mnt, u_long have_vers,
191 if (have_vers == want_vers &&
192 hasmntval(mnt, MNTTAB_OPT_VERS) != want_vers) {
194 xsnprintf(optsbuf, sizeof(optsbuf),
195 "%s=%d", MNTTAB_OPT_VERS, want_vers);
196 append_opts(zopts, l, optsbuf);
199 #endif /* MOUNT_TABLE_ON_FILE && MNTTAB_OPT_VERS */
202 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 #ifdef MOUNT_TABLE_ON_FILE
206 char *zopts = NULL, *xopts = NULL;
208 #endif /* MOUNT_TABLE_ON_FILE */
209 char *mnt_dir = NULL;
211 #ifdef NEED_AUTOFS_SPACE_HACK
212 char *old_mnt_dir = NULL;
213 /* perform space hack */
215 old_mnt_dir = mnt->mnt_dir;
216 mnt->mnt_dir = mnt_dir = autofs_strdup_space_hack(old_mnt_dir);
218 #endif /* NEED_AUTOFS_SPACE_HACK */
219 mnt_dir = xstrdup(mnt->mnt_dir);
221 dlog("'%s' fstype " MTYPE_PRINTF_TYPE " (%s) flags %#x (%s)",
222 mnt_dir, type, mnt->mnt_type, flags, mnt->mnt_opts);
225 error = MOUNT_TRAP(type, mnt, flags, mnt_data);
228 plog(XLOG_ERROR, "'%s': mount: %m", mnt_dir);
230 * The following code handles conditions which shouldn't
231 * occur. They are possible either because amd screws up
232 * in preparing for the mount, or because some human
233 * messed with the mount point. Both have been known to
234 * happen. -- stolcke 2/22/95
236 if (errno == EBUSY) {
238 * Also, sometimes unmount isn't called, e.g., because
239 * our mountlist is garbled. This leaves old mount
240 * points around which need to be removed before we
241 * can mount something new in their place.
243 errno = umount_fs(mnt_dir, mnttabname, on_autofs);
245 plog(XLOG_ERROR, "'%s': umount: %m", mnt_dir);
247 plog(XLOG_WARNING, "extra umount required for '%s'", mnt_dir);
248 error = MOUNT_TRAP(type, mnt, flags, mnt_data);
253 if (error < 0 && --retry > 0) {
258 #ifdef NEED_AUTOFS_SPACE_HACK
259 /* Undo space hack */
261 mnt->mnt_dir = old_mnt_dir;
262 #endif /* NEED_AUTOFS_SPACE_HACK */
269 #ifdef MOUNT_TABLE_ON_FILE
271 * Allocate memory for options:
272 * dev=..., vers={2,3}, proto={tcp,udp}
274 l = strlen(mnt->mnt_opts) + 48;
275 zopts = (char *) xmalloc(l);
277 /* copy standard options */
278 xopts = mnt->mnt_opts;
280 xstrlcpy(zopts, xopts, l);
282 # ifdef MNTTAB_OPT_DEV
284 /* add the extra dev= field to the mount table */
286 if (lstat(mnt_dir, &stb) == 0) {
288 if (sizeof(stb.st_dev) == 2) /* e.g. SunOS 4.1 */
289 xsnprintf(optsbuf, sizeof(optsbuf), "%s=%04lx",
290 MNTTAB_OPT_DEV, (u_long) stb.st_dev & 0xffff);
291 else /* e.g. System Vr4 */
292 xsnprintf(optsbuf, sizeof(optsbuf), "%s=%08lx",
293 MNTTAB_OPT_DEV, (u_long) stb.st_dev);
294 append_opts(zopts, l, optsbuf);
297 # endif /* MNTTAB_OPT_DEV */
299 # if defined(HAVE_FS_NFS4) && defined(MNTTAB_OPT_VERS)
300 addvers(zopts, l, mnt, nfs_version, NFS_VERSION4);
301 # endif /* defined(HAVE_FS_NFS4) && defined(MNTTAB_OPT_VERS) */
302 # if defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)
303 addvers(zopts, l, mnt, nfs_version, NFS_VERSION3);
304 # endif /* defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS) */
305 # ifdef MNTTAB_OPT_VERS
306 addvers(zopts, l, mnt, nfs_version, NFS_VERSION2);
307 # endif /* MNTTAB_OPT_VERS */
309 # ifdef MNTTAB_OPT_PROTO
311 * add the extra proto={tcp,udp} field to the mount table,
312 * unless already specified by user.
314 if (nfs_proto && !amu_hasmntopt(mnt, MNTTAB_OPT_PROTO)) {
316 xsnprintf(optsbuf, sizeof(optsbuf), "%s=%s", MNTTAB_OPT_PROTO, nfs_proto);
317 append_opts(zopts, l, optsbuf);
319 # endif /* MNTTAB_OPT_PROTO */
321 /* finally, store the options into the mount table structure */
322 mnt->mnt_opts = zopts;
325 * Additional fields in mntent_t
328 # ifdef HAVE_MNTENT_T_MNT_CNODE
330 # endif /* HAVE_MNTENT_T_MNT_CNODE */
332 # ifdef HAVE_MNTENT_T_MNT_RO
333 mnt->mnt_ro = (amu_hasmntopt(mnt, MNTTAB_OPT_RO) != NULL);
334 # endif /* HAVE_MNTENT_T_MNT_RO */
336 # ifdef HAVE_MNTENT_T_MNT_TIME
337 # ifdef HAVE_MNTENT_T_MNT_TIME_STRING
338 { /* allocate enough space for a long */
339 size_t l = 13 * sizeof(char);
340 char *str = (char *) xmalloc(l);
341 xsnprintf(str, l, "%ld", time((time_t *) NULL));
344 # else /* not HAVE_MNTENT_T_MNT_TIME_STRING */
345 mnt->mnt_time = time((time_t *) NULL);
346 # endif /* not HAVE_MNTENT_T_MNT_TIME_STRING */
347 # endif /* HAVE_MNTENT_T_MNT_TIME */
349 write_mntent(mnt, mnttabname);
351 # ifdef MNTTAB_OPT_DEV
353 XFREE(mnt->mnt_opts);
354 mnt->mnt_opts = xopts;
356 # endif /* MNTTAB_OPT_DEV */
357 #endif /* MOUNT_TABLE_ON_FILE */
366 * Compute all NFS attribute cache related flags separately. Note that this
367 * function now computes attribute-cache flags for both Amd's automount
368 * points (NFS) as well as any normal NFS mount that Amd performs. Edit
372 compute_nfs_attrcache_flags(struct nfs_common_args *nap, mntent_t *mntp)
375 int err_acval = 1; /* 1 means we found no 'actimeo' value */
376 #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)
377 int err_acrdmm; /* for ac{reg,dir}{min,max} */
378 #endif /* HAVE_NFS_ARGS_T_AC{REG,DIR}{MIN,MAX} */
380 /************************************************************************/
381 /*** ATTRIBUTE CACHES ***/
382 /************************************************************************/
384 * acval is set to 0 at the top of the function. If actimeo mount option
385 * exists and defined in mntopts, then its acval is set to it.
386 * If the value is non-zero, then we set all attribute cache fields to it.
387 * If acval is zero, it means it was never defined in mntopts or the
388 * actimeo mount option does not exist, in which case we check for
389 * individual mount options per attribute cache.
390 * Regardless of the value of acval, mount flags are set based directly
391 * on the values of the attribute caches.
393 #ifdef MNTTAB_OPT_ACTIMEO
394 err_acval = hasmntvalerr(mntp, MNTTAB_OPT_ACTIMEO, &acval); /* attr cache timeout (sec) */
395 #endif /* MNTTAB_OPT_ACTIMEO */
398 #ifdef HAVE_NFS_ARGS_T_ACREGMIN
399 err_acrdmm = 1; /* 1 means we found no acregmin value */
401 nap->acregmin = acval; /* min ac timeout for reg files (sec) */
403 # ifdef MNTTAB_OPT_ACREGMIN
405 err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMIN, &tmp);
407 # else /* not MNTTAB_OPT_ACREGMIN */
409 # endif /* not MNTTAB_OPT_ACREGMIN */
411 /* set this flag iff we changed acregmin (possibly to zero) */
412 # ifdef MNT2_NFS_OPT_ACREGMIN
413 if (!err_acval || !err_acrdmm)
414 nap->flags |= MNT2_NFS_OPT_ACREGMIN;
415 # endif /* MNT2_NFS_OPT_ACREGMIN */
416 #endif /* HAVE_NFS_ARGS_T_ACREGMIN */
419 #ifdef HAVE_NFS_ARGS_T_ACREGMAX
420 err_acrdmm = 1; /* 1 means we found no acregmax value */
422 nap->acregmax = acval; /* max ac timeout for reg files (sec) */
424 # ifdef MNTTAB_OPT_ACREGMAX
426 err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACREGMAX, &tmp);
428 # else /* not MNTTAB_OPT_ACREGMAX */
430 # endif /* not MNTTAB_OPT_ACREGMAX */
432 /* set this flag iff we changed acregmax (possibly to zero) */
433 # ifdef MNT2_NFS_OPT_ACREGMAX
434 if (!err_acval || !err_acrdmm)
435 nap->flags |= MNT2_NFS_OPT_ACREGMAX;
436 # endif /* MNT2_NFS_OPT_ACREGMAX */
437 #endif /* HAVE_NFS_ARGS_T_ACREGMAX */
440 #ifdef HAVE_NFS_ARGS_T_ACDIRMIN
441 err_acrdmm = 1; /* 1 means we found no acdirmin value */
443 nap->acdirmin = acval; /* min ac timeout for dirs (sec) */
445 # ifdef MNTTAB_OPT_ACDIRMIN
447 err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMIN, &tmp);
449 # else /* not MNTTAB_OPT_ACDIRMIN */
451 # endif /* not MNTTAB_OPT_ACDIRMIN */
453 /* set this flag iff we changed acdirmin (possibly to zero) */
454 # ifdef MNT2_NFS_OPT_ACDIRMIN
455 if (!err_acval || !err_acrdmm)
456 nap->flags |= MNT2_NFS_OPT_ACDIRMIN;
457 # endif /* MNT2_NFS_OPT_ACDIRMIN */
458 #endif /* HAVE_NFS_ARGS_T_ACDIRMIN */
461 #ifdef HAVE_NFS_ARGS_T_ACDIRMAX
462 err_acrdmm = 1; /* 1 means we found no acdirmax value */
464 nap->acdirmax = acval; /* max ac timeout for dirs (sec) */
466 # ifdef MNTTAB_OPT_ACDIRMAX
468 err_acrdmm = hasmntvalerr(mntp, MNTTAB_OPT_ACDIRMAX, &tmp);
470 # else /* not MNTTAB_OPT_ACDIRMAX */
472 # endif /* not MNTTAB_OPT_ACDIRMAX */
474 /* set this flag iff we changed acdirmax (possibly to zero) */
475 # ifdef MNT2_NFS_OPT_ACDIRMAX
476 if (!err_acval || !err_acrdmm)
477 nap->flags |= MNT2_NFS_OPT_ACDIRMAX;
478 # endif /* MNT2_NFS_OPT_ACDIRMAX */
479 #endif /* HAVE_NFS_ARGS_T_ACDIRMAX */
482 /* don't cache attributes */
483 #if defined(MNTTAB_OPT_NOAC) && defined(MNT2_NFS_OPT_NOAC)
484 if (amu_hasmntopt(mntp, MNTTAB_OPT_NOAC) != NULL)
485 nap->flags |= MNT2_NFS_OPT_NOAC;
486 #endif /* defined(MNTTAB_OPT_NOAC) && defined(MNT2_NFS_OPT_NOAC) */
492 compute_nfs_common_args(struct nfs_common_args *nap, mntent_t *mntp,
493 const char *nfs_proto, u_long nfs_version)
495 #ifdef MNT2_NFS_OPT_TCP
496 if (nfs_proto && STREQ(nfs_proto, "tcp"))
497 nap->flags |= MNT2_NFS_OPT_TCP;
498 #endif /* MNT2_NFS_OPT_TCP */
500 #ifdef MNT2_NFS_OPT_NOCONN
501 /* check if user specified to use unconnected or connected sockets */
502 if (amu_hasmntopt(mntp, MNTTAB_OPT_NOCONN) != NULL)
503 nap->flags |= MNT2_NFS_OPT_NOCONN;
504 else if (amu_hasmntopt(mntp, MNTTAB_OPT_CONN) != NULL)
505 nap->flags &= ~MNT2_NFS_OPT_NOCONN;
508 * Some OSs want you to set noconn always. Some want you to always turn
509 * it off. Others want you to turn it on/off only if NFS V.3 is used.
510 * And all of that changes from revision to another. This is
511 * particularly true of OpenBSD, NetBSD, and FreeBSD. So, rather than
512 * attempt to auto-detect this, I'm forced to "fix" it in the individual
513 * conf/nfs_prot/nfs_prot_*.h files.
515 # ifdef USE_UNCONNECTED_NFS_SOCKETS
516 if (!(nap->flags & MNT2_NFS_OPT_NOCONN)) {
517 nap->flags |= MNT2_NFS_OPT_NOCONN;
518 plog(XLOG_WARNING, "noconn option not specified, and was just turned ON (OS override)! (May cause NFS hangs on some systems...)");
520 # endif /* USE_UNCONNECTED_NFS_SOCKETS */
521 # ifdef USE_CONNECTED_NFS_SOCKETS
522 if (nap->flags & MNT2_NFS_OPT_NOCONN) {
523 nap->flags &= ~MNT2_NFS_OPT_NOCONN;
524 plog(XLOG_WARNING, "noconn option specified, and was just turned OFF (OS override)! (May cause NFS hangs on some systems...)");
526 # endif /* USE_CONNECTED_NFS_SOCKETS */
528 #endif /* MNT2_NFS_OPT_NOCONN */
530 #ifdef MNT2_NFS_OPT_RESVPORT
531 # ifdef MNTTAB_OPT_RESVPORT
532 if (amu_hasmntopt(mntp, MNTTAB_OPT_RESVPORT) != NULL)
533 nap->flags |= MNT2_NFS_OPT_RESVPORT;
534 # else /* not MNTTAB_OPT_RESVPORT */
535 nap->flags |= MNT2_NFS_OPT_RESVPORT;
536 # endif /* not MNTTAB_OPT_RESVPORT */
537 #endif /* MNT2_NFS_OPT_RESVPORT */
539 nap->rsize = hasmntval(mntp, MNTTAB_OPT_RSIZE);
540 #ifdef MNT2_NFS_OPT_RSIZE
542 nap->flags |= MNT2_NFS_OPT_RSIZE;
543 #endif /* MNT2_NFS_OPT_RSIZE */
544 if (nfs_version == NFS_VERSION && nap->rsize > 8192)
547 nap->wsize = hasmntval(mntp, MNTTAB_OPT_WSIZE);
548 #ifdef MNT2_NFS_OPT_WSIZE
550 nap->flags |= MNT2_NFS_OPT_WSIZE;
551 #endif /* MNT2_NFS_OPT_WSIZE */
552 if (nfs_version == NFS_VERSION && nap->wsize > 8192)
555 nap->timeo = hasmntval(mntp, MNTTAB_OPT_TIMEO);
556 #ifdef MNT2_NFS_OPT_TIMEO
558 nap->flags |= MNT2_NFS_OPT_TIMEO;
559 #endif /* MNT2_NFS_OPT_TIMEO */
561 nap->retrans = hasmntval(mntp, MNTTAB_OPT_RETRANS);
562 #ifdef MNT2_NFS_OPT_RETRANS
564 nap->flags |= MNT2_NFS_OPT_RETRANS;
565 #endif /* MNT2_NFS_OPT_RETRANS */
567 #ifdef MNT2_NFS_OPT_SOFT
568 if (amu_hasmntopt(mntp, MNTTAB_OPT_SOFT) != NULL)
569 nap->flags |= MNT2_NFS_OPT_SOFT;
570 #endif /* MNT2_NFS_OPT_SOFT */
572 #ifdef MNT2_NFS_OPT_SPONGY
573 if (amu_hasmntopt(mntp, MNTTAB_OPT_SPONGY) != NULL) {
574 nap->flags |= MNT2_NFS_OPT_SPONGY;
575 if (*flags & MNT2_NFS_OPT_SOFT) {
576 plog(XLOG_USER, "Mount opts soft and spongy are incompatible - soft ignored");
577 nap->flags &= ~MNT2_NFS_OPT_SOFT;
580 #endif /* MNT2_NFS_OPT_SPONGY */
582 #if defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY)
583 /* Ultrix has separate generic and NFS ro flags */
584 if (genflags & MNT2_GEN_OPT_RONLY)
585 nap->flags |= MNT2_NFS_OPT_RONLY;
586 #endif /* defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY) */
588 #ifdef MNTTAB_OPT_INTR
589 if (amu_hasmntopt(mntp, MNTTAB_OPT_INTR) != NULL)
591 * Either turn on the "allow interrupts" option, or
592 * turn off the "disallow interrupts" option"
594 # ifdef MNT2_NFS_OPT_INTR
595 nap->flags |= MNT2_NFS_OPT_INTR;
596 # endif /* MNT2_NFS_OPT_INTR */
597 # ifdef MNT2_NFS_OPT_NOINTR
598 nap->flags &= ~MNT2_NFS_OPT_NOINTR;
599 # endif /* MNT2_NFS_OPT_NOINTR */
600 # ifdef MNT2_NFS_OPT_INT
601 nap->flags |= MNT2_NFS_OPT_INT;
602 # endif /* MNT2_NFS_OPT_INT */
603 # ifdef MNT2_NFS_OPT_NOINT
604 nap->flags &= ~MNT2_NFS_OPT_NOINT;
605 # endif /* MNT2_NFS_OPT_NOINT */
606 #endif /* MNTTAB_OPT_INTR */
608 #ifdef MNT2_NFS_OPT_NOACL
609 if (amu_hasmntopt(mntp, MNTTAB_OPT_NOACL) != NULL)
610 nap->flags |= MNT2_NFS_OPT_NOACL;
611 #endif /* MNT2_NFS_OPT_NOACL */
613 #ifdef MNTTAB_OPT_NODEVS
614 if (amu_hasmntopt(mntp, MNTTAB_OPT_NODEVS) != NULL)
615 nap->flags |= MNT2_NFS_OPT_NODEVS;
616 #endif /* MNTTAB_OPT_NODEVS */
618 #ifdef MNTTAB_OPT_COMPRESS
619 if (amu_hasmntopt(mntp, MNTTAB_OPT_COMPRESS) != NULL)
620 nap->flags |= MNT2_NFS_OPT_COMPRESS;
621 #endif /* MNTTAB_OPT_COMPRESS */
623 #ifdef MNTTAB_OPT_PRIVATE /* mount private, single-client tree */
624 if (amu_hasmntopt(mntp, MNTTAB_OPT_PRIVATE) != NULL)
625 nap->flags |= MNT2_NFS_OPT_PRIVATE;
626 #endif /* MNTTAB_OPT_PRIVATE */
629 #if defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO)
630 if (amu_hasmntopt(mntp, MNTTAB_OPT_NOCTO) != NULL)
631 nap->flags |= MNT2_NFS_OPT_NOCTO;
632 #endif /* defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO) */
634 #if defined(MNT2_NFS_OPT_PROPLIST) && defined(MNTTAB_OPT_PROPLIST)
635 if (amu_hasmntopt(mntp, MNTTAB_OPT_PROPLIST) != NULL)
636 nap->flags |= MNT2_NFS_OPT_PROPLIST;
637 #endif /* defined(MNT2_NFS_OPT_PROPLIST) && defined(MNTTAB_OPT_PROPLIST) */
639 #if defined(MNT2_NFS_OPT_NONLM) && defined(MNTTAB_OPT_NOLOCK)
640 if (amu_hasmntopt(mntp, MNTTAB_OPT_NOLOCK) != NULL)
641 nap->flags |= MNT2_NFS_OPT_NONLM;
642 #endif /* defined(MNT2_NFS_OPT_NONLM) && defined(MNTTAB_OPT_NOLOCK) */
644 #if defined(MNT2_NFS_OPT_XLATECOOKIE) && defined(MNTTAB_OPT_XLATECOOKIE)
645 if (amu_hasmntopt(mntp, MNTTAB_OPT_XLATECOOKIE) != NULL)
646 nap->flags |= MNT2_NFS_OPT_XLATECOOKIE;
647 #endif /* defined(MNT2_NFS_OPT_XLATECOOKIE) && defined(MNTTAB_OPT_XLATECOOKIE) */
651 print_nfs_common_args(const struct nfs_common_args *a)
653 plog(XLOG_DEBUG, "NA->flags = 0x%lx", a->flags);
655 plog(XLOG_DEBUG, "NA->rsize = %lu", a->rsize);
656 plog(XLOG_DEBUG, "NA->wsize = %lu", a->wsize);
657 plog(XLOG_DEBUG, "NA->timeo = %lu", a->timeo);
658 plog(XLOG_DEBUG, "NA->retrans = %lu", a->retrans);
660 #ifdef HAVE_NFS_ARGS_T_ACREGMIN
661 plog(XLOG_DEBUG, "NA->acregmin = %lu", a->acregmin);
662 plog(XLOG_DEBUG, "NA->acregmax = %lu", a->acregmax);
663 plog(XLOG_DEBUG, "NA->acdirmin = %lu", a->acdirmin);
664 plog(XLOG_DEBUG, "NA->acdirmax = %lu", a->acdirmax);
665 #endif /* HAVE_NFS_ARGS_T_ACREGMIN */
669 discard_nfs23_args(nfs_args_t *nap)
671 #ifdef HAVE_TRANSPORT_TYPE_TLI
672 free_knetconfig(nap->knconf);
674 XFREE(nap->addr); /* allocated in compute_nfs_args() */
675 #endif /* HAVE_TRANSPORT_TYPE_TLI */
679 /* get string version (in hex) of identifier */
681 get_hex_string(u_int len, const char *fhdata)
689 if (!fhdata || len == 0 || len > 10240)
693 buf = xrealloc(buf, i);
694 arr = xrealloc(arr, len * sizeof(*arr));
699 memset(arr, 0, len * sizeof(*arr));
700 memcpy(arr, fhdata, len);
702 for (i = 0; i < len; i++) {
703 xsnprintf(str, sizeof(str), "%04x", ntohs(arr[i]));
704 xstrlcat(buf, str, xlen);
710 print_nfs_sockaddr_in(const char *tag, const struct sockaddr_in *sap)
713 plog(XLOG_DEBUG, "NA->%s.sin_family = %d", tag, sap->sin_family);
714 plog(XLOG_DEBUG, "NA->%s.sin_port = %d", tag, ntohs(sap->sin_port));
715 if (inet_ntop(AF_INET, &sap->sin_addr, name, sizeof(name)) == NULL)
717 plog(XLOG_DEBUG, "NA->%s.sin_addr = \"%s\"", tag, name);
721 * print a subset of fields from "struct nfs_args" that are otherwise
722 * not being provided anywhere else.
725 print_nfs23_args(const nfs_args_t *nap, u_long nfs_version)
727 int fhlen = 32; /* default: NFS V.2 file handle length is 32 */
728 #ifdef HAVE_TRANSPORT_TYPE_TLI
730 struct knetconfig *kncp;
731 #else /* not HAVE_TRANSPORT_TYPE_TLI */
732 struct sockaddr_in *sap;
733 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
734 struct nfs_common_args a;
737 plog(XLOG_DEBUG, "NULL nfs_args!");
741 /* override default file handle size */
747 #endif /* NFS_FHSIZE */
749 #ifdef HAVE_TRANSPORT_TYPE_TLI
751 plog(XLOG_DEBUG, "NA->addr {netbuf} (maxlen=%d, len=%d) = \"%s\"",
752 nbp->maxlen, nbp->len,
753 get_hex_string(nbp->len, nbp->buf));
755 plog(XLOG_DEBUG, "NA->syncaddr {netbuf} %p", nbp);
757 plog(XLOG_DEBUG, "NA->knconf->semantics %lu", (u_long) kncp->knc_semantics);
758 plog(XLOG_DEBUG, "NA->knconf->protofmly \"%s\"", kncp->knc_protofmly);
759 plog(XLOG_DEBUG, "NA->knconf->proto \"%s\"", kncp->knc_proto);
760 plog(XLOG_DEBUG, "NA->knconf->rdev %lu", (u_long) kncp->knc_rdev);
761 /* don't print knconf->unused field */
762 #else /* not HAVE_TRANSPORT_TYPE_TLI */
763 # ifdef NFS_ARGS_T_ADDR_IS_POINTER
764 sap = (struct sockaddr_in *) nap->addr;
765 # else /* not NFS_ARGS_T_ADDR_IS_POINTER */
766 sap = (struct sockaddr_in *) &nap->addr;
767 # endif /* not NFS_ARGS_T_ADDR_IS_POINTER */
768 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
769 /* as per POSIX, sin_len need not be set (used internally by kernel) */
770 plog(XLOG_DEBUG, "NA->addr.sin_len = %d", sap->sin_len);
771 #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
772 print_nfs_sockaddr_in("addr", sap);
773 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
774 #ifdef HAVE_NFS_ARGS_T_ADDRLEN
775 plog(XLOG_DEBUG, "NA->addrlen = %d", nap->addrlen);
776 #endif /* ifdef HAVE_NFS_ARGS_T_ADDRLEN */
778 plog(XLOG_DEBUG, "NA->hostname = \"%s\"", nap->hostname ? nap->hostname : "null");
779 #ifdef HAVE_NFS_ARGS_T_NAMLEN
780 plog(XLOG_DEBUG, "NA->namlen = %d", nap->namlen);
781 #endif /* HAVE_NFS_ARGS_T_NAMLEN */
783 #ifdef MNT2_NFS_OPT_FSNAME
784 plog(XLOG_DEBUG, "NA->fsname = \"%s\"", nap->fsname ? nap->fsname : "null");
785 #endif /* MNT2_NFS_OPT_FSNAME */
787 #ifdef HAVE_NFS_ARGS_T_FHSIZE
788 plog(XLOG_DEBUG, "NA->fhsize = %d", nap->fhsize);
790 #endif /* HAVE_NFS_ARGS_T_FHSIZE */
791 #ifdef HAVE_NFS_ARGS_T_FH_LEN
792 plog(XLOG_DEBUG, "NA->fh_len = %d", nap->fh_len);
794 #endif /* HAVE_NFS_ARGS_T_FH_LEN */
797 * XXX: need to figure out how to correctly print file handles,
798 * since some times they are pointers, and sometimes the real structure
799 * is stored in nfs_args. Even if it is a pointer, it can be the actual
800 * char[] array, or a structure containing multiple fields.
802 plog(XLOG_DEBUG, "NA->filehandle = \"%s\"",
803 get_hex_string(fhlen, (const char *) &nap->NFS_FH_FIELD));
805 #ifdef HAVE_NFS_ARGS_T_SOTYPE
806 plog(XLOG_DEBUG, "NA->sotype = %d", nap->sotype);
807 #endif /* HAVE_NFS_ARGS_T_SOTYPE */
808 #ifdef HAVE_NFS_ARGS_T_PROTO
809 plog(XLOG_DEBUG, "NA->proto = %d", (int) nap->proto);
810 #endif /* HAVE_NFS_ARGS_T_PROTO */
811 #ifdef HAVE_NFS_ARGS_T_VERSION
812 plog(XLOG_DEBUG, "NA->version = %d", nap->version);
813 #endif /* HAVE_NFS_ARGS_T_VERSION */
815 put_nfs_common_args(nap, a);
816 print_nfs_common_args(&a);
818 #ifdef HAVE_NFS_ARGS_T_BSIZE
819 plog(XLOG_DEBUG, "NA->bsize = %d", nap->bsize);
820 #endif /* HAVE_NFS_ARGS_T_BSIZE */
822 #ifdef MNTTAB_OPT_SYMTTL
823 plog(XLOG_DEBUG, "NA->symttl = %d", nap->symttl);
824 #endif /* MNTTAB_OPT_SYMTTL */
825 #ifdef MNTTAB_OPT_PG_THRESH
826 plog(XLOG_DEBUG, "NA->pg_thresh = %d", nap->pg_thresh);
827 #endif /* MNTTAB_OPT_PG_THRESH */
829 #ifdef MNT2_NFS_OPT_BIODS
830 plog(XLOG_DEBUG, "NA->biods = %d", nap->biods);
831 #endif /* MNT2_NFS_OPT_BIODS */
837 * Fill in the many possible fields and flags of struct nfs_args.
839 * nap: pre-allocated structure to fill in.
840 * mntp: mount entry structure (includes options)
841 * genflags: generic mount flags already determined
842 * nfsncp: (TLI only) netconfig entry for this NFS mount
843 * ip_addr: IP address of file server
844 * nfs_version: 2, 3, or 0 if unknown
845 * nfs_proto: "udp", "tcp", or NULL.
846 * fhp: file handle structure pointer
847 * host_name: name of remote NFS host
848 * fs_name: remote file system name to mount
851 compute_nfs23_args(nfs_args_t *nap,
854 struct netconfig *nfsncp,
855 struct sockaddr_in *ip_addr,
858 am_nfs_handle_t *fhp,
862 struct nfs_common_args a;
863 /* initialize just in case */
864 memset((voidp) nap, 0, sizeof(nfs_args_t));
866 /* compute all of the NFS attribute-cache flags */
867 memset(&a, 0, sizeof(a));
868 compute_nfs_attrcache_flags(&a, mntp);
869 compute_nfs_common_args(&a, mntp, nfs_proto, nfs_version);
870 get_nfs_common_args(nap, a);
872 /************************************************************************/
873 /*** FILEHANDLE DATA AND LENGTH ***/
874 /************************************************************************/
876 if (nfs_version == NFS_VERSION3) {
878 plog(XLOG_FATAL, "cannot pass NULL fh for NFSv%lu", nfs_version);
883 # if defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN)
885 * Some systems (Irix/bsdi3) have a separate field in nfs_args for
886 * the length of the file handle for NFS V3. They insist that
887 * the file handle set in nfs_args be plain bytes, and not
888 * include the length field.
890 NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v3.am_fh3_data);
891 # else /* not defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN) */
892 NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v3);
893 # endif /* not defined(HAVE_NFS_ARGS_T_FHSIZE) || defined(HAVE_NFS_ARGS_T_FH_LEN) */
894 # ifdef MNT2_NFS_OPT_NFSV3
895 nap->flags |= MNT2_NFS_OPT_NFSV3;
896 # endif /* MNT2_NFS_OPT_NFSV3 */
897 # ifdef MNT2_NFS_OPT_VER3
898 nap->flags |= MNT2_NFS_OPT_VER3;
899 # endif /* MNT2_NFS_OPT_VER3 */
901 #endif /* HAVE_FS_NFS3 */
904 plog(XLOG_FATAL, "cannot pass NULL fh for NFSv%lu", nfs_version);
908 NFS_FH_DREF(nap->NFS_FH_FIELD, &fhp->v2);
911 #ifdef HAVE_NFS_ARGS_T_FHSIZE
913 if (nfs_version == NFS_VERSION3)
914 nap->fhsize = fhp->v3.am_fh3_length;
916 # endif /* HAVE_FS_NFS3 */
917 nap->fhsize = FHSIZE;
918 #endif /* HAVE_NFS_ARGS_T_FHSIZE */
920 /* this is the version of the nfs_args structure, not of NFS! */
921 #ifdef HAVE_NFS_ARGS_T_FH_LEN
923 if (nfs_version == NFS_VERSION3)
924 nap->fh_len = fhp->v3.am_fh3_length;
926 # endif /* HAVE_FS_NFS3 */
927 nap->fh_len = FHSIZE;
928 #endif /* HAVE_NFS_ARGS_T_FH_LEN */
930 /************************************************************************/
932 /************************************************************************/
934 * XXX: warning, using xstrlcpy in NFS_HN_DREF, which may corrupt a
935 * struct nfs_args, or truncate our concocted "hostname:/path"
936 * string prematurely.
938 NFS_HN_DREF(nap->hostname, host_name);
939 #ifdef MNT2_NFS_OPT_HOSTNAME
940 nap->flags |= MNT2_NFS_OPT_HOSTNAME;
941 #endif /* MNT2_NFS_OPT_HOSTNAME */
943 /************************************************************************/
944 /*** IP ADDRESS OF REMOTE HOST ***/
945 /************************************************************************/
947 #ifdef HAVE_TRANSPORT_TYPE_TLI
948 nap->addr = ALLOC(struct netbuf); /* free()'ed at end of mount_nfs_fh() */
949 #endif /* HAVE_TRANSPORT_TYPE_TLI */
950 NFS_SA_DREF(nap, ip_addr);
953 /************************************************************************/
954 /*** NFS PROTOCOL (UDP, TCP) AND VERSION ***/
955 /************************************************************************/
956 #ifdef HAVE_NFS_ARGS_T_SOTYPE
957 /* bsdi3 uses this */
959 if (STREQ(nfs_proto, "tcp"))
960 nap->sotype = SOCK_STREAM;
961 else if (STREQ(nfs_proto, "udp"))
962 nap->sotype = SOCK_DGRAM;
964 #endif /* HAVE_NFS_ARGS_T_SOTYPE */
966 #ifdef HAVE_NFS_ARGS_T_PROTO
967 nap->proto = 0; /* bsdi3 sets this field to zero */
970 if (STREQ(nfs_proto, "tcp")) /* AIX 4.2.x needs this */
971 nap->proto = IPPROTO_TCP;
972 else if (STREQ(nfs_proto, "udp"))
973 nap->proto = IPPROTO_UDP;
975 # endif /* IPPROTO_TCP */
976 #endif /* HAVE_NFS_ARGS_T_SOTYPE */
978 #ifdef HAVE_NFS_ARGS_T_VERSION
979 # ifdef NFS_ARGSVERSION
980 nap->version = NFS_ARGSVERSION; /* BSDI 3.0 and OpenBSD 2.2 */
981 # endif /* NFS_ARGSVERSION */
982 # ifdef DG_MOUNT_NFS_VERSION
983 nap->version = DG_MOUNT_NFS_VERSION; /* dg-ux */
984 # endif /* DG_MOUNT_NFS_VERSION */
985 #endif /* HAVE_NFS_ARGS_VERSION */
987 /************************************************************************/
988 /*** OTHER NFS SOCKET RELATED OPTIONS AND FLAGS ***/
989 /************************************************************************/
991 /************************************************************************/
992 /*** OTHER FLAGS AND OPTIONS ***/
993 /************************************************************************/
995 #ifdef MNT2_NFS_OPT_BIODS
996 if ((nap->biods = hasmntval(mntp, MNTTAB_OPT_BIODS)))
997 nap->flags |= MNT2_NFS_OPT_BIODS;
998 #endif /* MNT2_NFS_OPT_BIODS */
1000 #ifdef MNTTAB_OPT_SYMTTL /* symlink cache time-to-live */
1001 if ((nap->symttl = hasmntval(mntp, MNTTAB_OPT_SYMTTL)))
1002 nap->args.flags |= MNT2_NFS_OPT_SYMTTL;
1003 #endif /* MNTTAB_OPT_SYMTTL */
1005 #ifdef MNT2_NFS_OPT_PGTHRESH /* paging threshold */
1006 if ((nap->pg_thresh = hasmntval(mntp, MNTTAB_OPT_PGTHRESH)))
1007 nap->args.flags |= MNT2_NFS_OPT_PGTHRESH;
1008 #endif /* MNT2_NFS_OPT_PGTHRESH */
1010 #if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX)
1011 if (amu_hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) {
1012 nap->flags |= MNT2_NFS_OPT_POSIX;
1013 # ifdef HAVE_NFS_ARGS_T_PATHCONF
1014 nap->pathconf = NULL;
1015 # endif /* HAVE_NFS_ARGS_T_PATHCONF */
1017 #endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */
1019 #ifdef HAVE_TRANSPORT_TYPE_TLI
1020 /* set up syncaddr field */
1021 nap->syncaddr = (struct netbuf *) NULL;
1023 /* set up knconf field */
1024 if (get_knetconfig(&nap->knconf, nfsncp, nfs_proto) < 0) {
1025 plog(XLOG_FATAL, "cannot fill knetconfig structure for nfs_args");
1029 /* update the flags field for knconf */
1030 nap->args.flags |= MNT2_NFS_OPT_KNCONF;
1031 #endif /* HAVE_TRANSPORT_TYPE_TLI */
1033 #ifdef MNT2_NFS_OPT_FSNAME
1034 nap->fsname = fs_name;
1035 nap->args.flags |= MNT2_NFS_OPT_FSNAME;
1036 #endif /* MNT2_NFS_OPT_FSNAME */
1039 #ifdef HAVE_NFS_ARGS_T_OPTSTR
1040 nap->optstr = mntp->mnt_opts;
1041 #endif /* HAVE_NFS_ARGS_T_OPTSTR */
1043 #if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS)
1044 nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS);
1045 if (nap->maxgrouplist != 0)
1046 nap->flags |= MNT2_NFS_OPT_MAXGRPS;
1047 #endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */
1049 /************************************************************************/
1050 /*** FINAL ACTIONS ***/
1051 /************************************************************************/
1053 #ifdef HAVE_NFS_ARGS_T_GFS_FLAGS
1054 /* Ultrix stores generic flags in nfs_args.gfs_flags. */
1055 nap->gfs_flags = genflags;
1056 #endif /* HAVE_NFS_ARGS_T_FLAGS */
1058 return; /* end of compute_nfs_args() function */
1063 #define RPC_AUTH_GSS_KRB5 390003
1064 #define RPC_AUTH_GSS_KRB5I 390004
1065 #define RPC_AUTH_GSS_KRB5P 390005
1066 #define RPC_AUTH_GSS_LKEY 390006
1067 #define RPC_AUTH_GSS_LKEYI 390007
1068 #define RPC_AUTH_GSS_LKEYP 390008
1069 #define RPC_AUTH_GSS_SPKM 390009
1070 #define RPC_AUTH_GSS_SPKMI 390010
1071 #define RPC_AUTH_GSS_SPKMP 390011
1077 { "unix", AUTH_UNIX },
1078 { "krb5", RPC_AUTH_GSS_KRB5 },
1079 { "krb5i", RPC_AUTH_GSS_KRB5I },
1080 { "krb5p", RPC_AUTH_GSS_KRB5P },
1081 { "lkey", RPC_AUTH_GSS_LKEY },
1082 { "lkeyi", RPC_AUTH_GSS_LKEYI },
1083 { "lkeyp", RPC_AUTH_GSS_LKEYP },
1084 { "spkm", RPC_AUTH_GSS_SPKM },
1085 { "spkmi", RPC_AUTH_GSS_SPKMI },
1086 { "spkmp", RPC_AUTH_GSS_SPKMP },
1090 set_nfs4_security(nfs4_args_t *nap, mntent_t *mntp)
1092 const char *o = hasmnteq(mntp, MNTTAB_OPT_SEC);
1099 for (l = 1, q = strchr(o, ','); q; q = strchr(q + 1, ','))
1102 nap->auth_flavours = xmalloc(l * sizeof(*nap->auth_flavours));
1104 s = ss = xstrdup(o);
1110 for (l = 0, i = 0; i < sizeof(flavours) / sizeof(flavours[0]); i++)
1111 if (strcmp(flavours[i].name, s) == 0) {
1112 nap->auth_flavours[l++] = flavours[i].num;
1116 if (i == sizeof(flavours) / sizeof(flavours[0]))
1117 plog(XLOG_ERROR, "Unknown NFSv4 security mechanism %s\n", s);
1126 nap->auth_flavourlen = l;
1131 get_my_ipv4addr(struct nfs_string *ns)
1134 char myname[MAXHOSTNAMELEN];
1136 if (gethostname(myname, sizeof(myname)) == -1)
1138 if ((hp = gethostbyname(myname)) == NULL)
1140 if (inet_ntop(AF_INET, hp->h_addr, myname, sizeof(myname)) == NULL)
1142 ns->len = strlen(myname);
1143 ns->data = xmalloc(ns->len + 1);
1144 memcpy(ns->data, myname, ns->len + 1);
1149 add_nfs4_mntopts(const nfs4_args_t *nap, mntent_t *mntp, char *sec)
1151 char *opts = mntp->mnt_opts;
1152 char buf[1024], addr[128];
1153 size_t len = strlen(mntp->mnt_opts);
1155 if (inet_ntop(AF_INET,
1156 &((const struct sockaddr_in *)nap->host_addr)->sin_addr,
1157 addr, sizeof(addr)) == NULL)
1160 xsnprintf(buf, sizeof(buf), ",clientaddr=%s,addr=%s", nap->client_addr.data,
1163 len += strlen(buf) + 1;
1165 if (sec && strcmp(sec, "unix") != 0) {
1166 len += strlen(sec) + strlen(MNTTAB_OPT_SEC) + 2; /* 2 = ",=" */
1170 opts = xrealloc(mntp->mnt_opts, len);
1171 xstrlcat(opts, buf, len);
1174 xstrlcat(opts, ",", len);
1175 xstrlcat(opts, MNTTAB_OPT_SEC, len);
1176 xstrlcat(opts, "=", len);
1177 xstrlcat(opts, sec, len);
1180 mntp->mnt_opts = opts;
1184 print_nfs4_security(const nfs4_args_t *nap)
1192 for (i = 0; i < nap->auth_flavourlen; i++) {
1194 for (j = 0; j < sizeof(flavours) / sizeof(flavours[0]); j++)
1195 if (flavours[j].num == nap->auth_flavours[i]) {
1196 xstrlcpy(num, flavours[j].name, sizeof(num));
1200 if (j == sizeof(flavours) / sizeof(flavours[0])) {
1201 plog(XLOG_ERROR, "Unknown NFSv4 security mechanism %d\n",
1202 nap->auth_flavours[i]);
1203 xsnprintf(num, sizeof(num), "*%d*", nap->auth_flavours[i]);
1207 xstrlcat(buf, ":", sizeof(buf));
1209 xstrlcat(buf, num, sizeof(buf));
1212 plog(XLOG_DEBUG, "NA->auth_flavours \"%s\"\n", buf);
1216 discard_nfs4_args(nfs4_args_t *nap)
1218 if (nap->client_addr.data)
1219 free(nap->client_addr.data);
1220 if (nap->hostname.data)
1221 free(nap->hostname.data);
1222 if (nap->mnt_path.data)
1223 free(nap->mnt_path.data);
1225 free(nap->host_addr);
1226 if (nap->auth_flavours)
1227 free(nap->auth_flavours);
1231 * Fill in the many possible fields and flags of struct nfs4_args.
1233 * nap: pre-allocated structure to fill in.
1234 * mntp: mount entry structure (includes options)
1235 * genflags: generic mount flags already determined
1236 * nfsncp: (TLI only) netconfig entry for this NFS mount
1237 * ip_addr: IP address of file server
1238 * nfs_version: 4, or 0 if unknown
1239 * nfs_proto: "udp", "tcp", or NULL.
1240 * fhp: file handle structure pointer
1241 * host_name: name of remote NFS host
1242 * fs_name: remote file system name to mount
1245 compute_nfs4_args(nfs4_args_t *nap,
1248 struct netconfig *nfsncp,
1249 struct sockaddr_in *ip_addr,
1252 am_nfs_handle_t *fhp,
1257 struct nfs_common_args a;
1260 /* initialize just in case */
1261 memset((voidp) nap, 0, sizeof(nfs4_args_t));
1263 /* compute all of the NFS attribute-cache flags */
1264 memset(&a, 0, sizeof(a));
1265 compute_nfs_attrcache_flags(&a, mntp);
1266 compute_nfs_common_args(&a, mntp, nfs_proto, nfs_version);
1267 get_nfs_common_args(nap, a);
1269 get_my_ipv4addr(&nap->client_addr);
1271 /************************************************************************/
1273 /************************************************************************/
1274 nap->hostname.len = strlen(host_name);
1275 nap->hostname.data = xmalloc(nap->hostname.len + 1);
1276 memcpy(nap->hostname.data, host_name, nap->hostname.len + 1);
1278 if ((s = strchr(fs_name, ':')) != NULL)
1283 nap->mnt_path.len = strlen(s);
1284 nap->mnt_path.data = xmalloc(nap->mnt_path.len + 1);
1285 memcpy(nap->mnt_path.data, s, nap->mnt_path.len + 1);
1286 plog(XLOG_DEBUG, "dir name %s\n", nap->mnt_path.data);
1288 /************************************************************************/
1289 /*** IP ADDRESS OF REMOTE HOST ***/
1290 /************************************************************************/
1291 nap->host_addrlen = sizeof(*ip_addr);
1292 nap->host_addr = xmalloc(nap->host_addrlen);
1293 memcpy(nap->host_addr, ip_addr, nap->host_addrlen);
1295 nfs_port = hasmntval(mntp, MNTTAB_OPT_PORT);
1297 nfs_port = htons(NFS_PORT);
1299 nfs_port = htons(nfs_port);
1301 ((struct sockaddr_in *)nap->host_addr)->sin_port = nfs_port;
1303 nap->proto = 0; /* bsdi3 sets this field to zero */
1305 if (STREQ(nfs_proto, "tcp")) /* AIX 4.2.x needs this */
1306 nap->proto = IPPROTO_TCP;
1307 else if (STREQ(nfs_proto, "udp"))
1308 nap->proto = IPPROTO_UDP;
1311 nap->version = NFS4_MOUNT_VERSION; /* BSDI 3.0 and OpenBSD 2.2 */
1313 /************************************************************************/
1314 /*** OTHER NFS SOCKET RELATED OPTIONS AND FLAGS ***/
1315 /************************************************************************/
1318 /************************************************************************/
1319 /*** OTHER FLAGS AND OPTIONS ***/
1320 /************************************************************************/
1322 #if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX)
1323 if (amu_hasmntopt(mntp, MNTTAB_OPT_POSIX) != NULL) {
1324 nap->args.flags |= MNT2_NFS_OPT_POSIX;
1325 # ifdef HAVE_NFS_ARGS_T_PATHCONF
1326 nap->pathconf = NULL;
1327 # endif /* HAVE_NFS_ARGS_T_PATHCONF */
1329 #endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */
1331 #if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS)
1332 nap->maxgrouplist = hasmntval(mntp, MNTTAB_OPT_MAXGROUPS);
1333 if (nap->maxgrouplist != 0)
1334 nap->args.flags |= MNT2_NFS_OPT_MAXGRPS;
1335 #endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */
1337 #ifdef HAVE_NFS_ARGS_T_OPTSTR
1338 nap->optstr = mntp->mnt_opts;
1339 #endif /* HAVE_NFS_ARGS_T_OPTSTR */
1341 /************************************************************************/
1342 /*** FINAL ACTIONS ***/
1343 /************************************************************************/
1345 #ifdef HAVE_NFS_ARGS_T_GFS_FLAGS
1346 /* Ultrix stores generic flags in nfs_args.gfs_flags. */
1347 nap->gfs_flags = genflags;
1348 #endif /* HAVE_NFS_ARGS_T_FLAGS */
1350 s = set_nfs4_security(nap, mntp);
1352 /* Add addresses to the mount options */
1353 add_nfs4_mntopts(nap, mntp, s);
1355 return; /* end of compute_nfs4_args() function */
1360 print_nfs4_args(const nfs4_args_t *nap, u_long nfs_version)
1362 struct sockaddr_in *sap;
1363 struct nfs_common_args a;
1366 plog(XLOG_DEBUG, "NULL nfs_args!");
1370 plog(XLOG_DEBUG, "NA->client_addr \"%s\"\n", nap->client_addr.data);
1371 plog(XLOG_DEBUG, "NA->mnt_path = \"%s\"", nap->mnt_path.data);
1372 plog(XLOG_DEBUG, "NA->hostname = \"%s\"", nap->hostname.data);
1373 sap = (struct sockaddr_in *) nap->host_addr;
1374 print_nfs_sockaddr_in("host_addr", sap);
1375 plog(XLOG_DEBUG, "NA->proto = %d", (int) nap->proto);
1376 #ifdef HAVE_NFS_ARGS_T_VERSION
1377 plog(XLOG_DEBUG, "NA->version = %d", nap->version);
1378 #endif /* HAVE_NFS_ARGS_T_VERSION */
1379 print_nfs4_security(nap);
1381 put_nfs_common_args(nap, a);
1382 print_nfs_common_args(&a);
1385 #endif /* HAVE_FS_NFS4 */
1388 compute_nfs_args(void *nap,
1391 struct netconfig *nfsncp,
1392 struct sockaddr_in *ip_addr,
1395 am_nfs_handle_t *fhp,
1400 if (nfs_version == NFS_VERSION4)
1401 compute_nfs4_args(nap, mntp, genflags, nfsncp, ip_addr, nfs_version,
1402 nfs_proto, fhp, host_name, fs_name);
1404 #endif /* HAVE_FS_NFS4 */
1405 compute_nfs23_args(nap, mntp, genflags, nfsncp, ip_addr, nfs_version,
1406 nfs_proto, fhp, host_name, fs_name);
1410 discard_nfs_args(void *nap, u_long nfs_version)
1413 if (nfs_version == NFS_VERSION4)
1414 discard_nfs4_args(nap);
1416 #endif /* HAVE_FS_NFS4 */
1417 discard_nfs23_args(nap);
1422 print_nfs_args(const void *nap, u_long nfs_version)
1425 if (nfs_version == NFS_VERSION4)
1426 print_nfs4_args(nap, nfs_version);
1428 #endif /* HAVE_FS_NFS4 */
1429 print_nfs23_args(nap, nfs_version);
1435 * Fill in special values for flags and fields of nfs_args, for an
1436 * automounter NFS mount.
1439 compute_automounter_nfs_args(nfs_args_t *nap, mntent_t *mntp)
1441 struct nfs_common_args a;
1443 #ifdef MNT2_NFS_OPT_SYMTTL
1445 * Don't let the kernel cache symbolic links we generate, or else lookups
1446 * will bypass amd and fail to remount stuff as needed.
1448 plog(XLOG_INFO, "turning on NFS option symttl and setting value to 0");
1449 nap->flags |= MNT2_NFS_OPT_SYMTTL;
1451 #endif /* MNT2_NFS_OPT_SYMTTL */
1454 * This completes the flags for the HIDE_MOUNT_TYPE code in the
1455 * mount_amfs_toplvl() function in amd/amfs_toplvl.c.
1456 * Some systems don't have a mount type, but a mount flag.
1458 #ifdef MNT2_NFS_OPT_AUTO
1459 nap->flags |= MNT2_NFS_OPT_AUTO;
1460 #endif /* MNT2_NFS_OPT_AUTO */
1461 #ifdef MNT2_NFS_OPT_IGNORE
1462 nap->flags |= MNT2_NFS_OPT_IGNORE;
1463 #endif /* MNT2_NFS_OPT_IGNORE */
1464 #ifdef MNT2_GEN_OPT_AUTOMNTFS
1465 nap->flags |= MNT2_GEN_OPT_AUTOMNTFS;
1466 #endif /* not MNT2_GEN_OPT_AUTOMNTFS */
1468 #ifdef MNT2_NFS_OPT_DUMBTIMR
1470 * Don't let the kernel start computing throughput of Amd. The numbers
1471 * will be meaningless because of the way Amd does mount retries.
1473 plog(XLOG_INFO, "%s: disabling nfs congestion window", mntp->mnt_dir);
1474 nap->flags |= MNT2_NFS_OPT_DUMBTIMR;
1475 #endif /* MNT2_NFS_OPT_DUMBTIMR */
1477 /* compute all of the NFS attribute-cache flags */
1478 memset(&a, 0, sizeof(a));
1479 a.flags = nap->flags;
1480 compute_nfs_attrcache_flags(&a, mntp);
1481 get_nfs_common_args(nap, a);
1484 * Provide a slight bit more security by requiring the kernel to use
1487 #ifdef MNT2_NFS_OPT_RESVPORT
1488 nap->flags |= MNT2_NFS_OPT_RESVPORT;
1489 #endif /* MNT2_NFS_OPT_RESVPORT */
1493 nfs_valid_version(u_long v)
1495 return v >= NFS_VERS_MIN && v <= NFS_VERS_MAX;