Ignore:
Timestamp:
Nov 14, 2012, 12:59:34 PM (13 years ago)
Author:
Silvan Scherrer
Message:

Samba Server: update vendor to 3.6.0

Location:
vendor/current/source4/libcli/wrepl
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • vendor/current/source4/libcli/wrepl/winsrepl.c

    r414 r740  
    55
    66   Copyright (C) Andrew Tridgell 2005
     7   Copyright (C) Stefan Metzmacher 2005-2010
    78   
    89   This program is free software; you can redistribute it and/or modify
     
    2324#include "lib/events/events.h"
    2425#include "../lib/util/dlinklist.h"
    25 #include "lib/socket/socket.h"
    2626#include "libcli/wrepl/winsrepl.h"
    2727#include "librpc/gen_ndr/ndr_winsrepl.h"
    2828#include "lib/stream/packet.h"
    29 #include "libcli/composite/composite.h"
    3029#include "system/network.h"
    3130#include "lib/socket/netif.h"
    3231#include "param/param.h"
    33 
    34 static struct wrepl_request *wrepl_request_finished(struct wrepl_request *req, NTSTATUS status);
    35 
    36 /*
    37   mark all pending requests as dead - called when a socket error happens
    38 */
    39 static void wrepl_socket_dead(struct wrepl_socket *wrepl_socket, NTSTATUS status)
    40 {
    41         wrepl_socket->dead = true;
    42 
    43         if (wrepl_socket->packet) {
    44                 packet_recv_disable(wrepl_socket->packet);
    45                 packet_set_fde(wrepl_socket->packet, NULL);
    46                 packet_set_socket(wrepl_socket->packet, NULL);
    47         }
    48 
    49         if (wrepl_socket->event.fde) {
    50                 talloc_free(wrepl_socket->event.fde);
    51                 wrepl_socket->event.fde = NULL;
    52         }
    53 
    54         if (wrepl_socket->sock) {
    55                 talloc_free(wrepl_socket->sock);
    56                 wrepl_socket->sock = NULL;
    57         }
    58 
    59         if (NT_STATUS_EQUAL(NT_STATUS_UNSUCCESSFUL, status)) {
    60                 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
    61         }
    62         while (wrepl_socket->recv_queue) {
    63                 struct wrepl_request *req = wrepl_socket->recv_queue;
    64                 DLIST_REMOVE(wrepl_socket->recv_queue, req);
    65                 wrepl_request_finished(req, status);
    66         }
    67 
    68         talloc_set_destructor(wrepl_socket, NULL);
    69         if (wrepl_socket->free_skipped) {
    70                 talloc_free(wrepl_socket);
    71         }
    72 }
    73 
    74 static void wrepl_request_timeout_handler(struct tevent_context *ev, struct tevent_timer *te,
    75                                           struct timeval t, void *ptr)
    76 {
    77         struct wrepl_request *req = talloc_get_type(ptr, struct wrepl_request);
    78         wrepl_socket_dead(req->wrepl_socket, NT_STATUS_IO_TIMEOUT);
    79 }
    80 
    81 /*
    82   handle recv events
    83 */
    84 static NTSTATUS wrepl_finish_recv(void *private_data, DATA_BLOB packet_blob_in)
    85 {
    86         struct wrepl_socket *wrepl_socket = talloc_get_type(private_data, struct wrepl_socket);
    87         struct wrepl_request *req = wrepl_socket->recv_queue;
    88         DATA_BLOB blob;
    89         enum ndr_err_code ndr_err;
    90 
    91         if (!req) {
    92                 DEBUG(1,("Received unexpected WINS packet of length %u!\n",
    93                          (unsigned)packet_blob_in.length));
    94                 return NT_STATUS_INVALID_NETWORK_RESPONSE;
    95         }
    96 
    97         req->packet = talloc(req, struct wrepl_packet);
    98         NT_STATUS_HAVE_NO_MEMORY(req->packet);
    99 
    100         blob.data = packet_blob_in.data + 4;
    101         blob.length = packet_blob_in.length - 4;
    102        
    103         /* we have a full request - parse it */
    104         ndr_err = ndr_pull_struct_blob(&blob, req->packet, wrepl_socket->iconv_convenience, req->packet,
    105                                        (ndr_pull_flags_fn_t)ndr_pull_wrepl_packet);
    106         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    107                 NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
    108                 wrepl_request_finished(req, status);
    109                 return NT_STATUS_OK;
    110         }
    111 
    112         if (DEBUGLVL(10)) {
    113                 DEBUG(10,("Received WINS packet of length %u\n",
    114                           (unsigned)packet_blob_in.length));
    115                 NDR_PRINT_DEBUG(wrepl_packet, req->packet);
    116         }
    117 
    118         wrepl_request_finished(req, NT_STATUS_OK);
    119         return NT_STATUS_OK;
    120 }
    121 
    122 /*
    123   handler for winrepl events
    124 */
    125 static void wrepl_handler(struct tevent_context *ev, struct tevent_fd *fde,
    126                           uint16_t flags, void *private_data)
    127 {
    128         struct wrepl_socket *wrepl_socket = talloc_get_type(private_data,
    129                                                             struct wrepl_socket);
    130         if (flags & EVENT_FD_READ) {
    131                 packet_recv(wrepl_socket->packet);
    132                 return;
    133         }
    134         if (flags & EVENT_FD_WRITE) {
    135                 packet_queue_run(wrepl_socket->packet);
    136         }
    137 }
    138 
    139 static void wrepl_error(void *private_data, NTSTATUS status)
    140 {
    141         struct wrepl_socket *wrepl_socket = talloc_get_type(private_data,
    142                                                             struct wrepl_socket);
    143         wrepl_socket_dead(wrepl_socket, status);
    144 }
    145 
    146 
    147 /*
    148   destroy a wrepl_socket destructor
    149 */
    150 static int wrepl_socket_destructor(struct wrepl_socket *sock)
    151 {
    152         if (sock->dead) {
    153                 sock->free_skipped = true;
    154                 return -1;
    155         }
    156         wrepl_socket_dead(sock, NT_STATUS_LOCAL_DISCONNECT);
    157         return 0;
     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*/
     39struct 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
     53bool wrepl_socket_is_connected(struct wrepl_socket *wrepl_sock)
     54{
     55        if (!wrepl_sock) {
     56                return false;
     57        }
     58
     59        if (!wrepl_sock->stream) {
     60                return false;
     61        }
     62
     63        return true;
    15864}
    15965
     
    16268  operations will use that event context
    16369*/
    164 struct wrepl_socket *wrepl_socket_init(TALLOC_CTX *mem_ctx,
    165                                        struct tevent_context *event_ctx,
    166                                        struct smb_iconv_convenience *iconv_convenience)
     70struct wrepl_socket *wrepl_socket_init(TALLOC_CTX *mem_ctx,
     71                                       struct tevent_context *event_ctx)
    16772{
    16873        struct wrepl_socket *wrepl_socket;
    169         NTSTATUS status;
    17074
    17175        wrepl_socket = talloc_zero(mem_ctx, struct wrepl_socket);
    172         if (!wrepl_socket) return NULL;
     76        if (!wrepl_socket) {
     77                return NULL;
     78        }
    17379
    17480        wrepl_socket->event.ctx = event_ctx;
    175         if (!wrepl_socket->event.ctx) goto failed;
    176 
    177         wrepl_socket->iconv_convenience = iconv_convenience;
    178 
    179         status = socket_create("ip", SOCKET_TYPE_STREAM, &wrepl_socket->sock, 0);
    180         if (!NT_STATUS_IS_OK(status)) goto failed;
    181 
    182         talloc_steal(wrepl_socket, wrepl_socket->sock);
     81        if (!wrepl_socket->event.ctx) {
     82                goto failed;
     83        }
     84
     85        wrepl_socket->request_queue = tevent_queue_create(wrepl_socket,
     86                                                          "wrepl request queue");
     87        if (wrepl_socket->request_queue == NULL) {
     88                goto failed;
     89        }
    18390
    18491        wrepl_socket->request_timeout   = WREPL_SOCKET_REQUEST_TIMEOUT;
    185 
    186         talloc_set_destructor(wrepl_socket, wrepl_socket_destructor);
    18792
    18893        return wrepl_socket;
     
    196101  initialise a wrepl_socket from an already existing connection
    197102*/
    198 struct wrepl_socket *wrepl_socket_merge(TALLOC_CTX *mem_ctx,
    199                                         struct tevent_context *event_ctx,
    200                                         struct socket_context *sock,
    201                                         struct packet_context *pack)
    202 {
    203         struct wrepl_socket *wrepl_socket;
    204 
    205         wrepl_socket = talloc_zero(mem_ctx, struct wrepl_socket);
    206         if (wrepl_socket == NULL) goto failed;
    207 
    208         wrepl_socket->event.ctx = event_ctx;
    209         if (wrepl_socket->event.ctx == NULL) goto failed;
    210 
    211         wrepl_socket->sock = sock;
    212         talloc_steal(wrepl_socket, wrepl_socket->sock);
    213 
    214 
    215         wrepl_socket->request_timeout   = WREPL_SOCKET_REQUEST_TIMEOUT;
    216 
    217         wrepl_socket->event.fde = event_add_fd(wrepl_socket->event.ctx, wrepl_socket,
    218                                                socket_get_fd(wrepl_socket->sock),
    219                                                EVENT_FD_READ,
    220                                                wrepl_handler, wrepl_socket);
    221         if (wrepl_socket->event.fde == NULL) {
    222                 goto failed;
    223         }
    224 
    225         wrepl_socket->packet = pack;
    226         talloc_steal(wrepl_socket, wrepl_socket->packet);
    227         packet_set_private(wrepl_socket->packet, wrepl_socket);
    228         packet_set_socket(wrepl_socket->packet, wrepl_socket->sock);
    229         packet_set_callback(wrepl_socket->packet, wrepl_finish_recv);
    230         packet_set_full_request(wrepl_socket->packet, packet_full_request_u32);
    231         packet_set_error_handler(wrepl_socket->packet, wrepl_error);
    232         packet_set_event_context(wrepl_socket->packet, wrepl_socket->event.ctx);
    233         packet_set_fde(wrepl_socket->packet, wrepl_socket->event.fde);
    234         packet_set_serialise(wrepl_socket->packet);
    235 
    236         talloc_set_destructor(wrepl_socket, wrepl_socket_destructor);
    237        
    238         return wrepl_socket;
    239 
    240 failed:
    241         talloc_free(wrepl_socket);
    242         return NULL;
    243 }
    244 
    245 /*
    246   destroy a wrepl_request
    247 */
    248 static int wrepl_request_destructor(struct wrepl_request *req)
    249 {
    250         if (req->state == WREPL_REQUEST_RECV) {
    251                 DLIST_REMOVE(req->wrepl_socket->recv_queue, req);
    252         }
    253         req->state = WREPL_REQUEST_ERROR;
    254         return 0;
    255 }
    256 
    257 /*
    258   wait for a request to complete
    259 */
    260 static NTSTATUS wrepl_request_wait(struct wrepl_request *req)
    261 {
    262         NT_STATUS_HAVE_NO_MEMORY(req);
    263         while (req->state < WREPL_REQUEST_DONE) {
    264                 event_loop_once(req->wrepl_socket->event.ctx);
    265         }
    266         return req->status;
     103NTSTATUS wrepl_socket_donate_stream(struct wrepl_socket *wrepl_socket,
     104                                    struct tstream_context **stream)
     105{
     106        if (wrepl_socket->stream) {
     107                return NT_STATUS_CONNECTION_ACTIVE;
     108        }
     109
     110        wrepl_socket->stream = talloc_move(wrepl_socket, stream);
     111        return NT_STATUS_OK;
     112}
     113
     114/*
     115  initialise a wrepl_socket from an already existing connection
     116*/
     117NTSTATUS 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        if (!wrepl_socket->stream) {
     124                return NT_STATUS_CONNECTION_INVALID;
     125        }
     126
     127        num_requests = tevent_queue_length(wrepl_socket->request_queue);
     128        if (num_requests > 0) {
     129                return NT_STATUS_CONNECTION_IN_USE;
     130        }
     131
     132        *stream = talloc_move(wrepl_socket, &wrepl_socket->stream);
     133        return NT_STATUS_OK;
     134}
     135
     136const char *wrepl_best_ip(struct loadparm_context *lp_ctx, const char *peer_ip)
     137{
     138        struct interface *ifaces;
     139        load_interfaces(lp_ctx, lpcfg_interfaces(lp_ctx), &ifaces);
     140        return iface_best_ip(ifaces, peer_ip);
    267141}
    268142
    269143struct wrepl_connect_state {
    270         struct composite_context *result;
    271         struct wrepl_socket *wrepl_socket;
    272         struct composite_context *creq;
     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;
    273151};
    274152
    275 /*
    276   handler for winrepl connection completion
    277 */
    278 static void wrepl_connect_handler(struct composite_context *creq)
    279 {
    280         struct wrepl_connect_state *state = talloc_get_type(creq->async.private_data,
     153static void wrepl_connect_trigger(struct tevent_req *req,
     154                                  void *private_date);
     155
     156struct 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        req = tevent_req_create(mem_ctx, &state,
     167                                struct wrepl_connect_state);
     168        if (req == NULL) {
     169                return NULL;
     170        }
     171
     172        state->caller.wrepl_socket = wrepl_socket;
     173        state->caller.ev = ev;
     174
     175        if (wrepl_socket->stream) {
     176                tevent_req_nterror(req, NT_STATUS_CONNECTION_ACTIVE);
     177                return tevent_req_post(req, ev);
     178        }
     179
     180        ret = tsocket_address_inet_from_strings(state, "ipv4",
     181                                                our_ip, 0,
     182                                                &state->local_address);
     183        if (ret != 0) {
     184                NTSTATUS status = map_nt_error_from_unix(errno);
     185                tevent_req_nterror(req, status);
     186                return tevent_req_post(req, ev);
     187        }
     188
     189        ret = tsocket_address_inet_from_strings(state, "ipv4",
     190                                                peer_ip, WINS_REPLICATION_PORT,
     191                                                &state->remote_address);
     192        if (ret != 0) {
     193                NTSTATUS status = map_nt_error_from_unix(errno);
     194                tevent_req_nterror(req, status);
     195                return tevent_req_post(req, ev);
     196        }
     197
     198        ok = tevent_queue_add(wrepl_socket->request_queue,
     199                              ev,
     200                              req,
     201                              wrepl_connect_trigger,
     202                              NULL);
     203        if (!ok) {
     204                tevent_req_nomem(NULL, req);
     205                return tevent_req_post(req, ev);
     206        }
     207
     208        if (wrepl_socket->request_timeout > 0) {
     209                struct timeval endtime;
     210                endtime = tevent_timeval_current_ofs(wrepl_socket->request_timeout, 0);
     211                ok = tevent_req_set_endtime(req, ev, endtime);
     212                if (!ok) {
     213                        return tevent_req_post(req, ev);
     214                }
     215        }
     216
     217        return req;
     218}
     219
     220static void wrepl_connect_done(struct tevent_req *subreq);
     221
     222static void wrepl_connect_trigger(struct tevent_req *req,
     223                                  void *private_date)
     224{
     225        struct wrepl_connect_state *state = tevent_req_data(req,
    281226                                            struct wrepl_connect_state);
    282         struct wrepl_socket *wrepl_socket = state->wrepl_socket;
    283         struct composite_context *result = state->result;
    284 
    285         result->status = socket_connect_recv(state->creq);
    286         if (!composite_is_ok(result)) return;
    287 
    288         wrepl_socket->event.fde = event_add_fd(wrepl_socket->event.ctx, wrepl_socket,
    289                                                socket_get_fd(wrepl_socket->sock),
    290                                                EVENT_FD_READ,
    291                                                wrepl_handler, wrepl_socket);
    292         if (composite_nomem(wrepl_socket->event.fde, result)) return;
    293 
    294         /* setup the stream -> packet parser */
    295         wrepl_socket->packet = packet_init(wrepl_socket);
    296         if (composite_nomem(wrepl_socket->packet, result)) return;
    297         packet_set_private(wrepl_socket->packet, wrepl_socket);
    298         packet_set_socket(wrepl_socket->packet, wrepl_socket->sock);
    299         packet_set_callback(wrepl_socket->packet, wrepl_finish_recv);
    300         packet_set_full_request(wrepl_socket->packet, packet_full_request_u32);
    301         packet_set_error_handler(wrepl_socket->packet, wrepl_error);
    302         packet_set_event_context(wrepl_socket->packet, wrepl_socket->event.ctx);
    303         packet_set_fde(wrepl_socket->packet, wrepl_socket->event.fde);
    304         packet_set_serialise(wrepl_socket->packet);
    305 
    306         composite_done(result);
    307 }
    308 
    309 const char *wrepl_best_ip(struct loadparm_context *lp_ctx, const char *peer_ip)
    310 {
    311         struct interface *ifaces;
    312         load_interfaces(lp_ctx, lp_interfaces(lp_ctx), &ifaces);
    313         return iface_best_ip(ifaces, peer_ip);
    314 }
    315 
    316 
    317 /*
    318   connect a wrepl_socket to a WINS server
    319 */
    320 struct composite_context *wrepl_connect_send(struct wrepl_socket *wrepl_socket,
    321                                              const char *our_ip, const char *peer_ip)
    322 {
    323         struct composite_context *result;
    324         struct wrepl_connect_state *state;
    325         struct socket_address *peer, *us;
    326 
    327         result = talloc_zero(wrepl_socket, struct composite_context);
    328         if (!result) return NULL;
    329 
    330         result->state           = COMPOSITE_STATE_IN_PROGRESS;
    331         result->event_ctx       = wrepl_socket->event.ctx;
    332 
    333         state = talloc_zero(result, struct wrepl_connect_state);
    334         if (composite_nomem(state, result)) return result;
    335         result->private_data    = state;
    336         state->result           = result;
    337         state->wrepl_socket     = wrepl_socket;
    338 
    339         us = socket_address_from_strings(state, wrepl_socket->sock->backend_name,
    340                                          our_ip, 0);
    341         if (composite_nomem(us, result)) return result;
    342 
    343         peer = socket_address_from_strings(state, wrepl_socket->sock->backend_name,
    344                                            peer_ip, WINS_REPLICATION_PORT);
    345         if (composite_nomem(peer, result)) return result;
    346 
    347         state->creq = socket_connect_send(wrepl_socket->sock, us, peer,
    348                                           0, wrepl_socket->event.ctx);
    349         composite_continue(result, state->creq, wrepl_connect_handler, state);
    350         return result;
     227        struct tevent_req *subreq;
     228
     229        subreq = tstream_inet_tcp_connect_send(state,
     230                                               state->caller.ev,
     231                                               state->local_address,
     232                                               state->remote_address);
     233        if (tevent_req_nomem(subreq, req)) {
     234                return;
     235        }
     236        tevent_req_set_callback(subreq, wrepl_connect_done, req);
     237
     238        return;
     239}
     240
     241static void wrepl_connect_done(struct tevent_req *subreq)
     242{
     243        struct tevent_req *req = tevent_req_callback_data(subreq,
     244                                 struct tevent_req);
     245        struct wrepl_connect_state *state = tevent_req_data(req,
     246                                            struct wrepl_connect_state);
     247        int ret;
     248        int sys_errno;
     249
     250        ret = tstream_inet_tcp_connect_recv(subreq, &sys_errno,
     251                                            state, &state->stream, NULL);
     252        if (ret != 0) {
     253                NTSTATUS status = map_nt_error_from_unix(sys_errno);
     254                tevent_req_nterror(req, status);
     255                return;
     256        }
     257
     258        tevent_req_done(req);
    351259}
    352260
     
    354262  connect a wrepl_socket to a WINS server - recv side
    355263*/
    356 NTSTATUS wrepl_connect_recv(struct composite_context *result)
    357 {
    358         struct wrepl_connect_state *state = talloc_get_type(result->private_data,
     264NTSTATUS wrepl_connect_recv(struct tevent_req *req)
     265{
     266        struct wrepl_connect_state *state = tevent_req_data(req,
    359267                                            struct wrepl_connect_state);
    360         struct wrepl_socket *wrepl_socket = state->wrepl_socket;
    361         NTSTATUS status = composite_wait(result);
    362 
    363         if (!NT_STATUS_IS_OK(status)) {
    364                 wrepl_socket_dead(wrepl_socket, status);
    365         }
    366 
    367         talloc_free(result);
    368         return status;
     268        struct wrepl_socket *wrepl_socket = state->caller.wrepl_socket;
     269        NTSTATUS status;
     270
     271        if (tevent_req_is_nterror(req, &status)) {
     272                tevent_req_received(req);
     273                return status;
     274        }
     275
     276        wrepl_socket->stream = talloc_move(wrepl_socket, &state->stream);
     277
     278        tevent_req_received(req);
     279        return NT_STATUS_OK;
    369280}
    370281
     
    375286                       const char *our_ip, const char *peer_ip)
    376287{
    377         struct composite_context *c_req = wrepl_connect_send(wrepl_socket, our_ip, peer_ip);
    378         return wrepl_connect_recv(c_req);
    379 }
    380 
    381 /*
    382    callback from wrepl_request_trigger()
    383 */
    384 static void wrepl_request_trigger_handler(struct tevent_context *ev, struct tevent_timer *te,
    385                                           struct timeval t, void *ptr)
    386 {
    387         struct wrepl_request *req = talloc_get_type(ptr, struct wrepl_request);
    388         if (req->async.fn) {
    389                 req->async.fn(req);
    390         }
    391 }
    392 
    393 /*
    394   trigger an immediate event on a wrepl_request
    395   the return value should only be used in wrepl_request_send()
    396   this is the only place where req->trigger is true
    397 */
    398 static struct wrepl_request *wrepl_request_finished(struct wrepl_request *req, NTSTATUS status)
    399 {
    400         struct tevent_timer *te;
    401 
    402         if (req->state == WREPL_REQUEST_RECV) {
    403                 DLIST_REMOVE(req->wrepl_socket->recv_queue, req);
    404         }
    405 
    406         if (!NT_STATUS_IS_OK(status)) {
    407                 req->state      = WREPL_REQUEST_ERROR;
    408         } else {
    409                 req->state      = WREPL_REQUEST_DONE;
    410         }
    411 
    412         req->status     = status;
    413 
    414         if (req->trigger) {
    415                 req->trigger = false;
    416                 /* a zero timeout means immediate */
    417                 te = event_add_timed(req->wrepl_socket->event.ctx,
    418                                      req, timeval_zero(),
    419                                      wrepl_request_trigger_handler, req);
    420                 if (!te) {
    421                         talloc_free(req);
    422                         return NULL;
    423                 }
    424                 return req;
    425         }
    426 
    427         if (req->async.fn) {
    428                 req->async.fn(req);
    429         }
    430         return NULL;
    431 }
    432 
    433 struct wrepl_send_ctrl_state {
     288        struct tevent_req *subreq;
     289        bool ok;
     290        NTSTATUS status;
     291
     292        subreq = wrepl_connect_send(wrepl_socket, wrepl_socket->event.ctx,
     293                                    wrepl_socket, our_ip, peer_ip);
     294        NT_STATUS_HAVE_NO_MEMORY(subreq);
     295
     296        ok = tevent_req_poll(subreq, wrepl_socket->event.ctx);
     297        if (!ok) {
     298                TALLOC_FREE(subreq);
     299                return NT_STATUS_INTERNAL_ERROR;
     300        }
     301
     302        status = wrepl_connect_recv(subreq);
     303        TALLOC_FREE(subreq);
     304        NT_STATUS_NOT_OK_RETURN(status);
     305
     306        return NT_STATUS_OK;
     307}
     308
     309struct wrepl_request_state {
     310        struct {
     311                struct wrepl_socket *wrepl_socket;
     312                struct tevent_context *ev;
     313        } caller;
    434314        struct wrepl_send_ctrl ctrl;
    435         struct wrepl_request *req;
    436         struct wrepl_socket *wrepl_sock;
     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;
    437325};
    438326
    439 static int wrepl_send_ctrl_destructor(struct wrepl_send_ctrl_state *s)
    440 {
    441         struct wrepl_request *req = s->wrepl_sock->recv_queue;
    442 
    443         /* check if the request is still in WREPL_STATE_RECV,
    444          * we need this here because the caller has may called
    445          * talloc_free(req) and wrepl_send_ctrl_state isn't
    446          * a talloc child of the request, so our s->req pointer
    447          * is maybe invalid!
    448          */
    449         for (; req; req = req->next) {
    450                 if (req == s->req) break;
    451         }
    452         if (!req) return 0;
    453 
    454         /* here, we need to make sure the async request handler is called
    455          * later in the next event_loop and now now
    456          */
    457         req->trigger = true;
    458         wrepl_request_finished(req, NT_STATUS_OK);
    459 
    460         if (s->ctrl.disconnect_after_send) {
    461                 wrepl_socket_dead(s->wrepl_sock, NT_STATUS_LOCAL_DISCONNECT);
    462         }
    463 
    464         return 0;
    465 }
    466 
    467 /*
    468   send a generic wins replication request
    469 */
    470 struct wrepl_request *wrepl_request_send(struct wrepl_socket *wrepl_socket,
    471                                          struct wrepl_packet *packet,
    472                                          struct wrepl_send_ctrl *ctrl)
    473 {
    474         struct wrepl_request *req;
    475         struct wrepl_wrap wrap;
    476         DATA_BLOB blob;
     327static void wrepl_request_trigger(struct tevent_req *req,
     328                                  void *private_data);
     329
     330struct 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;
    477338        NTSTATUS status;
    478339        enum ndr_err_code ndr_err;
    479 
    480         req = talloc_zero(wrepl_socket, struct wrepl_request);
    481         if (!req) return NULL;
    482         req->wrepl_socket = wrepl_socket;
    483         req->state        = WREPL_REQUEST_RECV;
    484         req->trigger      = true;
    485 
    486         DLIST_ADD_END(wrepl_socket->recv_queue, req, struct wrepl_request *);
    487         talloc_set_destructor(req, wrepl_request_destructor);
    488 
    489         if (wrepl_socket->dead) {
    490                 return wrepl_request_finished(req, NT_STATUS_INVALID_CONNECTION);
    491         }
    492 
    493         wrap.packet = *packet;
    494         ndr_err = ndr_push_struct_blob(&blob, req, wrepl_socket->iconv_convenience, &wrap,
     340        bool ok;
     341
     342        if (wrepl_socket->event.ctx != ev) {
     343                /* TODO: remove wrepl_socket->event.ctx !!! */
     344                smb_panic("wrepl_associate_stop_send event context mismatch!");
     345                return NULL;
     346        }
     347
     348        req = tevent_req_create(mem_ctx, &state,
     349                                struct wrepl_request_state);
     350        if (req == NULL) {
     351                return NULL;
     352        }
     353
     354        state->caller.wrepl_socket = wrepl_socket;
     355        state->caller.ev = ev;
     356
     357        if (ctrl) {
     358                state->ctrl = *ctrl;
     359        }
     360
     361        if (wrepl_socket->stream == NULL) {
     362                tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION);
     363                return tevent_req_post(req, ev);
     364        }
     365
     366        state->req.wrap.packet = *packet;
     367        ndr_err = ndr_push_struct_blob(&state->req.blob, state,
     368                                       &state->req.wrap,
    495369                                       (ndr_push_flags_fn_t)ndr_push_wrepl_wrap);
    496370        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
    497371                status = ndr_map_error2ntstatus(ndr_err);
    498                 return wrepl_request_finished(req, status);
     372                tevent_req_nterror(req, status);
     373                return tevent_req_post(req, ev);
     374        }
     375
     376        state->req.iov.iov_base = (char *) state->req.blob.data;
     377        state->req.iov.iov_len = state->req.blob.length;
     378
     379        ok = tevent_queue_add(wrepl_socket->request_queue,
     380                              ev,
     381                              req,
     382                              wrepl_request_trigger,
     383                              NULL);
     384        if (!ok) {
     385                tevent_req_nomem(NULL, req);
     386                return tevent_req_post(req, ev);
     387        }
     388
     389        if (wrepl_socket->request_timeout > 0) {
     390                struct timeval endtime;
     391                endtime = tevent_timeval_current_ofs(wrepl_socket->request_timeout, 0);
     392                ok = tevent_req_set_endtime(req, ev, endtime);
     393                if (!ok) {
     394                        return tevent_req_post(req, ev);
     395                }
     396        }
     397
     398        return req;
     399}
     400
     401static void wrepl_request_writev_done(struct tevent_req *subreq);
     402
     403static void wrepl_request_trigger(struct tevent_req *req,
     404                                  void *private_data)
     405{
     406        struct wrepl_request_state *state = tevent_req_data(req,
     407                                            struct wrepl_request_state);
     408        struct tevent_req *subreq;
     409
     410        if (state->caller.wrepl_socket->stream == NULL) {
     411                tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION);
     412                return;
    499413        }
    500414
    501415        if (DEBUGLVL(10)) {
    502                 DEBUG(10,("Sending WINS packet of length %u\n",
    503                           (unsigned)blob.length));
    504                 NDR_PRINT_DEBUG(wrepl_packet, &wrap.packet);
    505         }
    506 
    507         if (wrepl_socket->request_timeout > 0) {
    508                 req->te = event_add_timed(wrepl_socket->event.ctx, req,
    509                                           timeval_current_ofs(wrepl_socket->request_timeout, 0),
    510                                           wrepl_request_timeout_handler, req);
    511                 if (!req->te) return wrepl_request_finished(req, NT_STATUS_NO_MEMORY);
    512         }
    513 
    514         if (ctrl && (ctrl->send_only || ctrl->disconnect_after_send)) {
    515                 struct wrepl_send_ctrl_state *s = talloc(blob.data, struct wrepl_send_ctrl_state);
    516                 if (!s) return wrepl_request_finished(req, NT_STATUS_NO_MEMORY);
    517                 s->ctrl         = *ctrl;
    518                 s->req          = req;
    519                 s->wrepl_sock   = wrepl_socket;
    520                 talloc_set_destructor(s, wrepl_send_ctrl_destructor);
    521         }
    522 
    523         status = packet_send(wrepl_socket->packet, blob);
     416                DEBUG(10,("Sending WINS packet of length %u\n",
     417                          (unsigned)state->req.blob.length));
     418                NDR_PRINT_DEBUG(wrepl_packet, &state->req.wrap.packet);
     419        }
     420
     421        subreq = tstream_writev_send(state,
     422                                     state->caller.ev,
     423                                     state->caller.wrepl_socket->stream,
     424                                     &state->req.iov, 1);
     425        if (tevent_req_nomem(subreq, req)) {
     426                return;
     427        }
     428        tevent_req_set_callback(subreq, wrepl_request_writev_done, req);
     429}
     430
     431static void wrepl_request_disconnect_done(struct tevent_req *subreq);
     432static void wrepl_request_read_pdu_done(struct tevent_req *subreq);
     433
     434static void wrepl_request_writev_done(struct tevent_req *subreq)
     435{
     436        struct tevent_req *req = tevent_req_callback_data(subreq,
     437                                 struct tevent_req);
     438        struct wrepl_request_state *state = tevent_req_data(req,
     439                                            struct wrepl_request_state);
     440        int ret;
     441        int sys_errno;
     442
     443        ret = tstream_writev_recv(subreq, &sys_errno);
     444        TALLOC_FREE(subreq);
     445        if (ret == -1) {
     446                NTSTATUS status = map_nt_error_from_unix(sys_errno);
     447                TALLOC_FREE(state->caller.wrepl_socket->stream);
     448                tevent_req_nterror(req, status);
     449                return;
     450        }
     451
     452        if (state->caller.wrepl_socket->stream == NULL) {
     453                tevent_req_nterror(req, NT_STATUS_INVALID_CONNECTION);
     454                return;
     455        }
     456
     457        if (state->ctrl.disconnect_after_send) {
     458                subreq = tstream_disconnect_send(state,
     459                                                 state->caller.ev,
     460                                                 state->caller.wrepl_socket->stream);
     461                if (tevent_req_nomem(subreq, req)) {
     462                        return;
     463                }
     464                tevent_req_set_callback(subreq, wrepl_request_disconnect_done, req);
     465                return;
     466        }
     467
     468        if (state->ctrl.send_only) {
     469                tevent_req_done(req);
     470                return;
     471        }
     472
     473        subreq = tstream_read_pdu_blob_send(state,
     474                                            state->caller.ev,
     475                                            state->caller.wrepl_socket->stream,
     476                                            4, /* initial_read_size */
     477                                            packet_full_request_u32,
     478                                            NULL);
     479        if (tevent_req_nomem(subreq, req)) {
     480                return;
     481        }
     482        tevent_req_set_callback(subreq, wrepl_request_read_pdu_done, req);
     483}
     484
     485static void wrepl_request_disconnect_done(struct tevent_req *subreq)
     486{
     487        struct tevent_req *req = tevent_req_callback_data(subreq,
     488                                 struct tevent_req);
     489        struct wrepl_request_state *state = tevent_req_data(req,
     490                                            struct wrepl_request_state);
     491        int ret;
     492        int sys_errno;
     493
     494        ret = tstream_disconnect_recv(subreq, &sys_errno);
     495        TALLOC_FREE(subreq);
     496        if (ret == -1) {
     497                NTSTATUS status = map_nt_error_from_unix(sys_errno);
     498                TALLOC_FREE(state->caller.wrepl_socket->stream);
     499                tevent_req_nterror(req, status);
     500                return;
     501        }
     502
     503        DEBUG(10,("WINS connection disconnected\n"));
     504        TALLOC_FREE(state->caller.wrepl_socket->stream);
     505
     506        tevent_req_done(req);
     507}
     508
     509static void wrepl_request_read_pdu_done(struct tevent_req *subreq)
     510{
     511        struct tevent_req *req = tevent_req_callback_data(subreq,
     512                                 struct tevent_req);
     513        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        status = tstream_read_pdu_blob_recv(subreq, state, &state->rep.blob);
    524520        if (!NT_STATUS_IS_OK(status)) {
    525                 return wrepl_request_finished(req, status);
    526         }
    527 
    528         req->trigger = false;
    529         return req;
    530 }
    531 
    532 /*
    533   receive a generic WINS replication reply
    534 */
    535 NTSTATUS wrepl_request_recv(struct wrepl_request *req,
     521                TALLOC_FREE(state->caller.wrepl_socket->stream);
     522                tevent_req_nterror(req, status);
     523                return;
     524        }
     525
     526        state->rep.packet = talloc(state, struct wrepl_packet);
     527        if (tevent_req_nomem(state->rep.packet, req)) {
     528                return;
     529        }
     530
     531        blob.data = state->rep.blob.data + 4;
     532        blob.length = state->rep.blob.length - 4;
     533
     534        /* we have a full request - parse it */
     535        ndr_err = ndr_pull_struct_blob(&blob,
     536                                       state->rep.packet,
     537                                       state->rep.packet,
     538                                       (ndr_pull_flags_fn_t)ndr_pull_wrepl_packet);
     539        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     540                status = ndr_map_error2ntstatus(ndr_err);
     541                tevent_req_nterror(req, status);
     542                return;
     543        }
     544
     545        if (DEBUGLVL(10)) {
     546                DEBUG(10,("Received WINS packet of length %u\n",
     547                          (unsigned)state->rep.blob.length));
     548                NDR_PRINT_DEBUG(wrepl_packet, state->rep.packet);
     549        }
     550
     551        tevent_req_done(req);
     552}
     553
     554NTSTATUS wrepl_request_recv(struct tevent_req *req,
    536555                            TALLOC_CTX *mem_ctx,
    537556                            struct wrepl_packet **packet)
    538557{
    539         NTSTATUS status = wrepl_request_wait(req);
    540         if (NT_STATUS_IS_OK(status) && packet) {
    541                 *packet = talloc_steal(mem_ctx, req->packet);
    542         }
    543         talloc_free(req);
    544         return status;
     558        struct wrepl_request_state *state = tevent_req_data(req,
     559                                            struct wrepl_request_state);
     560        NTSTATUS status;
     561
     562        if (tevent_req_is_nterror(req, &status)) {
     563                TALLOC_FREE(state->caller.wrepl_socket->stream);
     564                tevent_req_received(req);
     565                return status;
     566        }
     567
     568        if (packet) {
     569                *packet = talloc_move(mem_ctx, &state->rep.packet);
     570        }
     571
     572        tevent_req_received(req);
     573        return NT_STATUS_OK;
    545574}
    546575
     
    550579NTSTATUS wrepl_request(struct wrepl_socket *wrepl_socket,
    551580                       TALLOC_CTX *mem_ctx,
    552                        struct wrepl_packet *req_packet,
     581                       const struct wrepl_packet *req_packet,
    553582                       struct wrepl_packet **reply_packet)
    554583{
    555         struct wrepl_request *req = wrepl_request_send(wrepl_socket, req_packet, NULL);
    556         return wrepl_request_recv(req, mem_ctx, reply_packet);
    557 }
    558 
    559 
    560 /*
    561   setup an association - send
    562 */
    563 struct wrepl_request *wrepl_associate_send(struct wrepl_socket *wrepl_socket,
    564                                            struct wrepl_associate *io)
    565 {
    566         struct wrepl_packet *packet;
    567         struct wrepl_request *req;
    568 
    569         packet = talloc_zero(wrepl_socket, struct wrepl_packet);
    570         if (packet == NULL) return NULL;
    571 
    572         packet->opcode                      = WREPL_OPCODE_BITS;
    573         packet->mess_type                   = WREPL_START_ASSOCIATION;
    574         packet->message.start.minor_version = 2;
    575         packet->message.start.major_version = 5;
     584        struct tevent_req *subreq;
     585        bool ok;
     586        NTSTATUS status;
     587
     588        subreq = wrepl_request_send(mem_ctx, wrepl_socket->event.ctx,
     589                                    wrepl_socket, req_packet, NULL);
     590        NT_STATUS_HAVE_NO_MEMORY(subreq);
     591
     592        ok = tevent_req_poll(subreq, wrepl_socket->event.ctx);
     593        if (!ok) {
     594                TALLOC_FREE(subreq);
     595                return NT_STATUS_INTERNAL_ERROR;
     596        }
     597
     598        status = wrepl_request_recv(subreq, mem_ctx, reply_packet);
     599        TALLOC_FREE(subreq);
     600        NT_STATUS_NOT_OK_RETURN(status);
     601
     602        return NT_STATUS_OK;
     603}
     604
     605
     606struct wrepl_associate_state {
     607        struct wrepl_packet packet;
     608        uint32_t assoc_ctx;
     609        uint16_t major_version;
     610};
     611
     612static void wrepl_associate_done(struct tevent_req *subreq);
     613
     614struct 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        if (wrepl_socket->event.ctx != ev) {
     624                /* TODO: remove wrepl_socket->event.ctx !!! */
     625                smb_panic("wrepl_associate_send event context mismatch!");
     626                return NULL;
     627        }
     628
     629        req = tevent_req_create(mem_ctx, &state,
     630                                struct wrepl_associate_state);
     631        if (req == NULL) {
     632                return NULL;
     633        };
     634
     635        state->packet.opcode                            = WREPL_OPCODE_BITS;
     636        state->packet.mess_type                         = WREPL_START_ASSOCIATION;
     637        state->packet.message.start.minor_version       = 2;
     638        state->packet.message.start.major_version       = 5;
    576639
    577640        /*
     
    583646         * and that would break nt4 <-> samba replication
    584647         */
    585         packet->padding = data_blob_talloc(packet, NULL, 21);
    586         if (packet->padding.data == NULL) {
    587                 talloc_free(packet);
    588                 return NULL;
    589         }
    590         memset(packet->padding.data, 0, packet->padding.length);
    591 
    592         req = wrepl_request_send(wrepl_socket, packet, NULL);
    593 
    594         talloc_free(packet);
    595 
    596         return req;     
     648        state->packet.padding   = data_blob_talloc(state, NULL, 21);
     649        if (tevent_req_nomem(state->packet.padding.data, req)) {
     650                return tevent_req_post(req, ev);
     651        }
     652        memset(state->packet.padding.data, 0, state->packet.padding.length);
     653
     654        subreq = wrepl_request_send(state, ev, wrepl_socket, &state->packet, NULL);
     655        if (tevent_req_nomem(subreq, req)) {
     656                return tevent_req_post(req, ev);
     657        }
     658        tevent_req_set_callback(subreq, wrepl_associate_done, req);
     659
     660        return req;
     661}
     662
     663static void wrepl_associate_done(struct tevent_req *subreq)
     664{
     665        struct tevent_req *req = tevent_req_callback_data(subreq,
     666                                 struct tevent_req);
     667        struct wrepl_associate_state *state = tevent_req_data(req,
     668                                              struct wrepl_associate_state);
     669        NTSTATUS status;
     670        struct wrepl_packet *packet;
     671
     672        status = wrepl_request_recv(subreq, state, &packet);
     673        TALLOC_FREE(subreq);
     674        if (!NT_STATUS_IS_OK(status)) {
     675                tevent_req_nterror(req, status);
     676                return;
     677        }
     678
     679        if (packet->mess_type != WREPL_START_ASSOCIATION_REPLY) {
     680                tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
     681                return;
     682        }
     683
     684        state->assoc_ctx = packet->message.start_reply.assoc_ctx;
     685        state->major_version = packet->message.start_reply.major_version;
     686
     687        tevent_req_done(req);
    597688}
    598689
     
    600691  setup an association - recv
    601692*/
    602 NTSTATUS wrepl_associate_recv(struct wrepl_request *req,
     693NTSTATUS wrepl_associate_recv(struct tevent_req *req,
    603694                              struct wrepl_associate *io)
    604695{
    605         struct wrepl_packet *packet=NULL;
    606         NTSTATUS status;
    607         status = wrepl_request_recv(req, req->wrepl_socket, &packet);
    608         NT_STATUS_NOT_OK_RETURN(status);
    609         if (packet->mess_type != WREPL_START_ASSOCIATION_REPLY) {
    610                 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
    611         }
    612         if (NT_STATUS_IS_OK(status)) {
    613                 io->out.assoc_ctx = packet->message.start_reply.assoc_ctx;
    614                 io->out.major_version = packet->message.start_reply.major_version;
    615         }
    616         talloc_free(packet);
    617         return status;
     696        struct wrepl_associate_state *state = tevent_req_data(req,
     697                                              struct wrepl_associate_state);
     698        NTSTATUS status;
     699
     700        if (tevent_req_is_nterror(req, &status)) {
     701                tevent_req_received(req);
     702                return status;
     703        }
     704
     705        io->out.assoc_ctx = state->assoc_ctx;
     706        io->out.major_version = state->major_version;
     707
     708        tevent_req_received(req);
     709        return NT_STATUS_OK;
    618710}
    619711
     
    624716                         struct wrepl_associate *io)
    625717{
    626         struct wrepl_request *req = wrepl_associate_send(wrepl_socket, io);
    627         return wrepl_associate_recv(req, io);
    628 }
    629 
    630 
    631 /*
    632   stop an association - send
    633 */
    634 struct wrepl_request *wrepl_associate_stop_send(struct wrepl_socket *wrepl_socket,
    635                                                 struct wrepl_associate_stop *io)
    636 {
    637         struct wrepl_packet *packet;
    638         struct wrepl_request *req;
     718        struct tevent_req *subreq;
     719        bool ok;
     720        NTSTATUS status;
     721
     722        subreq = wrepl_associate_send(wrepl_socket, wrepl_socket->event.ctx,
     723                                      wrepl_socket, io);
     724        NT_STATUS_HAVE_NO_MEMORY(subreq);
     725
     726        ok = tevent_req_poll(subreq, wrepl_socket->event.ctx);
     727        if (!ok) {
     728                TALLOC_FREE(subreq);
     729                return NT_STATUS_INTERNAL_ERROR;
     730        }
     731
     732        status = wrepl_associate_recv(subreq, io);
     733        TALLOC_FREE(subreq);
     734        NT_STATUS_NOT_OK_RETURN(status);
     735
     736        return NT_STATUS_OK;
     737}
     738
     739struct wrepl_associate_stop_state {
     740        struct wrepl_packet packet;
    639741        struct wrepl_send_ctrl ctrl;
    640 
    641         packet = talloc_zero(wrepl_socket, struct wrepl_packet);
    642         if (packet == NULL) return NULL;
    643 
    644         packet->opcode                  = WREPL_OPCODE_BITS;
    645         packet->assoc_ctx               = io->in.assoc_ctx;
    646         packet->mess_type               = WREPL_STOP_ASSOCIATION;
    647         packet->message.stop.reason     = io->in.reason;
    648 
    649         ZERO_STRUCT(ctrl);
     742};
     743
     744static void wrepl_associate_stop_done(struct tevent_req *subreq);
     745
     746struct 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        if (wrepl_socket->event.ctx != ev) {
     756                /* TODO: remove wrepl_socket->event.ctx !!! */
     757                smb_panic("wrepl_associate_stop_send event context mismatch!");
     758                return NULL;
     759        }
     760
     761        req = tevent_req_create(mem_ctx, &state,
     762                                struct wrepl_associate_stop_state);
     763        if (req == NULL) {
     764                return NULL;
     765        };
     766
     767        state->packet.opcode                    = WREPL_OPCODE_BITS;
     768        state->packet.assoc_ctx                 = io->in.assoc_ctx;
     769        state->packet.mess_type                 = WREPL_STOP_ASSOCIATION;
     770        state->packet.message.stop.reason       = io->in.reason;
     771
    650772        if (io->in.reason == 0) {
    651                 ctrl.send_only                  = true;
    652                 ctrl.disconnect_after_send      = true;
    653         }
    654 
    655         req = wrepl_request_send(wrepl_socket, packet, &ctrl);
    656 
    657         talloc_free(packet);
    658 
    659         return req;     
     773                state->ctrl.send_only                   = true;
     774                state->ctrl.disconnect_after_send       = true;
     775        }
     776
     777        subreq = wrepl_request_send(state, ev, wrepl_socket, &state->packet, &state->ctrl);
     778        if (tevent_req_nomem(subreq, req)) {
     779                return tevent_req_post(req, ev);
     780        }
     781        tevent_req_set_callback(subreq, wrepl_associate_stop_done, req);
     782
     783        return req;
     784}
     785
     786static void wrepl_associate_stop_done(struct tevent_req *subreq)
     787{
     788        struct tevent_req *req = tevent_req_callback_data(subreq,
     789                                 struct tevent_req);
     790        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        status = wrepl_request_recv(subreq, state, NULL);
     796        TALLOC_FREE(subreq);
     797        if (!NT_STATUS_IS_OK(status)) {
     798                tevent_req_nterror(req, status);
     799                return;
     800        }
     801
     802        tevent_req_done(req);
    660803}
    661804
     
    663806  stop an association - recv
    664807*/
    665 NTSTATUS wrepl_associate_stop_recv(struct wrepl_request *req,
     808NTSTATUS wrepl_associate_stop_recv(struct tevent_req *req,
    666809                                   struct wrepl_associate_stop *io)
    667810{
    668         struct wrepl_packet *packet=NULL;
    669         NTSTATUS status;
    670         status = wrepl_request_recv(req, req->wrepl_socket, &packet);
    671         NT_STATUS_NOT_OK_RETURN(status);
    672         talloc_free(packet);
    673         return status;
     811        NTSTATUS status;
     812
     813        if (tevent_req_is_nterror(req, &status)) {
     814                tevent_req_received(req);
     815                return status;
     816        }
     817
     818        tevent_req_received(req);
     819        return NT_STATUS_OK;
    674820}
    675821
     
    680826                              struct wrepl_associate_stop *io)
    681827{
    682         struct wrepl_request *req = wrepl_associate_stop_send(wrepl_socket, io);
    683         return wrepl_associate_stop_recv(req, io);
    684 }
    685 
    686 /*
    687   fetch the partner tables - send
    688 */
    689 struct wrepl_request *wrepl_pull_table_send(struct wrepl_socket *wrepl_socket,
    690                                             struct wrepl_pull_table *io)
    691 {
     828        struct tevent_req *subreq;
     829        bool ok;
     830        NTSTATUS status;
     831
     832        subreq = wrepl_associate_stop_send(wrepl_socket, wrepl_socket->event.ctx,
     833                                           wrepl_socket, io);
     834        NT_STATUS_HAVE_NO_MEMORY(subreq);
     835
     836        ok = tevent_req_poll(subreq, wrepl_socket->event.ctx);
     837        if (!ok) {
     838                TALLOC_FREE(subreq);
     839                return NT_STATUS_INTERNAL_ERROR;
     840        }
     841
     842        status = wrepl_associate_stop_recv(subreq, io);
     843        TALLOC_FREE(subreq);
     844        NT_STATUS_NOT_OK_RETURN(status);
     845
     846        return NT_STATUS_OK;
     847}
     848
     849struct wrepl_pull_table_state {
     850        struct wrepl_packet packet;
     851        uint32_t num_partners;
     852        struct wrepl_wins_owner *partners;
     853};
     854
     855static void wrepl_pull_table_done(struct tevent_req *subreq);
     856
     857struct 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        if (wrepl_socket->event.ctx != ev) {
     867                /* TODO: remove wrepl_socket->event.ctx !!! */
     868                smb_panic("wrepl_pull_table_send event context mismatch!");
     869                return NULL;
     870        }
     871
     872        req = tevent_req_create(mem_ctx, &state,
     873                                struct wrepl_pull_table_state);
     874        if (req == NULL) {
     875                return NULL;
     876        };
     877
     878        state->packet.opcode                            = WREPL_OPCODE_BITS;
     879        state->packet.assoc_ctx                         = io->in.assoc_ctx;
     880        state->packet.mess_type                         = WREPL_REPLICATION;
     881        state->packet.message.replication.command       = WREPL_REPL_TABLE_QUERY;
     882
     883        subreq = wrepl_request_send(state, ev, wrepl_socket, &state->packet, NULL);
     884        if (tevent_req_nomem(subreq, req)) {
     885                return tevent_req_post(req, ev);
     886        }
     887        tevent_req_set_callback(subreq, wrepl_pull_table_done, req);
     888
     889        return req;
     890}
     891
     892static void wrepl_pull_table_done(struct tevent_req *subreq)
     893{
     894        struct tevent_req *req = tevent_req_callback_data(subreq,
     895                                 struct tevent_req);
     896        struct wrepl_pull_table_state *state = tevent_req_data(req,
     897                                               struct wrepl_pull_table_state);
     898        NTSTATUS status;
    692899        struct wrepl_packet *packet;
    693         struct wrepl_request *req;
    694 
    695         packet = talloc_zero(wrepl_socket, struct wrepl_packet);
    696         if (packet == NULL) return NULL;
    697 
    698         packet->opcode                      = WREPL_OPCODE_BITS;
    699         packet->assoc_ctx                   = io->in.assoc_ctx;
    700         packet->mess_type                   = WREPL_REPLICATION;
    701         packet->message.replication.command = WREPL_REPL_TABLE_QUERY;
    702 
    703         req = wrepl_request_send(wrepl_socket, packet, NULL);
    704 
    705         talloc_free(packet);
    706 
    707         return req;     
    708 }
    709 
     900        struct wrepl_table *table;
     901
     902        status = wrepl_request_recv(subreq, state, &packet);
     903        TALLOC_FREE(subreq);
     904        if (!NT_STATUS_IS_OK(status)) {
     905                tevent_req_nterror(req, status);
     906                return;
     907        }
     908
     909        if (packet->mess_type != WREPL_REPLICATION) {
     910                tevent_req_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
     911                return;
     912        }
     913
     914        if (packet->message.replication.command != WREPL_REPL_TABLE_REPLY) {
     915                tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
     916                return;
     917        }
     918
     919        table = &packet->message.replication.info.table;
     920
     921        state->num_partners = table->partner_count;
     922        state->partners = talloc_move(state, &table->partners);
     923
     924        tevent_req_done(req);
     925}
    710926
    711927/*
    712928  fetch the partner tables - recv
    713929*/
    714 NTSTATUS wrepl_pull_table_recv(struct wrepl_request *req,
     930NTSTATUS wrepl_pull_table_recv(struct tevent_req *req,
    715931                               TALLOC_CTX *mem_ctx,
    716932                               struct wrepl_pull_table *io)
    717933{
    718         struct wrepl_packet *packet=NULL;
    719         NTSTATUS status;
    720         struct wrepl_table *table;
    721         int i;
    722 
    723         status = wrepl_request_recv(req, req->wrepl_socket, &packet);
    724         NT_STATUS_NOT_OK_RETURN(status);
    725         if (packet->mess_type != WREPL_REPLICATION) {
    726                 status = NT_STATUS_NETWORK_ACCESS_DENIED;
    727         } else if (packet->message.replication.command != WREPL_REPL_TABLE_REPLY) {
    728                 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
    729         }
    730         if (!NT_STATUS_IS_OK(status)) goto failed;
    731 
    732         table = &packet->message.replication.info.table;
    733         io->out.num_partners = table->partner_count;
    734         io->out.partners = talloc_steal(mem_ctx, table->partners);
    735         for (i=0;i<io->out.num_partners;i++) {
    736                 talloc_steal(io->out.partners, io->out.partners[i].address);
    737         }
    738 
    739 failed:
    740         talloc_free(packet);
    741         return status;
    742 }
    743 
     934        struct wrepl_pull_table_state *state = tevent_req_data(req,
     935                                               struct wrepl_pull_table_state);
     936        NTSTATUS status;
     937
     938        if (tevent_req_is_nterror(req, &status)) {
     939                tevent_req_received(req);
     940                return status;
     941        }
     942
     943        io->out.num_partners = state->num_partners;
     944        io->out.partners = talloc_move(mem_ctx, &state->partners);
     945
     946        tevent_req_received(req);
     947        return NT_STATUS_OK;
     948}
    744949
    745950/*
     
    750955                          struct wrepl_pull_table *io)
    751956{
    752         struct wrepl_request *req = wrepl_pull_table_send(wrepl_socket, io);
    753         return wrepl_pull_table_recv(req, mem_ctx, io);
    754 }
    755 
    756 
    757 /*
    758   fetch the names for a WINS partner - send
    759 */
    760 struct wrepl_request *wrepl_pull_names_send(struct wrepl_socket *wrepl_socket,
    761                                             struct wrepl_pull_names *io)
    762 {
     957        struct tevent_req *subreq;
     958        bool ok;
     959        NTSTATUS status;
     960
     961        subreq = wrepl_pull_table_send(mem_ctx, wrepl_socket->event.ctx,
     962                                       wrepl_socket, io);
     963        NT_STATUS_HAVE_NO_MEMORY(subreq);
     964
     965        ok = tevent_req_poll(subreq, wrepl_socket->event.ctx);
     966        if (!ok) {
     967                TALLOC_FREE(subreq);
     968                return NT_STATUS_INTERNAL_ERROR;
     969        }
     970
     971        status = wrepl_pull_table_recv(subreq, mem_ctx, io);
     972        TALLOC_FREE(subreq);
     973        NT_STATUS_NOT_OK_RETURN(status);
     974
     975        return NT_STATUS_OK;
     976}
     977
     978
     979struct 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
     988static void wrepl_pull_names_done(struct tevent_req *subreq);
     989
     990struct 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        if (wrepl_socket->event.ctx != ev) {
     1000                /* TODO: remove wrepl_socket->event.ctx !!! */
     1001                smb_panic("wrepl_pull_names_send event context mismatch!");
     1002                return NULL;
     1003        }
     1004
     1005        req = tevent_req_create(mem_ctx, &state,
     1006                                struct wrepl_pull_names_state);
     1007        if (req == NULL) {
     1008                return NULL;
     1009        };
     1010        state->caller.io = io;
     1011
     1012        state->packet.opcode                            = WREPL_OPCODE_BITS;
     1013        state->packet.assoc_ctx                         = io->in.assoc_ctx;
     1014        state->packet.mess_type                         = WREPL_REPLICATION;
     1015        state->packet.message.replication.command       = WREPL_REPL_SEND_REQUEST;
     1016        state->packet.message.replication.info.owner    = io->in.partner;
     1017
     1018        subreq = wrepl_request_send(state, ev, wrepl_socket, &state->packet, NULL);
     1019        if (tevent_req_nomem(subreq, req)) {
     1020                return tevent_req_post(req, ev);
     1021        }
     1022        tevent_req_set_callback(subreq, wrepl_pull_names_done, req);
     1023
     1024        return req;
     1025}
     1026
     1027static void wrepl_pull_names_done(struct tevent_req *subreq)
     1028{
     1029        struct tevent_req *req = tevent_req_callback_data(subreq,
     1030                                 struct tevent_req);
     1031        struct wrepl_pull_names_state *state = tevent_req_data(req,
     1032                                               struct wrepl_pull_names_state);
     1033        NTSTATUS status;
    7631034        struct wrepl_packet *packet;
    764         struct wrepl_request *req;
    765 
    766         packet = talloc_zero(wrepl_socket, struct wrepl_packet);
    767         if (packet == NULL) return NULL;
    768 
    769         packet->opcode                         = WREPL_OPCODE_BITS;
    770         packet->assoc_ctx                      = io->in.assoc_ctx;
    771         packet->mess_type                      = WREPL_REPLICATION;
    772         packet->message.replication.command    = WREPL_REPL_SEND_REQUEST;
    773         packet->message.replication.info.owner = io->in.partner;
    774 
    775         req = wrepl_request_send(wrepl_socket, packet, NULL);
    776 
    777         talloc_free(packet);
    778 
    779         return req;     
    780 }
    781 
    782 /*
    783   fetch the names for a WINS partner - recv
    784 */
    785 NTSTATUS wrepl_pull_names_recv(struct wrepl_request *req,
    786                                TALLOC_CTX *mem_ctx,
    787                                struct wrepl_pull_names *io)
    788 {
    789         struct wrepl_packet *packet=NULL;
    790         NTSTATUS status;
    791         int i;
    792 
    793         status = wrepl_request_recv(req, req->wrepl_socket, &packet);
    794         NT_STATUS_NOT_OK_RETURN(status);
    795         if (packet->mess_type != WREPL_REPLICATION ||
    796             packet->message.replication.command != WREPL_REPL_SEND_REPLY) {
    797                 status = NT_STATUS_UNEXPECTED_NETWORK_ERROR;
    798         }
    799         if (!NT_STATUS_IS_OK(status)) goto failed;
    800 
    801         io->out.num_names = packet->message.replication.info.reply.num_names;
    802 
    803         io->out.names = talloc_array(packet, struct wrepl_name, io->out.num_names);
    804         if (io->out.names == NULL) goto nomem;
     1035        uint32_t i;
     1036
     1037        status = wrepl_request_recv(subreq, state, &packet);
     1038        TALLOC_FREE(subreq);
     1039        if (!NT_STATUS_IS_OK(status)) {
     1040                tevent_req_nterror(req, status);
     1041                return;
     1042        }
     1043
     1044        if (packet->mess_type != WREPL_REPLICATION) {
     1045                tevent_req_nterror(req, NT_STATUS_NETWORK_ACCESS_DENIED);
     1046                return;
     1047        }
     1048
     1049        if (packet->message.replication.command != WREPL_REPL_SEND_REPLY) {
     1050                tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
     1051                return;
     1052        }
     1053
     1054        state->num_names = packet->message.replication.info.reply.num_names;
     1055
     1056        state->names = talloc_array(state, struct wrepl_name, state->num_names);
     1057        if (tevent_req_nomem(state->names, req)) {
     1058                return;
     1059        }
    8051060
    8061061        /* convert the list of names and addresses to a sane format */
    807         for (i=0;i<io->out.num_names;i++) {
     1062        for (i=0; i < state->num_names; i++) {
    8081063                struct wrepl_wins_name *wname = &packet->message.replication.info.reply.names[i];
    809                 struct wrepl_name *name = &io->out.names[i];
     1064                struct wrepl_name *name = &state->names[i];
    8101065
    8111066                name->name      = *wname->name;
    812                 talloc_steal(io->out.names, wname->name);
     1067                talloc_steal(state->names, wname->name);
    8131068                name->type      = WREPL_NAME_TYPE(wname->flags);
    8141069                name->state     = WREPL_NAME_STATE(wname->flags);
     
    8171072                name->raw_flags = wname->flags;
    8181073                name->version_id= wname->id;
    819                 name->owner     = talloc_strdup(io->out.names, io->in.partner.address);
    820                 if (name->owner == NULL) goto nomem;
     1074                name->owner     = talloc_strdup(state->names,
     1075                                                state->caller.io->in.partner.address);
     1076                if (tevent_req_nomem(name->owner, req)) {
     1077                        return;
     1078                }
    8211079
    8221080                /* trying to save 1 or 2 bytes on the wire isn't a good idea */
    8231081                if (wname->flags & 2) {
    824                         int j;
     1082                        uint32_t j;
    8251083
    8261084                        name->num_addresses = wname->addresses.addresses.num_ips;
    827                         name->addresses = talloc_array(io->out.names,
    828                                                        struct wrepl_address, 
     1085                        name->addresses = talloc_array(state->names,
     1086                                                       struct wrepl_address,
    8291087                                                       name->num_addresses);
    830                         if (name->addresses == NULL) goto nomem;
     1088                        if (tevent_req_nomem(name->addresses, req)) {
     1089                                return;
     1090                        }
     1091
    8311092                        for (j=0;j<name->num_addresses;j++) {
    832                                 name->addresses[j].owner = 
    833                                         talloc_steal(name->addresses,
    834                                                      wname->addresses.addresses.ips[j].owner);
     1093                                name->addresses[j].owner =
     1094                                        talloc_move(name->addresses,
     1095                                                    &wname->addresses.addresses.ips[j].owner);
    8351096                                name->addresses[j].address =
    836                                         talloc_steal(name->addresses,
    837                                                      wname->addresses.addresses.ips[j].ip);
     1097                                        talloc_move(name->addresses,
     1098                                                    &wname->addresses.addresses.ips[j].ip);
    8381099                        }
    8391100                } else {
    8401101                        name->num_addresses = 1;
    841                         name->addresses = talloc(io->out.names, struct wrepl_address);
    842                         if (name->addresses == NULL) goto nomem;
    843                         name->addresses[0].owner = talloc_strdup(name->addresses,io->in.partner.address);
    844                         if (name->addresses[0].owner == NULL) goto nomem;
    845                         name->addresses[0].address = talloc_steal(name->addresses,
    846                                                                   wname->addresses.ip);
     1102                        name->addresses = talloc_array(state->names,
     1103                                                       struct wrepl_address,
     1104                                                       name->num_addresses);
     1105                        if (tevent_req_nomem(name->addresses, req)) {
     1106                                return;
     1107                        }
     1108
     1109                        name->addresses[0].owner = talloc_strdup(name->addresses, name->owner);
     1110                        if (tevent_req_nomem(name->addresses[0].owner, req)) {
     1111                                return;
     1112                        }
     1113                        name->addresses[0].address = talloc_move(name->addresses,
     1114                                                                 &wname->addresses.ip);
    8471115                }
    8481116        }
    8491117
    850         talloc_steal(mem_ctx, io->out.names);
    851         talloc_free(packet);
    852         return NT_STATUS_OK;
    853 nomem:
    854         status = NT_STATUS_NO_MEMORY;
    855 failed:
    856         talloc_free(packet);
    857         return status;
     1118        tevent_req_done(req);
     1119}
     1120
     1121/*
     1122  fetch the names for a WINS partner - recv
     1123*/
     1124NTSTATUS wrepl_pull_names_recv(struct tevent_req *req,
     1125                               TALLOC_CTX *mem_ctx,
     1126                               struct wrepl_pull_names *io)
     1127{
     1128        struct wrepl_pull_names_state *state = tevent_req_data(req,
     1129                                               struct wrepl_pull_names_state);
     1130        NTSTATUS status;
     1131
     1132        if (tevent_req_is_nterror(req, &status)) {
     1133                tevent_req_received(req);
     1134                return status;
     1135        }
     1136
     1137        io->out.num_names = state->num_names;
     1138        io->out.names = talloc_move(mem_ctx, &state->names);
     1139
     1140        tevent_req_received(req);
     1141        return NT_STATUS_OK;
    8581142}
    8591143
     
    8671151                          struct wrepl_pull_names *io)
    8681152{
    869         struct wrepl_request *req = wrepl_pull_names_send(wrepl_socket, io);
    870         return wrepl_pull_names_recv(req, mem_ctx, io);
    871 }
     1153        struct tevent_req *subreq;
     1154        bool ok;
     1155        NTSTATUS status;
     1156
     1157        subreq = wrepl_pull_names_send(mem_ctx, wrepl_socket->event.ctx,
     1158                                       wrepl_socket, io);
     1159        NT_STATUS_HAVE_NO_MEMORY(subreq);
     1160
     1161        ok = tevent_req_poll(subreq, wrepl_socket->event.ctx);
     1162        if (!ok) {
     1163                TALLOC_FREE(subreq);
     1164                return NT_STATUS_INTERNAL_ERROR;
     1165        }
     1166
     1167        status = wrepl_pull_names_recv(subreq, mem_ctx, io);
     1168        TALLOC_FREE(subreq);
     1169        NT_STATUS_NOT_OK_RETURN(status);
     1170
     1171        return NT_STATUS_OK;
     1172}
  • vendor/current/source4/libcli/wrepl/winsrepl.h

    r414 r740  
    55
    66   Copyright (C) Andrew Tridgell 2005
     7   Copyright (C) Stefan Metzmacher 2005-2010
    78
    89   This program is free software; you can redistribute it and/or modify
     
    2324#include "librpc/gen_ndr/winsrepl.h"
    2425
    25 /*
    26   main context structure for the wins replication client library
    27 */
    28 struct wrepl_socket {
    29         struct socket_context *sock;
    30         struct packet_context *packet;
    31 
    32         struct {
    33                 struct tevent_context *ctx;
    34                 struct tevent_fd *fde;
    35         } event;
    36 
    37         /* a queue of replies waiting to be received */
    38         struct wrepl_request *recv_queue;
    39 
    40         /* the default timeout for requests, 0 means no timeout */
    41 #define WREPL_SOCKET_REQUEST_TIMEOUT    (60)
    42         uint32_t request_timeout;
    43 
    44         /* counter for request timeouts, after 2 timeouts the socket is marked as dead */
    45         uint32_t timeout_count;
    46 
    47         /* remember is the socket is dead */
    48         bool dead;
    49 
    50         /* remember if we need to free the wrepl_socket at the end of wrepl_socket_dead() */
    51         bool free_skipped;
    52 
    53         struct smb_iconv_convenience *iconv_convenience;
    54 };
     26struct wrepl_request;
     27struct wrepl_socket;
    5528
    5629struct wrepl_send_ctrl {
     
    5831        bool disconnect_after_send;
    5932};
    60 
    61 enum wrepl_request_state {
    62         WREPL_REQUEST_INIT  = 0,
    63         WREPL_REQUEST_RECV  = 1,
    64         WREPL_REQUEST_DONE  = 2,
    65         WREPL_REQUEST_ERROR = 3
    66 };
    67 
    68 /*
    69   a WINS replication request
    70 */
    71 struct wrepl_request {
    72         struct wrepl_request *next, *prev;
    73         struct wrepl_socket *wrepl_socket;
    74 
    75         enum wrepl_request_state state;
    76         bool trigger;
    77         NTSTATUS status;
    78 
    79         struct tevent_timer *te;
    80 
    81         struct wrepl_packet *packet;
    82 
    83         struct {
    84                 void (*fn)(struct wrepl_request *);
    85                 void *private_data;
    86         } async;
    87 };
    88 
    8933
    9034/*
     
    13074         (is_static ? WREPL_FLAGS_IS_STATIC : 0))
    13175
     76struct wrepl_address {
     77        const char *owner;
     78        const char *address;
     79};
     80
     81struct wrepl_name {
     82        struct nbt_name name;
     83        enum wrepl_name_type type;
     84        enum wrepl_name_state state;
     85        enum wrepl_name_node node;
     86        bool is_static;
     87        uint32_t raw_flags;
     88        uint64_t version_id;
     89        const char *owner;
     90        uint32_t num_addresses;
     91        struct wrepl_address *addresses;
     92};
     93
    13294/*
    13395  a full pull replication
     
    140102        struct {
    141103                uint32_t num_names;
    142                 struct wrepl_name {
    143                         struct nbt_name name;
    144                         enum wrepl_name_type type;
    145                         enum wrepl_name_state state;
    146                         enum wrepl_name_node node;
    147                         bool is_static;
    148                         uint32_t raw_flags;
    149                         uint64_t version_id;
    150                         const char *owner;
    151                         uint32_t num_addresses;
    152                         struct wrepl_address {
    153                                 const char *owner;
    154                                 const char *address;
    155                         } *addresses;
    156                 } *names;
     104                struct wrepl_name *names;
    157105        } out;
    158106};
    159107
    160 struct resolve_context;
     108struct tstream_context;
    161109
    162110#include "libcli/wrepl/winsrepl_proto.h"
Note: See TracChangeset for help on using the changeset viewer.