xref: /plan9/sys/src/cmd/9nfs/rpc.c (revision ff8c3af2f44d95267f67219afa20ba82ff6cf7e4)
1 #include "all.h"
2 
3 #define	SHORT(x)	r->x = (p[1] | (p[0]<<8)); p += 2
4 #define	LONG(x)		r->x = (p[3] | (p[2]<<8) |\
5 				(p[1]<<16) | (p[0]<<24)); p += 4
6 #define SKIPLONG	p += 4
7 #define	PTR(x, n)	r->x = (void *)(p); p += ROUNDUP(n)
8 
9 uchar v4prefix[12] = {
10 	0, 0, 0, 0,
11 	0, 0, 0, 0,
12 	0, 0, 0xff, 0xff,
13 };
14 
15 int
16 rpcM2S(void *ap, Rpccall *r, int n)
17 {
18 	uchar *p = ap;
19 	int k;
20 
21 	p += 12;
22 	LONG(host);
23 	p += 12;
24 	LONG(lhost);
25 	SHORT(port);
26 	SHORT(lport);
27 	LONG(xid);
28 	LONG(mtype);
29 	switch(r->mtype){
30 	case CALL:
31 		LONG(rpcvers);
32 		if(r->rpcvers != 2)
33 			break;
34 		LONG(prog);
35 		LONG(vers);
36 		LONG(proc);
37 		LONG(cred.flavor);
38 		LONG(cred.count);
39 		PTR(cred.data, r->cred.count);
40 		LONG(verf.flavor);
41 		LONG(verf.count);
42 		PTR(verf.data, r->verf.count);
43 		r->up = 0;
44 		k = n - (p - (uchar *)ap);
45 		if(k < 0)
46 			break;
47 		PTR(args, k);
48 		break;
49 	case REPLY:
50 		LONG(stat);
51 		switch(r->stat){
52 		case MSG_ACCEPTED:
53 			LONG(averf.flavor);
54 			LONG(averf.count);
55 			PTR(averf.data, r->averf.count);
56 			LONG(astat);
57 			switch(r->astat){
58 			case SUCCESS:
59 				k = n - (p - (uchar *)ap);
60 				if(k < 0)
61 					break;
62 				PTR(results, k);
63 				break;
64 			case PROG_MISMATCH:
65 				LONG(plow);
66 				LONG(phigh);
67 				break;
68 			}
69 			break;
70 		case MSG_DENIED:
71 			LONG(rstat);
72 			switch(r->rstat){
73 			case RPC_MISMATCH:
74 				LONG(rlow);
75 				LONG(rhigh);
76 				break;
77 			case AUTH_ERROR:
78 				LONG(authstat);
79 				break;
80 			}
81 			break;
82 		}
83 		break;
84 	}
85 	n -= p - (uchar *)ap;
86 	return n;
87 }
88 
89 int
90 auth2unix(Auth *arg, Authunix *r)
91 {
92 	int i, n;
93 	uchar *p;
94 
95 	if(arg->flavor != AUTH_UNIX)
96 		return -1;
97 	p = arg->data;
98 	LONG(stamp);
99 	LONG(mach.n);
100 	PTR(mach.s, r->mach.n);
101 	LONG(uid);
102 	LONG(gid);
103 	LONG(gidlen);
104 	n = r->gidlen;
105 	for(i=0; i<n && i < nelem(r->gids); i++){
106 		LONG(gids[i]);
107 	}
108 	for(; i<n; i++){
109 		SKIPLONG;
110 	}
111 	return arg->count - (p - (uchar *)arg->data);
112 }
113 
114 int
115 string2S(void *arg, String *r)
116 {
117 	uchar *p;
118 	char *s;
119 
120 	p = arg;
121 	LONG(n);
122 	PTR(s, r->n);
123 	/* must NUL terminate */
124 	s = malloc(r->n+1);
125 	if(s == nil)
126 		panic("malloc(%ld) failed in string2S\n", r->n+1);
127 	memmove(s, r->s, r->n);
128 	s[r->n] = '\0';
129 	r->s = strstore(s);
130 	free(s);
131 	return p - (uchar *)arg;
132 }
133 
134 #undef	SHORT
135 #undef	LONG
136 #undef	PTR
137 
138 #define	SHORT(x)	p[1] = r->x; p[0] = r->x>>8; p += 2
139 #define	LONG(x)		p[3] = r->x; p[2] = r->x>>8; p[1] = r->x>>16; p[0] = r->x>>24; p += 4
140 
141 #define	PTR(x,n)	memmove(p, r->x, n); p += ROUNDUP(n)
142 
143 int
144 rpcS2M(Rpccall *r, int ndata, void *ap)
145 {
146 	uchar *p = ap;
147 
148 	memmove(p, v4prefix, 12);
149 	p += 12;
150 	LONG(host);
151 	memmove(p, v4prefix, 12);
152 	p += 12;
153 	LONG(lhost);
154 	SHORT(port);
155 	SHORT(lport);
156 	LONG(xid);
157 	LONG(mtype);
158 	switch(r->mtype){
159 	case CALL:
160 		LONG(rpcvers);
161 		LONG(prog);
162 		LONG(vers);
163 		LONG(proc);
164 		LONG(cred.flavor);
165 		LONG(cred.count);
166 		PTR(cred.data, r->cred.count);
167 		LONG(verf.flavor);
168 		LONG(verf.count);
169 		PTR(verf.data, r->verf.count);
170 		PTR(args, ndata);
171 		break;
172 	case REPLY:
173 		LONG(stat);
174 		switch(r->stat){
175 		case MSG_ACCEPTED:
176 			LONG(averf.flavor);
177 			LONG(averf.count);
178 			PTR(averf.data, r->averf.count);
179 			LONG(astat);
180 			switch(r->astat){
181 			case SUCCESS:
182 				PTR(results, ndata);
183 				break;
184 			case PROG_MISMATCH:
185 				LONG(plow);
186 				LONG(phigh);
187 				break;
188 			}
189 			break;
190 		case MSG_DENIED:
191 			LONG(rstat);
192 			switch(r->rstat){
193 			case RPC_MISMATCH:
194 				LONG(rlow);
195 				LONG(rhigh);
196 				break;
197 			case AUTH_ERROR:
198 				LONG(authstat);
199 				break;
200 			}
201 			break;
202 		}
203 		break;
204 	}
205 	return p - (uchar *)ap;
206 }
207 
208 #undef	SHORT
209 #undef	LONG
210 #undef	PTR
211 
212 #define	LONG(m, x)	fprint(fd, "%s = %ld\n", m, r->x)
213 
214 #define	PTR(m, count)	fprint(fd, "%s [%ld]\n", m, count)
215 
216 void
217 rpcprint(int fd, Rpccall *r)
218 {
219 	fprint(fd, "%s: host = %I, port = %ld\n",
220 		argv0, r->host, r->port);
221 	LONG("xid", xid);
222 	LONG("mtype", mtype);
223 	switch(r->mtype){
224 	case CALL:
225 		LONG("rpcvers", rpcvers);
226 		LONG("prog", prog);
227 		LONG("vers", vers);
228 		LONG("proc", proc);
229 		LONG("cred.flavor", cred.flavor);
230 		PTR("cred.data", r->cred.count);
231 		LONG("verf.flavor", verf.flavor);
232 		PTR("verf.data", r->verf.count);
233 		fprint(fd, "args...\n");
234 		break;
235 	case REPLY:
236 		LONG("stat", stat);
237 		switch(r->stat){
238 		case MSG_ACCEPTED:
239 			LONG("averf.flavor", averf.flavor);
240 			PTR("averf.data", r->averf.count);
241 			LONG("astat", astat);
242 			switch(r->astat){
243 			case SUCCESS:
244 				fprint(fd, "results...\n");
245 				break;
246 			case PROG_MISMATCH:
247 				LONG("plow", plow);
248 				LONG("phigh", phigh);
249 				break;
250 			}
251 			break;
252 		case MSG_DENIED:
253 			LONG("rstat", rstat);
254 			switch(r->rstat){
255 			case RPC_MISMATCH:
256 				LONG("rlow", rlow);
257 				LONG("rhigh", rhigh);
258 				break;
259 			case AUTH_ERROR:
260 				LONG("authstat", authstat);
261 				break;
262 			}
263 			break;
264 		}
265 	}
266 }
267 
268 void
269 showauth(Auth *ap)
270 {
271 	Authunix au;
272 	int i;
273 
274 	if(auth2unix(ap, &au) != 0){
275 		chat("auth flavor=%ld, count=%ld",
276 			ap->flavor, ap->count);
277 		for(i=0; i<ap->count; i++)
278 			chat(" %.2ux", ((uchar *)ap->data)[i]);
279 	}else{
280 		chat("auth: %ld %.*s u=%ld g=%ld",
281 			au.stamp, utfnlen(au.mach.s, au.mach.n), au.mach.s, au.uid, au.gid);
282 		for(i=0; i<au.gidlen; i++)
283 			chat(", %ld", au.gids[i]);
284 	}
285 	chat("...");
286 }
287 
288 int
289 garbage(Rpccall *reply, char *msg)
290 {
291 	chat("%s\n", msg ? msg : "garbage");
292 	reply->astat = GARBAGE_ARGS;
293 	return 0;
294 }
295 
296 int
297 error(Rpccall *reply, int errno)
298 {
299 	uchar *dataptr = reply->results;
300 
301 	chat("error %d\n", errno);
302 	PLONG(errno);
303 	return dataptr - (uchar *)reply->results;
304 }
305