From 72cd9fd8e29ed1d6c917f9bc9fad1d2fda5d0da5 Mon Sep 17 00:00:00 2001 From: SunilSamra Date: Wed, 16 Aug 2023 13:00:16 +0100 Subject: [PATCH] #1752 - Created dns.py protocol file with DNSPacket and DNSRequest and DNSReply packets - Added reset_component logic for dns_server.py and dns_client.py --- .../simulator/network/protocols/dns.py | 113 ++++++++++++++++++ .../simulator/system/services/dns_client.py | 3 +- .../simulator/system/services/dns_server.py | 4 +- 3 files changed, 117 insertions(+), 3 deletions(-) create mode 100644 src/primaite/simulator/network/protocols/dns.py diff --git a/src/primaite/simulator/network/protocols/dns.py b/src/primaite/simulator/network/protocols/dns.py new file mode 100644 index 00000000..fa88652c --- /dev/null +++ b/src/primaite/simulator/network/protocols/dns.py @@ -0,0 +1,113 @@ +from __future__ import annotations + +from ipaddress import IPv4Address +from typing import Optional + +from pydantic import BaseModel + + +class DNSEntry(BaseModel): + """ + Represents an entry in the DNS cache. + + :param domain_name: The domain name which a node would like to access. + :param ip_address: The IP address through which the domain name is reachable. + """ + + domain_name: str + ip_address: IPv4Address + + +class DNSRequest(BaseModel): + """Represents a DNS Request packet of a network frame. + + :param sender_mac_addr: Sender MAC address. + :param sender_ip: Sender IP address. + :param target_mac_addr: Target MAC address. + :param target_ip: Target IP address. + :param domain_name_request: Domain Name Request for IP address. + """ + + sender_mac_addr: str + "Sender MAC address." + sender_ip: IPv4Address + "Sender IP address." + target_mac_addr: Optional[str] = None + "Target MAC address of the DNS Server." + target_ip: IPv4Address + "Target IP address of the DNS Server." + domain_name_request: str + "Domain Name Request for IP address." + + +class DNSReply(BaseModel): + """Represents a DNS Reply packet of a network frame. + + :param sender_mac_addr: Sender MAC address. + :param sender_ip: Sender IP address. + :param target_mac_addr: Target MAC address of DNS Client. + :param target_ip: Target IP address of DNS Client. + :param domain_name_ip_address: IP Address of the Domain Name requested. + """ + + sender_mac_addr: str + "Sender MAC address." + sender_ip: IPv4Address + "Sender IP address." + target_mac_addr: Optional[str] = None + "Target MAC address of the DNS Server." + target_ip: IPv4Address + "Target IP address of the DNS Server." + domain_name_ip_address: IPv4Address + "IP Address of the Domain Name requested." + + +class DNSPacket(BaseModel): + """ + Represents the DNS layer of a network frame. + + :param dns_request: DNS Request packet sent by DNS Client. + :param dns_reply: DNS Reply packet generated by DNS Server. + + :Example: + + >>> dns_request = DNSPacket( + ... dns_request=DNSRequest(sender_mac_addr="aa:bb:cc:dd:ee:ff", sender_ip = IPv4Address("192.168.0.1"), + ... target_ip = IPv4Address("192.168.0.2"), domain_name_request="www.google.co.uk"), + ... dns_reply=None + ... ) + >>> dns_response = DNSPacket( + ... dns_request=DNSRequest(sender_mac_addr="aa:bb:cc:dd:ee:ff", sender_ip = IPv4Address("192.168.0.1"), + ... target_ip = IPv4Address("192.168.0.2"), domain_name_request="www.google.co.uk"), + ... dns_reply=DNSReply(sender_mac_addr="gg:hh:ii:jj:kk:ll", sender_ip = IPv4Address("192.168.0.2"), + ... target_ip = IPv4Address("192.168.0.1"), domain_name_ip_address=IPv4Address("142.250.179.227")) + ... ) + """ + + dns_request: DNSRequest + "DNS Request packet sent by DNS Client." + dns_reply: Optional[DNSReply] = None + "DNS Reply packet generated by DNS Server." + + def generate_reply(self, domain_ip_address: IPv4Address) -> DNSPacket: + """Generate a new DNSPacket to be sent as a response with a DNS Reply packet which contains the IP address. + + :param domain_ip_address: The IP address that was being sought after from the original target domain name. + :return: A new instance of DNSPacket. + """ + return DNSPacket( + dns_request=DNSRequest( + sender_mac_addr=self.dns_request.sender_mac_addr, + sender_ip=self.dns_request.sender_ip, + target_mac_addr=self.dns_request.target_mac_addr, + target_ip=self.dns_request.target_ip, + domain_name_request=self.dns_request.domain_name_request, + ), + dns_reply=DNSReply( + sender_mac_addr=self.dns_request.target_mac_addr, + sender_ip=self.dns_request.target_ip, + target_mac_addr=self.dns_request.sender_mac_addr, + target_ip=self.dns_request.sender_ip, + domain_name_ip_address=domain_ip_address, + ), + ) diff --git a/src/primaite/simulator/system/services/dns_client.py b/src/primaite/simulator/system/services/dns_client.py index ebbe4058..7b080244 100644 --- a/src/primaite/simulator/system/services/dns_client.py +++ b/src/primaite/simulator/system/services/dns_client.py @@ -41,7 +41,8 @@ class DNSClient(BaseModel): This method ensures the Service is ready for a new episode, including resetting any stateful properties or statistics, and clearing any message queues. """ - pass + self.target_url = "" + self.dns_cache = {} def send(self, payload: Any, session_id: str, **kwargs) -> bool: """ diff --git a/src/primaite/simulator/system/services/dns_server.py b/src/primaite/simulator/system/services/dns_server.py index e7b51f38..7eed51b5 100644 --- a/src/primaite/simulator/system/services/dns_server.py +++ b/src/primaite/simulator/system/services/dns_server.py @@ -7,7 +7,7 @@ from pydantic import BaseModel class DNSServer(BaseModel): """Represents a DNS Server as a Service.""" - dns_table: dict[str:str] = {"https://google.co.uk": "8.8.8.8"} + dns_table: dict[str:str] = {} @abstractmethod def describe_state(self) -> Dict: @@ -37,7 +37,7 @@ class DNSServer(BaseModel): This method ensures the Service is ready for a new episode, including resetting any stateful properties or statistics, and clearing any message queues. """ - pass + self.dns_table = {} def send(self, payload: Any, session_id: str, **kwargs) -> bool: """