using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Runtime.Serialization.Formatters.Binary; using System.Runtime.Serialization; using System.IO; using System.Drawing; using System.Text.RegularExpressions; namespace EduNetworkBuilder { //This is a network packet that can either contain data, or another packet [Serializable] public class Packet { public PacketType MyType = PacketType.none; public PacketStatus _MyStatus = PacketStatus.processing; //new packets start by being processed by the source device public PacketStatus MyStatus { get { return _MyStatus; } set { _MyStatus = value; if(_MyStatus == PacketStatus.finished_ok) { Tracking.Finished = true; } if (_MyStatus == PacketStatus.finished_failed || _MyStatus == PacketStatus.finished_ok) { string status = _MyStatus.ToString(); PacketDump(" " + status, DebugPausePoint.packet_kill); } if (_MyStatus == PacketStatus.finished_ok) Tracking.Finished = true; } } public int packetID; public int VLANID = NB.UntaggedVLAN; //starts on the management vlan public int TTL = 20; public int TickTTL = 50; public int health = 100; public IPAddress sourceIP; public IPAddress OriginalDestIP; public IPAddress TsourceIP; //This is the local link source ip. It should go along with the local MAC address public IPAddress destIP; public string sourceMAC; public string destMAC; public Packet payloadPacket = null; public string payloadData = ""; //Contains the mac-address, or ip-address string, or something else public string EncryptionString = ""; public IPAddress payloadIP = null; public PacketMessage Tracking = new PacketMessage(); public NetworkComponent WhereAmI = null; public NetworkLink LastNetworkLink = null; public nb_direction myDirection = nb_direction.none; public int myLinkPercent = 0; //How far along the path are we. 0%, 50%, 100%. For moving a dot along the link line public bool packet_good = true; DateTime StartTime = DateTime.Now; public NetworkCard OutboundNic = null; public NetworkCard InboundNic = null; public NetworkInterface InboundInterface = null; public NetworkInterface OutboundIF = null; public IPAddress OutboundIP = new IPAddress(NB.ZeroIPString); public string OutboundMAC = ""; public string OutboundDestMAC = ""; public bool isFresh = false; //Set to be true if the packet is new. Set false as soon as it is processed public bool DebugOn = false; public bool ready_to_delete { get { Tracking.duration = DateTime.Now - StartTime; if (MyStatus == PacketStatus.finished_failed) { packet_good = false; return true; } if (MyStatus == PacketStatus.finished_ok) { packet_good = true; //It should already be good, but we state it just in case return true; } if (MyStatus == PacketStatus.finished) { packet_good = true; //It should already be good, but we state it just in case return true; } return false; } } public Packet(Packet copyfrom) { MyType = copyfrom.MyType; TTL = copyfrom.TTL; sourceIP = copyfrom.sourceIP; TsourceIP = copyfrom.TsourceIP; destIP = copyfrom.destIP; sourceMAC = copyfrom.sourceMAC; destMAC = copyfrom.destMAC; payloadData = copyfrom.payloadData; payloadPacket = copyfrom.payloadPacket; EncryptionString = copyfrom.EncryptionString; payloadIP = copyfrom.payloadIP; Tracking = copyfrom.Tracking; WhereAmI = copyfrom.WhereAmI; health = copyfrom.health; StartTime = copyfrom.StartTime; OriginalDestIP = copyfrom.OriginalDestIP; packetID = copyfrom.packetID; VLANID = copyfrom.VLANID; Tracking.AddMessage(DebugLevel.debug, WhereAmI, NB.Translate("P_PacketDuplicated")); } //Generate a packet with the given payload. public Packet(NetworkComponent start, string source, string dest, string payload, PacketType theType, int NewPacketID=-1) { if (NewPacketID == -1) { packetID = NB.nextPacketID(); } else { packetID = NewPacketID; } WhereAmI = start; payloadData = payload; MyType = theType; if(theType == PacketType.arp_answer || theType == PacketType.arp_request || theType == PacketType.dhcp_request || theType == PacketType.dhcp_answer) { sourceMAC = source; destMAC = dest; OutboundDestMAC = dest; Tracking.AddMessage(DebugLevel.info, start, theType.ToString() + string.Format(NB.Translate("Packet Created"))); Tracking.AddMessage(DebugLevel.routing, start, string.Format(" MAC: {0} -> {1}", source, dest)); } else { sourceIP = new IPAddress(source); TsourceIP = new IPAddress(source); destIP = new IPAddress(dest); if (destIP.BroadcastAddress == destIP.GetIP) { destMAC = NB.BroadcastMACString; OutboundDestMAC = destMAC; } Tracking.AddMessage(DebugLevel.info, start, NB.Translate("Packet Created")); Tracking.AddMessage(DebugLevel.routing, start, string.Format(" IP: {0} -> {1}", source, dest)); Tracking.AddMessage(DebugLevel.debug, start, string.Format(NB.Translate(" IPs Translated {0} -> {1}"),sourceIP.GetIP.ToIpString(), destIP.GetIP.ToIpString())); } isFresh = true; } public Packet(NetworkComponent start, IPAddress dest, string payload, PacketType theType, int NewPacketID = -1) { WhereAmI = start; payloadData = payload; MyType = theType; if (NewPacketID == -1) { packetID = NB.nextPacketID(); } else { packetID = NewPacketID; } if (theType != PacketType.arp_answer && theType != PacketType.arp_request) { sourceIP = new IPAddress(NB.ZeroIPString); destIP = dest; if (destIP != null && destIP.BroadcastAddress == destIP.GetIP) destMAC = NB.BroadcastMACString; Tracking.AddMessage(DebugLevel.info, start, NB.Translate("Packet Created")); Tracking.AddMessage(DebugLevel.routing, start, string.Format(" IP:{0} -> {1}", sourceIP.GetIP.ToIpString(), dest.GetIP.ToIpString())); } else { sourceIP = new IPAddress(NB.ZeroIPString); destMAC = NB.BroadcastMACString; destIP = dest; Tracking.AddMessage(DebugLevel.info, start, NB.Translate("Packet Created")); //Tracking.AddMessage(DebugLevel.routing, start, " IP:" + sourceIP.GetIP.ToIpString() + " -> " + dest.GetIP.ToIpString()); } isFresh = true; } public Point PacketLocation() { if (NB.GetComponentType(WhereAmI) != GeneralComponentType.link) return new Point(-1,-1); NetworkLink Nl = (NetworkLink)WhereAmI; Point mylocation = Nl.PositionOnLine(myDirection, myLinkPercent); return mylocation; } public Rectangle PacketRectangle() { Point start = PacketLocation(); int half = NB.PacketPixelSize / 2; return new Rectangle(start.X - half, start.Y - half, NB.PacketPixelSize, NB.PacketPixelSize); } public void Print(Image BaseImage) { //we draw a packet on the map Point thePoint = PacketLocation(); if (thePoint.X == -1 || thePoint.Y == -1) return; //It is an invalid location Color pencolor = Color.Blue; switch (MyType) { case PacketType.arp_answer: case PacketType.arp_request: pencolor = Color.Green; break; case PacketType.dhcp_answer: case PacketType.dhcp_request: pencolor = Color.Red; break; case PacketType.ping_answer: case PacketType.ping_request: pencolor = Color.Blue; break; case PacketType.tun_packet: pencolor = Color.White; break; case PacketType.vpn_packet: pencolor = Color.Orange; break; } Network theNet = NB.GetNetwork(); if (theNet == null) { Pen myPen = new Pen(pencolor, NB.PacketPixelSize); Graphics.FromImage(BaseImage).DrawEllipse(myPen, PacketRectangle()); } else { Color VLANPacketColor = theNet.ColorFromPacketVLAN(VLANID); //if (VLANPacketColor != Color.Blue) // pencolor = VLANPacketColor; Image tImage = theNet.GetPacketImage(pencolor, VLANPacketColor); //if (VLANPacketColor != Color.Blue && VLANPacketColor != Color.Empty) //{ // tImage = theNet.ColoredImage(tImage, VLANPacketColor); //} Graphics.FromImage(BaseImage).DrawImage(tImage, PacketRectangle()); } } /// /// See if we need to do anything for a packet. If so, do one step in processing it /// public void ProcessTick() { TickTTL--; switch(MyStatus) { case PacketStatus.processing: //The packet is "inside" the device. // Here we masquerade // Here we route // Here the packet is just about to exit. Maybe we need to set the "source IP" if (NB.PacketVersionNum != 2) { DoProcessing(); } else { DoMainProcessing(); } break; case PacketStatus.finished_ok: case PacketStatus.finished_failed: break; //we do not have anything to do. case PacketStatus.input: //Just entering a device. case PacketStatus.moving: //Traversing a link DoMoving(); break; case PacketStatus.output: //Just leaving a device break; case PacketStatus.waiting_for_arp: //We need to see if the arp information has shown up. If so, we resume if (NB.GetComponentType(WhereAmI) == GeneralComponentType.device) { NetworkDevice ndWhere = (NetworkDevice)WhereAmI; IPAddress dest = ndWhere.DestinationFromIP(destIP); string dMAC = ndWhere.ArpFromIP(dest.GetIP.ToIpString()); if (dMAC != "" || destMAC == NB.BroadcastMACString) { MyStatus = PacketStatus.processing; } else { Network MyNet = NB.GetNetwork(); if(MyNet.CountPackets(PacketType.arp_answer) + MyNet.CountPackets(PacketType.arp_request) == 0) { //No more arps going. We do not have an answer! Tracking.AddMessage(DebugLevel.info, WhereAmI, NB.Translate("P_ProcessTick") + ": "+ dest.GetIP.ToIpString()); Tracking.Status = NB.LeftPad(WhereAmI.hostname) + NB.Translate("P_ProcessTick"); MyStatus = PacketStatus.finished_failed; } return; } } break; } } private void DoMainProcessing() { //We pass it to the device if (WhereAmI == null) { AddMessage(DebugLevel.debug, NB.Translate("P_PacketLostLong")); Tracking.Status = NB.Translate("P_PacketLostShort"); MyStatus = PacketStatus.finished_failed; return; //We cannot process the packet } WhereAmI.ProcessPacket(this);//The device knows how to do the processing } private void DoProcessing() { //The packet is "inside" the device. // Here we masquerade // Here we route // Here the packet is just about to exit. Maybe we need to set the "source IP" //We need to find out which interface we are leaving. //Then we figure out what rules we need to follow from there //So, we pass the packet to the device to process if (WhereAmI == null) { AddMessage(DebugLevel.debug, NB.Translate("P_PacketLostLong")); Tracking.Status = NB.Translate("P_PacketLostShort"); MyStatus = PacketStatus.finished_failed; return; //We cannot process the packet } WhereAmI.DoProcessing(this);//The device knows how to do the processing } private void DoMoving() { if (WhereAmI == null) { AddMessage(DebugLevel.debug, NB.Translate("P_PacketLostLong")); Tracking.Status = NB.Translate("P_PacketLostShort"); MyStatus = PacketStatus.finished_failed; return; //We cannot process the packet } WhereAmI.DoMoving(this);//The device knows how to do the processing } public void ReplaceMessage(PacketMessage Tracker) { Tracking = Tracker; //We do this if we are making a new packet, but tracking it with the old one. //We do this for arp requests. } public void StartOnLink(NetworkLink theLink, NetworkDevice start_device) { if (theLink == null) return; //Console.WriteLine("Starting on link: " + theLink.GetUniqueIdentifier + " vlanID = " + VLANID.ToString()); //We are just about to go out. Verify we are not getting blocked by the firewall. if (start_device.FirewallRules.Count > 0) { if (InboundInterface != null && OutboundIF != null) { if (!start_device.FirewallAllows(InboundInterface.nic_name, OutboundIF.nic_name)) { ResponseToPacket rtp = start_device.HowToRespondToPacket(this); if (rtp != ResponseToPacket.accept) { //If we are here, the packet is rejected. string message = string.Format(NB.Translate("P_FirewallDropped"), start_device.hostname); AddMessage(DebugLevel.filtering, message); Tracking.Status = message; Tracking.AddMessage(DebugLevel.info, start_device, message); AddMessage(DebugLevel.info, message); MyStatus = PacketStatus.finished_ok; return; } } } } InboundNic = null; InboundInterface = null; WhereAmI = theLink; LastNetworkLink = theLink; MyStatus = PacketStatus.moving; myLinkPercent = 0; TickTTL = 200; //We keep resetting this as we go. OutboundIF = null; OutboundIP = null; OutboundMAC = ""; OutboundNic = null; if (theLink.IsSource(start_device.GetUniqueIdentifier)) myDirection = nb_direction.to_dst; else myDirection = nb_direction.to_src; //Console.WriteLine(NB.Translate("P_StartingOnLink") + string.Format(" SMAC: {0} DMAC: {1}",sourceMAC,destMAC)); AddMessage(DebugLevel.debug, " " + NB.Translate("P_StartingOnLink")); } public void StartOnDevice(NetworkDevice theDevice) { WhereAmI = theDevice; MyStatus = PacketStatus.processing; myLinkPercent = 0; TickTTL = 200; } public void PrepareToDelete() { Network myNet = NB.GetNetwork(); if(myNet != null) { if (payloadPacket != null) { payloadPacket.PrepareToDelete(); payloadPacket.Tracking.AddMessage(DebugLevel.info, WhereAmI, Tracking.Status); payloadPacket.Tracking.Status = Tracking.Status; payloadPacket.MyStatus = MyStatus; } if(MyType == PacketType.arp_request && MyStatus == PacketStatus.finished_failed) { Tracking.AddMessage(DebugLevel.info, NB.Translate("P_Packet"), NB.Translate("P_PacketFailedToReach") + ": " + destIP.GetIPString); Tracking.Status = NB.Translate("P_PacketFailedToReach2") + ": "+ destIP.GetIPString; MyStatus = PacketStatus.finished_failed; } if (MyStatus != PacketStatus.finished) myNet.AddMessage(Tracking); //We only store finished_failed, and finished_ok //if (sourceIP != null && destIP != null) //{ // if (MyType == PacketType.ping_answer && MyStatus == PacketStatus.finished_failed) // { // myNet.NoteActionDone(NetTestType.FailedPing, destIP.GetIPString, sourceIP.GetIPString); // } // if (MyType == PacketType.ping_request && MyStatus == PacketStatus.finished_failed) // { // myNet.NoteActionDone(NetTestType.FailedPing, sourceIP.GetIPString, destIP.GetIPString); // if(WhereAmI != null) // Console.WriteLine("Dropping at: "+ WhereAmI.hostname); // } //} } } public void AddMessage(DebugLevel tLevel, string tMessage) { Tracking.AddMessage(tLevel, WhereAmI, tMessage); } public void IncrementDistance() { myLinkPercent += NB.LinkStep; } public bool Arrived() { if (myLinkPercent >= 100) return true; return false; } public bool isFinshed() { if (_MyStatus == PacketStatus.finished_ok) return true; if (_MyStatus == PacketStatus.finished_failed) return true; if (_MyStatus == PacketStatus.finished_ok) return true; return false; } private bool debugIsSet(DebugPausePoint what) { DebugPausePoint SetPoint = NB.GetDebugPauseSetting(); if ((SetPoint & what) == what) return true; return false; } public void PacketDump(string hostname, DebugPausePoint WhereWeAre) { DebugPausePoint WhatIsSet = NB.GetDebugPauseSetting(); string position = WhereWeAre.ToString(); string sIP = NB.ZeroIPString; string dIP = NB.ZeroIPString; if (sourceIP != null) sIP = sourceIP.GetIPString; if (destIP != null) dIP = destIP.GetIPString; position = Regex.Replace(position, "packet_", ""); if ((WhereWeAre & WhatIsSet) != WhereWeAre) return; //We are not set to debug here. if ((WhatIsSet & DebugPausePoint.pause) == DebugPausePoint.pause) { Console.WriteLine("Pausing"); } if ((WhatIsSet & DebugPausePoint.dump) == DebugPausePoint.dump) { Console.WriteLine(string.Format("{0}: {1} PACKET: dstIP: {2} destMAC: {3}", hostname, position, dIP, destMAC)); Console.WriteLine(string.Format("{0}: {1} PACKET: srcIP: {2} srcMAC: {3}", hostname, position, sIP, sourceMAC)); Console.WriteLine("---"); } AddMessage(DebugLevel.packet, string.Format("{0}: {1} PACKET: dstIP: {2} destMAC: {3}", hostname, position, dIP, destMAC)); AddMessage(DebugLevel.packet, string.Format("{0}: {1} PACKET: srcIP: {2} srcMAC: {3}", hostname,position,sIP,sourceMAC)); } public static T Clone(T source) { if (!typeof(T).IsSerializable) { throw new ArgumentException(NB.Translate("NC_CloneSerialzable"), NB.Translate("NC_source")); } // Don't serialize a null object, simply return the default for that object if (Object.ReferenceEquals(source, null)) { return default(T); } IFormatter formatter = new BinaryFormatter(); Stream stream = new MemoryStream(); using (stream) { formatter.Serialize(stream, source); stream.Seek(0, SeekOrigin.Begin); return (T)formatter.Deserialize(stream); } } } }