#2248 - Final run over all the docstrings after running pre-commit. All tests now working. Updated CHANGELOG.md.

This commit is contained in:
Chris McCarthy
2024-02-08 10:53:30 +00:00
parent 0c96fef3ec
commit 411f0a320f
41 changed files with 582 additions and 328 deletions

View File

@@ -20,6 +20,7 @@ class ARP(Service):
Manages ARP for resolving network layer addresses into link layer addresses. It maintains an ARP cache,
sends ARP requests and replies, and processes incoming ARP packets.
"""
arp: Dict[IPV4Address, ARPEntry] = {}
def __init__(self, **kwargs):
@@ -29,6 +30,14 @@ class ARP(Service):
super().__init__(**kwargs)
def describe_state(self) -> Dict:
"""
Produce a dictionary describing the current state of this object.
:return: Current state of this object and child objects.
"""
state = super().describe_state()
state.update({str(ip): arp_entry.mac_address for ip, arp_entry in self.arp.items()})
return super().describe_state()
def show(self, markdown: bool = False):
@@ -57,11 +66,7 @@ class ARP(Service):
self.arp.clear()
def add_arp_cache_entry(
self,
ip_address: IPV4Address,
mac_address: str,
network_interface: NetworkInterface,
override: bool = False
self, ip_address: IPV4Address, mac_address: str, network_interface: NetworkInterface, override: bool = False
):
"""
Add an ARP entry to the cache.
@@ -139,7 +144,8 @@ class ARP(Service):
)
else:
self.sys_log.error(
"Cannot send ARP request as there is no outbound Network Interface to use. Try configuring the default gateway."
"Cannot send ARP request as there is no outbound Network Interface to use. Try configuring the default "
"gateway."
)
def send_arp_reply(self, arp_reply: ARPPacket):
@@ -147,12 +153,10 @@ class ARP(Service):
Sends an ARP reply in response to an ARP request.
:param arp_reply: The ARP packet containing the reply.
:param from_network_interface: The NIC from which the ARP reply is sent.
"""
outbound_network_interface = self.software_manager.session_manager.resolve_outbound_network_interface(
arp_reply.target_ip_address
)
)
if outbound_network_interface:
self.sys_log.info(
f"Sending ARP reply from {arp_reply.sender_mac_addr}/{arp_reply.sender_ip_address} "
@@ -162,14 +166,14 @@ class ARP(Service):
payload=arp_reply,
dst_ip_address=arp_reply.target_ip_address,
dst_port=self.port,
ip_protocol=self.protocol
ip_protocol=self.protocol,
)
else:
self.sys_log.error(
"Cannot send ARP reply as there is no outbound Network Interface to use. Try configuring the default gateway."
"Cannot send ARP reply as there is no outbound Network Interface to use. Try configuring the default "
"gateway."
)
@abstractmethod
def _process_arp_request(self, arp_packet: ARPPacket, from_network_interface: NetworkInterface):
"""
@@ -197,7 +201,7 @@ class ARP(Service):
self.add_arp_cache_entry(
ip_address=arp_packet.sender_ip_address,
mac_address=arp_packet.sender_mac_addr,
network_interface=from_network_interface
network_interface=from_network_interface,
)
def receive(self, payload: Any, session_id: str, **kwargs) -> bool:

View File

@@ -1,8 +1,9 @@
import secrets
from ipaddress import IPv4Address
from typing import Dict, Any, Union, Optional, Tuple
from typing import Any, Dict, Optional, Tuple, Union
from primaite import getLogger
from primaite.simulator.network.hardware.base import NetworkInterface
from primaite.simulator.network.protocols.icmp import ICMPPacket, ICMPType
from primaite.simulator.network.transmission.data_link_layer import Frame
from primaite.simulator.network.transmission.network_layer import IPProtocol
@@ -19,6 +20,7 @@ class ICMP(Service):
Enables the sending and receiving of ICMP messages such as echo requests and replies. This is typically used for
network diagnostics, notably the ping command.
"""
request_replies: Dict = {}
def __init__(self, **kwargs):
@@ -28,7 +30,12 @@ class ICMP(Service):
super().__init__(**kwargs)
def describe_state(self) -> Dict:
pass
"""
Produce a dictionary describing the current state of this object.
:return: Current state of this object and child objects.
"""
return super().describe_state()
def clear(self):
"""
@@ -56,9 +63,7 @@ class ICMP(Service):
self.sys_log.info(f"Pinging {target_ip_address}:", to_terminal=True)
sequence, identifier = 0, None
while sequence < pings:
sequence, identifier = self._send_icmp_echo_request(
target_ip_address, sequence, identifier, pings
)
sequence, identifier = self._send_icmp_echo_request(target_ip_address, sequence, identifier, pings)
request_replies = self.software_manager.icmp.request_replies.get(identifier)
passed = request_replies == pings
if request_replies:
@@ -76,7 +81,7 @@ class ICMP(Service):
return passed
def _send_icmp_echo_request(
self, target_ip_address: IPv4Address, sequence: int = 0, identifier: Optional[int] = None, pings: int = 4
self, target_ip_address: IPv4Address, sequence: int = 0, identifier: Optional[int] = None, pings: int = 4
) -> Tuple[int, Union[int, None]]:
"""
Sends an ICMP echo request to a specified target IP address.
@@ -91,7 +96,8 @@ class ICMP(Service):
if not network_interface:
self.sys_log.error(
"Cannot send ICMP echo request as there is no outbound Network Interface to use. Try configuring the default gateway."
"Cannot send ICMP echo request as there is no outbound Network Interface to use. Try configuring the "
"default gateway."
)
return pings, None
@@ -105,11 +111,11 @@ class ICMP(Service):
dst_ip_address=target_ip_address,
dst_port=self.port,
ip_protocol=self.protocol,
icmp_packet=icmp_packet
icmp_packet=icmp_packet,
)
return sequence, icmp_packet.identifier
def _process_icmp_echo_request(self, frame: Frame, from_network_interface):
def _process_icmp_echo_request(self, frame: Frame, from_network_interface: NetworkInterface):
"""
Processes an ICMP echo request received by the service.
@@ -121,11 +127,12 @@ class ICMP(Service):
network_interface = self.software_manager.session_manager.resolve_outbound_network_interface(
frame.ip.src_ip_address
)
)
if not network_interface:
self.sys_log.error(
"Cannot send ICMP echo reply as there is no outbound Network Interface to use. Try configuring the default gateway."
"Cannot send ICMP echo reply as there is no outbound Network Interface to use. Try configuring the "
"default gateway."
)
return
@@ -143,7 +150,7 @@ class ICMP(Service):
dst_ip_address=frame.ip.src_ip_address,
dst_port=self.port,
ip_protocol=self.protocol,
icmp_packet=icmp_packet
icmp_packet=icmp_packet,
)
def _process_icmp_echo_reply(self, frame: Frame):
@@ -159,7 +166,7 @@ class ICMP(Service):
f"bytes={len(frame.payload)}, "
f"time={time_str}, "
f"TTL={frame.ip.ttl}",
to_terminal=True
to_terminal=True,
)
if not self.request_replies.get(frame.icmp.identifier):
self.request_replies[frame.icmp.identifier] = 0

View File

@@ -70,10 +70,6 @@ class NTPServer(Service):
payload = payload.generate_reply(time)
# send reply
self.software_manager.session_manager.receive_payload_from_software_manager(
payload=payload,
src_port=self.port,
dst_port=self.port,
ip_protocol=self.protocol,
session_id=session_id
payload=payload, src_port=self.port, dst_port=self.port, ip_protocol=self.protocol, session_id=session_id
)
return True