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 return (r); 351 352 if (*num > L9P_MAX_WELEM) 353 return (-1); 354 355 for (i = 0, lim = *num; i < lim; i++) { 356 ret = l9p_puqid(msg, &qids[i]); 357 if (ret < 0) 358 return (-1); 359 r += ret; 360 } 361 return (r); 362 } 363 364 /* 365 * Pack or unpack a l9p_stat. 366 * 367 * These have variable size, and the size further depends on 368 * the protocol version. 369 * 370 * Returns the number of bytes packed/unpacked, or -1 on error. 371 */ 372 ssize_t 373 l9p_pustat(struct l9p_message *msg, struct l9p_stat *stat, 374 enum l9p_version version) 375 { 376 ssize_t r = 0; 377 uint16_t size; 378 379 /* The on-wire size field excludes the size of the size field. */ 380 if (msg->lm_mode == L9P_PACK) 381 size = l9p_sizeof_stat(stat, version) - 2; 382 383 r += l9p_pu16(msg, &size); 384 r += l9p_pu16(msg, &stat->type); 385 r += l9p_pu32(msg, &stat->dev); 386 r += l9p_puqid(msg, &stat->qid); 387 r += l9p_pu32(msg, &stat->mode); 388 r += l9p_pu32(msg, &stat->atime); 389 r += l9p_pu32(msg, &stat->mtime); 390 r += l9p_pu64(msg, &stat->length); 391 r += l9p_pustring(msg, &stat->name); 392 r += l9p_pustring(msg, &stat->uid); 393 r += l9p_pustring(msg, &stat->gid); 394 r += l9p_pustring(msg, &stat->muid); 395 396 if (version >= L9P_2000U) { 397 r += l9p_pustring(msg, &stat->extension); 398 r += l9p_pu32(msg, &stat->n_uid); 399 r += l9p_pu32(msg, &stat->n_gid); 400 r += l9p_pu32(msg, &stat->n_muid); 401 } 402 403 if (r < size + 2) 404 return (-1); 405 406 return (r); 407 } 408 409 /* 410 * Pack or unpack a variable-length dirent. 411 * 412 * If unpacking, the name field is malloc()ed and the caller must 413 * free it. 414 * 415 * Returns the wire-format length, or -1 if we ran out of room. 416 */ 417 ssize_t 418 l9p_pudirent(struct l9p_message *msg, struct l9p_dirent *de) 419 { 420 ssize_t r, s; 421 422 r = l9p_puqid(msg, &de->qid); 423 r += l9p_pu64(msg, &de->offset); 424 r += l9p_pu8(msg, &de->type); 425 s = l9p_pustring(msg, &de->name); 426 if (r < QID_SIZE + 8 + 1 || s < 0) 427 return (-1); 428 return (r + s); 429 } 430 431 /* 432 * Pack or unpack a request or response (fcall). 433 * 434 * Returns 0 on success, -1 on error. (It's up to the caller 435 * to call l9p_freefcall on our failure.) 436 */ 437 int 438 l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall, 439 enum l9p_version version) 440 { 441 uint32_t length = 0; 442 ssize_t r; 443 444 /* 445 * Get overall length, type, and tag, which should appear 446 * in all messages. If not even that works, abort immediately. 447 */ 448 l9p_pu32(msg, &length); 449 l9p_pu8(msg, &fcall->hdr.type); 450 r = l9p_pu16(msg, &fcall->hdr.tag); 451 if (r < 0) 452 return (-1); 453 454 /* 455 * Decode remainder of message. When unpacking, this may 456 * allocate memory, even if we fail during the decode. 457 * Note that the initial fcall is zeroed out, though, so 458 * we can just freefcall() to release whatever might have 459 * gotten allocated, if the unpack fails due to a short 460 * packet. 461 */ 462 switch (fcall->hdr.type) { 463 case L9P_TVERSION: 464 case L9P_RVERSION: 465 l9p_pu32(msg, &fcall->version.msize); 466 r = l9p_pustring(msg, &fcall->version.version); 467 break; 468 469 case L9P_TAUTH: 470 l9p_pu32(msg, &fcall->tauth.afid); 471 r = l9p_pustring(msg, &fcall->tauth.uname); 472 if (r < 0) 473 break; 474 r = l9p_pustring(msg, &fcall->tauth.aname); 475 if (r < 0) 476 break; 477 if (version >= L9P_2000U) 478 r = l9p_pu32(msg, &fcall->tauth.n_uname); 479 break; 480 481 case L9P_RAUTH: 482 r = l9p_puqid(msg, &fcall->rauth.aqid); 483 break; 484 485 case L9P_TATTACH: 486 l9p_pu32(msg, &fcall->hdr.fid); 487 l9p_pu32(msg, &fcall->tattach.afid); 488 r = l9p_pustring(msg, &fcall->tattach.uname); 489 if (r < 0) 490 break; 491 r = l9p_pustring(msg, &fcall->tattach.aname); 492 if (r < 0) 493 break; 494 if (version >= L9P_2000U) 495 r = l9p_pu32(msg, &fcall->tattach.n_uname); 496 break; 497 498 case L9P_RATTACH: 499 r = l9p_puqid(msg, &fcall->rattach.qid); 500 break; 501 502 case L9P_RERROR: 503 r = l9p_pustring(msg, &fcall->error.ename); 504 if (r < 0) 505 break; 506 if (version >= L9P_2000U) 507 r = l9p_pu32(msg, &fcall->error.errnum); 508 break; 509 510 case L9P_RLERROR: 511 r = l9p_pu32(msg, &fcall->error.errnum); 512 break; 513 514 case L9P_TFLUSH: 515 r = l9p_pu16(msg, &fcall->tflush.oldtag); 516 break; 517 518 case L9P_RFLUSH: 519 break; 520 521 case L9P_TWALK: 522 l9p_pu32(msg, &fcall->hdr.fid); 523 l9p_pu32(msg, &fcall->twalk.newfid); 524 r = l9p_pustrings(msg, &fcall->twalk.nwname, 525 fcall->twalk.wname, N(fcall->twalk.wname)); 526 break; 527 528 case L9P_RWALK: 529 r = l9p_puqids(msg, &fcall->rwalk.nwqid, fcall->rwalk.wqid); 530 break; 531 532 case L9P_TOPEN: 533 l9p_pu32(msg, &fcall->hdr.fid); 534 r = l9p_pu8(msg, &fcall->topen.mode); 535 break; 536 537 case L9P_ROPEN: 538 l9p_puqid(msg, &fcall->ropen.qid); 539 r = l9p_pu32(msg, &fcall->ropen.iounit); 540 break; 541 542 case L9P_TCREATE: 543 l9p_pu32(msg, &fcall->hdr.fid); 544 r = l9p_pustring(msg, &fcall->tcreate.name); 545 if (r < 0) 546 break; 547 l9p_pu32(msg, &fcall->tcreate.perm); 548 r = l9p_pu8(msg, &fcall->tcreate.mode); 549 if (version >= L9P_2000U) 550 r = l9p_pustring(msg, &fcall->tcreate.extension); 551 break; 552 553 case L9P_RCREATE: 554 l9p_puqid(msg, &fcall->rcreate.qid); 555 r = l9p_pu32(msg, &fcall->rcreate.iounit); 556 break; 557 558 case L9P_TREAD: 559 case L9P_TREADDIR: 560 l9p_pu32(msg, &fcall->hdr.fid); 561 l9p_pu64(msg, &fcall->io.offset); 562 r = l9p_pu32(msg, &fcall->io.count); 563 break; 564 565 case L9P_RREAD: 566 case L9P_RREADDIR: 567 r = l9p_pu32(msg, &fcall->io.count); 568 break; 569 570 case L9P_TWRITE: 571 l9p_pu32(msg, &fcall->hdr.fid); 572 l9p_pu64(msg, &fcall->io.offset); 573 r = l9p_pu32(msg, &fcall->io.count); 574 break; 575 576 case L9P_RWRITE: 577 r = l9p_pu32(msg, &fcall->io.count); 578 break; 579 580 case L9P_TCLUNK: 581 case L9P_TSTAT: 582 case L9P_TREMOVE: 583 case L9P_TSTATFS: 584 r = l9p_pu32(msg, &fcall->hdr.fid); 585 break; 586 587 case L9P_RCLUNK: 588 case L9P_RREMOVE: 589 break; 590 591 case L9P_RSTAT: 592 { 593 uint16_t size = l9p_sizeof_stat(&fcall->rstat.stat, 594 version); 595 l9p_pu16(msg, &size); 596 r = l9p_pustat(msg, &fcall->rstat.stat, version); 597 } 598 break; 599 600 case L9P_TWSTAT: 601 { 602 uint16_t size; 603 l9p_pu32(msg, &fcall->hdr.fid); 604 l9p_pu16(msg, &size); 605 r = l9p_pustat(msg, &fcall->twstat.stat, version); 606 } 607 break; 608 609 case L9P_RWSTAT: 610 break; 611 612 case L9P_RSTATFS: 613 l9p_pu32(msg, &fcall->rstatfs.statfs.type); 614 l9p_pu32(msg, &fcall->rstatfs.statfs.bsize); 615 l9p_pu64(msg, &fcall->rstatfs.statfs.blocks); 616 l9p_pu64(msg, &fcall->rstatfs.statfs.bfree); 617 l9p_pu64(msg, &fcall->rstatfs.statfs.bavail); 618 l9p_pu64(msg, &fcall->rstatfs.statfs.files); 619 l9p_pu64(msg, &fcall->rstatfs.statfs.ffree); 620 l9p_pu64(msg, &fcall->rstatfs.statfs.fsid); 621 r = l9p_pu32(msg, &fcall->rstatfs.statfs.namelen); 622 break; 623 624 case L9P_TLOPEN: 625 l9p_pu32(msg, &fcall->hdr.fid); 626 r = l9p_pu32(msg, &fcall->tlopen.flags); 627 break; 628 629 case L9P_RLOPEN: 630 l9p_puqid(msg, &fcall->rlopen.qid); 631 r = l9p_pu32(msg, &fcall->rlopen.iounit); 632 break; 633 634 case L9P_TLCREATE: 635 l9p_pu32(msg, &fcall->hdr.fid); 636 r = l9p_pustring(msg, &fcall->tlcreate.name); 637 if (r < 0) 638 break; 639 l9p_pu32(msg, &fcall->tlcreate.flags); 640 l9p_pu32(msg, &fcall->tlcreate.mode); 641 r = l9p_pu32(msg, &fcall->tlcreate.gid); 642 break; 643 644 case L9P_RLCREATE: 645 l9p_puqid(msg, &fcall->rlcreate.qid); 646 r = l9p_pu32(msg, &fcall->rlcreate.iounit); 647 break; 648 649 case L9P_TSYMLINK: 650 l9p_pu32(msg, &fcall->hdr.fid); 651 r = l9p_pustring(msg, &fcall->tsymlink.name); 652 if (r < 0) 653 break; 654 r = l9p_pustring(msg, &fcall->tsymlink.symtgt); 655 if (r < 0) 656 break; 657 r = l9p_pu32(msg, &fcall->tlcreate.gid); 658 break; 659 660 case L9P_RSYMLINK: 661 r = l9p_puqid(msg, &fcall->rsymlink.qid); 662 break; 663 664 case L9P_TMKNOD: 665 l9p_pu32(msg, &fcall->hdr.fid); 666 r = l9p_pustring(msg, &fcall->tmknod.name); 667 if (r < 0) 668 break; 669 l9p_pu32(msg, &fcall->tmknod.mode); 670 l9p_pu32(msg, &fcall->tmknod.major); 671 l9p_pu32(msg, &fcall->tmknod.minor); 672 r = l9p_pu32(msg, &fcall->tmknod.gid); 673 break; 674 675 case L9P_RMKNOD: 676 r = l9p_puqid(msg, &fcall->rmknod.qid); 677 break; 678 679 case L9P_TRENAME: 680 l9p_pu32(msg, &fcall->hdr.fid); 681 l9p_pu32(msg, &fcall->trename.dfid); 682 r = l9p_pustring(msg, &fcall->trename.name); 683 break; 684 685 case L9P_RRENAME: 686 break; 687 688 case L9P_TREADLINK: 689 r = l9p_pu32(msg, &fcall->hdr.fid); 690 break; 691 692 case L9P_RREADLINK: 693 r = l9p_pustring(msg, &fcall->rreadlink.target); 694 break; 695 696 case L9P_TGETATTR: 697 l9p_pu32(msg, &fcall->hdr.fid); 698 r = l9p_pu64(msg, &fcall->tgetattr.request_mask); 699 break; 700 701 case L9P_RGETATTR: 702 l9p_pu64(msg, &fcall->rgetattr.valid); 703 l9p_puqid(msg, &fcall->rgetattr.qid); 704 l9p_pu32(msg, &fcall->rgetattr.mode); 705 l9p_pu32(msg, &fcall->rgetattr.uid); 706 l9p_pu32(msg, &fcall->rgetattr.gid); 707 l9p_pu64(msg, &fcall->rgetattr.nlink); 708 l9p_pu64(msg, &fcall->rgetattr.rdev); 709 l9p_pu64(msg, &fcall->rgetattr.size); 710 l9p_pu64(msg, &fcall->rgetattr.blksize); 711 l9p_pu64(msg, &fcall->rgetattr.blocks); 712 l9p_pu64(msg, &fcall->rgetattr.atime_sec); 713 l9p_pu64(msg, &fcall->rgetattr.atime_nsec); 714 l9p_pu64(msg, &fcall->rgetattr.mtime_sec); 715 l9p_pu64(msg, &fcall->rgetattr.mtime_nsec); 716 l9p_pu64(msg, &fcall->rgetattr.ctime_sec); 717 l9p_pu64(msg, &fcall->rgetattr.ctime_nsec); 718 l9p_pu64(msg, &fcall->rgetattr.btime_sec); 719 l9p_pu64(msg, &fcall->rgetattr.btime_nsec); 720 l9p_pu64(msg, &fcall->rgetattr.gen); 721 r = l9p_pu64(msg, &fcall->rgetattr.data_version); 722 break; 723 724 case L9P_TSETATTR: 725 l9p_pu32(msg, &fcall->hdr.fid); 726 l9p_pu32(msg, &fcall->tsetattr.valid); 727 l9p_pu32(msg, &fcall->tsetattr.mode); 728 l9p_pu32(msg, &fcall->tsetattr.uid); 729 l9p_pu32(msg, &fcall->tsetattr.gid); 730 l9p_pu64(msg, &fcall->tsetattr.size); 731 l9p_pu64(msg, &fcall->tsetattr.atime_sec); 732 l9p_pu64(msg, &fcall->tsetattr.atime_nsec); 733 l9p_pu64(msg, &fcall->tsetattr.mtime_sec); 734 r = l9p_pu64(msg, &fcall->tsetattr.mtime_nsec); 735 break; 736 737 case L9P_RSETATTR: 738 break; 739 740 case L9P_TXATTRWALK: 741 l9p_pu32(msg, &fcall->hdr.fid); 742 l9p_pu32(msg, &fcall->txattrwalk.newfid); 743 r = l9p_pustring(msg, &fcall->txattrwalk.name); 744 break; 745 746 case L9P_RXATTRWALK: 747 r = l9p_pu64(msg, &fcall->rxattrwalk.size); 748 break; 749 750 case L9P_TXATTRCREATE: 751 l9p_pu32(msg, &fcall->hdr.fid); 752 r = l9p_pustring(msg, &fcall->txattrcreate.name); 753 if (r < 0) 754 break; 755 l9p_pu64(msg, &fcall->txattrcreate.attr_size); 756 r = l9p_pu32(msg, &fcall->txattrcreate.flags); 757 break; 758 759 case L9P_RXATTRCREATE: 760 break; 761 762 case L9P_TFSYNC: 763 r = l9p_pu32(msg, &fcall->hdr.fid); 764 break; 765 766 case L9P_RFSYNC: 767 break; 768 769 case L9P_TLOCK: 770 l9p_pu32(msg, &fcall->hdr.fid); 771 l9p_pu8(msg, &fcall->tlock.type); 772 l9p_pu32(msg, &fcall->tlock.flags); 773 l9p_pu64(msg, &fcall->tlock.start); 774 l9p_pu64(msg, &fcall->tlock.length); 775 l9p_pu32(msg, &fcall->tlock.proc_id); 776 r = l9p_pustring(msg, &fcall->tlock.client_id); 777 break; 778 779 case L9P_RLOCK: 780 r = l9p_pu8(msg, &fcall->rlock.status); 781 break; 782 783 case L9P_TGETLOCK: 784 l9p_pu32(msg, &fcall->hdr.fid); 785 /* FALLTHROUGH */ 786 787 case L9P_RGETLOCK: 788 l9p_pu8(msg, &fcall->getlock.type); 789 l9p_pu64(msg, &fcall->getlock.start); 790 l9p_pu64(msg, &fcall->getlock.length); 791 l9p_pu32(msg, &fcall->getlock.proc_id); 792 r = l9p_pustring(msg, &fcall->getlock.client_id); 793 break; 794 795 case L9P_TLINK: 796 l9p_pu32(msg, &fcall->tlink.dfid); 797 l9p_pu32(msg, &fcall->hdr.fid); 798 r = l9p_pustring(msg, &fcall->tlink.name); 799 break; 800 801 case L9P_RLINK: 802 break; 803 804 case L9P_TMKDIR: 805 l9p_pu32(msg, &fcall->hdr.fid); 806 r = l9p_pustring(msg, &fcall->tmkdir.name); 807 if (r < 0) 808 break; 809 l9p_pu32(msg, &fcall->tmkdir.mode); 810 r = l9p_pu32(msg, &fcall->tmkdir.gid); 811 break; 812 813 case L9P_RMKDIR: 814 r = l9p_puqid(msg, &fcall->rmkdir.qid); 815 break; 816 817 case L9P_TRENAMEAT: 818 l9p_pu32(msg, &fcall->hdr.fid); 819 r = l9p_pustring(msg, &fcall->trenameat.oldname); 820 if (r < 0) 821 break; 822 l9p_pu32(msg, &fcall->trenameat.newdirfid); 823 r = l9p_pustring(msg, &fcall->trenameat.newname); 824 break; 825 826 case L9P_RRENAMEAT: 827 break; 828 829 case L9P_TUNLINKAT: 830 l9p_pu32(msg, &fcall->hdr.fid); 831 r = l9p_pustring(msg, &fcall->tunlinkat.name); 832 if (r < 0) 833 break; 834 r = l9p_pu32(msg, &fcall->tunlinkat.flags); 835 break; 836 837 case L9P_RUNLINKAT: 838 break; 839 840 default: 841 L9P_LOG(L9P_ERROR, "%s(): missing case for type %d", 842 __func__, fcall->hdr.type); 843 break; 844 } 845 846 /* Check for over- or under-run, or pustring error. */ 847 if (r < 0) 848 return (-1); 849 850 if (msg->lm_mode == L9P_PACK) { 851 /* Rewind to the beginning and install size at front. */ 852 uint32_t len = (uint32_t)msg->lm_size; 853 msg->lm_cursor_offset = 0; 854 msg->lm_cursor_iov = 0; 855 856 /* 857 * Subtract 4 bytes from current size, becase we're 858 * overwriting size (rewinding message to the beginning) 859 * and writing again, which will increase it 4 more. 860 */ 861 msg->lm_size -= sizeof(uint32_t); 862 863 if (fcall->hdr.type == L9P_RREAD || 864 fcall->hdr.type == L9P_RREADDIR) 865 len += fcall->io.count; 866 867 l9p_pu32(msg, &len); 868 } 869 870 return (0); 871 } 872 873 /* 874 * Free any strings or other data malloc'ed in the process of 875 * packing or unpacking an fcall. 876 */ 877 void 878 l9p_freefcall(union l9p_fcall *fcall) 879 { 880 uint16_t i; 881 882 switch (fcall->hdr.type) { 883 884 case L9P_TVERSION: 885 case L9P_RVERSION: 886 free(fcall->version.version); 887 return; 888 889 case L9P_TATTACH: 890 free(fcall->tattach.aname); 891 free(fcall->tattach.uname); 892 return; 893 894 case L9P_TWALK: 895 for (i = 0; i < fcall->twalk.nwname; i++) 896 free(fcall->twalk.wname[i]); 897 return; 898 899 case L9P_TCREATE: 900 case L9P_TOPEN: 901 free(fcall->tcreate.name); 902 free(fcall->tcreate.extension); 903 return; 904 905 case L9P_RSTAT: 906 l9p_freestat(&fcall->rstat.stat); 907 return; 908 909 case L9P_TWSTAT: 910 l9p_freestat(&fcall->twstat.stat); 911 return; 912 913 case L9P_TLCREATE: 914 free(fcall->tlcreate.name); 915 return; 916 917 case L9P_TSYMLINK: 918 free(fcall->tsymlink.name); 919 free(fcall->tsymlink.symtgt); 920 return; 921 922 case L9P_TMKNOD: 923 free(fcall->tmknod.name); 924 return; 925 926 case L9P_TRENAME: 927 free(fcall->trename.name); 928 return; 929 930 case L9P_RREADLINK: 931 free(fcall->rreadlink.target); 932 return; 933 934 case L9P_TXATTRWALK: 935 free(fcall->txattrwalk.name); 936 return; 937 938 case L9P_TXATTRCREATE: 939 free(fcall->txattrcreate.name); 940 return; 941 942 case L9P_TLOCK: 943 free(fcall->tlock.client_id); 944 return; 945 946 case L9P_TGETLOCK: 947 case L9P_RGETLOCK: 948 free(fcall->getlock.client_id); 949 return; 950 951 case L9P_TLINK: 952 free(fcall->tlink.name); 953 return; 954 955 case L9P_TMKDIR: 956 free(fcall->tmkdir.name); 957 return; 958 959 case L9P_TRENAMEAT: 960 free(fcall->trenameat.oldname); 961 free(fcall->trenameat.newname); 962 return; 963 964 case L9P_TUNLINKAT: 965 free(fcall->tunlinkat.name); 966 return; 967 } 968 } 969 970 void 971 l9p_freestat(struct l9p_stat *stat) 972 { 973 free(stat->name); 974 free(stat->extension); 975 free(stat->uid); 976 free(stat->gid); 977 free(stat->muid); 978 } 979 980 uint16_t 981 l9p_sizeof_stat(struct l9p_stat *stat, enum l9p_version version) 982 { 983 uint16_t size = L9P_WORD /* size */ 984 + L9P_WORD /* type */ 985 + L9P_DWORD /* dev */ 986 + QID_SIZE /* qid */ 987 + 3 * L9P_DWORD /* mode, atime, mtime */ 988 + L9P_QWORD /* length */ 989 + STRING_SIZE(stat->name) 990 + STRING_SIZE(stat->uid) 991 + STRING_SIZE(stat->gid) 992 + STRING_SIZE(stat->muid); 993 994 if (version >= L9P_2000U) { 995 size += STRING_SIZE(stat->extension) 996 + 3 * L9P_DWORD; 997 } 998 999 return (size); 1000 } 1001