aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/internal.h1
-rw-r--r--fs/nfs/nfs4namespace.c6
-rw-r--r--fs/nfs/super.c148
3 files changed, 22 insertions, 133 deletions
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index ff68397f9b19..cf1da3e22004 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -214,7 +214,6 @@ void nfs_zap_acl_cache(struct inode *inode);
214extern int nfs_wait_bit_killable(void *word); 214extern int nfs_wait_bit_killable(void *word);
215 215
216/* super.c */ 216/* super.c */
217void nfs_parse_ip_address(char *, size_t, struct sockaddr *, size_t *);
218extern struct file_system_type nfs_xdev_fs_type; 217extern struct file_system_type nfs_xdev_fs_type;
219#ifdef CONFIG_NFS_V4 218#ifdef CONFIG_NFS_V4
220extern struct file_system_type nfs4_xdev_fs_type; 219extern struct file_system_type nfs4_xdev_fs_type;
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index 2a2a0a7143ad..43c86b7556e1 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -121,9 +121,9 @@ 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 nfs_set_port(mountdata->addr, NFS_PORT);
129 129
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 8526008eba72..1eeba8e53802 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -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 *
@@ -1344,11 +1225,14 @@ static int nfs_parse_mount_options(char *raw,
1344 string = match_strdup(args); 1225 string = match_strdup(args);
1345 if (string == NULL) 1226 if (string == NULL)
1346 goto out_nomem; 1227 goto out_nomem;
1347 nfs_parse_ip_address(string, strlen(string), 1228 mnt->nfs_server.addrlen =
1348 (struct sockaddr *) 1229 rpc_pton(string, strlen(string),
1349 &mnt->nfs_server.address, 1230 (struct sockaddr *)
1350 &mnt->nfs_server.addrlen); 1231 &mnt->nfs_server.address,
1232 sizeof(mnt->nfs_server.address));
1351 kfree(string); 1233 kfree(string);
1234 if (mnt->nfs_server.addrlen == 0)
1235 goto out_invalid_address;
1352 break; 1236 break;
1353 case Opt_clientaddr: 1237 case Opt_clientaddr:
1354 string = match_strdup(args); 1238 string = match_strdup(args);
@@ -1368,11 +1252,14 @@ static int nfs_parse_mount_options(char *raw,
1368 string = match_strdup(args); 1252 string = match_strdup(args);
1369 if (string == NULL) 1253 if (string == NULL)
1370 goto out_nomem; 1254 goto out_nomem;
1371 nfs_parse_ip_address(string, strlen(string), 1255 mnt->mount_server.addrlen =
1372 (struct sockaddr *) 1256 rpc_pton(string, strlen(string),
1373 &mnt->mount_server.address, 1257 (struct sockaddr *)
1374 &mnt->mount_server.addrlen); 1258 &mnt->mount_server.address,
1259 sizeof(mnt->mount_server.address));
1375 kfree(string); 1260 kfree(string);
1261 if (mnt->mount_server.addrlen == 0)
1262 goto out_invalid_address;
1376 break; 1263 break;
1377 case Opt_lookupcache: 1264 case Opt_lookupcache:
1378 string = match_strdup(args); 1265 string = match_strdup(args);
@@ -1424,8 +1311,11 @@ static int nfs_parse_mount_options(char *raw,
1424 1311
1425 return 1; 1312 return 1;
1426 1313
1314out_invalid_address:
1315 printk(KERN_INFO "NFS: bad IP address specified: %s\n", p);
1316 return 0;
1427out_invalid_value: 1317out_invalid_value:
1428 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);
1429 return 0; 1319 return 0;
1430out_nomem: 1320out_nomem:
1431 printk(KERN_INFO "NFS: not enough memory to parse option\n"); 1321 printk(KERN_INFO "NFS: not enough memory to parse option\n");