XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFESystem

【Rust】XFE系统,基于Rust和汇编

公开
关注 0 Fork 0 Star 0
UTF-8
using XFESystem.Network;

namespace XFESystem.Network.Tests;

public sealed class DnsTests
{
    static byte[] Name(string value)
    {
        var bytes = new List<byte>();
        foreach (string label in value.Split('.')) { bytes.Add((byte)label.Length); bytes.AddRange(System.Text.Encoding.ASCII.GetBytes(label)); }
        bytes.Add(0); return bytes.ToArray();
    }
    static byte[] Query()
    { byte[] bytes = new byte[512]; int length = DnsMessage.WriteQuery(bytes, 1234, "www.bing.com"); return bytes[..length]; }
    [Fact]
    public void CompressedAnswerIsBoundToTheExactQuestion()
    {
        byte[] answer = PacketFixture.Answer(Query(), 0x01020304);
        Assert.Equal(0x01020304u, DnsMessage.ReadAddress(answer, 1234, "WWW.BING.COM."));
        Assert.Throws<InvalidDataException>(() => DnsMessage.ReadAddress(answer, 1235, "www.bing.com"));
        Assert.Throws<InvalidDataException>(() => DnsMessage.ReadAddress(answer, 1234, "other.bing.com"));
    }
    [Fact]
    public void CnameChainCanResolveAnAddressAppearingBeforeItsAlias()
    {
        byte[] query = Query(), alias = Name("edge.example.com");
        byte[] answer = new byte[query.Length + alias.Length + 14 + 12 + alias.Length]; query.CopyTo(answer, 0);
        NetworkPackets.Write16(answer, 2, 0x8180); NetworkPackets.Write16(answer, 6, 2); int at = query.Length;
        // A record first; parser must bind its owner through the later CNAME.
        alias.CopyTo(answer, at); at += alias.Length; NetworkPackets.Write16(answer, at, 1); NetworkPackets.Write16(answer, at + 2, 1);
        NetworkPackets.Write32(answer, at + 4, 60); NetworkPackets.Write16(answer, at + 8, 4); NetworkPackets.Write32(answer, at + 10, 0x01020304); at += 14;
        NetworkPackets.Write16(answer, at, 0xc00c); NetworkPackets.Write16(answer, at + 2, 5); NetworkPackets.Write16(answer, at + 4, 1);
        NetworkPackets.Write32(answer, at + 6, 60); NetworkPackets.Write16(answer, at + 10, (ushort)alias.Length); alias.CopyTo(answer, at + 12);
        Assert.Equal(0x01020304u, DnsMessage.ReadAddress(answer, 1234, "www.bing.com"));
    }
    [Fact]
    public void TruncationAndCompressionCyclesFailWithoutUnboundedParsing()
    {
        byte[] answer = PacketFixture.Answer(Query(), 0x01020304);
        Assert.Throws<InvalidDataException>(() => DnsMessage.ReadAddress(answer[..^1], 1234, "www.bing.com"));
        answer[12] = 0xc0; answer[13] = 12;
        Assert.Throws<InvalidDataException>(() => DnsMessage.ReadAddress(answer, 1234, "www.bing.com"));
    }
    [Theory]
    [InlineData(0x8380)]
    [InlineData(0x8183)]
    [InlineData(0x0180)]
    public void TruncatedNxdomainAndNonresponseAreRejected(int flags)
    {
        byte[] answer = PacketFixture.Answer(Query(), 0x01020304); NetworkPackets.Write16(answer, 2, (ushort)flags);
        Assert.Throws<InvalidDataException>(() => DnsMessage.ReadAddress(answer, 1234, "www.bing.com"));
    }
    [Fact]
    public void UnrelatedAnswerCannotSubstituteAnotherHost()
    {
        byte[] answer = PacketFixture.Answer(Query(), 0x01020304); int at = Query().Length;
        // Point the RR owner at 'bing.com', not the question's 'www.bing.com'.
        NetworkPackets.Write16(answer, at, 0xc010);
        Assert.Throws<InvalidDataException>(() => DnsMessage.ReadAddress(answer, 1234, "www.bing.com"));
    }
    [Theory]
    [InlineData("bad..name")]
    [InlineData("https://www.bing.com/")]
    [InlineData("bad\r\nname")]
    public void InvalidQueryNamesAreRejected(string host) => Assert.Throws<ArgumentException>(() => DnsMessage.WriteQuery(new byte[512], 1, host));
}