using System.Collections.Generic;
using System.Net.Sockets;
using Microsoft.VisualStudio.TestTools.UnitTesting;
public ushort QuestionCount;
public ushort AnswerCount;
public ushort AuthorityCount;
public ushort AdditionalCount;
public struct DNSQuestion
private static Dictionary<string, string> dnsRecords = new Dictionary<string, string>()
{"example.com", "127.0.0.1"},
{"google.com", "142.250.184.142"}
public static string DNSFormatToString(byte[] data, ref int offset)
StringBuilder domainName = new StringBuilder();
int length = data[offset];
for (int i = 0; i < length; i++)
domainName.Append((char)data[offset]);
return domainName.ToString();
public static byte[] StringToDNSFormat(string domainName)
List<byte> result = new List<byte>();
string[] labels = domainName.Split('.');
foreach (string label in labels)
result.Add((byte)label.Length);
foreach (char c in label)
public static string IPv4ToString(byte[] ipBytes)
return $"{ipBytes[0]}.{ipBytes[1]}.{ipBytes[2]}.{ipBytes[3]}";
public static byte[] StringToIPv4(string ipString)
string[] parts = ipString.Split('.');
byte[] ipBytes = new byte[4];
for (int i = 0; i < 4; i++)
ipBytes[i] = byte.Parse(parts[i]);
public static byte[] ConstructResponse(byte[] receivedData)
DNSHeader header = new DNSHeader();
header.Id = (ushort)(receivedData[0] << 8 | receivedData[1]);
header.Flags = (ushort)(receivedData[2] << 8 | receivedData[3]);
header.QuestionCount = (ushort)(receivedData[4] << 8 | receivedData[5]);
header.AnswerCount = (ushort)(receivedData[6] << 8 | receivedData[7]);
header.AuthorityCount = (ushort)(receivedData[8] << 8 | receivedData[9]);
header.AdditionalCount = (ushort)(receivedData[10] << 8 | receivedData[11]);
string domainName = DNSFormatToString(receivedData, ref offset);
ushort queryType = (ushort)(receivedData[offset] << 8 | receivedData[offset + 1]);
ushort queryClass = (ushort)(receivedData[offset + 2] << 8 | receivedData[offset + 3]);
string ipAddress = dnsRecords.ContainsKey(domainName) ? dnsRecords[domainName] : null;
List<byte> response = new List<byte>();
header.AnswerCount = (ushort)(ipAddress != null ? 1 : 0);
response.AddRange(BitConverter.GetBytes(header.Id).Reverse());
response.AddRange(BitConverter.GetBytes(header.Flags).Reverse());
response.AddRange(BitConverter.GetBytes(header.QuestionCount).Reverse());
response.AddRange(BitConverter.GetBytes(header.AnswerCount).Reverse());
response.AddRange(BitConverter.GetBytes(header.AuthorityCount).Reverse());
response.AddRange(BitConverter.GetBytes(header.AdditionalCount).Reverse());
byte[] domainNameBytes = StringToDNSFormat(domainName);
response.AddRange(domainNameBytes);
response.AddRange(BitConverter.GetBytes(queryType).Reverse());
response.AddRange(BitConverter.GetBytes(queryClass).Reverse());
response.AddRange(domainNameBytes);
response.AddRange(BitConverter.GetBytes(type).Reverse());
response.AddRange(BitConverter.GetBytes(@class).Reverse());
response.AddRange(BitConverter.GetBytes(ttl).Reverse());
response.AddRange(BitConverter.GetBytes(rdLength).Reverse());
byte[] ipBytes = StringToIPv4(ipAddress);
response.AddRange(ipBytes);
return response.ToArray();
public static void StartServer()
UdpClient udpServer = new UdpClient(53);
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Any, 0);
Console.WriteLine("DNS Server started. Listening on port 53...");
byte[] receivedData = udpServer.Receive(ref remoteEP);
Console.WriteLine($"Received request from {remoteEP.Address}:{remoteEP.Port}");
byte[] responseData = ConstructResponse(receivedData);
udpServer.Send(responseData, responseData.Length, remoteEP);
Console.WriteLine($"Sent response to {remoteEP.Address}:{remoteEP.Port}");
Console.WriteLine($"Exception: {e}");
public static void Main(string[] args)
Console.WriteLine("Running tests...\n");
Type testClassType = typeof(DNSTests);
object testInstance = Activator.CreateInstance(testClassType);
MethodInfo[] testMethods = testClassType.GetMethods()
.Where(m => m.GetCustomAttributes(typeof(TestMethodAttribute), false).Length > 0)
int passed = 0, failed = 0;
foreach (var method in testMethods)
method.Invoke(testInstance, null);
Console.WriteLine($"✅ {method.Name} PASSED");
Console.WriteLine($"❌ {method.Name} FAILED: {ex.InnerException?.Message ?? ex.Message}");
public void DNSFormatToString_ValidData_ReturnsDomainName()
byte[] data = { 7, (byte)'e', (byte)'x', (byte)'a', (byte)'m', (byte)'p', (byte)'l', (byte)'e', 3, (byte)'c', (byte)'o', (byte)'m', 0 };
string domainName = DNSServer.DNSFormatToString(data, ref offset);
Assert.AreEqual("example.com", domainName);
public void StringToDNSFormat_ValidDomainName_ReturnsDNSFormat()
string domainName = "example.com";
byte[] expected = { 7, (byte)'e', (byte)'x', (byte)'a', (byte)'m', (byte)'p', (byte)'l', (byte)'e', 3, (byte)'c', (byte)'o', (byte)'m', 0 };
byte[] actual = DNSServer.StringToDNSFormat(domainName);
CollectionAssert.AreEqual(expected, actual);
public void IPv4ToString_ValidBytes_ReturnsString()
byte[] ipBytes = { 127, 0, 0, 1 };
string ipString = DNSServer.IPv4ToString(ipBytes);
Assert.AreEqual("127.0.0.1", ipString);
public void StringToIPv4_ValidString_ReturnsBytes()
string ipString = "127.0.0.1";
byte[] expected = { 127, 0, 0, 1 };
byte[] actual = DNSServer.StringToIPv4(ipString);
CollectionAssert.AreEqual(expected, actual);
public void ConstructResponse_ValidRequest_ReturnsResponse()
0x07, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x03, 0x63, 0x6f, 0x6d, 0x00,
byte[] response = DNSServer.ConstructResponse(request);
Assert.IsNotNull(response);
Assert.IsTrue(response.Length > 12);