1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * Copyright 2023 MNX Cloud, Inc.
29 */
30
31 #include <stdio.h>
32 #include <sys/types.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <sys/param.h>
36 #include <libintl.h>
37 #include <locale.h>
38 #include <rpc/rpc.h>
39 #include <rpcsvc/nlm_prot.h>
40
41 #include <sys/systeminfo.h>
42 #include <netdb.h>
43 #include <nss_dbdefs.h>
44
45 #include <nfs/nfs.h>
46 #include <nfs/export.h>
47 #include <nfs/nfssys.h>
48
49 extern char *optarg;
50 extern int optind;
51 extern int _nfssys(enum nfssys_op, void *);
52
53 static int share_zap(char *, char *);
54
55 /*
56 * Clear locks and v4 related state held by
57 * 'client'.
58 */
59 static int
nfs4_clr_state(char * client)60 nfs4_clr_state(char *client)
61 {
62 int he_error;
63 char he_buf[NSS_BUFLEN_HOSTS];
64 struct hostent host_ent, *he;
65 char **ap;
66 struct nfs4clrst_args arg;
67
68 if ((he = gethostbyname_r(client, &host_ent, he_buf, sizeof (he_buf),
69 &he_error)) == NULL) {
70 (void) fprintf(stderr,
71 gettext("client name '%s' can not be resolved\n"), client);
72 return (1);
73 }
74
75 if (he_error) {
76 perror("gethostbyname");
77 return (1);
78 }
79
80 /*
81 * The NFS4 clear state interface is
82 * versioned in case we need to pass
83 * more information in the future.
84 */
85 arg.vers = NFS4_CLRST_VERSION;
86 arg.addr_type = he->h_addrtype;
87
88 /*
89 * Iterate over IP Addresses clear
90 * state for each.
91 */
92 for (ap = he->h_addr_list; *ap; ap++) {
93 arg.ap = *ap;
94 if (_nfssys(NFS4_CLR_STATE, &arg) != 0) {
95 perror("nfssys(NFS4_CLR_STATE)");
96 return (1);
97 }
98 }
99 return (0);
100 }
101
102 int
main(int argc,char * argv[])103 main(int argc, char *argv[])
104 {
105 int i, c, ret;
106 int sflag = 0;
107 int errflg = 0;
108 char myhostname[MAXHOSTNAMELEN];
109
110 if (geteuid() != (uid_t)0) {
111 (void) fprintf(stderr, gettext("clear_locks: must be root\n"));
112 exit(1);
113 }
114
115 (void) setlocale(LC_ALL, "");
116
117 #if !defined(TEXT_DOMAIN)
118 #define TEXT_DOMAIN "SYS_TEST"
119 #endif
120 (void) textdomain(TEXT_DOMAIN);
121
122 /*
123 * Get the official hostname for this host
124 */
125 sysinfo(SI_HOSTNAME, myhostname, sizeof (myhostname));
126
127 while ((c = getopt(argc, argv, "s")) != EOF) {
128 switch (c) {
129 case 's':
130 sflag++;
131 break;
132 case '?':
133 errflg++;
134 }
135 }
136
137 i = argc - optind;
138 if (errflg || i != 1) {
139 (void) fprintf(stderr,
140 gettext("Usage: clear_locks [-s] hostname\n"));
141 exit(2);
142 }
143
144 if (sflag) {
145 (void) fprintf(stdout, gettext(
146 "Clearing locks held for NFS client %s on server %s\n"),
147 myhostname, argv[optind]);
148 ret = share_zap(myhostname, argv[optind]);
149 } else {
150 (void) fprintf(stdout, gettext(
151 "Clearing locks held for NFS client %s on server %s\n"),
152 argv[optind], myhostname);
153 ret = share_zap(argv[optind], myhostname);
154 ret += nfs4_clr_state(argv[optind]);
155 }
156
157 return (ret);
158 }
159
160
161 /*
162 * Request that host 'server' free all locks held by
163 * host 'client'.
164 */
165 static int
share_zap(char * client,char * server)166 share_zap(char *client, char *server)
167 {
168 struct nlm_notify notify;
169 enum clnt_stat rslt;
170
171 notify.state = 0;
172 notify.name = client;
173 rslt = rpc_call(server, NLM_PROG, NLM_VERSX, NLM_FREE_ALL,
174 xdr_nlm_notify, (char *)¬ify, xdr_void, 0, NULL);
175 if (rslt != RPC_SUCCESS) {
176 clnt_perrno(rslt);
177 return (3);
178 }
179 (void) fprintf(stderr,
180 gettext("clear of locks held for %s on %s returned success\n"),
181 client, server);
182 return (0);
183 }
184