aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/super.c
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2008-06-23 12:36:53 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-07-09 12:09:28 -0400
commitce3b7e1906ebbe96753fe090b36de6ffb8e0e0e7 (patch)
tree7518683c3a5818a0d48d377fa5dd4a37faddaec7 /fs/nfs/super.c
parentd1aa08257312f1439c1ab7c8a18e3856f9530f46 (diff)
NFS: Add string length argument to nfs_parse_server_address
To make nfs_parse_server_address() more generally useful, allow it to accept input strings that are not terminated with '\0'. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r--fs/nfs/super.c100
1 files changed, 70 insertions, 30 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index ea4abd266a7..d27aa1db007 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -705,38 +705,76 @@ static int nfs_verify_server_address(struct sockaddr *addr)
705 return 0; 705 return 0;
706} 706}
707 707
708/* 708static void nfs_parse_ipv4_address(char *string, size_t str_len,
709 * Parse string addresses passed in via a mount option, 709 struct sockaddr *sap, size_t *addr_len)
710 * and construct a sockaddr based on the result.
711 *
712 * If address parsing fails, set the sockaddr's address
713 * family to AF_UNSPEC to force nfs_verify_server_address()
714 * to punt the mount.
715 */
716static void nfs_parse_server_address(char *value,
717 struct sockaddr *sap,
718 size_t *len)
719{ 710{
720 if (strchr(value, ':')) { 711 struct sockaddr_in *sin = (struct sockaddr_in *)sap;
721 struct sockaddr_in6 *ap = (struct sockaddr_in6 *)sap; 712 u8 *addr = (u8 *)&sin->sin_addr.s_addr;
722 u8 *addr = (u8 *)&ap->sin6_addr.in6_u;
723 713
724 ap->sin6_family = AF_INET6; 714 if (str_len <= INET_ADDRSTRLEN) {
725 *len = sizeof(*ap); 715 dfprintk(MOUNT, "NFS: parsing IPv4 address %*s\n",
726 if (in6_pton(value, -1, addr, '\0', NULL)) 716 (int)str_len, string);
717
718 sin->sin_family = AF_INET;
719 *addr_len = sizeof(*sin);
720 if (in4_pton(string, str_len, addr, '\0', NULL))
727 return; 721 return;
728 } else { 722 }
729 struct sockaddr_in *ap = (struct sockaddr_in *)sap; 723
730 u8 *addr = (u8 *)&ap->sin_addr.s_addr; 724 sap->sa_family = AF_UNSPEC;
725 *addr_len = 0;
726}
727
728#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
729static void nfs_parse_ipv6_address(char *string, size_t str_len,
730 struct sockaddr *sap, size_t *addr_len)
731{
732 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sap;
733 u8 *addr = (u8 *)&sin6->sin6_addr.in6_u;
734
735 if (str_len <= INET6_ADDRSTRLEN) {
736 dfprintk(MOUNT, "NFS: parsing IPv6 address %*s\n",
737 (int)str_len, string);
731 738
732 ap->sin_family = AF_INET; 739 sin6->sin6_family = AF_INET6;
733 *len = sizeof(*ap); 740 *addr_len = sizeof(*sin6);
734 if (in4_pton(value, -1, addr, '\0', NULL)) 741 if (in6_pton(string, str_len, addr, '\0', NULL))
735 return; 742 return;
736 } 743 }
737 744
738 sap->sa_family = AF_UNSPEC; 745 sap->sa_family = AF_UNSPEC;
739 *len = 0; 746 *addr_len = 0;
747}
748#else
749static void nfs_parse_ipv6_address(char *string, size_t str_len,
750 struct sockaddr *sap, size_t *addr_len)
751{
752 sap->sa_family = AF_UNSPEC;
753 *addr_len = 0;
754}
755#endif
756
757/*
758 * Construct a sockaddr based on the contents of a string that contains
759 * an IP address in presentation format.
760 *
761 * If there is a problem constructing the new sockaddr, set the address
762 * family to AF_UNSPEC.
763 */
764static void nfs_parse_ip_address(char *string, size_t str_len,
765 struct sockaddr *sap, size_t *addr_len)
766{
767 unsigned int i, colons;
768
769 colons = 0;
770 for (i = 0; i < str_len; i++)
771 if (string[i] == ':')
772 colons++;
773
774 if (colons >= 2)
775 nfs_parse_ipv6_address(string, str_len, sap, addr_len);
776 else
777 nfs_parse_ipv4_address(string, str_len, sap, addr_len);
740} 778}
741 779
742/* 780/*
@@ -1070,9 +1108,10 @@ static int nfs_parse_mount_options(char *raw,
1070 string = match_strdup(args); 1108 string = match_strdup(args);
1071 if (string == NULL) 1109 if (string == NULL)
1072 goto out_nomem; 1110 goto out_nomem;
1073 nfs_parse_server_address(string, (struct sockaddr *) 1111 nfs_parse_ip_address(string, strlen(string),
1074 &mnt->nfs_server.address, 1112 (struct sockaddr *)
1075 &mnt->nfs_server.addrlen); 1113 &mnt->nfs_server.address,
1114 &mnt->nfs_server.addrlen);
1076 kfree(string); 1115 kfree(string);
1077 break; 1116 break;
1078 case Opt_clientaddr: 1117 case Opt_clientaddr:
@@ -1093,9 +1132,10 @@ static int nfs_parse_mount_options(char *raw,
1093 string = match_strdup(args); 1132 string = match_strdup(args);
1094 if (string == NULL) 1133 if (string == NULL)
1095 goto out_nomem; 1134 goto out_nomem;
1096 nfs_parse_server_address(string, (struct sockaddr *) 1135 nfs_parse_ip_address(string, strlen(string),
1097 &mnt->mount_server.address, 1136 (struct sockaddr *)
1098 &mnt->mount_server.addrlen); 1137 &mnt->mount_server.address,
1138 &mnt->mount_server.addrlen);
1099 kfree(string); 1139 kfree(string);
1100 break; 1140 break;
1101 1141