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