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