}
}
+void acl_getacl_cb(struct rpc_context *rpc _U_, int status, void *data, void *private_data)
+{
+ struct client *client = private_data;
+ GETACL3res *res = data;
+
+ printf("Got NFSACL/GETACL reply\n");
+
+ if (status == RPC_STATUS_SUCCESS) {
+ printf("Got an ACL : ACL status:%d\n", res->status);
+ if (res->status == NFS3_OK) {
+ int i;
+ printf("ACL MASK 0x%08x\n", res->GETACL3res_u.resok.mask);
+ printf("NUM ACE %d\n", res->GETACL3res_u.resok.ace_count);
+ for (i=0; i<res->GETACL3res_u.resok.ace.ace_len; i++) {
+ printf("Type:0x%08x\n", res->GETACL3res_u.resok.ace.ace_val[i].type);
+ printf("ID:%d\n", res->GETACL3res_u.resok.ace.ace_val[i].id);
+ printf("Perm:0x%08x\n", res->GETACL3res_u.resok.ace.ace_val[i].perm);
+ }
+ }
+ }
+
+ printf("Disconnect socket from nfs server\n");
+ if (rpc_disconnect(rpc, "normal disconnect") != 0) {
+ printf("Failed to disconnect socket to nfs\n");
+ exit(10);
+ }
+
+ printf("Connect to RPC.RQUOTAD on %s:%d\n", client->server, client->rquota_port);
+ if (rpc_connect_async(rpc, client->server, client->rquota_port, rquota_connect_cb, client) != 0) {
+ printf("Failed to start connection\n");
+ exit(10);
+ }
+}
+
+void acl_null_cb(struct rpc_context *rpc _U_, int status, void *data, void *private_data)
+{
+ struct client *client = private_data;
+
+ printf("Got NFSACL/NULL reply\n");
+ printf("Get ACL for root handle\n");
+
+ if (rpc_nfsacl_getacl_async(rpc, acl_getacl_cb, &client->rootfh, NFSACL_MASK_ACL_ENTRY|NFSACL_MASK_ACL_COUNT|NFSACL_MASK_ACL_DEFAULT_ENTRY|NFSACL_MASK_ACL_DEFAULT_COUNT, client) != 0) {
+ printf("Failed to send getacl request\n");
+ exit(10);
+ }
+
+}
+
void nfs_fsinfo_cb(struct rpc_context *rpc _U_, int status, void *data, void *private_data)
{
struct client *client = private_data;
printf("Read Max:%d\n", (int)res->FSINFO3res_u.resok.rtmax);
printf("Write Max:%d\n", (int)res->FSINFO3res_u.resok.wtmax);
- printf("Disconnect socket from nfs server\n");
- if (rpc_disconnect(rpc, "normal disconnect") != 0) {
- printf("Failed to disconnect socket to nfs\n");
- exit(10);
- }
-
- printf("Connect to RPC.RQUOTAD on %s:%d\n", client->server, client->rquota_port);
- if (rpc_connect_async(rpc, client->server, client->rquota_port, rquota_connect_cb, client) != 0) {
- printf("Failed to start connection\n");
+ printf("Send NFSACL/NULL request\n");
+ if (rpc_nfsacl_null_async(rpc, acl_null_cb, client) != 0) {
+ printf("Failed to send acl/null request\n");
exit(10);
}
}
* data is NULL.
*/
int rpc_rquota2_getactivequota_async(struct rpc_context *rpc, rpc_cb cb, char *export, int type, int uid, void *private_data);
+
+
+
+/*
+ * Call NFSACL/NULL
+ * Call the NULL procedure for the NFSACL
+ *
+ * Function returns
+ * 0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. The callback will not be invoked.
+ *
+ * When the callback is invoked, status indicates the result:
+ * RPC_STATUS_SUCCESS : We got a successful response from the rquota daemon.
+ * data is NULL
+ * RPC_STATUS_ERROR : An error occured when trying to contact the rquota daemon.
+ * data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ * data is NULL.
+ */
+int rpc_nfsacl_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data);
+
+/*
+ * Call NFSACL/GETACL
+ *
+ * Function returns
+ * 0 : The call was initiated. The callback will be invoked when the call completes.
+ * <0 : An error occured when trying to set up the call. The callback will not be invoked.
+ *
+ * When the callback is invoked, status indicates the result:
+ * RPC_STATUS_SUCCESS : We got a successful response from the rquota daemon.
+ * data is a GETACL3res pointer
+ * RPC_STATUS_ERROR : An error occured when trying to contact the rquota daemon.
+ * data is the error string.
+ * RPC_STATUS_CANCEL : The connection attempt was aborted before it could complete.
+ * data is NULL.
+ */
+int rpc_nfsacl_getacl_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint32_t mask, void *private_data);
+
libnfs_la_CPPFLAGS = -I$(abs_top_srcdir)/include
libnfs_la_SOURCES = \
$(nfs_SOURCES_GENERATED) \
- nfs.c
+ nfs.c nfsacl.c
$(nfs_GENERATED) : nfs-stamp
nfs-stamp : nfs.x
-/* copied from rfc 1813 */
+/* NFS part from rfc 1813, NFSACL part is from wireshark sources */
const NFS3_FHSIZE = 64; /* Maximum bytes in a V3 file handle */
const NFS3_WRITEVERFSIZE = 8;
NFS3_COMMIT(COMMIT3args) = 21;
} = 3;
} = 100003;
+
+
+
+/* NFS ACL definitions based on wireshark souces and network traces */
+/* NFSACL interface. Uses same port/process as NFS */
+
+enum nfsacl_type {
+ NFSACL_TYPE_USER_OBJ = 0x0001,
+ NFSACL_TYPE_USER = 0x0002,
+ NFSACL_TYPE_GROUP_OBJ = 0x0004,
+ NFSACL_TYPE_GROUP = 0x0008,
+ NFSACL_TYPE_CLASS_OBJ = 0x0010,
+ NFSACL_TYPE_CLASS = 0x0020,
+ NFSACL_TYPE_DEFAULT = 0x1000,
+ NFSACL_TYPE_DEFAULT_USER_OBJ = 0x1001,
+ NFSACL_TYPE_DEFAULT_USER = 0x1002,
+ NFSACL_TYPE_DEFAULT_GROUP_OBJ = 0x1004,
+ NFSACL_TYPE_DEFAULT_GROUP = 0x1008,
+ NFSACL_TYPE_DEFAULT_CLASS_OBJ = 0x1010,
+ NFSACL_TYPE_DEFAULT_OTHER_OBJ = 0x1020
+};
+
+const NFSACL_PERM_READ = 0x04;
+const NFSACL_PERM_WRITE = 0x02;
+const NFSACL_PERM_EXEC = 0x01;
+
+struct nfsacl_ace {
+ enum nfsacl_type type;
+ uint32_t id;
+ uint32_t perm;
+};
+
+const NFSACL_MASK_ACL_ENTRY = 0x0001;
+const NFSACL_MASK_ACL_COUNT = 0x0002;
+const NFSACL_MASK_ACL_DEFAULT_ENTRY = 0x0004;
+const NFSACL_MASK_ACL_DEFAULT_COUNT = 0x0008;
+
+struct GETACL3args {
+ nfs_fh3 dir;
+ uint32 mask;
+};
+
+struct GETACL3resok {
+ post_op_attr attr;
+ uint32_t mask;
+ uint32_t ace_count;
+ struct nfsacl_ace ace<>;
+ uint32_t default_ace_count;
+ struct nfsacl_ace default_ace<>;
+};
+
+union GETACL3res switch (nfsstat3 status) {
+case NFS3_OK:
+ GETACL3resok resok;
+default:
+ void;
+};
+
+program NFSACL_PROGRAM {
+ version NFSACL_V3 {
+ void
+ NFSACL3_NULL(void) = 0;
+
+ GETACL3res
+ NFSACL3_GETACL(GETACL3args) = 1;
+ } = 3;
+} = 100227;
--- /dev/null
+/*
+ Copyright (C) 2010 by Ronnie Sahlberg <ronniesahlberg@gmail.com>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdio.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include "libnfs.h"
+#include "libnfs-raw.h"
+#include "libnfs-private.h"
+#include "libnfs-raw-nfs.h"
+
+
+int rpc_nfsacl_null_async(struct rpc_context *rpc, rpc_cb cb, void *private_data)
+{
+ struct rpc_pdu *pdu;
+
+ pdu = rpc_allocate_pdu(rpc, NFSACL_PROGRAM, NFSACL_V3, NFSACL3_NULL, cb, private_data, (xdrproc_t)xdr_void, 0);
+ if (pdu == NULL) {
+ rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfsacl/null call");
+ return -1;
+ }
+
+ if (rpc_queue_pdu(rpc, pdu) != 0) {
+ rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfsacl/null call");
+ rpc_free_pdu(rpc, pdu);
+ return -2;
+ }
+
+ return 0;
+}
+
+
+int rpc_nfsacl_getacl_async(struct rpc_context *rpc, rpc_cb cb, struct nfs_fh3 *fh, uint32_t mask, void *private_data)
+{
+ struct rpc_pdu *pdu;
+ GETACL3args args;
+
+ pdu = rpc_allocate_pdu(rpc, NFSACL_PROGRAM, NFSACL_V3, NFSACL3_GETACL, cb, private_data, (xdrproc_t)xdr_GETACL3res, sizeof(GETACL3res));
+ if (pdu == NULL) {
+ rpc_set_error(rpc, "Out of memory. Failed to allocate pdu for nfsacl/getacl call");
+ return -1;
+ }
+
+ args.dir.data.data_len = fh->data.data_len;
+ args.dir.data.data_val = fh->data.data_val;
+ args.mask = mask;
+
+ if (xdr_GETACL3args(&pdu->xdr, &args) == 0) {
+ rpc_set_error(rpc, "XDR error: Failed to encode GETACL3args");
+ rpc_free_pdu(rpc, pdu);
+ return -2;
+ }
+
+ if (rpc_queue_pdu(rpc, pdu) != 0) {
+ rpc_set_error(rpc, "Out of memory. Failed to queue pdu for nfsacl/getacl call");
+ rpc_free_pdu(rpc, pdu);
+ return -2;
+ }
+
+ return 0;
+}