1 /*
2 * linux/net/sunrpc/xdr.c
3 *
4 * Generic XDR support.
5 *
6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
7 */
8
9 #include <linux/types.h>
10 #include <linux/socket.h>
11 #include <linux/string.h>
12 #include <linux/kernel.h>
13 #include <linux/in.h>
14 #include <linux/sunrpc/xdr.h>
15 #include <linux/sunrpc/msg_prot.h>
16
17 u32 rpc_success, rpc_prog_unavail, rpc_prog_mismatch, rpc_proc_unavail,
18 rpc_garbage_args, rpc_system_err;
19 u32 rpc_auth_ok, rpc_autherr_badcred, rpc_autherr_rejectedcred,
20 rpc_autherr_badverf, rpc_autherr_rejectedverf, rpc_autherr_tooweak;
21 u32 xdr_zero, xdr_one, xdr_two;
22
23 void
24 xdr_init(void)
25 {
26 static int inited = 0;
27
28 if (inited)
29 return;
30
31 xdr_zero = htonl(0);
32 xdr_one = htonl(1);
33 xdr_two = htonl(2);
34
35 rpc_success = htonl(RPC_SUCCESS);
36 rpc_prog_unavail = htonl(RPC_PROG_UNAVAIL);
37 rpc_prog_mismatch = htonl(RPC_PROG_MISMATCH);
38 rpc_proc_unavail = htonl(RPC_PROC_UNAVAIL);
39 rpc_garbage_args = htonl(RPC_GARBAGE_ARGS);
40 rpc_system_err = htonl(RPC_SYSTEM_ERR);
41
42 rpc_auth_ok = htonl(RPC_AUTH_OK);
43 rpc_autherr_badcred = htonl(RPC_AUTH_BADCRED);
44 rpc_autherr_rejectedcred = htonl(RPC_AUTH_REJECTEDCRED);
45 rpc_autherr_badverf = htonl(RPC_AUTH_BADVERF);
46 rpc_autherr_rejectedverf = htonl(RPC_AUTH_REJECTEDVERF);
47 rpc_autherr_tooweak = htonl(RPC_AUTH_TOOWEAK);
48
49 inited = 1;
50 }
51
52 /*
53 * XDR functions for basic NFS types
54 */
55 u32 *
56 xdr_encode_netobj(u32 *p, const struct xdr_netobj *obj)
57 {
58 unsigned int quadlen = XDR_QUADLEN(obj->len);
59
60 p[quadlen] = 0; /* zero trailing bytes */
61 *p++ = htonl(obj->len);
62 memcpy(p, obj->data, obj->len);
63 return p + XDR_QUADLEN(obj->len);
64 }
65
66 u32 *
67 xdr_decode_netobj_fixed(u32 *p, void *obj, unsigned int len)
68 {
69 if (ntohl(*p++) != len)
70 return NULL;
71 memcpy(obj, p, len);
72 return p + XDR_QUADLEN(len);
73 }
74
75 u32 *
76 xdr_decode_netobj(u32 *p, struct xdr_netobj *obj)
77 {
78 unsigned int len;
79
80 if ((len = ntohl(*p++)) > XDR_MAX_NETOBJ)
81 return NULL;
82 obj->len = len;
83 obj->data = (u8 *) p;
84 return p + XDR_QUADLEN(len);
85 }
86
87 u32 *
88 xdr_encode_array(u32 *p, const char *array, unsigned int len)
89 {
90 int quadlen = XDR_QUADLEN(len);
91
92 p[quadlen] = 0;
93 *p++ = htonl(len);
94 memcpy(p, array, len);
95 return p + quadlen;
96 }
97
98 u32 *
99 xdr_encode_string(u32 *p, const char *string)
100 {
101 return xdr_encode_array(p, string, strlen(string));
102 }
103
104 u32 *
105 xdr_decode_string(u32 *p, char **sp, int *lenp, int maxlen)
106 {
107 unsigned int len;
108 char *string;
109
110 if ((len = ntohl(*p++)) > maxlen)
111 return NULL;
112 if (lenp)
113 *lenp = len;
114 if ((len % 4) != 0) {
115 string = (char *) p;
116 } else {
117 string = (char *) (p - 1);
118 memmove(string, p, len);
119 }
120 string[len] = '\0';
121 *sp = string;
122 return p + XDR_QUADLEN(len);
123 }
124
125 /*
126 * Realign the iovec if the server missed out some reply elements
127 * (such as post-op attributes,...)
128 * Note: This is a simple implementation that assumes that
129 * len <= iov->iov_len !!!
130 * The RPC header (assumed to be the 1st element in the iov array)
131 * is not shifted.
132 */
133 void xdr_shift_iovec(struct iovec *iov, int nr, size_t len)
134 {
135 struct iovec *pvec;
136
137 for (pvec = iov + nr - 1; nr > 1; nr--, pvec--) {
138 struct iovec *svec = pvec - 1;
139
140 if (len > pvec->iov_len) {
141 printk(KERN_DEBUG "RPC: Urk! Large shift of short iovec.\n");
142 return;
143 }
144 memmove((char *)pvec->iov_base + len, pvec->iov_base,
145 pvec->iov_len - len);
146
147 if (len > svec->iov_len) {
148 printk(KERN_DEBUG "RPC: Urk! Large shift of short iovec.\n");
149 return;
150 }
151 memcpy(pvec->iov_base,
152 (char *)svec->iov_base + svec->iov_len - len, len);
153 }
154 }
155
156 /*
157 * Zero the last n bytes in an iovec array of 'nr' elements
158 */
159 void xdr_zero_iovec(struct iovec *iov, int nr, size_t n)
160 {
161 struct iovec *pvec;
162
163 for (pvec = iov + nr - 1; n && nr > 0; nr--, pvec--) {
164 if (n < pvec->iov_len) {
165 memset((char *)pvec->iov_base + pvec->iov_len - n, 0, n);
166 n = 0;
167 } else {
168 memset(pvec->iov_base, 0, pvec->iov_len);
169 n -= pvec->iov_len;
170 }
171 }
172 }
173
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.