The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/netsmb/smb_rq.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 8fc67c2fb1368977aa532d7a84e1cda9


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.