]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/lib9p/pack.c
lib9p: Remove potential buffer overwrite in l9p_puqids()
[FreeBSD/FreeBSD.git] / contrib / lib9p / pack.c
1 /*
2  * Copyright 2016 Jakub Klama <jceel@FreeBSD.org>
3  * All rights reserved
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted providing that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
22  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
23  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24  * POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27
28 /*
29  * Based on libixp code: ©2007-2010 Kris Maglione <maglione.k at Gmail>
30  */
31
32 #include <stdlib.h>
33 #include <string.h>
34 #include <assert.h>
35 #include <sys/types.h>
36 #include <sys/param.h>
37 #ifdef __APPLE__
38 # include "apple_endian.h"
39 #else
40 # include <sys/endian.h>
41 #endif
42 #include <sys/uio.h>
43 #include "lib9p.h"
44 #include "lib9p_impl.h"
45 #include "log.h"
46
47 #define N(ary)          (sizeof(ary) / sizeof(*ary))
48 #define STRING_SIZE(s)  (L9P_WORD + (s != NULL ? (uint16_t)strlen(s) : 0))
49 #define QID_SIZE        (L9P_BYTE + L9P_DWORD + L9P_QWORD)
50
51 static ssize_t l9p_iov_io(struct l9p_message *, void *, size_t);
52 static inline ssize_t l9p_pu8(struct l9p_message *, uint8_t *);
53 static inline ssize_t l9p_pu16(struct l9p_message *, uint16_t *);
54 static inline ssize_t l9p_pu32(struct l9p_message *, uint32_t *);
55 static inline ssize_t l9p_pu64(struct l9p_message *, uint64_t *);
56 static ssize_t l9p_pustring(struct l9p_message *, char **s);
57 static ssize_t l9p_pustrings(struct l9p_message *, uint16_t *, char **, size_t);
58 static ssize_t l9p_puqid(struct l9p_message *, struct l9p_qid *);
59 static ssize_t l9p_puqids(struct l9p_message *, uint16_t *, struct l9p_qid *q);
60
61 /*
62  * Transfer data from incoming request, or to outgoing response,
63  * using msg to track position and direction within request/response.
64  *
65  * Returns the number of bytes actually transferred (which is always
66  * just len itself, converted to signed), or -1 if we ran out of space.
67  *
68  * Note that if we return -1, subsequent l9p_iov_io() calls with
69  * the same (and not-reset) msg and len > 0 will also return -1.
70  * This means most users can just check the *last* call for failure.
71  */
72 static ssize_t
73 l9p_iov_io(struct l9p_message *msg, void *buffer, size_t len)
74 {
75         size_t done = 0;
76         size_t left = len;
77
78         assert(msg != NULL);
79
80         if (len == 0)
81                 return (0);
82
83         if (msg->lm_cursor_iov >= msg->lm_niov)
84                 return (-1);
85
86         assert(buffer != NULL);
87
88         while (left > 0) {
89                 size_t idx = msg->lm_cursor_iov;
90                 size_t space = msg->lm_iov[idx].iov_len - msg->lm_cursor_offset;
91                 size_t towrite = MIN(space, left);
92
93                 if (msg->lm_mode == L9P_PACK) {
94                         memcpy((char *)msg->lm_iov[idx].iov_base +
95                             msg->lm_cursor_offset, (char *)buffer + done,
96                             towrite);
97                 }
98
99                 if (msg->lm_mode == L9P_UNPACK) {
100                         memcpy((char *)buffer + done,
101                             (char *)msg->lm_iov[idx].iov_base +
102                             msg->lm_cursor_offset, towrite);
103                 }
104
105                 msg->lm_cursor_offset += towrite;
106
107                 done += towrite;
108                 left -= towrite;
109
110                 if (space - towrite == 0) {
111                         /* Advance to next iov */
112                         msg->lm_cursor_iov++;
113                         msg->lm_cursor_offset = 0;
114
115                         if (msg->lm_cursor_iov >= msg->lm_niov && left > 0)
116                                 return (-1);
117                 }
118         }
119
120         msg->lm_size += done;
121         return ((ssize_t)done);
122 }
123
124 /*
125  * Pack or unpack a byte (8 bits).
126  *
127  * Returns 1 (success, 1 byte) or -1 (error).
128  */
129 static inline ssize_t
130 l9p_pu8(struct l9p_message *msg, uint8_t *val)
131 {
132
133         return (l9p_iov_io(msg, val, sizeof (uint8_t)));
134 }
135
136 /*
137  * Pack or unpack 16-bit value.
138  *
139  * Returns 2 or -1.
140  */
141 static inline ssize_t
142 l9p_pu16(struct l9p_message *msg, uint16_t *val)
143 {
144 #if _BYTE_ORDER != _LITTLE_ENDIAN
145         /*
146          * The ifdefs are annoying, but there is no need
147          * for all of this foolery on little-endian hosts,
148          * and I don't expect the compiler to optimize it
149          * all away.
150          */
151         uint16_t copy;
152         ssize_t ret;
153
154         if (msg->lm_mode == L9P_PACK) {
155                 copy = htole16(*val);
156                 return (l9p_iov_io(msg, &copy, sizeof (uint16_t)));
157         }
158         ret = l9p_iov_io(msg, val, sizeof (uint16_t));
159         *val = le16toh(*val);
160         return (ret);
161 #else
162         return (l9p_iov_io(msg, val, sizeof (uint16_t)));
163 #endif
164 }
165
166 /*
167  * Pack or unpack 32-bit value.
168  *
169  * Returns 4 or -1.
170  */
171 static inline ssize_t
172 l9p_pu32(struct l9p_message *msg, uint32_t *val)
173 {
174 #if _BYTE_ORDER != _LITTLE_ENDIAN
175         uint32_t copy;
176         ssize_t ret;
177
178         if (msg->lm_mode == L9P_PACK) {
179                 copy = htole32(*val);
180                 return (l9p_iov_io(msg, &copy, sizeof (uint32_t)));
181         }
182         ret = l9p_iov_io(msg, val, sizeof (uint32_t));
183         *val = le32toh(*val);
184         return (ret);
185 #else
186         return (l9p_iov_io(msg, val, sizeof (uint32_t)));
187 #endif
188 }
189
190 /*
191  * Pack or unpack 64-bit value.
192  *
193  * Returns 8 or -1.
194  */
195 static inline ssize_t
196 l9p_pu64(struct l9p_message *msg, uint64_t *val)
197 {
198 #if _BYTE_ORDER != _LITTLE_ENDIAN
199         uint64_t copy;
200         ssize_t ret;
201
202         if (msg->lm_mode == L9P_PACK) {
203                 copy = htole64(*val);
204                 return (l9p_iov_io(msg, &copy, sizeof (uint64_t)));
205         }
206         ret = l9p_iov_io(msg, val, sizeof (uint32_t));
207         *val = le64toh(*val);
208         return (ret);
209 #else
210         return (l9p_iov_io(msg, val, sizeof (uint64_t)));
211 #endif
212 }
213
214 /*
215  * Pack or unpack a string, encoded as 2-byte length followed by
216  * string bytes.  The returned length is 2 greater than the
217  * length of the string itself.
218  *
219  * When unpacking, this allocates a new string (NUL-terminated).
220  *
221  * Return -1 on error (not space, or failed to allocate string,
222  * or illegal string).
223  *
224  * Note that pustring (and hence pustrings) can return an error
225  * even when l9p_iov_io succeeds.
226  */
227 static ssize_t
228 l9p_pustring(struct l9p_message *msg, char **s)
229 {
230         uint16_t len;
231
232         if (msg->lm_mode == L9P_PACK)
233                 len = *s != NULL ? (uint16_t)strlen(*s) : 0;
234
235         if (l9p_pu16(msg, &len) < 0)
236                 return (-1);
237
238         if (msg->lm_mode == L9P_UNPACK) {
239                 *s = l9p_calloc(1, len + 1);
240                 if (*s == NULL)
241                         return (-1);
242         }
243
244         if (l9p_iov_io(msg, *s, len) < 0)
245                 return (-1);
246
247         if (msg->lm_mode == L9P_UNPACK) {
248                 /*
249                  * An embedded NUL byte in a string is illegal.
250                  * We don't necessarily have to check (we'll just
251                  * treat it as a shorter string), but checking
252                  * seems like a good idea.
253                  */
254                 if (memchr(*s, '\0', len) != NULL)
255                         return (-1);
256         }
257
258         return ((ssize_t)len + 2);
259 }
260
261 /*
262  * Pack or unpack a number (*num) of strings (but at most max of
263  * them).
264  *
265  * Returns the number of bytes transferred, including the packed
266  * number of strings.  If packing and the packed number of strings
267  * was reduced, the original *num value is unchanged; only the
268  * wire-format number is reduced.  If unpacking and the input
269  * number of strings exceeds the max, the incoming *num is reduced
270  * to lim, if needed.  (NOTE ASYMMETRY HERE!)
271  *
272  * Returns -1 on error.
273  */
274 static ssize_t
275 l9p_pustrings(struct l9p_message *msg, uint16_t *num, char **strings,
276     size_t max)
277 {
278         size_t i, lim;
279         ssize_t r, ret;
280         uint16_t adjusted;
281
282         if (msg->lm_mode == L9P_PACK) {
283                 lim = *num;
284                 if (lim > max)
285                         lim = max;
286                 adjusted = (uint16_t)lim;
287                 r = l9p_pu16(msg, &adjusted);
288         } else {
289                 r = l9p_pu16(msg, num);
290                 lim = *num;
291                 if (lim > max)
292                         *num = (uint16_t)(lim = max);
293         }
294         if (r < 0)
295                 return (-1);
296
297         for (i = 0; i < lim; i++) {
298                 ret = l9p_pustring(msg, &strings[i]);
299                 if (ret < 1)
300                         return (-1);
301
302                 r += ret;
303         }
304
305         return (r);
306 }
307
308 /*
309  * Pack or unpack a qid.
310  *
311  * Returns 13 (success) or -1 (error).
312  */
313 static ssize_t
314 l9p_puqid(struct l9p_message *msg, struct l9p_qid *qid)
315 {
316         ssize_t r;
317         uint8_t type;
318
319         if (msg->lm_mode == L9P_PACK) {
320                 type = qid->type;
321                 r = l9p_pu8(msg, &type);
322         } else {
323                 r = l9p_pu8(msg, &type);
324                 qid->type = type;
325         }
326         if (r > 0)
327                 r = l9p_pu32(msg, &qid->version);
328         if (r > 0)
329                 r = l9p_pu64(msg, &qid->path);
330
331         return (r > 0 ? QID_SIZE : r);
332 }
333
334 /*
335  * Pack or unpack *num qids.
336  *
337  * Returns 2 + 13 * *num (after possibly setting *num), or -1 on error.
338  */
339 static ssize_t
340 l9p_puqids(struct l9p_message *msg, uint16_t *num, struct l9p_qid *qids)
341 {
342         size_t i, lim;
343         ssize_t ret, r;
344
345         r = l9p_pu16(msg, num);
346         if (r <= 0)
347                 return (r);
348
349         if (*num > L9P_MAX_WELEM)
350                 return (-1);
351
352         for (i = 0, lim = *num; i < lim; i++) {
353                 ret = l9p_puqid(msg, &qids[i]);
354                 if (ret < 0)
355                         return (-1);
356                 r += ret;
357         }
358         return (r);
359 }
360
361 /*
362  * Pack or unpack a l9p_stat.
363  *
364  * These have variable size, and the size further depends on
365  * the protocol version.
366  *
367  * Returns the number of bytes packed/unpacked, or -1 on error.
368  */
369 ssize_t
370 l9p_pustat(struct l9p_message *msg, struct l9p_stat *stat,
371     enum l9p_version version)
372 {
373         ssize_t r = 0;
374         uint16_t size;
375
376         /* The on-wire size field excludes the size of the size field. */
377         if (msg->lm_mode == L9P_PACK)
378                 size = l9p_sizeof_stat(stat, version) - 2;
379
380         r += l9p_pu16(msg, &size);
381         r += l9p_pu16(msg, &stat->type);
382         r += l9p_pu32(msg, &stat->dev);
383         r += l9p_puqid(msg, &stat->qid);
384         r += l9p_pu32(msg, &stat->mode);
385         r += l9p_pu32(msg, &stat->atime);
386         r += l9p_pu32(msg, &stat->mtime);
387         r += l9p_pu64(msg, &stat->length);
388         r += l9p_pustring(msg, &stat->name);
389         r += l9p_pustring(msg, &stat->uid);
390         r += l9p_pustring(msg, &stat->gid);
391         r += l9p_pustring(msg, &stat->muid);
392
393         if (version >= L9P_2000U) {
394                 r += l9p_pustring(msg, &stat->extension);
395                 r += l9p_pu32(msg, &stat->n_uid);
396                 r += l9p_pu32(msg, &stat->n_gid);
397                 r += l9p_pu32(msg, &stat->n_muid);
398         }
399
400         if (r < size + 2)
401                 return (-1);
402
403         return (r);
404 }
405
406 /*
407  * Pack or unpack a variable-length dirent.
408  *
409  * If unpacking, the name field is malloc()ed and the caller must
410  * free it.
411  *
412  * Returns the wire-format length, or -1 if we ran out of room.
413  */
414 ssize_t
415 l9p_pudirent(struct l9p_message *msg, struct l9p_dirent *de)
416 {
417         ssize_t r, s;
418
419         r = l9p_puqid(msg, &de->qid);
420         r += l9p_pu64(msg, &de->offset);
421         r += l9p_pu8(msg, &de->type);
422         s = l9p_pustring(msg, &de->name);
423         if (r < QID_SIZE + 8 + 1 || s < 0)
424                 return (-1);
425         return (r + s);
426 }
427
428 /*
429  * Pack or unpack a request or response (fcall).
430  *
431  * Returns 0 on success, -1 on error.  (It's up to the caller
432  * to call l9p_freefcall on our failure.)
433  */
434 int
435 l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall,
436     enum l9p_version version)
437 {
438         uint32_t length = 0;
439         ssize_t r;
440
441         /*
442          * Get overall length, type, and tag, which should appear
443          * in all messages.  If not even that works, abort immediately.
444          */
445         l9p_pu32(msg, &length);
446         l9p_pu8(msg, &fcall->hdr.type);
447         r = l9p_pu16(msg, &fcall->hdr.tag);
448         if (r < 0)
449                 return (-1);
450
451         /*
452          * Decode remainder of message.  When unpacking, this may
453          * allocate memory, even if we fail during the decode.
454          * Note that the initial fcall is zeroed out, though, so
455          * we can just freefcall() to release whatever might have
456          * gotten allocated, if the unpack fails due to a short
457          * packet.
458          */
459         switch (fcall->hdr.type) {
460         case L9P_TVERSION:
461         case L9P_RVERSION:
462                 l9p_pu32(msg, &fcall->version.msize);
463                 r = l9p_pustring(msg, &fcall->version.version);
464                 break;
465
466         case L9P_TAUTH:
467                 l9p_pu32(msg, &fcall->tauth.afid);
468                 r = l9p_pustring(msg, &fcall->tauth.uname);
469                 if (r < 0)
470                         break;
471                 r = l9p_pustring(msg, &fcall->tauth.aname);
472                 if (r < 0)
473                         break;
474                 if (version >= L9P_2000U)
475                         r = l9p_pu32(msg, &fcall->tauth.n_uname);
476                 break;
477
478         case L9P_RAUTH:
479                 r = l9p_puqid(msg, &fcall->rauth.aqid);
480                 break;
481
482         case L9P_TATTACH:
483                 l9p_pu32(msg, &fcall->hdr.fid);
484                 l9p_pu32(msg, &fcall->tattach.afid);
485                 r = l9p_pustring(msg, &fcall->tattach.uname);
486                 if (r < 0)
487                         break;
488                 r = l9p_pustring(msg, &fcall->tattach.aname);
489                 if (r < 0)
490                         break;
491                 if (version >= L9P_2000U)
492                         r = l9p_pu32(msg, &fcall->tattach.n_uname);
493                 break;
494
495         case L9P_RATTACH:
496                 r = l9p_puqid(msg, &fcall->rattach.qid);
497                 break;
498
499         case L9P_RERROR:
500                 r = l9p_pustring(msg, &fcall->error.ename);
501                 if (r < 0)
502                         break;
503                 if (version >= L9P_2000U)
504                         r = l9p_pu32(msg, &fcall->error.errnum);
505                 break;
506
507         case L9P_RLERROR:
508                 r = l9p_pu32(msg, &fcall->error.errnum);
509                 break;
510
511         case L9P_TFLUSH:
512                 r = l9p_pu16(msg, &fcall->tflush.oldtag);
513                 break;
514
515         case L9P_RFLUSH:
516                 break;
517
518         case L9P_TWALK:
519                 l9p_pu32(msg, &fcall->hdr.fid);
520                 l9p_pu32(msg, &fcall->twalk.newfid);
521                 r = l9p_pustrings(msg, &fcall->twalk.nwname,
522                     fcall->twalk.wname, N(fcall->twalk.wname));
523                 break;
524
525         case L9P_RWALK:
526                 r = l9p_puqids(msg, &fcall->rwalk.nwqid, fcall->rwalk.wqid);
527                 break;
528
529         case L9P_TOPEN:
530                 l9p_pu32(msg, &fcall->hdr.fid);
531                 r = l9p_pu8(msg, &fcall->topen.mode);
532                 break;
533
534         case L9P_ROPEN:
535                 l9p_puqid(msg, &fcall->ropen.qid);
536                 r = l9p_pu32(msg, &fcall->ropen.iounit);
537                 break;
538
539         case L9P_TCREATE:
540                 l9p_pu32(msg, &fcall->hdr.fid);
541                 r = l9p_pustring(msg, &fcall->tcreate.name);
542                 if (r < 0)
543                         break;
544                 l9p_pu32(msg, &fcall->tcreate.perm);
545                 r = l9p_pu8(msg, &fcall->tcreate.mode);
546                 if (version >= L9P_2000U)
547                         r = l9p_pustring(msg, &fcall->tcreate.extension);
548                 break;
549
550         case L9P_RCREATE:
551                 l9p_puqid(msg, &fcall->rcreate.qid);
552                 r = l9p_pu32(msg, &fcall->rcreate.iounit);
553                 break;
554
555         case L9P_TREAD:
556         case L9P_TREADDIR:
557                 l9p_pu32(msg, &fcall->hdr.fid);
558                 l9p_pu64(msg, &fcall->io.offset);
559                 r = l9p_pu32(msg, &fcall->io.count);
560                 break;
561
562         case L9P_RREAD:
563         case L9P_RREADDIR:
564                 r = l9p_pu32(msg, &fcall->io.count);
565                 break;
566
567         case L9P_TWRITE:
568                 l9p_pu32(msg, &fcall->hdr.fid);
569                 l9p_pu64(msg, &fcall->io.offset);
570                 r = l9p_pu32(msg, &fcall->io.count);
571                 break;
572
573         case L9P_RWRITE:
574                 r = l9p_pu32(msg, &fcall->io.count);
575                 break;
576
577         case L9P_TCLUNK:
578         case L9P_TSTAT:
579         case L9P_TREMOVE:
580         case L9P_TSTATFS:
581                 r = l9p_pu32(msg, &fcall->hdr.fid);
582                 break;
583
584         case L9P_RCLUNK:
585         case L9P_RREMOVE:
586                 break;
587
588         case L9P_RSTAT:
589         {
590                 uint16_t size = l9p_sizeof_stat(&fcall->rstat.stat,
591                     version);
592                 l9p_pu16(msg, &size);
593                 r = l9p_pustat(msg, &fcall->rstat.stat, version);
594         }
595                 break;
596
597         case L9P_TWSTAT:
598         {
599                 uint16_t size;
600                 l9p_pu32(msg, &fcall->hdr.fid);
601                 l9p_pu16(msg, &size);
602                 r = l9p_pustat(msg, &fcall->twstat.stat, version);
603         }
604                 break;
605
606         case L9P_RWSTAT:
607                 break;
608
609         case L9P_RSTATFS:
610                 l9p_pu32(msg, &fcall->rstatfs.statfs.type);
611                 l9p_pu32(msg, &fcall->rstatfs.statfs.bsize);
612                 l9p_pu64(msg, &fcall->rstatfs.statfs.blocks);
613                 l9p_pu64(msg, &fcall->rstatfs.statfs.bfree);
614                 l9p_pu64(msg, &fcall->rstatfs.statfs.bavail);
615                 l9p_pu64(msg, &fcall->rstatfs.statfs.files);
616                 l9p_pu64(msg, &fcall->rstatfs.statfs.ffree);
617                 l9p_pu64(msg, &fcall->rstatfs.statfs.fsid);
618                 r = l9p_pu32(msg, &fcall->rstatfs.statfs.namelen);
619                 break;
620
621         case L9P_TLOPEN:
622                 l9p_pu32(msg, &fcall->hdr.fid);
623                 r = l9p_pu32(msg, &fcall->tlopen.flags);
624                 break;
625
626         case L9P_RLOPEN:
627                 l9p_puqid(msg, &fcall->rlopen.qid);
628                 r = l9p_pu32(msg, &fcall->rlopen.iounit);
629                 break;
630
631         case L9P_TLCREATE:
632                 l9p_pu32(msg, &fcall->hdr.fid);
633                 r = l9p_pustring(msg, &fcall->tlcreate.name);
634                 if (r < 0)
635                         break;
636                 l9p_pu32(msg, &fcall->tlcreate.flags);
637                 l9p_pu32(msg, &fcall->tlcreate.mode);
638                 r = l9p_pu32(msg, &fcall->tlcreate.gid);
639                 break;
640
641         case L9P_RLCREATE:
642                 l9p_puqid(msg, &fcall->rlcreate.qid);
643                 r = l9p_pu32(msg, &fcall->rlcreate.iounit);
644                 break;
645
646         case L9P_TSYMLINK:
647                 l9p_pu32(msg, &fcall->hdr.fid);
648                 r = l9p_pustring(msg, &fcall->tsymlink.name);
649                 if (r < 0)
650                         break;
651                 r = l9p_pustring(msg, &fcall->tsymlink.symtgt);
652                 if (r < 0)
653                         break;
654                 r = l9p_pu32(msg, &fcall->tlcreate.gid);
655                 break;
656
657         case L9P_RSYMLINK:
658                 r = l9p_puqid(msg, &fcall->rsymlink.qid);
659                 break;
660
661         case L9P_TMKNOD:
662                 l9p_pu32(msg, &fcall->hdr.fid);
663                 r = l9p_pustring(msg, &fcall->tmknod.name);
664                 if (r < 0)
665                         break;
666                 l9p_pu32(msg, &fcall->tmknod.mode);
667                 l9p_pu32(msg, &fcall->tmknod.major);
668                 l9p_pu32(msg, &fcall->tmknod.minor);
669                 r = l9p_pu32(msg, &fcall->tmknod.gid);
670                 break;
671
672         case L9P_RMKNOD:
673                 r = l9p_puqid(msg, &fcall->rmknod.qid);
674                 break;
675
676         case L9P_TRENAME:
677                 l9p_pu32(msg, &fcall->hdr.fid);
678                 l9p_pu32(msg, &fcall->trename.dfid);
679                 r = l9p_pustring(msg, &fcall->trename.name);
680                 break;
681
682         case L9P_RRENAME:
683                 break;
684
685         case L9P_TREADLINK:
686                 r = l9p_pu32(msg, &fcall->hdr.fid);
687                 break;
688
689         case L9P_RREADLINK:
690                 r = l9p_pustring(msg, &fcall->rreadlink.target);
691                 break;
692
693         case L9P_TGETATTR:
694                 l9p_pu32(msg, &fcall->hdr.fid);
695                 r = l9p_pu64(msg, &fcall->tgetattr.request_mask);
696                 break;
697
698         case L9P_RGETATTR:
699                 l9p_pu64(msg, &fcall->rgetattr.valid);
700                 l9p_puqid(msg, &fcall->rgetattr.qid);
701                 l9p_pu32(msg, &fcall->rgetattr.mode);
702                 l9p_pu32(msg, &fcall->rgetattr.uid);
703                 l9p_pu32(msg, &fcall->rgetattr.gid);
704                 l9p_pu64(msg, &fcall->rgetattr.nlink);
705                 l9p_pu64(msg, &fcall->rgetattr.rdev);
706                 l9p_pu64(msg, &fcall->rgetattr.size);
707                 l9p_pu64(msg, &fcall->rgetattr.blksize);
708                 l9p_pu64(msg, &fcall->rgetattr.blocks);
709                 l9p_pu64(msg, &fcall->rgetattr.atime_sec);
710                 l9p_pu64(msg, &fcall->rgetattr.atime_nsec);
711                 l9p_pu64(msg, &fcall->rgetattr.mtime_sec);
712                 l9p_pu64(msg, &fcall->rgetattr.mtime_nsec);
713                 l9p_pu64(msg, &fcall->rgetattr.ctime_sec);
714                 l9p_pu64(msg, &fcall->rgetattr.ctime_nsec);
715                 l9p_pu64(msg, &fcall->rgetattr.btime_sec);
716                 l9p_pu64(msg, &fcall->rgetattr.btime_nsec);
717                 l9p_pu64(msg, &fcall->rgetattr.gen);
718                 r = l9p_pu64(msg, &fcall->rgetattr.data_version);
719                 break;
720
721         case L9P_TSETATTR:
722                 l9p_pu32(msg, &fcall->hdr.fid);
723                 l9p_pu32(msg, &fcall->tsetattr.valid);
724                 l9p_pu32(msg, &fcall->tsetattr.mode);
725                 l9p_pu32(msg, &fcall->tsetattr.uid);
726                 l9p_pu32(msg, &fcall->tsetattr.gid);
727                 l9p_pu64(msg, &fcall->tsetattr.size);
728                 l9p_pu64(msg, &fcall->tsetattr.atime_sec);
729                 l9p_pu64(msg, &fcall->tsetattr.atime_nsec);
730                 l9p_pu64(msg, &fcall->tsetattr.mtime_sec);
731                 r = l9p_pu64(msg, &fcall->tsetattr.mtime_nsec);
732                 break;
733
734         case L9P_RSETATTR:
735                 break;
736
737         case L9P_TXATTRWALK:
738                 l9p_pu32(msg, &fcall->hdr.fid);
739                 l9p_pu32(msg, &fcall->txattrwalk.newfid);
740                 r = l9p_pustring(msg, &fcall->txattrwalk.name);
741                 break;
742
743         case L9P_RXATTRWALK:
744                 r = l9p_pu64(msg, &fcall->rxattrwalk.size);
745                 break;
746
747         case L9P_TXATTRCREATE:
748                 l9p_pu32(msg, &fcall->hdr.fid);
749                 r = l9p_pustring(msg, &fcall->txattrcreate.name);
750                 if (r < 0)
751                         break;
752                 l9p_pu64(msg, &fcall->txattrcreate.attr_size);
753                 r = l9p_pu32(msg, &fcall->txattrcreate.flags);
754                 break;
755
756         case L9P_RXATTRCREATE:
757                 break;
758
759         case L9P_TFSYNC:
760                 r = l9p_pu32(msg, &fcall->hdr.fid);
761                 break;
762
763         case L9P_RFSYNC:
764                 break;
765
766         case L9P_TLOCK:
767                 l9p_pu32(msg, &fcall->hdr.fid);
768                 l9p_pu8(msg, &fcall->tlock.type);
769                 l9p_pu32(msg, &fcall->tlock.flags);
770                 l9p_pu64(msg, &fcall->tlock.start);
771                 l9p_pu64(msg, &fcall->tlock.length);
772                 l9p_pu32(msg, &fcall->tlock.proc_id);
773                 r = l9p_pustring(msg, &fcall->tlock.client_id);
774                 break;
775
776         case L9P_RLOCK:
777                 r = l9p_pu8(msg, &fcall->rlock.status);
778                 break;
779
780         case L9P_TGETLOCK:
781                 l9p_pu32(msg, &fcall->hdr.fid);
782                 /* FALLTHROUGH */
783
784         case L9P_RGETLOCK:
785                 l9p_pu8(msg, &fcall->getlock.type);
786                 l9p_pu64(msg, &fcall->getlock.start);
787                 l9p_pu64(msg, &fcall->getlock.length);
788                 l9p_pu32(msg, &fcall->getlock.proc_id);
789                 r = l9p_pustring(msg, &fcall->getlock.client_id);
790                 break;
791
792         case L9P_TLINK:
793                 l9p_pu32(msg, &fcall->tlink.dfid);
794                 l9p_pu32(msg, &fcall->hdr.fid);
795                 r = l9p_pustring(msg, &fcall->tlink.name);
796                 break;
797
798         case L9P_RLINK:
799                 break;
800
801         case L9P_TMKDIR:
802                 l9p_pu32(msg, &fcall->hdr.fid);
803                 r = l9p_pustring(msg, &fcall->tmkdir.name);
804                 if (r < 0)
805                         break;
806                 l9p_pu32(msg, &fcall->tmkdir.mode);
807                 r = l9p_pu32(msg, &fcall->tmkdir.gid);
808                 break;
809
810         case L9P_RMKDIR:
811                 r = l9p_puqid(msg, &fcall->rmkdir.qid);
812                 break;
813
814         case L9P_TRENAMEAT:
815                 l9p_pu32(msg, &fcall->hdr.fid);
816                 r = l9p_pustring(msg, &fcall->trenameat.oldname);
817                 if (r < 0)
818                         break;
819                 l9p_pu32(msg, &fcall->trenameat.newdirfid);
820                 r = l9p_pustring(msg, &fcall->trenameat.newname);
821                 break;
822
823         case L9P_RRENAMEAT:
824                 break;
825
826         case L9P_TUNLINKAT:
827                 l9p_pu32(msg, &fcall->hdr.fid);
828                 r = l9p_pustring(msg, &fcall->tunlinkat.name);
829                 if (r < 0)
830                         break;
831                 r = l9p_pu32(msg, &fcall->tunlinkat.flags);
832                 break;
833
834         case L9P_RUNLINKAT:
835                 break;
836
837         default:
838                 L9P_LOG(L9P_ERROR, "%s(): missing case for type %d",
839                     __func__, fcall->hdr.type);
840                 break;
841         }
842
843         /* Check for over- or under-run, or pustring error. */
844         if (r < 0)
845                 return (-1);
846
847         if (msg->lm_mode == L9P_PACK) {
848                 /* Rewind to the beginning and install size at front. */
849                 uint32_t len = (uint32_t)msg->lm_size;
850                 msg->lm_cursor_offset = 0;
851                 msg->lm_cursor_iov = 0;
852
853                 /*
854                  * Subtract 4 bytes from current size, becase we're
855                  * overwriting size (rewinding message to the beginning)
856                  * and writing again, which will increase it 4 more.
857                  */
858                 msg->lm_size -= sizeof(uint32_t);
859
860                 if (fcall->hdr.type == L9P_RREAD ||
861                     fcall->hdr.type == L9P_RREADDIR)
862                         len += fcall->io.count;
863
864                 l9p_pu32(msg, &len);
865         }
866
867         return (0);
868 }
869
870 /*
871  * Free any strings or other data malloc'ed in the process of
872  * packing or unpacking an fcall.
873  */
874 void
875 l9p_freefcall(union l9p_fcall *fcall)
876 {
877         uint16_t i;
878
879         switch (fcall->hdr.type) {
880
881         case L9P_TVERSION:
882         case L9P_RVERSION:
883                 free(fcall->version.version);
884                 return;
885
886         case L9P_TATTACH:
887                 free(fcall->tattach.aname);
888                 free(fcall->tattach.uname);
889                 return;
890
891         case L9P_TWALK:
892                 for (i = 0; i < fcall->twalk.nwname; i++)
893                         free(fcall->twalk.wname[i]);
894                 return;
895
896         case L9P_TCREATE:
897         case L9P_TOPEN:
898                 free(fcall->tcreate.name);
899                 free(fcall->tcreate.extension);
900                 return;
901
902         case L9P_RSTAT:
903                 l9p_freestat(&fcall->rstat.stat);
904                 return;
905
906         case L9P_TWSTAT:
907                 l9p_freestat(&fcall->twstat.stat);
908                 return;
909
910         case L9P_TLCREATE:
911                 free(fcall->tlcreate.name);
912                 return;
913
914         case L9P_TSYMLINK:
915                 free(fcall->tsymlink.name);
916                 free(fcall->tsymlink.symtgt);
917                 return;
918
919         case L9P_TMKNOD:
920                 free(fcall->tmknod.name);
921                 return;
922
923         case L9P_TRENAME:
924                 free(fcall->trename.name);
925                 return;
926
927         case L9P_RREADLINK:
928                 free(fcall->rreadlink.target);
929                 return;
930
931         case L9P_TXATTRWALK:
932                 free(fcall->txattrwalk.name);
933                 return;
934
935         case L9P_TXATTRCREATE:
936                 free(fcall->txattrcreate.name);
937                 return;
938
939         case L9P_TLOCK:
940                 free(fcall->tlock.client_id);
941                 return;
942
943         case L9P_TGETLOCK:
944         case L9P_RGETLOCK:
945                 free(fcall->getlock.client_id);
946                 return;
947
948         case L9P_TLINK:
949                 free(fcall->tlink.name);
950                 return;
951
952         case L9P_TMKDIR:
953                 free(fcall->tmkdir.name);
954                 return;
955
956         case L9P_TRENAMEAT:
957                 free(fcall->trenameat.oldname);
958                 free(fcall->trenameat.newname);
959                 return;
960
961         case L9P_TUNLINKAT:
962                 free(fcall->tunlinkat.name);
963                 return;
964         }
965 }
966
967 void
968 l9p_freestat(struct l9p_stat *stat)
969 {
970         free(stat->name);
971         free(stat->extension);
972         free(stat->uid);
973         free(stat->gid);
974         free(stat->muid);
975 }
976
977 uint16_t
978 l9p_sizeof_stat(struct l9p_stat *stat, enum l9p_version version)
979 {
980         uint16_t size = L9P_WORD /* size */
981             + L9P_WORD /* type */
982             + L9P_DWORD /* dev */
983             + QID_SIZE /* qid */
984             + 3 * L9P_DWORD /* mode, atime, mtime */
985             + L9P_QWORD /* length */
986             + STRING_SIZE(stat->name)
987             + STRING_SIZE(stat->uid)
988             + STRING_SIZE(stat->gid)
989             + STRING_SIZE(stat->muid);
990
991         if (version >= L9P_2000U) {
992                 size += STRING_SIZE(stat->extension)
993                     + 3 * L9P_DWORD;
994         }
995
996         return (size);
997 }