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
xdrgen_decode_void(struct xdr_stream * xdr)16 xdrgen_decode_void(struct xdr_stream *xdr)
17 {
18 return true;
19 }
20
21 static inline bool
xdrgen_encode_void(struct xdr_stream * xdr)22 xdrgen_encode_void(struct xdr_stream *xdr)
23 {
24 return true;
25 }
26
27 static inline bool
xdrgen_decode_bool(struct xdr_stream * xdr,bool * ptr)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
xdrgen_encode_bool(struct xdr_stream * xdr,bool val)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
xdrgen_decode_short(struct xdr_stream * xdr,s16 * ptr)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
xdrgen_encode_short(struct xdr_stream * xdr,s16 val)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
xdrgen_decode_unsigned_short(struct xdr_stream * xdr,u16 * ptr)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
xdrgen_encode_unsigned_short(struct xdr_stream * xdr,u16 val)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
xdrgen_decode_int(struct xdr_stream * xdr,s32 * ptr)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
xdrgen_encode_int(struct xdr_stream * xdr,s32 val)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
xdrgen_decode_unsigned_int(struct xdr_stream * xdr,u32 * ptr)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
xdrgen_encode_unsigned_int(struct xdr_stream * xdr,u32 val)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
xdrgen_decode_long(struct xdr_stream * xdr,s32 * ptr)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
xdrgen_encode_long(struct xdr_stream * xdr,s32 val)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
xdrgen_decode_unsigned_long(struct xdr_stream * xdr,u32 * ptr)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
xdrgen_encode_unsigned_long(struct xdr_stream * xdr,u32 val)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
xdrgen_decode_hyper(struct xdr_stream * xdr,s64 * ptr)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
xdrgen_encode_hyper(struct xdr_stream * xdr,s64 val)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
xdrgen_decode_unsigned_hyper(struct xdr_stream * xdr,u64 * ptr)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
xdrgen_encode_unsigned_hyper(struct xdr_stream * xdr,u64 val)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
xdrgen_decode_string(struct xdr_stream * xdr,string * ptr,u32 maxlen)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
xdrgen_encode_string(struct xdr_stream * xdr,string val,u32 maxlen)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
xdrgen_decode_opaque(struct xdr_stream * xdr,opaque * ptr,u32 maxlen)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
xdrgen_encode_opaque(struct xdr_stream * xdr,opaque val)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