Changeset 740 for vendor/current/source4/libcli/wrepl
- Timestamp:
- Nov 14, 2012, 12:59:34 PM (13 years ago)
- Location:
- vendor/current/source4/libcli/wrepl
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source4/libcli/wrepl/winsrepl.c
r414 r740 5 5 6 6 Copyright (C) Andrew Tridgell 2005 7 Copyright (C) Stefan Metzmacher 2005-2010 7 8 8 9 This program is free software; you can redistribute it and/or modify … … 23 24 #include "lib/events/events.h" 24 25 #include "../lib/util/dlinklist.h" 25 #include "lib/socket/socket.h"26 26 #include "libcli/wrepl/winsrepl.h" 27 27 #include "librpc/gen_ndr/ndr_winsrepl.h" 28 28 #include "lib/stream/packet.h" 29 #include "libcli/composite/composite.h"30 29 #include "system/network.h" 31 30 #include "lib/socket/netif.h" 32 31 #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 */ 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 bool 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; 158 64 } 159 65 … … 162 68 operations will use that event context 163 69 */ 164 struct wrepl_socket *wrepl_socket_init(TALLOC_CTX *mem_ctx, 165 struct tevent_context *event_ctx, 166 struct smb_iconv_convenience *iconv_convenience) 70 struct wrepl_socket *wrepl_socket_init(TALLOC_CTX *mem_ctx, 71 struct tevent_context *event_ctx) 167 72 { 168 73 struct wrepl_socket *wrepl_socket; 169 NTSTATUS status;170 74 171 75 wrepl_socket = talloc_zero(mem_ctx, struct wrepl_socket); 172 if (!wrepl_socket) return NULL; 76 if (!wrepl_socket) { 77 return NULL; 78 } 173 79 174 80 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 } 183 90 184 91 wrepl_socket->request_timeout = WREPL_SOCKET_REQUEST_TIMEOUT; 185 186 talloc_set_destructor(wrepl_socket, wrepl_socket_destructor);187 92 188 93 return wrepl_socket; … … 196 101 initialise a wrepl_socket from an already existing connection 197 102 */ 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; 103 NTSTATUS 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 */ 117 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 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 136 const 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); 267 141 } 268 142 269 143 struct 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; 273 151 }; 274 152 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, 153 static void wrepl_connect_trigger(struct tevent_req *req, 154 void *private_date); 155 156 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 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 220 static void wrepl_connect_done(struct tevent_req *subreq); 221 222 static void wrepl_connect_trigger(struct tevent_req *req, 223 void *private_date) 224 { 225 struct wrepl_connect_state *state = tevent_req_data(req, 281 226 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 241 static 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); 351 259 } 352 260 … … 354 262 connect a wrepl_socket to a WINS server - recv side 355 263 */ 356 NTSTATUS wrepl_connect_recv(struct composite_context *result)357 { 358 struct wrepl_connect_state *state = t alloc_get_type(result->private_data,264 NTSTATUS wrepl_connect_recv(struct tevent_req *req) 265 { 266 struct wrepl_connect_state *state = tevent_req_data(req, 359 267 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; 369 280 } 370 281 … … 375 286 const char *our_ip, const char *peer_ip) 376 287 { 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 309 struct wrepl_request_state { 310 struct { 311 struct wrepl_socket *wrepl_socket; 312 struct tevent_context *ev; 313 } caller; 434 314 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; 437 325 }; 438 326 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; 327 static void wrepl_request_trigger(struct tevent_req *req, 328 void *private_data); 329 330 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; 477 338 NTSTATUS status; 478 339 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, 495 369 (ndr_push_flags_fn_t)ndr_push_wrepl_wrap); 496 370 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 497 371 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 401 static void wrepl_request_writev_done(struct tevent_req *subreq); 402 403 static 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; 499 413 } 500 414 501 415 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 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 static 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 485 static 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 509 static 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); 524 520 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 554 NTSTATUS wrepl_request_recv(struct tevent_req *req, 536 555 TALLOC_CTX *mem_ctx, 537 556 struct wrepl_packet **packet) 538 557 { 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; 545 574 } 546 575 … … 550 579 NTSTATUS wrepl_request(struct wrepl_socket *wrepl_socket, 551 580 TALLOC_CTX *mem_ctx, 552 struct wrepl_packet *req_packet,581 const struct wrepl_packet *req_packet, 553 582 struct wrepl_packet **reply_packet) 554 583 { 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 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 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 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; 576 639 577 640 /* … … 583 646 * and that would break nt4 <-> samba replication 584 647 */ 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 663 static 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); 597 688 } 598 689 … … 600 691 setup an association - recv 601 692 */ 602 NTSTATUS wrepl_associate_recv(struct wrepl_request*req,693 NTSTATUS wrepl_associate_recv(struct tevent_req *req, 603 694 struct wrepl_associate *io) 604 695 { 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; 618 710 } 619 711 … … 624 716 struct wrepl_associate *io) 625 717 { 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 739 struct wrepl_associate_stop_state { 740 struct wrepl_packet packet; 639 741 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 744 static void wrepl_associate_stop_done(struct tevent_req *subreq); 745 746 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 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 650 772 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 786 static 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); 660 803 } 661 804 … … 663 806 stop an association - recv 664 807 */ 665 NTSTATUS wrepl_associate_stop_recv(struct wrepl_request*req,808 NTSTATUS wrepl_associate_stop_recv(struct tevent_req *req, 666 809 struct wrepl_associate_stop *io) 667 810 { 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; 674 820 } 675 821 … … 680 826 struct wrepl_associate_stop *io) 681 827 { 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 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 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 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 892 static 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; 692 899 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 } 710 926 711 927 /* 712 928 fetch the partner tables - recv 713 929 */ 714 NTSTATUS wrepl_pull_table_recv(struct wrepl_request*req,930 NTSTATUS wrepl_pull_table_recv(struct tevent_req *req, 715 931 TALLOC_CTX *mem_ctx, 716 932 struct wrepl_pull_table *io) 717 933 { 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 } 744 949 745 950 /* … … 750 955 struct wrepl_pull_table *io) 751 956 { 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 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 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 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 1027 static 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; 763 1034 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 } 805 1060 806 1061 /* 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++) { 808 1063 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]; 810 1065 811 1066 name->name = *wname->name; 812 talloc_steal( io->out.names, wname->name);1067 talloc_steal(state->names, wname->name); 813 1068 name->type = WREPL_NAME_TYPE(wname->flags); 814 1069 name->state = WREPL_NAME_STATE(wname->flags); … … 817 1072 name->raw_flags = wname->flags; 818 1073 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 } 821 1079 822 1080 /* trying to save 1 or 2 bytes on the wire isn't a good idea */ 823 1081 if (wname->flags & 2) { 824 int j;1082 uint32_t j; 825 1083 826 1084 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, 829 1087 name->num_addresses); 830 if (name->addresses == NULL) goto nomem; 1088 if (tevent_req_nomem(name->addresses, req)) { 1089 return; 1090 } 1091 831 1092 for (j=0;j<name->num_addresses;j++) { 832 name->addresses[j].owner = 833 talloc_ steal(name->addresses,834 1093 name->addresses[j].owner = 1094 talloc_move(name->addresses, 1095 &wname->addresses.addresses.ips[j].owner); 835 1096 name->addresses[j].address = 836 talloc_ steal(name->addresses,837 1097 talloc_move(name->addresses, 1098 &wname->addresses.addresses.ips[j].ip); 838 1099 } 839 1100 } else { 840 1101 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); 847 1115 } 848 1116 } 849 1117 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 */ 1124 NTSTATUS 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; 858 1142 } 859 1143 … … 867 1151 struct wrepl_pull_names *io) 868 1152 { 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 5 5 6 6 Copyright (C) Andrew Tridgell 2005 7 Copyright (C) Stefan Metzmacher 2005-2010 7 8 8 9 This program is free software; you can redistribute it and/or modify … … 23 24 #include "librpc/gen_ndr/winsrepl.h" 24 25 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 }; 26 struct wrepl_request; 27 struct wrepl_socket; 55 28 56 29 struct wrepl_send_ctrl { … … 58 31 bool disconnect_after_send; 59 32 }; 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 = 366 };67 68 /*69 a WINS replication request70 */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 89 33 90 34 /* … … 130 74 (is_static ? WREPL_FLAGS_IS_STATIC : 0)) 131 75 76 struct wrepl_address { 77 const char *owner; 78 const char *address; 79 }; 80 81 struct 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 132 94 /* 133 95 a full pull replication … … 140 102 struct { 141 103 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; 157 105 } out; 158 106 }; 159 107 160 struct resolve_context;108 struct tstream_context; 161 109 162 110 #include "libcli/wrepl/winsrepl_proto.h"
Note:
See TracChangeset
for help on using the changeset viewer.