GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libc/rpc/xdr.c Lines: 0 223 0.0 %
Date: 2017-11-07 Branches: 0 149 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: xdr.c,v 1.16 2017/01/21 08:29:13 krw Exp $ */
2
3
/*
4
 * Copyright (c) 2010, Oracle America, Inc.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions are
8
 * met:
9
 *
10
 *     * Redistributions of source code must retain the above copyright
11
 *       notice, this list of conditions and the following disclaimer.
12
 *     * Redistributions in binary form must reproduce the above
13
 *       copyright notice, this list of conditions and the following
14
 *       disclaimer in the documentation and/or other materials
15
 *       provided with the distribution.
16
 *     * Neither the name of the "Oracle America, Inc." nor the names of its
17
 *       contributors may be used to endorse or promote products derived
18
 *       from this software without specific prior written permission.
19
 *
20
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23
 *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24
 *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25
 *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
 *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27
 *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
 *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29
 *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30
 *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31
 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
 */
33
34
/*
35
 * xdr.c, Generic XDR routines implementation.
36
 *
37
 * These are the "generic" xdr routines used to serialize and de-serialize
38
 * most common data items.  See xdr.h for more info on the interface to
39
 * xdr.
40
 */
41
42
#include <stdio.h>
43
#include <stdlib.h>
44
#include <string.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(xdrproc_t proc, char *objp)
67
{
68
	XDR x;
69
70
	x.x_op = XDR_FREE;
71
	(*proc)(&x, objp);
72
}
73
DEF_WEAK(xdr_free);
74
75
/*
76
 * XDR nothing
77
 */
78
bool_t
79
xdr_void(void)
80
	/* XDR *xdrs; */
81
	/* caddr_t addr; */
82
{
83
84
	return (TRUE);
85
}
86
DEF_WEAK(xdr_void);
87
88
89
/*
90
 * XDR integers
91
 */
92
bool_t
93
xdr_int(XDR *xdrs, int *ip)
94
{
95
	long l;
96
97
	switch (xdrs->x_op) {
98
99
	case XDR_ENCODE:
100
		l = (long) *ip;
101
		return (XDR_PUTLONG(xdrs, &l));
102
103
	case XDR_DECODE:
104
		if (!XDR_GETLONG(xdrs, &l)) {
105
			return (FALSE);
106
		}
107
		*ip = (int) l;
108
		return (TRUE);
109
110
	case XDR_FREE:
111
		return (TRUE);
112
	}
113
	return (FALSE);
114
}
115
DEF_WEAK(xdr_int);
116
117
/*
118
 * XDR unsigned integers
119
 */
120
bool_t
121
xdr_u_int(XDR *xdrs, u_int *up)
122
{
123
	u_long l;
124
125
	switch (xdrs->x_op) {
126
127
	case XDR_ENCODE:
128
		l = (u_long) *up;
129
		return (XDR_PUTLONG(xdrs, (long *)&l));
130
131
	case XDR_DECODE:
132
		if (!XDR_GETLONG(xdrs, (long *)&l)) {
133
			return (FALSE);
134
		}
135
		*up = (u_int) l;
136
		return (TRUE);
137
138
	case XDR_FREE:
139
		return (TRUE);
140
	}
141
	return (FALSE);
142
}
143
DEF_WEAK(xdr_u_int);
144
145
146
/*
147
 * XDR long integers
148
 * same as xdr_u_long - open coded to save a proc call!
149
 */
150
bool_t
151
xdr_long(XDR *xdrs, long int *lp)
152
{
153
	switch (xdrs->x_op) {
154
	case XDR_ENCODE:
155
		return (XDR_PUTLONG(xdrs, lp));
156
	case XDR_DECODE:
157
		return (XDR_GETLONG(xdrs, lp));
158
	case XDR_FREE:
159
		return (TRUE);
160
	}
161
162
	return (FALSE);
163
}
164
DEF_WEAK(xdr_long);
165
166
/*
167
 * XDR unsigned long integers
168
 * same as xdr_long - open coded to save a proc call!
169
 */
170
bool_t
171
xdr_u_long(XDR *xdrs, u_long *ulp)
172
{
173
	switch (xdrs->x_op) {
174
	case XDR_ENCODE:
175
		return (XDR_PUTLONG(xdrs, (long *)ulp));
176
	case XDR_DECODE:
177
		return (XDR_GETLONG(xdrs, (long *)ulp));
178
	case XDR_FREE:
179
		return (TRUE);
180
	}
181
	return (FALSE);
182
}
183
DEF_WEAK(xdr_u_long);
184
185
186
/*
187
 * XDR 32-bit integers
188
 * same as xdr_u_int32_t - open coded to save a proc call!
189
 */
190
bool_t
191
xdr_int32_t(XDR *xdrs, int32_t *int32_p)
192
{
193
	long l;
194
195
	switch (xdrs->x_op) {
196
197
	case XDR_ENCODE:
198
		l = (long) *int32_p;
199
		return (XDR_PUTLONG(xdrs, &l));
200
201
	case XDR_DECODE:
202
		if (!XDR_GETLONG(xdrs, &l)) {
203
			return (FALSE);
204
		}
205
		*int32_p = (int32_t) l;
206
		return (TRUE);
207
208
	case XDR_FREE:
209
		return (TRUE);
210
	}
211
	return (FALSE);
212
}
213
214
/*
215
 * XDR unsigned 32-bit integers
216
 * same as xdr_int32_t - open coded to save a proc call!
217
 */
218
bool_t
219
xdr_u_int32_t(XDR *xdrs, u_int32_t *u_int32_p)
220
{
221
	u_long l;
222
223
	switch (xdrs->x_op) {
224
225
	case XDR_ENCODE:
226
		l = (u_long) *u_int32_p;
227
		return (XDR_PUTLONG(xdrs, (long *)&l));
228
229
	case XDR_DECODE:
230
		if (!XDR_GETLONG(xdrs, (long *)&l)) {
231
			return (FALSE);
232
		}
233
		*u_int32_p = (u_int32_t) l;
234
		return (TRUE);
235
236
	case XDR_FREE:
237
		return (TRUE);
238
	}
239
	return (FALSE);
240
}
241
DEF_WEAK(xdr_u_int32_t);
242
243
244
/*
245
 * XDR short integers
246
 */
247
bool_t
248
xdr_short(XDR *xdrs, short int *sp)
249
{
250
	long l;
251
252
	switch (xdrs->x_op) {
253
254
	case XDR_ENCODE:
255
		l = (long) *sp;
256
		return (XDR_PUTLONG(xdrs, &l));
257
258
	case XDR_DECODE:
259
		if (!XDR_GETLONG(xdrs, &l)) {
260
			return (FALSE);
261
		}
262
		*sp = (short) l;
263
		return (TRUE);
264
265
	case XDR_FREE:
266
		return (TRUE);
267
	}
268
	return (FALSE);
269
}
270
DEF_WEAK(xdr_short);
271
272
/*
273
 * XDR unsigned short integers
274
 */
275
bool_t
276
xdr_u_short(XDR *xdrs, u_short *usp)
277
{
278
	u_long l;
279
280
	switch (xdrs->x_op) {
281
282
	case XDR_ENCODE:
283
		l = (u_long) *usp;
284
		return (XDR_PUTLONG(xdrs, (long *)&l));
285
286
	case XDR_DECODE:
287
		if (!XDR_GETLONG(xdrs, (long *)&l)) {
288
			return (FALSE);
289
		}
290
		*usp = (u_short) l;
291
		return (TRUE);
292
293
	case XDR_FREE:
294
		return (TRUE);
295
	}
296
	return (FALSE);
297
}
298
DEF_WEAK(xdr_u_short);
299
300
301
/*
302
 * XDR 16-bit integers
303
 */
304
bool_t
305
xdr_int16_t(XDR *xdrs, int16_t *int16_p)
306
{
307
	long l;
308
309
	switch (xdrs->x_op) {
310
311
	case XDR_ENCODE:
312
		l = (long) *int16_p;
313
		return (XDR_PUTLONG(xdrs, &l));
314
315
	case XDR_DECODE:
316
		if (!XDR_GETLONG(xdrs, &l)) {
317
			return (FALSE);
318
		}
319
		*int16_p = (int16_t) l;
320
		return (TRUE);
321
322
	case XDR_FREE:
323
		return (TRUE);
324
	}
325
	return (FALSE);
326
}
327
328
/*
329
 * XDR unsigned 16-bit integers
330
 */
331
bool_t
332
xdr_u_int16_t(XDR *xdrs, u_int16_t *u_int16_p)
333
{
334
	u_long l;
335
336
	switch (xdrs->x_op) {
337
338
	case XDR_ENCODE:
339
		l = (u_long) *u_int16_p;
340
		return (XDR_PUTLONG(xdrs, (long *)&l));
341
342
	case XDR_DECODE:
343
		if (!XDR_GETLONG(xdrs, (long *)&l)) {
344
			return (FALSE);
345
		}
346
		*u_int16_p = (u_int16_t) l;
347
		return (TRUE);
348
349
	case XDR_FREE:
350
		return (TRUE);
351
	}
352
	return (FALSE);
353
}
354
355
356
/*
357
 * XDR a char
358
 */
359
bool_t
360
xdr_char(XDR *xdrs, char *cp)
361
{
362
	int i;
363
364
	i = (*cp);
365
	if (!xdr_int(xdrs, &i)) {
366
		return (FALSE);
367
	}
368
	*cp = i;
369
	return (TRUE);
370
}
371
372
/*
373
 * XDR an unsigned char
374
 */
375
bool_t
376
xdr_u_char(XDR *xdrs, u_char *cp)
377
{
378
	u_int u;
379
380
	u = (*cp);
381
	if (!xdr_u_int(xdrs, &u)) {
382
		return (FALSE);
383
	}
384
	*cp = u;
385
	return (TRUE);
386
}
387
388
/*
389
 * XDR booleans
390
 */
391
bool_t
392
xdr_bool(XDR *xdrs, int32_t *bp)
393
{
394
	long lb;
395
396
	switch (xdrs->x_op) {
397
398
	case XDR_ENCODE:
399
		lb = *bp ? XDR_TRUE : XDR_FALSE;
400
		return (XDR_PUTLONG(xdrs, &lb));
401
402
	case XDR_DECODE:
403
		if (!XDR_GETLONG(xdrs, &lb)) {
404
			return (FALSE);
405
		}
406
		*bp = (lb == XDR_FALSE) ? FALSE : TRUE;
407
		return (TRUE);
408
409
	case XDR_FREE:
410
		return (TRUE);
411
	}
412
	return (FALSE);
413
}
414
DEF_WEAK(xdr_bool);
415
416
/*
417
 * XDR enumerations
418
 */
419
bool_t
420
xdr_enum(XDR *xdrs, int32_t *ep)
421
{
422
	enum sizecheck { SIZEVAL };	/* used to find the size of an enum */
423
424
	/*
425
	 * enums are treated as ints
426
	 */
427
	if (sizeof (enum sizecheck) == sizeof (long)) {
428
		return (xdr_long(xdrs, (long *)ep));
429
	} else if (sizeof (enum sizecheck) == sizeof (int)) {
430
		return (xdr_int(xdrs, (int *)ep));
431
	} else if (sizeof (enum sizecheck) == sizeof (short)) {
432
		return (xdr_short(xdrs, (short *)ep));
433
	} else {
434
		return (FALSE);
435
	}
436
}
437
DEF_WEAK(xdr_enum);
438
439
/*
440
 * XDR opaque data
441
 * Allows the specification of a fixed size sequence of opaque bytes.
442
 * cp points to the opaque object and cnt gives the byte length.
443
 */
444
bool_t
445
xdr_opaque(XDR *xdrs, caddr_t cp, u_int cnt)
446
{
447
	u_int rndup;
448
	static int crud[BYTES_PER_XDR_UNIT];
449
450
	/*
451
	 * if no data we are done
452
	 */
453
	if (cnt == 0)
454
		return (TRUE);
455
456
	/*
457
	 * round byte count to full xdr units
458
	 */
459
	rndup = cnt % BYTES_PER_XDR_UNIT;
460
	if (rndup > 0)
461
		rndup = BYTES_PER_XDR_UNIT - rndup;
462
463
	if (xdrs->x_op == XDR_DECODE) {
464
		if (!XDR_GETBYTES(xdrs, cp, cnt)) {
465
			return (FALSE);
466
		}
467
		if (rndup == 0)
468
			return (TRUE);
469
		return (XDR_GETBYTES(xdrs, (caddr_t)crud, rndup));
470
	}
471
472
	if (xdrs->x_op == XDR_ENCODE) {
473
		if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
474
			return (FALSE);
475
		}
476
		if (rndup == 0)
477
			return (TRUE);
478
		return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
479
	}
480
481
	if (xdrs->x_op == XDR_FREE) {
482
		return (TRUE);
483
	}
484
485
	return (FALSE);
486
}
487
DEF_WEAK(xdr_opaque);
488
489
/*
490
 * XDR counted bytes
491
 * *cpp is a pointer to the bytes, *sizep is the count.
492
 * If *cpp is NULL maxsize bytes are allocated
493
 */
494
bool_t
495
xdr_bytes(XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize)
496
{
497
	char *sp = *cpp;  /* sp is the actual string pointer */
498
	u_int nodesize;
499
500
	/*
501
	 * first deal with the length since xdr bytes are counted
502
	 */
503
	if (! xdr_u_int(xdrs, sizep)) {
504
		return (FALSE);
505
	}
506
	nodesize = *sizep;
507
	if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
508
		return (FALSE);
509
	}
510
511
	/*
512
	 * now deal with the actual bytes
513
	 */
514
	switch (xdrs->x_op) {
515
516
	case XDR_DECODE:
517
		if (nodesize == 0) {
518
			return (TRUE);
519
		}
520
		if (sp == NULL) {
521
			*cpp = sp = (char *)mem_alloc(nodesize);
522
		}
523
		if (sp == NULL)
524
			return (FALSE);
525
		/* fall into ... */
526
527
	case XDR_ENCODE:
528
		return (xdr_opaque(xdrs, sp, nodesize));
529
530
	case XDR_FREE:
531
		if (sp != NULL) {
532
			mem_free(sp, nodesize);
533
			*cpp = NULL;
534
		}
535
		return (TRUE);
536
	}
537
	return (FALSE);
538
}
539
DEF_WEAK(xdr_bytes);
540
541
/*
542
 * Implemented here due to commonality of the object.
543
 */
544
bool_t
545
xdr_netobj(XDR *xdrs, struct netobj *np)
546
{
547
548
	return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
549
}
550
551
/*
552
 * XDR a descriminated union
553
 * Support routine for discriminated unions.
554
 * You create an array of xdrdiscrim structures, terminated with
555
 * an entry with a null procedure pointer.  The routine gets
556
 * the discriminant value and then searches the array of xdrdiscrims
557
 * looking for that value.  It calls the procedure given in the xdrdiscrim
558
 * to handle the discriminant.  If there is no specific routine a default
559
 * routine may be called.
560
 * If there is no specific or default routine an error is returned.
561
 */
562
bool_t
563
xdr_union(XDR *xdrs,
564
    int32_t *dscmp,		/* enum to decide which arm to work on */
565
    char *unp,			/* the union itself */
566
    struct xdr_discrim *choices,	/* [value, xdr proc] for each arm */
567
    xdrproc_t dfault)		/* default xdr routine */
568
{
569
	enum_t dscm;
570
571
	/*
572
	 * we deal with the discriminator;  it's an enum
573
	 */
574
	if (! xdr_enum(xdrs, dscmp)) {
575
		return (FALSE);
576
	}
577
	dscm = *dscmp;
578
579
	/*
580
	 * search choices for a value that matches the discriminator.
581
	 * if we find one, execute the xdr routine for that value.
582
	 */
583
	for (; choices->proc != NULL; choices++) {
584
		if (choices->value == dscm)
585
			return ((*(choices->proc))(xdrs, unp));
586
	}
587
588
	/*
589
	 * no match - execute the default xdr routine if there is one
590
	 */
591
	return ((dfault == NULL) ? FALSE :
592
	    (*dfault)(xdrs, unp));
593
}
594
DEF_WEAK(xdr_union);
595
596
597
/*
598
 * Non-portable xdr primitives.
599
 * Care should be taken when moving these routines to new architectures.
600
 */
601
602
603
/*
604
 * XDR null terminated ASCII strings
605
 * xdr_string deals with "C strings" - arrays of bytes that are
606
 * terminated by a NULL character.  The parameter cpp references a
607
 * pointer to storage; If the pointer is null, then the necessary
608
 * storage is allocated.  The last parameter is the max allowed length
609
 * of the string as specified by a protocol.
610
 */
611
bool_t
612
xdr_string(XDR *xdrs, char **cpp, u_int maxsize)
613
{
614
	char *sp = *cpp;  /* sp is the actual string pointer */
615
	u_int size;
616
	u_int nodesize;
617
618
	/*
619
	 * first deal with the length since xdr strings are counted-strings
620
	 */
621
	switch (xdrs->x_op) {
622
	case XDR_FREE:
623
		if (sp == NULL) {
624
			return(TRUE);	/* already free */
625
		}
626
		/* fall through... */
627
	case XDR_ENCODE:
628
		size = strlen(sp);
629
		break;
630
	default:
631
		break;
632
	}
633
	if (! xdr_u_int(xdrs, &size)) {
634
		return (FALSE);
635
	}
636
	if (size > maxsize) {
637
		return (FALSE);
638
	}
639
	nodesize = size + 1;
640
641
	/*
642
	 * now deal with the actual bytes
643
	 */
644
	switch (xdrs->x_op) {
645
646
	case XDR_DECODE:
647
		if (nodesize == 0) {
648
			return (TRUE);
649
		}
650
		if (sp == NULL)
651
			*cpp = sp = (char *)mem_alloc(nodesize);
652
		if (sp == NULL)
653
			return (FALSE);
654
		sp[size] = 0;
655
		/* fall into ... */
656
657
	case XDR_ENCODE:
658
		return (xdr_opaque(xdrs, sp, size));
659
660
	case XDR_FREE:
661
		mem_free(sp, nodesize);
662
		*cpp = NULL;
663
		return (TRUE);
664
	}
665
	return (FALSE);
666
}
667
DEF_WEAK(xdr_string);
668
669
/*
670
 * Wrapper for xdr_string that can be called directly from
671
 * routines like clnt_call
672
 */
673
bool_t
674
xdr_wrapstring(XDR *xdrs, char **cpp)
675
{
676
	return xdr_string(xdrs, cpp, LASTUNSIGNED);
677
}
678
679
bool_t
680
xdr_int64_t(XDR *xdrs, int64_t *llp)
681
{
682
	u_long ul[2];
683
684
	switch (xdrs->x_op) {
685
	case XDR_ENCODE:
686
		ul[0] = (u_long)((u_int64_t)*llp >> 32) & 0xffffffff;
687
		ul[1] = (u_long)((u_int64_t)*llp) & 0xffffffff;
688
		if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
689
			return (FALSE);
690
		return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
691
	case XDR_DECODE:
692
		if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
693
			return (FALSE);
694
		if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
695
			return (FALSE);
696
		*llp = (int64_t)
697
		    (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
698
		return (TRUE);
699
	case XDR_FREE:
700
		return (TRUE);
701
	}
702
	/* NOTREACHED */
703
	return (FALSE);
704
}
705
706
bool_t
707
xdr_u_int64_t(XDR *xdrs, u_int64_t *ullp)
708
{
709
	u_long ul[2];
710
711
	switch (xdrs->x_op) {
712
	case XDR_ENCODE:
713
		ul[0] = (u_long)(*ullp >> 32) & 0xffffffff;
714
		ul[1] = (u_long)(*ullp) & 0xffffffff;
715
		if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
716
			return (FALSE);
717
		return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
718
	case XDR_DECODE:
719
		if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
720
			return (FALSE);
721
		if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
722
			return (FALSE);
723
		*ullp = (u_int64_t)
724
		    (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
725
		return (TRUE);
726
	case XDR_FREE:
727
		return (TRUE);
728
	}
729
	/* NOTREACHED */
730
	return (FALSE);
731
}