~ubuntu-branches/ubuntu/lucid/loop-aes-utils/lucid-security

« back to all changes in this revision

Viewing changes to debian/patches/30nfs4.dpatch

  • Committer: Bazaar Package Importer
  • Author(s): Max Vozeler
  • Date: 2008-08-22 11:57:17 UTC
  • mfrom: (8.1.3 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080822115717-v8wfa8pxwlfvyje0
Tags: 2.13.1-4
* patches/losetup_add_option_f.dpatch: 
  - Added to support "find next free loop" in losetup.
    (closes: #495682)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#! /bin/sh /usr/share/dpatch/dpatch-run
2
 
## 30nfs4.dpatch by LaMont Jones <lamont@debian.org>
3
 
##
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>
7
 
 
8
 
@DPATCH@
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
12
 
@@ -29,7 +29,7 @@
13
 
 
14
 
 MAYBE = pivot_root swapoff
15
 
 
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
19
 
 
20
 
 all: $(PROGS)
21
 
@@ -54,7 +54,7 @@
22
 
 
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)
28
 
 
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
33
 
@@ -387,6 +387,7 @@
34
 
 .IR msdos ,
35
 
 .IR ncpfs ,
36
 
 .IR nfs ,
37
 
+.IR nfs4 ,
38
 
 .IR ntfs ,
39
 
 .IR proc ,
40
 
 .IR qnx4 ,
41
 
@@ -424,7 +425,7 @@
42
 
 program has to do is issue a simple
43
 
 .IR mount (2)
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
50
 
@@ -452,9 +453,10 @@
51
 
 All of the filesystem types listed there will be tried,
52
 
 except for those that are labeled "nodev" (e.g.,
53
 
 .IR devpts ,
54
 
-.I proc
55
 
+.IR proc ,
56
 
+.IR nfs ,
57
 
 and
58
 
-.IR nfs ).
59
 
+.IR nfs4 ).
60
 
 If
61
 
 .I /etc/filesystems
62
 
 ends in a line with a single * only, mount will read
63
 
@@ -1368,6 +1370,73 @@
64
 
 .B nolock
65
 
 Do not use locking. Do not start lockd.
66
 
 
67
 
+.SH "Mount options for nfs4"
68
 
+Instead of a textual option string, parsed by the kernel, the
69
 
+.I nfs4
70
 
+file system expects a binary argument of type
71
 
+.IR "struct nfs4_mount_data" .
72
 
+The program
73
 
+.B mount
74
 
+itself parses the following options of the form `tag=value',
75
 
+and puts them in the structure mentioned:
76
 
+.BI rsize= n,
77
 
+.BI wsize= n,
78
 
+.BI timeo= n,
79
 
+.BI retrans= n,
80
 
+.BI acregmin= n,
81
 
+.BI acregmax= n,
82
 
+.BI acdirmin= n,
83
 
+.BI acdirmax= n,
84
 
+.BI actimeo= n,
85
 
+.BI retry= n,
86
 
+.BI port= n,
87
 
+.BI proto= n,
88
 
+.BI clientaddr= n,
89
 
+.BI sec= n.
90
 
+The option
91
 
+.BI addr= n
92
 
+is accepted but ignored.
93
 
+Also the following Boolean options, possibly preceded by
94
 
+.B no
95
 
+are recognized:
96
 
+.BR bg ,
97
 
+.BR fg ,
98
 
+.BR soft ,
99
 
+.BR hard ,
100
 
+.BR intr ,
101
 
+.BR cto ,
102
 
+.BR ac ,
103
 
+For details, see
104
 
+.BR nfs (5).
105
 
+
106
 
+Especially useful options include
107
 
+.TP
108
 
+.B rsize=32768,wsize=32768
109
 
+This will make your NFS connection faster than with the default
110
 
+buffer size of 4096.
111
 
+.TP
112
 
+.B hard
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
116
 
+.BR intr .
117
 
+When the NFS server is back online the program will continue undisturbed
118
 
+from where it was. This is probably what you want.
119
 
+.TP
120
 
+.B soft
121
 
+This option allows the kernel to time out if the NFS server is not
122
 
+responding for some time. The time can be
123
 
+specified with
124
 
+.BR timeo=time .
125
 
+This timeout value is expressed in tenths of a second.
126
 
+The
127
 
+.BR soft
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
131
 
+.BR proto=udp
132
 
+or with a short timeout.
133
 
+
134
 
 .SH "Mount options for ntfs"
135
 
 .TP
136
 
 .BI iocharset= name
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
140
 
@@ -859,8 +859,23 @@
141
 
                      "without support for the type `nfs'"));
142
 
 #endif
143
 
   }
144
 
+#ifdef HAVE_NFS
145
 
+  /*
146
 
+   * NFSv4 support
147
 
+   */
148
 
+  if (!fake && types && streq (types, "nfs4")) {
149
 
+    mnt_err = nfs4mount(spec, node, &flags, &extra_opts, &mount_opts, bg);
150
 
+    if (mnt_err)
151
 
+      return mnt_err;
152
 
+       goto nosigblock;
153
 
+#else
154
 
+    die (EX_SOFTWARE, _("mount: this version was compiled "
155
 
+                     "without support for the type `nfs4'"));
156
 
+#endif
157
 
+  }
158
 
 
159
 
   block_signals (SIG_BLOCK);
160
 
+nosigblock:
161
 
 
162
 
   if (!fake) {
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
167
 
@@ -3,7 +3,7 @@
168
 
 .\" patches. "
169
 
 .TH NFS 5 "20 November 1993" "Linux 0.99" "Linux Programmer's Manual"
170
 
 .SH NAME
171
 
-nfs \- nfs fstab format and options
172
 
+nfs \- nfs and nfs4 fstab format and options
173
 
 .SH SYNOPSIS
174
 
 .B /etc/fstab
175
 
 .SH DESCRIPTION
176
 
@@ -17,14 +17,51 @@
177
 
 and the NFS specific options that control
178
 
 the way the filesystem is mounted.
179
 
 .P
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
185
 
+.BR nfs
186
 
+file system type and specify
187
 
+.BR nfsvers=2 .
188
 
+Version 2 is the default protocol version for the
189
 
+.BR nfs
190
 
+file system type when
191
 
+.BR nfsvers=
192
 
+is not specified on the mount command.
193
 
+To mount via NFS version 3, use the
194
 
+.BR nfs
195
 
+file system type and specify
196
 
+.BR nfsvers=3 .
197
 
+To mount via NFS version 4, use the
198
 
+.BR nfs4
199
 
+file system type.
200
 
+The
201
 
+.BR nfsvers=
202
 
+keyword is not supported for the
203
 
+.BR nfs4
204
 
+file system type.
205
 
+.P
206
 
+These file system types share similar mount options;
207
 
+the differences are listed below.
208
 
+.P
209
 
+Here is an example from an \fI/etc/fstab\fP file for an NFSv2 mount
210
 
+over UDP.
211
 
 .sp
212
 
 .nf
213
 
 .ta 2.5i +0.75i +0.75i +1.0i
214
 
 server:/usr/local/pub  /pub    nfs     rsize=8192,wsize=8192,timeo=14,intr
215
 
 .fi
216
 
+.P
217
 
+Here is an example for an NFSv4 mount over TCP using Kerberos
218
 
+5 mutual authentication.
219
 
+.sp
220
 
+.nf
221
 
+.ta 2.5i +0.75i +0.75i +1.0i
222
 
+server:/usr/local/pub  /pub    nfs4    proto=tcp,sec=krb5,hard,intr
223
 
+.fi
224
 
 .DT
225
 
-.SS Options
226
 
+.SS Options for the nfs file system type
227
 
 .TP 1.5i
228
 
 .I rsize=n
229
 
 The number of bytes NFS uses when reading files from an NFS server.
230
 
@@ -128,7 +165,7 @@
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.
236
 
 .TP 1.5i
237
 
 .I nfsprog=n
238
 
 Use an alternate RPC program number to contact the
239
 
@@ -141,7 +178,7 @@
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.
245
 
 .TP 1.5i
246
 
 .I nolock
247
 
 Disable NFS locking. Do not start lockd.
248
 
@@ -193,9 +230,25 @@
249
 
 .TP 1.5i
250
 
 .I noac
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.
258
 
+.TP 1.5i
259
 
+.I sec=mode
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
273
 
+or privacy.
274
 
 .TP 1.5i
275
 
 .I tcp
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
280
 
 interrupted.
281
 
+.SS Options for the nfs4 file system type
282
 
+.TP 1.5i
283
 
+.I rsize=n
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
287
 
+.IR rsize=32768 .)
288
 
+This value is negotiated with the server.
289
 
+.TP 1.5i
290
 
+.I wsize=n
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
294
 
+.IR wsize=32768 .)
295
 
+This value is negotiated with the server.
296
 
+.TP 1.5i
297
 
+.I timeo=n
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
301
 
+.IR proto=udp
302
 
+or
303
 
+.IR proto=tcp
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.
314
 
+.TP 1.5i
315
 
+.I retrans=n
316
 
+The number of minor timeouts and retransmissions that must occur before
317
 
+a major timeout occurs.  The default is 5 timeouts for
318
 
+.IR proto=udp
319
 
+and 2 timeouts for
320
 
+.IR proto=tcp .
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.
324
 
+.TP 1.5i
325
 
+.I acregmin=n
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.
329
 
+.TP 1.5i
330
 
+.I acregmax=n
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.
334
 
+.TP 1.5i
335
 
+.I acdirmin=n
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.
339
 
+.TP 1.5i
340
 
+.I acdirmax=n
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.
344
 
+.TP 1.5i
345
 
+.I actimeo=n
346
 
+Using actimeo sets all of
347
 
+.I acregmin,
348
 
+.I acregmax,
349
 
+.I acdirmin,
350
 
+and
351
 
+.I acdirmax
352
 
+to the same value.
353
 
+There is no default value.
354
 
+.TP 1.5i
355
 
+.I retry=n
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.
359
 
+.TP 1.5i
360
 
+.I port=n
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
366
 
+used instead.
367
 
+.TP 1.5i
368
 
+.I proto=n
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
373
 
+.IR udp
374
 
+and
375
 
+.IR tcp .
376
 
+.TP 1.5i
377
 
+.I clientaddr=n
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.
382
 
+.TP 1.5i
383
 
+.I sec=mode
384
 
+Same as \f3sec=mode\f1 for the nfs filesystem type (see above).
385
 
+.TP 1.5i
386
 
+.I bg
387
 
+If an NFS mount attempt times out, retry the mount
388
 
+in the background.
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.
394
 
+.TP 1.5i
395
 
+.I fg
396
 
+If the first NFS mount attempt times out, retry the mount
397
 
+in the foreground.
398
 
+This is the complement of the
399
 
+.I bg
400
 
+option, and also the default behavior.
401
 
+.TP 1.5i
402
 
+.I soft
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.
406
 
+.TP 1.5i
407
 
+.I hard
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.
411
 
+.TP 1.5i
412
 
+.I intr
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.
417
 
+.TP 1.5i
418
 
+.I nocto
419
 
+Suppress the retrieval of new attributes when creating a file.
420
 
+.TP 1.5i
421
 
+.I noac
422
 
+Disable attribute caching, and force synchronous writes.
423
 
+This extracts a
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.
427
 
+.P
428
 
+All of the non-value options have corresponding nooption forms.
429
 
+For example, nointr means don't allow file operations to be
430
 
+interrupted.
431
 
 .SH FILES
432
 
 .I /etc/fstab
433
 
 .SH "SEE ALSO"
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
437
 
@@ -0,0 +1,82 @@
438
 
+#ifndef _LINUX_NFS4_MOUNT_H
439
 
+#define _LINUX_NFS4_MOUNT_H
440
 
+
441
 
+/*
442
 
+ *  linux/include/linux/nfs4_mount.h
443
 
+ *
444
 
+ *  Copyright (C) 2002  Trond Myklebust
445
 
+ *
446
 
+ *  structure passed from user-space to kernel-space during an nfsv4 mount
447
 
+ */
448
 
+
449
 
+/*
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.
455
 
+ */
456
 
+#define NFS4_MOUNT_VERSION     1
457
 
+
458
 
+struct nfs_string {
459
 
+       unsigned int len;
460
 
+       const char* data;
461
 
+};
462
 
+
463
 
+struct nfs4_mount_data {
464
 
+       int version;                            /* 1 */
465
 
+       int flags;                              /* 1 */
466
 
+       int rsize;                              /* 1 */
467
 
+       int wsize;                              /* 1 */
468
 
+       int timeo;                              /* 1 */
469
 
+       int retrans;                            /* 1 */
470
 
+       int acregmin;                           /* 1 */
471
 
+       int acregmax;                           /* 1 */
472
 
+       int acdirmin;                           /* 1 */
473
 
+       int acdirmax;                           /* 1 */
474
 
+
475
 
+       /* see the definition of 'struct clientaddr4' in RFC3010 */
476
 
+       struct nfs_string client_addr;          /* 1 */
477
 
+
478
 
+       /* Mount path */
479
 
+       struct nfs_string mnt_path;             /* 1 */
480
 
+
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 */
486
 
+
487
 
+       /* Transport protocol to use */
488
 
+       int proto;                              /* 1 */
489
 
+
490
 
+       /* Pseudo-flavours to use for authentication. See RFC2623 */
491
 
+       int auth_flavourlen;                    /* 1 */
492
 
+       int *auth_flavours;                     /* 1 */
493
 
+};
494
 
+
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
498
 
+ */
499
 
+
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
506
 
+
507
 
+/* pseudoflavors: */
508
 
+
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
518
 
+
519
 
+#endif
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
523
 
@@ -0,0 +1,433 @@
524
 
+/*
525
 
+ * nfs4mount.c -- Linux NFS mount
526
 
+ * Copyright (C) 2002 Trond Myklebust <trond.myklebust@fys.uio.no>
527
 
+ *
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.
532
 
+ *
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.
537
 
+ *
538
 
+ * Note: this file based on the original nfsmount.c
539
 
+ */
540
 
+
541
 
+#include "../defines.h"        /* for HAVE_rpcsvc_nfs_prot_h and HAVE_inet_aton */
542
 
+
543
 
+#include <linux/posix_types.h>
544
 
+#include <asm/posix_types.h>
545
 
+#undef __FD_CLR
546
 
+#undef __FD_SET
547
 
+#undef __FD_ISSET
548
 
+#undef __FD_ZERO
549
 
+
550
 
+#include <unistd.h>
551
 
+#include <stdio.h>
552
 
+#include <string.h>
553
 
+#include <errno.h>
554
 
+#include <netdb.h>
555
 
+#include <time.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>
565
 
+#else
566
 
+#include <linux/nfs.h>
567
 
+#define nfsstat nfs_stat
568
 
+#endif
569
 
+
570
 
+#include "sundries.h"
571
 
+
572
 
+#include "mount_constants.h"
573
 
+#include "nfs4_mount.h"
574
 
+
575
 
+#include "nls.h"
576
 
+
577
 
+#if defined(VAR_LOCK_DIR)
578
 
+#define DEFAULT_DIR VAR_LOCK_DIR
579
 
+#else
580
 
+#define DEFAULT_DIR "/var/run"
581
 
+#endif
582
 
+
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")); \
588
 
+       } \
589
 
+} while(0);
590
 
+
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")); \
595
 
+               } \
596
 
+} while(0); 
597
 
+
598
 
+#ifndef NFS_PORT
599
 
+#define NFS_PORT 2049
600
 
+#endif
601
 
+
602
 
+extern int clnt_ping(struct sockaddr_in *, const u_long, const u_long, const u_int);
603
 
+extern void rpc_strerror(void);
604
 
+
605
 
+struct {
606
 
+       char    *flavour;
607
 
+       int     fnum;
608
 
+} flav_map[] = {
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               },
622
 
+};
623
 
+
624
 
+#define FMAPSIZE               (sizeof(flav_map)/sizeof(flav_map[0]))
625
 
+#define MAX_USER_FLAVOUR       16
626
 
+
627
 
+static int parse_sec(char *sec, int *pseudoflavour)
628
 
+{
629
 
+       int i, num_flavour = 0;
630
 
+
631
 
+       for (sec = strtok(sec, ":"); sec; sec = strtok(NULL, ":")) {
632
 
+               if (num_flavour >= MAX_USER_FLAVOUR) {
633
 
+                       fprintf(stderr,
634
 
+                               _("mount: maximum number of security flavors "
635
 
+                                 "exceeded\n"));
636
 
+                       return 0;
637
 
+               }
638
 
+               for (i = 0; i < FMAPSIZE; i++) {
639
 
+                       if (strcmp(sec, flav_map[i].flavour) == 0) {
640
 
+                               pseudoflavour[num_flavour++] = flav_map[i].fnum;
641
 
+                               break;
642
 
+                       }
643
 
+               }
644
 
+               if (i == FMAPSIZE) {
645
 
+                       fprintf(stderr,
646
 
+                               _("mount: unknown security type %s\n"), sec);
647
 
+                       return 0;
648
 
+               }
649
 
+       }
650
 
+       if (!num_flavour)
651
 
+               fprintf(stderr,
652
 
+                       _("mount: no security flavors passed to sec= option\n"));
653
 
+       return num_flavour;
654
 
+}
655
 
+
656
 
+static int parse_devname(char *hostdir, char **hostname, char **dirname)
657
 
+{
658
 
+       char *s;
659
 
+
660
 
+       if (!(s = strchr(hostdir, ':'))) {
661
 
+               fprintf(stderr,
662
 
+                       _("mount: "
663
 
+                         "directory to mount not in host:dir format\n"));
664
 
+               return -1;
665
 
+       }
666
 
+       *hostname = hostdir;
667
 
+       *dirname = s + 1;
668
 
+       *s = '\0';
669
 
+       /* Ignore all but first hostname in replicated mounts
670
 
+          until they can be fully supported. (mack@sgi.com) */
671
 
+       if ((s = strchr(hostdir, ','))) {
672
 
+               *s = '\0';
673
 
+               fprintf(stderr,
674
 
+                       _("mount: warning: "
675
 
+                         "multiple hostnames not supported\n"));
676
 
+       }
677
 
+       return 0;
678
 
+}
679
 
+
680
 
+static int fill_ipv4_sockaddr(const char *hostname, struct sockaddr_in *addr)
681
 
+{
682
 
+       struct hostent *hp;
683
 
+       addr->sin_family = AF_INET;
684
 
+
685
 
+       if (inet_aton(hostname, &addr->sin_addr))
686
 
+               return 0;
687
 
+       if ((hp = gethostbyname(hostname)) == NULL) {
688
 
+               fprintf(stderr, _("mount: can't get address for %s\n"),
689
 
+                       hostname);
690
 
+               return -1;
691
 
+       }
692
 
+       if (hp->h_length > sizeof(struct in_addr)) {
693
 
+               fprintf(stderr,
694
 
+                       _("mount: got bad hp->h_length\n"));
695
 
+               hp->h_length = sizeof(struct in_addr);
696
 
+       }
697
 
+       memcpy(&addr->sin_addr, hp->h_addr, hp->h_length);
698
 
+       return 0;
699
 
+}
700
 
+
701
 
+static int get_my_ipv4addr(char *ip_addr, int len)
702
 
+{
703
 
+       char myname[1024];
704
 
+       struct sockaddr_in myaddr;
705
 
+
706
 
+       if (gethostname(myname, sizeof(myname))) {
707
 
+               fprintf(stderr, _("mount: can't determine client address\n"));
708
 
+               return -1;
709
 
+       }
710
 
+       if (fill_ipv4_sockaddr(myname, &myaddr))
711
 
+               return -1;
712
 
+       snprintf(ip_addr, len, "%s", inet_ntoa(myaddr.sin_addr));
713
 
+       ip_addr[len-1] = '\0';
714
 
+       return 0;
715
 
+}
716
 
+
717
 
+int nfs4mount(const char *spec, const char *node, int *flags,
718
 
+             char **extra_opts, char **mount_opts,
719
 
+             int running_bg)
720
 
+{
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;
727
 
+
728
 
+       char *hostname, *dirname, *old_opts;
729
 
+       char new_opts[1024];
730
 
+       char *opt, *opteq;
731
 
+       char *s;
732
 
+       int val;
733
 
+       int bg, soft, intr;
734
 
+       int nocto, noac;
735
 
+       int retry;
736
 
+       int retval;
737
 
+
738
 
+       retval = EX_FAIL;
739
 
+       if (strlen(spec) >= sizeof(hostdir)) {
740
 
+               fprintf(stderr, _("mount: "
741
 
+                                 "excessively long host:dir argument\n"));
742
 
+               goto fail;
743
 
+       }
744
 
+       strcpy(hostdir, spec);
745
 
+       if (parse_devname(hostdir, &hostname, &dirname))
746
 
+               goto fail;
747
 
+
748
 
+       if (fill_ipv4_sockaddr(hostname, &server_addr))
749
 
+               goto fail;
750
 
+       if (get_my_ipv4addr(ip_addr, sizeof(ip_addr)))
751
 
+               goto fail;
752
 
+
753
 
+       /* add IP address to mtab options for use when unmounting */
754
 
+       s = inet_ntoa(server_addr.sin_addr);
755
 
+       old_opts = *extra_opts;
756
 
+       if (!old_opts)
757
 
+               old_opts = "";
758
 
+       if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) {
759
 
+               fprintf(stderr, _("mount: "
760
 
+                                 "excessively long option argument\n"));
761
 
+               goto fail;
762
 
+       }
763
 
+       snprintf(new_opts, sizeof(new_opts), "%s%saddr=%s",
764
 
+                old_opts, *old_opts ? "," : "", s);
765
 
+       *extra_opts = xstrdup(new_opts);
766
 
+
767
 
+       /* Set default options.
768
 
+        * rsize/wsize and timeo are left 0 in order to
769
 
+        * let the kernel decide.
770
 
+        */
771
 
+       memset(&data, 0, sizeof(data));
772
 
+       data.retrans    = 3;
773
 
+       data.acregmin   = 3;
774
 
+       data.acregmax   = 60;
775
 
+       data.acdirmin   = 30;
776
 
+       data.acdirmax   = 60;
777
 
+       data.proto      = IPPROTO_TCP;
778
 
+
779
 
+       bg = 0;
780
 
+       soft = 0;
781
 
+       intr = NFS4_MOUNT_INTR;
782
 
+       nocto = 0;
783
 
+       noac = 0;
784
 
+       retry = 10000;          /* 10000 minutes ~ 1 week */
785
 
+
786
 
+       /*
787
 
+        * NFSv4 specifies that the default port should be 2049
788
 
+        */
789
 
+       server_addr.sin_port = htons(NFS_PORT);
790
 
+
791
 
+       /* parse options */
792
 
+
793
 
+       for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {
794
 
+               if ((opteq = strchr(opt, '='))) {
795
 
+                       val = atoi(opteq + 1);  
796
 
+                       *opteq = '\0';
797
 
+                       if (!strcmp(opt, "rsize"))
798
 
+                               data.rsize = val;
799
 
+                       else if (!strcmp(opt, "wsize"))
800
 
+                               data.wsize = val;
801
 
+                       else if (!strcmp(opt, "timeo"))
802
 
+                               data.timeo = val;
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;
818
 
+                       }
819
 
+                       else if (!strcmp(opt, "retry"))
820
 
+                               retry = val;
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;
828
 
+                               else
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"),
833
 
+                                                               opteq+1);
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);
838
 
+                               if (!num_flavour)
839
 
+                                       goto fail;
840
 
+                       } else if (!strcmp(opt, "addr")) {
841
 
+                               /* ignore */;
842
 
+                       } else {
843
 
+                               printf(_("unknown nfs mount parameter: "
844
 
+                                        "%s=%d\n"), opt, val);
845
 
+                               goto fail;
846
 
+                       }
847
 
+               } else {
848
 
+                       val = 1;
849
 
+                       if (!strncmp(opt, "no", 2)) {
850
 
+                               val = 0;
851
 
+                               opt += 2;
852
 
+                       }
853
 
+                       if (!strcmp(opt, "bg")) 
854
 
+                               bg = val;
855
 
+                       else if (!strcmp(opt, "fg")) 
856
 
+                               bg = !val;
857
 
+                       else if (!strcmp(opt, "soft"))
858
 
+                               soft = val;
859
 
+                       else if (!strcmp(opt, "hard"))
860
 
+                               soft = !val;
861
 
+                       else if (!strcmp(opt, "intr"))
862
 
+                               intr = val;
863
 
+                       else if (!strcmp(opt, "cto"))
864
 
+                               nocto = !val;
865
 
+                       else if (!strcmp(opt, "ac"))
866
 
+                               noac = !val;
867
 
+                       else {
868
 
+                               if (!sloppy) {
869
 
+                                       printf(_("unknown nfs mount option: "
870
 
+                                                "%s%s\n"), val ? "" : "no", opt);
871
 
+                                       goto fail;
872
 
+                               }
873
 
+                       }
874
 
+               }
875
 
+       }
876
 
+
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);
881
 
+
882
 
+       /*
883
 
+        * Give a warning if the rpc.idmapd daemon is not running
884
 
+        */
885
 
+       idmapd_check();
886
 
+
887
 
+       if (num_flavour == 0)
888
 
+               pseudoflavour[num_flavour++] = AUTH_UNIX;
889
 
+       else {
890
 
+               /*
891
 
+                * ditto with rpc.gssd daemon
892
 
+                */
893
 
+               gssd_check();
894
 
+       }
895
 
+       data.auth_flavourlen = num_flavour;
896
 
+       data.auth_flavours = pseudoflavour;
897
 
+
898
 
+       data.client_addr.data = ip_addr;
899
 
+       data.client_addr.len = strlen(ip_addr);
900
 
+
901
 
+       data.mnt_path.data = dirname;
902
 
+       data.mnt_path.len = strlen(dirname);
903
 
+
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);
908
 
+
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);
921
 
+
922
 
+       if (num_flavour > 0) {
923
 
+               int pf_cnt, i;
924
 
+
925
 
+               printf("sec = ");
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);
930
 
+                                       break;
931
 
+                               }
932
 
+                       }
933
 
+                       printf("%s", (pf_cnt < num_flavour-1) ? ":" : "\n");
934
 
+               }
935
 
+       }
936
 
+       printf("proto = %s\n", (data.proto == IPPROTO_TCP) ? "tcp" : "udp");
937
 
+#endif
938
 
+
939
 
+       data.version = NFS4_MOUNT_VERSION;
940
 
+
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);
944
 
+               goto fail;
945
 
+       }
946
 
+
947
 
+       *mount_opts = (char *) &data;
948
 
+       /* clean up */
949
 
+       return 0;
950
 
+
951
 
+fail:
952
 
+       if (verbose) {
953
 
+               rpc_strerror();
954
 
+       }
955
 
+       return retval;
956
 
+}
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
960
 
@@ -8,7 +8,9 @@
961
 
  * so it is easiest to ignore the kernel altogether (at compile time).
962
 
  */
963
 
 
964
 
-#define NFS_MOUNT_VERSION      4
965
 
+#define NFS_MOUNT_VERSION 6
966
 
+#define NFS_MAX_CONTEXT_LEN   256
967
 
+
968
 
 
969
 
 struct nfs2_fh {
970
 
         char                    data[32];
971
 
@@ -36,6 +38,9 @@
972
 
        int             namlen;                 /* 2 */
973
 
        unsigned int    bsize;                  /* 3 */
974
 
        struct nfs3_fh  root;                   /* 4 */
975
 
+       int             pseudoflavor;           /* 5 */
976
 
+       char    context[NFS_MAX_CONTEXT_LEN + 1]; /* 6 */
977
 
+
978
 
 };
979
 
 
980
 
 /* bits in the flags field */
981
 
@@ -51,4 +56,19 @@
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 */
986
 
+
987
 
+/* security pseudoflavors */
988
 
+
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
999
 
+#endif
1000
 
 
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
1004
 
@@ -34,6 +34,7 @@
1005
 
 
1006
 
 #include "../defines.h"        /* for HAVE_rpcsvc_nfs_prot_h and HAVE_inet_aton */
1007
 
 
1008
 
+#include <ctype.h>
1009
 
 #include <unistd.h>
1010
 
 #include <stdio.h>
1011
 
 #include <string.h>
1012
 
@@ -72,11 +73,121 @@
1013
 
 #define NFS_FHSIZE 32
1014
 
 #endif
1015
 
 
1016
 
+#define MNT_SENDBUFSIZE ((u_int)2048)
1017
 
+#define MNT_RECVBUFSIZE ((u_int)1024)
1018
 
+
1019
 
 static char *nfs_strerror(int stat);
1020
 
 
1021
 
 #define MAKE_VERSION(p,q,r)    (65536*(p) + 256*(q) + (r))
1022
 
 
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)
1026
 
+
1027
 
+#ifndef HAVE_inet_aton
1028
 
+#define inet_aton(a,b) (0)
1029
 
+#endif
1030
 
+
1031
 
+typedef dirpath mnt2arg_t;
1032
 
+typedef dirpath mnt3arg_t;
1033
 
+typedef dirpath mntarg_t;
1034
 
+
1035
 
+typedef struct fhstatus  mnt2res_t;
1036
 
+typedef struct mountres3 mnt3res_t;
1037
 
+typedef union {
1038
 
+       mnt2res_t nfsv2;
1039
 
+       mnt3res_t nfsv3;
1040
 
+} mntres_t;
1041
 
+
1042
 
+typedef struct {
1043
 
+       char **hostname;
1044
 
+       struct sockaddr_in saddr;
1045
 
+       struct pmap pmap;
1046
 
+} clnt_addr_t;
1047
 
+
1048
 
+/* RPC call timeout values */
1049
 
+static const struct timeval TIMEOUT = { 20, 0 };
1050
 
+static const struct timeval RETRY_TIMEOUT = { 3, 0 };
1051
 
+
1052
 
+static int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp);
1053
 
+
1054
 
+int clnt_ping(struct sockaddr_in *, const u_long, const u_long, const u_int);
1055
 
+
1056
 
+/* Convert RPC errors into strings */
1057
 
+void rpc_strerror(void)
1058
 
+{
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);
1062
 
+
1063
 
+       if (estr) {
1064
 
+               if ((ptr = index(estr, ':')))
1065
 
+                       estr = ++ptr;
1066
 
+
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));
1070
 
+       }
1071
 
+}
1072
 
+
1073
 
+/* Define the order in which to probe for UDP/TCP services */
1074
 
+static const u_int *
1075
 
+proto_probelist(const int use_tcp)
1076
 
+{
1077
 
+       static const u_int probe_both[] = { IPPROTO_TCP, IPPROTO_UDP, 0 };
1078
 
+       static const u_int probe_udponly[] = { IPPROTO_UDP, 0 };
1079
 
+       if (use_tcp)
1080
 
+               return probe_both;
1081
 
+       return probe_udponly;
1082
 
+}
1083
 
+
1084
 
+/* Define the order in which NFS versions are probed on portmapper */
1085
 
+static const u_long *
1086
 
+nfs_probelist(const int vers)
1087
 
+{
1088
 
+       static const u_long nfs2_probe[] = { 2, 0};
1089
 
+       static const u_long nfs3_probe[] = { 3, 2, 0};
1090
 
+       switch (vers) {
1091
 
+       case 3:
1092
 
+               return nfs3_probe;
1093
 
+       default:
1094
 
+               return nfs2_probe;
1095
 
+       }
1096
 
+}
1097
 
+
1098
 
+/* Define the order in which Mountd versions are probed on portmapper */
1099
 
+static const u_long *
1100
 
+mnt_probelist(const int vers)
1101
 
+{
1102
 
+       static const u_long mnt1_probe[] = { 1, 2, 0 };
1103
 
+       static const u_long mnt3_probe[] = { 3, 1, 2, 0 };
1104
 
+       switch (vers) {
1105
 
+       case 3:
1106
 
+               return mnt3_probe;
1107
 
+       default:
1108
 
+               return mnt1_probe;
1109
 
+       }
1110
 
+}
1111
 
+
1112
 
+/* Map an NFS version into the corresponding Mountd version */
1113
 
+static u_long
1114
 
+nfsvers_to_mnt(const u_long vers)
1115
 
+{
1116
 
+       static const u_long nfs_to_mnt[] = { 0, 0, 1, 3 };
1117
 
+       if (vers <= 3)
1118
 
+               return nfs_to_mnt[vers];
1119
 
+       return 0;
1120
 
+}
1121
 
+
1122
 
+/* Map a Mountd version into the corresponding NFS version */
1123
 
+static u_long
1124
 
+mntvers_to_nfs(const u_long vers)
1125
 
+{
1126
 
+       static const u_long mnt_to_nfs[] = { 0, 2, 2, 3 };
1127
 
+       if (vers <= 3)
1128
 
+               return mnt_to_nfs[vers];
1129
 
+       return 0;
1130
 
+}
1131
 
 
1132
 
 static int
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
1137
 
  */
1138
 
+static int nfs_mount_version = NFS_MOUNT_VERSION;
1139
 
+
1140
 
 static int
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;
1145
 
 
1146
 
        if (kernel_version == -1)
1147
 
                kernel_version = linux_version_code();
1148
 
 
1149
 
        if (kernel_version) {
1150
 
             if (kernel_version < MAKE_VERSION(2,1,32))
1151
 
-                 nfs_mount_version = 1;
1152
 
+                 mnt_version = 1;
1153
 
             else if (kernel_version < MAKE_VERSION(2,2,18))
1154
 
-                 nfs_mount_version = 3;
1155
 
+                 mnt_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;
1161
 
+                 mnt_version = 3;
1162
 
+            else if (kernel_version < MAKE_VERSION(2,6,3))
1163
 
+                 mnt_version = 4;
1164
 
             else
1165
 
-                 nfs_mount_version = 4; /* since 2.3.99pre4 */
1166
 
+                 mnt_version = 6;
1167
 
        }
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;
1174
 
 }
1175
 
 
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)
1183
 
+static int
1184
 
+nfs_gethostbyname(const char *hostname, struct sockaddr_in *saddr)
1185
 
 {
1186
 
-       struct pmaplist *pmap;
1187
 
-       static struct pmap p = {0, 0, 0, 0};
1188
 
+       struct hostent *hp;
1189
 
 
1190
 
-       if (version > MAX_NFSPROT)
1191
 
-               version = MAX_NFSPROT;
1192
 
-       if (!prog)
1193
 
-               prog = MOUNTPROG;
1194
 
-       p.pm_prog = prog;
1195
 
-       p.pm_vers = version;
1196
 
-       p.pm_prot = proto;
1197
 
-       p.pm_port = port;
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"),
1202
 
+                               hostname);
1203
 
+                       return 0;
1204
 
+               } else {
1205
 
+                       if (hp->h_length > sizeof(*saddr)) {
1206
 
+                               fprintf(stderr,
1207
 
+                                       _("mount: got bad hp->h_length\n"));
1208
 
+                               hp->h_length = sizeof(*saddr);
1209
 
+                       }
1210
 
+                       memcpy(&saddr->sin_addr, hp->h_addr, hp->h_length);
1211
 
+               }
1212
 
+       }
1213
 
+       return 1;
1214
 
+}
1215
 
 
1216
 
-       server_addr->sin_port = PMAPPORT;
1217
 
-       pmap = pmap_getmaps(server_addr);
1218
 
+/*
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
1222
 
+ * RPC call.
1223
 
+ */
1224
 
+int
1225
 
+clnt_ping(struct sockaddr_in *saddr, const u_long prog, const u_long vers,
1226
 
+         const u_int prot)
1227
 
+{
1228
 
+       CLIENT *clnt=NULL;
1229
 
+       int sock, stat;
1230
 
+       static char clnt_res;
1231
 
 
1232
 
-       while (pmap) {
1233
 
-               if (pmap->pml_map.pm_prog != prog)
1234
 
-                       goto next;
1235
 
-               if (!version && p.pm_vers > pmap->pml_map.pm_vers)
1236
 
-                       goto next;
1237
 
-               if (version > 2 && pmap->pml_map.pm_vers != version)
1238
 
-                       goto next;
1239
 
-               if (version && version <= 2 && pmap->pml_map.pm_vers > 2)
1240
 
-                       goto next;
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))
1244
 
-                       goto next;
1245
 
-               memcpy(&p, &pmap->pml_map, sizeof(p));
1246
 
-       next:
1247
 
-               pmap = pmap->pml_next;
1248
 
+       rpc_createerr.cf_stat = stat = 0;
1249
 
+       sock = RPC_ANYSOCK;
1250
 
+       switch(prot) {
1251
 
+       case IPPROTO_UDP:
1252
 
+               clnt = clntudp_bufcreate(saddr, prog, vers,
1253
 
+                                        RETRY_TIMEOUT, &sock,
1254
 
+                                        RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
1255
 
+               break;
1256
 
+       case IPPROTO_TCP:
1257
 
+               clnt = clnttcp_create(saddr, prog, vers, &sock,
1258
 
+                                     RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
1259
 
+               break;
1260
 
+       default:
1261
 
+               goto out_bad;
1262
 
        }
1263
 
-       if (!p.pm_vers)
1264
 
-               p.pm_vers = MOUNTVERS;
1265
 
-       if (!p.pm_prot)
1266
 
-               p.pm_prot = IPPROTO_TCP;
1267
 
-#if 0
1268
 
-       if (!p.pm_port) {
1269
 
-               p.pm_port = pmap_getport(server_addr, p.pm_prog, p.pm_vers,
1270
 
-                                        p.pm_prot);
1271
 
+       if (!clnt)
1272
 
+               goto out_bad;
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,
1277
 
+                        TIMEOUT);
1278
 
+       clnt_destroy(clnt);
1279
 
+       close(sock);
1280
 
+       if (stat != RPC_PROGVERSMISMATCH)
1281
 
+               return 1;
1282
 
+
1283
 
+ out_bad:
1284
 
+       return 0;
1285
 
+}
1286
 
+
1287
 
+/*
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.
1291
 
+ */
1292
 
+static int
1293
 
+probe_port(clnt_addr_t *server, 
1294
 
+          const u_long *versions,
1295
 
+          const u_int *protos)
1296
 
+{
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,
1301
 
+               *p_vers;
1302
 
+       const u_int prot = (u_int)pmap->pm_prot,
1303
 
+               *p_prot;
1304
 
+       const u_short port = (u_short) pmap->pm_port;
1305
 
+       u_short p_port;
1306
 
+       p_prot = prot ? &prot : protos;
1307
 
+       p_vers = vers ? &vers : versions;
1308
 
+       rpc_createerr.cf_stat = 0;
1309
 
+       for (;;) {
1310
 
+               saddr->sin_port = htons(PMAPPORT);
1311
 
+               p_port = pmap_getport(saddr, prog, *p_vers, *p_prot);
1312
 
+               if (p_port) {
1313
 
+                       if (!port || port == p_port) {
1314
 
+                               saddr->sin_port = htons(port);
1315
 
+                               if (clnt_ping(saddr, prog, *p_vers, *p_prot))
1316
 
+                                       goto out_ok;
1317
 
+                       }
1318
 
+               } else if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED)
1319
 
+                       break;
1320
 
+               if (!prot) {
1321
 
+                       if (*++p_prot)
1322
 
+                               continue;
1323
 
+                       p_prot = protos;
1324
 
+               }
1325
 
+               if (vers || !*++p_vers)
1326
 
+                       break;
1327
 
        }
1328
 
+       return 0;
1329
 
+ out_ok:
1330
 
+       if (!vers)
1331
 
+               pmap->pm_vers = *p_vers;
1332
 
+       if (!prot)
1333
 
+               pmap->pm_prot = *p_prot;
1334
 
+       if (!port)
1335
 
+               pmap->pm_port = p_port;
1336
 
+       rpc_createerr.cf_stat = 0;
1337
 
+       return 1;
1338
 
+}
1339
 
+
1340
 
+static int
1341
 
+probe_nfsport(clnt_addr_t *nfs_server)
1342
 
+{
1343
 
+       const struct pmap *pmap = &nfs_server->pmap;
1344
 
+       const u_long *probe_vers;
1345
 
+       const u_int *probe_prot;
1346
 
+
1347
 
+       if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
1348
 
+               return 1;
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);
1352
 
+}
1353
 
+
1354
 
+static int
1355
 
+probe_mntport(clnt_addr_t *mnt_server)
1356
 
+{
1357
 
+       const struct pmap *pmap = &mnt_server->pmap;
1358
 
+       const u_long *probe_vers;
1359
 
+       const u_int *probe_prot;
1360
 
+
1361
 
+       if (pmap->pm_vers && pmap->pm_prot && pmap->pm_port)
1362
 
+               return 1;
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);
1366
 
+}
1367
 
+
1368
 
+static int
1369
 
+probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server)
1370
 
+{
1371
 
+       struct pmap *nfs_pmap = &nfs_server->pmap;
1372
 
+       struct pmap *mnt_pmap = &mnt_server->pmap;
1373
 
+       struct pmap save_nfs, save_mnt;
1374
 
+       int res;
1375
 
+       const u_long *probe_vers;
1376
 
+
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)
1390
 
+                               return 1;
1391
 
+                       memcpy(mnt_pmap, &save_mnt, sizeof(*mnt_pmap));
1392
 
+               }
1393
 
+               if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED)
1394
 
+                       break;
1395
 
+               memcpy(nfs_pmap, &save_nfs, sizeof(*nfs_pmap));
1396
 
+       }
1397
 
+ out_bad:
1398
 
+       return 0;
1399
 
+ version_fixed:
1400
 
+       if (!probe_nfsport(nfs_server))
1401
 
+               goto out_bad;
1402
 
+       return probe_mntport(mnt_server);
1403
 
+}
1404
 
+
1405
 
+static CLIENT *
1406
 
+mnt_openclnt(clnt_addr_t *mnt_server, int *msock, const int report_errs)
1407
 
+{
1408
 
+       struct sockaddr_in *mnt_saddr = &mnt_server->saddr;
1409
 
+       struct pmap *mnt_pmap = &mnt_server->pmap;
1410
 
+       CLIENT *clnt;
1411
 
+
1412
 
+       /* contact the mount daemon via TCP */
1413
 
+       mnt_saddr->sin_port = htons((u_short)mnt_pmap->pm_port);
1414
 
+       *msock = RPC_ANYSOCK;
1415
 
+
1416
 
+       switch (mnt_pmap->pm_prot) {
1417
 
+       case IPPROTO_UDP:
1418
 
+               clnt = clntudp_bufcreate(mnt_saddr,
1419
 
+                                        mnt_pmap->pm_prog, mnt_pmap->pm_vers,
1420
 
+                                        RETRY_TIMEOUT, msock,
1421
 
+                                        MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
1422
 
+               break;
1423
 
+       case IPPROTO_TCP:
1424
 
+               clnt = clnttcp_create(mnt_saddr,
1425
 
+                                     mnt_pmap->pm_prog, mnt_pmap->pm_vers,
1426
 
+                                     msock,
1427
 
+                                     MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
1428
 
+               break;
1429
 
+       default:
1430
 
+               goto out_bad;
1431
 
+       }
1432
 
+       if (!clnt)
1433
 
+               goto report_err;
1434
 
+       /* try to mount hostname:dirname */
1435
 
+       clnt->cl_auth = authunix_create_default();
1436
 
+       return clnt;
1437
 
+ report_err:
1438
 
+       if (report_errs)
1439
 
+               clnt_pcreateerror("mount");
1440
 
+ out_bad:
1441
 
+       return NULL;
1442
 
+}
1443
 
+
1444
 
+static inline void
1445
 
+mnt_closeclnt(CLIENT *clnt, int msock)
1446
 
+{
1447
 
+       auth_destroy(clnt->cl_auth);
1448
 
+       clnt_destroy(clnt);
1449
 
+       close(msock);
1450
 
+}
1451
 
+
1452
 
+static inline enum clnt_stat
1453
 
+nfs3_mount(CLIENT *clnt, mnt3arg_t *mnt3arg, mnt3res_t *mnt3res)
1454
 
+{
1455
 
+       return clnt_call(clnt, MOUNTPROC3_MNT,
1456
 
+                        (xdrproc_t) xdr_dirpath, (caddr_t) mnt3arg,
1457
 
+                        (xdrproc_t) xdr_mountres3, (caddr_t) mnt3res,
1458
 
+                        TIMEOUT);
1459
 
+}
1460
 
+
1461
 
+static inline enum clnt_stat
1462
 
+nfs2_mount(CLIENT *clnt, mnt2arg_t *mnt2arg, mnt2res_t *mnt2res)
1463
 
+{
1464
 
+       return clnt_call(clnt, MOUNTPROC_MNT,
1465
 
+                        (xdrproc_t) xdr_dirpath, (caddr_t) mnt2arg,
1466
 
+                        (xdrproc_t) xdr_fhstatus, (caddr_t) mnt2res,
1467
 
+                        TIMEOUT);
1468
 
+}
1469
 
+
1470
 
+static int
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)
1473
 
+{
1474
 
+       CLIENT *clnt;
1475
 
+       enum clnt_stat stat;
1476
 
+       int msock;
1477
 
+
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");
1488
 
+                       } else {
1489
 
+                               fprintf(stderr, ".\n");
1490
 
+                       }
1491
 
+                       if (verbose) {
1492
 
+                               rpc_strerror();
1493
 
+                       }
1494
 
+               }
1495
 
+               goto out_bad;
1496
 
+       }
1497
 
+
1498
 
+       clnt = mnt_openclnt(mnt_server, &msock, report_errs);
1499
 
+       if (!clnt)
1500
 
+               goto out_bad;
1501
 
+       /* make pointers in xdr_mountres3 NULL so
1502
 
+        * that xdr_array allocates memory for us
1503
 
+        */
1504
 
+       memset(mntres, 0, sizeof(*mntres));
1505
 
+       switch (mnt_server->pmap.pm_vers) {
1506
 
+       case 3:
1507
 
+               stat = nfs3_mount(clnt, mntarg, &mntres->nfsv3);
1508
 
+               break;
1509
 
+       case 2:
1510
 
+       case 1:
1511
 
+               stat = nfs2_mount(clnt, mntarg, &mntres->nfsv2);
1512
 
+               break;
1513
 
+       default:
1514
 
+               goto out_bad;
1515
 
+       }
1516
 
+       if (stat != RPC_SUCCESS && report_errs)
1517
 
+               clnt_perror(clnt, "mount");
1518
 
+       mnt_closeclnt(clnt, msock);
1519
 
+       if (stat == RPC_SUCCESS)
1520
 
+               return 1;
1521
 
+ out_bad:
1522
 
+       return 0;
1523
 
+}
1524
 
+
1525
 
+static int
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)
1529
 
+{
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;
1533
 
+       int len;
1534
 
+       char *opt, *opteq;
1535
 
+       char *mounthost = NULL;
1536
 
+       char cbuf[128];
1537
 
+
1538
 
+       data->flags = 0;
1539
 
+       *bg = 0;
1540
 
+
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);      
1547
 
+                       *opteq = '\0';
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;
1570
 
+                       }
1571
 
+                       else if (!strcmp(opt, "retry"))
1572
 
+                               *retry = val;
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;
1588
 
+                               opt = "nfsvers";
1589
 
+#if NFS_MOUNT_VERSION >= 2
1590
 
+                       } else if (!strcmp(opt, "namlen")) {
1591
 
+                               if (nfs_mount_version >= 2)
1592
 
+                                       data->namlen = val;
1593
 
+                               else if (!sloppy)
1594
 
+                                       goto bad_parameter;
1595
 
 #endif
1596
 
-#if 0
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? */
1601
 
-       if (!p.pm_port)
1602
 
-               p.pm_port = MOUNTPORT;
1603
 
+                       } else if (!strcmp(opt, "addr")) {
1604
 
+                               /* ignore */;
1605
 
+                               continue;
1606
 
+                       } else if (!sloppy)
1607
 
+                               goto bad_parameter;
1608
 
+                       sprintf(cbuf, "%s=%s,", opt, opteq+1);
1609
 
+               } else if (opteq) {
1610
 
+                       *opteq = '\0';
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;
1620
 
 #endif
1621
 
-       return &p;
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);
1630
 
+                                       continue;
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"),
1653
 
+                                               secflavor);
1654
 
+                                       goto bad_parameter;
1655
 
+                               }
1656
 
+                               data->flags |= NFS_MOUNT_SECFLAVOUR;
1657
 
+#endif
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;
1663
 
+                               
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;
1668
 
+                               }
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);
1673
 
+               } else {
1674
 
+                       int val = 1;
1675
 
+                       if (!strncmp(opt, "no", 2)) {
1676
 
+                               val = 0;
1677
 
+                               opt += 2;
1678
 
+                       }
1679
 
+                       if (!strcmp(opt, "bg")) 
1680
 
+                               *bg = val;
1681
 
+                       else if (!strcmp(opt, "fg")) 
1682
 
+                               *bg = !val;
1683
 
+                       else if (!strcmp(opt, "soft")) {
1684
 
+                               data->flags &= ~NFS_MOUNT_SOFT;
1685
 
+                               if (val)
1686
 
+                                       data->flags |= NFS_MOUNT_SOFT;
1687
 
+                       } else if (!strcmp(opt, "hard")) {
1688
 
+                               data->flags &= ~NFS_MOUNT_SOFT;
1689
 
+                               if (!val)
1690
 
+                                       data->flags |= NFS_MOUNT_SOFT;
1691
 
+                       } else if (!strcmp(opt, "intr")) {
1692
 
+                               data->flags &= ~NFS_MOUNT_INTR;
1693
 
+                               if (val)
1694
 
+                                       data->flags |= NFS_MOUNT_INTR;
1695
 
+                       } else if (!strcmp(opt, "posix")) {
1696
 
+                               data->flags &= ~NFS_MOUNT_POSIX;
1697
 
+                               if (val)
1698
 
+                                       data->flags |= NFS_MOUNT_POSIX;
1699
 
+                       } else if (!strcmp(opt, "cto")) {
1700
 
+                               data->flags &= ~NFS_MOUNT_NOCTO;
1701
 
+                               if (!val)
1702
 
+                                       data->flags |= NFS_MOUNT_NOCTO;
1703
 
+                       } else if (!strcmp(opt, "ac")) {
1704
 
+                               data->flags &= ~NFS_MOUNT_NOAC;
1705
 
+                               if (!val)
1706
 
+                                       data->flags |= NFS_MOUNT_NOAC;
1707
 
+#if NFS_MOUNT_VERSION >= 2
1708
 
+                       } else if (!strcmp(opt, "tcp")) {
1709
 
+                               data->flags &= ~NFS_MOUNT_TCP;
1710
 
+                               if (val) {
1711
 
+                                       if (nfs_mount_version < 2)
1712
 
+                                               goto bad_option;
1713
 
+                                       nfs_pmap->pm_prot = IPPROTO_TCP;
1714
 
+                                       data->flags |= NFS_MOUNT_TCP;
1715
 
+                               } else
1716
 
+                                       nfs_pmap->pm_prot = IPPROTO_UDP;
1717
 
+                       } else if (!strcmp(opt, "udp")) {
1718
 
+                               data->flags &= ~NFS_MOUNT_TCP;
1719
 
+                               if (!val) {
1720
 
+                                       if (nfs_mount_version < 2)
1721
 
+                                               goto bad_option;
1722
 
+                                       nfs_pmap->pm_prot = IPPROTO_TCP;
1723
 
+                                       data->flags |= NFS_MOUNT_TCP;
1724
 
+                               } else
1725
 
+                                       nfs_pmap->pm_prot = IPPROTO_UDP;
1726
 
+#endif
1727
 
+#if NFS_MOUNT_VERSION >= 3
1728
 
+                       } else if (!strcmp(opt, "lock")) {
1729
 
+                               data->flags &= ~NFS_MOUNT_NONLM;
1730
 
+                               if (!val) {
1731
 
+                                       if (nfs_mount_version < 3)
1732
 
+                                               goto bad_option;
1733
 
+                                       data->flags |= NFS_MOUNT_NONLM;
1734
 
+                               }
1735
 
+#endif
1736
 
+#if NFS_MOUNT_VERSION >= 4
1737
 
+                       } else if (!strcmp(opt, "broken_suid")) {
1738
 
+                               data->flags &= ~NFS_MOUNT_BROKEN_SUID;
1739
 
+                               if (val) {
1740
 
+                                       if (nfs_mount_version < 4)
1741
 
+                                               goto bad_option;
1742
 
+                                       data->flags |= NFS_MOUNT_BROKEN_SUID;
1743
 
+                               }
1744
 
+#endif
1745
 
+                       } else {
1746
 
+                       bad_option:
1747
 
+                               if (!sloppy) {
1748
 
+                                       printf(_("Unsupported nfs mount option: "
1749
 
+                                                "%s%s\n"), val ? "" : "no", opt);
1750
 
+                                       goto out_bad;
1751
 
+                               }
1752
 
+                       }
1753
 
+                       sprintf(cbuf, val ? "%s,":"no%s,", opt);
1754
 
+               }
1755
 
+               len += strlen(cbuf);
1756
 
+               if (len >= opt_size) {
1757
 
+                       printf(_("mount: excessively long option argument\n"));
1758
 
+                       goto out_bad;
1759
 
+               }
1760
 
+               strcat(new_opts, cbuf);
1761
 
+       }
1762
 
+       /* See if the nfs host = mount host. */
1763
 
+       if (mounthost) {
1764
 
+               if (!nfs_gethostbyname(mounthost, mnt_saddr))
1765
 
+                       goto out_bad;
1766
 
+               *mnt_server->hostname = mounthost;
1767
 
+       }
1768
 
+       return 1;
1769
 
+ bad_parameter:
1770
 
+       printf(_("Bad nfs mount parameter: %s\n"), opt);
1771
 
+ out_bad:
1772
 
+       return 0;
1773
 
 }
1774
 
 
1775
 
-int nfsmount(const char *spec, const char *node, int *flags,
1776
 
-            char **extra_opts, char **mount_opts, int *nfs_mount_vers,
1777
 
-            int running_bg)
1778
 
+static inline int
1779
 
+nfsmnt_check_compat(const struct pmap *nfs_pmap, const struct pmap *mnt_pmap)
1780
 
+{
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"));
1786
 
+               else
1787
 
+                       fprintf(stderr, _("NFS version %ld is not supported.\n"), 
1788
 
+                               nfs_pmap->pm_vers);
1789
 
+               goto out_bad;
1790
 
+       }
1791
 
+       if (mnt_pmap->pm_vers > MAX_MNTPROT) {
1792
 
+               fprintf(stderr, _("NFS mount version %ld s not supported.\n"), 
1793
 
+                       mnt_pmap->pm_vers);
1794
 
+               goto out_bad;
1795
 
+       }
1796
 
+       return 1;
1797
 
+ out_bad:
1798
 
+       return 0;
1799
 
+}
1800
 
+
1801
 
+int
1802
 
+nfsmount(const char *spec, const char *node, int *flags,
1803
 
+        char **extra_opts, char **mount_opts, int *nfs_mount_vers,
1804
 
+        int running_bg)
1805
 
 {
1806
 
        static char *prev_bg_host;
1807
 
        char hostdir[1024];
1808
 
-       CLIENT *mclient;
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;
1817
 
        int val;
1818
 
-       struct hostent *hp;
1819
 
-       struct sockaddr_in server_addr;
1820
 
-       struct sockaddr_in mount_server_addr;
1821
 
-       struct pmap *pm_mnt;
1822
 
-       int msock, fsock;
1823
 
-       struct timeval retry_timeout;
1824
 
-       union {
1825
 
-               struct fhstatus nfsv2;
1826
 
-               struct mountres3 nfsv3;
1827
 
-       } status;
1828
 
+
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;
1835
 
+
1836
 
+       int fsock;
1837
 
+
1838
 
+       mntres_t mntres;
1839
 
+
1840
 
        struct stat statbuf;
1841
 
        char *s;
1842
 
-       int port, mountport, proto, bg, soft, intr;
1843
 
-       int posix, nocto, noac, nolock, broken_suid;
1844
 
-       int retry, tcp;
1845
 
-       int mountprog, mountvers, nfsprog, nfsvers;
1846
 
+       int bg, retry;
1847
 
        int retval;
1848
 
        time_t t;
1849
 
        time_t prevt;
1850
 
@@ -231,8 +851,7 @@
1851
 
        nfs_mount_version = *nfs_mount_vers;
1852
 
 
1853
 
        retval = EX_FAIL;
1854
 
-       msock = fsock = -1;
1855
 
-       mclient = NULL;
1856
 
+       fsock = -1;
1857
 
        if (strlen(spec) >= sizeof(hostdir)) {
1858
 
                fprintf(stderr, _("mount: "
1859
 
                                  "excessively long host:dir argument\n"));
1860
 
@@ -258,49 +877,23 @@
1861
 
                goto fail;
1862
 
        }
1863
 
 
1864
 
-       server_addr.sin_family = AF_INET;
1865
 
-#ifdef HAVE_inet_aton
1866
 
-       if (!inet_aton(hostname, &server_addr.sin_addr))
1867
 
-#endif
1868
 
-       {
1869
 
-               if ((hp = gethostbyname(hostname)) == NULL) {
1870
 
-                       fprintf(stderr, _("mount: can't get address for %s\n"),
1871
 
-                               hostname);
1872
 
-                       goto fail;
1873
 
-               } else {
1874
 
-                       if (hp->h_length > sizeof(struct in_addr)) {
1875
 
-                               fprintf(stderr,
1876
 
-                                       _("mount: got bad hp->h_length\n"));
1877
 
-                               hp->h_length = sizeof(struct in_addr);
1878
 
-                       }
1879
 
-                       memcpy(&server_addr.sin_addr,
1880
 
-                              hp->h_addr, hp->h_length);
1881
 
-               }
1882
 
-       }
1883
 
-
1884
 
-       memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr));
1885
 
+       if (!nfs_gethostbyname(hostname, nfs_saddr))
1886
 
+               goto fail;
1887
 
+       mounthost = hostname;
1888
 
+       memcpy (&mnt_server.saddr, nfs_saddr, sizeof (mnt_server.saddr));
1889
 
 
1890
 
        /* add IP address to mtab options for use when unmounting */
1891
 
 
1892
 
-       s = inet_ntoa(server_addr.sin_addr);
1893
 
+       s = inet_ntoa(nfs_saddr->sin_addr);
1894
 
        old_opts = *extra_opts;
1895
 
        if (!old_opts)
1896
 
                old_opts = "";
1897
 
-       if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) {
1898
 
-               fprintf(stderr, _("mount: "
1899
 
-                                 "excessively long option argument\n"));
1900
 
-               goto fail;
1901
 
-       }
1902
 
-       sprintf(new_opts, "%s%saddr=%s",
1903
 
-               old_opts, *old_opts ? "," : "", s);
1904
 
-       *extra_opts = xstrdup(new_opts);
1905
 
 
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));
1911
 
-       data.retrans    = 3;
1912
 
        data.acregmin   = 3;
1913
 
        data.acregmax   = 60;
1914
 
        data.acdirmin   = 30;
1915
 
@@ -308,169 +901,24 @@
1916
 
 #if NFS_MOUNT_VERSION >= 2
1917
 
        data.namlen     = NAME_MAX;
1918
 
 #endif
1919
 
+       data.pseudoflavor = AUTH_SYS;
1920
 
 
1921
 
        bg = 0;
1922
 
-       soft = 0;
1923
 
-       intr = 0;
1924
 
-       posix = 0;
1925
 
-       nocto = 0;
1926
 
-       nolock = 0;
1927
 
-       broken_suid = 0;
1928
 
-       noac = 0;
1929
 
        retry = 10000;          /* 10000 minutes ~ 1 week */
1930
 
-       tcp = 0;
1931
 
 
1932
 
-       mountprog = MOUNTPROG;
1933
 
-       mountvers = 0;
1934
 
-       port = 0;
1935
 
-       mountport = 0;
1936
 
-       nfsprog = NFS_PROGRAM;
1937
 
-       nfsvers = 0;
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;
1942
 
 
1943
 
        /* parse options */
1944
 
+       new_opts[0] = 0;
1945
 
+       if (!parse_options(old_opts, &data, &bg, &retry, &mnt_server, &nfs_server,
1946
 
+                          new_opts, sizeof(new_opts)))
1947
 
+               goto fail;
1948
 
+       if (!nfsmnt_check_compat(nfs_pmap, mnt_pmap))
1949
 
+               goto fail;
1950
 
 
1951
 
-       for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) {
1952
 
-               if ((opteq = strchr(opt, '='))) {
1953
 
-                       val = atoi(opteq + 1);  
1954
 
-                       *opteq = '\0';
1955
 
-                       if (!strcmp(opt, "rsize"))
1956
 
-                               data.rsize = val;
1957
 
-                       else if (!strcmp(opt, "wsize"))
1958
 
-                               data.wsize = val;
1959
 
-                       else if (!strcmp(opt, "timeo"))
1960
 
-                               data.timeo = val;
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;
1976
 
-                       }
1977
 
-                       else if (!strcmp(opt, "retry"))
1978
 
-                               retry = val;
1979
 
-                       else if (!strcmp(opt, "port"))
1980
 
-                               port = val;
1981
 
-                       else if (!strcmp(opt, "mountport"))
1982
 
-                               mountport = val;
1983
 
-                       else if (!strcmp(opt, "mounthost"))
1984
 
-                               mounthost=xstrndup(opteq+1,
1985
 
-                                                  strcspn(opteq+1," \t\n\r,"));
1986
 
-                       else if (!strcmp(opt, "mountprog"))
1987
 
-                               mountprog = val;
1988
 
-                       else if (!strcmp(opt, "mountvers"))
1989
 
-                               mountvers = val;
1990
 
-                       else if (!strcmp(opt, "nfsprog"))
1991
 
-                               nfsprog = val;
1992
 
-                       else if (!strcmp(opt, "nfsvers") ||
1993
 
-                                !strcmp(opt, "vers"))
1994
 
-                               nfsvers = val;
1995
 
-                       else if (!strcmp(opt, "proto")) {
1996
 
-                               if (!strncmp(opteq+1, "tcp", 3))
1997
 
-                                       tcp = 1;
1998
 
-                               else if (!strncmp(opteq+1, "udp", 3))
1999
 
-                                       tcp = 0;
2000
 
-                               else
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;
2006
 
-                               else
2007
 
-#endif
2008
 
-                                       printf(_("Warning: Option namlen is not supported.\n"));
2009
 
-                       } else if (!strcmp(opt, "addr")) {
2010
 
-                               /* ignore */;
2011
 
-                       } else {
2012
 
-                               printf(_("unknown nfs mount parameter: "
2013
 
-                                        "%s=%d\n"), opt, val);
2014
 
-                               goto fail;
2015
 
-                       }
2016
 
-               } else {
2017
 
-                       val = 1;
2018
 
-                       if (!strncmp(opt, "no", 2)) {
2019
 
-                               val = 0;
2020
 
-                               opt += 2;
2021
 
-                       }
2022
 
-                       if (!strcmp(opt, "bg")) 
2023
 
-                               bg = val;
2024
 
-                       else if (!strcmp(opt, "fg")) 
2025
 
-                               bg = !val;
2026
 
-                       else if (!strcmp(opt, "soft"))
2027
 
-                               soft = val;
2028
 
-                       else if (!strcmp(opt, "hard"))
2029
 
-                               soft = !val;
2030
 
-                       else if (!strcmp(opt, "intr"))
2031
 
-                               intr = val;
2032
 
-                       else if (!strcmp(opt, "posix"))
2033
 
-                               posix = val;
2034
 
-                       else if (!strcmp(opt, "cto"))
2035
 
-                               nocto = !val;
2036
 
-                       else if (!strcmp(opt, "ac"))
2037
 
-                               noac = !val;
2038
 
-                       else if (!strcmp(opt, "tcp"))
2039
 
-                               tcp = val;
2040
 
-                       else if (!strcmp(opt, "udp"))
2041
 
-                               tcp = !val;
2042
 
-                       else if (!strcmp(opt, "lock")) {
2043
 
-                               if (nfs_mount_version >= 3)
2044
 
-                                       nolock = !val;
2045
 
-                               else
2046
 
-                                       printf(_("Warning: option nolock is not supported.\n"));
2047
 
-                       } else if (!strcmp(opt, "broken_suid")) {
2048
 
-                               broken_suid = val;
2049
 
-                       } else {
2050
 
-                               if (!sloppy) {
2051
 
-                                       printf(_("unknown nfs mount option: "
2052
 
-                                                "%s%s\n"), val ? "" : "no", opt);
2053
 
-                                       goto fail;
2054
 
-                               }
2055
 
-                       }
2056
 
-               }
2057
 
-       }
2058
 
-       proto = (tcp) ? IPPROTO_TCP : IPPROTO_UDP;
2059
 
-
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);
2068
 
-#endif
2069
 
-#if NFS_MOUNT_VERSION >= 3
2070
 
-       if (nfs_mount_version >= 3)
2071
 
-               data.flags |= (nolock ? NFS_MOUNT_NONLM : 0);
2072
 
-#endif
2073
 
-#if NFS_MOUNT_VERSION >= 4
2074
 
-       if (nfs_mount_version >= 4)
2075
 
-               data.flags |= (broken_suid ? NFS_MOUNT_BROKEN_SUID : 0);
2076
 
-#endif
2077
 
-       if (nfsvers > MAX_NFSPROT) {
2078
 
-               fprintf(stderr, "NFSv%d not supported!\n", nfsvers);
2079
 
-               return 0;
2080
 
-       }
2081
 
-       if (mountvers > MAX_NFSPROT) {
2082
 
-               fprintf(stderr, "NFSv%d not supported!\n", nfsvers);
2083
 
-               return 0;
2084
 
-       }
2085
 
-       if (nfsvers && !mountvers)
2086
 
-               mountvers = (nfsvers < 3) ? 1 : nfsvers;
2087
 
-       if (nfsvers && nfsvers < mountvers)
2088
 
-               mountvers = nfsvers;
2089
 
-
2090
 
-       /* Adjust options if none specified */
2091
 
-       if (!data.timeo)
2092
 
-               data.timeo = tcp ? 70 : 7;
2093
 
 
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);
2112
 
 #endif
2113
 
+#if NFS_MOUNT_VERSION >= 5
2114
 
+       printf("sec = %u\n", data.pseudoflavor);
2115
 
+#endif
2116
 
 #endif
2117
 
 
2118
 
        data.version = nfs_mount_version;
2119
 
        *mount_opts = (char *) &data;
2120
 
 
2121
 
        if (*flags & MS_REMOUNT)
2122
 
-               return 0;
2123
 
+               goto out_ok;
2124
 
 
2125
 
        /*
2126
 
         * If the previous mount operation on the same host was
2127
 
@@ -512,28 +964,6 @@
2128
 
        }
2129
 
 
2130
 
        /* create mount deamon client */
2131
 
-       /* See if the nfs host = mount host. */
2132
 
-       if (mounthost) {
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);
2136
 
-               } else {
2137
 
-                       if ((hp = gethostbyname(mounthost)) == NULL) {
2138
 
-                               fprintf(stderr, _("mount: can't get address for %s\n"),
2139
 
-                                       mounthost);
2140
 
-                               goto fail;
2141
 
-                       } else {
2142
 
-                               if (hp->h_length > sizeof(struct in_addr)) {
2143
 
-                                       fprintf(stderr,
2144
 
-                                               _("mount: got bad hp->h_length?\n"));
2145
 
-                                       hp->h_length = sizeof(struct in_addr);
2146
 
-                               }
2147
 
-                               mount_server_addr.sin_family = AF_INET;
2148
 
-                               memcpy(&mount_server_addr.sin_addr,
2149
 
-                                      hp->h_addr, hp->h_length);
2150
 
-                       }
2151
 
-               }
2152
 
-       }
2153
 
 
2154
 
        /*
2155
 
         * The following loop implements the mount retries. On the first
2156
 
@@ -551,15 +981,13 @@
2157
 
         *
2158
 
         * Only the first error message will be displayed.
2159
 
         */
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;
2165
 
        prevt = 0;
2166
 
        t = 30;
2167
 
        val = 1;
2168
 
 
2169
 
+       memcpy(&save_nfs, nfs_pmap, sizeof(save_nfs));
2170
 
+       memcpy(&save_mnt, mnt_pmap, sizeof(save_mnt));
2171
 
        for (;;) {
2172
 
                if (bg && stat(node, &statbuf) == -1) {
2173
 
                        /* no mount point yet - sleep */
2174
 
@@ -570,89 +998,18 @@
2175
 
                                        val = 30;
2176
 
                        }
2177
 
                } else {
2178
 
+                       int stat;
2179
 
                        /* be careful not to use too many CPU cycles */
2180
 
                        if (t - prevt < 30)
2181
 
                                sleep(30);
2182
 
 
2183
 
-                       pm_mnt = get_mountport(&mount_server_addr,
2184
 
-                                              mountprog,
2185
 
-                                              mountvers,
2186
 
-                                              proto,
2187
 
-                                              mountport,
2188
 
-                                              nfs_mount_version);
2189
 
-
2190
 
-                       /* contact the mount daemon via TCP */
2191
 
-                       mount_server_addr.sin_port = htons(pm_mnt->pm_port);
2192
 
-                       msock = RPC_ANYSOCK;
2193
 
-
2194
 
-                       switch (pm_mnt->pm_prot) {
2195
 
-                       case IPPROTO_UDP:
2196
 
-                               mclient = clntudp_create(&mount_server_addr,
2197
 
-                                                        pm_mnt->pm_prog,
2198
 
-                                                        pm_mnt->pm_vers,
2199
 
-                                                        retry_timeout,
2200
 
-                                                        &msock);
2201
 
-                               if (mclient)
2202
 
-                                       break;
2203
 
-                               mount_server_addr.sin_port =
2204
 
-                                       htons(pm_mnt->pm_port);
2205
 
-                               msock = RPC_ANYSOCK;
2206
 
-                       case IPPROTO_TCP:
2207
 
-                               mclient = clnttcp_create(&mount_server_addr,
2208
 
-                                                        pm_mnt->pm_prog,
2209
 
-                                                        pm_mnt->pm_vers,
2210
 
-                                                        &msock, 0, 0);
2211
 
+                       stat = nfs_call_mount(&mnt_server, &nfs_server,
2212
 
+                                             &dirname, &mntres,
2213
 
+                                             !running_bg && prevt == 0);
2214
 
+                       if (stat)
2215
 
                                break;
2216
 
-                       default:
2217
 
-                               mclient = 0;
2218
 
-                       }
2219
 
-
2220
 
-                       if (mclient) {
2221
 
-                               /* try to mount hostname:dirname */
2222
 
-                               mclient->cl_auth = authunix_create_default();
2223
 
-
2224
 
-                               /* make pointers in xdr_mountres3 NULL so
2225
 
-                                * that xdr_array allocates memory for us
2226
 
-                                */
2227
 
-                               memset(&status, 0, sizeof(status));
2228
 
-
2229
 
-                               if (pm_mnt->pm_vers == 3)
2230
 
-                                       clnt_stat = clnt_call(mclient,
2231
 
-                                                    MOUNTPROC3_MNT,
2232
 
-                                                    (xdrproc_t) xdr_dirpath,
2233
 
-                                                    (caddr_t) &dirname,
2234
 
-                                                    (xdrproc_t) xdr_mountres3,
2235
 
-                                                    (caddr_t) &status,
2236
 
-                                                    total_timeout);
2237
 
-                               else
2238
 
-                                       clnt_stat = clnt_call(mclient,
2239
 
-                                                    MOUNTPROC_MNT,
2240
 
-                                                    (xdrproc_t) xdr_dirpath,
2241
 
-                                                    (caddr_t) &dirname,
2242
 
-                                                    (xdrproc_t) xdr_fhstatus,
2243
 
-                                                    (caddr_t) &status,
2244
 
-                                                    total_timeout);
2245
 
-
2246
 
-                               if (clnt_stat == RPC_SUCCESS)
2247
 
-                                       break;          /* we're done */
2248
 
-#if 0
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 */
2254
 
-                               }
2255
 
-#endif
2256
 
-                               if (!running_bg && prevt == 0)
2257
 
-                                       clnt_perror(mclient, "mount");
2258
 
-                               auth_destroy(mclient->cl_auth);
2259
 
-                               clnt_destroy(mclient);
2260
 
-                               mclient = 0;
2261
 
-                               close(msock);
2262
 
-                       } else {
2263
 
-                               if (!running_bg && prevt == 0)
2264
 
-                                       clnt_pcreateerror("mount");
2265
 
-                       }
2266
 
+                       memcpy(nfs_pmap, &save_nfs, sizeof(*nfs_pmap));
2267
 
+                       memcpy(mnt_pmap, &save_mnt, sizeof(*mnt_pmap));
2268
 
                        prevt = t;
2269
 
                }
2270
 
 
2271
 
@@ -668,36 +1025,63 @@
2272
 
                if (t >= timeout)
2273
 
                        goto fail;
2274
 
        }
2275
 
-       nfsvers = (pm_mnt->pm_vers < 2) ? 2 : pm_mnt->pm_vers;
2276
 
 
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) {
2281
 
                        fprintf(stderr,
2282
 
-                               "mount: %s:%s failed, reason given by server: %s\n",
2283
 
+                               _("mount: %s:%s failed, reason given by server: %s\n"),
2284
 
                                hostname, dirname,
2285
 
-                               nfs_strerror(status.nfsv2.fhs_status));
2286
 
+                               nfs_strerror(mntres.nfsv2.fhs_status));
2287
 
                        goto fail;
2288
 
                }
2289
 
                memcpy(data.root.data,
2290
 
-                      (char *) status.nfsv2.fhstatus_u.fhs_fhandle,
2291
 
+                      (char *) mntres.nfsv2.fhstatus_u.fhs_fhandle,
2292
 
                       NFS_FHSIZE);
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,
2298
 
                       NFS_FHSIZE);
2299
 
 #endif
2300
 
        } else {
2301
 
 #if NFS_MOUNT_VERSION >= 4
2302
 
+               mountres3_ok *mountres;
2303
 
                fhandle3 *fhandle;
2304
 
-               if (status.nfsv3.fhs_status != 0) {
2305
 
+               int i, *flavor, yum = 0;
2306
 
+               if (mntres.nfsv3.fhs_status != 0) {
2307
 
                        fprintf(stderr,
2308
 
-                               "mount: %s:%s failed, reason given by server: %s\n",
2309
 
+                               _("mount: %s:%s failed, reason given by server: %s\n"),
2310
 
                                hostname, dirname,
2311
 
-                               nfs_strerror(status.nfsv3.fhs_status));
2312
 
+                               nfs_strerror(mntres.nfsv3.fhs_status));
2313
 
                        goto fail;
2314
 
                }
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;
2319
 
+               if (i <= 0) 
2320
 
+                       goto noauth_flavours;
2321
 
+
2322
 
+               flavor = mountres->auth_flavours.auth_flavours_val;
2323
 
+               while (--i >= 0) {
2324
 
+                       if (flavor[i] == data.pseudoflavor)
2325
 
+                               yum = 1;
2326
 
+#ifdef NFS_MOUNT_DEBUG
2327
 
+                       printf("auth flavor %d: %d\n",
2328
 
+                               i, flavor[i]);
2329
 
+#endif
2330
 
+               }
2331
 
+               if (!yum) {
2332
 
+                       fprintf(stderr,
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);
2338
 
+                       goto fail;
2339
 
+               }
2340
 
+noauth_flavours:
2341
 
+#endif
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 @@
2347
 
 
2348
 
        /* create nfs socket for kernel */
2349
 
 
2350
 
-       if (tcp) {
2351
 
-               if (nfs_mount_version < 3) {
2352
 
-                       printf(_("NFS over TCP is not supported.\n"));
2353
 
-                       goto fail;
2354
 
-               }
2355
 
+       if (nfs_pmap->pm_prot == IPPROTO_TCP)
2356
 
                fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
2357
 
-       } else
2358
 
+       else
2359
 
                fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
2360
 
        if (fsock < 0) {
2361
 
                perror(_("nfs socket"));
2362
 
@@ -727,72 +1107,163 @@
2363
 
                perror(_("nfs bindresvport"));
2364
 
                goto fail;
2365
 
        }
2366
 
-       if (port == 0) {
2367
 
-               server_addr.sin_port = PMAPPORT;
2368
 
-               port = pmap_getport(&server_addr, nfsprog, nfsvers,
2369
 
-                                   tcp ? IPPROTO_TCP : IPPROTO_UDP);
2370
 
-#if 1
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.
2375
 
-                */
2376
 
-               if (port == 0 && tcp == 1) {
2377
 
-                       perror(_("nfs server reported service unavailable"));
2378
 
-                       goto fail;
2379
 
-               }
2380
 
-#endif
2381
 
-
2382
 
-               if (port == 0)
2383
 
-                       port = NFS_PORT;
2384
 
-#ifdef NFS_MOUNT_DEBUG
2385
 
-               else
2386
 
-                       printf(_("used portmapper to find NFS port\n"));
2387
 
-#endif
2388
 
-       }
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);
2392
 
 #endif
2393
 
-       server_addr.sin_port = htons(port);
2394
 
+       nfs_saddr->sin_port = htons(nfs_pmap->pm_port);
2395
 
        /*
2396
 
         * connect() the socket for kernels 1.3.10 and below only,
2397
 
         * to avoid problems with multihomed hosts.
2398
 
         * --Swen
2399
 
         */
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"));
2406
 
                goto fail;
2407
 
        }
2408
 
 
2409
 
+#if NFS_MOUNT_VERSION >= 2
2410
 
+       if (nfs_pmap->pm_prot == IPPROTO_TCP)
2411
 
+               data.flags |= NFS_MOUNT_TCP;
2412
 
+       else
2413
 
+               data.flags &= ~NFS_MOUNT_TCP;
2414
 
+#endif
2415
 
+
2416
 
        /* prepare data structure for kernel */
2417
 
 
2418
 
        data.fd = fsock;
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));
2422
 
 
2423
 
-       /* clean up */
2424
 
+ out_ok:
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"));
2429
 
+               goto fail;
2430
 
+       }
2431
 
 
2432
 
-       auth_destroy(mclient->cl_auth);
2433
 
-       clnt_destroy(mclient);
2434
 
-       close(msock);
2435
 
+       snprintf(cbuf, sizeof(cbuf)-1, "addr=%s", s);
2436
 
+       strcat(new_opts, cbuf);
2437
 
+
2438
 
+       *extra_opts = xstrdup(new_opts);
2439
 
        return 0;
2440
 
 
2441
 
        /* abort */
2442
 
-
2443
 
  fail:
2444
 
-       if (msock != -1) {
2445
 
-               if (mclient) {
2446
 
-                       auth_destroy(mclient->cl_auth);
2447
 
-                       clnt_destroy(mclient);
2448
 
-               }
2449
 
-               close(msock);
2450
 
-       }
2451
 
        if (fsock != -1)
2452
 
                close(fsock);
2453
 
        return retval;
2454
 
-}      
2455
 
+}
2456
 
+
2457
 
+static inline enum clnt_stat
2458
 
+nfs3_umount(dirpath *argp, CLIENT *clnt)
2459
 
+{
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,
2465
 
+                        TIMEOUT);
2466
 
+}
2467
 
+
2468
 
+static inline enum clnt_stat
2469
 
+nfs2_umount(dirpath *argp, CLIENT *clnt)
2470
 
+{
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,
2476
 
+                        TIMEOUT);
2477
 
+}
2478
 
+
2479
 
+static int
2480
 
+nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp)
2481
 
+{
2482
 
+       CLIENT *clnt;
2483
 
+       enum clnt_stat res = 0;
2484
 
+       int msock;
2485
 
+
2486
 
+       clnt = mnt_openclnt(mnt_server, &msock, 1);
2487
 
+       if (!clnt)
2488
 
+               goto out_bad;
2489
 
+       switch (mnt_server->pmap.pm_vers) {
2490
 
+       case 3:
2491
 
+               res = nfs3_umount(argp, clnt);
2492
 
+               break;
2493
 
+       case 2:
2494
 
+       case 1:
2495
 
+               res = nfs2_umount(argp, clnt);
2496
 
+               break;
2497
 
+       default:
2498
 
+               break;
2499
 
+       }
2500
 
+       mnt_closeclnt(clnt, msock);
2501
 
+       if (res == RPC_SUCCESS)
2502
 
+               return 1;
2503
 
+ out_bad:
2504
 
+       return 0;
2505
 
+}
2506
 
+
2507
 
+int
2508
 
+nfsumount(const char *spec, const char *opts)
2509
 
+{
2510
 
+       char *hostname;
2511
 
+       char *dirname;
2512
 
+       clnt_addr_t mnt_server = { &hostname, };
2513
 
+       struct pmap *pmap = &mnt_server.pmap;
2514
 
+       char *p;
2515
 
+
2516
 
+       nfs_mount_version = find_kernel_nfs_mount_version();
2517
 
+       if (spec == NULL || (p = strchr(spec,':')) == NULL)
2518
 
+               goto out_bad;
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);
2523
 
+#endif
2524
 
+
2525
 
+       if (opts && (p = strstr(opts, "addr="))) {
2526
 
+               char *q;
2527
 
+
2528
 
+               free(hostname);
2529
 
+               p += 5;
2530
 
+               q = p;
2531
 
+               while (*q && *q != ',') q++;
2532
 
+               hostname = xstrndup(p,q-p);
2533
 
+       }
2534
 
+
2535
 
+       if (opts && (p = strstr(opts, "mounthost="))) {
2536
 
+               char *q;
2537
 
+
2538
 
+               free(hostname);
2539
 
+               p += 10;
2540
 
+               q = p;
2541
 
+               while (*q && *q != ',') q++;
2542
 
+               hostname = xstrndup(p,q-p);
2543
 
+       }
2544
 
+
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);
2555
 
+
2556
 
+       if (!nfs_gethostbyname(hostname, &mnt_server.saddr))
2557
 
+               goto out_bad;
2558
 
+       if (!probe_mntport(&mnt_server))
2559
 
+               goto out_bad;
2560
 
+       return nfs_call_umount(&mnt_server, &dirname);
2561
 
+ out_bad:
2562
 
+       return 0;
2563
 
+}
2564
 
 
2565
 
 /*
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
2570
 
@@ -37,6 +37,9 @@
2571
 
 #ifdef HAVE_NFS
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);
2577
 
 #endif
2578
 
 
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
2583
 
@@ -90,6 +90,11 @@
2584
 
 /* True if ruid != euid.  */
2585
 
 int suid = 0;
2586
 
 
2587
 
+/* Needed by nfs4mount.c */
2588
 
+int sloppy = 0;
2589
 
+
2590
 
+
2591
 
+
2592
 
 /*
2593
 
  * check_special_umountprog()
2594
 
  *     If there is a special umount program for this type, exec it.
2595
 
@@ -297,7 +302,7 @@
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);
2601
 
 #endif
2602
 
  
2603
 
        umnt_err = umnt_err2 = 0;