1177633Sdfr/* $NetBSD: xdr.c,v 1.22 2000/07/06 03:10:35 christos Exp $ */ 2177633Sdfr 3177633Sdfr/* 4177633Sdfr * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5177633Sdfr * unrestricted use provided that this legend is included on all tape 6177633Sdfr * media and as a part of the software program in whole or part. Users 7177633Sdfr * may copy or modify Sun RPC without charge, but are not authorized 8177633Sdfr * to license or distribute it to anyone else except as part of a product or 9177633Sdfr * program developed by the user. 10177633Sdfr * 11177633Sdfr * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12177633Sdfr * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13177633Sdfr * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14177633Sdfr * 15177633Sdfr * Sun RPC is provided with no support and without any obligation on the 16177633Sdfr * part of Sun Microsystems, Inc. to assist in its use, correction, 17177633Sdfr * modification or enhancement. 18177633Sdfr * 19177633Sdfr * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20177633Sdfr * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21177633Sdfr * OR ANY PART THEREOF. 22177633Sdfr * 23177633Sdfr * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24177633Sdfr * or profits or other special, indirect and consequential damages, even if 25177633Sdfr * Sun has been advised of the possibility of such damages. 26177633Sdfr * 27177633Sdfr * Sun Microsystems, Inc. 28177633Sdfr * 2550 Garcia Avenue 29177633Sdfr * Mountain View, California 94043 30177633Sdfr */ 31177633Sdfr 32177633Sdfr#if defined(LIBC_SCCS) && !defined(lint) 33177633Sdfrstatic char *sccsid2 = "@(#)xdr.c 1.35 87/08/12"; 34177633Sdfrstatic char *sccsid = "@(#)xdr.c 2.1 88/07/29 4.0 RPCSRC"; 35177633Sdfr#endif 36177633Sdfr#include <sys/cdefs.h> 37177633Sdfr__FBSDID("$FreeBSD$"); 38177633Sdfr 39177633Sdfr/* 40177633Sdfr * xdr.c, Generic XDR routines implementation. 41177633Sdfr * 42177633Sdfr * Copyright (C) 1986, Sun Microsystems, Inc. 43177633Sdfr * 44177633Sdfr * These are the "generic" xdr routines used to serialize and de-serialize 45177633Sdfr * most common data items. See xdr.h for more info on the interface to 46177633Sdfr * xdr. 47177633Sdfr */ 48177633Sdfr 49177633Sdfr#include <sys/param.h> 50177633Sdfr#include <sys/systm.h> 51177633Sdfr#include <sys/kernel.h> 52177633Sdfr#include <sys/malloc.h> 53177633Sdfr 54177633Sdfr#include <rpc/types.h> 55177633Sdfr#include <rpc/xdr.h> 56177633Sdfr 57177633Sdfrtypedef quad_t longlong_t; /* ANSI long long type */ 58177633Sdfrtypedef u_quad_t u_longlong_t; /* ANSI unsigned long long type */ 59177633Sdfr 60177633Sdfr/* 61177633Sdfr * constants specific to the xdr "protocol" 62177633Sdfr */ 63177633Sdfr#define XDR_FALSE ((long) 0) 64177633Sdfr#define XDR_TRUE ((long) 1) 65177633Sdfr#define LASTUNSIGNED ((u_int) 0-1) 66177633Sdfr 67177633Sdfr/* 68177633Sdfr * for unit alignment 69177633Sdfr */ 70177633Sdfrstatic const char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 }; 71177633Sdfr 72177633Sdfr/* 73177633Sdfr * Free a data structure using XDR 74177633Sdfr * Not a filter, but a convenient utility nonetheless 75177633Sdfr */ 76177633Sdfrvoid 77177633Sdfrxdr_free(xdrproc_t proc, void *objp) 78177633Sdfr{ 79177633Sdfr XDR x; 80177633Sdfr 81177633Sdfr x.x_op = XDR_FREE; 82177633Sdfr (*proc)(&x, objp); 83177633Sdfr} 84177633Sdfr 85177633Sdfr/* 86177633Sdfr * XDR nothing 87177633Sdfr */ 88177633Sdfrbool_t 89177633Sdfrxdr_void(void) 90177633Sdfr{ 91177633Sdfr 92177633Sdfr return (TRUE); 93177633Sdfr} 94177633Sdfr 95177633Sdfr 96177633Sdfr/* 97177633Sdfr * XDR integers 98177633Sdfr */ 99177633Sdfrbool_t 100177633Sdfrxdr_int(XDR *xdrs, int *ip) 101177633Sdfr{ 102177633Sdfr long l; 103177633Sdfr 104177633Sdfr switch (xdrs->x_op) { 105177633Sdfr 106177633Sdfr case XDR_ENCODE: 107177633Sdfr l = (long) *ip; 108177633Sdfr return (XDR_PUTLONG(xdrs, &l)); 109177633Sdfr 110177633Sdfr case XDR_DECODE: 111177633Sdfr if (!XDR_GETLONG(xdrs, &l)) { 112177633Sdfr return (FALSE); 113177633Sdfr } 114177633Sdfr *ip = (int) l; 115177633Sdfr return (TRUE); 116177633Sdfr 117177633Sdfr case XDR_FREE: 118177633Sdfr return (TRUE); 119177633Sdfr } 120177633Sdfr /* NOTREACHED */ 121177633Sdfr return (FALSE); 122177633Sdfr} 123177633Sdfr 124177633Sdfr/* 125177633Sdfr * XDR unsigned integers 126177633Sdfr */ 127177633Sdfrbool_t 128177633Sdfrxdr_u_int(XDR *xdrs, u_int *up) 129177633Sdfr{ 130177633Sdfr u_long l; 131177633Sdfr 132177633Sdfr switch (xdrs->x_op) { 133177633Sdfr 134177633Sdfr case XDR_ENCODE: 135177633Sdfr l = (u_long) *up; 136177633Sdfr return (XDR_PUTLONG(xdrs, (long *)&l)); 137177633Sdfr 138177633Sdfr case XDR_DECODE: 139177633Sdfr if (!XDR_GETLONG(xdrs, (long *)&l)) { 140177633Sdfr return (FALSE); 141177633Sdfr } 142177633Sdfr *up = (u_int) l; 143177633Sdfr return (TRUE); 144177633Sdfr 145177633Sdfr case XDR_FREE: 146177633Sdfr return (TRUE); 147177633Sdfr } 148177633Sdfr /* NOTREACHED */ 149177633Sdfr return (FALSE); 150177633Sdfr} 151177633Sdfr 152177633Sdfr 153177633Sdfr/* 154177633Sdfr * XDR long integers 155177633Sdfr * same as xdr_u_long - open coded to save a proc call! 156177633Sdfr */ 157177633Sdfrbool_t 158177633Sdfrxdr_long(XDR *xdrs, long *lp) 159177633Sdfr{ 160177633Sdfr switch (xdrs->x_op) { 161177633Sdfr case XDR_ENCODE: 162177633Sdfr return (XDR_PUTLONG(xdrs, lp)); 163177633Sdfr case XDR_DECODE: 164177633Sdfr return (XDR_GETLONG(xdrs, lp)); 165177633Sdfr case XDR_FREE: 166177633Sdfr return (TRUE); 167177633Sdfr } 168177633Sdfr /* NOTREACHED */ 169177633Sdfr return (FALSE); 170177633Sdfr} 171177633Sdfr 172177633Sdfr/* 173177633Sdfr * XDR unsigned long integers 174177633Sdfr * same as xdr_long - open coded to save a proc call! 175177633Sdfr */ 176177633Sdfrbool_t 177177633Sdfrxdr_u_long(XDR *xdrs, u_long *ulp) 178177633Sdfr{ 179177633Sdfr switch (xdrs->x_op) { 180177633Sdfr case XDR_ENCODE: 181177633Sdfr return (XDR_PUTLONG(xdrs, (long *)ulp)); 182177633Sdfr case XDR_DECODE: 183177633Sdfr return (XDR_GETLONG(xdrs, (long *)ulp)); 184177633Sdfr case XDR_FREE: 185177633Sdfr return (TRUE); 186177633Sdfr } 187177633Sdfr /* NOTREACHED */ 188177633Sdfr return (FALSE); 189177633Sdfr} 190177633Sdfr 191177633Sdfr 192177633Sdfr/* 193177633Sdfr * XDR 32-bit integers 194177633Sdfr * same as xdr_uint32_t - open coded to save a proc call! 195177633Sdfr */ 196177633Sdfrbool_t 197177633Sdfrxdr_int32_t(XDR *xdrs, int32_t *int32_p) 198177633Sdfr{ 199177633Sdfr long l; 200177633Sdfr 201177633Sdfr switch (xdrs->x_op) { 202177633Sdfr 203177633Sdfr case XDR_ENCODE: 204177633Sdfr l = (long) *int32_p; 205177633Sdfr return (XDR_PUTLONG(xdrs, &l)); 206177633Sdfr 207177633Sdfr case XDR_DECODE: 208177633Sdfr if (!XDR_GETLONG(xdrs, &l)) { 209177633Sdfr return (FALSE); 210177633Sdfr } 211177633Sdfr *int32_p = (int32_t) l; 212177633Sdfr return (TRUE); 213177633Sdfr 214177633Sdfr case XDR_FREE: 215177633Sdfr return (TRUE); 216177633Sdfr } 217177633Sdfr /* NOTREACHED */ 218177633Sdfr return (FALSE); 219177633Sdfr} 220177633Sdfr 221177633Sdfr/* 222177633Sdfr * XDR unsigned 32-bit integers 223177633Sdfr * same as xdr_int32_t - open coded to save a proc call! 224177633Sdfr */ 225177633Sdfrbool_t 226177633Sdfrxdr_uint32_t(XDR *xdrs, uint32_t *uint32_p) 227177633Sdfr{ 228177633Sdfr u_long l; 229177633Sdfr 230177633Sdfr switch (xdrs->x_op) { 231177633Sdfr 232177633Sdfr case XDR_ENCODE: 233177633Sdfr l = (u_long) *uint32_p; 234177633Sdfr return (XDR_PUTLONG(xdrs, (long *)&l)); 235177633Sdfr 236177633Sdfr case XDR_DECODE: 237177633Sdfr if (!XDR_GETLONG(xdrs, (long *)&l)) { 238177633Sdfr return (FALSE); 239177633Sdfr } 240177633Sdfr *uint32_p = (uint32_t) l; 241177633Sdfr return (TRUE); 242177633Sdfr 243177633Sdfr case XDR_FREE: 244177633Sdfr return (TRUE); 245177633Sdfr } 246177633Sdfr /* NOTREACHED */ 247177633Sdfr return (FALSE); 248177633Sdfr} 249177633Sdfr 250177633Sdfr 251177633Sdfr/* 252177633Sdfr * XDR short integers 253177633Sdfr */ 254177633Sdfrbool_t 255177633Sdfrxdr_short(XDR *xdrs, short *sp) 256177633Sdfr{ 257177633Sdfr long l; 258177633Sdfr 259177633Sdfr switch (xdrs->x_op) { 260177633Sdfr 261177633Sdfr case XDR_ENCODE: 262177633Sdfr l = (long) *sp; 263177633Sdfr return (XDR_PUTLONG(xdrs, &l)); 264177633Sdfr 265177633Sdfr case XDR_DECODE: 266177633Sdfr if (!XDR_GETLONG(xdrs, &l)) { 267177633Sdfr return (FALSE); 268177633Sdfr } 269177633Sdfr *sp = (short) l; 270177633Sdfr return (TRUE); 271177633Sdfr 272177633Sdfr case XDR_FREE: 273177633Sdfr return (TRUE); 274177633Sdfr } 275177633Sdfr /* NOTREACHED */ 276177633Sdfr return (FALSE); 277177633Sdfr} 278177633Sdfr 279177633Sdfr/* 280177633Sdfr * XDR unsigned short integers 281177633Sdfr */ 282177633Sdfrbool_t 283177633Sdfrxdr_u_short(XDR *xdrs, u_short *usp) 284177633Sdfr{ 285177633Sdfr u_long l; 286177633Sdfr 287177633Sdfr switch (xdrs->x_op) { 288177633Sdfr 289177633Sdfr case XDR_ENCODE: 290177633Sdfr l = (u_long) *usp; 291177633Sdfr return (XDR_PUTLONG(xdrs, (long *)&l)); 292177633Sdfr 293177633Sdfr case XDR_DECODE: 294177633Sdfr if (!XDR_GETLONG(xdrs, (long *)&l)) { 295177633Sdfr return (FALSE); 296177633Sdfr } 297177633Sdfr *usp = (u_short) l; 298177633Sdfr return (TRUE); 299177633Sdfr 300177633Sdfr case XDR_FREE: 301177633Sdfr return (TRUE); 302177633Sdfr } 303177633Sdfr /* NOTREACHED */ 304177633Sdfr return (FALSE); 305177633Sdfr} 306177633Sdfr 307177633Sdfr 308177633Sdfr/* 309177633Sdfr * XDR 16-bit integers 310177633Sdfr */ 311177633Sdfrbool_t 312177633Sdfrxdr_int16_t(XDR *xdrs, int16_t *int16_p) 313177633Sdfr{ 314177633Sdfr long l; 315177633Sdfr 316177633Sdfr switch (xdrs->x_op) { 317177633Sdfr 318177633Sdfr case XDR_ENCODE: 319177633Sdfr l = (long) *int16_p; 320177633Sdfr return (XDR_PUTLONG(xdrs, &l)); 321177633Sdfr 322177633Sdfr case XDR_DECODE: 323177633Sdfr if (!XDR_GETLONG(xdrs, &l)) { 324177633Sdfr return (FALSE); 325177633Sdfr } 326177633Sdfr *int16_p = (int16_t) l; 327177633Sdfr return (TRUE); 328177633Sdfr 329177633Sdfr case XDR_FREE: 330177633Sdfr return (TRUE); 331177633Sdfr } 332177633Sdfr /* NOTREACHED */ 333177633Sdfr return (FALSE); 334177633Sdfr} 335177633Sdfr 336177633Sdfr/* 337177633Sdfr * XDR unsigned 16-bit integers 338177633Sdfr */ 339177633Sdfrbool_t 340177633Sdfrxdr_uint16_t(XDR *xdrs, uint16_t *uint16_p) 341177633Sdfr{ 342177633Sdfr u_long l; 343177633Sdfr 344177633Sdfr switch (xdrs->x_op) { 345177633Sdfr 346177633Sdfr case XDR_ENCODE: 347177633Sdfr l = (u_long) *uint16_p; 348177633Sdfr return (XDR_PUTLONG(xdrs, (long *)&l)); 349177633Sdfr 350177633Sdfr case XDR_DECODE: 351177633Sdfr if (!XDR_GETLONG(xdrs, (long *)&l)) { 352177633Sdfr return (FALSE); 353177633Sdfr } 354177633Sdfr *uint16_p = (uint16_t) l; 355177633Sdfr return (TRUE); 356177633Sdfr 357177633Sdfr case XDR_FREE: 358177633Sdfr return (TRUE); 359177633Sdfr } 360177633Sdfr /* NOTREACHED */ 361177633Sdfr return (FALSE); 362177633Sdfr} 363177633Sdfr 364177633Sdfr 365177633Sdfr/* 366177633Sdfr * XDR a char 367177633Sdfr */ 368177633Sdfrbool_t 369177633Sdfrxdr_char(XDR *xdrs, char *cp) 370177633Sdfr{ 371177633Sdfr int i; 372177633Sdfr 373177633Sdfr i = (*cp); 374177633Sdfr if (!xdr_int(xdrs, &i)) { 375177633Sdfr return (FALSE); 376177633Sdfr } 377177633Sdfr *cp = i; 378177633Sdfr return (TRUE); 379177633Sdfr} 380177633Sdfr 381177633Sdfr/* 382177633Sdfr * XDR an unsigned char 383177633Sdfr */ 384177633Sdfrbool_t 385177633Sdfrxdr_u_char(XDR *xdrs, u_char *cp) 386177633Sdfr{ 387177633Sdfr u_int u; 388177633Sdfr 389177633Sdfr u = (*cp); 390177633Sdfr if (!xdr_u_int(xdrs, &u)) { 391177633Sdfr return (FALSE); 392177633Sdfr } 393177633Sdfr *cp = u; 394177633Sdfr return (TRUE); 395177633Sdfr} 396177633Sdfr 397177633Sdfr/* 398177633Sdfr * XDR booleans 399177633Sdfr */ 400177633Sdfrbool_t 401177633Sdfrxdr_bool(XDR *xdrs, bool_t *bp) 402177633Sdfr{ 403177633Sdfr long lb; 404177633Sdfr 405177633Sdfr switch (xdrs->x_op) { 406177633Sdfr 407177633Sdfr case XDR_ENCODE: 408177633Sdfr lb = *bp ? XDR_TRUE : XDR_FALSE; 409177633Sdfr return (XDR_PUTLONG(xdrs, &lb)); 410177633Sdfr 411177633Sdfr case XDR_DECODE: 412177633Sdfr if (!XDR_GETLONG(xdrs, &lb)) { 413177633Sdfr return (FALSE); 414177633Sdfr } 415177633Sdfr *bp = (lb == XDR_FALSE) ? FALSE : TRUE; 416177633Sdfr return (TRUE); 417177633Sdfr 418177633Sdfr case XDR_FREE: 419177633Sdfr return (TRUE); 420177633Sdfr } 421177633Sdfr /* NOTREACHED */ 422177633Sdfr return (FALSE); 423177633Sdfr} 424177633Sdfr 425177633Sdfr/* 426177633Sdfr * XDR enumerations 427177633Sdfr */ 428177633Sdfrbool_t 429177633Sdfrxdr_enum(XDR *xdrs, enum_t *ep) 430177633Sdfr{ 431177633Sdfr enum sizecheck { SIZEVAL }; /* used to find the size of an enum */ 432177633Sdfr 433177633Sdfr /* 434177633Sdfr * enums are treated as ints 435177633Sdfr */ 436177633Sdfr /* LINTED */ if (sizeof (enum sizecheck) == sizeof (long)) { 437177633Sdfr return (xdr_long(xdrs, (long *)(void *)ep)); 438177633Sdfr } else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (int)) { 439177633Sdfr return (xdr_int(xdrs, (int *)(void *)ep)); 440177633Sdfr } else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (short)) { 441177633Sdfr return (xdr_short(xdrs, (short *)(void *)ep)); 442177633Sdfr } else { 443177633Sdfr return (FALSE); 444177633Sdfr } 445177633Sdfr} 446177633Sdfr 447177633Sdfr/* 448177633Sdfr * XDR opaque data 449177633Sdfr * Allows the specification of a fixed size sequence of opaque bytes. 450177633Sdfr * cp points to the opaque object and cnt gives the byte length. 451177633Sdfr */ 452177633Sdfrbool_t 453177633Sdfrxdr_opaque(XDR *xdrs, caddr_t cp, u_int cnt) 454177633Sdfr{ 455177633Sdfr u_int rndup; 456177633Sdfr static int crud[BYTES_PER_XDR_UNIT]; 457177633Sdfr 458177633Sdfr /* 459177633Sdfr * if no data we are done 460177633Sdfr */ 461177633Sdfr if (cnt == 0) 462177633Sdfr return (TRUE); 463177633Sdfr 464177633Sdfr /* 465177633Sdfr * round byte count to full xdr units 466177633Sdfr */ 467177633Sdfr rndup = cnt % BYTES_PER_XDR_UNIT; 468177633Sdfr if (rndup > 0) 469177633Sdfr rndup = BYTES_PER_XDR_UNIT - rndup; 470177633Sdfr 471177633Sdfr if (xdrs->x_op == XDR_DECODE) { 472177633Sdfr if (!XDR_GETBYTES(xdrs, cp, cnt)) { 473177633Sdfr return (FALSE); 474177633Sdfr } 475177633Sdfr if (rndup == 0) 476177633Sdfr return (TRUE); 477177633Sdfr return (XDR_GETBYTES(xdrs, (caddr_t)(void *)crud, rndup)); 478177633Sdfr } 479177633Sdfr 480177633Sdfr if (xdrs->x_op == XDR_ENCODE) { 481177633Sdfr if (!XDR_PUTBYTES(xdrs, cp, cnt)) { 482177633Sdfr return (FALSE); 483177633Sdfr } 484177633Sdfr if (rndup == 0) 485177633Sdfr return (TRUE); 486177633Sdfr return (XDR_PUTBYTES(xdrs, xdr_zero, rndup)); 487177633Sdfr } 488177633Sdfr 489177633Sdfr if (xdrs->x_op == XDR_FREE) { 490177633Sdfr return (TRUE); 491177633Sdfr } 492177633Sdfr 493177633Sdfr return (FALSE); 494177633Sdfr} 495177633Sdfr 496177633Sdfr/* 497177633Sdfr * XDR counted bytes 498177633Sdfr * *cpp is a pointer to the bytes, *sizep is the count. 499177633Sdfr * If *cpp is NULL maxsize bytes are allocated 500177633Sdfr */ 501177633Sdfrbool_t 502177633Sdfrxdr_bytes(XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize) 503177633Sdfr{ 504177633Sdfr char *sp = *cpp; /* sp is the actual string pointer */ 505177633Sdfr u_int nodesize; 506177633Sdfr 507177633Sdfr /* 508177633Sdfr * first deal with the length since xdr bytes are counted 509177633Sdfr */ 510177633Sdfr if (! xdr_u_int(xdrs, sizep)) { 511177633Sdfr return (FALSE); 512177633Sdfr } 513177633Sdfr nodesize = *sizep; 514177633Sdfr if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) { 515177633Sdfr return (FALSE); 516177633Sdfr } 517177633Sdfr 518177633Sdfr /* 519177633Sdfr * now deal with the actual bytes 520177633Sdfr */ 521177633Sdfr switch (xdrs->x_op) { 522177633Sdfr 523177633Sdfr case XDR_DECODE: 524177633Sdfr if (nodesize == 0) { 525177633Sdfr return (TRUE); 526177633Sdfr } 527177633Sdfr if (sp == NULL) { 528177633Sdfr *cpp = sp = mem_alloc(nodesize); 529177633Sdfr } 530177633Sdfr if (sp == NULL) { 531177633Sdfr printf("xdr_bytes: out of memory"); 532177633Sdfr return (FALSE); 533177633Sdfr } 534177633Sdfr /* FALLTHROUGH */ 535177633Sdfr 536177633Sdfr case XDR_ENCODE: 537177633Sdfr return (xdr_opaque(xdrs, sp, nodesize)); 538177633Sdfr 539177633Sdfr case XDR_FREE: 540177633Sdfr if (sp != NULL) { 541177633Sdfr mem_free(sp, nodesize); 542177633Sdfr *cpp = NULL; 543177633Sdfr } 544177633Sdfr return (TRUE); 545177633Sdfr } 546177633Sdfr /* NOTREACHED */ 547177633Sdfr return (FALSE); 548177633Sdfr} 549177633Sdfr 550177633Sdfr/* 551177633Sdfr * Implemented here due to commonality of the object. 552177633Sdfr */ 553177633Sdfrbool_t 554177633Sdfrxdr_netobj(XDR *xdrs, struct netobj *np) 555177633Sdfr{ 556177633Sdfr 557177633Sdfr return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ)); 558177633Sdfr} 559177633Sdfr 560177633Sdfr/* 561177633Sdfr * XDR a descriminated union 562177633Sdfr * Support routine for discriminated unions. 563177633Sdfr * You create an array of xdrdiscrim structures, terminated with 564177633Sdfr * an entry with a null procedure pointer. The routine gets 565177633Sdfr * the discriminant value and then searches the array of xdrdiscrims 566177633Sdfr * looking for that value. It calls the procedure given in the xdrdiscrim 567177633Sdfr * to handle the discriminant. If there is no specific routine a default 568177633Sdfr * routine may be called. 569177633Sdfr * If there is no specific or default routine an error is returned. 570177633Sdfr */ 571177633Sdfrbool_t 572177633Sdfrxdr_union(XDR *xdrs, 573177633Sdfr enum_t *dscmp, /* enum to decide which arm to work on */ 574177633Sdfr char *unp, /* the union itself */ 575177633Sdfr const struct xdr_discrim *choices, /* [value, xdr proc] for each arm */ 576177633Sdfr xdrproc_t dfault) /* default xdr routine */ 577177633Sdfr{ 578177633Sdfr enum_t dscm; 579177633Sdfr 580177633Sdfr /* 581177633Sdfr * we deal with the discriminator; it's an enum 582177633Sdfr */ 583177633Sdfr if (! xdr_enum(xdrs, dscmp)) { 584177633Sdfr return (FALSE); 585177633Sdfr } 586177633Sdfr dscm = *dscmp; 587177633Sdfr 588177633Sdfr /* 589177633Sdfr * search choices for a value that matches the discriminator. 590177633Sdfr * if we find one, execute the xdr routine for that value. 591177633Sdfr */ 592177633Sdfr for (; choices->proc != NULL_xdrproc_t; choices++) { 593177633Sdfr if (choices->value == dscm) 594177633Sdfr return ((*(choices->proc))(xdrs, unp)); 595177633Sdfr } 596177633Sdfr 597177633Sdfr /* 598177633Sdfr * no match - execute the default xdr routine if there is one 599177633Sdfr */ 600177633Sdfr return ((dfault == NULL_xdrproc_t) ? FALSE : 601177633Sdfr (*dfault)(xdrs, unp)); 602177633Sdfr} 603177633Sdfr 604177633Sdfr 605177633Sdfr/* 606177633Sdfr * Non-portable xdr primitives. 607177633Sdfr * Care should be taken when moving these routines to new architectures. 608177633Sdfr */ 609177633Sdfr 610177633Sdfr 611177633Sdfr/* 612177633Sdfr * XDR null terminated ASCII strings 613177633Sdfr * xdr_string deals with "C strings" - arrays of bytes that are 614177633Sdfr * terminated by a NULL character. The parameter cpp references a 615177633Sdfr * pointer to storage; If the pointer is null, then the necessary 616177633Sdfr * storage is allocated. The last parameter is the max allowed length 617177633Sdfr * of the string as specified by a protocol. 618177633Sdfr */ 619177633Sdfrbool_t 620177633Sdfrxdr_string(XDR *xdrs, char **cpp, u_int maxsize) 621177633Sdfr{ 622177633Sdfr char *sp = *cpp; /* sp is the actual string pointer */ 623177633Sdfr u_int size; 624177633Sdfr u_int nodesize; 625177633Sdfr 626177633Sdfr /* 627177633Sdfr * first deal with the length since xdr strings are counted-strings 628177633Sdfr */ 629177633Sdfr switch (xdrs->x_op) { 630177633Sdfr case XDR_FREE: 631177633Sdfr if (sp == NULL) { 632177633Sdfr return(TRUE); /* already free */ 633177633Sdfr } 634177633Sdfr /* FALLTHROUGH */ 635177633Sdfr case XDR_ENCODE: 636177633Sdfr size = strlen(sp); 637177633Sdfr break; 638177633Sdfr case XDR_DECODE: 639177633Sdfr break; 640177633Sdfr } 641177633Sdfr if (! xdr_u_int(xdrs, &size)) { 642177633Sdfr return (FALSE); 643177633Sdfr } 644177633Sdfr if (size > maxsize) { 645177633Sdfr return (FALSE); 646177633Sdfr } 647177633Sdfr nodesize = size + 1; 648177633Sdfr 649177633Sdfr /* 650177633Sdfr * now deal with the actual bytes 651177633Sdfr */ 652177633Sdfr switch (xdrs->x_op) { 653177633Sdfr 654177633Sdfr case XDR_DECODE: 655177633Sdfr if (nodesize == 0) { 656177633Sdfr return (TRUE); 657177633Sdfr } 658177633Sdfr if (sp == NULL) 659177633Sdfr *cpp = sp = mem_alloc(nodesize); 660177633Sdfr if (sp == NULL) { 661177633Sdfr printf("xdr_string: out of memory"); 662177633Sdfr return (FALSE); 663177633Sdfr } 664177633Sdfr sp[size] = 0; 665177633Sdfr /* FALLTHROUGH */ 666177633Sdfr 667177633Sdfr case XDR_ENCODE: 668177633Sdfr return (xdr_opaque(xdrs, sp, size)); 669177633Sdfr 670177633Sdfr case XDR_FREE: 671177633Sdfr mem_free(sp, nodesize); 672177633Sdfr *cpp = NULL; 673177633Sdfr return (TRUE); 674177633Sdfr } 675177633Sdfr /* NOTREACHED */ 676177633Sdfr return (FALSE); 677177633Sdfr} 678177633Sdfr 679177633Sdfr/* 680177633Sdfr * Wrapper for xdr_string that can be called directly from 681177633Sdfr * routines like clnt_call 682177633Sdfr */ 683177633Sdfrbool_t 684177633Sdfrxdr_wrapstring(XDR *xdrs, char **cpp) 685177633Sdfr{ 686177633Sdfr return xdr_string(xdrs, cpp, LASTUNSIGNED); 687177633Sdfr} 688177633Sdfr 689177633Sdfr/* 690177633Sdfr * NOTE: xdr_hyper(), xdr_u_hyper(), xdr_longlong_t(), and xdr_u_longlong_t() 691177633Sdfr * are in the "non-portable" section because they require that a `long long' 692177633Sdfr * be a 64-bit type. 693177633Sdfr * 694177633Sdfr * --thorpej@netbsd.org, November 30, 1999 695177633Sdfr */ 696177633Sdfr 697177633Sdfr/* 698177633Sdfr * XDR 64-bit integers 699177633Sdfr */ 700177633Sdfrbool_t 701177633Sdfrxdr_int64_t(XDR *xdrs, int64_t *llp) 702177633Sdfr{ 703177633Sdfr u_long ul[2]; 704177633Sdfr 705177633Sdfr switch (xdrs->x_op) { 706177633Sdfr case XDR_ENCODE: 707177633Sdfr ul[0] = (u_long)((uint64_t)*llp >> 32) & 0xffffffff; 708177633Sdfr ul[1] = (u_long)((uint64_t)*llp) & 0xffffffff; 709177633Sdfr if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE) 710177633Sdfr return (FALSE); 711177633Sdfr return (XDR_PUTLONG(xdrs, (long *)&ul[1])); 712177633Sdfr case XDR_DECODE: 713177633Sdfr if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE) 714177633Sdfr return (FALSE); 715177633Sdfr if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE) 716177633Sdfr return (FALSE); 717177633Sdfr *llp = (int64_t) 718177633Sdfr (((uint64_t)ul[0] << 32) | ((uint64_t)ul[1])); 719177633Sdfr return (TRUE); 720177633Sdfr case XDR_FREE: 721177633Sdfr return (TRUE); 722177633Sdfr } 723177633Sdfr /* NOTREACHED */ 724177633Sdfr return (FALSE); 725177633Sdfr} 726177633Sdfr 727177633Sdfr 728177633Sdfr/* 729177633Sdfr * XDR unsigned 64-bit integers 730177633Sdfr */ 731177633Sdfrbool_t 732177633Sdfrxdr_uint64_t(XDR *xdrs, uint64_t *ullp) 733177633Sdfr{ 734177633Sdfr u_long ul[2]; 735177633Sdfr 736177633Sdfr switch (xdrs->x_op) { 737177633Sdfr case XDR_ENCODE: 738177633Sdfr ul[0] = (u_long)(*ullp >> 32) & 0xffffffff; 739177633Sdfr ul[1] = (u_long)(*ullp) & 0xffffffff; 740177633Sdfr if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE) 741177633Sdfr return (FALSE); 742177633Sdfr return (XDR_PUTLONG(xdrs, (long *)&ul[1])); 743177633Sdfr case XDR_DECODE: 744177633Sdfr if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE) 745177633Sdfr return (FALSE); 746177633Sdfr if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE) 747177633Sdfr return (FALSE); 748177633Sdfr *ullp = (uint64_t) 749177633Sdfr (((uint64_t)ul[0] << 32) | ((uint64_t)ul[1])); 750177633Sdfr return (TRUE); 751177633Sdfr case XDR_FREE: 752177633Sdfr return (TRUE); 753177633Sdfr } 754177633Sdfr /* NOTREACHED */ 755177633Sdfr return (FALSE); 756177633Sdfr} 757177633Sdfr 758177633Sdfr 759177633Sdfr/* 760177633Sdfr * XDR hypers 761177633Sdfr */ 762177633Sdfrbool_t 763177633Sdfrxdr_hyper(XDR *xdrs, longlong_t *llp) 764177633Sdfr{ 765177633Sdfr 766177633Sdfr /* 767177633Sdfr * Don't bother open-coding this; it's a fair amount of code. Just 768177633Sdfr * call xdr_int64_t(). 769177633Sdfr */ 770177633Sdfr return (xdr_int64_t(xdrs, (int64_t *)llp)); 771177633Sdfr} 772177633Sdfr 773177633Sdfr 774177633Sdfr/* 775177633Sdfr * XDR unsigned hypers 776177633Sdfr */ 777177633Sdfrbool_t 778177633Sdfrxdr_u_hyper(XDR *xdrs, u_longlong_t *ullp) 779177633Sdfr{ 780177633Sdfr 781177633Sdfr /* 782177633Sdfr * Don't bother open-coding this; it's a fair amount of code. Just 783177633Sdfr * call xdr_uint64_t(). 784177633Sdfr */ 785177633Sdfr return (xdr_uint64_t(xdrs, (uint64_t *)ullp)); 786177633Sdfr} 787177633Sdfr 788177633Sdfr 789177633Sdfr/* 790177633Sdfr * XDR longlong_t's 791177633Sdfr */ 792177633Sdfrbool_t 793177633Sdfrxdr_longlong_t(XDR *xdrs, longlong_t *llp) 794177633Sdfr{ 795177633Sdfr 796177633Sdfr /* 797177633Sdfr * Don't bother open-coding this; it's a fair amount of code. Just 798177633Sdfr * call xdr_int64_t(). 799177633Sdfr */ 800177633Sdfr return (xdr_int64_t(xdrs, (int64_t *)llp)); 801177633Sdfr} 802177633Sdfr 803177633Sdfr 804177633Sdfr/* 805177633Sdfr * XDR u_longlong_t's 806177633Sdfr */ 807177633Sdfrbool_t 808177633Sdfrxdr_u_longlong_t(XDR *xdrs, u_longlong_t *ullp) 809177633Sdfr{ 810177633Sdfr 811177633Sdfr /* 812177633Sdfr * Don't bother open-coding this; it's a fair amount of code. Just 813177633Sdfr * call xdr_uint64_t(). 814177633Sdfr */ 815177633Sdfr return (xdr_uint64_t(xdrs, (uint64_t *)ullp)); 816177633Sdfr} 817