/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * Copyright 2023 MNX Cloud, Inc. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include extern char *optarg; extern int optind; extern int _nfssys(enum nfssys_op, void *); static int share_zap(char *, char *); /* * Clear locks and v4 related state held by * 'client'. */ static int nfs4_clr_state(char *client) { int he_error; char he_buf[NSS_BUFLEN_HOSTS]; struct hostent host_ent, *he; char **ap; struct nfs4clrst_args arg; if ((he = gethostbyname_r(client, &host_ent, he_buf, sizeof (he_buf), &he_error)) == NULL) { (void) fprintf(stderr, gettext("client name '%s' can not be resolved\n"), client); return (1); } if (he_error) { perror("gethostbyname"); return (1); } /* * The NFS4 clear state interface is * versioned in case we need to pass * more information in the future. */ arg.vers = NFS4_CLRST_VERSION; arg.addr_type = he->h_addrtype; /* * Iterate over IP Addresses clear * state for each. */ for (ap = he->h_addr_list; *ap; ap++) { arg.ap = *ap; if (_nfssys(NFS4_CLR_STATE, &arg) != 0) { perror("nfssys(NFS4_CLR_STATE)"); return (1); } } return (0); } int main(int argc, char *argv[]) { int i, c, ret; int sflag = 0; int errflg = 0; char myhostname[MAXHOSTNAMELEN]; if (geteuid() != (uid_t)0) { (void) fprintf(stderr, gettext("clear_locks: must be root\n")); exit(1); } (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) #define TEXT_DOMAIN "SYS_TEST" #endif (void) textdomain(TEXT_DOMAIN); /* * Get the official hostname for this host */ sysinfo(SI_HOSTNAME, myhostname, sizeof (myhostname)); while ((c = getopt(argc, argv, "s")) != EOF) { switch (c) { case 's': sflag++; break; case '?': errflg++; } } i = argc - optind; if (errflg || i != 1) { (void) fprintf(stderr, gettext("Usage: clear_locks [-s] hostname\n")); exit(2); } if (sflag) { (void) fprintf(stdout, gettext( "Clearing locks held for NFS client %s on server %s\n"), myhostname, argv[optind]); ret = share_zap(myhostname, argv[optind]); } else { (void) fprintf(stdout, gettext( "Clearing locks held for NFS client %s on server %s\n"), argv[optind], myhostname); ret = share_zap(argv[optind], myhostname); ret += nfs4_clr_state(argv[optind]); } return (ret); } /* * Request that host 'server' free all locks held by * host 'client'. */ static int share_zap(char *client, char *server) { struct nlm_notify notify; enum clnt_stat rslt; notify.state = 0; notify.name = client; rslt = rpc_call(server, NLM_PROG, NLM_VERSX, NLM_FREE_ALL, xdr_nlm_notify, (char *)¬ify, xdr_void, 0, NULL); if (rslt != RPC_SUCCESS) { clnt_perrno(rslt); return (3); } (void) fprintf(stderr, gettext("clear of locks held for %s on %s returned success\n"), client, server); return (0); }