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