/* update the wins_owner_table max_version, if the given version is the highest version if no entry for the wins_owner exists yet, create one */ NTSTATUS wreplsrv_add_table(struct wreplsrv_service *service, TALLOC_CTX *mem_ctx, struct wreplsrv_owner **_table, const char *wins_owner, uint64_t version) { struct wreplsrv_owner *table = *_table; struct wreplsrv_owner *cur; if (!wins_owner || strcmp(wins_owner, "0.0.0.0") == 0) { wins_owner = service->wins_db->local_owner; } cur = wreplsrv_find_owner(service, table, wins_owner); /* if it doesn't exists yet, create one */ if (!cur) { cur = talloc_zero(mem_ctx, struct wreplsrv_owner); NT_STATUS_HAVE_NO_MEMORY(cur); cur->owner.address = talloc_strdup(cur, wins_owner); NT_STATUS_HAVE_NO_MEMORY(cur->owner.address); cur->owner.min_version = 0; cur->owner.max_version = 0; cur->owner.type = 1; /* don't know why this is always 1 */ cur->partner = wreplsrv_find_partner(service, wins_owner); DLIST_ADD_END(table, cur, struct wreplsrv_owner *); *_table = table; }
/* called when we get a new connection */ static void wreplsrv_accept(struct stream_connection *conn) { struct wreplsrv_service *service = talloc_get_type(conn->private_data, struct wreplsrv_service); struct wreplsrv_in_connection *wrepl_conn; struct tsocket_address *peer_addr; char *peer_ip; struct tevent_req *subreq; int rc; wrepl_conn = talloc_zero(conn, struct wreplsrv_in_connection); if (wrepl_conn == NULL) { stream_terminate_connection(conn, "wreplsrv_accept: out of memory"); return; } wrepl_conn->send_queue = tevent_queue_create(conn, "wrepl_accept"); if (wrepl_conn->send_queue == NULL) { stream_terminate_connection(conn, "wrepl_accept: out of memory"); return; } TALLOC_FREE(conn->event.fde); rc = tstream_bsd_existing_socket(wrepl_conn, socket_get_fd(conn->socket), &wrepl_conn->tstream); if (rc < 0) { stream_terminate_connection(conn, "wrepl_accept: out of memory"); return; } socket_set_flags(conn->socket, SOCKET_FLAG_NOCLOSE); wrepl_conn->conn = conn; wrepl_conn->service = service; peer_addr = conn->remote_address; if (!tsocket_address_is_inet(peer_addr, "ipv4")) { DEBUG(0,("wreplsrv_accept: non ipv4 peer addr '%s'\n", tsocket_address_string(peer_addr, wrepl_conn))); wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_accept: " "invalid peer IP"); return; } peer_ip = tsocket_address_inet_addr_string(peer_addr, wrepl_conn); if (peer_ip == NULL) { wreplsrv_terminate_in_connection(wrepl_conn, "wreplsrv_accept: " "could not convert peer IP into a string"); return; } wrepl_conn->partner = wreplsrv_find_partner(service, peer_ip); irpc_add_name(conn->msg_ctx, "wreplsrv_connection"); /* * The wrepl pdu's has the length as 4 byte (initial_read_size), * packet_full_request_u32 provides the pdu length then. */ subreq = tstream_read_pdu_blob_send(wrepl_conn, wrepl_conn->conn->event.ctx, wrepl_conn->tstream, 4, /* initial_read_size */ packet_full_request_u32, wrepl_conn); if (subreq == NULL) { wreplsrv_terminate_in_connection(wrepl_conn, "wrepl_accept: " "no memory for tstream_read_pdu_blob_send"); return; } tevent_req_set_callback(subreq, wreplsrv_call_loop, wrepl_conn); }
/* load our replication partners */ NTSTATUS wreplsrv_load_partners(struct wreplsrv_service *service) { struct wreplsrv_partner *partner; struct ldb_result *res = NULL; int ret; TALLOC_CTX *tmp_ctx; int i; uint64_t new_seqnumber; new_seqnumber = wins_config_db_get_seqnumber(service->config.ldb); /* if it's not the first run and nothing changed we're done */ if (service->config.seqnumber != 0 && service->config.seqnumber == new_seqnumber) { return NT_STATUS_OK; } tmp_ctx = talloc_new(service); NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); service->config.seqnumber = new_seqnumber; /* find the record in the WINS database */ ret = ldb_search(service->config.ldb, tmp_ctx, &res, ldb_dn_new(tmp_ctx, service->config.ldb, "CN=PARTNERS"), LDB_SCOPE_SUBTREE, NULL, "(objectClass=wreplPartner)"); if (ret != LDB_SUCCESS) goto failed; /* first disable all existing partners */ for (partner=service->partners; partner; partner = partner->next) { partner->type = WINSREPL_PARTNER_NONE; } for (i=0; i < res->count; i++) { const char *address; address = ldb_msg_find_attr_as_string(res->msgs[i], "address", NULL); if (!address) { goto failed; } partner = wreplsrv_find_partner(service, address); if (partner) { if (partner->name != partner->address) { talloc_free(discard_const(partner->name)); } partner->name = NULL; talloc_free(discard_const(partner->our_address)); partner->our_address = NULL; /* force rescheduling of pulling */ partner->pull.next_run = timeval_zero(); } else { partner = talloc_zero(service, struct wreplsrv_partner); if (partner == NULL) goto failed; partner->service = service; partner->address = address; talloc_steal(partner, partner->address); DLIST_ADD_END(service->partners, partner, struct wreplsrv_partner *); } partner->name = ldb_msg_find_attr_as_string(res->msgs[i], "name", partner->address); talloc_steal(partner, partner->name); partner->our_address = ldb_msg_find_attr_as_string(res->msgs[i], "ourAddress", NULL); talloc_steal(partner, partner->our_address); partner->type = ldb_msg_find_attr_as_uint(res->msgs[i], "type", WINSREPL_PARTNER_BOTH); partner->pull.interval = ldb_msg_find_attr_as_uint(res->msgs[i], "pullInterval", WINSREPL_DEFAULT_PULL_INTERVAL); partner->pull.retry_interval = ldb_msg_find_attr_as_uint(res->msgs[i], "pullRetryInterval", WINSREPL_DEFAULT_PULL_RETRY_INTERVAL); partner->push.change_count = ldb_msg_find_attr_as_uint(res->msgs[i], "pushChangeCount", WINSREPL_DEFAULT_PUSH_CHANGE_COUNT); partner->push.use_inform = ldb_msg_find_attr_as_uint(res->msgs[i], "pushUseInform", true); DEBUG(3,("wreplsrv_load_partners: found partner: %s type: 0x%X\n", partner->address, partner->type)); } DEBUG(2,("wreplsrv_load_partners: %u partners found: wins_config_db seqnumber %llu\n", res->count, (unsigned long long)service->config.seqnumber)); talloc_free(tmp_ctx); return NT_STATUS_OK; failed: talloc_free(tmp_ctx); return NT_STATUS_FOOBAR; }