1 /*
2  * Copyright (c) 2008 Isilon Inc http://www.isilon.com/
3  * Authors: Doug Rabson <dfr@rabson.org>
4  * Developed with Red Inc: Alfred Perlstein <alfred@freebsd.org>
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 /*
29  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
30  */
31 
32 /*
33  * Client-side RPC wrappers (nlm_..._rpc)
34  * Called from nlm_client.c
35  *
36  * Source code derived from FreeBSD nlm_advlock.c
37  */
38 
39 #include <sys/param.h>
40 #include <sys/fcntl.h>
41 #include <sys/lock.h>
42 #include <sys/flock.h>
43 #include <sys/mount.h>
44 #include <sys/mutex.h>
45 #include <sys/proc.h>
46 #include <sys/syslog.h>
47 #include <sys/systm.h>
48 #include <sys/unistd.h>
49 #include <sys/vnode.h>
50 #include <sys/queue.h>
51 
52 #include <rpcsvc/nlm_prot.h>
53 
54 #include <nfs/nfs.h>
55 #include <nfs/nfs_clnt.h>
56 #include <nfs/export.h>
57 #include <nfs/rnode.h>
58 
59 #include "nlm_impl.h"
60 
61 static void
nlm_convert_to_nlm_lock(struct nlm_lock * dst,struct nlm4_lock * src)62 nlm_convert_to_nlm_lock(struct nlm_lock *dst, struct nlm4_lock *src)
63 {
64 	dst->caller_name = src->caller_name;
65 	dst->fh = src->fh;
66 	dst->oh = src->oh;
67 	dst->svid = src->svid;
68 	dst->l_offset = src->l_offset;
69 	dst->l_len = src->l_len;
70 }
71 
72 static void
nlm_convert_to_nlm4_holder(struct nlm4_holder * dst,struct nlm_holder * src)73 nlm_convert_to_nlm4_holder(struct nlm4_holder *dst, struct nlm_holder *src)
74 {
75 	dst->exclusive = src->exclusive;
76 	dst->svid = src->svid;
77 	dst->oh = src->oh;
78 	dst->l_offset = src->l_offset;
79 	dst->l_len = src->l_len;
80 }
81 
82 static void
nlm_convert_to_nlm4_res(struct nlm4_res * dst,struct nlm_res * src)83 nlm_convert_to_nlm4_res(struct nlm4_res *dst, struct nlm_res *src)
84 {
85 	dst->cookie = src->cookie;
86 	dst->stat.stat = (enum nlm4_stats) src->stat.stat;
87 }
88 
89 enum clnt_stat
nlm_test_rpc(nlm4_testargs * args,nlm4_testres * res,CLIENT * client,rpcvers_t vers)90 nlm_test_rpc(nlm4_testargs *args, nlm4_testres *res,
91     CLIENT *client, rpcvers_t vers)
92 {
93 	if (vers == NLM4_VERS) {
94 		return (nlm4_test_4(args, res, client));
95 	} else {
96 		nlm_testargs args1;
97 		nlm_testres res1;
98 		enum clnt_stat stat;
99 
100 		args1.cookie = args->cookie;
101 		args1.exclusive = args->exclusive;
102 		nlm_convert_to_nlm_lock(&args1.alock, &args->alock);
103 		(void) memset(&res1, 0, sizeof (res1));
104 
105 		stat = nlm_test_1(&args1, &res1, client);
106 
107 		if (stat == RPC_SUCCESS) {
108 			res->cookie = res1.cookie;
109 			res->stat.stat = (enum nlm4_stats) res1.stat.stat;
110 			if (res1.stat.stat == nlm_denied)
111 				nlm_convert_to_nlm4_holder(
112 				    &res->stat.nlm4_testrply_u.holder,
113 				    &res1.stat.nlm_testrply_u.holder);
114 		}
115 
116 		return (stat);
117 	}
118 }
119 
120 enum clnt_stat
nlm_lock_rpc(nlm4_lockargs * args,nlm4_res * res,CLIENT * client,rpcvers_t vers)121 nlm_lock_rpc(nlm4_lockargs *args, nlm4_res *res,
122     CLIENT *client, rpcvers_t vers)
123 {
124 	if (vers == NLM4_VERS) {
125 		return (nlm4_lock_4(args, res, client));
126 	} else {
127 		nlm_lockargs args1;
128 		nlm_res res1;
129 		enum clnt_stat stat;
130 
131 		args1.cookie = args->cookie;
132 		args1.block = args->block;
133 		args1.exclusive = args->exclusive;
134 		nlm_convert_to_nlm_lock(&args1.alock, &args->alock);
135 		args1.reclaim = args->reclaim;
136 		args1.state = args->state;
137 		(void) memset(&res1, 0, sizeof (res1));
138 
139 		stat = nlm_lock_1(&args1, &res1, client);
140 
141 		if (stat == RPC_SUCCESS) {
142 			nlm_convert_to_nlm4_res(res, &res1);
143 		}
144 
145 		return (stat);
146 	}
147 }
148 
149 enum clnt_stat
nlm_cancel_rpc(nlm4_cancargs * args,nlm4_res * res,CLIENT * client,rpcvers_t vers)150 nlm_cancel_rpc(nlm4_cancargs *args, nlm4_res *res,
151     CLIENT *client, rpcvers_t vers)
152 {
153 	if (vers == NLM4_VERS) {
154 		return (nlm4_cancel_4(args, res, client));
155 	} else {
156 		nlm_cancargs args1;
157 		nlm_res res1;
158 		enum clnt_stat stat;
159 
160 		args1.cookie = args->cookie;
161 		args1.block = args->block;
162 		args1.exclusive = args->exclusive;
163 		nlm_convert_to_nlm_lock(&args1.alock, &args->alock);
164 		(void) memset(&res1, 0, sizeof (res1));
165 
166 		stat = nlm_cancel_1(&args1, &res1, client);
167 
168 		if (stat == RPC_SUCCESS) {
169 			nlm_convert_to_nlm4_res(res, &res1);
170 		}
171 
172 		return (stat);
173 	}
174 }
175 
176 enum clnt_stat
nlm_unlock_rpc(nlm4_unlockargs * args,nlm4_res * res,CLIENT * client,rpcvers_t vers)177 nlm_unlock_rpc(nlm4_unlockargs *args, nlm4_res *res,
178     CLIENT *client, rpcvers_t vers)
179 {
180 	if (vers == NLM4_VERS) {
181 		return (nlm4_unlock_4(args, res, client));
182 	} else {
183 		nlm_unlockargs args1;
184 		nlm_res res1;
185 		enum clnt_stat stat;
186 
187 		args1.cookie = args->cookie;
188 		nlm_convert_to_nlm_lock(&args1.alock, &args->alock);
189 		(void) memset(&res1, 0, sizeof (res1));
190 
191 		stat = nlm_unlock_1(&args1, &res1, client);
192 
193 		if (stat == RPC_SUCCESS) {
194 			nlm_convert_to_nlm4_res(res, &res1);
195 		}
196 
197 		return (stat);
198 	}
199 }
200 
201 enum clnt_stat
nlm_null_rpc(CLIENT * client,rpcvers_t vers)202 nlm_null_rpc(CLIENT *client, rpcvers_t vers)
203 {
204 	if (vers == NLM4_VERS)
205 		return (nlm4_null_4(NULL, NULL, client));
206 
207 	return (nlm_null_1(NULL, NULL, client));
208 }
209 
210 /*
211  * Share reservations
212  */
213 
214 static void
nlm_convert_to_nlm_share(struct nlm_share * dst,struct nlm4_share * src)215 nlm_convert_to_nlm_share(struct nlm_share *dst, struct nlm4_share *src)
216 {
217 
218 	dst->caller_name = src->caller_name;
219 	dst->fh = src->fh;
220 	dst->oh = src->oh;
221 	dst->mode = src->mode;
222 	dst->access = src->access;
223 }
224 
225 static void
nlm_convert_to_nlm4_shres(struct nlm4_shareres * dst,struct nlm_shareres * src)226 nlm_convert_to_nlm4_shres(struct nlm4_shareres *dst,
227 	struct nlm_shareres *src)
228 {
229 	dst->cookie = src->cookie;
230 	dst->stat = (enum nlm4_stats) src->stat;
231 	dst->sequence = src->sequence;
232 }
233 
234 
235 enum clnt_stat
nlm_share_rpc(nlm4_shareargs * args,nlm4_shareres * res,CLIENT * client,rpcvers_t vers)236 nlm_share_rpc(nlm4_shareargs *args, nlm4_shareres *res,
237     CLIENT *client, rpcvers_t vers)
238 {
239 	if (vers == NLM4_VERS) {
240 		return (nlm4_share_4(args, res, client));
241 	} else {
242 		nlm_shareargs args3;
243 		nlm_shareres res3;
244 		enum clnt_stat stat;
245 
246 		args3.cookie = args->cookie;
247 		nlm_convert_to_nlm_share(&args3.share, &args->share);
248 		args3.reclaim = args->reclaim;
249 		(void) memset(&res3, 0, sizeof (res3));
250 
251 		stat = nlm_share_3(&args3, &res3, client);
252 
253 		if (stat == RPC_SUCCESS) {
254 			nlm_convert_to_nlm4_shres(res, &res3);
255 		}
256 
257 		return (stat);
258 	}
259 }
260 
261 enum clnt_stat
nlm_unshare_rpc(nlm4_shareargs * args,nlm4_shareres * res,CLIENT * client,rpcvers_t vers)262 nlm_unshare_rpc(nlm4_shareargs *args, nlm4_shareres *res,
263     CLIENT *client, rpcvers_t vers)
264 {
265 	if (vers == NLM4_VERS) {
266 		return (nlm4_unshare_4(args, res, client));
267 	} else {
268 		nlm_shareargs args3;
269 		nlm_shareres res3;
270 		enum clnt_stat stat;
271 
272 		args3.cookie = args->cookie;
273 		nlm_convert_to_nlm_share(&args3.share, &args->share);
274 		args3.reclaim = args->reclaim;
275 		(void) memset(&res3, 0, sizeof (res3));
276 
277 		stat = nlm_unshare_3(&args3, &res3, client);
278 
279 		if (stat == RPC_SUCCESS) {
280 			nlm_convert_to_nlm4_shres(res, &res3);
281 		}
282 
283 		return (stat);
284 	}
285 }
286