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