diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2008-06-23 12:36:45 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2008-07-09 12:09:27 -0400 |
commit | d1aa08257312f1439c1ab7c8a18e3856f9530f46 (patch) | |
tree | 04ac6b07e5fda3ea93a706fb4074e92b7a95aee3 /fs | |
parent | dc04589827f7e1af12714af8bb00e3f3c4c48c62 (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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/super.c | 90 |
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 | /* | 1198 | static 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 | */ | ||
1203 | static 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 | */ | ||
1259 | static 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 | |||
1293 | out_bad_devname: | ||
1294 | dfprintk(MOUNT, "NFS: device name not in host:path format\n"); | ||
1295 | return -EINVAL; | ||
1296 | |||
1297 | out_nomem: | ||
1298 | dfprintk(MOUNT, "NFS: not enough memory to parse device name\n"); | ||
1299 | return -ENOMEM; | ||
1300 | |||
1301 | out_hostname: | ||
1302 | dfprintk(MOUNT, "NFS: server hostname too long\n"); | ||
1303 | return -ENAMETOOLONG; | ||
1304 | |||
1305 | out_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 | */ | ||
1319 | static 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 | * |