+
+/*
+ * NFS mount file system attributes
+ */
+struct nfs_fsattr {
+ uint32_t nfsa_flags; /* file system flags */
+ uint32_t nfsa_lease; /* lease time in seconds */
+ uint32_t nfsa_maxname; /* maximum filename size */
+ uint32_t nfsa_maxlink; /* maximum # links */
+ uint32_t nfsa_bsize; /* block size */
+ uint32_t nfsa_pad; /* UNUSED */
+ uint64_t nfsa_maxfilesize; /* maximum file size */
+ uint64_t nfsa_maxread; /* maximum read size */
+ uint64_t nfsa_maxwrite; /* maximum write size */
+ uint64_t nfsa_files_avail; /* file slots available */
+ uint64_t nfsa_files_free; /* file slots free */
+ uint64_t nfsa_files_total; /* file slots total */
+ uint64_t nfsa_space_avail; /* disk space available */
+ uint64_t nfsa_space_free; /* disk space free */
+ uint64_t nfsa_space_total; /* disk space total */
+ uint32_t nfsa_supp_attr[NFS_ATTR_BITMAP_LEN]; /* attributes supported on this file system */
+ uint32_t nfsa_bitmap[NFS_ATTR_BITMAP_LEN]; /* valid attributes */
+};
+#define NFS_FSFLAG_LINK 0x00000001
+#define NFS_FSFLAG_SYMLINK 0x00000002
+#define NFS_FSFLAG_UNIQUE_FH 0x00000004
+#define NFS_FSFLAG_ACL 0x00000008
+#define NFS_FSFLAG_SET_TIME 0x00000010
+#define NFS_FSFLAG_CASE_INSENSITIVE 0x00000020
+#define NFS_FSFLAG_CASE_PRESERVING 0x00000040
+#define NFS_FSFLAG_CHOWN_RESTRICTED 0x00000080
+#define NFS_FSFLAG_HOMOGENEOUS 0x00000100
+#define NFS_FSFLAG_NO_TRUNC 0x00000200
+#define NFS_FSFLAG_NAMED_ATTR 0x00000400
+#define NFS_FSFLAG_FHTYPE_MASK 0xFF000000
+#define NFS_FSFLAG_FHTYPE_SHIFT 24
+
+/*
+ * NFS file system location structures
+ */
+struct nfs_fs_server {
+ char * ns_name; /* name of server */
+ char ** ns_addresses; /* array of addresses for server */
+ uint32_t ns_addrcount; /* # of addresses */
+};
+struct nfs_fs_path {
+ char ** np_components; /* array of component pointers */
+ uint32_t np_compcount; /* # components in path */
+};
+struct nfs_fs_location {
+ struct nfs_fs_server ** nl_servers; /* array of server pointers */
+ struct nfs_fs_path nl_path; /* file system path */
+ uint32_t nl_servcount; /* # of servers */
+};
+
+struct nfs_location_index {
+ uint8_t nli_flags; /* misc flags */
+ uint8_t nli_loc; /* location index */
+ uint8_t nli_serv; /* server index */
+ uint8_t nli_addr; /* address index */
+};
+#define NLI_VALID 0x01 /* index is valid */
+
+struct nfs_fs_locations {
+ struct nfs_fs_path nl_root; /* current server's root file system path */
+ uint32_t nl_numlocs; /* # of locations */
+ struct nfs_location_index nl_current; /* index of current location/server/address */
+ struct nfs_fs_location **nl_locations; /* array of fs locations */
+};
+
+/*
+ * RPC record marker parsing state
+ */
+struct nfs_rpc_record_state {
+ mbuf_t nrrs_m; /* mbufs for current record */
+ mbuf_t nrrs_mlast;
+ uint16_t nrrs_lastfrag; /* last fragment of record */
+ uint16_t nrrs_markerleft; /* marker bytes remaining */
+ uint32_t nrrs_fragleft; /* fragment bytes remaining */
+ uint32_t nrrs_reclen; /* length of RPC record */
+};
+
+/*
+ * NFS socket structures
+ */
+struct nfs_socket {
+ lck_mtx_t nso_lock; /* nfs socket lock */
+ TAILQ_ENTRY(nfs_socket) nso_link; /* list of sockets */
+ struct sockaddr * nso_saddr; /* socket address */
+ struct sockaddr * nso_saddr2; /* additional socket address */
+ void * nso_wake; /* address to wake up */
+ time_t nso_timestamp;
+ time_t nso_reqtimestamp; /* last request sent */
+ socket_t nso_so; /* socket */
+ uint8_t nso_sotype; /* Type of socket */
+ uint16_t nso_flags; /* NSO_* flags */
+ struct nfs_location_index nso_location; /* location index */
+ uint32_t nso_protocol; /* RPC protocol */
+ uint32_t nso_version; /* RPC protocol version */
+ uint32_t nso_pingxid; /* RPC XID of NULL ping request */
+ int nso_error; /* saved error/status */
+ struct nfs_rpc_record_state nso_rrs; /* RPC record parsing state (TCP) */
+};
+TAILQ_HEAD(nfssocketlist, nfs_socket);
+/* nso_flags */
+#define NSO_UPCALL 0x0001 /* socket upcall in progress */
+#define NSO_DEAD 0x0002 /* socket is dead */
+#define NSO_CONNECTING 0x0004 /* socket is being connected */
+#define NSO_CONNECTED 0x0008 /* socket connection complete */
+#define NSO_PINGING 0x0010 /* socket is being tested */
+#define NSO_VERIFIED 0x0020 /* socket appears functional */
+#define NSO_DISCONNECTING 0x0040 /* socket is being disconnected */
+
+/* NFS connect socket search state */
+struct nfs_socket_search {
+ struct nfs_location_index nss_startloc; /* starting location index */
+ struct nfs_location_index nss_nextloc; /* next location index */
+ struct nfssocketlist nss_socklist; /* list of active sockets */
+ time_t nss_timestamp; /* search start time */
+ time_t nss_last; /* timestamp of last socket */
+ struct nfs_socket * nss_sock; /* found socket */
+ uint8_t nss_sotype; /* TCP/UDP */
+ uint8_t nss_sockcnt; /* # of active sockets */
+ in_port_t nss_port; /* port # to connect to */
+ uint32_t nss_protocol; /* RPC protocol */
+ uint32_t nss_version; /* RPC protocol version */
+ uint32_t nss_flags; /* (see below) */
+ int nss_addrcnt; /* Number addresses to try or left */
+ int nss_timeo; /* how long we are willing to wait */
+ int nss_error; /* best error we've gotten so far */
+};
+/* nss_flags */
+#define NSS_VERBOSE 0x00000001 /* OK to log info about socket search */
+#define NSS_WARNED 0x00000002 /* logged warning about socket search taking a while */
+
+/*
+ * function table for calling version-specific NFS functions
+ */
+struct nfs_funcs {
+ int (*nf_mount)(struct nfsmount *, vfs_context_t, nfsnode_t *);
+ int (*nf_update_statfs)(struct nfsmount *, vfs_context_t);
+ int (*nf_getquota)(struct nfsmount *, vfs_context_t, uid_t, int, struct dqblk *);
+ int (*nf_access_rpc)(nfsnode_t, u_int32_t *, vfs_context_t);
+ int (*nf_getattr_rpc)(nfsnode_t, mount_t, u_char *, size_t, int, vfs_context_t, struct nfs_vattr *, u_int64_t *);
+ int (*nf_setattr_rpc)(nfsnode_t, struct vnode_attr *, vfs_context_t);
+ int (*nf_read_rpc_async)(nfsnode_t, off_t, size_t, thread_t, kauth_cred_t, struct nfsreq_cbinfo *, struct nfsreq **);
+ int (*nf_read_rpc_async_finish)(nfsnode_t, struct nfsreq *, uio_t, size_t *, int *);
+ int (*nf_readlink_rpc)(nfsnode_t, char *, uint32_t *, vfs_context_t);
+ int (*nf_write_rpc_async)(nfsnode_t, uio_t, size_t, thread_t, kauth_cred_t, int, struct nfsreq_cbinfo *, struct nfsreq **);
+ int (*nf_write_rpc_async_finish)(nfsnode_t, struct nfsreq *, int *, size_t *, uint64_t *);
+ int (*nf_commit_rpc)(nfsnode_t, uint64_t, uint64_t, kauth_cred_t, uint64_t);
+ int (*nf_lookup_rpc_async)(nfsnode_t, char *, int, vfs_context_t, struct nfsreq **);
+ int (*nf_lookup_rpc_async_finish)(nfsnode_t, char *, int, vfs_context_t, struct nfsreq *, u_int64_t *, fhandle_t *, struct nfs_vattr *);
+ int (*nf_remove_rpc)(nfsnode_t, char *, int, thread_t, kauth_cred_t);
+ int (*nf_rename_rpc)(nfsnode_t, char *, int, nfsnode_t, char *, int, vfs_context_t);
+ int (*nf_setlock_rpc)(nfsnode_t, struct nfs_open_file *, struct nfs_file_lock *, int, int, thread_t, kauth_cred_t);
+ int (*nf_unlock_rpc)(nfsnode_t, struct nfs_lock_owner *, int, uint64_t, uint64_t, int, thread_t, kauth_cred_t);
+ int (*nf_getlock_rpc)(nfsnode_t, struct nfs_lock_owner *, struct flock *, uint64_t, uint64_t, vfs_context_t);
+};
+
+/*
+ * The long form of the NFSv4 client ID.
+ */
+struct nfs_client_id {
+ TAILQ_ENTRY(nfs_client_id) nci_link; /* list of client IDs */
+ char *nci_id; /* client id buffer */
+ int nci_idlen; /* length of client id buffer */
+};
+TAILQ_HEAD(nfsclientidlist, nfs_client_id);
+extern struct nfsclientidlist nfsclientids;
+