]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
lib/tsocket: allow only one tstream_disconnect_send/recv
authorStefan Metzmacher <metze@samba.org>
Fri, 16 May 2025 08:04:25 +0000 (10:04 +0200)
committerStefan Metzmacher <metze@samba.org>
Wed, 18 Jun 2025 17:52:37 +0000 (17:52 +0000)
And don't allow readv and writev anymore.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Volker Lendecke <vl@samba.org>
lib/tsocket/tsocket.c

index 9a734b2739f5f15d81a979c73d588a8a419bc5e2..92d8e9272637c4874df5af16b9991f9311f7aed5 100644 (file)
@@ -445,6 +445,7 @@ struct tstream_context {
 
        struct tevent_req *readv_req;
        struct tevent_req *writev_req;
+       struct tevent_req *disconnect_req;
 };
 
 static int tstream_context_destructor(struct tstream_context *stream)
@@ -457,6 +458,10 @@ static int tstream_context_destructor(struct tstream_context *stream)
                tevent_req_received(stream->writev_req);
        }
 
+       if (stream->disconnect_req != NULL) {
+               tevent_req_received(stream->disconnect_req);
+       }
+
        return 0;
 }
 
@@ -479,6 +484,7 @@ struct tstream_context *_tstream_context_create(TALLOC_CTX *mem_ctx,
        stream->ops             = ops;
        stream->readv_req       = NULL;
        stream->writev_req      = NULL;
+       stream->disconnect_req  = NULL;
 
        state = talloc_size(stream, psize);
        if (state == NULL) {
@@ -566,6 +572,11 @@ struct tevent_req *tstream_readv_send(TALLOC_CTX *mem_ctx,
                goto post;
        }
 
+       if (stream->disconnect_req != NULL) {
+               tevent_req_error(req, ECONNABORTED);
+               goto post;
+       }
+
        if (stream->readv_req) {
                tevent_req_error(req, EBUSY);
                goto post;
@@ -684,6 +695,11 @@ struct tevent_req *tstream_writev_send(TALLOC_CTX *mem_ctx,
                goto post;
        }
 
+       if (stream->disconnect_req != NULL) {
+               tevent_req_error(req, ECONNABORTED);
+               goto post;
+       }
+
        if (stream->writev_req) {
                tevent_req_error(req, EBUSY);
                goto post;
@@ -743,8 +759,23 @@ int tstream_writev_recv(struct tevent_req *req,
 
 struct tstream_disconnect_state {
        const struct tstream_context_ops *ops;
+       struct tstream_context *stream;
 };
 
+static void tstream_disconnect_cleanup(struct tevent_req *req,
+                                      enum tevent_req_state req_state)
+{
+       struct tstream_disconnect_state *state = tevent_req_data(req,
+                                                struct tstream_disconnect_state);
+
+       if (state->stream != NULL) {
+               state->stream->disconnect_req = NULL;
+               state->stream = NULL;
+       }
+
+       return;
+}
+
 static void tstream_disconnect_done(struct tevent_req *subreq);
 
 struct tevent_req *tstream_disconnect_send(TALLOC_CTX *mem_ctx,
@@ -762,12 +793,21 @@ struct tevent_req *tstream_disconnect_send(TALLOC_CTX *mem_ctx,
        }
 
        state->ops = stream->ops;
+       state->stream = stream;
 
        if (stream->readv_req || stream->writev_req) {
                tevent_req_error(req, EBUSY);
                goto post;
        }
 
+       if (stream->disconnect_req != NULL) {
+               tevent_req_error(req, EALREADY);
+               goto post;
+       }
+       stream->disconnect_req = req;
+
+       tevent_req_set_cleanup_fn(req, tstream_disconnect_cleanup);
+
        subreq = state->ops->disconnect_send(state, ev, stream);
        if (tevent_req_nomem(subreq, req)) {
                goto post;