xref: /freebsd/contrib/lib9p/pack.c (revision 2e3f49888ec8851bafb22011533217487764fdb0)
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 }
998