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 #pragma ident "%Z%%M% %I% %E% SMI"
28
29 #include <stdio.h>
30 #include <sys/types.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 #include <sys/param.h>
34 #include <libintl.h>
35 #include <locale.h>
36 #include <rpc/rpc.h>
37 #include <rpcsvc/nlm_prot.h>
38
39 #include <sys/systeminfo.h>
40 #include <netdb.h>
41 #include <nss_dbdefs.h>
42
43 #include <nfs/nfs.h>
44 #include <nfs/export.h>
45 #include <nfs/nfssys.h>
46
47 extern char *optarg;
48 extern int optind;
49 extern int _nfssys(enum nfssys_op, void *);
50
51 static int share_zap(char *, char *);
52
53 /*
54 * Clear locks and v4 related state held by
55 * 'client'.
56 */
57 static int
nfs4_clr_state(char * client)58 nfs4_clr_state(char *client)
59 {
60 int he_error;
61 char he_buf[NSS_BUFLEN_HOSTS];
62 struct hostent host_ent, *he;
63 char **ap;
64 struct nfs4clrst_args arg;
65
66 if ((he = gethostbyname_r(client, &host_ent, he_buf, sizeof (he_buf),
67 &he_error)) == NULL) {
68 (void) fprintf(stderr,
69 gettext("client name '%s' can not be resolved\n"),
70 client);
71 return (1);
72 }
73
74 if (he_error) {
75 perror("gethostbyname");
76 return (1);
77 }
78
79 /*
80 * The NFS4 clear state interface is
81 * versioned in case we need to pass
82 * more information in the future.
83 */
84 arg.vers = NFS4_CLRST_VERSION;
85 arg.addr_type = he->h_addrtype;
86
87 /*
88 * Iterate over IP Addresses clear
89 * state for each.
90 */
91 for (ap = he->h_addr_list; *ap; ap++) {
92 arg.ap = *ap;
93 _nfssys(NFS4_CLR_STATE, &arg);
94 }
95 return (0);
96 }
97
98 int
main(int argc,char * argv[])99 main(int argc, char *argv[])
100 {
101 int i, c, ret;
102 int sflag = 0;
103 int errflg = 0;
104 char myhostname[MAXHOSTNAMELEN];
105
106 if (geteuid() != (uid_t)0) {
107 (void) fprintf(stderr, gettext("clear_locks: must be root\n"));
108 exit(1);
109 }
110
111 (void) setlocale(LC_ALL, "");
112
113 #if !defined(TEXT_DOMAIN)
114 #define TEXT_DOMAIN "SYS_TEST"
115 #endif
116 (void) textdomain(TEXT_DOMAIN);
117
118 /*
119 * Get the official hostname for this host
120 */
121 sysinfo(SI_HOSTNAME, myhostname, sizeof (myhostname));
122
123 while ((c = getopt(argc, argv, "s")) != EOF) {
124 switch (c) {
125 case 's':
126 sflag++;
127 break;
128 case '?':
129 errflg++;
130 }
131 }
132
133 i = argc - optind;
134 if (errflg || i != 1) {
135 (void) fprintf(stderr,
136 gettext("Usage: clear_locks [-s] hostname\n"));
137 exit(2);
138 }
139
140 if (sflag) {
141 (void) fprintf(stdout,
142 gettext("Clearing locks held for NFS client %s on server %s\n"),
143 myhostname, argv[optind]);
144 ret = share_zap(myhostname, argv[optind]);
145 } else {
146 (void) fprintf(stdout,
147 gettext("Clearing locks held for NFS client %s on server %s\n"),
148 argv[optind], myhostname);
149 ret = share_zap(argv[optind], myhostname);
150 ret += nfs4_clr_state(argv[optind]);
151 }
152
153 return (ret);
154 }
155
156
157 /*
158 * Request that host 'server' free all locks held by
159 * host 'client'.
160 */
161 static int
share_zap(char * client,char * server)162 share_zap(char *client, char *server)
163 {
164 struct nlm_notify notify;
165 enum clnt_stat rslt;
166
167 notify.state = 0;
168 notify.name = client;
169 rslt = rpc_call(server, NLM_PROG, NLM_VERSX, NLM_FREE_ALL,
170 xdr_nlm_notify, (char *)¬ify, xdr_void, 0, NULL);
171 if (rslt != RPC_SUCCESS) {
172 clnt_perrno(rslt);
173 return (3);
174 }
175 (void) fprintf(stderr,
176 gettext("clear of locks held for %s on %s returned success\n"),
177 client, server);
178 return (0);
179 }
180