package jos.system.net.jeps;
/*
* Adress Resolution Protocol
*
* Almost literally RFC 826 compliant.
* Need to implement queueing of outgoing packets while resolution
* is pending.
*/
class ARP extends Protocol
{
private ARPTableEntry firstEntry; // ARP table, Linked list.
private EthernetNetworkInterface ni;
private HWAddr hwaddr;
static HWAddr hwnone;
static HWAddr hwbcast;
ARP(EthernetNetworkInterface ni,HWAddr hwaddr)
{
protocolNumber=0x806;
firstEntry=null;
next=null;
this.ni=ni;
this.hwaddr=hwaddr;
hwnone=new HWAddr((byte)0,(byte)0,(byte)0,(byte)0,(byte)0,(byte)0);
hwbcast=new HWAddr((byte)255,(byte)255,(byte)255,(byte)255,(byte)255,(byte)255);
}
ARPTableEntry find(IPAddr ipaddr) // Search the Table
{
ARPTableEntry currentEntry=firstEntry;
while ((currentEntry != null))
{
if (currentEntry.getIPAddr().equals(ipaddr))
{return currentEntry;}
currentEntry=currentEntry.getNextEntry();
}
return null;
}
public HWAddr getHWAddr(IPAddr ipaddr)
{
ARPTableEntry ent = find(ipaddr);
if (ent!=null)
{
if (ent.getState()==ARPTableEntry.ARP_STATE_RESOLVED)
{ return ent.getHWAddr(); }
}
return null;
}
void add(ARPTableEntry newEntry)
{
/* New Entries are added to the front of the list
as we assume they are going to be the subject
of immidiate communication. */
newEntry.setNextEntry(firstEntry);
firstEntry = newEntry;
}
void request(IPAddr ipaddr)
{
add(new ARPTableEntry(ARPTableEntry.ARP_STATE_PENDING,hwnone,ipaddr));
ni.writePacket(new ARPPacket(hwaddr,ni.ipaddr,hwnone,ipaddr,ARPPacket.ARP_REQ),
hwaddr,hwbcast,protocolNumber);
}
/*
* Tries to conform to the procedure outlined in RFC 826
*/
public void Handle(Packet p)
{
ARPPacket ap=new ARPPacket(p.data);
System.out.println("ARP "+ap.toString());
if (ap.hwa_fmt!=1) return; // This is Ethernet
if (ap.prota_fmt!=0x800) return; // We only speak IP
boolean merge = false; // This var for literal RFC compliance.
ARPTableEntry currentEntry = find(ap.ip_src);
if (currentEntry!=null)
{
currentEntry.setState(ARPTableEntry.ARP_STATE_RESOLVED);
currentEntry.setHWAddr(ap.hw_src);
currentEntry.touch();
merge=true;
}
if (!ap.ip_dest.equals(ni.ipaddr)) return; // Not for us!
if (!merge)
{
add(new ARPTableEntry(ARPTableEntry.ARP_STATE_RESOLVED,ap.hw_src,ap.ip_src));
}
if (ap.operation==ARPPacket.ARP_REQ) // Send reply.
{
ni.writePacket(new ARPPacket(hwaddr,ni.ipaddr,ap.hw_src,ap.ip_src,ARPPacket.ARP_REP),
hwaddr,ap.hw_src,protocolNumber);
}
}
};