/* * queue a wbsrv_call reply on a wbsrv_connection * NOTE: that this implies talloc_free(call), * use talloc_reference(call) if you need it after * calling wbsrv_queue_reply */ NTSTATUS wbsrv_samba3_send_reply(struct wbsrv_samba3_call *call) { struct wbsrv_connection *wbsrv_conn = call->wbconn; struct tevent_req *subreq; NTSTATUS status; status = wbsrv_samba3_push_reply(call); NT_STATUS_NOT_OK_RETURN(status); call->out_iov[0].iov_base = (char *) call->out.data; call->out_iov[0].iov_len = call->out.length; subreq = tstream_writev_queue_send(call, wbsrv_conn->conn->event.ctx, wbsrv_conn->tstream, wbsrv_conn->send_queue, call->out_iov, 1); if (subreq == NULL) { wbsrv_terminate_connection(wbsrv_conn, "wbsrv_call_loop: " "no memory for tstream_writev_queue_send"); return NT_STATUS_NO_MEMORY; } tevent_req_set_callback(subreq, wbsrv_samba3_send_reply_done, call); return status; }
static void wreplsrv_call_loop(struct tevent_req *subreq) { struct wreplsrv_in_connection *wrepl_conn = tevent_req_callback_data(subreq, struct wreplsrv_in_connection); struct wreplsrv_in_call *call; NTSTATUS status; call = talloc_zero(wrepl_conn, struct wreplsrv_in_call); if (call == NULL) { wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_call_loop: " "no memory for wrepl_samba3_call"); return; } call->wreplconn = wrepl_conn; status = tstream_read_pdu_blob_recv(subreq, call, &call->in); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { const char *reason; reason = talloc_asprintf(call, "wreplsrv_call_loop: " "tstream_read_pdu_blob_recv() - %s", nt_errstr(status)); if (!reason) { reason = nt_errstr(status); } wreplsrv_terminate_in_connection(wrepl_conn, reason); return; } DEBUG(10,("Received wrepl packet of length %lu from %s\n", (long) call->in.length, tsocket_address_string(wrepl_conn->conn->remote_address, call))); /* skip length header */ call->in.data += 4; call->in.length -= 4; status = wreplsrv_process(wrepl_conn, &call); if (!NT_STATUS_IS_OK(status)) { const char *reason; reason = talloc_asprintf(call, "wreplsrv_call_loop: " "tstream_read_pdu_blob_recv() - %s", nt_errstr(status)); if (reason == NULL) { reason = nt_errstr(status); } wreplsrv_terminate_in_connection(wrepl_conn, reason); return; } /* We handed over the connection so we're done here */ if (wrepl_conn->tstream == NULL) { return; } /* Invalid WINS-Replication packet, we just ignore it */ if (call == NULL) { goto noreply; } call->out_iov[0].iov_base = (char *) call->out.data; call->out_iov[0].iov_len = call->out.length; subreq = tstream_writev_queue_send(call, wrepl_conn->conn->event.ctx, wrepl_conn->tstream, wrepl_conn->send_queue, call->out_iov, 1); if (subreq == NULL) { wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_call_loop: " "no memory for tstream_writev_queue_send"); return; } tevent_req_set_callback(subreq, wreplsrv_call_writev_done, call); noreply: /* * The wrepl pdu's has the length as 4 byte (initial_read_size), * provides the pdu length then. */ subreq = tstream_read_pdu_blob_send(wrepl_conn, wrepl_conn->conn->event.ctx, wrepl_conn->tstream, 4, /* initial_read_size */ packet_full_request_u32, wrepl_conn); if (subreq == NULL) { wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_call_loop: " "no memory for tstream_read_pdu_blob_send"); return; } tevent_req_set_callback(subreq, wreplsrv_call_loop, wrepl_conn); }
static void ldapsrv_call_process_done(struct tevent_req *subreq) { struct ldapsrv_call *call = tevent_req_callback_data(subreq, struct ldapsrv_call); struct ldapsrv_connection *conn = call->conn; NTSTATUS status; DATA_BLOB blob = data_blob_null; conn->active_call = NULL; status = ldapsrv_process_call_recv(subreq); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { ldapsrv_terminate_connection(conn, nt_errstr(status)); return; } /* build all the replies into a single blob */ while (call->replies) { DATA_BLOB b; bool ret; if (!ldap_encode(call->replies->msg, samba_ldap_control_handlers(), &b, call)) { DEBUG(0,("Failed to encode ldap reply of type %d\n", call->replies->msg->type)); ldapsrv_terminate_connection(conn, "ldap_encode failed"); return; } ret = data_blob_append(call, &blob, b.data, b.length); data_blob_free(&b); talloc_set_name_const(blob.data, "Outgoing, encoded LDAP packet"); if (!ret) { ldapsrv_terminate_connection(conn, "data_blob_append failed"); return; } DLIST_REMOVE(call->replies, call->replies); } if (blob.length == 0) { TALLOC_FREE(call); ldapsrv_call_read_next(conn); return; } call->out_iov.iov_base = blob.data; call->out_iov.iov_len = blob.length; subreq = tstream_writev_queue_send(call, conn->connection->event.ctx, conn->sockets.active, conn->sockets.send_queue, &call->out_iov, 1); if (subreq == NULL) { ldapsrv_terminate_connection(conn, "stream_writev_queue_send failed"); return; } tevent_req_set_callback(subreq, ldapsrv_call_writev_done, call); }
static void kdc_tcp_call_proxy_done(struct tevent_req *subreq) { struct kdc_tcp_call *call = tevent_req_callback_data(subreq, struct kdc_tcp_call); struct kdc_tcp_connection *kdc_conn = call->kdc_conn; NTSTATUS status; status = kdc_tcp_proxy_recv(subreq, call, &call->out); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { /* generate an error packet */ status = kdc_proxy_unavailable_error(kdc_conn->kdc_socket->kdc, call, &call->out); } if (!NT_STATUS_IS_OK(status)) { const char *reason; reason = talloc_asprintf(call, "kdc_tcp_call_proxy_done: " "kdc_proxy_unavailable_error - %s", nt_errstr(status)); if (!reason) { reason = "kdc_tcp_call_proxy_done: kdc_proxy_unavailable_error() failed"; } kdc_tcp_terminate_connection(call->kdc_conn, reason); return; } /* First add the length of the out buffer */ RSIVAL(call->out_hdr, 0, call->out.length); call->out_iov[0].iov_base = (char *) call->out_hdr; call->out_iov[0].iov_len = 4; call->out_iov[1].iov_base = (char *) call->out.data; call->out_iov[1].iov_len = call->out.length; subreq = tstream_writev_queue_send(call, kdc_conn->conn->event.ctx, kdc_conn->tstream, kdc_conn->send_queue, call->out_iov, 2); if (subreq == NULL) { kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: " "no memory for tstream_writev_queue_send"); return; } tevent_req_set_callback(subreq, kdc_tcp_call_writev_done, call); /* * The krb5 tcp pdu's has the length as 4 byte (initial_read_size), * packet_full_request_u32 provides the pdu length then. */ subreq = tstream_read_pdu_blob_send(kdc_conn, kdc_conn->conn->event.ctx, kdc_conn->tstream, 4, /* initial_read_size */ packet_full_request_u32, kdc_conn); if (subreq == NULL) { kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: " "no memory for tstream_read_pdu_blob_send"); return; } tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn); }
static void kdc_tcp_call_loop(struct tevent_req *subreq) { struct kdc_tcp_connection *kdc_conn = tevent_req_callback_data(subreq, struct kdc_tcp_connection); struct kdc_tcp_call *call; NTSTATUS status; enum kdc_process_ret ret; call = talloc(kdc_conn, struct kdc_tcp_call); if (call == NULL) { kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: " "no memory for kdc_tcp_call"); return; } call->kdc_conn = kdc_conn; status = tstream_read_pdu_blob_recv(subreq, call, &call->in); TALLOC_FREE(subreq); if (!NT_STATUS_IS_OK(status)) { const char *reason; reason = talloc_asprintf(call, "kdc_tcp_call_loop: " "tstream_read_pdu_blob_recv() - %s", nt_errstr(status)); if (!reason) { reason = nt_errstr(status); } kdc_tcp_terminate_connection(kdc_conn, reason); return; } DEBUG(10,("Received krb5 TCP packet of length %lu from %s\n", (long) call->in.length, tsocket_address_string(kdc_conn->conn->remote_address, call))); /* skip length header */ call->in.data +=4; call->in.length -= 4; /* Call krb5 */ ret = kdc_conn->kdc_socket->process(kdc_conn->kdc_socket->kdc, call, &call->in, &call->out, kdc_conn->conn->remote_address, kdc_conn->conn->local_address, 0 /* Stream */); if (ret == KDC_PROCESS_FAILED) { kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: process function failed"); return; } if (ret == KDC_PROCESS_PROXY) { uint16_t port; if (!kdc_conn->kdc_socket->kdc->am_rodc) { kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: proxying requested when not RODC"); return; } port = tsocket_address_inet_port(kdc_conn->conn->local_address); subreq = kdc_tcp_proxy_send(call, kdc_conn->conn->event.ctx, kdc_conn->kdc_socket->kdc, port, call->in); if (subreq == NULL) { kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: kdc_tcp_proxy_send failed"); return; } tevent_req_set_callback(subreq, kdc_tcp_call_proxy_done, call); return; } /* First add the length of the out buffer */ RSIVAL(call->out_hdr, 0, call->out.length); call->out_iov[0].iov_base = (char *) call->out_hdr; call->out_iov[0].iov_len = 4; call->out_iov[1].iov_base = (char *) call->out.data; call->out_iov[1].iov_len = call->out.length; subreq = tstream_writev_queue_send(call, kdc_conn->conn->event.ctx, kdc_conn->tstream, kdc_conn->send_queue, call->out_iov, 2); if (subreq == NULL) { kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: " "no memory for tstream_writev_queue_send"); return; } tevent_req_set_callback(subreq, kdc_tcp_call_writev_done, call); /* * The krb5 tcp pdu's has the length as 4 byte (initial_read_size), * packet_full_request_u32 provides the pdu length then. */ subreq = tstream_read_pdu_blob_send(kdc_conn, kdc_conn->conn->event.ctx, kdc_conn->tstream, 4, /* initial_read_size */ packet_full_request_u32, kdc_conn); if (subreq == NULL) { kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: " "no memory for tstream_read_pdu_blob_send"); return; } tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn); }