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