xref: /linux/include/linux/sunrpc/xdrgen/_builtins.h (revision c17ee635fd3a482b2ad2bf5e269755c2eae5f25e)
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 
15 static inline bool
16 xdrgen_decode_void(struct xdr_stream *xdr)
17 {
18 	return true;
19 }
20 
21 static inline bool
22 xdrgen_encode_void(struct xdr_stream *xdr)
23 {
24 	return true;
25 }
26 
27 static inline bool
28 xdrgen_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 
38 static inline bool
39 xdrgen_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  */
55 static inline bool
56 xdrgen_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  */
72 static inline bool
73 xdrgen_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  */
87 static inline bool
88 xdrgen_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 
98 static inline bool
99 xdrgen_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 
109 static inline bool
110 xdrgen_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 
120 static inline bool
121 xdrgen_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 
131 static inline bool
132 xdrgen_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 
142 static inline bool
143 xdrgen_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 
153 static inline bool
154 xdrgen_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 
164 static inline bool
165 xdrgen_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 
175 static inline bool
176 xdrgen_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 
186 static inline bool
187 xdrgen_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 
197 static inline bool
198 xdrgen_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 
208 static inline bool
209 xdrgen_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 
219 static inline bool
220 xdrgen_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 
230 static inline bool
231 xdrgen_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 
241 static inline bool
242 xdrgen_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 
259 static inline bool
260 xdrgen_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 
270 static inline bool
271 xdrgen_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 
288 static inline bool
289 xdrgen_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_ */
300