xref: /openbmc/linux/fs/lockd/svcxdr.h (revision 89c485c7)
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