184 lines
5.5 KiB
C#
184 lines
5.5 KiB
C#
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* Microsoft Research, Cambridge
|
|
* author: Yaron Weinsberg, Richard Black
|
|
*/
|
|
|
|
using NetStack.Common;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Diagnostics;
|
|
using System.Net.IP;
|
|
|
|
using Drivers.Net;
|
|
using NetStack.Protocols;
|
|
|
|
using Microsoft.Singularity;
|
|
|
|
namespace NetStack.Runtime
|
|
{
|
|
/**
|
|
* This module implements the ICMP protocol
|
|
*/
|
|
public class IcmpModule : IProtocol
|
|
{
|
|
// the ip handler
|
|
protected IProtocol ip;
|
|
|
|
// INetModule interfaces
|
|
// ------------------------
|
|
string INetModule.ModuleName {get {return "ICMP";} }
|
|
|
|
ushort INetModule.ModuleVersion {get {return 0x01;}} // 0.1
|
|
|
|
[ Conditional("DEBUG_ICMP") ]
|
|
private static void DebugPrint(string format, params object [] args)
|
|
{
|
|
Core.Log(format, args);
|
|
}
|
|
|
|
public bool StartModule()
|
|
{
|
|
DebugPrint("Starting ICMP module...");
|
|
|
|
ip = Core.Instance().GetProtocolByName("IP");
|
|
Debug.Assert(ip!=null);
|
|
return true;
|
|
}
|
|
|
|
public bool StopModule()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
public bool DestroyModule()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// IProtocol interfaces
|
|
// ------------------------
|
|
public bool Initialize(ProtocolParams parameters)
|
|
{
|
|
Debug.Assert(parameters == null || parameters["name"]=="ICMP");
|
|
|
|
Core.Instance().RegisterProtocol(this);
|
|
// no need to register at the packet level!
|
|
return true;
|
|
}
|
|
|
|
public ushort GetProtocolID()
|
|
{
|
|
return ((ushort)IPFormat.Protocol.ICMP);
|
|
}
|
|
|
|
// create a protocol session and register it
|
|
// internally
|
|
public Session CreateSession()
|
|
{
|
|
Session icmp = new IcmpSession(this);
|
|
Core.Instance().RegisterSession(this,icmp);
|
|
// register internally
|
|
// sessions += new Session.OnPacketReceive(icmp.OnReceive);
|
|
return icmp;
|
|
}
|
|
|
|
// the session event dispatching instance
|
|
// public event Session.OnPacketReceive sessions;
|
|
|
|
// handle incoming IP packets
|
|
public NetStatus OnProtocolReceive(NetPacket! pkt)
|
|
{
|
|
// handle ICMP messages
|
|
// ---------------------
|
|
// start analyzing the request
|
|
Multiplexer! mux = (!)Core.Instance().GetMuxForAdapter((IAdapter!)pkt.AdapterContext);
|
|
|
|
// IP should have passed us a context which
|
|
// is the IPHeader... lets see...
|
|
IPFormat.IPHeader! ipHeader = (IPFormat.IPHeader!)pkt.OverlapContext;
|
|
|
|
// read the icmp header
|
|
IcmpFormat.IcmpHeader icmpHeader;
|
|
if (!IcmpFormat.ReadIcmpHeader(pkt, out icmpHeader))
|
|
{
|
|
return NetStatus.Code.PROTOCOL_OK;
|
|
}
|
|
|
|
// handle various types
|
|
switch(icmpHeader.type) {
|
|
case (byte)IcmpFormat.IcmpType.ECHO_REQUEST:
|
|
if (icmpHeader.code == 0) {
|
|
DebugPrint("IcmpModule: Handling ECHO_REQUEST From: {0}", ipHeader.Source);
|
|
|
|
// send reply
|
|
int length = pkt.Length;
|
|
byte [] pktData = new byte [length];
|
|
Array.Copy(pkt.GetRawData(), 0, pktData, 0, length);
|
|
|
|
IcmpFormat.CreateFastEchoReply(
|
|
pktData,
|
|
ipHeader.totalLength-IPFormat.Size
|
|
);
|
|
NetPacket reply = new NetPacket(pktData);
|
|
mux.SendDirect(reply);
|
|
return NetStatus.Code.PROTOCOL_OK;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
DebugPrint("IcmpModule: Dispatching packet to Sessions");
|
|
|
|
// our sessions wants the IP header as well, IP
|
|
// already shrinked the packet for us so no need
|
|
// to shrink the packet
|
|
pkt.Clip(EthernetFormat.Size,ipHeader.totalLength - 1);
|
|
|
|
// fire the event to any interested sessions
|
|
// (we could also use Core.Instance().Sessions to
|
|
// choose a specific session...)
|
|
|
|
// if (sessions != null)
|
|
//{
|
|
//sessions(this, pkt, icmpHeader);
|
|
//}
|
|
|
|
return NetStatus.Code.PROTOCOL_OK;
|
|
}
|
|
|
|
// this method send a ready made ICMP packet (IP level only),
|
|
// it uses the IP layer.
|
|
public NetStatus OnProtocolSend(NetPacket! pkt)
|
|
{
|
|
ip.OnProtocolSend(pkt);
|
|
return NetStatus.Code.PROTOCOL_OK;
|
|
}
|
|
|
|
public NetStatus SetProtocolSpecific(ushort opcode,byte[]! data)
|
|
{
|
|
return NetStatus.Code.PROTOCOL_OK;
|
|
}
|
|
|
|
|
|
public NetStatus GetProtocolSpecific(ushort opcode,out byte[] data)
|
|
{
|
|
data = null;
|
|
return NetStatus.Code.PROTOCOL_OK;
|
|
}
|
|
|
|
// ctor
|
|
public IcmpModule()
|
|
{
|
|
}
|
|
}
|
|
}
|