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