How to create an A and Ptr records using DNSClient

Mar 31, 2012 at 4:37 AM

Alex,

I was wondering if you can provide a working example of code that I can use to create an A and Ptr records using Dynamic Update method.

I have the following code that I am using however I get a FormatError return code from server and I am not exactly sure what I am doing wrong.

var client = new DnsClient(IPAddress.Parse("192.168.1.2"), 0);
var updateMessage = new DnsUpdateMessage();
updateMessage.ZoneName = "somezone.com";
var aRecord = new ARecord("testing.somezone.com", 86400, IPAddress.Parse("10.10.10.1"));
var addRecord = new AddRecordUpdate(aRecord);
updateMessage.Updates.Add(addRecord);
var result = client.SendUpdate(updateMessage); 

After checking result.ResultCode I can clearly see that its coming back with FormatError.

Any help is greatly appreciated.

Coordinator
Mar 31, 2012 at 10:37 AM

Hi,

your sample is working without any problem on my site using Bind as server.

What software is running on your server and how is the zone configured, that you are updating? Are you sending the update directly to the zone master?

Mar 31, 2012 at 4:40 PM

I am using Microsoft DNS server that comes with the Active Directory.
I have it configured to accept Nonsecure and Secure Dynamic Updates.
I have one zone setup on the server which is configured to be the primary zone.
Let me know if I am missing something. 

Coordinator
Apr 2, 2012 at 10:29 AM

Are you sending the query direct to the primary dns server or are you sending it to any forwarding dns server (like a router)?

Aug 13, 2013 at 12:30 AM
hi,
I get the same problem with Windows 2008 R2 DNS

what I find out is that the the library is calling sendupdate,
a call is made to PrepareMessage(message, out messageLength, out messageData, out tsigKeySelector, out tsigOriginalMac);
and that this function return a messagelength <> size of messagedata

for exemple messagedata is a 89 byte array while messagelength return value is 63
is it a source of problem ?

nicolas
Apr 21, 2014 at 6:28 PM
Edited Apr 21, 2014 at 6:28 PM
nis75: I don't think that's necessarily a problem. It could just be that the buffer size is slightly larger than the actual contents of the buffer.

I have the same problem when sending update messages to a Windows DNS, and the issue is that the client sends a class of ANY for the zone section. I was able to do an update using the nsupdate tool (from BIND) and noticed that it specifies the class as IN. So it seems that the Windows DNS requires the zone section to exactly match the zone you are trying to update. I checked the relevant RFC's (2136 and 1035) and the specification seems to be ambiguous on what the correct behavior is. In any case, a simple option to specify the zone class (possibly using ANY as the default value) would be a good enough change IMO.

/Christian
May 15, 2014 at 3:14 PM
Edited May 15, 2014 at 3:25 PM
I had the same problem and I was able to solve it, as Seapalm suggested, by adding a new Property on the DNSUpdateMessage Class.
The code snippet is as follows:


 public RecordType ZoneType
        {
            get { return Questions.Count > 0 ? Questions[0].RecordType : RecordType.Null; }
            set
            {
                if (String.IsNullOrEmpty(this.ZoneName))
                    throw new ArgumentException("Zone name must be provided", "message");
                Questions[0].RecordType = value;
            }
        }
And a sample implementation for a ptr record for MS DNS Server would be :
            String DNSerrver ="192.168.1.1";
            String ClientIP = "192.168.1.25";
            String ClientName = "Hostname";
            Int DnsQueryTimeout=1000;
            DnsClient c = new DnsClient(System.Net.IPAddress.Parse(DnsServer), DnsQueryTimeout);
            System.Net.IPAddress myip = System.Net.IPAddress.Parse(ClientIP);
            byte[] IPbytes = myip.GetAddressBytes();
            StringBuilder sb = new StringBuilder();
            //Reverse the order to construct the ptr record
            for (int i = IPbytes.Length - 1; i >= 0; i--)
            {
                sb.Append(((int)IPbytes[i]).ToString());
                sb.Append(".");

            }
            sb.Append("in-addr.arpa");
            string dnsptrrecord = sb.ToString();
            DnsMessage existingrecords = c.Resolve(dnsptrrecord, RecordType.Ptr);
            DnsUpdateMessage msg = new DnsUpdateMessage();
            msg.ZoneName = "1.168.192.in-addr.arpa";
            msg.ZoneType = RecordType.Soa; //This is where you change the zone type

            foreach (DnsRecordBase b in existingrecords.AnswerRecords)
            {
                msg.Updates.Add(new DeleteRecordUpdate(b));
            }


            msg.Updates.Add(new AddRecordUpdate(new PtrRecord(dnsptrrecord, TTL, ClientName)));
            DnsUpdateMessage dnsresult = c.SendUpdate(msg);
            if (dnsresult.ReturnCode != ReturnCode.NoError)
                throw new Exception("DNS Update Failed with: " + dnsresult.ReturnCode + " for " +dnsptrrecord + " " +ClientName);
Hope it helps
Makis
May 20, 2014 at 8:06 AM
Edited May 20, 2014 at 10:37 AM
I had the same problem (FormatError) using above code against a Win2003 DNS server (without security).
Modig's code didn't fix it for me but pointed me in the right direction. As seapalm pointed out it is about the zone class, not the zone type (as stated by Modig).
RFC 2136 states in section 2.3:
The ZNAME is the zone name, the ZTYPE must be SOA, and the ZCLASS is the zone's class.
I added the following property to the DnsUpdateMessage class:
    public RecordClass ZoneClass
    {
      get { return Questions.Count > 0 ? Questions[0].RecordClass : RecordClass.Any; }
      set
      {
        if (String.IsNullOrEmpty(this.ZoneName))
          throw new ArgumentException("Zone name must be provided", "message");
        this.Questions[0].RecordClass = value;
      }
    }
In the calling code I set: updateMessage.ZoneClass = RecordClass.INet;. Now it works.
I wonder if it is possible to automatically set the correct zone class automatically or if INet is a better default. Does anybody know if INet also works on a BIND server?