+ struct ntp_signd_connection *ntp_signd_conn = tevent_req_callback_data(subreq,
+ struct ntp_signd_connection);
+ struct ntp_signd_call *call;
+ NTSTATUS status;
+
+ call = talloc(ntp_signd_conn, struct ntp_signd_call);
+ if (call == NULL) {
+ ntp_signd_terminate_connection(ntp_signd_conn,
+ "ntp_signd_call_loop: "
+ "no memory for ntp_signd_call");
+ return;
+ }
+ call->ntp_signd_conn = ntp_signd_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, "ntp_signd_call_loop: "
+ "tstream_read_pdu_blob_recv() - %s",
+ nt_errstr(status));
+ if (reason == NULL) {
+ reason = nt_errstr(status);
+ }
+
+ ntp_signd_terminate_connection(ntp_signd_conn, reason);
+ return;
+ }
+
+ DEBUG(10,("Received NTP TCP packet of length %lu from %s\n",
+ (long) call->in.length,
+ tsocket_address_string(ntp_signd_conn->conn->remote_address, call)));
+
+ /* skip length header */
+ call->in.data +=4;
+ call->in.length -= 4;
+
+ status = ntp_signd_process(ntp_signd_conn,
+ call,
+ &call->in,
+ &call->out);
+ if (! NT_STATUS_IS_OK(status)) {
+ const char *reason;
+
+ reason = talloc_asprintf(call, "ntp_signd_process failed: %s",
+ nt_errstr(status));
+ if (reason == NULL) {
+ reason = nt_errstr(status);
+ }
+
+ ntp_signd_terminate_connection(ntp_signd_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 = call->out_hdr;
+ call->out_iov[0].iov_len = 4;
+
+ call->out_iov[1].iov_base = call->out.data;
+ call->out_iov[1].iov_len = call->out.length;
+
+ subreq = tstream_writev_queue_send(call,
+ ntp_signd_conn->conn->event.ctx,
+ ntp_signd_conn->tstream,
+ ntp_signd_conn->send_queue,
+ call->out_iov, 2);
+ if (subreq == NULL) {
+ ntp_signd_terminate_connection(ntp_signd_conn, "ntp_signd_call_loop: "
+ "no memory for tstream_writev_queue_send");
+ return;
+ }
+
+ tevent_req_set_callback(subreq, ntp_signd_call_writev_done, call);
+
+ /*
+ * The NTP 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(ntp_signd_conn,
+ ntp_signd_conn->conn->event.ctx,
+ ntp_signd_conn->tstream,
+ 4, /* initial_read_size */
+ packet_full_request_u32,
+ ntp_signd_conn);
+ if (subreq == NULL) {
+ ntp_signd_terminate_connection(ntp_signd_conn, "ntp_signd_call_loop: "
+ "no memory for tstream_read_pdu_blob_send");
+ return;
+ }
+ tevent_req_set_callback(subreq, ntp_signd_call_loop, ntp_signd_conn);
+}
+
+static void ntp_signd_call_writev_done(struct tevent_req *subreq)
+{
+ struct ntp_signd_call *call = tevent_req_callback_data(subreq,
+ struct ntp_signd_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, "ntp_signd_call_writev_done: "
+ "tstream_writev_queue_recv() - %d:%s",
+ sys_errno, strerror(sys_errno));
+ if (!reason) {
+ reason = "ntp_signd_call_writev_done: "
+ "tstream_writev_queue_recv() failed";
+ }
+
+ ntp_signd_terminate_connection(call->ntp_signd_conn, reason);
+ return;
+ }
+
+ /* We don't care about errors */
+
+ talloc_free(call);