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 /* 37 * Generic XDR routines implementation. 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 #include "mt.h" 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 * round byte count to full xdr units 385 */ 386 rndup = cnt % BYTES_PER_XDR_UNIT; 387 if ((int)rndup > 0) 388 rndup = BYTES_PER_XDR_UNIT - rndup; 389 390 switch (xdrs->x_op) { 391 case XDR_DECODE: 392 if (!XDR_GETBYTES(xdrs, cp, cnt)) 393 return (FALSE); 394 if (rndup == 0) 395 return (TRUE); 396 return (XDR_GETBYTES(xdrs, crud, rndup)); 397 case XDR_ENCODE: 398 if (!XDR_PUTBYTES(xdrs, cp, cnt)) 399 return (FALSE); 400 if (rndup == 0) 401 return (TRUE); 402 return (XDR_PUTBYTES(xdrs, (caddr_t)&xdr_zero[0], rndup)); 403 case XDR_FREE: 404 return (TRUE); 405 } 406 return (FALSE); 407 } 408 409 /* 410 * XDR counted bytes 411 * *cpp is a pointer to the bytes, *sizep is the count. 412 * If *cpp is NULL maxsize bytes are allocated 413 */ 414 415 static const char xdr_err[] = "xdr_%s: out of memory"; 416 417 bool_t 418 xdr_bytes(XDR *xdrs, char **cpp, uint_t *sizep, const uint_t maxsize) 419 { 420 char *sp = *cpp; /* sp is the actual string pointer */ 421 uint_t nodesize; 422 423 /* 424 * first deal with the length since xdr bytes are counted 425 * We decided not to use MACRO XDR_U_INT here, because the 426 * advantages here will be miniscule compared to xdr_bytes. 427 * This saved us 100 bytes in the library size. 428 */ 429 if (!xdr_u_int(xdrs, sizep)) 430 return (FALSE); 431 nodesize = *sizep; 432 if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) 433 return (FALSE); 434 435 /* 436 * now deal with the actual bytes 437 */ 438 switch (xdrs->x_op) { 439 case XDR_DECODE: 440 if (nodesize == 0) 441 return (TRUE); 442 if (sp == NULL) 443 *cpp = sp = malloc(nodesize); 444 if (sp == NULL) { 445 (void) syslog(LOG_ERR, xdr_err, (const char *)"bytes"); 446 return (FALSE); 447 } 448 /*FALLTHROUGH*/ 449 case XDR_ENCODE: 450 return (xdr_opaque(xdrs, sp, nodesize)); 451 case XDR_FREE: 452 if (sp != NULL) { 453 free(sp); 454 *cpp = NULL; 455 } 456 return (TRUE); 457 } 458 return (FALSE); 459 } 460 461 /* 462 * Implemented here due to commonality of the object. 463 */ 464 bool_t 465 xdr_netobj(XDR *xdrs, struct netobj *np) 466 { 467 return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ)); 468 } 469 470 /* 471 * XDR a descriminated union 472 * Support routine for discriminated unions. 473 * You create an array of xdrdiscrim structures, terminated with 474 * an entry with a null procedure pointer. The routine gets 475 * the discriminant value and then searches the array of xdrdiscrims 476 * looking for that value. It calls the procedure given in the xdrdiscrim 477 * to handle the discriminant. If there is no specific routine a default 478 * routine may be called. 479 * If there is no specific or default routine an error is returned. 480 */ 481 bool_t 482 xdr_union(XDR *xdrs, enum_t *dscmp, char *unp, 483 const struct xdr_discrim *choices, const xdrproc_t dfault) 484 { 485 enum_t dscm; 486 487 /* 488 * we deal with the discriminator; it's an enum 489 */ 490 if (!xdr_enum(xdrs, dscmp)) 491 return (FALSE); 492 dscm = *dscmp; 493 494 /* 495 * search choices for a value that matches the discriminator. 496 * if we find one, execute the xdr routine for that value. 497 */ 498 for (; choices->proc != NULL_xdrproc_t; choices++) { 499 if (choices->value == dscm) 500 return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED)); 501 } 502 503 /* 504 * no match - execute the default xdr routine if there is one 505 */ 506 return ((dfault == NULL_xdrproc_t) ? FALSE : 507 (*dfault)(xdrs, unp, LASTUNSIGNED)); 508 } 509 510 511 /* 512 * Non-portable xdr primitives. 513 * Care should be taken when moving these routines to new architectures. 514 */ 515 516 517 /* 518 * XDR null terminated ASCII strings 519 * xdr_string deals with "C strings" - arrays of bytes that are 520 * terminated by a NULL character. The parameter cpp references a 521 * pointer to storage; If the pointer is null, then the necessary 522 * storage is allocated. The last parameter is the max allowed length 523 * of the string as specified by a protocol. 524 */ 525 bool_t 526 xdr_string(XDR *xdrs, char **cpp, const uint_t maxsize) 527 { 528 char *newsp, *sp = *cpp; /* sp is the actual string pointer */ 529 uint_t size, block; 530 uint64_t bytesread; 531 532 /* 533 * first deal with the length since xdr strings are counted-strings 534 */ 535 switch (xdrs->x_op) { 536 case XDR_FREE: 537 if (sp == NULL) 538 return (TRUE); /* already free */ 539 /*FALLTHROUGH*/ 540 case XDR_ENCODE: 541 size = (sp != NULL) ? (uint_t)strlen(sp) : 0; 542 break; 543 } 544 /* 545 * We decided not to use MACRO XDR_U_INT here, because the 546 * advantages here will be miniscule compared to xdr_string. 547 * This saved us 100 bytes in the library size. 548 */ 549 if (!xdr_u_int(xdrs, &size)) 550 return (FALSE); 551 if (size > maxsize) 552 return (FALSE); 553 554 /* 555 * now deal with the actual bytes 556 */ 557 switch (xdrs->x_op) { 558 case XDR_DECODE: 559 /* if buffer is already given, call xdr_opaque() directly */ 560 if (sp != NULL) { 561 if (!xdr_opaque(xdrs, sp, size)) 562 return (FALSE); 563 sp[size] = 0; 564 return (TRUE); 565 } 566 567 /* 568 * We have to allocate a buffer of size 'size'. To avoid 569 * malloc()ing one huge chunk, we'll read the bytes in max 570 * FRAGMENT size blocks and keep realloc()ing. 'block' is 571 * the number of bytes to read in each xdr_opaque() and 572 * 'bytesread' is what we have already read. sp is NULL 573 * when we are in the loop for the first time. 574 */ 575 bytesread = 0; 576 do { 577 block = MIN(size - bytesread, FRAGMENT); 578 /* 579 * allocate enough for 'bytesread + block' bytes and 580 * one extra for the terminating NULL. 581 */ 582 newsp = realloc(sp, bytesread + block + 1); 583 if (newsp == NULL) { 584 if (sp != NULL) 585 free(sp); 586 return (FALSE); 587 } 588 sp = newsp; 589 if (!xdr_opaque(xdrs, &sp[bytesread], block)) { 590 free(sp); 591 return (FALSE); 592 } 593 bytesread += block; 594 } while (bytesread < size); 595 596 sp[bytesread] = 0; /* terminate the string with a NULL */ 597 *cpp = sp; 598 return (TRUE); 599 case XDR_ENCODE: 600 return (xdr_opaque(xdrs, sp, size)); 601 case XDR_FREE: 602 free(sp); 603 *cpp = NULL; 604 return (TRUE); 605 } 606 return (FALSE); 607 } 608 609 bool_t 610 xdr_hyper(XDR *xdrs, longlong_t *hp) 611 { 612 switch (xdrs->x_op) { 613 case XDR_ENCODE: 614 #if defined(_LONG_LONG_HTOL) 615 if (XDR_PUTINT32(xdrs, (int *)hp) == TRUE) 616 /* LINTED pointer cast */ 617 return (XDR_PUTINT32(xdrs, (int *)((char *)hp + 618 BYTES_PER_XDR_UNIT))); 619 #else 620 /* LINTED pointer cast */ 621 if (XDR_PUTINT32(xdrs, (int *)((char *)hp + 622 BYTES_PER_XDR_UNIT)) == TRUE) 623 return (XDR_PUTINT32(xdrs, (int32_t *)hp)); 624 #endif 625 return (FALSE); 626 case XDR_DECODE: 627 #if defined(_LONG_LONG_HTOL) 628 if (XDR_GETINT32(xdrs, (int *)hp) == FALSE || 629 /* LINTED pointer cast */ 630 (XDR_GETINT32(xdrs, (int *)((char *)hp + 631 BYTES_PER_XDR_UNIT)) == FALSE)) 632 return (FALSE); 633 #else 634 /* LINTED pointer cast */ 635 if ((XDR_GETINT32(xdrs, (int *)((char *)hp + 636 BYTES_PER_XDR_UNIT)) == FALSE) || 637 (XDR_GETINT32(xdrs, (int *)hp) == FALSE)) 638 return (FALSE); 639 #endif 640 return (TRUE); 641 case XDR_FREE: 642 return (TRUE); 643 } 644 return (FALSE); 645 } 646 647 bool_t 648 xdr_u_hyper(XDR *xdrs, u_longlong_t *hp) 649 { 650 return (xdr_hyper(xdrs, (longlong_t *)hp)); 651 } 652 653 bool_t 654 xdr_longlong_t(XDR *xdrs, longlong_t *hp) 655 { 656 return (xdr_hyper(xdrs, hp)); 657 } 658 659 bool_t 660 xdr_u_longlong_t(XDR *xdrs, u_longlong_t *hp) 661 { 662 return (xdr_hyper(xdrs, (longlong_t *)hp)); 663 } 664 665 /* 666 * Wrapper for xdr_string that can be called directly from 667 * routines like clnt_call 668 */ 669 bool_t 670 xdr_wrapstring(XDR *xdrs, char **cpp) 671 { 672 return (xdr_string(xdrs, cpp, LASTUNSIGNED)); 673 } 674