smb_rq.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765
  1. /*-
  2. * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  3. *
  4. * Copyright (c) 2000-2001 Boris Popov
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  17. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  20. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  22. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26. * SUCH DAMAGE.
  27. */
  28. #include <sys/cdefs.h>
  29. __FBSDID("$FreeBSD$");
  30. #include <sys/param.h>
  31. #include <sys/systm.h>
  32. #include <sys/endian.h>
  33. #include <sys/kernel.h>
  34. #include <sys/malloc.h>
  35. #include <sys/module.h>
  36. #include <sys/proc.h>
  37. #include <sys/lock.h>
  38. #include <sys/sysctl.h>
  39. #include <sys/socket.h>
  40. #include <sys/socketvar.h>
  41. #include <sys/mbuf.h>
  42. #include <netsmb/smb.h>
  43. #include <netsmb/smb_conn.h>
  44. #include <netsmb/smb_rq.h>
  45. #include <netsmb/smb_subr.h>
  46. #include <netsmb/smb_tran.h>
  47. static MALLOC_DEFINE(M_SMBRQ, "SMBRQ", "SMB request");
  48. MODULE_DEPEND(netsmb, libmchain, 1, 1, 1);
  49. static int smb_rq_reply(struct smb_rq *rqp);
  50. static int smb_rq_enqueue(struct smb_rq *rqp);
  51. static int smb_rq_getenv(struct smb_connobj *layer,
  52. struct smb_vc **vcpp, struct smb_share **sspp);
  53. static int smb_rq_new(struct smb_rq *rqp, u_char cmd);
  54. static int smb_t2_reply(struct smb_t2rq *t2p);
  55. int
  56. smb_rq_alloc(struct smb_connobj *layer, u_char cmd, struct smb_cred *scred,
  57. struct smb_rq **rqpp)
  58. {
  59. struct smb_rq *rqp;
  60. int error;
  61. rqp = malloc(sizeof(*rqp), M_SMBRQ, M_WAITOK);
  62. if (rqp == NULL)
  63. return ENOMEM;
  64. error = smb_rq_init(rqp, layer, cmd, scred);
  65. rqp->sr_flags |= SMBR_ALLOCED;
  66. if (error) {
  67. smb_rq_done(rqp);
  68. return error;
  69. }
  70. *rqpp = rqp;
  71. return 0;
  72. }
  73. static char tzero[12];
  74. int
  75. smb_rq_init(struct smb_rq *rqp, struct smb_connobj *layer, u_char cmd,
  76. struct smb_cred *scred)
  77. {
  78. int error;
  79. bzero(rqp, sizeof(*rqp));
  80. smb_sl_init(&rqp->sr_slock, "srslock");
  81. error = smb_rq_getenv(layer, &rqp->sr_vc, &rqp->sr_share);
  82. if (error)
  83. return error;
  84. error = smb_vc_access(rqp->sr_vc, scred, SMBM_EXEC);
  85. if (error)
  86. return error;
  87. if (rqp->sr_share) {
  88. error = smb_share_access(rqp->sr_share, scred, SMBM_EXEC);
  89. if (error)
  90. return error;
  91. }
  92. rqp->sr_cred = scred;
  93. rqp->sr_mid = smb_vc_nextmid(rqp->sr_vc);
  94. return smb_rq_new(rqp, cmd);
  95. }
  96. static int
  97. smb_rq_new(struct smb_rq *rqp, u_char cmd)
  98. {
  99. struct smb_vc *vcp = rqp->sr_vc;
  100. struct mbchain *mbp = &rqp->sr_rq;
  101. int error;
  102. u_int16_t flags2;
  103. rqp->sr_sendcnt = 0;
  104. mb_done(mbp);
  105. md_done(&rqp->sr_rp);
  106. error = mb_init(mbp);
  107. if (error)
  108. return error;
  109. mb_put_mem(mbp, SMB_SIGNATURE, SMB_SIGLEN, MB_MSYSTEM);
  110. mb_put_uint8(mbp, cmd);
  111. mb_put_uint32le(mbp, 0); /* DosError */
  112. mb_put_uint8(mbp, vcp->vc_hflags);
  113. flags2 = vcp->vc_hflags2;
  114. if (cmd == SMB_COM_TRANSACTION || cmd == SMB_COM_TRANSACTION_SECONDARY)
  115. flags2 &= ~SMB_FLAGS2_UNICODE;
  116. if (cmd == SMB_COM_NEGOTIATE)
  117. flags2 &= ~SMB_FLAGS2_SECURITY_SIGNATURE;
  118. mb_put_uint16le(mbp, flags2);
  119. if ((flags2 & SMB_FLAGS2_SECURITY_SIGNATURE) == 0) {
  120. mb_put_mem(mbp, tzero, 12, MB_MSYSTEM);
  121. rqp->sr_rqsig = NULL;
  122. } else {
  123. mb_put_uint16le(mbp, 0 /*scred->sc_p->p_pid >> 16*/);
  124. rqp->sr_rqsig = (u_int8_t *)mb_reserve(mbp, 8);
  125. mb_put_uint16le(mbp, 0);
  126. }
  127. rqp->sr_rqtid = mb_reserve(mbp, sizeof(u_int16_t));
  128. mb_put_uint16le(mbp, 1 /*scred->sc_p->p_pid & 0xffff*/);
  129. rqp->sr_rquid = mb_reserve(mbp, sizeof(u_int16_t));
  130. mb_put_uint16le(mbp, rqp->sr_mid);
  131. return 0;
  132. }
  133. void
  134. smb_rq_done(struct smb_rq *rqp)
  135. {
  136. mb_done(&rqp->sr_rq);
  137. md_done(&rqp->sr_rp);
  138. smb_sl_destroy(&rqp->sr_slock);
  139. if (rqp->sr_flags & SMBR_ALLOCED)
  140. free(rqp, M_SMBRQ);
  141. }
  142. /*
  143. * Simple request-reply exchange
  144. */
  145. int
  146. smb_rq_simple(struct smb_rq *rqp)
  147. {
  148. struct smb_vc *vcp = rqp->sr_vc;
  149. int error = EINVAL, i;
  150. for (i = 0; i < SMB_MAXRCN; i++) {
  151. rqp->sr_flags &= ~SMBR_RESTART;
  152. rqp->sr_timo = vcp->vc_timo;
  153. rqp->sr_state = SMBRQ_NOTSENT;
  154. error = smb_rq_enqueue(rqp);
  155. if (error)
  156. return error;
  157. error = smb_rq_reply(rqp);
  158. if (error == 0)
  159. break;
  160. if ((rqp->sr_flags & (SMBR_RESTART | SMBR_NORESTART)) != SMBR_RESTART)
  161. break;
  162. }
  163. return error;
  164. }
  165. static int
  166. smb_rq_enqueue(struct smb_rq *rqp)
  167. {
  168. struct smb_share *ssp = rqp->sr_share;
  169. int error;
  170. if (ssp == NULL || rqp->sr_cred == &rqp->sr_vc->vc_iod->iod_scred) {
  171. return smb_iod_addrq(rqp);
  172. }
  173. for (;;) {
  174. SMBS_ST_LOCK(ssp);
  175. if (ssp->ss_flags & SMBS_RECONNECTING) {
  176. msleep(&ssp->ss_vcgenid, SMBS_ST_LOCKPTR(ssp),
  177. PWAIT | PDROP, "90trcn", hz);
  178. if (smb_td_intr(rqp->sr_cred->scr_td))
  179. return EINTR;
  180. continue;
  181. }
  182. if (smb_share_valid(ssp) || (ssp->ss_flags & SMBS_CONNECTED) == 0) {
  183. SMBS_ST_UNLOCK(ssp);
  184. } else {
  185. SMBS_ST_UNLOCK(ssp);
  186. error = smb_iod_request(rqp->sr_vc->vc_iod,
  187. SMBIOD_EV_TREECONNECT | SMBIOD_EV_SYNC, ssp);
  188. if (error)
  189. return error;
  190. }
  191. error = smb_iod_addrq(rqp);
  192. if (error != EXDEV)
  193. break;
  194. }
  195. return error;
  196. }
  197. void
  198. smb_rq_wstart(struct smb_rq *rqp)
  199. {
  200. rqp->sr_wcount = mb_reserve(&rqp->sr_rq, sizeof(u_int8_t));
  201. rqp->sr_rq.mb_count = 0;
  202. }
  203. void
  204. smb_rq_wend(struct smb_rq *rqp)
  205. {
  206. if (rqp->sr_wcount == NULL) {
  207. SMBERROR("no wcount\n"); /* actually panic */
  208. return;
  209. }
  210. if (rqp->sr_rq.mb_count & 1)
  211. SMBERROR("odd word count\n");
  212. *rqp->sr_wcount = rqp->sr_rq.mb_count / 2;
  213. }
  214. void
  215. smb_rq_bstart(struct smb_rq *rqp)
  216. {
  217. rqp->sr_bcount = mb_reserve(&rqp->sr_rq, sizeof(u_short));
  218. rqp->sr_rq.mb_count = 0;
  219. }
  220. void
  221. smb_rq_bend(struct smb_rq *rqp)
  222. {
  223. int bcnt;
  224. if (rqp->sr_bcount == NULL) {
  225. SMBERROR("no bcount\n"); /* actually panic */
  226. return;
  227. }
  228. bcnt = rqp->sr_rq.mb_count;
  229. if (bcnt > 0xffff)
  230. SMBERROR("byte count too large (%d)\n", bcnt);
  231. le16enc(rqp->sr_bcount, bcnt);
  232. }
  233. int
  234. smb_rq_intr(struct smb_rq *rqp)
  235. {
  236. if (rqp->sr_flags & SMBR_INTR)
  237. return EINTR;
  238. return smb_td_intr(rqp->sr_cred->scr_td);
  239. }
  240. int
  241. smb_rq_getrequest(struct smb_rq *rqp, struct mbchain **mbpp)
  242. {
  243. *mbpp = &rqp->sr_rq;
  244. return 0;
  245. }
  246. int
  247. smb_rq_getreply(struct smb_rq *rqp, struct mdchain **mbpp)
  248. {
  249. *mbpp = &rqp->sr_rp;
  250. return 0;
  251. }
  252. static int
  253. smb_rq_getenv(struct smb_connobj *layer,
  254. struct smb_vc **vcpp, struct smb_share **sspp)
  255. {
  256. struct smb_vc *vcp = NULL;
  257. struct smb_share *ssp = NULL;
  258. struct smb_connobj *cp;
  259. int error = 0;
  260. switch (layer->co_level) {
  261. case SMBL_VC:
  262. vcp = CPTOVC(layer);
  263. if (layer->co_parent == NULL) {
  264. SMBERROR("zombie VC %s\n", vcp->vc_srvname);
  265. error = EINVAL;
  266. break;
  267. }
  268. break;
  269. case SMBL_SHARE:
  270. ssp = CPTOSS(layer);
  271. cp = layer->co_parent;
  272. if (cp == NULL) {
  273. SMBERROR("zombie share %s\n", ssp->ss_name);
  274. error = EINVAL;
  275. break;
  276. }
  277. error = smb_rq_getenv(cp, &vcp, NULL);
  278. if (error)
  279. break;
  280. break;
  281. default:
  282. SMBERROR("invalid layer %d passed\n", layer->co_level);
  283. error = EINVAL;
  284. }
  285. if (vcpp)
  286. *vcpp = vcp;
  287. if (sspp)
  288. *sspp = ssp;
  289. return error;
  290. }
  291. /*
  292. * Wait for reply on the request
  293. */
  294. static int
  295. smb_rq_reply(struct smb_rq *rqp)
  296. {
  297. struct mdchain *mdp = &rqp->sr_rp;
  298. u_int32_t tdw;
  299. u_int8_t tb;
  300. int error, rperror = 0;
  301. error = smb_iod_waitrq(rqp);
  302. if (error)
  303. return error;
  304. error = md_get_uint32(mdp, &tdw);
  305. if (error)
  306. return error;
  307. error = md_get_uint8(mdp, &tb);
  308. if (rqp->sr_vc->vc_hflags2 & SMB_FLAGS2_ERR_STATUS) {
  309. error = md_get_uint32le(mdp, &rqp->sr_error);
  310. } else {
  311. error = md_get_uint8(mdp, &rqp->sr_errclass);
  312. error = md_get_uint8(mdp, &tb);
  313. error = md_get_uint16le(mdp, &rqp->sr_serror);
  314. if (!error)
  315. rperror = smb_maperror(rqp->sr_errclass, rqp->sr_serror);
  316. }
  317. error = md_get_uint8(mdp, &rqp->sr_rpflags);
  318. error = md_get_uint16le(mdp, &rqp->sr_rpflags2);
  319. error = md_get_uint32(mdp, &tdw);
  320. error = md_get_uint32(mdp, &tdw);
  321. error = md_get_uint32(mdp, &tdw);
  322. error = md_get_uint16le(mdp, &rqp->sr_rptid);
  323. error = md_get_uint16le(mdp, &rqp->sr_rppid);
  324. error = md_get_uint16le(mdp, &rqp->sr_rpuid);
  325. error = md_get_uint16le(mdp, &rqp->sr_rpmid);
  326. if (error == 0 &&
  327. (rqp->sr_vc->vc_hflags2 & SMB_FLAGS2_SECURITY_SIGNATURE))
  328. error = smb_rq_verify(rqp);
  329. SMBSDEBUG("M:%04x, P:%04x, U:%04x, T:%04x, E: %d:%d\n",
  330. rqp->sr_rpmid, rqp->sr_rppid, rqp->sr_rpuid, rqp->sr_rptid,
  331. rqp->sr_errclass, rqp->sr_serror);
  332. return error ? error : rperror;
  333. }
  334. #define ALIGN4(a) (((a) + 3) & ~3)
  335. /*
  336. * TRANS2 request implementation
  337. */
  338. int
  339. smb_t2_alloc(struct smb_connobj *layer, u_short setup, struct smb_cred *scred,
  340. struct smb_t2rq **t2pp)
  341. {
  342. struct smb_t2rq *t2p;
  343. int error;
  344. t2p = malloc(sizeof(*t2p), M_SMBRQ, M_WAITOK);
  345. if (t2p == NULL)
  346. return ENOMEM;
  347. error = smb_t2_init(t2p, layer, setup, scred);
  348. t2p->t2_flags |= SMBT2_ALLOCED;
  349. if (error) {
  350. smb_t2_done(t2p);
  351. return error;
  352. }
  353. *t2pp = t2p;
  354. return 0;
  355. }
  356. int
  357. smb_t2_init(struct smb_t2rq *t2p, struct smb_connobj *source, u_short setup,
  358. struct smb_cred *scred)
  359. {
  360. int error;
  361. bzero(t2p, sizeof(*t2p));
  362. t2p->t2_source = source;
  363. t2p->t2_setupcount = 1;
  364. t2p->t2_setupdata = t2p->t2_setup;
  365. t2p->t2_setup[0] = setup;
  366. t2p->t2_fid = 0xffff;
  367. t2p->t2_cred = scred;
  368. error = smb_rq_getenv(source, &t2p->t2_vc, NULL);
  369. if (error)
  370. return error;
  371. return 0;
  372. }
  373. void
  374. smb_t2_done(struct smb_t2rq *t2p)
  375. {
  376. mb_done(&t2p->t2_tparam);
  377. mb_done(&t2p->t2_tdata);
  378. md_done(&t2p->t2_rparam);
  379. md_done(&t2p->t2_rdata);
  380. if (t2p->t2_flags & SMBT2_ALLOCED)
  381. free(t2p, M_SMBRQ);
  382. }
  383. static int
  384. smb_t2_placedata(struct mbuf *mtop, u_int16_t offset, u_int16_t count,
  385. struct mdchain *mdp)
  386. {
  387. struct mbuf *m, *m0;
  388. int len;
  389. m0 = m_split(mtop, offset, M_WAITOK);
  390. len = m_length(m0, &m);
  391. m->m_len -= len - count;
  392. if (mdp->md_top == NULL) {
  393. md_initm(mdp, m0);
  394. } else
  395. m_cat(mdp->md_top, m0);
  396. return 0;
  397. }
  398. static int
  399. smb_t2_reply(struct smb_t2rq *t2p)
  400. {
  401. struct mdchain *mdp;
  402. struct smb_rq *rqp = t2p->t2_rq;
  403. int error, totpgot, totdgot;
  404. u_int16_t totpcount, totdcount, pcount, poff, doff, pdisp, ddisp;
  405. u_int16_t tmp, bc, dcount;
  406. u_int8_t wc;
  407. error = smb_rq_reply(rqp);
  408. if (error)
  409. return error;
  410. if ((t2p->t2_flags & SMBT2_ALLSENT) == 0) {
  411. /*
  412. * this is an interim response, ignore it.
  413. */
  414. SMBRQ_SLOCK(rqp);
  415. md_next_record(&rqp->sr_rp);
  416. SMBRQ_SUNLOCK(rqp);
  417. return 0;
  418. }
  419. /*
  420. * Now we have to get all subsequent responses. The CIFS specification
  421. * says that they can be disordered which is weird.
  422. * TODO: timo
  423. */
  424. totpgot = totdgot = 0;
  425. totpcount = totdcount = 0xffff;
  426. mdp = &rqp->sr_rp;
  427. for (;;) {
  428. m_dumpm(mdp->md_top);
  429. if ((error = md_get_uint8(mdp, &wc)) != 0)
  430. break;
  431. if (wc < 10) {
  432. error = ENOENT;
  433. break;
  434. }
  435. if ((error = md_get_uint16le(mdp, &tmp)) != 0)
  436. break;
  437. if (totpcount > tmp)
  438. totpcount = tmp;
  439. md_get_uint16le(mdp, &tmp);
  440. if (totdcount > tmp)
  441. totdcount = tmp;
  442. if ((error = md_get_uint16le(mdp, &tmp)) != 0 || /* reserved */
  443. (error = md_get_uint16le(mdp, &pcount)) != 0 ||
  444. (error = md_get_uint16le(mdp, &poff)) != 0 ||
  445. (error = md_get_uint16le(mdp, &pdisp)) != 0)
  446. break;
  447. if (pcount != 0 && pdisp != totpgot) {
  448. SMBERROR("Can't handle disordered parameters %d:%d\n",
  449. pdisp, totpgot);
  450. error = EINVAL;
  451. break;
  452. }
  453. if ((error = md_get_uint16le(mdp, &dcount)) != 0 ||
  454. (error = md_get_uint16le(mdp, &doff)) != 0 ||
  455. (error = md_get_uint16le(mdp, &ddisp)) != 0)
  456. break;
  457. if (dcount != 0 && ddisp != totdgot) {
  458. SMBERROR("Can't handle disordered data\n");
  459. error = EINVAL;
  460. break;
  461. }
  462. md_get_uint8(mdp, &wc);
  463. md_get_uint8(mdp, NULL);
  464. tmp = wc;
  465. while (tmp--)
  466. md_get_uint16(mdp, NULL);
  467. if ((error = md_get_uint16le(mdp, &bc)) != 0)
  468. break;
  469. /* tmp = SMB_HDRLEN + 1 + 10 * 2 + 2 * wc + 2;*/
  470. if (dcount) {
  471. error = smb_t2_placedata(mdp->md_top, doff, dcount,
  472. &t2p->t2_rdata);
  473. if (error)
  474. break;
  475. }
  476. if (pcount) {
  477. error = smb_t2_placedata(mdp->md_top, poff, pcount,
  478. &t2p->t2_rparam);
  479. if (error)
  480. break;
  481. }
  482. totpgot += pcount;
  483. totdgot += dcount;
  484. if (totpgot >= totpcount && totdgot >= totdcount) {
  485. error = 0;
  486. t2p->t2_flags |= SMBT2_ALLRECV;
  487. break;
  488. }
  489. /*
  490. * We're done with this reply, look for the next one.
  491. */
  492. SMBRQ_SLOCK(rqp);
  493. md_next_record(&rqp->sr_rp);
  494. SMBRQ_SUNLOCK(rqp);
  495. error = smb_rq_reply(rqp);
  496. if (error)
  497. break;
  498. }
  499. return error;
  500. }
  501. /*
  502. * Perform a full round of TRANS2 request
  503. */
  504. static int
  505. smb_t2_request_int(struct smb_t2rq *t2p)
  506. {
  507. struct smb_vc *vcp = t2p->t2_vc;
  508. struct smb_cred *scred = t2p->t2_cred;
  509. struct mbchain *mbp;
  510. struct mdchain *mdp, mbparam, mbdata;
  511. struct mbuf *m;
  512. struct smb_rq *rqp;
  513. int totpcount, leftpcount, totdcount, leftdcount, len, txmax, i;
  514. int error, doff, poff, txdcount, txpcount, nmlen;
  515. m = t2p->t2_tparam.mb_top;
  516. if (m) {
  517. md_initm(&mbparam, m); /* do not free it! */
  518. totpcount = m_fixhdr(m);
  519. if (totpcount > 0xffff) /* maxvalue for u_short */
  520. return EINVAL;
  521. } else
  522. totpcount = 0;
  523. m = t2p->t2_tdata.mb_top;
  524. if (m) {
  525. md_initm(&mbdata, m); /* do not free it! */
  526. totdcount = m_fixhdr(m);
  527. if (totdcount > 0xffff)
  528. return EINVAL;
  529. } else
  530. totdcount = 0;
  531. leftdcount = totdcount;
  532. leftpcount = totpcount;
  533. txmax = vcp->vc_txmax;
  534. error = smb_rq_alloc(t2p->t2_source, t2p->t_name ?
  535. SMB_COM_TRANSACTION : SMB_COM_TRANSACTION2, scred, &rqp);
  536. if (error)
  537. return error;
  538. rqp->sr_flags |= SMBR_MULTIPACKET;
  539. t2p->t2_rq = rqp;
  540. rqp->sr_t2 = t2p;
  541. mbp = &rqp->sr_rq;
  542. smb_rq_wstart(rqp);
  543. mb_put_uint16le(mbp, totpcount);
  544. mb_put_uint16le(mbp, totdcount);
  545. mb_put_uint16le(mbp, t2p->t2_maxpcount);
  546. mb_put_uint16le(mbp, t2p->t2_maxdcount);
  547. mb_put_uint8(mbp, t2p->t2_maxscount);
  548. mb_put_uint8(mbp, 0); /* reserved */
  549. mb_put_uint16le(mbp, 0); /* flags */
  550. mb_put_uint32le(mbp, 0); /* Timeout */
  551. mb_put_uint16le(mbp, 0); /* reserved 2 */
  552. len = mb_fixhdr(mbp);
  553. /*
  554. * now we have known packet size as
  555. * ALIGN4(len + 5 * 2 + setupcount * 2 + 2 + strlen(name) + 1),
  556. * and need to decide which parts should go into the first request
  557. */
  558. nmlen = t2p->t_name ? strlen(t2p->t_name) : 0;
  559. len = ALIGN4(len + 5 * 2 + t2p->t2_setupcount * 2 + 2 + nmlen + 1);
  560. if (len + leftpcount > txmax) {
  561. txpcount = min(leftpcount, txmax - len);
  562. poff = len;
  563. txdcount = 0;
  564. doff = 0;
  565. } else {
  566. txpcount = leftpcount;
  567. poff = txpcount ? len : 0;
  568. len = ALIGN4(len + txpcount);
  569. txdcount = min(leftdcount, txmax - len);
  570. doff = txdcount ? len : 0;
  571. }
  572. leftpcount -= txpcount;
  573. leftdcount -= txdcount;
  574. mb_put_uint16le(mbp, txpcount);
  575. mb_put_uint16le(mbp, poff);
  576. mb_put_uint16le(mbp, txdcount);
  577. mb_put_uint16le(mbp, doff);
  578. mb_put_uint8(mbp, t2p->t2_setupcount);
  579. mb_put_uint8(mbp, 0);
  580. for (i = 0; i < t2p->t2_setupcount; i++)
  581. mb_put_uint16le(mbp, t2p->t2_setupdata[i]);
  582. smb_rq_wend(rqp);
  583. smb_rq_bstart(rqp);
  584. /* TDUNICODE */
  585. if (t2p->t_name)
  586. mb_put_mem(mbp, t2p->t_name, nmlen, MB_MSYSTEM);
  587. mb_put_uint8(mbp, 0); /* terminating zero */
  588. len = mb_fixhdr(mbp);
  589. if (txpcount) {
  590. mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO);
  591. error = md_get_mbuf(&mbparam, txpcount, &m);
  592. SMBSDEBUG("%d:%d:%d\n", error, txpcount, txmax);
  593. if (error)
  594. goto freerq;
  595. mb_put_mbuf(mbp, m);
  596. }
  597. len = mb_fixhdr(mbp);
  598. if (txdcount) {
  599. mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO);
  600. error = md_get_mbuf(&mbdata, txdcount, &m);
  601. if (error)
  602. goto freerq;
  603. mb_put_mbuf(mbp, m);
  604. }
  605. smb_rq_bend(rqp); /* incredible, but thats it... */
  606. error = smb_rq_enqueue(rqp);
  607. if (error)
  608. goto freerq;
  609. if (leftpcount == 0 && leftdcount == 0)
  610. t2p->t2_flags |= SMBT2_ALLSENT;
  611. error = smb_t2_reply(t2p);
  612. if (error)
  613. goto bad;
  614. while (leftpcount || leftdcount) {
  615. t2p->t2_flags |= SMBT2_SECONDARY;
  616. error = smb_rq_new(rqp, t2p->t_name ?
  617. SMB_COM_TRANSACTION_SECONDARY : SMB_COM_TRANSACTION2_SECONDARY);
  618. if (error)
  619. goto bad;
  620. mbp = &rqp->sr_rq;
  621. smb_rq_wstart(rqp);
  622. mb_put_uint16le(mbp, totpcount);
  623. mb_put_uint16le(mbp, totdcount);
  624. len = mb_fixhdr(mbp);
  625. /*
  626. * now we have known packet size as
  627. * ALIGN4(len + 7 * 2 + 2) for T2 request, and -2 for T one,
  628. * and need to decide which parts should go into request
  629. */
  630. len = ALIGN4(len + 6 * 2 + 2);
  631. if (t2p->t_name == NULL)
  632. len += 2;
  633. if (len + leftpcount > txmax) {
  634. txpcount = min(leftpcount, txmax - len);
  635. poff = len;
  636. txdcount = 0;
  637. doff = 0;
  638. } else {
  639. txpcount = leftpcount;
  640. poff = txpcount ? len : 0;
  641. len = ALIGN4(len + txpcount);
  642. txdcount = min(leftdcount, txmax - len);
  643. doff = txdcount ? len : 0;
  644. }
  645. mb_put_uint16le(mbp, txpcount);
  646. mb_put_uint16le(mbp, poff);
  647. mb_put_uint16le(mbp, totpcount - leftpcount);
  648. mb_put_uint16le(mbp, txdcount);
  649. mb_put_uint16le(mbp, doff);
  650. mb_put_uint16le(mbp, totdcount - leftdcount);
  651. leftpcount -= txpcount;
  652. leftdcount -= txdcount;
  653. if (t2p->t_name == NULL)
  654. mb_put_uint16le(mbp, t2p->t2_fid);
  655. smb_rq_wend(rqp);
  656. smb_rq_bstart(rqp);
  657. mb_put_uint8(mbp, 0); /* name */
  658. len = mb_fixhdr(mbp);
  659. if (txpcount) {
  660. mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO);
  661. error = md_get_mbuf(&mbparam, txpcount, &m);
  662. if (error)
  663. goto bad;
  664. mb_put_mbuf(mbp, m);
  665. }
  666. len = mb_fixhdr(mbp);
  667. if (txdcount) {
  668. mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO);
  669. error = md_get_mbuf(&mbdata, txdcount, &m);
  670. if (error)
  671. goto bad;
  672. mb_put_mbuf(mbp, m);
  673. }
  674. smb_rq_bend(rqp);
  675. rqp->sr_state = SMBRQ_NOTSENT;
  676. error = smb_iod_request(vcp->vc_iod, SMBIOD_EV_NEWRQ, NULL);
  677. if (error)
  678. goto bad;
  679. } /* while left params or data */
  680. t2p->t2_flags |= SMBT2_ALLSENT;
  681. mdp = &t2p->t2_rdata;
  682. if (mdp->md_top) {
  683. m_fixhdr(mdp->md_top);
  684. md_initm(mdp, mdp->md_top);
  685. }
  686. mdp = &t2p->t2_rparam;
  687. if (mdp->md_top) {
  688. m_fixhdr(mdp->md_top);
  689. md_initm(mdp, mdp->md_top);
  690. }
  691. bad:
  692. smb_iod_removerq(rqp);
  693. freerq:
  694. smb_rq_done(rqp);
  695. if (error) {
  696. if (rqp->sr_flags & SMBR_RESTART)
  697. t2p->t2_flags |= SMBT2_RESTART;
  698. md_done(&t2p->t2_rparam);
  699. md_done(&t2p->t2_rdata);
  700. }
  701. return error;
  702. }
  703. int
  704. smb_t2_request(struct smb_t2rq *t2p)
  705. {
  706. int error = EINVAL, i;
  707. for (i = 0; i < SMB_MAXRCN; i++) {
  708. t2p->t2_flags &= ~SMBR_RESTART;
  709. error = smb_t2_request_int(t2p);
  710. if (error == 0)
  711. break;
  712. if ((t2p->t2_flags & (SMBT2_RESTART | SMBT2_NORESTART)) != SMBT2_RESTART)
  713. break;
  714. }
  715. return error;
  716. }