mirror of
https://github.com/u-boot/u-boot.git
synced 2025-04-19 03:15:00 +00:00
net: nfs: fix file handle length in NFSv3
The NFS protocol uses file handles to refer to file or directory.
In NFSv2 file handles have a fixed size of 32 bytes.
In NFSv3 file handles have a variable length up to 64 bytes. This is
also true for the MOUNT protocol. [1]
When the NFSv3 server replies with a file handle length > 32 bytes, U-Boot
only copies 32 bytes of that file handle and the next LOOKUP Call fails:
BIOS> nfs ${loadaddr} 192.168.1.51:/nfsroot/opos93dev-br/boot/Image
Using ethernet@428a0000 device
File transfer via NFS from server 192.168.1.51; our IP address is 192.168.1.133
Filename '/nfsroot/opos93dev-br/boot/Image'.
Load address: 0x80400000
Loading: *** ERROR: File lookup fail
done
BIOS>
Looking at this transfer in Wireshark, we can see that the server
replies with the following file handle:
length: 36
[hash (CRC-32): 0x230ac67b]
FileHandle: 0100070101005e000000000091763911f87c449fa73c298552db19ba0c9f60002980cfd2
and U-Boot sends the following file handle in the next LOOKUP Call:
length: 32
[hash (CRC-32): 0x6314131b]
FileHandle: 000000240100070101005e000000000091763911f87c449fa73c298552db19ba
Fix this by using a variable length file handle for dirfh.
[1] https://www.rfc-editor.org/rfc/rfc1813.html#page-106
Fixes: b0baca9820
("net: NFS: Add NFSv3 support")
Signed-off-by: Sébastien Szymanski <sebastien.szymanski@armadeus.com>
Tested-by: Andrew Davis <afd@ti.com>
This commit is contained in:
parent
6821d13fb0
commit
d2986567b2
1 changed files with 13 additions and 5 deletions
16
net/nfs.c
16
net/nfs.c
|
@ -57,7 +57,8 @@ static int nfs_offset = -1;
|
|||
static int nfs_len;
|
||||
static const ulong nfs_timeout = CONFIG_NFS_TIMEOUT;
|
||||
|
||||
static char dirfh[NFS_FHSIZE]; /* NFSv2 / NFSv3 file handle of directory */
|
||||
static char dirfh[NFS3_FHSIZE]; /* NFSv2 / NFSv3 file handle of directory */
|
||||
static unsigned int dirfh3_length; /* (variable) length of dirfh when NFSv3 */
|
||||
static char filefh[NFS3_FHSIZE]; /* NFSv2 / NFSv3 file handle */
|
||||
static unsigned int filefh3_length; /* (variable) length of filefh when NFSv3 */
|
||||
|
||||
|
@ -377,9 +378,9 @@ static void nfs_lookup_req(char *fname)
|
|||
|
||||
rpc_req(PROG_NFS, NFS_LOOKUP, data, len);
|
||||
} else { /* NFS_V3 */
|
||||
*p++ = htonl(NFS_FHSIZE); /* Dir handle length */
|
||||
memcpy(p, dirfh, NFS_FHSIZE);
|
||||
p += (NFS_FHSIZE / 4);
|
||||
*p++ = htonl(dirfh3_length); /* Dir handle length */
|
||||
memcpy(p, dirfh, dirfh3_length);
|
||||
p += (dirfh3_length / 4);
|
||||
*p++ = htonl(fnamelen);
|
||||
if (fnamelen & 3)
|
||||
*(p + fnamelen / 4) = 0;
|
||||
|
@ -565,7 +566,14 @@ static int nfs_mount_reply(uchar *pkt, unsigned len)
|
|||
|
||||
fs_mounted = 1;
|
||||
/* NFSv2 and NFSv3 use same structure */
|
||||
if (choosen_nfs_version != NFS_V3) {
|
||||
memcpy(dirfh, rpc_pkt.u.reply.data + 1, NFS_FHSIZE);
|
||||
} else {
|
||||
dirfh3_length = ntohl(rpc_pkt.u.reply.data[1]);
|
||||
if (dirfh3_length > NFS3_FHSIZE)
|
||||
dirfh3_length = NFS3_FHSIZE;
|
||||
memcpy(dirfh, rpc_pkt.u.reply.data + 2, dirfh3_length);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue