1 /*
2 * This file and its contents are supplied under the terms of the
3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 * You may only use this file in accordance with the terms of version
5 * 1.0 of the CDDL.
6 *
7 * A full copy of the text of the CDDL should have accompanied this
8 * source. A copy is of the CDDL is also available via the Internet
9 * at http://www.illumos.org/license/CDDL.
10 */
11
12 /*
13 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
14 */
15
16 /*
17 * NFS Lock Manager, server-side dispatch tables and
18 * dispatch programs: nlm_prog_3, nlm_prog4
19 *
20 * These are called by RPC framework after the RPC service
21 * endpoints setup done in nlm_impl.c: nlm_svc_add_ep().
22 *
23 * Originally from rpcgen, then reduced.
24 */
25
26 #include <sys/param.h>
27 #include <sys/systm.h>
28 #include <sys/sdt.h>
29 #include <rpcsvc/nlm_prot.h>
30 #include "nlm_impl.h"
31
32 /*
33 * Dispatch entry function pointers.
34 */
35 typedef bool_t (*nlm_svc_func_t)(void *, void *, struct svc_req *);
36 typedef void (*nlm_freeres_func_t)(void *);
37
38 /*
39 * Entries in the dispatch tables below.
40 */
41 struct dispatch_entry {
42 nlm_svc_func_t de_svc; /* service routine function */
43 xdrproc_t de_xargs; /* XDR args decode function */
44 xdrproc_t de_xres; /* XDR res encode function */
45 nlm_freeres_func_t de_resfree; /* free res function */
46 int de_ressz; /* size of result */
47 uint_t de_flags; /* flags */
48 };
49
50 /* Flag bits in de_flags */
51 #define NLM_DISP_NOREMOTE 1 /* Local calls only */
52
53 /*
54 * Cast macros for dispatch table function pointers.
55 */
56 #define NLM_SVC_FUNC(func) (nlm_svc_func_t)func
57 #define NLM_FREERES_FUNC(func) (nlm_freeres_func_t)func
58
59 /* ARGSUSED */
60 static bool_t
nlm_null_svc(void * args,void * resp,struct svc_req * sr)61 nlm_null_svc(void *args, void *resp, struct svc_req *sr)
62 {
63 return (TRUE);
64 }
65
66 /*
67 * The common NLM service dispatch function, used by
68 * both: nlm_prog_3, nlm_prog_4
69 */
70 void
nlm_dispatch(struct svc_req * rqstp,SVCXPRT * transp,const struct dispatch_entry * de)71 nlm_dispatch(
72 struct svc_req *rqstp,
73 SVCXPRT *transp,
74 const struct dispatch_entry *de)
75 {
76 union {
77 /* All the arg types */
78 nlm_cancargs au_cancargs;
79 nlm_lockargs au_lockargs;
80 nlm_notify au_notify;
81 nlm_res au_res;
82 nlm_shareargs au_shareargs;
83 nlm_sm_status au_sm_status;
84 nlm_testargs au_testargs;
85 nlm_testres au_testres;
86 nlm_unlockargs au_unlockargs;
87 nlm4_cancargs au_cancargs4;
88 nlm4_lockargs au_lockargs4;
89 nlm4_notify au_notify4;
90 nlm4_res au_res4;
91 nlm4_shareargs au_shareargs4;
92 nlm4_testargs au_testargs4;
93 nlm4_testres au_testres4;
94 nlm4_unlockargs au_unlockargs4;
95 } argu;
96 void *args = &argu;
97 union {
98 /* All the ret types */
99 int ru_int;
100 nlm_res ru_res;
101 nlm_shareres ru_shareres;
102 nlm_testres ru_testres;
103 nlm4_res ru_res4;
104 nlm4_shareres ru_shareres4;
105 nlm4_testres ru_testres4;
106
107 } resu;
108 void *res = &resu;
109 nlm_svc_func_t func;
110 bool_t do_reply = FALSE;
111 bool_t dupcached = FALSE;
112 struct dupreq *dr;
113 int dupstat;
114
115 if ((func = de->de_svc) == NULL) {
116 svcerr_noproc(transp);
117 return;
118 }
119
120 if ((de->de_flags & NLM_DISP_NOREMOTE) &&
121 !nlm_caller_is_local(transp)) {
122 svcerr_noproc(transp);
123 return;
124 }
125
126 /*
127 * This section from rpcgen, and then modified slightly.
128 *
129 * Dispatch entries that should _never_ send a response
130 * (i.e. all the _MSG and _RES entries) put NULL in the
131 * de_xres field to indicate that. For such entries, we
132 * will NOT call svc_sendreply nor xdr_free(). Normal
133 * dispatch entries skip svc_sendreply if the dispatch
134 * function returns zero, but always call xdr_free().
135 *
136 * There are more complex cases where some dispatch
137 * functions need to send their own reply. We chose
138 * to indicate those by returning false from the
139 * service routine.
140 */
141 bzero(&argu, sizeof (argu));
142 if (!SVC_GETARGS(transp, de->de_xargs, args)) {
143 svcerr_decode(transp);
144 return;
145 }
146
147 /*
148 * Duplicate request cache.
149 *
150 * Since none of the NLM replies are very large we have simplified the
151 * DRC by not distinguishing between idempotent and non-idempotent
152 * requests.
153 */
154 dupstat = SVC_DUP_EXT(transp, rqstp, res, de->de_ressz, &dr,
155 &dupcached);
156
157 switch (dupstat) {
158 case DUP_ERROR:
159 svcerr_systemerr(transp);
160 break;
161 case DUP_INPROGRESS:
162 break;
163 case DUP_NEW:
164 case DUP_DROP:
165 /*
166 * When UFS is quiescing it uses lockfs to block vnode
167 * operations until it has finished quiescing. Set the
168 * thread's T_DONTPEND flag to prevent the service routine
169 * from blocking due to a lockfs lock. (See ufs_check_lockfs)
170 */
171 curthread->t_flag |= T_DONTPEND;
172
173 bzero(&resu, sizeof (resu));
174 do_reply = (*func)(args, res, rqstp);
175
176 curthread->t_flag &= ~T_DONTPEND;
177 if (curthread->t_flag & T_WOULDBLOCK) {
178 curthread->t_flag &= ~T_WOULDBLOCK;
179 SVC_DUPDONE_EXT(transp, dr, res, NULL,
180 de->de_ressz, DUP_DROP);
181 do_reply = FALSE;
182 break;
183 }
184 SVC_DUPDONE_EXT(transp, dr, res, de->de_resfree,
185 de->de_ressz, DUP_DONE);
186 dupcached = TRUE;
187 break;
188 case DUP_DONE:
189 /*
190 * The service routine may have been responsible for sending
191 * the reply for the original request but for a re-xmitted
192 * request we don't invoke the service routine so we must
193 * re-xmit the reply from the dispatch function.
194 *
195 * If de_xres is NULL this is a one-way message so no reply is
196 * needed.
197 */
198 if (de->de_xres != NULL_xdrproc_t) {
199 do_reply = TRUE;
200 }
201 break;
202 }
203
204 if (do_reply) {
205 ASSERT(de->de_xres != NULL_xdrproc_t);
206 DTRACE_PROBE3(sendreply, struct svc_req *, rqstp,
207 SVCXPRT *, transp, struct dispatch_entry *, de);
208
209 if (!svc_sendreply(transp, de->de_xres, res)) {
210 svcerr_systemerr(transp);
211 NLM_ERR("nlm_dispatch(): svc_sendreply() failed!\n");
212 }
213
214 if (!dupcached) {
215 xdr_free(de->de_xres, res);
216 }
217 }
218
219 if (!SVC_FREEARGS(transp, de->de_xargs, args))
220 NLM_WARN("nlm_dispatch(): unable to free arguments");
221 }
222
223 /*
224 * Result free functions. The functions are called by the RPC duplicate
225 * request cache code when an entry is being evicted from the cache.
226 */
227 static void
nlm_res_free(nlm_res * resp)228 nlm_res_free(nlm_res *resp)
229 {
230 xdr_free(xdr_nlm_res, (char *)resp);
231 }
232
233 static void
nlm_shareres_free(nlm_shareres * resp)234 nlm_shareres_free(nlm_shareres *resp)
235 {
236 xdr_free(xdr_nlm_shareres, (char *)resp);
237 }
238
239 static void
nlm_testres_free(nlm_testres * resp)240 nlm_testres_free(nlm_testres *resp)
241 {
242 xdr_free(xdr_nlm_testres, (char *)resp);
243 }
244
245 static void
nlm4_res_free(nlm4_res * resp)246 nlm4_res_free(nlm4_res *resp)
247 {
248 xdr_free(xdr_nlm4_res, (char *)resp);
249 }
250
251 static void
nlm4_shareres_free(nlm4_shareres * resp)252 nlm4_shareres_free(nlm4_shareres *resp)
253 {
254 xdr_free(xdr_nlm4_shareres, (char *)resp);
255 }
256
257 static void
nlm4_testres_free(nlm4_testres * resp)258 nlm4_testres_free(nlm4_testres *resp)
259 {
260 xdr_free(xdr_nlm4_testres, (char *)resp);
261 }
262
263 /*
264 * Dispatch tables for each program version.
265 *
266 * The tables here were all originally from rpcgen,
267 * but then arg/resp sizes removed, flags added.
268 */
269
270 /*
271 * Dispatch table for versions 1, 2, 3
272 * (NLM_VERS, NLM_SM, NLM_VERSX)
273 */
274 static const struct dispatch_entry
275 nlm_prog_3_dtable[] = {
276
277 /*
278 * Version 1 (NLM_VERS) entries.
279 */
280
281 { /* 0: NULLPROC */
282 NLM_SVC_FUNC(nlm_null_svc),
283 (xdrproc_t)xdr_void,
284 (xdrproc_t)xdr_void,
285 NULL,
286 0,
287 0 },
288
289 { /* 1: NLM_TEST */
290 NLM_SVC_FUNC(nlm_test_1_svc),
291 (xdrproc_t)xdr_nlm_testargs,
292 (xdrproc_t)xdr_nlm_testres,
293 NLM_FREERES_FUNC(nlm_testres_free),
294 sizeof (nlm_testres),
295 0 },
296
297 { /* 2: NLM_LOCK */
298 NLM_SVC_FUNC(nlm_lock_1_svc),
299 (xdrproc_t)xdr_nlm_lockargs,
300 (xdrproc_t)xdr_nlm_res,
301 NLM_FREERES_FUNC(nlm_res_free),
302 sizeof (nlm_res),
303 0 },
304
305 { /* 3: NLM_CANCEL */
306 NLM_SVC_FUNC(nlm_cancel_1_svc),
307 (xdrproc_t)xdr_nlm_cancargs,
308 (xdrproc_t)xdr_nlm_res,
309 NLM_FREERES_FUNC(nlm_res_free),
310 sizeof (nlm_res),
311 0 },
312
313 { /* 4: NLM_UNLOCK */
314 NLM_SVC_FUNC(nlm_unlock_1_svc),
315 (xdrproc_t)xdr_nlm_unlockargs,
316 (xdrproc_t)xdr_nlm_res,
317 NLM_FREERES_FUNC(nlm_res_free),
318 sizeof (nlm_res),
319 0 },
320
321 { /* 5: NLM_GRANTED */
322 NLM_SVC_FUNC(nlm_granted_1_svc),
323 (xdrproc_t)xdr_nlm_testargs,
324 (xdrproc_t)xdr_nlm_res,
325 NLM_FREERES_FUNC(nlm_res_free),
326 sizeof (nlm_res),
327 0 },
328
329 /*
330 * All the _MSG and _RES entries are "one way" calls that
331 * skip the usual RPC reply. We give them a null xdr_res
332 * function so the dispatcher will not send a reply.
333 */
334
335 { /* 6: NLM_TEST_MSG */
336 NLM_SVC_FUNC(nlm_test_msg_1_svc),
337 (xdrproc_t)xdr_nlm_testargs,
338 (xdrproc_t)0,
339 NULL,
340 0,
341 0 },
342
343 { /* 7: NLM_LOCK_MSG */
344 NLM_SVC_FUNC(nlm_lock_msg_1_svc),
345 (xdrproc_t)xdr_nlm_lockargs,
346 (xdrproc_t)0,
347 NULL,
348 0,
349 0 },
350
351 { /* 8: NLM_CANCEL_MSG */
352 NLM_SVC_FUNC(nlm_cancel_msg_1_svc),
353 (xdrproc_t)xdr_nlm_cancargs,
354 (xdrproc_t)0,
355 NULL,
356 0,
357 0 },
358
359 { /* 9: NLM_UNLOCK_MSG */
360 NLM_SVC_FUNC(nlm_unlock_msg_1_svc),
361 (xdrproc_t)xdr_nlm_unlockargs,
362 (xdrproc_t)0,
363 NULL,
364 0,
365 0 },
366
367 { /* 10: NLM_GRANTED_MSG */
368 NLM_SVC_FUNC(nlm_granted_msg_1_svc),
369 (xdrproc_t)xdr_nlm_testargs,
370 (xdrproc_t)0,
371 NULL,
372 0,
373 0 },
374
375 { /* 11: NLM_TEST_RES */
376 NLM_SVC_FUNC(nlm_test_res_1_svc),
377 (xdrproc_t)xdr_nlm_testres,
378 (xdrproc_t)0,
379 NULL,
380 0,
381 0 },
382
383 { /* 12: NLM_LOCK_RES */
384 NLM_SVC_FUNC(nlm_lock_res_1_svc),
385 (xdrproc_t)xdr_nlm_res,
386 (xdrproc_t)0,
387 NULL,
388 0,
389 0 },
390
391 { /* 13: NLM_CANCEL_RES */
392 NLM_SVC_FUNC(nlm_cancel_res_1_svc),
393 (xdrproc_t)xdr_nlm_res,
394 (xdrproc_t)0,
395 NULL,
396 0,
397 0 },
398
399 { /* 14: NLM_UNLOCK_RES */
400 NLM_SVC_FUNC(nlm_unlock_res_1_svc),
401 (xdrproc_t)xdr_nlm_res,
402 (xdrproc_t)0,
403 NULL,
404 0,
405 0 },
406
407 { /* 15: NLM_GRANTED_RES */
408 NLM_SVC_FUNC(nlm_granted_res_1_svc),
409 (xdrproc_t)xdr_nlm_res,
410 (xdrproc_t)0,
411 NULL,
412 0,
413 0 },
414
415 { /* 16: not used */
416 NLM_SVC_FUNC(0),
417 (xdrproc_t)0,
418 (xdrproc_t)0,
419 NULL,
420 0,
421 0 },
422
423 { /* 17: NLM_SM_NOTIFY1 */
424 NLM_SVC_FUNC(nlm_sm_notify1_2_svc),
425 (xdrproc_t)xdr_nlm_sm_status,
426 (xdrproc_t)xdr_void,
427 NULL,
428 0,
429 NLM_DISP_NOREMOTE },
430
431 { /* 18: NLM_SM_NOTIFY2 */
432 NLM_SVC_FUNC(nlm_sm_notify2_2_svc),
433 (xdrproc_t)xdr_nlm_sm_status,
434 (xdrproc_t)xdr_void,
435 NULL,
436 0,
437 NLM_DISP_NOREMOTE },
438
439 /*
440 * Version 3 (NLM_VERSX) entries.
441 */
442
443 { /* 19: not used */
444 NLM_SVC_FUNC(0),
445 (xdrproc_t)0,
446 (xdrproc_t)0,
447 NULL,
448 0,
449 0 },
450
451 { /* 20: NLM_SHARE */
452 NLM_SVC_FUNC(nlm_share_3_svc),
453 (xdrproc_t)xdr_nlm_shareargs,
454 (xdrproc_t)xdr_nlm_shareres,
455 NLM_FREERES_FUNC(nlm_shareres_free),
456 sizeof (nlm_shareres),
457 0 },
458
459 { /* 21: NLM_UNSHARE */
460 NLM_SVC_FUNC(nlm_unshare_3_svc),
461 (xdrproc_t)xdr_nlm_shareargs,
462 (xdrproc_t)xdr_nlm_shareres,
463 NLM_FREERES_FUNC(nlm_shareres_free),
464 sizeof (nlm_shareres),
465 0 },
466
467 { /* 22: NLM_NM_LOCK */
468 NLM_SVC_FUNC(nlm_nm_lock_3_svc),
469 (xdrproc_t)xdr_nlm_lockargs,
470 (xdrproc_t)xdr_nlm_res,
471 NLM_FREERES_FUNC(nlm_res_free),
472 sizeof (nlm_res),
473 0 },
474
475 { /* 23: NLM_FREE_ALL */
476 NLM_SVC_FUNC(nlm_free_all_3_svc),
477 (xdrproc_t)xdr_nlm_notify,
478 (xdrproc_t)xdr_void,
479 NULL,
480 0,
481 0 },
482 };
483 static int nlm_prog_3_dtsize =
484 sizeof (nlm_prog_3_dtable) /
485 sizeof (nlm_prog_3_dtable[0]);
486
487 /*
488 * RPC dispatch function for nlm_prot versions: 1,2,3
489 */
490 void
nlm_prog_3(struct svc_req * rqstp,register SVCXPRT * transp)491 nlm_prog_3(struct svc_req *rqstp, register SVCXPRT *transp)
492 {
493 const struct dispatch_entry *de;
494 rpcproc_t max_proc;
495
496 switch (rqstp->rq_vers) {
497 case NLM_VERS:
498 max_proc = NLM_GRANTED_RES;
499 break;
500 case NLM_SM:
501 max_proc = NLM_SM_NOTIFY2;
502 break;
503 case NLM_VERSX:
504 max_proc = NLM_FREE_ALL;
505 break;
506 default:
507 /* Our svc registration should prevent this. */
508 ASSERT(0); /* paranoid */
509 svcerr_noprog(transp);
510 return;
511 }
512 ASSERT(max_proc < nlm_prog_3_dtsize);
513
514 if (rqstp->rq_proc > max_proc) {
515 svcerr_noproc(transp);
516 return;
517 }
518
519 de = &nlm_prog_3_dtable[rqstp->rq_proc];
520
521 nlm_dispatch(rqstp, transp, de);
522 }
523
524 /*
525 * Dispatch table for version 4 (NLM4_VERS)
526 */
527 static const struct dispatch_entry
528 nlm_prog_4_dtable[] = {
529
530 { /* 0: NULLPROC */
531 NLM_SVC_FUNC(nlm_null_svc),
532 (xdrproc_t)xdr_void,
533 (xdrproc_t)xdr_void,
534 NULL,
535 0,
536 0 },
537
538 { /* 1: NLM4_TEST */
539 NLM_SVC_FUNC(nlm4_test_4_svc),
540 (xdrproc_t)xdr_nlm4_testargs,
541 (xdrproc_t)xdr_nlm4_testres,
542 NLM_FREERES_FUNC(nlm4_testres_free),
543 sizeof (nlm4_testres),
544 0 },
545
546 { /* 2: NLM4_LOCK */
547 NLM_SVC_FUNC(nlm4_lock_4_svc),
548 (xdrproc_t)xdr_nlm4_lockargs,
549 (xdrproc_t)xdr_nlm4_res,
550 NLM_FREERES_FUNC(nlm4_res_free),
551 sizeof (nlm4_res),
552 0 },
553
554 { /* 3: NLM4_CANCEL */
555 NLM_SVC_FUNC(nlm4_cancel_4_svc),
556 (xdrproc_t)xdr_nlm4_cancargs,
557 (xdrproc_t)xdr_nlm4_res,
558 NLM_FREERES_FUNC(nlm4_res_free),
559 sizeof (nlm4_res),
560 0 },
561
562 { /* 4: NLM4_UNLOCK */
563 NLM_SVC_FUNC(nlm4_unlock_4_svc),
564 (xdrproc_t)xdr_nlm4_unlockargs,
565 (xdrproc_t)xdr_nlm4_res,
566 NLM_FREERES_FUNC(nlm4_res_free),
567 sizeof (nlm4_res),
568 0 },
569
570 { /* 5: NLM4_GRANTED */
571 NLM_SVC_FUNC(nlm4_granted_4_svc),
572 (xdrproc_t)xdr_nlm4_testargs,
573 (xdrproc_t)xdr_nlm4_res,
574 NLM_FREERES_FUNC(nlm4_res_free),
575 sizeof (nlm4_res),
576 0 },
577
578 /*
579 * All the _MSG and _RES entries are "one way" calls that
580 * skip the usual RPC reply. We give them a null xdr_res
581 * function so the dispatcher will not send a reply.
582 */
583
584 { /* 6: NLM4_TEST_MSG */
585 NLM_SVC_FUNC(nlm4_test_msg_4_svc),
586 (xdrproc_t)xdr_nlm4_testargs,
587 (xdrproc_t)0,
588 NULL,
589 0,
590 0 },
591
592 { /* 7: NLM4_LOCK_MSG */
593 NLM_SVC_FUNC(nlm4_lock_msg_4_svc),
594 (xdrproc_t)xdr_nlm4_lockargs,
595 (xdrproc_t)0,
596 NULL,
597 0,
598 0 },
599
600 { /* 8: NLM4_CANCEL_MSG */
601 NLM_SVC_FUNC(nlm4_cancel_msg_4_svc),
602 (xdrproc_t)xdr_nlm4_cancargs,
603 (xdrproc_t)0,
604 NULL,
605 0,
606 0 },
607
608 { /* 9: NLM4_UNLOCK_MSG */
609 NLM_SVC_FUNC(nlm4_unlock_msg_4_svc),
610 (xdrproc_t)xdr_nlm4_unlockargs,
611 (xdrproc_t)0,
612 NULL,
613 0,
614 0 },
615
616 { /* 10: NLM4_GRANTED_MSG */
617 NLM_SVC_FUNC(nlm4_granted_msg_4_svc),
618 (xdrproc_t)xdr_nlm4_testargs,
619 (xdrproc_t)0,
620 NULL,
621 0,
622 0 },
623
624 { /* 11: NLM4_TEST_RES */
625 NLM_SVC_FUNC(nlm4_test_res_4_svc),
626 (xdrproc_t)xdr_nlm4_testres,
627 (xdrproc_t)0,
628 NULL,
629 0,
630 0 },
631
632 { /* 12: NLM4_LOCK_RES */
633 NLM_SVC_FUNC(nlm4_lock_res_4_svc),
634 (xdrproc_t)xdr_nlm4_res,
635 (xdrproc_t)0,
636 NULL,
637 0,
638 0 },
639
640 { /* 13: NLM4_CANCEL_RES */
641 NLM_SVC_FUNC(nlm4_cancel_res_4_svc),
642 (xdrproc_t)xdr_nlm4_res,
643 (xdrproc_t)0,
644 NULL,
645 0,
646 0 },
647
648 { /* 14: NLM4_UNLOCK_RES */
649 NLM_SVC_FUNC(nlm4_unlock_res_4_svc),
650 (xdrproc_t)xdr_nlm4_res,
651 (xdrproc_t)0,
652 NULL,
653 0,
654 0 },
655
656 { /* 15: NLM4_GRANTED_RES */
657 NLM_SVC_FUNC(nlm4_granted_res_4_svc),
658 (xdrproc_t)xdr_nlm4_res,
659 (xdrproc_t)0,
660 NULL,
661 0,
662 0 },
663
664 { /* 16: not used */
665 NLM_SVC_FUNC(0),
666 (xdrproc_t)0,
667 (xdrproc_t)0,
668 NULL,
669 0,
670 0 },
671
672 { /* 17: NLM_SM_NOTIFY1 (not in v4) */
673 NLM_SVC_FUNC(0),
674 (xdrproc_t)0,
675 (xdrproc_t)0,
676 NULL,
677 0,
678 0 },
679
680 { /* 18: NLM_SM_NOTIFY2 (not in v4) */
681 NLM_SVC_FUNC(0),
682 (xdrproc_t)0,
683 (xdrproc_t)0,
684 NULL,
685 0,
686 0 },
687
688 { /* 19: not used */
689 NLM_SVC_FUNC(0),
690 (xdrproc_t)0,
691 (xdrproc_t)0,
692 NULL,
693 0,
694 0 },
695
696 { /* 20: NLM4_SHARE */
697 NLM_SVC_FUNC(nlm4_share_4_svc),
698 (xdrproc_t)xdr_nlm4_shareargs,
699 (xdrproc_t)xdr_nlm4_shareres,
700 NLM_FREERES_FUNC(nlm4_shareres_free),
701 sizeof (nlm4_shareres),
702 0 },
703
704 { /* 21: NLM4_UNSHARE */
705 NLM_SVC_FUNC(nlm4_unshare_4_svc),
706 (xdrproc_t)xdr_nlm4_shareargs,
707 (xdrproc_t)xdr_nlm4_shareres,
708 NLM_FREERES_FUNC(nlm4_shareres_free),
709 sizeof (nlm4_shareres),
710 0 },
711
712 { /* 22: NLM4_NM_LOCK */
713 NLM_SVC_FUNC(nlm4_nm_lock_4_svc),
714 (xdrproc_t)xdr_nlm4_lockargs,
715 (xdrproc_t)xdr_nlm4_res,
716 NLM_FREERES_FUNC(nlm4_res_free),
717 sizeof (nlm4_res),
718 0 },
719
720 { /* 23: NLM4_FREE_ALL */
721 NLM_SVC_FUNC(nlm4_free_all_4_svc),
722 (xdrproc_t)xdr_nlm4_notify,
723 (xdrproc_t)xdr_void,
724 NULL,
725 0,
726 0 },
727 };
728 static int nlm_prog_4_dtsize =
729 sizeof (nlm_prog_4_dtable) /
730 sizeof (nlm_prog_4_dtable[0]);
731
732 /*
733 * RPC dispatch function for nlm_prot version 4.
734 */
735 void
nlm_prog_4(struct svc_req * rqstp,register SVCXPRT * transp)736 nlm_prog_4(struct svc_req *rqstp, register SVCXPRT *transp)
737 {
738 const struct dispatch_entry *de;
739
740 if (rqstp->rq_vers != NLM4_VERS) {
741 /* Our svc registration should prevent this. */
742 ASSERT(0); /* paranoid */
743 svcerr_noprog(transp);
744 return;
745 }
746
747 if (rqstp->rq_proc >= nlm_prog_4_dtsize) {
748 svcerr_noproc(transp);
749 return;
750 }
751
752 de = &nlm_prog_4_dtable[rqstp->rq_proc];
753
754 nlm_dispatch(rqstp, transp, de);
755 }
756