[nfs] Add support for NFS protocol

Tested-by: Robin Smidsrød <robin@smidsrod.no>
Signed-off-by: Marin Hannache <git@mareo.fr>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Marin Hannache
2013-07-15 17:56:29 +02:00
committed by Michael Brown
parent ed28c8304c
commit 30de9e8300
21 changed files with 2238 additions and 5 deletions

View File

@@ -1,6 +1,8 @@
#ifndef ETHERBOOT_BIG_BSWAP_H
#define ETHERBOOT_BIG_BSWAP_H
#define htonll(x) (x)
#define ntohll(x) (x)
#define ntohl(x) (x)
#define htonl(x) (x)
#define ntohs(x) (x)

View File

@@ -450,6 +450,18 @@ struct dhcp_netdev_desc {
*/
#define DHCP_EB_REVERSE_PASSWORD DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xc1 )
/** User ID
*
* This will be used as the user id for AUTH_SYS based authentication in NFS.
*/
#define DHCP_EB_UID DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xc2 )
/** Group ID
*
* This will be used as the group id for AUTH_SYS based authentication in NFS.
*/
#define DHCP_EB_GID DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xc3 )
/** iPXE version number */
#define DHCP_EB_VERSION DHCP_ENCAP_OPT ( DHCP_EB_ENCAP, 0xeb )

View File

@@ -208,6 +208,12 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define ERRFILE_fcoe ( ERRFILE_NET | 0x002e0000 )
#define ERRFILE_fcns ( ERRFILE_NET | 0x002f0000 )
#define ERRFILE_vlan ( ERRFILE_NET | 0x00300000 )
#define ERRFILE_oncrpc ( ERRFILE_NET | 0x00310000 )
#define ERRFILE_portmap ( ERRFILE_NET | 0x00320000 )
#define ERRFILE_nfs ( ERRFILE_NET | 0x00330000 )
#define ERRFILE_nfs_open ( ERRFILE_NET | 0x00340000 )
#define ERRFILE_mount ( ERRFILE_NET | 0x00350000 )
#define ERRFILE_oncrpc_iob ( ERRFILE_NET | 0x00360000 )
#define ERRFILE_image ( ERRFILE_IMAGE | 0x00000000 )
#define ERRFILE_elf ( ERRFILE_IMAGE | 0x00010000 )

View File

@@ -54,6 +54,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define DHCP_EB_FEATURE_VLAN 0x26 /**< VLAN support */
#define DHCP_EB_FEATURE_MENU 0x27 /**< Menu support */
#define DHCP_EB_FEATURE_SDI 0x28 /**< SDI image support */
#define DHCP_EB_FEATURE_NFS 0x29 /**< NFS protocol */
/** @} */

76
src/include/ipxe/mount.h Normal file
View File

@@ -0,0 +1,76 @@
#ifndef _IPXE_MOUNT_H
#define _IPXE_MOUNT_H
#include <ipxe/nfs.h>
/** @file
*
* NFS MOUNT protocol.
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
/** NFS MOUNT protocol number */
#define ONCRPC_MOUNT 100005
/** NFS MOUNT protocol version */
#define MOUNT_VERS 3
/** No error */
#define MNT3_OK 0
/** Not owner */
#define MNT3ERR_PERM 1
/** No such file or directory */
#define MNT3ERR_NOENT 2
/** I/O error */
#define MNT3ERR_IO 5
/** Permission denied */
#define MNT3ERR_ACCES 13
/** Not a directory */
#define MNT3ERR_NOTDIR 20
/** Invalid argument */
#define MNT3ERR_INVAL 22
/** Filename too long */
#define MNT3ERR_NAMETOOLONG 63
/** Operation not supported */
#define MNT3ERR_NOTSUPP 10004
/** A failure on the server */
#define MNT3ERR_SERVERFAULT 10006
/**
* A MOUNT MNT reply
*
*/
struct mount_mnt_reply {
/** Reply status */
uint32_t status;
/** Root file handle */
struct nfs_fh fh;
};
/**
* Prepare an ONC RPC session to be used as a MOUNT session
*
* @v session ONC RPC session
* @v credential ONC RPC credential
*
* The credential parameter must not be NULL, use 'oncrpc_auth_none' if you
* don't want a particular scheme to be used.
*/
static inline void mount_init_session ( struct oncrpc_session *session,
struct oncrpc_cred *credential ) {
oncrpc_init_session ( session, credential, &oncrpc_auth_none,
ONCRPC_MOUNT, MOUNT_VERS );
}
int mount_mnt ( struct interface *intf, struct oncrpc_session *session,
const char *mountpoint );
int mount_umnt ( struct interface *intf, struct oncrpc_session *session,
const char *mountpoint );
int mount_get_mnt_reply ( struct mount_mnt_reply *mnt_reply,
struct oncrpc_reply *reply );
#endif /* _IPXE_MOUNT_H */

157
src/include/ipxe/nfs.h Normal file
View File

@@ -0,0 +1,157 @@
#ifndef _IPXE_NFS_H
#define _IPXE_NFS_H
#include <stdint.h>
#include <ipxe/oncrpc.h>
/** @file
*
* Network File System protocol.
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
/** NFS protocol number */
#define ONCRPC_NFS 100003
/** NFS protocol version */
#define NFS_VERS 3
/** No error*/
#define NFS3_OK 0
/** Not owner */
#define NFS3ERR_PERM 1
/** No such file or directory */
#define NFS3ERR_NOENT 2
/** I/O error */
#define NFS3ERR_IO 5
/** No such device or address */
#define NFS3ERR_NXIO 6
/** Permission denied */
#define NFS3ERR_ACCES 13
/** The file specified already exists */
#define NFS3ERR_EXIST 17
/** Attempt to do a cross-device hard link */
#define NFS3ERR_XDEV 18
/** No such device */
#define NFS3ERR_NODEV 19
/** Not a directory */
#define NFS3ERR_NOTDIR 20
/**Is a directory */
#define NFS3ERR_ISDIR 21
/** Invalid argument */
#define NFS3ERR_INVAL 22
/** Filename too long */
#define NFS3ERR_NAMETOOLONG 63
/** Invalid file handle */
#define NFS3ERR_STALE 70
/** Too many levels of remote in path */
#define NFS3ERR_REMOTE 71
/** Illegal NFS file handle */
#define NFS3ERR_BADHANDLE 10001
/** READDIR or READDIRPLUS cookie is stale */
#define NFS3ERR_BAD_COOKIE 10003
/** Operation not supported */
#define NFS3ERR_NOTSUPP 10004
/** Buffer or request is too small */
#define NFS3ERR_TOOSMALL 10005
/** An error occurred on the server which does not map to any of the legal NFS
* version 3 protocol error values */
#define NFS3ERR_SERVERFAULT 10006
/** The server initiated the request, but was not able to complete it in a
* timely fashion */
#define NFS3ERR_JUKEBOX 10008
enum nfs_attr_type {
NFS_ATTR_SYMLINK = 5,
};
/**
* A NFS file handle
*
*/
struct nfs_fh {
uint8_t fh[64];
size_t size;
};
/**
* A NFS LOOKUP reply
*
*/
struct nfs_lookup_reply {
/** Reply status */
uint32_t status;
/** Entity type */
enum nfs_attr_type ent_type;
/** File handle */
struct nfs_fh fh;
};
/**
* A NFS READLINK reply
*
*/
struct nfs_readlink_reply {
/** Reply status */
uint32_t status;
/** File path length */
uint32_t path_len;
/** File path */
char *path;
};
/**
* A NFS READ reply
*
*/
struct nfs_read_reply {
/** Reply status */
uint32_t status;
/** File size */
uint64_t filesize;
/** Bytes read */
uint32_t count;
/** End-of-File indicator */
uint32_t eof;
/** Data length */
uint32_t data_len;
/** Data read */
void *data;
};
size_t nfs_iob_get_fh ( struct io_buffer *io_buf, struct nfs_fh *fh );
size_t nfs_iob_add_fh ( struct io_buffer *io_buf, const struct nfs_fh *fh );
/**
* Prepare an ONC RPC session to be used as a NFS session
*
* @v session ONC RPC session
* @v credential ONC RPC credential
*
* The credential parameter must not be NULL, use 'oncrpc_auth_none' if you
* don't want a particular scheme to be used.
*/
static inline void nfs_init_session ( struct oncrpc_session *session,
struct oncrpc_cred *credential ) {
oncrpc_init_session ( session, credential, &oncrpc_auth_none,
ONCRPC_NFS, NFS_VERS );
}
int nfs_lookup ( struct interface *intf, struct oncrpc_session *session,
const struct nfs_fh *fh, const char *filename );
int nfs_readlink ( struct interface *intf, struct oncrpc_session *session,
const struct nfs_fh *fh );
int nfs_read ( struct interface *intf, struct oncrpc_session *session,
const struct nfs_fh *fh, uint64_t offset, uint32_t count );
int nfs_get_lookup_reply ( struct nfs_lookup_reply *lookup_reply,
struct oncrpc_reply *reply );
int nfs_get_readlink_reply ( struct nfs_readlink_reply *readlink_reply,
struct oncrpc_reply *reply );
int nfs_get_read_reply ( struct nfs_read_reply *read_reply,
struct oncrpc_reply *reply );
#endif /* _IPXE_NFS_H */

View File

@@ -0,0 +1,12 @@
#ifndef _IPXE_NFS_OPEN_H
#define _IPXE_NFS_OPEN_H
/** @file
*
* Network File System protocol.
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
#endif /* _IPXE_NFS_OPEN_H */

128
src/include/ipxe/oncrpc.h Normal file
View File

@@ -0,0 +1,128 @@
#ifndef _IPXE_ONCRPC_H
#define _IPXE_ONCRPC_H
#include <stdint.h>
#include <ipxe/interface.h>
#include <ipxe/iobuf.h>
/** @file
*
* SUN ONC RPC protocol.
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
/** ONC RCP Version */
#define ONCRPC_VERS 2
/** ONC RPC Null Authentication */
#define ONCRPC_AUTH_NONE 0
/** ONC RPC System Authentication (also called UNIX Authentication) */
#define ONCRPC_AUTH_SYS 1
/** Size of an ONC RPC header */
#define ONCRPC_HEADER_SIZE ( 11 * sizeof ( uint32_t ) )
#define ONCRPC_FIELD( type, value ) { oncrpc_ ## type, { .type = value } }
#define ONCRPC_SUBFIELD( type, args... ) \
{ oncrpc_ ## type, { .type = { args } } }
#define ONCRPC_FIELD_END { oncrpc_none, { } }
/** Enusure that size is a multiple of four */
#define oncrpc_align( size ) ( ( (size) + 3 ) & ~3 )
/**
* Calculate the length of a string, including padding bytes.
*
* @v str String
* @ret size Length of the padded string
*/
#define oncrpc_strlen( str ) ( oncrpc_align ( strlen ( str ) ) + \
sizeof ( uint32_t ) )
struct oncrpc_cred {
uint32_t flavor;
uint32_t length;
};
struct oncrpc_cred_sys {
struct oncrpc_cred credential;
uint32_t stamp;
char *hostname;
uint32_t uid;
uint32_t gid;
uint32_t aux_gid_len;
uint32_t aux_gid[16];
};
struct oncrpc_reply
{
struct oncrpc_cred *verifier;
uint32_t rpc_id;
uint32_t reply_state;
uint32_t accept_state;
uint32_t frame_size;
struct io_buffer *data;
};
struct oncrpc_session {
struct oncrpc_reply pending_reply;
struct oncrpc_cred *credential;
struct oncrpc_cred *verifier;
uint32_t rpc_id;
uint32_t prog_name;
uint32_t prog_vers;
};
enum oncrpc_field_type {
oncrpc_none = 0,
oncrpc_int32,
oncrpc_int64,
oncrpc_str,
oncrpc_array,
oncrpc_intarray,
oncrpc_cred,
};
union oncrpc_field_value {
struct {
size_t length;
const void *ptr;
} array;
struct {
size_t length;
const uint32_t *ptr;
} intarray;
int64_t int64;
int32_t int32;
const char *str;
const struct oncrpc_cred *cred;
};
struct oncrpc_field {
enum oncrpc_field_type type;
union oncrpc_field_value value;
};
extern struct oncrpc_cred oncrpc_auth_none;
int oncrpc_init_cred_sys ( struct oncrpc_cred_sys *auth_sys );
void oncrpc_init_session ( struct oncrpc_session *session,
struct oncrpc_cred *credential,
struct oncrpc_cred *verifier, uint32_t prog_name,
uint32_t prog_vers );
int oncrpc_call ( struct interface *intf, struct oncrpc_session *session,
uint32_t proc_name, const struct oncrpc_field fields[] );
size_t oncrpc_compute_size ( const struct oncrpc_field fields[] );
int oncrpc_get_reply ( struct oncrpc_session *session,
struct oncrpc_reply *reply, struct io_buffer *io_buf );
#endif /* _IPXE_ONCRPC_H */

View File

@@ -0,0 +1,102 @@
#ifndef _IPXE_ONCRPC_IOB_H
#define _IPXE_ONCRPC_IOB_H
#include <stdint.h>
#include <string.h>
#include <ipxe/iobuf.h>
#include <ipxe/refcnt.h>
#include <ipxe/oncrpc.h>
/** @file
*
* SUN ONC RPC protocol.
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
/**
* Add a string to the end of an I/O buffer
*
* @v io_buf I/O buffer
* @v val String
* @ret size Size of the data written
*/
#define oncrpc_iob_add_string( buf, str ) \
( { \
const char * _str = (str); \
oncrpc_iob_add_array ( (buf), strlen ( _str ), _str ); \
} )
/**
* Get a 32 bits integer from the beginning of an I/O buffer
*
* @v buf I/O buffer
* @ret int Integer
*/
#define oncrpc_iob_get_int( buf ) \
( { \
uint32_t *_val; \
_val = (buf)->data; \
iob_pull ( (buf), sizeof ( uint32_t ) ); \
ntohl ( *_val ); \
} )
/**
* Get a 64 bits integer from the beginning of an I/O buffer
*
* @v buf I/O buffer
* @ret int Integer
*/
#define oncrpc_iob_get_int64( buf ) \
( { \
uint64_t *_val; \
_val = (buf)->data; \
iob_pull ( (buf), sizeof ( uint64_t ) ); \
ntohll ( *_val ); \
} )
size_t oncrpc_iob_add_fields ( struct io_buffer *io_buf,
const struct oncrpc_field fields[] );
size_t oncrpc_iob_add_array ( struct io_buffer *io_buf, size_t length,
const void *data );
size_t oncrpc_iob_add_intarray ( struct io_buffer *io_buf, size_t length,
const uint32_t *array );
size_t oncrpc_iob_add_cred ( struct io_buffer *io_buf,
const struct oncrpc_cred *cred );
size_t oncrpc_iob_get_cred ( struct io_buffer *io_buf,
struct oncrpc_cred *cred );
/**
* Add a 32 bits integer to the end of an I/O buffer
*
* @v io_buf I/O buffer
* @v val Integer
* @ret size Size of the data written
*/
static inline size_t oncrpc_iob_add_int ( struct io_buffer *io_buf,
uint32_t val ) {
* ( uint32_t * ) iob_put ( io_buf, sizeof ( val ) ) = htonl ( val );
return ( sizeof ( val) );
}
/**
* Add a 64 bits integer to the end of an I/O buffer
*
* @v io_buf I/O buffer
* @v val Integer
* @ret size Size of the data written
*/
static inline size_t oncrpc_iob_add_int64 ( struct io_buffer *io_buf,
uint64_t val ) {
* ( uint64_t * ) iob_put ( io_buf, sizeof ( val ) ) = htonll ( val );
return ( sizeof ( val) );
}
#endif /* _IPXE_ONCRPC_IOB_H */

View File

@@ -0,0 +1,63 @@
#ifndef _IPXE_PORTMAP_H
#define _IPXE_PORTMAP_H
#include <stdint.h>
#include <ipxe/oncrpc.h>
/** @file
*
* SUN ONC RPC protocol.
*
*/
FILE_LICENCE ( GPL2_OR_LATER );
/** PORTMAP default port */
#define PORTMAP_PORT 111
/** PORTMAP protocol number */
#define ONCRPC_PORTMAP 100000
/** PORTMAP version */
#define PORTMAP_VERS 2
/** TCP protocol number */
#define PORTMAP_PROTO_TCP 6
/** UDB protocol number */
#define PORTMAP_PROTO_UDP 17
/**
* A PORTMAP GETPORT reply
*
*/
struct portmap_getport_reply {
/** Port returned */
uint32_t port;
};
/**
* Prepare an ONC RPC session to be used as a PORTMAP session
*
* @v session ONC RPC session
* @v credential ONC RPC credential
*
* The credential parameter must not be NULL, use 'oncrpc_auth_none' if you
* don't want a particular scheme to be used.
*/
static inline void portmap_init_session ( struct oncrpc_session *session,
struct oncrpc_cred *credential) {
oncrpc_init_session ( session, credential, &oncrpc_auth_none,
ONCRPC_PORTMAP, PORTMAP_VERS );
}
int portmap_getport ( struct interface *intf, struct oncrpc_session *session,
uint32_t prog, uint32_t vers, uint32_t proto );
int portmap_get_getport_reply ( struct portmap_getport_reply *getport_reply,
struct oncrpc_reply *reply );
#endif /* _IPXE_PORTMAP_H */

View File

@@ -109,17 +109,27 @@ enum {
* Note that this is a separate concept from a URI with an absolute
* path.
*/
static inline int uri_is_absolute ( struct uri *uri ) {
static inline int uri_is_absolute ( const struct uri *uri ) {
return ( uri->scheme != NULL );
}
/**
* URI has an opaque part
*
* @v uri URI
* @ret has_opaque URI has an opaque part
*/
static inline int uri_has_opaque ( const struct uri *uri ) {
return ( uri->opaque && ( uri->opaque[0] != '\0' ) );
}
/**
* URI has a path
*
* @v uri URI
* @ret has_path URI has a path
*/
static inline int uri_has_path ( struct uri *uri ) {
static inline int uri_has_path ( const struct uri *uri ) {
return ( uri->path && ( uri->path[0] != '\0' ) );
}
@@ -133,7 +143,7 @@ static inline int uri_has_path ( struct uri *uri ) {
* concept from an absolute URI. Note also that a URI may not have a
* path at all.
*/
static inline int uri_has_absolute_path ( struct uri *uri ) {
static inline int uri_has_absolute_path ( const struct uri *uri ) {
return ( uri->path && ( uri->path[0] == '/' ) );
}
@@ -147,7 +157,7 @@ static inline int uri_has_absolute_path ( struct uri *uri ) {
* this is a separate concept from a relative URI. Note also that a
* URI may not have a path at all.
*/
static inline int uri_has_relative_path ( struct uri *uri ) {
static inline int uri_has_relative_path ( const struct uri *uri ) {
return ( uri->path && ( uri->path[0] != '/' ) );
}

View File

@@ -3,6 +3,8 @@
FILE_LICENCE ( GPL2_OR_LATER );
#define htonll(x) __bswap_64(x)
#define ntohll(x) __bswap_64(x)
#define ntohl(x) __bswap_32(x)
#define htonl(x) __bswap_32(x)
#define ntohs(x) __bswap_16(x)