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