Attempt to fix the merged build
[jra/samba/.git] / libcli / nbt / nbtsocket.c
index 57531d2e7b404fa4982bf2880dad696d6fcc18b6..dac61efc118bfb0b1825e71feef869e90f59c47f 100644 (file)
@@ -21,8 +21,9 @@
 
 #include "includes.h"
 #include "lib/events/events.h"
-#include "lib/util/dlinklist.h"
+#include "../lib/util/dlinklist.h"
 #include "../libcli/nbt/libnbt.h"
+#include "../libcli/nbt/nbt_proto.h"
 #include "lib/socket/socket.h"
 #include "librpc/gen_ndr/ndr_nbt.h"
 #include "param/param.h"
@@ -113,7 +114,7 @@ failed:
 /*
   handle a request timeout
 */
-static void nbt_name_socket_timeout(struct event_context *ev, struct timed_event *te,
+static void nbt_name_socket_timeout(struct tevent_context *ev, struct tevent_timer *te,
                                    struct timeval t, void *private)
 {
        struct nbt_name_request *req = talloc_get_type(private,
@@ -230,9 +231,20 @@ static void nbt_name_socket_recv(struct nbt_name_socket *nbtsock)
                return;
        }
 
+       talloc_steal(req, packet);
+       talloc_steal(req, src);
+       talloc_free(tmp_ctx);
+       nbt_name_socket_handle_response_packet(req, packet, src);
+}
+
+void nbt_name_socket_handle_response_packet(struct nbt_name_request *req,
+                                           struct nbt_name_packet *packet,
+                                           struct socket_address *src)
+{
        /* if this is a WACK response, this we need to go back to waiting,
           but perhaps increase the timeout */
        if ((packet->operation & NBT_OPCODE) == NBT_OPCODE_WACK) {
+               uint32_t ttl;
                if (req->received_wack || packet->ancount < 1) {
                        nbt_name_request_destructor(req);
                        req->status = NT_STATUS_INVALID_NETWORK_RESPONSE;
@@ -244,13 +256,26 @@ static void nbt_name_socket_recv(struct nbt_name_socket *nbtsock)
                   has received our request */
                req->num_retries   = 0;
                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(global_loadparm, NULL, "nbt", "wack_timeout", 30);
+               /*
+                * there is a timeout in the packet,
+                * it is 5 + 4 * num_old_addresses
+                *
+                * although w2k3 screws it up
+                * and uses num_old_addresses = 0
+                *
+                * so we better fallback to the maximum
+                * of num_old_addresses = 25 if we got
+                * a timeout of less than 9s (5 + 4*1)
+                * or more than 105s (5 + 4*25).
+                */
+               ttl = packet->answers[0].ttl;
+               if ((ttl < (5 + 4*1)) || (ttl > (5 + 4*25))) {
+                       ttl = 5 + 4*25;
+               }
+               req->timeout = ttl;
                req->te = event_add_timed(req->nbtsock->event_ctx, req,
                                          timeval_current_ofs(req->timeout, 0),
                                          nbt_name_socket_timeout, req);
-               talloc_free(tmp_ctx);
                return;
        }
 
@@ -272,7 +297,6 @@ static void nbt_name_socket_recv(struct nbt_name_socket *nbtsock)
        /* if we don't want multiple replies then we are done */
        if (req->allow_multiple_replies &&
            req->num_replies < NBT_MAX_REPLIES) {
-               talloc_free(tmp_ctx);
                return;
        }
 
@@ -281,7 +305,6 @@ static void nbt_name_socket_recv(struct nbt_name_socket *nbtsock)
        req->status = NT_STATUS_OK;
 
 done:
-       talloc_free(tmp_ctx);
        if (req->async.fn) {
                req->async.fn(req);
        }
@@ -290,7 +313,7 @@ done:
 /*
   handle fd events on a nbt_name_socket
 */
-static void nbt_name_socket_handler(struct event_context *ev, struct fd_event *fde,
+static void nbt_name_socket_handler(struct tevent_context *ev, struct tevent_fd *fde,
                                    uint16_t flags, void *private)
 {
        struct nbt_name_socket *nbtsock = talloc_get_type(private,
@@ -309,7 +332,7 @@ 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 tevent_context *event_ctx,
                                             struct smb_iconv_convenience *iconv_convenience)
 {
        struct nbt_name_socket *nbtsock;
@@ -493,6 +516,19 @@ _PUBLIC_ NTSTATUS nbt_set_incoming_handler(struct nbt_name_socket *nbtsock,
        return NT_STATUS_OK;
 }
 
+/*
+  setup a handler for unexpected requests
+*/
+NTSTATUS nbt_set_unexpected_handler(struct nbt_name_socket *nbtsock,
+                                   void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *,
+                                                   struct socket_address *),
+                                   void *private_data)
+{
+       nbtsock->unexpected.handler = handler;
+       nbtsock->unexpected.private_data = private_data;
+       EVENT_FD_READABLE(nbtsock->fde);
+       return NT_STATUS_OK;
+}
 
 /*
   turn a NBT rcode into a NTSTATUS