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 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 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 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