1
#! /bin/sh /usr/share/dpatch/dpatch-run
2
## 30nfs4.dpatch by LaMont Jones <lamont@debian.org>
4
## All lines beginning with `## DP:' are a description of the patch.
5
## DP: Originally from util-linux 2.12r-9
6
## DP: Rediff against 20_loop-AES, Max Vozeler <xam@debian.org>
9
diff -urNad trunk~/mount/Makefile trunk/mount/Makefile
10
--- trunk~/mount/Makefile 2006-05-11 16:24:59.000000000 +0200
11
+++ trunk/mount/Makefile 2006-05-11 16:26:01.000000000 +0200
14
MAYBE = pivot_root swapoff
16
-NFS_OBJS = nfsmount.o nfsmount_xdr.o nfsmount_clnt.o
17
+NFS_OBJS = nfsmount.o nfsmount_xdr.o nfsmount_clnt.o nfs4mount.o
18
GEN_FILES = nfsmount.h nfsmount_xdr.c nfsmount_clnt.c
23
umount: umount.o fstab.o sundries.o xmalloc.o realpath.o mntent.o \
24
getusername.o get_label_uuid.o mount_by_label.o mount_blkid.o \
25
- version.o $(LIB)/env.o loumount.o
26
+ version.o nfsmount.o nfsmount_xdr.o $(LIB)/env.o loumount.o
27
$(LINK) $^ -o $@ $(BLKID_LIB)
29
swapon: swapon.o version.o xmalloc.o \
30
diff -urNad trunk~/mount/mount.8 trunk/mount/mount.8
31
--- trunk~/mount/mount.8 2006-05-11 16:24:59.000000000 +0200
32
+++ trunk/mount/mount.8 2006-05-11 16:25:00.000000000 +0200
42
program has to do is issue a simple
44
system call, and no detailed knowledge of the filesystem type is required.
45
-For a few types however (like nfs, smbfs, ncpfs) ad hoc code is
46
+For a few types however (like nfs, nfs4, smbfs, ncpfs) ad hoc code is
47
necessary. The nfs ad hoc code is built in, but smbfs and ncpfs
48
have a separate mount program. In order to make it possible to
49
treat all types in a uniform way, mount will execute the program
51
All of the filesystem types listed there will be tried,
52
except for those that are labeled "nodev" (e.g.,
62
ends in a line with a single * only, mount will read
63
@@ -1368,6 +1370,73 @@
65
Do not use locking. Do not start lockd.
67
+.SH "Mount options for nfs4"
68
+Instead of a textual option string, parsed by the kernel, the
70
+file system expects a binary argument of type
71
+.IR "struct nfs4_mount_data" .
74
+itself parses the following options of the form `tag=value',
75
+and puts them in the structure mentioned:
92
+is accepted but ignored.
93
+Also the following Boolean options, possibly preceded by
106
+Especially useful options include
108
+.B rsize=32768,wsize=32768
109
+This will make your NFS connection faster than with the default
110
+buffer size of 4096.
113
+The program accessing a file on a NFS mounted file system will hang
114
+when the server crashes. The process cannot be interrupted or
115
+killed unless you also specify
117
+When the NFS server is back online the program will continue undisturbed
118
+from where it was. This is probably what you want.
121
+This option allows the kernel to time out if the NFS server is not
122
+responding for some time. The time can be
125
+This timeout value is expressed in tenths of a second.
128
+option might be useful if your NFS server sometimes doesn't respond
129
+or will be rebooted while some process tries to get a file from the server.
130
+Avoid using this option with
132
+or with a short timeout.
134
.SH "Mount options for ntfs"
137
diff -urNad trunk~/mount/mount.c trunk/mount/mount.c
138
--- trunk~/mount/mount.c 2006-05-11 16:24:59.000000000 +0200
139
+++ trunk/mount/mount.c 2006-05-11 16:25:00.000000000 +0200
141
"without support for the type `nfs'"));
148
+ if (!fake && types && streq (types, "nfs4")) {
149
+ mnt_err = nfs4mount(spec, node, &flags, &extra_opts, &mount_opts, bg);
154
+ die (EX_SOFTWARE, _("mount: this version was compiled "
155
+ "without support for the type `nfs4'"));
159
block_signals (SIG_BLOCK);
163
mnt5_res = guess_fstype_and_mount (spec, node, &types, flags & ~MS_NOSYS,
164
diff -urNad trunk~/mount/nfs.5 trunk/mount/nfs.5
165
--- trunk~/mount/nfs.5 2006-01-29 19:00:03.000000000 +0100
166
+++ trunk/mount/nfs.5 2006-05-11 16:25:00.000000000 +0200
169
.TH NFS 5 "20 November 1993" "Linux 0.99" "Linux Programmer's Manual"
171
-nfs \- nfs fstab format and options
172
+nfs \- nfs and nfs4 fstab format and options
177
and the NFS specific options that control
178
the way the filesystem is mounted.
180
-Here is an example from an \fI/etc/fstab\fP file from an NFS mount.
181
+Three different versions of the NFS protocol are
182
+supported by the Linux NFS client:
183
+NFS version 2, NFS version 3, and NFS version 4.
184
+To mount via NFS version 2, use the
186
+file system type and specify
188
+Version 2 is the default protocol version for the
190
+file system type when
192
+is not specified on the mount command.
193
+To mount via NFS version 3, use the
195
+file system type and specify
197
+To mount via NFS version 4, use the
202
+keyword is not supported for the
206
+These file system types share similar mount options;
207
+the differences are listed below.
209
+Here is an example from an \fI/etc/fstab\fP file for an NFSv2 mount
213
.ta 2.5i +0.75i +0.75i +1.0i
214
server:/usr/local/pub /pub nfs rsize=8192,wsize=8192,timeo=14,intr
217
+Here is an example for an NFSv4 mount over TCP using Kerberos
218
+5 mutual authentication.
221
+.ta 2.5i +0.75i +0.75i +1.0i
222
+server:/usr/local/pub /pub nfs4 proto=tcp,sec=krb5,hard,intr
226
+.SS Options for the nfs file system type
229
The number of bytes NFS uses when reading files from an NFS server.
231
Use an alternate RPC version number to contact the
232
mount daemon on the remote host. This option is useful
233
for hosts that can run multiple NFS servers.
234
-The default value is version 1.
235
+The default value depends on which kernel you are using.
238
Use an alternate RPC program number to contact the
240
Use an alternate RPC version number to contact the
241
NFS daemon on the remote host. This option is useful
242
for hosts that can run multiple NFS servers.
243
-The default value is version 2.
244
+The default value depends on which kernel you are using.
247
Disable NFS locking. Do not start lockd.
251
Disable all forms of attribute caching entirely. This extracts a
252
-server performance penalty but it allows two different NFS clients
253
-to get reasonable good results when both clients are actively
254
-writing to common filesystem on the server.
255
+significant performance penalty but it allows two different NFS clients
256
+to get reasonable results when both clients are actively
257
+writing to a common export on the server.
260
+Set the security flavor for this mount to "mode".
261
+The default setting is \f3sec=sys\f1, which uses local
262
+unix uids and gids to authenticate NFS operations (AUTH_SYS).
263
+Other currently supported settings are:
264
+\f3sec=krb5\f1, which uses Kerberos V5 instead of local unix uids
265
+and gids to authenticate users;
266
+\f3sec=krb5i\f1, which uses Kerberos V5 for user authentication
267
+and performs integrity checking of NFS operations using secure
268
+checksums to prevent data tampering; and
269
+\f3sec=krb5p\f1, which uses Kerberos V5 for user authentication
270
+and integrity checking, and encrypts NFS traffic to prevent
271
+traffic sniffing (this is the most secure setting).
272
+Note that there is a performance penalty when using integrity
276
Mount the NFS filesystem using the TCP protocol instead of the
277
@@ -208,6 +261,156 @@
278
All of the non-value options have corresponding nooption forms.
279
For example, nointr means don't allow file operations to be
281
+.SS Options for the nfs4 file system type
284
+The number of bytes NFS uses when reading files from an NFS server.
285
+The default value is dependent on the kernel, currently 4096 bytes.
286
+(However, throughput is improved greatly by asking for
288
+This value is negotiated with the server.
291
+The number of bytes NFS uses when writing files to an NFS server.
292
+The default value is dependent on the kernel, currently 4096 bytes.
293
+(However, throughput is improved greatly by asking for
295
+This value is negotiated with the server.
298
+The value in tenths of a second before sending the
299
+first retransmission after an RPC timeout.
300
+The default value depends on whether
304
+is in effect (see below).
305
+The default value for UDP is 7 tenths of a second.
306
+The default value for TCP is 60 seconds.
307
+After the first timeout,
308
+the timeout is doubled after each successive timeout until a maximum
309
+timeout of 60 seconds is reached or the enough retransmissions
310
+have occured to cause a major timeout. Then, if the filesystem
311
+is hard mounted, each new timeout cascade restarts at twice the
312
+initial value of the previous cascade, again doubling at each
313
+retransmission. The maximum timeout is always 60 seconds.
316
+The number of minor timeouts and retransmissions that must occur before
317
+a major timeout occurs. The default is 5 timeouts for
321
+When a major timeout
322
+occurs, the file operation is either aborted or a "server not responding"
323
+message is printed on the console.
326
+The minimum time in seconds that attributes of a regular file should
327
+be cached before requesting fresh information from a server.
328
+The default is 3 seconds.
331
+The maximum time in seconds that attributes of a regular file can
332
+be cached before requesting fresh information from a server.
333
+The default is 60 seconds.
336
+The minimum time in seconds that attributes of a directory should
337
+be cached before requesting fresh information from a server.
338
+The default is 30 seconds.
341
+The maximum time in seconds that attributes of a directory can
342
+be cached before requesting fresh information from a server.
343
+The default is 60 seconds.
346
+Using actimeo sets all of
353
+There is no default value.
356
+The number of minutes to retry an NFS mount operation
357
+in the foreground or background before giving up.
358
+The default value is 10000 minutes, which is roughly one week.
361
+The numeric value of the port to connect to the NFS server on.
362
+If the port number is 0 (the default) then query the
363
+remote host's portmapper for the port number to use.
364
+If the remote host's NFS daemon is not registered with
365
+its portmapper, the standard NFS port number 2049 is
369
+Mount the NFS filesystem using a specific network protocol
370
+instead of the default UDP protocol.
371
+Many NFS version 4 servers only support TCP.
372
+Valid protocol types are
378
+On a multi-homed client, this
379
+causes the client to use a specific callback address when
380
+communicating with an NFS version 4 server.
381
+This option is currently ignored.
384
+Same as \f3sec=mode\f1 for the nfs filesystem type (see above).
387
+If an NFS mount attempt times out, retry the mount
389
+After a mount operation is backgrounded, all subsequent mounts
390
+on the same NFS server will be backgrounded immediately, without
391
+first attempting the mount.
392
+A missing mount point is treated as a timeout,
393
+to allow for nested NFS mounts.
396
+If the first NFS mount attempt times out, retry the mount
398
+This is the complement of the
400
+option, and also the default behavior.
403
+If an NFS file operation has a major timeout then report an I/O error to
404
+the calling program.
405
+The default is to continue retrying NFS file operations indefinitely.
408
+If an NFS file operation has a major timeout then report
409
+"server not responding" on the console and continue retrying indefinitely.
410
+This is the default.
413
+If an NFS file operation has a major timeout and it is hard mounted,
414
+then allow signals to interupt the file operation and cause it to
415
+return EINTR to the calling program. The default is to not
416
+allow file operations to be interrupted.
419
+Suppress the retrieval of new attributes when creating a file.
422
+Disable attribute caching, and force synchronous writes.
424
+server performance penalty but it allows two different NFS clients
425
+to get reasonable good results when both clients are actively
426
+writing to common filesystem on the server.
428
+All of the non-value options have corresponding nooption forms.
429
+For example, nointr means don't allow file operations to be
434
diff -urNad trunk~/mount/nfs4_mount.h trunk/mount/nfs4_mount.h
435
--- trunk~/mount/nfs4_mount.h 1970-01-01 01:00:00.000000000 +0100
436
+++ trunk/mount/nfs4_mount.h 2006-05-11 16:25:00.000000000 +0200
438
+#ifndef _LINUX_NFS4_MOUNT_H
439
+#define _LINUX_NFS4_MOUNT_H
442
+ * linux/include/linux/nfs4_mount.h
444
+ * Copyright (C) 2002 Trond Myklebust
446
+ * structure passed from user-space to kernel-space during an nfsv4 mount
450
+ * WARNING! Do not delete or change the order of these fields. If
451
+ * a new field is required then add it to the end. The version field
452
+ * tracks which fields are present. This will ensure some measure of
453
+ * mount-to-kernel version compatibility. Some of these aren't used yet
454
+ * but here they are anyway.
456
+#define NFS4_MOUNT_VERSION 1
463
+struct nfs4_mount_data {
464
+ int version; /* 1 */
469
+ int retrans; /* 1 */
470
+ int acregmin; /* 1 */
471
+ int acregmax; /* 1 */
472
+ int acdirmin; /* 1 */
473
+ int acdirmax; /* 1 */
475
+ /* see the definition of 'struct clientaddr4' in RFC3010 */
476
+ struct nfs_string client_addr; /* 1 */
479
+ struct nfs_string mnt_path; /* 1 */
481
+ /* Server details */
482
+ struct nfs_string hostname; /* 1 */
483
+ /* Server IP address */
484
+ unsigned int host_addrlen; /* 1 */
485
+ struct sockaddr* host_addr; /* 1 */
487
+ /* Transport protocol to use */
490
+ /* Pseudo-flavours to use for authentication. See RFC2623 */
491
+ int auth_flavourlen; /* 1 */
492
+ int *auth_flavours; /* 1 */
495
+/* bits in the flags field */
496
+/* Note: the fields that correspond to existing NFSv2/v3 mount options
497
+ * should mirror the values from include/linux/nfs_mount.h
500
+#define NFS4_MOUNT_SOFT 0x0001 /* 1 */
501
+#define NFS4_MOUNT_INTR 0x0002 /* 1 */
502
+#define NFS4_MOUNT_NOCTO 0x0010 /* 1 */
503
+#define NFS4_MOUNT_NOAC 0x0020 /* 1 */
504
+#define NFS4_MOUNT_STRICTLOCK 0x1000 /* 1 */
505
+#define NFS4_MOUNT_FLAGMASK 0xFFFF
507
+/* pseudoflavors: */
509
+#define RPC_AUTH_GSS_KRB5 390003
510
+#define RPC_AUTH_GSS_KRB5I 390004
511
+#define RPC_AUTH_GSS_KRB5P 390005
512
+#define RPC_AUTH_GSS_LKEY 390006
513
+#define RPC_AUTH_GSS_LKEYI 390007
514
+#define RPC_AUTH_GSS_LKEYP 390008
515
+#define RPC_AUTH_GSS_SPKM 390009
516
+#define RPC_AUTH_GSS_SPKMI 390010
517
+#define RPC_AUTH_GSS_SPKMP 390011
520
diff -urNad trunk~/mount/nfs4mount.c trunk/mount/nfs4mount.c
521
--- trunk~/mount/nfs4mount.c 1970-01-01 01:00:00.000000000 +0100
522
+++ trunk/mount/nfs4mount.c 2006-05-11 16:25:00.000000000 +0200
525
+ * nfs4mount.c -- Linux NFS mount
526
+ * Copyright (C) 2002 Trond Myklebust <trond.myklebust@fys.uio.no>
528
+ * This program is free software; you can redistribute it and/or modify
529
+ * it under the terms of the GNU General Public License as published by
530
+ * the Free Software Foundation; either version 2, or (at your option)
531
+ * any later version.
533
+ * This program is distributed in the hope that it will be useful,
534
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
535
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
536
+ * GNU General Public License for more details.
538
+ * Note: this file based on the original nfsmount.c
541
+#include "../defines.h" /* for HAVE_rpcsvc_nfs_prot_h and HAVE_inet_aton */
543
+#include <linux/posix_types.h>
544
+#include <asm/posix_types.h>
556
+#include <sys/socket.h>
557
+#include <sys/time.h>
558
+#include <sys/utsname.h>
559
+#include <sys/stat.h>
560
+#include <netinet/in.h>
561
+#include <arpa/inet.h>
562
+#include <rpc/auth.h>
563
+#ifdef HAVE_rpcsvc_nfs_prot_h
564
+#include <rpcsvc/nfs_prot.h>
566
+#include <linux/nfs.h>
567
+#define nfsstat nfs_stat
570
+#include "sundries.h"
572
+#include "mount_constants.h"
573
+#include "nfs4_mount.h"
577
+#if defined(VAR_LOCK_DIR)
578
+#define DEFAULT_DIR VAR_LOCK_DIR
580
+#define DEFAULT_DIR "/var/run"
583
+char *IDMAPLCK = DEFAULT_DIR "/rpc.idmapd.pid";
584
+#define idmapd_check() do { \
585
+ if (access(IDMAPLCK, F_OK)) { \
586
+ printf(_("Warning: rpc.idmapd appears not to be running.\n" \
587
+ " All uids will be mapped to the nobody uid.\n")); \
591
+char *GSSDLCK = DEFAULT_DIR "/rpc.gssd";
592
+#define gssd_check() do { \
593
+ if (access(GSSDLCK, F_OK)) { \
594
+ printf(_("Warning: rpc.gssd appears not to be running.\n")); \
599
+#define NFS_PORT 2049
602
+extern int clnt_ping(struct sockaddr_in *, const u_long, const u_long, const u_int);
603
+extern void rpc_strerror(void);
609
+ { "krb5", RPC_AUTH_GSS_KRB5 },
610
+ { "krb5i", RPC_AUTH_GSS_KRB5I },
611
+ { "krb5p", RPC_AUTH_GSS_KRB5P },
612
+ { "lipkey", RPC_AUTH_GSS_LKEY },
613
+ { "lipkey-i", RPC_AUTH_GSS_LKEYI },
614
+ { "lipkey-p", RPC_AUTH_GSS_LKEYP },
615
+ { "spkm3", RPC_AUTH_GSS_SPKM },
616
+ { "spkm3i", RPC_AUTH_GSS_SPKMI },
617
+ { "spkm3p", RPC_AUTH_GSS_SPKMP },
618
+ { "unix", AUTH_UNIX },
619
+ { "sys", AUTH_SYS },
620
+ { "null", AUTH_NULL },
621
+ { "none", AUTH_NONE },
624
+#define FMAPSIZE (sizeof(flav_map)/sizeof(flav_map[0]))
625
+#define MAX_USER_FLAVOUR 16
627
+static int parse_sec(char *sec, int *pseudoflavour)
629
+ int i, num_flavour = 0;
631
+ for (sec = strtok(sec, ":"); sec; sec = strtok(NULL, ":")) {
632
+ if (num_flavour >= MAX_USER_FLAVOUR) {
634
+ _("mount: maximum number of security flavors "
638
+ for (i = 0; i < FMAPSIZE; i++) {
639
+ if (strcmp(sec, flav_map[i].flavour) == 0) {
640
+ pseudoflavour[num_flavour++] = flav_map[i].fnum;
644
+ if (i == FMAPSIZE) {
646
+ _("mount: unknown security type %s\n"), sec);
652
+ _("mount: no security flavors passed to sec= option\n"));
653
+ return num_flavour;
656
+static int parse_devname(char *hostdir, char **hostname, char **dirname)
660
+ if (!(s = strchr(hostdir, ':'))) {
663
+ "directory to mount not in host:dir format\n"));
666
+ *hostname = hostdir;
669
+ /* Ignore all but first hostname in replicated mounts
670
+ until they can be fully supported. (mack@sgi.com) */
671
+ if ((s = strchr(hostdir, ','))) {
674
+ _("mount: warning: "
675
+ "multiple hostnames not supported\n"));
680
+static int fill_ipv4_sockaddr(const char *hostname, struct sockaddr_in *addr)
682
+ struct hostent *hp;
683
+ addr->sin_family = AF_INET;
685
+ if (inet_aton(hostname, &addr->sin_addr))
687
+ if ((hp = gethostbyname(hostname)) == NULL) {
688
+ fprintf(stderr, _("mount: can't get address for %s\n"),
692
+ if (hp->h_length > sizeof(struct in_addr)) {
694
+ _("mount: got bad hp->h_length\n"));
695
+ hp->h_length = sizeof(struct in_addr);
697
+ memcpy(&addr->sin_addr, hp->h_addr, hp->h_length);
701
+static int get_my_ipv4addr(char *ip_addr, int len)
704
+ struct sockaddr_in myaddr;
706
+ if (gethostname(myname, sizeof(myname))) {
707
+ fprintf(stderr, _("mount: can't determine client address\n"));
710
+ if (fill_ipv4_sockaddr(myname, &myaddr))
712
+ snprintf(ip_addr, len, "%s", inet_ntoa(myaddr.sin_addr));
713
+ ip_addr[len-1] = '\0';
717
+int nfs4mount(const char *spec, const char *node, int *flags,
718
+ char **extra_opts, char **mount_opts,
721
+ static struct nfs4_mount_data data;
722
+ static char hostdir[1024];
723
+ static char ip_addr[16] = "127.0.0.1";
724
+ static struct sockaddr_in server_addr;
725
+ static int pseudoflavour[MAX_USER_FLAVOUR];
726
+ int num_flavour = 0;
728
+ char *hostname, *dirname, *old_opts;
729
+ char new_opts[1024];
733
+ int bg, soft, intr;
739
+ if (strlen(spec) >= sizeof(hostdir)) {
740
+ fprintf(stderr, _("mount: "
741
+ "excessively long host:dir argument\n"));
744
+ strcpy(hostdir, spec);
745
+ if (parse_devname(hostdir, &hostname, &dirname))
748
+ if (fill_ipv4_sockaddr(hostname, &server_addr))
750
+ if (get_my_ipv4addr(ip_addr, sizeof(ip_addr)))
753
+ /* add IP address to mtab options for use when unmounting */
754
+ s = inet_ntoa(server_addr.sin_addr);
755
+ old_opts = *extra_opts;
758
+ if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) {
759
+ fprintf(stderr, _("mount: "
760
+ "excessively long option argument\n"));
763
+ snprintf(new_opts, sizeof(new_opts), "%s%saddr=%s",
764
+ old_opts, *old_opts ? "," : "", s);
765
+ *extra_opts = xstrdup(new_opts);
767
+ /* Set default options.
768
+ * rsize/wsize and timeo are left 0 in order to
769
+ * let the kernel decide.
771
+ memset(&data, 0, sizeof(data));
774
+ data.acregmax = 60;
775
+ data.acdirmin = 30;
776
+ data.acdirmax = 60;
777
+ data.proto = IPPROTO_TCP;
781
+ intr = NFS4_MOUNT_INTR;
784
+ retry = 10000; /* 10000 minutes ~ 1 week */
787
+ * NFSv4 specifies that the default port should be 2049
789
+ server_addr.sin_port = htons(NFS_PORT);
791
+ /* parse options */
793
+ for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {
794
+ if ((opteq = strchr(opt, '='))) {
795
+ val = atoi(opteq + 1);
797
+ if (!strcmp(opt, "rsize"))
799
+ else if (!strcmp(opt, "wsize"))
801
+ else if (!strcmp(opt, "timeo"))
803
+ else if (!strcmp(opt, "retrans"))
804
+ data.retrans = val;
805
+ else if (!strcmp(opt, "acregmin"))
806
+ data.acregmin = val;
807
+ else if (!strcmp(opt, "acregmax"))
808
+ data.acregmax = val;
809
+ else if (!strcmp(opt, "acdirmin"))
810
+ data.acdirmin = val;
811
+ else if (!strcmp(opt, "acdirmax"))
812
+ data.acdirmax = val;
813
+ else if (!strcmp(opt, "actimeo")) {
814
+ data.acregmin = val;
815
+ data.acregmax = val;
816
+ data.acdirmin = val;
817
+ data.acdirmax = val;
819
+ else if (!strcmp(opt, "retry"))
821
+ else if (!strcmp(opt, "port"))
822
+ server_addr.sin_port = htons(val);
823
+ else if (!strcmp(opt, "proto")) {
824
+ if (!strncmp(opteq+1, "tcp", 3))
825
+ data.proto = IPPROTO_TCP;
826
+ else if (!strncmp(opteq+1, "udp", 3))
827
+ data.proto = IPPROTO_UDP;
829
+ printf(_("Warning: Unrecognized proto= option.\n"));
830
+ } else if (!strcmp(opt, "clientaddr")) {
831
+ if (strlen(opteq+1) >= sizeof(ip_addr))
832
+ printf(_("Invalid client address %s"),
834
+ strncpy(ip_addr,opteq+1, sizeof(ip_addr));
835
+ ip_addr[sizeof(ip_addr)-1] = '\0';
836
+ } else if (!strcmp(opt, "sec")) {
837
+ num_flavour = parse_sec(opteq+1, pseudoflavour);
840
+ } else if (!strcmp(opt, "addr")) {
843
+ printf(_("unknown nfs mount parameter: "
844
+ "%s=%d\n"), opt, val);
849
+ if (!strncmp(opt, "no", 2)) {
853
+ if (!strcmp(opt, "bg"))
855
+ else if (!strcmp(opt, "fg"))
857
+ else if (!strcmp(opt, "soft"))
859
+ else if (!strcmp(opt, "hard"))
861
+ else if (!strcmp(opt, "intr"))
863
+ else if (!strcmp(opt, "cto"))
865
+ else if (!strcmp(opt, "ac"))
869
+ printf(_("unknown nfs mount option: "
870
+ "%s%s\n"), val ? "" : "no", opt);
877
+ data.flags = (soft ? NFS4_MOUNT_SOFT : 0)
878
+ | (intr ? NFS4_MOUNT_INTR : 0)
879
+ | (nocto ? NFS4_MOUNT_NOCTO : 0)
880
+ | (noac ? NFS4_MOUNT_NOAC : 0);
883
+ * Give a warning if the rpc.idmapd daemon is not running
887
+ if (num_flavour == 0)
888
+ pseudoflavour[num_flavour++] = AUTH_UNIX;
891
+ * ditto with rpc.gssd daemon
895
+ data.auth_flavourlen = num_flavour;
896
+ data.auth_flavours = pseudoflavour;
898
+ data.client_addr.data = ip_addr;
899
+ data.client_addr.len = strlen(ip_addr);
901
+ data.mnt_path.data = dirname;
902
+ data.mnt_path.len = strlen(dirname);
904
+ data.hostname.data = hostname;
905
+ data.hostname.len = strlen(hostname);
906
+ data.host_addr = (struct sockaddr *)&server_addr;
907
+ data.host_addrlen = sizeof(server_addr);
909
+#ifdef NFS_MOUNT_DEBUG
910
+ printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
911
+ data.rsize, data.wsize, data.timeo, data.retrans);
912
+ printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n",
913
+ data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);
914
+ printf("port = %d, bg = %d, retry = %d, flags = %.8x\n",
915
+ ntohs(server_addr.sin_port), bg, retry, data.flags);
916
+ printf("soft = %d, intr = %d, nocto = %d, noac = %d\n",
917
+ (data.flags & NFS4_MOUNT_SOFT) != 0,
918
+ (data.flags & NFS4_MOUNT_INTR) != 0,
919
+ (data.flags & NFS4_MOUNT_NOCTO) != 0,
920
+ (data.flags & NFS4_MOUNT_NOAC) != 0);
922
+ if (num_flavour > 0) {
926
+ for (pf_cnt = 0; pf_cnt < num_flavour; pf_cnt++) {
927
+ for (i = 0; i < FMAPSIZE; i++) {
928
+ if (flav_map[i].fnum == pseudoflavour[pf_cnt]) {
929
+ printf("%s", flav_map[i].flavour);
933
+ printf("%s", (pf_cnt < num_flavour-1) ? ":" : "\n");
936
+ printf("proto = %s\n", (data.proto == IPPROTO_TCP) ? "tcp" : "udp");
939
+ data.version = NFS4_MOUNT_VERSION;
941
+ clnt_ping(&server_addr, NFS_PROGRAM, 4, data.proto);
942
+ if (rpc_createerr.cf_stat) {
943
+ fprintf(stderr, "mount to NFS server '%s' failed.\n", data.hostname.data);
947
+ *mount_opts = (char *) &data;
957
diff -urNad trunk~/mount/nfs_mount4.h trunk/mount/nfs_mount4.h
958
--- trunk~/mount/nfs_mount4.h 2006-01-29 19:00:03.000000000 +0100
959
+++ trunk/mount/nfs_mount4.h 2006-05-11 16:25:00.000000000 +0200
961
* so it is easiest to ignore the kernel altogether (at compile time).
964
-#define NFS_MOUNT_VERSION 4
965
+#define NFS_MOUNT_VERSION 6
966
+#define NFS_MAX_CONTEXT_LEN 256
973
unsigned int bsize; /* 3 */
974
struct nfs3_fh root; /* 4 */
975
+ int pseudoflavor; /* 5 */
976
+ char context[NFS_MAX_CONTEXT_LEN + 1]; /* 6 */
980
/* bits in the flags field */
982
#define NFS_MOUNT_KERBEROS 0x0100 /* 3 */
983
#define NFS_MOUNT_NONLM 0x0200 /* 3 */
984
#define NFS_MOUNT_BROKEN_SUID 0x0400 /* 4 */
985
+#define NFS_MOUNT_SECFLAVOUR 0x2000 /* 5 */
987
+/* security pseudoflavors */
989
+#ifndef AUTH_GSS_KRB5
990
+#define AUTH_GSS_KRB5 390003
991
+#define AUTH_GSS_KRB5I 390004
992
+#define AUTH_GSS_KRB5P 390005
993
+#define AUTH_GSS_LKEY 390006
994
+#define AUTH_GSS_LKEYI 390007
995
+#define AUTH_GSS_LKEYP 390008
996
+#define AUTH_GSS_SPKM 390009
997
+#define AUTH_GSS_SPKMI 390010
998
+#define AUTH_GSS_SPKMP 390011
1001
diff -urNad trunk~/mount/nfsmount.c trunk/mount/nfsmount.c
1002
--- trunk~/mount/nfsmount.c 2006-01-29 19:00:06.000000000 +0100
1003
+++ trunk/mount/nfsmount.c 2006-05-11 16:25:00.000000000 +0200
1006
#include "../defines.h" /* for HAVE_rpcsvc_nfs_prot_h and HAVE_inet_aton */
1012
@@ -72,11 +73,121 @@
1013
#define NFS_FHSIZE 32
1016
+#define MNT_SENDBUFSIZE ((u_int)2048)
1017
+#define MNT_RECVBUFSIZE ((u_int)1024)
1019
static char *nfs_strerror(int stat);
1021
#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
1023
#define MAX_NFSPROT ((nfs_mount_version >= 4) ? 3 : 2)
1024
+#define MAX_MNTPROT ((nfs_mount_version >= 4) ? 3 : 2)
1025
+#define HAVE_RELIABLE_TCP (nfs_mount_version >= 4)
1027
+#ifndef HAVE_inet_aton
1028
+#define inet_aton(a,b) (0)
1031
+typedef dirpath mnt2arg_t;
1032
+typedef dirpath mnt3arg_t;
1033
+typedef dirpath mntarg_t;
1035
+typedef struct fhstatus mnt2res_t;
1036
+typedef struct mountres3 mnt3res_t;
1044
+ struct sockaddr_in saddr;
1048
+/* RPC call timeout values */
1049
+static const struct timeval TIMEOUT = { 20, 0 };
1050
+static const struct timeval RETRY_TIMEOUT = { 3, 0 };
1052
+static int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp);
1054
+int clnt_ping(struct sockaddr_in *, const u_long, const u_long, const u_int);
1056
+/* Convert RPC errors into strings */
1057
+void rpc_strerror(void)
1059
+ int cf_stat = rpc_createerr.cf_stat;
1060
+ int cf_errno = rpc_createerr.cf_error.re_errno;
1061
+ char *ptr, *estr = clnt_sperrno(cf_stat);
1064
+ if ((ptr = index(estr, ':')))
1067
+ fprintf(stderr, "RPC Error: %d (%s )\n", cf_stat, estr);
1068
+ if (cf_stat == RPC_SYSTEMERROR)
1069
+ fprintf(stderr, "System Error: %d (%s)\n", cf_errno, strerror(cf_errno));
1073
+/* Define the order in which to probe for UDP/TCP services */
1074
+static const u_int *
1075
+proto_probelist(const int use_tcp)
1077
+ static const u_int probe_both[] = { IPPROTO_TCP, IPPROTO_UDP, 0 };
1078
+ static const u_int probe_udponly[] = { IPPROTO_UDP, 0 };
1080
+ return probe_both;
1081
+ return probe_udponly;
1084
+/* Define the order in which NFS versions are probed on portmapper */
1085
+static const u_long *
1086
+nfs_probelist(const int vers)
1088
+ static const u_long nfs2_probe[] = { 2, 0};
1089
+ static const u_long nfs3_probe[] = { 3, 2, 0};
1092
+ return nfs3_probe;
1094
+ return nfs2_probe;
1098
+/* Define the order in which Mountd versions are probed on portmapper */
1099
+static const u_long *
1100
+mnt_probelist(const int vers)
1102
+ static const u_long mnt1_probe[] = { 1, 2, 0 };
1103
+ static const u_long mnt3_probe[] = { 3, 1, 2, 0 };
1106
+ return mnt3_probe;
1108
+ return mnt1_probe;
1112
+/* Map an NFS version into the corresponding Mountd version */
1114
+nfsvers_to_mnt(const u_long vers)
1116
+ static const u_long nfs_to_mnt[] = { 0, 0, 1, 3 };
1118
+ return nfs_to_mnt[vers];
1122
+/* Map a Mountd version into the corresponding NFS version */
1124
+mntvers_to_nfs(const u_long vers)
1126
+ static const u_long mnt_to_nfs[] = { 0, 2, 2, 3 };
1128
+ return mnt_to_nfs[vers];
1133
linux_version_code(void) {
1134
@@ -102,123 +213,632 @@
1135
* NFS_MOUNT_VERSION: these nfsmount sources at compile time
1136
* nfs_mount_version: version this source and running kernel can handle
1138
+static int nfs_mount_version = NFS_MOUNT_VERSION;
1141
find_kernel_nfs_mount_version(void) {
1142
static int kernel_version = -1;
1143
- int nfs_mount_version = NFS_MOUNT_VERSION;
1144
+ int mnt_version = NFS_MOUNT_VERSION;
1146
if (kernel_version == -1)
1147
kernel_version = linux_version_code();
1149
if (kernel_version) {
1150
if (kernel_version < MAKE_VERSION(2,1,32))
1151
- nfs_mount_version = 1;
1153
else if (kernel_version < MAKE_VERSION(2,2,18))
1154
- nfs_mount_version = 3;
1156
else if (kernel_version < MAKE_VERSION(2,3,0))
1157
- nfs_mount_version = 4; /* since 2.2.18pre9 */
1158
+ mnt_version = 4; /* since 2.2.18pre9 */
1159
else if (kernel_version < MAKE_VERSION(2,3,99))
1160
- nfs_mount_version = 3;
1162
+ else if (kernel_version < MAKE_VERSION(2,6,3))
1165
- nfs_mount_version = 4; /* since 2.3.99pre4 */
1168
- if (nfs_mount_version > NFS_MOUNT_VERSION)
1169
- nfs_mount_version = NFS_MOUNT_VERSION;
1170
- return nfs_mount_version;
1171
+ if (mnt_version > NFS_MOUNT_VERSION)
1172
+ mnt_version = NFS_MOUNT_VERSION;
1173
+ return mnt_version;
1176
-static struct pmap *
1177
-get_mountport(struct sockaddr_in *server_addr,
1178
- long unsigned prog,
1179
- long unsigned version,
1180
- long unsigned proto,
1181
- long unsigned port,
1182
- int nfs_mount_version)
1184
+nfs_gethostbyname(const char *hostname, struct sockaddr_in *saddr)
1186
- struct pmaplist *pmap;
1187
- static struct pmap p = {0, 0, 0, 0};
1188
+ struct hostent *hp;
1190
- if (version > MAX_NFSPROT)
1191
- version = MAX_NFSPROT;
1195
- p.pm_vers = version;
1196
- p.pm_prot = proto;
1198
+ saddr->sin_family = AF_INET;
1199
+ if (!inet_aton(hostname, &saddr->sin_addr)) {
1200
+ if ((hp = gethostbyname(hostname)) == NULL) {
1201
+ fprintf(stderr, _("mount: can't get address for %s\n"),
1205
+ if (hp->h_length > sizeof(*saddr)) {
1207
+ _("mount: got bad hp->h_length\n"));
1208
+ hp->h_length = sizeof(*saddr);
1210
+ memcpy(&saddr->sin_addr, hp->h_addr, hp->h_length);
1216
- server_addr->sin_port = PMAPPORT;
1217
- pmap = pmap_getmaps(server_addr);
1219
+ * Sigh... pmap_getport() doesn't actually check the version number.
1220
+ * In order to make sure that the server actually supports the service
1221
+ * we're requesting, we open and RPC client, and fire off a NULL
1225
+clnt_ping(struct sockaddr_in *saddr, const u_long prog, const u_long vers,
1228
+ CLIENT *clnt=NULL;
1230
+ static char clnt_res;
1233
- if (pmap->pml_map.pm_prog != prog)
1235
- if (!version && p.pm_vers > pmap->pml_map.pm_vers)
1237
- if (version > 2 && pmap->pml_map.pm_vers != version)
1239
- if (version && version <= 2 && pmap->pml_map.pm_vers > 2)
1241
- if (pmap->pml_map.pm_vers > MAX_NFSPROT ||
1242
- (proto && p.pm_prot && pmap->pml_map.pm_prot != proto) ||
1243
- (port && pmap->pml_map.pm_port != port))
1245
- memcpy(&p, &pmap->pml_map, sizeof(p));
1247
- pmap = pmap->pml_next;
1248
+ rpc_createerr.cf_stat = stat = 0;
1249
+ sock = RPC_ANYSOCK;
1252
+ clnt = clntudp_bufcreate(saddr, prog, vers,
1253
+ RETRY_TIMEOUT, &sock,
1254
+ RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
1257
+ clnt = clnttcp_create(saddr, prog, vers, &sock,
1258
+ RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
1264
- p.pm_vers = MOUNTVERS;
1266
- p.pm_prot = IPPROTO_TCP;
1269
- p.pm_port = pmap_getport(server_addr, p.pm_prog, p.pm_vers,
1273
+ memset(&clnt_res, 0, sizeof(clnt_res));
1274
+ stat = clnt_call(clnt, NULLPROC,
1275
+ (xdrproc_t)xdr_void, (caddr_t)NULL,
1276
+ (xdrproc_t)xdr_void, (caddr_t)&clnt_res,
1278
+ clnt_destroy(clnt);
1280
+ if (stat != RPC_PROGVERSMISMATCH)
1288
+ * Use the portmapper to discover whether or not the service we want is
1289
+ * available. The lists 'versions' and 'protos' define ordered sequences
1290
+ * of service versions and udp/tcp protocols to probe for.
1293
+probe_port(clnt_addr_t *server,
1294
+ const u_long *versions,
1295
+ const u_int *protos)
1297
+ struct sockaddr_in *saddr = &server->saddr;
1298
+ struct pmap *pmap = &server->pmap;
1299
+ const u_long prog = pmap->pm_prog,
1300
+ vers = pmap->pm_vers,
1302
+ const u_int prot = (u_int)pmap->pm_prot,
1304
+ const u_short port = (u_short) pmap->pm_port;
1306
+ p_prot = prot ? &prot : protos;
1307
+ p_vers = vers ? &vers : versions;
1308
+ rpc_createerr.cf_stat = 0;
1310
+ saddr->sin_port = htons(PMAPPORT);
1311
+ p_port = pmap_getport(saddr, prog, *p_vers, *p_prot);
1313
+ if (!port || port == p_port) {
1314
+ saddr->sin_port = htons(port);
1315
+ if (clnt_ping(saddr, prog, *p_vers, *p_prot))
1318
+ } else if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED)
1325
+ if (vers || !*++p_vers)
1331
+ pmap->pm_vers = *p_vers;
1333
+ pmap->pm_prot = *p_prot;
1335
+ pmap->pm_port = p_port;
1336
+ rpc_createerr.cf_stat = 0;
1341
+probe_nfsport(clnt_addr_t *nfs_server)
1343
+ const struct pmap *pmap = &nfs_server->pmap;
1344
+ const u_long *probe_vers;
1345
+ const u_int *probe_prot;
1347
+ if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
1349
+ probe_vers = nfs_probelist(MAX_NFSPROT);
1350
+ probe_prot = proto_probelist(HAVE_RELIABLE_TCP);
1351
+ return probe_port(nfs_server, probe_vers, probe_prot);
1355
+probe_mntport(clnt_addr_t *mnt_server)
1357
+ const struct pmap *pmap = &mnt_server->pmap;
1358
+ const u_long *probe_vers;
1359
+ const u_int *probe_prot;
1361
+ if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
1363
+ probe_vers = mnt_probelist(MAX_MNTPROT);
1364
+ probe_prot = proto_probelist(HAVE_RELIABLE_TCP);
1365
+ return probe_port(mnt_server, probe_vers, probe_prot);
1369
+probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
1371
+ struct pmap *nfs_pmap = &nfs_server->pmap;
1372
+ struct pmap *mnt_pmap = &mnt_server->pmap;
1373
+ struct pmap save_nfs, save_mnt;
1375
+ const u_long *probe_vers;
1377
+ if (mnt_pmap->pm_vers && !nfs_pmap->pm_vers)
1378
+ nfs_pmap->pm_vers = mntvers_to_nfs(mnt_pmap->pm_vers);
1379
+ else if (nfs_pmap->pm_vers && !mnt_pmap->pm_vers)
1380
+ mnt_pmap->pm_vers = nfsvers_to_mnt(nfs_pmap->pm_vers);
1381
+ if (nfs_pmap->pm_vers)
1382
+ goto version_fixed;
1383
+ memcpy(&save_nfs, nfs_pmap, sizeof(save_nfs));
1384
+ memcpy(&save_mnt, mnt_pmap, sizeof(save_mnt));
1385
+ for (probe_vers = mnt_probelist(MAX_MNTPROT); *probe_vers; probe_vers++) {
1386
+ nfs_pmap->pm_vers = mntvers_to_nfs(*probe_vers);
1387
+ if ((res = probe_nfsport(nfs_server) != 0)) {
1388
+ mnt_pmap->pm_vers = *probe_vers;
1389
+ if ((res = probe_mntport(mnt_server)) != 0)
1391
+ memcpy(mnt_pmap, &save_mnt, sizeof(*mnt_pmap));
1393
+ if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED)
1395
+ memcpy(nfs_pmap, &save_nfs, sizeof(*nfs_pmap));
1400
+ if (!probe_nfsport(nfs_server))
1402
+ return probe_mntport(mnt_server);
1406
+mnt_openclnt(clnt_addr_t *mnt_server, int *msock, const int report_errs)
1408
+ struct sockaddr_in *mnt_saddr = &mnt_server->saddr;
1409
+ struct pmap *mnt_pmap = &mnt_server->pmap;
1412
+ /* contact the mount daemon via TCP */
1413
+ mnt_saddr->sin_port = htons((u_short)mnt_pmap->pm_port);
1414
+ *msock = RPC_ANYSOCK;
1416
+ switch (mnt_pmap->pm_prot) {
1418
+ clnt = clntudp_bufcreate(mnt_saddr,
1419
+ mnt_pmap->pm_prog, mnt_pmap->pm_vers,
1420
+ RETRY_TIMEOUT, msock,
1421
+ MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
1424
+ clnt = clnttcp_create(mnt_saddr,
1425
+ mnt_pmap->pm_prog, mnt_pmap->pm_vers,
1427
+ MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
1434
+ /* try to mount hostname:dirname */
1435
+ clnt->cl_auth = authunix_create_default();
1439
+ clnt_pcreateerror("mount");
1445
+mnt_closeclnt(CLIENT *clnt, int msock)
1447
+ auth_destroy(clnt->cl_auth);
1448
+ clnt_destroy(clnt);
1452
+static inline enum clnt_stat
1453
+nfs3_mount(CLIENT *clnt, mnt3arg_t *mnt3arg, mnt3res_t *mnt3res)
1455
+ return clnt_call(clnt, MOUNTPROC3_MNT,
1456
+ (xdrproc_t) xdr_dirpath, (caddr_t) mnt3arg,
1457
+ (xdrproc_t) xdr_mountres3, (caddr_t) mnt3res,
1461
+static inline enum clnt_stat
1462
+nfs2_mount(CLIENT *clnt, mnt2arg_t *mnt2arg, mnt2res_t *mnt2res)
1464
+ return clnt_call(clnt, MOUNTPROC_MNT,
1465
+ (xdrproc_t) xdr_dirpath, (caddr_t) mnt2arg,
1466
+ (xdrproc_t) xdr_fhstatus, (caddr_t) mnt2res,
1471
+nfs_call_mount(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server,
1472
+ mntarg_t *mntarg, mntres_t *mntres, const int report_errs)
1475
+ enum clnt_stat stat;
1478
+ if (!probe_bothports(mnt_server, nfs_server)) {
1479
+ if (report_errs) {
1480
+ fprintf(stderr, "mount to NFS server '%s' failed",
1481
+ *nfs_server->hostname);
1482
+ if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED) {
1483
+ fprintf(stderr, ": server is down.\n");
1484
+ } else if (nfs_server->pmap.pm_prot) {
1485
+ fprintf(stderr, ": possible invalid protocol.\n");
1486
+ } else if (nfs_server->pmap.pm_port) {
1487
+ fprintf(stderr, ": possible invalid port.\n");
1489
+ fprintf(stderr, ".\n");
1498
+ clnt = mnt_openclnt(mnt_server, &msock, report_errs);
1501
+ /* make pointers in xdr_mountres3 NULL so
1502
+ * that xdr_array allocates memory for us
1504
+ memset(mntres, 0, sizeof(*mntres));
1505
+ switch (mnt_server->pmap.pm_vers) {
1507
+ stat = nfs3_mount(clnt, mntarg, &mntres->nfsv3);
1511
+ stat = nfs2_mount(clnt, mntarg, &mntres->nfsv2);
1516
+ if (stat != RPC_SUCCESS && report_errs)
1517
+ clnt_perror(clnt, "mount");
1518
+ mnt_closeclnt(clnt, msock);
1519
+ if (stat == RPC_SUCCESS)
1526
+parse_options(char *old_opts, struct nfs_mount_data *data,
1527
+ int *bg, int *retry, clnt_addr_t *mnt_server,
1528
+ clnt_addr_t *nfs_server, char *new_opts, const int opt_size)
1530
+ struct sockaddr_in *mnt_saddr = &mnt_server->saddr;
1531
+ struct pmap *mnt_pmap = &mnt_server->pmap;
1532
+ struct pmap *nfs_pmap = &nfs_server->pmap;
1534
+ char *opt, *opteq;
1535
+ char *mounthost = NULL;
1541
+ len = strlen(new_opts);
1542
+ for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {
1543
+ if (strlen(opt) >= sizeof(cbuf))
1544
+ goto bad_parameter;
1545
+ if ((opteq = strchr(opt, '=')) && isdigit(opteq[1])) {
1546
+ int val = atoi(opteq + 1);
1548
+/* printf("opt=%s\n", opt); */
1549
+ if (!strcmp(opt, "rsize"))
1550
+ data->rsize = val;
1551
+ else if (!strcmp(opt, "wsize"))
1552
+ data->wsize = val;
1553
+ else if (!strcmp(opt, "timeo"))
1554
+ data->timeo = val;
1555
+ else if (!strcmp(opt, "retrans"))
1556
+ data->retrans = val;
1557
+ else if (!strcmp(opt, "acregmin"))
1558
+ data->acregmin = val;
1559
+ else if (!strcmp(opt, "acregmax"))
1560
+ data->acregmax = val;
1561
+ else if (!strcmp(opt, "acdirmin"))
1562
+ data->acdirmin = val;
1563
+ else if (!strcmp(opt, "acdirmax"))
1564
+ data->acdirmax = val;
1565
+ else if (!strcmp(opt, "actimeo")) {
1566
+ data->acregmin = val;
1567
+ data->acregmax = val;
1568
+ data->acdirmin = val;
1569
+ data->acdirmax = val;
1571
+ else if (!strcmp(opt, "retry"))
1573
+ else if (!strcmp(opt, "port"))
1574
+ nfs_pmap->pm_port = val;
1575
+ else if (!strcmp(opt, "mountport"))
1576
+ mnt_pmap->pm_port = val;
1577
+ else if (!strcmp(opt, "mountprog"))
1578
+ mnt_pmap->pm_prog = val;
1579
+ else if (!strcmp(opt, "mountvers"))
1580
+ mnt_pmap->pm_vers = val;
1581
+ else if (!strcmp(opt, "mounthost"))
1582
+ mounthost=xstrndup(opteq+1, strcspn(opteq+1," \t\n\r,"));
1583
+ else if (!strcmp(opt, "nfsprog"))
1584
+ nfs_pmap->pm_prog = val;
1585
+ else if (!strcmp(opt, "nfsvers") ||
1586
+ !strcmp(opt, "vers")) {
1587
+ nfs_pmap->pm_vers = val;
1589
+#if NFS_MOUNT_VERSION >= 2
1590
+ } else if (!strcmp(opt, "namlen")) {
1591
+ if (nfs_mount_version >= 2)
1592
+ data->namlen = val;
1594
+ goto bad_parameter;
1597
-#define MOUNTPORT 635
1598
- /* HJLu wants to remove all traces of the old default port.
1599
- Are there still people running a mount RPC service on this
1600
- port without having a portmapper? */
1602
- p.pm_port = MOUNTPORT;
1603
+ } else if (!strcmp(opt, "addr")) {
1606
+ } else if (!sloppy)
1607
+ goto bad_parameter;
1608
+ sprintf(cbuf, "%s=%s,", opt, opteq+1);
1609
+ } else if (opteq) {
1611
+ if (!strcmp(opt, "proto")) {
1612
+ if (!strcmp(opteq+1, "udp")) {
1613
+ nfs_pmap->pm_prot = IPPROTO_UDP;
1614
+#if NFS_MOUNT_VERSION >= 2
1615
+ data->flags &= ~NFS_MOUNT_TCP;
1616
+ } else if (!strcmp(opteq+1, "tcp") &&
1617
+ nfs_mount_version > 2) {
1618
+ nfs_pmap->pm_prot = IPPROTO_TCP;
1619
+ data->flags |= NFS_MOUNT_TCP;
1622
+ } else if (!sloppy)
1623
+ goto bad_parameter;
1624
+#if NFS_MOUNT_VERSION >= 5
1625
+ } else if (!strcmp(opt, "sec")) {
1626
+ char *secflavor = opteq+1;
1627
+ /* see RFC 2623 */
1628
+ if (nfs_mount_version < 5) {
1629
+ printf(_("Warning: ignoring sec=%s option\n"), secflavor);
1631
+ } else if (!strcmp(secflavor, "sys"))
1632
+ data->pseudoflavor = AUTH_SYS;
1633
+ else if (!strcmp(secflavor, "krb5"))
1634
+ data->pseudoflavor = AUTH_GSS_KRB5;
1635
+ else if (!strcmp(secflavor, "krb5i"))
1636
+ data->pseudoflavor = AUTH_GSS_KRB5I;
1637
+ else if (!strcmp(secflavor, "krb5p"))
1638
+ data->pseudoflavor = AUTH_GSS_KRB5P;
1639
+ else if (!strcmp(secflavor, "lipkey"))
1640
+ data->pseudoflavor = AUTH_GSS_LKEY;
1641
+ else if (!strcmp(secflavor, "lipkey-i"))
1642
+ data->pseudoflavor = AUTH_GSS_LKEYI;
1643
+ else if (!strcmp(secflavor, "lipkey-p"))
1644
+ data->pseudoflavor = AUTH_GSS_LKEYP;
1645
+ else if (!strcmp(secflavor, "spkm3"))
1646
+ data->pseudoflavor = AUTH_GSS_SPKM;
1647
+ else if (!strcmp(secflavor, "spkm3i"))
1648
+ data->pseudoflavor = AUTH_GSS_SPKMI;
1649
+ else if (!strcmp(secflavor, "spkm3p"))
1650
+ data->pseudoflavor = AUTH_GSS_SPKMP;
1651
+ else if(!sloppy) {
1652
+ printf(_("Warning: Unrecognized security flavor %s.\n"),
1654
+ goto bad_parameter;
1656
+ data->flags |= NFS_MOUNT_SECFLAVOUR;
1658
+ } else if (!strcmp(opt, "mounthost"))
1659
+ mounthost=xstrndup(opteq+1,
1660
+ strcspn(opteq+1," \t\n\r,"));
1661
+ else if (!strcmp(opt, "context")) {
1662
+ char *context = opteq + 1;
1664
+ if (strlen(context) > NFS_MAX_CONTEXT_LEN) {
1665
+ printf(_("context parameter exceeds limit of %d\n"),
1666
+ NFS_MAX_CONTEXT_LEN);
1667
+ goto bad_parameter;
1669
+ strncpy(data->context, context, NFS_MAX_CONTEXT_LEN);
1670
+ } else if (!sloppy)
1671
+ goto bad_parameter;
1672
+ sprintf(cbuf, "%s=%s,", opt, opteq+1);
1675
+ if (!strncmp(opt, "no", 2)) {
1679
+ if (!strcmp(opt, "bg"))
1681
+ else if (!strcmp(opt, "fg"))
1683
+ else if (!strcmp(opt, "soft")) {
1684
+ data->flags &= ~NFS_MOUNT_SOFT;
1686
+ data->flags |= NFS_MOUNT_SOFT;
1687
+ } else if (!strcmp(opt, "hard")) {
1688
+ data->flags &= ~NFS_MOUNT_SOFT;
1690
+ data->flags |= NFS_MOUNT_SOFT;
1691
+ } else if (!strcmp(opt, "intr")) {
1692
+ data->flags &= ~NFS_MOUNT_INTR;
1694
+ data->flags |= NFS_MOUNT_INTR;
1695
+ } else if (!strcmp(opt, "posix")) {
1696
+ data->flags &= ~NFS_MOUNT_POSIX;
1698
+ data->flags |= NFS_MOUNT_POSIX;
1699
+ } else if (!strcmp(opt, "cto")) {
1700
+ data->flags &= ~NFS_MOUNT_NOCTO;
1702
+ data->flags |= NFS_MOUNT_NOCTO;
1703
+ } else if (!strcmp(opt, "ac")) {
1704
+ data->flags &= ~NFS_MOUNT_NOAC;
1706
+ data->flags |= NFS_MOUNT_NOAC;
1707
+#if NFS_MOUNT_VERSION >= 2
1708
+ } else if (!strcmp(opt, "tcp")) {
1709
+ data->flags &= ~NFS_MOUNT_TCP;
1711
+ if (nfs_mount_version < 2)
1713
+ nfs_pmap->pm_prot = IPPROTO_TCP;
1714
+ data->flags |= NFS_MOUNT_TCP;
1716
+ nfs_pmap->pm_prot = IPPROTO_UDP;
1717
+ } else if (!strcmp(opt, "udp")) {
1718
+ data->flags &= ~NFS_MOUNT_TCP;
1720
+ if (nfs_mount_version < 2)
1722
+ nfs_pmap->pm_prot = IPPROTO_TCP;
1723
+ data->flags |= NFS_MOUNT_TCP;
1725
+ nfs_pmap->pm_prot = IPPROTO_UDP;
1727
+#if NFS_MOUNT_VERSION >= 3
1728
+ } else if (!strcmp(opt, "lock")) {
1729
+ data->flags &= ~NFS_MOUNT_NONLM;
1731
+ if (nfs_mount_version < 3)
1733
+ data->flags |= NFS_MOUNT_NONLM;
1736
+#if NFS_MOUNT_VERSION >= 4
1737
+ } else if (!strcmp(opt, "broken_suid")) {
1738
+ data->flags &= ~NFS_MOUNT_BROKEN_SUID;
1740
+ if (nfs_mount_version < 4)
1742
+ data->flags |= NFS_MOUNT_BROKEN_SUID;
1748
+ printf(_("Unsupported nfs mount option: "
1749
+ "%s%s\n"), val ? "" : "no", opt);
1753
+ sprintf(cbuf, val ? "%s,":"no%s,", opt);
1755
+ len += strlen(cbuf);
1756
+ if (len >= opt_size) {
1757
+ printf(_("mount: excessively long option argument\n"));
1760
+ strcat(new_opts, cbuf);
1762
+ /* See if the nfs host = mount host. */
1764
+ if (!nfs_gethostbyname(mounthost, mnt_saddr))
1766
+ *mnt_server->hostname = mounthost;
1770
+ printf(_("Bad nfs mount parameter: %s\n"), opt);
1775
-int nfsmount(const char *spec, const char *node, int *flags,
1776
- char **extra_opts, char **mount_opts, int *nfs_mount_vers,
1779
+nfsmnt_check_compat(const struct pmap *nfs_pmap, const struct pmap *mnt_pmap)
1781
+ if (nfs_pmap->pm_vers &&
1782
+ (nfs_pmap->pm_vers > MAX_NFSPROT || nfs_pmap->pm_vers < 2)) {
1783
+ if (nfs_pmap->pm_vers == 4)
1784
+ fprintf(stderr, _("'vers=4' is not supported. "
1785
+ "Use '-t nfs4' instead.\n"));
1787
+ fprintf(stderr, _("NFS version %ld is not supported.\n"),
1788
+ nfs_pmap->pm_vers);
1791
+ if (mnt_pmap->pm_vers > MAX_MNTPROT) {
1792
+ fprintf(stderr, _("NFS mount version %ld s not supported.\n"),
1793
+ mnt_pmap->pm_vers);
1802
+nfsmount(const char *spec, const char *node, int *flags,
1803
+ char **extra_opts, char **mount_opts, int *nfs_mount_vers,
1806
static char *prev_bg_host;
1809
char *hostname, *dirname, *old_opts, *mounthost = NULL;
1810
- char new_opts[1024];
1811
- struct timeval total_timeout;
1812
- enum clnt_stat clnt_stat;
1813
+ char new_opts[1024], cbuf[1024];
1814
static struct nfs_mount_data data;
1815
- char *opt, *opteq;
1816
- int nfs_mount_version;
1818
- struct hostent *hp;
1819
- struct sockaddr_in server_addr;
1820
- struct sockaddr_in mount_server_addr;
1821
- struct pmap *pm_mnt;
1823
- struct timeval retry_timeout;
1825
- struct fhstatus nfsv2;
1826
- struct mountres3 nfsv3;
1829
+ clnt_addr_t mnt_server = { &mounthost, };
1830
+ clnt_addr_t nfs_server = { &hostname, };
1831
+ struct sockaddr_in *nfs_saddr = &nfs_server.saddr;
1832
+ struct pmap *mnt_pmap = &mnt_server.pmap,
1833
+ *nfs_pmap = &nfs_server.pmap;
1834
+ struct pmap save_mnt, save_nfs;
1840
struct stat statbuf;
1842
- int port, mountport, proto, bg, soft, intr;
1843
- int posix, nocto, noac, nolock, broken_suid;
1845
- int mountprog, mountvers, nfsprog, nfsvers;
1851
nfs_mount_version = *nfs_mount_vers;
1854
- msock = fsock = -1;
1857
if (strlen(spec) >= sizeof(hostdir)) {
1858
fprintf(stderr, _("mount: "
1859
"excessively long host:dir argument\n"));
1860
@@ -258,49 +877,23 @@
1864
- server_addr.sin_family = AF_INET;
1865
-#ifdef HAVE_inet_aton
1866
- if (!inet_aton(hostname, &server_addr.sin_addr))
1869
- if ((hp = gethostbyname(hostname)) == NULL) {
1870
- fprintf(stderr, _("mount: can't get address for %s\n"),
1874
- if (hp->h_length > sizeof(struct in_addr)) {
1876
- _("mount: got bad hp->h_length\n"));
1877
- hp->h_length = sizeof(struct in_addr);
1879
- memcpy(&server_addr.sin_addr,
1880
- hp->h_addr, hp->h_length);
1884
- memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr));
1885
+ if (!nfs_gethostbyname(hostname, nfs_saddr))
1887
+ mounthost = hostname;
1888
+ memcpy (&mnt_server.saddr, nfs_saddr, sizeof (mnt_server.saddr));
1890
/* add IP address to mtab options for use when unmounting */
1892
- s = inet_ntoa(server_addr.sin_addr);
1893
+ s = inet_ntoa(nfs_saddr->sin_addr);
1894
old_opts = *extra_opts;
1897
- if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) {
1898
- fprintf(stderr, _("mount: "
1899
- "excessively long option argument\n"));
1902
- sprintf(new_opts, "%s%saddr=%s",
1903
- old_opts, *old_opts ? "," : "", s);
1904
- *extra_opts = xstrdup(new_opts);
1906
/* Set default options.
1907
* rsize/wsize (and bsize, for ver >= 3) are left 0 in order to
1908
* let the kernel decide.
1909
* timeo is filled in after we know whether it'll be TCP or UDP. */
1910
memset(&data, 0, sizeof(data));
1915
@@ -308,169 +901,24 @@
1916
#if NFS_MOUNT_VERSION >= 2
1917
data.namlen = NAME_MAX;
1919
+ data.pseudoflavor = AUTH_SYS;
1929
retry = 10000; /* 10000 minutes ~ 1 week */
1932
- mountprog = MOUNTPROG;
1936
- nfsprog = NFS_PROGRAM;
1938
+ memset(mnt_pmap, 0, sizeof(*mnt_pmap));
1939
+ mnt_pmap->pm_prog = MOUNTPROG;
1940
+ memset(nfs_pmap, 0, sizeof(*nfs_pmap));
1941
+ nfs_pmap->pm_prog = NFS_PROGRAM;
1945
+ if (!parse_options(old_opts, &data, &bg, &retry, &mnt_server, &nfs_server,
1946
+ new_opts, sizeof(new_opts)))
1948
+ if (!nfsmnt_check_compat(nfs_pmap, mnt_pmap))
1951
- for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {
1952
- if ((opteq = strchr(opt, '='))) {
1953
- val = atoi(opteq + 1);
1955
- if (!strcmp(opt, "rsize"))
1957
- else if (!strcmp(opt, "wsize"))
1959
- else if (!strcmp(opt, "timeo"))
1961
- else if (!strcmp(opt, "retrans"))
1962
- data.retrans = val;
1963
- else if (!strcmp(opt, "acregmin"))
1964
- data.acregmin = val;
1965
- else if (!strcmp(opt, "acregmax"))
1966
- data.acregmax = val;
1967
- else if (!strcmp(opt, "acdirmin"))
1968
- data.acdirmin = val;
1969
- else if (!strcmp(opt, "acdirmax"))
1970
- data.acdirmax = val;
1971
- else if (!strcmp(opt, "actimeo")) {
1972
- data.acregmin = val;
1973
- data.acregmax = val;
1974
- data.acdirmin = val;
1975
- data.acdirmax = val;
1977
- else if (!strcmp(opt, "retry"))
1979
- else if (!strcmp(opt, "port"))
1981
- else if (!strcmp(opt, "mountport"))
1983
- else if (!strcmp(opt, "mounthost"))
1984
- mounthost=xstrndup(opteq+1,
1985
- strcspn(opteq+1," \t\n\r,"));
1986
- else if (!strcmp(opt, "mountprog"))
1988
- else if (!strcmp(opt, "mountvers"))
1990
- else if (!strcmp(opt, "nfsprog"))
1992
- else if (!strcmp(opt, "nfsvers") ||
1993
- !strcmp(opt, "vers"))
1995
- else if (!strcmp(opt, "proto")) {
1996
- if (!strncmp(opteq+1, "tcp", 3))
1998
- else if (!strncmp(opteq+1, "udp", 3))
2001
- printf(_("Warning: Unrecognized proto= option.\n"));
2002
- } else if (!strcmp(opt, "namlen")) {
2003
-#if NFS_MOUNT_VERSION >= 2
2004
- if (nfs_mount_version >= 2)
2005
- data.namlen = val;
2008
- printf(_("Warning: Option namlen is not supported.\n"));
2009
- } else if (!strcmp(opt, "addr")) {
2012
- printf(_("unknown nfs mount parameter: "
2013
- "%s=%d\n"), opt, val);
2018
- if (!strncmp(opt, "no", 2)) {
2022
- if (!strcmp(opt, "bg"))
2024
- else if (!strcmp(opt, "fg"))
2026
- else if (!strcmp(opt, "soft"))
2028
- else if (!strcmp(opt, "hard"))
2030
- else if (!strcmp(opt, "intr"))
2032
- else if (!strcmp(opt, "posix"))
2034
- else if (!strcmp(opt, "cto"))
2036
- else if (!strcmp(opt, "ac"))
2038
- else if (!strcmp(opt, "tcp"))
2040
- else if (!strcmp(opt, "udp"))
2042
- else if (!strcmp(opt, "lock")) {
2043
- if (nfs_mount_version >= 3)
2046
- printf(_("Warning: option nolock is not supported.\n"));
2047
- } else if (!strcmp(opt, "broken_suid")) {
2048
- broken_suid = val;
2051
- printf(_("unknown nfs mount option: "
2052
- "%s%s\n"), val ? "" : "no", opt);
2058
- proto = (tcp) ? IPPROTO_TCP : IPPROTO_UDP;
2060
- data.flags = (soft ? NFS_MOUNT_SOFT : 0)
2061
- | (intr ? NFS_MOUNT_INTR : 0)
2062
- | (posix ? NFS_MOUNT_POSIX : 0)
2063
- | (nocto ? NFS_MOUNT_NOCTO : 0)
2064
- | (noac ? NFS_MOUNT_NOAC : 0);
2065
-#if NFS_MOUNT_VERSION >= 2
2066
- if (nfs_mount_version >= 2)
2067
- data.flags |= (tcp ? NFS_MOUNT_TCP : 0);
2069
-#if NFS_MOUNT_VERSION >= 3
2070
- if (nfs_mount_version >= 3)
2071
- data.flags |= (nolock ? NFS_MOUNT_NONLM : 0);
2073
-#if NFS_MOUNT_VERSION >= 4
2074
- if (nfs_mount_version >= 4)
2075
- data.flags |= (broken_suid ? NFS_MOUNT_BROKEN_SUID : 0);
2077
- if (nfsvers > MAX_NFSPROT) {
2078
- fprintf(stderr, "NFSv%d not supported!\n", nfsvers);
2081
- if (mountvers > MAX_NFSPROT) {
2082
- fprintf(stderr, "NFSv%d not supported!\n", nfsvers);
2085
- if (nfsvers && !mountvers)
2086
- mountvers = (nfsvers < 3) ? 1 : nfsvers;
2087
- if (nfsvers && nfsvers < mountvers)
2088
- mountvers = nfsvers;
2090
- /* Adjust options if none specified */
2092
- data.timeo = tcp ? 70 : 7;
2094
#ifdef NFS_MOUNT_DEBUG
2095
printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
2096
@@ -478,9 +926,10 @@
2097
printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n",
2098
data.acregmin, data.acregmax, data.acdirmin, data.acdirmax);
2099
printf("port = %d, bg = %d, retry = %d, flags = %.8x\n",
2100
- port, bg, retry, data.flags);
2101
+ nfs_pmap->pm_port, bg, retry, data.flags);
2102
printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n",
2103
- mountprog, mountvers, nfsprog, nfsvers);
2104
+ mnt_pmap->pm_prog, mnt_pmap->pm_vers,
2105
+ nfs_pmap->pm_prog, nfs_pmap->pm_vers);
2106
printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n",
2107
(data.flags & NFS_MOUNT_SOFT) != 0,
2108
(data.flags & NFS_MOUNT_INTR) != 0,
2109
@@ -491,13 +940,16 @@
2110
printf("tcp = %d\n",
2111
(data.flags & NFS_MOUNT_TCP) != 0);
2113
+#if NFS_MOUNT_VERSION >= 5
2114
+ printf("sec = %u\n", data.pseudoflavor);
2118
data.version = nfs_mount_version;
2119
*mount_opts = (char *) &data;
2121
if (*flags & MS_REMOUNT)
2126
* If the previous mount operation on the same host was
2127
@@ -512,28 +964,6 @@
2130
/* create mount deamon client */
2131
- /* See if the nfs host = mount host. */
2133
- if (mounthost[0] >= '0' && mounthost[0] <= '9') {
2134
- mount_server_addr.sin_family = AF_INET;
2135
- mount_server_addr.sin_addr.s_addr = inet_addr(hostname);
2137
- if ((hp = gethostbyname(mounthost)) == NULL) {
2138
- fprintf(stderr, _("mount: can't get address for %s\n"),
2142
- if (hp->h_length > sizeof(struct in_addr)) {
2144
- _("mount: got bad hp->h_length?\n"));
2145
- hp->h_length = sizeof(struct in_addr);
2147
- mount_server_addr.sin_family = AF_INET;
2148
- memcpy(&mount_server_addr.sin_addr,
2149
- hp->h_addr, hp->h_length);
2155
* The following loop implements the mount retries. On the first
2156
@@ -551,15 +981,13 @@
2158
* Only the first error message will be displayed.
2160
- retry_timeout.tv_sec = 3;
2161
- retry_timeout.tv_usec = 0;
2162
- total_timeout.tv_sec = 20;
2163
- total_timeout.tv_usec = 0;
2164
timeout = time(NULL) + 60 * retry;
2169
+ memcpy(&save_nfs, nfs_pmap, sizeof(save_nfs));
2170
+ memcpy(&save_mnt, mnt_pmap, sizeof(save_mnt));
2172
if (bg && stat(node, &statbuf) == -1) {
2173
/* no mount point yet - sleep */
2174
@@ -570,89 +998,18 @@
2179
/* be careful not to use too many CPU cycles */
2183
- pm_mnt = get_mountport(&mount_server_addr,
2188
- nfs_mount_version);
2190
- /* contact the mount daemon via TCP */
2191
- mount_server_addr.sin_port = htons(pm_mnt->pm_port);
2192
- msock = RPC_ANYSOCK;
2194
- switch (pm_mnt->pm_prot) {
2196
- mclient = clntudp_create(&mount_server_addr,
2203
- mount_server_addr.sin_port =
2204
- htons(pm_mnt->pm_port);
2205
- msock = RPC_ANYSOCK;
2207
- mclient = clnttcp_create(&mount_server_addr,
2211
+ stat = nfs_call_mount(&mnt_server, &nfs_server,
2212
+ &dirname, &mntres,
2213
+ !running_bg && prevt == 0);
2221
- /* try to mount hostname:dirname */
2222
- mclient->cl_auth = authunix_create_default();
2224
- /* make pointers in xdr_mountres3 NULL so
2225
- * that xdr_array allocates memory for us
2227
- memset(&status, 0, sizeof(status));
2229
- if (pm_mnt->pm_vers == 3)
2230
- clnt_stat = clnt_call(mclient,
2232
- (xdrproc_t) xdr_dirpath,
2233
- (caddr_t) &dirname,
2234
- (xdrproc_t) xdr_mountres3,
2235
- (caddr_t) &status,
2238
- clnt_stat = clnt_call(mclient,
2240
- (xdrproc_t) xdr_dirpath,
2241
- (caddr_t) &dirname,
2242
- (xdrproc_t) xdr_fhstatus,
2243
- (caddr_t) &status,
2246
- if (clnt_stat == RPC_SUCCESS)
2247
- break; /* we're done */
2249
- /* errno? who sets errno? */
2250
- /* this fragment breaks bg mounting */
2251
- if (errno != ECONNREFUSED) {
2252
- clnt_perror(mclient, "mount");
2253
- goto fail; /* don't retry */
2256
- if (!running_bg && prevt == 0)
2257
- clnt_perror(mclient, "mount");
2258
- auth_destroy(mclient->cl_auth);
2259
- clnt_destroy(mclient);
2263
- if (!running_bg && prevt == 0)
2264
- clnt_pcreateerror("mount");
2266
+ memcpy(nfs_pmap, &save_nfs, sizeof(*nfs_pmap));
2267
+ memcpy(mnt_pmap, &save_mnt, sizeof(*mnt_pmap));
2271
@@ -668,36 +1025,63 @@
2275
- nfsvers = (pm_mnt->pm_vers < 2) ? 2 : pm_mnt->pm_vers;
2277
- if (nfsvers == 2) {
2278
- if (status.nfsv2.fhs_status != 0) {
2279
+ if (nfs_pmap->pm_vers == 2) {
2280
+ if (mntres.nfsv2.fhs_status != 0) {
2282
- "mount: %s:%s failed, reason given by server: %s\n",
2283
+ _("mount: %s:%s failed, reason given by server: %s\n"),
2285
- nfs_strerror(status.nfsv2.fhs_status));
2286
+ nfs_strerror(mntres.nfsv2.fhs_status));
2289
memcpy(data.root.data,
2290
- (char *) status.nfsv2.fhstatus_u.fhs_fhandle,
2291
+ (char *) mntres.nfsv2.fhstatus_u.fhs_fhandle,
2293
#if NFS_MOUNT_VERSION >= 4
2294
data.root.size = NFS_FHSIZE;
2295
memcpy(data.old_root.data,
2296
- (char *) status.nfsv2.fhstatus_u.fhs_fhandle,
2297
+ (char *) mntres.nfsv2.fhstatus_u.fhs_fhandle,
2301
#if NFS_MOUNT_VERSION >= 4
2302
+ mountres3_ok *mountres;
2304
- if (status.nfsv3.fhs_status != 0) {
2305
+ int i, *flavor, yum = 0;
2306
+ if (mntres.nfsv3.fhs_status != 0) {
2308
- "mount: %s:%s failed, reason given by server: %s\n",
2309
+ _("mount: %s:%s failed, reason given by server: %s\n"),
2311
- nfs_strerror(status.nfsv3.fhs_status));
2312
+ nfs_strerror(mntres.nfsv3.fhs_status));
2315
- fhandle = &status.nfsv3.mountres3_u.mountinfo.fhandle;
2316
+#if NFS_MOUNT_VERSION >= 5
2317
+ mountres = &mntres.nfsv3.mountres3_u.mountinfo;
2318
+ i = mountres->auth_flavours.auth_flavours_len;
2320
+ goto noauth_flavours;
2322
+ flavor = mountres->auth_flavours.auth_flavours_val;
2323
+ while (--i >= 0) {
2324
+ if (flavor[i] == data.pseudoflavor)
2326
+#ifdef NFS_MOUNT_DEBUG
2327
+ printf("auth flavor %d: %d\n",
2333
+ "mount: %s:%s failed, "
2334
+ "security flavor not supported\n",
2335
+ hostname, dirname);
2336
+ /* server has registered us in mtab, send umount */
2337
+ nfs_call_umount(&mnt_server, &dirname);
2342
+ fhandle = &mntres.nfsv3.mountres3_u.mountinfo.fhandle;
2343
memset(data.old_root.data, 0, NFS_FHSIZE);
2344
memset(&data.root, 0, sizeof(data.root));
2345
data.root.size = fhandle->fhandle3_len;
2346
@@ -711,13 +1095,9 @@
2348
/* create nfs socket for kernel */
2351
- if (nfs_mount_version < 3) {
2352
- printf(_("NFS over TCP is not supported.\n"));
2355
+ if (nfs_pmap->pm_prot == IPPROTO_TCP)
2356
fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
2359
fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
2361
perror(_("nfs socket"));
2362
@@ -727,72 +1107,163 @@
2363
perror(_("nfs bindresvport"));
2367
- server_addr.sin_port = PMAPPORT;
2368
- port = pmap_getport(&server_addr, nfsprog, nfsvers,
2369
- tcp ? IPPROTO_TCP : IPPROTO_UDP);
2371
- /* Here we check to see if user is mounting with the
2372
- * tcp option. If so, and if the portmap returns a
2373
- * '0' for port (service unavailable), we then exit,
2374
- * notifying the user, rather than hanging up mount.
2376
- if (port == 0 && tcp == 1) {
2377
- perror(_("nfs server reported service unavailable"));
2384
-#ifdef NFS_MOUNT_DEBUG
2386
- printf(_("used portmapper to find NFS port\n"));
2389
#ifdef NFS_MOUNT_DEBUG
2390
- printf(_("using port %d for nfs deamon\n"), port);
2391
+ printf(_("using port %d for nfs deamon\n"), nfs_pmap->pm_port);
2393
- server_addr.sin_port = htons(port);
2394
+ nfs_saddr->sin_port = htons(nfs_pmap->pm_port);
2396
* connect() the socket for kernels 1.3.10 and below only,
2397
* to avoid problems with multihomed hosts.
2400
if (linux_version_code() <= 66314
2401
- && connect(fsock, (struct sockaddr *) &server_addr,
2402
- sizeof (server_addr)) < 0) {
2403
+ && connect(fsock, (struct sockaddr *) nfs_saddr,
2404
+ sizeof (*nfs_saddr)) < 0) {
2405
perror(_("nfs connect"));
2409
+#if NFS_MOUNT_VERSION >= 2
2410
+ if (nfs_pmap->pm_prot == IPPROTO_TCP)
2411
+ data.flags |= NFS_MOUNT_TCP;
2413
+ data.flags &= ~NFS_MOUNT_TCP;
2416
/* prepare data structure for kernel */
2419
- memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr));
2420
+ memcpy((char *) &data.addr, (char *) nfs_saddr, sizeof(data.addr));
2421
strncpy(data.hostname, hostname, sizeof(data.hostname));
2425
+ /* Ensure we have enough padding for the following strcat()s */
2426
+ if (strlen(new_opts) + strlen(s) + 30 >= sizeof(new_opts)) {
2427
+ fprintf(stderr, _("mount: "
2428
+ "excessively long option argument\n"));
2432
- auth_destroy(mclient->cl_auth);
2433
- clnt_destroy(mclient);
2435
+ snprintf(cbuf, sizeof(cbuf)-1, "addr=%s", s);
2436
+ strcat(new_opts, cbuf);
2438
+ *extra_opts = xstrdup(new_opts);
2444
- if (msock != -1) {
2446
- auth_destroy(mclient->cl_auth);
2447
- clnt_destroy(mclient);
2457
+static inline enum clnt_stat
2458
+nfs3_umount(dirpath *argp, CLIENT *clnt)
2460
+ static char clnt_res;
2461
+ memset (&clnt_res, 0, sizeof(clnt_res));
2462
+ return clnt_call(clnt, MOUNTPROC_UMNT,
2463
+ (xdrproc_t) xdr_dirpath, (caddr_t)argp,
2464
+ (xdrproc_t) xdr_void, (caddr_t) &clnt_res,
2468
+static inline enum clnt_stat
2469
+nfs2_umount(dirpath *argp, CLIENT *clnt)
2471
+ static char clnt_res;
2472
+ memset (&clnt_res, 0, sizeof(clnt_res));
2473
+ return clnt_call(clnt, MOUNTPROC_UMNT,
2474
+ (xdrproc_t) xdr_dirpath, (caddr_t)argp,
2475
+ (xdrproc_t) xdr_void, (caddr_t) &clnt_res,
2480
+nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp)
2483
+ enum clnt_stat res = 0;
2486
+ clnt = mnt_openclnt(mnt_server, &msock, 1);
2489
+ switch (mnt_server->pmap.pm_vers) {
2491
+ res = nfs3_umount(argp, clnt);
2495
+ res = nfs2_umount(argp, clnt);
2500
+ mnt_closeclnt(clnt, msock);
2501
+ if (res == RPC_SUCCESS)
2508
+nfsumount(const char *spec, const char *opts)
2512
+ clnt_addr_t mnt_server = { &hostname, };
2513
+ struct pmap *pmap = &mnt_server.pmap;
2516
+ nfs_mount_version = find_kernel_nfs_mount_version();
2517
+ if (spec == NULL || (p = strchr(spec,':')) == NULL)
2519
+ hostname = xstrndup(spec, p-spec);
2520
+ dirname = xstrdup(p+1);
2521
+#ifdef NFS_MOUNT_DEBUG
2522
+ printf(_("host: %s, directory: %s\n"), hostname, dirname);
2525
+ if (opts && (p = strstr(opts, "addr="))) {
2531
+ while (*q && *q != ',') q++;
2532
+ hostname = xstrndup(p,q-p);
2535
+ if (opts && (p = strstr(opts, "mounthost="))) {
2541
+ while (*q && *q != ',') q++;
2542
+ hostname = xstrndup(p,q-p);
2545
+ pmap->pm_prog = MOUNTPROG;
2546
+ pmap->pm_vers = MOUNTVERS;
2547
+ if (opts && (p = strstr(opts, "mountprog=")) && isdigit(*(p+10)))
2548
+ pmap->pm_prog = atoi(p+10);
2549
+ if (opts && (p = strstr(opts, "mountport=")) && isdigit(*(p+10)))
2550
+ pmap->pm_port = atoi(p+10);
2551
+ if (opts && (p = strstr(opts, "nfsvers=")) && isdigit(*(p+8)))
2552
+ pmap->pm_vers = nfsvers_to_mnt(atoi(p+8));
2553
+ if (opts && (p = strstr(opts, "mountvers=")) && isdigit(*(p+10)))
2554
+ pmap->pm_vers = atoi(p+10);
2556
+ if (!nfs_gethostbyname(hostname, &mnt_server.saddr))
2558
+ if (!probe_mntport(&mnt_server))
2560
+ return nfs_call_umount(&mnt_server, &dirname);
2566
* We need to translate between nfs status return values and
2567
diff -urNad trunk~/mount/sundries.h trunk/mount/sundries.h
2568
--- trunk~/mount/sundries.h 2006-01-29 19:00:03.000000000 +0100
2569
+++ trunk/mount/sundries.h 2006-05-11 16:25:00.000000000 +0200
2572
int nfsmount (const char *spec, const char *node, int *flags,
2573
char **orig_opts, char **opt_args, int *version, int running_bg);
2574
+int nfs4mount (const char *spec, const char *node, int *flags,
2575
+ char **orig_opts, char **opt_args, int running_bg);
2576
+int nfsumount(const char *spec, const char *opts);
2579
/* exit status - bits below are ORed */
2580
diff -urNad trunk~/mount/umount.c trunk/mount/umount.c
2581
--- trunk~/mount/umount.c 2006-05-11 16:24:59.000000000 +0200
2582
+++ trunk/mount/umount.c 2006-05-11 16:25:00.000000000 +0200
2584
/* True if ruid != euid. */
2587
+/* Needed by nfs4mount.c */
2593
* check_special_umountprog()
2594
* If there is a special umount program for this type, exec it.
2596
/* Ignore any RPC errors, so that you can umount the filesystem
2597
if the server is down. */
2598
if (strcasecmp(type, "nfs") == 0)
2599
- nfs_umount_rpc_call(spec, opts);
2600
+ nfsumount(spec, opts);
2603
umnt_err = umnt_err2 = 0;