Add context for libcli_resolve.
[samba-svnmirror.git] / source / libcli / wrepl / winsrepl.c
index 909bedf5302c37f952829e03f95ab3caef39a985..00346c45a4497edecbe90980b1b44ef2dc3a9aab 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 "lib/socket/socket.h"
 #include "libcli/wrepl/winsrepl.h"
+#include "librpc/gen_ndr/ndr_winsrepl.h"
 #include "lib/stream/packet.h"
 #include "libcli/composite/composite.h"
+#include "system/network.h"
+#include "lib/socket/netif.h"
+#include "param/param.h"
+#include "libcli/resolve/resolve.h"
 
 static struct wrepl_request *wrepl_request_finished(struct wrepl_request *req, NTSTATUS status);
 
@@ -35,7 +39,7 @@ static struct wrepl_request *wrepl_request_finished(struct wrepl_request *req, N
 */
 static void wrepl_socket_dead(struct wrepl_socket *wrepl_socket, NTSTATUS status)
 {
-       wrepl_socket->dead = True;
+       wrepl_socket->dead = true;
 
        if (wrepl_socket->packet) {
                packet_recv_disable(wrepl_socket->packet);
@@ -83,9 +87,11 @@ static NTSTATUS wrepl_finish_recv(void *private, DATA_BLOB packet_blob_in)
        struct wrepl_socket *wrepl_socket = talloc_get_type(private, struct wrepl_socket);
        struct wrepl_request *req = wrepl_socket->recv_queue;
        DATA_BLOB blob;
+       enum ndr_err_code ndr_err;
 
        if (!req) {
-               DEBUG(1,("Received unexpected WINS packet of length %u!\n", packet_blob_in.length));
+               DEBUG(1,("Received unexpected WINS packet of length %u!\n", 
+                        (unsigned)packet_blob_in.length));
                return NT_STATUS_INVALID_NETWORK_RESPONSE;
        }
 
@@ -96,20 +102,22 @@ static NTSTATUS wrepl_finish_recv(void *private, DATA_BLOB packet_blob_in)
        blob.length = packet_blob_in.length - 4;
        
        /* we have a full request - parse it */
-       req->status = ndr_pull_struct_blob(&blob,
-                                          req->packet, req->packet,
-                                          (ndr_pull_flags_fn_t)ndr_pull_wrepl_packet);
-       if (!NT_STATUS_IS_OK(req->status)) {
-               wrepl_request_finished(req, req->status);
+       ndr_err = ndr_pull_struct_blob(&blob,
+                                      req->packet, req->packet,
+                                      (ndr_pull_flags_fn_t)ndr_pull_wrepl_packet);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
+               wrepl_request_finished(req, status);
                return NT_STATUS_OK;
        }
 
        if (DEBUGLVL(10)) {
-               DEBUG(10,("Received WINS packet of length %u\n", packet_blob_in.length));
+               DEBUG(10,("Received WINS packet of length %u\n", 
+                         (unsigned)packet_blob_in.length));
                NDR_PRINT_DEBUG(wrepl_packet, req->packet);
        }
 
-       wrepl_request_finished(req, req->status);
+       wrepl_request_finished(req, NT_STATUS_OK);
        return NT_STATUS_OK;
 }
 
@@ -141,11 +149,10 @@ static void wrepl_error(void *private, NTSTATUS status)
 /*
   destroy a wrepl_socket destructor
 */
-static int wrepl_socket_destructor(void *ptr)
+static int wrepl_socket_destructor(struct wrepl_socket *sock)
 {
-       struct wrepl_socket *sock = talloc_get_type(ptr, struct wrepl_socket);
        if (sock->dead) {
-               sock->free_skipped = True;
+               sock->free_skipped = true;
                return -1;
        }
        wrepl_socket_dead(sock, NT_STATUS_LOCAL_DISCONNECT);
@@ -241,9 +248,8 @@ failed:
 /*
   destroy a wrepl_request
 */
-static int wrepl_request_destructor(void *ptr)
+static int wrepl_request_destructor(struct wrepl_request *req)
 {
-       struct wrepl_request *req = talloc_get_type(ptr, struct wrepl_request);
        if (req->state == WREPL_REQUEST_RECV) {
                DLIST_REMOVE(req->wrepl_socket->recv_queue, req);
        }
@@ -326,7 +332,7 @@ struct composite_context *wrepl_connect_send(struct wrepl_socket *wrepl_socket,
        state->wrepl_socket     = wrepl_socket;
 
        if (!our_ip) {
-               our_ip = iface_best_ip(peer_ip);
+               our_ip = iface_best_ip(global_loadparm, peer_ip);
        }
 
        us = socket_address_from_strings(state, wrepl_socket->sock->backend_name, 
@@ -338,7 +344,8 @@ struct composite_context *wrepl_connect_send(struct wrepl_socket *wrepl_socket,
        if (composite_nomem(peer, result)) return result;
 
        state->creq = socket_connect_send(wrepl_socket->sock, us, peer,
-                                         0, wrepl_socket->event.ctx);
+                                         0, lp_resolve_context(global_loadparm), 
+                                         wrepl_socket->event.ctx);
        composite_continue(result, state->creq, wrepl_connect_handler, state);
        return result;
 }
@@ -385,7 +392,7 @@ static void wrepl_request_trigger_handler(struct event_context *ev, struct timed
 /*
   trigger an immediate event on a wrepl_request
   the return value should only be used in wrepl_request_send()
-  this is the only place where req->trigger is True
+  this is the only place where req->trigger is true
 */
 static struct wrepl_request *wrepl_request_finished(struct wrepl_request *req, NTSTATUS status)
 {
@@ -404,7 +411,7 @@ static struct wrepl_request *wrepl_request_finished(struct wrepl_request *req, N
        req->status     = status;
 
        if (req->trigger) {
-               req->trigger = False;
+               req->trigger = false;
                /* a zero timeout means immediate */
                te = event_add_timed(req->wrepl_socket->event.ctx,
                                     req, timeval_zero(),
@@ -428,9 +435,8 @@ struct wrepl_send_ctrl_state {
        struct wrepl_socket *wrepl_sock;
 };
 
-static int wrepl_send_ctrl_destructor(void *ptr)
+static int wrepl_send_ctrl_destructor(struct wrepl_send_ctrl_state *s)
 {
-       struct wrepl_send_ctrl_state *s = talloc_get_type(ptr, struct wrepl_send_ctrl_state);
        struct wrepl_request *req = s->wrepl_sock->recv_queue;
 
        /* check if the request is still in WREPL_STATE_RECV,
@@ -447,7 +453,7 @@ static int wrepl_send_ctrl_destructor(void *ptr)
        /* here, we need to make sure the async request handler is called
         * later in the next event_loop and now now
         */
-       req->trigger = True;
+       req->trigger = true;
        wrepl_request_finished(req, NT_STATUS_OK);
 
        if (s->ctrl.disconnect_after_send) {
@@ -467,12 +473,14 @@ struct wrepl_request *wrepl_request_send(struct wrepl_socket *wrepl_socket,
        struct wrepl_request *req;
        struct wrepl_wrap wrap;
        DATA_BLOB blob;
+       NTSTATUS status;
+       enum ndr_err_code ndr_err;
 
        req = talloc_zero(wrepl_socket, struct wrepl_request);
        if (!req) return NULL;
        req->wrepl_socket = wrepl_socket;
        req->state        = WREPL_REQUEST_RECV;
-       req->trigger      = True;
+       req->trigger      = true;
 
        DLIST_ADD_END(wrepl_socket->recv_queue, req, struct wrepl_request *);
        talloc_set_destructor(req, wrepl_request_destructor);
@@ -482,14 +490,16 @@ struct wrepl_request *wrepl_request_send(struct wrepl_socket *wrepl_socket,
        }
 
        wrap.packet = *packet;
-       req->status = ndr_push_struct_blob(&blob, req, &wrap,
-                                          (ndr_push_flags_fn_t)ndr_push_wrepl_wrap);
-       if (!NT_STATUS_IS_OK(req->status)) {
-               return wrepl_request_finished(req, req->status);
+       ndr_err = ndr_push_struct_blob(&blob, req, &wrap,
+                                      (ndr_push_flags_fn_t)ndr_push_wrepl_wrap);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               status = ndr_map_error2ntstatus(ndr_err);
+               return wrepl_request_finished(req, status);
        }
 
        if (DEBUGLVL(10)) {
-               DEBUG(10,("Sending WINS packet of length %u\n", blob.length));
+               DEBUG(10,("Sending WINS packet of length %u\n", 
+                         (unsigned)blob.length));
                NDR_PRINT_DEBUG(wrepl_packet, &wrap.packet);
        }
 
@@ -509,12 +519,12 @@ struct wrepl_request *wrepl_request_send(struct wrepl_socket *wrepl_socket,
                talloc_set_destructor(s, wrepl_send_ctrl_destructor);
        }
 
-       req->status = packet_send(wrepl_socket->packet, blob);
-       if (!NT_STATUS_IS_OK(req->status)) {
-               return wrepl_request_finished(req, req->status);
+       status = packet_send(wrepl_socket->packet, blob);
+       if (!NT_STATUS_IS_OK(status)) {
+               return wrepl_request_finished(req, status);
        }
 
-       req->trigger = False;
+       req->trigger = false;
        return req;
 }
 
@@ -563,6 +573,21 @@ struct wrepl_request *wrepl_associate_send(struct wrepl_socket *wrepl_socket,
        packet->message.start.minor_version = 2;
        packet->message.start.major_version = 5;
 
+       /*
+        * nt4 uses 41 bytes for the start_association call
+        * so do it the same and as we don't know th emeanings of this bytes
+        * we just send zeros and nt4, w2k and w2k3 seems to be happy with this
+        *
+        * if we don't do this nt4 uses an old version of the wins replication protocol
+        * and that would break nt4 <-> samba replication
+        */
+       packet->padding = data_blob_talloc(packet, NULL, 21);
+       if (packet->padding.data == NULL) {
+               talloc_free(packet);
+               return NULL;
+       }
+       memset(packet->padding.data, 0, packet->padding.length);
+
        req = wrepl_request_send(wrepl_socket, packet, NULL);
 
        talloc_free(packet);
@@ -621,8 +646,8 @@ struct wrepl_request *wrepl_associate_stop_send(struct wrepl_socket *wrepl_socke
 
        ZERO_STRUCT(ctrl);
        if (io->in.reason == 0) {
-               ctrl.send_only                  = True;
-               ctrl.disconnect_after_send      = True;
+               ctrl.send_only                  = true;
+               ctrl.disconnect_after_send      = true;
        }
 
        req = wrepl_request_send(wrepl_socket, packet, &ctrl);