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#include <stdlib.h>
29#include <string.h>
30#include <assert.h>
31#include <errno.h>
32#include <sys/param.h>
33#include <sys/uio.h>
34#if defined(__FreeBSD__)
35#include <sys/sbuf.h>
36#else
37#include "sbuf/sbuf.h"
38#endif
39#include "lib9p.h"
40#include "lib9p_impl.h"
41#include "fcall.h"
42#include "fid.h"
43#include "hashtable.h"
44#include "log.h"
45#include "linux_errno.h"
46#include "backend/backend.h"
47#include "threadpool.h"
48
49#define N(x)    (sizeof(x) / sizeof(x[0]))
50
51static int l9p_dispatch_tversion(struct l9p_request *req);
52static int l9p_dispatch_tattach(struct l9p_request *req);
53static int l9p_dispatch_tclunk(struct l9p_request *req);
54static int l9p_dispatch_tcreate(struct l9p_request *req);
55static int l9p_dispatch_topen(struct l9p_request *req);
56static int l9p_dispatch_tread(struct l9p_request *req);
57static int l9p_dispatch_tremove(struct l9p_request *req);
58static int l9p_dispatch_tstat(struct l9p_request *req);
59static int l9p_dispatch_twalk(struct l9p_request *req);
60static int l9p_dispatch_twrite(struct l9p_request *req);
61static int l9p_dispatch_twstat(struct l9p_request *req);
62static int l9p_dispatch_tstatfs(struct l9p_request *req);
63static int l9p_dispatch_tlopen(struct l9p_request *req);
64static int l9p_dispatch_tlcreate(struct l9p_request *req);
65static int l9p_dispatch_tsymlink(struct l9p_request *req);
66static int l9p_dispatch_tmknod(struct l9p_request *req);
67static int l9p_dispatch_trename(struct l9p_request *req);
68static int l9p_dispatch_treadlink(struct l9p_request *req);
69static int l9p_dispatch_tgetattr(struct l9p_request *req);
70static int l9p_dispatch_tsetattr(struct l9p_request *req);
71static int l9p_dispatch_txattrwalk(struct l9p_request *req);
72static int l9p_dispatch_txattrcreate(struct l9p_request *req);
73static int l9p_dispatch_treaddir(struct l9p_request *req);
74static int l9p_dispatch_tfsync(struct l9p_request *req);
75static int l9p_dispatch_tlock(struct l9p_request *req);
76static int l9p_dispatch_tgetlock(struct l9p_request *req);
77static int l9p_dispatch_tlink(struct l9p_request *req);
78static int l9p_dispatch_tmkdir(struct l9p_request *req);
79static int l9p_dispatch_trenameat(struct l9p_request *req);
80static int l9p_dispatch_tunlinkat(struct l9p_request *req);
81
82/*
83 * Each Txxx handler has a "must run" flag.  If it is false,
84 * we check for a flush request before calling the handler.
85 * If a flush is already requested we can instantly fail the
86 * request with EINTR.
87 *
88 * Tclunk and Tremove must run because they make their fids
89 * become invalid.  Tversion and Tattach should never get
90 * a flush request applied (it makes no sense as the connection
91 * is not really running yet), so it should be harmless to
92 * set them either way, but for now we have them as must-run.
93 * Flushing a Tflush is not really allowed either so we keep
94 * these as must-run too (although they run without being done
95 * threaded anyway).
96 */
97struct l9p_handler {
98	enum l9p_ftype type;
99	int (*handler)(struct l9p_request *);
100	bool must_run;
101};
102
103static const struct l9p_handler l9p_handlers_no_version[] = {
104	{L9P_TVERSION, l9p_dispatch_tversion, true},
105};
106
107static const struct l9p_handler l9p_handlers_base[] = {
108	{L9P_TVERSION, l9p_dispatch_tversion, true},
109	{L9P_TATTACH, l9p_dispatch_tattach, true},
110	{L9P_TCLUNK, l9p_dispatch_tclunk, true},
111	{L9P_TFLUSH, l9p_threadpool_tflush, true},
112	{L9P_TCREATE, l9p_dispatch_tcreate, false},
113	{L9P_TOPEN, l9p_dispatch_topen, false},
114	{L9P_TREAD, l9p_dispatch_tread, false},
115	{L9P_TWRITE, l9p_dispatch_twrite, false},
116	{L9P_TREMOVE, l9p_dispatch_tremove, true},
117	{L9P_TSTAT, l9p_dispatch_tstat, false},
118	{L9P_TWALK, l9p_dispatch_twalk, false},
119	{L9P_TWSTAT, l9p_dispatch_twstat, false}
120};
121static const struct l9p_handler l9p_handlers_dotu[] = {
122	{L9P_TVERSION, l9p_dispatch_tversion, true},
123	{L9P_TATTACH, l9p_dispatch_tattach, true},
124	{L9P_TCLUNK, l9p_dispatch_tclunk, true},
125	{L9P_TFLUSH, l9p_threadpool_tflush, true},
126	{L9P_TCREATE, l9p_dispatch_tcreate, false},
127	{L9P_TOPEN, l9p_dispatch_topen, false},
128	{L9P_TREAD, l9p_dispatch_tread, false},
129	{L9P_TWRITE, l9p_dispatch_twrite, false},
130	{L9P_TREMOVE, l9p_dispatch_tremove, true},
131	{L9P_TSTAT, l9p_dispatch_tstat, false},
132	{L9P_TWALK, l9p_dispatch_twalk, false},
133	{L9P_TWSTAT, l9p_dispatch_twstat, false}
134};
135static const struct l9p_handler l9p_handlers_dotL[] = {
136	{L9P_TVERSION, l9p_dispatch_tversion, true},
137	{L9P_TATTACH, l9p_dispatch_tattach, true},
138	{L9P_TCLUNK, l9p_dispatch_tclunk, true},
139	{L9P_TFLUSH, l9p_threadpool_tflush, true},
140	{L9P_TCREATE, l9p_dispatch_tcreate, false},
141	{L9P_TOPEN, l9p_dispatch_topen, false},
142	{L9P_TREAD, l9p_dispatch_tread, false},
143	{L9P_TWRITE, l9p_dispatch_twrite, false},
144	{L9P_TREMOVE, l9p_dispatch_tremove, true},
145	{L9P_TSTAT, l9p_dispatch_tstat, false},
146	{L9P_TWALK, l9p_dispatch_twalk, false},
147	{L9P_TWSTAT, l9p_dispatch_twstat, false},
148	{L9P_TSTATFS, l9p_dispatch_tstatfs, false},
149	{L9P_TLOPEN, l9p_dispatch_tlopen, false},
150	{L9P_TLCREATE, l9p_dispatch_tlcreate, false},
151	{L9P_TSYMLINK, l9p_dispatch_tsymlink, false},
152	{L9P_TMKNOD, l9p_dispatch_tmknod, false},
153	{L9P_TRENAME, l9p_dispatch_trename, false},
154	{L9P_TREADLINK, l9p_dispatch_treadlink, false},
155	{L9P_TGETATTR, l9p_dispatch_tgetattr, false},
156	{L9P_TSETATTR, l9p_dispatch_tsetattr, false},
157	{L9P_TXATTRWALK, l9p_dispatch_txattrwalk, false},
158	{L9P_TXATTRCREATE, l9p_dispatch_txattrcreate, false},
159	{L9P_TREADDIR, l9p_dispatch_treaddir, false},
160	{L9P_TFSYNC, l9p_dispatch_tfsync, false},
161	{L9P_TLOCK, l9p_dispatch_tlock, true},
162	{L9P_TGETLOCK, l9p_dispatch_tgetlock, true},
163	{L9P_TLINK, l9p_dispatch_tlink, false},
164	{L9P_TMKDIR, l9p_dispatch_tmkdir, false},
165	{L9P_TRENAMEAT, l9p_dispatch_trenameat, false},
166	{L9P_TUNLINKAT, l9p_dispatch_tunlinkat, false},
167};
168
169/*
170 * NB: version index 0 is reserved for new connections, and
171 * is a protocol that handles only L9P_TVERSION.  Once we get a
172 * valid version, we start a new session using its dispatch table.
173 */
174static const struct {
175	const char *name;
176	const struct l9p_handler *handlers;
177	int n_handlers;
178} l9p_versions[] = {
179	{ "<none>", l9p_handlers_no_version, N(l9p_handlers_no_version) },
180	{ "9P2000", l9p_handlers_base, N(l9p_handlers_base) },
181	{ "9P2000.u", l9p_handlers_dotu, N(l9p_handlers_dotu), },
182	{ "9P2000.L", l9p_handlers_dotL, N(l9p_handlers_dotL), },
183};
184
185/*
186 * Run the appropriate handler for this request.
187 * It's our caller's responsibility to respond.
188 */
189int
190l9p_dispatch_request(struct l9p_request *req)
191{
192	struct l9p_connection *conn;
193#if defined(L9P_DEBUG)
194	struct sbuf *sb;
195#endif
196	size_t i, n;
197	const struct l9p_handler *handlers, *hp;
198	bool flush_requested;
199
200	conn = req->lr_conn;
201	flush_requested = req->lr_flushstate == L9P_FLUSH_REQUESTED_PRE_START;
202
203	handlers = l9p_versions[conn->lc_version].handlers;
204	n = (size_t)l9p_versions[conn->lc_version].n_handlers;
205	for (hp = handlers, i = 0; i < n; hp++, i++)
206		if (req->lr_req.hdr.type == hp->type)
207			goto found;
208	hp = NULL;
209found:
210
211#if defined(L9P_DEBUG)
212	sb = sbuf_new_auto();
213	if (flush_requested) {
214		sbuf_cat(sb, "FLUSH requested pre-dispatch");
215		if (hp != NULL && hp->must_run)
216			sbuf_cat(sb, ", but must run");
217		sbuf_cat(sb, ": ");
218	}
219	l9p_describe_fcall(&req->lr_req, conn->lc_version, sb);
220	sbuf_finish(sb);
221
222	L9P_LOG(L9P_DEBUG, "%s", sbuf_data(sb));
223	sbuf_delete(sb);
224#endif
225
226	if (hp != NULL) {
227		if (!flush_requested || hp->must_run)
228			return (hp->handler(req));
229		return (EINTR);
230	}
231
232	L9P_LOG(L9P_WARNING, "unknown request of type %d",
233	    req->lr_req.hdr.type);
234	return (ENOSYS);
235}
236
237/*
238 * Translate BSD errno to 9P2000/9P2000.u errno.
239 */
240static inline int
241e29p(int errnum)
242{
243	static int const table[] = {
244		[ENOTEMPTY] = EPERM,
245		[EDQUOT] = EPERM,
246		[ENOSYS] = EPERM,	/* ??? */
247	};
248
249	if ((size_t)errnum < N(table) && table[errnum] != 0)
250		return (table[errnum]);
251	if (errnum <= ERANGE)
252		return (errnum);
253	return (EIO);			/* ??? */
254}
255
256/*
257 * Translate BSD errno to Linux errno.
258 */
259static inline int
260e2linux(int errnum)
261{
262	static int const table[] = {
263		[EDEADLK] = LINUX_EDEADLK,
264		[EAGAIN] = LINUX_EAGAIN,
265		[EINPROGRESS] = LINUX_EINPROGRESS,
266		[EALREADY] = LINUX_EALREADY,
267		[ENOTSOCK] = LINUX_ENOTSOCK,
268		[EDESTADDRREQ] = LINUX_EDESTADDRREQ,
269		[EMSGSIZE] = LINUX_EMSGSIZE,
270		[EPROTOTYPE] = LINUX_EPROTOTYPE,
271		[ENOPROTOOPT] = LINUX_ENOPROTOOPT,
272		[EPROTONOSUPPORT] = LINUX_EPROTONOSUPPORT,
273		[ESOCKTNOSUPPORT] = LINUX_ESOCKTNOSUPPORT,
274		[EOPNOTSUPP] = LINUX_EOPNOTSUPP,
275		[EPFNOSUPPORT] = LINUX_EPFNOSUPPORT,
276		[EAFNOSUPPORT] = LINUX_EAFNOSUPPORT,
277		[EADDRINUSE] = LINUX_EADDRINUSE,
278		[EADDRNOTAVAIL] = LINUX_EADDRNOTAVAIL,
279		[ENETDOWN] = LINUX_ENETDOWN,
280		[ENETUNREACH] = LINUX_ENETUNREACH,
281		[ENETRESET] = LINUX_ENETRESET,
282		[ECONNABORTED] = LINUX_ECONNABORTED,
283		[ECONNRESET] = LINUX_ECONNRESET,
284		[ENOBUFS] = LINUX_ENOBUFS,
285		[EISCONN] = LINUX_EISCONN,
286		[ENOTCONN] = LINUX_ENOTCONN,
287		[ESHUTDOWN] = LINUX_ESHUTDOWN,
288		[ETOOMANYREFS] = LINUX_ETOOMANYREFS,
289		[ETIMEDOUT] = LINUX_ETIMEDOUT,
290		[ECONNREFUSED] = LINUX_ECONNREFUSED,
291		[ELOOP] = LINUX_ELOOP,
292		[ENAMETOOLONG] = LINUX_ENAMETOOLONG,
293		[EHOSTDOWN] = LINUX_EHOSTDOWN,
294		[EHOSTUNREACH] = LINUX_EHOSTUNREACH,
295		[ENOTEMPTY] = LINUX_ENOTEMPTY,
296		[EPROCLIM] = LINUX_EAGAIN,
297		[EUSERS] = LINUX_EUSERS,
298		[EDQUOT] = LINUX_EDQUOT,
299		[ESTALE] = LINUX_ESTALE,
300		[EREMOTE] = LINUX_EREMOTE,
301		/* EBADRPC = unmappable? */
302		/* ERPCMISMATCH = unmappable? */
303		/* EPROGUNAVAIL = unmappable? */
304		/* EPROGMISMATCH = unmappable? */
305		/* EPROCUNAVAIL = unmappable? */
306		[ENOLCK] = LINUX_ENOLCK,
307		[ENOSYS] = LINUX_ENOSYS,
308		/* EFTYPE = unmappable? */
309		/* EAUTH = unmappable? */
310		/* ENEEDAUTH = unmappable? */
311		[EIDRM] = LINUX_EIDRM,
312		[ENOMSG] = LINUX_ENOMSG,
313		[EOVERFLOW] = LINUX_EOVERFLOW,
314		[ECANCELED] = LINUX_ECANCELED,
315		[EILSEQ] = LINUX_EILSEQ,
316		/* EDOOFUS = unmappable? */
317		[EBADMSG] = LINUX_EBADMSG,
318		[EMULTIHOP] = LINUX_EMULTIHOP,
319		[ENOLINK] = LINUX_ENOLINK,
320		[EPROTO] = LINUX_EPROTO,
321		/* ENOTCAPABLE = unmappable? */
322#ifdef ECAPMODE
323		[ECAPMODE] = EPERM,
324#endif
325#ifdef ENOTRECOVERABLE
326		[ENOTRECOVERABLE] = LINUX_ENOTRECOVERABLE,
327#endif
328#ifdef EOWNERDEAD
329		[EOWNERDEAD] = LINUX_EOWNERDEAD,
330#endif
331	};
332
333	/*
334	 * In case we want to return a raw Linux errno, allow negative
335	 * values a la Linux kernel internals.
336	 *
337	 * Values up to ERANGE are shared across systems (see
338	 * linux_errno.h), except for EAGAIN.
339	 */
340	if (errnum < 0)
341		return (-errnum);
342
343	if ((size_t)errnum < N(table) && table[errnum] != 0)
344		return (table[errnum]);
345
346	if (errnum <= ERANGE)
347		return (errnum);
348
349	L9P_LOG(L9P_WARNING, "cannot map errno %d to anything reasonable",
350	    errnum);
351
352	return (LINUX_ENOTRECOVERABLE);	/* ??? */
353}
354
355/*
356 * Send response to request, or possibly just drop request.
357 * We also need to know whether to remove the request from
358 * the tag hash table.
359 */
360void
361l9p_respond(struct l9p_request *req, bool drop, bool rmtag)
362{
363	struct l9p_connection *conn = req->lr_conn;
364	size_t iosize;
365#if defined(L9P_DEBUG)
366	struct sbuf *sb;
367	const char *ftype;
368#endif
369	int error;
370
371	req->lr_resp.hdr.tag = req->lr_req.hdr.tag;
372
373	error = req->lr_error;
374	if (error == 0)
375		req->lr_resp.hdr.type = req->lr_req.hdr.type + 1;
376	else {
377		if (conn->lc_version == L9P_2000L) {
378			req->lr_resp.hdr.type = L9P_RLERROR;
379			req->lr_resp.error.errnum = (uint32_t)e2linux(error);
380		} else {
381			req->lr_resp.hdr.type = L9P_RERROR;
382			req->lr_resp.error.ename = strerror(error);
383			req->lr_resp.error.errnum = (uint32_t)e29p(error);
384		}
385	}
386
387#if defined(L9P_DEBUG)
388	sb = sbuf_new_auto();
389	l9p_describe_fcall(&req->lr_resp, conn->lc_version, sb);
390	sbuf_finish(sb);
391
392	switch (req->lr_flushstate) {
393	case L9P_FLUSH_NONE:
394		ftype = "";
395		break;
396	case L9P_FLUSH_REQUESTED_PRE_START:
397		ftype = "FLUSH requested pre-dispatch: ";
398		break;
399	case L9P_FLUSH_REQUESTED_POST_START:
400		ftype = "FLUSH requested while running: ";
401		break;
402	case L9P_FLUSH_TOOLATE:
403		ftype = "FLUSH requested too late: ";
404		break;
405	}
406	L9P_LOG(L9P_DEBUG, "%s%s%s",
407	    drop ? "DROP: " : "", ftype, sbuf_data(sb));
408	sbuf_delete(sb);
409#endif
410
411	error = drop ? 0 :
412	    l9p_pufcall(&req->lr_resp_msg, &req->lr_resp, conn->lc_version);
413	if (rmtag)
414		ht_remove(&conn->lc_requests, req->lr_req.hdr.tag);
415	if (error != 0) {
416		L9P_LOG(L9P_ERROR, "cannot pack response");
417		drop = true;
418	}
419
420	if (drop) {
421		conn->lc_lt.lt_drop_response(req,
422		    req->lr_resp_msg.lm_iov, req->lr_resp_msg.lm_niov,
423		    conn->lc_lt.lt_aux);
424	} else {
425		iosize = req->lr_resp_msg.lm_size;
426
427		/*
428		 * Include I/O size in calculation for Rread and
429		 * Rreaddir responses.
430		 */
431		if (req->lr_resp.hdr.type == L9P_RREAD ||
432		    req->lr_resp.hdr.type == L9P_RREADDIR)
433			iosize += req->lr_resp.io.count;
434
435		conn->lc_lt.lt_send_response(req,
436		    req->lr_resp_msg.lm_iov, req->lr_resp_msg.lm_niov,
437		    iosize, conn->lc_lt.lt_aux);
438	}
439
440	l9p_freefcall(&req->lr_req);
441	l9p_freefcall(&req->lr_resp);
442
443	free(req);
444}
445
446/*
447 * This allows a caller to iterate through the data in a
448 * read or write request (creating the data if packing,
449 * scanning through it if unpacking).  This is used for
450 * writing readdir entries, so mode should be L9P_PACK
451 * (but we allow L9P_UNPACK so that debug code can also scan
452 * through the data later, if desired).
453 *
454 * This relies on the Tread op having positioned the request's
455 * iov to the beginning of the data buffer (note the l9p_seek_iov
456 * in l9p_dispatch_tread).
457 */
458void
459l9p_init_msg(struct l9p_message *msg, struct l9p_request *req,
460    enum l9p_pack_mode mode)
461{
462
463	msg->lm_size = 0;
464	msg->lm_mode = mode;
465	msg->lm_cursor_iov = 0;
466	msg->lm_cursor_offset = 0;
467	msg->lm_niov = req->lr_data_niov;
468	memcpy(msg->lm_iov, req->lr_data_iov,
469	    sizeof (struct iovec) * req->lr_data_niov);
470}
471
472enum fid_lookup_flags {
473	F_REQUIRE_OPEN = 0x01,	/* require that the file be marked OPEN */
474	F_REQUIRE_DIR = 0x02,	/* require that the file be marked ISDIR */
475	F_REQUIRE_XATTR = 0x04,	/* require that the file be marked XATTR */
476	F_REQUIRE_AUTH = 0x08,	/* require that the fid be marked AUTH */
477	F_FORBID_OPEN = 0x10,	/* forbid that the file be marked OPEN */
478	F_FORBID_DIR = 0x20,	/* forbid that the file be marked ISDIR */
479	F_FORBID_XATTR = 0x40,	/* forbid that the file be marked XATTR */
480	F_ALLOW_AUTH = 0x80,	/* allow that the fid be marked AUTH */
481};
482
483/*
484 * Look up a fid.  It must correspond to a valid file, else we return
485 * the given errno (some "not a valid fid" calls must return EIO and
486 * some must return EINVAL and qemu returns ENOENT in other cases and
487 * so on, so we just provide a general "return this error number").
488 *
489 * Callers may also set constraints: fid must be (or not be) open,
490 * must be (or not be) a directory, must be (or not be) an xattr.
491 *
492 * Only one op has a fid that *must* be an auth fid.  Most ops forbid
493 * auth fids  So instead of FORBID we have ALLOW here and the default
494 * is FORBID.
495 */
496static inline int
497fid_lookup(struct l9p_connection *conn, uint32_t fid, int err, int flags,
498    struct l9p_fid **afile)
499{
500	struct l9p_fid *file;
501
502	file = ht_find(&conn->lc_files, fid);
503	if (file == NULL)
504		return (err);
505
506	/*
507	 * As soon as we go multithreaded / async, this
508	 * assert has to become "return EINVAL" or "return err".
509	 *
510	 * We may also need a way to mark a fid as
511	 * "in async op" (valid for some purposes, but cannot be
512	 * used elsewhere until async op is completed or aborted).
513	 *
514	 * For now, this serves for bug-detecting.
515	 */
516	assert(l9p_fid_isvalid(file));
517
518	/*
519	 * Note that we're inline expanded and flags is constant,
520	 * so unnecessary tests just drop out entirely.
521	 */
522	if ((flags & F_REQUIRE_OPEN) && !l9p_fid_isopen(file))
523		return (EINVAL);
524	if ((flags & F_FORBID_OPEN) && l9p_fid_isopen(file))
525		return (EINVAL);
526	if ((flags & F_REQUIRE_DIR) && !l9p_fid_isdir(file))
527		return (ENOTDIR);
528	if ((flags & F_FORBID_DIR) && l9p_fid_isdir(file))
529		return (EISDIR);
530	if ((flags & F_REQUIRE_XATTR) && !l9p_fid_isxattr(file))
531		return (EINVAL);
532	if ((flags & F_FORBID_XATTR) && l9p_fid_isxattr(file))
533		return (EINVAL);
534	if (l9p_fid_isauth(file)) {
535		if ((flags & (F_REQUIRE_AUTH | F_ALLOW_AUTH)) == 0)
536			return (EINVAL);
537	} else if (flags & F_REQUIRE_AUTH)
538		return (EINVAL);
539	*afile = file;
540	return (0);
541}
542
543/*
544 * Append variable-size stat object and adjust io count.
545 * Returns 0 if the entire stat object was packed, -1 if not.
546 * A fully packed object updates the request's io count.
547 *
548 * Caller must use their own private l9p_message object since
549 * a partially packed object will leave the message object in
550 * a useless state.
551 *
552 * Frees the stat object.
553 */
554int
555l9p_pack_stat(struct l9p_message *msg, struct l9p_request *req,
556    struct l9p_stat *st)
557{
558	struct l9p_connection *conn = req->lr_conn;
559	uint16_t size = l9p_sizeof_stat(st, conn->lc_version);
560	int ret = 0;
561
562	assert(msg->lm_mode == L9P_PACK);
563
564	if (req->lr_resp.io.count + size > req->lr_req.io.count ||
565	    l9p_pustat(msg, st, conn->lc_version) < 0)
566		ret = -1;
567	else
568		req->lr_resp.io.count += size;
569	l9p_freestat(st);
570	return (ret);
571}
572
573static int
574l9p_dispatch_tversion(struct l9p_request *req)
575{
576	struct l9p_connection *conn = req->lr_conn;
577	struct l9p_server *server = conn->lc_server;
578	enum l9p_version remote_version = L9P_INVALID_VERSION;
579	size_t i;
580	const char *remote_version_name;
581
582	for (i = 0; i < N(l9p_versions); i++) {
583		if (strcmp(req->lr_req.version.version,
584		    l9p_versions[i].name) == 0) {
585			remote_version = (enum l9p_version)i;
586			break;
587		}
588	}
589
590	if (remote_version == L9P_INVALID_VERSION) {
591		L9P_LOG(L9P_ERROR, "unsupported remote version: %s",
592		    req->lr_req.version.version);
593		return (ENOSYS);
594	}
595
596	remote_version_name = l9p_versions[remote_version].name;
597	L9P_LOG(L9P_INFO, "remote version: %s", remote_version_name);
598	L9P_LOG(L9P_INFO, "local version: %s",
599	    l9p_versions[server->ls_max_version].name);
600
601	conn->lc_version = MIN(remote_version, server->ls_max_version);
602	conn->lc_msize = MIN(req->lr_req.version.msize, conn->lc_msize);
603	conn->lc_max_io_size = conn->lc_msize - 24;
604	req->lr_resp.version.version = strdup(remote_version_name);
605	req->lr_resp.version.msize = conn->lc_msize;
606	return (0);
607}
608
609static int
610l9p_dispatch_tattach(struct l9p_request *req)
611{
612	struct l9p_connection *conn = req->lr_conn;
613	struct l9p_backend *be;
614	struct l9p_fid *fid;
615	int error;
616
617	/*
618	 * We still don't have Tauth yet, but let's code this part
619	 * anyway.
620	 *
621	 * Look up the auth fid first since if it fails we can just
622	 * return immediately.
623	 */
624	if (req->lr_req.tattach.afid != L9P_NOFID) {
625		error = fid_lookup(conn, req->lr_req.tattach.afid, EINVAL,
626		    F_REQUIRE_AUTH, &req->lr_fid2);
627		if (error)
628			return (error);
629	} else
630		req->lr_fid2 = NULL;
631
632	fid = l9p_connection_alloc_fid(conn, req->lr_req.hdr.fid);
633	if (fid == NULL)
634		return (EINVAL);
635
636	be = conn->lc_server->ls_backend;
637
638	req->lr_fid = fid;
639
640	/* For backend convenience, set NONUNAME on 9P2000. */
641	if (conn->lc_version == L9P_2000)
642		req->lr_req.tattach.n_uname = L9P_NONUNAME;
643	error = be->attach(be->softc, req);
644
645	/*
646	 * On success, fid becomes valid; on failure, disconnect.
647	 * It certainly *should* be a directory here...
648	 */
649	if (error == 0) {
650		l9p_fid_setvalid(fid);
651		if (req->lr_resp.rattach.qid.type & L9P_QTDIR)
652			l9p_fid_setdir(fid);
653	} else
654		l9p_connection_remove_fid(conn, fid);
655	return (error);
656}
657
658static int
659l9p_dispatch_tclunk(struct l9p_request *req)
660{
661	struct l9p_connection *conn = req->lr_conn;
662	struct l9p_backend *be;
663	struct l9p_fid *fid;
664	int error;
665
666	/* Note that clunk is the only way to dispose of an auth fid. */
667	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
668	    F_ALLOW_AUTH, &fid);
669	if (error)
670		return (error);
671
672	be = conn->lc_server->ls_backend;
673	l9p_fid_unsetvalid(fid);
674
675	/*
676	 * If it's an xattr fid there must, by definition, be an
677	 * xattrclunk.  The xattrclunk function can only be NULL if
678	 * xattrwalk and xattrcreate are NULL or always return error.
679	 *
680	 * Q: do we want to allow async xattrclunk in case of very
681	 * large xattr create?  This will make things difficult,
682	 * so probably not.
683	 */
684	if (l9p_fid_isxattr(fid))
685		error = be->xattrclunk(be->softc, fid);
686	else
687		error = be->clunk(be->softc, fid);
688
689	/* fid is now gone regardless of any error return */
690	l9p_connection_remove_fid(conn, fid);
691	return (error);
692}
693
694static int
695l9p_dispatch_tcreate(struct l9p_request *req)
696{
697	struct l9p_connection *conn = req->lr_conn;
698	struct l9p_backend *be;
699	uint32_t dmperm;
700	int error;
701
702	/* Incoming fid must represent a directory that has not been opened. */
703	error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL,
704	    F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid);
705	if (error)
706		return (error);
707
708	be = conn->lc_server->ls_backend;
709	dmperm = req->lr_req.tcreate.perm;
710#define MKDIR_OR_SIMILAR \
711    (L9P_DMDIR | L9P_DMSYMLINK | L9P_DMNAMEDPIPE | L9P_DMSOCKET | L9P_DMDEVICE)
712
713	/*
714	 * TODO:
715	 *  - check new file name
716	 *  - break out different kinds of create (file vs mkdir etc)
717	 *  - add async file-create (leaves req->lr_fid in limbo)
718	 *
719	 * A successful file-create changes the fid into an open file.
720	 */
721	error = be->create(be->softc, req);
722	if (error == 0 && (dmperm & MKDIR_OR_SIMILAR) == 0) {
723		l9p_fid_unsetdir(req->lr_fid);
724		l9p_fid_setopen(req->lr_fid);
725	}
726
727	return (error);
728}
729
730static int
731l9p_dispatch_topen(struct l9p_request *req)
732{
733	struct l9p_connection *conn = req->lr_conn;
734	struct l9p_backend *be;
735	int error;
736
737	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
738	    F_FORBID_OPEN | F_FORBID_XATTR, &req->lr_fid);
739	if (error)
740		return (error);
741
742	be = conn->lc_server->ls_backend;
743
744	/*
745	 * TODO:
746	 *  - add async open (leaves req->lr_fid in limbo)
747	 */
748	error = be->open(be->softc, req);
749	if (error == 0)
750		l9p_fid_setopen(req->lr_fid);
751	return (error);
752}
753
754static int
755l9p_dispatch_tread(struct l9p_request *req)
756{
757	struct l9p_connection *conn = req->lr_conn;
758	struct l9p_backend *be;
759	struct l9p_fid *fid;
760	int error;
761
762	/* Xattr fids are not open, so we need our own tests. */
763	error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL, 0, &req->lr_fid);
764	if (error)
765		return (error);
766
767	/*
768	 * Adjust so that writing messages (packing data) starts
769	 * right after the count field in the response.
770	 *
771	 * size[4] + Rread[1] + tag[2] + count[4] = 11
772	 */
773	l9p_seek_iov(req->lr_resp_msg.lm_iov, req->lr_resp_msg.lm_niov,
774	    req->lr_data_iov, &req->lr_data_niov, 11);
775
776	/*
777	 * If it's an xattr fid there must, by definition, be an
778	 * xattrread.  The xattrread function can only be NULL if
779	 * xattrwalk and xattrcreate are NULL or always return error.
780	 *
781	 * TODO:
782	 *   separate out directory-read
783	 *   allow async read
784	 */
785	be = conn->lc_server->ls_backend;
786	fid = req->lr_fid;
787	if (l9p_fid_isxattr(fid)) {
788		error = be->xattrread(be->softc, req);
789	} else if (l9p_fid_isopen(fid)) {
790		error = be->read(be->softc, req);
791	} else {
792		error = EINVAL;
793	}
794
795	return (error);
796}
797
798static int
799l9p_dispatch_tremove(struct l9p_request *req)
800{
801	struct l9p_connection *conn = req->lr_conn;
802	struct l9p_backend *be;
803	struct l9p_fid *fid;
804	int error;
805
806	/*
807	 * ?? Should we allow Tremove on auth fids? If so, do
808	 * we pretend it is just a Tclunk?
809	 */
810	error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL, 0, &fid);
811	if (error)
812		return (error);
813
814	be = conn->lc_server->ls_backend;
815	l9p_fid_unsetvalid(fid);
816
817	error = be->remove(be->softc, fid);
818	/* fid is now gone regardless of any error return */
819	l9p_connection_remove_fid(conn, fid);
820	return (error);
821}
822
823static int
824l9p_dispatch_tstat(struct l9p_request *req)
825{
826	struct l9p_connection *conn = req->lr_conn;
827	struct l9p_backend *be;
828	struct l9p_fid *fid;
829	int error;
830
831	/* Allow Tstat on auth fid?  Seems harmless enough... */
832	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
833	    F_ALLOW_AUTH, &fid);
834	if (error)
835		return (error);
836
837	be = conn->lc_server->ls_backend;
838	req->lr_fid = fid;
839	error = be->stat(be->softc, req);
840
841	if (error == 0) {
842		if (l9p_fid_isauth(fid))
843			req->lr_resp.rstat.stat.qid.type |= L9P_QTAUTH;
844
845		/* should we check req->lr_resp.rstat.qid.type L9P_QTDIR bit? */
846		if (req->lr_resp.rstat.stat.qid.type &= L9P_QTDIR)
847			l9p_fid_setdir(fid);
848		else
849			l9p_fid_unsetdir(fid);
850	}
851
852	return (error);
853}
854
855static int
856l9p_dispatch_twalk(struct l9p_request *req)
857{
858	struct l9p_connection *conn = req->lr_conn;
859	struct l9p_backend *be;
860	struct l9p_fid *fid, *newfid;
861	uint16_t n;
862	int error;
863
864	/* Can forbid XATTR, but cannot require DIR. */
865	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
866	    F_FORBID_XATTR, &fid);
867	if (error)
868		return (error);
869
870	if (req->lr_req.twalk.hdr.fid != req->lr_req.twalk.newfid) {
871		newfid = l9p_connection_alloc_fid(conn,
872		    req->lr_req.twalk.newfid);
873		if (newfid == NULL)
874			return (EINVAL);
875	} else
876		newfid = fid;
877
878	be = conn->lc_server->ls_backend;
879	req->lr_fid = fid;
880	req->lr_newfid = newfid;
881	error = be->walk(be->softc, req);
882
883	/*
884	 * If newfid == fid, then fid itself has (potentially) changed,
885	 * but is still valid.  Otherwise set newfid valid on
886	 * success, and destroy it on error.
887	 */
888	if (newfid != fid) {
889		if (error == 0)
890			l9p_fid_setvalid(newfid);
891		else
892			l9p_connection_remove_fid(conn, newfid);
893	}
894
895	/*
896	 * If we walked any name elements, the last (n-1'th) qid
897	 * has the type (dir vs file) for the new fid.  Otherwise
898	 * the type of newfid is the same as fid.  Of course, if
899	 * n==0 and fid==newfid, fid is already set up correctly
900	 * as the whole thing was a big no-op, but it's safe to
901	 * copy its dir bit to itself.
902	 */
903	if (error == 0) {
904		n = req->lr_resp.rwalk.nwqid;
905		if (n > 0) {
906			if (req->lr_resp.rwalk.wqid[n - 1].type & L9P_QTDIR)
907				l9p_fid_setdir(newfid);
908		} else {
909			if (l9p_fid_isdir(fid))
910				l9p_fid_setdir(newfid);
911		}
912	}
913	return (error);
914}
915
916static int
917l9p_dispatch_twrite(struct l9p_request *req)
918{
919	struct l9p_connection *conn = req->lr_conn;
920	struct l9p_backend *be;
921	struct l9p_fid *fid;
922	int error;
923
924	/* Cannot require open due to xattr write, but can forbid dir. */
925	error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL,
926	    F_FORBID_DIR, &req->lr_fid);
927	if (error)
928		return (error);
929
930	/*
931	 * Adjust to point to the data to be written (a la
932	 * l9p_dispatch_tread, but we're pointing into the request
933	 * buffer rather than the response):
934	 *
935	 * size[4] + Twrite[1] + tag[2] + fid[4] + offset[8] + count[4] = 23
936	 */
937	l9p_seek_iov(req->lr_req_msg.lm_iov, req->lr_req_msg.lm_niov,
938	    req->lr_data_iov, &req->lr_data_niov, 23);
939
940	/*
941	 * Unlike read, write and xattrwrite are optional (for R/O fs).
942	 *
943	 * TODO:
944	 *   allow async write
945	 */
946	be = conn->lc_server->ls_backend;
947	fid = req->lr_fid;
948	if (l9p_fid_isxattr(fid)) {
949		error = be->xattrwrite != NULL ?
950		    be->xattrwrite(be->softc, req) : ENOSYS;
951	} else if (l9p_fid_isopen(fid)) {
952		error = be->write != NULL ?
953		    be->write(be->softc, req) : ENOSYS;
954	} else {
955		error = EINVAL;
956	}
957
958	return (error);
959}
960
961static int
962l9p_dispatch_twstat(struct l9p_request *req)
963{
964	struct l9p_connection *conn = req->lr_conn;
965	struct l9p_backend *be;
966	int error;
967
968	error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL,
969	    F_FORBID_XATTR, &req->lr_fid);
970	if (error)
971		return (error);
972
973	be = conn->lc_server->ls_backend;
974	error = be->wstat != NULL ? be->wstat(be->softc, req) : ENOSYS;
975	return (error);
976}
977
978static int
979l9p_dispatch_tstatfs(struct l9p_request *req)
980{
981	struct l9p_connection *conn = req->lr_conn;
982	struct l9p_backend *be;
983	int error;
984
985	/* Should we allow statfs on auth fids? */
986	error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL, 0, &req->lr_fid);
987	if (error)
988		return (error);
989
990	be = conn->lc_server->ls_backend;
991	error = be->statfs(be->softc, req);
992	return (error);
993}
994
995static int
996l9p_dispatch_tlopen(struct l9p_request *req)
997{
998	struct l9p_connection *conn = req->lr_conn;
999	struct l9p_backend *be;
1000	int error;
1001
1002	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1003	    F_FORBID_OPEN | F_FORBID_XATTR, &req->lr_fid);
1004	if (error)
1005		return (error);
1006
1007	be = conn->lc_server->ls_backend;
1008
1009	/*
1010	 * TODO:
1011	 *  - add async open (leaves req->lr_fid in limbo)
1012	 */
1013	error = be->lopen != NULL ? be->lopen(be->softc, req) : ENOSYS;
1014	if (error == 0)
1015		l9p_fid_setopen(req->lr_fid);
1016	return (error);
1017}
1018
1019static int
1020l9p_dispatch_tlcreate(struct l9p_request *req)
1021{
1022	struct l9p_connection *conn = req->lr_conn;
1023	struct l9p_backend *be;
1024	int error;
1025
1026	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1027	    F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid);
1028	if (error)
1029		return (error);
1030
1031	be = conn->lc_server->ls_backend;
1032
1033	/*
1034	 * TODO:
1035	 *  - check new file name
1036	 *  - add async create (leaves req->lr_fid in limbo)
1037	 */
1038	error = be->lcreate != NULL ? be->lcreate(be->softc, req) : ENOSYS;
1039	if (error == 0) {
1040		l9p_fid_unsetdir(req->lr_fid);
1041		l9p_fid_setopen(req->lr_fid);
1042	}
1043	return (error);
1044}
1045
1046static int
1047l9p_dispatch_tsymlink(struct l9p_request *req)
1048{
1049	struct l9p_connection *conn = req->lr_conn;
1050	struct l9p_backend *be;
1051	int error;
1052
1053	/* This doesn't affect the containing dir; maybe allow OPEN? */
1054	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1055	    F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid);
1056	if (error)
1057		return (error);
1058
1059	be = conn->lc_server->ls_backend;
1060
1061	/*
1062	 * TODO:
1063	 *  - check new file name
1064	 */
1065	error = be->symlink != NULL ? be->symlink(be->softc, req) : ENOSYS;
1066	return (error);
1067}
1068
1069static int
1070l9p_dispatch_tmknod(struct l9p_request *req)
1071{
1072	struct l9p_connection *conn = req->lr_conn;
1073	struct l9p_backend *be;
1074	int error;
1075
1076	/* This doesn't affect the containing dir; maybe allow OPEN? */
1077	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1078	    F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid);
1079	if (error)
1080		return (error);
1081
1082	be = conn->lc_server->ls_backend;
1083
1084	/*
1085	 * TODO:
1086	 *  - check new file name
1087	 */
1088	error = be->mknod != NULL ? be->mknod(be->softc, req) : ENOSYS;
1089	return (error);
1090}
1091
1092static int
1093l9p_dispatch_trename(struct l9p_request *req)
1094{
1095	struct l9p_connection *conn = req->lr_conn;
1096	struct l9p_backend *be;
1097	int error;
1098
1099	/* Rename directory or file (including symlink etc). */
1100	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1101	    F_FORBID_XATTR, &req->lr_fid);
1102	if (error)
1103		return (error);
1104
1105	/* Doesn't affect new dir fid; maybe allow OPEN? */
1106	error = fid_lookup(conn, req->lr_req.trename.dfid, ENOENT,
1107	    F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid2);
1108	if (error)
1109		return (error);
1110
1111	be = conn->lc_server->ls_backend;
1112
1113	/*
1114	 * TODO:
1115	 *  - check new file name (trename.name)
1116	 */
1117	error = be->rename != NULL ? be->rename(be->softc, req) : ENOSYS;
1118	return (error);
1119}
1120
1121static int
1122l9p_dispatch_treadlink(struct l9p_request *req)
1123{
1124	struct l9p_connection *conn = req->lr_conn;
1125	struct l9p_backend *be;
1126	int error;
1127
1128	/*
1129	 * The underlying readlink will fail unless it's a symlink,
1130	 * and the back end has to check, but we might as well forbid
1131	 * directories and open files here since it's cheap.
1132	 */
1133	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1134	    F_FORBID_DIR | F_FORBID_OPEN, &req->lr_fid);
1135	if (error)
1136		return (error);
1137
1138	be = conn->lc_server->ls_backend;
1139
1140	error = be->readlink != NULL ? be->readlink(be->softc, req) : ENOSYS;
1141	return (error);
1142}
1143
1144static int
1145l9p_dispatch_tgetattr(struct l9p_request *req)
1146{
1147	struct l9p_connection *conn = req->lr_conn;
1148	struct l9p_backend *be;
1149	int error;
1150
1151	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1152	    F_FORBID_XATTR, &req->lr_fid);
1153	if (error)
1154		return (error);
1155
1156	be = conn->lc_server->ls_backend;
1157
1158	error = be->getattr != NULL ? be->getattr(be->softc, req) : ENOSYS;
1159	return (error);
1160}
1161
1162static int
1163l9p_dispatch_tsetattr(struct l9p_request *req)
1164{
1165	struct l9p_connection *conn = req->lr_conn;
1166	struct l9p_backend *be;
1167	int error;
1168
1169	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1170	    F_FORBID_XATTR, &req->lr_fid);
1171	if (error)
1172		return (error);
1173
1174	be = conn->lc_server->ls_backend;
1175
1176	error = be->setattr != NULL ? be->setattr(be->softc, req) : ENOSYS;
1177	return (error);
1178}
1179
1180static int
1181l9p_dispatch_txattrwalk(struct l9p_request *req)
1182{
1183	struct l9p_connection *conn = req->lr_conn;
1184	struct l9p_backend *be;
1185	struct l9p_fid *fid, *newfid;
1186	int error;
1187
1188	/*
1189	 * Not sure if we care if file-or-dir is open or not.
1190	 * However, the fid argument should always be a file or
1191	 * dir and the newfid argument must be supplied, must
1192	 * be different, and always becomes a new xattr,
1193	 * so this is not very much like Twalk.
1194	 */
1195	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1196	    F_FORBID_XATTR, &fid);
1197	if (error)
1198		return (error);
1199
1200	newfid = l9p_connection_alloc_fid(conn, req->lr_req.txattrwalk.newfid);
1201	if (newfid == NULL)
1202		return (EINVAL);
1203
1204	be = conn->lc_server->ls_backend;
1205
1206	req->lr_fid = fid;
1207	req->lr_newfid = newfid;
1208	error = be->xattrwalk != NULL ? be->xattrwalk(be->softc, req) : ENOSYS;
1209
1210	/*
1211	 * Success/fail is similar to Twalk, except that we need
1212	 * to set the xattr type bit in the new fid.  It's also
1213	 * much simpler since newfid is always a new fid.
1214	 */
1215	if (error == 0) {
1216		l9p_fid_setvalid(newfid);
1217		l9p_fid_setxattr(newfid);
1218	} else {
1219		l9p_connection_remove_fid(conn, newfid);
1220	}
1221	return (error);
1222}
1223
1224static int
1225l9p_dispatch_txattrcreate(struct l9p_request *req)
1226{
1227	struct l9p_connection *conn = req->lr_conn;
1228	struct l9p_backend *be;
1229	struct l9p_fid *fid;
1230	int error;
1231
1232	/*
1233	 * Forbid incoming open fid since it's going to become an
1234	 * xattr fid instead.  If it turns out we need to allow
1235	 * it, fs code will need to handle this.
1236	 *
1237	 * Curiously, qemu 9pfs uses ENOENT for a bad txattrwalk
1238	 * fid, but EINVAL for txattrcreate (so we do too).
1239	 */
1240	error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL,
1241	    F_FORBID_XATTR | F_FORBID_OPEN, &fid);
1242	if (error)
1243		return (error);
1244
1245	be = conn->lc_server->ls_backend;
1246
1247	req->lr_fid = fid;
1248	error = be->xattrcreate != NULL ? be->xattrcreate(be->softc, req) :
1249	    ENOSYS;
1250
1251	/*
1252	 * On success, fid has changed from a regular (file or dir)
1253	 * fid to an xattr fid.
1254	 */
1255	if (error == 0) {
1256		l9p_fid_unsetdir(fid);
1257		l9p_fid_setxattr(fid);
1258	}
1259	return (error);
1260}
1261
1262static int
1263l9p_dispatch_treaddir(struct l9p_request *req)
1264{
1265	struct l9p_connection *conn = req->lr_conn;
1266	struct l9p_backend *be;
1267	int error;
1268
1269	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1270	    F_REQUIRE_DIR | F_REQUIRE_OPEN, &req->lr_fid);
1271	if (error)
1272		return (error);
1273
1274	/*
1275	 * Adjust so that writing messages (packing data) starts
1276	 * right after the count field in the response.
1277	 *
1278	 * size[4] + Rreaddir[1] + tag[2] + count[4] = 11
1279	 */
1280	l9p_seek_iov(req->lr_resp_msg.lm_iov, req->lr_resp_msg.lm_niov,
1281	    req->lr_data_iov, &req->lr_data_niov, 11);
1282
1283	be = conn->lc_server->ls_backend;
1284
1285	error = be->readdir != NULL ? be->readdir(be->softc, req) : ENOSYS;
1286	return (error);
1287}
1288
1289static int
1290l9p_dispatch_tfsync(struct l9p_request *req)
1291{
1292	struct l9p_connection *conn = req->lr_conn;
1293	struct l9p_backend *be;
1294	int error;
1295
1296	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1297	    F_REQUIRE_OPEN, &req->lr_fid);
1298	if (error)
1299		return (error);
1300
1301	be = conn->lc_server->ls_backend;
1302
1303	error = be->fsync != NULL ? be->fsync(be->softc, req) : ENOSYS;
1304	return (error);
1305}
1306
1307static int
1308l9p_dispatch_tlock(struct l9p_request *req)
1309{
1310	struct l9p_connection *conn = req->lr_conn;
1311	struct l9p_backend *be;
1312	int error;
1313
1314	/* Forbid directories? */
1315	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1316	    F_REQUIRE_OPEN, &req->lr_fid);
1317	if (error)
1318		return (error);
1319
1320	be = conn->lc_server->ls_backend;
1321
1322	/*
1323	 * TODO: multiple client handling; perhaps async locking.
1324	 */
1325	error = be->lock != NULL ? be->lock(be->softc, req) : ENOSYS;
1326	return (error);
1327}
1328
1329static int
1330l9p_dispatch_tgetlock(struct l9p_request *req)
1331{
1332	struct l9p_connection *conn = req->lr_conn;
1333	struct l9p_backend *be;
1334	int error;
1335
1336	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1337	    F_REQUIRE_OPEN, &req->lr_fid);
1338	if (error)
1339		return (error);
1340
1341	be = conn->lc_server->ls_backend;
1342
1343	/*
1344	 * TODO: multiple client handling; perhaps async locking.
1345	 */
1346	error = be->getlock != NULL ? be->getlock(be->softc, req) : ENOSYS;
1347	return (error);
1348}
1349
1350static int
1351l9p_dispatch_tlink(struct l9p_request *req)
1352{
1353	struct l9p_connection *conn = req->lr_conn;
1354	struct l9p_backend *be;
1355	int error;
1356
1357	/*
1358	 * Note, dfid goes into fid2 in current scheme.
1359	 *
1360	 * Allow open dir?  Target dir fid is not modified...
1361	 */
1362	error = fid_lookup(conn, req->lr_req.tlink.dfid, ENOENT,
1363	    F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid2);
1364	if (error)
1365		return (error);
1366
1367	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1368	    F_FORBID_DIR | F_FORBID_XATTR, &req->lr_fid);
1369	if (error)
1370		return (error);
1371
1372	be = conn->lc_server->ls_backend;
1373
1374	error = be->link != NULL ? be->link(be->softc, req) : ENOSYS;
1375	return (error);
1376}
1377
1378static int
1379l9p_dispatch_tmkdir(struct l9p_request *req)
1380{
1381	struct l9p_connection *conn = req->lr_conn;
1382	struct l9p_backend *be;
1383	int error;
1384
1385	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1386	    F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid);
1387	if (error)
1388		return (error);
1389
1390	/* Slashes embedded in the name are not allowed */
1391	if (strchr(req->lr_req.tlcreate.name, '/') != NULL)
1392		return (EINVAL);
1393
1394	be = conn->lc_server->ls_backend;
1395	error = be->mkdir != NULL ? be->mkdir(be->softc, req) : ENOSYS;
1396	return (error);
1397}
1398
1399static int
1400l9p_dispatch_trenameat(struct l9p_request *req)
1401{
1402	struct l9p_connection *conn = req->lr_conn;
1403	struct l9p_backend *be;
1404	int error;
1405
1406	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1407	    F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid);
1408	if (error)
1409		return (error);
1410
1411	error = fid_lookup(conn, req->lr_req.trenameat.newdirfid, ENOENT,
1412	    F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid2);
1413	if (error)
1414		return (error);
1415
1416	be = conn->lc_server->ls_backend;
1417
1418	/* TODO: check old and new names */
1419	error = be->renameat != NULL ? be->renameat(be->softc, req) : ENOSYS;
1420	return (error);
1421}
1422
1423static int
1424l9p_dispatch_tunlinkat(struct l9p_request *req)
1425{
1426	struct l9p_connection *conn = req->lr_conn;
1427	struct l9p_backend *be;
1428	int error;
1429
1430	error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT,
1431	    F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid);
1432	if (error)
1433		return (error);
1434
1435	be = conn->lc_server->ls_backend;
1436
1437	/* TODO: check dir-or-file name */
1438	error = be->unlinkat != NULL ? be->unlinkat(be->softc, req) : ENOSYS;
1439	return (error);
1440}
1441