This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "lib/events/events.h"
-#include "dlinklist.h"
+#include "lib/util/dlinklist.h"
#include "libcli/nbt/libnbt.h"
#include "lib/socket/socket.h"
#include "librpc/gen_ndr/ndr_nbt.h"
+#include "param/param.h"
#define NBT_MAX_REPLIES 1000
/*
destroy a pending request
*/
-static int nbt_name_request_destructor(void *ptr)
-{
- struct nbt_name_request *req = talloc_get_type(ptr, struct nbt_name_request);
-
+static int nbt_name_request_destructor(struct nbt_name_request *req)
+{
if (req->state == NBT_REQUEST_SEND) {
DLIST_REMOVE(req->nbtsock->send_queue, req);
}
req->name_trn_id = 0;
}
if (req->te) {
+ talloc_free(req->te);
req->te = NULL;
}
if (req->nbtsock->send_queue == NULL) {
talloc_free(tmp_ctx);
if (req->async.fn) {
req->async.fn(req);
+ } else if (req->is_reply) {
+ talloc_free(req);
}
return;
}
}
if (req->async.fn) {
req->async.fn(req);
+ } else if (req->is_reply) {
+ talloc_free(req);
}
}
-/*
+/**
handle recv events on a nbt name socket
*/
static void nbt_name_socket_recv(struct nbt_name_socket *nbtsock)
{
TALLOC_CTX *tmp_ctx = talloc_new(nbtsock);
NTSTATUS status;
+ enum ndr_err_code ndr_err;
struct socket_address *src;
DATA_BLOB blob;
size_t nread, dsize;
}
/* parse the request */
- status = ndr_pull_struct_blob(&blob, packet, packet,
- (ndr_pull_flags_fn_t)ndr_pull_nbt_name_packet);
- if (!NT_STATUS_IS_OK(status)) {
+ ndr_err = ndr_pull_struct_blob(&blob, packet, nbtsock->iconv_convenience, packet,
+ (ndr_pull_flags_fn_t)ndr_pull_nbt_name_packet);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ status = ndr_map_error2ntstatus(ndr_err);
DEBUG(2,("Failed to parse incoming NBT name packet - %s\n",
nt_errstr(status)));
talloc_free(tmp_ctx);
}
/* find the matching request */
- req = idr_find(nbtsock->idr, packet->name_trn_id);
+ req = (struct nbt_name_request *)idr_find(nbtsock->idr,
+ packet->name_trn_id);
if (req == NULL) {
if (nbtsock->unexpected.handler) {
nbtsock->unexpected.handler(nbtsock, packet, src);
} else {
- DEBUG(2,("Failed to match request for incoming name packet id 0x%04x on %p\n",
+ DEBUG(10,("Failed to match request for incoming name packet id 0x%04x on %p\n",
packet->name_trn_id, nbtsock));
}
talloc_free(tmp_ctx);
/* we know we won't need any more retries - the server
has received our request */
req->num_retries = 0;
- req->received_wack = True;
+ req->received_wack = true;
/* although there can be a timeout in the packet, w2k3 screws it up,
so better to set it ourselves */
- req->timeout = lp_parm_int(-1, "nbt", "wack_timeout", 30);
+ req->timeout = lp_parm_int(global_loadparm, NULL, "nbt", "wack_timeout", 30);
req->te = event_add_timed(req->nbtsock->event_ctx, req,
timeval_current_ofs(req->timeout, 0),
nbt_name_socket_timeout, req);
then operations will use that event context
*/
_PUBLIC_ struct nbt_name_socket *nbt_name_socket_init(TALLOC_CTX *mem_ctx,
- struct event_context *event_ctx)
+ struct event_context *event_ctx,
+ struct smb_iconv_convenience *iconv_convenience)
{
struct nbt_name_socket *nbtsock;
NTSTATUS status;
nbtsock->num_pending = 0;
nbtsock->incoming.handler = NULL;
nbtsock->unexpected.handler = NULL;
+ nbtsock->iconv_convenience = iconv_convenience;
nbtsock->fde = event_add_fd(nbtsock->event_ctx, nbtsock,
socket_get_fd(nbtsock->sock), 0,
struct socket_address *dest,
struct nbt_name_packet *request,
int timeout, int retries,
- BOOL allow_multiple_replies)
+ bool allow_multiple_replies)
{
struct nbt_name_request *req;
int id;
- NTSTATUS status;
+ enum ndr_err_code ndr_err;
req = talloc_zero(nbtsock, struct nbt_name_request);
if (req == NULL) goto failed;
req->nbtsock = nbtsock;
req->allow_multiple_replies = allow_multiple_replies;
req->state = NBT_REQUEST_SEND;
- req->is_reply = False;
+ req->is_reply = false;
req->timeout = timeout;
req->num_retries = retries;
req->dest = dest;
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;
+ ndr_err = ndr_push_struct_blob(&req->encoded, req,
+ req->nbtsock->iconv_convenience,
+ request,
+ (ndr_push_flags_fn_t)ndr_push_nbt_name_packet);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) goto failed;
DLIST_ADD_END(nbtsock->send_queue, req, struct nbt_name_request *);
struct nbt_name_packet *request)
{
struct nbt_name_request *req;
- NTSTATUS status;
+ enum ndr_err_code ndr_err;
req = talloc_zero(nbtsock, struct nbt_name_request);
NT_STATUS_HAVE_NO_MEMORY(req);
req->dest = dest;
if (talloc_reference(req, dest) == NULL) goto failed;
req->state = NBT_REQUEST_SEND;
- req->is_reply = True;
+ req->is_reply = true;
talloc_set_destructor(req, nbt_name_request_destructor);
NDR_PRINT_DEBUG(nbt_name_packet, request);
}
- 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)) {
+ ndr_err = ndr_push_struct_blob(&req->encoded, req,
+ req->nbtsock->iconv_convenience,
+ request,
+ (ndr_push_flags_fn_t)ndr_push_nbt_name_packet);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
talloc_free(req);
- return status;
+ return ndr_map_error2ntstatus(ndr_err);
}
DLIST_ADD_END(nbtsock->send_queue, req, struct nbt_name_request *);
if (event_loop_once(req->nbtsock->event_ctx) != 0) {
req->state = NBT_REQUEST_ERROR;
req->status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
- if (req->async.fn) {
- req->async.fn(req);
- }
+ break;
}
}
return req->status;