using sys = System;
using Cosmos.HAL;
using Cosmos.HAL.Network;
using Cosmos.System.Network.IPv4;
namespace Cosmos.System.Network.ARP
{
///
/// ARPPacket class. See also: .
///
internal class ARPPacket : EthernetPacket
{
///
/// Hardware type.
///
protected ushort aHardwareType;
///
/// Protocol type.
///
protected ushort aProtocolType;
///
/// Hardware address length.
///
protected byte aHardwareLen;
///
/// Protocol address length.
///
protected byte aProtocolLen;
///
/// Operation code.
///
protected ushort aOperation;
///
/// ARP handler.
///
/// Packet data.
/// Thrown on fatal error (contact support).
/// Thrown on IO error.
/// Thrown on fatal error (contact support).
/// Thrown on fatal error (contact support).
internal static void ARPHandler(byte[] packetData)
{
ARPPacket arp_packet = new ARPPacket(packetData);
//Sys.Console.WriteLine("Received ARP Packet");
//Sys.Console.WriteLine(arp_packet.ToString());
if (arp_packet.Operation == 0x01)
{
if ((arp_packet.HardwareType == 1) && (arp_packet.ProtocolType == 0x0800))
{
ARPRequest_Ethernet arp_request = new ARPRequest_Ethernet(packetData);
if (arp_request.SenderIP == null)
{
NetworkStack.debugger.Send("SenderIP null in ARPHandler!");
}
arp_request = new ARPRequest_Ethernet(packetData);
ARPCache.Update(arp_request.SenderIP, arp_request.SenderMAC);
if (NetworkStack.AddressMap.ContainsKey(arp_request.TargetIP.Hash) == true)
{
NetworkStack.debugger.Send("ARP Request Recvd from " + arp_request.SenderIP.ToString());
NetworkDevice nic = NetworkStack.AddressMap[arp_request.TargetIP.Hash];
ARPReply_Ethernet reply =
new ARPReply_Ethernet(nic.MACAddress, arp_request.TargetIP, arp_request.SenderMAC, arp_request.SenderIP);
nic.QueueBytes(reply.RawData);
}
}
}
else if (arp_packet.Operation == 0x02)
{
if ((arp_packet.HardwareType == 1) && (arp_packet.ProtocolType == 0x0800))
{
ARPReply_Ethernet arp_reply = new ARPReply_Ethernet(packetData);
NetworkStack.debugger.Send("Received ARP Reply");
NetworkStack.debugger.Send(arp_reply.ToString());
NetworkStack.debugger.Send("ARP Reply Recvd from " + arp_reply.SenderIP.ToString());
ARPCache.Update(arp_reply.SenderIP, arp_reply.SenderMAC);
OutgoingBuffer.ARPCache_Update(arp_reply);
}
}
}
///
/// Work around to make VMT scanner include the initFields method
///
public static void VMTInclude()
{
new ARPPacket();
}
///
/// Create new inctanse of the class.
///
internal ARPPacket()
: base()
{ }
///
/// Create new inctanse of the class.
///
/// Raw data.
internal ARPPacket(byte[] rawData)
: base(rawData)
{ }
///
/// Init ARPPacket fields.
///
protected override void initFields()
{
base.initFields();
aHardwareType = (ushort)((RawData[14] << 8) | RawData[15]);
aProtocolType = (ushort)((RawData[16] << 8) | RawData[17]);
aHardwareLen = RawData[18];
aProtocolLen = RawData[19];
aOperation = (ushort)((RawData[20] << 8) | RawData[21]);
}
///
/// Create new inctanse of the class.
///
/// Destination MAC address.
/// Source MAC address.
/// Hardware type.
/// Protocol type.
/// Hardware address length.
/// Protocol length.
/// Operation.
/// Packet size.
protected ARPPacket(MACAddress dest, MACAddress src, ushort hwType, ushort protoType,
byte hwLen, byte protoLen, ushort operation, int packet_size)
: base(dest, src, 0x0806, packet_size)
{
RawData[14] = (byte)(hwType >> 8);
RawData[15] = (byte)(hwType >> 0);
RawData[16] = (byte)(protoType >> 8);
RawData[17] = (byte)(protoType >> 0);
RawData[18] = hwLen;
RawData[19] = protoLen;
RawData[20] = (byte)(operation >> 8);
RawData[21] = (byte)(operation >> 0);
initFields();
}
///
/// Get operation.
///
internal ushort Operation => aOperation;
///
/// Get hardware type.
///
internal ushort HardwareType => aHardwareType;
///
/// Get protocol type.
///
internal ushort ProtocolType => aProtocolType;
///
/// To string.
///
/// string value.
public override string ToString()
{
return "ARP Packet Src=" + srcMAC + ", Dest=" + destMAC + ", HWType=" + aHardwareType + ", Protocol=" + aProtocolType +
", Operation=" + Operation;
}
}
}