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