wreplsrv: log a successful replication cycle at level 1
[kai/samba.git] / source4 / wrepl_server / wrepl_in_connection.c
index a6abf99e411b00e0cb786084842cb7e4673007a5..ecc265e590abcb4e922ab24565a4a66a2b62db6f 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 "dlinklist.h"
-#include "lib/events/events.h"
 #include "lib/socket/socket.h"
 #include "lib/stream/packet.h"
 #include "smbd/service_task.h"
 #include "smbd/service_stream.h"
+#include "smbd/service.h"
 #include "lib/messaging/irpc.h"
 #include "librpc/gen_ndr/ndr_winsrepl.h"
 #include "wrepl_server/wrepl_server.h"
-#include "nbt_server/wins/winsdb.h"
-#include "ldb/include/ldb.h"
+#include "smbd/process_model.h"
+#include "system/network.h"
+#include "lib/socket/netif.h"
+#include "param/param.h"
 
 void wreplsrv_terminate_in_connection(struct wreplsrv_in_connection *wreplconn, const char *reason)
 {
        stream_terminate_connection(wreplconn->conn, reason);
 }
 
-static int terminate_after_send_destructor(void *ptr)
+static int terminate_after_send_destructor(struct wreplsrv_in_connection **tas)
 {
-       struct wreplsrv_in_connection **tas = talloc_get_type(ptr, struct wreplsrv_in_connection *);
        wreplsrv_terminate_in_connection(*tas, "wreplsrv_in_connection: terminate_after_send");
        return 0;
 }
@@ -56,6 +55,7 @@ static NTSTATUS wreplsrv_recv_request(void *private, DATA_BLOB blob)
        DATA_BLOB packet_out_blob;
        struct wrepl_wrap packet_out_wrap;
        NTSTATUS status;
+       enum ndr_err_code ndr_err;
 
        call = talloc_zero(wreplconn, struct wreplsrv_in_call);
        NT_STATUS_HAVE_NO_MEMORY(call);
@@ -65,12 +65,17 @@ static NTSTATUS wreplsrv_recv_request(void *private, DATA_BLOB blob)
        packet_in_blob.data = blob.data + 4;
        packet_in_blob.length = blob.length - 4;
 
-       status = ndr_pull_struct_blob(&packet_in_blob, call, &call->req_packet,
-                                     (ndr_pull_flags_fn_t)ndr_pull_wrepl_packet);
-       NT_STATUS_NOT_OK_RETURN(status);
+       ndr_err = ndr_pull_struct_blob(&packet_in_blob, call, 
+                                      lp_iconv_convenience(wreplconn->service->task->lp_ctx),
+                                      &call->req_packet,
+                                      (ndr_pull_flags_fn_t)ndr_pull_wrepl_packet);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               return ndr_map_error2ntstatus(ndr_err);
+       }
 
        if (DEBUGLVL(10)) {
-               DEBUG(10,("Received WINS-Replication packet of length %u\n", packet_in_blob.length + 4));
+               DEBUG(10,("Received WINS-Replication packet of length %u\n", 
+                         (unsigned)packet_in_blob.length + 4));
                NDR_PRINT_DEBUG(wrepl_packet, &call->req_packet);
        }
 
@@ -85,9 +90,13 @@ static NTSTATUS wreplsrv_recv_request(void *private, DATA_BLOB blob)
 
        /* and now encode the reply */
        packet_out_wrap.packet = call->rep_packet;
-       status = ndr_push_struct_blob(&packet_out_blob, call, &packet_out_wrap,
+       ndr_err = ndr_push_struct_blob(&packet_out_blob, call, 
+                                      lp_iconv_convenience(wreplconn->service->task->lp_ctx),
+                                      &packet_out_wrap,
                                      (ndr_push_flags_fn_t)ndr_push_wrepl_wrap);
-       NT_STATUS_NOT_OK_RETURN(status);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               return ndr_map_error2ntstatus(ndr_err);
+       }
 
        if (DEBUGLVL(10)) {
                DEBUG(10,("Sending WINS-Replication packet of length %d\n", (int)packet_out_blob.length));
@@ -147,7 +156,7 @@ static void wreplsrv_accept(struct stream_connection *conn)
 {
        struct wreplsrv_service *service = talloc_get_type(conn->private, struct wreplsrv_service);
        struct wreplsrv_in_connection *wreplconn;
-       const char *peer_ip;
+       struct socket_address *peer_ip;
 
        wreplconn = talloc_zero(conn, struct wreplsrv_in_connection);
        if (!wreplconn) {
@@ -171,19 +180,14 @@ static void wreplsrv_accept(struct stream_connection *conn)
 
        wreplconn->conn         = conn;
        wreplconn->service      = service;
-       wreplconn->our_ip       = socket_get_my_addr(conn->socket, wreplconn);
-       if (!wreplconn->our_ip) {
-               wreplsrv_terminate_in_connection(wreplconn, "wreplsrv_accept: out of memory");
-               return;
-       }
 
        peer_ip = socket_get_peer_addr(conn->socket, wreplconn);
        if (!peer_ip) {
-               wreplsrv_terminate_in_connection(wreplconn, "wreplsrv_accept: out of memory");
+               wreplsrv_terminate_in_connection(wreplconn, "wreplsrv_accept: could not obtain peer IP from kernel");
                return;
        }
 
-       wreplconn->partner      = wreplsrv_find_partner(service, peer_ip);
+       wreplconn->partner      = wreplsrv_find_partner(service, peer_ip->addr);
 
        conn->private = wreplconn;
 
@@ -214,7 +218,7 @@ NTSTATUS wreplsrv_in_connection_merge(struct wreplsrv_partner *partner,
        /* within the wrepl task we want to be a single process, so
           ask for the single process model ops and pass these to the
           stream_setup_socket() call. */
-       model_ops = process_model_byname("single");
+       model_ops = process_model_startup(service->task->event_ctx, "single");
        if (!model_ops) {
                DEBUG(0,("Can't find 'single' process model_ops"));
                return NT_STATUS_INTERNAL_ERROR;
@@ -225,10 +229,8 @@ NTSTATUS wreplsrv_in_connection_merge(struct wreplsrv_partner *partner,
 
        wrepl_in->service       = service;
        wrepl_in->partner       = partner;
-       wrepl_in->our_ip        = socket_get_my_addr(sock, wrepl_in);
-       NT_STATUS_HAVE_NO_MEMORY(wrepl_in->our_ip);
 
-       status = stream_new_connection_merge(service->task->event_ctx, model_ops,
+       status = stream_new_connection_merge(service->task->event_ctx, service->task->lp_ctx, model_ops,
                                             sock, &wreplsrv_stream_ops, service->task->msg_ctx,
                                             wrepl_in, &conn);
        NT_STATUS_NOT_OK_RETURN(status);
@@ -260,7 +262,7 @@ NTSTATUS wreplsrv_in_connection_merge(struct wreplsrv_partner *partner,
 /*
   startup the wrepl port 42 server sockets
 */
-NTSTATUS wreplsrv_setup_sockets(struct wreplsrv_service *service)
+NTSTATUS wreplsrv_setup_sockets(struct wreplsrv_service *service, struct loadparm_context *lp_ctx)
 {
        NTSTATUS status;
        struct task_server *task = service->task;
@@ -271,24 +273,33 @@ NTSTATUS wreplsrv_setup_sockets(struct wreplsrv_service *service)
        /* within the wrepl task we want to be a single process, so
           ask for the single process model ops and pass these to the
           stream_setup_socket() call. */
-       model_ops = process_model_byname("single");
+       model_ops = process_model_startup(task->event_ctx, "single");
        if (!model_ops) {
                DEBUG(0,("Can't find 'single' process model_ops"));
                return NT_STATUS_INTERNAL_ERROR;
        }
 
-       if (lp_interfaces() && lp_bind_interfaces_only()) {
-               int num_interfaces = iface_count();
+       if (lp_interfaces(lp_ctx) && lp_bind_interfaces_only(lp_ctx)) {
+               int num_interfaces;
                int i;
+               struct interface *ifaces;
+
+               load_interfaces(task, lp_interfaces(lp_ctx), &ifaces);
+
+               num_interfaces = iface_count(ifaces);
 
                /* We have been given an interfaces line, and been 
                   told to only bind to those interfaces. Create a
                   socket per interface and bind to only these.
                */
                for(i = 0; i < num_interfaces; i++) {
-                       address = iface_n_ip(i);
-                       status = stream_setup_socket(task->event_ctx, model_ops, &wreplsrv_stream_ops,
-                                                    "ipv4", address, &port, service);
+                       address = iface_n_ip(ifaces, i);
+                       status = stream_setup_socket(task->event_ctx, 
+                                                    task->lp_ctx, model_ops, 
+                                                    &wreplsrv_stream_ops,
+                                                    "ipv4", address, &port, 
+                                                     lp_socket_options(task->lp_ctx), 
+                                                    service);
                        if (!NT_STATUS_IS_OK(status)) {
                                DEBUG(0,("stream_setup_socket(address=%s,port=%u) failed - %s\n",
                                         address, port, nt_errstr(status)));
@@ -296,9 +307,11 @@ NTSTATUS wreplsrv_setup_sockets(struct wreplsrv_service *service)
                        }
                }
        } else {
-               address = lp_socket_address();
-               status = stream_setup_socket(task->event_ctx, model_ops, &wreplsrv_stream_ops,
-                                            "ipv4", address, &port, service);
+               address = lp_socket_address(lp_ctx);
+               status = stream_setup_socket(task->event_ctx, task->lp_ctx, 
+                                            model_ops, &wreplsrv_stream_ops,
+                                            "ipv4", address, &port, lp_socket_options(task->lp_ctx), 
+                                            service);
                if (!NT_STATUS_IS_OK(status)) {
                        DEBUG(0,("stream_setup_socket(address=%s,port=%u) failed - %s\n",
                                 address, port, nt_errstr(status)));