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