+
+/*
+ Receive an alter reply from the transport
+*/
+static void dcerpc_alter_recv_data(struct dcerpc_connection *conn, struct ncacn_packet *pkt)
+{
+ struct composite_context *c;
+ struct dcerpc_pipe *pipe;
+
+ c = talloc_get_type(conn->alter_private, struct composite_context);
+ pipe = talloc_get_type(c->private_data, struct dcerpc_pipe);
+
+ /* mark the connection as not waiting for a alter context reply */
+ conn->alter_private = NULL;
+
+ if (pkt->ptype == DCERPC_PKT_ALTER_RESP &&
+ pkt->u.alter_resp.num_results == 1 &&
+ pkt->u.alter_resp.ctx_list[0].result != 0) {
+ DEBUG(2,("dcerpc: alter_resp failed - reason %d\n",
+ pkt->u.alter_resp.ctx_list[0].reason));
+ composite_error(c, dcerpc_map_reason(pkt->u.alter_resp.ctx_list[0].reason));
+ return;
+ }
+
+ if (pkt->ptype != DCERPC_PKT_ALTER_RESP ||
+ pkt->u.alter_resp.num_results == 0 ||
+ pkt->u.alter_resp.ctx_list[0].result != 0) {
+ composite_error(c, NT_STATUS_UNSUCCESSFUL);
+ return;
+ }
+
+ /* the alter_resp might contain a reply set of credentials */
+ if (pipe->conn->security_state.auth_info &&
+ pkt->u.alter_resp.auth_info.length) {
+ c->status = ndr_pull_struct_blob(
+ &pkt->u.alter_resp.auth_info, pipe,
+ pipe->conn->security_state.auth_info,
+ (ndr_pull_flags_fn_t)ndr_pull_dcerpc_auth);
+ if (!composite_is_ok(c)) return;
+ }
+
+ composite_done(c);
+}
+
+/*
+ send a dcerpc alter_context request
+*/
+struct composite_context *dcerpc_alter_context_send(struct dcerpc_pipe *p,
+ TALLOC_CTX *mem_ctx,
+ const struct dcerpc_syntax_id *syntax,
+ const struct dcerpc_syntax_id *transfer_syntax)
+{
+ struct composite_context *c;
+ struct ncacn_packet pkt;
+ DATA_BLOB blob;
+
+ c = talloc_zero(mem_ctx, struct composite_context);
+ if (c == NULL) return NULL;
+
+ c->state = COMPOSITE_STATE_IN_PROGRESS;
+ c->private_data = p;
+ c->event_ctx = p->conn->event_ctx;
+
+ p->syntax = *syntax;
+ p->transfer_syntax = *transfer_syntax;
+
+ init_ncacn_hdr(p->conn, &pkt);
+
+ pkt.ptype = DCERPC_PKT_ALTER;
+ pkt.pfc_flags = DCERPC_PFC_FLAG_FIRST | DCERPC_PFC_FLAG_LAST;
+ pkt.call_id = p->conn->call_id;
+ pkt.auth_length = 0;
+
+ pkt.u.alter.max_xmit_frag = 5840;
+ pkt.u.alter.max_recv_frag = 5840;
+ pkt.u.alter.assoc_group_id = 0;
+ pkt.u.alter.num_contexts = 1;
+ pkt.u.alter.ctx_list = talloc_array(mem_ctx,
+ struct dcerpc_ctx_list, 1);
+ if (pkt.u.alter.ctx_list == NULL) {
+ c->status = NT_STATUS_NO_MEMORY;
+ goto failed;
+ }
+ pkt.u.alter.ctx_list[0].context_id = p->context_id;
+ pkt.u.alter.ctx_list[0].num_transfer_syntaxes = 1;
+ pkt.u.alter.ctx_list[0].abstract_syntax = p->syntax;
+ pkt.u.alter.ctx_list[0].transfer_syntaxes = &p->transfer_syntax;
+ pkt.u.alter.auth_info = data_blob(NULL, 0);
+
+ /* construct the NDR form of the packet */
+ c->status = ncacn_push_auth(&blob, mem_ctx, &pkt,
+ p->conn->security_state.auth_info);
+ if (!NT_STATUS_IS_OK(c->status)) {
+ goto failed;
+ }
+
+ p->conn->transport.recv_data = dcerpc_recv_data;
+ p->conn->alter_private = c;
+
+ c->status = p->conn->transport.send_request(p->conn, &blob, True);
+ if (!NT_STATUS_IS_OK(c->status)) {
+ goto failed;
+ }
+
+ event_add_timed(c->event_ctx, c,
+ timeval_current_ofs(DCERPC_REQUEST_TIMEOUT, 0),
+ bind_timeout_handler, c);
+
+ return c;
+
+ failed:
+ composite_error(c, c->status);
+ return c;
+}
+
+NTSTATUS dcerpc_alter_context_recv(struct composite_context *ctx)
+{
+ NTSTATUS result = composite_wait(ctx);
+ talloc_free(ctx);
+ return result;
+}
+
+/*
+ send a dcerpc alter_context request
+*/
+NTSTATUS dcerpc_alter_context(struct dcerpc_pipe *p,
+ TALLOC_CTX *mem_ctx,
+ const struct dcerpc_syntax_id *syntax,
+ const struct dcerpc_syntax_id *transfer_syntax)
+{
+ struct composite_context *creq;
+ creq = dcerpc_alter_context_send(p, mem_ctx, syntax, transfer_syntax);
+ return dcerpc_alter_context_recv(creq);
+}