1a6a63ca5SChuck Lever /* SPDX-License-Identifier: GPL-2.0 */
2a6a63ca5SChuck Lever /*
3a6a63ca5SChuck Lever * Encode/decode NLM basic data types
4a6a63ca5SChuck Lever *
5a6a63ca5SChuck Lever * Basic NLMv3 XDR data types are not defined in an IETF standards
6a6a63ca5SChuck Lever * document. X/Open has a description of these data types that
7a6a63ca5SChuck Lever * is useful. See Chapter 10 of "Protocols for Interworking:
8a6a63ca5SChuck Lever * XNFS, Version 3W".
9a6a63ca5SChuck Lever *
10a6a63ca5SChuck Lever * Basic NLMv4 XDR data types are defined in Appendix II.1.4 of
11a6a63ca5SChuck Lever * RFC 1813: "NFS Version 3 Protocol Specification".
12a6a63ca5SChuck Lever *
13a6a63ca5SChuck Lever * Author: Chuck Lever <chuck.lever@oracle.com>
14a6a63ca5SChuck Lever *
15a6a63ca5SChuck Lever * Copyright (c) 2020, Oracle and/or its affiliates.
16a6a63ca5SChuck Lever */
17a6a63ca5SChuck Lever
18a6a63ca5SChuck Lever #ifndef _LOCKD_SVCXDR_H_
19a6a63ca5SChuck Lever #define _LOCKD_SVCXDR_H_
20a6a63ca5SChuck Lever
21a6a63ca5SChuck Lever static inline bool
svcxdr_decode_stats(struct xdr_stream * xdr,__be32 * status)22a6a63ca5SChuck Lever svcxdr_decode_stats(struct xdr_stream *xdr, __be32 *status)
23a6a63ca5SChuck Lever {
24a6a63ca5SChuck Lever __be32 *p;
25a6a63ca5SChuck Lever
26a6a63ca5SChuck Lever p = xdr_inline_decode(xdr, XDR_UNIT);
27a6a63ca5SChuck Lever if (!p)
28a6a63ca5SChuck Lever return false;
29a6a63ca5SChuck Lever *status = *p;
30a6a63ca5SChuck Lever
31a6a63ca5SChuck Lever return true;
32a6a63ca5SChuck Lever }
33a6a63ca5SChuck Lever
34a6a63ca5SChuck Lever static inline bool
svcxdr_encode_stats(struct xdr_stream * xdr,__be32 status)35a6a63ca5SChuck Lever svcxdr_encode_stats(struct xdr_stream *xdr, __be32 status)
36a6a63ca5SChuck Lever {
37a6a63ca5SChuck Lever __be32 *p;
38a6a63ca5SChuck Lever
39a6a63ca5SChuck Lever p = xdr_reserve_space(xdr, XDR_UNIT);
40a6a63ca5SChuck Lever if (!p)
41a6a63ca5SChuck Lever return false;
42a6a63ca5SChuck Lever *p = status;
43a6a63ca5SChuck Lever
44a6a63ca5SChuck Lever return true;
45a6a63ca5SChuck Lever }
46a6a63ca5SChuck Lever
47a6a63ca5SChuck Lever static inline bool
svcxdr_decode_string(struct xdr_stream * xdr,char ** data,unsigned int * data_len)48a6a63ca5SChuck Lever svcxdr_decode_string(struct xdr_stream *xdr, char **data, unsigned int *data_len)
49a6a63ca5SChuck Lever {
50a6a63ca5SChuck Lever __be32 *p;
51a6a63ca5SChuck Lever u32 len;
52a6a63ca5SChuck Lever
53a6a63ca5SChuck Lever if (xdr_stream_decode_u32(xdr, &len) < 0)
54a6a63ca5SChuck Lever return false;
55a6a63ca5SChuck Lever if (len > NLM_MAXSTRLEN)
56a6a63ca5SChuck Lever return false;
57a6a63ca5SChuck Lever p = xdr_inline_decode(xdr, len);
58a6a63ca5SChuck Lever if (!p)
59a6a63ca5SChuck Lever return false;
60a6a63ca5SChuck Lever *data_len = len;
61a6a63ca5SChuck Lever *data = (char *)p;
62a6a63ca5SChuck Lever
63a6a63ca5SChuck Lever return true;
64a6a63ca5SChuck Lever }
65a6a63ca5SChuck Lever
66a6a63ca5SChuck Lever /*
67a6a63ca5SChuck Lever * NLM cookies are defined by specification to be a variable-length
68a6a63ca5SChuck Lever * XDR opaque no longer than 1024 bytes. However, this implementation
69a6a63ca5SChuck Lever * limits their length to 32 bytes, and treats zero-length cookies
70a6a63ca5SChuck Lever * specially.
71a6a63ca5SChuck Lever */
72a6a63ca5SChuck Lever static inline bool
svcxdr_decode_cookie(struct xdr_stream * xdr,struct nlm_cookie * cookie)73a6a63ca5SChuck Lever svcxdr_decode_cookie(struct xdr_stream *xdr, struct nlm_cookie *cookie)
74a6a63ca5SChuck Lever {
75a6a63ca5SChuck Lever __be32 *p;
76a6a63ca5SChuck Lever u32 len;
77a6a63ca5SChuck Lever
78a6a63ca5SChuck Lever if (xdr_stream_decode_u32(xdr, &len) < 0)
79a6a63ca5SChuck Lever return false;
80a6a63ca5SChuck Lever if (len > NLM_MAXCOOKIELEN)
81a6a63ca5SChuck Lever return false;
82a6a63ca5SChuck Lever if (!len)
83a6a63ca5SChuck Lever goto out_hpux;
84a6a63ca5SChuck Lever
85a6a63ca5SChuck Lever p = xdr_inline_decode(xdr, len);
86a6a63ca5SChuck Lever if (!p)
87a6a63ca5SChuck Lever return false;
88a6a63ca5SChuck Lever cookie->len = len;
89a6a63ca5SChuck Lever memcpy(cookie->data, p, len);
90a6a63ca5SChuck Lever
91a6a63ca5SChuck Lever return true;
92a6a63ca5SChuck Lever
93a6a63ca5SChuck Lever /* apparently HPUX can return empty cookies */
94a6a63ca5SChuck Lever out_hpux:
95a6a63ca5SChuck Lever cookie->len = 4;
96a6a63ca5SChuck Lever memset(cookie->data, 0, 4);
97a6a63ca5SChuck Lever return true;
98a6a63ca5SChuck Lever }
99a6a63ca5SChuck Lever
100a6a63ca5SChuck Lever static inline bool
svcxdr_encode_cookie(struct xdr_stream * xdr,const struct nlm_cookie * cookie)101a6a63ca5SChuck Lever svcxdr_encode_cookie(struct xdr_stream *xdr, const struct nlm_cookie *cookie)
102a6a63ca5SChuck Lever {
103a6a63ca5SChuck Lever __be32 *p;
104a6a63ca5SChuck Lever
105a6a63ca5SChuck Lever if (xdr_stream_encode_u32(xdr, cookie->len) < 0)
106a6a63ca5SChuck Lever return false;
107a6a63ca5SChuck Lever p = xdr_reserve_space(xdr, cookie->len);
108a6a63ca5SChuck Lever if (!p)
109a6a63ca5SChuck Lever return false;
110a6a63ca5SChuck Lever memcpy(p, cookie->data, cookie->len);
111a6a63ca5SChuck Lever
112a6a63ca5SChuck Lever return true;
113a6a63ca5SChuck Lever }
114a6a63ca5SChuck Lever
115a6a63ca5SChuck Lever static inline bool
svcxdr_decode_owner(struct xdr_stream * xdr,struct xdr_netobj * obj)116a6a63ca5SChuck Lever svcxdr_decode_owner(struct xdr_stream *xdr, struct xdr_netobj *obj)
117a6a63ca5SChuck Lever {
118a6a63ca5SChuck Lever __be32 *p;
119a6a63ca5SChuck Lever u32 len;
120a6a63ca5SChuck Lever
121a6a63ca5SChuck Lever if (xdr_stream_decode_u32(xdr, &len) < 0)
122a6a63ca5SChuck Lever return false;
123a6a63ca5SChuck Lever if (len > XDR_MAX_NETOBJ)
124a6a63ca5SChuck Lever return false;
125a6a63ca5SChuck Lever p = xdr_inline_decode(xdr, len);
126a6a63ca5SChuck Lever if (!p)
127a6a63ca5SChuck Lever return false;
128a6a63ca5SChuck Lever obj->len = len;
129a6a63ca5SChuck Lever obj->data = (u8 *)p;
130a6a63ca5SChuck Lever
131a6a63ca5SChuck Lever return true;
132a6a63ca5SChuck Lever }
133a6a63ca5SChuck Lever
134a6a63ca5SChuck Lever static inline bool
svcxdr_encode_owner(struct xdr_stream * xdr,const struct xdr_netobj * obj)135a6a63ca5SChuck Lever svcxdr_encode_owner(struct xdr_stream *xdr, const struct xdr_netobj *obj)
136a6a63ca5SChuck Lever {
137*89c485c7SChuck Lever if (obj->len > XDR_MAX_NETOBJ)
138a6a63ca5SChuck Lever return false;
139*89c485c7SChuck Lever return xdr_stream_encode_opaque(xdr, obj->data, obj->len) > 0;
140a6a63ca5SChuck Lever }
141a6a63ca5SChuck Lever
142a6a63ca5SChuck Lever #endif /* _LOCKD_SVCXDR_H_ */
143