1#include <rpc/rpc.h> 2#include <string.h> 3 4#define LASTUNSIGNED ((u_int)((int)0-1)) 5 6/* 7 * Primitives for stuffing data into and retrieving data from an XDR 8 */ 9 10bool_t xdr_bytes (XDR *xdr, char **cpp, u_int *sizep, u_int maxsize) 11{ 12 switch(xdr->x_op) { 13 case XDR_DECODE: 14 if(!XDR_RECV_UINT(xdr, sizep) || *sizep > maxsize) 15 return FALSE; 16 if(*sizep == 0) 17 return TRUE; 18 if(*cpp == NULL) 19 *cpp = (char *) mem_alloc(*sizep); 20 if(*cpp == NULL) return FALSE; 21 return XDR_RECV_BYTES(xdr, (uint8 *) *cpp, *sizep); 22 case XDR_ENCODE: 23 return (XDR_SEND_UINT(xdr, sizep) && 24 *sizep <= maxsize && 25 XDR_SEND_BYTES(xdr, (uint8 *) *cpp, *sizep)); 26 case XDR_FREE: 27 if (*cpp) { 28 mem_free(*cpp); 29 *cpp = NULL; 30 } 31 return TRUE; 32 default: 33 break; 34 } 35 return FALSE; 36} /* xdr_bytes */ 37 38bool_t xdr_send_enum (xdr_s_type *xdr, const void *value, uint32 size) 39{ 40 switch (size) { 41 case 4: 42 return XDR_SEND_INT32(xdr, (int32 *) value); 43 case 2: 44 return XDR_SEND_INT16(xdr, (int16 *) value); 45 case 1: 46 return XDR_SEND_INT8(xdr, (int8 *) value); 47 default: 48 return FALSE; 49 } 50} /* xdr_send_enum */ 51 52bool_t xdr_recv_enum (xdr_s_type *xdr, void *value, uint32 size) 53{ 54 switch (size) { 55 case 4: 56 return XDR_RECV_INT32(xdr, (int32 *) value); 57 case 2: 58 return XDR_RECV_INT16(xdr, (int16 *) value); 59 case 1: 60 return XDR_RECV_INT8(xdr, (int8 *) value); 61 default: 62 return FALSE; 63 } 64} /* xdr_recv_enum */ 65 66#include <stdio.h> 67 68bool_t xdr_enum (XDR *xdr, enum_t *ep) 69{ 70 switch(xdr->x_op) { 71 case XDR_ENCODE: 72 return XDR_SEND_INT32(xdr, (int32 *)ep); 73 case XDR_DECODE: 74 return XDR_RECV_INT32(xdr, (int32 *)ep); 75 case XDR_FREE: 76 return TRUE; 77 default: 78 break; 79 } 80 return FALSE; 81} /* xdr_enum */ 82 83bool_t xdr_u_int (XDR *xdr, u_int *uip) 84{ 85 switch(xdr->x_op) { 86 case XDR_ENCODE: 87 return XDR_SEND_UINT32(xdr, (uint32 *) uip); 88 case XDR_DECODE: 89 return XDR_RECV_UINT32(xdr, (uint32 *) uip); 90 case XDR_FREE: 91 return TRUE; 92 default: 93 break; 94 } 95 return FALSE; 96} /* xdr_u_int */ 97 98bool_t xdr_u_char (XDR *xdr, u_char *cp) 99{ 100 u_int u = (*cp); 101 if (!xdr_u_int (xdr, &u)) 102 return FALSE; 103 *cp = (u_char) u; 104 return TRUE; 105} /* xdr_u_char */ 106 107bool_t xdr_long (XDR *xdr, long *lp) 108{ 109 switch (xdr->x_op) { 110 case XDR_ENCODE: 111 return XDR_SEND_INT32(xdr, (int32_t *)lp); 112 case XDR_DECODE: 113 return XDR_RECV_INT32(xdr, (int32_t *)lp); 114 case XDR_FREE: 115 return TRUE; 116 default: 117 break; 118 } 119 return FALSE; 120} /* xdr_long */ 121 122bool_t xdr_u_long (XDR *xdr, u_long *ulp) 123{ 124 switch (xdr->x_op) { 125 case XDR_ENCODE: 126 return XDR_SEND_UINT32(xdr, (uint32_t *)ulp); 127 case XDR_DECODE: 128 return XDR_RECV_UINT32(xdr, (uint32_t *)ulp); 129 case XDR_FREE: 130 return TRUE; 131 default: 132 break; 133 } 134 return FALSE; 135} /* xdr_u_long */ 136 137/* 138 * XDR hyper integers 139 * same as xdr_hyper - open coded to save a proc call! 140 */ 141bool_t xdr_u_hyper (XDR *xdrs, u_quad_t *ullp) 142{ 143 unsigned long t1; 144 unsigned long t2; 145 146 if (xdrs->x_op == XDR_ENCODE) { 147 t1 = (unsigned long) ((*ullp) >> 32); 148 t2 = (unsigned long) (*ullp); 149 return (XDR_SEND_INT32(xdrs, (int32 *)&t1) && 150 XDR_SEND_INT32(xdrs, (int32 *)&t2)); 151 } 152 153 if (xdrs->x_op == XDR_DECODE) { 154 if (!XDR_RECV_INT32(xdrs, (int32 *)&t1) || 155 !XDR_RECV_INT32(xdrs, (int32 *)&t2)) 156 return FALSE; 157 *ullp = ((u_quad_t) t1) << 32; 158 *ullp |= t2; 159 return TRUE; 160 } 161 162 return xdrs->x_op == XDR_FREE; 163} 164 165bool_t 166xdr_u_quad_t (XDR *xdrs, u_quad_t *ullp) 167{ 168 return xdr_u_hyper(xdrs, ullp); 169} 170 171bool_t xdr_u_short (XDR *xdr, u_short *usp) 172{ 173 u_long l; 174 175 switch (xdr->x_op) { 176 case XDR_ENCODE: 177 l = *usp; 178 return XDR_SEND_UINT32(xdr, (uint32_t *)&l); 179 case XDR_DECODE: 180 if(!XDR_RECV_UINT32(xdr, (uint32_t *)&l)) 181 return FALSE; 182 *usp = (u_short)l; 183 return TRUE; 184 case XDR_FREE: 185 return TRUE; 186 default: 187 break; 188 } 189 190 return FALSE; 191} /* xdr_u_short */ 192 193/* 194 * xdr_vector(): 195 * 196 * XDR a fixed length array. Unlike variable-length arrays, 197 * the storage of fixed length arrays is static and unfreeable. 198 * > basep: base of the array 199 * > size: size of the array 200 * > elemsize: size of each element 201 * > xdr_elem: routine to XDR each element 202 */ 203bool_t 204xdr_vector (XDR *xdrs, 205 char *basep, 206 u_int nelem, 207 u_int elemsize, 208 xdrproc_t xdr_elem) 209{ 210 u_int i; 211 char *elptr; 212 213 elptr = basep; 214 for (i = 0; i < nelem; i++) { 215 if (!(*xdr_elem) (xdrs, elptr, LASTUNSIGNED)) 216 return FALSE; 217 elptr += elemsize; 218 } 219 return TRUE; 220} 221 222bool_t xdr_bool (XDR *xdr, bool_t *bp) 223{ 224 uint32 lb; 225 226 switch(xdr->x_op) { 227 case XDR_ENCODE: 228 lb = *bp ? TRUE : FALSE; 229 return XDR_SEND_UINT32(xdr, &lb); 230 case XDR_DECODE: 231 if (!XDR_RECV_UINT32(xdr, &lb)) 232 return FALSE; 233 *bp = (lb == FALSE) ? FALSE : TRUE; 234 return TRUE; 235 case XDR_FREE: 236 return TRUE; 237 default: 238 break; 239 } 240 241 return FALSE; 242} /* xdr_bool */ 243 244/* 245 * XDR an indirect pointer 246 * xdr_reference is for recursively translating a structure that is 247 * referenced by a pointer inside the structure that is currently being 248 * translated. pp references a pointer to storage. If *pp is null 249 * the necessary storage is allocated. 250 * size is the size of the referneced structure. 251 * proc is the routine to handle the referenced structure. 252 */ 253bool_t 254xdr_reference (XDR *xdrs, 255 caddr_t *pp, /* the pointer to work on */ 256 u_int size, /* size of the object pointed to */ 257 xdrproc_t proc) /* xdr routine to handle the object */ 258{ 259 bool_t stat; 260 261 if (*pp == NULL) { 262 switch (xdrs->x_op) { 263 case XDR_FREE: 264 return TRUE; 265 266 case XDR_DECODE: 267 *pp = (caddr_t) mem_alloc (size); 268 if (*pp == NULL) return FALSE; 269 memset(*pp, 0, size); 270 break; 271 default: 272 break; 273 } 274 } 275 276 stat = (*proc) (xdrs, *pp, LASTUNSIGNED); 277 278 if (xdrs->x_op == XDR_FREE) { 279 mem_free(*pp); 280 *pp = NULL; 281 } 282 return stat; 283} /* xdr_reference */ 284 285/* 286 * xdr_pointer(): 287 * 288 * XDR a pointer to a possibly recursive data structure. This 289 * differs with xdr_reference in that it can serialize/deserialize 290 * trees correctly. 291 * 292 * What's sent is actually a union: 293 * 294 * union object_pointer switch (bool_t b) { 295 * case TRUE: object_data data; 296 * case FALSE: void nothing; 297 * } 298 * 299 * > objpp: Pointer to the pointer to the object. 300 * > obj_size: size of the object. 301 * > xdr_obj: routine to XDR an object. 302 * 303 */ 304 305bool_t 306xdr_pointer (XDR *xdrs, 307 char **objpp, 308 u_int obj_size, 309 xdrproc_t xdr_obj) 310{ 311 bool_t more_data; 312 313 more_data = (*objpp != NULL); 314 if (!xdr_bool (xdrs, &more_data)) 315 return FALSE; 316 317 if (!more_data) { 318 *objpp = NULL; 319 return TRUE; 320 } 321 return xdr_reference (xdrs, objpp, obj_size, xdr_obj); 322} /* xdr_pointer */ 323 324bool_t xdr_void (void) 325{ 326 return TRUE; 327} /* xdr_void */ 328 329/* 330 * XDR an array of arbitrary elements 331 * *addrp is a pointer to the array, *sizep is the number of elements. 332 * If addrp is NULL (*sizep * elsize) bytes are allocated. 333 * elsize is the size (in bytes) of each element, and elproc is the 334 * xdr procedure to call to handle each element of the array. 335 */ 336bool_t 337xdr_array (XDR *xdrs, 338 caddr_t *addrp,/* array pointer */ 339 u_int *sizep, /* number of elements */ 340 u_int maxsize, /* max numberof elements */ 341 u_int elsize, /* size in bytes of each element */ 342 xdrproc_t elproc) /* xdr routine to handle each element */ 343{ 344 u_int i; 345 caddr_t target = *addrp; 346 u_int c;/* the actual element count */ 347 bool_t stat = TRUE; 348 u_int nodesize; 349 350 /* like strings, arrays are really counted arrays */ 351 if (!xdr_u_int (xdrs, sizep)) 352 return FALSE; 353 c = *sizep; 354 if ((c > maxsize) && (xdrs->x_op != XDR_FREE)) 355 return FALSE; 356 nodesize = c * elsize; 357 358 /* 359 * if we are deserializing, we may need to allocate an array. 360 * We also save time by checking for a null array if we are freeing. 361 */ 362 if (target == NULL) 363 switch (xdrs->x_op) { 364 case XDR_DECODE: 365 if (c == 0) 366 return TRUE; 367 *addrp = target = mem_alloc (nodesize); 368 if (!*addrp) return FALSE; 369 memset (target, 0, nodesize); 370 break; 371 case XDR_FREE: 372 return TRUE; 373 default: 374 break; 375 } 376 377 /* 378 * now we xdr each element of array 379 */ 380 for (i = 0; (i < c) && stat; i++) { 381 stat = (*elproc) (xdrs, target, LASTUNSIGNED); 382 target += elsize; 383 } 384 385 /* 386 * the array may need freeing 387 */ 388 if (xdrs->x_op == XDR_FREE) { 389 mem_free(*addrp); 390 *addrp = NULL; 391 } 392 393 return stat; 394} 395 396bool_t xdr_int(XDR *xdr, int *ip) 397{ 398 switch (xdr->x_op) { 399 case XDR_ENCODE: 400 return XDR_SEND_INT32(xdr, (int32 *) ip); 401 case XDR_DECODE: 402 return XDR_RECV_INT32(xdr, (int32 *) ip); 403 case XDR_FREE: 404 return TRUE; 405 default: 406 break; 407 } 408 409 return FALSE; 410} /* xdr_int */ 411 412bool_t xdr_opaque (XDR *xdr, caddr_t cp, u_int cnt) 413{ 414 /* if no data we are done */ 415 if (cnt == 0) 416 return TRUE; 417 418 switch (xdr->x_op) { 419 case XDR_ENCODE: 420 return XDR_SEND_BYTES(xdr, (uint8 *) cp, cnt); 421 case XDR_DECODE: 422 return XDR_RECV_BYTES(xdr, (uint8 *) cp, cnt); 423 case XDR_FREE: 424 return TRUE; 425 default: 426 break; 427 } 428 429 return FALSE; 430} /* xdr_opaque */ 431 432bool_t xdr_char (XDR *xdr, char *cp) 433{ 434 int i; 435 i = (*cp); 436 if (!xdr_int (xdr, &i)) 437 return FALSE; 438 *cp = i; 439 return TRUE; 440} /* xdr_char */ 441 442bool_t 443xdr_quad_t (XDR *xdrs, quad_t *llp) 444{ 445 return xdr_u_quad_t(xdrs, (u_quad_t *)llp); 446} 447 448bool_t xdr_short (XDR *xdr, short *sp) 449{ 450 long l; 451 switch (xdr->x_op) { 452 case XDR_ENCODE: 453 l = *sp; 454 return XDR_SEND_INT32(xdr, (int32_t *)&l); 455 case XDR_DECODE: 456 if (!XDR_RECV_INT32(xdr, (int32_t *)&l)) 457 return FALSE; 458 *sp = (short)l; 459 return TRUE; 460 case XDR_FREE: 461 return TRUE; 462 default: 463 break; 464 } 465 return FALSE; 466} /* xdr_short */ 467 468/* 469 * Non-portable xdr primitives. 470 * Care should be taken when moving these routines to new architectures. 471 */ 472 473/* 474 * XDR null terminated ASCII strings 475 * xdr_string deals with "C strings" - arrays of bytes that are 476 * terminated by a NULL character. The parameter cpp references a 477 * pointer to storage; If the pointer is null, then the necessary 478 * storage is allocated. The last parameter is the max allowed length 479 * of the string as specified by a protocol. 480 */ 481bool_t xdr_string (XDR *xdr, char **cpp, u_int maxsize) 482{ 483 u_int size; 484 u_int nodesize; 485 486 /* 487 * first deal with the length since xdr strings are counted-strings 488 */ 489 switch (xdr->x_op) { 490 case XDR_FREE: 491 if (*cpp == NULL) return TRUE; 492 /* fall through... */ 493 case XDR_ENCODE: 494 if (*cpp == NULL) return FALSE; 495 size = strlen(*cpp); 496 break; 497 case XDR_DECODE: 498 break; 499 default: 500 break; 501 } 502 503 if (!xdr_u_int(xdr, &size)) return FALSE; 504 if (size > maxsize) return FALSE; 505 nodesize = size + 1; 506 507 /* 508 * now deal with the actual bytes 509 */ 510 switch (xdr->x_op) { 511 case XDR_DECODE: 512 if (nodesize == 0) return TRUE; 513 if (*cpp == NULL) 514 *cpp = (char *)mem_alloc(nodesize); 515 if (*cpp == NULL) return FALSE; 516 (*cpp)[size] = 0; 517 /* fall through... */ 518 case XDR_ENCODE: 519 return xdr_opaque(xdr, *cpp, size); 520 case XDR_FREE: 521 mem_free(*cpp); 522 *cpp = NULL; 523 return TRUE; 524 default: 525 break; 526 } 527 return FALSE; 528} /* xdr_string */ 529