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