Merge branch 'v4-0-trivial' into v4-0-test
[kai/samba.git] / source / libcli / nbt / nbtsocket.c
index 50da8168e072a6b59337a43898cbeb96cd9a3629..95a1643efc42e0068c9d7fc30f208c587573f6d5 100644 (file)
@@ -7,7 +7,7 @@
    
    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);
        }
@@ -47,6 +45,7 @@ static int nbt_name_request_destructor(void *ptr)
                req->name_trn_id = 0;
        }
        if (req->te) {
+               talloc_free(req->te);
                req->te = NULL;
        }
        if (req->nbtsock->send_queue == NULL) {
@@ -104,6 +103,8 @@ failed:
        talloc_free(tmp_ctx);
        if (req->async.fn) {
                req->async.fn(req);
+       } else if (req->is_reply) {
+               talloc_free(req);
        }
        return;
 }
@@ -142,18 +143,21 @@ static void nbt_name_socket_timeout(struct event_context *ev, struct timed_event
        }
        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;
@@ -186,9 +190,10 @@ static void nbt_name_socket_recv(struct nbt_name_socket *nbtsock)
        }
 
        /* 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);
@@ -212,12 +217,13 @@ static void nbt_name_socket_recv(struct nbt_name_socket *nbtsock)
        }
 
        /* 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);
@@ -237,10 +243,10 @@ static void nbt_name_socket_recv(struct nbt_name_socket *nbtsock)
                /* 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);
@@ -303,7 +309,8 @@ static void nbt_name_socket_handler(struct event_context *ev, struct fd_event *f
   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;
@@ -332,6 +339,7 @@ _PUBLIC_ struct nbt_name_socket *nbt_name_socket_init(TALLOC_CTX *mem_ctx,
        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,
@@ -351,11 +359,11 @@ struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock,
                                               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;
@@ -363,7 +371,7 @@ struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock,
        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;
@@ -388,9 +396,11 @@ 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;
+       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 *);
 
@@ -418,7 +428,7 @@ NTSTATUS nbt_name_reply_send(struct nbt_name_socket *nbtsock,
                             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);
@@ -427,7 +437,7 @@ NTSTATUS nbt_name_reply_send(struct nbt_name_socket *nbtsock,
        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);        
 
@@ -435,11 +445,13 @@ NTSTATUS nbt_name_reply_send(struct nbt_name_socket *nbtsock,
                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 *);
@@ -464,9 +476,7 @@ NTSTATUS nbt_name_request_recv(struct nbt_name_request *req)
                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;