iPXE
nfs_open.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/socket.h>
30 #include <ipxe/tcpip.h>
31 #include <ipxe/in.h>
32 #include <ipxe/iobuf.h>
33 #include <ipxe/xfer.h>
34 #include <ipxe/open.h>
35 #include <ipxe/uri.h>
36 #include <ipxe/features.h>
37 #include <ipxe/nfs.h>
38 #include <ipxe/nfs_open.h>
39 #include <ipxe/oncrpc.h>
40 #include <ipxe/oncrpc_iob.h>
41 #include <ipxe/portmap.h>
42 #include <ipxe/mount.h>
43 #include <ipxe/nfs_uri.h>
44 
45 /** @file
46  *
47  * Network File System protocol
48  *
49  */
50 
52 
53 #define NFS_RSIZE 100000
54 
60 };
61 
67 };
68 
69 enum nfs_state {
70  NFS_NONE = 0,
78 };
79 
80 /**
81  * A NFS request
82  *
83  */
84 struct nfs_request {
85  /** Reference counter */
86  struct refcnt refcnt;
87  /** Data transfer interface */
88  struct interface xfer;
89 
93 
97 
101 
103 
104  char * hostname;
105  struct nfs_uri uri;
106 
110 
111  size_t remaining;
112  int eof;
113 };
114 
115 static void nfs_step ( struct nfs_request *nfs );
116 
117 /**
118  * Free NFS request
119  *
120  * @v refcnt Reference counter
121  */
122 static void nfs_free ( struct refcnt *refcnt ) {
123  struct nfs_request *nfs;
124 
125  nfs = container_of ( refcnt, struct nfs_request, refcnt );
126  DBGC ( nfs, "NFS_OPEN %p freed\n", nfs );
127 
128  nfs_uri_free ( &nfs->uri );
129 
130  free ( nfs->hostname );
131  free ( nfs->auth_sys.hostname );
132  free ( nfs );
133 }
134 
135 /**
136  * Mark NFS operation as complete
137  *
138  * @v nfs NFS request
139  * @v rc Return status code
140  */
141 static void nfs_done ( struct nfs_request *nfs, int rc ) {
142  if ( rc == 0 && nfs->nfs_state != NFS_CLOSED )
143  rc = -ECONNRESET;
144 
145  DBGC ( nfs, "NFS_OPEN %p completed (%s)\n", nfs, strerror ( rc ) );
146 
147  intf_shutdown ( &nfs->xfer, rc );
148  intf_shutdown ( &nfs->pm_intf, rc );
149  intf_shutdown ( &nfs->mount_intf, rc );
150  intf_shutdown ( &nfs->nfs_intf, rc );
151 }
152 
153 static int nfs_connect ( struct interface *intf, uint16_t port,
154  const char *hostname ) {
155  struct sockaddr_tcpip peer;
156  struct sockaddr_tcpip local;
157 
158  if ( ! intf || ! hostname || ! port )
159  return -EINVAL;
160 
161  memset ( &peer, 0, sizeof ( peer ) );
162  memset ( &local, 0, sizeof ( local ) );
163  peer.st_port = htons ( port );
164 
165  /* Use a local port < 1024 to avoid using the 'insecure' option in
166  * /etc/exports file. */
168 
169  return xfer_open_named_socket ( intf, SOCK_STREAM,
170  ( struct sockaddr * ) &peer, hostname,
171  ( struct sockaddr * ) &local );
172 }
173 
174 static void nfs_pm_step ( struct nfs_request *nfs ) {
175  int rc;
176 
177  if ( ! xfer_window ( &nfs->pm_intf ) )
178  return;
179 
180  if ( nfs->pm_state == NFS_PORTMAP_NONE ) {
181  DBGC ( nfs, "NFS_OPEN %p GETPORT call (mount)\n", nfs );
182 
183  rc = portmap_getport ( &nfs->pm_intf, &nfs->pm_session,
186  if ( rc != 0 )
187  goto err;
188 
189  nfs->pm_state++;
190  return;
191  }
192 
193  if ( nfs->pm_state == NFS_PORTMAP_NFSPORT ) {
194  DBGC ( nfs, "NFS_OPEN %p GETPORT call (nfs)\n", nfs );
195 
196  rc = portmap_getport ( &nfs->pm_intf, &nfs->pm_session,
199  if ( rc != 0 )
200  goto err;
201 
202  return;
203  }
204 
205  return;
206 err:
207  nfs_done ( nfs, rc );
208 }
209 
210 static int nfs_pm_deliver ( struct nfs_request *nfs,
211  struct io_buffer *io_buf,
212  struct xfer_metadata *meta __unused ) {
213  int rc;
214  struct oncrpc_reply reply;
215  struct portmap_getport_reply getport_reply;
216 
217  oncrpc_get_reply ( &nfs->pm_session, &reply, io_buf );
218  if ( reply.accept_state != 0 )
219  {
220  rc = -EPROTO;
221  goto err;
222  }
223 
224  if ( nfs->pm_state == NFS_PORTMAP_MOUNTPORT ) {
225  DBGC ( nfs, "NFS_OPEN %p got GETPORT reply (mount)\n", nfs );
226 
227  rc = portmap_get_getport_reply ( &getport_reply, &reply );
228  if ( rc != 0 )
229  goto err;
230 
231  rc = nfs_connect ( &nfs->mount_intf, getport_reply.port,
232  nfs->hostname );
233  if ( rc != 0 )
234  goto err;
235 
236  nfs->pm_state++;
237  nfs_pm_step ( nfs );
238 
239  goto done;
240  }
241 
242  if ( nfs->pm_state == NFS_PORTMAP_NFSPORT ) {
243  DBGC ( nfs, "NFS_OPEN %p got GETPORT reply (nfs)\n", nfs );
244 
245  rc = portmap_get_getport_reply ( &getport_reply, &reply );
246  if ( rc != 0 )
247  goto err;
248 
249  rc = nfs_connect ( &nfs->nfs_intf, getport_reply.port,
250  nfs->hostname );
251  if ( rc != 0 )
252  goto err;
253 
254  intf_shutdown ( &nfs->pm_intf, 0 );
255  nfs->pm_state++;
256 
257  goto done;
258  }
259 
260  rc = -EPROTO;
261 err:
262  nfs_done ( nfs, rc );
263 done:
264  free_iob ( io_buf );
265  return 0;
266 }
267 
268 static void nfs_mount_step ( struct nfs_request *nfs ) {
269  int rc;
270 
271  if ( ! xfer_window ( &nfs->mount_intf ) )
272  return;
273 
274  if ( nfs->mount_state == NFS_MOUNT_NONE ) {
275  DBGC ( nfs, "NFS_OPEN %p MNT call (%s)\n", nfs,
276  nfs_uri_mountpoint ( &nfs->uri ) );
277 
278  rc = mount_mnt ( &nfs->mount_intf, &nfs->mount_session,
279  nfs_uri_mountpoint ( &nfs->uri ) );
280  if ( rc != 0 )
281  goto err;
282 
283  nfs->mount_state++;
284  return;
285  }
286 
287  if ( nfs->mount_state == NFS_MOUNT_UMNT ) {
288  DBGC ( nfs, "NFS_OPEN %p UMNT call\n", nfs );
289 
290  rc = mount_umnt ( &nfs->mount_intf, &nfs->mount_session,
291  nfs_uri_mountpoint ( &nfs->uri ) );
292  if ( rc != 0 )
293  goto err;
294  }
295 
296  return;
297 err:
298  nfs_done ( nfs, rc );
299 }
300 
301 static int nfs_mount_deliver ( struct nfs_request *nfs,
302  struct io_buffer *io_buf,
303  struct xfer_metadata *meta __unused ) {
304  int rc;
305  struct oncrpc_reply reply;
306  struct mount_mnt_reply mnt_reply;
307 
308  oncrpc_get_reply ( &nfs->mount_session, &reply, io_buf );
309  if ( reply.accept_state != 0 )
310  {
311  rc = -EPROTO;
312  goto err;
313  }
314 
315  if ( nfs->mount_state == NFS_MOUNT_MNT ) {
316  DBGC ( nfs, "NFS_OPEN %p got MNT reply\n", nfs );
317  rc = mount_get_mnt_reply ( &mnt_reply, &reply );
318  if ( rc != 0 ) {
319  switch ( mnt_reply.status ) {
320  case MNT3ERR_NOTDIR:
321  case MNT3ERR_NOENT:
322  case MNT3ERR_ACCES:
323  break;
324 
325  default:
326  goto err;
327  }
328 
329  if ( ! strcmp ( nfs_uri_mountpoint ( &nfs->uri ),
330  "/" ) )
331  goto err;
332 
333  if ( ( rc = nfs_uri_next_mountpoint ( &nfs->uri ) ) )
334  goto err;
335 
336  DBGC ( nfs, "NFS_OPEN %p MNT failed retrying with " \
337  "%s\n", nfs, nfs_uri_mountpoint ( &nfs->uri ) );
338 
339  nfs->mount_state--;
340  nfs_mount_step ( nfs );
341 
342  goto done;
343  }
344 
345  nfs->current_fh = mnt_reply.fh;
346  nfs->nfs_state = NFS_LOOKUP;
347  nfs_step ( nfs );
348 
349  goto done;
350  }
351 
352  if ( nfs->mount_state == NFS_MOUNT_UMNT ) {
353  DBGC ( nfs, "NFS_OPEN %p got UMNT reply\n", nfs );
354  nfs_done ( nfs, 0 );
355 
356  goto done;
357  }
358 
359  rc = -EPROTO;
360 err:
361  nfs_done ( nfs, rc );
362 done:
363  free_iob ( io_buf );
364  return 0;
365 }
366 
367 static void nfs_step ( struct nfs_request *nfs ) {
368  int rc;
369  char *path_component;
370 
371  if ( ! xfer_window ( &nfs->nfs_intf ) )
372  return;
373 
374  if ( nfs->nfs_state == NFS_LOOKUP ) {
375  path_component = nfs_uri_next_path_component ( &nfs->uri );
376 
377  DBGC ( nfs, "NFS_OPEN %p LOOKUP call (%s)\n", nfs,
378  path_component );
379 
380  rc = nfs_lookup ( &nfs->nfs_intf, &nfs->nfs_session,
381  &nfs->current_fh, path_component );
382  if ( rc != 0 )
383  goto err;
384 
385  nfs->nfs_state++;
386  return;
387  }
388 
389 
390  if ( nfs->nfs_state == NFS_READLINK ) {
391  DBGC ( nfs, "NFS_OPEN %p READLINK call\n", nfs );
392 
393  rc = nfs_readlink ( &nfs->nfs_intf, &nfs->nfs_session,
394  &nfs->readlink_fh );
395  if ( rc != 0 )
396  goto err;
397 
398  nfs->nfs_state++;
399  return;
400  }
401 
402  if ( nfs->nfs_state == NFS_READ ) {
403  DBGC ( nfs, "NFS_OPEN %p READ call\n", nfs );
404 
405  rc = nfs_read ( &nfs->nfs_intf, &nfs->nfs_session,
406  &nfs->current_fh, nfs->file_offset,
407  NFS_RSIZE );
408  if ( rc != 0 )
409  goto err;
410 
411  nfs->nfs_state++;
412  return;
413  }
414 
415  return;
416 err:
417  nfs_done ( nfs, rc );
418 }
419 
420 static int nfs_deliver ( struct nfs_request *nfs,
421  struct io_buffer *io_buf,
422  struct xfer_metadata *meta __unused ) {
423  int rc;
424  struct oncrpc_reply reply;
425 
426  if ( nfs->remaining == 0 ) {
427  oncrpc_get_reply ( &nfs->nfs_session, &reply, io_buf );
428  if ( reply.accept_state != 0 ) {
429  rc = -EPROTO;
430  goto err;
431  }
432  }
433 
434  if ( nfs->nfs_state == NFS_LOOKUP_SENT ) {
435  struct nfs_lookup_reply lookup_reply;
436 
437  DBGC ( nfs, "NFS_OPEN %p got LOOKUP reply\n", nfs );
438 
439  rc = nfs_get_lookup_reply ( &lookup_reply, &reply );
440  if ( rc != 0 )
441  goto err;
442 
443  if ( lookup_reply.ent_type == NFS_ATTR_SYMLINK ) {
444  nfs->readlink_fh = lookup_reply.fh;
445  nfs->nfs_state = NFS_READLINK;
446  } else {
447  nfs->current_fh = lookup_reply.fh;
448 
449  if ( nfs->uri.lookup_pos[0] == '\0' )
450  nfs->nfs_state = NFS_READ;
451  else
452  nfs->nfs_state--;
453  }
454 
455  nfs_step ( nfs );
456  goto done;
457  }
458 
459  if ( nfs->nfs_state == NFS_READLINK_SENT ) {
460  char *path;
461  struct nfs_readlink_reply readlink_reply;
462 
463  DBGC ( nfs, "NFS_OPEN %p got READLINK reply\n", nfs );
464 
465  rc = nfs_get_readlink_reply ( &readlink_reply, &reply );
466  if ( rc != 0 )
467  goto err;
468 
469  if ( readlink_reply.path_len == 0 )
470  {
471  rc = -EINVAL;
472  goto err;
473  }
474 
475  if ( ! ( path = strndup ( readlink_reply.path,
476  readlink_reply.path_len ) ) )
477  {
478  rc = -ENOMEM;
479  goto err;
480  }
481 
482  nfs_uri_symlink ( &nfs->uri, path );
483  free ( path );
484 
485  DBGC ( nfs, "NFS_OPEN %p new path: %s\n", nfs,
486  nfs->uri.path );
487 
488  nfs->nfs_state = NFS_LOOKUP;
489  nfs_step ( nfs );
490  goto done;
491  }
492 
493  if ( nfs->nfs_state == NFS_READ_SENT ) {
494  if ( nfs->remaining == 0 ) {
495  DBGC ( nfs, "NFS_OPEN %p got READ reply\n", nfs );
496 
497  struct nfs_read_reply read_reply;
498 
499  rc = nfs_get_read_reply ( &read_reply, &reply );
500  if ( rc != 0 )
501  goto err;
502 
503  if ( nfs->file_offset == 0 ) {
504  DBGC2 ( nfs, "NFS_OPEN %p size: %llu bytes\n",
505  nfs, read_reply.filesize );
506 
507  xfer_seek ( &nfs->xfer, read_reply.filesize );
508  xfer_seek ( &nfs->xfer, 0 );
509  }
510 
511  nfs->file_offset += read_reply.count;
512  nfs->remaining = read_reply.count;
513  nfs->eof = read_reply.eof;
514  }
515 
516  size_t len = iob_len ( io_buf );
517  if ( len > nfs->remaining )
518  iob_unput ( io_buf, len - nfs->remaining );
519 
520  nfs->remaining -= iob_len ( io_buf );
521 
522  DBGC ( nfs, "NFS_OPEN %p got %zd bytes\n", nfs,
523  iob_len ( io_buf ) );
524 
525  rc = xfer_deliver_iob ( &nfs->xfer, iob_disown ( io_buf ) );
526  if ( rc != 0 )
527  goto err;
528 
529  if ( nfs->remaining == 0 ) {
530  if ( ! nfs->eof ) {
531  nfs->nfs_state--;
532  nfs_step ( nfs );
533  } else {
534  intf_shutdown ( &nfs->nfs_intf, 0 );
535  nfs->nfs_state++;
536  nfs->mount_state++;
537  nfs_mount_step ( nfs );
538  }
539  }
540 
541  return 0;
542  }
543 
544  rc = -EPROTO;
545 err:
546  nfs_done ( nfs, rc );
547 done:
548  free_iob ( io_buf );
549  return 0;
550 }
551 
552 /*****************************************************************************
553  * Interfaces
554  *
555  */
556 
558  INTF_OP ( intf_close, struct nfs_request *, nfs_done ),
559 };
560 
561 /** NFS data transfer interface descriptor */
563  INTF_DESC ( struct nfs_request, xfer, nfs_xfer_operations );
564 
566  INTF_OP ( intf_close, struct nfs_request *, nfs_done ),
569 };
570 
572  INTF_DESC ( struct nfs_request, pm_intf, nfs_pm_operations );
573 
575  INTF_OP ( intf_close, struct nfs_request *, nfs_done ),
578 };
579 
581  INTF_DESC ( struct nfs_request, mount_intf, nfs_mount_operations );
582 
584  INTF_OP ( intf_close, struct nfs_request *, nfs_done ),
587 };
588 
590  INTF_DESC_PASSTHRU ( struct nfs_request, nfs_intf, nfs_operations,
591  xfer );
592 
593 /*****************************************************************************
594  *
595  * URI opener
596  *
597  */
598 
599 static int nfs_parse_uri ( struct nfs_request *nfs, const struct uri *uri ) {
600  int rc;
601 
602  if ( ! uri || ! uri->host || ! uri->path )
603  return -EINVAL;
604 
605  if ( ( rc = nfs_uri_init ( &nfs->uri, uri ) ) != 0 )
606  return rc;
607 
608  if ( ! ( nfs->hostname = strdup ( uri->host ) ) ) {
609  rc = -ENOMEM;
610  goto err_hostname;
611  }
612 
613  DBGC ( nfs, "NFS_OPEN %p URI parsed: (mountpoint=%s, path=%s)\n",
614  nfs, nfs_uri_mountpoint ( &nfs->uri), nfs->uri.path );
615 
616  return 0;
617 
618 err_hostname:
619  nfs_uri_free ( &nfs->uri );
620  return rc;
621 }
622 
623 /**
624  * Initiate a NFS connection
625  *
626  * @v xfer Data transfer interface
627  * @v uri Uniform Resource Identifier
628  * @ret rc Return status code
629  */
630 static int nfs_open ( struct interface *xfer, struct uri *uri ) {
631  int rc;
632  struct nfs_request *nfs;
633 
634  nfs = zalloc ( sizeof ( *nfs ) );
635  if ( ! nfs )
636  return -ENOMEM;
637 
638  rc = nfs_parse_uri( nfs, uri );
639  if ( rc != 0 )
640  goto err_uri;
641 
642  rc = oncrpc_init_cred_sys ( &nfs->auth_sys );
643  if ( rc != 0 )
644  goto err_cred;
645 
646  ref_init ( &nfs->refcnt, nfs_free );
647  intf_init ( &nfs->xfer, &nfs_xfer_desc, &nfs->refcnt );
648  intf_init ( &nfs->pm_intf, &nfs_pm_desc, &nfs->refcnt );
649  intf_init ( &nfs->mount_intf, &nfs_mount_desc, &nfs->refcnt );
650  intf_init ( &nfs->nfs_intf, &nfs_desc, &nfs->refcnt );
651 
655 
656  DBGC ( nfs, "NFS_OPEN %p connecting to port mapper (%s:%d)...\n", nfs,
657  nfs->hostname, PORTMAP_PORT );
658 
659  rc = nfs_connect ( &nfs->pm_intf, PORTMAP_PORT, nfs->hostname );
660  if ( rc != 0 )
661  goto err_connect;
662 
663  /* Attach to parent interface, mortalise self, and return */
664  intf_plug_plug ( &nfs->xfer, xfer );
665  ref_put ( &nfs->refcnt );
666 
667  return 0;
668 
669 err_connect:
670  free ( nfs->auth_sys.hostname );
671 err_cred:
672  nfs_uri_free ( &nfs->uri );
673  free ( nfs->hostname );
674 err_uri:
675  free ( nfs );
676  return rc;
677 }
678 
679 /** NFS URI opener */
680 struct uri_opener nfs_uri_opener __uri_opener = {
681  .scheme = "nfs",
682  .open = nfs_open,
683 };
void nfs_uri_free(struct nfs_uri *uri)
Definition: nfs_uri.c:143
struct interface nfs_intf
Definition: nfs_open.c:92
#define EINVAL
Invalid argument.
Definition: errno.h:428
An object interface operation.
Definition: interface.h:17
#define ECONNRESET
Connection reset.
Definition: errno.h:363
TCP/IP socket address.
Definition: tcpip.h:75
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition: xfer.c:146
unsigned short uint16_t
Definition: stdint.h:11
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:249
int mount_get_mnt_reply(struct mount_mnt_reply *mnt_reply, struct oncrpc_reply *reply)
Parse an MNT reply.
Definition: mount.c:91
enum nfs_pm_state pm_state
Definition: nfs_open.c:94
struct oncrpc_session mount_session
Definition: nfs_open.c:99
Data transfer metadata.
Definition: xfer.h:22
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition: interface.c:278
static void nfs_done(struct nfs_request *nfs, int rc)
Mark NFS operation as complete.
Definition: nfs_open.c:141
int xfer_deliver_iob(struct interface *intf, struct io_buffer *iobuf)
Deliver datagram as I/O buffer without metadata.
Definition: xfer.c:255
FEATURE(FEATURE_PROTOCOL, "NFS", DHCP_EB_FEATURE_NFS, 1)
#define ONCRPC_NFS
NFS protocol number.
Definition: nfs.h:16
A NFS file handle.
Definition: nfs.h:74
uint32_t count
Bytes read.
Definition: nfs.h:116
#define FEATURE_PROTOCOL
Network protocols.
Definition: features.h:21
int nfs_get_read_reply(struct nfs_read_reply *read_reply, struct oncrpc_reply *reply)
Parse a READ reply.
Definition: nfs.c:241
int nfs_get_lookup_reply(struct nfs_lookup_reply *lookup_reply, struct oncrpc_reply *reply)
Parse a LOOKUP reply.
Definition: nfs.c:154
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:64
Error codes.
struct interface xfer
Data transfer interface.
Definition: nfs_open.c:88
struct nfs_uri uri
Definition: nfs_open.c:105
static void nfs_init_session(struct oncrpc_session *session, struct oncrpc_cred *credential)
Prepare an ONC RPC session to be used as a NFS session.
Definition: nfs.h:137
static int nfs_mount_deliver(struct nfs_request *nfs, struct io_buffer *io_buf, struct xfer_metadata *meta __unused)
Definition: nfs_open.c:301
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
size_t remaining
Definition: nfs_open.c:111
static struct interface_operation nfs_operations[]
Definition: nfs_open.c:583
static void nfs_free(struct refcnt *refcnt)
Free NFS request.
Definition: nfs_open.c:122
#define DBGC(...)
Definition: compiler.h:505
A NFS request.
Definition: nfs_open.c:84
struct nfs_fh fh
File handle.
Definition: nfs.h:89
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition: interface.c:107
unsigned long long uint64_t
Definition: stdint.h:13
static struct interface_operation nfs_pm_operations[]
Definition: nfs_open.c:565
uint32_t accept_state
Definition: oncrpc.h:66
static struct interface_descriptor nfs_xfer_desc
NFS data transfer interface descriptor.
Definition: nfs_open.c:562
enum nfs_mount_state mount_state
Definition: nfs_open.c:95
#define NFS_VERS
NFS protocol version.
Definition: nfs.h:19
Bind to a privileged port (less than 1024)
Definition: tcpip.h:66
Uniform Resource Identifiers.
static int nfs_connect(struct interface *intf, uint16_t port, const char *hostname)
Definition: nfs_open.c:153
#define ONCRPC_MOUNT
NFS MOUNT protocol number.
Definition: mount.h:15
uint32_t eof
End-of-File indicator.
Definition: nfs.h:118
#define PORTMAP_PROTO_TCP
TCP protocol number.
Definition: portmap.h:26
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition: xfer.c:116
struct uri_opener nfs_uri_opener __uri_opener
NFS URI opener.
Definition: nfs_open.c:680
uint64_t file_offset
Definition: nfs_open.c:109
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
struct oncrpc_cred_sys auth_sys
Definition: nfs_open.c:102
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
char * lookup_pos
Definition: nfs_uri.h:18
Data transfer interfaces.
A reference counter.
Definition: refcnt.h:26
static void portmap_init_session(struct oncrpc_session *session, struct oncrpc_cred *credential)
Prepare an ONC RPC session to be used as a PORTMAP session.
Definition: portmap.h:50
static struct interface_descriptor nfs_desc
Definition: nfs_open.c:589
A NFS LOOKUP reply.
Definition: nfs.h:83
#define ENOMEM
Not enough space.
Definition: errno.h:534
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition: iobuf.h:212
enum nfs_attr_type ent_type
Entity type.
Definition: nfs.h:87
u8 port
Port number.
Definition: CIB_PRM.h:31
Assertions.
struct nfs_fh fh
Root file handle.
Definition: mount.h:50
static int nfs_open(struct interface *xfer, struct uri *uri)
Initiate a NFS connection.
Definition: nfs_open.c:630
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
struct nfs_fh readlink_fh
Definition: nfs_open.c:107
An object interface.
Definition: interface.h:124
int portmap_get_getport_reply(struct portmap_getport_reply *getport_reply, struct oncrpc_reply *reply)
Parse a GETPORT reply.
Definition: portmap.c:80
int oncrpc_init_cred_sys(struct oncrpc_cred_sys *auth_sys)
Initialize an ONC RPC AUTH SYS credential structure.
Definition: oncrpc.c:84
nfs_pm_state
Definition: nfs_open.c:55
const char * path
Path (after URI decoding)
Definition: uri.h:80
static struct interface_descriptor nfs_pm_desc
Definition: nfs_open.c:571
const char * scheme
URI protocol name.
Definition: open.h:53
enum nfs_state nfs_state
Definition: nfs_open.c:96
Transport-network layer interface.
Feature list.
static struct interface_operation nfs_xfer_operations[]
Definition: nfs_open.c:557
#define MOUNT_VERS
NFS MOUNT protocol version.
Definition: mount.h:17
int oncrpc_get_reply(struct oncrpc_session *session __unused, struct oncrpc_reply *reply, struct io_buffer *io_buf)
Parse an I/O buffer to extract a ONC RPC REPLY.
Definition: oncrpc.c:215
SUN ONC RPC protocol.
#define EPROTO
Protocol error.
Definition: errno.h:624
int xfer_seek(struct interface *intf, off_t offset)
Seek to position.
Definition: xfer.c:351
int meta(WINDOW *, bool)
Generalized socket address structure.
Definition: socket.h:96
An object interface descriptor.
Definition: interface.h:55
#define iob_unput(iobuf, len)
Definition: iobuf.h:135
nfs_mount_state
Definition: nfs_open.c:62
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static void(* free)(struct refcnt *refcnt))
Definition: refcnt.h:54
#define MNT3ERR_NOENT
No such file or directory.
Definition: mount.h:25
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
int nfs_uri_init(struct nfs_uri *nfs_uri, const struct uri *uri)
Definition: nfs_uri.c:32
#define PORTMAP_PORT
PORTMAP default port.
Definition: portmap.h:16
A NFS READ reply.
Definition: nfs.h:110
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:155
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:32
char * strdup(const char *src)
Duplicate string.
Definition: string.c:380
uint32_t status
Reply status.
Definition: mount.h:48
struct interface mount_intf
Definition: nfs_open.c:91
char * hostname
Definition: oncrpc.h:54
#define SOCK_STREAM
Definition: socket.h:24
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:194
struct oncrpc_session pm_session
Definition: nfs_open.c:98
Data transfer interface opening.
char * nfs_uri_mountpoint(const struct nfs_uri *uri)
Definition: nfs_uri.c:54
const char * host
Host name.
Definition: uri.h:76
static int nfs_parse_uri(struct nfs_request *nfs, const struct uri *uri)
Definition: nfs_open.c:599
struct nfs_fh current_fh
Definition: nfs_open.c:108
static void nfs_pm_step(struct nfs_request *nfs)
Definition: nfs_open.c:174
int portmap_getport(struct interface *intf, struct oncrpc_session *session, uint32_t prog, uint32_t vers, uint32_t proto)
Send a GETPORT request.
Definition: portmap.c:59
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
int mount_mnt(struct interface *intf, struct oncrpc_session *session, const char *mountpoint)
Send a MNT request.
Definition: mount.c:56
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:80
uint32_t len
Length.
Definition: ena.h:14
int nfs_readlink(struct interface *intf, struct oncrpc_session *session, const struct nfs_fh *fh)
Send a READLINK request.
Definition: nfs.c:115
#define DBGC2(...)
Definition: compiler.h:522
Network File System protocol URI handling functions.
int strcmp(const char *first, const char *second)
Compare strings.
Definition: string.c:173
Network File System protocol.
static void mount_init_session(struct oncrpc_session *session, struct oncrpc_cred *credential)
Prepare an ONC RPC session to be used as a MOUNT session.
Definition: mount.h:62
Network File System protocol.
char * hostname
Definition: nfs_open.c:104
uint16_t st_flags
Flags.
Definition: tcpip.h:79
struct oncrpc_session nfs_session
Definition: nfs_open.c:100
static struct interface_descriptor nfs_mount_desc
Definition: nfs_open.c:580
char * strndup(const char *src, size_t max)
Duplicate string.
Definition: string.c:392
A Uniform Resource Identifier.
Definition: uri.h:64
#define INTF_DESC_PASSTHRU(object_type, intf, operations, passthru)
Define an object interface descriptor with pass-through interface.
Definition: interface.h:97
struct mschapv2_challenge peer
Peer challenge.
Definition: mschapv2.h:12
static void nfs_step(struct nfs_request *nfs)
Definition: nfs_open.c:367
static void nfs_mount_step(struct nfs_request *nfs)
Definition: nfs_open.c:268
struct refcnt refcnt
Reference counter.
Definition: nfs_open.c:86
SUN ONC RPC protocol.
#define DHCP_EB_FEATURE_NFS
NFS protocol.
Definition: features.h:57
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition: interface.h:203
Socket addresses.
A URI opener.
Definition: open.h:47
int nfs_get_readlink_reply(struct nfs_readlink_reply *readlink_reply, struct oncrpc_reply *reply)
Parse a READLINK reply.
Definition: nfs.c:198
int nfs_uri_symlink(struct nfs_uri *uri, const char *symlink)
Definition: nfs_uri.c:84
int mount_umnt(struct interface *intf, struct oncrpc_session *session, const char *mountpoint)
Send a UMNT request.
Definition: mount.c:74
SUN ONC RPC protocol.
Time source.
int nfs_uri_next_mountpoint(struct nfs_uri *uri)
Definition: nfs_uri.c:62
nfs_state
Definition: nfs_open.c:69
struct oncrpc_cred credential
Definition: oncrpc.h:52
A MOUNT MNT reply.
Definition: mount.h:46
String functions.
uint32_t port
Port returned.
Definition: portmap.h:37
#define htons(value)
Definition: byteswap.h:135
char * nfs_uri_next_path_component(struct nfs_uri *uri)
Definition: nfs_uri.c:121
struct bofm_section_header done
Definition: bofm_test.c:46
#define NFS_RSIZE
Definition: nfs_open.c:53
char * path
Definition: nfs_uri.h:17
NFS MOUNT protocol.
uint64_t filesize
File size.
Definition: nfs.h:114
static int nfs_deliver(struct nfs_request *nfs, struct io_buffer *io_buf, struct xfer_metadata *meta __unused)
Definition: nfs_open.c:420
int xfer_open_named_socket(struct interface *xfer, int semantics, struct sockaddr *peer, const char *name, struct sockaddr *local)
Open named socket.
Definition: resolv.c:402
#define MNT3ERR_ACCES
Permission denied.
Definition: mount.h:29
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106
A PORTMAP GETPORT reply.
Definition: portmap.h:35
static int nfs_pm_deliver(struct nfs_request *nfs, struct io_buffer *io_buf, struct xfer_metadata *meta __unused)
Definition: nfs_open.c:210
static struct interface_operation nfs_mount_operations[]
Definition: nfs_open.c:574
void * memset(void *dest, int character, size_t len) __nonnull
#define MNT3ERR_NOTDIR
Not a directory.
Definition: mount.h:31
A persistent I/O buffer.
Definition: iobuf.h:33
struct interface pm_intf
Definition: nfs_open.c:90