/*1* Copyright 2016 Jakub Klama <[email protected]>2* All rights reserved3*4* Redistribution and use in source and binary forms, with or without5* modification, are permitted providing that the following conditions6* are met:7* 1. Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9* 2. Redistributions in binary form must reproduce the above copyright10* notice, this list of conditions and the following disclaimer in the11* documentation and/or other materials provided with the distribution.12*13* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR14* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED15* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE16* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY17* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL18* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS19* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)20* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,21* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING22* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE23* POSSIBILITY OF SUCH DAMAGE.24*25*/2627/*28* Based on libixp code: ©2007-2010 Kris Maglione <maglione.k at Gmail>29*/3031#ifndef LIB9P_FCALL_H32#define LIB9P_FCALL_H3334#include <stdint.h>3536#define L9P_MAX_WELEM 2563738/*39* Function call/reply (Tfoo/Rfoo) numbers.40*41* These are protocol code numbers, so the exact values42* matter. However, __FIRST and __LAST_PLUS_ONE are for43* debug code, and just need to encompass the entire range.44*45* Note that we rely (in the debug code) on Rfoo == Tfoo+1.46*/47enum l9p_ftype {48L9P__FIRST = 6, /* NB: must be <= all legal values */49L9P_TLERROR = 6, /* illegal; exists for parity with Rlerror */50L9P_RLERROR,51L9P_TSTATFS = 8,52L9P_RSTATFS,53L9P_TLOPEN = 12,54L9P_RLOPEN,55L9P_TLCREATE = 14,56L9P_RLCREATE,57L9P_TSYMLINK = 16,58L9P_RSYMLINK,59L9P_TMKNOD = 18,60L9P_RMKNOD,61L9P_TRENAME = 20,62L9P_RRENAME,63L9P_TREADLINK = 22,64L9P_RREADLINK,65L9P_TGETATTR = 24,66L9P_RGETATTR,67L9P_TSETATTR = 26,68L9P_RSETATTR,69L9P_TXATTRWALK = 30,70L9P_RXATTRWALK,71L9P_TXATTRCREATE = 32,72L9P_RXATTRCREATE,73L9P_TREADDIR = 40,74L9P_RREADDIR,75L9P_TFSYNC = 50,76L9P_RFSYNC,77L9P_TLOCK = 52,78L9P_RLOCK,79L9P_TGETLOCK = 54,80L9P_RGETLOCK,81L9P_TLINK = 70,82L9P_RLINK,83L9P_TMKDIR = 72,84L9P_RMKDIR,85L9P_TRENAMEAT = 74,86L9P_RRENAMEAT,87L9P_TUNLINKAT = 76,88L9P_RUNLINKAT,89L9P_TVERSION = 100,90L9P_RVERSION,91L9P_TAUTH = 102,92L9P_RAUTH,93L9P_TATTACH = 104,94L9P_RATTACH,95L9P_TERROR = 106, /* illegal */96L9P_RERROR,97L9P_TFLUSH = 108,98L9P_RFLUSH,99L9P_TWALK = 110,100L9P_RWALK,101L9P_TOPEN = 112,102L9P_ROPEN,103L9P_TCREATE = 114,104L9P_RCREATE,105L9P_TREAD = 116,106L9P_RREAD,107L9P_TWRITE = 118,108L9P_RWRITE,109L9P_TCLUNK = 120,110L9P_RCLUNK,111L9P_TREMOVE = 122,112L9P_RREMOVE,113L9P_TSTAT = 124,114L9P_RSTAT,115L9P_TWSTAT = 126,116L9P_RWSTAT,117L9P__LAST_PLUS_1, /* NB: must be last */118};119120/*121* When a Tfoo request comes over the wire, we decode it122* (pack.c) from wire format into a request laid out in123* a "union l9p_fcall" object. This object is not in wire124* format, but rather in something more convenient for us125* to operate on.126*127* We then dispatch the request (request.c, backend/fs.c) and128* use another "union l9p_fcall" object to build a reply.129* The reply is converted to wire format on the way back out130* (pack.c again).131*132* All sub-objects start with a header containing the request133* or reply type code and two-byte tag, and whether or not it134* is needed, a four-byte fid.135*136* What this means here is that the data structures within137* the union can be shared across various requests and replies.138* For instance, replies to OPEN, CREATE, LCREATE, LOPEN, MKDIR, and139* SYMLINK are all fairly similar (providing a qid and sometimes140* an iounit) and hence can all use the l9p_f_ropen structure.141* Which structures are used for which operations is somewhat142* arbitrary; for programming ease, if an operation shares a143* data structure, it still has its own name: there are union144* members named ropen, rcreate, rlcreate, rlopen, rmkdir, and145* rsymlink, even though all use struct l9p_f_ropen.146*147* The big exception to the above rule is struct l9p_f_io, which148* is used as both request and reply for all of READ, WRITE, and149* READDIR. Moreover, the READDIR reply must be pre-packed into150* wire format (it is handled like raw data a la READ).151*152* Some request messages (e.g., TREADLINK) fit in a header, having153* just type code, tag, and fid. These have no separate data154* structure, nor union member name. Similarly, some reply155* messages (e.g., RCLUNK, RREMOVE, RRENAME) have just the type156* code and tag.157*/158159/*160* Type code bits in (the first byte of) a qid.161*/162enum l9p_qid_type {163L9P_QTDIR = 0x80, /* type bit for directories */164L9P_QTAPPEND = 0x40, /* type bit for append only files */165L9P_QTEXCL = 0x20, /* type bit for exclusive use files */166L9P_QTMOUNT = 0x10, /* type bit for mounted channel */167L9P_QTAUTH = 0x08, /* type bit for authentication file */168L9P_QTTMP = 0x04, /* type bit for non-backed-up file */169L9P_QTSYMLINK = 0x02, /* type bit for symbolic link */170L9P_QTFILE = 0x00 /* type bits for plain file */171};172173/*174* Extra permission bits in create and file modes (stat).175*/176#define L9P_DMDIR 0x80000000177enum {178L9P_DMAPPEND = 0x40000000,179L9P_DMEXCL = 0x20000000,180L9P_DMMOUNT = 0x10000000,181L9P_DMAUTH = 0x08000000,182L9P_DMTMP = 0x04000000,183L9P_DMSYMLINK = 0x02000000,184/* 9P2000.u extensions */185L9P_DMDEVICE = 0x00800000,186L9P_DMNAMEDPIPE = 0x00200000,187L9P_DMSOCKET = 0x00100000,188L9P_DMSETUID = 0x00080000,189L9P_DMSETGID = 0x00040000,190};191192/*193* Open/create mode bits in 9P2000 and 9P2000.u operations194* (not Linux lopen and lcreate flags, which are different).195* Note that the mode field is only one byte wide.196*/197enum l9p_omode {198L9P_OREAD = 0, /* open for read */199L9P_OWRITE = 1, /* write */200L9P_ORDWR = 2, /* read and write */201L9P_OEXEC = 3, /* execute, == read but check execute permission */202L9P_OACCMODE = 3, /* mask for the above access-mode bits */203L9P_OTRUNC = 16, /* or'ed in (except for exec), truncate file first */204L9P_OCEXEC = 32, /* or'ed in, close on exec */205L9P_ORCLOSE = 64, /* or'ed in, remove on close */206L9P_ODIRECT = 128, /* or'ed in, direct access */207};208209/*210* Flag bits in 9P2000.L operations (Tlopen, Tlcreate). These are211* basically just the Linux L_* flags. The bottom 3 bits are the212* same as for l9p_omode, although open-for-exec is not used:213* instead, the client does a Tgetattr and checks the mode for214* execute bits, then just opens for reading.215*216* Each L_O_xxx is just value O_xxx has on Linux in <fcntl.h>;217* not all are necessarily used. From observation, we do get218* L_O_CREAT and L_O_EXCL when creating with exclusive, and always219* get L_O_LARGEFILE. We do get L_O_APPEND when opening for220* append. We also get both L_O_DIRECT and L_O_DIRECTORY set221* when opening directories.222*223* We probably never get L_O_NOCTTY which makes no sense, and224* some of the other options may need to be handled on the client.225*/226enum l9p_l_o_flags {227L9P_L_O_CREAT = 000000100U,228L9P_L_O_EXCL = 000000200U,229L9P_L_O_NOCTTY = 000000400U,230L9P_L_O_TRUNC = 000001000U,231L9P_L_O_APPEND = 000002000U,232L9P_L_O_NONBLOCK = 000004000U,233L9P_L_O_DSYNC = 000010000U,234L9P_L_O_FASYNC = 000020000U,235L9P_L_O_DIRECT = 000040000U,236L9P_L_O_LARGEFILE = 000100000U,237L9P_L_O_DIRECTORY = 000200000U,238L9P_L_O_NOFOLLOW = 000400000U,239L9P_L_O_NOATIME = 001000000U,240L9P_L_O_CLOEXEC = 002000000U,241L9P_L_O_SYNC = 004000000U,242L9P_L_O_PATH = 010000000U,243L9P_L_O_TMPFILE = 020000000U,244};245246struct l9p_hdr {247uint8_t type;248uint16_t tag;249uint32_t fid;250};251252struct l9p_qid {253uint8_t type;254uint32_t version;255uint64_t path;256};257258struct l9p_stat {259uint16_t type;260uint32_t dev;261struct l9p_qid qid;262uint32_t mode;263uint32_t atime;264uint32_t mtime;265uint64_t length;266char *name;267char *uid;268char *gid;269char *muid;270char *extension;271uint32_t n_uid;272uint32_t n_gid;273uint32_t n_muid;274};275276#define L9P_FSTYPE 0x01021997277278struct l9p_statfs {279uint32_t type; /* file system type */280uint32_t bsize; /* block size for I/O */281uint64_t blocks; /* file system size (bsize-byte blocks) */282uint64_t bfree; /* free blocks in fs */283uint64_t bavail; /* free blocks avail to non-superuser*/284uint64_t files; /* file nodes in file system (# inodes) */285uint64_t ffree; /* free file nodes in fs */286uint64_t fsid; /* file system identifier */287uint32_t namelen; /* maximum length of filenames */288};289290struct l9p_f_version {291struct l9p_hdr hdr;292uint32_t msize;293char *version;294};295296struct l9p_f_tflush {297struct l9p_hdr hdr;298uint16_t oldtag;299};300301struct l9p_f_error {302struct l9p_hdr hdr;303char *ename;304uint32_t errnum;305};306307struct l9p_f_ropen {308struct l9p_hdr hdr;309struct l9p_qid qid;310uint32_t iounit;311};312313struct l9p_f_rauth {314struct l9p_hdr hdr;315struct l9p_qid aqid;316};317318struct l9p_f_attach {319struct l9p_hdr hdr;320uint32_t afid;321char *uname;322char *aname;323uint32_t n_uname;324};325#define L9P_NOFID ((uint32_t)-1) /* in Tattach, no auth fid */326#define L9P_NONUNAME ((uint32_t)-1) /* in Tattach, no n_uname */327328struct l9p_f_tcreate {329struct l9p_hdr hdr;330uint32_t perm;331char *name;332uint8_t mode; /* +Topen */333char *extension;334};335336struct l9p_f_twalk {337struct l9p_hdr hdr;338uint32_t newfid;339uint16_t nwname;340char *wname[L9P_MAX_WELEM];341};342343struct l9p_f_rwalk {344struct l9p_hdr hdr;345uint16_t nwqid;346struct l9p_qid wqid[L9P_MAX_WELEM];347};348349struct l9p_f_io {350struct l9p_hdr hdr;351uint64_t offset; /* Tread, Twrite, Treaddir */352uint32_t count; /* Tread, Twrite, Rread, Treaddir, Rreaddir */353};354355struct l9p_f_rstat {356struct l9p_hdr hdr;357struct l9p_stat stat;358};359360struct l9p_f_twstat {361struct l9p_hdr hdr;362struct l9p_stat stat;363};364365struct l9p_f_rstatfs {366struct l9p_hdr hdr;367struct l9p_statfs statfs;368};369370/* Used for Tlcreate, Tlopen, Tmkdir, Tunlinkat. */371struct l9p_f_tlcreate {372struct l9p_hdr hdr;373char *name; /* Tlcreate, Tmkdir, Tunlinkat */374uint32_t flags; /* Tlcreate, Tlopen, Tmkdir, Tunlinkat */375uint32_t mode; /* Tlcreate, Tmkdir */376uint32_t gid; /* Tlcreate, Tmkdir */377};378379struct l9p_f_tsymlink {380struct l9p_hdr hdr;381char *name;382char *symtgt;383uint32_t gid;384};385386struct l9p_f_tmknod {387struct l9p_hdr hdr;388char *name;389uint32_t mode;390uint32_t major;391uint32_t minor;392uint32_t gid;393};394395struct l9p_f_trename {396struct l9p_hdr hdr;397uint32_t dfid;398char *name;399};400401struct l9p_f_rreadlink {402struct l9p_hdr hdr;403char *target;404};405406struct l9p_f_tgetattr {407struct l9p_hdr hdr;408uint64_t request_mask;409};410411struct l9p_f_rgetattr {412struct l9p_hdr hdr;413uint64_t valid;414struct l9p_qid qid;415uint32_t mode;416uint32_t uid;417uint32_t gid;418uint64_t nlink;419uint64_t rdev;420uint64_t size;421uint64_t blksize;422uint64_t blocks;423uint64_t atime_sec;424uint64_t atime_nsec;425uint64_t mtime_sec;426uint64_t mtime_nsec;427uint64_t ctime_sec;428uint64_t ctime_nsec;429uint64_t btime_sec;430uint64_t btime_nsec;431uint64_t gen;432uint64_t data_version;433};434435/* Fields in req->request_mask and reply->valid for Tgetattr, Rgetattr. */436enum l9pl_getattr_flags {437L9PL_GETATTR_MODE = 0x00000001,438L9PL_GETATTR_NLINK = 0x00000002,439L9PL_GETATTR_UID = 0x00000004,440L9PL_GETATTR_GID = 0x00000008,441L9PL_GETATTR_RDEV = 0x00000010,442L9PL_GETATTR_ATIME = 0x00000020,443L9PL_GETATTR_MTIME = 0x00000040,444L9PL_GETATTR_CTIME = 0x00000080,445L9PL_GETATTR_INO = 0x00000100,446L9PL_GETATTR_SIZE = 0x00000200,447L9PL_GETATTR_BLOCKS = 0x00000400,448/* everything up to and including BLOCKS is BASIC */449L9PL_GETATTR_BASIC = L9PL_GETATTR_MODE |450L9PL_GETATTR_NLINK |451L9PL_GETATTR_UID |452L9PL_GETATTR_GID |453L9PL_GETATTR_RDEV |454L9PL_GETATTR_ATIME |455L9PL_GETATTR_MTIME |456L9PL_GETATTR_CTIME |457L9PL_GETATTR_INO |458L9PL_GETATTR_SIZE |459L9PL_GETATTR_BLOCKS,460L9PL_GETATTR_BTIME = 0x00000800,461L9PL_GETATTR_GEN = 0x00001000,462L9PL_GETATTR_DATA_VERSION = 0x00002000,463/* BASIC + birthtime + gen + data-version = ALL */464L9PL_GETATTR_ALL = L9PL_GETATTR_BASIC |465L9PL_GETATTR_BTIME |466L9PL_GETATTR_GEN |467L9PL_GETATTR_DATA_VERSION,468};469470struct l9p_f_tsetattr {471struct l9p_hdr hdr;472uint32_t valid;473uint32_t mode;474uint32_t uid;475uint32_t gid;476uint64_t size;477uint64_t atime_sec; /* if valid & L9PL_SETATTR_ATIME_SET */478uint64_t atime_nsec; /* (else use on-server time) */479uint64_t mtime_sec; /* if valid & L9PL_SETATTR_MTIME_SET */480uint64_t mtime_nsec; /* (else use on-server time) */481};482483/* Fields in req->valid for Tsetattr. */484enum l9pl_setattr_flags {485L9PL_SETATTR_MODE = 0x00000001,486L9PL_SETATTR_UID = 0x00000002,487L9PL_SETATTR_GID = 0x00000004,488L9PL_SETATTR_SIZE = 0x00000008,489L9PL_SETATTR_ATIME = 0x00000010,490L9PL_SETATTR_MTIME = 0x00000020,491L9PL_SETATTR_CTIME = 0x00000040,492L9PL_SETATTR_ATIME_SET = 0x00000080,493L9PL_SETATTR_MTIME_SET = 0x00000100,494};495496struct l9p_f_txattrwalk {497struct l9p_hdr hdr;498uint32_t newfid;499char *name;500};501502struct l9p_f_rxattrwalk {503struct l9p_hdr hdr;504uint64_t size;505};506507struct l9p_f_txattrcreate {508struct l9p_hdr hdr;509char *name;510uint64_t attr_size;511uint32_t flags;512};513514struct l9p_f_tlock {515struct l9p_hdr hdr;516uint8_t type; /* from l9pl_lock_type */517uint32_t flags; /* from l9pl_lock_flags */518uint64_t start;519uint64_t length;520uint32_t proc_id;521char *client_id;522};523524enum l9pl_lock_type {525L9PL_LOCK_TYPE_RDLOCK = 0,526L9PL_LOCK_TYPE_WRLOCK = 1,527L9PL_LOCK_TYPE_UNLOCK = 2,528};529530enum l9pl_lock_flags {531L9PL_LOCK_TYPE_BLOCK = 1,532L9PL_LOCK_TYPE_RECLAIM = 2,533};534535struct l9p_f_rlock {536struct l9p_hdr hdr;537uint8_t status; /* from l9pl_lock_status */538};539540enum l9pl_lock_status {541L9PL_LOCK_SUCCESS = 0,542L9PL_LOCK_BLOCKED = 1,543L9PL_LOCK_ERROR = 2,544L9PL_LOCK_GRACE = 3,545};546547struct l9p_f_getlock {548struct l9p_hdr hdr;549uint8_t type; /* from l9pl_lock_type */550uint64_t start;551uint64_t length;552uint32_t proc_id;553char *client_id;554};555556struct l9p_f_tlink {557struct l9p_hdr hdr;558uint32_t dfid;559char *name;560};561562struct l9p_f_trenameat {563struct l9p_hdr hdr;564char *oldname;565uint32_t newdirfid;566char *newname;567};568569/*570* Flags in Tunlinkat (which re-uses f_tlcreate data structure but571* with different meaning).572*/573enum l9p_l_unlinkat_flags {574/* not sure if any other AT_* flags are passed through */575L9PL_AT_REMOVEDIR = 0x0200,576};577578union l9p_fcall {579struct l9p_hdr hdr;580struct l9p_f_version version;581struct l9p_f_tflush tflush;582struct l9p_f_ropen ropen;583struct l9p_f_ropen rcreate;584struct l9p_f_ropen rattach;585struct l9p_f_error error;586struct l9p_f_rauth rauth;587struct l9p_f_attach tattach;588struct l9p_f_attach tauth;589struct l9p_f_tcreate tcreate;590struct l9p_f_tcreate topen;591struct l9p_f_twalk twalk;592struct l9p_f_rwalk rwalk;593struct l9p_f_twstat twstat;594struct l9p_f_rstat rstat;595struct l9p_f_rstatfs rstatfs;596struct l9p_f_tlcreate tlopen;597struct l9p_f_ropen rlopen;598struct l9p_f_tlcreate tlcreate;599struct l9p_f_ropen rlcreate;600struct l9p_f_tsymlink tsymlink;601struct l9p_f_ropen rsymlink;602struct l9p_f_tmknod tmknod;603struct l9p_f_ropen rmknod;604struct l9p_f_trename trename;605struct l9p_f_rreadlink rreadlink;606struct l9p_f_tgetattr tgetattr;607struct l9p_f_rgetattr rgetattr;608struct l9p_f_tsetattr tsetattr;609struct l9p_f_txattrwalk txattrwalk;610struct l9p_f_rxattrwalk rxattrwalk;611struct l9p_f_txattrcreate txattrcreate;612struct l9p_f_tlock tlock;613struct l9p_f_rlock rlock;614struct l9p_f_getlock getlock;615struct l9p_f_tlink tlink;616struct l9p_f_tlcreate tmkdir;617struct l9p_f_ropen rmkdir;618struct l9p_f_trenameat trenameat;619struct l9p_f_tlcreate tunlinkat;620struct l9p_f_io io;621};622623#endif /* LIB9P_FCALL_H */624625626