Annotation of /trunk/util-linux/patches/util-linux-2.12i-nfsv4.patch
Parent Directory | Revision Log
Revision 153 -
(hide annotations)
(download)
Tue May 8 20:52:56 2007 UTC (17 years, 4 months ago) by niro
File size: 12854 byte(s)
Tue May 8 20:52:56 2007 UTC (17 years, 4 months ago) by niro
File size: 12854 byte(s)
-import
1 | niro | 153 | diff -ur util-linux-2.12i.orig/mount/Makefile util-linux-2.12i/mount/Makefile |
2 | --- util-linux-2.12i.orig/mount/Makefile 2004-11-11 20:03:33.032897551 -0500 | ||
3 | +++ util-linux-2.12i/mount/Makefile 2004-11-11 20:04:38.279986828 -0500 | ||
4 | @@ -29,2 +29,4 @@ | ||
5 | |||
6 | +NFS_OBJS += nfs4mount.o | ||
7 | +GEN_FILES += nfs4mount.c | ||
8 | all: $(PROGS) | ||
9 | diff -ur util-linux-2.12i.orig/mount/mount.c util-linux-2.12i/mount/mount.c | ||
10 | --- util-linux-2.12i.orig/mount/mount.c 2004-11-11 20:03:33.033897369 -0500 | ||
11 | +++ util-linux-2.12i/mount/mount.c 2004-11-11 20:03:40.384555521 -0500 | ||
12 | @@ -810,6 +810,19 @@ | ||
13 | "without support for the type `nfs'")); | ||
14 | #endif | ||
15 | } | ||
16 | +#ifdef HAVE_NFS | ||
17 | + /* | ||
18 | + * NFSv4 support | ||
19 | + */ | ||
20 | + if (!fake && types && streq (types, "nfs4")) { | ||
21 | + mnt_err = nfs4mount(spec, node, &flags, &extra_opts, &mount_opts, bg); | ||
22 | + if (mnt_err) | ||
23 | + return mnt_err; | ||
24 | +#else | ||
25 | + die (EX_SOFTWARE, _("mount: this version was compiled " | ||
26 | + "without support for the type `nfs4'")); | ||
27 | +#endif | ||
28 | + } | ||
29 | |||
30 | block_signals (SIG_BLOCK); | ||
31 | |||
32 | diff -ur util-linux-2.12i.orig/mount/sundries.h util-linux-2.12i/mount/sundries.h | ||
33 | --- util-linux-2.12i.orig/mount/sundries.h 2004-11-11 20:03:33.034897186 -0500 | ||
34 | +++ util-linux-2.12i/mount/sundries.h 2004-11-11 20:03:40.386555156 -0500 | ||
35 | @@ -37,6 +37,8 @@ | ||
36 | #ifdef HAVE_NFS | ||
37 | int nfsmount (const char *spec, const char *node, int *flags, | ||
38 | char **orig_opts, char **opt_args, int *version, int running_bg); | ||
39 | +int nfs4mount (const char *spec, const char *node, int *flags, | ||
40 | + char **orig_opts, char **opt_args, int running_bg); | ||
41 | #endif | ||
42 | |||
43 | /* exit status - bits below are ORed */ | ||
44 | diff -puN /dev/null mount/nfs4_mount.h | ||
45 | --- /dev/null 2003-01-08 17:56:04.000000000 -0500 | ||
46 | +++ util-linux-2.11z-bfields/mount/nfs4_mount.h 2003-04-23 16:40:57.000000000 -0400 | ||
47 | @@ -0,0 +1,82 @@ | ||
48 | +#ifndef _LINUX_NFS4_MOUNT_H | ||
49 | +#define _LINUX_NFS4_MOUNT_H | ||
50 | + | ||
51 | +/* | ||
52 | + * linux/include/linux/nfs4_mount.h | ||
53 | + * | ||
54 | + * Copyright (C) 2002 Trond Myklebust | ||
55 | + * | ||
56 | + * structure passed from user-space to kernel-space during an nfsv4 mount | ||
57 | + */ | ||
58 | + | ||
59 | +/* | ||
60 | + * WARNING! Do not delete or change the order of these fields. If | ||
61 | + * a new field is required then add it to the end. The version field | ||
62 | + * tracks which fields are present. This will ensure some measure of | ||
63 | + * mount-to-kernel version compatibility. Some of these aren't used yet | ||
64 | + * but here they are anyway. | ||
65 | + */ | ||
66 | +#define NFS4_MOUNT_VERSION 1 | ||
67 | + | ||
68 | +struct nfs_string { | ||
69 | + unsigned int len; | ||
70 | + const char* data; | ||
71 | +}; | ||
72 | + | ||
73 | +struct nfs4_mount_data { | ||
74 | + int version; /* 1 */ | ||
75 | + int flags; /* 1 */ | ||
76 | + int rsize; /* 1 */ | ||
77 | + int wsize; /* 1 */ | ||
78 | + int timeo; /* 1 */ | ||
79 | + int retrans; /* 1 */ | ||
80 | + int acregmin; /* 1 */ | ||
81 | + int acregmax; /* 1 */ | ||
82 | + int acdirmin; /* 1 */ | ||
83 | + int acdirmax; /* 1 */ | ||
84 | + | ||
85 | + /* see the definition of 'struct clientaddr4' in RFC3010 */ | ||
86 | + struct nfs_string client_addr; /* 1 */ | ||
87 | + | ||
88 | + /* Mount path */ | ||
89 | + struct nfs_string mnt_path; /* 1 */ | ||
90 | + | ||
91 | + /* Server details */ | ||
92 | + struct nfs_string hostname; /* 1 */ | ||
93 | + /* Server IP address */ | ||
94 | + unsigned int host_addrlen; /* 1 */ | ||
95 | + struct sockaddr* host_addr; /* 1 */ | ||
96 | + | ||
97 | + /* Transport protocol to use */ | ||
98 | + int proto; /* 1 */ | ||
99 | + | ||
100 | + /* Pseudo-flavours to use for authentication. See RFC2623 */ | ||
101 | + int auth_flavourlen; /* 1 */ | ||
102 | + int *auth_flavours; /* 1 */ | ||
103 | +}; | ||
104 | + | ||
105 | +/* bits in the flags field */ | ||
106 | +/* Note: the fields that correspond to existing NFSv2/v3 mount options | ||
107 | + * should mirror the values from include/linux/nfs_mount.h | ||
108 | + */ | ||
109 | + | ||
110 | +#define NFS4_MOUNT_SOFT 0x0001 /* 1 */ | ||
111 | +#define NFS4_MOUNT_INTR 0x0002 /* 1 */ | ||
112 | +#define NFS4_MOUNT_NOCTO 0x0010 /* 1 */ | ||
113 | +#define NFS4_MOUNT_NOAC 0x0020 /* 1 */ | ||
114 | +#define NFS4_MOUNT_STRICTLOCK 0x1000 /* 1 */ | ||
115 | +#define NFS4_MOUNT_FLAGMASK 0xFFFF | ||
116 | + | ||
117 | +/* pseudoflavors: */ | ||
118 | + | ||
119 | +#define RPC_AUTH_GSS_KRB5 390003 | ||
120 | +#define RPC_AUTH_GSS_KRB5I 390004 | ||
121 | +#define RPC_AUTH_GSS_KRB5P 390005 | ||
122 | +#define RPC_AUTH_GSS_LKEY 390006 | ||
123 | +#define RPC_AUTH_GSS_LKEYI 390007 | ||
124 | +#define RPC_AUTH_GSS_LKEYP 390008 | ||
125 | +#define RPC_AUTH_GSS_SPKM 390009 | ||
126 | +#define RPC_AUTH_GSS_SPKMI 390010 | ||
127 | +#define RPC_AUTH_GSS_SPKMP 390011 | ||
128 | + | ||
129 | +#endif | ||
130 | diff -puN /dev/null mount/nfs4mount.c | ||
131 | --- /dev/null 2003-01-08 17:56:04.000000000 -0500 | ||
132 | +++ util-linux-2.11z-bfields/mount/nfs4mount.c 2003-04-23 17:28:54.000000000 -0400 | ||
133 | @@ -0,0 +1,323 @@ | ||
134 | +/* | ||
135 | + * nfs4mount.c -- Linux NFS mount | ||
136 | + * Copyright (C) 2002 Trond Myklebust <trond.myklebust@fys.uio.no> | ||
137 | + * | ||
138 | + * This program is free software; you can redistribute it and/or modify | ||
139 | + * it under the terms of the GNU General Public License as published by | ||
140 | + * the Free Software Foundation; either version 2, or (at your option) | ||
141 | + * any later version. | ||
142 | + * | ||
143 | + * This program is distributed in the hope that it will be useful, | ||
144 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
145 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
146 | + * GNU General Public License for more details. | ||
147 | + * | ||
148 | + * Note: this file based on the original nfsmount.c | ||
149 | + */ | ||
150 | + | ||
151 | +#include "../defines.h" /* for HAVE_rpcsvc_nfs_prot_h and HAVE_inet_aton */ | ||
152 | + | ||
153 | +#include <linux/posix_types.h> | ||
154 | +#include <asm/posix_types.h> | ||
155 | +#undef __FD_CLR | ||
156 | +#undef __FD_SET | ||
157 | +#undef __FD_ISSET | ||
158 | +#undef __FD_ZERO | ||
159 | + | ||
160 | +#include <unistd.h> | ||
161 | +#include <stdio.h> | ||
162 | +#include <string.h> | ||
163 | +#include <errno.h> | ||
164 | +#include <netdb.h> | ||
165 | +#include <time.h> | ||
166 | +#include <sys/socket.h> | ||
167 | +#include <sys/time.h> | ||
168 | +#include <sys/utsname.h> | ||
169 | +#include <sys/stat.h> | ||
170 | +#include <netinet/in.h> | ||
171 | +#include <arpa/inet.h> | ||
172 | + | ||
173 | +#include "sundries.h" | ||
174 | + | ||
175 | +#include "mount_constants.h" | ||
176 | +#include "nfs4_mount.h" | ||
177 | + | ||
178 | +#include "nls.h" | ||
179 | + | ||
180 | +#ifndef NFS_PORT | ||
181 | +#define NFS_PORT 2049 | ||
182 | +#endif | ||
183 | + | ||
184 | +static int parse_devname(char *hostdir, char **hostname, char **dirname) | ||
185 | +{ | ||
186 | + char *s; | ||
187 | + | ||
188 | + if (!(s = strchr(hostdir, ':'))) { | ||
189 | + fprintf(stderr, | ||
190 | + _("mount: " | ||
191 | + "directory to mount not in host:dir format\n")); | ||
192 | + return -1; | ||
193 | + } | ||
194 | + *hostname = hostdir; | ||
195 | + *dirname = s + 1; | ||
196 | + *s = '\0'; | ||
197 | + /* Ignore all but first hostname in replicated mounts | ||
198 | + until they can be fully supported. (mack@sgi.com) */ | ||
199 | + if ((s = strchr(hostdir, ','))) { | ||
200 | + *s = '\0'; | ||
201 | + fprintf(stderr, | ||
202 | + _("mount: warning: " | ||
203 | + "multiple hostnames not supported\n")); | ||
204 | + } | ||
205 | + return 0; | ||
206 | +} | ||
207 | + | ||
208 | +static int fill_ipv4_sockaddr(const char *hostname, struct sockaddr_in *addr) | ||
209 | +{ | ||
210 | + struct hostent *hp; | ||
211 | + addr->sin_family = AF_INET; | ||
212 | + | ||
213 | + if (inet_aton(hostname, &addr->sin_addr)) | ||
214 | + return 0; | ||
215 | + if ((hp = gethostbyname(hostname)) == NULL) { | ||
216 | + fprintf(stderr, _("mount: can't get address for %s\n"), | ||
217 | + hostname); | ||
218 | + return -1; | ||
219 | + } | ||
220 | + if (hp->h_length > sizeof(struct in_addr)) { | ||
221 | + fprintf(stderr, | ||
222 | + _("mount: got bad hp->h_length\n")); | ||
223 | + hp->h_length = sizeof(struct in_addr); | ||
224 | + } | ||
225 | + memcpy(&addr->sin_addr, hp->h_addr, hp->h_length); | ||
226 | + return 0; | ||
227 | +} | ||
228 | + | ||
229 | +static int get_my_ipv4addr(char *ip_addr, int len) | ||
230 | +{ | ||
231 | + char myname[1024]; | ||
232 | + struct sockaddr_in myaddr; | ||
233 | + | ||
234 | + if (gethostname(myname, sizeof(myname))) { | ||
235 | + fprintf(stderr, _("mount: can't determine client address\n")); | ||
236 | + return -1; | ||
237 | + } | ||
238 | + if (fill_ipv4_sockaddr(myname, &myaddr)) | ||
239 | + return -1; | ||
240 | + snprintf(ip_addr, len, "%s", inet_ntoa(myaddr.sin_addr)); | ||
241 | + ip_addr[len-1] = '\0'; | ||
242 | + return 0; | ||
243 | +} | ||
244 | + | ||
245 | +int nfs4mount(const char *spec, const char *node, int *flags, | ||
246 | + char **extra_opts, char **mount_opts, | ||
247 | + int running_bg) | ||
248 | +{ | ||
249 | + static struct nfs4_mount_data data; | ||
250 | + static char hostdir[1024]; | ||
251 | + static char ip_addr[16] = "127.0.0.1"; | ||
252 | + static struct sockaddr_in server_addr; | ||
253 | + static int pseudoflavour = 0; | ||
254 | + | ||
255 | + char *hostname, *dirname, *old_opts; | ||
256 | + char new_opts[1024]; | ||
257 | + char *opt, *opteq; | ||
258 | + char *s; | ||
259 | + int val; | ||
260 | + int port, bg, soft, intr; | ||
261 | + int nocto, noac; | ||
262 | + int retry; | ||
263 | + int retval; | ||
264 | + | ||
265 | + retval = EX_FAIL; | ||
266 | + if (strlen(spec) >= sizeof(hostdir)) { | ||
267 | + fprintf(stderr, _("mount: " | ||
268 | + "excessively long host:dir argument\n")); | ||
269 | + goto fail; | ||
270 | + } | ||
271 | + strcpy(hostdir, spec); | ||
272 | + if (parse_devname(hostdir, &hostname, &dirname)) | ||
273 | + goto fail; | ||
274 | + | ||
275 | + if (fill_ipv4_sockaddr(hostname, &server_addr)) | ||
276 | + goto fail; | ||
277 | + if (get_my_ipv4addr(ip_addr, sizeof(ip_addr))) | ||
278 | + goto fail; | ||
279 | + | ||
280 | + /* add IP address to mtab options for use when unmounting */ | ||
281 | + s = inet_ntoa(server_addr.sin_addr); | ||
282 | + old_opts = *extra_opts; | ||
283 | + if (!old_opts) | ||
284 | + old_opts = ""; | ||
285 | + if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) { | ||
286 | + fprintf(stderr, _("mount: " | ||
287 | + "excessively long option argument\n")); | ||
288 | + goto fail; | ||
289 | + } | ||
290 | + snprintf(new_opts, sizeof(new_opts), "%s%saddr=%s", | ||
291 | + old_opts, *old_opts ? "," : "", s); | ||
292 | + *extra_opts = xstrdup(new_opts); | ||
293 | + | ||
294 | + /* Set default options. | ||
295 | + * rsize/wsize and timeo are left 0 in order to | ||
296 | + * let the kernel decide. | ||
297 | + */ | ||
298 | + memset(&data, 0, sizeof(data)); | ||
299 | + data.retrans = 3; | ||
300 | + data.acregmin = 3; | ||
301 | + data.acregmax = 60; | ||
302 | + data.acdirmin = 30; | ||
303 | + data.acdirmax = 60; | ||
304 | + data.proto = IPPROTO_TCP; | ||
305 | + | ||
306 | + bg = 0; | ||
307 | + soft = 0; | ||
308 | + intr = 0; | ||
309 | + nocto = 0; | ||
310 | + noac = 0; | ||
311 | + retry = 10000; /* 10000 minutes ~ 1 week */ | ||
312 | + | ||
313 | + /* | ||
314 | + * NFSv4 specifies that the default port should be 2049 | ||
315 | + */ | ||
316 | + port = NFS_PORT; | ||
317 | + | ||
318 | + /* parse options */ | ||
319 | + | ||
320 | + for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) { | ||
321 | + if ((opteq = strchr(opt, '='))) { | ||
322 | + val = atoi(opteq + 1); | ||
323 | + *opteq = '\0'; | ||
324 | + if (!strcmp(opt, "rsize")) | ||
325 | + data.rsize = val; | ||
326 | + else if (!strcmp(opt, "wsize")) | ||
327 | + data.wsize = val; | ||
328 | + else if (!strcmp(opt, "timeo")) | ||
329 | + data.timeo = val; | ||
330 | + else if (!strcmp(opt, "retrans")) | ||
331 | + data.retrans = val; | ||
332 | + else if (!strcmp(opt, "acregmin")) | ||
333 | + data.acregmin = val; | ||
334 | + else if (!strcmp(opt, "acregmax")) | ||
335 | + data.acregmax = val; | ||
336 | + else if (!strcmp(opt, "acdirmin")) | ||
337 | + data.acdirmin = val; | ||
338 | + else if (!strcmp(opt, "acdirmax")) | ||
339 | + data.acdirmax = val; | ||
340 | + else if (!strcmp(opt, "actimeo")) { | ||
341 | + data.acregmin = val; | ||
342 | + data.acregmax = val; | ||
343 | + data.acdirmin = val; | ||
344 | + data.acdirmax = val; | ||
345 | + } | ||
346 | + else if (!strcmp(opt, "retry")) | ||
347 | + retry = val; | ||
348 | + else if (!strcmp(opt, "port")) | ||
349 | + port = val; | ||
350 | + else if (!strcmp(opt, "proto")) { | ||
351 | + if (!strncmp(opteq+1, "tcp", 3)) | ||
352 | + data.proto = IPPROTO_TCP; | ||
353 | + else if (!strncmp(opteq+1, "udp", 3)) | ||
354 | + data.proto = IPPROTO_UDP; | ||
355 | + else | ||
356 | + printf(_("Warning: Unrecognized proto= option.\n")); | ||
357 | + } else if (!strcmp(opt, "clientaddr")) { | ||
358 | + if (strlen(opteq+1) >= sizeof(ip_addr)) | ||
359 | + printf(_("Invalid client address %s"), | ||
360 | + opteq+1); | ||
361 | + strncpy(ip_addr,opteq+1, sizeof(ip_addr)); | ||
362 | + ip_addr[sizeof(ip_addr)-1] = '\0'; | ||
363 | + } else if (!strcmp(opt, "sec")) { | ||
364 | + if (!strncmp(opteq+1, "krb5i",5)) | ||
365 | + pseudoflavour = 390004; | ||
366 | + else if (!strncmp(opteq+1, "krb5p",5)) | ||
367 | + pseudoflavour = 390005; | ||
368 | + else if (!strncmp(opteq+1, "krb5",4)) | ||
369 | + pseudoflavour = 390003; | ||
370 | + else { | ||
371 | + printf(_("unknown security type %s\n"), | ||
372 | + opteq+1); | ||
373 | + goto fail; | ||
374 | + } | ||
375 | + } else if (!strcmp(opt, "addr")) { | ||
376 | + /* ignore */; | ||
377 | + } else { | ||
378 | + printf(_("unknown nfs mount parameter: " | ||
379 | + "%s=%d\n"), opt, val); | ||
380 | + goto fail; | ||
381 | + } | ||
382 | + } else { | ||
383 | + val = 1; | ||
384 | + if (!strncmp(opt, "no", 2)) { | ||
385 | + val = 0; | ||
386 | + opt += 2; | ||
387 | + } | ||
388 | + if (!strcmp(opt, "bg")) | ||
389 | + bg = val; | ||
390 | + else if (!strcmp(opt, "fg")) | ||
391 | + bg = !val; | ||
392 | + else if (!strcmp(opt, "soft")) | ||
393 | + soft = val; | ||
394 | + else if (!strcmp(opt, "hard")) | ||
395 | + soft = !val; | ||
396 | + else if (!strcmp(opt, "intr")) | ||
397 | + intr = val; | ||
398 | + else if (!strcmp(opt, "cto")) | ||
399 | + nocto = !val; | ||
400 | + else if (!strcmp(opt, "ac")) | ||
401 | + noac = !val; | ||
402 | + else { | ||
403 | + if (!sloppy) { | ||
404 | + printf(_("unknown nfs mount option: " | ||
405 | + "%s%s\n"), val ? "" : "no", opt); | ||
406 | + goto fail; | ||
407 | + } | ||
408 | + } | ||
409 | + } | ||
410 | + } | ||
411 | + | ||
412 | + data.flags = (soft ? NFS4_MOUNT_SOFT : 0) | ||
413 | + | (intr ? NFS4_MOUNT_INTR : 0) | ||
414 | + | (nocto ? NFS4_MOUNT_NOCTO : 0) | ||
415 | + | (noac ? NFS4_MOUNT_NOAC : 0); | ||
416 | + | ||
417 | + if (pseudoflavour != 0) { | ||
418 | + data.auth_flavourlen = 1; | ||
419 | + data.auth_flavours = &pseudoflavour; | ||
420 | + } | ||
421 | + | ||
422 | + data.client_addr.data = ip_addr; | ||
423 | + data.client_addr.len = strlen(ip_addr); | ||
424 | + | ||
425 | + data.mnt_path.data = dirname; | ||
426 | + data.mnt_path.len = strlen(dirname); | ||
427 | + | ||
428 | + data.hostname.data = hostname; | ||
429 | + data.hostname.len = strlen(hostname); | ||
430 | + data.host_addr = (struct sockaddr *)&server_addr; | ||
431 | + data.host_addrlen = sizeof(server_addr); | ||
432 | + | ||
433 | +#ifdef NFS_MOUNT_DEBUG | ||
434 | + printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n", | ||
435 | + data.rsize, data.wsize, data.timeo, data.retrans); | ||
436 | + printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n", | ||
437 | + data.acregmin, data.acregmax, data.acdirmin, data.acdirmax); | ||
438 | + printf("port = %d, bg = %d, retry = %d, flags = %.8x\n", | ||
439 | + port, bg, retry, data.flags); | ||
440 | + printf("soft = %d, intr = %d, nocto = %d, noac = %d\n", | ||
441 | + (data.flags & NFS4_MOUNT_SOFT) != 0, | ||
442 | + (data.flags & NFS4_MOUNT_INTR) != 0, | ||
443 | + (data.flags & NFS4_MOUNT_NOCTO) != 0, | ||
444 | + (data.flags & NFS4_MOUNT_NOAC) != 0); | ||
445 | + printf("proto = %s\n", (data.proto == IPPROTO_TCP) ? "tcp" : "udp"); | ||
446 | +#endif | ||
447 | + | ||
448 | + data.version = NFS4_MOUNT_VERSION; | ||
449 | + | ||
450 | + *mount_opts = (char *) &data; | ||
451 | + /* clean up */ | ||
452 | + return 0; | ||
453 | + | ||
454 | +fail: | ||
455 | + return retval; | ||
456 | +} |