1/*	$NetBSD: rpc_callmsg.c,v 1.16 2000/07/14 08:40:42 fvdl Exp $	*/
2
3/*-
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 * Copyright (c) 2009, Sun Microsystems, Inc.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 * - Redistributions of source code must retain the above copyright notice,
12 *   this list of conditions and the following disclaimer.
13 * - Redistributions in binary form must reproduce the above copyright notice,
14 *   this list of conditions and the following disclaimer in the documentation
15 *   and/or other materials provided with the distribution.
16 * - Neither the name of Sun Microsystems, 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 "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
34/*
35 * rpc_callmsg.c
36 *
37 * Copyright (C) 1984, Sun Microsystems, Inc.
38 *
39 */
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/malloc.h>
44
45#include <rpc/rpc.h>
46
47/*
48 * XDR a call message
49 */
50bool_t
51xdr_callmsg(XDR *xdrs, struct rpc_msg *cmsg)
52{
53	enum msg_type *prm_direction;
54	int32_t *buf;
55	struct opaque_auth *oa;
56
57	if (xdrs->x_op == XDR_ENCODE) {
58		if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) {
59			return (FALSE);
60		}
61		if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) {
62			return (FALSE);
63		}
64		buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT
65			+ RNDUP(cmsg->rm_call.cb_cred.oa_length)
66			+ 2 * BYTES_PER_XDR_UNIT
67			+ RNDUP(cmsg->rm_call.cb_verf.oa_length));
68		if (buf != NULL) {
69			IXDR_PUT_INT32(buf, cmsg->rm_xid);
70			IXDR_PUT_ENUM(buf, cmsg->rm_direction);
71			if (cmsg->rm_direction != CALL) {
72				return (FALSE);
73			}
74			IXDR_PUT_INT32(buf, cmsg->rm_call.cb_rpcvers);
75			if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
76				return (FALSE);
77			}
78			IXDR_PUT_INT32(buf, cmsg->rm_call.cb_prog);
79			IXDR_PUT_INT32(buf, cmsg->rm_call.cb_vers);
80			IXDR_PUT_INT32(buf, cmsg->rm_call.cb_proc);
81			oa = &cmsg->rm_call.cb_cred;
82			IXDR_PUT_ENUM(buf, oa->oa_flavor);
83			IXDR_PUT_INT32(buf, oa->oa_length);
84			if (oa->oa_length) {
85				memcpy(buf, oa->oa_base, oa->oa_length);
86				buf += RNDUP(oa->oa_length) / sizeof (int32_t);
87			}
88			oa = &cmsg->rm_call.cb_verf;
89			IXDR_PUT_ENUM(buf, oa->oa_flavor);
90			IXDR_PUT_INT32(buf, oa->oa_length);
91			if (oa->oa_length) {
92				memcpy(buf, oa->oa_base, oa->oa_length);
93				/* no real need....
94				buf += RNDUP(oa->oa_length) / sizeof (int32_t);
95				*/
96			}
97			return (TRUE);
98		}
99	}
100	if (xdrs->x_op == XDR_DECODE) {
101		buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT);
102		if (buf != NULL) {
103			cmsg->rm_xid = IXDR_GET_UINT32(buf);
104			cmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type);
105			if (cmsg->rm_direction != CALL) {
106				return (FALSE);
107			}
108			cmsg->rm_call.cb_rpcvers = IXDR_GET_UINT32(buf);
109			if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
110				return (FALSE);
111			}
112			cmsg->rm_call.cb_prog = IXDR_GET_UINT32(buf);
113			cmsg->rm_call.cb_vers = IXDR_GET_UINT32(buf);
114			cmsg->rm_call.cb_proc = IXDR_GET_UINT32(buf);
115			oa = &cmsg->rm_call.cb_cred;
116			oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
117			oa->oa_length = (u_int)IXDR_GET_UINT32(buf);
118			if (oa->oa_length) {
119				if (oa->oa_length > MAX_AUTH_BYTES) {
120					return (FALSE);
121				}
122				if (oa->oa_base == NULL) {
123					oa->oa_base = (caddr_t)
124					    mem_alloc(oa->oa_length);
125					if (oa->oa_base == NULL)
126						return (FALSE);
127				}
128				buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length));
129				if (buf == NULL) {
130					if (xdr_opaque(xdrs, oa->oa_base,
131					    oa->oa_length) == FALSE) {
132						return (FALSE);
133					}
134				} else {
135					memcpy(oa->oa_base, buf,
136					    oa->oa_length);
137					/* no real need....
138					buf += RNDUP(oa->oa_length) /
139						sizeof (int32_t);
140					*/
141				}
142			}
143			oa = &cmsg->rm_call.cb_verf;
144			buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
145			if (buf == NULL) {
146				if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE ||
147				    xdr_u_int(xdrs, &oa->oa_length) == FALSE) {
148					return (FALSE);
149				}
150			} else {
151				oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
152				oa->oa_length = (u_int)IXDR_GET_UINT32(buf);
153			}
154			if (oa->oa_length) {
155				if (oa->oa_length > MAX_AUTH_BYTES) {
156					return (FALSE);
157				}
158				if (oa->oa_base == NULL) {
159					oa->oa_base = (caddr_t)
160					    mem_alloc(oa->oa_length);
161					if (oa->oa_base == NULL)
162						return (FALSE);
163				}
164				buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length));
165				if (buf == NULL) {
166					if (xdr_opaque(xdrs, oa->oa_base,
167					    oa->oa_length) == FALSE) {
168						return (FALSE);
169					}
170				} else {
171					memcpy(oa->oa_base, buf,
172					    oa->oa_length);
173					/* no real need...
174					buf += RNDUP(oa->oa_length) /
175						sizeof (int32_t);
176					*/
177				}
178			}
179			return (TRUE);
180		}
181	}
182	prm_direction = &cmsg->rm_direction;
183	if (
184	    xdr_uint32_t(xdrs, &(cmsg->rm_xid)) &&
185	    xdr_enum(xdrs, (enum_t *) prm_direction) &&
186	    (cmsg->rm_direction == CALL) &&
187	    xdr_uint32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
188	    (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) &&
189	    xdr_uint32_t(xdrs, &(cmsg->rm_call.cb_prog)) &&
190	    xdr_uint32_t(xdrs, &(cmsg->rm_call.cb_vers)) &&
191	    xdr_uint32_t(xdrs, &(cmsg->rm_call.cb_proc)) &&
192	    xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_cred)) )
193		return (xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_verf)));
194	return (FALSE);
195}
196