lock_proc.c revision 1.5 1 1.5 fvdl /* $NetBSD: lock_proc.c,v 1.5 2000/06/09 14:00:52 fvdl Exp $ */
2 1.1 scottr
3 1.1 scottr /*
4 1.1 scottr * Copyright (c) 1995
5 1.1 scottr * A.R. Gordon (andrew.gordon (at) net-tel.co.uk). All rights reserved.
6 1.1 scottr *
7 1.1 scottr * Redistribution and use in source and binary forms, with or without
8 1.1 scottr * modification, are permitted provided that the following conditions
9 1.1 scottr * are met:
10 1.1 scottr * 1. Redistributions of source code must retain the above copyright
11 1.1 scottr * notice, this list of conditions and the following disclaimer.
12 1.1 scottr * 2. Redistributions in binary form must reproduce the above copyright
13 1.1 scottr * notice, this list of conditions and the following disclaimer in the
14 1.1 scottr * documentation and/or other materials provided with the distribution.
15 1.1 scottr * 3. All advertising materials mentioning features or use of this software
16 1.1 scottr * must display the following acknowledgement:
17 1.1 scottr * This product includes software developed for the FreeBSD project
18 1.1 scottr * 4. Neither the name of the author nor the names of any co-contributors
19 1.1 scottr * may be used to endorse or promote products derived from this software
20 1.1 scottr * without specific prior written permission.
21 1.1 scottr *
22 1.1 scottr * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND
23 1.1 scottr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 1.1 scottr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 1.1 scottr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 1.1 scottr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 1.1 scottr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 1.1 scottr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 1.1 scottr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 1.1 scottr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 1.1 scottr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 1.1 scottr * SUCH DAMAGE.
33 1.1 scottr *
34 1.1 scottr */
35 1.1 scottr
36 1.2 lukem #include <sys/cdefs.h>
37 1.2 lukem #ifndef lint
38 1.5 fvdl __RCSID("$NetBSD: lock_proc.c,v 1.5 2000/06/09 14:00:52 fvdl Exp $");
39 1.2 lukem #endif
40 1.2 lukem
41 1.1 scottr #include <sys/param.h>
42 1.1 scottr #include <sys/socket.h>
43 1.1 scottr
44 1.1 scottr #include <netinet/in.h>
45 1.1 scottr #include <arpa/inet.h>
46 1.1 scottr
47 1.2 lukem #include <netdb.h>
48 1.2 lukem #include <stdio.h>
49 1.2 lukem #include <string.h>
50 1.2 lukem #include <syslog.h>
51 1.5 fvdl #include <netconfig.h>
52 1.2 lukem
53 1.1 scottr #include <rpc/rpc.h>
54 1.1 scottr #include <rpcsvc/sm_inter.h>
55 1.1 scottr
56 1.1 scottr #include "lockd.h"
57 1.1 scottr #include "nlm_prot.h"
58 1.4 bouyer #include "lockd_lock.h"
59 1.1 scottr
60 1.1 scottr
61 1.1 scottr #define CLIENT_CACHE_SIZE 64 /* No. of client sockets cached */
62 1.1 scottr #define CLIENT_CACHE_LIFETIME 120 /* In seconds */
63 1.1 scottr
64 1.2 lukem static void log_from_addr __P((char *, struct svc_req *));
65 1.5 fvdl static int addrcmp __P((struct sockaddr *, struct sockaddr *));
66 1.2 lukem
67 1.1 scottr /* log_from_addr ----------------------------------------------------------- */
68 1.1 scottr /*
69 1.1 scottr * Purpose: Log name of function called and source address
70 1.1 scottr * Returns: Nothing
71 1.1 scottr * Notes: Extracts the source address from the transport handle
72 1.1 scottr * passed in as part of the called procedure specification
73 1.1 scottr */
74 1.4 bouyer static void
75 1.1 scottr log_from_addr(fun_name, req)
76 1.1 scottr char *fun_name;
77 1.1 scottr struct svc_req *req;
78 1.1 scottr {
79 1.5 fvdl struct sockaddr *addr;
80 1.5 fvdl char hostname_buf[NI_MAXHOST];
81 1.5 fvdl
82 1.5 fvdl addr = svc_getrpccaller(req->rq_xprt)->buf;
83 1.5 fvdl if (getnameinfo(addr , addr->sa_len, hostname_buf, sizeof hostname_buf,
84 1.5 fvdl NULL, 0, 0) != 0)
85 1.5 fvdl return;
86 1.1 scottr
87 1.1 scottr syslog(LOG_DEBUG, "%s from %s", fun_name, hostname_buf);
88 1.1 scottr }
89 1.1 scottr
90 1.1 scottr /* get_client -------------------------------------------------------------- */
91 1.1 scottr /*
92 1.1 scottr * Purpose: Get a CLIENT* for making RPC calls to lockd on given host
93 1.1 scottr * Returns: CLIENT* pointer, from clnt_udp_create, or NULL if error
94 1.1 scottr * Notes: Creating a CLIENT* is quite expensive, involving a
95 1.1 scottr * conversation with the remote portmapper to get the
96 1.1 scottr * port number. Since a given client is quite likely
97 1.1 scottr * to make several locking requests in succession, it is
98 1.1 scottr * desirable to cache the created CLIENT*.
99 1.1 scottr *
100 1.1 scottr * Since we are using UDP rather than TCP, there is no cost
101 1.1 scottr * to the remote system in keeping these cached indefinitely.
102 1.1 scottr * Unfortunately there is a snag: if the remote system
103 1.1 scottr * reboots, the cached portmapper results will be invalid,
104 1.1 scottr * and we will never detect this since all of the xxx_msg()
105 1.1 scottr * calls return no result - we just fire off a udp packet
106 1.1 scottr * and hope for the best.
107 1.1 scottr *
108 1.1 scottr * We solve this by discarding cached values after two
109 1.1 scottr * minutes, regardless of whether they have been used
110 1.1 scottr * in the meanwhile (since a bad one might have been used
111 1.1 scottr * plenty of times, as the host keeps retrying the request
112 1.1 scottr * and we keep sending the reply back to the wrong port).
113 1.1 scottr *
114 1.1 scottr * Given that the entries will always expire in the order
115 1.1 scottr * that they were created, there is no point in a LRU
116 1.1 scottr * algorithm for when the cache gets full - entries are
117 1.1 scottr * always re-used in sequence.
118 1.1 scottr */
119 1.1 scottr static CLIENT *clnt_cache_ptr[CLIENT_CACHE_SIZE];
120 1.1 scottr static long clnt_cache_time[CLIENT_CACHE_SIZE]; /* time entry created */
121 1.5 fvdl static struct sockaddr_storage clnt_cache_addr[CLIENT_CACHE_SIZE];
122 1.1 scottr static int clnt_cache_next_to_use = 0;
123 1.1 scottr
124 1.5 fvdl static int
125 1.5 fvdl addrcmp(sa1, sa2)
126 1.5 fvdl struct sockaddr *sa1;
127 1.5 fvdl struct sockaddr *sa2;
128 1.5 fvdl {
129 1.5 fvdl int len;
130 1.5 fvdl void *p1, *p2;
131 1.5 fvdl
132 1.5 fvdl if (sa1->sa_family != sa2->sa_family)
133 1.5 fvdl return -1;
134 1.5 fvdl
135 1.5 fvdl switch (sa1->sa_family) {
136 1.5 fvdl case AF_INET:
137 1.5 fvdl p1 = &((struct sockaddr_in *)sa1)->sin_addr;
138 1.5 fvdl p2 = &((struct sockaddr_in *)sa2)->sin_addr;
139 1.5 fvdl len = 4;
140 1.5 fvdl break;
141 1.5 fvdl case AF_INET6:
142 1.5 fvdl p1 = &((struct sockaddr_in6 *)sa1)->sin6_addr;
143 1.5 fvdl p2 = &((struct sockaddr_in6 *)sa2)->sin6_addr;
144 1.5 fvdl len = 16;
145 1.5 fvdl break;
146 1.5 fvdl default:
147 1.5 fvdl return -1;
148 1.5 fvdl }
149 1.5 fvdl
150 1.5 fvdl return memcmp(p1, p2, len);
151 1.5 fvdl }
152 1.5 fvdl
153 1.4 bouyer CLIENT *
154 1.4 bouyer get_client(host_addr, vers)
155 1.5 fvdl struct sockaddr *host_addr;
156 1.5 fvdl rpcvers_t vers;
157 1.1 scottr {
158 1.1 scottr CLIENT *client;
159 1.1 scottr struct timeval retry_time, time_now;
160 1.5 fvdl int i;
161 1.5 fvdl char *netid;
162 1.5 fvdl struct netconfig *nconf;
163 1.5 fvdl char host[NI_MAXHOST];
164 1.1 scottr
165 1.1 scottr gettimeofday(&time_now, NULL);
166 1.1 scottr
167 1.1 scottr /*
168 1.1 scottr * Search for the given client in the cache, zapping any expired
169 1.1 scottr * entries that we happen to notice in passing.
170 1.1 scottr */
171 1.1 scottr for (i = 0; i < CLIENT_CACHE_SIZE; i++) {
172 1.1 scottr client = clnt_cache_ptr[i];
173 1.1 scottr if (client && ((clnt_cache_time[i] + CLIENT_CACHE_LIFETIME)
174 1.1 scottr < time_now.tv_sec)) {
175 1.1 scottr /* Cache entry has expired. */
176 1.1 scottr if (debug_level > 3)
177 1.1 scottr syslog(LOG_DEBUG, "Expired CLIENT* in cache");
178 1.1 scottr clnt_cache_time[i] = 0L;
179 1.1 scottr clnt_destroy(client);
180 1.1 scottr clnt_cache_ptr[i] = NULL;
181 1.1 scottr client = NULL;
182 1.1 scottr }
183 1.5 fvdl if (client && !addrcmp((struct sockaddr *)&clnt_cache_addr[i],
184 1.5 fvdl host_addr)) {
185 1.1 scottr /* Found it! */
186 1.1 scottr if (debug_level > 3)
187 1.1 scottr syslog(LOG_DEBUG, "Found CLIENT* in cache");
188 1.1 scottr return (client);
189 1.1 scottr }
190 1.1 scottr }
191 1.1 scottr
192 1.1 scottr /* Not found in cache. Free the next entry if it is in use. */
193 1.1 scottr if (clnt_cache_ptr[clnt_cache_next_to_use]) {
194 1.1 scottr clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]);
195 1.1 scottr clnt_cache_ptr[clnt_cache_next_to_use] = NULL;
196 1.1 scottr }
197 1.1 scottr
198 1.5 fvdl /*
199 1.5 fvdl * Need a host string for clnt_tp_create. Use NI_NUMERICHOST
200 1.5 fvdl * to avoid DNS lookups.
201 1.5 fvdl */
202 1.5 fvdl if (getnameinfo(host_addr, host_addr->sa_len, host, sizeof host,
203 1.5 fvdl NULL, 0, NI_NUMERICHOST) != 0) {
204 1.5 fvdl syslog(LOG_ERR, "unable to get name string for caller");
205 1.5 fvdl return NULL;
206 1.5 fvdl }
207 1.5 fvdl
208 1.4 bouyer #if 1
209 1.5 fvdl if (host_addr->sa_family == AF_INET6)
210 1.5 fvdl netid = "udp6";
211 1.5 fvdl else
212 1.5 fvdl netid = "udp";
213 1.4 bouyer #else
214 1.5 fvdl if (host_addr->sa_family == AF_INET6)
215 1.5 fvdl netid = "tcp6";
216 1.5 fvdl else
217 1.5 fvdl netid = "tcp";
218 1.4 bouyer #endif
219 1.5 fvdl nconf = getnetconfigent(netid);
220 1.5 fvdl if (nconf == NULL) {
221 1.5 fvdl syslog(LOG_ERR, "could not get netconfig info for '%s': "
222 1.5 fvdl "no /etc/netconfig file?", netid);
223 1.5 fvdl return NULL;
224 1.5 fvdl }
225 1.5 fvdl
226 1.5 fvdl client = clnt_tp_create(host, NLM_PROG, vers, nconf);
227 1.5 fvdl freenetconfigent(nconf);
228 1.5 fvdl
229 1.1 scottr if (!client) {
230 1.1 scottr syslog(LOG_ERR, clnt_spcreateerror("clntudp_create"));
231 1.5 fvdl syslog(LOG_ERR, "Unable to return result to %s", host);
232 1.1 scottr return NULL;
233 1.1 scottr }
234 1.1 scottr
235 1.1 scottr /* Success - update the cache entry */
236 1.1 scottr clnt_cache_ptr[clnt_cache_next_to_use] = client;
237 1.5 fvdl memcpy(&clnt_cache_addr[clnt_cache_next_to_use], host_addr,
238 1.5 fvdl host_addr->sa_len);
239 1.1 scottr clnt_cache_time[clnt_cache_next_to_use] = time_now.tv_sec;
240 1.1 scottr if (++clnt_cache_next_to_use > CLIENT_CACHE_SIZE)
241 1.1 scottr clnt_cache_next_to_use = 0;
242 1.1 scottr
243 1.1 scottr /*
244 1.1 scottr * Disable the default timeout, so we can specify our own in calls
245 1.1 scottr * to clnt_call(). (Note that the timeout is a different concept
246 1.1 scottr * from the retry period set in clnt_udp_create() above.)
247 1.1 scottr */
248 1.1 scottr retry_time.tv_sec = -1;
249 1.1 scottr retry_time.tv_usec = -1;
250 1.1 scottr clnt_control(client, CLSET_TIMEOUT, (char *)&retry_time);
251 1.1 scottr
252 1.1 scottr if (debug_level > 3)
253 1.5 fvdl syslog(LOG_DEBUG, "Created CLIENT* for %s", host);
254 1.1 scottr return client;
255 1.1 scottr }
256 1.1 scottr
257 1.1 scottr
258 1.1 scottr /* transmit_result --------------------------------------------------------- */
259 1.1 scottr /*
260 1.1 scottr * Purpose: Transmit result for nlm_xxx_msg pseudo-RPCs
261 1.1 scottr * Returns: Nothing - we have no idea if the datagram got there
262 1.1 scottr * Notes: clnt_call() will always fail (with timeout) as we are
263 1.1 scottr * calling it with timeout 0 as a hack to just issue a datagram
264 1.1 scottr * without expecting a result
265 1.1 scottr */
266 1.4 bouyer void
267 1.4 bouyer transmit_result(opcode, result, addr)
268 1.1 scottr int opcode;
269 1.1 scottr nlm_res *result;
270 1.4 bouyer struct sockaddr *addr;
271 1.1 scottr {
272 1.1 scottr static char dummy;
273 1.1 scottr CLIENT *cli;
274 1.1 scottr struct timeval timeo;
275 1.1 scottr int success;
276 1.1 scottr
277 1.5 fvdl if ((cli = get_client(addr, NLM_VERS)) != NULL) {
278 1.1 scottr timeo.tv_sec = 0; /* No timeout - not expecting response */
279 1.1 scottr timeo.tv_usec = 0;
280 1.1 scottr
281 1.1 scottr success = clnt_call(cli, opcode, xdr_nlm_res, result, xdr_void,
282 1.1 scottr &dummy, timeo);
283 1.1 scottr
284 1.1 scottr if (debug_level > 2)
285 1.4 bouyer syslog(LOG_DEBUG, "clnt_call returns %d(%s)",
286 1.4 bouyer success, clnt_sperrno(success));
287 1.1 scottr }
288 1.1 scottr }
289 1.3 bouyer /* transmit4_result --------------------------------------------------------- */
290 1.3 bouyer /*
291 1.3 bouyer * Purpose: Transmit result for nlm4_xxx_msg pseudo-RPCs
292 1.3 bouyer * Returns: Nothing - we have no idea if the datagram got there
293 1.3 bouyer * Notes: clnt_call() will always fail (with timeout) as we are
294 1.3 bouyer * calling it with timeout 0 as a hack to just issue a datagram
295 1.3 bouyer * without expecting a result
296 1.3 bouyer */
297 1.4 bouyer void
298 1.4 bouyer transmit4_result(opcode, result, addr)
299 1.3 bouyer int opcode;
300 1.3 bouyer nlm4_res *result;
301 1.4 bouyer struct sockaddr *addr;
302 1.3 bouyer {
303 1.3 bouyer static char dummy;
304 1.3 bouyer CLIENT *cli;
305 1.3 bouyer struct timeval timeo;
306 1.3 bouyer int success;
307 1.3 bouyer
308 1.5 fvdl if ((cli = get_client(addr, NLM_VERS4)) != NULL) {
309 1.3 bouyer timeo.tv_sec = 0; /* No timeout - not expecting response */
310 1.3 bouyer timeo.tv_usec = 0;
311 1.3 bouyer
312 1.3 bouyer success = clnt_call(cli, opcode, xdr_nlm4_res, result, xdr_void,
313 1.3 bouyer &dummy, timeo);
314 1.3 bouyer
315 1.3 bouyer if (debug_level > 2)
316 1.4 bouyer syslog(LOG_DEBUG, "clnt_call returns %d(%s)",
317 1.4 bouyer success, clnt_sperrno(success));
318 1.3 bouyer }
319 1.3 bouyer }
320 1.4 bouyer
321 1.4 bouyer /*
322 1.4 bouyer * converts a struct nlm_lock to struct nlm4_lock
323 1.4 bouyer */
324 1.4 bouyer static void nlmtonlm4 __P((struct nlm_lock *, struct nlm4_lock *));
325 1.4 bouyer static void
326 1.4 bouyer nlmtonlm4(arg, arg4)
327 1.4 bouyer struct nlm_lock *arg;
328 1.4 bouyer struct nlm4_lock *arg4;
329 1.4 bouyer {
330 1.4 bouyer memcpy(arg4, arg, sizeof(nlm_lock));
331 1.4 bouyer arg4->l_offset = arg->l_offset;
332 1.4 bouyer arg4->l_len = arg->l_len;
333 1.4 bouyer }
334 1.1 scottr /* ------------------------------------------------------------------------- */
335 1.1 scottr /*
336 1.1 scottr * Functions for Unix<->Unix locking (ie. monitored locking, with rpc.statd
337 1.1 scottr * involved to ensure reclaim of locks after a crash of the "stateless"
338 1.1 scottr * server.
339 1.1 scottr *
340 1.1 scottr * These all come in two flavours - nlm_xxx() and nlm_xxx_msg().
341 1.1 scottr * The first are standard RPCs with argument and result.
342 1.1 scottr * The nlm_xxx_msg() calls implement exactly the same functions, but
343 1.1 scottr * use two pseudo-RPCs (one in each direction). These calls are NOT
344 1.1 scottr * standard use of the RPC protocol in that they do not return a result
345 1.1 scottr * at all (NB. this is quite different from returning a void result).
346 1.1 scottr * The effect of this is to make the nlm_xxx_msg() calls simple unacknowledged
347 1.1 scottr * datagrams, requiring higher-level code to perform retries.
348 1.1 scottr *
349 1.1 scottr * Despite the disadvantages of the nlm_xxx_msg() approach (some of which
350 1.1 scottr * are documented in the comments to get_client() above), this is the
351 1.1 scottr * interface used by all current commercial NFS implementations
352 1.1 scottr * [Solaris, SCO, AIX etc.]. This is presumed to be because these allow
353 1.1 scottr * implementations to continue using the standard RPC libraries, while
354 1.1 scottr * avoiding the block-until-result nature of the library interface.
355 1.1 scottr *
356 1.1 scottr * No client implementations have been identified so far that make use
357 1.1 scottr * of the true RPC version (early SunOS releases would be a likely candidate
358 1.1 scottr * for testing).
359 1.1 scottr */
360 1.1 scottr
361 1.1 scottr /* nlm_test ---------------------------------------------------------------- */
362 1.1 scottr /*
363 1.1 scottr * Purpose: Test whether a specified lock would be granted if requested
364 1.1 scottr * Returns: nlm_granted (or error code)
365 1.1 scottr * Notes:
366 1.1 scottr */
367 1.1 scottr nlm_testres *
368 1.1 scottr nlm_test_1_svc(arg, rqstp)
369 1.1 scottr nlm_testargs *arg;
370 1.1 scottr struct svc_req *rqstp;
371 1.1 scottr {
372 1.1 scottr static nlm_testres res;
373 1.4 bouyer struct nlm4_lock arg4;
374 1.4 bouyer struct nlm4_holder *holder;
375 1.4 bouyer nlmtonlm4(&arg->alock, &arg4);
376 1.1 scottr
377 1.1 scottr if (debug_level)
378 1.1 scottr log_from_addr("nlm_test", rqstp);
379 1.1 scottr
380 1.4 bouyer holder = testlock(&arg4, 0);
381 1.1 scottr /*
382 1.1 scottr * Copy the cookie from the argument into the result. Note that this
383 1.1 scottr * is slightly hazardous, as the structure contains a pointer to a
384 1.1 scottr * malloc()ed buffer that will get freed by the caller. However, the
385 1.1 scottr * main function transmits the result before freeing the argument
386 1.1 scottr * so it is in fact safe.
387 1.1 scottr */
388 1.1 scottr res.cookie = arg->cookie;
389 1.4 bouyer if (holder == NULL) {
390 1.4 bouyer res.stat.stat = nlm_granted;
391 1.4 bouyer } else {
392 1.4 bouyer res.stat.stat = nlm_denied;
393 1.4 bouyer memcpy(&res.stat.nlm_testrply_u.holder, holder,
394 1.4 bouyer sizeof(struct nlm_holder));
395 1.4 bouyer res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset;
396 1.4 bouyer res.stat.nlm_testrply_u.holder.l_len = holder->l_len;
397 1.4 bouyer }
398 1.1 scottr return (&res);
399 1.1 scottr }
400 1.1 scottr
401 1.1 scottr void *
402 1.1 scottr nlm_test_msg_1_svc(arg, rqstp)
403 1.1 scottr nlm_testargs *arg;
404 1.1 scottr struct svc_req *rqstp;
405 1.1 scottr {
406 1.1 scottr nlm_testres res;
407 1.1 scottr static char dummy;
408 1.5 fvdl struct sockaddr *addr;
409 1.1 scottr CLIENT *cli;
410 1.1 scottr int success;
411 1.1 scottr struct timeval timeo;
412 1.4 bouyer struct nlm4_lock arg4;
413 1.4 bouyer struct nlm4_holder *holder;
414 1.4 bouyer
415 1.4 bouyer nlmtonlm4(&arg->alock, &arg4);
416 1.1 scottr
417 1.1 scottr if (debug_level)
418 1.1 scottr log_from_addr("nlm_test_msg", rqstp);
419 1.1 scottr
420 1.4 bouyer holder = testlock(&arg4, 0);
421 1.4 bouyer
422 1.1 scottr res.cookie = arg->cookie;
423 1.4 bouyer if (holder == NULL) {
424 1.4 bouyer res.stat.stat = nlm_granted;
425 1.4 bouyer } else {
426 1.4 bouyer res.stat.stat = nlm_denied;
427 1.4 bouyer memcpy(&res.stat.nlm_testrply_u.holder, holder,
428 1.4 bouyer sizeof(struct nlm_holder));
429 1.4 bouyer res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset;
430 1.4 bouyer res.stat.nlm_testrply_u.holder.l_len = holder->l_len;
431 1.4 bouyer }
432 1.1 scottr
433 1.1 scottr /*
434 1.1 scottr * nlm_test has different result type to the other operations, so
435 1.1 scottr * can't use transmit_result() in this case
436 1.1 scottr */
437 1.5 fvdl addr = svc_getrpccaller(rqstp->rq_xprt)->buf;
438 1.4 bouyer if ((cli = get_client(addr, NLM_VERS)) != NULL) {
439 1.1 scottr timeo.tv_sec = 0; /* No timeout - not expecting response */
440 1.1 scottr timeo.tv_usec = 0;
441 1.1 scottr
442 1.1 scottr success = clnt_call(cli, NLM_TEST_RES, xdr_nlm_testres,
443 1.1 scottr &res, xdr_void, &dummy, timeo);
444 1.1 scottr
445 1.1 scottr if (debug_level > 2)
446 1.4 bouyer syslog(LOG_DEBUG, "clnt_call returns %d", success);
447 1.1 scottr }
448 1.1 scottr return (NULL);
449 1.1 scottr }
450 1.1 scottr
451 1.1 scottr /* nlm_lock ---------------------------------------------------------------- */
452 1.1 scottr /*
453 1.1 scottr * Purposes: Establish a lock
454 1.1 scottr * Returns: granted, denied or blocked
455 1.1 scottr * Notes: *** grace period support missing
456 1.1 scottr */
457 1.1 scottr nlm_res *
458 1.1 scottr nlm_lock_1_svc(arg, rqstp)
459 1.1 scottr nlm_lockargs *arg;
460 1.1 scottr struct svc_req *rqstp;
461 1.1 scottr {
462 1.1 scottr static nlm_res res;
463 1.4 bouyer struct nlm4_lockargs arg4;
464 1.4 bouyer nlmtonlm4(&arg->alock, &arg4.alock);
465 1.4 bouyer arg4.cookie = arg->cookie;
466 1.4 bouyer arg4.block = arg->block;
467 1.4 bouyer arg4.exclusive = arg->exclusive;
468 1.4 bouyer arg4.reclaim = arg->reclaim;
469 1.4 bouyer arg4.state = arg->state;
470 1.1 scottr
471 1.1 scottr if (debug_level)
472 1.1 scottr log_from_addr("nlm_lock", rqstp);
473 1.1 scottr
474 1.1 scottr /* copy cookie from arg to result. See comment in nlm_test_1() */
475 1.1 scottr res.cookie = arg->cookie;
476 1.1 scottr
477 1.4 bouyer res.stat.stat = getlock(&arg4, rqstp, LOCK_MON);
478 1.1 scottr return (&res);
479 1.1 scottr }
480 1.1 scottr
481 1.1 scottr void *
482 1.1 scottr nlm_lock_msg_1_svc(arg, rqstp)
483 1.1 scottr nlm_lockargs *arg;
484 1.1 scottr struct svc_req *rqstp;
485 1.1 scottr {
486 1.1 scottr static nlm_res res;
487 1.4 bouyer struct nlm4_lockargs arg4;
488 1.4 bouyer
489 1.4 bouyer nlmtonlm4(&arg->alock, &arg4.alock);
490 1.4 bouyer arg4.cookie = arg->cookie;
491 1.4 bouyer arg4.block = arg->block;
492 1.4 bouyer arg4.exclusive = arg->exclusive;
493 1.4 bouyer arg4.reclaim = arg->reclaim;
494 1.4 bouyer arg4.state = arg->state;
495 1.1 scottr
496 1.1 scottr if (debug_level)
497 1.1 scottr log_from_addr("nlm_lock_msg", rqstp);
498 1.1 scottr
499 1.1 scottr res.cookie = arg->cookie;
500 1.4 bouyer res.stat.stat = getlock(&arg4, rqstp, LOCK_ASYNC | LOCK_MON);
501 1.4 bouyer transmit_result(NLM_LOCK_RES, &res,
502 1.4 bouyer (struct sockaddr *)svc_getcaller(rqstp->rq_xprt));
503 1.1 scottr
504 1.1 scottr return (NULL);
505 1.1 scottr }
506 1.1 scottr
507 1.1 scottr /* nlm_cancel -------------------------------------------------------------- */
508 1.1 scottr /*
509 1.1 scottr * Purpose: Cancel a blocked lock request
510 1.1 scottr * Returns: granted or denied
511 1.1 scottr * Notes:
512 1.1 scottr */
513 1.1 scottr nlm_res *
514 1.1 scottr nlm_cancel_1_svc(arg, rqstp)
515 1.1 scottr nlm_cancargs *arg;
516 1.1 scottr struct svc_req *rqstp;
517 1.1 scottr {
518 1.1 scottr static nlm_res res;
519 1.4 bouyer struct nlm4_lock arg4;
520 1.4 bouyer
521 1.4 bouyer nlmtonlm4(&arg->alock, &arg4);
522 1.1 scottr
523 1.1 scottr if (debug_level)
524 1.1 scottr log_from_addr("nlm_cancel", rqstp);
525 1.1 scottr
526 1.1 scottr /* copy cookie from arg to result. See comment in nlm_test_1() */
527 1.1 scottr res.cookie = arg->cookie;
528 1.1 scottr
529 1.1 scottr /*
530 1.1 scottr * Since at present we never return 'nlm_blocked', there can never be
531 1.1 scottr * a lock to cancel, so this call always fails.
532 1.1 scottr */
533 1.4 bouyer res.stat.stat = unlock(&arg4, LOCK_CANCEL);
534 1.1 scottr return (&res);
535 1.1 scottr }
536 1.1 scottr
537 1.1 scottr void *
538 1.1 scottr nlm_cancel_msg_1_svc(arg, rqstp)
539 1.1 scottr nlm_cancargs *arg;
540 1.1 scottr struct svc_req *rqstp;
541 1.1 scottr {
542 1.1 scottr static nlm_res res;
543 1.4 bouyer struct nlm4_lock arg4;
544 1.4 bouyer
545 1.4 bouyer nlmtonlm4(&arg->alock, &arg4);
546 1.1 scottr
547 1.1 scottr if (debug_level)
548 1.1 scottr log_from_addr("nlm_cancel_msg", rqstp);
549 1.1 scottr
550 1.1 scottr res.cookie = arg->cookie;
551 1.1 scottr /*
552 1.1 scottr * Since at present we never return 'nlm_blocked', there can never be
553 1.1 scottr * a lock to cancel, so this call always fails.
554 1.1 scottr */
555 1.4 bouyer res.stat.stat = unlock(&arg4, LOCK_CANCEL);
556 1.4 bouyer transmit_result(NLM_CANCEL_RES, &res,
557 1.4 bouyer (struct sockaddr *)svc_getcaller(rqstp->rq_xprt));
558 1.1 scottr return (NULL);
559 1.1 scottr }
560 1.1 scottr
561 1.1 scottr /* nlm_unlock -------------------------------------------------------------- */
562 1.1 scottr /*
563 1.1 scottr * Purpose: Release an existing lock
564 1.1 scottr * Returns: Always granted, unless during grace period
565 1.1 scottr * Notes: "no such lock" error condition is ignored, as the
566 1.1 scottr * protocol uses unreliable UDP datagrams, and may well
567 1.1 scottr * re-try an unlock that has already succeeded.
568 1.1 scottr */
569 1.1 scottr nlm_res *
570 1.1 scottr nlm_unlock_1_svc(arg, rqstp)
571 1.1 scottr nlm_unlockargs *arg;
572 1.1 scottr struct svc_req *rqstp;
573 1.1 scottr {
574 1.1 scottr static nlm_res res;
575 1.4 bouyer struct nlm4_lock arg4;
576 1.4 bouyer
577 1.4 bouyer nlmtonlm4(&arg->alock, &arg4);
578 1.1 scottr
579 1.1 scottr if (debug_level)
580 1.1 scottr log_from_addr("nlm_unlock", rqstp);
581 1.1 scottr
582 1.4 bouyer res.stat.stat = unlock(&arg4, 0);
583 1.1 scottr res.cookie = arg->cookie;
584 1.1 scottr
585 1.1 scottr return (&res);
586 1.1 scottr }
587 1.1 scottr
588 1.1 scottr void *
589 1.1 scottr nlm_unlock_msg_1_svc(arg, rqstp)
590 1.1 scottr nlm_unlockargs *arg;
591 1.1 scottr struct svc_req *rqstp;
592 1.1 scottr {
593 1.1 scottr static nlm_res res;
594 1.4 bouyer struct nlm4_lock arg4;
595 1.4 bouyer
596 1.4 bouyer nlmtonlm4(&arg->alock, &arg4);
597 1.1 scottr
598 1.1 scottr if (debug_level)
599 1.1 scottr log_from_addr("nlm_unlock_msg", rqstp);
600 1.1 scottr
601 1.4 bouyer res.stat.stat = unlock(&arg4, 0);
602 1.1 scottr res.cookie = arg->cookie;
603 1.1 scottr
604 1.4 bouyer transmit_result(NLM_UNLOCK_RES, &res,
605 1.4 bouyer (struct sockaddr *)svc_getcaller(rqstp->rq_xprt));
606 1.1 scottr return (NULL);
607 1.1 scottr }
608 1.1 scottr
609 1.1 scottr /* ------------------------------------------------------------------------- */
610 1.1 scottr /*
611 1.1 scottr * Client-side pseudo-RPCs for results. Note that for the client there
612 1.1 scottr * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
613 1.1 scottr * version returns the results in the RPC result, and so the client
614 1.1 scottr * does not normally receive incoming RPCs.
615 1.1 scottr *
616 1.1 scottr * The exception to this is nlm_granted(), which is genuinely an RPC
617 1.1 scottr * call from the server to the client - a 'call-back' in normal procedure
618 1.1 scottr * call terms.
619 1.1 scottr */
620 1.1 scottr
621 1.1 scottr /* nlm_granted ------------------------------------------------------------- */
622 1.1 scottr /*
623 1.1 scottr * Purpose: Receive notification that formerly blocked lock now granted
624 1.1 scottr * Returns: always success ('granted')
625 1.1 scottr * Notes:
626 1.1 scottr */
627 1.1 scottr nlm_res *
628 1.1 scottr nlm_granted_1_svc(arg, rqstp)
629 1.1 scottr nlm_testargs *arg;
630 1.1 scottr struct svc_req *rqstp;
631 1.1 scottr {
632 1.1 scottr static nlm_res res;
633 1.1 scottr
634 1.1 scottr if (debug_level)
635 1.1 scottr log_from_addr("nlm_granted", rqstp);
636 1.1 scottr
637 1.1 scottr /* copy cookie from arg to result. See comment in nlm_test_1() */
638 1.1 scottr res.cookie = arg->cookie;
639 1.1 scottr
640 1.1 scottr res.stat.stat = nlm_granted;
641 1.1 scottr return (&res);
642 1.1 scottr }
643 1.1 scottr
644 1.1 scottr void *
645 1.1 scottr nlm_granted_msg_1_svc(arg, rqstp)
646 1.1 scottr nlm_testargs *arg;
647 1.1 scottr struct svc_req *rqstp;
648 1.1 scottr {
649 1.1 scottr static nlm_res res;
650 1.1 scottr
651 1.1 scottr if (debug_level)
652 1.1 scottr log_from_addr("nlm_granted_msg", rqstp);
653 1.1 scottr
654 1.1 scottr res.cookie = arg->cookie;
655 1.1 scottr res.stat.stat = nlm_granted;
656 1.4 bouyer transmit_result(NLM_GRANTED_RES, &res,
657 1.4 bouyer (struct sockaddr *)svc_getcaller(rqstp->rq_xprt));
658 1.1 scottr return (NULL);
659 1.1 scottr }
660 1.1 scottr
661 1.1 scottr /* nlm_test_res ------------------------------------------------------------ */
662 1.1 scottr /*
663 1.1 scottr * Purpose: Accept result from earlier nlm_test_msg() call
664 1.1 scottr * Returns: Nothing
665 1.1 scottr */
666 1.1 scottr void *
667 1.1 scottr nlm_test_res_1_svc(arg, rqstp)
668 1.1 scottr nlm_testres *arg;
669 1.1 scottr struct svc_req *rqstp;
670 1.1 scottr {
671 1.1 scottr if (debug_level)
672 1.1 scottr log_from_addr("nlm_test_res", rqstp);
673 1.1 scottr return (NULL);
674 1.1 scottr }
675 1.1 scottr
676 1.1 scottr /* nlm_lock_res ------------------------------------------------------------ */
677 1.1 scottr /*
678 1.1 scottr * Purpose: Accept result from earlier nlm_lock_msg() call
679 1.1 scottr * Returns: Nothing
680 1.1 scottr */
681 1.1 scottr void *
682 1.1 scottr nlm_lock_res_1_svc(arg, rqstp)
683 1.1 scottr nlm_res *arg;
684 1.1 scottr struct svc_req *rqstp;
685 1.1 scottr {
686 1.1 scottr if (debug_level)
687 1.1 scottr log_from_addr("nlm_lock_res", rqstp);
688 1.1 scottr
689 1.1 scottr return (NULL);
690 1.1 scottr }
691 1.1 scottr
692 1.1 scottr /* nlm_cancel_res ---------------------------------------------------------- */
693 1.1 scottr /*
694 1.1 scottr * Purpose: Accept result from earlier nlm_cancel_msg() call
695 1.1 scottr * Returns: Nothing
696 1.1 scottr */
697 1.1 scottr void *
698 1.1 scottr nlm_cancel_res_1_svc(arg, rqstp)
699 1.1 scottr nlm_res *arg;
700 1.1 scottr struct svc_req *rqstp;
701 1.1 scottr {
702 1.1 scottr if (debug_level)
703 1.1 scottr log_from_addr("nlm_cancel_res", rqstp);
704 1.1 scottr return (NULL);
705 1.1 scottr }
706 1.1 scottr
707 1.1 scottr /* nlm_unlock_res ---------------------------------------------------------- */
708 1.1 scottr /*
709 1.1 scottr * Purpose: Accept result from earlier nlm_unlock_msg() call
710 1.1 scottr * Returns: Nothing
711 1.1 scottr */
712 1.1 scottr void *
713 1.1 scottr nlm_unlock_res_1_svc(arg, rqstp)
714 1.1 scottr nlm_res *arg;
715 1.1 scottr struct svc_req *rqstp;
716 1.1 scottr {
717 1.1 scottr if (debug_level)
718 1.1 scottr log_from_addr("nlm_unlock_res", rqstp);
719 1.1 scottr return (NULL);
720 1.1 scottr }
721 1.1 scottr
722 1.1 scottr /* nlm_granted_res --------------------------------------------------------- */
723 1.1 scottr /*
724 1.1 scottr * Purpose: Accept result from earlier nlm_granted_msg() call
725 1.1 scottr * Returns: Nothing
726 1.1 scottr */
727 1.1 scottr void *
728 1.1 scottr nlm_granted_res_1_svc(arg, rqstp)
729 1.1 scottr nlm_res *arg;
730 1.1 scottr struct svc_req *rqstp;
731 1.1 scottr {
732 1.1 scottr if (debug_level)
733 1.1 scottr log_from_addr("nlm_granted_res", rqstp);
734 1.1 scottr return (NULL);
735 1.1 scottr }
736 1.1 scottr
737 1.1 scottr /* ------------------------------------------------------------------------- */
738 1.1 scottr /*
739 1.1 scottr * Calls for PCNFS locking (aka non-monitored locking, no involvement
740 1.1 scottr * of rpc.statd).
741 1.1 scottr *
742 1.1 scottr * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
743 1.1 scottr */
744 1.1 scottr
745 1.1 scottr /* nlm_share --------------------------------------------------------------- */
746 1.1 scottr /*
747 1.1 scottr * Purpose: Establish a DOS-style lock
748 1.1 scottr * Returns: success or failure
749 1.1 scottr * Notes: Blocking locks are not supported - client is expected
750 1.1 scottr * to retry if required.
751 1.1 scottr */
752 1.1 scottr nlm_shareres *
753 1.1 scottr nlm_share_3_svc(arg, rqstp)
754 1.1 scottr nlm_shareargs *arg;
755 1.1 scottr struct svc_req *rqstp;
756 1.1 scottr {
757 1.1 scottr static nlm_shareres res;
758 1.1 scottr
759 1.1 scottr if (debug_level)
760 1.1 scottr log_from_addr("nlm_share", rqstp);
761 1.1 scottr
762 1.1 scottr res.cookie = arg->cookie;
763 1.1 scottr res.stat = nlm_granted;
764 1.1 scottr res.sequence = 1234356; /* X/Open says this field is ignored? */
765 1.1 scottr return (&res);
766 1.1 scottr }
767 1.1 scottr
768 1.1 scottr /* nlm_unshare ------------------------------------------------------------ */
769 1.1 scottr /*
770 1.1 scottr * Purpose: Release a DOS-style lock
771 1.1 scottr * Returns: nlm_granted, unless in grace period
772 1.1 scottr * Notes:
773 1.1 scottr */
774 1.1 scottr nlm_shareres *
775 1.1 scottr nlm_unshare_3_svc(arg, rqstp)
776 1.1 scottr nlm_shareargs *arg;
777 1.1 scottr struct svc_req *rqstp;
778 1.1 scottr {
779 1.1 scottr static nlm_shareres res;
780 1.1 scottr
781 1.1 scottr if (debug_level)
782 1.1 scottr log_from_addr("nlm_unshare", rqstp);
783 1.1 scottr
784 1.1 scottr res.cookie = arg->cookie;
785 1.1 scottr res.stat = nlm_granted;
786 1.1 scottr res.sequence = 1234356; /* X/Open says this field is ignored? */
787 1.1 scottr return (&res);
788 1.1 scottr }
789 1.1 scottr
790 1.1 scottr /* nlm_nm_lock ------------------------------------------------------------ */
791 1.1 scottr /*
792 1.1 scottr * Purpose: non-monitored version of nlm_lock()
793 1.1 scottr * Returns: as for nlm_lock()
794 1.1 scottr * Notes: These locks are in the same style as the standard nlm_lock,
795 1.1 scottr * but the rpc.statd should not be called to establish a
796 1.1 scottr * monitor for the client machine, since that machine is
797 1.1 scottr * declared not to be running a rpc.statd, and so would not
798 1.1 scottr * respond to the statd protocol.
799 1.1 scottr */
800 1.1 scottr nlm_res *
801 1.1 scottr nlm_nm_lock_3_svc(arg, rqstp)
802 1.1 scottr nlm_lockargs *arg;
803 1.1 scottr struct svc_req *rqstp;
804 1.1 scottr {
805 1.1 scottr static nlm_res res;
806 1.1 scottr
807 1.1 scottr if (debug_level)
808 1.1 scottr log_from_addr("nlm_nm_lock", rqstp);
809 1.1 scottr
810 1.1 scottr /* copy cookie from arg to result. See comment in nlm_test_1() */
811 1.1 scottr res.cookie = arg->cookie;
812 1.1 scottr res.stat.stat = nlm_granted;
813 1.1 scottr return (&res);
814 1.1 scottr }
815 1.1 scottr
816 1.1 scottr /* nlm_free_all ------------------------------------------------------------ */
817 1.1 scottr /*
818 1.1 scottr * Purpose: Release all locks held by a named client
819 1.1 scottr * Returns: Nothing
820 1.1 scottr * Notes: Potential denial of service security problem here - the
821 1.1 scottr * locks to be released are specified by a host name, independent
822 1.1 scottr * of the address from which the request has arrived.
823 1.1 scottr * Should probably be rejected if the named host has been
824 1.1 scottr * using monitored locks.
825 1.1 scottr */
826 1.1 scottr void *
827 1.1 scottr nlm_free_all_3_svc(arg, rqstp)
828 1.1 scottr nlm_notify *arg;
829 1.1 scottr struct svc_req *rqstp;
830 1.1 scottr {
831 1.1 scottr static char dummy;
832 1.1 scottr
833 1.1 scottr if (debug_level)
834 1.1 scottr log_from_addr("nlm_free_all", rqstp);
835 1.1 scottr return (&dummy);
836 1.1 scottr }
837 1.3 bouyer
838 1.3 bouyer /* calls for nlm version 4 (NFSv3) */
839 1.3 bouyer /* nlm_test ---------------------------------------------------------------- */
840 1.3 bouyer /*
841 1.3 bouyer * Purpose: Test whether a specified lock would be granted if requested
842 1.3 bouyer * Returns: nlm_granted (or error code)
843 1.3 bouyer * Notes:
844 1.3 bouyer */
845 1.3 bouyer nlm4_testres *
846 1.3 bouyer nlm4_test_4_svc(arg, rqstp)
847 1.3 bouyer nlm4_testargs *arg;
848 1.3 bouyer struct svc_req *rqstp;
849 1.3 bouyer {
850 1.3 bouyer static nlm4_testres res;
851 1.4 bouyer struct nlm4_holder *holder;
852 1.3 bouyer
853 1.3 bouyer if (debug_level)
854 1.3 bouyer log_from_addr("nlm4_test", rqstp);
855 1.3 bouyer
856 1.4 bouyer holder = testlock(&arg->alock, LOCK_V4);
857 1.4 bouyer
858 1.3 bouyer /*
859 1.3 bouyer * Copy the cookie from the argument into the result. Note that this
860 1.3 bouyer * is slightly hazardous, as the structure contains a pointer to a
861 1.3 bouyer * malloc()ed buffer that will get freed by the caller. However, the
862 1.3 bouyer * main function transmits the result before freeing the argument
863 1.3 bouyer * so it is in fact safe.
864 1.3 bouyer */
865 1.3 bouyer res.cookie = arg->cookie;
866 1.4 bouyer if (holder == NULL) {
867 1.4 bouyer res.stat.stat = nlm4_granted;
868 1.4 bouyer } else {
869 1.4 bouyer res.stat.stat = nlm4_denied;
870 1.4 bouyer memcpy(&res.stat.nlm4_testrply_u.holder, holder,
871 1.4 bouyer sizeof(struct nlm4_holder));
872 1.4 bouyer }
873 1.3 bouyer return (&res);
874 1.3 bouyer }
875 1.3 bouyer
876 1.3 bouyer void *
877 1.3 bouyer nlm4_test_msg_4_svc(arg, rqstp)
878 1.3 bouyer nlm4_testargs *arg;
879 1.3 bouyer struct svc_req *rqstp;
880 1.3 bouyer {
881 1.3 bouyer nlm4_testres res;
882 1.3 bouyer static char dummy;
883 1.5 fvdl struct sockaddr *addr;
884 1.3 bouyer CLIENT *cli;
885 1.3 bouyer int success;
886 1.3 bouyer struct timeval timeo;
887 1.4 bouyer struct nlm4_holder *holder;
888 1.3 bouyer
889 1.3 bouyer if (debug_level)
890 1.3 bouyer log_from_addr("nlm4_test_msg", rqstp);
891 1.3 bouyer
892 1.4 bouyer holder = testlock(&arg->alock, LOCK_V4);
893 1.4 bouyer
894 1.3 bouyer res.cookie = arg->cookie;
895 1.4 bouyer if (holder == NULL) {
896 1.4 bouyer res.stat.stat = nlm4_granted;
897 1.4 bouyer } else {
898 1.4 bouyer res.stat.stat = nlm4_denied;
899 1.4 bouyer memcpy(&res.stat.nlm4_testrply_u.holder, holder,
900 1.4 bouyer sizeof(struct nlm4_holder));
901 1.4 bouyer }
902 1.3 bouyer
903 1.3 bouyer /*
904 1.3 bouyer * nlm_test has different result type to the other operations, so
905 1.3 bouyer * can't use transmit4_result() in this case
906 1.3 bouyer */
907 1.5 fvdl addr = svc_getrpccaller(rqstp->rq_xprt)->buf;
908 1.4 bouyer if ((cli = get_client(addr, NLM_VERS4)) != NULL) {
909 1.3 bouyer timeo.tv_sec = 0; /* No timeout - not expecting response */
910 1.3 bouyer timeo.tv_usec = 0;
911 1.3 bouyer
912 1.3 bouyer success = clnt_call(cli, NLM4_TEST_RES, xdr_nlm4_testres,
913 1.3 bouyer &res, xdr_void, &dummy, timeo);
914 1.3 bouyer
915 1.3 bouyer if (debug_level > 2)
916 1.4 bouyer syslog(LOG_DEBUG, "clnt_call returns %d", success);
917 1.3 bouyer }
918 1.3 bouyer return (NULL);
919 1.3 bouyer }
920 1.3 bouyer
921 1.3 bouyer /* nlm_lock ---------------------------------------------------------------- */
922 1.3 bouyer /*
923 1.3 bouyer * Purposes: Establish a lock
924 1.3 bouyer * Returns: granted, denied or blocked
925 1.3 bouyer * Notes: *** grace period support missing
926 1.3 bouyer */
927 1.3 bouyer nlm4_res *
928 1.3 bouyer nlm4_lock_4_svc(arg, rqstp)
929 1.3 bouyer nlm4_lockargs *arg;
930 1.3 bouyer struct svc_req *rqstp;
931 1.3 bouyer {
932 1.3 bouyer static nlm4_res res;
933 1.3 bouyer
934 1.3 bouyer if (debug_level)
935 1.3 bouyer log_from_addr("nlm4_lock", rqstp);
936 1.3 bouyer
937 1.3 bouyer /* copy cookie from arg to result. See comment in nlm_test_4() */
938 1.3 bouyer res.cookie = arg->cookie;
939 1.3 bouyer
940 1.4 bouyer res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_V4);
941 1.3 bouyer return (&res);
942 1.3 bouyer }
943 1.3 bouyer
944 1.3 bouyer void *
945 1.3 bouyer nlm4_lock_msg_4_svc(arg, rqstp)
946 1.3 bouyer nlm4_lockargs *arg;
947 1.3 bouyer struct svc_req *rqstp;
948 1.3 bouyer {
949 1.3 bouyer static nlm4_res res;
950 1.3 bouyer
951 1.3 bouyer if (debug_level)
952 1.3 bouyer log_from_addr("nlm4_lock_msg", rqstp);
953 1.3 bouyer
954 1.3 bouyer res.cookie = arg->cookie;
955 1.4 bouyer res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_ASYNC | LOCK_V4);
956 1.4 bouyer transmit4_result(NLM4_LOCK_RES, &res,
957 1.4 bouyer (struct sockaddr *)svc_getcaller(rqstp->rq_xprt));
958 1.3 bouyer
959 1.3 bouyer return (NULL);
960 1.3 bouyer }
961 1.3 bouyer
962 1.3 bouyer /* nlm_cancel -------------------------------------------------------------- */
963 1.3 bouyer /*
964 1.3 bouyer * Purpose: Cancel a blocked lock request
965 1.3 bouyer * Returns: granted or denied
966 1.3 bouyer * Notes:
967 1.3 bouyer */
968 1.3 bouyer nlm4_res *
969 1.3 bouyer nlm4_cancel_4_svc(arg, rqstp)
970 1.3 bouyer nlm4_cancargs *arg;
971 1.3 bouyer struct svc_req *rqstp;
972 1.3 bouyer {
973 1.3 bouyer static nlm4_res res;
974 1.3 bouyer
975 1.3 bouyer if (debug_level)
976 1.3 bouyer log_from_addr("nlm4_cancel", rqstp);
977 1.3 bouyer
978 1.3 bouyer /* copy cookie from arg to result. See comment in nlm_test_1() */
979 1.3 bouyer res.cookie = arg->cookie;
980 1.3 bouyer
981 1.3 bouyer /*
982 1.3 bouyer * Since at present we never return 'nlm_blocked', there can never be
983 1.3 bouyer * a lock to cancel, so this call always fails.
984 1.3 bouyer */
985 1.4 bouyer res.stat.stat = unlock(&arg->alock, LOCK_CANCEL);
986 1.3 bouyer return (&res);
987 1.3 bouyer }
988 1.3 bouyer
989 1.3 bouyer void *
990 1.3 bouyer nlm4_cancel_msg_4_svc(arg, rqstp)
991 1.3 bouyer nlm4_cancargs *arg;
992 1.3 bouyer struct svc_req *rqstp;
993 1.3 bouyer {
994 1.3 bouyer static nlm4_res res;
995 1.3 bouyer
996 1.3 bouyer if (debug_level)
997 1.3 bouyer log_from_addr("nlm4_cancel_msg", rqstp);
998 1.3 bouyer
999 1.3 bouyer res.cookie = arg->cookie;
1000 1.3 bouyer /*
1001 1.3 bouyer * Since at present we never return 'nlm_blocked', there can never be
1002 1.3 bouyer * a lock to cancel, so this call always fails.
1003 1.3 bouyer */
1004 1.4 bouyer res.stat.stat = unlock(&arg->alock, LOCK_CANCEL | LOCK_V4);
1005 1.4 bouyer transmit4_result(NLM4_CANCEL_RES, &res,
1006 1.4 bouyer (struct sockaddr *)svc_getcaller(rqstp->rq_xprt));
1007 1.3 bouyer return (NULL);
1008 1.3 bouyer }
1009 1.3 bouyer
1010 1.3 bouyer /* nlm_unlock -------------------------------------------------------------- */
1011 1.3 bouyer /*
1012 1.3 bouyer * Purpose: Release an existing lock
1013 1.3 bouyer * Returns: Always granted, unless during grace period
1014 1.3 bouyer * Notes: "no such lock" error condition is ignored, as the
1015 1.3 bouyer * protocol uses unreliable UDP datagrams, and may well
1016 1.3 bouyer * re-try an unlock that has already succeeded.
1017 1.3 bouyer */
1018 1.3 bouyer nlm4_res *
1019 1.3 bouyer nlm4_unlock_4_svc(arg, rqstp)
1020 1.3 bouyer nlm4_unlockargs *arg;
1021 1.3 bouyer struct svc_req *rqstp;
1022 1.3 bouyer {
1023 1.3 bouyer static nlm4_res res;
1024 1.3 bouyer
1025 1.3 bouyer if (debug_level)
1026 1.3 bouyer log_from_addr("nlm4_unlock", rqstp);
1027 1.3 bouyer
1028 1.4 bouyer res.stat.stat = unlock(&arg->alock, LOCK_V4);
1029 1.3 bouyer res.cookie = arg->cookie;
1030 1.3 bouyer
1031 1.3 bouyer return (&res);
1032 1.3 bouyer }
1033 1.3 bouyer
1034 1.3 bouyer void *
1035 1.3 bouyer nlm4_unlock_msg_4_svc(arg, rqstp)
1036 1.3 bouyer nlm4_unlockargs *arg;
1037 1.3 bouyer struct svc_req *rqstp;
1038 1.3 bouyer {
1039 1.3 bouyer static nlm4_res res;
1040 1.3 bouyer
1041 1.3 bouyer if (debug_level)
1042 1.3 bouyer log_from_addr("nlm4_unlock_msg", rqstp);
1043 1.3 bouyer
1044 1.4 bouyer res.stat.stat = unlock(&arg->alock, LOCK_V4);
1045 1.3 bouyer res.cookie = arg->cookie;
1046 1.3 bouyer
1047 1.4 bouyer transmit4_result(NLM4_UNLOCK_RES, &res,
1048 1.4 bouyer (struct sockaddr *)svc_getcaller(rqstp->rq_xprt));
1049 1.3 bouyer return (NULL);
1050 1.3 bouyer }
1051 1.3 bouyer
1052 1.3 bouyer /* ------------------------------------------------------------------------- */
1053 1.3 bouyer /*
1054 1.3 bouyer * Client-side pseudo-RPCs for results. Note that for the client there
1055 1.3 bouyer * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
1056 1.3 bouyer * version returns the results in the RPC result, and so the client
1057 1.3 bouyer * does not normally receive incoming RPCs.
1058 1.3 bouyer *
1059 1.3 bouyer * The exception to this is nlm_granted(), which is genuinely an RPC
1060 1.3 bouyer * call from the server to the client - a 'call-back' in normal procedure
1061 1.3 bouyer * call terms.
1062 1.3 bouyer */
1063 1.3 bouyer
1064 1.3 bouyer /* nlm_granted ------------------------------------------------------------- */
1065 1.3 bouyer /*
1066 1.3 bouyer * Purpose: Receive notification that formerly blocked lock now granted
1067 1.3 bouyer * Returns: always success ('granted')
1068 1.3 bouyer * Notes:
1069 1.3 bouyer */
1070 1.3 bouyer nlm4_res *
1071 1.3 bouyer nlm4_granted_4_svc(arg, rqstp)
1072 1.3 bouyer nlm4_testargs *arg;
1073 1.3 bouyer struct svc_req *rqstp;
1074 1.3 bouyer {
1075 1.3 bouyer static nlm4_res res;
1076 1.3 bouyer
1077 1.3 bouyer if (debug_level)
1078 1.3 bouyer log_from_addr("nlm4_granted", rqstp);
1079 1.3 bouyer
1080 1.3 bouyer /* copy cookie from arg to result. See comment in nlm_test_1() */
1081 1.3 bouyer res.cookie = arg->cookie;
1082 1.3 bouyer
1083 1.3 bouyer res.stat.stat = nlm4_granted;
1084 1.3 bouyer return (&res);
1085 1.3 bouyer }
1086 1.3 bouyer
1087 1.3 bouyer void *
1088 1.3 bouyer nlm4_granted_msg_4_svc(arg, rqstp)
1089 1.3 bouyer nlm4_testargs *arg;
1090 1.3 bouyer struct svc_req *rqstp;
1091 1.3 bouyer {
1092 1.3 bouyer static nlm4_res res;
1093 1.3 bouyer
1094 1.3 bouyer if (debug_level)
1095 1.3 bouyer log_from_addr("nlm4_granted_msg", rqstp);
1096 1.3 bouyer
1097 1.3 bouyer res.cookie = arg->cookie;
1098 1.3 bouyer res.stat.stat = nlm4_granted;
1099 1.4 bouyer transmit4_result(NLM4_GRANTED_RES, &res,
1100 1.5 fvdl (struct sockaddr *)svc_getrpccaller(rqstp->rq_xprt)->buf);
1101 1.3 bouyer return (NULL);
1102 1.3 bouyer }
1103 1.3 bouyer
1104 1.3 bouyer /* nlm_test_res ------------------------------------------------------------ */
1105 1.3 bouyer /*
1106 1.3 bouyer * Purpose: Accept result from earlier nlm_test_msg() call
1107 1.3 bouyer * Returns: Nothing
1108 1.3 bouyer */
1109 1.3 bouyer void *
1110 1.3 bouyer nlm4_test_res_4_svc(arg, rqstp)
1111 1.3 bouyer nlm4_testres *arg;
1112 1.3 bouyer struct svc_req *rqstp;
1113 1.3 bouyer {
1114 1.3 bouyer if (debug_level)
1115 1.3 bouyer log_from_addr("nlm4_test_res", rqstp);
1116 1.3 bouyer return (NULL);
1117 1.3 bouyer }
1118 1.3 bouyer
1119 1.3 bouyer /* nlm_lock_res ------------------------------------------------------------ */
1120 1.3 bouyer /*
1121 1.3 bouyer * Purpose: Accept result from earlier nlm_lock_msg() call
1122 1.3 bouyer * Returns: Nothing
1123 1.3 bouyer */
1124 1.3 bouyer void *
1125 1.3 bouyer nlm4_lock_res_4_svc(arg, rqstp)
1126 1.3 bouyer nlm4_res *arg;
1127 1.3 bouyer struct svc_req *rqstp;
1128 1.3 bouyer {
1129 1.3 bouyer if (debug_level)
1130 1.3 bouyer log_from_addr("nlm4_lock_res", rqstp);
1131 1.3 bouyer
1132 1.3 bouyer return (NULL);
1133 1.3 bouyer }
1134 1.3 bouyer
1135 1.3 bouyer /* nlm_cancel_res ---------------------------------------------------------- */
1136 1.3 bouyer /*
1137 1.3 bouyer * Purpose: Accept result from earlier nlm_cancel_msg() call
1138 1.3 bouyer * Returns: Nothing
1139 1.3 bouyer */
1140 1.3 bouyer void *
1141 1.3 bouyer nlm4_cancel_res_4_svc(arg, rqstp)
1142 1.3 bouyer nlm4_res *arg;
1143 1.3 bouyer struct svc_req *rqstp;
1144 1.3 bouyer {
1145 1.3 bouyer if (debug_level)
1146 1.3 bouyer log_from_addr("nlm4_cancel_res", rqstp);
1147 1.3 bouyer return (NULL);
1148 1.3 bouyer }
1149 1.3 bouyer
1150 1.3 bouyer /* nlm_unlock_res ---------------------------------------------------------- */
1151 1.3 bouyer /*
1152 1.3 bouyer * Purpose: Accept result from earlier nlm_unlock_msg() call
1153 1.3 bouyer * Returns: Nothing
1154 1.3 bouyer */
1155 1.3 bouyer void *
1156 1.3 bouyer nlm4_unlock_res_4_svc(arg, rqstp)
1157 1.3 bouyer nlm4_res *arg;
1158 1.3 bouyer struct svc_req *rqstp;
1159 1.3 bouyer {
1160 1.3 bouyer if (debug_level)
1161 1.3 bouyer log_from_addr("nlm4_unlock_res", rqstp);
1162 1.3 bouyer return (NULL);
1163 1.3 bouyer }
1164 1.3 bouyer
1165 1.3 bouyer /* nlm_granted_res --------------------------------------------------------- */
1166 1.3 bouyer /*
1167 1.3 bouyer * Purpose: Accept result from earlier nlm_granted_msg() call
1168 1.3 bouyer * Returns: Nothing
1169 1.3 bouyer */
1170 1.3 bouyer void *
1171 1.3 bouyer nlm4_granted_res_4_svc(arg, rqstp)
1172 1.3 bouyer nlm4_res *arg;
1173 1.3 bouyer struct svc_req *rqstp;
1174 1.3 bouyer {
1175 1.3 bouyer if (debug_level)
1176 1.3 bouyer log_from_addr("nlm4_granted_res", rqstp);
1177 1.3 bouyer return (NULL);
1178 1.3 bouyer }
1179 1.3 bouyer
1180 1.3 bouyer /* ------------------------------------------------------------------------- */
1181 1.3 bouyer /*
1182 1.3 bouyer * Calls for PCNFS locking (aka non-monitored locking, no involvement
1183 1.3 bouyer * of rpc.statd).
1184 1.3 bouyer *
1185 1.3 bouyer * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
1186 1.3 bouyer */
1187 1.3 bouyer
1188 1.3 bouyer /* nlm_share --------------------------------------------------------------- */
1189 1.3 bouyer /*
1190 1.3 bouyer * Purpose: Establish a DOS-style lock
1191 1.3 bouyer * Returns: success or failure
1192 1.3 bouyer * Notes: Blocking locks are not supported - client is expected
1193 1.3 bouyer * to retry if required.
1194 1.3 bouyer */
1195 1.3 bouyer nlm4_shareres *
1196 1.3 bouyer nlm4_share_4_svc(arg, rqstp)
1197 1.3 bouyer nlm4_shareargs *arg;
1198 1.3 bouyer struct svc_req *rqstp;
1199 1.3 bouyer {
1200 1.3 bouyer static nlm4_shareres res;
1201 1.3 bouyer
1202 1.3 bouyer if (debug_level)
1203 1.3 bouyer log_from_addr("nlm4_share", rqstp);
1204 1.3 bouyer
1205 1.3 bouyer res.cookie = arg->cookie;
1206 1.3 bouyer res.stat = nlm4_granted;
1207 1.3 bouyer res.sequence = 1234356; /* X/Open says this field is ignored? */
1208 1.3 bouyer return (&res);
1209 1.3 bouyer }
1210 1.3 bouyer
1211 1.3 bouyer /* nlm4_unshare ------------------------------------------------------------ */
1212 1.3 bouyer /*
1213 1.3 bouyer * Purpose: Release a DOS-style lock
1214 1.3 bouyer * Returns: nlm_granted, unless in grace period
1215 1.3 bouyer * Notes:
1216 1.3 bouyer */
1217 1.3 bouyer nlm4_shareres *
1218 1.3 bouyer nlm4_unshare_4_svc(arg, rqstp)
1219 1.3 bouyer nlm4_shareargs *arg;
1220 1.3 bouyer struct svc_req *rqstp;
1221 1.3 bouyer {
1222 1.3 bouyer static nlm4_shareres res;
1223 1.3 bouyer
1224 1.3 bouyer if (debug_level)
1225 1.3 bouyer log_from_addr("nlm_unshare", rqstp);
1226 1.3 bouyer
1227 1.3 bouyer res.cookie = arg->cookie;
1228 1.3 bouyer res.stat = nlm4_granted;
1229 1.3 bouyer res.sequence = 1234356; /* X/Open says this field is ignored? */
1230 1.3 bouyer return (&res);
1231 1.3 bouyer }
1232 1.3 bouyer
1233 1.3 bouyer /* nlm4_nm_lock ------------------------------------------------------------ */
1234 1.3 bouyer /*
1235 1.3 bouyer * Purpose: non-monitored version of nlm4_lock()
1236 1.3 bouyer * Returns: as for nlm4_lock()
1237 1.3 bouyer * Notes: These locks are in the same style as the standard nlm4_lock,
1238 1.3 bouyer * but the rpc.statd should not be called to establish a
1239 1.3 bouyer * monitor for the client machine, since that machine is
1240 1.3 bouyer * declared not to be running a rpc.statd, and so would not
1241 1.3 bouyer * respond to the statd protocol.
1242 1.3 bouyer */
1243 1.3 bouyer nlm4_res *
1244 1.3 bouyer nlm4_nm_lock_4_svc(arg, rqstp)
1245 1.3 bouyer nlm4_lockargs *arg;
1246 1.3 bouyer struct svc_req *rqstp;
1247 1.3 bouyer {
1248 1.3 bouyer static nlm4_res res;
1249 1.3 bouyer
1250 1.3 bouyer if (debug_level)
1251 1.3 bouyer log_from_addr("nlm4_nm_lock", rqstp);
1252 1.3 bouyer
1253 1.3 bouyer /* copy cookie from arg to result. See comment in nlm4_test_1() */
1254 1.3 bouyer res.cookie = arg->cookie;
1255 1.3 bouyer res.stat.stat = nlm4_granted;
1256 1.3 bouyer return (&res);
1257 1.3 bouyer }
1258 1.3 bouyer
1259 1.3 bouyer /* nlm4_free_all ------------------------------------------------------------ */
1260 1.3 bouyer /*
1261 1.3 bouyer * Purpose: Release all locks held by a named client
1262 1.3 bouyer * Returns: Nothing
1263 1.3 bouyer * Notes: Potential denial of service security problem here - the
1264 1.3 bouyer * locks to be released are specified by a host name, independent
1265 1.3 bouyer * of the address from which the request has arrived.
1266 1.3 bouyer * Should probably be rejected if the named host has been
1267 1.3 bouyer * using monitored locks.
1268 1.3 bouyer */
1269 1.3 bouyer void *
1270 1.3 bouyer nlm4_free_all_4_svc(arg, rqstp)
1271 1.3 bouyer nlm_notify *arg;
1272 1.3 bouyer struct svc_req *rqstp;
1273 1.3 bouyer {
1274 1.3 bouyer static char dummy;
1275 1.3 bouyer
1276 1.3 bouyer if (debug_level)
1277 1.3 bouyer log_from_addr("nlm4_free_all", rqstp);
1278 1.3 bouyer return (&dummy);
1279 1.3 bouyer }
1280 1.3 bouyer
1281 1.4 bouyer /* nlm_sm_notify --------------------------------------------------------- */
1282 1.4 bouyer /*
1283 1.4 bouyer * Purpose: called by rpc.statd when a monitored host state changes.
1284 1.4 bouyer * Returns: Nothing
1285 1.4 bouyer */
1286 1.4 bouyer void *
1287 1.4 bouyer nlm_sm_notify_0_svc(arg, rqstp)
1288 1.4 bouyer struct nlm_sm_status *arg;
1289 1.4 bouyer struct svc_req *rqstp;
1290 1.4 bouyer {
1291 1.4 bouyer static char dummy;
1292 1.4 bouyer notify(arg->mon_name, arg->state);
1293 1.4 bouyer return (&dummy);
1294 1.4 bouyer }
1295