aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2008-06-23 12:36:45 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-07-09 12:09:27 -0400
commitd1aa08257312f1439c1ab7c8a18e3856f9530f46 (patch)
tree04ac6b07e5fda3ea93a706fb4074e92b7a95aee3
parentdc04589827f7e1af12714af8bb00e3f3c4c48c62 (diff)
NFS: Support raw IPv6 address hostnames during NFS mount operation
Traditionally the mount command has looked for a ":" to separate the server's hostname from the export path in the mounted on device name, like this: mount server:/export /mounted/on/dir The server's hostname is "server" and the export path is "/export". You can also substitute a specific IPv4 network address for the server hostname, like this: mount 192.168.0.55:/export /mounted/on/dir Raw IPv6 addresses present a problem, however, because they look something like this: fe80::200:5aff:fe00:30b Note the use of colons. To get around the presence of colons, copy the Solaris convention used for mounting IPv6 servers by address: wrap a raw IPv6 address with square brackets. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/super.c90
1 files changed, 82 insertions, 8 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index c4ee8b3a27c1..ea4abd266a7a 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -1195,14 +1195,9 @@ static int nfs_try_mount(struct nfs_parsed_mount_data *args,
1195 return status; 1195 return status;
1196} 1196}
1197 1197
1198/* 1198static int nfs_parse_simple_hostname(const char *dev_name,
1199 * Split "dev_name" into "hostname:export_path". 1199 char **hostname, size_t maxnamlen,
1200 * 1200 char **export_path, size_t maxpathlen)
1201 * Note: caller frees hostname and export path, even on error.
1202 */
1203static int nfs_parse_devname(const char *dev_name,
1204 char **hostname, size_t maxnamlen,
1205 char **export_path, size_t maxpathlen)
1206{ 1201{
1207 size_t len; 1202 size_t len;
1208 char *colon, *comma; 1203 char *colon, *comma;
@@ -1257,6 +1252,85 @@ out_path:
1257} 1252}
1258 1253
1259/* 1254/*
1255 * Hostname has square brackets around it because it contains one or
1256 * more colons. We look for the first closing square bracket, and a
1257 * colon must follow it.
1258 */
1259static int nfs_parse_protected_hostname(const char *dev_name,
1260 char **hostname, size_t maxnamlen,
1261 char **export_path, size_t maxpathlen)
1262{
1263 size_t len;
1264 char *start, *end;
1265
1266 start = (char *)(dev_name + 1);
1267
1268 end = strchr(start, ']');
1269 if (end == NULL)
1270 goto out_bad_devname;
1271 if (*(end + 1) != ':')
1272 goto out_bad_devname;
1273
1274 len = end - start;
1275 if (len > maxnamlen)
1276 goto out_hostname;
1277
1278 /* N.B. caller will free nfs_server.hostname in all cases */
1279 *hostname = kstrndup(start, len, GFP_KERNEL);
1280 if (*hostname == NULL)
1281 goto out_nomem;
1282
1283 end += 2;
1284 len = strlen(end);
1285 if (len > maxpathlen)
1286 goto out_path;
1287 *export_path = kstrndup(end, len, GFP_KERNEL);
1288 if (!*export_path)
1289 goto out_nomem;
1290
1291 return 0;
1292
1293out_bad_devname:
1294 dfprintk(MOUNT, "NFS: device name not in host:path format\n");
1295 return -EINVAL;
1296
1297out_nomem:
1298 dfprintk(MOUNT, "NFS: not enough memory to parse device name\n");
1299 return -ENOMEM;
1300
1301out_hostname:
1302 dfprintk(MOUNT, "NFS: server hostname too long\n");
1303 return -ENAMETOOLONG;
1304
1305out_path:
1306 dfprintk(MOUNT, "NFS: export pathname too long\n");
1307 return -ENAMETOOLONG;
1308}
1309
1310/*
1311 * Split "dev_name" into "hostname:export_path".
1312 *
1313 * The leftmost colon demarks the split between the server's hostname
1314 * and the export path. If the hostname starts with a left square
1315 * bracket, then it may contain colons.
1316 *
1317 * Note: caller frees hostname and export path, even on error.
1318 */
1319static int nfs_parse_devname(const char *dev_name,
1320 char **hostname, size_t maxnamlen,
1321 char **export_path, size_t maxpathlen)
1322{
1323 if (*dev_name == '[')
1324 return nfs_parse_protected_hostname(dev_name,
1325 hostname, maxnamlen,
1326 export_path, maxpathlen);
1327
1328 return nfs_parse_simple_hostname(dev_name,
1329 hostname, maxnamlen,
1330 export_path, maxpathlen);
1331}
1332
1333/*
1260 * Validate the NFS2/NFS3 mount data 1334 * Validate the NFS2/NFS3 mount data
1261 * - fills in the mount root filehandle 1335 * - fills in the mount root filehandle
1262 * 1336 *