qio: Do not kick when calling qdiscard()
[akaros.git] / kern / src / ns / convM2S.c
1 /* Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
2  * Portions Copyright © 1997-1999 Vita Nuova Limited
3  * Portions Copyright © 2000-2007 Vita Nuova Holdings Limited
4  *                                (www.vitanuova.com)
5  * Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
6  *
7  * Modified for the Akaros operating system:
8  * Copyright (c) 2013-2014 The Regents of the University of California
9  * Copyright (c) 2013-2015 Google Inc.
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a copy
12  * of this software and associated documentation files (the "Software"), to deal
13  * in the Software without restriction, including without limitation the rights
14  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15  * copies of the Software, and to permit persons to whom the Software is
16  * furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included in
19  * all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
24  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27  * SOFTWARE. */
28
29 #include <vfs.h>
30 #include <kfs.h>
31 #include <slab.h>
32 #include <kmalloc.h>
33 #include <kref.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <assert.h>
37 #include <error.h>
38 #include <cpio.h>
39 #include <pmap.h>
40 #include <smp.h>
41 #include <ip.h>
42
43 static
44 uint8_t *gstring(uint8_t * p, uint8_t * ep, char **s)
45 {
46         unsigned int n;
47
48         if (p + BIT16SZ > ep)
49                 return NULL;
50         n = GBIT16(p);
51         p += BIT16SZ - 1;
52         if (p + n + 1 > ep)
53                 return NULL;
54         /* move it down, on top of count, to make room for '\0' */
55         memmove(p, p + 1, n);
56         p[n] = '\0';
57         *s = (char *)p;
58         p += n + 1;
59         return p;
60 }
61
62 static
63 uint8_t *gqid(uint8_t * p, uint8_t * ep, struct qid *q)
64 {
65         if (p + QIDSZ > ep)
66                 return NULL;
67         q->type = GBIT8(p);
68         p += BIT8SZ;
69         q->vers = GBIT32(p);
70         p += BIT32SZ;
71         q->path = GBIT64(p);
72         p += BIT64SZ;
73         return p;
74 }
75
76 void init_empty_dir(struct dir *d)
77 {
78         d->type = ~0;
79         d->dev = ~0;
80         d->qid.path = ~0;
81         d->qid.vers = ~0;
82         d->qid.type = ~0;
83         d->mode = ~0;
84         d->atime = ~0;
85         d->mtime = ~0;
86         d->length = ~0;
87         d->name = "";
88         d->uid = "";
89         d->gid = "";
90         d->muid = "";
91 }
92
93 /*
94  * no syntactic checks.
95  * three causes for error:
96  *  1. message size field is incorrect
97  *  2. input buffer too short for its own data (counts too long, etc.)
98  *  3. too many names or qids
99  * gqid() and gstring() return NULL if they would reach beyond buffer.
100  * main switch statement checks range and also can fall through
101  * to test at end of routine.
102  */
103 unsigned int convM2S(uint8_t * ap, unsigned int nap, struct fcall *f)
104 {
105         uint8_t *p, *ep;
106         unsigned int i, size;
107
108         p = ap;
109         ep = p + nap;
110
111         if (p + BIT32SZ + BIT8SZ + BIT16SZ > ep)
112                 return 0;
113         size = GBIT32(p);
114         p += BIT32SZ;
115
116         if (size < BIT32SZ + BIT8SZ + BIT16SZ)
117                 return 0;
118
119         f->type = GBIT8(p);
120         p += BIT8SZ;
121         f->tag = GBIT16(p);
122         p += BIT16SZ;
123
124         switch (f->type) {
125                 default:
126                         return 0;
127
128                 case Tversion:
129                         if (p + BIT32SZ > ep)
130                                 return 0;
131                         f->msize = GBIT32(p);
132                         p += BIT32SZ;
133                         p = gstring(p, ep, &f->version);
134                         break;
135
136                 case Tflush:
137                         if (p + BIT16SZ > ep)
138                                 return 0;
139                         f->oldtag = GBIT16(p);
140                         p += BIT16SZ;
141                         break;
142
143                 case Tauth:
144                         if (p + BIT32SZ > ep)
145                                 return 0;
146                         f->afid = GBIT32(p);
147                         p += BIT32SZ;
148                         p = gstring(p, ep, &f->uname);
149                         if (p == NULL)
150                                 break;
151                         p = gstring(p, ep, &f->aname);
152                         if (p == NULL)
153                                 break;
154                         break;
155
156                 case Tattach:
157                         if (p + BIT32SZ > ep)
158                                 return 0;
159                         f->fid = GBIT32(p);
160                         p += BIT32SZ;
161                         if (p + BIT32SZ > ep)
162                                 return 0;
163                         f->afid = GBIT32(p);
164                         p += BIT32SZ;
165                         p = gstring(p, ep, &f->uname);
166                         if (p == NULL)
167                                 break;
168                         p = gstring(p, ep, &f->aname);
169                         if (p == NULL)
170                                 break;
171                         break;
172
173                 case Twalk:
174                         if (p + BIT32SZ + BIT32SZ + BIT16SZ > ep)
175                                 return 0;
176                         f->fid = GBIT32(p);
177                         p += BIT32SZ;
178                         f->newfid = GBIT32(p);
179                         p += BIT32SZ;
180                         f->nwname = GBIT16(p);
181                         p += BIT16SZ;
182                         if (f->nwname > MAXWELEM)
183                                 return 0;
184                         for (i = 0; i < f->nwname; i++) {
185                                 p = gstring(p, ep, &f->wname[i]);
186                                 if (p == NULL)
187                                         break;
188                         }
189                         break;
190
191                 case Topen:
192                         if (p + BIT32SZ + BIT8SZ > ep)
193                                 return 0;
194                         f->fid = GBIT32(p);
195                         p += BIT32SZ;
196                         f->mode = GBIT8(p);
197                         p += BIT8SZ;
198                         break;
199
200                 case Tcreate:
201                         if (p + BIT32SZ > ep)
202                                 return 0;
203                         f->fid = GBIT32(p);
204                         p += BIT32SZ;
205                         p = gstring(p, ep, &f->name);
206                         if (p == NULL)
207                                 break;
208                         if (p + BIT32SZ + BIT8SZ > ep)
209                                 return 0;
210                         f->perm = GBIT32(p);
211                         p += BIT32SZ;
212                         f->mode = GBIT8(p);
213                         p += BIT8SZ;
214                         break;
215
216                 case Tread:
217                         if (p + BIT32SZ + BIT64SZ + BIT32SZ > ep)
218                                 return 0;
219                         f->fid = GBIT32(p);
220                         p += BIT32SZ;
221                         f->offset = GBIT64(p);
222                         p += BIT64SZ;
223                         f->count = GBIT32(p);
224                         p += BIT32SZ;
225                         break;
226
227                 case Twrite:
228                         if (p + BIT32SZ + BIT64SZ + BIT32SZ > ep)
229                                 return 0;
230                         f->fid = GBIT32(p);
231                         p += BIT32SZ;
232                         f->offset = GBIT64(p);
233                         p += BIT64SZ;
234                         f->count = GBIT32(p);
235                         p += BIT32SZ;
236                         if (p + f->count > ep)
237                                 return 0;
238                         f->data = (char *)p;
239                         p += f->count;
240                         break;
241
242                 case Tclunk:
243                 case Tremove:
244                         if (p + BIT32SZ > ep)
245                                 return 0;
246                         f->fid = GBIT32(p);
247                         p += BIT32SZ;
248                         break;
249
250                 case Tstat:
251                         if (p + BIT32SZ > ep)
252                                 return 0;
253                         f->fid = GBIT32(p);
254                         p += BIT32SZ;
255                         break;
256
257                 case Twstat:
258                         if (p + BIT32SZ + BIT16SZ > ep)
259                                 return 0;
260                         f->fid = GBIT32(p);
261                         p += BIT32SZ;
262                         f->nstat = GBIT16(p);
263                         p += BIT16SZ;
264                         if (p + f->nstat > ep)
265                                 return 0;
266                         f->stat = p;
267                         p += f->nstat;
268                         break;
269
270 /*
271  */
272                 case Rversion:
273                         if (p + BIT32SZ > ep)
274                                 return 0;
275                         f->msize = GBIT32(p);
276                         p += BIT32SZ;
277                         p = gstring(p, ep, &f->version);
278                         break;
279
280                 case Rerror:
281                         p = gstring(p, ep, &f->ename);
282                         break;
283
284                 case Rflush:
285                         break;
286
287                 case Rauth:
288                         p = gqid(p, ep, &f->aqid);
289                         if (p == NULL)
290                                 break;
291                         break;
292
293                 case Rattach:
294                         p = gqid(p, ep, &f->qid);
295                         if (p == NULL)
296                                 break;
297                         break;
298
299                 case Rwalk:
300                         if (p + BIT16SZ > ep)
301                                 return 0;
302                         f->nwqid = GBIT16(p);
303                         p += BIT16SZ;
304                         if (f->nwqid > MAXWELEM)
305                                 return 0;
306                         for (i = 0; i < f->nwqid; i++) {
307                                 p = gqid(p, ep, &f->wqid[i]);
308                                 if (p == NULL)
309                                         break;
310                         }
311                         break;
312
313                 case Ropen:
314                 case Rcreate:
315                         p = gqid(p, ep, &f->qid);
316                         if (p == NULL)
317                                 break;
318                         if (p + BIT32SZ > ep)
319                                 return 0;
320                         f->iounit = GBIT32(p);
321                         p += BIT32SZ;
322                         break;
323
324                 case Rread:
325                         if (p + BIT32SZ > ep)
326                                 return 0;
327                         f->count = GBIT32(p);
328                         p += BIT32SZ;
329                         if (p + f->count > ep)
330                                 return 0;
331                         f->data = (char *)p;
332                         p += f->count;
333                         break;
334
335                 case Rwrite:
336                         if (p + BIT32SZ > ep)
337                                 return 0;
338                         f->count = GBIT32(p);
339                         p += BIT32SZ;
340                         break;
341
342                 case Rclunk:
343                 case Rremove:
344                         break;
345
346                 case Rstat:
347                         if (p + BIT16SZ > ep)
348                                 return 0;
349                         f->nstat = GBIT16(p);
350                         p += BIT16SZ;
351                         if (p + f->nstat > ep)
352                                 return 0;
353                         f->stat = p;
354                         p += f->nstat;
355                         break;
356
357                 case Rwstat:
358                         break;
359         }
360
361         if (p == NULL || p > ep)
362                 return 0;
363         if (ap + size == p)
364                 return size;
365         return 0;
366 }