Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) 2024 Oracle and/or its affiliates.
4 *
5 * This header defines XDR data type primitives specified in
6 * Section 4 of RFC 4506, used by RPC programs implemented
7 * in the Linux kernel.
8 */
9
10#ifndef _SUNRPC_XDRGEN__BUILTINS_H_
11#define _SUNRPC_XDRGEN__BUILTINS_H_
12
13#include <linux/sunrpc/xdr.h>
14
15static inline bool
16xdrgen_decode_void(struct xdr_stream *xdr)
17{
18 return true;
19}
20
21static inline bool
22xdrgen_encode_void(struct xdr_stream *xdr)
23{
24 return true;
25}
26
27static inline bool
28xdrgen_decode_bool(struct xdr_stream *xdr, bool *ptr)
29{
30 __be32 *p = xdr_inline_decode(xdr, XDR_UNIT);
31
32 if (unlikely(!p))
33 return false;
34 *ptr = (*p != xdr_zero);
35 return true;
36}
37
38static inline bool
39xdrgen_encode_bool(struct xdr_stream *xdr, bool val)
40{
41 __be32 *p = xdr_reserve_space(xdr, XDR_UNIT);
42
43 if (unlikely(!p))
44 return false;
45 *p = val ? xdr_one : xdr_zero;
46 return true;
47}
48
49/*
50 * De facto (non-standard but commonly implemented) signed short type:
51 * - Wire sends sign-extended 32-bit value (e.g., 0xFFFFFFFF)
52 * - be32_to_cpup() returns u32 (0xFFFFFFFF)
53 * - Explicit (s16) cast truncates to 16 bits (0xFFFF = -1)
54 */
55static inline bool
56xdrgen_decode_short(struct xdr_stream *xdr, s16 *ptr)
57{
58 __be32 *p = xdr_inline_decode(xdr, XDR_UNIT);
59
60 if (unlikely(!p))
61 return false;
62 *ptr = (s16)be32_to_cpup(p);
63 return true;
64}
65
66/*
67 * De facto (non-standard but commonly implemented) signed short type:
68 * - C integer promotion sign-extends s16 val to int before passing to
69 * cpu_to_be32()
70 * - This is well-defined: -1 as s16 -1 as int 0xFFFFFFFF on wire
71 */
72static inline bool
73xdrgen_encode_short(struct xdr_stream *xdr, s16 val)
74{
75 __be32 *p = xdr_reserve_space(xdr, XDR_UNIT);
76
77 if (unlikely(!p))
78 return false;
79 *p = cpu_to_be32(val);
80 return true;
81}
82
83/*
84 * De facto (non-standard but commonly implemented) unsigned short type:
85 * 16-bit integer zero-extended to fill one XDR_UNIT.
86 */
87static inline bool
88xdrgen_decode_unsigned_short(struct xdr_stream *xdr, u16 *ptr)
89{
90 __be32 *p = xdr_inline_decode(xdr, XDR_UNIT);
91
92 if (unlikely(!p))
93 return false;
94 *ptr = (u16)be32_to_cpup(p);
95 return true;
96}
97
98static inline bool
99xdrgen_encode_unsigned_short(struct xdr_stream *xdr, u16 val)
100{
101 __be32 *p = xdr_reserve_space(xdr, XDR_UNIT);
102
103 if (unlikely(!p))
104 return false;
105 *p = cpu_to_be32(val);
106 return true;
107}
108
109static inline bool
110xdrgen_decode_int(struct xdr_stream *xdr, s32 *ptr)
111{
112 __be32 *p = xdr_inline_decode(xdr, XDR_UNIT);
113
114 if (unlikely(!p))
115 return false;
116 *ptr = be32_to_cpup(p);
117 return true;
118}
119
120static inline bool
121xdrgen_encode_int(struct xdr_stream *xdr, s32 val)
122{
123 __be32 *p = xdr_reserve_space(xdr, XDR_UNIT);
124
125 if (unlikely(!p))
126 return false;
127 *p = cpu_to_be32(val);
128 return true;
129}
130
131static inline bool
132xdrgen_decode_unsigned_int(struct xdr_stream *xdr, u32 *ptr)
133{
134 __be32 *p = xdr_inline_decode(xdr, XDR_UNIT);
135
136 if (unlikely(!p))
137 return false;
138 *ptr = be32_to_cpup(p);
139 return true;
140}
141
142static inline bool
143xdrgen_encode_unsigned_int(struct xdr_stream *xdr, u32 val)
144{
145 __be32 *p = xdr_reserve_space(xdr, XDR_UNIT);
146
147 if (unlikely(!p))
148 return false;
149 *p = cpu_to_be32(val);
150 return true;
151}
152
153static inline bool
154xdrgen_decode_long(struct xdr_stream *xdr, s32 *ptr)
155{
156 __be32 *p = xdr_inline_decode(xdr, XDR_UNIT);
157
158 if (unlikely(!p))
159 return false;
160 *ptr = be32_to_cpup(p);
161 return true;
162}
163
164static inline bool
165xdrgen_encode_long(struct xdr_stream *xdr, s32 val)
166{
167 __be32 *p = xdr_reserve_space(xdr, XDR_UNIT);
168
169 if (unlikely(!p))
170 return false;
171 *p = cpu_to_be32(val);
172 return true;
173}
174
175static inline bool
176xdrgen_decode_unsigned_long(struct xdr_stream *xdr, u32 *ptr)
177{
178 __be32 *p = xdr_inline_decode(xdr, XDR_UNIT);
179
180 if (unlikely(!p))
181 return false;
182 *ptr = be32_to_cpup(p);
183 return true;
184}
185
186static inline bool
187xdrgen_encode_unsigned_long(struct xdr_stream *xdr, u32 val)
188{
189 __be32 *p = xdr_reserve_space(xdr, XDR_UNIT);
190
191 if (unlikely(!p))
192 return false;
193 *p = cpu_to_be32(val);
194 return true;
195}
196
197static inline bool
198xdrgen_decode_hyper(struct xdr_stream *xdr, s64 *ptr)
199{
200 __be32 *p = xdr_inline_decode(xdr, XDR_UNIT * 2);
201
202 if (unlikely(!p))
203 return false;
204 *ptr = get_unaligned_be64(p);
205 return true;
206}
207
208static inline bool
209xdrgen_encode_hyper(struct xdr_stream *xdr, s64 val)
210{
211 __be32 *p = xdr_reserve_space(xdr, XDR_UNIT * 2);
212
213 if (unlikely(!p))
214 return false;
215 put_unaligned_be64(val, p);
216 return true;
217}
218
219static inline bool
220xdrgen_decode_unsigned_hyper(struct xdr_stream *xdr, u64 *ptr)
221{
222 __be32 *p = xdr_inline_decode(xdr, XDR_UNIT * 2);
223
224 if (unlikely(!p))
225 return false;
226 *ptr = get_unaligned_be64(p);
227 return true;
228}
229
230static inline bool
231xdrgen_encode_unsigned_hyper(struct xdr_stream *xdr, u64 val)
232{
233 __be32 *p = xdr_reserve_space(xdr, XDR_UNIT * 2);
234
235 if (unlikely(!p))
236 return false;
237 put_unaligned_be64(val, p);
238 return true;
239}
240
241static inline bool
242xdrgen_decode_string(struct xdr_stream *xdr, string *ptr, u32 maxlen)
243{
244 __be32 *p;
245 u32 len;
246
247 if (unlikely(xdr_stream_decode_u32(xdr, &len) < 0))
248 return false;
249 if (unlikely(maxlen && len > maxlen))
250 return false;
251 p = xdr_inline_decode(xdr, len);
252 if (unlikely(!p))
253 return false;
254 ptr->data = (unsigned char *)p;
255 ptr->len = len;
256 return true;
257}
258
259static inline bool
260xdrgen_encode_string(struct xdr_stream *xdr, string val, u32 maxlen)
261{
262 __be32 *p = xdr_reserve_space(xdr, XDR_UNIT + xdr_align_size(val.len));
263
264 if (unlikely(!p))
265 return false;
266 xdr_encode_opaque(p, val.data, val.len);
267 return true;
268}
269
270static inline bool
271xdrgen_decode_opaque(struct xdr_stream *xdr, opaque *ptr, u32 maxlen)
272{
273 __be32 *p;
274 u32 len;
275
276 if (unlikely(xdr_stream_decode_u32(xdr, &len) < 0))
277 return false;
278 if (unlikely(maxlen && len > maxlen))
279 return false;
280 p = xdr_inline_decode(xdr, len);
281 if (unlikely(!p))
282 return false;
283 ptr->data = (u8 *)p;
284 ptr->len = len;
285 return true;
286}
287
288static inline bool
289xdrgen_encode_opaque(struct xdr_stream *xdr, opaque val)
290{
291 __be32 *p = xdr_reserve_space(xdr, XDR_UNIT + xdr_align_size(val.len));
292
293 if (unlikely(!p))
294 return false;
295 xdr_encode_opaque(p, val.data, val.len);
296 return true;
297}
298
299#endif /* _SUNRPC_XDRGEN__BUILTINS_H_ */