/* * Build an SMB2 error response. [MS-SMB2] 2.2.2 */ void smb2sr_put_error_data(smb_request_t *sr, uint32_t status, mbuf_chain_t *mbc) { DWORD len; /* * The common dispatch code writes this when it * updates the SMB2 header before sending. */ sr->smb2_status = status; /* Rewind to the end of the SMB header. */ sr->reply.chain_offset = sr->smb2_reply_hdr + SMB2_HDR_SIZE; /* * NB: Must provide at least one byte of error data, * per [MS-SMB2] 2.2.2 */ if (mbc != NULL && (len = MBC_LENGTH(mbc)) != 0) { (void) smb_mbc_encodef( &sr->reply, "wwlC", 9, /* StructSize */ /* w */ 0, /* reserved */ /* w */ len, /* l */ mbc); /* C */ } else { (void) smb_mbc_encodef( &sr->reply, "wwl.", 9, /* StructSize */ /* w */ 0, /* reserved */ /* w */ 0); /* l. */ } }
void smb_reply_notify_change_request(smb_request_t *sr) { smb_node_t *node; smb_srqueue_t *srq; int total_bytes, n_setup, n_param, n_data; int param_off, param_pad, data_off, data_pad; struct smb_xa *xa; smb_error_t err; SMB_REQ_VALID(sr); srq = sr->session->s_srqueue; smb_srqueue_waitq_to_runq(srq); xa = sr->r_xa; node = sr->sr_ncr.nc_node; if (--node->waiting_event == 0) { node->flags &= ~(NODE_FLAGS_NOTIFY_CHANGE | NODE_FLAGS_CHANGED); smb_fem_fcn_uninstall(node); } mutex_enter(&sr->sr_mutex); switch (sr->sr_state) { case SMB_REQ_STATE_EVENT_OCCURRED: sr->sr_state = SMB_REQ_STATE_ACTIVE; /* many things changed */ (void) smb_mbc_encodef(&xa->rep_data_mb, "l", 0L); /* setup the NT transact reply */ n_setup = MBC_LENGTH(&xa->rep_setup_mb); n_param = MBC_LENGTH(&xa->rep_param_mb); n_data = MBC_LENGTH(&xa->rep_data_mb); n_setup = (n_setup + 1) / 2; /* Convert to setup words */ param_pad = 1; /* must be one */ param_off = param_pad + 32 + 37 + (n_setup << 1) + 2; /* Pad to 4 bytes */ data_pad = (4 - ((param_off + n_param) & 3)) % 4; /* Param off from hdr */ data_off = param_off + n_param + data_pad; total_bytes = param_pad + n_param + data_pad + n_data; (void) smbsr_encode_result(sr, 18+n_setup, total_bytes, "b3.llllllllbCw#.C#.C", 18 + n_setup, /* wct */ n_param, /* Total Parameter Bytes */ n_data, /* Total Data Bytes */ n_param, /* Total Parameter Bytes this buffer */ param_off, /* Param offset from header start */ 0, /* Param displacement */ n_data, /* Total Data Bytes this buffer */ data_off, /* Data offset from header start */ 0, /* Data displacement */ n_setup, /* suwcnt */ &xa->rep_setup_mb, /* setup[] */ total_bytes, /* Total data bytes */ param_pad, &xa->rep_param_mb, data_pad, &xa->rep_data_mb); break; case SMB_REQ_STATE_CANCELED: err.status = NT_STATUS_CANCELLED; err.errcls = ERRDOS; err.errcode = ERROR_OPERATION_ABORTED; smbsr_set_error(sr, &err); (void) smb_mbc_encodef(&sr->reply, "bwbw", (short)0, 0L, (short)0, 0L); sr->smb_wct = 0; sr->smb_bcc = 0; break; default: ASSERT(0); } mutex_exit(&sr->sr_mutex); /* Setup the header */ (void) smb_mbc_poke(&sr->reply, 0, SMB_HEADER_ED_FMT, sr->first_smb_com, sr->smb_rcls, sr->smb_reh, sr->smb_err, sr->smb_flg | SMB_FLAGS_REPLY, sr->smb_flg2, sr->smb_pid_high, sr->smb_sig, sr->smb_tid, sr->smb_pid, sr->smb_uid, sr->smb_mid); if (sr->session->signing.flags & SMB_SIGNING_ENABLED) smb_sign_reply(sr, NULL); /* send the reply */ DTRACE_PROBE1(ncr__reply, struct smb_request *, sr) (void) smb_session_send(sr->session, 0, &sr->reply); smbsr_cleanup(sr); mutex_enter(&sr->sr_mutex); sr->sr_state = SMB_REQ_STATE_COMPLETED; mutex_exit(&sr->sr_mutex); smb_srqueue_runq_exit(srq); smb_request_free(sr); }