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