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 *sccsid = "from: @(#)xdr.c 1.35 87/08/12";*/ 32 /*static char *sccsid = "from: @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC";*/ 33 static char *rcsid = "$Id: xdr.c,v 1.1 1993/10/27 05:41:06 paul Exp $"; 34 #endif 35 36 /* 37 * xdr.c, Generic XDR routines implementation. 38 * 39 * Copyright (C) 1986, Sun Microsystems, Inc. 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 46 #include <stdio.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 * XDR integers 92 */ 93 bool_t 94 xdr_int(xdrs, ip) 95 XDR *xdrs; 96 int *ip; 97 { 98 99 #ifdef lint 100 (void) (xdr_short(xdrs, (short *)ip)); 101 return (xdr_long(xdrs, (long *)ip)); 102 #else 103 if (sizeof (int) == sizeof (long)) { 104 return (xdr_long(xdrs, (long *)ip)); 105 } else { 106 return (xdr_short(xdrs, (short *)ip)); 107 } 108 #endif 109 } 110 111 /* 112 * XDR unsigned integers 113 */ 114 bool_t 115 xdr_u_int(xdrs, up) 116 XDR *xdrs; 117 u_int *up; 118 { 119 120 #ifdef lint 121 (void) (xdr_short(xdrs, (short *)up)); 122 return (xdr_u_long(xdrs, (u_long *)up)); 123 #else 124 if (sizeof (u_int) == sizeof (u_long)) { 125 return (xdr_u_long(xdrs, (u_long *)up)); 126 } else { 127 return (xdr_short(xdrs, (short *)up)); 128 } 129 #endif 130 } 131 132 /* 133 * XDR long integers 134 * same as xdr_u_long - open coded to save a proc call! 135 */ 136 bool_t 137 xdr_long(xdrs, lp) 138 register XDR *xdrs; 139 long *lp; 140 { 141 142 if (xdrs->x_op == XDR_ENCODE) 143 return (XDR_PUTLONG(xdrs, lp)); 144 145 if (xdrs->x_op == XDR_DECODE) 146 return (XDR_GETLONG(xdrs, lp)); 147 148 if (xdrs->x_op == XDR_FREE) 149 return (TRUE); 150 151 return (FALSE); 152 } 153 154 /* 155 * XDR unsigned long integers 156 * same as xdr_long - open coded to save a proc call! 157 */ 158 bool_t 159 xdr_u_long(xdrs, ulp) 160 register XDR *xdrs; 161 u_long *ulp; 162 { 163 164 if (xdrs->x_op == XDR_DECODE) 165 return (XDR_GETLONG(xdrs, (long *)ulp)); 166 if (xdrs->x_op == XDR_ENCODE) 167 return (XDR_PUTLONG(xdrs, (long *)ulp)); 168 if (xdrs->x_op == XDR_FREE) 169 return (TRUE); 170 return (FALSE); 171 } 172 173 /* 174 * XDR short integers 175 */ 176 bool_t 177 xdr_short(xdrs, sp) 178 register XDR *xdrs; 179 short *sp; 180 { 181 long l; 182 183 switch (xdrs->x_op) { 184 185 case XDR_ENCODE: 186 l = (long) *sp; 187 return (XDR_PUTLONG(xdrs, &l)); 188 189 case XDR_DECODE: 190 if (!XDR_GETLONG(xdrs, &l)) { 191 return (FALSE); 192 } 193 *sp = (short) l; 194 return (TRUE); 195 196 case XDR_FREE: 197 return (TRUE); 198 } 199 return (FALSE); 200 } 201 202 /* 203 * XDR unsigned short integers 204 */ 205 bool_t 206 xdr_u_short(xdrs, usp) 207 register XDR *xdrs; 208 u_short *usp; 209 { 210 u_long l; 211 212 switch (xdrs->x_op) { 213 214 case XDR_ENCODE: 215 l = (u_long) *usp; 216 return (XDR_PUTLONG(xdrs, &l)); 217 218 case XDR_DECODE: 219 if (!XDR_GETLONG(xdrs, &l)) { 220 return (FALSE); 221 } 222 *usp = (u_short) l; 223 return (TRUE); 224 225 case XDR_FREE: 226 return (TRUE); 227 } 228 return (FALSE); 229 } 230 231 232 /* 233 * XDR a char 234 */ 235 bool_t 236 xdr_char(xdrs, cp) 237 XDR *xdrs; 238 char *cp; 239 { 240 int i; 241 242 i = (*cp); 243 if (!xdr_int(xdrs, &i)) { 244 return (FALSE); 245 } 246 *cp = i; 247 return (TRUE); 248 } 249 250 /* 251 * XDR an unsigned char 252 */ 253 bool_t 254 xdr_u_char(xdrs, cp) 255 XDR *xdrs; 256 char *cp; 257 { 258 u_int u; 259 260 u = (*cp); 261 if (!xdr_u_int(xdrs, &u)) { 262 return (FALSE); 263 } 264 *cp = u; 265 return (TRUE); 266 } 267 268 /* 269 * XDR booleans 270 */ 271 bool_t 272 xdr_bool(xdrs, bp) 273 register XDR *xdrs; 274 bool_t *bp; 275 { 276 long lb; 277 278 switch (xdrs->x_op) { 279 280 case XDR_ENCODE: 281 lb = *bp ? XDR_TRUE : XDR_FALSE; 282 return (XDR_PUTLONG(xdrs, &lb)); 283 284 case XDR_DECODE: 285 if (!XDR_GETLONG(xdrs, &lb)) { 286 return (FALSE); 287 } 288 *bp = (lb == XDR_FALSE) ? FALSE : TRUE; 289 return (TRUE); 290 291 case XDR_FREE: 292 return (TRUE); 293 } 294 return (FALSE); 295 } 296 297 /* 298 * XDR enumerations 299 */ 300 bool_t 301 xdr_enum(xdrs, ep) 302 XDR *xdrs; 303 enum_t *ep; 304 { 305 #ifndef lint 306 enum sizecheck { SIZEVAL }; /* used to find the size of an enum */ 307 308 /* 309 * enums are treated as ints 310 */ 311 if (sizeof (enum sizecheck) == sizeof (long)) { 312 return (xdr_long(xdrs, (long *)ep)); 313 } else if (sizeof (enum sizecheck) == sizeof (short)) { 314 return (xdr_short(xdrs, (short *)ep)); 315 } else { 316 return (FALSE); 317 } 318 #else 319 (void) (xdr_short(xdrs, (short *)ep)); 320 return (xdr_long(xdrs, (long *)ep)); 321 #endif 322 } 323 324 /* 325 * XDR opaque data 326 * Allows the specification of a fixed size sequence of opaque bytes. 327 * cp points to the opaque object and cnt gives the byte length. 328 */ 329 bool_t 330 xdr_opaque(xdrs, cp, cnt) 331 register XDR *xdrs; 332 caddr_t cp; 333 register u_int cnt; 334 { 335 register u_int rndup; 336 static crud[BYTES_PER_XDR_UNIT]; 337 338 /* 339 * if no data we are done 340 */ 341 if (cnt == 0) 342 return (TRUE); 343 344 /* 345 * round byte count to full xdr units 346 */ 347 rndup = cnt % BYTES_PER_XDR_UNIT; 348 if (rndup > 0) 349 rndup = BYTES_PER_XDR_UNIT - rndup; 350 351 if (xdrs->x_op == XDR_DECODE) { 352 if (!XDR_GETBYTES(xdrs, cp, cnt)) { 353 return (FALSE); 354 } 355 if (rndup == 0) 356 return (TRUE); 357 return (XDR_GETBYTES(xdrs, crud, rndup)); 358 } 359 360 if (xdrs->x_op == XDR_ENCODE) { 361 if (!XDR_PUTBYTES(xdrs, cp, cnt)) { 362 return (FALSE); 363 } 364 if (rndup == 0) 365 return (TRUE); 366 return (XDR_PUTBYTES(xdrs, xdr_zero, rndup)); 367 } 368 369 if (xdrs->x_op == XDR_FREE) { 370 return (TRUE); 371 } 372 373 return (FALSE); 374 } 375 376 /* 377 * XDR counted bytes 378 * *cpp is a pointer to the bytes, *sizep is the count. 379 * If *cpp is NULL maxsize bytes are allocated 380 */ 381 bool_t 382 xdr_bytes(xdrs, cpp, sizep, maxsize) 383 register XDR *xdrs; 384 char **cpp; 385 register u_int *sizep; 386 u_int maxsize; 387 { 388 register char *sp = *cpp; /* sp is the actual string pointer */ 389 register u_int nodesize; 390 391 /* 392 * first deal with the length since xdr bytes are counted 393 */ 394 if (! xdr_u_int(xdrs, sizep)) { 395 return (FALSE); 396 } 397 nodesize = *sizep; 398 if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) { 399 return (FALSE); 400 } 401 402 /* 403 * now deal with the actual bytes 404 */ 405 switch (xdrs->x_op) { 406 407 case XDR_DECODE: 408 if (nodesize == 0) { 409 return (TRUE); 410 } 411 if (sp == NULL) { 412 *cpp = sp = (char *)mem_alloc(nodesize); 413 } 414 if (sp == NULL) { 415 (void) fprintf(stderr, "xdr_bytes: out of memory\n"); 416 return (FALSE); 417 } 418 /* fall into ... */ 419 420 case XDR_ENCODE: 421 return (xdr_opaque(xdrs, sp, nodesize)); 422 423 case XDR_FREE: 424 if (sp != NULL) { 425 mem_free(sp, nodesize); 426 *cpp = NULL; 427 } 428 return (TRUE); 429 } 430 return (FALSE); 431 } 432 433 /* 434 * Implemented here due to commonality of the object. 435 */ 436 bool_t 437 xdr_netobj(xdrs, np) 438 XDR *xdrs; 439 struct netobj *np; 440 { 441 442 return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ)); 443 } 444 445 /* 446 * XDR a descriminated union 447 * Support routine for discriminated unions. 448 * You create an array of xdrdiscrim structures, terminated with 449 * an entry with a null procedure pointer. The routine gets 450 * the discriminant value and then searches the array of xdrdiscrims 451 * looking for that value. It calls the procedure given in the xdrdiscrim 452 * to handle the discriminant. If there is no specific routine a default 453 * routine may be called. 454 * If there is no specific or default routine an error is returned. 455 */ 456 bool_t 457 xdr_union(xdrs, dscmp, unp, choices, dfault) 458 register XDR *xdrs; 459 enum_t *dscmp; /* enum to decide which arm to work on */ 460 char *unp; /* the union itself */ 461 struct xdr_discrim *choices; /* [value, xdr proc] for each arm */ 462 xdrproc_t dfault; /* default xdr routine */ 463 { 464 register enum_t dscm; 465 466 /* 467 * we deal with the discriminator; it's an enum 468 */ 469 if (! xdr_enum(xdrs, dscmp)) { 470 return (FALSE); 471 } 472 dscm = *dscmp; 473 474 /* 475 * search choices for a value that matches the discriminator. 476 * if we find one, execute the xdr routine for that value. 477 */ 478 for (; choices->proc != NULL_xdrproc_t; choices++) { 479 if (choices->value == dscm) 480 return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED)); 481 } 482 483 /* 484 * no match - execute the default xdr routine if there is one 485 */ 486 return ((dfault == NULL_xdrproc_t) ? FALSE : 487 (*dfault)(xdrs, unp, LASTUNSIGNED)); 488 } 489 490 491 /* 492 * Non-portable xdr primitives. 493 * Care should be taken when moving these routines to new architectures. 494 */ 495 496 497 /* 498 * XDR null terminated ASCII strings 499 * xdr_string deals with "C strings" - arrays of bytes that are 500 * terminated by a NULL character. The parameter cpp references a 501 * pointer to storage; If the pointer is null, then the necessary 502 * storage is allocated. The last parameter is the max allowed length 503 * of the string as specified by a protocol. 504 */ 505 bool_t 506 xdr_string(xdrs, cpp, maxsize) 507 register XDR *xdrs; 508 char **cpp; 509 u_int maxsize; 510 { 511 register char *sp = *cpp; /* sp is the actual string pointer */ 512 u_int size; 513 u_int nodesize; 514 515 /* 516 * first deal with the length since xdr strings are counted-strings 517 */ 518 switch (xdrs->x_op) { 519 case XDR_FREE: 520 if (sp == NULL) { 521 return(TRUE); /* already free */ 522 } 523 /* fall through... */ 524 case XDR_ENCODE: 525 size = strlen(sp); 526 break; 527 } 528 if (! xdr_u_int(xdrs, &size)) { 529 return (FALSE); 530 } 531 if (size > maxsize) { 532 return (FALSE); 533 } 534 nodesize = size + 1; 535 536 /* 537 * now deal with the actual bytes 538 */ 539 switch (xdrs->x_op) { 540 541 case XDR_DECODE: 542 if (nodesize == 0) { 543 return (TRUE); 544 } 545 if (sp == NULL) 546 *cpp = sp = (char *)mem_alloc(nodesize); 547 if (sp == NULL) { 548 (void) fprintf(stderr, "xdr_string: out of memory\n"); 549 return (FALSE); 550 } 551 sp[size] = 0; 552 /* fall into ... */ 553 554 case XDR_ENCODE: 555 return (xdr_opaque(xdrs, sp, size)); 556 557 case XDR_FREE: 558 mem_free(sp, nodesize); 559 *cpp = NULL; 560 return (TRUE); 561 } 562 return (FALSE); 563 } 564 565 /* 566 * Wrapper for xdr_string that can be called directly from 567 * routines like clnt_call 568 */ 569 bool_t 570 xdr_wrapstring(xdrs, cpp) 571 XDR *xdrs; 572 char **cpp; 573 { 574 if (xdr_string(xdrs, cpp, LASTUNSIGNED)) { 575 return (TRUE); 576 } 577 return (FALSE); 578 } 579