void smb_t2_done(struct smb_t2rq *t2p) { mb_done(&t2p->t2_tparam); mb_done(&t2p->t2_tdata); md_done(&t2p->t2_rparam); md_done(&t2p->t2_rdata); if (t2p->t2_flags & SMBT2_ALLOCED) free(t2p, M_SMBRQ); }
void smb_t2_done(struct smb_t2rq *t2p) { mb_done(&t2p->t2_tparam); mb_done(&t2p->t2_tdata); md_done(&t2p->t2_rparam); md_done(&t2p->t2_rdata); mutex_destroy(&t2p->t2_lock); cv_destroy(&t2p->t2_cond); if (t2p->t2_flags & SMBT2_ALLOCED) kmem_free(t2p, sizeof (*t2p)); }
void smb_nt_done(struct smb_ntrq *ntp) { mb_done(&ntp->nt_tsetup); mb_done(&ntp->nt_tparam); mb_done(&ntp->nt_tdata); md_done(&ntp->nt_rparam); md_done(&ntp->nt_rdata); cv_destroy(&ntp->nt_cond); mutex_destroy(&ntp->nt_lock); if (ntp->nt_flags & SMBT2_ALLOCED) kmem_free(ntp, sizeof (*ntp)); }
static int smb_rq_new(struct smb_rq *rqp, uchar_t cmd) { struct mbchain *mbp = &rqp->sr_rq; struct smb_vc *vcp = rqp->sr_vc; int error; ASSERT(rqp != NULL); rqp->sr_sendcnt = 0; rqp->sr_cmd = cmd; mb_done(mbp); md_done(&rqp->sr_rp); error = mb_init(mbp); if (error) return (error); /* * Is this the right place to save the flags? */ rqp->sr_rqflags = vcp->vc_hflags; rqp->sr_rqflags2 = vcp->vc_hflags2; /* * The SMB header is filled in later by * smb_rq_fillhdr (see below) * Just reserve space here. */ mb_put_mem(mbp, NULL, SMB_HDRLEN, MB_MZERO); return (0); }
static int smb_rq_new(struct smb_rq *rqp, u_char cmd) { struct smb_vc *vcp = rqp->sr_vc; struct mbchain *mbp = &rqp->sr_rq; int error; rqp->sr_sendcnt = 0; mb_done(mbp); md_done(&rqp->sr_rp); error = mb_init(mbp); if (error) return error; mb_put_mem(mbp, SMB_SIGNATURE, SMB_SIGLEN, MB_MSYSTEM); mb_put_uint8(mbp, cmd); mb_put_uint32le(mbp, 0); /* DosError */ mb_put_uint8(mbp, vcp->vc_hflags); mb_put_uint16le(mbp, vcp->vc_hflags2); mb_put_mem(mbp, tzero, 12, MB_MSYSTEM); rqp->sr_rqtid = (u_int16_t*)mb_reserve(mbp, sizeof(u_int16_t)); mb_put_uint16le(mbp, 1 /*scred->sc_p->p_pid & 0xffff*/); rqp->sr_rquid = (u_int16_t*)mb_reserve(mbp, sizeof(u_int16_t)); mb_put_uint16le(mbp, rqp->sr_mid); return 0; }
void smb_rq_done(struct smb_rq *rqp) { mb_done(&rqp->sr_rq); md_done(&rqp->sr_rp); smb_sl_destroy(&rqp->sr_slock); if (rqp->sr_flags & SMBR_ALLOCED) free(rqp, M_SMBRQ); }
void ncp_rq_done(struct ncp_rq *rqp) { mb_done(&rqp->rq); md_done(&rqp->rp); if (rqp->nr_flags & NCPR_ALLOCED) free(rqp, M_NCPRQ); return; }
/** * The truncate system call sets the file size in the database. */ static int md_truncate(const char* path, unsigned long long size) { sqlite3_stmt *stmt = NULL; const char *tail = NULL; int rc; rc = sqlite3_prepare(md_db, "UPDATE File SET bytes=? WHERE name=?", 1024, &stmt, &tail); md_clerr(rc); sqlite3_bind_int64(stmt, 1, (long long)size); sqlite3_bind_text(stmt, 2, path, strlen(path), SQLITE_STATIC); rc = sqlite3_step(stmt); md_done(rc); return 0; }
/** * The mknod call inserts a new file into the database with default * times. */ static int md_invalidate(int file, int store) { sqlite3_stmt *stmt = NULL; const char *tail = NULL; int rc; rc = sqlite3_prepare(md_db, "INSERT INTO Invalid (file, store) VALUES (?, ?)", 1024, &stmt, &tail ); md_clerr(rc); sqlite3_bind_int(stmt, 1, file); sqlite3_bind_int(stmt, 2, store); rc = sqlite3_step(stmt); md_done(rc); return 0; }
/** * The mknod call inserts a new file into the database with default * times. */ static int md_mknod(const char* path, mode_t mode) { sqlite3_stmt *stmt = NULL; const char *tail = NULL; int rc; rc = sqlite3_prepare(md_db, "INSERT INTO File (name, mode, mtime, atime, ctime) VALUES (?, ?, strftime('%s','now'), strftime('%s','now'), strftime('%s','now'))", 1024, &stmt, &tail ); md_clerr(rc); sqlite3_bind_text(stmt, 1, path, strlen(path), SQLITE_STATIC); sqlite3_bind_int(stmt, 2, mode); rc = sqlite3_step(stmt); md_done(rc); return 0; }
/* * Put next record in place of existing */ int md_next_record(struct mdchain *mdp) { struct mbuf *m; if (mdp->md_top == NULL) return ENOENT; m = mdp->md_top->m_nextpkt; md_done(mdp); if (m == NULL) return ENOENT; md_initm(mdp, m); return 0; }
/* * Done with a request object. Free its contents. * If it was allocated (SMBR_ALLOCED) free it too. * Some of these are stack locals, not allocated. * * No locks here - this is the last ref. */ void smb_rq_done(struct smb_rq *rqp) { /* * No smb_vc_rele() here - see smb_rq_init() */ mb_done(&rqp->sr_rq); md_done(&rqp->sr_rp); mutex_destroy(&rqp->sr_lock); cv_destroy(&rqp->sr_cond); if (rqp->sr_flags & SMBR_ALLOCED) kmem_free(rqp, sizeof (*rqp)); }
/** * The unlink call removes a file from the database. */ static int md_unlink(const char* path) { sqlite3_stmt *stmt = NULL; const char *tail = NULL; int rc; rc = sqlite3_prepare(md_db, "DELETE FROM File WHERE name = ?", 1024, &stmt, &tail ); md_clerr(rc); sqlite3_bind_text(stmt, 1, path, strlen(path), SQLITE_STATIC); rc = sqlite3_step(stmt); md_done(rc); return 0; }
/** * The chown call sets the UID and the GID in the database. */ static int md_chown(const char* path, uid_t uid, gid_t gid) { sqlite3_stmt *stmt = NULL; const char *tail = NULL; int rc; rc = sqlite3_prepare(md_db, "UPDATE File SET uid=?, gid=? WHERE name=?", 1024, &stmt, &tail); md_clerr(rc); sqlite3_bind_int(stmt, 1, uid); sqlite3_bind_int(stmt, 2, gid); sqlite3_bind_text(stmt, 3, path, strlen(path), SQLITE_STATIC); rc = sqlite3_step(stmt); md_done(rc); return 0; }
/** * This function deletes an invalidated file, when an object server has recovered it. */ static int md_setvalid(int file, char* hostname, int port) { sqlite3_stmt *stmt = NULL; const char *tail = NULL; int rc; rc = sqlite3_prepare(md_db, "DELETE FROM Invalid WHERE file=? AND store IN (SELECT store FROM StoreAddress WHERE addr=? AND PORT=?)", 1024, &stmt, &tail ); md_clerr(rc); sqlite3_bind_int(stmt, 1, file); sqlite3_bind_text(stmt, 2, hostname, strlen(hostname), SQLITE_STATIC); sqlite3_bind_int(stmt, 3, port); rc = sqlite3_step(stmt); md_done(rc); return 0; }
static int smb_rq_new(struct smb_rq *rqp, u_char cmd) { struct smb_vc *vcp = rqp->sr_vc; struct mbchain *mbp = &rqp->sr_rq; int error; u_int16_t flags2; rqp->sr_sendcnt = 0; mb_done(mbp); md_done(&rqp->sr_rp); error = mb_init(mbp); if (error) return error; mb_put_mem(mbp, SMB_SIGNATURE, SMB_SIGLEN, MB_MSYSTEM); mb_put_uint8(mbp, cmd); mb_put_uint32le(mbp, 0); /* DosError */ mb_put_uint8(mbp, vcp->vc_hflags); flags2 = vcp->vc_hflags2; if (cmd == SMB_COM_TRANSACTION || cmd == SMB_COM_TRANSACTION_SECONDARY) flags2 &= ~SMB_FLAGS2_UNICODE; if (cmd == SMB_COM_NEGOTIATE) flags2 &= ~SMB_FLAGS2_SECURITY_SIGNATURE; mb_put_uint16le(mbp, flags2); if ((flags2 & SMB_FLAGS2_SECURITY_SIGNATURE) == 0) { mb_put_mem(mbp, tzero, 12, MB_MSYSTEM); rqp->sr_rqsig = NULL; } else { mb_put_uint16le(mbp, 0 /*scred->sc_p->p_pid >> 16*/); rqp->sr_rqsig = (u_int8_t *)mb_reserve(mbp, 8); mb_put_uint16le(mbp, 0); } rqp->sr_rqtid = mb_reserve(mbp, sizeof(u_int16_t)); mb_put_uint16le(mbp, 1 /*scred->sc_p->p_pid & 0xffff*/); rqp->sr_rquid = mb_reserve(mbp, sizeof(u_int16_t)); mb_put_uint16le(mbp, rqp->sr_mid); return 0; }
/* * Perform a full round of TRANS2 request */ static int smb_t2_request_int(struct smb_t2rq *t2p) { struct smb_vc *vcp = t2p->t2_vc; struct smb_cred *scred = t2p->t2_cred; struct mbchain *mbp; struct mdchain *mdp, mbparam, mbdata; mblk_t *m; struct smb_rq *rqp; int totpcount, leftpcount, totdcount, leftdcount, len, txmax, i; int error, doff, poff, txdcount, txpcount, nmlen, nmsize; m = t2p->t2_tparam.mb_top; if (m) { md_initm(&mbparam, m); /* do not free it! */ totpcount = m_fixhdr(m); if (totpcount > 0xffff) /* maxvalue for ushort_t */ return (EINVAL); } else totpcount = 0; m = t2p->t2_tdata.mb_top; if (m) { md_initm(&mbdata, m); /* do not free it! */ totdcount = m_fixhdr(m); if (totdcount > 0xffff) return (EINVAL); } else totdcount = 0; leftdcount = totdcount; leftpcount = totpcount; txmax = vcp->vc_txmax; error = smb_rq_alloc(t2p->t2_source, t2p->t_name ? SMB_COM_TRANSACTION : SMB_COM_TRANSACTION2, scred, &rqp); if (error) return (error); rqp->sr_timo = smb_timo_default; rqp->sr_flags |= SMBR_MULTIPACKET; t2p->t2_rq = rqp; mbp = &rqp->sr_rq; smb_rq_wstart(rqp); mb_put_uint16le(mbp, totpcount); mb_put_uint16le(mbp, totdcount); mb_put_uint16le(mbp, t2p->t2_maxpcount); mb_put_uint16le(mbp, t2p->t2_maxdcount); mb_put_uint8(mbp, t2p->t2_maxscount); mb_put_uint8(mbp, 0); /* reserved */ mb_put_uint16le(mbp, 0); /* flags */ mb_put_uint32le(mbp, 0); /* Timeout */ mb_put_uint16le(mbp, 0); /* reserved 2 */ len = mb_fixhdr(mbp); /* * Now we know the size of the trans overhead stuff: * ALIGN4(len + 5 * 2 + setupcount * 2 + 2 + nmsize), * where nmsize is the OTW size of the name, including * the unicode null terminator and any alignment. * Use this to decide which parts (and how much) * can go into this request: params, data */ nmlen = t2p->t_name ? t2p->t_name_len : 0; nmsize = nmlen + 1; /* null term. */ if (SMB_UNICODE_STRINGS(vcp)) { nmsize *= 2; /* we know put_dmem will need to align */ nmsize += 1; } len = ALIGN4(len + 5 * 2 + t2p->t2_setupcount * 2 + 2 + nmsize); if (len + leftpcount > txmax) { txpcount = min(leftpcount, txmax - len); poff = len; txdcount = 0; doff = 0; } else { txpcount = leftpcount; poff = txpcount ? len : 0; /* * Other client traffic seems to "ALIGN2" here. The extra * 2 byte pad we use has no observed downside and may be * required for some old servers(?) */ len = ALIGN4(len + txpcount); txdcount = min(leftdcount, txmax - len); doff = txdcount ? len : 0; } leftpcount -= txpcount; leftdcount -= txdcount; mb_put_uint16le(mbp, txpcount); mb_put_uint16le(mbp, poff); mb_put_uint16le(mbp, txdcount); mb_put_uint16le(mbp, doff); mb_put_uint8(mbp, t2p->t2_setupcount); mb_put_uint8(mbp, 0); for (i = 0; i < t2p->t2_setupcount; i++) { mb_put_uint16le(mbp, t2p->t2_setupdata[i]); } smb_rq_wend(rqp); smb_rq_bstart(rqp); if (t2p->t_name) { /* Put the string and terminating null. */ smb_put_dmem(mbp, vcp, t2p->t_name, nmlen + 1, SMB_CS_NONE, NULL); } else { /* nmsize accounts for padding, char size. */ mb_put_mem(mbp, NULL, nmsize, MB_MZERO); } len = mb_fixhdr(mbp); if (txpcount) { mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); error = md_get_mbuf(&mbparam, txpcount, &m); SMBSDEBUG("%d:%d:%d\n", error, txpcount, txmax); if (error) goto freerq; mb_put_mbuf(mbp, m); } len = mb_fixhdr(mbp); if (txdcount) { mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); error = md_get_mbuf(&mbdata, txdcount, &m); if (error) goto freerq; mb_put_mbuf(mbp, m); } smb_rq_bend(rqp); /* incredible, but thats it... */ error = smb_rq_enqueue(rqp); if (error) goto freerq; if (leftpcount || leftdcount) { error = smb_rq_reply(rqp); if (error) goto bad; /* * this is an interim response, ignore it. */ SMBRQ_LOCK(rqp); md_next_record(&rqp->sr_rp); SMBRQ_UNLOCK(rqp); } while (leftpcount || leftdcount) { error = smb_rq_new(rqp, t2p->t_name ? SMB_COM_TRANSACTION_SECONDARY : SMB_COM_TRANSACTION2_SECONDARY); if (error) goto bad; mbp = &rqp->sr_rq; smb_rq_wstart(rqp); mb_put_uint16le(mbp, totpcount); mb_put_uint16le(mbp, totdcount); len = mb_fixhdr(mbp); /* * now we have known packet size as * ALIGN4(len + 7 * 2 + 2) for T2 request, and -2 for T one, * and need to decide which parts should go into request */ len = ALIGN4(len + 6 * 2 + 2); if (t2p->t_name == NULL) len += 2; if (len + leftpcount > txmax) { txpcount = min(leftpcount, txmax - len); poff = len; txdcount = 0; doff = 0; } else { txpcount = leftpcount; poff = txpcount ? len : 0; len = ALIGN4(len + txpcount); txdcount = min(leftdcount, txmax - len); doff = txdcount ? len : 0; } mb_put_uint16le(mbp, txpcount); mb_put_uint16le(mbp, poff); mb_put_uint16le(mbp, totpcount - leftpcount); mb_put_uint16le(mbp, txdcount); mb_put_uint16le(mbp, doff); mb_put_uint16le(mbp, totdcount - leftdcount); leftpcount -= txpcount; leftdcount -= txdcount; if (t2p->t_name == NULL) mb_put_uint16le(mbp, t2p->t2_fid); smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_uint8(mbp, 0); /* name */ len = mb_fixhdr(mbp); if (txpcount) { mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); error = md_get_mbuf(&mbparam, txpcount, &m); if (error) goto bad; mb_put_mbuf(mbp, m); } len = mb_fixhdr(mbp); if (txdcount) { mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); error = md_get_mbuf(&mbdata, txdcount, &m); if (error) goto bad; mb_put_mbuf(mbp, m); } smb_rq_bend(rqp); error = smb_iod_multirq(rqp); if (error) goto bad; } /* while left params or data */ error = smb_t2_reply(t2p); if (error && !(t2p->t2_flags & SMBT2_MOREDATA)) goto bad; mdp = &t2p->t2_rdata; if (mdp->md_top) { m_fixhdr(mdp->md_top); md_initm(mdp, mdp->md_top); } mdp = &t2p->t2_rparam; if (mdp->md_top) { m_fixhdr(mdp->md_top); md_initm(mdp, mdp->md_top); } bad: smb_iod_removerq(rqp); freerq: if (error && !(t2p->t2_flags & SMBT2_MOREDATA)) { if (rqp->sr_flags & SMBR_RESTART) t2p->t2_flags |= SMBT2_RESTART; md_done(&t2p->t2_rparam); md_done(&t2p->t2_rdata); } smb_rq_done(rqp); return (error); }
/* * Perform a full round of NT_TRANSACTION request */ static int smb_nt_request_int(struct smb_ntrq *ntp) { struct smb_vc *vcp = ntp->nt_vc; struct smb_cred *scred = ntp->nt_cred; struct mbchain *mbp; struct mdchain *mdp, mbsetup, mbparam, mbdata; mblk_t *m; struct smb_rq *rqp; int totpcount, leftpcount, totdcount, leftdcount, len, txmax; int error, doff, poff, txdcount, txpcount; int totscount; m = ntp->nt_tsetup.mb_top; if (m) { md_initm(&mbsetup, m); /* do not free it! */ totscount = m_fixhdr(m); if (totscount > 2 * 0xff) return (EINVAL); } else totscount = 0; m = ntp->nt_tparam.mb_top; if (m) { md_initm(&mbparam, m); /* do not free it! */ totpcount = m_fixhdr(m); if (totpcount > 0x7fffffff) return (EINVAL); } else totpcount = 0; m = ntp->nt_tdata.mb_top; if (m) { md_initm(&mbdata, m); /* do not free it! */ totdcount = m_fixhdr(m); if (totdcount > 0x7fffffff) return (EINVAL); } else totdcount = 0; leftdcount = totdcount; leftpcount = totpcount; txmax = vcp->vc_txmax; error = smb_rq_alloc(ntp->nt_source, SMB_COM_NT_TRANSACT, scred, &rqp); if (error) return (error); rqp->sr_timo = smb_timo_default; rqp->sr_flags |= SMBR_MULTIPACKET; ntp->nt_rq = rqp; mbp = &rqp->sr_rq; smb_rq_wstart(rqp); mb_put_uint8(mbp, ntp->nt_maxscount); mb_put_uint16le(mbp, 0); /* reserved (flags?) */ mb_put_uint32le(mbp, totpcount); mb_put_uint32le(mbp, totdcount); mb_put_uint32le(mbp, ntp->nt_maxpcount); mb_put_uint32le(mbp, ntp->nt_maxdcount); len = mb_fixhdr(mbp); /* * now we have known packet size as * ALIGN4(len + 4 * 4 + 1 + 2 + ((totscount+1)&~1) + 2), * and need to decide which parts should go into the first request */ len = ALIGN4(len + 4 * 4 + 1 + 2 + ((totscount+1)&~1) + 2); if (len + leftpcount > txmax) { txpcount = min(leftpcount, txmax - len); poff = len; txdcount = 0; doff = 0; } else { txpcount = leftpcount; poff = txpcount ? len : 0; len = ALIGN4(len + txpcount); txdcount = min(leftdcount, txmax - len); doff = txdcount ? len : 0; } leftpcount -= txpcount; leftdcount -= txdcount; mb_put_uint32le(mbp, txpcount); mb_put_uint32le(mbp, poff); mb_put_uint32le(mbp, txdcount); mb_put_uint32le(mbp, doff); mb_put_uint8(mbp, (totscount+1)/2); mb_put_uint16le(mbp, ntp->nt_function); if (totscount) { error = md_get_mbuf(&mbsetup, totscount, &m); SMBSDEBUG("%d:%d:%d\n", error, totscount, txmax); if (error) goto freerq; mb_put_mbuf(mbp, m); if (totscount & 1) mb_put_uint8(mbp, 0); /* setup is in words */ } smb_rq_wend(rqp); smb_rq_bstart(rqp); len = mb_fixhdr(mbp); if (txpcount) { mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); error = md_get_mbuf(&mbparam, txpcount, &m); SMBSDEBUG("%d:%d:%d\n", error, txpcount, txmax); if (error) goto freerq; mb_put_mbuf(mbp, m); } len = mb_fixhdr(mbp); if (txdcount) { mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); error = md_get_mbuf(&mbdata, txdcount, &m); if (error) goto freerq; mb_put_mbuf(mbp, m); } smb_rq_bend(rqp); /* incredible, but thats it... */ error = smb_rq_enqueue(rqp); if (error) goto freerq; if (leftpcount || leftdcount) { error = smb_rq_reply(rqp); if (error) goto bad; /* * this is an interim response, ignore it. */ SMBRQ_LOCK(rqp); md_next_record(&rqp->sr_rp); SMBRQ_UNLOCK(rqp); } while (leftpcount || leftdcount) { error = smb_rq_new(rqp, SMB_COM_NT_TRANSACT_SECONDARY); if (error) goto bad; mbp = &rqp->sr_rq; smb_rq_wstart(rqp); mb_put_mem(mbp, NULL, 3, MB_MZERO); mb_put_uint32le(mbp, totpcount); mb_put_uint32le(mbp, totdcount); len = mb_fixhdr(mbp); /* * now we have known packet size as * ALIGN4(len + 6 * 4 + 2) * and need to decide which parts should go into request */ len = ALIGN4(len + 6 * 4 + 2); if (len + leftpcount > txmax) { txpcount = min(leftpcount, txmax - len); poff = len; txdcount = 0; doff = 0; } else { txpcount = leftpcount; poff = txpcount ? len : 0; len = ALIGN4(len + txpcount); txdcount = min(leftdcount, txmax - len); doff = txdcount ? len : 0; } mb_put_uint32le(mbp, txpcount); mb_put_uint32le(mbp, poff); mb_put_uint32le(mbp, totpcount - leftpcount); mb_put_uint32le(mbp, txdcount); mb_put_uint32le(mbp, doff); mb_put_uint32le(mbp, totdcount - leftdcount); leftpcount -= txpcount; leftdcount -= txdcount; smb_rq_wend(rqp); smb_rq_bstart(rqp); len = mb_fixhdr(mbp); if (txpcount) { mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); error = md_get_mbuf(&mbparam, txpcount, &m); if (error) goto bad; mb_put_mbuf(mbp, m); } len = mb_fixhdr(mbp); if (txdcount) { mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); error = md_get_mbuf(&mbdata, txdcount, &m); if (error) goto bad; mb_put_mbuf(mbp, m); } smb_rq_bend(rqp); error = smb_iod_multirq(rqp); if (error) goto bad; } /* while left params or data */ error = smb_nt_reply(ntp); if (error && !(ntp->nt_flags & SMBT2_MOREDATA)) goto bad; mdp = &ntp->nt_rdata; if (mdp->md_top) { m_fixhdr(mdp->md_top); md_initm(mdp, mdp->md_top); } mdp = &ntp->nt_rparam; if (mdp->md_top) { m_fixhdr(mdp->md_top); md_initm(mdp, mdp->md_top); } bad: smb_iod_removerq(rqp); freerq: if (error && !(ntp->nt_flags & SMBT2_MOREDATA)) { if (rqp->sr_flags & SMBR_RESTART) ntp->nt_flags |= SMBT2_RESTART; md_done(&ntp->nt_rparam); md_done(&ntp->nt_rdata); } smb_rq_done(rqp); return (error); }
/* * Perform a full round of TRANS2 request */ static int smb_t2_request_int(struct smb_t2rq *t2p) { struct smb_vc *vcp = t2p->t2_vc; struct smb_cred *scred = t2p->t2_cred; struct mbchain *mbp; struct mdchain *mdp, mbparam, mbdata; struct mbuf *m; struct smb_rq *rqp; int totpcount, leftpcount, totdcount, leftdcount, len, txmax, i; int error, doff, poff, txdcount, txpcount, nmlen; m = t2p->t2_tparam.mb_top; if (m) { md_initm(&mbparam, m); /* do not free it! */ totpcount = m_fixhdr(m); if (totpcount > 0xffff) /* maxvalue for u_short */ return EINVAL; } else totpcount = 0; m = t2p->t2_tdata.mb_top; if (m) { md_initm(&mbdata, m); /* do not free it! */ totdcount = m_fixhdr(m); if (totdcount > 0xffff) return EINVAL; } else totdcount = 0; leftdcount = totdcount; leftpcount = totpcount; txmax = vcp->vc_txmax; error = smb_rq_alloc(t2p->t2_source, t2p->t_name ? SMB_COM_TRANSACTION : SMB_COM_TRANSACTION2, scred, &rqp); if (error) return error; rqp->sr_flags |= SMBR_MULTIPACKET; t2p->t2_rq = rqp; rqp->sr_t2 = t2p; mbp = &rqp->sr_rq; smb_rq_wstart(rqp); mb_put_uint16le(mbp, totpcount); mb_put_uint16le(mbp, totdcount); mb_put_uint16le(mbp, t2p->t2_maxpcount); mb_put_uint16le(mbp, t2p->t2_maxdcount); mb_put_uint8(mbp, t2p->t2_maxscount); mb_put_uint8(mbp, 0); /* reserved */ mb_put_uint16le(mbp, 0); /* flags */ mb_put_uint32le(mbp, 0); /* Timeout */ mb_put_uint16le(mbp, 0); /* reserved 2 */ len = mb_fixhdr(mbp); /* * now we have known packet size as * ALIGN4(len + 5 * 2 + setupcount * 2 + 2 + strlen(name) + 1), * and need to decide which parts should go into the first request */ nmlen = t2p->t_name ? strlen(t2p->t_name) : 0; len = ALIGN4(len + 5 * 2 + t2p->t2_setupcount * 2 + 2 + nmlen + 1); if (len + leftpcount > txmax) { txpcount = min(leftpcount, txmax - len); poff = len; txdcount = 0; doff = 0; } else { txpcount = leftpcount; poff = txpcount ? len : 0; len = ALIGN4(len + txpcount); txdcount = min(leftdcount, txmax - len); doff = txdcount ? len : 0; } leftpcount -= txpcount; leftdcount -= txdcount; mb_put_uint16le(mbp, txpcount); mb_put_uint16le(mbp, poff); mb_put_uint16le(mbp, txdcount); mb_put_uint16le(mbp, doff); mb_put_uint8(mbp, t2p->t2_setupcount); mb_put_uint8(mbp, 0); for (i = 0; i < t2p->t2_setupcount; i++) mb_put_uint16le(mbp, t2p->t2_setupdata[i]); smb_rq_wend(rqp); smb_rq_bstart(rqp); /* TDUNICODE */ if (t2p->t_name) mb_put_mem(mbp, t2p->t_name, nmlen, MB_MSYSTEM); mb_put_uint8(mbp, 0); /* terminating zero */ len = mb_fixhdr(mbp); if (txpcount) { mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); error = md_get_mbuf(&mbparam, txpcount, &m); SMBSDEBUG("%d:%d:%d\n", error, txpcount, txmax); if (error) goto freerq; mb_put_mbuf(mbp, m); } len = mb_fixhdr(mbp); if (txdcount) { mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); error = md_get_mbuf(&mbdata, txdcount, &m); if (error) goto freerq; mb_put_mbuf(mbp, m); } smb_rq_bend(rqp); /* incredible, but thats it... */ error = smb_rq_enqueue(rqp); if (error) goto freerq; if (leftpcount == 0 && leftdcount == 0) t2p->t2_flags |= SMBT2_ALLSENT; error = smb_t2_reply(t2p); if (error) goto bad; while (leftpcount || leftdcount) { t2p->t2_flags |= SMBT2_SECONDARY; error = smb_rq_new(rqp, t2p->t_name ? SMB_COM_TRANSACTION_SECONDARY : SMB_COM_TRANSACTION2_SECONDARY); if (error) goto bad; mbp = &rqp->sr_rq; smb_rq_wstart(rqp); mb_put_uint16le(mbp, totpcount); mb_put_uint16le(mbp, totdcount); len = mb_fixhdr(mbp); /* * now we have known packet size as * ALIGN4(len + 7 * 2 + 2) for T2 request, and -2 for T one, * and need to decide which parts should go into request */ len = ALIGN4(len + 6 * 2 + 2); if (t2p->t_name == NULL) len += 2; if (len + leftpcount > txmax) { txpcount = min(leftpcount, txmax - len); poff = len; txdcount = 0; doff = 0; } else { txpcount = leftpcount; poff = txpcount ? len : 0; len = ALIGN4(len + txpcount); txdcount = min(leftdcount, txmax - len); doff = txdcount ? len : 0; } mb_put_uint16le(mbp, txpcount); mb_put_uint16le(mbp, poff); mb_put_uint16le(mbp, totpcount - leftpcount); mb_put_uint16le(mbp, txdcount); mb_put_uint16le(mbp, doff); mb_put_uint16le(mbp, totdcount - leftdcount); leftpcount -= txpcount; leftdcount -= txdcount; if (t2p->t_name == NULL) mb_put_uint16le(mbp, t2p->t2_fid); smb_rq_wend(rqp); smb_rq_bstart(rqp); mb_put_uint8(mbp, 0); /* name */ len = mb_fixhdr(mbp); if (txpcount) { mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); error = md_get_mbuf(&mbparam, txpcount, &m); if (error) goto bad; mb_put_mbuf(mbp, m); } len = mb_fixhdr(mbp); if (txdcount) { mb_put_mem(mbp, NULL, ALIGN4(len) - len, MB_MZERO); error = md_get_mbuf(&mbdata, txdcount, &m); if (error) goto bad; mb_put_mbuf(mbp, m); } smb_rq_bend(rqp); rqp->sr_state = SMBRQ_NOTSENT; error = smb_iod_request(vcp->vc_iod, SMBIOD_EV_NEWRQ, NULL); if (error) goto bad; } /* while left params or data */ t2p->t2_flags |= SMBT2_ALLSENT; mdp = &t2p->t2_rdata; if (mdp->md_top) { m_fixhdr(mdp->md_top); md_initm(mdp, mdp->md_top); } mdp = &t2p->t2_rparam; if (mdp->md_top) { m_fixhdr(mdp->md_top); md_initm(mdp, mdp->md_top); } bad: smb_iod_removerq(rqp); freerq: smb_rq_done(rqp); if (error) { if (rqp->sr_flags & SMBR_RESTART) t2p->t2_flags |= SMBT2_RESTART; md_done(&t2p->t2_rparam); md_done(&t2p->t2_rdata); } return error; }