public DNSRecord(Domain name, AddressClass address_class, UInt32 ttl, IDNSResource resource) { Name = name; AddressClass = address_class; TimeToLive = ttl; Resource = resource; }
public bool Equals(IDNSResource other) { if (!(other is AAAAResource)) { return(false); } var other_resource = (AAAAResource)other; return (this.Address.Equals(other_resource.Address) ); }
public bool Equals(IDNSResource other) { if (!(other is PTRResource)) { return(false); } var other_resource = (PTRResource)other; return (this.Pointer == other_resource.Pointer ); }
public bool Equals(IDNSResource other) { if (!(other is CNAMEResource)) { return(false); } var other_resource = (CNAMEResource)other; return (this.Alias == other_resource.Alias ); }
public bool Equals(IDNSResource other) { if (!(other is NSResource)) { return(false); } var other_resource = (NSResource)other; return (this.Nameserver == other_resource.Nameserver ); }
public bool Equals(IDNSResource other) { if (!(other is MXResource)) { return(false); } var other_resource = (MXResource)other; return (this.Preference == other_resource.Preference && this.Mailserver == other_resource.Mailserver ); }
/** * Decodes the raw bytes of a DNS resource record into an * object. */ public static DNSRecord Unserialize(DNSInputStream stream) { var name = stream.ReadDomain(); var record_type = (ResourceRecordType)stream.ReadUInt16(); var class_type = (AddressClass)stream.ReadUInt16(); var ttl = stream.ReadUInt32(); var record_size = stream.ReadUInt16(); IDNSResource resource = null; switch (record_type.Normalize()) { case ResourceRecordType.HOST_ADDRESS: resource = AResource.Unserialize(stream, record_size); break; case ResourceRecordType.NAME_SERVER: resource = NSResource.Unserialize(stream, record_size); break; case ResourceRecordType.START_OF_AUTHORITY: resource = SOAResource.Unserialize(stream, record_size); break; case ResourceRecordType.CANONICAL_NAME: resource = CNAMEResource.Unserialize(stream, record_size); break; case ResourceRecordType.MAIL_EXCHANGE: resource = MXResource.Unserialize(stream, record_size); break; case ResourceRecordType.POINTER: resource = PTRResource.Unserialize(stream, record_size); break; case ResourceRecordType.HOST_6ADDRESS: resource = AAAAResource.Unserialize(stream, record_size); break; case ResourceRecordType.UNSUPPORTED: // Advance the byte counter - even if we can't parse it, // we have to properly ignore it stream.ReadBytes(record_size); resource = null; break; } return(new DNSRecord(name, class_type.Normalize(), ttl, resource)); }
public bool Equals(IDNSResource other) { if (!(other is SOAResource)) { return(false); } var other_resource = (SOAResource)other; return (this.PrimaryNameServer == other_resource.PrimaryNameServer && this.Hostmaster == other_resource.Hostmaster && this.Serial == other_resource.Serial && this.RefreshSeconds == other_resource.RefreshSeconds && this.RetrySeconds == other_resource.RetrySeconds && this.ExpireSeconds == other_resource.ExpireSeconds && this.MinimumTTL == other_resource.MinimumTTL ); }
/** * Produces a new zone from an input XML file. */ public static DNSZone Unserialize(XmlDocument config) { DNSRecord start_of_authority = null; var records = new List <DNSRecord>(); var relays = new List <EndPoint>(); if (config.DocumentElement.Name != "zone") { throw new InvalidDataException("Root element must be called zone"); } foreach (var entry in config.DocumentElement.ChildNodes.OfType <XmlNode>()) { if (entry.NodeType != XmlNodeType.Element) { logger.Trace("Ignoring node of type {0}", entry.NodeType); continue; } bool is_record = entry.Name == "A" || entry.Name == "NS" || entry.Name == "CNAME" || entry.Name == "MX" || entry.Name == "SOA" || entry.Name == "PTR" || entry.Name == "AAAA"; if (is_record) { if (entry.Attributes["name"] == null || entry.Attributes["class"] == null || entry.Attributes["ttl"] == null) { throw new InvalidDataException("Resource records must have 'name', 'class' and 'ttl' attributes"); } var record_name = new Domain(entry.Attributes["name"].Value); AddressClass record_class; switch (entry.Attributes["class"].Value) { case "IN": record_class = AddressClass.INTERNET; break; default: throw new InvalidDataException("Only address class 'IN' is supported"); } UInt32 record_ttl = 0; try { record_ttl = UInt32.Parse(entry.Attributes["ttl"].Value); } catch (Exception err) { if (err is OverflowException || err is FormatException) { throw new InvalidDataException(entry.Attributes["ttl"].Value + " is not a valid TTL"); } else { throw; } } IDNSResource resource = null; switch (entry.Name) { case "A": if (entry.Attributes["address"] == null) { throw new InvalidDataException("A record must have address"); } IPv4Address address; try { address = IPv4Address.Parse(entry.Attributes["address"].Value); } catch (FormatException) { throw new InvalidDataException(entry.Attributes["address"].Value + " is not a valid IPv4 address"); } resource = new AResource(address); logger.Trace("A record: address={0}", ((AResource)resource).Address); break; case "NS": if (entry.Attributes["nameserver"] == null) { throw new InvalidDataException("NS record must have a nameserver"); } resource = new NSResource(new Domain(entry.Attributes["nameserver"].Value)); logger.Trace("NS record: nameserver={0}", ((NSResource)resource).Nameserver); break; case "CNAME": if (entry.Attributes["alias"] == null) { throw new InvalidDataException("CNAME record must have an alias"); } resource = new CNAMEResource(new Domain(entry.Attributes["alias"].Value)); logger.Trace("CNAME record: alias={0}", ((CNAMEResource)resource).Alias); break; case "MX": if (entry.Attributes["priority"] == null || entry.Attributes["mailserver"] == null) { throw new InvalidDataException("MX record must have priority and mailserver"); } var mailserver = new Domain(entry.Attributes["mailserver"].Value); UInt16 preference = 0; try { preference = UInt16.Parse(entry.Attributes["priority"].Value); } catch (Exception err) { if (err is OverflowException || err is FormatException) { throw new InvalidDataException(entry.Attributes["priority"].Value + " is not a valid priority value"); } else { throw; } } resource = new MXResource(preference, mailserver); logger.Trace("MX record: priority={0} mailserver={1}", ((MXResource)resource).Preference, ((MXResource)resource).Mailserver); break; case "PTR": if (entry.Attributes["pointer"] == null) { throw new InvalidDataException("PTR record must have pointer"); } if (!reverse_zone_v4.IsSubdomain(record_name) && !reverse_zone_v6.IsSubdomain(record_name)) { throw new InvalidDataException("PTR record be in the in-addr.arpa or ip6.arpa zone"); } resource = new PTRResource(new Domain(entry.Attributes["pointer"].Value)); logger.Trace("PTR record: pointer={0}", ((PTRResource)resource).Pointer); break; case "AAAA": if (entry.Attributes["address"] == null) { throw new InvalidDataException("AAAA record must have address"); } IPv6Address v6address; try { v6address = IPv6Address.Parse(entry.Attributes["address"].Value); } catch (FormatException) { throw new InvalidDataException(entry.Attributes["address"].Value + " is not a valid IPv4 address"); } resource = new AAAAResource(v6address); logger.Trace("AAAA record: address={0}", ((AAAAResource)resource).Address); break; case "SOA": if (entry.Attributes["primary-ns"] == null || entry.Attributes["hostmaster"] == null || entry.Attributes["serial"] == null || entry.Attributes["refresh"] == null || entry.Attributes["retry"] == null || entry.Attributes["expire"] == null || entry.Attributes["min-ttl"] == null) { throw new InvalidDataException("SOA record missing one of: primary-ns, hostmaster, serial, refresh, retry, expire and min-ttl"); } var primary_ns = new Domain(entry.Attributes["primary-ns"].Value); var hostmaster = new Domain(entry.Attributes["hostmaster"].Value); UInt32 serial = 0; try { serial = UInt32.Parse(entry.Attributes["serial"].Value); } catch (Exception err) { if (err is OverflowException || err is FormatException) { throw new InvalidDataException(entry.Attributes["serial"].Value + " is not a valid serial number"); } else { throw; } } UInt32 refresh = 0; try { refresh = UInt32.Parse(entry.Attributes["refresh"].Value); } catch (Exception err) { if (err is OverflowException || err is FormatException) { throw new InvalidDataException(entry.Attributes["refresh"].Value + " is not a valid refresh value"); } else { throw; } } UInt32 retry = 0; try { retry = UInt32.Parse(entry.Attributes["retry"].Value); } catch (Exception err) { if (err is OverflowException || err is FormatException) { throw new InvalidDataException(entry.Attributes["retry"].Value + " is not a valid retry value"); } else { throw; } } UInt32 expire = 0; try { expire = UInt32.Parse(entry.Attributes["expire"].Value); } catch (Exception err) { if (err is OverflowException || err is FormatException) { throw new InvalidDataException(entry.Attributes["expire"].Value + " is not a valid expire value"); } else { throw; } } UInt32 minttl = 0; try { minttl = UInt32.Parse(entry.Attributes["min-ttl"].Value); } catch (Exception err) { if (err is OverflowException || err is FormatException) { throw new InvalidDataException(entry.Attributes["min-ttl"].Value + " is not a valid expire value"); } else { throw; } } resource = new SOAResource(primary_ns, hostmaster, serial, refresh, retry, expire, minttl); logger.Trace("SOA record: primary-ns={0} hostmaster={1} serial={2} refresh={3} retry={4} expire={5} min-ttl={6}", ((SOAResource)resource).PrimaryNameServer, ((SOAResource)resource).Hostmaster, ((SOAResource)resource).Serial, ((SOAResource)resource).RefreshSeconds, ((SOAResource)resource).RetrySeconds, ((SOAResource)resource).ExpireSeconds, ((SOAResource)resource).MinimumTTL); break; } var record = new DNSRecord(record_name, record_class, record_ttl, resource); if (record.Resource.Type == ResourceRecordType.START_OF_AUTHORITY) { if (start_of_authority == null) { logger.Trace("Found SOA: {0}", record); start_of_authority = record; } else { throw new InvalidDataException("Cannot have more than one SOA record in zone"); } } else { logger.Trace("Found other record: {0}", record); records.Add(record); } } else if (entry.Name == "relay") { if (entry.Attributes["address"] == null || entry.Attributes["port"] == null) { throw new InvalidDataException("relay record must have address and port"); } IPAddress address; int port; try { address = IPAddress.Parse(entry.Attributes["address"].Value); } catch (FormatException) { throw new InvalidDataException(entry.Attributes["address"].Value + " is not a valid IPv4 address"); } try { port = int.Parse(entry.Attributes["port"].Value); } catch (FormatException) { throw new InvalidDataException(entry.Attributes["port"].Value + " is not a valid port"); } try { relays.Add(new IPEndPoint(address, port)); } catch (ArgumentOutOfRangeException) { throw new InvalidDataException(entry.Attributes["port"].Value + " is not a valid port"); } logger.Trace("Found relay: {0}:{1}", address, port); } else { throw new InvalidDataException(entry.Name + " is not a valid zone entry"); } } if (start_of_authority == null) { throw new InvalidDataException("Zone does not have SOA record"); } var zone = new DNSZone(start_of_authority, relays.ToArray()); foreach (var record in records) { if (record.TimeToLive < ((SOAResource)start_of_authority.Resource).MinimumTTL) { logger.Trace("Correcting TTL: Record {0} has smaller TTL than SOA MinTTL {1}", record, start_of_authority); record.TimeToLive = ((SOAResource)start_of_authority.Resource).MinimumTTL; } zone.Add(record); } return(zone); }