From 6799fde75d1ccf93171874fd33f9e89e4472fd81 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 6 Oct 2005 14:38:07 +0000 Subject: r10766: - make it possible to mark a wrepl_request as send only, used for WREPL_REPL_INFORM* messsages - make it possible to close the connection after a request was send used for WREPL_ASSOCIATION_STOP - fix the torture test that tests the assoc context handling between connections, you can issue a request and get the reply on another connection, I think we should not implement that in our server code, as I think it's a security hole, you can cause a windows server to send the replies to someone another client, that doesn't wait for data, and as there're no massage_id in the protocol the client would be confused by a replies that doesn't belong to a query metze (This used to be commit dfc95de8fa7ded8ea92cafe58cf86efcc7920156) --- source4/libcli/wrepl/winsrepl.c | 100 +++++++++++++++++++++++++++++++++++----- 1 file changed, 89 insertions(+), 11 deletions(-) (limited to 'source4/libcli/wrepl/winsrepl.c') diff --git a/source4/libcli/wrepl/winsrepl.c b/source4/libcli/wrepl/winsrepl.c index 297dccbf38..31ef1ffbeb 100644 --- a/source4/libcli/wrepl/winsrepl.c +++ b/source4/libcli/wrepl/winsrepl.c @@ -31,6 +31,7 @@ */ static void wrepl_socket_dead(struct wrepl_socket *wrepl_socket, NTSTATUS status) { + talloc_set_destructor(wrepl_socket, NULL); wrepl_socket->dead = True; if (wrepl_socket->fde) { @@ -96,9 +97,31 @@ static void wrepl_handler_send(struct wrepl_socket *wrepl_socket) return; } - DLIST_REMOVE(wrepl_socket->send_queue, req); - DLIST_ADD_END(wrepl_socket->recv_queue, req, struct wrepl_request *); - req->state = WREPL_REQUEST_RECV; + if (req->disconnect_after_send) { + DLIST_REMOVE(wrepl_socket->send_queue, req); + req->status = NT_STATUS_OK; + req->state = WREPL_REQUEST_DONE; + wrepl_socket_dead(wrepl_socket, NT_STATUS_LOCAL_DISCONNECT); + if (req->async.fn) { + req->async.fn(req); + } + return; + } + + if (req->send_only) { + DLIST_REMOVE(wrepl_socket->send_queue, req); + req->status = NT_STATUS_OK; + req->state = WREPL_REQUEST_DONE; + if (req->async.fn) { + EVENT_FD_READABLE(wrepl_socket->fde); + req->async.fn(req); + return; + } + } else { + DLIST_REMOVE(wrepl_socket->send_queue, req); + DLIST_ADD_END(wrepl_socket->recv_queue, req, struct wrepl_request *); + req->state = WREPL_REQUEST_RECV; + } EVENT_FD_READABLE(wrepl_socket->fde); } @@ -289,7 +312,7 @@ failed: static int wrepl_socket_destructor(void *ptr) { struct wrepl_socket *sock = talloc_get_type(ptr, struct wrepl_socket); - wrepl_socket_dead(sock, NT_STATUS_CONNECTION_DISCONNECTED); + wrepl_socket_dead(sock, NT_STATUS_LOCAL_DISCONNECT); return 0; } @@ -415,7 +438,7 @@ static NTSTATUS wrepl_request_wait(struct wrepl_request *req) connect a wrepl_socket to a WINS server */ struct wrepl_request *wrepl_connect_send(struct wrepl_socket *wrepl_socket, - const char *address) + const char *our_ip, const char *peer_ip) { struct wrepl_request *req; NTSTATUS status; @@ -429,8 +452,12 @@ struct wrepl_request *wrepl_connect_send(struct wrepl_socket *wrepl_socket, DLIST_ADD(wrepl_socket->recv_queue, req); talloc_set_destructor(req, wrepl_request_destructor); - - status = socket_connect(wrepl_socket->sock, iface_best_ip(address), 0, address, + + if (!our_ip) { + our_ip = iface_best_ip(peer_ip); + } + + status = socket_connect(wrepl_socket->sock, our_ip, 0, peer_ip, WINS_REPLICATION_PORT, 0); if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) goto failed; @@ -453,9 +480,9 @@ NTSTATUS wrepl_connect_recv(struct wrepl_request *req) /* connect a wrepl_socket to a WINS server - sync API */ -NTSTATUS wrepl_connect(struct wrepl_socket *wrepl_socket, const char *address) +NTSTATUS wrepl_connect(struct wrepl_socket *wrepl_socket, const char *our_ip, const char *peer_ip) { - struct wrepl_request *req = wrepl_connect_send(wrepl_socket, address); + struct wrepl_request *req = wrepl_connect_send(wrepl_socket, our_ip, peer_ip); return wrepl_connect_recv(req); } @@ -618,6 +645,59 @@ NTSTATUS wrepl_associate(struct wrepl_socket *wrepl_socket, } +/* + stop an association - send +*/ +struct wrepl_request *wrepl_associate_stop_send(struct wrepl_socket *wrepl_socket, + struct wrepl_associate_stop *io) +{ + struct wrepl_packet *packet; + struct wrepl_request *req; + + packet = talloc_zero(wrepl_socket, struct wrepl_packet); + if (packet == NULL) return NULL; + + packet->opcode = WREPL_OPCODE_BITS; + packet->assoc_ctx = io->in.assoc_ctx; + packet->mess_type = WREPL_STOP_ASSOCIATION; + packet->message.stop.reason = io->in.reason; + + req = wrepl_request_send(wrepl_socket, packet); + + if (req && io->in.reason == 0) { + req->send_only = True; + req->disconnect_after_send = True; + } + + talloc_free(packet); + + return req; +} + +/* + stop an association - recv +*/ +NTSTATUS wrepl_associate_stop_recv(struct wrepl_request *req, + struct wrepl_associate_stop *io) +{ + struct wrepl_packet *packet=NULL; + NTSTATUS status; + status = wrepl_request_recv(req, req->wrepl_socket, &packet); + NT_STATUS_NOT_OK_RETURN(status); + talloc_free(packet); + return status; +} + +/* + setup an association - sync api +*/ +NTSTATUS wrepl_associate_stop(struct wrepl_socket *wrepl_socket, + struct wrepl_associate_stop *io) +{ + struct wrepl_request *req = wrepl_associate_stop_send(wrepl_socket, io); + return wrepl_associate_stop_recv(req, io); +} + /* fetch the partner tables - send */ @@ -735,8 +815,6 @@ NTSTATUS wrepl_pull_names_recv(struct wrepl_request *req, io->out.num_names = packet->message.replication.info.reply.num_names; - status = NT_STATUS_NO_MEMORY; - io->out.names = talloc_array(packet, struct wrepl_name, io->out.num_names); if (io->out.names == NULL) goto nomem; -- cgit