1 /* $NetBSD: xdr.c,v 1.22 2000/07/06 03:10:35 christos Exp $ */ 2 3 /* 4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5 * unrestricted use provided that this legend is included on all tape 6 * media and as a part of the software program in whole or part. Users 7 * may copy or modify Sun RPC without charge, but are not authorized 8 * to license or distribute it to anyone else except as part of a product or 9 * program developed by the user. 10 * 11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14 * 15 * Sun RPC is provided with no support and without any obligation on the 16 * part of Sun Microsystems, Inc. to assist in its use, correction, 17 * modification or enhancement. 18 * 19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21 * OR ANY PART THEREOF. 22 * 23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24 * or profits or other special, indirect and consequential damages, even if 25 * Sun has been advised of the possibility of such damages. 26 * 27 * Sun Microsystems, Inc. 28 * 2550 Garcia Avenue 29 * Mountain View, California 94043 30 */ 31 32 #if defined(LIBC_SCCS) && !defined(lint) 33 static char *sccsid2 = "@(#)xdr.c 1.35 87/08/12"; 34 static char *sccsid = "@(#)xdr.c 2.1 88/07/29 4.0 RPCSRC"; 35 #endif 36 #include <sys/cdefs.h> 37 __FBSDID("$FreeBSD$"); 38 39 /* 40 * xdr.c, Generic XDR routines implementation. 41 * 42 * Copyright (C) 1986, Sun Microsystems, Inc. 43 * 44 * These are the "generic" xdr routines used to serialize and de-serialize 45 * most common data items. See xdr.h for more info on the interface to 46 * xdr. 47 */ 48 49 #include <sys/param.h> 50 #include <sys/systm.h> 51 #include <sys/kernel.h> 52 #include <sys/malloc.h> 53 #include <sys/module.h> 54 55 #include <rpc/rpc.h> 56 #include <rpc/rpc_com.h> 57 #include <rpc/types.h> 58 #include <rpc/xdr.h> 59 60 typedef quad_t longlong_t; /* ANSI long long type */ 61 typedef u_quad_t u_longlong_t; /* ANSI unsigned long long type */ 62 63 /* 64 * constants specific to the xdr "protocol" 65 */ 66 #define XDR_FALSE ((long) 0) 67 #define XDR_TRUE ((long) 1) 68 69 MALLOC_DEFINE(M_RPC, "rpc", "Remote Procedure Call"); 70 71 /* 72 * for unit alignment 73 */ 74 static const char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 }; 75 76 /* 77 * Free a data structure using XDR 78 * Not a filter, but a convenient utility nonetheless 79 */ 80 void 81 xdr_free(xdrproc_t proc, void *objp) 82 { 83 XDR x; 84 85 x.x_op = XDR_FREE; 86 (*proc)(&x, objp); 87 } 88 89 /* 90 * XDR nothing 91 */ 92 bool_t 93 xdr_void(void) 94 { 95 96 return (TRUE); 97 } 98 99 /* 100 * XDR integers 101 */ 102 bool_t 103 xdr_int(XDR *xdrs, int *ip) 104 { 105 long l; 106 107 switch (xdrs->x_op) { 108 case XDR_ENCODE: 109 l = (long) *ip; 110 return (XDR_PUTLONG(xdrs, &l)); 111 112 case XDR_DECODE: 113 if (!XDR_GETLONG(xdrs, &l)) { 114 return (FALSE); 115 } 116 *ip = (int) l; 117 return (TRUE); 118 119 case XDR_FREE: 120 return (TRUE); 121 } 122 /* NOTREACHED */ 123 return (FALSE); 124 } 125 126 /* 127 * XDR unsigned integers 128 */ 129 bool_t 130 xdr_u_int(XDR *xdrs, u_int *up) 131 { 132 u_long l; 133 134 switch (xdrs->x_op) { 135 case XDR_ENCODE: 136 l = (u_long) *up; 137 return (XDR_PUTLONG(xdrs, (long *)&l)); 138 139 case XDR_DECODE: 140 if (!XDR_GETLONG(xdrs, (long *)&l)) { 141 return (FALSE); 142 } 143 *up = (u_int) l; 144 return (TRUE); 145 146 case XDR_FREE: 147 return (TRUE); 148 } 149 /* NOTREACHED */ 150 return (FALSE); 151 } 152 153 /* 154 * XDR long integers 155 * same as xdr_u_long - open coded to save a proc call! 156 */ 157 bool_t 158 xdr_long(XDR *xdrs, long *lp) 159 { 160 switch (xdrs->x_op) { 161 case XDR_ENCODE: 162 return (XDR_PUTLONG(xdrs, lp)); 163 case XDR_DECODE: 164 return (XDR_GETLONG(xdrs, lp)); 165 case XDR_FREE: 166 return (TRUE); 167 } 168 /* NOTREACHED */ 169 return (FALSE); 170 } 171 172 /* 173 * XDR unsigned long integers 174 * same as xdr_long - open coded to save a proc call! 175 */ 176 bool_t 177 xdr_u_long(XDR *xdrs, u_long *ulp) 178 { 179 switch (xdrs->x_op) { 180 case XDR_ENCODE: 181 return (XDR_PUTLONG(xdrs, (long *)ulp)); 182 case XDR_DECODE: 183 return (XDR_GETLONG(xdrs, (long *)ulp)); 184 case XDR_FREE: 185 return (TRUE); 186 } 187 /* NOTREACHED */ 188 return (FALSE); 189 } 190 191 /* 192 * XDR 32-bit integers 193 * same as xdr_uint32_t - open coded to save a proc call! 194 */ 195 bool_t 196 xdr_int32_t(XDR *xdrs, int32_t *int32_p) 197 { 198 long l; 199 200 switch (xdrs->x_op) { 201 case XDR_ENCODE: 202 l = (long) *int32_p; 203 return (XDR_PUTLONG(xdrs, &l)); 204 205 case XDR_DECODE: 206 if (!XDR_GETLONG(xdrs, &l)) { 207 return (FALSE); 208 } 209 *int32_p = (int32_t) l; 210 return (TRUE); 211 212 case XDR_FREE: 213 return (TRUE); 214 } 215 /* NOTREACHED */ 216 return (FALSE); 217 } 218 219 /* 220 * XDR unsigned 32-bit integers 221 * same as xdr_int32_t - open coded to save a proc call! 222 */ 223 bool_t 224 xdr_uint32_t(XDR *xdrs, uint32_t *uint32_p) 225 { 226 u_long l; 227 228 switch (xdrs->x_op) { 229 case XDR_ENCODE: 230 l = (u_long) *uint32_p; 231 return (XDR_PUTLONG(xdrs, (long *)&l)); 232 233 case XDR_DECODE: 234 if (!XDR_GETLONG(xdrs, (long *)&l)) { 235 return (FALSE); 236 } 237 *uint32_p = (uint32_t) l; 238 return (TRUE); 239 240 case XDR_FREE: 241 return (TRUE); 242 } 243 /* NOTREACHED */ 244 return (FALSE); 245 } 246 247 /* 248 * XDR short integers 249 */ 250 bool_t 251 xdr_short(XDR *xdrs, short *sp) 252 { 253 long l; 254 255 switch (xdrs->x_op) { 256 case XDR_ENCODE: 257 l = (long) *sp; 258 return (XDR_PUTLONG(xdrs, &l)); 259 260 case XDR_DECODE: 261 if (!XDR_GETLONG(xdrs, &l)) { 262 return (FALSE); 263 } 264 *sp = (short) l; 265 return (TRUE); 266 267 case XDR_FREE: 268 return (TRUE); 269 } 270 /* NOTREACHED */ 271 return (FALSE); 272 } 273 274 /* 275 * XDR unsigned short integers 276 */ 277 bool_t 278 xdr_u_short(XDR *xdrs, u_short *usp) 279 { 280 u_long l; 281 282 switch (xdrs->x_op) { 283 case XDR_ENCODE: 284 l = (u_long) *usp; 285 return (XDR_PUTLONG(xdrs, (long *)&l)); 286 287 case XDR_DECODE: 288 if (!XDR_GETLONG(xdrs, (long *)&l)) { 289 return (FALSE); 290 } 291 *usp = (u_short) l; 292 return (TRUE); 293 294 case XDR_FREE: 295 return (TRUE); 296 } 297 /* NOTREACHED */ 298 return (FALSE); 299 } 300 301 /* 302 * XDR 16-bit integers 303 */ 304 bool_t 305 xdr_int16_t(XDR *xdrs, int16_t *int16_p) 306 { 307 long l; 308 309 switch (xdrs->x_op) { 310 case XDR_ENCODE: 311 l = (long) *int16_p; 312 return (XDR_PUTLONG(xdrs, &l)); 313 314 case XDR_DECODE: 315 if (!XDR_GETLONG(xdrs, &l)) { 316 return (FALSE); 317 } 318 *int16_p = (int16_t) l; 319 return (TRUE); 320 321 case XDR_FREE: 322 return (TRUE); 323 } 324 /* NOTREACHED */ 325 return (FALSE); 326 } 327 328 /* 329 * XDR unsigned 16-bit integers 330 */ 331 bool_t 332 xdr_uint16_t(XDR *xdrs, uint16_t *uint16_p) 333 { 334 u_long l; 335 336 switch (xdrs->x_op) { 337 case XDR_ENCODE: 338 l = (u_long) *uint16_p; 339 return (XDR_PUTLONG(xdrs, (long *)&l)); 340 341 case XDR_DECODE: 342 if (!XDR_GETLONG(xdrs, (long *)&l)) { 343 return (FALSE); 344 } 345 *uint16_p = (uint16_t) l; 346 return (TRUE); 347 348 case XDR_FREE: 349 return (TRUE); 350 } 351 /* NOTREACHED */ 352 return (FALSE); 353 } 354 355 /* 356 * XDR a char 357 */ 358 bool_t 359 xdr_char(XDR *xdrs, char *cp) 360 { 361 u_int i; 362 363 i = *((unsigned char *)cp); 364 if (!xdr_u_int(xdrs, &i)) { 365 return (FALSE); 366 } 367 *((unsigned char *)cp) = i; 368 return (TRUE); 369 } 370 371 /* 372 * XDR an unsigned char 373 */ 374 bool_t 375 xdr_u_char(XDR *xdrs, u_char *cp) 376 { 377 u_int u; 378 379 u = (*cp); 380 if (!xdr_u_int(xdrs, &u)) { 381 return (FALSE); 382 } 383 *cp = u; 384 return (TRUE); 385 } 386 387 /* 388 * XDR booleans 389 */ 390 bool_t 391 xdr_bool(XDR *xdrs, bool_t *bp) 392 { 393 long lb; 394 395 switch (xdrs->x_op) { 396 case XDR_ENCODE: 397 lb = *bp ? XDR_TRUE : XDR_FALSE; 398 return (XDR_PUTLONG(xdrs, &lb)); 399 400 case XDR_DECODE: 401 if (!XDR_GETLONG(xdrs, &lb)) { 402 return (FALSE); 403 } 404 *bp = (lb == XDR_FALSE) ? FALSE : TRUE; 405 return (TRUE); 406 407 case XDR_FREE: 408 return (TRUE); 409 } 410 /* NOTREACHED */ 411 return (FALSE); 412 } 413 414 /* 415 * XDR enumerations 416 */ 417 bool_t 418 xdr_enum(XDR *xdrs, enum_t *ep) 419 { 420 enum sizecheck { SIZEVAL }; /* used to find the size of an enum */ 421 422 /* 423 * enums are treated as ints 424 */ 425 /* LINTED */ if (sizeof (enum sizecheck) == sizeof (long)) { 426 return (xdr_long(xdrs, (long *)(void *)ep)); 427 } else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (int)) { 428 return (xdr_int(xdrs, (int *)(void *)ep)); 429 } else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (short)) { 430 return (xdr_short(xdrs, (short *)(void *)ep)); 431 } else { 432 return (FALSE); 433 } 434 } 435 436 /* 437 * XDR opaque data 438 * Allows the specification of a fixed size sequence of opaque bytes. 439 * cp points to the opaque object and cnt gives the byte length. 440 */ 441 bool_t 442 xdr_opaque(XDR *xdrs, caddr_t cp, u_int cnt) 443 { 444 u_int rndup; 445 static int crud[BYTES_PER_XDR_UNIT]; 446 447 /* 448 * if no data we are done 449 */ 450 if (cnt == 0) 451 return (TRUE); 452 453 /* 454 * round byte count to full xdr units 455 */ 456 rndup = cnt % BYTES_PER_XDR_UNIT; 457 if (rndup > 0) 458 rndup = BYTES_PER_XDR_UNIT - rndup; 459 460 if (xdrs->x_op == XDR_DECODE) { 461 if (!XDR_GETBYTES(xdrs, cp, cnt)) { 462 return (FALSE); 463 } 464 if (rndup == 0) 465 return (TRUE); 466 return (XDR_GETBYTES(xdrs, (caddr_t)(void *)crud, rndup)); 467 } 468 469 if (xdrs->x_op == XDR_ENCODE) { 470 if (!XDR_PUTBYTES(xdrs, cp, cnt)) { 471 return (FALSE); 472 } 473 if (rndup == 0) 474 return (TRUE); 475 return (XDR_PUTBYTES(xdrs, xdr_zero, rndup)); 476 } 477 478 if (xdrs->x_op == XDR_FREE) { 479 return (TRUE); 480 } 481 482 return (FALSE); 483 } 484 485 /* 486 * XDR counted bytes 487 * *cpp is a pointer to the bytes, *sizep is the count. 488 * If *cpp is NULL maxsize bytes are allocated 489 */ 490 bool_t 491 xdr_bytes(XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize) 492 { 493 char *sp = *cpp; /* sp is the actual string pointer */ 494 u_int nodesize; 495 bool_t ret, allocated = FALSE; 496 497 /* 498 * first deal with the length since xdr bytes are counted 499 */ 500 if (! xdr_u_int(xdrs, sizep)) { 501 return (FALSE); 502 } 503 nodesize = *sizep; 504 if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) { 505 return (FALSE); 506 } 507 508 /* 509 * now deal with the actual bytes 510 */ 511 switch (xdrs->x_op) { 512 case XDR_DECODE: 513 if (nodesize == 0) { 514 return (TRUE); 515 } 516 if (sp == NULL) { 517 *cpp = sp = mem_alloc(nodesize); 518 allocated = TRUE; 519 } 520 if (sp == NULL) { 521 printf("xdr_bytes: out of memory"); 522 return (FALSE); 523 } 524 /* FALLTHROUGH */ 525 526 case XDR_ENCODE: 527 ret = xdr_opaque(xdrs, sp, nodesize); 528 if ((xdrs->x_op == XDR_DECODE) && (ret == FALSE)) { 529 if (allocated == TRUE) { 530 mem_free(sp, nodesize); 531 *cpp = NULL; 532 } 533 } 534 return (ret); 535 536 case XDR_FREE: 537 if (sp != NULL) { 538 mem_free(sp, nodesize); 539 *cpp = NULL; 540 } 541 return (TRUE); 542 } 543 /* NOTREACHED */ 544 return (FALSE); 545 } 546 547 /* 548 * Implemented here due to commonality of the object. 549 */ 550 bool_t 551 xdr_netobj(XDR *xdrs, struct netobj *np) 552 { 553 554 return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ)); 555 } 556 557 /* 558 * XDR a descriminated union 559 * Support routine for discriminated unions. 560 * You create an array of xdrdiscrim structures, terminated with 561 * an entry with a null procedure pointer. The routine gets 562 * the discriminant value and then searches the array of xdrdiscrims 563 * looking for that value. It calls the procedure given in the xdrdiscrim 564 * to handle the discriminant. If there is no specific routine a default 565 * routine may be called. 566 * If there is no specific or default routine an error is returned. 567 */ 568 bool_t 569 xdr_union(XDR *xdrs, 570 enum_t *dscmp, /* enum to decide which arm to work on */ 571 char *unp, /* the union itself */ 572 const struct xdr_discrim *choices, /* [value, xdr proc] for each arm */ 573 xdrproc_t dfault) /* default xdr routine */ 574 { 575 enum_t dscm; 576 577 /* 578 * we deal with the discriminator; it's an enum 579 */ 580 if (! xdr_enum(xdrs, dscmp)) { 581 return (FALSE); 582 } 583 dscm = *dscmp; 584 585 /* 586 * search choices for a value that matches the discriminator. 587 * if we find one, execute the xdr routine for that value. 588 */ 589 for (; choices->proc != NULL_xdrproc_t; choices++) { 590 if (choices->value == dscm) 591 return ((*(choices->proc))(xdrs, unp)); 592 } 593 594 /* 595 * no match - execute the default xdr routine if there is one 596 */ 597 return ((dfault == NULL_xdrproc_t) ? FALSE : 598 (*dfault)(xdrs, unp)); 599 } 600 601 /* 602 * Non-portable xdr primitives. 603 * Care should be taken when moving these routines to new architectures. 604 */ 605 606 /* 607 * XDR null terminated ASCII strings 608 * xdr_string deals with "C strings" - arrays of bytes that are 609 * terminated by a NULL character. The parameter cpp references a 610 * pointer to storage; If the pointer is null, then the necessary 611 * storage is allocated. The last parameter is the max allowed length 612 * of the string as specified by a protocol. 613 */ 614 bool_t 615 xdr_string(XDR *xdrs, char **cpp, u_int maxsize) 616 { 617 char *sp = *cpp; /* sp is the actual string pointer */ 618 u_int size; 619 u_int nodesize; 620 bool_t ret, allocated = FALSE; 621 622 /* 623 * first deal with the length since xdr strings are counted-strings 624 */ 625 switch (xdrs->x_op) { 626 case XDR_FREE: 627 if (sp == NULL) { 628 return(TRUE); /* already free */ 629 } 630 /* FALLTHROUGH */ 631 case XDR_ENCODE: 632 size = strlen(sp); 633 break; 634 case XDR_DECODE: 635 break; 636 } 637 if (! xdr_u_int(xdrs, &size)) { 638 return (FALSE); 639 } 640 if (size > maxsize) { 641 return (FALSE); 642 } 643 nodesize = size + 1; 644 645 /* 646 * now deal with the actual bytes 647 */ 648 switch (xdrs->x_op) { 649 case XDR_DECODE: 650 if (nodesize == 0) { 651 return (TRUE); 652 } 653 if (sp == NULL) { 654 *cpp = sp = mem_alloc(nodesize); 655 allocated = TRUE; 656 } 657 if (sp == NULL) { 658 printf("xdr_string: out of memory"); 659 return (FALSE); 660 } 661 sp[size] = 0; 662 /* FALLTHROUGH */ 663 664 case XDR_ENCODE: 665 ret = xdr_opaque(xdrs, sp, size); 666 if ((xdrs->x_op == XDR_DECODE) && (ret == FALSE)) { 667 if (allocated == TRUE) { 668 mem_free(sp, nodesize); 669 *cpp = NULL; 670 } 671 } 672 return (ret); 673 674 case XDR_FREE: 675 mem_free(sp, nodesize); 676 *cpp = NULL; 677 return (TRUE); 678 } 679 /* NOTREACHED */ 680 return (FALSE); 681 } 682 683 /* 684 * Wrapper for xdr_string that can be called directly from 685 * routines like clnt_call 686 */ 687 bool_t 688 xdr_wrapstring(XDR *xdrs, char **cpp) 689 { 690 return xdr_string(xdrs, cpp, RPC_MAXDATASIZE); 691 } 692 693 /* 694 * NOTE: xdr_hyper(), xdr_u_hyper(), xdr_longlong_t(), and xdr_u_longlong_t() 695 * are in the "non-portable" section because they require that a `long long' 696 * be a 64-bit type. 697 * 698 * --thorpej@netbsd.org, November 30, 1999 699 */ 700 701 /* 702 * XDR 64-bit integers 703 */ 704 bool_t 705 xdr_int64_t(XDR *xdrs, int64_t *llp) 706 { 707 u_long ul[2]; 708 709 switch (xdrs->x_op) { 710 case XDR_ENCODE: 711 ul[0] = (u_long)((uint64_t)*llp >> 32) & 0xffffffff; 712 ul[1] = (u_long)((uint64_t)*llp) & 0xffffffff; 713 if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE) 714 return (FALSE); 715 return (XDR_PUTLONG(xdrs, (long *)&ul[1])); 716 case XDR_DECODE: 717 if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE) 718 return (FALSE); 719 if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE) 720 return (FALSE); 721 *llp = (int64_t) 722 (((uint64_t)ul[0] << 32) | ((uint64_t)ul[1])); 723 return (TRUE); 724 case XDR_FREE: 725 return (TRUE); 726 } 727 /* NOTREACHED */ 728 return (FALSE); 729 } 730 731 /* 732 * XDR unsigned 64-bit integers 733 */ 734 bool_t 735 xdr_uint64_t(XDR *xdrs, uint64_t *ullp) 736 { 737 u_long ul[2]; 738 739 switch (xdrs->x_op) { 740 case XDR_ENCODE: 741 ul[0] = (u_long)(*ullp >> 32) & 0xffffffff; 742 ul[1] = (u_long)(*ullp) & 0xffffffff; 743 if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE) 744 return (FALSE); 745 return (XDR_PUTLONG(xdrs, (long *)&ul[1])); 746 case XDR_DECODE: 747 if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE) 748 return (FALSE); 749 if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE) 750 return (FALSE); 751 *ullp = (uint64_t) 752 (((uint64_t)ul[0] << 32) | ((uint64_t)ul[1])); 753 return (TRUE); 754 case XDR_FREE: 755 return (TRUE); 756 } 757 /* NOTREACHED */ 758 return (FALSE); 759 } 760 761 /* 762 * XDR hypers 763 */ 764 bool_t 765 xdr_hyper(XDR *xdrs, longlong_t *llp) 766 { 767 768 /* 769 * Don't bother open-coding this; it's a fair amount of code. Just 770 * call xdr_int64_t(). 771 */ 772 return (xdr_int64_t(xdrs, (int64_t *)llp)); 773 } 774 775 /* 776 * XDR unsigned hypers 777 */ 778 bool_t 779 xdr_u_hyper(XDR *xdrs, u_longlong_t *ullp) 780 { 781 782 /* 783 * Don't bother open-coding this; it's a fair amount of code. Just 784 * call xdr_uint64_t(). 785 */ 786 return (xdr_uint64_t(xdrs, (uint64_t *)ullp)); 787 } 788 789 /* 790 * XDR longlong_t's 791 */ 792 bool_t 793 xdr_longlong_t(XDR *xdrs, longlong_t *llp) 794 { 795 796 /* 797 * Don't bother open-coding this; it's a fair amount of code. Just 798 * call xdr_int64_t(). 799 */ 800 return (xdr_int64_t(xdrs, (int64_t *)llp)); 801 } 802 803 /* 804 * XDR u_longlong_t's 805 */ 806 bool_t 807 xdr_u_longlong_t(XDR *xdrs, u_longlong_t *ullp) 808 { 809 810 /* 811 * Don't bother open-coding this; it's a fair amount of code. Just 812 * call xdr_uint64_t(). 813 */ 814 return (xdr_uint64_t(xdrs, (uint64_t *)ullp)); 815 } 816 817 /* 818 * Kernel module glue 819 */ 820 static int 821 xdr_modevent(module_t mod, int type, void *data) 822 { 823 824 return (0); 825 } 826 static moduledata_t xdr_mod = { 827 "xdr", 828 xdr_modevent, 829 NULL, 830 }; 831 DECLARE_MODULE(xdr, xdr_mod, SI_SUB_VFS, SI_ORDER_ANY); 832 MODULE_VERSION(xdr, 1); 833