xref: /freebsd/sys/rpc/rpc_callmsg.c (revision 6bfca4dcab07dad45a805879d954876b353c0810)
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  */
50 bool_t
51 xdr_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