2 * Copyright (c) 1997-1999 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. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgment:
21 * This product includes software developed by the University of
22 * California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 * may be used to endorse or promote products derived from this software
25 * without specific prior written permission.
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 * $Id: mount_fs.c,v 1.8 1999/09/18 08:38:06 ezk Exp $
42 * $FreeBSD: src/contrib/amd/libamu/mount_fs.c,v 1.4 1999/09/23 05:36:01 obrien Exp $
43 * $DragonFly: src/contrib/amd/libamu/mount_fs.c,v 1.2 2003/06/17 04:23:57 dillon Exp $
49 #endif /* HAVE_CONFIG_H */
54 /* ensure that mount table options are delimited by a comma */
55 #define append_opts(old, new) { \
56 if (*(old) != '\0') strcat(old, ","); \
60 * Standard mount flags
62 struct opt_tab mnt_flags
[] =
64 #if defined(MNT2_GEN_OPT_RDONLY) && defined(MNTTAB_OPT_RO)
65 {MNTTAB_OPT_RO
, MNT2_GEN_OPT_RDONLY
},
66 #endif /* defined(MNT2_GEN_OPT_RDONLY) && defined(MNTTAB_OPT_RO) */
68 #if defined(MNT2_GEN_OPT_NOCACHE) && defined(MNTTAB_OPT_NOCACHE)
69 {MNTTAB_OPT_NOCACHE
, MNT2_GEN_OPT_NOCACHE
},
70 #endif /* defined(MNT2_GEN_OPT_NOCACHE) && defined(MNTTAB_OPT_NOCACHE) */
72 /* the "grpid" mount option can be offered as generic of NFS */
73 #ifdef MNTTAB_OPT_GRPID
74 # ifdef MNT2_GEN_OPT_GRPID
75 {MNTTAB_OPT_GRPID
, MNT2_GEN_OPT_GRPID
},
76 # endif /* MNT2_GEN_OPT_GRPID */
77 # ifdef MNT2_NFS_OPT_GRPID
78 {MNTTAB_OPT_GRPID
, MNT2_NFS_OPT_GRPID
},
79 # endif /* MNT2_NFS_OPT_GRPID */
80 #endif /* MNTTAB_OPT_GRPID */
82 #if defined(MNT2_GEN_OPT_MULTI) && defined(MNTTAB_OPT_MULTI)
83 {MNTTAB_OPT_MULTI
, MNT2_GEN_OPT_MULTI
},
84 #endif /* defined(MNT2_GEN_OPT_MULTI) && defined(MNTTAB_OPT_MULTI) */
86 #if defined(MNT2_GEN_OPT_NODEV) && defined(MNTTAB_OPT_NODEV)
87 {MNTTAB_OPT_NODEV
, MNT2_GEN_OPT_NODEV
},
88 #endif /* defined(MNT2_GEN_OPT_NODEV) && defined(MNTTAB_OPT_NODEV) */
90 #if defined(MNT2_GEN_OPT_NOEXEC) && defined(MNTTAB_OPT_NOEXEC)
91 {MNTTAB_OPT_NOEXEC
, MNT2_GEN_OPT_NOEXEC
},
92 #endif /* defined(MNT2_GEN_OPT_NOEXEC) && defined(MNTTAB_OPT_NOEXEC) */
94 #if defined(MNT2_GEN_OPT_NOSUB) && defined(MNTTAB_OPT_NOSUB)
95 {MNTTAB_OPT_NOSUB
, MNT2_GEN_OPT_NOSUB
},
96 #endif /* defined(MNT2_GEN_OPT_NOSUB) && defined(MNTTAB_OPT_NOSUB) */
98 #if defined(MNT2_GEN_OPT_NOSUID) && defined(MNTTAB_OPT_NOSUID)
99 {MNTTAB_OPT_NOSUID
, MNT2_GEN_OPT_NOSUID
},
100 #endif /* defined(MNT2_GEN_OPT_NOSUID) && defined(MNTTAB_OPT_NOSUID) */
102 #if defined(MNT2_GEN_OPT_SYNC) && defined(MNTTAB_OPT_SYNC)
103 {MNTTAB_OPT_SYNC
, MNT2_GEN_OPT_SYNC
},
104 #endif /* defined(MNT2_GEN_OPT_SYNC) && defined(MNTTAB_OPT_SYNC) */
106 #if defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY)
107 {MNTTAB_OPT_OVERLAY
, MNT2_GEN_OPT_OVERLAY
},
108 #endif /* defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY) */
114 /* compute generic mount flags */
116 compute_mount_flags(mntent_t
*mntp
)
121 /* start: this must come first */
122 #ifdef MNT2_GEN_OPT_NEWTYPE
123 flags
= MNT2_GEN_OPT_NEWTYPE
;
124 #else /* not MNT2_GEN_OPT_NEWTYPE */
125 /* Not all machines have MNT2_GEN_OPT_NEWTYPE (HP-UX 9.01) */
127 #endif /* not MNT2_GEN_OPT_NEWTYPE */
129 #if defined(MNT2_GEN_OPT_OVERLAY) && defined(MNTTAB_OPT_OVERLAY)
131 * Overlay this amd mount (presumably on another amd which died
132 * before and left the machine hung). This will allow a new amd or
133 * hlfsd to be remounted on top of another one.
135 if (hasmntopt(mntp
, MNTTAB_OPT_OVERLAY
)) {
136 flags
|= MNT2_GEN_OPT_OVERLAY
;
137 plog(XLOG_INFO
, "using an overlay mount");
139 #endif /* defined(MNT2_GEN_OVERLAY) && defined(MNTOPT_OVERLAY) */
142 * Crack basic mount options
144 for (opt
= mnt_flags
; opt
->opt
; opt
++) {
145 flags
|= hasmntopt(mntp
, opt
->opt
) ? opt
->flag
: 0;
152 /* compute generic mount flags for automounter mounts */
154 compute_automounter_mount_flags(mntent_t
*mntp
)
158 #ifdef MNT2_GEN_OPT_IGNORE
159 flags
|= MNT2_GEN_OPT_IGNORE
;
160 #endif /* not MNT2_GEN_OPT_IGNORE */
161 #ifdef MNT2_GEN_OPT_AUTOMNTFS
162 flags
|= MNT2_GEN_OPT_AUTOMNTFS
;
163 #endif /* not MNT2_GEN_OPT_AUTOMNTFS */
170 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
)
173 #ifdef MOUNT_TABLE_ON_FILE
174 # ifdef MNTTAB_OPT_DEV
176 # endif /* MNTTAB_OPT_DEV */
177 char *zopts
= NULL
, *xopts
= NULL
;
178 # if defined(MNTTAB_OPT_DEV) || (defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)) || defined(MNTTAB_OPT_PROTO)
180 # endif /* defined(MNTTAB_OPT_DEV) || (defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)) || defined(MNTTAB_OPT_PROTO) */
181 #endif /* MOUNT_TABLE_ON_FILE */
183 char buf
[80]; /* buffer for sprintf */
187 sprintf(buf
, "%s%s%s",
188 "%s fstype ", MTYPE_PRINTF_TYPE
, " (%s) flags %#x (%s)");
189 dlog(buf
, mnt
->mnt_dir
, type
, mnt
->mnt_type
, flags
, mnt
->mnt_opts
);
195 error
= MOUNT_TRAP(type
, mnt
, flags
, mnt_data
);
198 plog(XLOG_ERROR
, "%s: mount: %m", mnt
->mnt_dir
);
200 * The following code handles conditions which shouldn't
201 * occur. They are possible either because amd screws up
202 * in preparing for the mount, or because some human
203 * messed with the mount point. Both have been known to
204 * happen. -- stolcke 2/22/95
206 if (errno
== ENOENT
) {
208 * Occasionally the mount point vanishes, probably
209 * due to some race condition. Just recreate it
212 errno
= mkdirs(mnt
->mnt_dir
, 0555);
213 if (errno
!= 0 && errno
!= EEXIST
)
214 plog(XLOG_ERROR
, "%s: mkdirs: %m", mnt
->mnt_dir
);
216 plog(XLOG_WARNING
, "extra mkdirs required for %s",
218 error
= MOUNT_TRAP(type
, mnt
, flags
, mnt_data
);
220 } else if (errno
== EBUSY
) {
222 * Also, sometimes unmount isn't called, e.g., because
223 * our mountlist is garbled. This leaves old mount
224 * points around which need to be removed before we
225 * can mount something new in their place.
227 errno
= umount_fs(mnt
->mnt_dir
, mnttabname
);
229 plog(XLOG_ERROR
, "%s: umount: %m", mnt
->mnt_dir
);
231 plog(XLOG_WARNING
, "extra umount required for %s",
233 error
= MOUNT_TRAP(type
, mnt
, flags
, mnt_data
);
238 if (error
< 0 && --retry
> 0) {
246 #ifdef MOUNT_TABLE_ON_FILE
248 * Allocate memory for options:
249 * dev=..., vers={2,3}, proto={tcp,udp}
251 zopts
= (char *) xmalloc(strlen(mnt
->mnt_opts
) + 48);
253 /* copy standard options */
254 xopts
= mnt
->mnt_opts
;
256 strcpy(zopts
, xopts
);
258 # ifdef MNTTAB_OPT_DEV
259 /* add the extra dev= field to the mount table */
260 if (lstat(mnt
->mnt_dir
, &stb
) == 0) {
261 if (sizeof(stb
.st_dev
) == 2) /* e.g. SunOS 4.1 */
262 sprintf(optsbuf
, "%s=%04lx",
263 MNTTAB_OPT_DEV
, (u_long
) stb
.st_dev
& 0xffff);
264 else /* e.g. System Vr4 */
265 sprintf(optsbuf
, "%s=%08lx",
266 MNTTAB_OPT_DEV
, (u_long
) stb
.st_dev
);
267 append_opts(zopts
, optsbuf
);
269 # endif /* MNTTAB_OPT_DEV */
271 # if defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS)
273 * add the extra vers={2,3} field to the mount table,
274 * unless already specified by user
276 if (nfs_version
== NFS_VERSION3
&&
277 hasmntval(mnt
, MNTTAB_OPT_VERS
) != NFS_VERSION3
) {
278 sprintf(optsbuf
, "%s=%d", MNTTAB_OPT_VERS
, NFS_VERSION3
);
279 append_opts(zopts
, optsbuf
);
281 # endif /* defined(HAVE_FS_NFS3) && defined(MNTTAB_OPT_VERS) */
283 # ifdef MNTTAB_OPT_PROTO
285 * add the extra proto={tcp,udp} field to the mount table,
286 * unless already specified by user.
288 if (nfs_proto
&& !hasmntopt(mnt
, MNTTAB_OPT_PROTO
)) {
289 sprintf(optsbuf
, "%s=%s", MNTTAB_OPT_PROTO
, nfs_proto
);
290 append_opts(zopts
, optsbuf
);
292 # endif /* MNTTAB_OPT_PROTO */
294 /* finally, store the options into the mount table structure */
295 mnt
->mnt_opts
= zopts
;
298 * Additional fields in mntent_t
301 # ifdef HAVE_FIELD_MNTENT_T_MNT_CNODE
303 # endif /* HAVE_FIELD_MNTENT_T_MNT_CNODE */
305 # ifdef HAVE_FIELD_MNTENT_T_MNT_RO
306 mnt
->mnt_ro
= (hasmntopt(mnt
, MNTTAB_OPT_RO
) != NULL
);
307 # endif /* HAVE_FIELD_MNTENT_T_MNT_RO */
309 # ifdef HAVE_FIELD_MNTENT_T_MNT_TIME
310 # ifdef HAVE_FIELD_MNTENT_T_MNT_TIME_STRING
311 { /* allocate enough space for a long */
312 char *str
= (char *) xmalloc(13 * sizeof(char));
313 sprintf(str
, "%ld", time((time_t *) NULL
));
316 # else /* not HAVE_FIELD_MNTENT_T_MNT_TIME_STRING */
317 mnt
->mnt_time
= time((time_t *) NULL
);
318 # endif /* not HAVE_FIELD_MNTENT_T_MNT_TIME_STRING */
319 # endif /* HAVE_FIELD_MNTENT_T_MNT_TIME */
321 write_mntent(mnt
, mnttabname
);
323 # ifdef MNTTAB_OPT_DEV
325 XFREE(mnt
->mnt_opts
);
326 mnt
->mnt_opts
= xopts
;
328 # endif /* MNTTAB_OPT_DEV */
329 #endif /* MOUNT_TABLE_ON_FILE */
336 * Fill in the many possible fields and flags of struct nfs_args.
338 * nap: pre-allocated structure to fill in.
339 * mntp: mount entry structure (includes options)
340 * genflags: generic mount flags already determined
341 * nfsncp: (TLI only) netconfig entry for this NFS mount
342 * ip_addr: IP address of file server
343 * nfs_version: 2, 3, (4 in the future), or 0 if unknown
344 * nfs_proto: "udp", "tcp", or NULL.
345 * fhp: file handle structure pointer
346 * host_name: name of remote NFS host
347 * fs_name: remote file system name to mount
350 #ifdef HAVE_TRANSPORT_TYPE_TLI
351 compute_nfs_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
)
352 #else /* not HAVE_TRANSPORT_TYPE_TLI */
353 compute_nfs_args(nfs_args_t
*nap
, mntent_t
*mntp
, int genflags
, struct sockaddr_in
*ip_addr
, u_long nfs_version
, char *nfs_proto
, am_nfs_handle_t
*fhp
, char *host_name
, char *fs_name
)
354 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
358 static am_nfs_fh3 fh3
; /* static, b/c gcc on aix corrupts stack */
359 #endif /* HAVE_FS_NFS3 */
361 /* initialize just in case */
362 memset((voidp
) nap
, 0, sizeof(nfs_args_t
));
364 /************************************************************************/
365 /*** FILEHANDLE DATA AND LENGTH ***/
366 /************************************************************************/
368 if (nfs_version
== NFS_VERSION3
) {
369 memset((voidp
) &fh3
, 0, sizeof(am_nfs_fh3
));
370 fh3
.fh3_length
= fhp
->v3
.mountres3_u
.mountinfo
.fhandle
.fhandle3_len
;
371 memmove(fh3
.fh3_u
.data
,
372 fhp
->v3
.mountres3_u
.mountinfo
.fhandle
.fhandle3_val
,
375 # if defined(HAVE_FIELD_NFS_ARGS_T_FHSIZE) || defined(HAVE_FIELD_NFS_ARGS_T_FH_LEN)
377 * Some systems (Irix/bsdi3) have a separate field in nfs_args for
378 * the length of the file handle for NFS V3. They insist that
379 * the file handle set in nfs_args be plain bytes, and not
380 * include the length field.
382 NFS_FH_DREF(nap
->NFS_FH_FIELD
, &(fh3
.fh3_u
.data
));
383 # else /* not defined(HAVE_FIELD_NFS_ARGS_T_FHSIZE) || defined(HAVE_FIELD_NFS_ARGS_T_FH_LEN) */
384 NFS_FH_DREF(nap
->NFS_FH_FIELD
, &fh3
);
385 # endif /* not defined(HAVE_FIELD_NFS_ARGS_T_FHSIZE) || defined(HAVE_FIELD_NFS_ARGS_T_FH_LEN) */
386 # ifdef MNT2_NFS_OPT_NFSV3
387 nap
->flags
|= MNT2_NFS_OPT_NFSV3
;
388 # endif /* MNT2_NFS_OPT_NFSV3 */
390 #endif /* HAVE_FS_NFS3 */
391 NFS_FH_DREF(nap
->NFS_FH_FIELD
, &(fhp
->v2
.fhs_fh
));
393 #ifdef HAVE_FIELD_NFS_ARGS_T_FHSIZE
395 if (nfs_version
== NFS_VERSION3
)
396 nap
->fhsize
= fh3
.fh3_length
;
398 # endif /* HAVE_FS_NFS3 */
399 nap
->fhsize
= FHSIZE
;
400 #endif /* HAVE_FIELD_NFS_ARGS_T_FHSIZE */
402 /* this is the version of the nfs_args structure, not of NFS! */
403 #ifdef HAVE_FIELD_NFS_ARGS_T_FH_LEN
405 if (nfs_version
== NFS_VERSION3
)
406 nap
->fh_len
= fh3
.fh3_length
;
408 # endif /* HAVE_FS_NFS3 */
409 nap
->fh_len
= FHSIZE
;
410 #endif /* HAVE_FIELD_NFS_ARGS_T_FH_LEN */
412 /************************************************************************/
414 /************************************************************************/
415 NFS_HN_DREF(nap
->hostname
, host_name
);
416 #ifdef MNT2_NFS_OPT_HOSTNAME
417 nap
->flags
|= MNT2_NFS_OPT_HOSTNAME
;
418 #endif /* MNT2_NFS_OPT_HOSTNAME */
420 /************************************************************************/
421 /*** ATTRIBUTE CACHES ***/
422 /************************************************************************/
424 * acval is set to 0 at the top of the function. If actimeo mount option
425 * exists and defined in mntopts, then it acval is set to it.
426 * If the value is non-zero, then we set all attribute cache fields to it.
427 * If acval is zero, it means it was never defined in mntopts or the
428 * actimeo mount option does not exist, in which case we check for
429 * individual mount options per attribute cache.
430 * Regardless of the value of acval, mount flags are set based directly
431 * on the values of the attribute caches.
433 #ifdef MNTTAB_OPT_ACTIMEO
434 acval
= hasmntval(mntp
, MNTTAB_OPT_ACTIMEO
); /* attr cache timeout (sec) */
435 #endif /* MNTTAB_OPT_ACTIMEO */
438 #ifdef HAVE_FIELD_NFS_ARGS_T_ACREGMIN
439 nap
->acregmin
= acval
; /* min ac timeout for reg files (sec) */
440 nap
->acregmax
= acval
; /* max ac timeout for reg files (sec) */
441 #endif /* HAVE_FIELD_NFS_ARGS_T_ACREGMIN */
442 #ifdef HAVE_FIELD_NFS_ARGS_T_ACDIRMIN
443 nap
->acdirmin
= acval
; /* min ac timeout for dirs (sec) */
444 nap
->acdirmax
= acval
; /* max ac timeout for dirs (sec) */
445 #endif /* HAVE_FIELD_NFS_ARGS_T_ACDIRMIN */
447 #ifdef MNTTAB_OPT_ACREGMIN
448 nap
->acregmin
= hasmntval(mntp
, MNTTAB_OPT_ACREGMIN
);
449 #endif /* MNTTAB_OPT_ACREGMIN */
450 #ifdef MNTTAB_OPT_ACREGMAX
451 nap
->acregmax
= hasmntval(mntp
, MNTTAB_OPT_ACREGMAX
);
452 #endif /* MNTTAB_OPT_ACREGMAX */
453 #ifdef MNTTAB_OPT_ACDIRMIN
454 nap
->acdirmin
= hasmntval(mntp
, MNTTAB_OPT_ACDIRMIN
);
455 #endif /* MNTTAB_OPT_ACDIRMIN */
456 #ifdef MNTTAB_OPT_ACDIRMAX
457 nap
->acdirmax
= hasmntval(mntp
, MNTTAB_OPT_ACDIRMAX
);
458 #endif /* MNTTAB_OPT_ACDIRMAX */
459 } /* end of "if (acval)" statement */
461 #ifdef MNT2_NFS_OPT_ACREGMIN
463 nap
->flags
|= MNT2_NFS_OPT_ACREGMIN
;
464 #endif /* MNT2_NFS_OPT_ACREGMIN */
465 #ifdef MNT2_NFS_OPT_ACREGMAX
467 nap
->flags
|= MNT2_NFS_OPT_ACREGMAX
;
468 #endif /* MNT2_NFS_OPT_ACREGMAX */
469 #ifdef MNT2_NFS_OPT_ACDIRMIN
471 nap
->flags
|= MNT2_NFS_OPT_ACDIRMIN
;
472 #endif /* MNT2_NFS_OPT_ACDIRMIN */
473 #ifdef MNT2_NFS_OPT_ACDIRMAX
475 nap
->flags
|= MNT2_NFS_OPT_ACDIRMAX
;
476 #endif /* MNT2_NFS_OPT_ACDIRMAX */
478 #ifdef MNTTAB_OPT_NOAC /* don't cache attributes */
479 if (hasmntopt(mntp
, MNTTAB_OPT_NOAC
) != NULL
)
480 nap
->flags
|= MNT2_NFS_OPT_NOAC
;
481 #endif /* MNTTAB_OPT_NOAC */
483 /************************************************************************/
484 /*** IP ADDRESS OF REMOTE HOST ***/
485 /************************************************************************/
487 #ifdef HAVE_TRANSPORT_TYPE_TLI
488 nap
->addr
= ALLOC(struct netbuf
); /* free()'ed at end of mount_nfs_fh() */
489 #endif /* HAVE_TRANSPORT_TYPE_TLI */
490 NFS_SA_DREF(nap
, ip_addr
);
493 /************************************************************************/
494 /*** NFS PROTOCOL (UDP, TCP) AND VERSION ***/
495 /************************************************************************/
496 #ifdef MNT2_NFS_OPT_TCP
497 if (nfs_proto
&& STREQ(nfs_proto
, "tcp"))
498 nap
->flags
|= MNT2_NFS_OPT_TCP
;
499 #endif /* MNT2_NFS_OPT_TCP */
501 #ifdef HAVE_FIELD_NFS_ARGS_T_SOTYPE
502 /* bsdi3 uses this */
504 if (STREQ(nfs_proto
, "tcp"))
505 nap
->sotype
= SOCK_STREAM
;
506 else if (STREQ(nfs_proto
, "udp"))
507 nap
->sotype
= SOCK_DGRAM
;
509 #endif /* HAVE_FIELD_NFS_ARGS_T_SOTYPE */
511 #ifdef HAVE_FIELD_NFS_ARGS_T_PROTO
512 nap
->proto
= 0; /* bsdi3 sets this field to zero */
515 if (STREQ(nfs_proto
, "tcp")) /* AIX 4.2.x needs this */
516 nap
->proto
= IPPROTO_TCP
;
517 else if (STREQ(nfs_proto
, "udp"))
518 nap
->proto
= IPPROTO_UDP
;
520 # endif /* IPPROTO_TCP */
521 #endif /* HAVE_FIELD_NFS_ARGS_T_SOTYPE */
523 #ifdef HAVE_FIELD_NFS_ARGS_T_VERSION
524 # ifdef NFS_ARGSVERSION
525 nap
->version
= NFS_ARGSVERSION
; /* BSDI 3.0 and OpenBSD 2.2 */
526 # endif /* NFS_ARGSVERSION */
527 # ifdef DG_MOUNT_NFS_VERSION
528 nap
->version
= DG_MOUNT_NFS_VERSION
; /* dg-ux */
529 # endif /* DG_MOUNT_NFS_VERSION */
530 #endif /* HAVE_FIELD_NFS_ARGS_VERSION */
532 /************************************************************************/
533 /*** OTHER NFS SOCKET RELATED OPTIONS AND FLAGS ***/
534 /************************************************************************/
535 #ifdef MNT2_NFS_OPT_NOCONN
536 /* check if user specified to use unconnected or connected sockets */
537 if (hasmntopt(mntp
, MNTTAB_OPT_NOCONN
) != NULL
)
538 nap
->flags
|= MNT2_NFS_OPT_NOCONN
;
539 else if (hasmntopt(mntp
, MNTTAB_OPT_CONN
) != NULL
)
540 nap
->flags
&= ~MNT2_NFS_OPT_NOCONN
;
543 * Some OSs want you to set noconn always. Some want you to always turn
544 * it off. Others want you to turn it on/off only if NFS V.3 is used.
545 * And all of that changes from revision to another. This is
546 * particularly true of OpenBSD, NetBSD, and FreeBSD. So, rather than
547 * attempt to auto-detect this, I'm forced to "fix" it in the individual
548 * conf/nfs_prot/nfs_prot_*.h files.
550 # ifdef USE_UNCONNECTED_NFS_SOCKETS
551 if (!(nap
->flags
& MNT2_NFS_OPT_NOCONN
)) {
552 nap
->flags
|= MNT2_NFS_OPT_NOCONN
;
553 plog(XLOG_WARNING
, "noconn option not specified, and was just turned ON (OS override)! (May cause NFS hangs on some systems...)");
555 # endif /* USE_UNCONNECTED_NFS_SOCKETS */
556 # ifdef USE_CONNECTED_NFS_SOCKETS
557 if (nap
->flags
& MNT2_NFS_OPT_NOCONN
) {
558 nap
->flags
&= ~MNT2_NFS_OPT_NOCONN
;
559 plog(XLOG_WARNING
, "noconn option specified, and was just turned OFF (OS override)! (May cause NFS hangs on some systems...)");
561 # endif /* USE_CONNECTED_NFS_SOCKETS */
563 #endif /* MNT2_NFS_OPT_NOCONN */
565 #ifdef MNT2_NFS_OPT_RESVPORT
566 # ifdef MNTTAB_OPT_RESVPORT
567 if (hasmntopt(mntp
, MNTTAB_OPT_RESVPORT
) != NULL
)
568 nap
->flags
|= MNT2_NFS_OPT_RESVPORT
;
569 # else /* not MNTTAB_OPT_RESVPORT */
570 nap
->flags
|= MNT2_NFS_OPT_RESVPORT
;
571 # endif /* not MNTTAB_OPT_RESVPORT */
572 #endif /* MNT2_NFS_OPT_RESVPORT */
574 /************************************************************************/
575 /*** OTHER FLAGS AND OPTIONS ***/
576 /************************************************************************/
578 #ifdef HAVE_TRANSPORT_TYPE_TLI
579 /* set up syncaddr field */
580 nap
->syncaddr
= (struct netbuf
*) NULL
;
582 /* set up knconf field */
583 if (get_knetconfig(&nap
->knconf
, nfsncp
, nfs_proto
) < 0) {
584 plog(XLOG_FATAL
, "cannot fill knetconfig structure for nfs_args");
587 /* update the flags field for knconf */
588 nap
->flags
|= MNT2_NFS_OPT_KNCONF
;
589 #endif /* HAVE_TRANSPORT_TYPE_TLI */
591 #ifdef MNT2_NFS_OPT_FSNAME
592 nap
->fsname
= fs_name
;
593 nap
->flags
|= MNT2_NFS_OPT_FSNAME
;
594 #endif /* MNT2_NFS_OPT_FSNAME */
596 nap
->rsize
= hasmntval(mntp
, MNTTAB_OPT_RSIZE
);
597 #ifdef MNT2_NFS_OPT_RSIZE
599 nap
->flags
|= MNT2_NFS_OPT_RSIZE
;
600 #endif /* MNT2_NFS_OPT_RSIZE */
602 nap
->wsize
= hasmntval(mntp
, MNTTAB_OPT_WSIZE
);
603 #ifdef MNT2_NFS_OPT_WSIZE
605 nap
->flags
|= MNT2_NFS_OPT_WSIZE
;
606 #endif /* MNT2_NFS_OPT_WSIZE */
608 nap
->timeo
= hasmntval(mntp
, MNTTAB_OPT_TIMEO
);
609 #ifdef MNT2_NFS_OPT_TIMEO
611 nap
->flags
|= MNT2_NFS_OPT_TIMEO
;
612 #endif /* MNT2_NFS_OPT_TIMEO */
614 nap
->retrans
= hasmntval(mntp
, MNTTAB_OPT_RETRANS
);
615 #ifdef MNT2_NFS_OPT_RETRANS
617 nap
->flags
|= MNT2_NFS_OPT_RETRANS
;
618 #endif /* MNT2_NFS_OPT_RETRANS */
620 #ifdef MNT2_NFS_OPT_BIODS
621 if ((nap
->biods
= hasmntval(mntp
, MNTTAB_OPT_BIODS
)))
622 nap
->flags
|= MNT2_NFS_OPT_BIODS
;
623 #endif /* MNT2_NFS_OPT_BIODS */
625 if (hasmntopt(mntp
, MNTTAB_OPT_SOFT
) != NULL
)
626 nap
->flags
|= MNT2_NFS_OPT_SOFT
;
628 #ifdef MNT2_NFS_OPT_SPONGY
629 if (hasmntopt(mntp
, MNTTAB_OPT_SPONGY
) != NULL
) {
630 nap
->flags
|= MNT2_NFS_OPT_SPONGY
;
631 if (nap
->flags
& MNT2_NFS_OPT_SOFT
) {
632 plog(XLOG_USER
, "Mount opts soft and spongy are incompatible - soft ignored");
633 nap
->flags
&= ~MNT2_NFS_OPT_SOFT
;
636 #endif /* MNT2_NFS_OPT_SPONGY */
638 #if defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY)
639 /* Ultrix has separate generic and NFS ro flags */
640 if (genflags
& MNT2_GEN_OPT_RONLY
)
641 nap
->flags
|= MNT2_NFS_OPT_RONLY
;
642 #endif /* defined(MNT2_GEN_OPT_RONLY) && defined(MNT2_NFS_OPT_RONLY) */
644 #ifdef MNTTAB_OPT_INTR
645 if (hasmntopt(mntp
, MNTTAB_OPT_INTR
) != NULL
)
647 * Either turn on the "allow interrupts" option, or
648 * turn off the "disallow interrupts" option"
650 # ifdef MNT2_NFS_OPT_INT
651 nap
->flags
|= MNT2_NFS_OPT_INT
;
652 # endif /* MNT2_NFS_OPT_INT */
653 # ifdef MNT2_NFS_OPT_NOINT
654 nap
->flags
&= ~MNT2_NFS_OPT_NOINT
;
655 # endif /* MNT2_NFS_OPT_NOINT */
656 #endif /* MNTTAB_OPT_INTR */
658 #ifdef MNTTAB_OPT_NODEVS
659 if (hasmntopt(mntp
, MNTTAB_OPT_NODEVS
) != NULL
)
660 nap
->flags
|= MNT2_NFS_OPT_NODEVS
;
661 #endif /* MNTTAB_OPT_NODEVS */
663 #ifdef MNTTAB_OPT_COMPRESS
664 if (hasmntopt(mntp
, MNTTAB_OPT_COMPRESS
) != NULL
)
665 nap
->flags
|= MNT2_NFS_OPT_COMPRESS
;
666 #endif /* MNTTAB_OPT_COMPRESS */
668 #ifdef MNTTAB_OPT_PRIVATE /* mount private, single-client tree */
669 if (hasmntopt(mntp
, MNTTAB_OPT_PRIVATE
) != NULL
)
670 nap
->flags
|= MNT2_NFS_OPT_PRIVATE
;
671 #endif /* MNTTAB_OPT_PRIVATE */
673 #ifdef MNTTAB_OPT_SYMTTL /* symlink cache time-to-live */
674 if ((nap
->symttl
= hasmntval(mntp
, MNTTAB_OPT_SYMTTL
)))
675 nap
->flags
|= MNT2_NFS_OPT_SYMTTL
;
676 #endif /* MNTTAB_OPT_SYMTTL */
678 #ifdef MNT2_NFS_OPT_PGTHRESH /* paging threshold */
679 if ((nap
->pg_thresh
= hasmntval(mntp
, MNTTAB_OPT_PGTHRESH
)))
680 nap
->flags
|= MNT2_NFS_OPT_PGTHRESH
;
681 #endif /* MNT2_NFS_OPT_PGTHRESH */
683 #if defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO)
684 if (hasmntopt(mntp
, MNTTAB_OPT_NOCTO
) != NULL
)
685 nap
->flags
|= MNT2_NFS_OPT_NOCTO
;
686 #endif /* defined(MNT2_NFS_OPT_NOCTO) && defined(MNTTAB_OPT_NOCTO) */
688 #if defined(MNT2_NFS_OPT_POSIX) && defined(MNTTAB_OPT_POSIX)
689 if (hasmntopt(mntp
, MNTTAB_OPT_POSIX
) != NULL
) {
690 nap
->flags
|= MNT2_NFS_OPT_POSIX
;
691 nap
->pathconf
= NULL
;
693 #endif /* MNT2_NFS_OPT_POSIX && MNTTAB_OPT_POSIX */
695 #if defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS)
696 nap
->maxgrouplist
= hasmntval(mntp
, MNTTAB_OPT_MAXGROUPS
);
697 if (nap
->maxgrouplist
!= 0)
698 nap
->flags
|= MNT2_NFS_OPT_MAXGRPS
;
699 #endif /* defined(MNT2_NFS_OPT_MAXGRPS) && defined(MNTTAB_OPT_MAXGROUPS) */
701 #ifdef HAVE_FIELD_NFS_ARGS_T_OPTSTR
702 nap
->optstr
= mntp
->mnt_opts
;
703 #endif /* HAVE_FIELD_NFS_ARGS_T_OPTSTR */
705 /************************************************************************/
706 /*** FINAL ACTIONS ***/
707 /************************************************************************/
709 #ifdef HAVE_FIELD_NFS_ARGS_T_GFS_FLAGS
710 /* Ultrix stores generic flags in nfs_args.gfs_flags. */
711 nap
->gfs_flags
= genflags
;
712 #endif /* HAVE_FIELD_NFS_ARGS_T_FLAGS */
714 return; /* end of compute_nfs_args() function */
719 * Fill in special values for flags and fields of nfs_args, for an
720 * automounter NFS mount.
723 compute_automounter_nfs_args(nfs_args_t
*nap
, mntent_t
*mntp
)
725 #ifdef MNT2_NFS_OPT_SYMTTL
727 * Don't let the kernel cache symbolic links we generate, or else lookups
728 * will bypass amd and fail to remount stuff as needed.
730 plog(XLOG_INFO
, "turning on NFS option symttl and setting value to %d", 0);
731 nap
->flags
|= MNT2_NFS_OPT_SYMTTL
;
733 #endif /* MNT2_NFS_OPT_SYMTTL */
736 * This completes the flags for the HIDE_MOUNT_TYPE code in the
737 * mount_amfs_toplvl() function in amd/amfs_toplvl.c.
738 * Some systems don't have a mount type, but a mount flag.
740 #ifdef MNT2_NFS_OPT_AUTO
741 nap
->flags
|= MNT2_NFS_OPT_AUTO
;
742 #endif /* MNT2_NFS_OPT_AUTO */
743 #ifdef MNT2_NFS_OPT_IGNORE
744 nap
->flags
|= MNT2_NFS_OPT_IGNORE
;
745 #endif /* MNT2_NFS_OPT_IGNORE */
746 #ifdef MNT2_GEN_OPT_AUTOMNTFS
747 nap
->flags
|= MNT2_GEN_OPT_AUTOMNTFS
;
748 #endif /* not MNT2_GEN_OPT_AUTOMNTFS */
750 #ifdef MNT2_NFS_OPT_DUMBTIMR
752 * Don't let the kernel start computing throughput of Amd The numbers will
753 * be meaningless because of the way Amd does mount retries.
755 plog(XLOG_INFO
, "%s: disabling nfs congestion window", mntp
->mnt_dir
);
756 nap
->flags
|= MNT2_NFS_OPT_DUMBTIMR
;
757 #endif /* MNT2_NFS_OPT_DUMBTIMR */
759 #ifdef MNT2_NFS_OPT_NOAC
761 * Don't cache attributes - they are changing under the kernel's feet.
762 * For example, IRIX5.2 will dispense with nfs lookup calls and hand stale
763 * filehandles to getattr unless we disable attribute caching on the
766 nap
->flags
|= MNT2_NFS_OPT_NOAC
;
767 #else /* not MNT2_NFS_OPT_NOAC */
769 * Setting these to 0 results in an error on some systems, which is why
770 * it's better to use "noac" if possible.
772 # if defined(MNT2_NFS_OPT_ACREGMIN) && defined(MNT2_NFS_OPT_ACREGMAX)
773 nap
->acregmin
= nap
->acregmax
= 0; /* XXX: was 1, but why? */
774 nap
->flags
|= MNT2_NFS_OPT_ACREGMIN
| MNT2_NFS_OPT_ACREGMAX
;
775 # endif /* defined(MNT2_NFS_OPT_ACREGMIN) && defined(MNT2_NFS_OPT_ACREGMAX) */
776 # if defined(MNT2_NFS_OPT_ACDIRMIN) && defined(MNT2_NFS_OPT_ACDIRMAX)
777 nap
->acdirmin
= nap
->acdirmax
= 0; /* XXX: was 1, but why? */
778 nap
->flags
|= MNT2_NFS_OPT_ACDIRMIN
| MNT2_NFS_OPT_ACDIRMAX
;
779 # endif /* defined(MNT2_NFS_OPT_ACDIRMIN) && defined(MNT2_NFS_OPT_ACDIRMAX) */
780 #endif /* not MNT2_NFS_OPT_NOAC */
782 * Provide a slight bit more security by requiring the kernel to use
785 #ifdef MNT2_NFS_OPT_RESVPORT
786 nap
->flags
|= MNT2_NFS_OPT_RESVPORT
;
787 #endif /* MNT2_NFS_OPT_RESVPORT */
792 /* get string version (in hex) of identifier */
794 get_hex_string(u_int len
, const char *fhdata
)
797 static char buf
[128]; /* better not go over it! */
804 memset(&arr
[0], 0, (64 * sizeof(short int)));
805 memcpy(&arr
[0], &fhdata
[0], len
);
806 for (i
=0; i
<len
/sizeof(short int); i
++) {
807 sprintf(str
, "%04x", ntohs(arr
[i
]));
815 * print a subset of fields from "struct nfs_args" that are otherwise
816 * not being provided anywhere else.
819 print_nfs_args(const nfs_args_t
*nap
, u_long nfs_version
)
821 int fhlen
= 32; /* default: NFS V.2 file handle length is 32 */
822 #ifdef HAVE_TRANSPORT_TYPE_TLI
824 struct knetconfig
*kncp
;
825 #else /* not HAVE_TRANSPORT_TYPE_TLI */
826 struct sockaddr_in
*sap
;
827 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
830 plog(XLOG_DEBUG
, "NULL nfs_args!");
834 /* override default file handle size */
840 #endif /* NFS_FHSIZE */
842 #ifdef HAVE_TRANSPORT_TYPE_TLI
844 plog(XLOG_DEBUG
, "NA->addr {netbuf} (maxlen=%d, len=%d) = \"%s\"",
845 nbp
->maxlen
, nbp
->len
,
846 get_hex_string(nbp
->len
, nbp
->buf
));
848 plog(XLOG_DEBUG
, "NA->syncaddr {netbuf} 0x%x", (int) nbp
);
850 plog(XLOG_DEBUG
, "NA->knconf->semantics %lu", (unsigned long) kncp
->knc_semantics
);
851 plog(XLOG_DEBUG
, "NA->knconf->protofmly \"%s\"", kncp
->knc_protofmly
);
852 plog(XLOG_DEBUG
, "NA->knconf->proto \"%s\"", kncp
->knc_proto
);
853 plog(XLOG_DEBUG
, "NA->knconf->rdev %lu", kncp
->knc_rdev
);
854 /* don't print knconf->unused field */
855 #else /* not HAVE_TRANSPORT_TYPE_TLI */
856 sap
= (struct sockaddr_in
*) &nap
->addr
;
857 plog(XLOG_DEBUG
, "NA->addr {sockaddr_in} (len=%d) = \"%s\"",
858 (int) sizeof(struct sockaddr_in
),
859 get_hex_string(sizeof(struct sockaddr_in
), (const char *)sap
));
860 #ifdef HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN
861 plog(XLOG_DEBUG
, "NA->addr.sin_len = \"%d\"", sap
->sin_len
);
862 #endif /* HAVE_FIELD_STRUCT_SOCKADDR_SA_LEN */
863 plog(XLOG_DEBUG
, "NA->addr.sin_family = \"%d\"", sap
->sin_family
);
864 plog(XLOG_DEBUG
, "NA->addr.sin_port = \"%d\"", sap
->sin_port
);
865 plog(XLOG_DEBUG
, "NA->addr.sin_addr = \"%s\"",
866 get_hex_string(sizeof(struct in_addr
), (const char *) &sap
->sin_addr
));
867 #endif /* not HAVE_TRANSPORT_TYPE_TLI */
869 plog(XLOG_DEBUG
, "NA->hostname = \"%s\"", nap
->hostname
? nap
->hostname
: "null");
870 #ifdef HAVE_FIELD_NFS_ARGS_T_NAMLEN
871 plog(XLOG_DEBUG
, "NA->namlen = %d", nap
->namlen
);
872 #endif /* HAVE_FIELD_NFS_ARGS_T_NAMLEN */
874 #ifdef MNT2_NFS_OPT_FSNAME
875 plog(XLOG_DEBUG
, "NA->fsname = \"%s\"", nap
->fsname
? nap
->fsname
: "null");
876 #endif /* MNT2_NFS_OPT_FSNAME */
878 #ifdef HAVE_FIELD_NFS_ARGS_T_FHSIZE
879 plog(XLOG_DEBUG
, "NA->fhsize = %d", nap
->fhsize
);
881 #endif /* HAVE_FIELD_NFS_ARGS_T_FHSIZE */
882 #ifdef HAVE_FIELD_NFS_ARGS_T_FH_LEN
883 plog(XLOG_DEBUG
, "NA->fh_len = %d", nap
->fh_len
);
885 #endif /* HAVE_FIELD_NFS_ARGS_T_FH_LEN */
888 * XXX: need to figure out how to correctly print file handles,
889 * since some times they are pointers, and sometimes the real structure
890 * is stored in nfs_args. Even if it is a pointer, it can be the actual
891 * char[] array, or a structure containing multiple fields.
893 plog(XLOG_DEBUG
, "NA->filehandle = \"%s\"",
894 get_hex_string(fhlen
, (const char *) &nap
->NFS_FH_FIELD
));
896 #ifdef HAVE_FIELD_NFS_ARGS_T_SOTYPE
897 plog(XLOG_DEBUG
, "NA->sotype = %d", nap
->sotype
);
898 #endif /* HAVE_FIELD_NFS_ARGS_T_SOTYPE */
899 #ifdef HAVE_FIELD_NFS_ARGS_T_PROTO
900 plog(XLOG_DEBUG
, "NA->proto = %d", (int) nap
->proto
);
901 #endif /* HAVE_FIELD_NFS_ARGS_T_PROTO */
902 #ifdef HAVE_FIELD_NFS_ARGS_T_VERSION
903 plog(XLOG_DEBUG
, "NA->version = %d", nap
->version
);
904 #endif /* HAVE_FIELD_NFS_ARGS_T_VERSION */
906 plog(XLOG_DEBUG
, "NA->flags = 0x%x", (int) nap
->flags
);
908 plog(XLOG_DEBUG
, "NA->rsize = %d", (int) nap
->rsize
);
909 plog(XLOG_DEBUG
, "NA->wsize = %d", (int) nap
->wsize
);
910 #ifdef HAVE_FIELD_NFS_ARGS_T_BSIZE
911 plog(XLOG_DEBUG
, "NA->bsize = %d", nap
->bsize
);
912 #endif /* HAVE_FIELD_NFS_ARGS_T_BSIZE */
913 plog(XLOG_DEBUG
, "NA->timeo = %d", (int) nap
->timeo
);
914 plog(XLOG_DEBUG
, "NA->retrans = %d", (int) nap
->retrans
);
916 #ifdef HAVE_FIELD_NFS_ARGS_T_ACREGMIN
917 plog(XLOG_DEBUG
, "NA->acregmin = %d", (int) nap
->acregmin
);
918 plog(XLOG_DEBUG
, "NA->acregmax = %d", (int) nap
->acregmax
);
919 plog(XLOG_DEBUG
, "NA->acdirmin = %d", (int) nap
->acdirmin
);
920 plog(XLOG_DEBUG
, "NA->acdirmax = %d", (int) nap
->acdirmax
);
921 #endif /* HAVE_FIELD_NFS_ARGS_T_ACREGMIN */
922 #ifdef MNTTAB_OPT_SYMTTL
923 plog(XLOG_DEBUG
, "NA->symttl = %d", nap
->symttl
);
924 #endif /* MNTTAB_OPT_SYMTTL */
925 #ifdef MNTTAB_OPT_PG_THRESH
926 plog(XLOG_DEBUG
, "NA->pg_thresh = %d", nap
->pg_thresh
);
927 #endif /* MNTTAB_OPT_PG_THRESH */
929 #ifdef MNT2_NFS_OPT_BIODS
930 plog(XLOG_DEBUG
, "NA->biods = %d", nap
->biods
);
931 #endif /* MNT2_NFS_OPT_BIODS */