iPXE
nfs.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2013 Marin Hannache <ipxe@mareo.fr>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  */
19 
20 #include <stdint.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <assert.h>
25 #include <errno.h>
26 #include <libgen.h>
27 #include <byteswap.h>
28 #include <ipxe/time.h>
29 #include <ipxe/iobuf.h>
30 #include <ipxe/open.h>
31 #include <ipxe/features.h>
32 #include <ipxe/nfs.h>
33 #include <ipxe/oncrpc.h>
34 #include <ipxe/oncrpc_iob.h>
35 #include <ipxe/portmap.h>
36 #include <ipxe/mount.h>
37 #include <ipxe/settings.h>
38 
39 /** @file
40  *
41  * Network File System protocol
42  *
43  */
44 
45 /** NFS LOOKUP procedure */
46 #define NFS_LOOKUP 3
47 /** NFS READLINK procedure */
48 #define NFS_READLINK 5
49 /** NFS READ procedure */
50 #define NFS_READ 6
51 
52 /**
53  * Extract a file handle from the beginning of an I/O buffer
54  *
55  * @v io_buf I/O buffer
56  * @v fh File handle
57  * @ret size Size of the data read
58  */
59 size_t nfs_iob_get_fh ( struct io_buffer *io_buf, struct nfs_fh *fh ) {
60  fh->size = oncrpc_iob_get_int ( io_buf );
61 
62  if ( fh->size > 64 )
63  return sizeof ( uint32_t );
64 
65  memcpy (fh->fh, io_buf->data, fh->size );
66  iob_pull ( io_buf, fh->size );
67 
68  return fh->size + sizeof ( uint32_t );
69 }
70 
71 /**
72  * Add a file handle to the end of an I/O buffer
73  *
74  * @v io_buf I/O buffer
75  * @v fh File handle
76  * @ret size Size of the data written
77  */
78 size_t nfs_iob_add_fh ( struct io_buffer *io_buf, const struct nfs_fh *fh ) {
79  size_t s;
80 
81  s = oncrpc_iob_add_int ( io_buf, fh->size );
82  memcpy ( iob_put ( io_buf, fh->size ), &fh->fh, fh->size );
83 
84  return s + fh->size;
85 }
86 
87 /**
88  * Send a LOOKUP request
89  *
90  * @v intf Interface to send the request on
91  * @v session ONC RPC session
92  * @v fh The file handle of the the directory
93  * @v filename The file name
94  * @ret rc Return status code
95  */
96 int nfs_lookup ( struct interface *intf, struct oncrpc_session *session,
97  const struct nfs_fh *fh, const char *filename ) {
98  struct oncrpc_field fields[] = {
99  ONCRPC_SUBFIELD ( array, fh->size, &fh->fh ),
100  ONCRPC_FIELD ( str, filename ),
102  };
103 
104  return oncrpc_call ( intf, session, NFS_LOOKUP, fields );
105 }
106 
107 /**
108  * Send a READLINK request
109  *
110  * @v intf Interface to send the request on
111  * @v session ONC RPC session
112  * @v fh The symlink file handle
113  * @ret rc Return status code
114  */
115 int nfs_readlink ( struct interface *intf, struct oncrpc_session *session,
116  const struct nfs_fh *fh ) {
117  struct oncrpc_field fields[] = {
118  ONCRPC_SUBFIELD ( array, fh->size, &fh->fh ),
120  };
121 
122  return oncrpc_call ( intf, session, NFS_READLINK, fields );
123 }
124 
125 /**
126  * Send a READ request
127  *
128  * @v intf Interface to send the request on
129  * @v session ONC RPC session
130  * @v fh The file handle
131  * @v offset Offset
132  * @v count Byte count
133  * @ret rc Return status code
134  */
135 int nfs_read ( struct interface *intf, struct oncrpc_session *session,
136  const struct nfs_fh *fh, uint64_t offset, uint32_t count ) {
137  struct oncrpc_field fields[] = {
138  ONCRPC_SUBFIELD ( array, fh->size, &fh->fh ),
140  ONCRPC_FIELD ( int32, count ),
142  };
143 
144  return oncrpc_call ( intf, session, NFS_READ, fields );
145 }
146 
147 /**
148  * Parse a LOOKUP reply
149  *
150  * @v lookup_reply A structure where the data will be saved
151  * @v reply The ONC RPC reply to get data from
152  * @ret rc Return status code
153  */
154 int nfs_get_lookup_reply ( struct nfs_lookup_reply *lookup_reply,
155  struct oncrpc_reply *reply ) {
156  if ( ! lookup_reply || ! reply )
157  return -EINVAL;
158 
159  lookup_reply->status = oncrpc_iob_get_int ( reply->data );
160  switch ( lookup_reply->status )
161  {
162  case NFS3_OK:
163  break;
164  case NFS3ERR_PERM:
165  return -EPERM;
166  case NFS3ERR_NOENT:
167  return -ENOENT;
168  case NFS3ERR_IO:
169  return -EIO;
170  case NFS3ERR_ACCES:
171  return -EACCES;
172  case NFS3ERR_NOTDIR:
173  return -ENOTDIR;
174  case NFS3ERR_NAMETOOLONG:
175  return -ENAMETOOLONG;
176  case NFS3ERR_STALE:
177  return -ESTALE;
178  case NFS3ERR_BADHANDLE:
179  case NFS3ERR_SERVERFAULT:
180  default:
181  return -EPROTO;
182  }
183 
184  nfs_iob_get_fh ( reply->data, &lookup_reply->fh );
185 
186  if ( oncrpc_iob_get_int ( reply->data ) == 1 )
187  lookup_reply->ent_type = oncrpc_iob_get_int ( reply->data );
188 
189  return 0;
190 }
191 /**
192  * Parse a READLINK reply
193  *
194  * @v readlink_reply A structure where the data will be saved
195  * @v reply The ONC RPC reply to get data from
196  * @ret rc Return status code
197  */
198 int nfs_get_readlink_reply ( struct nfs_readlink_reply *readlink_reply,
199  struct oncrpc_reply *reply ) {
200  if ( ! readlink_reply || ! reply )
201  return -EINVAL;
202 
203  readlink_reply->status = oncrpc_iob_get_int ( reply->data );
204  switch ( readlink_reply->status )
205  {
206  case NFS3_OK:
207  break;
208  case NFS3ERR_IO:
209  return -EIO;
210  case NFS3ERR_ACCES:
211  return -EACCES;
212  case NFS3ERR_INVAL:
213  return -EINVAL;
214  case NFS3ERR_NOTSUPP:
215  return -ENOTSUP;
216  case NFS3ERR_STALE:
217  return -ESTALE;
218  case NFS3ERR_BADHANDLE:
219  case NFS3ERR_SERVERFAULT:
220  default:
221  return -EPROTO;
222  }
223 
224  if ( oncrpc_iob_get_int ( reply->data ) == 1 )
225  iob_pull ( reply->data, 5 * sizeof ( uint32_t ) +
226  8 * sizeof ( uint64_t ) );
227 
228  readlink_reply->path_len = oncrpc_iob_get_int ( reply->data );
229  readlink_reply->path = reply->data->data;
230 
231  return 0;
232 }
233 
234 /**
235  * Parse a READ reply
236  *
237  * @v read_reply A structure where the data will be saved
238  * @v reply The ONC RPC reply to get data from
239  * @ret rc Return status code
240  */
241 int nfs_get_read_reply ( struct nfs_read_reply *read_reply,
242  struct oncrpc_reply *reply ) {
243  if ( ! read_reply || ! reply )
244  return -EINVAL;
245 
246  read_reply->status = oncrpc_iob_get_int ( reply->data );
247  switch ( read_reply->status )
248  {
249  case NFS3_OK:
250  break;
251  case NFS3ERR_PERM:
252  return -EPERM;
253  case NFS3ERR_NOENT:
254  return -ENOENT;
255  case NFS3ERR_IO:
256  return -EIO;
257  case NFS3ERR_NXIO:
258  return -ENXIO;
259  case NFS3ERR_ACCES:
260  return -EACCES;
261  case NFS3ERR_INVAL:
262  return -EINVAL;
263  case NFS3ERR_STALE:
264  return -ESTALE;
265  case NFS3ERR_BADHANDLE:
266  case NFS3ERR_SERVERFAULT:
267  default:
268  return -EPROTO;
269  }
270 
271  if ( oncrpc_iob_get_int ( reply->data ) == 1 )
272  {
273  iob_pull ( reply->data, 5 * sizeof ( uint32_t ) );
274  read_reply->filesize = oncrpc_iob_get_int64 ( reply->data );
275  iob_pull ( reply->data, 7 * sizeof ( uint64_t ) );
276  }
277 
278  read_reply->count = oncrpc_iob_get_int ( reply->data );
279  read_reply->eof = oncrpc_iob_get_int ( reply->data );
280  read_reply->data_len = oncrpc_iob_get_int ( reply->data );
281  read_reply->data = reply->data->data;
282 
283  if ( read_reply->count != read_reply->data_len )
284  return -EPROTO;
285 
286  return 0;
287 }
288 
#define ONCRPC_FIELD(type, value)
Definition: oncrpc.h:28
#define NFS3ERR_NAMETOOLONG
Filename too long.
Definition: nfs.h:46
#define iob_pull(iobuf, len)
Definition: iobuf.h:98
#define EINVAL
Invalid argument.
Definition: errno.h:428
#define iob_put(iobuf, len)
Definition: iobuf.h:116
uint32_t status
Reply status.
Definition: nfs.h:85
uint32_t status
Reply status.
Definition: nfs.h:112
A NFS file handle.
Definition: nfs.h:74
uint32_t count
Bytes read.
Definition: nfs.h:116
int nfs_get_read_reply(struct nfs_read_reply *read_reply, struct oncrpc_reply *reply)
Parse a READ reply.
Definition: nfs.c:241
#define NFS_LOOKUP
NFS LOOKUP procedure.
Definition: nfs.c:46
size_t nfs_iob_add_fh(struct io_buffer *io_buf, const struct nfs_fh *fh)
Add a file handle to the end of an I/O buffer.
Definition: nfs.c:78
uint8_t fh[64]
Definition: nfs.h:75
int nfs_get_lookup_reply(struct nfs_lookup_reply *lookup_reply, struct oncrpc_reply *reply)
Parse a LOOKUP reply.
Definition: nfs.c:154
Error codes.
#define oncrpc_iob_get_int64(buf)
Get a 64 bits integer from the beginning of an I/O buffer.
Definition: oncrpc_iob.h:52
I/O buffers.
#define NFS3_OK
No error.
Definition: nfs.h:22
struct nfs_fh fh
File handle.
Definition: nfs.h:89
#define NFS_READLINK
NFS READLINK procedure.
Definition: nfs.c:48
#define ENOENT
No such file or directory.
Definition: errno.h:514
unsigned long long uint64_t
Definition: stdint.h:13
#define EACCES
Permission denied.
Definition: errno.h:298
uint32_t eof
End-of-File indicator.
Definition: nfs.h:118
int oncrpc_call(struct interface *intf, struct oncrpc_session *session, uint32_t proc_name, const struct oncrpc_field fields[])
Definition: oncrpc.c:129
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
int nfs_lookup(struct interface *intf, struct oncrpc_session *session, const struct nfs_fh *fh, const char *filename)
Send a LOOKUP request.
Definition: nfs.c:96
int nfs_read(struct interface *intf, struct oncrpc_session *session, const struct nfs_fh *fh, uint64_t offset, uint32_t count)
Send a READ request.
Definition: nfs.c:135
int64_t int64
Definition: stdint.h:33
A NFS LOOKUP reply.
Definition: nfs.h:83
enum nfs_attr_type ent_type
Entity type.
Definition: nfs.h:87
void * memcpy(void *dest, const void *src, size_t len) __nonnull
#define oncrpc_iob_get_int(buf)
Get a 32 bits integer from the beginning of an I/O buffer.
Definition: oncrpc_iob.h:38
size_t size
Definition: nfs.h:76
uint32_t array
Array number.
Definition: edd.h:30
#define NFS3ERR_SERVERFAULT
An error occurred on the server which does not map to any of the legal NFS version 3 protocol error v...
Definition: nfs.h:61
int32_t int32
Definition: stdint.h:31
#define NFS3ERR_PERM
Not owner.
Definition: nfs.h:24
Assertions.
An object interface.
Definition: interface.h:109
struct ntlm_data session
Session key.
Definition: ntlm.h:24
#define ENOTDIR
Not a directory.
Definition: errno.h:574
static userptr_t size_t offset
Offset of the first segment within the content.
Definition: deflate.h:259
Feature list.
static size_t oncrpc_iob_add_int(struct io_buffer *io_buf, uint32_t val)
Add a 32 bits integer to the end of an I/O buffer.
Definition: oncrpc_iob.h:83
SUN ONC RPC protocol.
#define EPROTO
Protocol error.
Definition: errno.h:624
Configuration settings.
#define NFS3ERR_NXIO
No such device or address.
Definition: nfs.h:30
uint32_t data_len
Data length.
Definition: nfs.h:120
A NFS READ reply.
Definition: nfs.h:110
#define ONCRPC_SUBFIELD(type, args...)
Definition: oncrpc.h:29
Data transfer interface opening.
size_t nfs_iob_get_fh(struct io_buffer *io_buf, struct nfs_fh *fh)
Extract a file handle from the beginning of an I/O buffer.
Definition: nfs.c:59
#define NFS3ERR_IO
I/O error.
Definition: nfs.h:28
#define NFS3ERR_NOTSUPP
Operation not supported.
Definition: nfs.h:56
unsigned int uint32_t
Definition: stdint.h:12
#define EPERM
Operation not permitted.
Definition: errno.h:614
#define ENXIO
No such device or address.
Definition: errno.h:599
#define NFS3ERR_NOENT
No such file or directory.
Definition: nfs.h:26
int nfs_readlink(struct interface *intf, struct oncrpc_session *session, const struct nfs_fh *fh)
Send a READLINK request.
Definition: nfs.c:115
#define ONCRPC_FIELD_END
Definition: oncrpc.h:32
Network File System protocol.
void * data
Start of data.
Definition: iobuf.h:44
#define EIO
Input/output error.
Definition: errno.h:433
#define NFS3ERR_BADHANDLE
Illegal NFS file handle.
Definition: nfs.h:52
uint16_t count
Number of entries.
Definition: ena.h:22
#define ENAMETOOLONG
Filename too long.
Definition: errno.h:473
#define NFS3ERR_STALE
Invalid file handle.
Definition: nfs.h:48
#define NFS_READ
NFS READ procedure.
Definition: nfs.c:50
void * data
Data read.
Definition: nfs.h:122
SUN ONC RPC protocol.
#define NFS3ERR_INVAL
Invalid argument.
Definition: nfs.h:44
int nfs_get_readlink_reply(struct nfs_readlink_reply *readlink_reply, struct oncrpc_reply *reply)
Parse a READLINK reply.
Definition: nfs.c:198
SUN ONC RPC protocol.
Time source.
String functions.
#define ESTALE
Stale file handle.
Definition: errno.h:659
#define NFS3ERR_ACCES
Permission denied.
Definition: nfs.h:32
NFS MOUNT protocol.
struct io_buffer * data
Definition: oncrpc.h:68
uint64_t filesize
File size.
Definition: nfs.h:114
#define NFS3ERR_NOTDIR
Not a directory.
Definition: nfs.h:40
A persistent I/O buffer.
Definition: iobuf.h:32