/* called when we can write to a connection */ static void wbsrv_send(struct stream_connection *conn, uint16_t flags) { struct wbsrv_connection *wbsrv_conn = talloc_get_type(conn->private_data, struct wbsrv_connection); /* this should never be triggered! */ wbsrv_terminate_connection(wbsrv_conn, "wbsrv_send: called"); }
static void wbsrv_accept(struct stream_connection *conn) { struct wbsrv_listen_socket *listen_socket = talloc_get_type(conn->private_data, struct wbsrv_listen_socket); struct wbsrv_connection *wbconn; wbconn = talloc_zero(conn, struct wbsrv_connection); if (!wbconn) { stream_terminate_connection(conn, "wbsrv_accept: out of memory"); return; } wbconn->conn = conn; wbconn->listen_socket = listen_socket; wbconn->lp_ctx = listen_socket->service->task->lp_ctx; conn->private_data = wbconn; wbconn->packet = packet_init(wbconn); if (wbconn->packet == NULL) { wbsrv_terminate_connection(wbconn, "wbsrv_accept: out of memory"); return; } packet_set_private(wbconn->packet, wbconn); packet_set_socket(wbconn->packet, conn->socket); packet_set_callback(wbconn->packet, wbsrv_samba3_process); packet_set_full_request(wbconn->packet, wbsrv_samba3_packet_full_request); packet_set_error_handler(wbconn->packet, wbsrv_recv_error); packet_set_event_context(wbconn->packet, conn->event.ctx); packet_set_fde(wbconn->packet, conn->event.fde); packet_set_serialise(wbconn->packet); }
static void wbsrv_samba3_send_reply_done(struct tevent_req *subreq) { struct wbsrv_samba3_call *call = tevent_req_callback_data(subreq, struct wbsrv_samba3_call); int sys_errno; int rc; rc = tstream_writev_queue_recv(subreq, &sys_errno); TALLOC_FREE(subreq); if (rc == -1) { const char *reason; reason = talloc_asprintf(call, "wbsrv_samba3_send_reply_done: " "tstream_writev_queue_recv() - %d:%s", sys_errno, strerror(sys_errno)); if (reason == NULL) { reason = "wbsrv_samba3_send_reply_done: " "tstream_writev_queue_recv() failed"; } wbsrv_terminate_connection(call->wbconn, reason); return; } talloc_free(call); }
/* * 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 wbsrv_accept(struct stream_connection *conn) { struct wbsrv_listen_socket *wbsrv_socket = talloc_get_type(conn->private_data, struct wbsrv_listen_socket); struct wbsrv_connection *wbsrv_conn; struct tevent_req *subreq; int rc; wbsrv_conn = talloc_zero(conn, struct wbsrv_connection); if (wbsrv_conn == NULL) { stream_terminate_connection(conn, "wbsrv_accept: out of memory"); return; } wbsrv_conn->send_queue = tevent_queue_create(conn, "wbsrv_accept"); if (wbsrv_conn->send_queue == NULL) { stream_terminate_connection(conn, "wbsrv_accept: out of memory"); return; } TALLOC_FREE(conn->event.fde); rc = tstream_bsd_existing_socket(wbsrv_conn, socket_get_fd(conn->socket), &wbsrv_conn->tstream); if (rc < 0) { stream_terminate_connection(conn, "wbsrv_accept: out of memory"); return; } wbsrv_conn->conn = conn; wbsrv_conn->listen_socket = wbsrv_socket; wbsrv_conn->lp_ctx = wbsrv_socket->service->task->lp_ctx; conn->private_data = wbsrv_conn; /* * The winbind pdu's has the length as 4 byte (initial_read_size), * wbsrv_samba3_packet_full_request provides the pdu length then. */ subreq = tstream_read_pdu_blob_send(wbsrv_conn, wbsrv_conn->conn->event.ctx, wbsrv_conn->tstream, 4, /* initial_read_size */ wbsrv_samba3_packet_full_request, wbsrv_conn); if (subreq == NULL) { wbsrv_terminate_connection(wbsrv_conn, "wbsrv_accept: " "no memory for tstream_read_pdu_blob_send"); return; } tevent_req_set_callback(subreq, wbsrv_call_loop, wbsrv_conn); }
/* * 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 *wbconn = call->wbconn; DATA_BLOB rep; NTSTATUS status; status = wbsrv_samba3_push_reply(call, call, &rep); NT_STATUS_NOT_OK_RETURN(status); status = packet_send(call->wbconn->packet, rep); talloc_free(call); if (!NT_STATUS_IS_OK(status)) { wbsrv_terminate_connection(wbconn, "failed to packet_send winbindd reply"); return status; } /* the call isn't needed any more */ return status; }
static void wbsrv_call_loop(struct tevent_req *subreq) { struct wbsrv_connection *wbsrv_conn = tevent_req_callback_data(subreq, struct wbsrv_connection); struct wbsrv_samba3_call *call; NTSTATUS status; call = talloc_zero(wbsrv_conn, struct wbsrv_samba3_call); if (call == NULL) { wbsrv_terminate_connection(wbsrv_conn, "wbsrv_call_loop: " "no memory for wbsrv_samba3_call"); return; } call->wbconn = wbsrv_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(wbsrv_conn, "wbsrv_call_loop: " "tstream_read_pdu_blob_recv() - %s", nt_errstr(status)); if (!reason) { reason = nt_errstr(status); } wbsrv_terminate_connection(wbsrv_conn, reason); return; } DEBUG(10,("Received winbind TCP packet of length %lu from %s\n", (long) call->in.length, tsocket_address_string(wbsrv_conn->conn->remote_address, call))); status = wbsrv_samba3_process(call); if (!NT_STATUS_IS_OK(status)) { const char *reason; reason = talloc_asprintf(wbsrv_conn, "wbsrv_call_loop: " "tstream_read_pdu_blob_recv() - %s", nt_errstr(status)); if (!reason) { reason = nt_errstr(status); } wbsrv_terminate_connection(wbsrv_conn, reason); return; } /* * The winbind pdu's has the length as 4 byte (initial_read_size), * wbsrv_samba3_packet_full_request provides the pdu length then. */ subreq = tstream_read_pdu_blob_send(wbsrv_conn, wbsrv_conn->conn->event.ctx, wbsrv_conn->tstream, 4, /* initial_read_size */ wbsrv_samba3_packet_full_request, wbsrv_conn); if (subreq == NULL) { wbsrv_terminate_connection(wbsrv_conn, "wbsrv_call_loop: " "no memory for tstream_read_pdu_blob_send"); return; } tevent_req_set_callback(subreq, wbsrv_call_loop, wbsrv_conn); }
/* called on a tcp recv */ static void wbsrv_recv(struct stream_connection *conn, uint16_t flags) { struct wbsrv_connection *wbsrv_conn = talloc_get_type(conn->private_data, struct wbsrv_connection); wbsrv_terminate_connection(wbsrv_conn, "wbsrv_recv: called"); }
/* called on a tcp recv error */ static void wbsrv_recv_error(void *private_data, NTSTATUS status) { struct wbsrv_connection *wbconn = talloc_get_type(private_data, struct wbsrv_connection); wbsrv_terminate_connection(wbconn, nt_errstr(status)); }