package jos.system.net.jeps;
/*************************************
* This class is supposed to process *
* IP datagrams. *
*************************************/
class IP extends Protocol
{
boolean FORWARDING_ENABLED = false; // IP forwarding default as per RFC 1122
Protocol firstProtocol = null;
RoutingTableEntry firstRoute = null;
RoutingTableEntry defaultGateway = null; // VIOLATION: MUST support more than one ... RFC 1122
ICMP icmp = null;
TCP tcp = null;
UDP udp= null;
static IP ip = null;
int currentId=1234; // ID for outgoing datatgrams
IP()
{
protocolNumber=0x800;
next=null;
icmp = new ICMP(this);
firstProtocol = icmp;
tcp= new TCP();
udp=new UDP();
firstProtocol.setNextProtocol(tcp);
firstProtocol.getNextProtocol().setNextProtocol(udp);
ip=this;
}
public void Handle(Packet p)
{
IPPacket ipp=null;
try {ipp = new IPPacket(p.data);}
catch (MalformedPacketException e) {return;} // As per RFC 1122
System.out.println("IP "+ipp.toString());
Packet pp=ipp.unpack(ipp.HEADER_LEN);
for (int i=0;i<nrInterfaces;i++)
{
if (ipp.dest.equals(interfaces[i].ipaddr))
{
demux(pp);
return;
}
}
if (FORWARDING_ENABLED)
{
/* Forward the datagram to the appropriate host */
System.out.println("Sorry, forwarding not supported");
}
else
{
/* SHOULD Send Error message Dest/Net unreach. */
/* Make sure you don't send errors for bcast! */
//System.out.println("NET/DEST UNREACH for "+ipp.toString());
}
}
void demux(Packet p)
{
boolean handled=false;
Protocol currentProtocol = firstProtocol;
while ((!handled) && (currentProtocol != null))
{
if (currentProtocol.getProtocolNumber()==p.protocol)
{
currentProtocol.Handle(p);
handled=true;
}
currentProtocol=currentProtocol.getNextProtocol();
}
}
public void addRoute(IPAddr net,IPAddr mask,IPAddr gw,int metric,NetworkInterface ni)
{
RoutingTableEntry route = new RoutingTableEntry(net,mask,gw,metric,ni);
route.setNextEntry(firstRoute);
firstRoute=route;
}
public void setDefaultRoute(IPAddr net,IPAddr mask,IPAddr gw,int metric,NetworkInterface ni)
{
RoutingTableEntry route = new RoutingTableEntry(net,mask,gw,metric,ni);
defaultGateway=route;
}
public RoutingTableEntry findRoute(IPAddr dest)
{
RoutingTableEntry currentEntry = firstRoute;
while (currentEntry != null)
{
if (currentEntry.net.equals(dest.mask(currentEntry.mask)))
{
return currentEntry;
}
currentEntry=currentEntry.getNextEntry();
}
System.out.println("No specific route found, returning the Default Gateway.");
return defaultGateway;
}
public void send(IPAddr dest,Packet p) throws NoRouteException
{
IPPacket ipp=new IPPacket();
ipp.data=p.pack(20).data;
ipp.dest=dest;
RoutingTableEntry rt = findRoute(dest);
if (rt==null) { throw new NoRouteException("No route for "+dest.toString());}
ipp.version=4;
ipp.hdr_length=5;
ipp.ttl=(byte)64;
ipp.tos=0;
ipp.fragment_offs=0;
ipp.id=currentId++;
ipp.length=p.data.length+(ipp.hdr_length*4);
ipp.protocol=p.protocol;
if (rt.ni!=null)
{
/* RFC 1122 - MAY send only on the "right" interface. */
ipp.src=rt.ni.ipaddr;
ipp.update();
rt.ni.writeIPPacket(ipp);
return;
}
if (rt.gateway!=null)
{
RoutingTableEntry rtgw = findRoute(rt.gateway);
if (rtgw==null)
{ throw new NoRouteException("No route for "+rt.gateway.toString());}
if (rtgw.ni==null)
{ throw new IllegalRouteException
("Malformed route for "+rt.gateway.toString());}
ipp.src=rtgw.ni.ipaddr;
ipp.update();
rtgw.ni.writeIPPacket(rt.gateway,ipp);
return;
}
throw new IllegalRouteException("Malformed route for "+dest.toString());
}
};