r11052: bring samba4 uptodate with the samba4-winsrepl branch,
authorStefan Metzmacher <metze@samba.org>
Fri, 14 Oct 2005 14:02:47 +0000 (14:02 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:44:43 +0000 (13:44 -0500)
before the bad merge

metze
(This used to be commit 471c0ca4abb17fb5f73c0efed195c67628c1c06e)

28 files changed:
source4/auth/kerberos/SConscript
source4/auth/ntlmssp/SConscript
source4/dsdb/SConscript
source4/include/structs.h
source4/lib/charset/SConscript
source4/lib/popt/SConscript
source4/lib/replace/SConscript
source4/lib/socket/SConscript
source4/lib/socket_wrapper/SConscript
source4/libcli/SConscript
source4/libcli/auth/SConscript
source4/libcli/ldap/SConscript
source4/libcli/security/SConscript
source4/librpc/SConscript
source4/nbt_server/defense.c
source4/nbt_server/nodestatus.c
source4/nbt_server/query.c
source4/nbt_server/wins/winsdb.c
source4/nbt_server/wins/winsdb.h
source4/nbt_server/wins/winsserver.c
source4/pidl/lib/Parse/Pidl/Ethereal/NDR.pm
source4/torture/nbt/dgram.c
source4/wrepl_server/config.mk
source4/wrepl_server/wrepl_in_call.c
source4/wrepl_server/wrepl_in_connection.c
source4/wrepl_server/wrepl_out_connection.c
source4/wrepl_server/wrepl_server.c
source4/wrepl_server/wrepl_server.h

index 8272f1c24a88875a03581f105f92a0d52bb60ced..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,6 +0,0 @@
-Import('hostenv')
-
-hostenv.StaticLibrary('kerberos',
-               ['kerberos.c','clikrb5.c','kerberos_verify.c',
-               'kerberos_util.c','kerberos_pac.c','gssapi_parse.c',
-               'krb5_init_context.c'])
index 1fb21c02cdde899f4e28ced50856cb141bd4d47e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,5 +0,0 @@
-Import('hostenv')
-
-hostenv.StaticLibrary('gensec_ntlmssp',
-               ['ntlmssp_parse.c','ntlmssp.c','ntlmssp_sign.c','ntlmssp_client.c',
-               'ntlmssp_server.c'])
index 9f73bc76730a24c652b5a7f54a8309dc8ed7b153..cdbf1461495843adf7a1c981cbcca5019a7299f4 100644 (file)
@@ -1,4 +1,5 @@
 Import('hostenv')
+
 dsdb_ldb_modules = []
 
 dsdb_ldb_modules.append(
index 2da6205ba83aa81481f00d16ef48fb2e40700380..68cae5d2562d3080f44cefb186e4e16af578057d 100644 (file)
@@ -277,9 +277,13 @@ struct wreplsrv_partner;
 struct wreplsrv_owner;
 struct wreplsrv_in_connection;
 struct wreplsrv_in_call;
+struct wreplsrv_out_connection;
+struct wreplsrv_pull_table_io;
+struct wreplsrv_pull_names_io;
+struct wreplsrv_pull_cycle_io;
+struct wreplsrv_push_notify_io;
 
 struct winsdb_record;
-struct winsdb_addr;
 
 struct wrepl_packet;
 struct wrepl_associate;
index 15ee49909cc13b88b124d191b9a9d81f0147a8d9..9bc474ff48b2d212b782c064ff5d64be8913b57d 100644 (file)
@@ -1,6 +1,7 @@
 #!/usr/bin/env python
 # tastes like -*- python -*-
 
+Import('hostenv')
 
 def _CheckIconvPath(context,path):
        # Some systems have iconv in libc, some have it in libiconv (OSF/1 and
index 64faff772c3617ddf7d6755da5f248ae7d28bd66..d9a576a031c6157ccbb25bee1a6d89e32aef9218 100644 (file)
@@ -1,4 +1,3 @@
-Import('hostenv')
 #            tastes like -*- python -*-
 Import('hostenv')
 
index 948c33bdc033828e768326314bca1735680bdd96..cf2810217587e5e13d86af0b7ee7de8cca78e144 100644 (file)
@@ -1,6 +1,5 @@
 #!/usr/bin/env python
 Import('hostenv defines')
-conf = Configure(hostenv)
 
 rep_files = ['replace.c', 'snprintf.c','dlfcn.c']
 
index 14080fa1b0cc7c3add4ff37c9e5b8acab06c5317..73c7eeeeacec33737469c96c118dbb00c0b693fd 100644 (file)
@@ -1,5 +1,6 @@
 #!/usr/bin/env python
 Import('hostenv defines')
+
 if hostenv['configure']:
        conf = hostenv.Configure()
        for h in ['sys/socket.h','sys/sockio.h','sys/un.h']:
index ab08e3af732fde3a15b1a50e35be091d4c57b33b..248922bcd7f9469684a1708a716fe378ee74599e 100644 (file)
@@ -1,4 +1,5 @@
 Import('hostenv')
+
 opts = Options(None, ARGUMENTS)
 opts.AddOptions(
        BoolOption('socket_wrapper','enable socket wrapper',0)
index 98847d93360a56515a985debe7a1c4281a2548f9..5b600fdcfff84cf62e1210be6b50ab35aca645f1 100644 (file)
@@ -1,4 +1,5 @@
 Import('hostenv')
+
 hostenv.Subsystem(
     'cli_utils',
     ['util/asn1.c',
index d527faac302d5a8546d9deac5d047b34a2efc927..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,3 +0,0 @@
-Import('hostenv')
-
-hostenv.StaticLibrary('cli_auth',['credentials.c','session.c','smbencrypt.c'])
index eef9a9f41c99ca1bbd6a711dedc9a4dfc14cba69..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,5 +0,0 @@
-Import('hostenv')
-
-hostenv.StaticLibrary('cli_ldap',
-               ['ldap.c','ldap_client.c','ldap_bind.c','ldap_msg.c','ldap_ndr.c',
-               'ldap_ildap.c'])
index e81051e07e1578a743bc3791ea4b78bc8b27b679..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,5 +0,0 @@
-Import('hostenv')
-
-hostenv.StaticLibrary('cli_security',
-               ['security_token.c','security_descriptor.c','dom_sid.c',
-                'access_check.c','privilege.c'])
index 059efab51a95ffeec1a3a79916033109fc08dd43..083a84fc36e131abf844473c878ddc853429731e 100644 (file)
@@ -1,5 +1,6 @@
 #!/usr/bin/python
 Import('hostenv')
+
 ndr_base_files = ['ndr/ndr.c', 'ndr/ndr_basic.c', 'ndr/ndr_string.c',
                  'ndr/ndr_obfuscate.c', 'ndr/ndr_misc.c'] 
 
index 55a345e18dbdbfaa403cf606b3ce981acbae7380..0819fd4f2f7c2fa65b3bf6c2bb73ed4202eb7137 100644 (file)
@@ -39,17 +39,17 @@ void nbtd_request_defense(struct nbt_name_socket *nbtsock,
        struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, 
                                                       struct nbtd_interface);
 
-       NBTD_ASSERT_PACKET(packet, src->addr, packet->qdcount == 1);
-       NBTD_ASSERT_PACKET(packet, src->addr, packet->arcount == 1);
-       NBTD_ASSERT_PACKET(packet, src->addr
+       NBTD_ASSERT_PACKET(packet, src, packet->qdcount == 1);
+       NBTD_ASSERT_PACKET(packet, src, packet->arcount == 1);
+       NBTD_ASSERT_PACKET(packet, src, 
                           packet->questions[0].question_type == NBT_QTYPE_NETBIOS);
-       NBTD_ASSERT_PACKET(packet, src->addr
+       NBTD_ASSERT_PACKET(packet, src, 
                           packet->questions[0].question_class == NBT_QCLASS_IP);
-       NBTD_ASSERT_PACKET(packet, src->addr
+       NBTD_ASSERT_PACKET(packet, src, 
                          packet->additional[0].rr_type == NBT_QTYPE_NETBIOS);
-       NBTD_ASSERT_PACKET(packet, src->addr
+       NBTD_ASSERT_PACKET(packet, src, 
                          packet->additional[0].rr_class == NBT_QCLASS_IP);
-       NBTD_ASSERT_PACKET(packet, src->addr
+       NBTD_ASSERT_PACKET(packet, src, 
                          packet->additional[0].rdata.netbios.length == 6);
 
        /* see if we have the requested name on this interface */
index ccbdc2b933726b77a747da172691f7c430da0389..efd4720790bdc43f41104b0d2acb10e16cd485f4 100644 (file)
@@ -106,9 +106,9 @@ void nbtd_query_status(struct nbt_name_socket *nbtsock,
        struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, 
                                                       struct nbtd_interface);
 
-       NBTD_ASSERT_PACKET(packet, src->addr, packet->qdcount == 1);
-       NBTD_ASSERT_PACKET(packet, src->addr, packet->questions[0].question_type == NBT_QTYPE_STATUS);
-       NBTD_ASSERT_PACKET(packet, src->addr, packet->questions[0].question_class == NBT_QCLASS_IP);
+       NBTD_ASSERT_PACKET(packet, src, packet->qdcount == 1);
+       NBTD_ASSERT_PACKET(packet, src, packet->questions[0].question_type == NBT_QTYPE_STATUS);
+       NBTD_ASSERT_PACKET(packet, src, packet->questions[0].question_class == NBT_QCLASS_IP);
 
        /* see if we have the requested name on this interface */
        name = &packet->questions[0].name;
index c64ac5986a8bdaff774154bf0eea42c9bf739610..1d8a61075024314f07599da759d7ad5d38559b2a 100644 (file)
@@ -45,10 +45,10 @@ void nbtd_request_query(struct nbt_name_socket *nbtsock,
                return;
        }
 
-       NBTD_ASSERT_PACKET(packet, src->addr, packet->qdcount == 1);
-       NBTD_ASSERT_PACKET(packet, src->addr
+       NBTD_ASSERT_PACKET(packet, src, packet->qdcount == 1);
+       NBTD_ASSERT_PACKET(packet, src, 
                           packet->questions[0].question_type == NBT_QTYPE_NETBIOS);
-       NBTD_ASSERT_PACKET(packet, src->addr
+       NBTD_ASSERT_PACKET(packet, src, 
                           packet->questions[0].question_class == NBT_QCLASS_IP);
 
        /* see if we have the requested name on this interface */
index 50baa5089812cc041cc96bcb8f23c5ee1b73059e..7ab82168375050d08ed79e1348b7a16040466ac8 100644 (file)
@@ -33,6 +33,7 @@
 */
 static uint64_t winsdb_allocate_version(struct wins_server *winssrv)
 {
+       int trans;
        int ret;
        struct ldb_context *ldb = winssrv->wins_db;
        struct ldb_dn *dn;
@@ -41,12 +42,21 @@ static uint64_t winsdb_allocate_version(struct wins_server *winssrv)
        TALLOC_CTX *tmp_ctx = talloc_new(winssrv);
        uint64_t maxVersion = 0;
 
-       dn = ldb_dn_explode(tmp_ctx, "CN=VERSION");
-       if (!dn) goto failed;
+       trans = ldb_transaction_start(ldb);
+       if (trans != LDB_SUCCESS) goto failed;
 
        dn = ldb_dn_explode(tmp_ctx, "CN=VERSION");
        if (!dn) goto failed;
 
+       /* find the record in the WINS database */
+       ret = ldb_search(ldb, dn, LDB_SCOPE_BASE, 
+                        NULL, NULL, &res);
+       if (res != NULL) {
+               talloc_steal(tmp_ctx, res);
+       }
+       if (ret < 0) goto failed;
+       if (ret > 1) goto failed;
+
        if (ret == 1) {
                maxVersion = ldb_msg_find_uint64(res[0], "maxVersion", 0);
        }
@@ -57,22 +67,27 @@ static uint64_t winsdb_allocate_version(struct wins_server *winssrv)
        msg->dn = dn;
 
 
-       ret = ldb_msg_add_empty(ldb, msg, "maxVersion", LDB_FLAG_MOD_REPLACE);
+       ret = ldb_msg_add_empty(msg, "objectClass", LDB_FLAG_MOD_REPLACE);
+       if (ret != 0) goto failed;
+       ret = ldb_msg_add_string(msg, "objectClass", "winsMaxVersion");
+       if (ret != 0) goto failed;
+       ret = ldb_msg_add_empty(msg, "maxVersion", LDB_FLAG_MOD_REPLACE);
        if (ret != 0) goto failed;
-       ret = ldb_msg_add_fmt(ldb, msg, "maxVersion", "%llu", maxVersion);
+       ret = ldb_msg_add_fmt(msg, "maxVersion", "%llu", maxVersion);
        if (ret != 0) goto failed;
 
        ret = ldb_modify(ldb, msg);
        if (ret != 0) ret = ldb_add(ldb, msg);
        if (ret != 0) goto failed;
 
-       talloc_free(tmp_ctx);
-       return maxVersion;
+       trans = ldb_transaction_commit(ldb);
+       if (trans != LDB_SUCCESS) goto failed;
 
        talloc_free(tmp_ctx);
        return maxVersion;
 
 failed:
+       if (trans == LDB_SUCCESS) ldb_transaction_cancel(ldb);
        talloc_free(tmp_ctx);
        return 0;
 }
@@ -172,177 +187,11 @@ static NTSTATUS winsdb_addr_decode(struct winsdb_record *rec, struct ldb_val *va
        if (!p) {
                /* support old entries, with only the address */
                addr->address           = talloc_steal(addr, val->data);
-               addr->wins_owner        = rec->wins_owner;
-               addr->expire_time       = rec->expire_time;
-               *_addr = addr;
-               return NT_STATUS_OK;
-       }
-
-       *p = '\0';p++;
-       addr->address = talloc_strdup(addr, address);
-       if (!addr->address) {
-               status = NT_STATUS_NO_MEMORY;
-               goto failed;
-       }
-
-       if (strncmp("winsOwner:", p, 10) != 0) {
-               status = NT_STATUS_INTERNAL_DB_CORRUPTION;
-               goto failed;
-       }
-       wins_owner = p + 10;
-       p = strchr(wins_owner, ';');
-       if (!p) {
-               status = NT_STATUS_INTERNAL_DB_CORRUPTION;
-               goto failed;
-       }
-
-       *p = '\0';p++;
-       addr->wins_owner = talloc_strdup(addr, wins_owner);
-       if (!addr->wins_owner) {
-               status = NT_STATUS_NO_MEMORY;
-               goto failed;
-       }
-
-       if (strncmp("expireTime:", p, 11) != 0) {
-               status = NT_STATUS_INTERNAL_DB_CORRUPTION;
-               goto failed;
-       }
-
-       expire_time = p + 11;
-       p = strchr(expire_time, ';');
-       if (!p) {
-               status = NT_STATUS_INTERNAL_DB_CORRUPTION;
-               goto failed;
-       }
-
-       *p = '\0';p++;
-       addr->expire_time = ldap_string_to_time(expire_time);
-
-       *_addr = addr;
-       return NT_STATUS_OK;
-failed:
-       talloc_free(addr);
-       return status;
-}
-
-/*
- encode the winsdb_addr("address") attribute like this:
- "172.31.1.1;winsOwner:172.31.9.202;expireTime:20050923032330.0Z"
-*/
-static int ldb_msg_add_winsdb_addr(struct ldb_context *ldb, struct ldb_message *msg, 
-                                  const char *attr_name, struct winsdb_addr *addr)
-{
-       struct ldb_val val;
-       const char *str;
-
-       dn = ldb_dn_string_compose(mem_ctx, NULL, "type=%02x", name->type);
-
-       addresses[len]->address = talloc_strdup(addresses[len], address);
-       if (!addresses[len]->address) {
-               talloc_free(addresses);
-               return NULL;
-       }
-
-       addresses[len]->wins_owner = talloc_strdup(addresses[len], wins_owner);
-       if (!addresses[len]->wins_owner) {
-               talloc_free(addresses);
-               return NULL;
-       }
-
-       addresses[len]->expire_time = expire_time;
-
-       addresses[len+1] = NULL;
-
-       return addresses;
-}
-
-void winsdb_addr_list_remove(struct winsdb_addr **addresses, const char *address)
-{
-       size_t i;
-
-       for (i=0; addresses[i]; i++) {
-               if (strcmp(addresses[i]->address, address) == 0) {
-                       break;
-               }
-       }
-       if (!addresses[i]) return;
-
-       for (; addresses[i]; i++) {
-               addresses[i] = addresses[i+1];
-       }
-
-       return;
-}
-
-struct winsdb_addr *winsdb_addr_list_check(struct winsdb_addr **addresses, const char *address)
-{
-       size_t i;
-
-       for (i=0; addresses[i]; i++) {
-               if (strcmp(addresses[i]->address, address) == 0) {
-                       return addresses[i];
-               }
-       }
-
-       return NULL;
-}
-
-size_t winsdb_addr_list_length(struct winsdb_addr **addresses)
-{
-       size_t i;
-       for (i=0; addresses[i]; i++);
-       return i;
-}
-
-const char **winsdb_addr_string_list(TALLOC_CTX *mem_ctx, struct winsdb_addr **addresses)
-{
-       size_t len = winsdb_addr_list_length(addresses);
-       const char **str_list;
-       size_t i;
-
-       str_list = talloc_array(mem_ctx, const char *, len + 1);
-       if (!str_list) return NULL;
-
-       for (i=0; i < len; i++) {
-               str_list[i] = talloc_strdup(str_list, addresses[i]->address);
-               if (!str_list[i]) {
-                       talloc_free(str_list);
-                       return NULL;
+               addr->wins_owner        = talloc_reference(addr, rec->wins_owner);
+               if (!addr->wins_owner) {
+                       status = NT_STATUS_NO_MEMORY;
+                       goto failed;
                }
-       }
-
-       str_list[len] = NULL;
-       return str_list;
-}
-
-/*
- decode the winsdb_addr("address") attribute:
- "172.31.1.1" or 
- "172.31.1.1;winsOwner:172.31.9.202;expireTime:20050923032330.0Z"
- are valid records
-*/
-static struct winsdb_addr *winsdb_addr_decode(struct winsdb_record *rec, TALLOC_CTX *mem_ctx, struct ldb_val *val)
-{
-       NTSTATUS status;
-       struct winsdb_addr *addr;
-       char *address;
-       char *wins_owner;
-       char *expire_time;
-       char *p;
-
-       addr = talloc(mem_ctx, struct winsdb_addr);
-       if (!addr) {
-               status = NT_STATUS_NO_MEMORY;
-               goto failed;
-       }
-
-       address = (char *)val->data;
-
-       p = strchr(address, ';');
-       if (!p) {
-               /* support old entries, with only the address */
-               addr->address           = talloc_steal(addr, val->data);
-               addr->wins_owner        = rec->wins_owner;
                addr->expire_time       = rec->expire_time;
                *_addr = addr;
                return NT_STATUS_OK;
@@ -386,7 +235,7 @@ static struct winsdb_addr *winsdb_addr_decode(struct winsdb_record *rec, TALLOC_
        }
 
        *p = '\0';p++;
-       addr->expire_time = ldap_string_to_time(expire_time);
+       addr->expire_time = ldb_string_to_time(expire_time);
 
        *_addr = addr;
        return NT_STATUS_OK;
@@ -399,7 +248,7 @@ failed:
  encode the winsdb_addr("address") attribute like this:
  "172.31.1.1;winsOwner:172.31.9.202;expireTime:20050923032330.0Z;"
 */
-static int ldb_msg_add_winsdb_addr(struct ldb_context *ldb, struct ldb_message *msg, 
+static int ldb_msg_add_winsdb_addr(struct ldb_message *msg, 
                                   const char *attr_name, struct winsdb_addr *addr)
 {
        struct ldb_val val;
@@ -407,13 +256,13 @@ static int ldb_msg_add_winsdb_addr(struct ldb_context *ldb, struct ldb_message *
 
        str = talloc_asprintf(msg, "%s;winsOwner:%s;expireTime:%s;",
                              addr->address, addr->wins_owner,
-                             ldap_timestring(msg, addr->expire_time));
+                             ldb_timestring(msg, addr->expire_time));
        if (!str) return -1;
 
        val.data = discard_const_p(uint8_t, str);
        val.length = strlen(str);
 
-       return ldb_msg_add_value(ldb, msg, attr_name, &val);
+       return ldb_msg_add_value(msg, attr_name, &val);
 }
 
 struct winsdb_addr **winsdb_addr_list_make(TALLOC_CTX *mem_ctx)
@@ -552,11 +401,11 @@ NTSTATUS winsdb_lookup(struct ldb_context *wins_db,
        if (!NT_STATUS_IS_OK(status)) goto failed;
 
        /* see if it has already expired */
-       if (rec->state == WINS_REC_ACTIVE &&
+       if (rec->state == WREPL_STATE_ACTIVE &&
            rec->expire_time <= time(NULL)) {
                DEBUG(5,("WINS: expiring name %s (expired at %s)\n", 
                         nbt_name_string(tmp_ctx, rec->name), timestring(tmp_ctx, rec->expire_time)));
-               rec->state = WINS_REC_RELEASED;
+               rec->state = WREPL_STATE_RELEASED;
        }
 
        talloc_steal(mem_ctx, rec);
@@ -587,69 +436,35 @@ NTSTATUS winsdb_record(struct ldb_message *msg, struct nbt_name *name, TALLOC_CT
                if (!NT_STATUS_IS_OK(status)) goto failed;
        }
 
-       /* parse it into a more convenient winsdb_record structure */
-       rec->name           = name;
-       rec->state          = ldb_msg_find_int(res[0], "active", WINS_REC_RELEASED);
-       rec->nb_flags       = ldb_msg_find_int(res[0], "nbFlags", 0);
-       rec->expire_time    = ldb_string_to_time(ldb_msg_find_string(res[0], "expires", NULL));
-       rec->registered_by  = ldb_msg_find_string(res[0], "registeredBy", NULL);
-       rec->version        = ldb_msg_find_uint64(res[0], "version", 0);
-       talloc_steal(rec, rec->wins_owner);
-       talloc_steal(rec, rec->registered_by);
-
-       if (!rec->wins_owner) rec->wins_owner = WINSDB_OWNER_LOCAL;
-
-       el = ldb_msg_find_element(msg, "address");
-       if (el == NULL) {
+       if (strlen(name->name) > 15) {
                status = NT_STATUS_INTERNAL_DB_CORRUPTION;
                goto failed;
        }
-
-       rec->addresses     = talloc_array(rec, struct winsdb_addr *, el->num_values+1);
-       if (rec->addresses == NULL) {
-               status = NT_STATUS_NO_MEMORY;
-               goto failed;
-       }
-
-       for (i=0;i<el->num_values;i++) {
-               status = winsdb_addr_decode(rec, &el->values[i], rec->addresses, &rec->addresses[i]);
-               if (!NT_STATUS_IS_OK(status)) goto failed;
-       }
-       rec->addresses[i] = NULL;
-
-       *_rec = rec;
-       return NT_STATUS_OK;
-failed:
-       if (NT_STATUS_EQUAL(NT_STATUS_INTERNAL_DB_CORRUPTION, status)) {
-               DEBUG(1,("winsdb_record: corrupted record: %s\n", ldb_dn_linearize(rec, msg->dn)));
-       }
-       talloc_free(rec);
-       return status;
-}
-
-       rec = talloc(mem_ctx, struct winsdb_record);
-       if (rec == NULL) {
-               status = NT_STATUS_NO_MEMORY;
+       if (name->scope && strlen(name->scope) > 238) {
+               status = NT_STATUS_INTERNAL_DB_CORRUPTION;
                goto failed;
        }
 
-       if (!name) {
-               status = winsdb_nbt_name(rec, msg->dn, &name);
-               if (!NT_STATUS_IS_OK(status)) goto failed;
-       }
-
        /* parse it into a more convenient winsdb_record structure */
-       rec->name           = name;
-       rec->state          = ldb_msg_find_int(msg, "state", WINS_REC_RELEASED);
-       rec->nb_flags       = ldb_msg_find_int(msg, "nbFlags", 0);
-       rec->wins_owner     = ldb_msg_find_string(msg, "winsOwner", NULL);
-       rec->expire_time    = ldap_string_to_time(ldb_msg_find_string(msg, "expireTime", NULL));
-       rec->registered_by  = ldb_msg_find_string(msg, "registeredBy", NULL);
-       rec->version        = ldb_msg_find_uint64(msg, "versionID", 0);
+       rec->name               = name;
+       rec->type               = ldb_msg_find_int(msg, "recordType", WREPL_TYPE_UNIQUE);
+       rec->state              = ldb_msg_find_int(msg, "recordState", WREPL_STATE_RELEASED);
+       rec->node               = ldb_msg_find_int(msg, "nodeType", WREPL_NODE_B);
+       rec->is_static          = ldb_msg_find_int(msg, "isStatic", 0);
+       rec->expire_time        = ldb_string_to_time(ldb_msg_find_string(msg, "expireTime", NULL));
+       rec->version            = ldb_msg_find_uint64(msg, "versionID", 0);
+       rec->wins_owner         = ldb_msg_find_string(msg, "winsOwner", NULL);
+       rec->registered_by      = ldb_msg_find_string(msg, "registeredBy", NULL);
        talloc_steal(rec, rec->wins_owner);
        talloc_steal(rec, rec->registered_by);
 
-       if (!rec->wins_owner) rec->wins_owner = WINSDB_OWNER_LOCAL;
+       if (!rec->wins_owner) {
+               rec->wins_owner = talloc_strdup(rec, WINSDB_OWNER_LOCAL);
+               if (rec->wins_owner == NULL) {
+                       status = NT_STATUS_NO_MEMORY;
+                       goto failed;
+               }
+       }
 
        el = ldb_msg_find_element(msg, "address");
        if (el == NULL) {
@@ -657,56 +472,11 @@ failed:
                goto failed;
        }
 
-       rec->addresses     = talloc_array(rec, struct winsdb_addr *, el->num_values+1);
-       if (rec->addresses == NULL) {
-               status = NT_STATUS_NO_MEMORY;
-               goto failed;
-       }
-
-       for (i=0;i<el->num_values;i++) {
-               status = winsdb_addr_decode(rec, &el->values[i], rec->addresses, &rec->addresses[i]);
-               if (!NT_STATUS_IS_OK(status)) goto failed;
-       }
-       rec->addresses[i] = NULL;
-
-       *_rec = rec;
-       return NT_STATUS_OK;
-failed:
-       if (NT_STATUS_EQUAL(NT_STATUS_INTERNAL_DB_CORRUPTION, status)) {
-               DEBUG(1,("winsdb_record: corrupted record: %s\n", ldb_dn_linearize(rec, msg->dn)));
-       }
-       talloc_free(rec);
-       return status;
-}
-
-       rec = talloc(mem_ctx, struct winsdb_record);
-       if (rec == NULL) {
-               status = NT_STATUS_NO_MEMORY;
-               goto failed;
-       }
-
-       if (!name) {
-               status = winsdb_nbt_name(rec, msg->dn, &name);
-               if (!NT_STATUS_IS_OK(status)) goto failed;
-       }
-
-       /* parse it into a more convenient winsdb_record structure */
-       rec->name           = name;
-       rec->state          = ldb_msg_find_int(msg, "state", WINS_REC_RELEASED);
-       rec->nb_flags       = ldb_msg_find_int(msg, "nbFlags", 0);
-       rec->wins_owner     = ldb_msg_find_string(msg, "winsOwner", NULL);
-       rec->expire_time    = ldap_string_to_time(ldb_msg_find_string(msg, "expireTime", NULL));
-       rec->registered_by  = ldb_msg_find_string(msg, "registeredBy", NULL);
-       rec->version        = ldb_msg_find_uint64(msg, "versionID", 0);
-       talloc_steal(rec, rec->wins_owner);
-       talloc_steal(rec, rec->registered_by);
-
-       if (!rec->wins_owner) rec->wins_owner = WINSDB_OWNER_LOCAL;
-
-       el = ldb_msg_find_element(msg, "address");
-       if (el == NULL) {
-               status = NT_STATUS_INTERNAL_DB_CORRUPTION;
-               goto failed;
+       if (rec->type == WREPL_TYPE_UNIQUE || rec->type == WREPL_TYPE_GROUP) {
+               if (el->num_values != 1) {
+                       status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+                       goto failed;
+               }
        }
 
        rec->addresses     = talloc_array(rec, struct winsdb_addr *, el->num_values+1);
@@ -853,6 +623,9 @@ uint8_t winsdb_delete(struct wins_server *winssrv, struct winsdb_record *rec)
        int trans;
        int ret;
 
+       trans = ldb_transaction_start(ldb);
+       if (trans != LDB_SUCCESS) goto failed;
+
        dn = winsdb_dn(tmp_ctx, rec->name);
        if (dn == NULL) goto failed;
 
index 2ac1884063ac1647f17d5f42df75ed331e0ff054..d93d50bdf7674f0066bd4ec18de82450fab6b888 100644 (file)
@@ -29,15 +29,6 @@ struct winsdb_addr {
        time_t expire_time;
 };
 
-#define WINSDB_OWNER_LOCAL     "0.0.0.0"
-#define WINSDB_GROUP_ADDRESS   "255.255.255.255"
-
-struct winsdb_addr {
-       const char *address;
-       const char *wins_owner;
-       time_t expire_time;
-};
-
 /*
   each record in the database contains the following information
 */
@@ -47,7 +38,6 @@ struct winsdb_record {
        enum wrepl_name_state state;
        enum wrepl_name_node node;
        BOOL is_static;
-       const char *wins_owner;
        time_t expire_time;
        uint64_t version;
        const char *wins_owner;
@@ -55,8 +45,6 @@ struct winsdb_record {
 
        /* only needed for debugging problems */
        const char *registered_by;
-       struct winsdb_addr **addresses;
-       uint64_t version;
 };
 
 struct wins_server {
index 0f6717f4a92e53951c25940e951926f81bcd9d4a..38540b87ad3df2bd18be2a29c7c74d5343261e65 100644 (file)
@@ -70,13 +70,22 @@ static uint8_t wins_register_new(struct nbt_name_socket *nbtsock,
        enum wrepl_name_node node;
        BOOL mhomed = ((packet->operation & NBT_OPCODE) == NBT_OPCODE_MULTI_HOME_REG);
 
-       rec.name          = name;
-       rec.nb_flags      = nb_flags;
-       rec.state         = WINS_REC_ACTIVE;
-       rec.wins_owner    = WINSDB_OWNER_LOCAL;
-       rec.expire_time   = time(NULL) + ttl;
-       rec.registered_by = src->addr;
-       rec.addresses     = winsdb_addr_list_make(packet);
+#define WREPL_NODE_NBT_FLAGS(nb_flags) \
+       ((nb_flags & NBT_NM_OWNER_TYPE)>>13)
+
+       type    = wrepl_type(nb_flags, name, mhomed);
+       node    = WREPL_NODE_NBT_FLAGS(nb_flags);
+
+       rec.name                = name;
+       rec.type                = type;
+       rec.state               = WREPL_STATE_ACTIVE;
+       rec.node                = node;
+       rec.is_static           = False;
+       rec.expire_time         = time(NULL) + ttl;
+       rec.version             = 0; /* will allocated later */
+       rec.wins_owner          = WINSDB_OWNER_LOCAL;
+       rec.registered_by       = src->addr;
+       rec.addresses           = winsdb_addr_list_make(packet);
        if (rec.addresses == NULL) return NBT_RCODE_SVR;
 
        rec.addresses     = winsdb_addr_list_add(rec.addresses,
@@ -148,7 +157,7 @@ static void nbtd_winsserver_register(struct nbt_name_socket *nbtsock,
        } else if (!NT_STATUS_IS_OK(status)) {
                rcode = NBT_RCODE_SVR;
                goto done;
-       } else if (rec->state != WINS_REC_ACTIVE) {
+       } else if (rec->state != WREPL_STATE_ACTIVE) {
                winsdb_delete(winssrv, rec);
                rcode = wins_register_new(nbtsock, packet, src);
                goto done;
@@ -164,14 +173,14 @@ static void nbtd_winsserver_register(struct nbt_name_socket *nbtsock,
 
        /* if its an active unique name, and the registration is for a group, then
           see if the unique name owner still wants the name */
-       if (!(rec->nb_flags & NBT_NM_GROUP) && (nb_flags & NBT_NM_GROUP)) {
+       if (!(rec->type == WREPL_TYPE_GROUP) && (nb_flags & NBT_NM_GROUP)) {
                wins_register_wack(nbtsock, packet, rec, src);
                return;
        }
 
        /* if the registration is for a group, then just update the expiry time 
           and we are done */
-       if (IS_GROUP_NAME(name, nb_flags)) {
+       if (nb_flags & NBT_NM_GROUP) {
                wins_update_ttl(nbtsock, packet, rec, src);
                goto done;
        }
@@ -217,14 +226,15 @@ static void nbtd_winsserver_query(struct nbt_name_socket *nbtsock,
        struct nbt_name *name = &packet->questions[0].name;
        struct winsdb_record *rec;
        const char **addresses;
+       uint16_t nb_flags = 0; /* TODO: ... */
 
        status = winsdb_lookup(winssrv->wins_db, name, packet, &rec);
-       if (!NT_STATUS_IS_OK(status) || rec->state != WINS_REC_ACTIVE) {
+       if (!NT_STATUS_IS_OK(status) || rec->state != WREPL_STATE_ACTIVE) {
                nbtd_negative_name_query_reply(nbtsock, packet, src);
                return;
        }
 
-       if (IS_GROUP_NAME(name, rec->nb_flags)) {
+       if (rec->type == WREPL_TYPE_GROUP) {
                addresses = talloc_array(packet, const char *, 2);
                if (addresses == NULL) {
                        nbtd_negative_name_query_reply(nbtsock, packet, src);
@@ -241,7 +251,7 @@ static void nbtd_winsserver_query(struct nbt_name_socket *nbtsock,
        }
 
        nbtd_name_query_reply(nbtsock, packet, src, name, 
-                             0, rec->nb_flags, addresses);
+                             0, nb_flags, addresses);
 }
 
 /*
@@ -260,8 +270,8 @@ static void nbtd_winsserver_release(struct nbt_name_socket *nbtsock,
 
        status = winsdb_lookup(winssrv->wins_db, name, packet, &rec);
        if (!NT_STATUS_IS_OK(status) || 
-           rec->state != WINS_REC_ACTIVE || 
-           IS_GROUP_NAME(name, rec->nb_flags)) {
+           rec->state != WREPL_STATE_ACTIVE || 
+           rec->type == WREPL_TYPE_GROUP) {
                goto done;
        }
 
index c4832e251a60f60791fe8168619c2401e0710a1b..8a4c0ed60c045f9ef0a634f6284a752030a7d750 100644 (file)
@@ -321,7 +321,6 @@ sub Element($$$)
        my $call_code = "offset = $dissectorname(tvb, offset, pinfo, tree, drep);";
 
        my $type = find_type($e->{TYPE});
-       $hf_used{$hf} = 1;
 
        if (not defined($type)) {
                # default settings
index f63ada51ae53c9b35e7c738c7cf1f384b42e8fa0..82cb62dd748588409c99d40dec0f4230a4233ef7 100644 (file)
@@ -262,8 +262,8 @@ static BOOL nbt_test_ntlogon(TALLOC_CTX *mem_ctx,
 
        dest.port = 0;
        dest.addr = address;
-       status = dgram_mailslot_ntlogon_send(dgmsock, &name, &dest, 
-                                            &myname, &logon);
+       status = dgram_mailslot_ntlogon_send(dgmsock, DGRAM_DIRECT_UNIQUE,
+                                            &name, &dest, &myname, &logon);
        if (!NT_STATUS_IS_OK(status)) {
                printf("Failed to send ntlogon request - %s\n", nt_errstr(status));
                goto failed;
index 18fdcad5e934483827a867ab387ac06cc8d06d84..8c1202ae94a27d29998bcf60bf19dd22a26124c5 100644 (file)
@@ -7,7 +7,9 @@ INIT_OBJ_FILES = \
                wrepl_server/wrepl_server.o \
                wrepl_server/wrepl_in_connection.o \
                wrepl_server/wrepl_in_call.o \
-               wrepl_server/wrepl_out_connection.o
+               wrepl_server/wrepl_out_connection.o \
+               wrepl_server/wrepl_out_helpers.o \
+               wrepl_server/wrepl_apply_records.o
 REQUIRED_SUBSYSTEMS = \
                LIBCLI_WREPL WINSDB
 # End SUBSYSTEM WREPL_SRV
index 4472a0fede29d872aa463481cb895380457bf6a1..7ccb52cc207b62fe691bf4fa5f0524efe90764df 100644 (file)
 #include "lib/messaging/irpc.h"
 #include "librpc/gen_ndr/ndr_winsrepl.h"
 #include "librpc/gen_ndr/ndr_nbt.h"
+#include "libcli/wrepl/winsrepl.h"
 #include "wrepl_server/wrepl_server.h"
+#include "wrepl_server/wrepl_out_helpers.h"
+#include "libcli/composite/composite.h"
 #include "nbt_server/wins/winsdb.h"
 #include "lib/ldb/include/ldb.h"
 
@@ -111,42 +114,12 @@ static NTSTATUS wreplsrv_in_table_query(struct wreplsrv_in_call *call)
        struct wreplsrv_service *service = call->wreplconn->service;
        struct wrepl_replication *repl_out = &call->rep_packet.message.replication;
        struct wrepl_table *table_out = &call->rep_packet.message.replication.info.table;
-       struct wreplsrv_owner *cur;
-       uint64_t local_max_version;
-       uint32_t i = 0;
+       const char *our_ip = call->wreplconn->our_ip;
 
        repl_out->command = WREPL_REPL_TABLE_REPLY;
 
-       table_out->partner_count        = 0;
-       table_out->partners             = NULL;
-       table_out->initiator            = WINSDB_OWNER_LOCAL;
-
-       local_max_version = wreplsrv_local_max_version(service);
-       if (local_max_version > 0) {
-               table_out->partner_count++;
-       }
-
-       for (cur = service->table; cur; cur = cur->next) {
-               table_out->partner_count++;
-       }
-
-       table_out->partners = talloc_array(call, struct wrepl_wins_owner, table_out->partner_count);
-       NT_STATUS_HAVE_NO_MEMORY(table_out->partners);
-
-       if (local_max_version > 0) {
-               table_out->partners[i].address          = call->wreplconn->our_ip;
-               table_out->partners[i].min_version      = 0;
-               table_out->partners[i].max_version      = local_max_version;
-               table_out->partners[i].type             = 1;
-               i++;
-       }
-
-       for (cur = service->table; cur; cur = cur->next) {
-               table_out->partners[i] = cur->owner;
-               i++;
-       }
-
-       return NT_STATUS_OK;
+       return wreplsrv_fill_wrepl_table(service, call, table_out,
+                                        our_ip, our_ip, True);
 }
 
 static int wreplsrv_in_sort_wins_name(struct wrepl_wins_name *n1,
@@ -157,42 +130,21 @@ static int wreplsrv_in_sort_wins_name(struct wrepl_wins_name *n1,
        return 0;
 }
 
-static NTSTATUS wreplsrv_record2wins_name(TALLOC_CTX *mem_ctx, struct wrepl_wins_name *name, struct winsdb_record *rec)
+static NTSTATUS wreplsrv_record2wins_name(TALLOC_CTX *mem_ctx,
+                                         const char *our_address,
+                                         struct wrepl_wins_name *name,
+                                         struct winsdb_record *rec)
 {
-       uint8_t *namebuf;
-       uint32_t namebuf_len;
-       uint32_t name_len;
-
-       name_len = strlen(rec->name->name);
-       if (name_len > 15) {
-               return NT_STATUS_INVALID_PARAMETER_MIX;
-       }
-
-       namebuf = (uint8_t *)talloc_asprintf(mem_ctx, "%-15s%c%s",
-                                           rec->name->name, 'X',
-                                           (rec->name->scope?rec->name->scope:""));
-       NT_STATUS_HAVE_NO_MEMORY(namebuf);
-       namebuf_len = strlen((char *)namebuf) + 1;
-
-       /*
-        * we need to set the type here, and use a place-holder in the talloc_asprintf()
-        * as the type can be 0x00, and then the namebuf_len = strlen(namebuf); would give wrong results
-        */
-       namebuf[15] = rec->name->type;
+       uint32_t num_ips, i;
+       struct wrepl_ip *ips;
 
-       /* oh wow, what a nasty bug in windows ... */
-       if (rec->name->type == 0x1b) {
-               namebuf[15] = namebuf[0];
-               namebuf[0] = 0x1b;
-       }
+       name->name              = rec->name;
+       talloc_steal(mem_ctx, rec->name);
 
-       name->name_len          = namebuf_len;
-       name->name              = namebuf;
        name->id                = rec->version;
        name->unknown           = WINSDB_GROUP_ADDRESS;
 
-       name->flags             = rec->nb_flags;
-       name->group_flag        = 0;
+       name->flags             = WREPL_NAME_FLAGS(rec->type, rec->state, rec->node, rec->is_static);
 
        switch (name->flags & 2) {
        case 0:
@@ -200,8 +152,24 @@ static NTSTATUS wreplsrv_record2wins_name(TALLOC_CTX *mem_ctx, struct wrepl_wins
                talloc_steal(mem_ctx, rec->addresses[0]->address);
                break;
        case 2:
-               name->addresses.addresses.num_ips       = 0;
-               name->addresses.addresses.ips           = NULL;
+               num_ips = winsdb_addr_list_length(rec->addresses);
+               ips     = talloc_array(mem_ctx, struct wrepl_ip, num_ips);
+               NT_STATUS_HAVE_NO_MEMORY(ips);
+
+               for (i = 0; i < num_ips; i++) {
+                       if (strcasecmp(WINSDB_OWNER_LOCAL, rec->addresses[i]->wins_owner) == 0) {
+                               ips[i].owner    = talloc_strdup(ips, our_address);
+                               NT_STATUS_HAVE_NO_MEMORY(ips[i].owner);
+                       } else {
+                               ips[i].owner    = rec->addresses[i]->wins_owner;
+                               talloc_steal(ips, rec->addresses[i]->wins_owner);
+                       }
+                       ips[i].ip       = rec->addresses[i]->address;
+                       talloc_steal(ips, rec->addresses[i]->address);
+               }
+
+               name->addresses.addresses.num_ips       = num_ips;
+               name->addresses.addresses.ips           = ips;
                break;
        }
 
@@ -251,7 +219,7 @@ static NTSTATUS wreplsrv_in_send_request(struct wreplsrv_in_call *call)
         * if the partner ask for nothing, or give invalid ranges,
         * return an empty list.
         */
-       if (owner_in->min_version >= owner_in->max_version) {
+       if (owner_in->min_version > owner_in->max_version) {
                return NT_STATUS_OK;
        }
 
@@ -259,19 +227,29 @@ static NTSTATUS wreplsrv_in_send_request(struct wreplsrv_in_call *call)
         * if the partner has already all records for nothing, or give invalid ranges,
         * return an empty list.
         */
-       if (owner_in->min_version >= owner->owner.max_version) {
+       if (owner_in->min_version > owner->owner.max_version) {
                return NT_STATUS_OK;
        }
 
-       filter = talloc_asprintf(call, "(&(winsOwner=%s)(objectClass=winsRecord)(state>=%u)(versionID>=%llu)(versionID<=%llu))",
-                                owner->owner.address, WINS_REC_ACTIVE, owner_in->min_version, owner_in->max_version);
+       filter = talloc_asprintf(call,
+                                "(&(winsOwner=%s)(objectClass=winsRecord)"
+                                "(|(recordState=%u)(recordState=%u))"
+                                "(versionID>=%llu)(versionID<=%llu))",
+                                owner->owner.address,
+                                WREPL_STATE_ACTIVE, WREPL_STATE_TOMBSTONE,
+                                owner_in->min_version, owner_in->max_version);
        NT_STATUS_HAVE_NO_MEMORY(filter);
        ret = ldb_search(service->wins_db, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &res);
        if (res != NULL) {
                talloc_steal(call, res);
        }
        if (ret < 0) return  NT_STATUS_INTERNAL_DB_CORRUPTION;
-       if (ret == 0) return NT_STATUS_OK;
+       if (ret == 0) {
+               DEBUG(2,("WINSREPL:reply [%u] records owner[%s] min[%llu] max[%llu] to partner[%s]\n",
+                       ret, owner_in->address, owner_in->min_version, owner_in->max_version,
+                       call->wreplconn->partner->address));
+               return NT_STATUS_OK;
+       }
 
        names = talloc_array(call, struct wrepl_wins_name, ret);
        NT_STATUS_HAVE_NO_MEMORY(names);
@@ -280,7 +258,7 @@ static NTSTATUS wreplsrv_in_send_request(struct wreplsrv_in_call *call)
                status = winsdb_record(res[i], NULL, call, &rec);
                NT_STATUS_NOT_OK_RETURN(status);
 
-               status = wreplsrv_record2wins_name(names, &names[i], rec);
+               status = wreplsrv_record2wins_name(names, call->wreplconn->our_ip, &names[i], rec);
                NT_STATUS_NOT_OK_RETURN(status);
                talloc_free(rec);
                talloc_free(res[i]);
@@ -289,12 +267,113 @@ static NTSTATUS wreplsrv_in_send_request(struct wreplsrv_in_call *call)
        /* sort the names before we send them */
        qsort(names, ret, sizeof(struct wrepl_wins_name), (comparison_fn_t)wreplsrv_in_sort_wins_name);
 
+       DEBUG(2,("WINSREPL:reply [%u] records owner[%s] min[%llu] max[%llu] to partner[%s]\n",
+               ret, owner_in->address, owner_in->min_version, owner_in->max_version,
+               call->wreplconn->partner->address));
+
        reply_out->num_names    = ret;
        reply_out->names        = names;
 
        return NT_STATUS_OK;
 }
 
+struct wreplsrv_in_update_state {
+       struct wreplsrv_in_connection *wrepl_in;
+       struct wreplsrv_out_connection *wrepl_out;
+       struct composite_context *creq;
+       struct wreplsrv_pull_cycle_io cycle_io;
+};
+
+static void wreplsrv_in_update_handler(struct composite_context *creq)
+{
+       struct wreplsrv_in_update_state *update_state = talloc_get_type(creq->async.private_data,
+                                                       struct wreplsrv_in_update_state);
+       NTSTATUS status;
+
+       status = wreplsrv_pull_cycle_recv(creq);
+
+       talloc_free(update_state->wrepl_out);
+
+       wreplsrv_terminate_in_connection(update_state->wrepl_in, nt_errstr(status));
+}
+
+static NTSTATUS wreplsrv_in_update(struct wreplsrv_in_call *call)
+{
+       struct wreplsrv_in_connection *wrepl_in = call->wreplconn;
+       struct wreplsrv_out_connection *wrepl_out;
+       struct wrepl_table *update_in = &call->req_packet.message.replication.info.table;
+       struct wreplsrv_in_update_state *update_state;
+
+       DEBUG(2,("WREPL_REPL_UPDATE: partner[%s] initiator[%s] num_owners[%u]\n",
+               call->wreplconn->partner->address,
+               update_in->initiator, update_in->partner_count));
+
+       /* 
+        * we need to flip the connection into a client connection
+        * and do a WREPL_REPL_SEND_REQUEST's on the that connection
+        * and then stop this connection
+        */
+       talloc_free(wrepl_in->conn->event.fde);
+       wrepl_in->conn->event.fde = NULL;
+
+       update_state = talloc(wrepl_in, struct wreplsrv_in_update_state);
+       NT_STATUS_HAVE_NO_MEMORY(update_state);
+
+       wrepl_out = talloc(update_state, struct wreplsrv_out_connection);
+       NT_STATUS_HAVE_NO_MEMORY(wrepl_out);
+       wrepl_out->service              = wrepl_in->service;
+       wrepl_out->partner              = wrepl_in->partner;
+       wrepl_out->assoc_ctx.our_ctx    = wrepl_in->assoc_ctx.our_ctx;
+       wrepl_out->assoc_ctx.peer_ctx   = wrepl_in->assoc_ctx.peer_ctx;
+       wrepl_out->sock                 = wrepl_socket_merge(wrepl_out,
+                                                            wrepl_in->conn->event.ctx,
+                                                            wrepl_in->conn->socket);
+       NT_STATUS_HAVE_NO_MEMORY(wrepl_out->sock);
+
+       update_state->wrepl_in                  = wrepl_in;
+       update_state->wrepl_out                 = wrepl_out;
+       update_state->cycle_io.in.partner       = wrepl_out->partner;
+       update_state->cycle_io.in.num_owners    = update_in->partner_count;
+       update_state->cycle_io.in.owners        = update_in->partners;
+       talloc_steal(update_state, update_in->partners);
+       update_state->cycle_io.in.wreplconn     = wrepl_out;
+       update_state->creq = wreplsrv_pull_cycle_send(update_state, &update_state->cycle_io);
+       if (!update_state->creq) {
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+
+       update_state->creq->async.fn            = wreplsrv_in_update_handler;
+       update_state->creq->async.private_data  = update_state;
+
+       return ERROR_INVALID_PARAMETER;
+}
+
+static NTSTATUS wreplsrv_in_update2(struct wreplsrv_in_call *call)
+{
+       return wreplsrv_in_update(call);
+}
+
+static NTSTATUS wreplsrv_in_inform(struct wreplsrv_in_call *call)
+{
+       struct wrepl_table *inform_in = &call->req_packet.message.replication.info.table;
+       NTSTATUS status;
+
+       DEBUG(2,("WREPL_REPL_INFORM: partner[%s] initiator[%s] num_owners[%u]\n",
+               call->wreplconn->partner->address,
+               inform_in->initiator, inform_in->partner_count));
+
+       status = wreplsrv_sched_inform_action(call->wreplconn->partner, inform_in);
+       NT_STATUS_NOT_OK_RETURN(status);
+
+       /* we don't reply to WREPL_REPL_INFORM messages */
+       return ERROR_INVALID_PARAMETER;
+}
+
+static NTSTATUS wreplsrv_in_inform2(struct wreplsrv_in_call *call)
+{
+       return wreplsrv_in_inform(call);
+}
+
 static NTSTATUS wreplsrv_in_replication(struct wreplsrv_in_call *call)
 {
        struct wrepl_replication *repl_in = &call->req_packet.message.replication;
@@ -318,6 +397,9 @@ static NTSTATUS wreplsrv_in_replication(struct wreplsrv_in_call *call)
 
        switch (repl_in->command) {
                case WREPL_REPL_TABLE_QUERY:
+                       if (!(call->wreplconn->partner->type & WINSREPL_PARTNER_PUSH)) {
+                               return wreplsrv_in_stop_assoc_ctx(call);
+                       }
                        status = wreplsrv_in_table_query(call);
                        break;
 
@@ -325,6 +407,9 @@ static NTSTATUS wreplsrv_in_replication(struct wreplsrv_in_call *call)
                        return ERROR_INVALID_PARAMETER;
 
                case WREPL_REPL_SEND_REQUEST:
+                       if (!(call->wreplconn->partner->type & WINSREPL_PARTNER_PUSH)) {
+                               return wreplsrv_in_stop_assoc_ctx(call);
+                       }
                        status = wreplsrv_in_send_request(call);
                        break;
 
@@ -332,16 +417,32 @@ static NTSTATUS wreplsrv_in_replication(struct wreplsrv_in_call *call)
                        return ERROR_INVALID_PARAMETER;
        
                case WREPL_REPL_UPDATE:
-                       return ERROR_INVALID_PARAMETER;
+                       if (!(call->wreplconn->partner->type & WINSREPL_PARTNER_PULL)) {
+                               return wreplsrv_in_stop_assoc_ctx(call);
+                       }
+                       status = wreplsrv_in_update(call);
+                       break;
 
-               case WREPL_REPL_5:
-                       return ERROR_INVALID_PARAMETER;
+               case WREPL_REPL_UPDATE2:
+                       if (!(call->wreplconn->partner->type & WINSREPL_PARTNER_PULL)) {
+                               return wreplsrv_in_stop_assoc_ctx(call);
+                       }
+                       status = wreplsrv_in_update2(call);
+                       break;
 
                case WREPL_REPL_INFORM:
-                       return ERROR_INVALID_PARAMETER;
+                       if (!(call->wreplconn->partner->type & WINSREPL_PARTNER_PULL)) {
+                               return wreplsrv_in_stop_assoc_ctx(call);
+                       }
+                       status = wreplsrv_in_inform(call);
+                       break;
 
-               case WREPL_REPL_9:
-                       return ERROR_INVALID_PARAMETER;
+               case WREPL_REPL_INFORM2:
+                       if (!(call->wreplconn->partner->type & WINSREPL_PARTNER_PULL)) {
+                               return wreplsrv_in_stop_assoc_ctx(call);
+                       }
+                       status = wreplsrv_in_inform2(call);
+                       break;
 
                default:
                        return ERROR_INVALID_PARAMETER;
@@ -406,7 +507,8 @@ NTSTATUS wreplsrv_in_call(struct wreplsrv_in_call *call)
        }
 
        if (NT_STATUS_IS_OK(status)) {
-               call->rep_packet.opcode         = WREPL_OPCODE_BITS;
+               /* let the backend to set some of the opcode bits, but always add the standards */
+               call->rep_packet.opcode         |= WREPL_OPCODE_BITS;
                call->rep_packet.assoc_ctx      = call->wreplconn->assoc_ctx.peer_ctx;
        }
 
index ed9c9998d7492e67a0da02620b8da8c9ad3d19ef..5ba36a50518ed5e42264cbb27782fa6c54317f43 100644 (file)
@@ -32,7 +32,7 @@
 #include "nbt_server/wins/winsdb.h"
 #include "ldb/include/ldb.h"
 
-static void wreplsrv_terminate_in_connection(struct wreplsrv_in_connection *wreplconn, const char *reason)
+void wreplsrv_terminate_in_connection(struct wreplsrv_in_connection *wreplconn, const char *reason)
 {
        stream_terminate_connection(wreplconn->conn, reason);
 }
@@ -266,6 +266,48 @@ static const struct stream_server_ops wreplsrv_stream_ops = {
        .send_handler           = wreplsrv_send,
 };
 
+/*
+  called when we get a new connection
+*/
+NTSTATUS wreplsrv_in_connection_merge(struct wreplsrv_partner *partner,
+                                     struct socket_context *sock,
+                                     struct wreplsrv_in_connection **_wrepl_in)
+{
+       struct wreplsrv_service *service = partner->service;
+       struct wreplsrv_in_connection *wrepl_in;
+       const struct model_ops *model_ops;
+       struct stream_connection *conn;
+       NTSTATUS status;
+
+       /* within the wrepl task we want to be a single process, so
+          ask for the single process model ops and pass these to the
+          stream_setup_socket() call. */
+       model_ops = process_model_byname("single");
+       if (!model_ops) {
+               DEBUG(0,("Can't find 'single' process model_ops"));
+               return NT_STATUS_INTERNAL_ERROR;
+       }
+
+       wrepl_in = talloc_zero(partner, struct wreplsrv_in_connection);
+       NT_STATUS_HAVE_NO_MEMORY(wrepl_in);
+
+       wrepl_in->service       = service;
+       wrepl_in->partner       = partner;
+       wrepl_in->our_ip        = socket_get_my_addr(sock, wrepl_in);
+       NT_STATUS_HAVE_NO_MEMORY(wrepl_in->our_ip);
+
+       status = stream_new_connection_merge(service->task->event_ctx, model_ops,
+                                            sock, &wreplsrv_stream_ops, service->task->msg_ctx,
+                                            wrepl_in, &conn);
+       NT_STATUS_NOT_OK_RETURN(status);
+
+       wrepl_in->conn          = conn;
+       talloc_steal(conn, wrepl_in);
+
+       *_wrepl_in = wrepl_in;
+       return NT_STATUS_OK;
+}
+
 /*
   startup the wrepl port 42 server sockets
 */
index 39406c7e2a709f03404a312062d32f2f572b0e28..0d5bfda185bb07e322cec5b410b4b65486f21ec7 100644 (file)
 #include "wrepl_server/wrepl_server.h"
 #include "nbt_server/wins/winsdb.h"
 #include "ldb/include/ldb.h"
+#include "libcli/composite/composite.h"
+#include "libcli/wrepl/winsrepl.h"
+#include "wrepl_server/wrepl_out_helpers.h"
+
+static void wreplsrv_pull_handler_te(struct event_context *ev, struct timed_event *te,
+                                    struct timeval t, void *ptr);
+
+static void wreplsrv_pull_handler_creq(struct composite_context *creq)
+{
+       struct wreplsrv_partner *partner = talloc_get_type(creq->async.private_data, struct wreplsrv_partner);
+       uint32_t interval;
+
+       partner->pull.last_status = wreplsrv_pull_cycle_recv(partner->pull.creq);
+       partner->pull.creq = NULL;
+       talloc_free(partner->pull.cycle_io);
+       partner->pull.cycle_io = NULL;
+
+       if (!NT_STATUS_IS_OK(partner->pull.last_status)) {
+               interval = partner->pull.error_count * partner->pull.retry_interval;
+               interval = MIN(interval, partner->pull.interval);
+               partner->pull.error_count++;
+
+               DEBUG(1,("wreplsrv_pull_cycle(%s): %s: next: %us\n",
+                        partner->address, nt_errstr(partner->pull.last_status),
+                        interval));
+       } else {
+               interval = partner->pull.interval;
+               partner->pull.error_count = 0;
+
+               DEBUG(2,("wreplsrv_pull_cycle(%s): %s: next: %us\n",
+                        partner->address, nt_errstr(partner->pull.last_status),
+                        interval));
+       }
+
+       partner->pull.te = event_add_timed(partner->service->task->event_ctx, partner,
+                                          timeval_current_ofs(interval, 0),
+                                          wreplsrv_pull_handler_te, partner);
+       if (!partner->pull.te) {
+               DEBUG(0,("wreplsrv_pull_handler_creq: event_add_timed() failed! no memory!\n"));
+       }
+}
+
+static void wreplsrv_pull_handler_te(struct event_context *ev, struct timed_event *te,
+                                    struct timeval t, void *ptr)
+{
+       struct wreplsrv_partner *partner = talloc_get_type(ptr, struct wreplsrv_partner);
+
+       partner->pull.te = NULL;
+
+       partner->pull.cycle_io = talloc(partner, struct wreplsrv_pull_cycle_io);
+       if (!partner->pull.cycle_io) {
+               goto requeue;
+       }
+
+       partner->pull.cycle_io->in.partner      = partner;
+       partner->pull.cycle_io->in.num_owners   = 0;
+       partner->pull.cycle_io->in.owners       = NULL;
+       partner->pull.cycle_io->in.wreplconn    = NULL;
+       partner->pull.creq = wreplsrv_pull_cycle_send(partner->pull.cycle_io, partner->pull.cycle_io);
+       if (!partner->pull.creq) {
+               DEBUG(1,("wreplsrv_pull_cycle_send(%s) failed\n",
+                        partner->address));
+               goto requeue;
+       }
+
+       partner->pull.creq->async.fn            = wreplsrv_pull_handler_creq;
+       partner->pull.creq->async.private_data  = partner;
+
+       return;
+requeue:
+       talloc_free(partner->pull.cycle_io);
+       partner->pull.cycle_io = NULL;
+       /* retry later */
+       partner->pull.te = event_add_timed(partner->service->task->event_ctx, partner,
+                                          timeval_add(&t, partner->pull.retry_interval, 0),
+                                          wreplsrv_pull_handler_te, partner);
+       if (!partner->pull.te) {
+               DEBUG(0,("wreplsrv_pull_handler_te: event_add_timed() failed! no memory!\n"));
+       }
+}
+
+NTSTATUS wreplsrv_sched_inform_action(struct wreplsrv_partner *partner, struct wrepl_table *inform_in)
+{
+       if (partner->pull.creq) {
+               /* there's already a pull in progress, so we're done */
+               return NT_STATUS_OK;
+       }
+
+       /* remove the scheduled pull */
+       talloc_free(partner->pull.te);
+       partner->pull.te = NULL;
+
+       partner->pull.cycle_io = talloc(partner, struct wreplsrv_pull_cycle_io);
+       if (!partner->pull.cycle_io) {
+               goto requeue;
+       }
+
+       partner->pull.cycle_io->in.partner      = partner;
+       partner->pull.cycle_io->in.num_owners   = inform_in->partner_count;
+       partner->pull.cycle_io->in.owners       = inform_in->partners;
+       talloc_steal(partner->pull.cycle_io, inform_in->partners);
+       partner->pull.cycle_io->in.wreplconn    = NULL;
+       partner->pull.creq = wreplsrv_pull_cycle_send(partner->pull.cycle_io, partner->pull.cycle_io);
+       if (!partner->pull.creq) {
+               DEBUG(1,("wreplsrv_pull_cycle_send(%s) failed\n",
+                        partner->address));
+               goto requeue;
+       }
+
+       partner->pull.creq->async.fn            = wreplsrv_pull_handler_creq;
+       partner->pull.creq->async.private_data  = partner;
+
+       return NT_STATUS_OK;
+requeue:
+       talloc_free(partner->pull.cycle_io);
+       partner->pull.cycle_io = NULL;
+       /* retry later */
+       partner->pull.te = event_add_timed(partner->service->task->event_ctx, partner,
+                                          timeval_current_ofs(partner->pull.retry_interval, 0),
+                                          wreplsrv_pull_handler_te, partner);
+       if (!partner->pull.te) {
+               DEBUG(0,("wreplsrv_pull_handler_te: event_add_timed() failed! no memory!\n"));
+       }
+
+       return NT_STATUS_OK;
+}
+
+static void wreplsrv_push_handler_te(struct event_context *ev, struct timed_event *te,
+                                    struct timeval t, void *ptr);
+
+static void wreplsrv_push_handler_creq(struct composite_context *creq)
+{
+       struct wreplsrv_partner *partner = talloc_get_type(creq->async.private_data, struct wreplsrv_partner);
+       uint32_t interval;
+
+       partner->push.last_status = wreplsrv_push_notify_recv(partner->push.creq);
+       partner->push.creq = NULL;
+       talloc_free(partner->push.notify_io);
+       partner->push.notify_io = NULL;
+
+       if (!NT_STATUS_IS_OK(partner->push.last_status)) {
+               interval = 15;
+
+               DEBUG(1,("wreplsrv_push_notify(%s): %s: next: %us\n",
+                        partner->address, nt_errstr(partner->push.last_status),
+                        interval));
+       } else {
+               interval = 100;
+
+               DEBUG(2,("wreplsrv_push_notify(%s): %s: next: %us\n",
+                        partner->address, nt_errstr(partner->push.last_status),
+                        interval));
+       }
+
+       partner->push.te = event_add_timed(partner->service->task->event_ctx, partner,
+                                          timeval_current_ofs(interval, 0),
+                                          wreplsrv_push_handler_te, partner);
+       if (!partner->push.te) {
+               DEBUG(0,("wreplsrv_push_handler_creq: event_add_timed() failed! no memory!\n"));
+       }
+}
+
+static void wreplsrv_push_handler_te(struct event_context *ev, struct timed_event *te,
+                                    struct timeval t, void *ptr)
+{
+       struct wreplsrv_partner *partner = talloc_get_type(ptr, struct wreplsrv_partner);
+
+       partner->push.te = NULL;
+
+       partner->push.notify_io = talloc(partner, struct wreplsrv_push_notify_io);
+       if (!partner->push.notify_io) {
+               goto requeue;
+       }
+
+       partner->push.notify_io->in.partner     = partner;
+       partner->push.notify_io->in.inform      = False;
+       partner->push.notify_io->in.propagate   = False;
+       partner->push.creq = wreplsrv_push_notify_send(partner->push.notify_io, partner->push.notify_io);
+       if (!partner->push.creq) {
+               DEBUG(1,("wreplsrv_push_notify_send(%s) failed\n",
+                        partner->address));
+               goto requeue;
+       }
+
+       partner->push.creq->async.fn            = wreplsrv_push_handler_creq;
+       partner->push.creq->async.private_data  = partner;
+
+       return;
+requeue:
+       talloc_free(partner->push.notify_io);
+       partner->push.notify_io = NULL;
+       /* retry later */
+       partner->push.te = event_add_timed(partner->service->task->event_ctx, partner,
+                                          timeval_add(&t, 5, 0),
+                                          wreplsrv_push_handler_te, partner);
+       if (!partner->push.te) {
+               DEBUG(0,("wreplsrv_push_handler_te: event_add_timed() failed! no memory!\n"));
+       }
+}
 
 NTSTATUS wreplsrv_setup_out_connections(struct wreplsrv_service *service)
 {
        struct wreplsrv_partner *cur;
 
        for (cur = service->partners; cur; cur = cur->next) {
-               if (!(cur->type & WINSREPL_PARTNER_PULL)) continue;
-
-               DEBUG(0,("TODO: pull from: %s\n", cur->address));
+               if (cur->type & WINSREPL_PARTNER_PULL) {
+                       cur->pull.te = event_add_timed(service->task->event_ctx, cur,
+                                                      timeval_zero(), wreplsrv_pull_handler_te, cur);
+                       NT_STATUS_HAVE_NO_MEMORY(cur->pull.te);
+               }
+               if (cur->type & WINSREPL_PARTNER_PUSH) {
+                       cur->push.te = event_add_timed(service->task->event_ctx, cur,
+                                                      timeval_zero(), wreplsrv_push_handler_te, cur);
+                       NT_STATUS_HAVE_NO_MEMORY(cur->push.te);
+               }
        }
 
        return NT_STATUS_OK;
index 97fa23cdf10fa1f6874c3eedaa5ab60e74943a02..b044ef829618f5210c546aae297331ac735c6a99 100644 (file)
@@ -80,14 +80,17 @@ static NTSTATUS wreplsrv_load_partners(struct wreplsrv_service *service)
        for (i=0; i < ret; i++) {
                struct wreplsrv_partner *partner;
 
-               partner = talloc(service, struct wreplsrv_partner);
+               partner = talloc_zero(service, struct wreplsrv_partner);
                if (partner == NULL) goto failed;
+               partner->service        = service;
 
                partner->address        = ldb_msg_find_string(res[i], "address", NULL);
                if (!partner->address) goto failed;
                partner->name           = ldb_msg_find_string(res[i], "name", partner->address);
                partner->type           = ldb_msg_find_int(res[i], "type", WINSREPL_PARTNER_BOTH);
                partner->pull.interval  = ldb_msg_find_int(res[i], "pullInterval", WINSREPL_DEFAULT_PULL_INTERVAL);
+               partner->pull.retry_interval = ldb_msg_find_int(res[i], "pullRetryInterval",
+                                                               WINSREPL_DEFAULT_PULL_RETRY_INTERVAL);
                partner->our_address    = ldb_msg_find_string(res[i], "ourAddress", NULL);
 
                talloc_steal(partner, partner->address);
@@ -104,6 +107,29 @@ failed:
        return NT_STATUS_FOOBAR;
 }
 
+BOOL wreplsrv_is_our_address(struct wreplsrv_service *service, const char *address)
+{
+       const char *our_address;
+
+       if (lp_interfaces() && lp_bind_interfaces_only()) {
+               int num_interfaces = iface_count();
+               int i;
+               for(i = 0; i < num_interfaces; i++) {
+                       our_address = iface_n_ip(i);
+                       if (strcasecmp(our_address, address) == 0) {
+                               return True;
+                       }
+               }
+       } else {
+               our_address = lp_socket_address();
+               if (strcasecmp(our_address, address) == 0) {
+                       return True;
+               }
+       }
+
+       return False;
+}
+
 uint64_t wreplsrv_local_max_version(struct wreplsrv_service *service)
 {
        int ret;
@@ -134,6 +160,49 @@ failed:
        return maxVersion;
 }
 
+NTSTATUS wreplsrv_fill_wrepl_table(struct wreplsrv_service *service,
+                                  TALLOC_CTX *mem_ctx,
+                                  struct wrepl_table *table_out,
+                                  const char *our_ip,
+                                  const char *initiator,
+                                  BOOL full_table)
+{
+       struct wreplsrv_owner *cur;
+       uint64_t local_max_version;
+       uint32_t i = 0;
+
+       table_out->partner_count        = 0;
+       table_out->partners             = NULL;
+       table_out->initiator            = initiator;
+
+       local_max_version = wreplsrv_local_max_version(service);
+       if (local_max_version > 0) {
+               table_out->partner_count++;
+       }
+
+       for (cur = service->table; full_table && cur; cur = cur->next) {
+               table_out->partner_count++;
+       }
+
+       table_out->partners = talloc_array(mem_ctx, struct wrepl_wins_owner, table_out->partner_count);
+       NT_STATUS_HAVE_NO_MEMORY(table_out->partners);
+
+       if (local_max_version > 0) {
+               table_out->partners[i].address          = our_ip;
+               table_out->partners[i].min_version      = 0;
+               table_out->partners[i].max_version      = local_max_version;
+               table_out->partners[i].type             = 1;
+               i++;
+       }
+
+       for (cur = service->table; full_table && cur; cur = cur->next) {
+               table_out->partners[i] = cur->owner;
+               i++;
+       }
+
+       return NT_STATUS_OK;
+}
+
 struct wreplsrv_owner *wreplsrv_find_owner(struct wreplsrv_owner *table, const char *wins_owner)
 {
        struct wreplsrv_owner *cur;
@@ -151,9 +220,9 @@ struct wreplsrv_owner *wreplsrv_find_owner(struct wreplsrv_owner *table, const c
  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
 */
-static NTSTATUS wreplsrv_add_table(struct wreplsrv_service *service,
-                                  TALLOC_CTX *mem_ctx, struct wreplsrv_owner **_table,
-                                  const char *wins_owner, uint64_t version)
+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;
index 278b15fbb7ceb7de97058b4a8b13014d08ca1290..63603c823dc21050a0830af8815158c3bf21d12c 100644 (file)
@@ -92,16 +92,38 @@ struct wreplsrv_in_connection {
   state of an outcoming wrepl connection
 */
 struct wreplsrv_out_connection {
+       /* our global service context */
+       struct wreplsrv_service *service;
+
+       /*
+        * the partner that connects us,
+        * can be NULL, when we got a connection
+        * from an unknown address
+        */
        struct wreplsrv_partner *partner;
+
+       /* keep track of the assoc_ctx's */
+       struct {
+               uint32_t our_ctx;
+               uint32_t peer_ctx;
+       } assoc_ctx;
+
+       /* 
+        * the client socket to the partner,
+        * NULL if not yet connected
+        */
+       struct wrepl_socket *sock;
 };
 
 enum winsrepl_partner_type {
+       WINSREPL_PARTNER_NONE = 0x0,
        WINSREPL_PARTNER_PULL = 0x1,
        WINSREPL_PARTNER_PUSH = 0x2,
        WINSREPL_PARTNER_BOTH = (WINSREPL_PARTNER_PULL | WINSREPL_PARTNER_PUSH)
 };
 
 #define WINSREPL_DEFAULT_PULL_INTERVAL (30*60)
+#define WINSREPL_DEFAULT_PULL_RETRY_INTERVAL (30)
 
 /*
  this represents one of our configured partners
@@ -109,6 +131,9 @@ enum winsrepl_partner_type {
 struct wreplsrv_partner {
        struct wreplsrv_partner *prev,*next;
 
+       /* our global service context */
+       struct wreplsrv_service *service;
+
        /* the netbios name of the partner, mostly just for debugging */
        const char *name;
 
@@ -129,12 +154,51 @@ struct wreplsrv_partner {
                /* the interval between 2 pull replications to the partner */
                uint32_t interval;
 
+               /* the retry_interval if a pull cycle failed to the partner */
+               uint32_t retry_interval;
+
+               /* the error count till the last success */
+               uint32_t error_count;
+
+               /* the status of the last pull cycle */
+               NTSTATUS last_status;
+
                /* this is a list of each wins_owner the partner knows about */
                struct wreplsrv_owner *table;
 
                /* the outgoing connection to the partner */
                struct wreplsrv_out_connection *wreplconn;
+
+               /* the current pending pull cycle request */
+               struct composite_context *creq;
+
+               /* the pull cycle io params */
+               struct wreplsrv_pull_cycle_io *cycle_io;
+
+               /* the current timed_event to the next pull cycle */
+               struct timed_event *te;
        } pull;
+
+       /* push specific options */
+       struct {
+               /* change count till push notification */
+               uint32_t change_count;
+
+               /* the status of the last push cycle */
+               NTSTATUS last_status;
+
+               /* the outgoing connection to the partner */
+               struct wreplsrv_out_connection *wreplconn;
+
+               /* the current push notification */
+               struct composite_context *creq;
+
+               /* the pull cycle io params */
+               struct wreplsrv_push_notify_io *notify_io;
+
+               /* the current timed_event to the next push notify */
+               struct timed_event *te;
+       } push;
 };
 
 struct wreplsrv_owner {