1*9a747e4fSDavid du Colombier #include <plan9.h>
2*9a747e4fSDavid du Colombier #include <fcall.h>
3*9a747e4fSDavid du Colombier
4*9a747e4fSDavid du Colombier static
5*9a747e4fSDavid du Colombier uchar*
gstring(uchar * p,uchar * ep,char ** s)6*9a747e4fSDavid du Colombier gstring(uchar *p, uchar *ep, char **s)
7*9a747e4fSDavid du Colombier {
8*9a747e4fSDavid du Colombier uint n;
9*9a747e4fSDavid du Colombier
10*9a747e4fSDavid du Colombier if(p+BIT16SZ > ep)
11*9a747e4fSDavid du Colombier return nil;
12*9a747e4fSDavid du Colombier n = GBIT16(p);
13*9a747e4fSDavid du Colombier p += BIT16SZ - 1;
14*9a747e4fSDavid du Colombier if(p+n+1 > ep)
15*9a747e4fSDavid du Colombier return nil;
16*9a747e4fSDavid du Colombier /* move it down, on top of count, to make room for '\0' */
17*9a747e4fSDavid du Colombier memmove(p, p + 1, n);
18*9a747e4fSDavid du Colombier p[n] = '\0';
19*9a747e4fSDavid du Colombier *s = (char*)p;
20*9a747e4fSDavid du Colombier p += n+1;
21*9a747e4fSDavid du Colombier return p;
22*9a747e4fSDavid du Colombier }
23*9a747e4fSDavid du Colombier
24*9a747e4fSDavid du Colombier static
25*9a747e4fSDavid du Colombier uchar*
gqid(uchar * p,uchar * ep,Qid * q)26*9a747e4fSDavid du Colombier gqid(uchar *p, uchar *ep, Qid *q)
27*9a747e4fSDavid du Colombier {
28*9a747e4fSDavid du Colombier if(p+QIDSZ > ep)
29*9a747e4fSDavid du Colombier return nil;
30*9a747e4fSDavid du Colombier q->type = GBIT8(p);
31*9a747e4fSDavid du Colombier p += BIT8SZ;
32*9a747e4fSDavid du Colombier q->vers = GBIT32(p);
33*9a747e4fSDavid du Colombier p += BIT32SZ;
34*9a747e4fSDavid du Colombier q->path = GBIT64(p);
35*9a747e4fSDavid du Colombier p += BIT64SZ;
36*9a747e4fSDavid du Colombier return p;
37*9a747e4fSDavid du Colombier }
38*9a747e4fSDavid du Colombier
39*9a747e4fSDavid du Colombier /*
40*9a747e4fSDavid du Colombier * no syntactic checks.
41*9a747e4fSDavid du Colombier * three causes for error:
42*9a747e4fSDavid du Colombier * 1. message size field is incorrect
43*9a747e4fSDavid du Colombier * 2. input buffer too short for its own data (counts too long, etc.)
44*9a747e4fSDavid du Colombier * 3. too many names or qids
45*9a747e4fSDavid du Colombier * gqid() and gstring() return nil if they would reach beyond buffer.
46*9a747e4fSDavid du Colombier * main switch statement checks range and also can fall through
47*9a747e4fSDavid du Colombier * to test at end of routine.
48*9a747e4fSDavid du Colombier */
49*9a747e4fSDavid du Colombier uint
convM2S(uchar * ap,uint nap,Fcall * f)50*9a747e4fSDavid du Colombier convM2S(uchar *ap, uint nap, Fcall *f)
51*9a747e4fSDavid du Colombier {
52*9a747e4fSDavid du Colombier uchar *p, *ep;
53*9a747e4fSDavid du Colombier uint i, size;
54*9a747e4fSDavid du Colombier
55*9a747e4fSDavid du Colombier p = ap;
56*9a747e4fSDavid du Colombier ep = p + nap;
57*9a747e4fSDavid du Colombier
58*9a747e4fSDavid du Colombier if(p+BIT32SZ+BIT8SZ+BIT16SZ > ep)
59*9a747e4fSDavid du Colombier return 0;
60*9a747e4fSDavid du Colombier size = GBIT32(p);
61*9a747e4fSDavid du Colombier p += BIT32SZ;
62*9a747e4fSDavid du Colombier
63*9a747e4fSDavid du Colombier if(size > nap)
64*9a747e4fSDavid du Colombier return 0;
65*9a747e4fSDavid du Colombier if(size < BIT32SZ+BIT8SZ+BIT16SZ)
66*9a747e4fSDavid du Colombier return 0;
67*9a747e4fSDavid du Colombier
68*9a747e4fSDavid du Colombier f->type = GBIT8(p);
69*9a747e4fSDavid du Colombier p += BIT8SZ;
70*9a747e4fSDavid du Colombier f->tag = GBIT16(p);
71*9a747e4fSDavid du Colombier p += BIT16SZ;
72*9a747e4fSDavid du Colombier
73*9a747e4fSDavid du Colombier switch(f->type)
74*9a747e4fSDavid du Colombier {
75*9a747e4fSDavid du Colombier default:
76*9a747e4fSDavid du Colombier return 0;
77*9a747e4fSDavid du Colombier
78*9a747e4fSDavid du Colombier case Tversion:
79*9a747e4fSDavid du Colombier if(p+BIT32SZ > ep)
80*9a747e4fSDavid du Colombier return 0;
81*9a747e4fSDavid du Colombier f->msize = GBIT32(p);
82*9a747e4fSDavid du Colombier p += BIT32SZ;
83*9a747e4fSDavid du Colombier p = gstring(p, ep, &f->version);
84*9a747e4fSDavid du Colombier break;
85*9a747e4fSDavid du Colombier
86*9a747e4fSDavid du Colombier /*
87*9a747e4fSDavid du Colombier case Tsession:
88*9a747e4fSDavid du Colombier if(p+BIT16SZ > ep)
89*9a747e4fSDavid du Colombier return 0;
90*9a747e4fSDavid du Colombier f->nchal = GBIT16(p);
91*9a747e4fSDavid du Colombier p += BIT16SZ;
92*9a747e4fSDavid du Colombier if(p+f->nchal > ep)
93*9a747e4fSDavid du Colombier return 0;
94*9a747e4fSDavid du Colombier f->chal = p;
95*9a747e4fSDavid du Colombier p += f->nchal;
96*9a747e4fSDavid du Colombier break;
97*9a747e4fSDavid du Colombier */
98*9a747e4fSDavid du Colombier
99*9a747e4fSDavid du Colombier case Tflush:
100*9a747e4fSDavid du Colombier if(p+BIT16SZ > ep)
101*9a747e4fSDavid du Colombier return 0;
102*9a747e4fSDavid du Colombier f->oldtag = GBIT16(p);
103*9a747e4fSDavid du Colombier p += BIT16SZ;
104*9a747e4fSDavid du Colombier break;
105*9a747e4fSDavid du Colombier
106*9a747e4fSDavid du Colombier case Tauth:
107*9a747e4fSDavid du Colombier if(p+BIT32SZ > ep)
108*9a747e4fSDavid du Colombier return 0;
109*9a747e4fSDavid du Colombier f->afid = GBIT32(p);
110*9a747e4fSDavid du Colombier p += BIT32SZ;
111*9a747e4fSDavid du Colombier p = gstring(p, ep, &f->uname);
112*9a747e4fSDavid du Colombier if(p == nil)
113*9a747e4fSDavid du Colombier break;
114*9a747e4fSDavid du Colombier p = gstring(p, ep, &f->aname);
115*9a747e4fSDavid du Colombier if(p == nil)
116*9a747e4fSDavid du Colombier break;
117*9a747e4fSDavid du Colombier break;
118*9a747e4fSDavid du Colombier
119*9a747e4fSDavid du Colombier /*
120*9a747e4fSDavid du Colombier b
121*9a747e4fSDavid du Colombier case Tattach:
122*9a747e4fSDavid du Colombier if(p+BIT32SZ > ep)
123*9a747e4fSDavid du Colombier return 0;
124*9a747e4fSDavid du Colombier f->fid = GBIT32(p);
125*9a747e4fSDavid du Colombier p += BIT32SZ;
126*9a747e4fSDavid du Colombier p = gstring(p, ep, &f->uname);
127*9a747e4fSDavid du Colombier if(p == nil)
128*9a747e4fSDavid du Colombier break;
129*9a747e4fSDavid du Colombier p = gstring(p, ep, &f->aname);
130*9a747e4fSDavid du Colombier if(p == nil)
131*9a747e4fSDavid du Colombier break;
132*9a747e4fSDavid du Colombier if(p+BIT16SZ > ep)
133*9a747e4fSDavid du Colombier return 0;
134*9a747e4fSDavid du Colombier f->nauth = GBIT16(p);
135*9a747e4fSDavid du Colombier p += BIT16SZ;
136*9a747e4fSDavid du Colombier if(p+f->nauth > ep)
137*9a747e4fSDavid du Colombier return 0;
138*9a747e4fSDavid du Colombier f->auth = p;
139*9a747e4fSDavid du Colombier p += f->nauth;
140*9a747e4fSDavid du Colombier break;
141*9a747e4fSDavid du Colombier */
142*9a747e4fSDavid du Colombier
143*9a747e4fSDavid du Colombier case Tattach:
144*9a747e4fSDavid du Colombier if(p+BIT32SZ > ep)
145*9a747e4fSDavid du Colombier return 0;
146*9a747e4fSDavid du Colombier f->fid = GBIT32(p);
147*9a747e4fSDavid du Colombier p += BIT32SZ;
148*9a747e4fSDavid du Colombier if(p+BIT32SZ > ep)
149*9a747e4fSDavid du Colombier return 0;
150*9a747e4fSDavid du Colombier f->afid = GBIT32(p);
151*9a747e4fSDavid du Colombier p += BIT32SZ;
152*9a747e4fSDavid du Colombier p = gstring(p, ep, &f->uname);
153*9a747e4fSDavid du Colombier if(p == nil)
154*9a747e4fSDavid du Colombier break;
155*9a747e4fSDavid du Colombier p = gstring(p, ep, &f->aname);
156*9a747e4fSDavid du Colombier if(p == nil)
157*9a747e4fSDavid du Colombier break;
158*9a747e4fSDavid du Colombier break;
159*9a747e4fSDavid du Colombier
160*9a747e4fSDavid du Colombier
161*9a747e4fSDavid du Colombier case Twalk:
162*9a747e4fSDavid du Colombier if(p+BIT32SZ+BIT32SZ+BIT16SZ > ep)
163*9a747e4fSDavid du Colombier return 0;
164*9a747e4fSDavid du Colombier f->fid = GBIT32(p);
165*9a747e4fSDavid du Colombier p += BIT32SZ;
166*9a747e4fSDavid du Colombier f->newfid = GBIT32(p);
167*9a747e4fSDavid du Colombier p += BIT32SZ;
168*9a747e4fSDavid du Colombier f->nwname = GBIT16(p);
169*9a747e4fSDavid du Colombier p += BIT16SZ;
170*9a747e4fSDavid du Colombier if(f->nwname > MAXWELEM)
171*9a747e4fSDavid du Colombier return 0;
172*9a747e4fSDavid du Colombier for(i=0; i<f->nwname; i++){
173*9a747e4fSDavid du Colombier p = gstring(p, ep, &f->wname[i]);
174*9a747e4fSDavid du Colombier if(p == nil)
175*9a747e4fSDavid du Colombier break;
176*9a747e4fSDavid du Colombier }
177*9a747e4fSDavid du Colombier break;
178*9a747e4fSDavid du Colombier
179*9a747e4fSDavid du Colombier case Topen:
180*9a747e4fSDavid du Colombier if(p+BIT32SZ+BIT8SZ > ep)
181*9a747e4fSDavid du Colombier return 0;
182*9a747e4fSDavid du Colombier f->fid = GBIT32(p);
183*9a747e4fSDavid du Colombier p += BIT32SZ;
184*9a747e4fSDavid du Colombier f->mode = GBIT8(p);
185*9a747e4fSDavid du Colombier p += BIT8SZ;
186*9a747e4fSDavid du Colombier break;
187*9a747e4fSDavid du Colombier
188*9a747e4fSDavid du Colombier case Tcreate:
189*9a747e4fSDavid du Colombier if(p+BIT32SZ > ep)
190*9a747e4fSDavid du Colombier return 0;
191*9a747e4fSDavid du Colombier f->fid = GBIT32(p);
192*9a747e4fSDavid du Colombier p += BIT32SZ;
193*9a747e4fSDavid du Colombier p = gstring(p, ep, &f->name);
194*9a747e4fSDavid du Colombier if(p == nil)
195*9a747e4fSDavid du Colombier break;
196*9a747e4fSDavid du Colombier if(p+BIT32SZ+BIT8SZ > ep)
197*9a747e4fSDavid du Colombier return 0;
198*9a747e4fSDavid du Colombier f->perm = GBIT32(p);
199*9a747e4fSDavid du Colombier p += BIT32SZ;
200*9a747e4fSDavid du Colombier f->mode = GBIT8(p);
201*9a747e4fSDavid du Colombier p += BIT8SZ;
202*9a747e4fSDavid du Colombier break;
203*9a747e4fSDavid du Colombier
204*9a747e4fSDavid du Colombier case Tread:
205*9a747e4fSDavid du Colombier if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
206*9a747e4fSDavid du Colombier return 0;
207*9a747e4fSDavid du Colombier f->fid = GBIT32(p);
208*9a747e4fSDavid du Colombier p += BIT32SZ;
209*9a747e4fSDavid du Colombier f->offset = GBIT64(p);
210*9a747e4fSDavid du Colombier p += BIT64SZ;
211*9a747e4fSDavid du Colombier f->count = GBIT32(p);
212*9a747e4fSDavid du Colombier p += BIT32SZ;
213*9a747e4fSDavid du Colombier break;
214*9a747e4fSDavid du Colombier
215*9a747e4fSDavid du Colombier case Twrite:
216*9a747e4fSDavid du Colombier if(p+BIT32SZ+BIT64SZ+BIT32SZ > ep)
217*9a747e4fSDavid du Colombier return 0;
218*9a747e4fSDavid du Colombier f->fid = GBIT32(p);
219*9a747e4fSDavid du Colombier p += BIT32SZ;
220*9a747e4fSDavid du Colombier f->offset = GBIT64(p);
221*9a747e4fSDavid du Colombier p += BIT64SZ;
222*9a747e4fSDavid du Colombier f->count = GBIT32(p);
223*9a747e4fSDavid du Colombier p += BIT32SZ;
224*9a747e4fSDavid du Colombier if(p+f->count > ep)
225*9a747e4fSDavid du Colombier return 0;
226*9a747e4fSDavid du Colombier f->data = (char*)p;
227*9a747e4fSDavid du Colombier p += f->count;
228*9a747e4fSDavid du Colombier break;
229*9a747e4fSDavid du Colombier
230*9a747e4fSDavid du Colombier case Tclunk:
231*9a747e4fSDavid du Colombier case Tremove:
232*9a747e4fSDavid du Colombier if(p+BIT32SZ > ep)
233*9a747e4fSDavid du Colombier return 0;
234*9a747e4fSDavid du Colombier f->fid = GBIT32(p);
235*9a747e4fSDavid du Colombier p += BIT32SZ;
236*9a747e4fSDavid du Colombier break;
237*9a747e4fSDavid du Colombier
238*9a747e4fSDavid du Colombier case Tstat:
239*9a747e4fSDavid du Colombier if(p+BIT32SZ > ep)
240*9a747e4fSDavid du Colombier return 0;
241*9a747e4fSDavid du Colombier f->fid = GBIT32(p);
242*9a747e4fSDavid du Colombier p += BIT32SZ;
243*9a747e4fSDavid du Colombier break;
244*9a747e4fSDavid du Colombier
245*9a747e4fSDavid du Colombier case Twstat:
246*9a747e4fSDavid du Colombier if(p+BIT32SZ+BIT16SZ > ep)
247*9a747e4fSDavid du Colombier return 0;
248*9a747e4fSDavid du Colombier f->fid = GBIT32(p);
249*9a747e4fSDavid du Colombier p += BIT32SZ;
250*9a747e4fSDavid du Colombier f->nstat = GBIT16(p);
251*9a747e4fSDavid du Colombier p += BIT16SZ;
252*9a747e4fSDavid du Colombier if(p+f->nstat > ep)
253*9a747e4fSDavid du Colombier return 0;
254*9a747e4fSDavid du Colombier f->stat = p;
255*9a747e4fSDavid du Colombier p += f->nstat;
256*9a747e4fSDavid du Colombier break;
257*9a747e4fSDavid du Colombier
258*9a747e4fSDavid du Colombier /*
259*9a747e4fSDavid du Colombier */
260*9a747e4fSDavid du Colombier case Rversion:
261*9a747e4fSDavid du Colombier if(p+BIT32SZ > ep)
262*9a747e4fSDavid du Colombier return 0;
263*9a747e4fSDavid du Colombier f->msize = GBIT32(p);
264*9a747e4fSDavid du Colombier p += BIT32SZ;
265*9a747e4fSDavid du Colombier p = gstring(p, ep, &f->version);
266*9a747e4fSDavid du Colombier break;
267*9a747e4fSDavid du Colombier
268*9a747e4fSDavid du Colombier /*
269*9a747e4fSDavid du Colombier case Rsession:
270*9a747e4fSDavid du Colombier if(p+BIT16SZ > ep)
271*9a747e4fSDavid du Colombier return 0;
272*9a747e4fSDavid du Colombier f->nchal = GBIT16(p);
273*9a747e4fSDavid du Colombier p += BIT16SZ;
274*9a747e4fSDavid du Colombier if(p+f->nchal > ep)
275*9a747e4fSDavid du Colombier return 0;
276*9a747e4fSDavid du Colombier f->chal = p;
277*9a747e4fSDavid du Colombier p += f->nchal;
278*9a747e4fSDavid du Colombier p = gstring(p, ep, &f->authid);
279*9a747e4fSDavid du Colombier if(p == nil)
280*9a747e4fSDavid du Colombier break;
281*9a747e4fSDavid du Colombier p = gstring(p, ep, &f->authdom);
282*9a747e4fSDavid du Colombier break;
283*9a747e4fSDavid du Colombier */
284*9a747e4fSDavid du Colombier
285*9a747e4fSDavid du Colombier case Rerror:
286*9a747e4fSDavid du Colombier p = gstring(p, ep, &f->ename);
287*9a747e4fSDavid du Colombier break;
288*9a747e4fSDavid du Colombier
289*9a747e4fSDavid du Colombier case Rflush:
290*9a747e4fSDavid du Colombier break;
291*9a747e4fSDavid du Colombier
292*9a747e4fSDavid du Colombier /*
293*9a747e4fSDavid du Colombier case Rattach:
294*9a747e4fSDavid du Colombier p = gqid(p, ep, &f->qid);
295*9a747e4fSDavid du Colombier if(p == nil)
296*9a747e4fSDavid du Colombier break;
297*9a747e4fSDavid du Colombier if(p+BIT16SZ > ep)
298*9a747e4fSDavid du Colombier return 0;
299*9a747e4fSDavid du Colombier f->nrauth = GBIT16(p);
300*9a747e4fSDavid du Colombier p += BIT16SZ;
301*9a747e4fSDavid du Colombier if(p+f->nrauth > ep)
302*9a747e4fSDavid du Colombier return 0;
303*9a747e4fSDavid du Colombier f->rauth = p;
304*9a747e4fSDavid du Colombier p += f->nrauth;
305*9a747e4fSDavid du Colombier break;
306*9a747e4fSDavid du Colombier */
307*9a747e4fSDavid du Colombier
308*9a747e4fSDavid du Colombier case Rattach:
309*9a747e4fSDavid du Colombier p = gqid(p, ep, &f->qid);
310*9a747e4fSDavid du Colombier if(p == nil)
311*9a747e4fSDavid du Colombier break;
312*9a747e4fSDavid du Colombier break;
313*9a747e4fSDavid du Colombier
314*9a747e4fSDavid du Colombier
315*9a747e4fSDavid du Colombier case Rwalk:
316*9a747e4fSDavid du Colombier if(p+BIT16SZ > ep)
317*9a747e4fSDavid du Colombier return 0;
318*9a747e4fSDavid du Colombier f->nwqid = GBIT16(p);
319*9a747e4fSDavid du Colombier p += BIT16SZ;
320*9a747e4fSDavid du Colombier if(f->nwqid > MAXWELEM)
321*9a747e4fSDavid du Colombier return 0;
322*9a747e4fSDavid du Colombier for(i=0; i<f->nwqid; i++){
323*9a747e4fSDavid du Colombier p = gqid(p, ep, &f->wqid[i]);
324*9a747e4fSDavid du Colombier if(p == nil)
325*9a747e4fSDavid du Colombier break;
326*9a747e4fSDavid du Colombier }
327*9a747e4fSDavid du Colombier break;
328*9a747e4fSDavid du Colombier
329*9a747e4fSDavid du Colombier case Ropen:
330*9a747e4fSDavid du Colombier case Rcreate:
331*9a747e4fSDavid du Colombier p = gqid(p, ep, &f->qid);
332*9a747e4fSDavid du Colombier if(p == nil)
333*9a747e4fSDavid du Colombier break;
334*9a747e4fSDavid du Colombier if(p+BIT32SZ > ep)
335*9a747e4fSDavid du Colombier return 0;
336*9a747e4fSDavid du Colombier f->iounit = GBIT32(p);
337*9a747e4fSDavid du Colombier p += BIT32SZ;
338*9a747e4fSDavid du Colombier break;
339*9a747e4fSDavid du Colombier
340*9a747e4fSDavid du Colombier case Rread:
341*9a747e4fSDavid du Colombier if(p+BIT32SZ > ep)
342*9a747e4fSDavid du Colombier return 0;
343*9a747e4fSDavid du Colombier f->count = GBIT32(p);
344*9a747e4fSDavid du Colombier p += BIT32SZ;
345*9a747e4fSDavid du Colombier if(p+f->count > ep)
346*9a747e4fSDavid du Colombier return 0;
347*9a747e4fSDavid du Colombier f->data = (char*)p;
348*9a747e4fSDavid du Colombier p += f->count;
349*9a747e4fSDavid du Colombier break;
350*9a747e4fSDavid du Colombier
351*9a747e4fSDavid du Colombier case Rwrite:
352*9a747e4fSDavid du Colombier if(p+BIT32SZ > ep)
353*9a747e4fSDavid du Colombier return 0;
354*9a747e4fSDavid du Colombier f->count = GBIT32(p);
355*9a747e4fSDavid du Colombier p += BIT32SZ;
356*9a747e4fSDavid du Colombier break;
357*9a747e4fSDavid du Colombier
358*9a747e4fSDavid du Colombier case Rclunk:
359*9a747e4fSDavid du Colombier case Rremove:
360*9a747e4fSDavid du Colombier break;
361*9a747e4fSDavid du Colombier
362*9a747e4fSDavid du Colombier case Rstat:
363*9a747e4fSDavid du Colombier if(p+BIT16SZ > ep)
364*9a747e4fSDavid du Colombier return 0;
365*9a747e4fSDavid du Colombier f->nstat = GBIT16(p);
366*9a747e4fSDavid du Colombier p += BIT16SZ;
367*9a747e4fSDavid du Colombier if(p+f->nstat > ep)
368*9a747e4fSDavid du Colombier return 0;
369*9a747e4fSDavid du Colombier f->stat = p;
370*9a747e4fSDavid du Colombier p += f->nstat;
371*9a747e4fSDavid du Colombier break;
372*9a747e4fSDavid du Colombier
373*9a747e4fSDavid du Colombier case Rwstat:
374*9a747e4fSDavid du Colombier break;
375*9a747e4fSDavid du Colombier }
376*9a747e4fSDavid du Colombier
377*9a747e4fSDavid du Colombier if(p==nil || p>ep)
378*9a747e4fSDavid du Colombier return 0;
379*9a747e4fSDavid du Colombier if(ap+size == p)
380*9a747e4fSDavid du Colombier return size;
381*9a747e4fSDavid du Colombier return 0;
382*9a747e4fSDavid du Colombier }
383