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 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 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 228 nlm_res_free(nlm_res *resp) 229 { 230 xdr_free(xdr_nlm_res, (char *)resp); 231 } 232 233 static void 234 nlm_shareres_free(nlm_shareres *resp) 235 { 236 xdr_free(xdr_nlm_shareres, (char *)resp); 237 } 238 239 static void 240 nlm_testres_free(nlm_testres *resp) 241 { 242 xdr_free(xdr_nlm_testres, (char *)resp); 243 } 244 245 static void 246 nlm4_res_free(nlm4_res *resp) 247 { 248 xdr_free(xdr_nlm4_res, (char *)resp); 249 } 250 251 static void 252 nlm4_shareres_free(nlm4_shareres *resp) 253 { 254 xdr_free(xdr_nlm4_shareres, (char *)resp); 255 } 256 257 static void 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 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 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 }