From owner-svn-src-head@FreeBSD.ORG Tue May 26 15:19:05 2009 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 53D1E106564A; Tue, 26 May 2009 15:19:05 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 3E5ED8FC12; Tue, 26 May 2009 15:19:05 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n4QFJ5i9061944; Tue, 26 May 2009 15:19:05 GMT (envelope-from rmacklem@svn.freebsd.org) Received: (from rmacklem@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n4QFJ4Gh061933; Tue, 26 May 2009 15:19:04 GMT (envelope-from rmacklem@svn.freebsd.org) Message-Id: <200905261519.n4QFJ4Gh061933@svn.freebsd.org> From: Rick Macklem Date: Tue, 26 May 2009 15:19:04 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r192811 - in head/usr.sbin: . nfscbd nfsdumpstate nfsrevoke nfsuserd X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 26 May 2009 15:19:05 -0000 Author: rmacklem Date: Tue May 26 15:19:04 2009 New Revision: 192811 URL: http://svn.freebsd.org/changeset/base/192811 Log: Add two new utilities and two new daemons to /usr/src/usr.sbin that are specifically used by the experimental nfsv4 subsystem. nfscbd - The NFSv4 client callback daemon. nfsuserd - The NFSv4 daemon that maps between user and group name and their corresponding uid/gid numbers. nfsdumpstate - A utility that dumps out the NFSv4 Open/Lock state. nfsrevoke - Administratively revokes an NFSv4 client, releasing all NFSv4 Open/Lock state it holds on the server. Approved by: kib (mentor) Added: head/usr.sbin/nfscbd/ head/usr.sbin/nfscbd/Makefile (contents, props changed) head/usr.sbin/nfscbd/nfscbd.8 (contents, props changed) head/usr.sbin/nfscbd/nfscbd.c (contents, props changed) head/usr.sbin/nfsdumpstate/ head/usr.sbin/nfsdumpstate/Makefile (contents, props changed) head/usr.sbin/nfsdumpstate/nfsdumpstate.8 (contents, props changed) head/usr.sbin/nfsdumpstate/nfsdumpstate.c (contents, props changed) head/usr.sbin/nfsrevoke/ head/usr.sbin/nfsrevoke/Makefile (contents, props changed) head/usr.sbin/nfsrevoke/nfsrevoke.8 (contents, props changed) head/usr.sbin/nfsrevoke/nfsrevoke.c (contents, props changed) head/usr.sbin/nfsuserd/ head/usr.sbin/nfsuserd/Makefile (contents, props changed) head/usr.sbin/nfsuserd/nfsuserd.8 (contents, props changed) head/usr.sbin/nfsuserd/nfsuserd.c (contents, props changed) Modified: head/usr.sbin/Makefile Modified: head/usr.sbin/Makefile ============================================================================== --- head/usr.sbin/Makefile Tue May 26 14:43:44 2009 (r192810) +++ head/usr.sbin/Makefile Tue May 26 15:19:04 2009 (r192811) @@ -110,7 +110,11 @@ SUBDIR= ${_ac} \ ${_ndiscvt} \ ${_ndp} \ newsyslog \ + nfscbd \ nfsd \ + nfsdumpstate \ + nfsrevoke \ + nfsuserd \ ${_ngctl} \ ${_nghook} \ nologin \ Added: head/usr.sbin/nfscbd/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/usr.sbin/nfscbd/Makefile Tue May 26 15:19:04 2009 (r192811) @@ -0,0 +1,6 @@ +# $FreeBSD$ + +PROG= nfscbd +MAN= nfscbd.8 + +.include Added: head/usr.sbin/nfscbd/nfscbd.8 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/usr.sbin/nfscbd/nfscbd.8 Tue May 26 15:19:04 2009 (r192811) @@ -0,0 +1,87 @@ +.\" Copyright (c) 2009 Rick Macklem, University of Guelph +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd April 25, 2009 +.Dt NFSCBD 8 +.Os +.Sh NAME +.Nm nfscbd +.Tn NFSv4 +client side callback daemon +.Sh SYNOPSIS +.Nm nfscbd +.Op Fl p Ar port_number +.Op Fl P Ar client_principal +.Sh DESCRIPTION +.Nm +runs on a client using +.Tn NFSv4 +to handle callback requests from the NFSv4 server. +If no +.Nm +is running, NFSv4 mounts will still work, but the server will never issue +Open Delegations to the client. +.Pp +One callback server and one master server +are always started. +.Pp +The following options are available: +.Bl -tag -width Ds +.It Fl p Ar port_number +Specifies what port# the callback server should use. +.It Fl P Ar client_principal +Specifies the host based principal name to be used as the target for +callbacks over RPCSEC_GSS. For KerberosV, it must be in the client's +default keytab file. +This client_principal should be the same one specified by the +.Cm gssname +argument being used by nfsv4 mounts. +If you do not specify this argument, callbacks will still work over AUTH_SYS, +which is what many extant servers use even for RPCSEC_GSS mounts, as of 2009. +.El +.Pp +For example, +.Dq Li "nfscbd -p 7654 -P root" +starts the daemon to handle callbacks on port# 7654 and is using the host based +principal root@. as the callback target. +.Pp +.Nm +listens for service requests at the port +defined by NFSV4_CBPORT in /usr/include/fs/nfs/nfs.h, unless +.Fl p +has been specified. +For more information on what callbacks and Open Delegations do, see +.%T "Network File System (NFS) Version 4 Protocol" , +RFC3530 . +.Pp +The +.Nm +utility exits 0 on success or >0 if an error occurred. +.Sh SEE ALSO +.Xr nfsv4 4 , +.Xr mount_nfs 8 +.Sh HISTORY +First introduced with the experimental nfs client for NFSv4 support in 2009. Added: head/usr.sbin/nfscbd/nfscbd.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/usr.sbin/nfscbd/nfscbd.c Tue May 26 15:19:04 2009 (r192811) @@ -0,0 +1,380 @@ +/*- + * Copyright (c) 2009 Rick Macklem, University of Guelph + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Global defs */ +#ifdef DEBUG +#define syslog(e, s) fprintf(stderr,(s)) +int debug = 1; +#else +int debug = 0; +#endif + +pid_t children; + +void nonfs(int); +void reapchild(int); +void usage(void); +void cleanup(int); +void child_cleanup(int); +void nfscbd_exit(int); +void killchildren(void); + +/* + * Nfs callback server daemon. + * + * 1 - do file descriptor and signal cleanup + * 2 - fork the nfscbd(s) + * 4 - create callback server socket(s) + * 5 - set up server socket for rpc + * + * For connectionless protocols, just pass the socket into the kernel via. + * nfssvc(). + * For connection based sockets, loop doing accepts. When you get a new + * socket from accept, pass the msgsock into the kernel via. nfssvc(). + */ +int +main(int argc, char *argv[], char **envp) +{ + struct group *grp; + struct nfscbd_args nfscbdargs; + struct nfsd_nfscbd_args nfscbdargs2; + struct passwd *pwd; + struct ucred *cr; + struct sockaddr_in inetaddr, inetpeer; + struct timeval ktv; + fd_set ready, sockbits; + int ch, connect_type_cnt, i, len, maxsock, msgsock, error; + int nfssvc_flag, on, sock, tcpsock, ret, mustfreeai = 0; + char *cp, **cpp, princname[128]; + char myname[MAXHOSTNAMELEN], *myfqdnname = NULL; + struct addrinfo *aip, hints; + pid_t pid; + sigset_t signew; + short myport = NFSV4_CBPORT; + + if (modfind("nfscl") < 0) { + /* Not present in kernel, try loading it */ + if (kldload("nfscl") < 0 || + modfind("nfscl") < 0) + errx(1, "nfscl is not available"); + } + /* + * First, get our fully qualified host name, if possible. + */ + if (gethostname(myname, MAXHOSTNAMELEN) >= 0) { + cp = strchr(myname, '.'); + if (cp != NULL && *(cp + 1) != '\0') { + cp = myname; + } else { + /* + * No domain on myname, so try looking it up. + */ + cp = NULL; + memset((void *)&hints, 0, sizeof (hints)); + hints.ai_flags = AI_CANONNAME; + error = getaddrinfo(myname, NULL, &hints, &aip); + if (error == 0) { + if (aip->ai_canonname != NULL && + (cp = strchr(aip->ai_canonname, '.')) != NULL + && *(cp + 1) != '\0') { + cp = aip->ai_canonname; + mustfreeai = 1; + } else { + freeaddrinfo(aip); + } + } + } + if (cp == NULL) + warnx("Can't get fully qualified host name"); + myfqdnname = cp; + } + + princname[0] = '\0'; +#define GETOPT "p:P:" +#define USAGE "[ -p port_num ] [ -P client_principal ]" + while ((ch = getopt(argc, argv, GETOPT)) != -1) + switch (ch) { + case 'p': + myport = atoi(optarg); + if (myport < 1) { + warnx("port# non-positive, reset to %d", + NFSV4_CBPORT); + myport = NFSV4_CBPORT; + } + break; + case 'P': + cp = optarg; + if (cp != NULL && strlen(cp) > 0 && + strlen(cp) < sizeof (princname)) { + if (strchr(cp, '@') == NULL && + myfqdnname != NULL) + snprintf(princname, sizeof (princname), + "%s@%s", cp, myfqdnname); + else + strlcpy(princname, cp, + sizeof (princname)); + } else { + warnx("client princ invalid. ignored\n"); + } + break; + default: + case '?': + usage(); + }; + argv += optind; + argc -= optind; + + if (argc > 0) + usage(); + + if (mustfreeai) + freeaddrinfo(aip); + nfscbdargs2.principal = (const char *)princname; + if (debug == 0) { + daemon(0, 0); + (void)signal(SIGTERM, SIG_IGN); + (void)signal(SIGHUP, SIG_IGN); + (void)signal(SIGINT, SIG_IGN); + (void)signal(SIGQUIT, SIG_IGN); + } + (void)signal(SIGSYS, nonfs); + (void)signal(SIGCHLD, reapchild); + + openlog("nfscbd:", LOG_PID, LOG_DAEMON); + + pid = fork(); + if (pid < 0) { + syslog(LOG_ERR, "fork: %m"); + nfscbd_exit(1); + } else if (pid > 0) { + children = pid; + } else { + (void)signal(SIGUSR1, child_cleanup); + setproctitle("server"); + nfssvc_flag = NFSSVC_NFSCBD; + if (nfssvc(nfssvc_flag, &nfscbdargs2) < 0) { + syslog(LOG_ERR, "nfssvc: %m"); + nfscbd_exit(1); + } + exit(0); + } + (void)signal(SIGUSR1, cleanup); + + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + syslog(LOG_ERR, "can't create udp socket"); + nfscbd_exit(1); + } + memset(&inetaddr, 0, sizeof inetaddr); + inetaddr.sin_family = AF_INET; + inetaddr.sin_addr.s_addr = INADDR_ANY; + inetaddr.sin_port = htons(myport); + inetaddr.sin_len = sizeof(inetaddr); + ret = bind(sock, (struct sockaddr *)&inetaddr, sizeof(inetaddr)); + /* If bind() fails, this is a restart, so just skip UDP. */ + if (ret == 0) { + len = sizeof(inetaddr); + if (getsockname(sock, (struct sockaddr *)&inetaddr, &len) < 0){ + syslog(LOG_ERR, "can't get bound addr"); + nfscbd_exit(1); + } + nfscbdargs.port = ntohs(inetaddr.sin_port); + if (nfscbdargs.port != myport) { + syslog(LOG_ERR, "BAD PORT#"); + nfscbd_exit(1); + } + nfscbdargs.sock = sock; + nfscbdargs.name = NULL; + nfscbdargs.namelen = 0; + if (nfssvc(NFSSVC_CBADDSOCK, &nfscbdargs) < 0) { + syslog(LOG_ERR, "can't Add UDP socket"); + nfscbd_exit(1); + } + } + (void)close(sock); + + /* Now set up the master server socket waiting for tcp connections. */ + on = 1; + FD_ZERO(&sockbits); + connect_type_cnt = 0; + if ((tcpsock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + syslog(LOG_ERR, "can't create tcp socket"); + nfscbd_exit(1); + } + if (setsockopt(tcpsock, + SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) + syslog(LOG_ERR, "setsockopt SO_REUSEADDR: %m"); + /* sin_port is already set */ + inetaddr.sin_family = AF_INET; + inetaddr.sin_addr.s_addr = INADDR_ANY; + inetaddr.sin_port = htons(myport); + inetaddr.sin_len = sizeof(inetaddr); + if (bind(tcpsock, + (struct sockaddr *)&inetaddr, sizeof (inetaddr)) < 0) { + syslog(LOG_ERR, "can't bind tcp addr"); + nfscbd_exit(1); + } + if (listen(tcpsock, 5) < 0) { + syslog(LOG_ERR, "listen failed"); + nfscbd_exit(1); + } + FD_SET(tcpsock, &sockbits); + maxsock = tcpsock; + connect_type_cnt++; + + setproctitle("master"); + + /* + * Loop forever accepting connections and passing the sockets + * into the kernel for the mounts. + */ + for (;;) { + ready = sockbits; + if (connect_type_cnt > 1) { + if (select(maxsock + 1, + &ready, NULL, NULL, NULL) < 1) { + syslog(LOG_ERR, "select failed: %m"); + nfscbd_exit(1); + } + } + if (FD_ISSET(tcpsock, &ready)) { + len = sizeof(inetpeer); + if ((msgsock = accept(tcpsock, + (struct sockaddr *)&inetpeer, &len)) < 0) { + syslog(LOG_ERR, "accept failed: %m"); + nfscbd_exit(1); + } + memset(inetpeer.sin_zero, 0, + sizeof (inetpeer.sin_zero)); + if (setsockopt(msgsock, SOL_SOCKET, + SO_KEEPALIVE, (char *)&on, sizeof(on)) < 0) + syslog(LOG_ERR, + "setsockopt SO_KEEPALIVE: %m"); + nfscbdargs.sock = msgsock; + nfscbdargs.name = (caddr_t)&inetpeer; + nfscbdargs.namelen = sizeof(inetpeer); + nfssvc(NFSSVC_CBADDSOCK, &nfscbdargs); + (void)close(msgsock); + } + } +} + +void +usage(void) +{ + + errx(1, "usage: nfscbd %s", USAGE); +} + +void +nonfs(int signo) +{ + syslog(LOG_ERR, "missing system call: NFS not available"); +} + +void +reapchild(int signo) +{ + pid_t pid; + int i; + + while ((pid = wait3(NULL, WNOHANG, NULL)) > 0) { + if (pid == children) + children = -1; + } +} + +void +killchildren(void) +{ + int i; + + if (children > 0) + kill(children, SIGKILL); +} + +/* + * Cleanup master after SIGUSR1. + */ +void +cleanup(int signo) +{ + nfscbd_exit(0); +} + +/* + * Cleanup child after SIGUSR1. + */ +void +child_cleanup(int signo) +{ + exit(0); +} + +void +nfscbd_exit(int status) +{ + killchildren(); + exit(status); +} Added: head/usr.sbin/nfsdumpstate/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/usr.sbin/nfsdumpstate/Makefile Tue May 26 15:19:04 2009 (r192811) @@ -0,0 +1,6 @@ +# $FreeBSD$ + +PROG= nfsdumpstate +MAN= nfsdumpstate.8 + +.include Added: head/usr.sbin/nfsdumpstate/nfsdumpstate.8 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/usr.sbin/nfsdumpstate/nfsdumpstate.8 Tue May 26 15:19:04 2009 (r192811) @@ -0,0 +1,71 @@ +.\" Copyright (c) 2009 Rick Macklem, University of Guelph +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd April 25, 2009 +.Dt NFSDUMPSTATE 8 +.Os +.Sh NAME +.Nm nfsdumpstate +.Nd display +.Tn NFSv4 +open/lock state +.Sh SYNOPSIS +.Nm nfsdumpstate +.Op Fl o +.Op Fl l Ar filename +.Sh DESCRIPTION +.Nm +displays open/lock state for the +.Tn NFSv4 +client and server in the experimental nfs subsystem. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl o +Displays a summary of Clients for NFSv4. Each line lists a Client with +the ClientID being the last field of the line. +.sp +.nf +The following are the client flag values displayed: +NC - Needs Confirmation +CB - Callbacks are enabled +GSS - Using RPCSEC_GSS +REV - Administratively Revoked, via nfsrevoke(8) +.fi +.sp +.It Fl l Ar filename +Displays a list of all NFSv4 Opens and Locks on the file specified by +the +.Ar filename . +The ClientID is the last field of each line. +.El +.Sh SEE ALSO +.Xr nfsv4 4 , +.Xr nfsrevoke 8 +.Sh HISTORY +The +.Nm +utility was introduced with the NFSv4 experimental subsystem in 2009. Added: head/usr.sbin/nfsdumpstate/nfsdumpstate.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/usr.sbin/nfsdumpstate/nfsdumpstate.c Tue May 26 15:19:04 2009 (r192811) @@ -0,0 +1,280 @@ +/*- + * Copyright (c) 2009 Rick Macklem, University of Guelph + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define DUMPSIZE 10000 + +static void dump_lockstate(char *); +static void dump_openstate(void); +static void usage(void); +static char *open_flags(uint32_t); +static char *deleg_flags(uint32_t); +static char *lock_flags(uint32_t); +static char *client_flags(uint32_t); + +static struct nfsd_dumpclients dp[DUMPSIZE]; +static struct nfsd_dumplocks lp[DUMPSIZE]; +static char flag_string[20]; + +int +main(int argc, char **argv) +{ + int ch, openstate; + char *lockfile; + + if (modfind("nfsd") < 0) + errx(1, "nfsd not loaded - self terminating"); + openstate = 0; + lockfile = NULL; + while ((ch = getopt(argc, argv, "ol")) != -1) + switch (ch) { + case 'o': + openstate = 1; + break; + case 'l': + lockfile = optarg; + break; + default: + usage(); + } + argc -= optind; + argv += optind; + + if (openstate == 0 && lockfile == NULL) + openstate = 1; + else if (openstate != 0 && lockfile != NULL) + errx(1, "-o and -l cannot both be specified"); + + /* + * For -o, dump all open/lock state. + * For -l, dump lock state for that file. + */ + if (openstate != 0) + dump_openstate(); + else + dump_lockstate(lockfile); + exit(0); +} + +static void +usage(void) +{ + + errx(1, "usage: nfsdumpstate [-o] [-l]"); +} + +/* + * Dump all open/lock state. + */ +static void +dump_openstate(void) +{ + struct nfsd_dumplist dumplist; + int cnt, i; + + dumplist.ndl_size = DUMPSIZE; + dumplist.ndl_list = (void *)dp; + if (nfssvc(NFSSVC_DUMPCLIENTS, &dumplist) < 0) + errx(1, "Can't perform dump clients syscall"); + + printf("%-13s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %-15s %s\n", + "Flags", "OpenOwner", "Open", "LockOwner", + "Lock", "Deleg", "OldDeleg", "Clientaddr", "ClientID"); + /* + * Loop through results, printing them out. + */ + cnt = 0; + while (dp[cnt].ndcl_clid.nclid_idlen > 0 && cnt < DUMPSIZE) { + printf("%-13s ", client_flags(dp[cnt].ndcl_flags)); + printf("%9d %9d %9d %9d %9d %9d ", + dp[cnt].ndcl_nopenowners, + dp[cnt].ndcl_nopens, + dp[cnt].ndcl_nlockowners, + dp[cnt].ndcl_nlocks, + dp[cnt].ndcl_ndelegs, + dp[cnt].ndcl_nolddelegs); + if (dp[cnt].ndcl_addrfam == AF_INET) + printf("%-15s ", + inet_ntoa(dp[cnt].ndcl_cbaddr.sin_addr)); + for (i = 0; i < dp[cnt].ndcl_clid.nclid_idlen; i++) + printf("%02x", dp[cnt].ndcl_clid.nclid_id[i]); + printf("\n"); + cnt++; + } +} + +/* + * Dump the lock state for a file. + */ +static void +dump_lockstate(char *fname) +{ + struct nfsd_dumplocklist dumplocklist; + int cnt, i; + + dumplocklist.ndllck_size = DUMPSIZE; + dumplocklist.ndllck_list = (void *)lp; + dumplocklist.ndllck_fname = fname; + if (nfssvc(NFSSVC_DUMPLOCKS, &dumplocklist) < 0) + errx(1, "Can't dump locks for %s\n", fname); + + printf("%-11s %-36s %-15s %s\n", + "Open/Lock", + " Stateid or Lock Range", + "Clientaddr", + "Owner and ClientID"); + /* + * Loop through results, printing them out. + */ + cnt = 0; + while (lp[cnt].ndlck_clid.nclid_idlen > 0 && cnt < DUMPSIZE) { + if (lp[cnt].ndlck_flags & NFSLCK_OPEN) + printf("%-11s %9d %08x %08x %08x ", + open_flags(lp[cnt].ndlck_flags), + lp[cnt].ndlck_stateid.seqid, + lp[cnt].ndlck_stateid.other[0], + lp[cnt].ndlck_stateid.other[1], + lp[cnt].ndlck_stateid.other[2]); + else if (lp[cnt].ndlck_flags & (NFSLCK_DELEGREAD | + NFSLCK_DELEGWRITE)) + printf("%-11s %9d %08x %08x %08x ", + deleg_flags(lp[cnt].ndlck_flags), + lp[cnt].ndlck_stateid.seqid, + lp[cnt].ndlck_stateid.other[0], + lp[cnt].ndlck_stateid.other[1], + lp[cnt].ndlck_stateid.other[2]); + else + printf("%-11s %17lld %17lld ", + lock_flags(lp[cnt].ndlck_flags), + lp[cnt].ndlck_first, + lp[cnt].ndlck_end); + if (lp[cnt].ndlck_addrfam == AF_INET) + printf("%-15s ", + inet_ntoa(lp[cnt].ndlck_cbaddr.sin_addr)); + else + printf("%-15s ", " "); + for (i = 0; i < lp[cnt].ndlck_owner.nclid_idlen; i++) + printf("%02x", lp[cnt].ndlck_owner.nclid_id[i]); + printf(" "); + for (i = 0; i < lp[cnt].ndlck_clid.nclid_idlen; i++) + printf("%02x", lp[cnt].ndlck_clid.nclid_id[i]); + printf("\n"); + cnt++; + } +} + +/* + * Parse the Open/Lock flag bits and create a string to be printed. + */ +static char * +open_flags(uint32_t flags) +{ + int i, j; + + strlcpy(flag_string, "Open ", sizeof (flag_string)); + i = 5; + if (flags & NFSLCK_READACCESS) + flag_string[i++] = 'R'; + if (flags & NFSLCK_WRITEACCESS) + flag_string[i++] = 'W'; + flag_string[i++] = ' '; + flag_string[i++] = 'D'; + flag_string[i] = 'N'; + j = i; + if (flags & NFSLCK_READDENY) + flag_string[i++] = 'R'; + if (flags & NFSLCK_WRITEDENY) + flag_string[i++] = 'W'; + if (i == j) + i++; + flag_string[i] = '\0'; + return (flag_string); +} + +static char * +deleg_flags(uint32_t flags) +{ + + if (flags & NFSLCK_DELEGREAD) + strlcpy(flag_string, "Deleg R", sizeof (flag_string)); + else + strlcpy(flag_string, "Deleg W", sizeof (flag_string)); + return (flag_string); +} + +static char * +lock_flags(uint32_t flags) +{ + + if (flags & NFSLCK_READ) + strlcpy(flag_string, "Lock R", sizeof (flag_string)); + else + strlcpy(flag_string, "Lock W", sizeof (flag_string)); + return (flag_string); +} + +static char * +client_flags(uint32_t flags) +{ + + flag_string[0] = '\0'; + if (flags & LCL_NEEDSCONFIRM) + strlcat(flag_string, "NC ", sizeof (flag_string)); + if (flags & LCL_CALLBACKSON) + strlcat(flag_string, "CB ", sizeof (flag_string)); + if (flags & LCL_GSS) + strlcat(flag_string, "GSS ", sizeof (flag_string)); + if (flags & LCL_ADMINREVOKED) + strlcat(flag_string, "REV", sizeof (flag_string)); + return (flag_string); +} Added: head/usr.sbin/nfsrevoke/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/usr.sbin/nfsrevoke/Makefile Tue May 26 15:19:04 2009 (r192811) @@ -0,0 +1,6 @@ +# $FreeBSD$ + +PROG= nfsrevoke +MAN= nfsrevoke.8 + +.include Added: head/usr.sbin/nfsrevoke/nfsrevoke.8 ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/usr.sbin/nfsrevoke/nfsrevoke.8 Tue May 26 15:19:04 2009 (r192811) @@ -0,0 +1,64 @@ +.\" Copyright (c) 2009 Rick Macklem, University of Guelph +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd April 25, 2009 +.Dt NFSREVOKE 8 +.Os +.Sh NAME +.Nm nfsrevoke +.Nd revoke +.Tn NFS +V4 client +.Sh SYNOPSIS +.Nm nfsrevoke +.Ar ClientId +.Sh DESCRIPTION +.Nm +This command is used by a system administrator to revoke a client's access +to the NFS Version 4 server. All Open/Lock state held by the client will +be released. +After revocation, the client will no longer be able to use state on the server +until it does a fresh SetClientID/SetClientIDConfirm operations sequence. +THIS SHOULD BE DONE AS A LAST RESORT ONLY, when clients are holding state +that must be released on the server. +.Pp +The +.Ar ClientId +argument is a hexadecimal string, which is the last field +of the +.Xr nfsdumpstate 8 +command's +.Fl o +and +.Fl l +options output. +.Sh SEE ALSO +.Xr nfsv4 4 , +.Xr nfsdumpstate 8 +.Sh HISTORY +The +.Nm +command was introduced as a part of the experimental nfs server subsystem. Added: head/usr.sbin/nfsrevoke/nfsrevoke.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/usr.sbin/nfsrevoke/nfsrevoke.c Tue May 26 15:19:04 2009 (r192811) @@ -0,0 +1,124 @@ +/*- + * Copyright (c) 2009 Rick Macklem, University of Guelph + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***