diff options
Diffstat (limited to 'source4/libcli')
-rw-r--r-- | source4/libcli/wrepl/winsrepl.c | 100 | ||||
-rw-r--r-- | source4/libcli/wrepl/winsrepl.h | 14 |
2 files changed, 103 insertions, 11 deletions
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); } @@ -619,6 +646,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 */ struct wrepl_request *wrepl_pull_table_send(struct wrepl_socket *wrepl_socket, @@ -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; diff --git a/source4/libcli/wrepl/winsrepl.h b/source4/libcli/wrepl/winsrepl.h index e78f0464e7..89a4c642b2 100644 --- a/source4/libcli/wrepl/winsrepl.h +++ b/source4/libcli/wrepl/winsrepl.h @@ -69,6 +69,10 @@ struct wrepl_request { DATA_BLOB buffer; + BOOL disconnect_after_send; + + BOOL send_only; + size_t num_read; struct timed_event *te; @@ -92,6 +96,16 @@ struct wrepl_associate { }; /* + setup an association +*/ +struct wrepl_associate_stop { + struct { + uint32_t assoc_ctx; + uint32_t reason; + } in; +}; + +/* pull the partner table */ struct wrepl_pull_table { |