aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2009-08-10 17:45:50 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2009-08-10 17:45:50 -0400
commit976a6f921cad26651d25e73826c05c7a023f5fa4 (patch)
treeb06e283e3fe342bcf444328390b211bb155fd9dc /fs
parente576e05a73bc1a00cdf56630942dbada1bf280a1 (diff)
parentc05988cdb06237738d361ef82fbf4df1020aa3db (diff)
Merge branch 'patches_cel-for-2.6.32' into nfs-for-2.6.32
Diffstat (limited to 'fs')
-rw-r--r--fs/lockd/host.c14
-rw-r--r--fs/lockd/mon.c44
-rw-r--r--fs/nfs/internal.h23
-rw-r--r--fs/nfs/mount_clnt.c79
-rw-r--r--fs/nfs/nfs4namespace.c8
-rw-r--r--fs/nfs/super.c247
-rw-r--r--fs/nfsd/nfsctl.c21
7 files changed, 184 insertions, 252 deletions
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 99d737bd4325..7cb076ac6b45 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -87,18 +87,6 @@ static unsigned int nlm_hash_address(const struct sockaddr *sap)
87 return hash & (NLM_HOST_NRHASH - 1); 87 return hash & (NLM_HOST_NRHASH - 1);
88} 88}
89 89
90static void nlm_clear_port(struct sockaddr *sap)
91{
92 switch (sap->sa_family) {
93 case AF_INET:
94 ((struct sockaddr_in *)sap)->sin_port = 0;
95 break;
96 case AF_INET6:
97 ((struct sockaddr_in6 *)sap)->sin6_port = 0;
98 break;
99 }
100}
101
102/* 90/*
103 * Common host lookup routine for server & client 91 * Common host lookup routine for server & client
104 */ 92 */
@@ -177,7 +165,7 @@ static struct nlm_host *nlm_lookup_host(struct nlm_lookup_host_info *ni)
177 host->h_addrbuf = nsm->sm_addrbuf; 165 host->h_addrbuf = nsm->sm_addrbuf;
178 memcpy(nlm_addr(host), ni->sap, ni->salen); 166 memcpy(nlm_addr(host), ni->sap, ni->salen);
179 host->h_addrlen = ni->salen; 167 host->h_addrlen = ni->salen;
180 nlm_clear_port(nlm_addr(host)); 168 rpc_set_port(nlm_addr(host), 0);
181 memcpy(nlm_srcaddr(host), ni->src_sap, ni->src_len); 169 memcpy(nlm_srcaddr(host), ni->src_sap, ni->src_len);
182 host->h_version = ni->version; 170 host->h_version = ni->version;
183 host->h_proto = ni->protocol; 171 host->h_proto = ni->protocol;
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 7fce1b525849..30c933188dd7 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -61,43 +61,6 @@ static inline struct sockaddr *nsm_addr(const struct nsm_handle *nsm)
61 return (struct sockaddr *)&nsm->sm_addr; 61 return (struct sockaddr *)&nsm->sm_addr;
62} 62}
63 63
64static void nsm_display_ipv4_address(const struct sockaddr *sap, char *buf,
65 const size_t len)
66{
67 const struct sockaddr_in *sin = (struct sockaddr_in *)sap;
68 snprintf(buf, len, "%pI4", &sin->sin_addr.s_addr);
69}
70
71static void nsm_display_ipv6_address(const struct sockaddr *sap, char *buf,
72 const size_t len)
73{
74 const struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
75
76 if (ipv6_addr_v4mapped(&sin6->sin6_addr))
77 snprintf(buf, len, "%pI4", &sin6->sin6_addr.s6_addr32[3]);
78 else if (sin6->sin6_scope_id != 0)
79 snprintf(buf, len, "%pI6%%%u", &sin6->sin6_addr,
80 sin6->sin6_scope_id);
81 else
82 snprintf(buf, len, "%pI6", &sin6->sin6_addr);
83}
84
85static void nsm_display_address(const struct sockaddr *sap,
86 char *buf, const size_t len)
87{
88 switch (sap->sa_family) {
89 case AF_INET:
90 nsm_display_ipv4_address(sap, buf, len);
91 break;
92 case AF_INET6:
93 nsm_display_ipv6_address(sap, buf, len);
94 break;
95 default:
96 snprintf(buf, len, "unsupported address family");
97 break;
98 }
99}
100
101static struct rpc_clnt *nsm_create(void) 64static struct rpc_clnt *nsm_create(void)
102{ 65{
103 struct sockaddr_in sin = { 66 struct sockaddr_in sin = {
@@ -307,8 +270,11 @@ static struct nsm_handle *nsm_create_handle(const struct sockaddr *sap,
307 memcpy(nsm_addr(new), sap, salen); 270 memcpy(nsm_addr(new), sap, salen);
308 new->sm_addrlen = salen; 271 new->sm_addrlen = salen;
309 nsm_init_private(new); 272 nsm_init_private(new);
310 nsm_display_address((const struct sockaddr *)&new->sm_addr, 273
311 new->sm_addrbuf, sizeof(new->sm_addrbuf)); 274 if (rpc_ntop(nsm_addr(new), new->sm_addrbuf,
275 sizeof(new->sm_addrbuf)) == 0)
276 (void)snprintf(new->sm_addrbuf, sizeof(new->sm_addrbuf),
277 "unsupported address family");
312 memcpy(new->sm_name, hostname, hostname_len); 278 memcpy(new->sm_name, hostname, hostname_len);
313 new->sm_name[hostname_len] = '\0'; 279 new->sm_name[hostname_len] = '\0';
314 280
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index e2ccb4a4398a..2e485677019c 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -102,6 +102,7 @@ struct nfs_mount_request {
102}; 102};
103 103
104extern int nfs_mount(struct nfs_mount_request *info); 104extern int nfs_mount(struct nfs_mount_request *info);
105extern void nfs_umount(const struct nfs_mount_request *info);
105 106
106/* client.c */ 107/* client.c */
107extern struct rpc_program nfs_program; 108extern struct rpc_program nfs_program;
@@ -213,7 +214,6 @@ void nfs_zap_acl_cache(struct inode *inode);
213extern int nfs_wait_bit_killable(void *word); 214extern int nfs_wait_bit_killable(void *word);
214 215
215/* super.c */ 216/* super.c */
216void nfs_parse_ip_address(char *, size_t, struct sockaddr *, size_t *);
217extern struct file_system_type nfs_xdev_fs_type; 217extern struct file_system_type nfs_xdev_fs_type;
218#ifdef CONFIG_NFS_V4 218#ifdef CONFIG_NFS_V4
219extern struct file_system_type nfs4_xdev_fs_type; 219extern struct file_system_type nfs4_xdev_fs_type;
@@ -374,24 +374,3 @@ unsigned int nfs_page_array_len(unsigned int base, size_t len)
374 return ((unsigned long)len + (unsigned long)base + 374 return ((unsigned long)len + (unsigned long)base +
375 PAGE_SIZE - 1) >> PAGE_SHIFT; 375 PAGE_SIZE - 1) >> PAGE_SHIFT;
376} 376}
377
378#define IPV6_SCOPE_DELIMITER '%'
379
380/*
381 * Set the port number in an address. Be agnostic about the address
382 * family.
383 */
384static inline void nfs_set_port(struct sockaddr *sap, unsigned short port)
385{
386 struct sockaddr_in *ap = (struct sockaddr_in *)sap;
387 struct sockaddr_in6 *ap6 = (struct sockaddr_in6 *)sap;
388
389 switch (sap->sa_family) {
390 case AF_INET:
391 ap->sin_port = htons(port);
392 break;
393 case AF_INET6:
394 ap6->sin6_port = htons(port);
395 break;
396 }
397}
diff --git a/fs/nfs/mount_clnt.c b/fs/nfs/mount_clnt.c
index 8b9affc8bab2..0adefc40cc89 100644
--- a/fs/nfs/mount_clnt.c
+++ b/fs/nfs/mount_clnt.c
@@ -209,6 +209,71 @@ out_mnt_err:
209 goto out; 209 goto out;
210} 210}
211 211
212/**
213 * nfs_umount - Notify a server that we have unmounted this export
214 * @info: pointer to umount request arguments
215 *
216 * MOUNTPROC_UMNT is advisory, so we set a short timeout, and always
217 * use UDP.
218 */
219void nfs_umount(const struct nfs_mount_request *info)
220{
221 static const struct rpc_timeout nfs_umnt_timeout = {
222 .to_initval = 1 * HZ,
223 .to_maxval = 3 * HZ,
224 .to_retries = 2,
225 };
226 struct rpc_create_args args = {
227 .protocol = IPPROTO_UDP,
228 .address = info->sap,
229 .addrsize = info->salen,
230 .timeout = &nfs_umnt_timeout,
231 .servername = info->hostname,
232 .program = &mnt_program,
233 .version = info->version,
234 .authflavor = RPC_AUTH_UNIX,
235 .flags = RPC_CLNT_CREATE_NOPING,
236 };
237 struct mountres result;
238 struct rpc_message msg = {
239 .rpc_argp = info->dirpath,
240 .rpc_resp = &result,
241 };
242 struct rpc_clnt *clnt;
243 int status;
244
245 if (info->noresvport)
246 args.flags |= RPC_CLNT_CREATE_NONPRIVPORT;
247
248 clnt = rpc_create(&args);
249 if (unlikely(IS_ERR(clnt)))
250 goto out_clnt_err;
251
252 dprintk("NFS: sending UMNT request for %s:%s\n",
253 (info->hostname ? info->hostname : "server"), info->dirpath);
254
255 if (info->version == NFS_MNT3_VERSION)
256 msg.rpc_proc = &clnt->cl_procinfo[MOUNTPROC3_UMNT];
257 else
258 msg.rpc_proc = &clnt->cl_procinfo[MOUNTPROC_UMNT];
259
260 status = rpc_call_sync(clnt, &msg, 0);
261 rpc_shutdown_client(clnt);
262
263 if (unlikely(status < 0))
264 goto out_call_err;
265
266 return;
267
268out_clnt_err:
269 dprintk("NFS: failed to create UMNT RPC client, status=%ld\n",
270 PTR_ERR(clnt));
271 return;
272
273out_call_err:
274 dprintk("NFS: UMNT request failed, status=%d\n", status);
275}
276
212/* 277/*
213 * XDR encode/decode functions for MOUNT 278 * XDR encode/decode functions for MOUNT
214 */ 279 */
@@ -407,6 +472,13 @@ static struct rpc_procinfo mnt_procedures[] = {
407 .p_statidx = MOUNTPROC_MNT, 472 .p_statidx = MOUNTPROC_MNT,
408 .p_name = "MOUNT", 473 .p_name = "MOUNT",
409 }, 474 },
475 [MOUNTPROC_UMNT] = {
476 .p_proc = MOUNTPROC_UMNT,
477 .p_encode = (kxdrproc_t)mnt_enc_dirpath,
478 .p_arglen = MNT_enc_dirpath_sz,
479 .p_statidx = MOUNTPROC_UMNT,
480 .p_name = "UMOUNT",
481 },
410}; 482};
411 483
412static struct rpc_procinfo mnt3_procedures[] = { 484static struct rpc_procinfo mnt3_procedures[] = {
@@ -419,6 +491,13 @@ static struct rpc_procinfo mnt3_procedures[] = {
419 .p_statidx = MOUNTPROC3_MNT, 491 .p_statidx = MOUNTPROC3_MNT,
420 .p_name = "MOUNT", 492 .p_name = "MOUNT",
421 }, 493 },
494 [MOUNTPROC3_UMNT] = {
495 .p_proc = MOUNTPROC3_UMNT,
496 .p_encode = (kxdrproc_t)mnt_enc_dirpath,
497 .p_arglen = MNT_enc_dirpath_sz,
498 .p_statidx = MOUNTPROC3_UMNT,
499 .p_name = "UMOUNT",
500 },
422}; 501};
423 502
424 503
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index 2a2a0a7143ad..ef22ee89aa77 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -121,11 +121,11 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
121 121
122 if (memchr(buf->data, IPV6_SCOPE_DELIMITER, buf->len)) 122 if (memchr(buf->data, IPV6_SCOPE_DELIMITER, buf->len))
123 continue; 123 continue;
124 nfs_parse_ip_address(buf->data, buf->len, 124 mountdata->addrlen = rpc_pton(buf->data, buf->len,
125 mountdata->addr, &mountdata->addrlen); 125 mountdata->addr, mountdata->addrlen);
126 if (mountdata->addr->sa_family == AF_UNSPEC) 126 if (mountdata->addrlen == 0)
127 continue; 127 continue;
128 nfs_set_port(mountdata->addr, NFS_PORT); 128 rpc_set_port(mountdata->addr, NFS_PORT);
129 129
130 memcpy(page2, buf->data, buf->len); 130 memcpy(page2, buf->data, buf->len);
131 page2[buf->len] = '\0'; 131 page2[buf->len] = '\0';
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 0b4cbdc60abd..9c85cdb353aa 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -158,7 +158,7 @@ static const match_table_t nfs_mount_option_tokens = {
158 { Opt_mountvers, "mountvers=%s" }, 158 { Opt_mountvers, "mountvers=%s" },
159 { Opt_nfsvers, "nfsvers=%s" }, 159 { Opt_nfsvers, "nfsvers=%s" },
160 { Opt_nfsvers, "vers=%s" }, 160 { Opt_nfsvers, "vers=%s" },
161 { Opt_minorversion, "minorversion=%u" }, 161 { Opt_minorversion, "minorversion=%s" },
162 162
163 { Opt_sec, "sec=%s" }, 163 { Opt_sec, "sec=%s" },
164 { Opt_proto, "proto=%s" }, 164 { Opt_proto, "proto=%s" },
@@ -742,129 +742,10 @@ static int nfs_verify_server_address(struct sockaddr *addr)
742 } 742 }
743 } 743 }
744 744
745 dfprintk(MOUNT, "NFS: Invalid IP address specified\n");
745 return 0; 746 return 0;
746} 747}
747 748
748static void nfs_parse_ipv4_address(char *string, size_t str_len,
749 struct sockaddr *sap, size_t *addr_len)
750{
751 struct sockaddr_in *sin = (struct sockaddr_in *)sap;
752 u8 *addr = (u8 *)&sin->sin_addr.s_addr;
753
754 if (str_len <= INET_ADDRSTRLEN) {
755 dfprintk(MOUNT, "NFS: parsing IPv4 address %*s\n",
756 (int)str_len, string);
757
758 sin->sin_family = AF_INET;
759 *addr_len = sizeof(*sin);
760 if (in4_pton(string, str_len, addr, '\0', NULL))
761 return;
762 }
763
764 sap->sa_family = AF_UNSPEC;
765 *addr_len = 0;
766}
767
768#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
769static int nfs_parse_ipv6_scope_id(const char *string, const size_t str_len,
770 const char *delim,
771 struct sockaddr_in6 *sin6)
772{
773 char *p;
774 size_t len;
775
776 if ((string + str_len) == delim)
777 return 1;
778
779 if (*delim != IPV6_SCOPE_DELIMITER)
780 return 0;
781
782 if (!(ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL))
783 return 0;
784
785 len = (string + str_len) - delim - 1;
786 p = kstrndup(delim + 1, len, GFP_KERNEL);
787 if (p) {
788 unsigned long scope_id = 0;
789 struct net_device *dev;
790
791 dev = dev_get_by_name(&init_net, p);
792 if (dev != NULL) {
793 scope_id = dev->ifindex;
794 dev_put(dev);
795 } else {
796 if (strict_strtoul(p, 10, &scope_id) == 0) {
797 kfree(p);
798 return 0;
799 }
800 }
801
802 kfree(p);
803
804 sin6->sin6_scope_id = scope_id;
805 dfprintk(MOUNT, "NFS: IPv6 scope ID = %lu\n", scope_id);
806 return 1;
807 }
808
809 return 0;
810}
811
812static void nfs_parse_ipv6_address(char *string, size_t str_len,
813 struct sockaddr *sap, size_t *addr_len)
814{
815 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
816 u8 *addr = (u8 *)&sin6->sin6_addr.in6_u;
817 const char *delim;
818
819 if (str_len <= INET6_ADDRSTRLEN) {
820 dfprintk(MOUNT, "NFS: parsing IPv6 address %*s\n",
821 (int)str_len, string);
822
823 sin6->sin6_family = AF_INET6;
824 *addr_len = sizeof(*sin6);
825 if (in6_pton(string, str_len, addr,
826 IPV6_SCOPE_DELIMITER, &delim) != 0) {
827 if (nfs_parse_ipv6_scope_id(string, str_len,
828 delim, sin6) != 0)
829 return;
830 }
831 }
832
833 sap->sa_family = AF_UNSPEC;
834 *addr_len = 0;
835}
836#else
837static void nfs_parse_ipv6_address(char *string, size_t str_len,
838 struct sockaddr *sap, size_t *addr_len)
839{
840 sap->sa_family = AF_UNSPEC;
841 *addr_len = 0;
842}
843#endif
844
845/*
846 * Construct a sockaddr based on the contents of a string that contains
847 * an IP address in presentation format.
848 *
849 * If there is a problem constructing the new sockaddr, set the address
850 * family to AF_UNSPEC.
851 */
852void nfs_parse_ip_address(char *string, size_t str_len,
853 struct sockaddr *sap, size_t *addr_len)
854{
855 unsigned int i, colons;
856
857 colons = 0;
858 for (i = 0; i < str_len; i++)
859 if (string[i] == ':')
860 colons++;
861
862 if (colons >= 2)
863 nfs_parse_ipv6_address(string, str_len, sap, addr_len);
864 else
865 nfs_parse_ipv4_address(string, str_len, sap, addr_len);
866}
867
868/* 749/*
869 * Sanity check the NFS transport protocol. 750 * Sanity check the NFS transport protocol.
870 * 751 *
@@ -904,8 +785,6 @@ static void nfs_set_mount_transport_protocol(struct nfs_parsed_mount_data *mnt)
904 785
905/* 786/*
906 * Parse the value of the 'sec=' option. 787 * Parse the value of the 'sec=' option.
907 *
908 * The flavor_len setting is for v4 mounts.
909 */ 788 */
910static int nfs_parse_security_flavors(char *value, 789static int nfs_parse_security_flavors(char *value,
911 struct nfs_parsed_mount_data *mnt) 790 struct nfs_parsed_mount_data *mnt)
@@ -916,53 +795,43 @@ static int nfs_parse_security_flavors(char *value,
916 795
917 switch (match_token(value, nfs_secflavor_tokens, args)) { 796 switch (match_token(value, nfs_secflavor_tokens, args)) {
918 case Opt_sec_none: 797 case Opt_sec_none:
919 mnt->auth_flavor_len = 0;
920 mnt->auth_flavors[0] = RPC_AUTH_NULL; 798 mnt->auth_flavors[0] = RPC_AUTH_NULL;
921 break; 799 break;
922 case Opt_sec_sys: 800 case Opt_sec_sys:
923 mnt->auth_flavor_len = 0;
924 mnt->auth_flavors[0] = RPC_AUTH_UNIX; 801 mnt->auth_flavors[0] = RPC_AUTH_UNIX;
925 break; 802 break;
926 case Opt_sec_krb5: 803 case Opt_sec_krb5:
927 mnt->auth_flavor_len = 1;
928 mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5; 804 mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5;
929 break; 805 break;
930 case Opt_sec_krb5i: 806 case Opt_sec_krb5i:
931 mnt->auth_flavor_len = 1;
932 mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5I; 807 mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5I;
933 break; 808 break;
934 case Opt_sec_krb5p: 809 case Opt_sec_krb5p:
935 mnt->auth_flavor_len = 1;
936 mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5P; 810 mnt->auth_flavors[0] = RPC_AUTH_GSS_KRB5P;
937 break; 811 break;
938 case Opt_sec_lkey: 812 case Opt_sec_lkey:
939 mnt->auth_flavor_len = 1;
940 mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEY; 813 mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEY;
941 break; 814 break;
942 case Opt_sec_lkeyi: 815 case Opt_sec_lkeyi:
943 mnt->auth_flavor_len = 1;
944 mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEYI; 816 mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEYI;
945 break; 817 break;
946 case Opt_sec_lkeyp: 818 case Opt_sec_lkeyp:
947 mnt->auth_flavor_len = 1;
948 mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEYP; 819 mnt->auth_flavors[0] = RPC_AUTH_GSS_LKEYP;
949 break; 820 break;
950 case Opt_sec_spkm: 821 case Opt_sec_spkm:
951 mnt->auth_flavor_len = 1;
952 mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKM; 822 mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKM;
953 break; 823 break;
954 case Opt_sec_spkmi: 824 case Opt_sec_spkmi:
955 mnt->auth_flavor_len = 1;
956 mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKMI; 825 mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKMI;
957 break; 826 break;
958 case Opt_sec_spkmp: 827 case Opt_sec_spkmp:
959 mnt->auth_flavor_len = 1;
960 mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKMP; 828 mnt->auth_flavors[0] = RPC_AUTH_GSS_SPKMP;
961 break; 829 break;
962 default: 830 default:
963 return 0; 831 return 0;
964 } 832 }
965 833
834 mnt->auth_flavor_len = 1;
966 return 1; 835 return 1;
967} 836}
968 837
@@ -1001,7 +870,6 @@ static int nfs_parse_mount_options(char *raw,
1001 while ((p = strsep(&raw, ",")) != NULL) { 870 while ((p = strsep(&raw, ",")) != NULL) {
1002 substring_t args[MAX_OPT_ARGS]; 871 substring_t args[MAX_OPT_ARGS];
1003 unsigned long option; 872 unsigned long option;
1004 int int_option;
1005 int token; 873 int token;
1006 874
1007 if (!*p) 875 if (!*p)
@@ -1273,11 +1141,16 @@ static int nfs_parse_mount_options(char *raw,
1273 } 1141 }
1274 break; 1142 break;
1275 case Opt_minorversion: 1143 case Opt_minorversion:
1276 if (match_int(args, &int_option)) 1144 string = match_strdup(args);
1277 return 0; 1145 if (string == NULL)
1278 if (int_option < 0 || int_option > NFS4_MAX_MINOR_VERSION) 1146 goto out_nomem;
1279 return 0; 1147 rc = strict_strtoul(string, 10, &option);
1280 mnt->minorversion = int_option; 1148 kfree(string);
1149 if (rc != 0)
1150 goto out_invalid_value;
1151 if (option > NFS4_MAX_MINOR_VERSION)
1152 goto out_invalid_value;
1153 mnt->minorversion = option;
1281 break; 1154 break;
1282 1155
1283 /* 1156 /*
@@ -1352,11 +1225,14 @@ static int nfs_parse_mount_options(char *raw,
1352 string = match_strdup(args); 1225 string = match_strdup(args);
1353 if (string == NULL) 1226 if (string == NULL)
1354 goto out_nomem; 1227 goto out_nomem;
1355 nfs_parse_ip_address(string, strlen(string), 1228 mnt->nfs_server.addrlen =
1356 (struct sockaddr *) 1229 rpc_pton(string, strlen(string),
1357 &mnt->nfs_server.address, 1230 (struct sockaddr *)
1358 &mnt->nfs_server.addrlen); 1231 &mnt->nfs_server.address,
1232 sizeof(mnt->nfs_server.address));
1359 kfree(string); 1233 kfree(string);
1234 if (mnt->nfs_server.addrlen == 0)
1235 goto out_invalid_address;
1360 break; 1236 break;
1361 case Opt_clientaddr: 1237 case Opt_clientaddr:
1362 string = match_strdup(args); 1238 string = match_strdup(args);
@@ -1376,11 +1252,14 @@ static int nfs_parse_mount_options(char *raw,
1376 string = match_strdup(args); 1252 string = match_strdup(args);
1377 if (string == NULL) 1253 if (string == NULL)
1378 goto out_nomem; 1254 goto out_nomem;
1379 nfs_parse_ip_address(string, strlen(string), 1255 mnt->mount_server.addrlen =
1380 (struct sockaddr *) 1256 rpc_pton(string, strlen(string),
1381 &mnt->mount_server.address, 1257 (struct sockaddr *)
1382 &mnt->mount_server.addrlen); 1258 &mnt->mount_server.address,
1259 sizeof(mnt->mount_server.address));
1383 kfree(string); 1260 kfree(string);
1261 if (mnt->mount_server.addrlen == 0)
1262 goto out_invalid_address;
1384 break; 1263 break;
1385 case Opt_lookupcache: 1264 case Opt_lookupcache:
1386 string = match_strdup(args); 1265 string = match_strdup(args);
@@ -1432,8 +1311,11 @@ static int nfs_parse_mount_options(char *raw,
1432 1311
1433 return 1; 1312 return 1;
1434 1313
1314out_invalid_address:
1315 printk(KERN_INFO "NFS: bad IP address specified: %s\n", p);
1316 return 0;
1435out_invalid_value: 1317out_invalid_value:
1436 printk(KERN_INFO "NFS: bad mount option value specified: %s \n", p); 1318 printk(KERN_INFO "NFS: bad mount option value specified: %s\n", p);
1437 return 0; 1319 return 0;
1438out_nomem: 1320out_nomem:
1439 printk(KERN_INFO "NFS: not enough memory to parse option\n"); 1321 printk(KERN_INFO "NFS: not enough memory to parse option\n");
@@ -1445,13 +1327,50 @@ out_security_failure:
1445} 1327}
1446 1328
1447/* 1329/*
1330 * Match the requested auth flavors with the list returned by
1331 * the server. Returns zero and sets the mount's authentication
1332 * flavor on success; returns -EACCES if server does not support
1333 * the requested flavor.
1334 */
1335static int nfs_walk_authlist(struct nfs_parsed_mount_data *args,
1336 struct nfs_mount_request *request)
1337{
1338 unsigned int i, j, server_authlist_len = *(request->auth_flav_len);
1339
1340 /*
1341 * We avoid sophisticated negotiating here, as there are
1342 * plenty of cases where we can get it wrong, providing
1343 * either too little or too much security.
1344 *
1345 * RFC 2623, section 2.7 suggests we SHOULD prefer the
1346 * flavor listed first. However, some servers list
1347 * AUTH_NULL first. Our caller plants AUTH_SYS, the
1348 * preferred default, in args->auth_flavors[0] if user
1349 * didn't specify sec= mount option.
1350 */
1351 for (i = 0; i < args->auth_flavor_len; i++)
1352 for (j = 0; j < server_authlist_len; j++)
1353 if (args->auth_flavors[i] == request->auth_flavs[j]) {
1354 dfprintk(MOUNT, "NFS: using auth flavor %d\n",
1355 request->auth_flavs[j]);
1356 args->auth_flavors[0] = request->auth_flavs[j];
1357 return 0;
1358 }
1359
1360 dfprintk(MOUNT, "NFS: server does not support requested auth flavor\n");
1361 nfs_umount(request);
1362 return -EACCES;
1363}
1364
1365/*
1448 * Use the remote server's MOUNT service to request the NFS file handle 1366 * Use the remote server's MOUNT service to request the NFS file handle
1449 * corresponding to the provided path. 1367 * corresponding to the provided path.
1450 */ 1368 */
1451static int nfs_try_mount(struct nfs_parsed_mount_data *args, 1369static int nfs_try_mount(struct nfs_parsed_mount_data *args,
1452 struct nfs_fh *root_fh) 1370 struct nfs_fh *root_fh)
1453{ 1371{
1454 unsigned int auth_flavor_len = 0; 1372 rpc_authflavor_t server_authlist[NFS_MAX_SECFLAVORS];
1373 unsigned int server_authlist_len = ARRAY_SIZE(server_authlist);
1455 struct nfs_mount_request request = { 1374 struct nfs_mount_request request = {
1456 .sap = (struct sockaddr *) 1375 .sap = (struct sockaddr *)
1457 &args->mount_server.address, 1376 &args->mount_server.address,
@@ -1459,7 +1378,8 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
1459 .protocol = args->mount_server.protocol, 1378 .protocol = args->mount_server.protocol,
1460 .fh = root_fh, 1379 .fh = root_fh,
1461 .noresvport = args->flags & NFS_MOUNT_NORESVPORT, 1380 .noresvport = args->flags & NFS_MOUNT_NORESVPORT,
1462 .auth_flav_len = &auth_flavor_len, 1381 .auth_flav_len = &server_authlist_len,
1382 .auth_flavs = server_authlist,
1463 }; 1383 };
1464 int status; 1384 int status;
1465 1385
@@ -1489,19 +1409,25 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
1489 /* 1409 /*
1490 * autobind will be used if mount_server.port == 0 1410 * autobind will be used if mount_server.port == 0
1491 */ 1411 */
1492 nfs_set_port(request.sap, args->mount_server.port); 1412 rpc_set_port(request.sap, args->mount_server.port);
1493 1413
1494 /* 1414 /*
1495 * Now ask the mount server to map our export path 1415 * Now ask the mount server to map our export path
1496 * to a file handle. 1416 * to a file handle.
1497 */ 1417 */
1498 status = nfs_mount(&request); 1418 status = nfs_mount(&request);
1499 if (status == 0) 1419 if (status != 0) {
1500 return 0; 1420 dfprintk(MOUNT, "NFS: unable to mount server %s, error %d\n",
1421 request.hostname, status);
1422 return status;
1423 }
1501 1424
1502 dfprintk(MOUNT, "NFS: unable to mount server %s, error %d\n", 1425 /*
1503 request.hostname, status); 1426 * MNTv1 (NFSv2) does not support auth flavor negotiation.
1504 return status; 1427 */
1428 if (args->mount_server.version != NFS_MNT3_VERSION)
1429 return 0;
1430 return nfs_walk_authlist(args, &request);
1505} 1431}
1506 1432
1507static int nfs_parse_simple_hostname(const char *dev_name, 1433static int nfs_parse_simple_hostname(const char *dev_name,
@@ -1676,6 +1602,7 @@ static int nfs_validate_mount_data(void *options,
1676 args->nfs_server.port = 0; /* autobind unless user sets port */ 1602 args->nfs_server.port = 0; /* autobind unless user sets port */
1677 args->nfs_server.protocol = XPRT_TRANSPORT_TCP; 1603 args->nfs_server.protocol = XPRT_TRANSPORT_TCP;
1678 args->auth_flavors[0] = RPC_AUTH_UNIX; 1604 args->auth_flavors[0] = RPC_AUTH_UNIX;
1605 args->auth_flavor_len = 1;
1679 1606
1680 switch (data->version) { 1607 switch (data->version) {
1681 case 1: 1608 case 1:
@@ -1776,7 +1703,7 @@ static int nfs_validate_mount_data(void *options,
1776 &args->nfs_server.address)) 1703 &args->nfs_server.address))
1777 goto out_no_address; 1704 goto out_no_address;
1778 1705
1779 nfs_set_port((struct sockaddr *)&args->nfs_server.address, 1706 rpc_set_port((struct sockaddr *)&args->nfs_server.address,
1780 args->nfs_server.port); 1707 args->nfs_server.port);
1781 1708
1782 nfs_set_mount_transport_protocol(args); 1709 nfs_set_mount_transport_protocol(args);
@@ -2339,7 +2266,7 @@ static int nfs4_validate_mount_data(void *options,
2339 args->acdirmax = NFS_DEF_ACDIRMAX; 2266 args->acdirmax = NFS_DEF_ACDIRMAX;
2340 args->nfs_server.port = NFS_PORT; /* 2049 unless user set port= */ 2267 args->nfs_server.port = NFS_PORT; /* 2049 unless user set port= */
2341 args->auth_flavors[0] = RPC_AUTH_UNIX; 2268 args->auth_flavors[0] = RPC_AUTH_UNIX;
2342 args->auth_flavor_len = 0; 2269 args->auth_flavor_len = 1;
2343 args->minorversion = 0; 2270 args->minorversion = 0;
2344 2271
2345 switch (data->version) { 2272 switch (data->version) {
@@ -2409,7 +2336,7 @@ static int nfs4_validate_mount_data(void *options,
2409 &args->nfs_server.address)) 2336 &args->nfs_server.address))
2410 return -EINVAL; 2337 return -EINVAL;
2411 2338
2412 nfs_set_port((struct sockaddr *)&args->nfs_server.address, 2339 rpc_set_port((struct sockaddr *)&args->nfs_server.address,
2413 args->nfs_server.port); 2340 args->nfs_server.port);
2414 2341
2415 nfs_validate_transport_protocol(args); 2342 nfs_validate_transport_protocol(args);
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 6d0847562d87..7e906c5b7671 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -37,6 +37,7 @@
37#include <linux/nfsd/xdr.h> 37#include <linux/nfsd/xdr.h>
38#include <linux/nfsd/syscall.h> 38#include <linux/nfsd/syscall.h>
39#include <linux/lockd/lockd.h> 39#include <linux/lockd/lockd.h>
40#include <linux/sunrpc/clnt.h>
40 41
41#include <asm/uaccess.h> 42#include <asm/uaccess.h>
42#include <net/ipv6.h> 43#include <net/ipv6.h>
@@ -490,22 +491,18 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size)
490 * 491 *
491 * Input: 492 * Input:
492 * buf: '\n'-terminated C string containing a 493 * buf: '\n'-terminated C string containing a
493 * presentation format IPv4 address 494 * presentation format IP address
494 * size: length of C string in @buf 495 * size: length of C string in @buf
495 * Output: 496 * Output:
496 * On success: returns zero if all specified locks were released; 497 * On success: returns zero if all specified locks were released;
497 * returns one if one or more locks were not released 498 * returns one if one or more locks were not released
498 * On error: return code is negative errno value 499 * On error: return code is negative errno value
499 *
500 * Note: Only AF_INET client addresses are passed in
501 */ 500 */
502static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size) 501static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
503{ 502{
504 struct sockaddr_in sin = { 503 struct sockaddr_storage address;
505 .sin_family = AF_INET, 504 struct sockaddr *sap = (struct sockaddr *)&address;
506 }; 505 size_t salen = sizeof(address);
507 int b1, b2, b3, b4;
508 char c;
509 char *fo_path; 506 char *fo_path;
510 507
511 /* sanity check */ 508 /* sanity check */
@@ -519,14 +516,10 @@ static ssize_t write_unlock_ip(struct file *file, char *buf, size_t size)
519 if (qword_get(&buf, fo_path, size) < 0) 516 if (qword_get(&buf, fo_path, size) < 0)
520 return -EINVAL; 517 return -EINVAL;
521 518
522 /* get ipv4 address */ 519 if (rpc_pton(fo_path, size, sap, salen) == 0)
523 if (sscanf(fo_path, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4)
524 return -EINVAL;
525 if (b1 > 255 || b2 > 255 || b3 > 255 || b4 > 255)
526 return -EINVAL; 520 return -EINVAL;
527 sin.sin_addr.s_addr = htonl((b1 << 24) | (b2 << 16) | (b3 << 8) | b4);
528 521
529 return nlmsvc_unlock_all_by_ip((struct sockaddr *)&sin); 522 return nlmsvc_unlock_all_by_ip(sap);
530} 523}
531 524
532/** 525/**