LCOV - code coverage report
Current view: top level - source4/libcli/wrepl - winsrepl.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 335 551 60.8 %
Date: 2024-02-28 12:06:22 Functions: 31 33 93.9 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    low level WINS replication client code
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2005
       7             :    Copyright (C) Stefan Metzmacher 2005-2010
       8             :    
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             :    
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             :    
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "lib/events/events.h"
      25             : #include "../lib/util/dlinklist.h"
      26             : #include "libcli/wrepl/winsrepl.h"
      27             : #include "librpc/gen_ndr/ndr_winsrepl.h"
      28             : #include "lib/stream/packet.h"
      29             : #include "system/network.h"
      30             : #include "lib/socket/netif.h"
      31             : #include "param/param.h"
      32             : #include "lib/util/tevent_ntstatus.h"
      33             : #include "lib/tsocket/tsocket.h"
      34             : #include "libcli/util/tstream.h"
      35             : 
      36             : /*
      37             :   main context structure for the wins replication client library
      38             : */
      39             : struct wrepl_socket {
      40             :         struct {
      41             :                 struct tevent_context *ctx;
      42             :         } event;
      43             : 
      44             :         /* the default timeout for requests, 0 means no timeout */
      45             : #define WREPL_SOCKET_REQUEST_TIMEOUT    (60)
      46             :         uint32_t request_timeout;
      47             : 
      48             :         struct tevent_queue *request_queue;
      49             : 
      50             :         struct tstream_context *stream;
      51             : };
      52             : 
      53         675 : bool wrepl_socket_is_connected(struct wrepl_socket *wrepl_sock)
      54             : {
      55         675 :         if (!wrepl_sock) {
      56           0 :                 return false;
      57             :         }
      58             : 
      59         675 :         if (!wrepl_sock->stream) {
      60           0 :                 return false;
      61             :         }
      62             : 
      63         675 :         return true;
      64             : }
      65             : 
      66             : /*
      67             :   initialise a wrepl_socket. The event_ctx is optional, if provided then
      68             :   operations will use that event context
      69             : */
      70        1354 : struct wrepl_socket *wrepl_socket_init(TALLOC_CTX *mem_ctx,
      71             :                                        struct tevent_context *event_ctx)
      72             : {
      73           0 :         struct wrepl_socket *wrepl_socket;
      74             : 
      75        1354 :         wrepl_socket = talloc_zero(mem_ctx, struct wrepl_socket);
      76        1354 :         if (!wrepl_socket) {
      77           0 :                 return NULL;
      78             :         }
      79             : 
      80        1354 :         wrepl_socket->event.ctx = event_ctx;
      81        1354 :         if (!wrepl_socket->event.ctx) {
      82           0 :                 goto failed;
      83             :         }
      84             : 
      85        1354 :         wrepl_socket->request_queue = tevent_queue_create(wrepl_socket,
      86             :                                                           "wrepl request queue");
      87        1354 :         if (wrepl_socket->request_queue == NULL) {
      88           0 :                 goto failed;
      89             :         }
      90             : 
      91        1354 :         wrepl_socket->request_timeout        = WREPL_SOCKET_REQUEST_TIMEOUT;
      92             : 
      93        1354 :         return wrepl_socket;
      94             : 
      95           0 : failed:
      96           0 :         talloc_free(wrepl_socket);
      97           0 :         return NULL;
      98             : }
      99             : 
     100             : /*
     101             :   initialise a wrepl_socket from an already existing connection
     102             : */
     103         675 : NTSTATUS wrepl_socket_donate_stream(struct wrepl_socket *wrepl_socket,
     104             :                                     struct tstream_context **stream)
     105             : {
     106         675 :         if (wrepl_socket->stream) {
     107           0 :                 return NT_STATUS_CONNECTION_ACTIVE;
     108             :         }
     109             : 
     110         675 :         wrepl_socket->stream = talloc_move(wrepl_socket, stream);
     111             :         /* as client we want to drain the recv queue on error */
     112         675 :         tstream_bsd_fail_readv_first_error(wrepl_socket->stream, false);
     113         675 :         return NT_STATUS_OK;
     114             : }
     115             : 
     116             : /*
     117             :   initialise a wrepl_socket from an already existing connection
     118             : */
     119           0 : NTSTATUS wrepl_socket_split_stream(struct wrepl_socket *wrepl_socket,
     120             :                                    TALLOC_CTX *mem_ctx,
     121             :                                    struct tstream_context **stream)
     122             : {
     123           0 :         size_t num_requests;
     124             : 
     125           0 :         if (!wrepl_socket->stream) {
     126           0 :                 return NT_STATUS_CONNECTION_INVALID;
     127             :         }
     128             : 
     129           0 :         num_requests = tevent_queue_length(wrepl_socket->request_queue);
     130           0 :         if (num_requests > 0) {
     131           0 :                 return NT_STATUS_CONNECTION_IN_USE;
     132             :         }
     133             : 
     134           0 :         *stream = talloc_move(wrepl_socket, &wrepl_socket->stream);
     135           0 :         return NT_STATUS_OK;
     136             : }
     137             : 
     138         679 : const char *wrepl_best_ip(struct loadparm_context *lp_ctx, const char *peer_ip)
     139             : {
     140           0 :         struct interface *ifaces;
     141         679 :         load_interface_list(lp_ctx, lp_ctx, &ifaces);
     142         679 :         return iface_list_best_ip(ifaces, peer_ip);
     143             : }
     144             : 
     145             : struct wrepl_connect_state {
     146             :         struct {
     147             :                 struct wrepl_socket *wrepl_socket;
     148             :                 struct tevent_context *ev;
     149             :         } caller;
     150             :         struct tsocket_address *local_address;
     151             :         struct tsocket_address *remote_address;
     152             :         struct tstream_context *stream;
     153             : };
     154             : 
     155             : static void wrepl_connect_trigger(struct tevent_req *req,
     156             :                                   void *private_date);
     157             : 
     158         679 : struct tevent_req *wrepl_connect_send(TALLOC_CTX *mem_ctx,
     159             :                                       struct tevent_context *ev,
     160             :                                       struct wrepl_socket *wrepl_socket,
     161             :                                       const char *our_ip, const char *peer_ip)
     162             : {
     163           0 :         struct tevent_req *req;
     164           0 :         struct wrepl_connect_state *state;
     165           0 :         int ret;
     166           0 :         bool ok;
     167             : 
     168         679 :         req = tevent_req_create(mem_ctx, &state,
     169             :                                 struct wrepl_connect_state);
     170         679 :         if (req == NULL) {
     171           0 :                 return NULL;
     172             :         }
     173             : 
     174         679 :         state->caller.wrepl_socket = wrepl_socket;
     175         679 :         state->caller.ev = ev;
     176             : 
     177         679 :         if (wrepl_socket->stream) {
     178           0 :                 tevent_req_nterror(req, NT_STATUS_CONNECTION_ACTIVE);
     179           0 :                 return tevent_req_post(req, ev);
     180             :         }
     181             : 
     182         679 :         ret = tsocket_address_inet_from_strings(state, "ipv4",
     183             :                                                 our_ip, 0,
     184             :                                                 &state->local_address);
     185         679 :         if (ret != 0) {
     186           0 :                 NTSTATUS status = map_nt_error_from_unix_common(errno);
     187           0 :                 tevent_req_nterror(req, status);
     188           0 :                 return tevent_req_post(req, ev);
     189             :         }
     190             : 
     191         679 :         ret = tsocket_address_inet_from_strings(state, "ipv4",
     192             :                                                 peer_ip, WINS_REPLICATION_PORT,
     193             :                                                 &state->remote_address);
     194         679 :         if (ret != 0) {
     195           0 :                 NTSTATUS status = map_nt_error_from_unix_common(errno);
     196           0 :                 tevent_req_nterror(req, status);
     197           0 :                 return tevent_req_post(req, ev);
     198             :         }
     199             : 
     200         679 :         ok = tevent_queue_add(wrepl_socket->request_queue,
     201             :                               ev,
     202             :                               req,
     203             :                               wrepl_connect_trigger,
     204             :                               NULL);
     205         679 :         if (!ok) {
     206           0 :                 tevent_req_oom(req);
     207           0 :                 return tevent_req_post(req, ev);
     208             :         }
     209             : 
     210         679 :         if (wrepl_socket->request_timeout > 0) {
     211           0 :                 struct timeval endtime;
     212         679 :                 endtime = tevent_timeval_current_ofs(wrepl_socket->request_timeout, 0);
     213         679 :                 ok = tevent_req_set_endtime(req, ev, endtime);
     214         679 :                 if (!ok) {
     215           0 :                         return tevent_req_post(req, ev);
     216             :                 }
     217             :         }
     218             : 
     219         679 :         return req;
     220             : }
     221             : 
     222             : static void wrepl_connect_done(struct tevent_req *subreq);
     223             : 
     224         679 : static void wrepl_connect_trigger(struct tevent_req *req,
     225             :                                   void *private_date)
     226             : {
     227         679 :         struct wrepl_connect_state *state = tevent_req_data(req,
     228             :                                             struct wrepl_connect_state);
     229           0 :         struct tevent_req *subreq;
     230             : 
     231         679 :         subreq = tstream_inet_tcp_connect_send(state,
     232             :                                                state->caller.ev,
     233         679 :                                                state->local_address,
     234         679 :                                                state->remote_address);
     235         679 :         if (tevent_req_nomem(subreq, req)) {
     236           0 :                 return;
     237             :         }
     238         679 :         tevent_req_set_callback(subreq, wrepl_connect_done, req);
     239             : 
     240         679 :         return;
     241             : }
     242             : 
     243         679 : static void wrepl_connect_done(struct tevent_req *subreq)
     244             : {
     245         679 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     246             :                                  struct tevent_req);
     247         679 :         struct wrepl_connect_state *state = tevent_req_data(req,
     248             :                                             struct wrepl_connect_state);
     249           0 :         int ret;
     250           0 :         int sys_errno;
     251             : 
     252         679 :         ret = tstream_inet_tcp_connect_recv(subreq, &sys_errno,
     253             :                                             state, &state->stream, NULL);
     254         679 :         if (ret != 0) {
     255           0 :                 NTSTATUS status = map_nt_error_from_unix_common(sys_errno);
     256           0 :                 tevent_req_nterror(req, status);
     257           0 :                 return;
     258             :         }
     259             : 
     260         679 :         tevent_req_done(req);
     261             : }
     262             : 
     263             : /*
     264             :   connect a wrepl_socket to a WINS server - recv side
     265             : */
     266         679 : NTSTATUS wrepl_connect_recv(struct tevent_req *req)
     267             : {
     268         679 :         struct wrepl_connect_state *state = tevent_req_data(req,
     269             :                                             struct wrepl_connect_state);
     270         679 :         struct wrepl_socket *wrepl_socket = state->caller.wrepl_socket;
     271           0 :         NTSTATUS status;
     272             : 
     273         679 :         if (tevent_req_is_nterror(req, &status)) {
     274           0 :                 tevent_req_received(req);
     275           0 :                 return status;
     276             :         }
     277             : 
     278         679 :         wrepl_socket->stream = talloc_move(wrepl_socket, &state->stream);
     279             : 
     280         679 :         tevent_req_received(req);
     281         679 :         return NT_STATUS_OK;
     282             : }
     283             : 
     284             : /*
     285             :   connect a wrepl_socket to a WINS server - sync API
     286             : */
     287         679 : NTSTATUS wrepl_connect(struct wrepl_socket *wrepl_socket,
     288             :                        const char *our_ip, const char *peer_ip)
     289             : {
     290           0 :         struct tevent_req *subreq;
     291           0 :         bool ok;
     292           0 :         NTSTATUS status;
     293             : 
     294         679 :         subreq = wrepl_connect_send(wrepl_socket, wrepl_socket->event.ctx,
     295             :                                     wrepl_socket, our_ip, peer_ip);
     296         679 :         NT_STATUS_HAVE_NO_MEMORY(subreq);
     297             : 
     298         679 :         ok = tevent_req_poll(subreq, wrepl_socket->event.ctx);
     299         679 :         if (!ok) {
     300           0 :                 TALLOC_FREE(subreq);
     301           0 :                 return NT_STATUS_INTERNAL_ERROR;
     302             :         }
     303             : 
     304         679 :         status = wrepl_connect_recv(subreq);
     305         679 :         TALLOC_FREE(subreq);
     306         679 :         NT_STATUS_NOT_OK_RETURN(status);
     307             : 
     308         679 :         return NT_STATUS_OK;
     309             : }
     310             : 
     311             : struct wrepl_request_state {
     312             :         struct {
     313             :                 struct wrepl_socket *wrepl_socket;
     314             :                 struct tevent_context *ev;
     315             :         } caller;
     316             :         struct wrepl_send_ctrl ctrl;
     317             :         struct {
     318             :                 struct wrepl_wrap wrap;
     319             :                 DATA_BLOB blob;
     320             :                 struct iovec iov;
     321             :         } req;
     322             :         bool one_way;
     323             :         struct {
     324             :                 DATA_BLOB blob;
     325             :                 struct wrepl_packet *packet;
     326             :         } rep;
     327             : };
     328             : 
     329             : static void wrepl_request_trigger(struct tevent_req *req,
     330             :                                   void *private_data);
     331             : 
     332        4164 : struct tevent_req *wrepl_request_send(TALLOC_CTX *mem_ctx,
     333             :                                       struct tevent_context *ev,
     334             :                                       struct wrepl_socket *wrepl_socket,
     335             :                                       const struct wrepl_packet *packet,
     336             :                                       const struct wrepl_send_ctrl *ctrl)
     337             : {
     338           0 :         struct tevent_req *req;
     339           0 :         struct wrepl_request_state *state;
     340           0 :         NTSTATUS status;
     341           0 :         enum ndr_err_code ndr_err;
     342           0 :         bool ok;
     343             : 
     344        4164 :         if (wrepl_socket->event.ctx != ev) {
     345             :                 /* TODO: remove wrepl_socket->event.ctx !!! */
     346           0 :                 smb_panic("wrepl_associate_stop_send event context mismatch!");
     347             :                 return NULL;
     348             :         }
     349             : 
     350        4164 :         req = tevent_req_create(mem_ctx, &state,
     351             :                                 struct wrepl_request_state);
     352        4164 :         if (req == NULL) {
     353           0 :                 return NULL;
     354             :         }
     355             : 
     356        4164 :         state->caller.wrepl_socket = wrepl_socket;
     357        4164 :         state->caller.ev = ev;
     358             : 
     359        4164 :         if (ctrl) {
     360         675 :                 state->ctrl = *ctrl;
     361             :         }
     362             : 
     363        4164 :         if (wrepl_socket->stream == NULL) {
     364           0 :                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
     365           0 :                 return tevent_req_post(req, ev);
     366             :         }
     367             : 
     368        4164 :         state->req.wrap.packet = *packet;
     369        4164 :         ndr_err = ndr_push_struct_blob(&state->req.blob, state,
     370        4164 :                                        &state->req.wrap,
     371             :                                        (ndr_push_flags_fn_t)ndr_push_wrepl_wrap);
     372        4164 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     373           0 :                 status = ndr_map_error2ntstatus(ndr_err);
     374           0 :                 tevent_req_nterror(req, status);
     375           0 :                 return tevent_req_post(req, ev);
     376             :         }
     377             : 
     378        4164 :         state->req.iov.iov_base = (char *) state->req.blob.data;
     379        4164 :         state->req.iov.iov_len = state->req.blob.length;
     380             : 
     381        4164 :         ok = tevent_queue_add(wrepl_socket->request_queue,
     382             :                               ev,
     383             :                               req,
     384             :                               wrepl_request_trigger,
     385             :                               NULL);
     386        4164 :         if (!ok) {
     387           0 :                 tevent_req_oom(req);
     388           0 :                 return tevent_req_post(req, ev);
     389             :         }
     390             : 
     391        4164 :         if (wrepl_socket->request_timeout > 0) {
     392           0 :                 struct timeval endtime;
     393        4164 :                 endtime = tevent_timeval_current_ofs(wrepl_socket->request_timeout, 0);
     394        4164 :                 ok = tevent_req_set_endtime(req, ev, endtime);
     395        4164 :                 if (!ok) {
     396           0 :                         return tevent_req_post(req, ev);
     397             :                 }
     398             :         }
     399             : 
     400        4164 :         return req;
     401             : }
     402             : 
     403             : static void wrepl_request_writev_done(struct tevent_req *subreq);
     404             : 
     405        4164 : static void wrepl_request_trigger(struct tevent_req *req,
     406             :                                   void *private_data)
     407             : {
     408        4164 :         struct wrepl_request_state *state = tevent_req_data(req,
     409             :                                             struct wrepl_request_state);
     410           0 :         struct tevent_req *subreq;
     411             : 
     412        4164 :         if (state->caller.wrepl_socket->stream == NULL) {
     413           0 :                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
     414           0 :                 return;
     415             :         }
     416             : 
     417        4164 :         if (DEBUGLVL(10)) {
     418           0 :                 DEBUG(10,("Sending WINS packet of length %u\n",
     419             :                           (unsigned)state->req.blob.length));
     420           0 :                 NDR_PRINT_DEBUG(wrepl_packet, &state->req.wrap.packet);
     421             :         }
     422             : 
     423        4164 :         subreq = tstream_writev_send(state,
     424             :                                      state->caller.ev,
     425        4164 :                                      state->caller.wrepl_socket->stream,
     426        4164 :                                      &state->req.iov, 1);
     427        4164 :         if (tevent_req_nomem(subreq, req)) {
     428           0 :                 return;
     429             :         }
     430        4164 :         tevent_req_set_callback(subreq, wrepl_request_writev_done, req);
     431             : }
     432             : 
     433             : static void wrepl_request_disconnect_done(struct tevent_req *subreq);
     434             : static void wrepl_request_read_pdu_done(struct tevent_req *subreq);
     435             : 
     436        4164 : static void wrepl_request_writev_done(struct tevent_req *subreq)
     437             : {
     438        4164 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     439             :                                  struct tevent_req);
     440        4164 :         struct wrepl_request_state *state = tevent_req_data(req,
     441             :                                             struct wrepl_request_state);
     442           0 :         int ret;
     443           0 :         int sys_errno;
     444             : 
     445        4164 :         ret = tstream_writev_recv(subreq, &sys_errno);
     446        4164 :         TALLOC_FREE(subreq);
     447        4164 :         if (ret == -1) {
     448           0 :                 NTSTATUS status = map_nt_error_from_unix_common(sys_errno);
     449           0 :                 TALLOC_FREE(state->caller.wrepl_socket->stream);
     450           0 :                 tevent_req_nterror(req, status);
     451           0 :                 return;
     452             :         }
     453             : 
     454        4164 :         if (state->caller.wrepl_socket->stream == NULL) {
     455           0 :                 tevent_req_nterror(req, NT_STATUS_CONNECTION_DISCONNECTED);
     456           0 :                 return;
     457             :         }
     458             : 
     459        4164 :         if (state->ctrl.disconnect_after_send) {
     460         675 :                 subreq = tstream_disconnect_send(state,
     461             :                                                  state->caller.ev,
     462         675 :                                                  state->caller.wrepl_socket->stream);
     463         675 :                 if (tevent_req_nomem(subreq, req)) {
     464           0 :                         return;
     465             :                 }
     466         675 :                 tevent_req_set_callback(subreq, wrepl_request_disconnect_done, req);
     467         675 :                 return;
     468             :         }
     469             : 
     470        3489 :         if (state->ctrl.send_only) {
     471           0 :                 tevent_req_done(req);
     472           0 :                 return;
     473             :         }
     474             : 
     475        3489 :         subreq = tstream_read_pdu_blob_send(state,
     476             :                                             state->caller.ev,
     477        3489 :                                             state->caller.wrepl_socket->stream,
     478             :                                             4, /* initial_read_size */
     479             :                                             tstream_full_request_u32,
     480             :                                             NULL);
     481        3489 :         if (tevent_req_nomem(subreq, req)) {
     482           0 :                 return;
     483             :         }
     484        3489 :         tevent_req_set_callback(subreq, wrepl_request_read_pdu_done, req);
     485             : }
     486             : 
     487         675 : static void wrepl_request_disconnect_done(struct tevent_req *subreq)
     488             : {
     489         675 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     490             :                                  struct tevent_req);
     491         675 :         struct wrepl_request_state *state = tevent_req_data(req,
     492             :                                             struct wrepl_request_state);
     493           0 :         int ret;
     494           0 :         int sys_errno;
     495             : 
     496         675 :         ret = tstream_disconnect_recv(subreq, &sys_errno);
     497         675 :         TALLOC_FREE(subreq);
     498         675 :         if (ret == -1) {
     499           0 :                 NTSTATUS status = map_nt_error_from_unix_common(sys_errno);
     500           0 :                 TALLOC_FREE(state->caller.wrepl_socket->stream);
     501           0 :                 tevent_req_nterror(req, status);
     502           0 :                 return;
     503             :         }
     504             : 
     505         675 :         DEBUG(10,("WINS connection disconnected\n"));
     506         675 :         TALLOC_FREE(state->caller.wrepl_socket->stream);
     507             : 
     508         675 :         tevent_req_done(req);
     509             : }
     510             : 
     511        3489 : static void wrepl_request_read_pdu_done(struct tevent_req *subreq)
     512             : {
     513        3489 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     514             :                                  struct tevent_req);
     515        3489 :         struct wrepl_request_state *state = tevent_req_data(req,
     516             :                                             struct wrepl_request_state);
     517           0 :         NTSTATUS status;
     518           0 :         DATA_BLOB blob;
     519           0 :         enum ndr_err_code ndr_err;
     520             : 
     521        3489 :         status = tstream_read_pdu_blob_recv(subreq, state, &state->rep.blob);
     522        3489 :         if (!NT_STATUS_IS_OK(status)) {
     523           0 :                 TALLOC_FREE(state->caller.wrepl_socket->stream);
     524           0 :                 tevent_req_nterror(req, status);
     525           0 :                 return;
     526             :         }
     527             : 
     528        3489 :         state->rep.packet = talloc(state, struct wrepl_packet);
     529        3489 :         if (tevent_req_nomem(state->rep.packet, req)) {
     530           0 :                 return;
     531             :         }
     532             : 
     533        3489 :         blob.data = state->rep.blob.data + 4;
     534        3489 :         blob.length = state->rep.blob.length - 4;
     535             : 
     536             :         /* we have a full request - parse it */
     537        3489 :         ndr_err = ndr_pull_struct_blob(&blob,
     538        3489 :                                        state->rep.packet,
     539        3489 :                                        state->rep.packet,
     540             :                                        (ndr_pull_flags_fn_t)ndr_pull_wrepl_packet);
     541        3489 :         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     542           0 :                 status = ndr_map_error2ntstatus(ndr_err);
     543           0 :                 tevent_req_nterror(req, status);
     544           0 :                 return;
     545             :         }
     546             : 
     547        3489 :         if (DEBUGLVL(10)) {
     548           0 :                 DEBUG(10,("Received WINS packet of length %u\n",
     549             :                           (unsigned)state->rep.blob.length));
     550           0 :                 NDR_PRINT_DEBUG(wrepl_packet, state->rep.packet);
     551             :         }
     552             : 
     553        3489 :         tevent_req_done(req);
     554             : }
     555             : 
     556        4164 : NTSTATUS wrepl_request_recv(struct tevent_req *req,
     557             :                             TALLOC_CTX *mem_ctx,
     558             :                             struct wrepl_packet **packet)
     559             : {
     560        4164 :         struct wrepl_request_state *state = tevent_req_data(req,
     561             :                                             struct wrepl_request_state);
     562           0 :         NTSTATUS status;
     563             : 
     564        4164 :         if (tevent_req_is_nterror(req, &status)) {
     565           0 :                 TALLOC_FREE(state->caller.wrepl_socket->stream);
     566           0 :                 tevent_req_received(req);
     567           0 :                 return status;
     568             :         }
     569             : 
     570        4164 :         if (packet) {
     571        3489 :                 *packet = talloc_move(mem_ctx, &state->rep.packet);
     572             :         }
     573             : 
     574        4164 :         tevent_req_received(req);
     575        4164 :         return NT_STATUS_OK;
     576             : }
     577             : 
     578             : /*
     579             :   a full WINS replication request/response
     580             : */
     581        1350 : NTSTATUS wrepl_request(struct wrepl_socket *wrepl_socket,
     582             :                        TALLOC_CTX *mem_ctx,
     583             :                        const struct wrepl_packet *req_packet,
     584             :                        struct wrepl_packet **reply_packet)
     585             : {
     586           0 :         struct tevent_req *subreq;
     587           0 :         bool ok;
     588           0 :         NTSTATUS status;
     589             : 
     590        1350 :         subreq = wrepl_request_send(mem_ctx, wrepl_socket->event.ctx,
     591             :                                     wrepl_socket, req_packet, NULL);
     592        1350 :         NT_STATUS_HAVE_NO_MEMORY(subreq);
     593             : 
     594        1350 :         ok = tevent_req_poll(subreq, wrepl_socket->event.ctx);
     595        1350 :         if (!ok) {
     596           0 :                 TALLOC_FREE(subreq);
     597           0 :                 return NT_STATUS_INTERNAL_ERROR;
     598             :         }
     599             : 
     600        1350 :         status = wrepl_request_recv(subreq, mem_ctx, reply_packet);
     601        1350 :         TALLOC_FREE(subreq);
     602        1350 :         NT_STATUS_NOT_OK_RETURN(status);
     603             : 
     604        1350 :         return NT_STATUS_OK;
     605             : }
     606             : 
     607             : 
     608             : struct wrepl_associate_state {
     609             :         struct wrepl_packet packet;
     610             :         uint32_t assoc_ctx;
     611             :         uint16_t major_version;
     612             : };
     613             : 
     614             : static void wrepl_associate_done(struct tevent_req *subreq);
     615             : 
     616         681 : struct tevent_req *wrepl_associate_send(TALLOC_CTX *mem_ctx,
     617             :                                         struct tevent_context *ev,
     618             :                                         struct wrepl_socket *wrepl_socket,
     619             :                                         const struct wrepl_associate *io)
     620             : {
     621           0 :         struct tevent_req *req;
     622           0 :         struct wrepl_associate_state *state;
     623           0 :         struct tevent_req *subreq;
     624             : 
     625         681 :         if (wrepl_socket->event.ctx != ev) {
     626             :                 /* TODO: remove wrepl_socket->event.ctx !!! */
     627           0 :                 smb_panic("wrepl_associate_send event context mismatch!");
     628             :                 return NULL;
     629             :         }
     630             : 
     631         681 :         req = tevent_req_create(mem_ctx, &state,
     632             :                                 struct wrepl_associate_state);
     633         681 :         if (req == NULL) {
     634           0 :                 return NULL;
     635           0 :         };
     636             : 
     637         681 :         state->packet.opcode                         = WREPL_OPCODE_BITS;
     638         681 :         state->packet.mess_type                              = WREPL_START_ASSOCIATION;
     639         681 :         state->packet.message.start.minor_version    = 2;
     640         681 :         state->packet.message.start.major_version    = 5;
     641             : 
     642             :         /*
     643             :          * nt4 uses 41 bytes for the start_association call
     644             :          * so do it the same and as we don't know the meanings of these bytes
     645             :          * we just send zeros and nt4, w2k and w2k3 seems to be happy with this
     646             :          *
     647             :          * if we don't do this nt4 uses an old version of the wins replication protocol
     648             :          * and that would break nt4 <-> samba replication
     649             :          */
     650         681 :         state->packet.padding        = data_blob_talloc(state, NULL, 21);
     651         681 :         if (tevent_req_nomem(state->packet.padding.data, req)) {
     652           0 :                 return tevent_req_post(req, ev);
     653             :         }
     654         681 :         memset(state->packet.padding.data, 0, state->packet.padding.length);
     655             : 
     656         681 :         subreq = wrepl_request_send(state, ev, wrepl_socket, &state->packet, NULL);
     657         681 :         if (tevent_req_nomem(subreq, req)) {
     658           0 :                 return tevent_req_post(req, ev);
     659             :         }
     660         681 :         tevent_req_set_callback(subreq, wrepl_associate_done, req);
     661             : 
     662         681 :         return req;
     663             : }
     664             : 
     665         681 : static void wrepl_associate_done(struct tevent_req *subreq)
     666             : {
     667         681 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     668             :                                  struct tevent_req);
     669         681 :         struct wrepl_associate_state *state = tevent_req_data(req,
     670             :                                               struct wrepl_associate_state);
     671           0 :         NTSTATUS status;
     672           0 :         struct wrepl_packet *packet;
     673             : 
     674         681 :         status = wrepl_request_recv(subreq, state, &packet);
     675         681 :         TALLOC_FREE(subreq);
     676         681 :         if (!NT_STATUS_IS_OK(status)) {
     677           0 :                 tevent_req_nterror(req, status);
     678           0 :                 return;
     679             :         }
     680             : 
     681         681 :         if (packet->mess_type != WREPL_START_ASSOCIATION_REPLY) {
     682           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
     683           0 :                 return;
     684             :         }
     685             : 
     686         681 :         state->assoc_ctx = packet->message.start_reply.assoc_ctx;
     687         681 :         state->major_version = packet->message.start_reply.major_version;
     688             : 
     689         681 :         tevent_req_done(req);
     690             : }
     691             : 
     692             : /*
     693             :   setup an association - recv
     694             : */
     695         681 : NTSTATUS wrepl_associate_recv(struct tevent_req *req,
     696             :                               struct wrepl_associate *io)
     697             : {
     698         681 :         struct wrepl_associate_state *state = tevent_req_data(req,
     699             :                                               struct wrepl_associate_state);
     700           0 :         NTSTATUS status;
     701             : 
     702         681 :         if (tevent_req_is_nterror(req, &status)) {
     703           0 :                 tevent_req_received(req);
     704           0 :                 return status;
     705             :         }
     706             : 
     707         681 :         io->out.assoc_ctx = state->assoc_ctx;
     708         681 :         io->out.major_version = state->major_version;
     709             : 
     710         681 :         tevent_req_received(req);
     711         681 :         return NT_STATUS_OK;
     712             : }
     713             : 
     714             : /*
     715             :   setup an association - sync api
     716             : */
     717         681 : NTSTATUS wrepl_associate(struct wrepl_socket *wrepl_socket,
     718             :                          struct wrepl_associate *io)
     719             : {
     720           0 :         struct tevent_req *subreq;
     721           0 :         bool ok;
     722           0 :         NTSTATUS status;
     723             : 
     724         681 :         subreq = wrepl_associate_send(wrepl_socket, wrepl_socket->event.ctx,
     725             :                                       wrepl_socket, io);
     726         681 :         NT_STATUS_HAVE_NO_MEMORY(subreq);
     727             : 
     728         681 :         ok = tevent_req_poll(subreq, wrepl_socket->event.ctx);
     729         681 :         if (!ok) {
     730           0 :                 TALLOC_FREE(subreq);
     731           0 :                 return NT_STATUS_INTERNAL_ERROR;
     732             :         }
     733             : 
     734         681 :         status = wrepl_associate_recv(subreq, io);
     735         681 :         TALLOC_FREE(subreq);
     736         681 :         NT_STATUS_NOT_OK_RETURN(status);
     737             : 
     738         681 :         return NT_STATUS_OK;
     739             : }
     740             : 
     741             : struct wrepl_associate_stop_state {
     742             :         struct wrepl_packet packet;
     743             :         struct wrepl_send_ctrl ctrl;
     744             : };
     745             : 
     746             : static void wrepl_associate_stop_done(struct tevent_req *subreq);
     747             : 
     748         675 : struct tevent_req *wrepl_associate_stop_send(TALLOC_CTX *mem_ctx,
     749             :                                              struct tevent_context *ev,
     750             :                                              struct wrepl_socket *wrepl_socket,
     751             :                                              const struct wrepl_associate_stop *io)
     752             : {
     753           0 :         struct tevent_req *req;
     754           0 :         struct wrepl_associate_stop_state *state;
     755           0 :         struct tevent_req *subreq;
     756             : 
     757         675 :         if (wrepl_socket->event.ctx != ev) {
     758             :                 /* TODO: remove wrepl_socket->event.ctx !!! */
     759           0 :                 smb_panic("wrepl_associate_stop_send event context mismatch!");
     760             :                 return NULL;
     761             :         }
     762             : 
     763         675 :         req = tevent_req_create(mem_ctx, &state,
     764             :                                 struct wrepl_associate_stop_state);
     765         675 :         if (req == NULL) {
     766           0 :                 return NULL;
     767           0 :         };
     768             : 
     769         675 :         state->packet.opcode                 = WREPL_OPCODE_BITS;
     770         675 :         state->packet.assoc_ctx                      = io->in.assoc_ctx;
     771         675 :         state->packet.mess_type                      = WREPL_STOP_ASSOCIATION;
     772         675 :         state->packet.message.stop.reason    = io->in.reason;
     773             : 
     774         675 :         if (io->in.reason == 0) {
     775         675 :                 state->ctrl.send_only                        = true;
     776         675 :                 state->ctrl.disconnect_after_send    = true;
     777             :         }
     778             : 
     779         675 :         subreq = wrepl_request_send(state, ev, wrepl_socket, &state->packet, &state->ctrl);
     780         675 :         if (tevent_req_nomem(subreq, req)) {
     781           0 :                 return tevent_req_post(req, ev);
     782             :         }
     783         675 :         tevent_req_set_callback(subreq, wrepl_associate_stop_done, req);
     784             : 
     785         675 :         return req;
     786             : }
     787             : 
     788         675 : static void wrepl_associate_stop_done(struct tevent_req *subreq)
     789             : {
     790         675 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     791             :                                  struct tevent_req);
     792         675 :         struct wrepl_associate_stop_state *state = tevent_req_data(req,
     793             :                                                    struct wrepl_associate_stop_state);
     794           0 :         NTSTATUS status;
     795             : 
     796             :         /* currently we don't care about a possible response */
     797         675 :         status = wrepl_request_recv(subreq, state, NULL);
     798         675 :         TALLOC_FREE(subreq);
     799         675 :         if (!NT_STATUS_IS_OK(status)) {
     800           0 :                 tevent_req_nterror(req, status);
     801           0 :                 return;
     802             :         }
     803             : 
     804         675 :         tevent_req_done(req);
     805             : }
     806             : 
     807             : /*
     808             :   stop an association - recv
     809             : */
     810         675 : NTSTATUS wrepl_associate_stop_recv(struct tevent_req *req,
     811             :                                    struct wrepl_associate_stop *io)
     812             : {
     813           0 :         NTSTATUS status;
     814             : 
     815         675 :         if (tevent_req_is_nterror(req, &status)) {
     816           0 :                 tevent_req_received(req);
     817           0 :                 return status;
     818             :         }
     819             : 
     820         675 :         tevent_req_received(req);
     821         675 :         return NT_STATUS_OK;
     822             : }
     823             : 
     824             : /*
     825             :   setup an association - sync api
     826             : */
     827           0 : NTSTATUS wrepl_associate_stop(struct wrepl_socket *wrepl_socket,
     828             :                               struct wrepl_associate_stop *io)
     829             : {
     830           0 :         struct tevent_req *subreq;
     831           0 :         bool ok;
     832           0 :         NTSTATUS status;
     833             : 
     834           0 :         subreq = wrepl_associate_stop_send(wrepl_socket, wrepl_socket->event.ctx,
     835             :                                            wrepl_socket, io);
     836           0 :         NT_STATUS_HAVE_NO_MEMORY(subreq);
     837             : 
     838           0 :         ok = tevent_req_poll(subreq, wrepl_socket->event.ctx);
     839           0 :         if (!ok) {
     840           0 :                 TALLOC_FREE(subreq);
     841           0 :                 return NT_STATUS_INTERNAL_ERROR;
     842             :         }
     843             : 
     844           0 :         status = wrepl_associate_stop_recv(subreq, io);
     845           0 :         TALLOC_FREE(subreq);
     846           0 :         NT_STATUS_NOT_OK_RETURN(status);
     847             : 
     848           0 :         return NT_STATUS_OK;
     849             : }
     850             : 
     851             : struct wrepl_pull_table_state {
     852             :         struct wrepl_packet packet;
     853             :         uint32_t num_partners;
     854             :         struct wrepl_wins_owner *partners;
     855             : };
     856             : 
     857             : static void wrepl_pull_table_done(struct tevent_req *subreq);
     858             : 
     859           3 : struct tevent_req *wrepl_pull_table_send(TALLOC_CTX *mem_ctx,
     860             :                                          struct tevent_context *ev,
     861             :                                          struct wrepl_socket *wrepl_socket,
     862             :                                          const struct wrepl_pull_table *io)
     863             : {
     864           0 :         struct tevent_req *req;
     865           0 :         struct wrepl_pull_table_state *state;
     866           0 :         struct tevent_req *subreq;
     867             : 
     868           3 :         if (wrepl_socket->event.ctx != ev) {
     869             :                 /* TODO: remove wrepl_socket->event.ctx !!! */
     870           0 :                 smb_panic("wrepl_pull_table_send event context mismatch!");
     871             :                 return NULL;
     872             :         }
     873             : 
     874           3 :         req = tevent_req_create(mem_ctx, &state,
     875             :                                 struct wrepl_pull_table_state);
     876           3 :         if (req == NULL) {
     877           0 :                 return NULL;
     878           0 :         };
     879             : 
     880           3 :         state->packet.opcode                         = WREPL_OPCODE_BITS;
     881           3 :         state->packet.assoc_ctx                              = io->in.assoc_ctx;
     882           3 :         state->packet.mess_type                              = WREPL_REPLICATION;
     883           3 :         state->packet.message.replication.command    = WREPL_REPL_TABLE_QUERY;
     884             : 
     885           3 :         subreq = wrepl_request_send(state, ev, wrepl_socket, &state->packet, NULL);
     886           3 :         if (tevent_req_nomem(subreq, req)) {
     887           0 :                 return tevent_req_post(req, ev);
     888             :         }
     889           3 :         tevent_req_set_callback(subreq, wrepl_pull_table_done, req);
     890             : 
     891           3 :         return req;
     892             : }
     893             : 
     894           3 : static void wrepl_pull_table_done(struct tevent_req *subreq)
     895             : {
     896           3 :         struct tevent_req *req = tevent_req_callback_data(subreq,
     897             :                                  struct tevent_req);
     898           3 :         struct wrepl_pull_table_state *state = tevent_req_data(req,
     899             :                                                struct wrepl_pull_table_state);
     900           0 :         NTSTATUS status;
     901           0 :         struct wrepl_packet *packet;
     902           0 :         struct wrepl_table *table;
     903             : 
     904           3 :         status = wrepl_request_recv(subreq, state, &packet);
     905           3 :         TALLOC_FREE(subreq);
     906           3 :         if (!NT_STATUS_IS_OK(status)) {
     907           0 :                 tevent_req_nterror(req, status);
     908           0 :                 return;
     909             :         }
     910             : 
     911           3 :         if (packet->mess_type != WREPL_REPLICATION) {
     912           0 :                 tevent_req_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
     913           0 :                 return;
     914             :         }
     915             : 
     916           3 :         if (packet->message.replication.command != WREPL_REPL_TABLE_REPLY) {
     917           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
     918           0 :                 return;
     919             :         }
     920             : 
     921           3 :         table = &packet->message.replication.info.table;
     922             : 
     923           3 :         state->num_partners = table->partner_count;
     924           3 :         state->partners = talloc_move(state, &table->partners);
     925             : 
     926           3 :         tevent_req_done(req);
     927             : }
     928             : 
     929             : /*
     930             :   fetch the partner tables - recv
     931             : */
     932           3 : NTSTATUS wrepl_pull_table_recv(struct tevent_req *req,
     933             :                                TALLOC_CTX *mem_ctx,
     934             :                                struct wrepl_pull_table *io)
     935             : {
     936           3 :         struct wrepl_pull_table_state *state = tevent_req_data(req,
     937             :                                                struct wrepl_pull_table_state);
     938           0 :         NTSTATUS status;
     939             : 
     940           3 :         if (tevent_req_is_nterror(req, &status)) {
     941           0 :                 tevent_req_received(req);
     942           0 :                 return status;
     943             :         }
     944             : 
     945           3 :         io->out.num_partners = state->num_partners;
     946           3 :         io->out.partners = talloc_move(mem_ctx, &state->partners);
     947             : 
     948           3 :         tevent_req_received(req);
     949           3 :         return NT_STATUS_OK;
     950             : }
     951             : 
     952             : /*
     953             :   fetch the partner table - sync api
     954             : */
     955           3 : NTSTATUS wrepl_pull_table(struct wrepl_socket *wrepl_socket,
     956             :                           TALLOC_CTX *mem_ctx,
     957             :                           struct wrepl_pull_table *io)
     958             : {
     959           0 :         struct tevent_req *subreq;
     960           0 :         bool ok;
     961           0 :         NTSTATUS status;
     962             : 
     963           3 :         subreq = wrepl_pull_table_send(mem_ctx, wrepl_socket->event.ctx,
     964             :                                        wrepl_socket, io);
     965           3 :         NT_STATUS_HAVE_NO_MEMORY(subreq);
     966             : 
     967           3 :         ok = tevent_req_poll(subreq, wrepl_socket->event.ctx);
     968           3 :         if (!ok) {
     969           0 :                 TALLOC_FREE(subreq);
     970           0 :                 return NT_STATUS_INTERNAL_ERROR;
     971             :         }
     972             : 
     973           3 :         status = wrepl_pull_table_recv(subreq, mem_ctx, io);
     974           3 :         TALLOC_FREE(subreq);
     975           3 :         NT_STATUS_NOT_OK_RETURN(status);
     976             : 
     977           3 :         return NT_STATUS_OK;
     978             : }
     979             : 
     980             : 
     981             : struct wrepl_pull_names_state {
     982             :         struct {
     983             :                 const struct wrepl_pull_names *io;
     984             :         } caller;
     985             :         struct wrepl_packet packet;
     986             :         uint32_t num_names;
     987             :         struct wrepl_name *names;
     988             : };
     989             : 
     990             : static void wrepl_pull_names_done(struct tevent_req *subreq);
     991             : 
     992        1455 : struct tevent_req *wrepl_pull_names_send(TALLOC_CTX *mem_ctx,
     993             :                                          struct tevent_context *ev,
     994             :                                          struct wrepl_socket *wrepl_socket,
     995             :                                          const struct wrepl_pull_names *io)
     996             : {
     997           0 :         struct tevent_req *req;
     998           0 :         struct wrepl_pull_names_state *state;
     999           0 :         struct tevent_req *subreq;
    1000             : 
    1001        1455 :         if (wrepl_socket->event.ctx != ev) {
    1002             :                 /* TODO: remove wrepl_socket->event.ctx !!! */
    1003           0 :                 smb_panic("wrepl_pull_names_send event context mismatch!");
    1004             :                 return NULL;
    1005             :         }
    1006             : 
    1007        1455 :         req = tevent_req_create(mem_ctx, &state,
    1008             :                                 struct wrepl_pull_names_state);
    1009        1455 :         if (req == NULL) {
    1010           0 :                 return NULL;
    1011           0 :         };
    1012        1455 :         state->caller.io = io;
    1013             : 
    1014        1455 :         state->packet.opcode                         = WREPL_OPCODE_BITS;
    1015        1455 :         state->packet.assoc_ctx                              = io->in.assoc_ctx;
    1016        1455 :         state->packet.mess_type                              = WREPL_REPLICATION;
    1017        1455 :         state->packet.message.replication.command    = WREPL_REPL_SEND_REQUEST;
    1018        1455 :         state->packet.message.replication.info.owner = io->in.partner;
    1019             : 
    1020        1455 :         subreq = wrepl_request_send(state, ev, wrepl_socket, &state->packet, NULL);
    1021        1455 :         if (tevent_req_nomem(subreq, req)) {
    1022           0 :                 return tevent_req_post(req, ev);
    1023             :         }
    1024        1455 :         tevent_req_set_callback(subreq, wrepl_pull_names_done, req);
    1025             : 
    1026        1455 :         return req;
    1027             : }
    1028             : 
    1029        1455 : static void wrepl_pull_names_done(struct tevent_req *subreq)
    1030             : {
    1031        1455 :         struct tevent_req *req = tevent_req_callback_data(subreq,
    1032             :                                  struct tevent_req);
    1033        1455 :         struct wrepl_pull_names_state *state = tevent_req_data(req,
    1034             :                                                struct wrepl_pull_names_state);
    1035           0 :         NTSTATUS status;
    1036           0 :         struct wrepl_packet *packet;
    1037           0 :         uint32_t i;
    1038             : 
    1039        1455 :         status = wrepl_request_recv(subreq, state, &packet);
    1040        1455 :         TALLOC_FREE(subreq);
    1041        1455 :         if (!NT_STATUS_IS_OK(status)) {
    1042           0 :                 tevent_req_nterror(req, status);
    1043           0 :                 return;
    1044             :         }
    1045             : 
    1046        1455 :         if (packet->mess_type != WREPL_REPLICATION) {
    1047           0 :                 tevent_req_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
    1048           0 :                 return;
    1049             :         }
    1050             : 
    1051        1455 :         if (packet->message.replication.command != WREPL_REPL_SEND_REPLY) {
    1052           0 :                 tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
    1053           0 :                 return;
    1054             :         }
    1055             : 
    1056        1455 :         state->num_names = packet->message.replication.info.reply.num_names;
    1057             : 
    1058        1455 :         state->names = talloc_array(state, struct wrepl_name, state->num_names);
    1059        1455 :         if (tevent_req_nomem(state->names, req)) {
    1060           0 :                 return;
    1061             :         }
    1062             : 
    1063             :         /* convert the list of names and addresses to a sane format */
    1064        2657 :         for (i=0; i < state->num_names; i++) {
    1065        1202 :                 struct wrepl_wins_name *wname = &packet->message.replication.info.reply.names[i];
    1066        1202 :                 struct wrepl_name *name = &state->names[i];
    1067             : 
    1068        1202 :                 name->name   = *wname->name;
    1069        1202 :                 talloc_steal(state->names, wname->name);
    1070        1202 :                 name->type   = WREPL_NAME_TYPE(wname->flags);
    1071        1202 :                 name->state  = WREPL_NAME_STATE(wname->flags);
    1072        1202 :                 name->node   = WREPL_NAME_NODE(wname->flags);
    1073        1202 :                 name->is_static      = WREPL_NAME_IS_STATIC(wname->flags);
    1074        1202 :                 name->raw_flags      = wname->flags;
    1075        1202 :                 name->version_id= wname->id;
    1076        2404 :                 name->owner  = talloc_strdup(state->names,
    1077        1202 :                                                 state->caller.io->in.partner.address);
    1078        1202 :                 if (tevent_req_nomem(name->owner, req)) {
    1079           0 :                         return;
    1080             :                 }
    1081             : 
    1082             :                 /* trying to save 1 or 2 bytes on the wire isn't a good idea */
    1083        1202 :                 if (wname->flags & 2) {
    1084           0 :                         uint32_t j;
    1085             : 
    1086         577 :                         name->num_addresses = wname->addresses.addresses.num_ips;
    1087         577 :                         name->addresses = talloc_array(state->names,
    1088             :                                                        struct wrepl_address,
    1089             :                                                        name->num_addresses);
    1090         577 :                         if (tevent_req_nomem(name->addresses, req)) {
    1091           0 :                                 return;
    1092             :                         }
    1093             : 
    1094        1418 :                         for (j=0;j<name->num_addresses;j++) {
    1095        1682 :                                 name->addresses[j].owner =
    1096         841 :                                         talloc_move(name->addresses,
    1097             :                                                     &wname->addresses.addresses.ips[j].owner);
    1098         841 :                                 name->addresses[j].address = 
    1099         841 :                                         talloc_move(name->addresses,
    1100             :                                                     &wname->addresses.addresses.ips[j].ip);
    1101             :                         }
    1102             :                 } else {
    1103         625 :                         name->num_addresses = 1;
    1104         625 :                         name->addresses = talloc_array(state->names,
    1105             :                                                        struct wrepl_address,
    1106             :                                                        name->num_addresses);
    1107         625 :                         if (tevent_req_nomem(name->addresses, req)) {
    1108           0 :                                 return;
    1109             :                         }
    1110             : 
    1111         625 :                         name->addresses[0].owner = talloc_strdup(name->addresses, name->owner);
    1112         625 :                         if (tevent_req_nomem(name->addresses[0].owner, req)) {
    1113           0 :                                 return;
    1114             :                         }
    1115         625 :                         name->addresses[0].address = talloc_move(name->addresses,
    1116             :                                                                  &wname->addresses.ip);
    1117             :                 }
    1118             :         }
    1119             : 
    1120        1455 :         tevent_req_done(req);
    1121             : }
    1122             : 
    1123             : /*
    1124             :   fetch the names for a WINS partner - recv
    1125             : */
    1126        1455 : NTSTATUS wrepl_pull_names_recv(struct tevent_req *req,
    1127             :                                TALLOC_CTX *mem_ctx,
    1128             :                                struct wrepl_pull_names *io)
    1129             : {
    1130        1455 :         struct wrepl_pull_names_state *state = tevent_req_data(req,
    1131             :                                                struct wrepl_pull_names_state);
    1132           0 :         NTSTATUS status;
    1133             : 
    1134        1455 :         if (tevent_req_is_nterror(req, &status)) {
    1135           0 :                 tevent_req_received(req);
    1136           0 :                 return status;
    1137             :         }
    1138             : 
    1139        1455 :         io->out.num_names = state->num_names;
    1140        1455 :         io->out.names = talloc_move(mem_ctx, &state->names);
    1141             : 
    1142        1455 :         tevent_req_received(req);
    1143        1455 :         return NT_STATUS_OK;
    1144             : }
    1145             : 
    1146             : 
    1147             : 
    1148             : /*
    1149             :   fetch the names for a WINS partner - sync api
    1150             : */
    1151         780 : NTSTATUS wrepl_pull_names(struct wrepl_socket *wrepl_socket,
    1152             :                           TALLOC_CTX *mem_ctx,
    1153             :                           struct wrepl_pull_names *io)
    1154             : {
    1155           0 :         struct tevent_req *subreq;
    1156           0 :         bool ok;
    1157           0 :         NTSTATUS status;
    1158             : 
    1159         780 :         subreq = wrepl_pull_names_send(mem_ctx, wrepl_socket->event.ctx,
    1160             :                                        wrepl_socket, io);
    1161         780 :         NT_STATUS_HAVE_NO_MEMORY(subreq);
    1162             : 
    1163         780 :         ok = tevent_req_poll(subreq, wrepl_socket->event.ctx);
    1164         780 :         if (!ok) {
    1165           0 :                 TALLOC_FREE(subreq);
    1166           0 :                 return NT_STATUS_INTERNAL_ERROR;
    1167             :         }
    1168             : 
    1169         780 :         status = wrepl_pull_names_recv(subreq, mem_ctx, io);
    1170         780 :         TALLOC_FREE(subreq);
    1171         780 :         NT_STATUS_NOT_OK_RETURN(status);
    1172             : 
    1173         780 :         return NT_STATUS_OK;
    1174             : }

Generated by: LCOV version 1.14