@@ -252,6 +252,17 @@ AC_ARG_ENABLE(nfsdcltrack,
enable_nfsdcltrack=$enableval,
enable_nfsdcltrack="yes")
+AC_ARG_ENABLE(nfsdctl,
+ [AS_HELP_STRING([--disable-nfsdctl],[disable nfsdctl program for controlling nfsd@<:@default=no@:>@])],
+ enable_nfsdctl=$enableval,
+ enable_nfsdctl="yes")
+ AM_CONDITIONAL(CONFIG_NFSDCTL, [test "$enable_nfsdctl" = "yes" ])
+ if test "$enable_nfsdctl" = yes; then
+ dnl Check for libnl3
+ PKG_CHECK_MODULES(LIBNL3, libnl-3.0 >= 3.1)
+ PKG_CHECK_MODULES(LIBNLGENL3, libnl-genl-3.0 >= 3.1)
+ fi
+
AC_ARG_ENABLE(nfsv4server,
[AS_HELP_STRING([--enable-nfsv4server],[enable support for NFSv4 only server @<:@default=no@:>@])],
enable_nfsv4server=$enableval,
@@ -739,6 +750,7 @@ AC_CONFIG_FILES([
utils/mountd/Makefile
utils/exportd/Makefile
utils/nfsd/Makefile
+ utils/nfsdctl/Makefile
utils/nfsref/Makefile
utils/nfsstat/Makefile
utils/nfsidmap/Makefile
@@ -35,6 +35,10 @@ if CONFIG_JUNCTION
OPTDIRS += nfsref
endif
+if CONFIG_NFSDCTL
+OPTDIRS += nfsdctl
+endif
+
SUBDIRS = \
exportfs \
mountd \
new file mode 100644
@@ -0,0 +1,10 @@
+## Process this file with automake to produce Makefile.in
+
+sbin_PROGRAMS = nfsdctl
+
+noinst_HEADERS = nfsdctl.h
+nfsdctl_SOURCES = nfsdctl.c
+nfsdctl_CFLAGS = $(LIBNL3_CFLAGS) $(LIBNLGENL3_CFLAGS)
+nfsdctl_LDADD = ../../support/nfs/libnfs.la $(LIBNL3_LIBS) $(LIBNLGENL3_LIBS)
+
+MAINTAINERCLEANFILES = Makefile.in
new file mode 100644
@@ -0,0 +1,531 @@
+#include <linux/module.h>
+#include <linux/version.h>
+#include <netlink/genl/genl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <stdbool.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <getopt.h>
+
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+#include <linux/netlink.h>
+
+#include "nfsdctl.h"
+
+/* compile note:
+ * gcc -I/usr/include/libnl3/ -o <prog-name> <prog-name>.c -lnl-3 -lnl-genl-3
+ */
+
+#define NFSD4_OPS_MAX_LEN sizeof(nfsd4_ops) / sizeof(nfsd4_ops[0])
+static const char *nfsd4_ops[] = {
+ [OP_ACCESS] = "OP_ACCESS",
+ [OP_CLOSE] = "OP_CLOSE",
+ [OP_COMMIT] = "OP_COMMIT",
+ [OP_CREATE] = "OP_CREATE",
+ [OP_DELEGRETURN] = "OP_DELEGRETURN",
+ [OP_GETATTR] = "OP_GETATTR",
+ [OP_GETFH] = "OP_GETFH",
+ [OP_LINK] = "OP_LINK",
+ [OP_LOCK] = "OP_LOCK",
+ [OP_LOCKT] = "OP_LOCKT",
+ [OP_LOCKU] = "OP_LOCKU",
+ [OP_LOOKUP] = "OP_LOOKUP",
+ [OP_LOOKUPP] = "OP_LOOKUPP",
+ [OP_NVERIFY] = "OP_NVERIFY",
+ [OP_OPEN] = "OP_OPEN",
+ [OP_OPEN_CONFIRM] = "OP_OPEN_CONFIRM",
+ [OP_OPEN_DOWNGRADE] = "OP_OPEN_DOWNGRADE",
+ [OP_PUTFH] = "OP_PUTFH",
+ [OP_PUTPUBFH] = "OP_PUTPUBFH",
+ [OP_PUTROOTFH] = "OP_PUTROOTFH",
+ [OP_READ] = "OP_READ",
+ [OP_READDIR] = "OP_READDIR",
+ [OP_READLINK] = "OP_READLINK",
+ [OP_REMOVE] = "OP_REMOVE",
+ [OP_RENAME] = "OP_RENAME",
+ [OP_RENEW] = "OP_RENEW",
+ [OP_RESTOREFH] = "OP_RESTOREFH",
+ [OP_SAVEFH] = "OP_SAVEFH",
+ [OP_SECINFO] = "OP_SECINFO",
+ [OP_SETATTR] = "OP_SETATTR",
+ [OP_SETCLIENTID] = "OP_SETCLIENTID",
+ [OP_SETCLIENTID_CONFIRM] = "OP_SETCLIENTID_CONFIRM",
+ [OP_VERIFY] = "OP_VERIFY",
+ [OP_WRITE] = "OP_WRITE",
+ [OP_RELEASE_LOCKOWNER] = "OP_RELEASE_LOCKOWNER",
+ /* NFSv4.1 operations */
+ [OP_EXCHANGE_ID] = "OP_EXCHANGE_ID",
+ [OP_BACKCHANNEL_CTL] = "OP_BACKCHANNEL_CTL",
+ [OP_BIND_CONN_TO_SESSION] = "OP_BIND_CONN_TO_SESSION",
+ [OP_CREATE_SESSION] = "OP_CREATE_SESSION",
+ [OP_DESTROY_SESSION] = "OP_DESTROY_SESSION",
+ [OP_SEQUENCE] = "OP_SEQUENCE",
+ [OP_DESTROY_CLIENTID] = "OP_DESTROY_CLIENTID",
+ [OP_RECLAIM_COMPLETE] = "OP_RECLAIM_COMPLETE",
+ [OP_SECINFO_NO_NAME] = "OP_SECINFO_NO_NAME",
+ [OP_TEST_STATEID] = "OP_TEST_STATEID",
+ [OP_FREE_STATEID] = "OP_FREE_STATEID",
+ [OP_GETDEVICEINFO] = "OP_GETDEVICEINFO",
+ [OP_LAYOUTGET] = "OP_LAYOUTGET",
+ [OP_LAYOUTCOMMIT] = "OP_LAYOUTCOMMIT",
+ [OP_LAYOUTRETURN] = "OP_LAYOUTRETURN",
+ /* NFSv4.2 operations */
+ [OP_ALLOCATE] = "OP_ALLOCATE",
+ [OP_DEALLOCATE] = "OP_DEALLOCATE",
+ [OP_CLONE] = "OP_CLONE",
+ [OP_COPY] = "OP_COPY",
+ [OP_READ_PLUS] = "OP_READ_PLUS",
+ [OP_SEEK] = "OP_SEEK",
+ [OP_OFFLOAD_STATUS] = "OP_OFFLOAD_STATUS",
+ [OP_OFFLOAD_CANCEL] = "OP_OFFLOAD_CANCEL",
+ [OP_COPY_NOTIFY] = "OP_COPY_NOTIFY",
+ [OP_GETXATTR] = "OP_GETXATTR",
+ [OP_SETXATTR] = "OP_SETXATTR",
+ [OP_LISTXATTRS] = "OP_LISTXATTRS",
+ [OP_REMOVEXATTR] = "OP_REMOVEXATTR",
+};
+
+static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
+ void *arg)
+{
+ int *ret = arg;
+
+ *ret = err->error;
+ return NL_SKIP;
+}
+
+static int finish_handler(struct nl_msg *msg, void *arg)
+{
+ int *ret = arg;
+
+ *ret = 0;
+ return NL_SKIP;
+}
+
+static int ack_handler(struct nl_msg *msg, void *arg)
+{
+ int *ret = arg;
+
+ *ret = 0;
+ return NL_STOP;
+}
+
+static void parse_rpc_status_get(struct genlmsghdr *gnlh)
+{
+ struct nlattr *attr;
+ int rem;
+
+ nla_for_each_attr(attr, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), rem) {
+ switch (nla_type(attr)) {
+ case NFSD_A_RPC_STATUS_XID:
+ case NFSD_A_RPC_STATUS_FLAGS:
+ printf(" 0x%08x", nla_get_u32(attr));
+ break;
+ case NFSD_A_RPC_STATUS_PROC:
+ case NFSD_A_RPC_STATUS_PROG:
+ printf(" %d", nla_get_u32(attr));
+ break;
+ case NFSD_A_RPC_STATUS_VERSION:
+ printf(" NFS%d", nla_get_u8(attr));
+ break;
+ case NFSD_A_RPC_STATUS_SERVICE_TIME:
+ printf(" %ld", nla_get_u64(attr));
+ break;
+ case NFSD_A_RPC_STATUS_DADDR4:
+ case NFSD_A_RPC_STATUS_SADDR4: {
+ struct in_addr addr = {
+ .s_addr = nla_get_u32(attr),
+ };
+
+ printf(" %s", inet_ntoa(addr));
+ break;
+ }
+ case NFSD_A_RPC_STATUS_DPORT:
+ case NFSD_A_RPC_STATUS_SPORT:
+ printf(" %hu", nla_get_u16(attr));
+ break;
+ case NFSD_A_RPC_STATUS_COMPOUND_OPS: {
+ unsigned int op = nla_get_u32(attr);
+
+ if (op < NFSD4_OPS_MAX_LEN)
+ printf(" %s", nfsd4_ops[op]);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ printf("\n");
+}
+
+static void parse_version_get(struct genlmsghdr *gnlh)
+{
+ struct nlattr *attr;
+ int rem;
+
+ printf("Server Versions:");
+ nla_for_each_attr(attr, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), rem) {
+ struct nlattr *a;
+ int i;
+
+ nla_for_each_nested(a, attr, i) {
+ switch (nla_type(a)) {
+ case NFSD_A_VERSION_MAJOR:
+ printf("\t%d", nla_get_u32(a));
+ break;
+ case NFSD_A_VERSION_MINOR:
+ printf(":%d", nla_get_u32(a));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ printf("\n");
+}
+
+static void parse_listener_get(struct genlmsghdr *gnlh)
+{
+ int rem, major, minor;
+ struct nlattr *attr;
+
+ printf("Server Listeners:");
+ nla_for_each_attr(attr, genlmsg_attrdata(gnlh, 0),
+ genlmsg_attrlen(gnlh, 0), rem) {
+ unsigned short proto = 0;
+ const char *name = NULL;
+ unsigned port = 0;
+ struct nlattr *a;
+ int i;
+
+ nla_for_each_nested(a, attr, i) {
+ switch (nla_type(a)) {
+ case NFSD_A_LISTENER_TRANSPORT_NAME:
+ name = nla_data(a);
+ break;
+ case NFSD_A_LISTENER_PORT:
+ port = nla_get_u32(a);
+ break;
+ case NFSD_A_LISTENER_INET_PROTO:
+ proto = nla_get_u16(a);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (name && port && proto)
+ printf("\n\t%s%s:%d",
+ name, proto == AF_INET6 ? "6" : "4", port);
+ }
+ printf("\n");
+}
+
+static int recv_handler(struct nl_msg *msg, void *arg)
+{
+ struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+ const struct nlattr *attr = genlmsg_attrdata(gnlh, 0);
+
+ switch (gnlh->cmd) {
+ case NFSD_CMD_RPC_STATUS_GET:
+ parse_rpc_status_get(gnlh);
+ break;
+ case NFSD_CMD_THREADS_GET:
+ if (nla_type(attr) == NFSD_A_SERVER_WORKER_THREADS)
+ printf("Running threads\t: %d\n", nla_get_u32(attr));
+ break;
+ case NFSD_CMD_VERSION_GET:
+ parse_version_get(gnlh);
+ break;
+ case NFSD_CMD_LISTENER_GET:
+ parse_listener_get(gnlh);
+ break;
+ default:
+ break;
+ }
+
+ return NL_SKIP;
+}
+
+static const struct option long_options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "rpc-status", no_argument, NULL, 'R' },
+ { "set-threads", required_argument, NULL, 't' },
+ { "get-threads", no_argument, NULL, 'T' },
+ { "set-version", required_argument, NULL, 'v' },
+ { "get-versions", no_argument, NULL, 'V' },
+ { "set-sockaddr", required_argument, NULL, 's' },
+ { "set-listener", required_argument, NULL, 'p' },
+ { "get-listeners", no_argument, NULL, 'P' },
+ { },
+};
+
+static int get_cmd_type(int arg)
+{
+ switch (arg) {
+ case 'R':
+ return NFSD_CMD_RPC_STATUS_GET;
+ case 't':
+ return NFSD_CMD_THREADS_SET;
+ case 'T':
+ return NFSD_CMD_THREADS_GET;
+ case 'v':
+ return NFSD_CMD_VERSION_SET;
+ case 'V':
+ return NFSD_CMD_VERSION_GET;
+ case 'p':
+ return NFSD_CMD_LISTENER_SET;
+ case 'P':
+ return NFSD_CMD_LISTENER_GET;
+ case 's':
+ return NFSD_CMD_SOCK_SET;
+ case 'h':
+ default:
+ return -EINVAL;
+ }
+}
+
+static void usage(char *argv[], const struct option *long_options)
+{
+ int i;
+
+ printf("\nOption for %s:\n", argv[0]);
+ for (i = 0; long_options[i].name != 0; i++) {
+ printf(" --%-15s", long_options[i].name);
+ if (long_options[i].flag != NULL)
+ printf(" flag (internal value: %d)",
+ *long_options[i].flag);
+ else
+ printf("\t short-option: -%c", long_options[i].val);
+ printf("\n");
+ }
+ printf("\n");
+}
+
+#define BUFFER_SIZE 8192
+static struct nl_msg *netlink_sock_and_msg_alloc(struct nl_sock **sock)
+{
+ struct nl_msg *msg = NULL;
+ int ret, id;
+
+ *sock = nl_socket_alloc();
+ if (!(*sock))
+ return NULL;
+
+ if (genl_connect(*sock)) {
+ fprintf(stderr, "Failed to connect to generic netlink\n");
+ goto error;
+ }
+
+ nl_socket_set_buffer_size(*sock, BUFFER_SIZE, BUFFER_SIZE);
+ setsockopt(nl_socket_get_fd(*sock), SOL_NETLINK, NETLINK_EXT_ACK,
+ &ret, sizeof(ret));
+
+ id = genl_ctrl_resolve(*sock, NFSD_FAMILY_NAME);
+ if (id < 0) {
+ fprintf(stderr, "%s not found\n", NFSD_FAMILY_NAME);
+ goto error;
+ }
+
+ msg = nlmsg_alloc();
+ if (!msg) {
+ fprintf(stderr, "failed to allocate netlink message\n");
+ goto error;
+ }
+
+ if (!genlmsg_put(msg, 0, 0, id, 0, 0, 0, 0)) {
+ fprintf(stderr, "failed to allocate netlink message\n");
+ goto error;
+ }
+
+ return msg;
+error:
+ nl_socket_free(*sock);
+ nlmsg_free(msg);
+ return NULL;
+}
+
+int main(char argc, char **argv)
+{
+ int port, proto, nl_cmd = 0, longindex = 0, opt, ret = 1;
+ char transport[64], addr[64];
+ struct genlmsghdr *ghdr;
+ struct nlmsghdr *nlh;
+ struct nl_sock *sock;
+ struct nl_msg *msg;
+ struct nl_cb *cb;
+
+ if (argc == 1) {
+ usage(argv, long_options);
+ return -EINVAL;
+ }
+
+ msg = netlink_sock_and_msg_alloc(&sock);
+ if (!msg)
+ return -ENOMEM;
+
+ ret = EINVAL;
+ nlh = nlmsg_hdr(msg);
+
+ while ((opt = getopt_long(argc, argv, "Rt:Tv:Vp:Ps:h",
+ long_options, &longindex)) != -1) {
+ int cmd = get_cmd_type(opt);
+ struct nlattr *a;
+
+ if (cmd < 0) {
+ usage(argv, long_options);
+ goto out;
+ }
+
+ if (nl_cmd && cmd != nl_cmd) {
+ usage(argv, long_options);
+ goto out;
+ }
+
+ nl_cmd = cmd;
+ switch (nl_cmd) {
+ case NFSD_CMD_RPC_STATUS_GET:
+ nlh->nlmsg_flags |= NLM_F_DUMP;
+ break;
+ case NFSD_CMD_THREADS_SET: {
+ int thread = strtoul(optarg, NULL, 0);
+
+ nla_put_u32(msg, NFSD_A_SERVER_WORKER_THREADS, thread);
+ break;
+ }
+ case NFSD_CMD_VERSION_SET: {
+ int major, minor;
+
+ if (sscanf(optarg, "%d.%d", &major, &minor) != 2) {
+ usage(argv, long_options);
+ goto out;
+ }
+
+
+ a = nla_nest_start(msg,
+ NLA_F_NESTED | NFSD_A_SERVER_PROTO_VERSION);
+ if (!a) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ nla_put_u32(msg, NFSD_A_VERSION_MAJOR, major);
+ nla_put_u32(msg, NFSD_A_VERSION_MINOR, minor);
+ nla_nest_end(msg, a);
+ break;
+ }
+ case NFSD_CMD_LISTENER_SET:
+ if (sscanf(optarg, "%s.%d.%d",
+ transport, &port, &proto) != 3) {
+ usage(argv, long_options);
+ goto out;
+ }
+
+
+ a = nla_nest_start(msg,
+ NLA_F_NESTED | NFSD_A_SERVER_LISTENER_INSTANCE);
+ if (!a) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ nla_put_string(msg, NFSD_A_LISTENER_TRANSPORT_NAME,
+ transport);
+ nla_put_u32(msg, NFSD_A_LISTENER_PORT, port);
+ nla_put_u16(msg, NFSD_A_LISTENER_INET_PROTO, proto);
+ nla_nest_end(msg, a);
+ break;
+ case NFSD_CMD_SOCK_SET: {
+ struct sockaddr_storage sa_storage = {};
+
+ if (sscanf(optarg, "[%s].%s.%d.%d",
+ addr, &port, transport, &proto) != 4) {
+ usage(argv, long_options);
+ goto out;
+ }
+
+ switch (proto) {
+ case AF_INET: {
+ struct sockaddr_in *sin = (void *)&sa_storage;
+
+ sin->sin_family = AF_INET;
+ sin->sin_port = htons(port);
+ if (inet_pton(AF_INET, addr,
+ &sin->sin_addr) != 1) {
+ ret = -EINVAL;
+ goto out;
+ }
+ break;
+ }
+ case AF_INET6: {
+ struct sockaddr_in6 *sin6 = (void *)&sa_storage;
+
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = htons(port);
+ if (inet_pton(AF_INET6, addr,
+ &sin6->sin6_addr) != 1) {
+ ret = -EINVAL;
+ goto out;
+ }
+ break;
+ }
+ default:
+ ret = -EINVAL;
+ goto out;
+ }
+
+ a = nla_nest_start(msg,
+ NLA_F_NESTED | NFSD_A_SERVER_SOCK_ADDR);
+ if (!a) {
+ ret = -ENOMEM;
+ goto out_cb;
+ }
+ nla_put(msg, NFSD_A_SOCK_ADDR, sizeof(sa_storage),
+ &sa_storage);
+ nla_put_string(msg, NFSD_A_SOCK_TRANSPORT_NAME,
+ transport);
+ nla_nest_end(msg, a);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ ghdr = nlmsg_data(nlh);
+ ghdr->cmd = nl_cmd;
+
+ cb = nl_cb_alloc(NL_CB_CUSTOM);
+ if (!cb) {
+ fprintf(stderr, "failed to allocate netlink callbacks\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = nl_send_auto_complete(sock, msg);
+ if (ret < 0)
+ goto out_cb;
+
+ ret = 1;
+ nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &ret);
+ nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, &ret);
+ nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &ret);
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, recv_handler, NULL);
+
+ while (ret > 0)
+ nl_recvmsgs(sock, cb);
+out_cb:
+ nl_cb_put(cb);
+out:
+ if (ret)
+ nlmsg_free(msg);
+ nl_socket_free(sock);
+ return ret;
+}
new file mode 100644
@@ -0,0 +1,183 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* Do not edit directly, auto-generated from: */
+/* Documentation/netlink/specs/nfsd.yaml */
+/* YNL-GEN uapi header */
+
+#ifndef _UAPI_LINUX_NFSD_H
+#define _UAPI_LINUX_NFSD_H
+
+#define NFSD_FAMILY_NAME "nfsd"
+#define NFSD_FAMILY_VERSION 1
+
+enum {
+ NFSD_A_RPC_STATUS_XID = 1,
+ NFSD_A_RPC_STATUS_FLAGS,
+ NFSD_A_RPC_STATUS_PROG,
+ NFSD_A_RPC_STATUS_VERSION,
+ NFSD_A_RPC_STATUS_PROC,
+ NFSD_A_RPC_STATUS_SERVICE_TIME,
+ NFSD_A_RPC_STATUS_PAD,
+ NFSD_A_RPC_STATUS_SADDR4,
+ NFSD_A_RPC_STATUS_DADDR4,
+ NFSD_A_RPC_STATUS_SADDR6,
+ NFSD_A_RPC_STATUS_DADDR6,
+ NFSD_A_RPC_STATUS_SPORT,
+ NFSD_A_RPC_STATUS_DPORT,
+ NFSD_A_RPC_STATUS_COMPOUND_OPS,
+
+ __NFSD_A_RPC_STATUS_MAX,
+ NFSD_A_RPC_STATUS_MAX = (__NFSD_A_RPC_STATUS_MAX - 1)
+};
+
+enum {
+ NFSD_A_SERVER_WORKER_THREADS = 1,
+
+ __NFSD_A_SERVER_WORKER_MAX,
+ NFSD_A_SERVER_WORKER_MAX = (__NFSD_A_SERVER_WORKER_MAX - 1)
+};
+
+enum {
+ NFSD_A_VERSION_MAJOR = 1,
+ NFSD_A_VERSION_MINOR,
+
+ __NFSD_A_VERSION_MAX,
+ NFSD_A_VERSION_MAX = (__NFSD_A_VERSION_MAX - 1)
+};
+
+enum {
+ NFSD_A_SERVER_PROTO_VERSION = 1,
+
+ __NFSD_A_SERVER_PROTO_MAX,
+ NFSD_A_SERVER_PROTO_MAX = (__NFSD_A_SERVER_PROTO_MAX - 1)
+};
+
+enum {
+ NFSD_A_LISTENER_TRANSPORT_NAME = 1,
+ NFSD_A_LISTENER_PORT,
+ NFSD_A_LISTENER_INET_PROTO,
+
+ __NFSD_A_LISTENER_MAX,
+ NFSD_A_LISTENER_MAX = (__NFSD_A_LISTENER_MAX - 1)
+};
+
+enum {
+ NFSD_A_SERVER_LISTENER_INSTANCE = 1,
+
+ __NFSD_A_SERVER_LISTENER_MAX,
+ NFSD_A_SERVER_LISTENER_MAX = (__NFSD_A_SERVER_LISTENER_MAX - 1)
+};
+
+enum {
+ NFSD_A_SOCK_ADDR = 1,
+ NFSD_A_SOCK_TRANSPORT_NAME,
+
+ __NFSD_A_SOCK_MAX,
+ NFSD_A_SOCK_MAX = (__NFSD_A_SOCK_MAX - 1)
+};
+
+enum {
+ NFSD_A_SERVER_SOCK_ADDR = 1,
+
+ __NFSD_A_SERVER_SOCK_MAX,
+ NFSD_A_SERVER_SOCK_MAX = (__NFSD_A_SERVER_SOCK_MAX - 1)
+};
+
+enum {
+ NFSD_CMD_RPC_STATUS_GET = 1,
+ NFSD_CMD_THREADS_SET,
+ NFSD_CMD_THREADS_GET,
+ NFSD_CMD_VERSION_SET,
+ NFSD_CMD_VERSION_GET,
+ NFSD_CMD_LISTENER_SET,
+ NFSD_CMD_LISTENER_GET,
+ NFSD_CMD_SOCK_SET,
+
+ __NFSD_CMD_MAX,
+ NFSD_CMD_MAX = (__NFSD_CMD_MAX - 1)
+};
+
+enum nfs_opnum4 {
+ OP_ACCESS = 3,
+ OP_CLOSE = 4,
+ OP_COMMIT = 5,
+ OP_CREATE = 6,
+ OP_DELEGPURGE = 7,
+ OP_DELEGRETURN = 8,
+ OP_GETATTR = 9,
+ OP_GETFH = 10,
+ OP_LINK = 11,
+ OP_LOCK = 12,
+ OP_LOCKT = 13,
+ OP_LOCKU = 14,
+ OP_LOOKUP = 15,
+ OP_LOOKUPP = 16,
+ OP_NVERIFY = 17,
+ OP_OPEN = 18,
+ OP_OPENATTR = 19,
+ OP_OPEN_CONFIRM = 20,
+ OP_OPEN_DOWNGRADE = 21,
+ OP_PUTFH = 22,
+ OP_PUTPUBFH = 23,
+ OP_PUTROOTFH = 24,
+ OP_READ = 25,
+ OP_READDIR = 26,
+ OP_READLINK = 27,
+ OP_REMOVE = 28,
+ OP_RENAME = 29,
+ OP_RENEW = 30,
+ OP_RESTOREFH = 31,
+ OP_SAVEFH = 32,
+ OP_SECINFO = 33,
+ OP_SETATTR = 34,
+ OP_SETCLIENTID = 35,
+ OP_SETCLIENTID_CONFIRM = 36,
+ OP_VERIFY = 37,
+ OP_WRITE = 38,
+ OP_RELEASE_LOCKOWNER = 39,
+
+ /* nfs41 */
+ OP_BACKCHANNEL_CTL = 40,
+ OP_BIND_CONN_TO_SESSION = 41,
+ OP_EXCHANGE_ID = 42,
+ OP_CREATE_SESSION = 43,
+ OP_DESTROY_SESSION = 44,
+ OP_FREE_STATEID = 45,
+ OP_GET_DIR_DELEGATION = 46,
+ OP_GETDEVICEINFO = 47,
+ OP_GETDEVICELIST = 48,
+ OP_LAYOUTCOMMIT = 49,
+ OP_LAYOUTGET = 50,
+ OP_LAYOUTRETURN = 51,
+ OP_SECINFO_NO_NAME = 52,
+ OP_SEQUENCE = 53,
+ OP_SET_SSV = 54,
+ OP_TEST_STATEID = 55,
+ OP_WANT_DELEGATION = 56,
+ OP_DESTROY_CLIENTID = 57,
+ OP_RECLAIM_COMPLETE = 58,
+
+ /* nfs42 */
+ OP_ALLOCATE = 59,
+ OP_COPY = 60,
+ OP_COPY_NOTIFY = 61,
+ OP_DEALLOCATE = 62,
+ OP_IO_ADVISE = 63,
+ OP_LAYOUTERROR = 64,
+ OP_LAYOUTSTATS = 65,
+ OP_OFFLOAD_CANCEL = 66,
+ OP_OFFLOAD_STATUS = 67,
+ OP_READ_PLUS = 68,
+ OP_SEEK = 69,
+ OP_WRITE_SAME = 70,
+ OP_CLONE = 71,
+
+ /* xattr support (RFC8726) */
+ OP_GETXATTR = 72,
+ OP_SETXATTR = 73,
+ OP_LISTXATTRS = 74,
+ OP_REMOVEXATTR = 75,
+
+ OP_ILLEGAL = 10044,
+};
+
+#endif /* _UAPI_LINUX_NFSD_H */