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 FILE_SECBOOT ( FORBIDDEN );
21 
22 #include <stdint.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <assert.h>
27 #include <errno.h>
28 #include <libgen.h>
29 #include <byteswap.h>
30 #include <ipxe/time.h>
31 #include <ipxe/iobuf.h>
32 #include <ipxe/open.h>
33 #include <ipxe/features.h>
34 #include <ipxe/nfs.h>
35 #include <ipxe/oncrpc.h>
36 #include <ipxe/oncrpc_iob.h>
37 #include <ipxe/portmap.h>
38 #include <ipxe/mount.h>
39 #include <ipxe/settings.h>
40 
41 /** @file
42  *
43  * Network File System protocol
44  *
45  */
46 
47 /** NFS LOOKUP procedure */
48 #define NFS_LOOKUP 3
49 /** NFS READLINK procedure */
50 #define NFS_READLINK 5
51 /** NFS READ procedure */
52 #define NFS_READ 6
53 
54 /**
55  * Extract a file handle from the beginning of an I/O buffer
56  *
57  * @v io_buf I/O buffer
58  * @v fh File handle
59  * @ret size Size of the data read
60  */
61 size_t nfs_iob_get_fh ( struct io_buffer *io_buf, struct nfs_fh *fh ) {
62  fh->size = oncrpc_iob_get_int ( io_buf );
63 
64  if ( fh->size > 64 )
65  return sizeof ( uint32_t );
66 
67  memcpy (fh->fh, io_buf->data, fh->size );
68  iob_pull ( io_buf, fh->size );
69 
70  return fh->size + sizeof ( uint32_t );
71 }
72 
73 /**
74  * Add a file handle to the end of an I/O buffer
75  *
76  * @v io_buf I/O buffer
77  * @v fh File handle
78  * @ret size Size of the data written
79  */
80 size_t nfs_iob_add_fh ( struct io_buffer *io_buf, const struct nfs_fh *fh ) {
81  size_t s;
82 
83  s = oncrpc_iob_add_int ( io_buf, fh->size );
84  memcpy ( iob_put ( io_buf, fh->size ), &fh->fh, fh->size );
85 
86  return s + fh->size;
87 }
88 
89 /**
90  * Send a LOOKUP request
91  *
92  * @v intf Interface to send the request on
93  * @v session ONC RPC session
94  * @v fh The file handle of the the directory
95  * @v filename The file name
96  * @ret rc Return status code
97  */
98 int nfs_lookup ( struct interface *intf, struct oncrpc_session *session,
99  const struct nfs_fh *fh, const char *filename ) {
100  struct oncrpc_field fields[] = {
101  ONCRPC_SUBFIELD ( array, fh->size, &fh->fh ),
102  ONCRPC_FIELD ( str, filename ),
104  };
105 
106  return oncrpc_call ( intf, session, NFS_LOOKUP, fields );
107 }
108 
109 /**
110  * Send a READLINK request
111  *
112  * @v intf Interface to send the request on
113  * @v session ONC RPC session
114  * @v fh The symlink file handle
115  * @ret rc Return status code
116  */
117 int nfs_readlink ( struct interface *intf, struct oncrpc_session *session,
118  const struct nfs_fh *fh ) {
119  struct oncrpc_field fields[] = {
120  ONCRPC_SUBFIELD ( array, fh->size, &fh->fh ),
122  };
123 
124  return oncrpc_call ( intf, session, NFS_READLINK, fields );
125 }
126 
127 /**
128  * Send a READ request
129  *
130  * @v intf Interface to send the request on
131  * @v session ONC RPC session
132  * @v fh The file handle
133  * @v offset Offset
134  * @v count Byte count
135  * @ret rc Return status code
136  */
137 int nfs_read ( struct interface *intf, struct oncrpc_session *session,
138  const struct nfs_fh *fh, uint64_t offset, uint32_t count ) {
139  struct oncrpc_field fields[] = {
140  ONCRPC_SUBFIELD ( array, fh->size, &fh->fh ),
142  ONCRPC_FIELD ( int32, count ),
144  };
145 
146  return oncrpc_call ( intf, session, NFS_READ, fields );
147 }
148 
149 /**
150  * Parse a LOOKUP reply
151  *
152  * @v lookup_reply A structure where the data will be saved
153  * @v reply The ONC RPC reply to get data from
154  * @ret rc Return status code
155  */
156 int nfs_get_lookup_reply ( struct nfs_lookup_reply *lookup_reply,
157  struct oncrpc_reply *reply ) {
158  if ( ! lookup_reply || ! reply )
159  return -EINVAL;
160 
161  lookup_reply->status = oncrpc_iob_get_int ( reply->data );
162  switch ( lookup_reply->status )
163  {
164  case NFS3_OK:
165  break;
166  case NFS3ERR_PERM:
167  return -EPERM;
168  case NFS3ERR_NOENT:
169  return -ENOENT;
170  case NFS3ERR_IO:
171  return -EIO;
172  case NFS3ERR_ACCES:
173  return -EACCES;
174  case NFS3ERR_NOTDIR:
175  return -ENOTDIR;
176  case NFS3ERR_NAMETOOLONG:
177  return -ENAMETOOLONG;
178  case NFS3ERR_STALE:
179  return -ESTALE;
180  case NFS3ERR_BADHANDLE:
181  case NFS3ERR_SERVERFAULT:
182  default:
183  return -EPROTO;
184  }
185 
186  nfs_iob_get_fh ( reply->data, &lookup_reply->fh );
187 
188  if ( oncrpc_iob_get_int ( reply->data ) == 1 )
189  lookup_reply->ent_type = oncrpc_iob_get_int ( reply->data );
190 
191  return 0;
192 }
193 /**
194  * Parse a READLINK reply
195  *
196  * @v readlink_reply A structure where the data will be saved
197  * @v reply The ONC RPC reply to get data from
198  * @ret rc Return status code
199  */
200 int nfs_get_readlink_reply ( struct nfs_readlink_reply *readlink_reply,
201  struct oncrpc_reply *reply ) {
202  if ( ! readlink_reply || ! reply )
203  return -EINVAL;
204 
205  readlink_reply->status = oncrpc_iob_get_int ( reply->data );
206  switch ( readlink_reply->status )
207  {
208  case NFS3_OK:
209  break;
210  case NFS3ERR_IO:
211  return -EIO;
212  case NFS3ERR_ACCES:
213  return -EACCES;
214  case NFS3ERR_INVAL:
215  return -EINVAL;
216  case NFS3ERR_NOTSUPP:
217  return -ENOTSUP;
218  case NFS3ERR_STALE:
219  return -ESTALE;
220  case NFS3ERR_BADHANDLE:
221  case NFS3ERR_SERVERFAULT:
222  default:
223  return -EPROTO;
224  }
225 
226  if ( oncrpc_iob_get_int ( reply->data ) == 1 )
227  iob_pull ( reply->data, 5 * sizeof ( uint32_t ) +
228  8 * sizeof ( uint64_t ) );
229 
230  readlink_reply->path_len = oncrpc_iob_get_int ( reply->data );
231  readlink_reply->path = reply->data->data;
232 
233  return 0;
234 }
235 
236 /**
237  * Parse a READ reply
238  *
239  * @v read_reply A structure where the data will be saved
240  * @v reply The ONC RPC reply to get data from
241  * @ret rc Return status code
242  */
243 int nfs_get_read_reply ( struct nfs_read_reply *read_reply,
244  struct oncrpc_reply *reply ) {
245  if ( ! read_reply || ! reply )
246  return -EINVAL;
247 
248  read_reply->status = oncrpc_iob_get_int ( reply->data );
249  switch ( read_reply->status )
250  {
251  case NFS3_OK:
252  break;
253  case NFS3ERR_PERM:
254  return -EPERM;
255  case NFS3ERR_NOENT:
256  return -ENOENT;
257  case NFS3ERR_IO:
258  return -EIO;
259  case NFS3ERR_NXIO:
260  return -ENXIO;
261  case NFS3ERR_ACCES:
262  return -EACCES;
263  case NFS3ERR_INVAL:
264  return -EINVAL;
265  case NFS3ERR_STALE:
266  return -ESTALE;
267  case NFS3ERR_BADHANDLE:
268  case NFS3ERR_SERVERFAULT:
269  default:
270  return -EPROTO;
271  }
272 
273  if ( oncrpc_iob_get_int ( reply->data ) == 1 )
274  {
275  iob_pull ( reply->data, 5 * sizeof ( uint32_t ) );
276  read_reply->filesize = oncrpc_iob_get_int64 ( reply->data );
277  iob_pull ( reply->data, 7 * sizeof ( uint64_t ) );
278  }
279 
280  read_reply->count = oncrpc_iob_get_int ( reply->data );
281  read_reply->eof = oncrpc_iob_get_int ( reply->data );
282  read_reply->data_len = oncrpc_iob_get_int ( reply->data );
283  read_reply->data = reply->data->data;
284 
285  if ( read_reply->count != read_reply->data_len )
286  return -EPROTO;
287 
288  return 0;
289 }
290 
#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:107
#define EINVAL
Invalid argument.
Definition: errno.h:429
#define iob_put(iobuf, len)
Definition: iobuf.h:125
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:243
#define NFS_LOOKUP
NFS LOOKUP procedure.
Definition: nfs.c:48
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:80
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:156
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:50
#define ENOENT
No such file or directory.
Definition: errno.h:515
unsigned long long uint64_t
Definition: stdint.h:13
#define EACCES
Permission denied.
Definition: errno.h:299
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:590
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:98
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:137
int64_t int64
Definition: stdint.h:34
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:31
#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:32
#define NFS3ERR_PERM
Not owner.
Definition: nfs.h:24
Assertions.
An object interface.
Definition: interface.h:125
#define ENOTDIR
Not a directory.
Definition: errno.h:575
FILE_SECBOOT(FORBIDDEN)
static unsigned int count
Number of entries.
Definition: dwmac.h:225
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:625
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:61
#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:615
#define ENXIO
No such device or address.
Definition: errno.h:600
#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:117
#define ONCRPC_FIELD_END
Definition: oncrpc.h:32
Network File System protocol.
void * data
Start of data.
Definition: iobuf.h:53
#define EIO
Input/output error.
Definition: errno.h:434
#define NFS3ERR_BADHANDLE
Illegal NFS file handle.
Definition: nfs.h:52
#define ENAMETOOLONG
Filename too long.
Definition: errno.h:474
#define NFS3ERR_STALE
Invalid file handle.
Definition: nfs.h:48
#define NFS_READ
NFS READ procedure.
Definition: nfs.c:52
uint16_t offset
Offset to command line.
Definition: bzimage.h:8
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:200
SUN ONC RPC protocol.
Time source.
String functions.
#define ESTALE
Stale file handle.
Definition: errno.h:660
#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:38