1 /*- 2 * Copyright (c) 2017 Juniper Networks, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided 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 WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * 25 */ 26 27 /* 28 * 9P Protocol Support Code 29 * This file provides the standard for the FS interactions with the server 30 * interface as it can understand only this protocol. The details of the 31 * protocol can be found here 32 * XXX (link to protocol details page on FreeBSD wiki) 33 */ 34 35 #include <sys/types.h> 36 #include <fs/p9fs/p9_client.h> 37 #include <fs/p9fs/p9_debug.h> 38 #include <fs/p9fs/p9_protocol.h> 39 40 #define P9FS_MAXLEN 255 41 42 static int p9_buf_writef(struct p9_buffer *buf, int proto_version, 43 const char *fmt, ...); 44 static void stat_free(struct p9_wstat *sbuf); 45 46 static void 47 stat_free(struct p9_wstat *stbuf) 48 { 49 50 free(stbuf->name, M_TEMP); 51 free(stbuf->uid, M_TEMP); 52 free(stbuf->gid, M_TEMP); 53 free(stbuf->muid, M_TEMP); 54 free(stbuf->extension, M_TEMP); 55 } 56 57 static size_t 58 buf_read(struct p9_buffer *buf, void *data, size_t size) 59 { 60 size_t len; 61 62 len = min(buf->size - buf->offset, size); 63 64 memcpy(data, &buf->sdata[buf->offset], len); 65 buf->offset += len; 66 67 return (size - len); 68 } 69 70 static size_t 71 buf_write(struct p9_buffer *buf, const void *data, size_t size) 72 { 73 size_t len; 74 75 len = min(buf->capacity - buf->size, size); 76 77 memcpy(&buf->sdata[buf->size], data, len); 78 buf->size += len; 79 80 return (size - len); 81 } 82 83 /* 84 * Main buf_read routine. This copies the data from the buffer into the 85 * respective values based on the data type. 86 * Here 87 * b - int8_t 88 * w - int16_t 89 * d - int32_t 90 * q - int64_t 91 * s - string 92 * u - uid 93 * g - gid 94 * Q - qid 95 * S - stat 96 * A - getattr (9P2000.L) 97 * D - data blob (int32_t size followed by void *, results are not freed) 98 * T - array of strings (int16_t count, followed by strings) 99 * R - array of qids (int16_t count, followed by qids) 100 * ? - return if version is not .u or .l 101 */ 102 static int 103 p9_buf_vreadf(struct p9_buffer *buf, int proto_version, const char *fmt, 104 va_list ap) 105 { 106 const char *ptr; 107 int error; 108 109 error = 0; 110 111 for (ptr = fmt; *ptr; ptr++) { 112 switch (*ptr) { 113 case 'b': 114 { 115 int8_t *val = va_arg(ap, int8_t *); 116 117 if (buf_read(buf, val, sizeof(*val))) 118 error = EFAULT; 119 break; 120 } 121 case 'w': 122 { 123 int16_t *val = va_arg(ap, int16_t *); 124 125 if (buf_read(buf, val, sizeof(*val))) 126 error = EFAULT; 127 break; 128 } 129 case 'd': 130 { 131 int32_t *val = va_arg(ap, int32_t *); 132 133 if (buf_read(buf, val, sizeof(*val))) 134 error = EFAULT; 135 break; 136 } 137 case 'q': 138 { 139 int64_t *val = va_arg(ap, int64_t *); 140 141 if (buf_read(buf, val, sizeof(*val))) 142 error = EFAULT; 143 break; 144 } 145 case 's': 146 { 147 char **sptr_p = va_arg(ap, char **); 148 uint16_t len; 149 char *sptr; 150 151 error = buf_read(buf, &len, sizeof(uint16_t)); 152 if (error) 153 break; 154 155 sptr = malloc(len + 1, M_TEMP, M_NOWAIT | M_ZERO); 156 157 if (buf_read(buf, sptr, len)) { 158 error = EFAULT; 159 free(sptr, M_TEMP); 160 sptr = NULL; 161 } else { 162 (sptr)[len] = 0; 163 *sptr_p = sptr; 164 } 165 break; 166 } 167 case 'u': 168 { 169 uid_t *val = va_arg(ap, uid_t *); 170 171 if (buf_read(buf, val, sizeof(*val))) 172 error = EFAULT; 173 break; 174 175 } 176 case 'g': 177 { 178 gid_t *val = va_arg(ap, gid_t *); 179 180 if (buf_read(buf, val, sizeof(*val))) 181 error = EFAULT; 182 break; 183 184 } 185 case 'Q': 186 { 187 struct p9_qid *qid = va_arg(ap, struct p9_qid *); 188 189 error = p9_buf_readf(buf, proto_version, "bdq", 190 &qid->type, &qid->version, &qid->path); 191 192 break; 193 } 194 case 'S': 195 { 196 struct p9_wstat *stbuf = va_arg(ap, struct p9_wstat *); 197 198 error = p9_buf_readf(buf, proto_version, "wwdQdddqssss?sddd", 199 &stbuf->size, &stbuf->type, &stbuf->dev, &stbuf->qid, 200 &stbuf->mode, &stbuf->atime, &stbuf->mtime, &stbuf->length, 201 &stbuf->name, &stbuf->uid, &stbuf->gid, &stbuf->muid, 202 &stbuf->extension, &stbuf->n_uid, &stbuf->n_gid, &stbuf->n_muid); 203 204 if (error != 0) 205 stat_free(stbuf); 206 break; 207 } 208 case 'A': 209 { 210 struct p9_stat_dotl *stbuf = va_arg(ap, struct p9_stat_dotl *); 211 212 error = p9_buf_readf(buf, proto_version, "qQdugqqqqqqqqqqqqqqq", 213 &stbuf->st_result_mask, &stbuf->qid, &stbuf->st_mode, 214 &stbuf->st_uid,&stbuf->st_gid, &stbuf->st_nlink, 215 &stbuf->st_rdev, &stbuf->st_size, &stbuf->st_blksize, 216 &stbuf->st_blocks, &stbuf->st_atime_sec, 217 &stbuf->st_atime_nsec, &stbuf->st_mtime_sec, 218 &stbuf->st_mtime_nsec, &stbuf->st_ctime_sec, 219 &stbuf->st_ctime_nsec, &stbuf->st_btime_sec, 220 &stbuf->st_btime_nsec, &stbuf->st_gen, 221 &stbuf->st_data_version); 222 223 break; 224 } 225 case 'D': 226 { 227 uint32_t *count = va_arg(ap, uint32_t *); 228 void **data = va_arg(ap, void **); 229 230 error = buf_read(buf, count, sizeof(uint32_t)); 231 if (error == 0) { 232 *count = MIN(*count, buf->size - buf->offset); 233 *data = &buf->sdata[buf->offset]; 234 } 235 break; 236 } 237 case 'T': 238 { 239 uint16_t *nwname_p = va_arg(ap, uint16_t *); 240 char ***wnames_p = va_arg(ap, char ***); 241 uint16_t nwname; 242 char **wnames; 243 int i; 244 245 error = buf_read(buf, nwname_p, sizeof(uint16_t)); 246 if (error != 0) 247 break; 248 249 nwname = *nwname_p; 250 wnames = malloc(sizeof(char *) * nwname, M_TEMP, M_NOWAIT | M_ZERO); 251 252 for (i = 0; i < nwname && (error == 0); i++) 253 error = p9_buf_readf(buf, proto_version, "s", &wnames[i]); 254 255 if (error != 0) { 256 for (i = 0; i < nwname; i++) 257 free((wnames)[i], M_TEMP); 258 free(wnames, M_TEMP); 259 } else 260 *wnames_p = wnames; 261 break; 262 } 263 case 'R': 264 { 265 uint16_t *nwqid_p = va_arg(ap, uint16_t *); 266 struct p9_qid **wqids_p = va_arg(ap, struct p9_qid **); 267 uint16_t nwqid; 268 struct p9_qid *wqids; 269 int i; 270 271 wqids = NULL; 272 error = buf_read(buf, nwqid_p, sizeof(uint16_t)); 273 if (error != 0) 274 break; 275 276 nwqid = *nwqid_p; 277 wqids = malloc(nwqid * sizeof(struct p9_qid), M_TEMP, M_NOWAIT | M_ZERO); 278 if (wqids == NULL) { 279 error = ENOMEM; 280 break; 281 } 282 for (i = 0; i < nwqid && (error == 0); i++) 283 error = p9_buf_readf(buf, proto_version, "Q", &(wqids)[i]); 284 285 if (error != 0) { 286 free(wqids, M_TEMP); 287 } else 288 *wqids_p = wqids; 289 290 break; 291 } 292 case '?': 293 { 294 if ((proto_version != p9_proto_2000u) && (proto_version != p9_proto_2000L)) 295 return (0); 296 break; 297 } 298 default: 299 break; 300 } 301 302 if (error != 0) 303 break; 304 } 305 306 return (error); 307 } 308 309 /* 310 * Main buf_write routine. This copies the data into the buffer from the 311 * respective values based on the data type. 312 * Here 313 * b - int8_t 314 * w - int16_t 315 * d - int32_t 316 * q - int64_t 317 * s - string 318 * u - uid 319 * g - gid 320 * Q - qid 321 * S - stat 322 * D - data blob (int32_t size followed by void *, results are not freed) 323 * T - array of strings (int16_t count, followed by strings) 324 * W - string of a specific length 325 * R - array of qids (int16_t count, followed by qids) 326 * A - setattr (9P2000.L) 327 * ? - return if version is not .u or .l 328 */ 329 330 int 331 p9_buf_vwritef(struct p9_buffer *buf, int proto_version, const char *fmt, 332 va_list ap) 333 { 334 const char *ptr; 335 int error; 336 337 error = 0; 338 339 for (ptr = fmt; *ptr; ptr++) { 340 switch (*ptr) { 341 case 'b': 342 { 343 int8_t val = va_arg(ap, int); 344 345 if (buf_write(buf, &val, sizeof(val))) 346 error = EFAULT; 347 break; 348 } 349 case 'w': 350 { 351 int16_t val = va_arg(ap, int); 352 353 if (buf_write(buf, &val, sizeof(val))) 354 error = EFAULT; 355 break; 356 } 357 case 'd': 358 { 359 int32_t val = va_arg(ap, int32_t); 360 361 if (buf_write(buf, &val, sizeof(val))) 362 error = EFAULT; 363 break; 364 } 365 case 'q': 366 { 367 int64_t val = va_arg(ap, int64_t); 368 369 if (buf_write(buf, &val, sizeof(val))) 370 error = EFAULT; 371 372 break; 373 } 374 case 's': 375 { 376 const char *sptr = va_arg(ap, const char *); 377 uint16_t len = 0; 378 379 if (sptr) 380 len = MIN(strlen(sptr), P9FS_MAXLEN); 381 382 error = buf_write(buf, &len, sizeof(uint16_t)); 383 if (error == 0 && buf_write(buf, sptr, len)) 384 error = EFAULT; 385 break; 386 } 387 case 'u': 388 { 389 uid_t val = va_arg(ap, uid_t); 390 391 if (buf_write(buf, &val, sizeof(val))) 392 error = EFAULT; 393 break; 394 395 } 396 case 'g': 397 { 398 gid_t val = va_arg(ap, gid_t); 399 400 if (buf_write(buf, &val, sizeof(val))) 401 error = EFAULT; 402 break; 403 404 } 405 case 'Q': 406 { 407 const struct p9_qid *qid = va_arg(ap, const struct p9_qid *); 408 409 error = p9_buf_writef(buf, proto_version, "bdq", 410 qid->type, qid->version, qid->path); 411 break; 412 } 413 case 'S': 414 { 415 struct p9_wstat *stbuf = va_arg(ap, struct p9_wstat *); 416 417 error = p9_buf_writef(buf, proto_version, 418 "wwdQdddqssss?sddd", stbuf->size, stbuf->type, stbuf->dev, &stbuf->qid, 419 stbuf->mode, stbuf->atime, stbuf->mtime, stbuf->length, stbuf->name, 420 stbuf->uid, stbuf->gid, stbuf->muid, stbuf->extension, stbuf->n_uid, 421 stbuf->n_gid, stbuf->n_muid); 422 423 if (error != 0) 424 stat_free(stbuf); 425 426 break; 427 } 428 case 'D': 429 { 430 uint32_t count = va_arg(ap, uint32_t); 431 void *data = va_arg(ap, void *); 432 433 error = buf_write(buf, &count, sizeof(uint32_t)); 434 if ((error == 0) && buf_write(buf, data, count)) 435 error = EFAULT; 436 437 break; 438 } 439 case 'T': 440 { 441 char **wnames = va_arg(ap, char **); 442 uint16_t nwnames = va_arg(ap, int); 443 444 error = buf_write(buf, &nwnames, sizeof(uint16_t)); 445 if (error == 0) { 446 int i = 0; 447 for (i = 0; i < nwnames; i++) { 448 error = p9_buf_writef(buf, proto_version, "s", wnames[i]); 449 if (error != 0) 450 break; 451 } 452 } 453 break; 454 } 455 case 'W': 456 { 457 const char *sptr = va_arg(ap, const char*); 458 uint16_t len = va_arg(ap, int); 459 460 error = buf_write(buf, &len, sizeof(uint16_t)); 461 if (error == 0 && buf_write(buf, sptr, len)) 462 error = EFAULT; 463 break; 464 465 } 466 case 'R': 467 { 468 uint16_t nwqid = va_arg(ap, int); 469 struct p9_qid *wqids = va_arg(ap, struct p9_qid *); 470 int i; 471 472 error = buf_write(buf, &nwqid, sizeof(uint16_t)); 473 if (error == 0) { 474 475 for (i = 0; i < nwqid; i++) { 476 error = p9_buf_writef(buf, proto_version, "Q", &wqids[i]); 477 if (error != 0) 478 break; 479 } 480 } 481 break; 482 } 483 case 'A': 484 { 485 struct p9_iattr_dotl *p9attr = va_arg(ap, struct p9_iattr_dotl *); 486 487 error = p9_buf_writef(buf, proto_version, "ddugqqqqq", 488 p9attr->valid, p9attr->mode, p9attr->uid, 489 p9attr->gid, p9attr->size, p9attr->atime_sec, 490 p9attr->atime_nsec, p9attr->mtime_sec, 491 p9attr->mtime_nsec); 492 493 break; 494 } 495 case '?': 496 { 497 if ((proto_version != p9_proto_2000u) && (proto_version != p9_proto_2000L)) 498 return (0); 499 break; 500 } 501 default: 502 break; 503 } 504 505 if (error != 0) 506 break; 507 } 508 509 return (error); 510 } 511 512 /* Variadic form of buf_read */ 513 int 514 p9_buf_readf(struct p9_buffer *buf, int proto_version, const char *fmt, ...) 515 { 516 va_list ap; 517 int ret; 518 519 va_start(ap, fmt); 520 ret = p9_buf_vreadf(buf, proto_version, fmt, ap); 521 va_end(ap); 522 523 return (ret); 524 } 525 526 /* Variadic form of buf_write */ 527 static int 528 p9_buf_writef(struct p9_buffer *buf, int proto_version, const char *fmt, ...) 529 { 530 va_list ap; 531 int ret; 532 533 va_start(ap, fmt); 534 ret = p9_buf_vwritef(buf, proto_version, fmt, ap); 535 va_end(ap); 536 537 return (ret); 538 } 539 540 /* File stats read routine for P9 to get attributes of files */ 541 int 542 p9stat_read(struct p9_client *clnt, char *buf, size_t len, struct p9_wstat *st) 543 { 544 struct p9_buffer msg_buf; 545 int ret; 546 547 msg_buf.size = len; 548 msg_buf.capacity = len; 549 msg_buf.sdata = buf; 550 msg_buf.offset = 0; 551 552 ret = p9_buf_readf(&msg_buf, clnt->proto_version, "S", st); 553 if (ret) { 554 P9_DEBUG(ERROR, "%s: failed: %d\n", __func__, ret); 555 } 556 557 return (ret); 558 } 559 560 /* 561 * P9_header preparation routine. All p9 buffers have to have this header(QEMU_HEADER) at the 562 * front of the buffer. 563 */ 564 int 565 p9_buf_prepare(struct p9_buffer *buf, int8_t type) 566 { 567 buf->id = type; 568 return (p9_buf_writef(buf, 0, "dbw", 0, type, buf->tag)); 569 } 570 571 /* 572 * Final write to the buffer, this is the total size of the buffer. Since the buffer length can 573 * vary with request, this is computed at the end just before sending the request to the driver 574 */ 575 int 576 p9_buf_finalize(struct p9_client *clnt, struct p9_buffer *buf) 577 { 578 int size; 579 int error; 580 581 size = buf->size; 582 buf->size = 0; 583 error = p9_buf_writef(buf, 0, "d", size); 584 buf->size = size; 585 586 P9_DEBUG(LPROTO, "%s: size=%d type: %d tag: %d\n", 587 __func__, buf->size, buf->id, buf->tag); 588 589 return (error); 590 } 591 592 /* Reset values of the buffer */ 593 void 594 p9_buf_reset(struct p9_buffer *buf) 595 { 596 597 buf->offset = 0; 598 buf->size = 0; 599 } 600 601 /* 602 * Directory entry read with the buf we have. Call this once we have the buf to parse. 603 * This buf, obtained from the server, is parsed to make dirent in readdir. 604 */ 605 int 606 p9_dirent_read(struct p9_client *clnt, char *buf, int start, int len, 607 struct p9_dirent *dent) 608 { 609 struct p9_buffer msg_buf; 610 int ret; 611 char *nameptr; 612 uint16_t sle; 613 614 msg_buf.size = len; 615 msg_buf.capacity = len; 616 msg_buf.sdata = buf; 617 msg_buf.offset = start; 618 619 ret = p9_buf_readf(&msg_buf, clnt->proto_version, "Qqbs", &dent->qid, 620 &dent->d_off, &dent->d_type, &nameptr); 621 if (ret) { 622 P9_DEBUG(ERROR, "%s: failed: %d\n", __func__, ret); 623 goto out; 624 } 625 626 sle = strlen(nameptr); 627 strncpy(dent->d_name, nameptr, sle); 628 dent->len = sle; 629 free(nameptr, M_TEMP); 630 out: 631 return (msg_buf.offset); 632 } 633