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

Line Branch Exec Source
1
/*	$OpenBSD: rpc_prot.c,v 1.15 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
 * rpc_prot.c
36
 *
37
 * This set of routines implements the rpc message definition,
38
 * its serializer and some common rpc utility routines.
39
 * The routines are meant for various implementations of rpc -
40
 * they are NOT for the rpc client or rpc service implementations!
41
 * Because authentication stuff is easy and is part of rpc, the opaque
42
 * routines are also in this program.
43
 */
44
45
#include <rpc/rpc.h>
46
47
/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
48
49
struct opaque_auth _null_auth;
50
51
/*
52
 * XDR an opaque authentication struct
53
 * (see auth.h)
54
 */
55
bool_t
56
xdr_opaque_auth(XDR *xdrs, struct opaque_auth *ap)
57
{
58
59
	if (xdr_enum(xdrs, &(ap->oa_flavor)))
60
		return (xdr_bytes(xdrs, &ap->oa_base,
61
		    &ap->oa_length, MAX_AUTH_BYTES));
62
	return (FALSE);
63
}
64
DEF_WEAK(xdr_opaque_auth);
65
66
/*
67
 * XDR a DES block
68
 */
69
bool_t
70
xdr_des_block(XDR *xdrs, des_block *blkp)
71
{
72
	return (xdr_opaque(xdrs, (caddr_t)blkp, sizeof(des_block)));
73
}
74
75
/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
76
77
/*
78
 * XDR the MSG_ACCEPTED part of a reply message union
79
 */
80
bool_t
81
xdr_accepted_reply(XDR *xdrs, struct accepted_reply *ar)
82
{
83
84
	/* personalized union, rather than calling xdr_union */
85
	if (! xdr_opaque_auth(xdrs, &(ar->ar_verf)))
86
		return (FALSE);
87
	if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat)))
88
		return (FALSE);
89
90
	switch (ar->ar_stat) {
91
	case SUCCESS:
92
		return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where));
93
	case PROG_MISMATCH:
94
		if (!xdr_u_int32_t(xdrs, &(ar->ar_vers.low)))
95
			return (FALSE);
96
		return (xdr_u_int32_t(xdrs, &(ar->ar_vers.high)));
97
	default:
98
		return (TRUE);  /* TRUE => open ended set of problems */
99
	}
100
}
101
DEF_WEAK(xdr_accepted_reply);
102
103
/*
104
 * XDR the MSG_DENIED part of a reply message union
105
 */
106
bool_t
107
xdr_rejected_reply(XDR *xdrs, struct rejected_reply *rr)
108
{
109
110
	/* personalized union, rather than calling xdr_union */
111
	if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat)))
112
		return (FALSE);
113
114
	switch (rr->rj_stat) {
115
	case RPC_MISMATCH:
116
		if (!xdr_u_int32_t(xdrs, &(rr->rj_vers.low)))
117
			return (FALSE);
118
		return (xdr_u_int32_t(xdrs, &(rr->rj_vers.high)));
119
	case AUTH_ERROR:
120
		return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why)));
121
	}
122
	return (FALSE);
123
}
124
DEF_WEAK(xdr_rejected_reply);
125
126
static struct xdr_discrim reply_dscrm[3] = {
127
	{ (int)MSG_ACCEPTED, xdr_accepted_reply },
128
	{ (int)MSG_DENIED, xdr_rejected_reply },
129
	{ __dontcare__, NULL } };
130
131
/*
132
 * XDR a reply message
133
 */
134
bool_t
135
xdr_replymsg(XDR *xdrs, struct rpc_msg *rmsg)
136
{
137
	if (xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) &&
138
	    xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) &&
139
	    rmsg->rm_direction == REPLY)
140
		return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat),
141
		   (caddr_t)&(rmsg->rm_reply.ru), reply_dscrm, NULL));
142
	return (FALSE);
143
}
144
DEF_WEAK(xdr_replymsg);
145
146
/*
147
 * Serializes the "static part" of a call message header.
148
 * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
149
 * The rm_xid is not really static, but the user can easily munge on the fly.
150
 */
151
bool_t
152
xdr_callhdr(XDR *xdrs, struct rpc_msg *cmsg)
153
{
154
155
	cmsg->rm_direction = CALL;
156
	cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
157
	if (xdrs->x_op == XDR_ENCODE &&
158
	    xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) &&
159
	    xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&
160
	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
161
	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)))
162
		return (xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)));
163
	return (FALSE);
164
}
165
DEF_WEAK(xdr_callhdr);
166
167
/* ************************** Client utility routine ************* */
168
169
static void
170
accepted(enum accept_stat acpt_stat, struct rpc_err *error)
171
{
172
173
	switch (acpt_stat) {
174
175
	case PROG_UNAVAIL:
176
		error->re_status = RPC_PROGUNAVAIL;
177
		return;
178
179
	case PROG_MISMATCH:
180
		error->re_status = RPC_PROGVERSMISMATCH;
181
		return;
182
183
	case PROC_UNAVAIL:
184
		error->re_status = RPC_PROCUNAVAIL;
185
		return;
186
187
	case GARBAGE_ARGS:
188
		error->re_status = RPC_CANTDECODEARGS;
189
		return;
190
191
	case SYSTEM_ERR:
192
		error->re_status = RPC_SYSTEMERROR;
193
		return;
194
195
	case SUCCESS:
196
		error->re_status = RPC_SUCCESS;
197
		return;
198
	}
199
	/* something's wrong, but we don't know what ... */
200
	error->re_status = RPC_FAILED;
201
	error->re_lb.s1 = (long)MSG_ACCEPTED;
202
	error->re_lb.s2 = (long)acpt_stat;
203
}
204
205
static void
206
rejected(enum reject_stat rjct_stat, struct rpc_err *error)
207
{
208
209
	switch (rjct_stat) {
210
211
	case RPC_MISMATCH:
212
		error->re_status = RPC_VERSMISMATCH;
213
		return;
214
215
	case AUTH_ERROR:
216
		error->re_status = RPC_AUTHERROR;
217
		return;
218
	}
219
	/* something's wrong, but we don't know what ... */
220
	error->re_status = RPC_FAILED;
221
	error->re_lb.s1 = (long)MSG_DENIED;
222
	error->re_lb.s2 = (long)rjct_stat;
223
}
224
225
/*
226
 * given a reply message, fills in the error
227
 */
228
void
229
_seterr_reply(struct rpc_msg *msg, struct rpc_err *error)
230
{
231
232
	/* optimized for normal, SUCCESSful case */
233
	switch (msg->rm_reply.rp_stat) {
234
235
	case MSG_ACCEPTED:
236
		if (msg->acpted_rply.ar_stat == SUCCESS) {
237
			error->re_status = RPC_SUCCESS;
238
			return;
239
		};
240
		accepted(msg->acpted_rply.ar_stat, error);
241
		break;
242
243
	case MSG_DENIED:
244
		rejected(msg->rjcted_rply.rj_stat, error);
245
		break;
246
247
	default:
248
		error->re_status = RPC_FAILED;
249
		error->re_lb.s1 = (long)(msg->rm_reply.rp_stat);
250
		break;
251
	}
252
	switch (error->re_status) {
253
254
	case RPC_VERSMISMATCH:
255
		error->re_vers.low = msg->rjcted_rply.rj_vers.low;
256
		error->re_vers.high = msg->rjcted_rply.rj_vers.high;
257
		break;
258
259
	case RPC_AUTHERROR:
260
		error->re_why = msg->rjcted_rply.rj_why;
261
		break;
262
263
	case RPC_PROGVERSMISMATCH:
264
		error->re_vers.low = msg->acpted_rply.ar_vers.low;
265
		error->re_vers.high = msg->acpted_rply.ar_vers.high;
266
		break;
267
268
	default:
269
		break;
270
	}
271
}
272
DEF_STRONG(_seterr_reply);