1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 /* 30 * Portions of this source code were derived from Berkeley 31 * 4.3 BSD under license from the Regents of the University of 32 * California. 33 */ 34 35 #pragma ident "%Z%%M% %I% %E% SMI" 36 37 /* 38 * xdr.c, Generic XDR routines implementation. 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 #include <stdlib.h> 45 #include <sys/types.h> 46 #include <sys/isa_defs.h> 47 #include <syslog.h> 48 #include <stdio.h> 49 #include <stdlib.h> 50 #include <string.h> 51 #include <limits.h> 52 #include <rpc/types.h> 53 #include <rpc/xdr.h> 54 #include <inttypes.h> 55 #include <sys/sysmacros.h> 56 #include <assert.h> 57 58 #pragma weak xdr_int64_t = xdr_hyper 59 #pragma weak xdr_uint64_t = xdr_u_hyper 60 #pragma weak xdr_int32_t = xdr_int 61 #pragma weak xdr_uint32_t = xdr_u_int 62 #pragma weak xdr_int16_t = xdr_short 63 #pragma weak xdr_uint16_t = xdr_u_short 64 #pragma weak xdr_int8_t = xdr_char 65 #pragma weak xdr_uint8_t = xdr_u_char 66 67 /* 68 * The following routine was part of a workaround for an rpcgen 69 * that was fixed, this routine should be removed sometime. 70 */ 71 #pragma weak xdr_ulonglong_t = xdr_u_longlong_t 72 73 /* 74 * constants specific to the xdr "protocol" 75 */ 76 #define XDR_FALSE ((uint_t)0) 77 #define XDR_TRUE ((uint_t)1) 78 #define LASTUNSIGNED ((uint_t)0-1) 79 80 /* fragment size to use when doing an xdr_string() */ 81 #define FRAGMENT 65536 82 83 /* 84 * for unit alignment 85 */ 86 static const char xdr_zero[BYTES_PER_XDR_UNIT] = { 0 }; 87 88 /* 89 * Free a data structure using XDR 90 * Not a filter, but a convenient utility nonetheless 91 */ 92 void 93 xdr_free(xdrproc_t proc, char *objp) 94 { 95 XDR x; 96 97 x.x_op = XDR_FREE; 98 (*proc)(&x, objp); 99 } 100 101 /* 102 * XDR nothing 103 */ 104 bool_t 105 xdr_void(void) 106 { 107 return (TRUE); 108 } 109 110 /* 111 * xdr_time_t sends time_t value over the wire. 112 * Due to RPC Protocol limitation, it can only send 113 * up to 32-bit integer quantity over the wire. 114 * 115 */ 116 bool_t 117 xdr_time_t(XDR *xdrs, time_t *tp) 118 { 119 int32_t i; 120 121 switch (xdrs->x_op) { 122 case XDR_ENCODE: 123 /* 124 * Check for the time overflow, when encoding it. 125 * Don't want to send OTW the time value too large to 126 * handle by the protocol. 127 */ 128 #if defined(_LP64) 129 if (*tp > INT32_MAX) 130 *tp = INT32_MAX; 131 else if (*tp < INT32_MIN) 132 *tp = INT32_MIN; 133 #endif 134 i = (int32_t)*tp; 135 return (XDR_PUTINT32(xdrs, &i)); 136 137 case XDR_DECODE: 138 if (!XDR_GETINT32(xdrs, &i)) 139 return (FALSE); 140 *tp = (time_t)i; 141 return (TRUE); 142 143 case XDR_FREE: 144 return (TRUE); 145 } 146 return (FALSE); 147 } 148 149 /* 150 * XDR integers 151 */ 152 bool_t 153 xdr_int(XDR *xdrs, int *ip) 154 { 155 switch (xdrs->x_op) { 156 case XDR_ENCODE: 157 return (XDR_PUTINT32(xdrs, ip)); 158 case XDR_DECODE: 159 return (XDR_GETINT32(xdrs, ip)); 160 case XDR_FREE: 161 return (TRUE); 162 } 163 return (FALSE); 164 } 165 166 /* 167 * XDR unsigned integers 168 */ 169 bool_t 170 xdr_u_int(XDR *xdrs, uint_t *up) 171 { 172 switch (xdrs->x_op) { 173 case XDR_ENCODE: 174 return (XDR_PUTINT32(xdrs, (int *)up)); 175 case XDR_DECODE: 176 return (XDR_GETINT32(xdrs, (int *)up)); 177 case XDR_FREE: 178 return (TRUE); 179 } 180 return (FALSE); 181 } 182 183 /* 184 * The definition of xdr_long()/xdr_u_long() is kept for backward 185 * compatibitlity. 186 * XDR long integers, same as xdr_u_long 187 */ 188 bool_t 189 xdr_long(XDR *xdrs, long *lp) 190 { 191 int32_t i; 192 193 switch (xdrs->x_op) { 194 case XDR_ENCODE: 195 #if defined(_LP64) 196 if ((*lp > INT32_MAX) || (*lp < INT32_MIN)) 197 return (FALSE); 198 #endif 199 i = (int32_t)*lp; 200 return (XDR_PUTINT32(xdrs, &i)); 201 case XDR_DECODE: 202 if (!XDR_GETINT32(xdrs, &i)) 203 return (FALSE); 204 *lp = (long)i; 205 return (TRUE); 206 case XDR_FREE: 207 return (TRUE); 208 } 209 return (FALSE); 210 } 211 212 /* 213 * XDR unsigned long integers 214 * same as xdr_long 215 */ 216 bool_t 217 xdr_u_long(XDR *xdrs, ulong_t *ulp) 218 { 219 uint32_t ui; 220 221 switch (xdrs->x_op) { 222 case XDR_ENCODE: 223 #if defined(_LP64) 224 if (*ulp > UINT32_MAX) 225 return (FALSE); 226 #endif 227 ui = (uint32_t)*ulp; 228 return (XDR_PUTINT32(xdrs, (int32_t *)&ui)); 229 case XDR_DECODE: 230 if (!XDR_GETINT32(xdrs, (int32_t *)&ui)) 231 return (FALSE); 232 *ulp = (ulong_t)ui; 233 return (TRUE); 234 case XDR_FREE: 235 return (TRUE); 236 } 237 return (FALSE); 238 } 239 240 /* 241 * XDR short integers 242 */ 243 bool_t 244 xdr_short(XDR *xdrs, short *sp) 245 { 246 int32_t l; 247 248 switch (xdrs->x_op) { 249 case XDR_ENCODE: 250 l = (int32_t)*sp; 251 return (XDR_PUTINT32(xdrs, &l)); 252 case XDR_DECODE: 253 if (!XDR_GETINT32(xdrs, &l)) 254 return (FALSE); 255 *sp = (short)l; 256 return (TRUE); 257 case XDR_FREE: 258 return (TRUE); 259 } 260 return (FALSE); 261 } 262 263 /* 264 * XDR unsigned short integers 265 */ 266 bool_t 267 xdr_u_short(XDR *xdrs, ushort_t *usp) 268 { 269 uint_t i; 270 271 switch (xdrs->x_op) { 272 case XDR_ENCODE: 273 i = (uint_t)*usp; 274 return (XDR_PUTINT32(xdrs, (int *)&i)); 275 case XDR_DECODE: 276 if (!XDR_GETINT32(xdrs, (int *)&i)) 277 return (FALSE); 278 *usp = (ushort_t)i; 279 return (TRUE); 280 case XDR_FREE: 281 return (TRUE); 282 } 283 return (FALSE); 284 } 285 286 287 /* 288 * XDR a char 289 */ 290 bool_t 291 xdr_char(XDR *xdrs, char *cp) 292 { 293 int i; 294 295 switch (xdrs->x_op) { 296 case XDR_ENCODE: 297 i = (*cp); 298 return (XDR_PUTINT32(xdrs, &i)); 299 case XDR_DECODE: 300 if (!XDR_GETINT32(xdrs, &i)) 301 return (FALSE); 302 *cp = (char)i; 303 return (TRUE); 304 case XDR_FREE: 305 return (TRUE); 306 } 307 return (FALSE); 308 } 309 310 /* 311 * XDR an unsigned char 312 */ 313 bool_t 314 xdr_u_char(XDR *xdrs, uchar_t *cp) 315 { 316 int i; 317 318 switch (xdrs->x_op) { 319 case XDR_ENCODE: 320 i = (*cp); 321 return (XDR_PUTINT32(xdrs, &i)); 322 case XDR_DECODE: 323 if (!XDR_GETINT32(xdrs, &i)) 324 return (FALSE); 325 *cp = (uchar_t)i; 326 return (TRUE); 327 case XDR_FREE: 328 return (TRUE); 329 } 330 return (FALSE); 331 } 332 333 /* 334 * XDR booleans 335 */ 336 bool_t 337 xdr_bool(XDR *xdrs, bool_t *bp) 338 { 339 int i; 340 341 switch (xdrs->x_op) { 342 case XDR_ENCODE: 343 i = *bp ? XDR_TRUE : XDR_FALSE; 344 return (XDR_PUTINT32(xdrs, &i)); 345 case XDR_DECODE: 346 if (!XDR_GETINT32(xdrs, &i)) 347 return (FALSE); 348 *bp = (i == XDR_FALSE) ? FALSE : TRUE; 349 return (TRUE); 350 case XDR_FREE: 351 return (TRUE); 352 } 353 return (FALSE); 354 } 355 356 /* 357 * XDR enumerations 358 */ 359 bool_t 360 xdr_enum(XDR *xdrs, enum_t *ep) 361 { 362 enum sizecheck { SIZEVAL }; /* used to find the size of an enum */ 363 364 /* 365 * enums are treated as ints 366 */ 367 /* CONSTCOND */ 368 assert(sizeof (enum sizecheck) == sizeof (int32_t)); 369 return (xdr_int(xdrs, (int *)ep)); 370 } 371 372 /* 373 * XDR opaque data 374 * Allows the specification of a fixed size sequence of opaque bytes. 375 * cp points to the opaque object and cnt gives the byte length. 376 */ 377 bool_t 378 xdr_opaque(XDR *xdrs, caddr_t cp, const uint_t cnt) 379 { 380 uint_t rndup; 381 char crud[BYTES_PER_XDR_UNIT]; 382 383 /* 384 * if no data we are done 385 */ 386 if (cnt == 0) 387 return (TRUE); 388 389 /* 390 * round byte count to full xdr units 391 */ 392 rndup = cnt % BYTES_PER_XDR_UNIT; 393 if ((int)rndup > 0) 394 rndup = BYTES_PER_XDR_UNIT - rndup; 395 396 switch (xdrs->x_op) { 397 case XDR_DECODE: 398 if (!XDR_GETBYTES(xdrs, cp, cnt)) 399 return (FALSE); 400 if (rndup == 0) 401 return (TRUE); 402 return (XDR_GETBYTES(xdrs, crud, rndup)); 403 case XDR_ENCODE: 404 if (!XDR_PUTBYTES(xdrs, cp, cnt)) 405 return (FALSE); 406 if (rndup == 0) 407 return (TRUE); 408 return (XDR_PUTBYTES(xdrs, (caddr_t)&xdr_zero[0], rndup)); 409 case XDR_FREE: 410 return (TRUE); 411 } 412 return (FALSE); 413 } 414 415 /* 416 * XDR counted bytes 417 * *cpp is a pointer to the bytes, *sizep is the count. 418 * If *cpp is NULL maxsize bytes are allocated 419 */ 420 421 static const char xdr_err[] = "xdr_%s: out of memory"; 422 423 bool_t 424 xdr_bytes(XDR *xdrs, char **cpp, uint_t *sizep, const uint_t maxsize) 425 { 426 char *sp = *cpp; /* sp is the actual string pointer */ 427 uint_t nodesize; 428 429 /* 430 * first deal with the length since xdr bytes are counted 431 * We decided not to use MACRO XDR_U_INT here, because the 432 * advantages here will be miniscule compared to xdr_bytes. 433 * This saved us 100 bytes in the library size. 434 */ 435 if (!xdr_u_int(xdrs, sizep)) 436 return (FALSE); 437 nodesize = *sizep; 438 if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) 439 return (FALSE); 440 441 /* 442 * now deal with the actual bytes 443 */ 444 switch (xdrs->x_op) { 445 case XDR_DECODE: 446 if (nodesize == 0) 447 return (TRUE); 448 if (sp == NULL) 449 *cpp = sp = malloc(nodesize); 450 if (sp == NULL) { 451 (void) syslog(LOG_ERR, xdr_err, (const char *)"bytes"); 452 return (FALSE); 453 } 454 /*FALLTHROUGH*/ 455 case XDR_ENCODE: 456 return (xdr_opaque(xdrs, sp, nodesize)); 457 case XDR_FREE: 458 if (sp != NULL) { 459 free(sp); 460 *cpp = NULL; 461 } 462 return (TRUE); 463 } 464 return (FALSE); 465 } 466 467 /* 468 * Implemented here due to commonality of the object. 469 */ 470 bool_t 471 xdr_netobj(XDR *xdrs, struct netobj *np) 472 { 473 return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ)); 474 } 475 476 /* 477 * XDR a descriminated union 478 * Support routine for discriminated unions. 479 * You create an array of xdrdiscrim structures, terminated with 480 * an entry with a null procedure pointer. The routine gets 481 * the discriminant value and then searches the array of xdrdiscrims 482 * looking for that value. It calls the procedure given in the xdrdiscrim 483 * to handle the discriminant. If there is no specific routine a default 484 * routine may be called. 485 * If there is no specific or default routine an error is returned. 486 */ 487 bool_t 488 xdr_union(XDR *xdrs, enum_t *dscmp, char *unp, 489 const struct xdr_discrim *choices, const xdrproc_t dfault) 490 { 491 enum_t dscm; 492 493 /* 494 * we deal with the discriminator; it's an enum 495 */ 496 if (!xdr_enum(xdrs, dscmp)) 497 return (FALSE); 498 dscm = *dscmp; 499 500 /* 501 * search choices for a value that matches the discriminator. 502 * if we find one, execute the xdr routine for that value. 503 */ 504 for (; choices->proc != NULL_xdrproc_t; choices++) { 505 if (choices->value == dscm) 506 return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED)); 507 } 508 509 /* 510 * no match - execute the default xdr routine if there is one 511 */ 512 return ((dfault == NULL_xdrproc_t) ? FALSE : 513 (*dfault)(xdrs, unp, LASTUNSIGNED)); 514 } 515 516 517 /* 518 * Non-portable xdr primitives. 519 * Care should be taken when moving these routines to new architectures. 520 */ 521 522 523 /* 524 * XDR null terminated ASCII strings 525 * xdr_string deals with "C strings" - arrays of bytes that are 526 * terminated by a NULL character. The parameter cpp references a 527 * pointer to storage; If the pointer is null, then the necessary 528 * storage is allocated. The last parameter is the max allowed length 529 * of the string as specified by a protocol. 530 */ 531 bool_t 532 xdr_string(XDR *xdrs, char **cpp, const uint_t maxsize) 533 { 534 char *newsp, *sp = *cpp; /* sp is the actual string pointer */ 535 uint_t size, block; 536 uint64_t bytesread; 537 538 /* 539 * first deal with the length since xdr strings are counted-strings 540 */ 541 switch (xdrs->x_op) { 542 case XDR_FREE: 543 if (sp == NULL) 544 return (TRUE); /* already free */ 545 /*FALLTHROUGH*/ 546 case XDR_ENCODE: 547 size = (sp != NULL) ? (uint_t)strlen(sp) : 0; 548 break; 549 } 550 /* 551 * We decided not to use MACRO XDR_U_INT here, because the 552 * advantages here will be miniscule compared to xdr_string. 553 * This saved us 100 bytes in the library size. 554 */ 555 if (!xdr_u_int(xdrs, &size)) 556 return (FALSE); 557 if (size > maxsize) 558 return (FALSE); 559 560 /* 561 * now deal with the actual bytes 562 */ 563 switch (xdrs->x_op) { 564 case XDR_DECODE: 565 /* if buffer is already given, call xdr_opaque() directly */ 566 if (sp != NULL) { 567 if (!xdr_opaque(xdrs, sp, size)) 568 return (FALSE); 569 sp[size] = 0; 570 return (TRUE); 571 } 572 573 /* 574 * We have to allocate a buffer of size 'size'. To avoid 575 * malloc()ing one huge chunk, we'll read the bytes in max 576 * FRAGMENT size blocks and keep realloc()ing. 'block' is 577 * the number of bytes to read in each xdr_opaque() and 578 * 'bytesread' is what we have already read. sp is NULL 579 * when we are in the loop for the first time. 580 */ 581 bytesread = 0; 582 do { 583 block = MIN(size - bytesread, FRAGMENT); 584 /* 585 * allocate enough for 'bytesread + block' bytes and 586 * one extra for the terminating NULL. 587 */ 588 newsp = realloc(sp, bytesread + block + 1); 589 if (newsp == NULL) { 590 if (sp != NULL) 591 free(sp); 592 return (FALSE); 593 } 594 sp = newsp; 595 if (!xdr_opaque(xdrs, &sp[bytesread], block)) { 596 free(sp); 597 return (FALSE); 598 } 599 bytesread += block; 600 } while (bytesread < size); 601 602 sp[bytesread] = 0; /* terminate the string with a NULL */ 603 *cpp = sp; 604 return (TRUE); 605 case XDR_ENCODE: 606 return (xdr_opaque(xdrs, sp, size)); 607 case XDR_FREE: 608 free(sp); 609 *cpp = NULL; 610 return (TRUE); 611 } 612 return (FALSE); 613 } 614 615 bool_t 616 xdr_hyper(XDR *xdrs, longlong_t *hp) 617 { 618 if (xdrs->x_op == XDR_ENCODE) { 619 #if defined(_LONG_LONG_HTOL) 620 if (XDR_PUTINT32(xdrs, (int *)hp) == TRUE) 621 /* LINTED pointer cast */ 622 return (XDR_PUTINT32(xdrs, (int *)((char *)hp + 623 BYTES_PER_XDR_UNIT))); 624 #else 625 /* LINTED pointer cast */ 626 if (XDR_PUTINT32(xdrs, (int *)((char *)hp + 627 BYTES_PER_XDR_UNIT)) == TRUE) 628 return (XDR_PUTINT32(xdrs, (int32_t *)hp)); 629 #endif 630 return (FALSE); 631 } 632 633 if (xdrs->x_op == XDR_DECODE) { 634 #if defined(_LONG_LONG_HTOL) 635 if (XDR_GETINT32(xdrs, (int *)hp) == FALSE || 636 /* LINTED pointer cast */ 637 (XDR_GETINT32(xdrs, (int *)((char *)hp + 638 BYTES_PER_XDR_UNIT)) == FALSE)) 639 return (FALSE); 640 #else 641 /* LINTED pointer cast */ 642 if ((XDR_GETINT32(xdrs, (int *)((char *)hp + 643 BYTES_PER_XDR_UNIT)) == FALSE) || 644 (XDR_GETINT32(xdrs, (int *)hp) == FALSE)) 645 return (FALSE); 646 #endif 647 return (TRUE); 648 } 649 return (TRUE); 650 } 651 652 bool_t 653 xdr_u_hyper(XDR *xdrs, u_longlong_t *hp) 654 { 655 return (xdr_hyper(xdrs, (longlong_t *)hp)); 656 } 657 658 bool_t 659 xdr_longlong_t(XDR *xdrs, longlong_t *hp) 660 { 661 return (xdr_hyper(xdrs, hp)); 662 } 663 664 bool_t 665 xdr_u_longlong_t(XDR *xdrs, u_longlong_t *hp) 666 { 667 return (xdr_hyper(xdrs, (longlong_t *)hp)); 668 } 669 670 /* 671 * Wrapper for xdr_string that can be called directly from 672 * routines like clnt_call 673 */ 674 bool_t 675 xdr_wrapstring(XDR *xdrs, char **cpp) 676 { 677 return (xdr_string(xdrs, cpp, LASTUNSIGNED)); 678 } 679