The branch, master has been updated
       via  4bba5fc samba-tool: dns: Update the copyright
       via  61d4d74 samba-tool: dns: Fix the output display of DNS records
       via  b45d6a6 samba-tool: dns: Add extra references for string objects as 
workaround
       via  a8a6b27 samba-tool: dns: Add support to add/update/delete MX and 
SRV records
       via  28b1282 samba-tool: dns: Convert dns data into a dns record for 
comparison
       via  4272a76 samba-tool: dns: Convert dns data in a string to DNS record
       via  1fc2fb5 samba-tool: dns: Add MXRecord type to add/update mx records
       via  169db33 dlz_bind9: Do not remove LDB record in subrdataset and 
delrdataset
      from  89586ed lib/tdb2: 2.0.0 ABI

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 4bba5fcecd1f7071aa0529527a11f0082f8d625f
Author: Amitay Isaacs <ami...@gmail.com>
Date:   Thu Feb 16 10:17:25 2012 +1100

    samba-tool: dns: Update the copyright
    
    Autobuild-User: Amitay Isaacs <ami...@samba.org>
    Autobuild-Date: Tue Feb 21 09:55:07 CET 2012 on sn-devel-104

commit 61d4d7414585149ff0b703c139201d74c7800cd1
Author: Amitay Isaacs <ami...@gmail.com>
Date:   Wed Feb 15 20:56:38 2012 +1100

    samba-tool: dns: Fix the output display of DNS records

commit b45d6a6d690b20e348336b9d5db678f3e574ad62
Author: Amitay Isaacs <ami...@gmail.com>
Date:   Wed Feb 15 20:45:48 2012 +1100

    samba-tool: dns: Add extra references for string objects as workaround
    
    This is a workaround for bug in pidl generated python bindings, where
    C object hold a pointer to python string without increasing reference
    count in python. So when the python string goes out of scope, the
    C pointer loses the value.

commit a8a6b27e06b97edb70f171cd881f0dd24c82b92e
Author: Amitay Isaacs <ami...@gmail.com>
Date:   Tue Feb 14 13:41:45 2012 +1100

    samba-tool: dns: Add support to add/update/delete MX and SRV records

commit 28b12827b67a758652e9cc86b059a9af44e548f6
Author: Amitay Isaacs <ami...@gmail.com>
Date:   Tue Feb 14 13:32:57 2012 +1100

    samba-tool: dns: Convert dns data into a dns record for comparison
    
    and compare two dns records directly. Refactor dns name comparision
    as dns_name_equal().

commit 4272a76075063a212c9a3b0454f69270799b3142
Author: Amitay Isaacs <ami...@gmail.com>
Date:   Tue Feb 14 13:19:36 2012 +1100

    samba-tool: dns: Convert dns data in a string to DNS record

commit 1fc2fb5de1862de36235c896d1c7c4000e3c0349
Author: Amitay Isaacs <ami...@gmail.com>
Date:   Tue Feb 14 13:00:35 2012 +1100

    samba-tool: dns: Add MXRecord type to add/update mx records

commit 169db333033b72b6f9ac1e7b23f0f2c151218c1f
Author: Amitay Isaacs <ami...@gmail.com>
Date:   Thu Feb 9 10:17:02 2012 +1100

    dlz_bind9: Do not remove LDB record in subrdataset and delrdataset
    
    This fixes the problem of large number of deleted records in DNS
    partitions due to frequent dynamic dns updates from windows
    clients. The typical pattern for dynamic update get converted
    into subrdataset() followed by addrdataset().  If there are no
    dnsRecord attributes left as a result of sub/delrdataset(),
    leave the LDB entry for dns name as is. The subsequent
    addrdataset() would add the dnsRecord attribute without
    re-creating the same entry.

-----------------------------------------------------------------------

Summary of changes:
 source4/dns_server/dlz_bind9.c               |   21 +--
 source4/scripting/python/samba/netcmd/dns.py |  219 +++++++++++++++++++-------
 2 files changed, 169 insertions(+), 71 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dns_server/dlz_bind9.c b/source4/dns_server/dlz_bind9.c
index 6f6b1da..7bb7a34 100644
--- a/source4/dns_server/dlz_bind9.c
+++ b/source4/dns_server/dlz_bind9.c
@@ -1614,14 +1614,11 @@ _PUBLIC_ isc_result_t dlz_subrdataset(const char *name, 
const char *rdatastr, vo
        }
 
        if (el->num_values == 0) {
-               /* delete the record */
-               ret = ldb_delete(state->samdb, dn);
-               b9_reset_session_info(state);
-       } else {
-               /* modify the record */
-               el->flags = LDB_FLAG_MOD_REPLACE;
-               ret = ldb_modify(state->samdb, res->msgs[0]);
+               ldb_msg_remove_element(res->msgs[0], el);
        }
+       el->flags = LDB_FLAG_MOD_REPLACE;
+       ret = ldb_modify(state->samdb, res->msgs[0]);
+
        b9_reset_session_info(state);
        if (ret != LDB_SUCCESS) {
                state->log(ISC_LOG_ERROR, "samba_dlz: failed to modify %s - %s",
@@ -1722,13 +1719,11 @@ _PUBLIC_ isc_result_t dlz_delrdataset(const char *name, 
const char *type, void *
        }
 
        if (el->num_values == 0) {
-               /* delete the record */
-               ret = ldb_delete(state->samdb, dn);
-       } else {
-               /* modify the record */
-               el->flags = LDB_FLAG_MOD_REPLACE;
-               ret = ldb_modify(state->samdb, res->msgs[0]);
+               ldb_msg_remove_element(res->msgs[0], el);
        }
+       el->flags = LDB_FLAG_MOD_REPLACE;
+       ret = ldb_modify(state->samdb, res->msgs[0]);
+
        b9_reset_session_info(state);
        if (ret != LDB_SUCCESS) {
                state->log(ISC_LOG_ERROR, "samba_dlz: failed to delete type %s 
in %s - %s",
diff --git a/source4/scripting/python/samba/netcmd/dns.py 
b/source4/scripting/python/samba/netcmd/dns.py
index 6d07db4..b84f29b 100644
--- a/source4/scripting/python/samba/netcmd/dns.py
+++ b/source4/scripting/python/samba/netcmd/dns.py
@@ -2,7 +2,7 @@
 #
 # DNS management tool
 #
-# Copyright (C) Amitay Isaacs 2011
+# Copyright (C) Amitay Isaacs 2011-2012
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -345,9 +345,10 @@ def print_dns_record(outf, rec):
                     rec.data.NamePrimaryServer.str,
                     rec.data.ZoneAdministratorEmail.str)
     elif rec.wType == dnsp.DNS_TYPE_MX:
-        mesg = 'MX: %s' % (rec.data.str)
+        mesg = 'MX: %s (%d)' % (rec.data.nameExchange.str, 
rec.data.wPreference)
     elif rec.wType == dnsp.DNS_TYPE_SRV:
-        mesg = 'SRV: %s (%d)' % (rec.data.nameTarget.str, rec.data.wPort)
+        mesg = 'SRV: %s (%d, %d, %d)' % (rec.data.nameTarget.str, 
rec.data.wPort,
+                                         rec.data.wPriority, rec.data.wWeight)
     outf.write('    %s (flags=%x, serial=%d, ttl=%d)\n' % (
                 mesg, rec.dwFlags, rec.dwSerial, rec.dwTtlSeconds))
 
@@ -421,6 +422,26 @@ class NSRecord(dnsserver.DNS_RPC_RECORD):
         ns.len = len(dns_server)
         self.data = ns
 
+#
+# FIXME: In MXRecord, SOARecord, SRVRecord keep a reference to strings
+#        to overcome the bug in pidl generated python bindings.
+#
+
+class MXRecord(dnsserver.DNS_RPC_RECORD):
+    def __init__(self, mail_server, preference, serial=1, ttl=900,
+                 rank=dnsp.DNS_RANK_ZONE, node_flag=0):
+        super(MXRecord, self).__init__()
+        self.wType = dnsp.DNS_TYPE_MX
+        self.dwFlags = rank | node_flag
+        self.dwSerial = serial
+        self.dwTtlSeconds = ttl
+        mx = dnsserver.DNS_RPC_RECORD_NAME_PREFERENCE()
+        mx.wPreference = preference
+        self._mail_server = mail_server
+        mx.nameExchange.str = self._mail_server
+        mx.nameExchange.len = len(self._mail_server)
+        self.data = mx
+
 class SOARecord(dnsserver.DNS_RPC_RECORD):
     def __init__(self, mname, rname, serial=1, refresh=900, retry=600,
                  expire=86400, minimum=3600, ttl=3600, rank=dnsp.DNS_RANK_ZONE,
@@ -435,10 +456,12 @@ class SOARecord(dnsserver.DNS_RPC_RECORD):
         soa.dwRefresh = refresh
         soa.dwRetry = retry
         soa.dwExpire = expire
-        soa.NamePrimaryServer.str = mname
-        soa.NamePrimaryServer.len = len(mname)
-        soa.ZoneAdministratorEmail.str = rname
-        soa.ZoneAdministratorEmail.len = len(rname)
+        self._mname = mname
+        soa.NamePrimaryServer.str = self._mname
+        soa.NamePrimaryServer.len = len(self._mname)
+        self._rname = rname
+        soa.ZoneAdministratorEmail.str = self._rname
+        soa.ZoneAdministratorEmail.len = len(self._rname)
         self.data = soa
 
 class SRVRecord(dnsserver.DNS_RPC_RECORD):
@@ -453,12 +476,68 @@ class SRVRecord(dnsserver.DNS_RPC_RECORD):
         srv.wPriority = priority
         srv.wWeight = weight
         srv.wPort = port
-        srv.nameTarget.str = target
-        srv.nameTarget.len = len(target)
+        self._target = target
+        srv.nameTarget.str = self._target
+        srv.nameTarget.len = len(self._target)
         self.data = srv
 
+
+# Convert data into a dns record
+def data_to_dns_record(record_type, data):
+    if record_type == dnsp.DNS_TYPE_A:
+        rec = ARecord(data)
+    elif record_type == dnsp.DNS_TYPE_AAAA:
+        rec = AAAARecord(data)
+    elif record_type == dnsp.DNS_TYPE_PTR:
+        rec = PTRRecord(data)
+    elif record_type == dnsp.DNS_TYPE_CNAME:
+        rec = CNameRecord(data)
+    elif record_type == dnsp.DNS_TYPE_NS:
+        rec = NSRecord(data)
+    elif record_type == dnsp.DNS_TYPE_MX:
+        tmp = data.split(' ')
+        if len(tmp) != 2:
+            raise CommandError('Data requires 2 elements - mail_server, 
preference')
+        mail_server = tmp[0]
+        preference = int(tmp[1])
+        rec = MXRecord(mail_server, preference)
+    elif record_type == dnsp.DNS_TYPE_SRV:
+        tmp = data.split(' ')
+        if len(tmp) != 4:
+            raise CommandError('Data requires 4 elements - server, port, 
priority, weight')
+        server = tmp[0]
+        port = int(tmp[1])
+        priority = int(tmp[2])
+        weight = int(tmp[3])
+        rec = SRVRecord(server, port, priority=priority, weight=weight)
+    elif record_type == dnsp.DNS_TYPE_SOA:
+        tmp = data.split(' ')
+        if len(tmp) != 7:
+            raise CommandError('Data requires 7 elements - nameserver, email, 
serial, '
+                               'refresh, retry, expire, minimumttl')
+        nameserver = tmp[0]
+        email = tmp[1]
+        serial = int(tmp[2])
+        refresh = int(tmp[3])
+        retry = int(tmp[4])
+        expire = int(tmp[5])
+        minimum = int(tmp[6])
+        rec = SOARecord(nameserver, email, serial=serial, refresh=refresh,
+                        retry=retry, expire=expire, minimum=minimum)
+    else:
+        raise CommandError('Unsupported record type')
+    return rec
+
+
+# Match dns name (of type DNS_RPC_NAME)
+def dns_name_equal(n1, n2):
+    return n1.str.rstrip('.').lower() == n2.str.rstrip('.').lower()
+
+
 # Match a dns record with specified data
 def dns_record_match(dns_conn, server, zone, name, record_type, data):
+    urec = data_to_dns_record(record_type, data)
+
     select_flags = dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
 
     try:
@@ -485,19 +564,40 @@ def dns_record_match(dns_conn, server, zone, name, 
record_type, data):
 
         found = False
         if record_type == dnsp.DNS_TYPE_A:
-            if rec.data == data:
+            if rec.data == urec.data:
                 found = True
         elif record_type == dnsp.DNS_TYPE_AAAA:
-            if rec.data == data:
+            if rec.data == urec.data:
                 found = True
         elif record_type == dnsp.DNS_TYPE_PTR:
-            if rec.data.str.rstrip('.').lower() == data.rstrip('.').lower():
+            if dns_name_equal(rec.data, urec.data):
                 found = True
         elif record_type == dnsp.DNS_TYPE_CNAME:
-            if rec.data.str.rstrip('.').lower() == data.rstrip('.').lower():
+            if dns_name_equal(rec.data, urec.data):
                 found = True
         elif record_type == dnsp.DNS_TYPE_NS:
-            if rec.data.str.rstrip('.').lower() == data.rstrip('.').lower():
+            if dns_name_equal(rec.data, urec.data):
+                found = True
+        elif record_type == dnsp.DNS_TYPE_MX:
+            if dns_name_equal(rec.data.nameExchange, urec.data.nameExchange) 
and \
+               rec.data.wPreference == urec.data.wPreference:
+                found = True
+        elif record_type == dnsp.DNS_TYPE_SRV:
+            if rec.data.wPriority == urec.data.wPriority and \
+               rec.data.wWeight == urec.data.wWeight and \
+               rec.data.wPort == urec.data.wPort and \
+               dns_name_equal(rec.data.nameTarget, urec.data.nameTarget):
+                found = True
+        elif record_type == dnsp.DNS_TYPE_SOA:
+            if rec.data.dwSerialNo == urec.data.dwSerialNo and \
+               rec.data.dwRefresh == urec.data.dwRefresh and \
+               rec.data.dwRetry == urec.data.dwRetry and \
+               rec.data.dwExpire == urec.data.dwExpire and \
+               rec.data.dwMinimumTtl == urec.data.dwMinimumTtl and \
+               dns_name_equal(rec.data.NamePrimaryServer,
+                              urec.data.NamePrimaryServer) and \
+               dns_name_equal(rec.data.ZoneAdministratorEmail,
+                              urec.data.ZoneAdministratorEmail):
                 found = True
         if found:
             rec_match = rec
@@ -862,9 +962,19 @@ class cmd_roothints(Command):
 
 
 class cmd_add_record(Command):
-    """Add a DNS record"""
+    """Add a DNS record
+
+       For each type data contents are as follows:
+         A      ipv4_address_string
+         AAAA   ipv6_address_string
+         PTR    fqdn_string
+         CNAME  fqdn_string
+         NS     fqdn_string
+         MX     "fqdn_string preference"
+         SRV    "fqdn_string port priority weight"
+    """
 
-    synopsis = '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS> <data>'
+    synopsis = '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SRV> 
<data>'
 
     takes_args = [ 'server', 'zone', 'name', 'rtype', 'data' ]
 
@@ -876,21 +986,12 @@ class cmd_add_record(Command):
 
     def run(self, server, zone, name, rtype, data, sambaopts=None, 
credopts=None, versionopts=None):
 
-        record_type = dns_type_flag(rtype)
-
-        if record_type == dnsp.DNS_TYPE_A:
-            rec = ARecord(data)
-        elif record_type == dnsp.DNS_TYPE_AAAA:
-            rec = AAAARecord(data)
-        elif record_type == dnsp.DNS_TYPE_PTR:
-            rec = PTRRecord(data)
-        elif record_type == dnsp.DNS_TYPE_CNAME:
-            rec = CNameRecord(data)
-        elif record_type == dnsp.DNS_TYPE_NS:
-            rec = NSRecord(data)
-        else:
+        if rtype.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SRV'):
             raise CommandError('Adding record of type %s is not supported' % 
rtype)
 
+        record_type = dns_type_flag(rtype)
+        rec = data_to_dns_record(record_type, data)
+
         self.lp = sambaopts.get_loadparm()
         self.creds = credopts.get_credentials(self.lp)
         dns_conn = dns_connect(server, self.lp, self.creds)
@@ -913,9 +1014,19 @@ class cmd_add_record(Command):
 
 
 class cmd_update_record(Command):
-    """Update a DNS record"""
+    """Update a DNS record
 
-    synopsis = '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS> <olddata> 
<newdata>'
+       For each type data contents are as follows:
+         A      ipv4_address_string
+         AAAA   ipv6_address_string
+         PTR    fqdn_string
+         CNAME  fqdn_string
+         NS     fqdn_string
+         MX     "fqdn_string preference"
+         SRV    "fqdn_string port priority weight"
+    """
+
+    synopsis = '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SRV> 
<olddata> <newdata>'
 
     takes_args = [ 'server', 'zone', 'name', 'rtype', 'olddata', 'newdata' ]
 
@@ -928,20 +1039,12 @@ class cmd_update_record(Command):
     def run(self, server, zone, name, rtype, olddata, newdata,
                 sambaopts=None, credopts=None, versionopts=None):
 
-        record_type = dns_type_flag(rtype)
-        if record_type == dnsp.DNS_TYPE_A:
-            rec = ARecord(newdata)
-        elif record_type == dnsp.DNS_TYPE_AAAA:
-            rec = AAAARecord(newdata)
-        elif record_type == dnsp.DNS_TYPE_PTR:
-            rec = PTRRecord(newdata)
-        elif record_type == dnsp.DNS_TYPE_CNAME:
-            rec = CNameRecord(newdata)
-        elif record_type == dnsp.DNS_TYPE_NS:
-            rec = NSRecord(newdata)
-        else:
+        if rtype.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SRV'):
             raise CommandError('Updating record of type %s is not supported' % 
rtype)
 
+        record_type = dns_type_flag(rtype)
+        rec = data_to_dns_record(record_type, newdata)
+
         self.lp = sambaopts.get_loadparm()
         self.creds = credopts.get_credentials(self.lp)
         dns_conn = dns_connect(server, self.lp, self.creds)
@@ -973,9 +1076,19 @@ class cmd_update_record(Command):
 
 
 class cmd_delete_record(Command):
-    """Delete a DNS record"""
+    """Delete a DNS record
+
+       For each type data contents are as follows:
+         A      ipv4_address_string
+         AAAA   ipv6_address_string
+         PTR    fqdn_string
+         CNAME  fqdn_string
+         NS     fqdn_string
+         MX     "fqdn_string preference"
+         SRV    "fqdn_string port priority weight"
+    """
 
-    synopsis = '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS> <data>'
+    synopsis = '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SRV> 
<data>'
 
     takes_args = [ 'server', 'zone', 'name', 'rtype', 'data' ]
 
@@ -987,21 +1100,11 @@ class cmd_delete_record(Command):
 
     def run(self, server, zone, name, rtype, data, sambaopts=None, 
credopts=None, versionopts=None):
 
-        record_type = dns_type_flag(rtype)
-
-        if record_type == dnsp.DNS_TYPE_A:
-            rec = ARecord(data)
-        elif record_type == dnsp.DNS_TYPE_AAAA:
-            rec = AAAARecord(data)
-        elif record_type == dnsp.DNS_TYPE_PTR:
-            rec = PTRRecord(data)
-        elif record_type == dnsp.DNS_TYPE_CNAME:
-            rec = CNameRecord(data)
-        elif record_type == dnsp.DNS_TYPE_NS:
-            rec = NSRecord(data)
-        else:
+        if rtype.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SRV'):
             raise CommandError('Deleting record of type %s is not supported' % 
rtype)
 
+        record_type = dns_type_flag(rtype)
+
         self.lp = sambaopts.get_loadparm()
         self.creds = credopts.get_credentials(self.lp)
         dns_conn = dns_connect(server, self.lp, self.creds)


-- 
Samba Shared Repository

Reply via email to