protocol.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654
  1. /*
  2. * net/9p/protocol.c
  3. *
  4. * 9P Protocol Support Code
  5. *
  6. * Copyright (C) 2008 by Eric Van Hensbergen <ericvh@gmail.com>
  7. *
  8. * Base on code from Anthony Liguori <aliguori@us.ibm.com>
  9. * Copyright (C) 2008 by IBM, Corp.
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License version 2
  13. * as published by the Free Software Foundation.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to:
  22. * Free Software Foundation
  23. * 51 Franklin Street, Fifth Floor
  24. * Boston, MA 02111-1301 USA
  25. *
  26. */
  27. #include <linux/module.h>
  28. #include <linux/errno.h>
  29. #include <linux/uaccess.h>
  30. #include <linux/slab.h>
  31. #include <linux/sched.h>
  32. #include <linux/types.h>
  33. #include <net/9p/9p.h>
  34. #include <net/9p/client.h>
  35. #include "protocol.h"
  36. #ifndef MIN
  37. #define MIN(a, b) (((a) < (b)) ? (a) : (b))
  38. #endif
  39. #ifndef MAX
  40. #define MAX(a, b) (((a) > (b)) ? (a) : (b))
  41. #endif
  42. #ifndef offset_of
  43. #define offset_of(type, memb) \
  44. ((unsigned long)(&((type *)0)->memb))
  45. #endif
  46. #ifndef container_of
  47. #define container_of(obj, type, memb) \
  48. ((type *)(((char *)obj) - offset_of(type, memb)))
  49. #endif
  50. static int
  51. p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...);
  52. #ifdef CONFIG_NET_9P_DEBUG
  53. void
  54. p9pdu_dump(int way, struct p9_fcall *pdu)
  55. {
  56. int i, n;
  57. u8 *data = pdu->sdata;
  58. int datalen = pdu->size;
  59. char buf[255];
  60. int buflen = 255;
  61. i = n = 0;
  62. if (datalen > (buflen-16))
  63. datalen = buflen-16;
  64. while (i < datalen) {
  65. n += scnprintf(buf + n, buflen - n, "%02x ", data[i]);
  66. if (i%4 == 3)
  67. n += scnprintf(buf + n, buflen - n, " ");
  68. if (i%32 == 31)
  69. n += scnprintf(buf + n, buflen - n, "\n");
  70. i++;
  71. }
  72. n += scnprintf(buf + n, buflen - n, "\n");
  73. if (way)
  74. P9_DPRINTK(P9_DEBUG_PKT, "[[[(%d) %s\n", datalen, buf);
  75. else
  76. P9_DPRINTK(P9_DEBUG_PKT, "]]](%d) %s\n", datalen, buf);
  77. }
  78. #else
  79. void
  80. p9pdu_dump(int way, struct p9_fcall *pdu)
  81. {
  82. }
  83. #endif
  84. EXPORT_SYMBOL(p9pdu_dump);
  85. void p9stat_free(struct p9_wstat *stbuf)
  86. {
  87. kfree(stbuf->name);
  88. kfree(stbuf->uid);
  89. kfree(stbuf->gid);
  90. kfree(stbuf->muid);
  91. kfree(stbuf->extension);
  92. }
  93. EXPORT_SYMBOL(p9stat_free);
  94. static size_t pdu_read(struct p9_fcall *pdu, void *data, size_t size)
  95. {
  96. size_t len = MIN(pdu->size - pdu->offset, size);
  97. memcpy(data, &pdu->sdata[pdu->offset], len);
  98. pdu->offset += len;
  99. return size - len;
  100. }
  101. static size_t pdu_write(struct p9_fcall *pdu, const void *data, size_t size)
  102. {
  103. size_t len = MIN(pdu->capacity - pdu->size, size);
  104. memcpy(&pdu->sdata[pdu->size], data, len);
  105. pdu->size += len;
  106. return size - len;
  107. }
  108. static size_t
  109. pdu_write_u(struct p9_fcall *pdu, const char __user *udata, size_t size)
  110. {
  111. size_t len = MIN(pdu->capacity - pdu->size, size);
  112. int err = copy_from_user(&pdu->sdata[pdu->size], udata, len);
  113. if (err)
  114. printk(KERN_WARNING "pdu_write_u returning: %d\n", err);
  115. pdu->size += len;
  116. return size - len;
  117. }
  118. /*
  119. b - int8_t
  120. w - int16_t
  121. d - int32_t
  122. q - int64_t
  123. s - string
  124. S - stat
  125. Q - qid
  126. D - data blob (int32_t size followed by void *, results are not freed)
  127. T - array of strings (int16_t count, followed by strings)
  128. R - array of qids (int16_t count, followed by qids)
  129. A - stat for 9p2000.L (p9_stat_dotl)
  130. ? - if optional = 1, continue parsing
  131. */
  132. static int
  133. p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,
  134. va_list ap)
  135. {
  136. const char *ptr;
  137. int errcode = 0;
  138. for (ptr = fmt; *ptr; ptr++) {
  139. switch (*ptr) {
  140. case 'b':{
  141. int8_t *val = va_arg(ap, int8_t *);
  142. if (pdu_read(pdu, val, sizeof(*val))) {
  143. errcode = -EFAULT;
  144. break;
  145. }
  146. }
  147. break;
  148. case 'w':{
  149. int16_t *val = va_arg(ap, int16_t *);
  150. __le16 le_val;
  151. if (pdu_read(pdu, &le_val, sizeof(le_val))) {
  152. errcode = -EFAULT;
  153. break;
  154. }
  155. *val = le16_to_cpu(le_val);
  156. }
  157. break;
  158. case 'd':{
  159. int32_t *val = va_arg(ap, int32_t *);
  160. __le32 le_val;
  161. if (pdu_read(pdu, &le_val, sizeof(le_val))) {
  162. errcode = -EFAULT;
  163. break;
  164. }
  165. *val = le32_to_cpu(le_val);
  166. }
  167. break;
  168. case 'q':{
  169. int64_t *val = va_arg(ap, int64_t *);
  170. __le64 le_val;
  171. if (pdu_read(pdu, &le_val, sizeof(le_val))) {
  172. errcode = -EFAULT;
  173. break;
  174. }
  175. *val = le64_to_cpu(le_val);
  176. }
  177. break;
  178. case 's':{
  179. char **sptr = va_arg(ap, char **);
  180. int16_t len;
  181. int size;
  182. errcode = p9pdu_readf(pdu, proto_version,
  183. "w", &len);
  184. if (errcode)
  185. break;
  186. size = MAX(len, 0);
  187. *sptr = kmalloc(size + 1, GFP_KERNEL);
  188. if (*sptr == NULL) {
  189. errcode = -EFAULT;
  190. break;
  191. }
  192. if (pdu_read(pdu, *sptr, size)) {
  193. errcode = -EFAULT;
  194. kfree(*sptr);
  195. *sptr = NULL;
  196. } else
  197. (*sptr)[size] = 0;
  198. }
  199. break;
  200. case 'Q':{
  201. struct p9_qid *qid =
  202. va_arg(ap, struct p9_qid *);
  203. errcode = p9pdu_readf(pdu, proto_version, "bdq",
  204. &qid->type, &qid->version,
  205. &qid->path);
  206. }
  207. break;
  208. case 'S':{
  209. struct p9_wstat *stbuf =
  210. va_arg(ap, struct p9_wstat *);
  211. memset(stbuf, 0, sizeof(struct p9_wstat));
  212. stbuf->n_uid = stbuf->n_gid = stbuf->n_muid =
  213. -1;
  214. errcode =
  215. p9pdu_readf(pdu, proto_version,
  216. "wwdQdddqssss?sddd",
  217. &stbuf->size, &stbuf->type,
  218. &stbuf->dev, &stbuf->qid,
  219. &stbuf->mode, &stbuf->atime,
  220. &stbuf->mtime, &stbuf->length,
  221. &stbuf->name, &stbuf->uid,
  222. &stbuf->gid, &stbuf->muid,
  223. &stbuf->extension,
  224. &stbuf->n_uid, &stbuf->n_gid,
  225. &stbuf->n_muid);
  226. if (errcode)
  227. p9stat_free(stbuf);
  228. }
  229. break;
  230. case 'D':{
  231. int32_t *count = va_arg(ap, int32_t *);
  232. void **data = va_arg(ap, void **);
  233. errcode =
  234. p9pdu_readf(pdu, proto_version, "d", count);
  235. if (!errcode) {
  236. *count =
  237. MIN(*count,
  238. pdu->size - pdu->offset);
  239. *data = &pdu->sdata[pdu->offset];
  240. }
  241. }
  242. break;
  243. case 'T':{
  244. int16_t *nwname = va_arg(ap, int16_t *);
  245. char ***wnames = va_arg(ap, char ***);
  246. errcode = p9pdu_readf(pdu, proto_version,
  247. "w", nwname);
  248. if (!errcode) {
  249. *wnames =
  250. kmalloc(sizeof(char *) * *nwname,
  251. GFP_KERNEL);
  252. if (!*wnames)
  253. errcode = -ENOMEM;
  254. }
  255. if (!errcode) {
  256. int i;
  257. for (i = 0; i < *nwname; i++) {
  258. errcode =
  259. p9pdu_readf(pdu,
  260. proto_version,
  261. "s",
  262. &(*wnames)[i]);
  263. if (errcode)
  264. break;
  265. }
  266. }
  267. if (errcode) {
  268. if (*wnames) {
  269. int i;
  270. for (i = 0; i < *nwname; i++)
  271. kfree((*wnames)[i]);
  272. }
  273. kfree(*wnames);
  274. *wnames = NULL;
  275. }
  276. }
  277. break;
  278. case 'R':{
  279. int16_t *nwqid = va_arg(ap, int16_t *);
  280. struct p9_qid **wqids =
  281. va_arg(ap, struct p9_qid **);
  282. *wqids = NULL;
  283. errcode =
  284. p9pdu_readf(pdu, proto_version, "w", nwqid);
  285. if (!errcode) {
  286. *wqids =
  287. kmalloc(*nwqid *
  288. sizeof(struct p9_qid),
  289. GFP_KERNEL);
  290. if (*wqids == NULL)
  291. errcode = -ENOMEM;
  292. }
  293. if (!errcode) {
  294. int i;
  295. for (i = 0; i < *nwqid; i++) {
  296. errcode =
  297. p9pdu_readf(pdu,
  298. proto_version,
  299. "Q",
  300. &(*wqids)[i]);
  301. if (errcode)
  302. break;
  303. }
  304. }
  305. if (errcode) {
  306. kfree(*wqids);
  307. *wqids = NULL;
  308. }
  309. }
  310. break;
  311. case 'A': {
  312. struct p9_stat_dotl *stbuf =
  313. va_arg(ap, struct p9_stat_dotl *);
  314. memset(stbuf, 0, sizeof(struct p9_stat_dotl));
  315. errcode =
  316. p9pdu_readf(pdu, proto_version,
  317. "qQdddqqqqqqqqqqqqqqq",
  318. &stbuf->st_result_mask,
  319. &stbuf->qid,
  320. &stbuf->st_mode,
  321. &stbuf->st_uid, &stbuf->st_gid,
  322. &stbuf->st_nlink,
  323. &stbuf->st_rdev, &stbuf->st_size,
  324. &stbuf->st_blksize, &stbuf->st_blocks,
  325. &stbuf->st_atime_sec,
  326. &stbuf->st_atime_nsec,
  327. &stbuf->st_mtime_sec,
  328. &stbuf->st_mtime_nsec,
  329. &stbuf->st_ctime_sec,
  330. &stbuf->st_ctime_nsec,
  331. &stbuf->st_btime_sec,
  332. &stbuf->st_btime_nsec,
  333. &stbuf->st_gen,
  334. &stbuf->st_data_version);
  335. }
  336. break;
  337. case '?':
  338. if ((proto_version != p9_proto_2000u) &&
  339. (proto_version != p9_proto_2000L))
  340. return 0;
  341. break;
  342. default:
  343. BUG();
  344. break;
  345. }
  346. if (errcode)
  347. break;
  348. }
  349. return errcode;
  350. }
  351. int
  352. p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt,
  353. va_list ap)
  354. {
  355. const char *ptr;
  356. int errcode = 0;
  357. for (ptr = fmt; *ptr; ptr++) {
  358. switch (*ptr) {
  359. case 'b':{
  360. int8_t val = va_arg(ap, int);
  361. if (pdu_write(pdu, &val, sizeof(val)))
  362. errcode = -EFAULT;
  363. }
  364. break;
  365. case 'w':{
  366. __le16 val = cpu_to_le16(va_arg(ap, int));
  367. if (pdu_write(pdu, &val, sizeof(val)))
  368. errcode = -EFAULT;
  369. }
  370. break;
  371. case 'd':{
  372. __le32 val = cpu_to_le32(va_arg(ap, int32_t));
  373. if (pdu_write(pdu, &val, sizeof(val)))
  374. errcode = -EFAULT;
  375. }
  376. break;
  377. case 'q':{
  378. __le64 val = cpu_to_le64(va_arg(ap, int64_t));
  379. if (pdu_write(pdu, &val, sizeof(val)))
  380. errcode = -EFAULT;
  381. }
  382. break;
  383. case 's':{
  384. const char *sptr = va_arg(ap, const char *);
  385. int16_t len = 0;
  386. if (sptr)
  387. len = MIN(strlen(sptr), USHRT_MAX);
  388. errcode = p9pdu_writef(pdu, proto_version,
  389. "w", len);
  390. if (!errcode && pdu_write(pdu, sptr, len))
  391. errcode = -EFAULT;
  392. }
  393. break;
  394. case 'Q':{
  395. const struct p9_qid *qid =
  396. va_arg(ap, const struct p9_qid *);
  397. errcode =
  398. p9pdu_writef(pdu, proto_version, "bdq",
  399. qid->type, qid->version,
  400. qid->path);
  401. } break;
  402. case 'S':{
  403. const struct p9_wstat *stbuf =
  404. va_arg(ap, const struct p9_wstat *);
  405. errcode =
  406. p9pdu_writef(pdu, proto_version,
  407. "wwdQdddqssss?sddd",
  408. stbuf->size, stbuf->type,
  409. stbuf->dev, &stbuf->qid,
  410. stbuf->mode, stbuf->atime,
  411. stbuf->mtime, stbuf->length,
  412. stbuf->name, stbuf->uid,
  413. stbuf->gid, stbuf->muid,
  414. stbuf->extension, stbuf->n_uid,
  415. stbuf->n_gid, stbuf->n_muid);
  416. } break;
  417. case 'D':{
  418. int32_t count = va_arg(ap, int32_t);
  419. const void *data = va_arg(ap, const void *);
  420. errcode = p9pdu_writef(pdu, proto_version, "d",
  421. count);
  422. if (!errcode && pdu_write(pdu, data, count))
  423. errcode = -EFAULT;
  424. }
  425. break;
  426. case 'U':{
  427. int32_t count = va_arg(ap, int32_t);
  428. const char __user *udata =
  429. va_arg(ap, const void __user *);
  430. errcode = p9pdu_writef(pdu, proto_version, "d",
  431. count);
  432. if (!errcode && pdu_write_u(pdu, udata, count))
  433. errcode = -EFAULT;
  434. }
  435. break;
  436. case 'T':{
  437. int16_t nwname = va_arg(ap, int);
  438. const char **wnames = va_arg(ap, const char **);
  439. errcode = p9pdu_writef(pdu, proto_version, "w",
  440. nwname);
  441. if (!errcode) {
  442. int i;
  443. for (i = 0; i < nwname; i++) {
  444. errcode =
  445. p9pdu_writef(pdu,
  446. proto_version,
  447. "s",
  448. wnames[i]);
  449. if (errcode)
  450. break;
  451. }
  452. }
  453. }
  454. break;
  455. case 'R':{
  456. int16_t nwqid = va_arg(ap, int);
  457. struct p9_qid *wqids =
  458. va_arg(ap, struct p9_qid *);
  459. errcode = p9pdu_writef(pdu, proto_version, "w",
  460. nwqid);
  461. if (!errcode) {
  462. int i;
  463. for (i = 0; i < nwqid; i++) {
  464. errcode =
  465. p9pdu_writef(pdu,
  466. proto_version,
  467. "Q",
  468. &wqids[i]);
  469. if (errcode)
  470. break;
  471. }
  472. }
  473. }
  474. break;
  475. case 'I':{
  476. struct p9_iattr_dotl *p9attr = va_arg(ap,
  477. struct p9_iattr_dotl *);
  478. errcode = p9pdu_writef(pdu, proto_version,
  479. "ddddqqqqq",
  480. p9attr->valid,
  481. p9attr->mode,
  482. p9attr->uid,
  483. p9attr->gid,
  484. p9attr->size,
  485. p9attr->atime_sec,
  486. p9attr->atime_nsec,
  487. p9attr->mtime_sec,
  488. p9attr->mtime_nsec);
  489. }
  490. break;
  491. case '?':
  492. if ((proto_version != p9_proto_2000u) &&
  493. (proto_version != p9_proto_2000L))
  494. return 0;
  495. break;
  496. default:
  497. BUG();
  498. break;
  499. }
  500. if (errcode)
  501. break;
  502. }
  503. return errcode;
  504. }
  505. int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...)
  506. {
  507. va_list ap;
  508. int ret;
  509. va_start(ap, fmt);
  510. ret = p9pdu_vreadf(pdu, proto_version, fmt, ap);
  511. va_end(ap);
  512. return ret;
  513. }
  514. static int
  515. p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...)
  516. {
  517. va_list ap;
  518. int ret;
  519. va_start(ap, fmt);
  520. ret = p9pdu_vwritef(pdu, proto_version, fmt, ap);
  521. va_end(ap);
  522. return ret;
  523. }
  524. int p9stat_read(char *buf, int len, struct p9_wstat *st, int proto_version)
  525. {
  526. struct p9_fcall fake_pdu;
  527. int ret;
  528. fake_pdu.size = len;
  529. fake_pdu.capacity = len;
  530. fake_pdu.sdata = buf;
  531. fake_pdu.offset = 0;
  532. ret = p9pdu_readf(&fake_pdu, proto_version, "S", st);
  533. if (ret) {
  534. P9_DPRINTK(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret);
  535. p9pdu_dump(1, &fake_pdu);
  536. }
  537. return ret;
  538. }
  539. EXPORT_SYMBOL(p9stat_read);
  540. int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type)
  541. {
  542. return p9pdu_writef(pdu, 0, "dbw", 0, type, tag);
  543. }
  544. int p9pdu_finalize(struct p9_fcall *pdu)
  545. {
  546. int size = pdu->size;
  547. int err;
  548. pdu->size = 0;
  549. err = p9pdu_writef(pdu, 0, "d", size);
  550. pdu->size = size;
  551. #ifdef CONFIG_NET_9P_DEBUG
  552. if ((p9_debug_level & P9_DEBUG_PKT) == P9_DEBUG_PKT)
  553. p9pdu_dump(0, pdu);
  554. #endif
  555. P9_DPRINTK(P9_DEBUG_9P, ">>> size=%d type: %d tag: %d\n", pdu->size,
  556. pdu->id, pdu->tag);
  557. return err;
  558. }
  559. void p9pdu_reset(struct p9_fcall *pdu)
  560. {
  561. pdu->offset = 0;
  562. pdu->size = 0;
  563. }
  564. int p9dirent_read(char *buf, int len, struct p9_dirent *dirent,
  565. int proto_version)
  566. {
  567. struct p9_fcall fake_pdu;
  568. int ret;
  569. char *nameptr;
  570. fake_pdu.size = len;
  571. fake_pdu.capacity = len;
  572. fake_pdu.sdata = buf;
  573. fake_pdu.offset = 0;
  574. ret = p9pdu_readf(&fake_pdu, proto_version, "Qqbs", &dirent->qid,
  575. &dirent->d_off, &dirent->d_type, &nameptr);
  576. if (ret) {
  577. P9_DPRINTK(P9_DEBUG_9P, "<<< p9dirent_read failed: %d\n", ret);
  578. p9pdu_dump(1, &fake_pdu);
  579. goto out;
  580. }
  581. strcpy(dirent->d_name, nameptr);
  582. out:
  583. return fake_pdu.offset;
  584. }
  585. EXPORT_SYMBOL(p9dirent_read);