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#ifndef LIB9P_FCALL_H
33#define LIB9P_FCALL_H
34
35#include <stdint.h>
36
37#define L9P_MAX_WELEM   256
38
39/*
40 * Function call/reply (Tfoo/Rfoo) numbers.
41 *
42 * These are protocol code numbers, so the exact values
43 * matter.  However, __FIRST and __LAST_PLUS_ONE are for
44 * debug code, and just need to encompass the entire range.
45 *
46 * Note that we rely (in the debug code) on Rfoo == Tfoo+1.
47 */
48enum l9p_ftype {
49	L9P__FIRST = 6,		/* NB: must be <= all legal values */
50	L9P_TLERROR = 6,	/* illegal; exists for parity with Rlerror */
51	L9P_RLERROR,
52	L9P_TSTATFS = 8,
53	L9P_RSTATFS,
54	L9P_TLOPEN = 12,
55	L9P_RLOPEN,
56	L9P_TLCREATE = 14,
57	L9P_RLCREATE,
58	L9P_TSYMLINK = 16,
59	L9P_RSYMLINK,
60	L9P_TMKNOD = 18,
61	L9P_RMKNOD,
62	L9P_TRENAME = 20,
63	L9P_RRENAME,
64	L9P_TREADLINK = 22,
65	L9P_RREADLINK,
66	L9P_TGETATTR = 24,
67	L9P_RGETATTR,
68	L9P_TSETATTR = 26,
69	L9P_RSETATTR,
70	L9P_TXATTRWALK = 30,
71	L9P_RXATTRWALK,
72	L9P_TXATTRCREATE = 32,
73	L9P_RXATTRCREATE,
74	L9P_TREADDIR = 40,
75	L9P_RREADDIR,
76	L9P_TFSYNC = 50,
77	L9P_RFSYNC,
78	L9P_TLOCK = 52,
79	L9P_RLOCK,
80	L9P_TGETLOCK = 54,
81	L9P_RGETLOCK,
82	L9P_TLINK = 70,
83	L9P_RLINK,
84	L9P_TMKDIR = 72,
85	L9P_RMKDIR,
86	L9P_TRENAMEAT = 74,
87	L9P_RRENAMEAT,
88	L9P_TUNLINKAT = 76,
89	L9P_RUNLINKAT,
90	L9P_TVERSION = 100,
91	L9P_RVERSION,
92	L9P_TAUTH = 102,
93	L9P_RAUTH,
94	L9P_TATTACH = 104,
95	L9P_RATTACH,
96	L9P_TERROR = 106, 	/* illegal */
97	L9P_RERROR,
98	L9P_TFLUSH = 108,
99	L9P_RFLUSH,
100	L9P_TWALK = 110,
101	L9P_RWALK,
102	L9P_TOPEN = 112,
103	L9P_ROPEN,
104	L9P_TCREATE = 114,
105	L9P_RCREATE,
106	L9P_TREAD = 116,
107	L9P_RREAD,
108	L9P_TWRITE = 118,
109	L9P_RWRITE,
110	L9P_TCLUNK = 120,
111	L9P_RCLUNK,
112	L9P_TREMOVE = 122,
113	L9P_RREMOVE,
114	L9P_TSTAT = 124,
115	L9P_RSTAT,
116	L9P_TWSTAT = 126,
117	L9P_RWSTAT,
118	L9P__LAST_PLUS_1,	/* NB: must be last */
119};
120
121/*
122 * When a Tfoo request comes over the wire, we decode it
123 * (pack.c) from wire format into a request laid out in
124 * a "union l9p_fcall" object.  This object is not in wire
125 * format, but rather in something more convenient for us
126 * to operate on.
127 *
128 * We then dispatch the request (request.c, backend/fs.c) and
129 * use another "union l9p_fcall" object to build a reply.
130 * The reply is converted to wire format on the way back out
131 * (pack.c again).
132 *
133 * All sub-objects start with a header containing the request
134 * or reply type code and two-byte tag, and whether or not it
135 * is needed, a four-byte fid.
136 *
137 * What this means here is that the data structures within
138 * the union can be shared across various requests and replies.
139 * For instance, replies to OPEN, CREATE, LCREATE, LOPEN, MKDIR, and
140 * SYMLINK are all fairly similar (providing a qid and sometimes
141 * an iounit) and hence can all use the l9p_f_ropen structure.
142 * Which structures are used for which operations is somewhat
143 * arbitrary; for programming ease, if an operation shares a
144 * data structure, it still has its own name: there are union
145 * members named ropen, rcreate, rlcreate, rlopen, rmkdir, and
146 * rsymlink, even though all use struct l9p_f_ropen.
147 *
148 * The big exception to the above rule is struct l9p_f_io, which
149 * is used as both request and reply for all of READ, WRITE, and
150 * READDIR.  Moreover, the READDIR reply must be pre-packed into
151 * wire format (it is handled like raw data a la READ).
152 *
153 * Some request messages (e.g., TREADLINK) fit in a header, having
154 * just type code, tag, and fid.  These have no separate data
155 * structure, nor union member name.  Similarly, some reply
156 * messages (e.g., RCLUNK, RREMOVE, RRENAME) have just the type
157 * code and tag.
158 */
159
160/*
161 * Type code bits in (the first byte of) a qid.
162 */
163enum l9p_qid_type {
164	L9P_QTDIR = 0x80, /* type bit for directories */
165	L9P_QTAPPEND = 0x40, /* type bit for append only files */
166	L9P_QTEXCL = 0x20, /* type bit for exclusive use files */
167	L9P_QTMOUNT = 0x10, /* type bit for mounted channel */
168	L9P_QTAUTH = 0x08, /* type bit for authentication file */
169	L9P_QTTMP = 0x04, /* type bit for non-backed-up file */
170	L9P_QTSYMLINK = 0x02, /* type bit for symbolic link */
171	L9P_QTFILE = 0x00 /* type bits for plain file */
172};
173
174/*
175 * Extra permission bits in create and file modes (stat).
176 */
177#define L9P_DMDIR 0x80000000
178enum {
179	L9P_DMAPPEND = 0x40000000,
180	L9P_DMEXCL = 0x20000000,
181	L9P_DMMOUNT = 0x10000000,
182	L9P_DMAUTH = 0x08000000,
183	L9P_DMTMP = 0x04000000,
184	L9P_DMSYMLINK = 0x02000000,
185	/* 9P2000.u extensions */
186	L9P_DMDEVICE = 0x00800000,
187	L9P_DMNAMEDPIPE = 0x00200000,
188	L9P_DMSOCKET = 0x00100000,
189	L9P_DMSETUID = 0x00080000,
190	L9P_DMSETGID = 0x00040000,
191};
192
193/*
194 * Open/create mode bits in 9P2000 and 9P2000.u operations
195 * (not Linux lopen and lcreate flags, which are different).
196 * Note that the mode field is only one byte wide.
197 */
198enum l9p_omode {
199	L9P_OREAD = 0,	/* open for read */
200	L9P_OWRITE = 1,	/* write */
201	L9P_ORDWR = 2,	/* read and write */
202	L9P_OEXEC = 3,	/* execute, == read but check execute permission */
203	L9P_OACCMODE = 3, /* mask for the above access-mode bits */
204	L9P_OTRUNC = 16,	/* or'ed in (except for exec), truncate file first */
205	L9P_OCEXEC = 32,	/* or'ed in, close on exec */
206	L9P_ORCLOSE = 64,	/* or'ed in, remove on close */
207	L9P_ODIRECT = 128,	/* or'ed in, direct access */
208};
209
210/*
211 * Flag bits in 9P2000.L operations (Tlopen, Tlcreate).  These are
212 * basically just the Linux L_* flags.  The bottom 3 bits are the
213 * same as for l9p_omode, although open-for-exec is not used:
214 * instead, the client does a Tgetattr and checks the mode for
215 * execute bits, then just opens for reading.
216 *
217 * Each L_O_xxx is just value O_xxx has on Linux in <fcntl.h>;
218 * not all are necessarily used.  From observation, we do get
219 * L_O_CREAT and L_O_EXCL when creating with exclusive, and always
220 * get L_O_LARGEFILE.  We do get L_O_APPEND when opening for
221 * append.  We also get both L_O_DIRECT and L_O_DIRECTORY set
222 * when opening directories.
223 *
224 * We probably never get L_O_NOCTTY which makes no sense, and
225 * some of the other options may need to be handled on the client.
226 */
227enum l9p_l_o_flags {
228	L9P_L_O_CREAT =		000000100U,
229	L9P_L_O_EXCL =		000000200U,
230	L9P_L_O_NOCTTY =	000000400U,
231	L9P_L_O_TRUNC =		000001000U,
232	L9P_L_O_APPEND =	000002000U,
233	L9P_L_O_NONBLOCK =	000004000U,
234	L9P_L_O_DSYNC =		000010000U,
235	L9P_L_O_FASYNC =	000020000U,
236	L9P_L_O_DIRECT =	000040000U,
237	L9P_L_O_LARGEFILE =	000100000U,
238	L9P_L_O_DIRECTORY =	000200000U,
239	L9P_L_O_NOFOLLOW =	000400000U,
240	L9P_L_O_NOATIME =	001000000U,
241	L9P_L_O_CLOEXEC =	002000000U,
242	L9P_L_O_SYNC =		004000000U,
243	L9P_L_O_PATH =		010000000U,
244	L9P_L_O_TMPFILE =	020000000U,
245};
246
247struct l9p_hdr {
248	uint8_t type;
249	uint16_t tag;
250	uint32_t fid;
251};
252
253struct l9p_qid {
254	uint8_t  type;
255	uint32_t version;
256	uint64_t path;
257};
258
259struct l9p_stat {
260	uint16_t type;
261	uint32_t dev;
262	struct l9p_qid qid;
263	uint32_t mode;
264	uint32_t atime;
265	uint32_t mtime;
266	uint64_t length;
267	char *name;
268	char *uid;
269	char *gid;
270	char *muid;
271	char *extension;
272	uint32_t n_uid;
273	uint32_t n_gid;
274	uint32_t n_muid;
275};
276
277#define	L9P_FSTYPE	 0x01021997
278
279struct l9p_statfs {
280	uint32_t type;		/* file system type */
281	uint32_t bsize;		/* block size for I/O */
282	uint64_t blocks;	/* file system size (bsize-byte blocks) */
283	uint64_t bfree;		/* free blocks in fs */
284	uint64_t bavail;	/* free blocks avail to non-superuser*/
285	uint64_t files;		/* file nodes in file system (# inodes) */
286	uint64_t ffree;		/* free file nodes in fs */
287	uint64_t fsid;		/* file system identifier */
288	uint32_t namelen;	/* maximum length of filenames */
289};
290
291struct l9p_f_version {
292	struct l9p_hdr hdr;
293	uint32_t msize;
294	char *version;
295};
296
297struct l9p_f_tflush {
298	struct l9p_hdr hdr;
299	uint16_t oldtag;
300};
301
302struct l9p_f_error {
303	struct l9p_hdr hdr;
304	char *ename;
305	uint32_t errnum;
306};
307
308struct l9p_f_ropen {
309	struct l9p_hdr hdr;
310	struct l9p_qid qid;
311	uint32_t iounit;
312};
313
314struct l9p_f_rauth {
315	struct l9p_hdr hdr;
316	struct l9p_qid aqid;
317};
318
319struct l9p_f_attach {
320	struct l9p_hdr hdr;
321	uint32_t afid;
322	char *uname;
323	char *aname;
324	uint32_t n_uname;
325};
326#define	L9P_NOFID ((uint32_t)-1)	/* in Tattach, no auth fid */
327#define	L9P_NONUNAME ((uint32_t)-1)	/* in Tattach, no n_uname */
328
329struct l9p_f_tcreate {
330	struct l9p_hdr hdr;
331	uint32_t perm;
332	char *name;
333	uint8_t mode; /* +Topen */
334	char *extension;
335};
336
337struct l9p_f_twalk {
338	struct l9p_hdr hdr;
339	uint32_t newfid;
340	uint16_t nwname;
341	char *wname[L9P_MAX_WELEM];
342};
343
344struct l9p_f_rwalk {
345	struct l9p_hdr hdr;
346	uint16_t nwqid;
347	struct l9p_qid wqid[L9P_MAX_WELEM];
348};
349
350struct l9p_f_io {
351	struct l9p_hdr hdr;
352	uint64_t offset; /* Tread, Twrite, Treaddir */
353	uint32_t count; /* Tread, Twrite, Rread, Treaddir, Rreaddir */
354};
355
356struct l9p_f_rstat {
357	struct l9p_hdr hdr;
358	struct l9p_stat stat;
359};
360
361struct l9p_f_twstat {
362	struct l9p_hdr hdr;
363	struct l9p_stat stat;
364};
365
366struct l9p_f_rstatfs {
367	struct l9p_hdr hdr;
368	struct l9p_statfs statfs;
369};
370
371/* Used for Tlcreate, Tlopen, Tmkdir, Tunlinkat. */
372struct l9p_f_tlcreate {
373	struct l9p_hdr hdr;
374	char *name;		/* Tlcreate, Tmkdir, Tunlinkat */
375	uint32_t flags;		/* Tlcreate, Tlopen, Tmkdir, Tunlinkat */
376	uint32_t mode;		/* Tlcreate, Tmkdir */
377	uint32_t gid;		/* Tlcreate, Tmkdir */
378};
379
380struct l9p_f_tsymlink {
381	struct l9p_hdr hdr;
382	char *name;
383	char *symtgt;
384	uint32_t gid;
385};
386
387struct l9p_f_tmknod {
388	struct l9p_hdr hdr;
389	char *name;
390	uint32_t mode;
391	uint32_t major;
392	uint32_t minor;
393	uint32_t gid;
394};
395
396struct l9p_f_trename {
397	struct l9p_hdr hdr;
398	uint32_t dfid;
399	char *name;
400};
401
402struct l9p_f_rreadlink {
403	struct l9p_hdr hdr;
404	char *target;
405};
406
407struct l9p_f_tgetattr {
408	struct l9p_hdr hdr;
409	uint64_t request_mask;
410};
411
412struct l9p_f_rgetattr {
413	struct l9p_hdr hdr;
414	uint64_t valid;
415	struct l9p_qid qid;
416	uint32_t mode;
417	uint32_t uid;
418	uint32_t gid;
419	uint64_t nlink;
420	uint64_t rdev;
421	uint64_t size;
422	uint64_t blksize;
423	uint64_t blocks;
424	uint64_t atime_sec;
425	uint64_t atime_nsec;
426	uint64_t mtime_sec;
427	uint64_t mtime_nsec;
428	uint64_t ctime_sec;
429	uint64_t ctime_nsec;
430	uint64_t btime_sec;
431	uint64_t btime_nsec;
432	uint64_t gen;
433	uint64_t data_version;
434};
435
436/* Fields in req->request_mask and reply->valid for Tgetattr, Rgetattr. */
437enum l9pl_getattr_flags {
438	L9PL_GETATTR_MODE = 0x00000001,
439	L9PL_GETATTR_NLINK = 0x00000002,
440	L9PL_GETATTR_UID = 0x00000004,
441	L9PL_GETATTR_GID = 0x00000008,
442	L9PL_GETATTR_RDEV = 0x00000010,
443	L9PL_GETATTR_ATIME = 0x00000020,
444	L9PL_GETATTR_MTIME = 0x00000040,
445	L9PL_GETATTR_CTIME = 0x00000080,
446	L9PL_GETATTR_INO = 0x00000100,
447	L9PL_GETATTR_SIZE = 0x00000200,
448	L9PL_GETATTR_BLOCKS = 0x00000400,
449	/* everything up to and including BLOCKS is BASIC */
450	L9PL_GETATTR_BASIC = L9PL_GETATTR_MODE |
451		L9PL_GETATTR_NLINK |
452		L9PL_GETATTR_UID |
453		L9PL_GETATTR_GID |
454		L9PL_GETATTR_RDEV |
455		L9PL_GETATTR_ATIME |
456		L9PL_GETATTR_MTIME |
457		L9PL_GETATTR_CTIME |
458		L9PL_GETATTR_INO |
459		L9PL_GETATTR_SIZE |
460		L9PL_GETATTR_BLOCKS,
461	L9PL_GETATTR_BTIME = 0x00000800,
462	L9PL_GETATTR_GEN = 0x00001000,
463	L9PL_GETATTR_DATA_VERSION = 0x00002000,
464	/* BASIC + birthtime + gen + data-version = ALL */
465	L9PL_GETATTR_ALL = L9PL_GETATTR_BASIC |
466		L9PL_GETATTR_BTIME |
467		L9PL_GETATTR_GEN |
468		L9PL_GETATTR_DATA_VERSION,
469};
470
471struct l9p_f_tsetattr {
472	struct l9p_hdr hdr;
473	uint32_t valid;
474	uint32_t mode;
475	uint32_t uid;
476	uint32_t gid;
477	uint64_t size;
478	uint64_t atime_sec;	/* if valid & L9PL_SETATTR_ATIME_SET */
479	uint64_t atime_nsec;	/* (else use on-server time) */
480	uint64_t mtime_sec;	/* if valid & L9PL_SETATTR_MTIME_SET */
481	uint64_t mtime_nsec;	/* (else use on-server time) */
482};
483
484/* Fields in req->valid for Tsetattr. */
485enum l9pl_setattr_flags {
486	L9PL_SETATTR_MODE = 0x00000001,
487	L9PL_SETATTR_UID = 0x00000002,
488	L9PL_SETATTR_GID = 0x00000004,
489	L9PL_SETATTR_SIZE = 0x00000008,
490	L9PL_SETATTR_ATIME = 0x00000010,
491	L9PL_SETATTR_MTIME = 0x00000020,
492	L9PL_SETATTR_CTIME = 0x00000040,
493	L9PL_SETATTR_ATIME_SET = 0x00000080,
494	L9PL_SETATTR_MTIME_SET = 0x00000100,
495};
496
497struct l9p_f_txattrwalk {
498	struct l9p_hdr hdr;
499	uint32_t newfid;
500	char *name;
501};
502
503struct l9p_f_rxattrwalk {
504	struct l9p_hdr hdr;
505	uint64_t size;
506};
507
508struct l9p_f_txattrcreate {
509	struct l9p_hdr hdr;
510	char *name;
511	uint64_t attr_size;
512	uint32_t flags;
513};
514
515struct l9p_f_tlock {
516	struct l9p_hdr hdr;
517	uint8_t type;		/* from l9pl_lock_type */
518	uint32_t flags;		/* from l9pl_lock_flags */
519	uint64_t start;
520	uint64_t length;
521	uint32_t proc_id;
522	char *client_id;
523};
524
525enum l9pl_lock_type {
526	L9PL_LOCK_TYPE_RDLOCK =	0,
527	L9PL_LOCK_TYPE_WRLOCK =	1,
528	L9PL_LOCK_TYPE_UNLOCK =	2,
529};
530
531enum l9pl_lock_flags {
532	L9PL_LOCK_TYPE_BLOCK = 1,
533	L9PL_LOCK_TYPE_RECLAIM = 2,
534};
535
536struct l9p_f_rlock {
537	struct l9p_hdr hdr;
538	uint8_t status;		/* from l9pl_lock_status */
539};
540
541enum l9pl_lock_status {
542	L9PL_LOCK_SUCCESS = 0,
543	L9PL_LOCK_BLOCKED = 1,
544	L9PL_LOCK_ERROR = 2,
545	L9PL_LOCK_GRACE = 3,
546};
547
548struct l9p_f_getlock {
549	struct l9p_hdr hdr;
550	uint8_t type;		/* from l9pl_lock_type */
551	uint64_t start;
552	uint64_t length;
553	uint32_t proc_id;
554	char *client_id;
555};
556
557struct l9p_f_tlink {
558	struct l9p_hdr hdr;
559	uint32_t dfid;
560	char *name;
561};
562
563struct l9p_f_trenameat {
564	struct l9p_hdr hdr;
565	char *oldname;
566	uint32_t newdirfid;
567	char *newname;
568};
569
570/*
571 * Flags in Tunlinkat (which re-uses f_tlcreate data structure but
572 * with different meaning).
573 */
574enum l9p_l_unlinkat_flags {
575	/* not sure if any other AT_* flags are passed through */
576	L9PL_AT_REMOVEDIR =	0x0200,
577};
578
579union l9p_fcall {
580	struct l9p_hdr hdr;
581	struct l9p_f_version version;
582	struct l9p_f_tflush tflush;
583	struct l9p_f_ropen ropen;
584	struct l9p_f_ropen rcreate;
585	struct l9p_f_ropen rattach;
586	struct l9p_f_error error;
587	struct l9p_f_rauth rauth;
588	struct l9p_f_attach tattach;
589	struct l9p_f_attach tauth;
590	struct l9p_f_tcreate tcreate;
591	struct l9p_f_tcreate topen;
592	struct l9p_f_twalk twalk;
593	struct l9p_f_rwalk rwalk;
594	struct l9p_f_twstat twstat;
595	struct l9p_f_rstat rstat;
596	struct l9p_f_rstatfs rstatfs;
597	struct l9p_f_tlcreate tlopen;
598	struct l9p_f_ropen rlopen;
599	struct l9p_f_tlcreate tlcreate;
600	struct l9p_f_ropen rlcreate;
601	struct l9p_f_tsymlink tsymlink;
602	struct l9p_f_ropen rsymlink;
603	struct l9p_f_tmknod tmknod;
604	struct l9p_f_ropen rmknod;
605	struct l9p_f_trename trename;
606	struct l9p_f_rreadlink rreadlink;
607	struct l9p_f_tgetattr tgetattr;
608	struct l9p_f_rgetattr rgetattr;
609	struct l9p_f_tsetattr tsetattr;
610	struct l9p_f_txattrwalk txattrwalk;
611	struct l9p_f_rxattrwalk rxattrwalk;
612	struct l9p_f_txattrcreate txattrcreate;
613	struct l9p_f_tlock tlock;
614	struct l9p_f_rlock rlock;
615	struct l9p_f_getlock getlock;
616	struct l9p_f_tlink tlink;
617	struct l9p_f_tlcreate tmkdir;
618	struct l9p_f_ropen rmkdir;
619	struct l9p_f_trenameat trenameat;
620	struct l9p_f_tlcreate tunlinkat;
621	struct l9p_f_io io;
622};
623
624#endif  /* LIB9P_FCALL_H */
625