diff options
author | Andrew Tridgell <tridge@samba.org> | 2005-01-31 04:53:53 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 13:09:24 -0500 |
commit | 0700676da69a68066e0a2f7541ffa0d3bf956616 (patch) | |
tree | 36a628dd1fd79946f9c131906d1cfbbc001a0d67 | |
parent | 784dde73bc2f59108c6f5123b9206851b97afc32 (diff) | |
download | samba-0700676da69a68066e0a2f7541ffa0d3bf956616.tar.gz samba-0700676da69a68066e0a2f7541ffa0d3bf956616.tar.bz2 samba-0700676da69a68066e0a2f7541ffa0d3bf956616.zip |
r5120: encode outgoing nbt packets when queueing them rather than in the send
event code, as elements of the callers packet structure could go away
while the queue is pending (if for example a name was de-registered
while a packet referencing that name is queued)
(This used to be commit 6726f15cf44388e5787eec223a8c9778110a508f)
-rw-r--r-- | source4/libcli/nbt/libnbt.h | 9 | ||||
-rw-r--r-- | source4/libcli/nbt/nbtsocket.c | 66 |
2 files changed, 45 insertions, 30 deletions
diff --git a/source4/libcli/nbt/libnbt.h b/source4/libcli/nbt/libnbt.h index a3630e2a12..35eff9961c 100644 --- a/source4/libcli/nbt/libnbt.h +++ b/source4/libcli/nbt/libnbt.h @@ -51,7 +51,14 @@ struct nbt_name_request { /* the timeout event */ struct timed_event *te; - struct nbt_name_packet *request; + /* the name transaction id */ + uint16_t name_trn_id; + + /* is it a reply? */ + BOOL is_reply; + + /* the encoded request */ + DATA_BLOB encoded; /* shall we allow multiple replies? */ BOOL allow_multiple_replies; diff --git a/source4/libcli/nbt/nbtsocket.c b/source4/libcli/nbt/nbtsocket.c index 90b4f6e029..3f16bf6921 100644 --- a/source4/libcli/nbt/nbtsocket.c +++ b/source4/libcli/nbt/nbtsocket.c @@ -41,10 +41,9 @@ static int nbt_name_request_destructor(void *ptr) if (req->state == NBT_REQUEST_WAIT) { req->nbtsock->num_pending--; } - if (req->request->name_trn_id != 0 && - !(req->request->operation & NBT_FLAG_REPLY)) { - idr_remove(req->nbtsock->idr, req->request->name_trn_id); - req->request->name_trn_id = 0; + if (req->name_trn_id != 0 && !req->is_reply) { + idr_remove(req->nbtsock->idr, req->name_trn_id); + req->name_trn_id = 0; } if (req->te) { req->te = NULL; @@ -70,26 +69,10 @@ static void nbt_name_socket_send(struct nbt_name_socket *nbtsock) NTSTATUS status; while ((req = nbtsock->send_queue)) { - DATA_BLOB blob; size_t len; - if (DEBUGLVL(10)) { - DEBUG(10,("Sending nbt packet to %s:%d\n", - req->dest_addr, req->dest_port)); - NDR_PRINT_DEBUG(nbt_name_packet, req->request); - } - - status = ndr_push_struct_blob(&blob, tmp_ctx, req->request, - (ndr_push_flags_fn_t) - ndr_push_nbt_name_packet); - if (!NT_STATUS_IS_OK(status)) goto failed; - - if (req->request->operation & NBT_FLAG_BROADCAST) { - socket_set_option(nbtsock->sock, "SO_BROADCAST", "1"); - } - - len = blob.length; - status = socket_sendto(nbtsock->sock, &blob, &len, 0, + len = req->encoded.length; + status = socket_sendto(nbtsock->sock, &req->encoded, &len, 0, req->dest_addr, req->dest_port); if (NT_STATUS_IS_ERR(status)) goto failed; @@ -99,7 +82,7 @@ static void nbt_name_socket_send(struct nbt_name_socket *nbtsock) } DLIST_REMOVE(nbtsock->send_queue, req); - if (req->request->operation & NBT_FLAG_REPLY) { + if (req->is_reply) { talloc_free(req); } else { req->state = NBT_REQUEST_WAIT; @@ -270,6 +253,7 @@ struct nbt_name_socket *nbt_name_socket_init(TALLOC_CTX *mem_ctx, nbtsock->send_queue = NULL; nbtsock->num_pending = 0; + nbtsock->incoming.handler = NULL; fde.fd = socket_get_fd(nbtsock->sock); fde.flags = 0; @@ -317,6 +301,7 @@ struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock, struct nbt_name_request *req; struct timed_event te; int id; + NTSTATUS status; req = talloc_zero(nbtsock, struct nbt_name_request); if (req == NULL) goto failed; @@ -325,13 +310,13 @@ struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock, req->dest_addr = talloc_strdup(req, dest_addr); if (req->dest_addr == NULL) goto failed; req->dest_port = dest_port; - req->request = talloc_reference(req, request); req->allow_multiple_replies = allow_multiple_replies; req->state = NBT_REQUEST_SEND; + req->is_reply = False; /* we select a random transaction id unless the user supplied one */ - if (req->request->name_trn_id == 0) { - req->request->name_trn_id = generate_random() % UINT16_MAX; + if (request->name_trn_id == 0) { + request->name_trn_id = generate_random() % UINT16_MAX; } /* choose the next available transaction id >= the one asked for. @@ -340,14 +325,15 @@ struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock, to ID guessing, but this at least makes accidential collisions less likely */ id = idr_get_new_above(req->nbtsock->idr, req, - req->request->name_trn_id, UINT16_MAX); + request->name_trn_id, UINT16_MAX); if (id == -1) { id = idr_get_new_above(req->nbtsock->idr, req, 1+(generate_random()%(UINT16_MAX/2)), UINT16_MAX); } if (id == -1) goto failed; - req->request->name_trn_id = id; + request->name_trn_id = id; + req->name_trn_id = id; te.next_event = timeout; te.handler = nbt_name_socket_timeout; @@ -356,8 +342,22 @@ struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock, talloc_set_destructor(req, nbt_name_request_destructor); + status = ndr_push_struct_blob(&req->encoded, req, request, + (ndr_push_flags_fn_t)ndr_push_nbt_name_packet); + if (!NT_STATUS_IS_OK(status)) goto failed; + DLIST_ADD_END(nbtsock->send_queue, req, struct nbt_name_request *); + if (request->operation & NBT_FLAG_BROADCAST) { + socket_set_option(nbtsock->sock, "SO_BROADCAST", "1"); + } + + if (DEBUGLVL(10)) { + DEBUG(10,("Queueing nbt packet to %s:%d\n", + req->dest_addr, req->dest_port)); + NDR_PRINT_DEBUG(nbt_name_packet, request); + } + nbtsock->fde->flags |= EVENT_FD_WRITE; return req; @@ -376,6 +376,7 @@ NTSTATUS nbt_name_reply_send(struct nbt_name_socket *nbtsock, struct nbt_name_packet *request) { struct nbt_name_request *req; + NTSTATUS status; req = talloc_zero(nbtsock, struct nbt_name_request); NT_STATUS_HAVE_NO_MEMORY(req); @@ -384,11 +385,18 @@ NTSTATUS nbt_name_reply_send(struct nbt_name_socket *nbtsock, req->dest_addr = talloc_strdup(req, dest_addr); if (req->dest_addr == NULL) goto failed; req->dest_port = dest_port; - req->request = talloc_reference(req, request); req->state = NBT_REQUEST_SEND; + req->is_reply = True; talloc_set_destructor(req, nbt_name_request_destructor); + status = ndr_push_struct_blob(&req->encoded, req, request, + (ndr_push_flags_fn_t)ndr_push_nbt_name_packet); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(req); + return status; + } + DLIST_ADD_END(nbtsock->send_queue, req, struct nbt_name_request *); nbtsock->fde->flags |= EVENT_FD_WRITE; |