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