lock_proc.c revision 1.3 1 1.3 bouyer /* $NetBSD: lock_proc.c,v 1.3 2000/02/02 18:17:42 bouyer 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.3 bouyer __RCSID("$NetBSD: lock_proc.c,v 1.3 2000/02/02 18:17:42 bouyer 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.2 lukem
52 1.1 scottr #include <rpc/rpc.h>
53 1.1 scottr #include <rpcsvc/sm_inter.h>
54 1.1 scottr
55 1.1 scottr #include "lockd.h"
56 1.1 scottr #include "nlm_prot.h"
57 1.1 scottr
58 1.1 scottr
59 1.1 scottr #define CLIENT_CACHE_SIZE 64 /* No. of client sockets cached */
60 1.1 scottr #define CLIENT_CACHE_LIFETIME 120 /* In seconds */
61 1.1 scottr
62 1.2 lukem static CLIENT *get_client __P((struct sockaddr_in *));
63 1.2 lukem static void log_from_addr __P((char *, struct svc_req *));
64 1.2 lukem static void transmit_result __P((int, nlm_res *, struct svc_req *));
65 1.3 bouyer static void transmit4_result __P((int, nlm4_res *, struct svc_req *));
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.1 scottr 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.1 scottr struct sockaddr_in *addr;
80 1.1 scottr struct hostent *host;
81 1.1 scottr char hostname_buf[40];
82 1.1 scottr
83 1.1 scottr addr = svc_getcaller(req->rq_xprt);
84 1.1 scottr host = gethostbyaddr((char *)&(addr->sin_addr), addr->sin_len, AF_INET);
85 1.1 scottr if (host) {
86 1.1 scottr strncpy(hostname_buf, host->h_name, sizeof(hostname_buf));
87 1.1 scottr hostname_buf[sizeof(hostname_buf) - 1] = '\0';
88 1.1 scottr } else /* No hostname available - print raw address */
89 1.1 scottr strcpy(hostname_buf, inet_ntoa(addr->sin_addr));
90 1.1 scottr
91 1.1 scottr syslog(LOG_DEBUG, "%s from %s", fun_name, hostname_buf);
92 1.1 scottr }
93 1.1 scottr
94 1.1 scottr /* get_client -------------------------------------------------------------- */
95 1.1 scottr /*
96 1.1 scottr * Purpose: Get a CLIENT* for making RPC calls to lockd on given host
97 1.1 scottr * Returns: CLIENT* pointer, from clnt_udp_create, or NULL if error
98 1.1 scottr * Notes: Creating a CLIENT* is quite expensive, involving a
99 1.1 scottr * conversation with the remote portmapper to get the
100 1.1 scottr * port number. Since a given client is quite likely
101 1.1 scottr * to make several locking requests in succession, it is
102 1.1 scottr * desirable to cache the created CLIENT*.
103 1.1 scottr *
104 1.1 scottr * Since we are using UDP rather than TCP, there is no cost
105 1.1 scottr * to the remote system in keeping these cached indefinitely.
106 1.1 scottr * Unfortunately there is a snag: if the remote system
107 1.1 scottr * reboots, the cached portmapper results will be invalid,
108 1.1 scottr * and we will never detect this since all of the xxx_msg()
109 1.1 scottr * calls return no result - we just fire off a udp packet
110 1.1 scottr * and hope for the best.
111 1.1 scottr *
112 1.1 scottr * We solve this by discarding cached values after two
113 1.1 scottr * minutes, regardless of whether they have been used
114 1.1 scottr * in the meanwhile (since a bad one might have been used
115 1.1 scottr * plenty of times, as the host keeps retrying the request
116 1.1 scottr * and we keep sending the reply back to the wrong port).
117 1.1 scottr *
118 1.1 scottr * Given that the entries will always expire in the order
119 1.1 scottr * that they were created, there is no point in a LRU
120 1.1 scottr * algorithm for when the cache gets full - entries are
121 1.1 scottr * always re-used in sequence.
122 1.1 scottr */
123 1.1 scottr static CLIENT *clnt_cache_ptr[CLIENT_CACHE_SIZE];
124 1.1 scottr static long clnt_cache_time[CLIENT_CACHE_SIZE]; /* time entry created */
125 1.1 scottr static struct in_addr clnt_cache_addr[CLIENT_CACHE_SIZE];
126 1.1 scottr static int clnt_cache_next_to_use = 0;
127 1.1 scottr
128 1.1 scottr static CLIENT *
129 1.1 scottr get_client(host_addr)
130 1.1 scottr struct sockaddr_in *host_addr;
131 1.1 scottr {
132 1.1 scottr CLIENT *client;
133 1.1 scottr struct timeval retry_time, time_now;
134 1.1 scottr int i, sock_no;
135 1.1 scottr
136 1.1 scottr gettimeofday(&time_now, NULL);
137 1.1 scottr
138 1.1 scottr /*
139 1.1 scottr * Search for the given client in the cache, zapping any expired
140 1.1 scottr * entries that we happen to notice in passing.
141 1.1 scottr */
142 1.1 scottr for (i = 0; i < CLIENT_CACHE_SIZE; i++) {
143 1.1 scottr client = clnt_cache_ptr[i];
144 1.1 scottr if (client && ((clnt_cache_time[i] + CLIENT_CACHE_LIFETIME)
145 1.1 scottr < time_now.tv_sec)) {
146 1.1 scottr /* Cache entry has expired. */
147 1.1 scottr if (debug_level > 3)
148 1.1 scottr syslog(LOG_DEBUG, "Expired CLIENT* in cache");
149 1.1 scottr clnt_cache_time[i] = 0L;
150 1.1 scottr clnt_destroy(client);
151 1.1 scottr clnt_cache_ptr[i] = NULL;
152 1.1 scottr client = NULL;
153 1.1 scottr }
154 1.1 scottr if (client && !memcmp(&clnt_cache_addr[i],
155 1.1 scottr &host_addr->sin_addr, sizeof(struct in_addr))) {
156 1.1 scottr /* Found it! */
157 1.1 scottr if (debug_level > 3)
158 1.1 scottr syslog(LOG_DEBUG, "Found CLIENT* in cache");
159 1.1 scottr return (client);
160 1.1 scottr }
161 1.1 scottr }
162 1.1 scottr
163 1.1 scottr /* Not found in cache. Free the next entry if it is in use. */
164 1.1 scottr if (clnt_cache_ptr[clnt_cache_next_to_use]) {
165 1.1 scottr clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]);
166 1.1 scottr clnt_cache_ptr[clnt_cache_next_to_use] = NULL;
167 1.1 scottr }
168 1.1 scottr
169 1.1 scottr /* Create the new client handle */
170 1.1 scottr sock_no = RPC_ANYSOCK;
171 1.1 scottr retry_time.tv_sec = 5;
172 1.1 scottr retry_time.tv_usec = 0;
173 1.1 scottr host_addr->sin_port = 0; /* Force consultation with portmapper */
174 1.1 scottr client = clntudp_create(host_addr, NLM_PROG, NLM_VERS,
175 1.1 scottr retry_time, &sock_no);
176 1.1 scottr if (!client) {
177 1.1 scottr syslog(LOG_ERR, clnt_spcreateerror("clntudp_create"));
178 1.1 scottr syslog(LOG_ERR, "Unable to return result to %s",
179 1.1 scottr inet_ntoa(host_addr->sin_addr));
180 1.1 scottr return NULL;
181 1.1 scottr }
182 1.1 scottr
183 1.1 scottr /* Success - update the cache entry */
184 1.1 scottr clnt_cache_ptr[clnt_cache_next_to_use] = client;
185 1.1 scottr clnt_cache_addr[clnt_cache_next_to_use] = host_addr->sin_addr;
186 1.1 scottr clnt_cache_time[clnt_cache_next_to_use] = time_now.tv_sec;
187 1.1 scottr if (++clnt_cache_next_to_use > CLIENT_CACHE_SIZE)
188 1.1 scottr clnt_cache_next_to_use = 0;
189 1.1 scottr
190 1.1 scottr /*
191 1.1 scottr * Disable the default timeout, so we can specify our own in calls
192 1.1 scottr * to clnt_call(). (Note that the timeout is a different concept
193 1.1 scottr * from the retry period set in clnt_udp_create() above.)
194 1.1 scottr */
195 1.1 scottr retry_time.tv_sec = -1;
196 1.1 scottr retry_time.tv_usec = -1;
197 1.1 scottr clnt_control(client, CLSET_TIMEOUT, (char *)&retry_time);
198 1.1 scottr
199 1.1 scottr if (debug_level > 3)
200 1.1 scottr syslog(LOG_DEBUG, "Created CLIENT* for %s",
201 1.1 scottr inet_ntoa(host_addr->sin_addr));
202 1.1 scottr return client;
203 1.1 scottr }
204 1.1 scottr
205 1.1 scottr
206 1.1 scottr /* transmit_result --------------------------------------------------------- */
207 1.1 scottr /*
208 1.1 scottr * Purpose: Transmit result for nlm_xxx_msg pseudo-RPCs
209 1.1 scottr * Returns: Nothing - we have no idea if the datagram got there
210 1.1 scottr * Notes: clnt_call() will always fail (with timeout) as we are
211 1.1 scottr * calling it with timeout 0 as a hack to just issue a datagram
212 1.1 scottr * without expecting a result
213 1.1 scottr */
214 1.1 scottr static void
215 1.1 scottr transmit_result(opcode, result, req)
216 1.1 scottr int opcode;
217 1.1 scottr nlm_res *result;
218 1.1 scottr struct svc_req *req;
219 1.1 scottr {
220 1.1 scottr static char dummy;
221 1.1 scottr struct sockaddr_in *addr;
222 1.1 scottr CLIENT *cli;
223 1.1 scottr struct timeval timeo;
224 1.1 scottr int success;
225 1.1 scottr
226 1.1 scottr addr = svc_getcaller(req->rq_xprt);
227 1.2 lukem if ((cli = get_client(addr)) != NULL) {
228 1.1 scottr timeo.tv_sec = 0; /* No timeout - not expecting response */
229 1.1 scottr timeo.tv_usec = 0;
230 1.1 scottr
231 1.1 scottr success = clnt_call(cli, opcode, xdr_nlm_res, result, xdr_void,
232 1.1 scottr &dummy, timeo);
233 1.1 scottr
234 1.1 scottr if (debug_level > 2)
235 1.1 scottr syslog(LOG_DEBUG, "clnt_call returns %d\n", success);
236 1.1 scottr }
237 1.1 scottr }
238 1.3 bouyer /* transmit4_result --------------------------------------------------------- */
239 1.3 bouyer /*
240 1.3 bouyer * Purpose: Transmit result for nlm4_xxx_msg pseudo-RPCs
241 1.3 bouyer * Returns: Nothing - we have no idea if the datagram got there
242 1.3 bouyer * Notes: clnt_call() will always fail (with timeout) as we are
243 1.3 bouyer * calling it with timeout 0 as a hack to just issue a datagram
244 1.3 bouyer * without expecting a result
245 1.3 bouyer */
246 1.3 bouyer static void
247 1.3 bouyer transmit4_result(opcode, result, req)
248 1.3 bouyer int opcode;
249 1.3 bouyer nlm4_res *result;
250 1.3 bouyer struct svc_req *req;
251 1.3 bouyer {
252 1.3 bouyer static char dummy;
253 1.3 bouyer struct sockaddr_in *addr;
254 1.3 bouyer CLIENT *cli;
255 1.3 bouyer struct timeval timeo;
256 1.3 bouyer int success;
257 1.3 bouyer
258 1.3 bouyer addr = svc_getcaller(req->rq_xprt);
259 1.3 bouyer if ((cli = get_client(addr)) != NULL) {
260 1.3 bouyer timeo.tv_sec = 0; /* No timeout - not expecting response */
261 1.3 bouyer timeo.tv_usec = 0;
262 1.3 bouyer
263 1.3 bouyer success = clnt_call(cli, opcode, xdr_nlm4_res, result, xdr_void,
264 1.3 bouyer &dummy, timeo);
265 1.3 bouyer
266 1.3 bouyer if (debug_level > 2)
267 1.3 bouyer syslog(LOG_DEBUG, "clnt_call returns %d\n", success);
268 1.3 bouyer }
269 1.3 bouyer }
270 1.1 scottr /* ------------------------------------------------------------------------- */
271 1.1 scottr /*
272 1.1 scottr * Functions for Unix<->Unix locking (ie. monitored locking, with rpc.statd
273 1.1 scottr * involved to ensure reclaim of locks after a crash of the "stateless"
274 1.1 scottr * server.
275 1.1 scottr *
276 1.1 scottr * These all come in two flavours - nlm_xxx() and nlm_xxx_msg().
277 1.1 scottr * The first are standard RPCs with argument and result.
278 1.1 scottr * The nlm_xxx_msg() calls implement exactly the same functions, but
279 1.1 scottr * use two pseudo-RPCs (one in each direction). These calls are NOT
280 1.1 scottr * standard use of the RPC protocol in that they do not return a result
281 1.1 scottr * at all (NB. this is quite different from returning a void result).
282 1.1 scottr * The effect of this is to make the nlm_xxx_msg() calls simple unacknowledged
283 1.1 scottr * datagrams, requiring higher-level code to perform retries.
284 1.1 scottr *
285 1.1 scottr * Despite the disadvantages of the nlm_xxx_msg() approach (some of which
286 1.1 scottr * are documented in the comments to get_client() above), this is the
287 1.1 scottr * interface used by all current commercial NFS implementations
288 1.1 scottr * [Solaris, SCO, AIX etc.]. This is presumed to be because these allow
289 1.1 scottr * implementations to continue using the standard RPC libraries, while
290 1.1 scottr * avoiding the block-until-result nature of the library interface.
291 1.1 scottr *
292 1.1 scottr * No client implementations have been identified so far that make use
293 1.1 scottr * of the true RPC version (early SunOS releases would be a likely candidate
294 1.1 scottr * for testing).
295 1.1 scottr */
296 1.1 scottr
297 1.1 scottr /* nlm_test ---------------------------------------------------------------- */
298 1.1 scottr /*
299 1.1 scottr * Purpose: Test whether a specified lock would be granted if requested
300 1.1 scottr * Returns: nlm_granted (or error code)
301 1.1 scottr * Notes:
302 1.1 scottr */
303 1.1 scottr nlm_testres *
304 1.1 scottr nlm_test_1_svc(arg, rqstp)
305 1.1 scottr nlm_testargs *arg;
306 1.1 scottr struct svc_req *rqstp;
307 1.1 scottr {
308 1.1 scottr static nlm_testres res;
309 1.1 scottr
310 1.1 scottr if (debug_level)
311 1.1 scottr log_from_addr("nlm_test", rqstp);
312 1.1 scottr
313 1.1 scottr /*
314 1.1 scottr * Copy the cookie from the argument into the result. Note that this
315 1.1 scottr * is slightly hazardous, as the structure contains a pointer to a
316 1.1 scottr * malloc()ed buffer that will get freed by the caller. However, the
317 1.1 scottr * main function transmits the result before freeing the argument
318 1.1 scottr * so it is in fact safe.
319 1.1 scottr */
320 1.1 scottr res.cookie = arg->cookie;
321 1.1 scottr res.stat.stat = nlm_granted;
322 1.1 scottr return (&res);
323 1.1 scottr }
324 1.1 scottr
325 1.1 scottr void *
326 1.1 scottr nlm_test_msg_1_svc(arg, rqstp)
327 1.1 scottr nlm_testargs *arg;
328 1.1 scottr struct svc_req *rqstp;
329 1.1 scottr {
330 1.1 scottr nlm_testres res;
331 1.1 scottr static char dummy;
332 1.1 scottr struct sockaddr_in *addr;
333 1.1 scottr CLIENT *cli;
334 1.1 scottr int success;
335 1.1 scottr struct timeval timeo;
336 1.1 scottr
337 1.1 scottr if (debug_level)
338 1.1 scottr log_from_addr("nlm_test_msg", rqstp);
339 1.1 scottr
340 1.1 scottr res.cookie = arg->cookie;
341 1.1 scottr res.stat.stat = nlm_granted;
342 1.1 scottr
343 1.1 scottr /*
344 1.1 scottr * nlm_test has different result type to the other operations, so
345 1.1 scottr * can't use transmit_result() in this case
346 1.1 scottr */
347 1.1 scottr addr = svc_getcaller(rqstp->rq_xprt);
348 1.2 lukem if ((cli = get_client(addr)) != NULL) {
349 1.1 scottr timeo.tv_sec = 0; /* No timeout - not expecting response */
350 1.1 scottr timeo.tv_usec = 0;
351 1.1 scottr
352 1.1 scottr success = clnt_call(cli, NLM_TEST_RES, xdr_nlm_testres,
353 1.1 scottr &res, xdr_void, &dummy, timeo);
354 1.1 scottr
355 1.1 scottr if (debug_level > 2)
356 1.1 scottr syslog(LOG_DEBUG, "clnt_call returns %d\n", success);
357 1.1 scottr }
358 1.1 scottr return (NULL);
359 1.1 scottr }
360 1.1 scottr
361 1.1 scottr /* nlm_lock ---------------------------------------------------------------- */
362 1.1 scottr /*
363 1.1 scottr * Purposes: Establish a lock
364 1.1 scottr * Returns: granted, denied or blocked
365 1.1 scottr * Notes: *** grace period support missing
366 1.1 scottr */
367 1.1 scottr nlm_res *
368 1.1 scottr nlm_lock_1_svc(arg, rqstp)
369 1.1 scottr nlm_lockargs *arg;
370 1.1 scottr struct svc_req *rqstp;
371 1.1 scottr {
372 1.1 scottr static nlm_res res;
373 1.1 scottr
374 1.1 scottr if (debug_level)
375 1.1 scottr log_from_addr("nlm_lock", rqstp);
376 1.1 scottr
377 1.1 scottr /* copy cookie from arg to result. See comment in nlm_test_1() */
378 1.1 scottr res.cookie = arg->cookie;
379 1.1 scottr
380 1.1 scottr res.stat.stat = nlm_granted;
381 1.1 scottr return (&res);
382 1.1 scottr }
383 1.1 scottr
384 1.1 scottr void *
385 1.1 scottr nlm_lock_msg_1_svc(arg, rqstp)
386 1.1 scottr nlm_lockargs *arg;
387 1.1 scottr struct svc_req *rqstp;
388 1.1 scottr {
389 1.1 scottr static nlm_res res;
390 1.1 scottr
391 1.1 scottr if (debug_level)
392 1.1 scottr log_from_addr("nlm_lock_msg", rqstp);
393 1.1 scottr
394 1.1 scottr res.cookie = arg->cookie;
395 1.1 scottr res.stat.stat = nlm_granted;
396 1.1 scottr transmit_result(NLM_LOCK_RES, &res, rqstp);
397 1.1 scottr
398 1.1 scottr return (NULL);
399 1.1 scottr }
400 1.1 scottr
401 1.1 scottr /* nlm_cancel -------------------------------------------------------------- */
402 1.1 scottr /*
403 1.1 scottr * Purpose: Cancel a blocked lock request
404 1.1 scottr * Returns: granted or denied
405 1.1 scottr * Notes:
406 1.1 scottr */
407 1.1 scottr nlm_res *
408 1.1 scottr nlm_cancel_1_svc(arg, rqstp)
409 1.1 scottr nlm_cancargs *arg;
410 1.1 scottr struct svc_req *rqstp;
411 1.1 scottr {
412 1.1 scottr static nlm_res res;
413 1.1 scottr
414 1.1 scottr if (debug_level)
415 1.1 scottr log_from_addr("nlm_cancel", rqstp);
416 1.1 scottr
417 1.1 scottr /* copy cookie from arg to result. See comment in nlm_test_1() */
418 1.1 scottr res.cookie = arg->cookie;
419 1.1 scottr
420 1.1 scottr /*
421 1.1 scottr * Since at present we never return 'nlm_blocked', there can never be
422 1.1 scottr * a lock to cancel, so this call always fails.
423 1.1 scottr */
424 1.1 scottr res.stat.stat = nlm_denied;
425 1.1 scottr return (&res);
426 1.1 scottr }
427 1.1 scottr
428 1.1 scottr void *
429 1.1 scottr nlm_cancel_msg_1_svc(arg, rqstp)
430 1.1 scottr nlm_cancargs *arg;
431 1.1 scottr struct svc_req *rqstp;
432 1.1 scottr {
433 1.1 scottr static nlm_res res;
434 1.1 scottr
435 1.1 scottr if (debug_level)
436 1.1 scottr log_from_addr("nlm_cancel_msg", rqstp);
437 1.1 scottr
438 1.1 scottr res.cookie = arg->cookie;
439 1.1 scottr /*
440 1.1 scottr * Since at present we never return 'nlm_blocked', there can never be
441 1.1 scottr * a lock to cancel, so this call always fails.
442 1.1 scottr */
443 1.1 scottr res.stat.stat = nlm_denied;
444 1.1 scottr transmit_result(NLM_CANCEL_RES, &res, rqstp);
445 1.1 scottr return (NULL);
446 1.1 scottr }
447 1.1 scottr
448 1.1 scottr /* nlm_unlock -------------------------------------------------------------- */
449 1.1 scottr /*
450 1.1 scottr * Purpose: Release an existing lock
451 1.1 scottr * Returns: Always granted, unless during grace period
452 1.1 scottr * Notes: "no such lock" error condition is ignored, as the
453 1.1 scottr * protocol uses unreliable UDP datagrams, and may well
454 1.1 scottr * re-try an unlock that has already succeeded.
455 1.1 scottr */
456 1.1 scottr nlm_res *
457 1.1 scottr nlm_unlock_1_svc(arg, rqstp)
458 1.1 scottr nlm_unlockargs *arg;
459 1.1 scottr struct svc_req *rqstp;
460 1.1 scottr {
461 1.1 scottr static nlm_res res;
462 1.1 scottr
463 1.1 scottr if (debug_level)
464 1.1 scottr log_from_addr("nlm_unlock", rqstp);
465 1.1 scottr
466 1.1 scottr res.stat.stat = nlm_granted;
467 1.1 scottr res.cookie = arg->cookie;
468 1.1 scottr
469 1.1 scottr return (&res);
470 1.1 scottr }
471 1.1 scottr
472 1.1 scottr void *
473 1.1 scottr nlm_unlock_msg_1_svc(arg, rqstp)
474 1.1 scottr nlm_unlockargs *arg;
475 1.1 scottr struct svc_req *rqstp;
476 1.1 scottr {
477 1.1 scottr static nlm_res res;
478 1.1 scottr
479 1.1 scottr if (debug_level)
480 1.1 scottr log_from_addr("nlm_unlock_msg", rqstp);
481 1.1 scottr
482 1.1 scottr res.stat.stat = nlm_granted;
483 1.1 scottr res.cookie = arg->cookie;
484 1.1 scottr
485 1.1 scottr transmit_result(NLM_UNLOCK_RES, &res, rqstp);
486 1.1 scottr return (NULL);
487 1.1 scottr }
488 1.1 scottr
489 1.1 scottr /* ------------------------------------------------------------------------- */
490 1.1 scottr /*
491 1.1 scottr * Client-side pseudo-RPCs for results. Note that for the client there
492 1.1 scottr * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
493 1.1 scottr * version returns the results in the RPC result, and so the client
494 1.1 scottr * does not normally receive incoming RPCs.
495 1.1 scottr *
496 1.1 scottr * The exception to this is nlm_granted(), which is genuinely an RPC
497 1.1 scottr * call from the server to the client - a 'call-back' in normal procedure
498 1.1 scottr * call terms.
499 1.1 scottr */
500 1.1 scottr
501 1.1 scottr /* nlm_granted ------------------------------------------------------------- */
502 1.1 scottr /*
503 1.1 scottr * Purpose: Receive notification that formerly blocked lock now granted
504 1.1 scottr * Returns: always success ('granted')
505 1.1 scottr * Notes:
506 1.1 scottr */
507 1.1 scottr nlm_res *
508 1.1 scottr nlm_granted_1_svc(arg, rqstp)
509 1.1 scottr nlm_testargs *arg;
510 1.1 scottr struct svc_req *rqstp;
511 1.1 scottr {
512 1.1 scottr static nlm_res res;
513 1.1 scottr
514 1.1 scottr if (debug_level)
515 1.1 scottr log_from_addr("nlm_granted", rqstp);
516 1.1 scottr
517 1.1 scottr /* copy cookie from arg to result. See comment in nlm_test_1() */
518 1.1 scottr res.cookie = arg->cookie;
519 1.1 scottr
520 1.1 scottr res.stat.stat = nlm_granted;
521 1.1 scottr return (&res);
522 1.1 scottr }
523 1.1 scottr
524 1.1 scottr void *
525 1.1 scottr nlm_granted_msg_1_svc(arg, rqstp)
526 1.1 scottr nlm_testargs *arg;
527 1.1 scottr struct svc_req *rqstp;
528 1.1 scottr {
529 1.1 scottr static nlm_res res;
530 1.1 scottr
531 1.1 scottr if (debug_level)
532 1.1 scottr log_from_addr("nlm_granted_msg", rqstp);
533 1.1 scottr
534 1.1 scottr res.cookie = arg->cookie;
535 1.1 scottr res.stat.stat = nlm_granted;
536 1.1 scottr transmit_result(NLM_GRANTED_RES, &res, rqstp);
537 1.1 scottr return (NULL);
538 1.1 scottr }
539 1.1 scottr
540 1.1 scottr /* nlm_test_res ------------------------------------------------------------ */
541 1.1 scottr /*
542 1.1 scottr * Purpose: Accept result from earlier nlm_test_msg() call
543 1.1 scottr * Returns: Nothing
544 1.1 scottr */
545 1.1 scottr void *
546 1.1 scottr nlm_test_res_1_svc(arg, rqstp)
547 1.1 scottr nlm_testres *arg;
548 1.1 scottr struct svc_req *rqstp;
549 1.1 scottr {
550 1.1 scottr if (debug_level)
551 1.1 scottr log_from_addr("nlm_test_res", rqstp);
552 1.1 scottr return (NULL);
553 1.1 scottr }
554 1.1 scottr
555 1.1 scottr /* nlm_lock_res ------------------------------------------------------------ */
556 1.1 scottr /*
557 1.1 scottr * Purpose: Accept result from earlier nlm_lock_msg() call
558 1.1 scottr * Returns: Nothing
559 1.1 scottr */
560 1.1 scottr void *
561 1.1 scottr nlm_lock_res_1_svc(arg, rqstp)
562 1.1 scottr nlm_res *arg;
563 1.1 scottr struct svc_req *rqstp;
564 1.1 scottr {
565 1.1 scottr if (debug_level)
566 1.1 scottr log_from_addr("nlm_lock_res", rqstp);
567 1.1 scottr
568 1.1 scottr return (NULL);
569 1.1 scottr }
570 1.1 scottr
571 1.1 scottr /* nlm_cancel_res ---------------------------------------------------------- */
572 1.1 scottr /*
573 1.1 scottr * Purpose: Accept result from earlier nlm_cancel_msg() call
574 1.1 scottr * Returns: Nothing
575 1.1 scottr */
576 1.1 scottr void *
577 1.1 scottr nlm_cancel_res_1_svc(arg, rqstp)
578 1.1 scottr nlm_res *arg;
579 1.1 scottr struct svc_req *rqstp;
580 1.1 scottr {
581 1.1 scottr if (debug_level)
582 1.1 scottr log_from_addr("nlm_cancel_res", rqstp);
583 1.1 scottr return (NULL);
584 1.1 scottr }
585 1.1 scottr
586 1.1 scottr /* nlm_unlock_res ---------------------------------------------------------- */
587 1.1 scottr /*
588 1.1 scottr * Purpose: Accept result from earlier nlm_unlock_msg() call
589 1.1 scottr * Returns: Nothing
590 1.1 scottr */
591 1.1 scottr void *
592 1.1 scottr nlm_unlock_res_1_svc(arg, rqstp)
593 1.1 scottr nlm_res *arg;
594 1.1 scottr struct svc_req *rqstp;
595 1.1 scottr {
596 1.1 scottr if (debug_level)
597 1.1 scottr log_from_addr("nlm_unlock_res", rqstp);
598 1.1 scottr return (NULL);
599 1.1 scottr }
600 1.1 scottr
601 1.1 scottr /* nlm_granted_res --------------------------------------------------------- */
602 1.1 scottr /*
603 1.1 scottr * Purpose: Accept result from earlier nlm_granted_msg() call
604 1.1 scottr * Returns: Nothing
605 1.1 scottr */
606 1.1 scottr void *
607 1.1 scottr nlm_granted_res_1_svc(arg, rqstp)
608 1.1 scottr nlm_res *arg;
609 1.1 scottr struct svc_req *rqstp;
610 1.1 scottr {
611 1.1 scottr if (debug_level)
612 1.1 scottr log_from_addr("nlm_granted_res", rqstp);
613 1.1 scottr return (NULL);
614 1.1 scottr }
615 1.1 scottr
616 1.1 scottr /* ------------------------------------------------------------------------- */
617 1.1 scottr /*
618 1.1 scottr * Calls for PCNFS locking (aka non-monitored locking, no involvement
619 1.1 scottr * of rpc.statd).
620 1.1 scottr *
621 1.1 scottr * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
622 1.1 scottr */
623 1.1 scottr
624 1.1 scottr /* nlm_share --------------------------------------------------------------- */
625 1.1 scottr /*
626 1.1 scottr * Purpose: Establish a DOS-style lock
627 1.1 scottr * Returns: success or failure
628 1.1 scottr * Notes: Blocking locks are not supported - client is expected
629 1.1 scottr * to retry if required.
630 1.1 scottr */
631 1.1 scottr nlm_shareres *
632 1.1 scottr nlm_share_3_svc(arg, rqstp)
633 1.1 scottr nlm_shareargs *arg;
634 1.1 scottr struct svc_req *rqstp;
635 1.1 scottr {
636 1.1 scottr static nlm_shareres res;
637 1.1 scottr
638 1.1 scottr if (debug_level)
639 1.1 scottr log_from_addr("nlm_share", rqstp);
640 1.1 scottr
641 1.1 scottr res.cookie = arg->cookie;
642 1.1 scottr res.stat = nlm_granted;
643 1.1 scottr res.sequence = 1234356; /* X/Open says this field is ignored? */
644 1.1 scottr return (&res);
645 1.1 scottr }
646 1.1 scottr
647 1.1 scottr /* nlm_unshare ------------------------------------------------------------ */
648 1.1 scottr /*
649 1.1 scottr * Purpose: Release a DOS-style lock
650 1.1 scottr * Returns: nlm_granted, unless in grace period
651 1.1 scottr * Notes:
652 1.1 scottr */
653 1.1 scottr nlm_shareres *
654 1.1 scottr nlm_unshare_3_svc(arg, rqstp)
655 1.1 scottr nlm_shareargs *arg;
656 1.1 scottr struct svc_req *rqstp;
657 1.1 scottr {
658 1.1 scottr static nlm_shareres res;
659 1.1 scottr
660 1.1 scottr if (debug_level)
661 1.1 scottr log_from_addr("nlm_unshare", rqstp);
662 1.1 scottr
663 1.1 scottr res.cookie = arg->cookie;
664 1.1 scottr res.stat = nlm_granted;
665 1.1 scottr res.sequence = 1234356; /* X/Open says this field is ignored? */
666 1.1 scottr return (&res);
667 1.1 scottr }
668 1.1 scottr
669 1.1 scottr /* nlm_nm_lock ------------------------------------------------------------ */
670 1.1 scottr /*
671 1.1 scottr * Purpose: non-monitored version of nlm_lock()
672 1.1 scottr * Returns: as for nlm_lock()
673 1.1 scottr * Notes: These locks are in the same style as the standard nlm_lock,
674 1.1 scottr * but the rpc.statd should not be called to establish a
675 1.1 scottr * monitor for the client machine, since that machine is
676 1.1 scottr * declared not to be running a rpc.statd, and so would not
677 1.1 scottr * respond to the statd protocol.
678 1.1 scottr */
679 1.1 scottr nlm_res *
680 1.1 scottr nlm_nm_lock_3_svc(arg, rqstp)
681 1.1 scottr nlm_lockargs *arg;
682 1.1 scottr struct svc_req *rqstp;
683 1.1 scottr {
684 1.1 scottr static nlm_res res;
685 1.1 scottr
686 1.1 scottr if (debug_level)
687 1.1 scottr log_from_addr("nlm_nm_lock", rqstp);
688 1.1 scottr
689 1.1 scottr /* copy cookie from arg to result. See comment in nlm_test_1() */
690 1.1 scottr res.cookie = arg->cookie;
691 1.1 scottr res.stat.stat = nlm_granted;
692 1.1 scottr return (&res);
693 1.1 scottr }
694 1.1 scottr
695 1.1 scottr /* nlm_free_all ------------------------------------------------------------ */
696 1.1 scottr /*
697 1.1 scottr * Purpose: Release all locks held by a named client
698 1.1 scottr * Returns: Nothing
699 1.1 scottr * Notes: Potential denial of service security problem here - the
700 1.1 scottr * locks to be released are specified by a host name, independent
701 1.1 scottr * of the address from which the request has arrived.
702 1.1 scottr * Should probably be rejected if the named host has been
703 1.1 scottr * using monitored locks.
704 1.1 scottr */
705 1.1 scottr void *
706 1.1 scottr nlm_free_all_3_svc(arg, rqstp)
707 1.1 scottr nlm_notify *arg;
708 1.1 scottr struct svc_req *rqstp;
709 1.1 scottr {
710 1.1 scottr static char dummy;
711 1.1 scottr
712 1.1 scottr if (debug_level)
713 1.1 scottr log_from_addr("nlm_free_all", rqstp);
714 1.1 scottr return (&dummy);
715 1.1 scottr }
716 1.3 bouyer
717 1.3 bouyer /* calls for nlm version 4 (NFSv3) */
718 1.3 bouyer /* nlm_test ---------------------------------------------------------------- */
719 1.3 bouyer /*
720 1.3 bouyer * Purpose: Test whether a specified lock would be granted if requested
721 1.3 bouyer * Returns: nlm_granted (or error code)
722 1.3 bouyer * Notes:
723 1.3 bouyer */
724 1.3 bouyer nlm4_testres *
725 1.3 bouyer nlm4_test_4_svc(arg, rqstp)
726 1.3 bouyer nlm4_testargs *arg;
727 1.3 bouyer struct svc_req *rqstp;
728 1.3 bouyer {
729 1.3 bouyer static nlm4_testres res;
730 1.3 bouyer
731 1.3 bouyer if (debug_level)
732 1.3 bouyer log_from_addr("nlm4_test", rqstp);
733 1.3 bouyer
734 1.3 bouyer /*
735 1.3 bouyer * Copy the cookie from the argument into the result. Note that this
736 1.3 bouyer * is slightly hazardous, as the structure contains a pointer to a
737 1.3 bouyer * malloc()ed buffer that will get freed by the caller. However, the
738 1.3 bouyer * main function transmits the result before freeing the argument
739 1.3 bouyer * so it is in fact safe.
740 1.3 bouyer */
741 1.3 bouyer res.cookie = arg->cookie;
742 1.3 bouyer res.stat.stat = nlm4_granted;
743 1.3 bouyer return (&res);
744 1.3 bouyer }
745 1.3 bouyer
746 1.3 bouyer void *
747 1.3 bouyer nlm4_test_msg_4_svc(arg, rqstp)
748 1.3 bouyer nlm4_testargs *arg;
749 1.3 bouyer struct svc_req *rqstp;
750 1.3 bouyer {
751 1.3 bouyer nlm4_testres res;
752 1.3 bouyer static char dummy;
753 1.3 bouyer struct sockaddr_in *addr;
754 1.3 bouyer CLIENT *cli;
755 1.3 bouyer int success;
756 1.3 bouyer struct timeval timeo;
757 1.3 bouyer
758 1.3 bouyer if (debug_level)
759 1.3 bouyer log_from_addr("nlm4_test_msg", rqstp);
760 1.3 bouyer
761 1.3 bouyer res.cookie = arg->cookie;
762 1.3 bouyer res.stat.stat = nlm4_granted;
763 1.3 bouyer
764 1.3 bouyer /*
765 1.3 bouyer * nlm_test has different result type to the other operations, so
766 1.3 bouyer * can't use transmit4_result() in this case
767 1.3 bouyer */
768 1.3 bouyer addr = svc_getcaller(rqstp->rq_xprt);
769 1.3 bouyer if ((cli = get_client(addr)) != NULL) {
770 1.3 bouyer timeo.tv_sec = 0; /* No timeout - not expecting response */
771 1.3 bouyer timeo.tv_usec = 0;
772 1.3 bouyer
773 1.3 bouyer success = clnt_call(cli, NLM4_TEST_RES, xdr_nlm4_testres,
774 1.3 bouyer &res, xdr_void, &dummy, timeo);
775 1.3 bouyer
776 1.3 bouyer if (debug_level > 2)
777 1.3 bouyer syslog(LOG_DEBUG, "clnt_call returns %d\n", success);
778 1.3 bouyer }
779 1.3 bouyer return (NULL);
780 1.3 bouyer }
781 1.3 bouyer
782 1.3 bouyer /* nlm_lock ---------------------------------------------------------------- */
783 1.3 bouyer /*
784 1.3 bouyer * Purposes: Establish a lock
785 1.3 bouyer * Returns: granted, denied or blocked
786 1.3 bouyer * Notes: *** grace period support missing
787 1.3 bouyer */
788 1.3 bouyer nlm4_res *
789 1.3 bouyer nlm4_lock_4_svc(arg, rqstp)
790 1.3 bouyer nlm4_lockargs *arg;
791 1.3 bouyer struct svc_req *rqstp;
792 1.3 bouyer {
793 1.3 bouyer static nlm4_res res;
794 1.3 bouyer
795 1.3 bouyer if (debug_level)
796 1.3 bouyer log_from_addr("nlm4_lock", rqstp);
797 1.3 bouyer
798 1.3 bouyer /* copy cookie from arg to result. See comment in nlm_test_4() */
799 1.3 bouyer res.cookie = arg->cookie;
800 1.3 bouyer
801 1.3 bouyer res.stat.stat = nlm4_granted;
802 1.3 bouyer return (&res);
803 1.3 bouyer }
804 1.3 bouyer
805 1.3 bouyer void *
806 1.3 bouyer nlm4_lock_msg_4_svc(arg, rqstp)
807 1.3 bouyer nlm4_lockargs *arg;
808 1.3 bouyer struct svc_req *rqstp;
809 1.3 bouyer {
810 1.3 bouyer static nlm4_res res;
811 1.3 bouyer
812 1.3 bouyer if (debug_level)
813 1.3 bouyer log_from_addr("nlm4_lock_msg", rqstp);
814 1.3 bouyer
815 1.3 bouyer res.cookie = arg->cookie;
816 1.3 bouyer res.stat.stat = nlm4_granted;
817 1.3 bouyer transmit4_result(NLM4_LOCK_RES, &res, rqstp);
818 1.3 bouyer
819 1.3 bouyer return (NULL);
820 1.3 bouyer }
821 1.3 bouyer
822 1.3 bouyer /* nlm_cancel -------------------------------------------------------------- */
823 1.3 bouyer /*
824 1.3 bouyer * Purpose: Cancel a blocked lock request
825 1.3 bouyer * Returns: granted or denied
826 1.3 bouyer * Notes:
827 1.3 bouyer */
828 1.3 bouyer nlm4_res *
829 1.3 bouyer nlm4_cancel_4_svc(arg, rqstp)
830 1.3 bouyer nlm4_cancargs *arg;
831 1.3 bouyer struct svc_req *rqstp;
832 1.3 bouyer {
833 1.3 bouyer static nlm4_res res;
834 1.3 bouyer
835 1.3 bouyer if (debug_level)
836 1.3 bouyer log_from_addr("nlm4_cancel", rqstp);
837 1.3 bouyer
838 1.3 bouyer /* copy cookie from arg to result. See comment in nlm_test_1() */
839 1.3 bouyer res.cookie = arg->cookie;
840 1.3 bouyer
841 1.3 bouyer /*
842 1.3 bouyer * Since at present we never return 'nlm_blocked', there can never be
843 1.3 bouyer * a lock to cancel, so this call always fails.
844 1.3 bouyer */
845 1.3 bouyer res.stat.stat = nlm4_denied;
846 1.3 bouyer return (&res);
847 1.3 bouyer }
848 1.3 bouyer
849 1.3 bouyer void *
850 1.3 bouyer nlm4_cancel_msg_4_svc(arg, rqstp)
851 1.3 bouyer nlm4_cancargs *arg;
852 1.3 bouyer struct svc_req *rqstp;
853 1.3 bouyer {
854 1.3 bouyer static nlm4_res res;
855 1.3 bouyer
856 1.3 bouyer if (debug_level)
857 1.3 bouyer log_from_addr("nlm4_cancel_msg", rqstp);
858 1.3 bouyer
859 1.3 bouyer res.cookie = arg->cookie;
860 1.3 bouyer /*
861 1.3 bouyer * Since at present we never return 'nlm_blocked', there can never be
862 1.3 bouyer * a lock to cancel, so this call always fails.
863 1.3 bouyer */
864 1.3 bouyer res.stat.stat = nlm4_denied;
865 1.3 bouyer transmit4_result(NLM4_CANCEL_RES, &res, rqstp);
866 1.3 bouyer return (NULL);
867 1.3 bouyer }
868 1.3 bouyer
869 1.3 bouyer /* nlm_unlock -------------------------------------------------------------- */
870 1.3 bouyer /*
871 1.3 bouyer * Purpose: Release an existing lock
872 1.3 bouyer * Returns: Always granted, unless during grace period
873 1.3 bouyer * Notes: "no such lock" error condition is ignored, as the
874 1.3 bouyer * protocol uses unreliable UDP datagrams, and may well
875 1.3 bouyer * re-try an unlock that has already succeeded.
876 1.3 bouyer */
877 1.3 bouyer nlm4_res *
878 1.3 bouyer nlm4_unlock_4_svc(arg, rqstp)
879 1.3 bouyer nlm4_unlockargs *arg;
880 1.3 bouyer struct svc_req *rqstp;
881 1.3 bouyer {
882 1.3 bouyer static nlm4_res res;
883 1.3 bouyer
884 1.3 bouyer if (debug_level)
885 1.3 bouyer log_from_addr("nlm4_unlock", rqstp);
886 1.3 bouyer
887 1.3 bouyer res.stat.stat = nlm4_granted;
888 1.3 bouyer res.cookie = arg->cookie;
889 1.3 bouyer
890 1.3 bouyer return (&res);
891 1.3 bouyer }
892 1.3 bouyer
893 1.3 bouyer void *
894 1.3 bouyer nlm4_unlock_msg_4_svc(arg, rqstp)
895 1.3 bouyer nlm4_unlockargs *arg;
896 1.3 bouyer struct svc_req *rqstp;
897 1.3 bouyer {
898 1.3 bouyer static nlm4_res res;
899 1.3 bouyer
900 1.3 bouyer if (debug_level)
901 1.3 bouyer log_from_addr("nlm4_unlock_msg", rqstp);
902 1.3 bouyer
903 1.3 bouyer res.stat.stat = nlm4_granted;
904 1.3 bouyer res.cookie = arg->cookie;
905 1.3 bouyer
906 1.3 bouyer transmit4_result(NLM4_UNLOCK_RES, &res, rqstp);
907 1.3 bouyer return (NULL);
908 1.3 bouyer }
909 1.3 bouyer
910 1.3 bouyer /* ------------------------------------------------------------------------- */
911 1.3 bouyer /*
912 1.3 bouyer * Client-side pseudo-RPCs for results. Note that for the client there
913 1.3 bouyer * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
914 1.3 bouyer * version returns the results in the RPC result, and so the client
915 1.3 bouyer * does not normally receive incoming RPCs.
916 1.3 bouyer *
917 1.3 bouyer * The exception to this is nlm_granted(), which is genuinely an RPC
918 1.3 bouyer * call from the server to the client - a 'call-back' in normal procedure
919 1.3 bouyer * call terms.
920 1.3 bouyer */
921 1.3 bouyer
922 1.3 bouyer /* nlm_granted ------------------------------------------------------------- */
923 1.3 bouyer /*
924 1.3 bouyer * Purpose: Receive notification that formerly blocked lock now granted
925 1.3 bouyer * Returns: always success ('granted')
926 1.3 bouyer * Notes:
927 1.3 bouyer */
928 1.3 bouyer nlm4_res *
929 1.3 bouyer nlm4_granted_4_svc(arg, rqstp)
930 1.3 bouyer nlm4_testargs *arg;
931 1.3 bouyer struct svc_req *rqstp;
932 1.3 bouyer {
933 1.3 bouyer static nlm4_res res;
934 1.3 bouyer
935 1.3 bouyer if (debug_level)
936 1.3 bouyer log_from_addr("nlm4_granted", rqstp);
937 1.3 bouyer
938 1.3 bouyer /* copy cookie from arg to result. See comment in nlm_test_1() */
939 1.3 bouyer res.cookie = arg->cookie;
940 1.3 bouyer
941 1.3 bouyer res.stat.stat = nlm4_granted;
942 1.3 bouyer return (&res);
943 1.3 bouyer }
944 1.3 bouyer
945 1.3 bouyer void *
946 1.3 bouyer nlm4_granted_msg_4_svc(arg, rqstp)
947 1.3 bouyer nlm4_testargs *arg;
948 1.3 bouyer struct svc_req *rqstp;
949 1.3 bouyer {
950 1.3 bouyer static nlm4_res res;
951 1.3 bouyer
952 1.3 bouyer if (debug_level)
953 1.3 bouyer log_from_addr("nlm4_granted_msg", rqstp);
954 1.3 bouyer
955 1.3 bouyer res.cookie = arg->cookie;
956 1.3 bouyer res.stat.stat = nlm4_granted;
957 1.3 bouyer transmit4_result(NLM4_GRANTED_RES, &res, rqstp);
958 1.3 bouyer return (NULL);
959 1.3 bouyer }
960 1.3 bouyer
961 1.3 bouyer /* nlm_test_res ------------------------------------------------------------ */
962 1.3 bouyer /*
963 1.3 bouyer * Purpose: Accept result from earlier nlm_test_msg() call
964 1.3 bouyer * Returns: Nothing
965 1.3 bouyer */
966 1.3 bouyer void *
967 1.3 bouyer nlm4_test_res_4_svc(arg, rqstp)
968 1.3 bouyer nlm4_testres *arg;
969 1.3 bouyer struct svc_req *rqstp;
970 1.3 bouyer {
971 1.3 bouyer if (debug_level)
972 1.3 bouyer log_from_addr("nlm4_test_res", rqstp);
973 1.3 bouyer return (NULL);
974 1.3 bouyer }
975 1.3 bouyer
976 1.3 bouyer /* nlm_lock_res ------------------------------------------------------------ */
977 1.3 bouyer /*
978 1.3 bouyer * Purpose: Accept result from earlier nlm_lock_msg() call
979 1.3 bouyer * Returns: Nothing
980 1.3 bouyer */
981 1.3 bouyer void *
982 1.3 bouyer nlm4_lock_res_4_svc(arg, rqstp)
983 1.3 bouyer nlm4_res *arg;
984 1.3 bouyer struct svc_req *rqstp;
985 1.3 bouyer {
986 1.3 bouyer if (debug_level)
987 1.3 bouyer log_from_addr("nlm4_lock_res", rqstp);
988 1.3 bouyer
989 1.3 bouyer return (NULL);
990 1.3 bouyer }
991 1.3 bouyer
992 1.3 bouyer /* nlm_cancel_res ---------------------------------------------------------- */
993 1.3 bouyer /*
994 1.3 bouyer * Purpose: Accept result from earlier nlm_cancel_msg() call
995 1.3 bouyer * Returns: Nothing
996 1.3 bouyer */
997 1.3 bouyer void *
998 1.3 bouyer nlm4_cancel_res_4_svc(arg, rqstp)
999 1.3 bouyer nlm4_res *arg;
1000 1.3 bouyer struct svc_req *rqstp;
1001 1.3 bouyer {
1002 1.3 bouyer if (debug_level)
1003 1.3 bouyer log_from_addr("nlm4_cancel_res", rqstp);
1004 1.3 bouyer return (NULL);
1005 1.3 bouyer }
1006 1.3 bouyer
1007 1.3 bouyer /* nlm_unlock_res ---------------------------------------------------------- */
1008 1.3 bouyer /*
1009 1.3 bouyer * Purpose: Accept result from earlier nlm_unlock_msg() call
1010 1.3 bouyer * Returns: Nothing
1011 1.3 bouyer */
1012 1.3 bouyer void *
1013 1.3 bouyer nlm4_unlock_res_4_svc(arg, rqstp)
1014 1.3 bouyer nlm4_res *arg;
1015 1.3 bouyer struct svc_req *rqstp;
1016 1.3 bouyer {
1017 1.3 bouyer if (debug_level)
1018 1.3 bouyer log_from_addr("nlm4_unlock_res", rqstp);
1019 1.3 bouyer return (NULL);
1020 1.3 bouyer }
1021 1.3 bouyer
1022 1.3 bouyer /* nlm_granted_res --------------------------------------------------------- */
1023 1.3 bouyer /*
1024 1.3 bouyer * Purpose: Accept result from earlier nlm_granted_msg() call
1025 1.3 bouyer * Returns: Nothing
1026 1.3 bouyer */
1027 1.3 bouyer void *
1028 1.3 bouyer nlm4_granted_res_4_svc(arg, rqstp)
1029 1.3 bouyer nlm4_res *arg;
1030 1.3 bouyer struct svc_req *rqstp;
1031 1.3 bouyer {
1032 1.3 bouyer if (debug_level)
1033 1.3 bouyer log_from_addr("nlm4_granted_res", rqstp);
1034 1.3 bouyer return (NULL);
1035 1.3 bouyer }
1036 1.3 bouyer
1037 1.3 bouyer /* nlm4_null --------------------------------------------------------- */
1038 1.3 bouyer /*
1039 1.3 bouyer * Purpose: Allows to test server response and timing
1040 1.3 bouyer * Returns: Nothing
1041 1.3 bouyer */
1042 1.3 bouyer void *
1043 1.3 bouyer nlm4_null_4_svc(arg, rqstp)
1044 1.3 bouyer void *arg;
1045 1.3 bouyer struct svc_req *rqstp;
1046 1.3 bouyer {
1047 1.3 bouyer if (debug_level)
1048 1.3 bouyer log_from_addr("nlm4_null", rqstp);
1049 1.3 bouyer return (NULL);
1050 1.3 bouyer }
1051 1.3 bouyer /* ------------------------------------------------------------------------- */
1052 1.3 bouyer /*
1053 1.3 bouyer * Calls for PCNFS locking (aka non-monitored locking, no involvement
1054 1.3 bouyer * of rpc.statd).
1055 1.3 bouyer *
1056 1.3 bouyer * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
1057 1.3 bouyer */
1058 1.3 bouyer
1059 1.3 bouyer /* nlm_share --------------------------------------------------------------- */
1060 1.3 bouyer /*
1061 1.3 bouyer * Purpose: Establish a DOS-style lock
1062 1.3 bouyer * Returns: success or failure
1063 1.3 bouyer * Notes: Blocking locks are not supported - client is expected
1064 1.3 bouyer * to retry if required.
1065 1.3 bouyer */
1066 1.3 bouyer nlm4_shareres *
1067 1.3 bouyer nlm4_share_4_svc(arg, rqstp)
1068 1.3 bouyer nlm4_shareargs *arg;
1069 1.3 bouyer struct svc_req *rqstp;
1070 1.3 bouyer {
1071 1.3 bouyer static nlm4_shareres res;
1072 1.3 bouyer
1073 1.3 bouyer if (debug_level)
1074 1.3 bouyer log_from_addr("nlm4_share", rqstp);
1075 1.3 bouyer
1076 1.3 bouyer res.cookie = arg->cookie;
1077 1.3 bouyer res.stat = nlm4_granted;
1078 1.3 bouyer res.sequence = 1234356; /* X/Open says this field is ignored? */
1079 1.3 bouyer return (&res);
1080 1.3 bouyer }
1081 1.3 bouyer
1082 1.3 bouyer /* nlm4_unshare ------------------------------------------------------------ */
1083 1.3 bouyer /*
1084 1.3 bouyer * Purpose: Release a DOS-style lock
1085 1.3 bouyer * Returns: nlm_granted, unless in grace period
1086 1.3 bouyer * Notes:
1087 1.3 bouyer */
1088 1.3 bouyer nlm4_shareres *
1089 1.3 bouyer nlm4_unshare_4_svc(arg, rqstp)
1090 1.3 bouyer nlm4_shareargs *arg;
1091 1.3 bouyer struct svc_req *rqstp;
1092 1.3 bouyer {
1093 1.3 bouyer static nlm4_shareres res;
1094 1.3 bouyer
1095 1.3 bouyer if (debug_level)
1096 1.3 bouyer log_from_addr("nlm_unshare", rqstp);
1097 1.3 bouyer
1098 1.3 bouyer res.cookie = arg->cookie;
1099 1.3 bouyer res.stat = nlm4_granted;
1100 1.3 bouyer res.sequence = 1234356; /* X/Open says this field is ignored? */
1101 1.3 bouyer return (&res);
1102 1.3 bouyer }
1103 1.3 bouyer
1104 1.3 bouyer /* nlm4_nm_lock ------------------------------------------------------------ */
1105 1.3 bouyer /*
1106 1.3 bouyer * Purpose: non-monitored version of nlm4_lock()
1107 1.3 bouyer * Returns: as for nlm4_lock()
1108 1.3 bouyer * Notes: These locks are in the same style as the standard nlm4_lock,
1109 1.3 bouyer * but the rpc.statd should not be called to establish a
1110 1.3 bouyer * monitor for the client machine, since that machine is
1111 1.3 bouyer * declared not to be running a rpc.statd, and so would not
1112 1.3 bouyer * respond to the statd protocol.
1113 1.3 bouyer */
1114 1.3 bouyer nlm4_res *
1115 1.3 bouyer nlm4_nm_lock_4_svc(arg, rqstp)
1116 1.3 bouyer nlm4_lockargs *arg;
1117 1.3 bouyer struct svc_req *rqstp;
1118 1.3 bouyer {
1119 1.3 bouyer static nlm4_res res;
1120 1.3 bouyer
1121 1.3 bouyer if (debug_level)
1122 1.3 bouyer log_from_addr("nlm4_nm_lock", rqstp);
1123 1.3 bouyer
1124 1.3 bouyer /* copy cookie from arg to result. See comment in nlm4_test_1() */
1125 1.3 bouyer res.cookie = arg->cookie;
1126 1.3 bouyer res.stat.stat = nlm4_granted;
1127 1.3 bouyer return (&res);
1128 1.3 bouyer }
1129 1.3 bouyer
1130 1.3 bouyer /* nlm4_free_all ------------------------------------------------------------ */
1131 1.3 bouyer /*
1132 1.3 bouyer * Purpose: Release all locks held by a named client
1133 1.3 bouyer * Returns: Nothing
1134 1.3 bouyer * Notes: Potential denial of service security problem here - the
1135 1.3 bouyer * locks to be released are specified by a host name, independent
1136 1.3 bouyer * of the address from which the request has arrived.
1137 1.3 bouyer * Should probably be rejected if the named host has been
1138 1.3 bouyer * using monitored locks.
1139 1.3 bouyer */
1140 1.3 bouyer void *
1141 1.3 bouyer nlm4_free_all_4_svc(arg, rqstp)
1142 1.3 bouyer nlm_notify *arg;
1143 1.3 bouyer struct svc_req *rqstp;
1144 1.3 bouyer {
1145 1.3 bouyer static char dummy;
1146 1.3 bouyer
1147 1.3 bouyer if (debug_level)
1148 1.3 bouyer log_from_addr("nlm4_free_all", rqstp);
1149 1.3 bouyer return (&dummy);
1150 1.3 bouyer }
1151 1.3 bouyer
1152