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