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