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