/* * This is the SMB2 handler for new smb requests, called from * smb_session_reader after SMB negotiate is done. For most SMB2 * requests, we just enqueue them for the smb_session_worker to * execute via the task queue, so they can block for resources * without stopping the reader thread. A few protocol messages * are special cases and are handled directly here in the reader * thread so they don't wait for taskq scheduling. * * This function must either enqueue the new request for * execution via the task queue, or execute it directly * and then free it. If this returns non-zero, the caller * will drop the session. */ int smb2sr_newrq(smb_request_t *sr) { uint32_t magic; uint16_t command; int rc; magic = LE_IN32(sr->sr_request_buf); if (magic != SMB2_PROTOCOL_MAGIC) { smb_request_free(sr); /* will drop the connection */ return (EPROTO); } /* * Execute Cancel requests immediately, (here in the * reader thread) so they won't wait for any other * commands we might already have in the task queue. * Cancel also skips signature verification and * does not consume a sequence number. * [MS-SMB2] 3.2.4.24 Cancellation... */ command = LE_IN16((uint8_t *)sr->sr_request_buf + 12); if (command == SMB2_CANCEL) { rc = smb2sr_newrq_cancel(sr); smb_request_free(sr); return (rc); } /* * XXX With SMB3 this is supposed to increment based on * the number of credits consumed by a request. Todo */ if (sr->session->signing.flags & SMB_SIGNING_ENABLED) { /* XXX MS-SMB2 is unclear on this. todo */ sr->session->signing.seqnum++; sr->sr_seqnum = sr->session->signing.seqnum; sr->reply_seqnum = sr->sr_seqnum; } /* * Submit the request to the task queue, which calls * smb2_dispatch_request when the workload permits. */ sr->sr_time_submitted = gethrtime(); sr->sr_state = SMB_REQ_STATE_SUBMITTED; sr->work_func = smb2sr_work; smb_srqueue_waitq_enter(sr->session->s_srqueue); (void) taskq_dispatch(sr->session->s_server->sv_worker_pool, smb_session_worker, sr, TQ_SLEEP); return (0); }
/* * smb_auth_qnd_unicode * * Quick and dirty unicode conversion! * Returns the length of dst in bytes. */ int smb_auth_qnd_unicode(smb_wchar_t *dst, const char *src, int length) { int i; unsigned int count; smb_wchar_t new_char; if ((count = oemtoucs(dst, src, length, OEM_CPG_1252)) == 0) { for (i = 0; i < length; ++i) { new_char = (smb_wchar_t)src[i] & 0xff; dst[i] = LE_IN16(&new_char); } dst[i] = 0; count = length; } return (count * sizeof (smb_wchar_t)); }