Exemplo n.º 1
0
 public DNSRecord(Domain name, AddressClass address_class, UInt32 ttl, IDNSResource resource)
 {
     Name         = name;
     AddressClass = address_class;
     TimeToLive   = ttl;
     Resource     = resource;
 }
Exemplo n.º 2
0
        public bool Equals(IDNSResource other)
        {
            if (!(other is AAAAResource))
            {
                return(false);
            }

            var other_resource = (AAAAResource)other;

            return
                (this.Address.Equals(other_resource.Address)
                );
        }
Exemplo n.º 3
0
        public bool Equals(IDNSResource other)
        {
            if (!(other is PTRResource))
            {
                return(false);
            }

            var other_resource = (PTRResource)other;

            return
                (this.Pointer == other_resource.Pointer
                );
        }
Exemplo n.º 4
0
        public bool Equals(IDNSResource other)
        {
            if (!(other is CNAMEResource))
            {
                return(false);
            }

            var other_resource = (CNAMEResource)other;

            return
                (this.Alias == other_resource.Alias
                );
        }
Exemplo n.º 5
0
        public bool Equals(IDNSResource other)
        {
            if (!(other is NSResource))
            {
                return(false);
            }

            var other_resource = (NSResource)other;

            return
                (this.Nameserver == other_resource.Nameserver
                );
        }
Exemplo n.º 6
0
        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
                );
        }
Exemplo n.º 7
0
        /**
         * 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));
        }
Exemplo n.º 8
0
        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
                );
        }
Exemplo n.º 9
0
        /**
         * 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);
        }