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

Generated by: LCOV version 1.13