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 */ 48 enum 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 */ 163 enum 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 178 enum { 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 */ 198 enum 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 */ 227 enum 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 247 struct l9p_hdr { 248 uint8_t type; 249 uint16_t tag; 250 uint32_t fid; 251 }; 252 253 struct l9p_qid { 254 uint8_t type; 255 uint32_t version; 256 uint64_t path; 257 }; 258 259 struct 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 279 struct 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 291 struct l9p_f_version { 292 struct l9p_hdr hdr; 293 uint32_t msize; 294 char *version; 295 }; 296 297 struct l9p_f_tflush { 298 struct l9p_hdr hdr; 299 uint16_t oldtag; 300 }; 301 302 struct l9p_f_error { 303 struct l9p_hdr hdr; 304 char *ename; 305 uint32_t errnum; 306 }; 307 308 struct l9p_f_ropen { 309 struct l9p_hdr hdr; 310 struct l9p_qid qid; 311 uint32_t iounit; 312 }; 313 314 struct l9p_f_rauth { 315 struct l9p_hdr hdr; 316 struct l9p_qid aqid; 317 }; 318 319 struct 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 329 struct 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 337 struct l9p_f_twalk { 338 struct l9p_hdr hdr; 339 uint32_t newfid; 340 uint16_t nwname; 341 char *wname[L9P_MAX_WELEM]; 342 }; 343 344 struct l9p_f_rwalk { 345 struct l9p_hdr hdr; 346 uint16_t nwqid; 347 struct l9p_qid wqid[L9P_MAX_WELEM]; 348 }; 349 350 struct 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 356 struct l9p_f_rstat { 357 struct l9p_hdr hdr; 358 struct l9p_stat stat; 359 }; 360 361 struct l9p_f_twstat { 362 struct l9p_hdr hdr; 363 struct l9p_stat stat; 364 }; 365 366 struct l9p_f_rstatfs { 367 struct l9p_hdr hdr; 368 struct l9p_statfs statfs; 369 }; 370 371 /* Used for Tlcreate, Tlopen, Tmkdir, Tunlinkat. */ 372 struct 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 380 struct l9p_f_tsymlink { 381 struct l9p_hdr hdr; 382 char *name; 383 char *symtgt; 384 uint32_t gid; 385 }; 386 387 struct 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 396 struct l9p_f_trename { 397 struct l9p_hdr hdr; 398 uint32_t dfid; 399 char *name; 400 }; 401 402 struct l9p_f_rreadlink { 403 struct l9p_hdr hdr; 404 char *target; 405 }; 406 407 struct l9p_f_tgetattr { 408 struct l9p_hdr hdr; 409 uint64_t request_mask; 410 }; 411 412 struct 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. */ 437 enum 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 471 struct 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. */ 485 enum 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 497 struct l9p_f_txattrwalk { 498 struct l9p_hdr hdr; 499 uint32_t newfid; 500 char *name; 501 }; 502 503 struct l9p_f_rxattrwalk { 504 struct l9p_hdr hdr; 505 uint64_t size; 506 }; 507 508 struct l9p_f_txattrcreate { 509 struct l9p_hdr hdr; 510 char *name; 511 uint64_t attr_size; 512 uint32_t flags; 513 }; 514 515 struct 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 525 enum l9pl_lock_type { 526 L9PL_LOCK_TYPE_RDLOCK = 0, 527 L9PL_LOCK_TYPE_WRLOCK = 1, 528 L9PL_LOCK_TYPE_UNLOCK = 2, 529 }; 530 531 enum l9pl_lock_flags { 532 L9PL_LOCK_TYPE_BLOCK = 1, 533 L9PL_LOCK_TYPE_RECLAIM = 2, 534 }; 535 536 struct l9p_f_rlock { 537 struct l9p_hdr hdr; 538 uint8_t status; /* from l9pl_lock_status */ 539 }; 540 541 enum 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 548 struct 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 557 struct l9p_f_tlink { 558 struct l9p_hdr hdr; 559 uint32_t dfid; 560 char *name; 561 }; 562 563 struct 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 */ 574 enum l9p_l_unlinkat_flags { 575 /* not sure if any other AT_* flags are passed through */ 576 L9PL_AT_REMOVEDIR = 0x0200, 577 }; 578 579 union 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