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