EduNetworkBuilder/EduNetworkBuilder/NetworkDevice.cs

2282 lines
90 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;
using System.Windows.Forms;
using System.Text.RegularExpressions;
using System.Xml;
namespace EduNetworkBuilder
{
[Serializable]
public class NetworkDevice : NetworkComponent
{
protected List<NetworkCard> NICs = new List<NetworkCard>();
protected IPAddress DefaultGW = new IPAddress(NB.ZeroIPString, NB.ZeroIPString, IPAddressType.gw);
protected Image MyImage = null;
protected Point MyLocation;
protected int Size;
protected List<ArpEntry> ArpTable = new List<ArpEntry>();
protected NetworkComponentType myType = NetworkComponentType.none;
protected List<IPAddress> RouteTable = new List<IPAddress>();
protected List<IPAddress> DHCPRanges = new List<IPAddress>();
protected List<ArpEntry> DHCPLeases = new List<ArpEntry>();
protected List<IPConnectionEntry> IPConnections = new List<IPConnectionEntry>();
protected bool isDNSServer = false;
protected bool isDHCPServer = false;
public bool CanServeDHCP = false;
public bool CanUseDHCP = false;
public bool MustUseDHCP = false;
public bool CanAddNics = false;
public Color BackgroundColor = Color.Empty;
public NetworkDevice(NetworkComponentType what, string tHostname, Point tLocation, NicType firstNic = NicType.eth)
{
hostname = tHostname;
MyLocation = tLocation;
myType = what;
SetImageFromType(what);
NetworkCard tnic = new NetworkCard(0,GetUniqueIdentifier,hostname,NicType.lo);
NICs.Add(tnic);
if (what == NetworkComponentType.net_switch || what == NetworkComponentType.net_hub)
{
if (firstNic != NicType.none)
{
tnic = new NetworkCard(0, GetUniqueIdentifier, hostname, NicType.management_interface);
NICs.Add(tnic);
}
for(int looper=1; looper < 8; looper++)
{
tnic = new NetworkCard(looper, GetUniqueIdentifier, hostname, NicType.port);
NICs.Add(tnic);
}
}
else
{
if (firstNic != NicType.none)
{
tnic = new NetworkCard(0, GetUniqueIdentifier, hostname);
NICs.Add(tnic);
}
if(what == NetworkComponentType.router)
{
tnic = new NetworkCard(1, GetUniqueIdentifier, hostname);
NICs.Add(tnic);
}
//**********Wireless***********
//Add a wireless network card to laptops, wireless bridge and wireless repeater
if (what == NetworkComponentType.laptop )
{
tnic = new NetworkCard(NICs.Count(), GetUniqueIdentifier, hostname,NicType.wlan); //Add a wireless nic
NICs.Add(tnic);
}
if (what == NetworkComponentType.wbridge)
{
NICs.Clear();
tnic = new NetworkCard(0, GetUniqueIdentifier, hostname, NicType.lo);
NICs.Add(tnic);
tnic = new NetworkCard(0, GetUniqueIdentifier, hostname, NicType.management_interface);
NICs.Add(tnic);
tnic = new NetworkCard(NICs.Count(), GetUniqueIdentifier, hostname, NicType.wlan); //Add a wireless nic
NICs.Add(tnic);
//A bridge is a switch with a wireless link, add 4 ports
for (int a = 0; a < 4; a++)
{
tnic = new NetworkCard(NICs.Count(), GetUniqueIdentifier, hostname, NicType.port); //Add a wireless nic
NICs.Add(tnic);
}
}
if (what == NetworkComponentType.wrepeater)
{
NICs.Clear();
tnic = new NetworkCard(0, GetUniqueIdentifier, hostname, NicType.lo);
NICs.Add(tnic);
tnic = new NetworkCard(0, GetUniqueIdentifier, hostname, NicType.management_interface);
NICs.Add(tnic);
tnic = new NetworkCard(NICs.Count(), GetUniqueIdentifier, hostname, NicType.wlan); //Add a wireless nic
NICs.Add(tnic);
tnic = new NetworkCard(NICs.Count(), GetUniqueIdentifier, hostname, NicType.wport); //Add a wireless port
NICs.Add(tnic);
}
if (what == NetworkComponentType.wrouter)
{
NICs.Clear();
tnic = new NetworkCard(0, GetUniqueIdentifier, hostname, NicType.lo);
NICs.Add(tnic);
tnic = new NetworkCard(0, GetUniqueIdentifier, hostname, NicType.management_interface);
NICs.Add(tnic);
//A wireless router has multiple ports
for (int a = 0; a < 4; a++)
{
tnic = new NetworkCard(NICs.Count(), GetUniqueIdentifier, hostname, NicType.port); //Add a switched port
NICs.Add(tnic);
}
for (int a = 0; a < 8; a++)
{
tnic = new NetworkCard(NICs.Count(), GetUniqueIdentifier, hostname, NicType.wport); //Add a wireless port
NICs.Add(tnic);
}
//Add one wan port
tnic = new NetworkCard(0, GetUniqueIdentifier, hostname, NicType.wan);
NICs.Insert(1, tnic); //Make this first in the list
}
if (what == NetworkComponentType.firewall)
{
//Have two lan ports
tnic = new NetworkCard(1, GetUniqueIdentifier, hostname, NicType.eth);
NICs.Add(tnic);
//Add one wan port
tnic = new NetworkCard(0, GetUniqueIdentifier, hostname, NicType.wan);
NICs.Insert(1,tnic); //Make this first in the list
}
}
ApplyRulesToDevice();
}
public int CountNics(NicType TheType)
{
int count = 0;
foreach(NetworkCard nic in NICs)
{
if(nic.GetNicType == TheType)
{
count++;
}
}
return count;
}
public void AddNic(NicType TheType = NicType.eth)
{
NetworkCard tnic;
int count = CountNics(TheType);
tnic = new NetworkCard(count, GetUniqueIdentifier, hostname, TheType);
NICs.Add(tnic);
ApplyRulesToDevice();
}
private void ApplyRulesToDevice()
{
if (myType == NetworkComponentType.server || myType == NetworkComponentType.firewall)
{
CanServeDHCP = true;
CanUseDHCP = false;
MustUseDHCP = false;
CanAddNics = true;
setNicsCanUseDHCP(false);
}
if (myType == NetworkComponentType.router)
{
CanServeDHCP = false;
CanUseDHCP = false;
MustUseDHCP = false;
CanAddNics = true;
setNicsCanUseDHCP(false);
}
if (myType == NetworkComponentType.pc || myType == NetworkComponentType.laptop ||
myType == NetworkComponentType.copier || myType == NetworkComponentType.printer)
{
CanServeDHCP = false;
CanUseDHCP = true;
MustUseDHCP = false;
CanAddNics = true;
setNicsCanUseDHCP(true);
}
if (myType == NetworkComponentType.net_switch || myType == NetworkComponentType.net_hub)
{
CanServeDHCP = false;
CanUseDHCP = true;
MustUseDHCP = false;
CanAddNics = false;
setNicsCanUseDHCP(true);
}
if (myType == NetworkComponentType.ip_phone)
{
CanServeDHCP = false;
CanUseDHCP = true;
MustUseDHCP = true;
CanAddNics = false;
setNicsCanUseDHCP(true);
}
}
private void setNicsCanUseDHCP(bool CanUse)
{
foreach(NetworkCard nic in NICs)
{
//if the device must use DHCP. we set it here.
if (MustUseDHCP && nic.CanUseDHCP)
{
nic.UsesDHCP = true;
nic.MustUseDHCP = true;
}
else
{
//we can only turn it off.
nic.CanUseDHCP = CanUse && nic.CanUseDHCP;
nic.MustUseDHCP = false;
}
}
}
public NetworkDevice(XmlNode theNode)
{
IsDirty = true;
Load(theNode);
SetImageFromType(myType);
}
public override void Destroy()
{
Network myNet = NB.GetNetwork();
NetworkLink nl;
if (myNet != null)
{
foreach(NetworkCard nic in NICs)
{
if(nic.ConnectedLink != -1)
{
nl = myNet.GetLinkFromID(nic.ConnectedLink);
if(nl != null)
{
myNet.RemoveComponent(nl);
}
nic.ConnectedLink = -1;
}
}
}
}
public void EditGateway()
{
DefaultGW.Edit(this,"Default Gateway");
}
public IPAddress GetGateway()
{
if(CanUseDHCP)
{
foreach(NetworkCard nic in NICs)
{
if(nic.UsesDHCP)
{
List<IPAddress> tlist = nic.IPAddressList();
if(tlist.Count > 0)
{
IPAddress newIP = new IPAddress(tlist[0].GetGateway.ToIpString());
return newIP;
}
}
}
}
return DefaultGW;
}
public NetworkComponentType GetNetType()
{
return myType;
}
public override void Load(XmlNode theNode)
{
NetworkCard newNic;
foreach (XmlNode Individual in theNode.ChildNodes)
{
XmlNodeType myNodetype = Individual.NodeType;
if (myNodetype == XmlNodeType.Element)
{
switch(Individual.Name.ToLower())
{
case "location":
string[] pointstr = Individual.InnerText.Split(',');
int x, y;
int.TryParse(pointstr[0], out x);
int.TryParse(pointstr[1], out y);
MyLocation = new Point(x, y);
break;
case "size":
int.TryParse(Individual.InnerText, out Size);
break;
case "uniqueidentifier":
int.TryParse(Individual.InnerText, out UniqueIdentifier);
break;
case "gateway":
DefaultGW = new IPAddress(Individual);
break;
case "hostname":
hostname = Individual.InnerText;
break;
case "mytype":
myType = NB.ParseEnum<NetworkComponentType>(Individual.InnerText);
break;
case "nic":
newNic = new NetworkCard(Individual);
NICs.Add(newNic);
break;
case "route":
IPAddress ip = new IPAddress(Individual);
RouteTable.Add(ip);
break;
case "isdns":
bool.TryParse(Individual.InnerText, out isDNSServer);
break;
case "isdhcp":
bool.TryParse(Individual.InnerText, out isDHCPServer);
break;
case "dhcprange":
IPAddress dhcpip = new IPAddress(Individual);
DHCPRanges.Add(dhcpip);
break;
}
}
}
ApplyRulesToDevice();
}
public override void Save(XmlWriter writer)
{
writer.WriteStartElement("device");
writer.WriteElementString("hostname", hostname);
writer.WriteElementString("size", Size.ToString());
writer.WriteElementString("uniqueidentifier", UniqueIdentifier.ToString());
writer.WriteElementString("location", MyLocation.X.ToString() + "," + MyLocation.Y.ToString());
writer.WriteElementString("mytype", myType.ToString());
writer.WriteElementString("isdns", isDNSServer.ToString());
writer.WriteElementString("isdhcp", isDHCPServer.ToString());
DefaultGW.Save(writer, "gateway");
foreach (NetworkCard nic in NICs)
{
nic.Save(writer);
}
foreach (IPAddress ip in RouteTable)
{
ip.Save(writer, "route");
}
foreach (IPAddress dhcp in DHCPRanges)
{
dhcp.Save(writer, "dhcprange");
}
writer.WriteEndElement();
}
public void SetDNSServer(bool isDNS)
{
isDNSServer = isDNS;
}
public bool GetIsDNSServer()
{
return isDNSServer;
}
public void SetDHCPServer(bool isDHCP)
{
isDHCPServer = isDHCP;
}
public bool GetIsDHCPServer()
{
return isDHCPServer;
}
public string TooltipString()
{
string answer = hostname;
//Add IP Addresses that are assigned
foreach (NetworkCard nic in NICs)
{
foreach(string addr in nic.IPAddresses())
{
answer += "\n" + addr;
}
}
if(BackgroundColor != Color.Empty)
{
//There is something wrong with it?
Network myNet = NB.GetNetwork();
List<string> DeviceMessages = myNet.GetTestMessages(hostname);
foreach (string tString in DeviceMessages)
{
answer += "\n" + tString;
}
}
return answer;
}
public List<string> ListOfConnectedHosts()
{
List<string> thelist = new List<string>();
foreach(NetworkCard nic in NICs)
{
if(nic.ConnectedLink != -1)
{
Network myNet = NB.GetNetwork();
NetworkLink Link = myNet.GetLinkFromID(nic.ConnectedLink);
if(Link != null)
{
NetworkDevice tmp = myNet.GetDeviceFromID(Link.Src);
if (tmp.hostname != hostname) thelist.Add(tmp.hostname);
tmp = myNet.GetDeviceFromID(Link.Dst);
if (tmp.hostname != hostname) thelist.Add(tmp.hostname);
}
}
}
return thelist;
}
public void RemoveLinkTo(string host)
{
Network myNet = NB.GetNetwork();
NetworkLink Link;
NetworkDevice item;
foreach (NetworkCard nic in NICs)
{
if (nic.ConnectedLink != -1)
{
Link = myNet.GetLinkFromID(nic.ConnectedLink);
if (Link != null)
{
item = myNet.GetDeviceFromID(Link.Dst);
if (item.hostname == host)
{
myNet.RemoveComponent(Link);
return;
}
item = myNet.GetDeviceFromID(Link.Src);
if (item.hostname == host)
{
myNet.RemoveComponent(Link);
return;
}
}
}
}
}
/// <summary>
/// Check to see if the device has a link to the specified host
/// </summary>
/// <param name="host"></param>
public bool HasLinkTo(string host)
{
Network myNet = NB.GetNetwork();
NetworkLink Link;
NetworkDevice item;
foreach (NetworkCard nic in NICs)
{
if (nic.ConnectedLink != -1)
{
Link = myNet.GetLinkFromID(nic.ConnectedLink);
if (Link != null)
{
if (Link.theLinkType == LinkType.broken) return false; //A broken link does not work
item = myNet.GetDeviceFromID(Link.Dst);
if (item.hostname == host)
{
return true;
}
item = myNet.GetDeviceFromID(Link.Src);
if (item.hostname == host)
{
return true;
}
}
}
}
return false;
}
private void SetImageFromType(NetworkComponentType what)
{
switch (what)
{
case NetworkComponentType.laptop:
MyImage = Properties.Resources.Laptop;
break;
case NetworkComponentType.pc:
MyImage = Properties.Resources.PC;
break;
case NetworkComponentType.server:
MyImage = Properties.Resources.Server;
break;
case NetworkComponentType.net_hub:
MyImage = Properties.Resources.Hub;
break;
case NetworkComponentType.net_switch:
MyImage = Properties.Resources.Switch;
break;
case NetworkComponentType.wap:
MyImage = Properties.Resources.wap;
break;
case NetworkComponentType.wrepeater:
MyImage = Properties.Resources.WRepeater;
break;
case NetworkComponentType.wbridge:
MyImage = Properties.Resources.WBridge;
break;
case NetworkComponentType.wrouter:
MyImage = Properties.Resources.WRouter;
break;
case NetworkComponentType.router:
MyImage = Properties.Resources.Router;
break;
case NetworkComponentType.ip_phone:
MyImage = Properties.Resources.ip_phone;
break;
case NetworkComponentType.firewall:
MyImage = Properties.Resources.firewall;
break;
case NetworkComponentType.printer:
MyImage = Properties.Resources.Printer;
break;
case NetworkComponentType.copier:
MyImage = Properties.Resources.Copier;
break;
}
}
public bool AtLocation(Point location)
{
if (location.X >= MyLocation.X && location.X <= MyLocation.X + Size &&
location.Y >= MyLocation.Y && location.Y <= MyLocation.Y + Size)
return true;
return false;
}
/// <summary>
/// returns the centerpoint of the device
/// </summary>
/// <returns>a point that is the center of the device</returns>
public Point GetCenter()
{
int delta = Size / 2;
return new Point(MyLocation.X + delta, MyLocation.Y + delta);
}
public void ChangeLocation(Point Location)
{
MyLocation = NB.GetSnapped(Location);
IsDirty = true;
}
public void SetSize(int tSize)
{
if (Size != tSize)
IsDirty = true;
Size = tSize;
}
public void AddNicInterface(int NicIndex)
{
if (NicIndex >= 0 && NicIndex < NICs.Count())
{
NICs[NicIndex].AddInterface();
}
}
public void EditNicInterface(int NicIndex, int ifIndex)
{
if(NicIndex >=0 && NicIndex < NICs.Count())
{
NICs[NicIndex].EditInterface(ifIndex);
}
}
public void DeleteNicInterface(int NicIndex, int ifIndex)
{
if (NicIndex >= 0 && NicIndex < NICs.Count())
{
NICs[NicIndex].DeleteInterface(ifIndex);
}
}
public void EditNicInterface(string NicName, int ifIndex)
{
NetworkCard nic = NicFromName(NicName);
if (nic != null)
{
nic.EditInterface(ifIndex);
}
}
public void EditNic(int index)
{
if (index < 0) return;
if (index > NICs.Count) return;
NICs[index].Edit();
}
public void DeleteNic(int index)
{
if (index < 0) return;
if (index > NICs.Count) return;
if (NICs[index].GetNicType == NicType.lo) return;
if (NICs[index].GetNicType == NicType.management_interface) return;
if (NICs[index].GetNicType == NicType.none) return;
Network theNet = NB.GetNetwork();
if(!theNet.ItemIsLocked(hostname,NICs[index].NicName(),NetTestType.LockNic))
{
if (theNet != null) theNet.RemoveLinksToNic(NICs[index].myID);
NICs.RemoveAt(index);
}
else
{
MessageBox.Show("The network card," + NICs[index].NicName() + " is locked as part of the puzzle.", "Locked NIC");
}
}
public List<string> NetworkCardStrings(bool OnlyUnused=true, bool OnlyLinkable=false)
{
List<string> macStrings = new List<string>();
int counter = 0;
bool CanUse = true;
foreach (NetworkCard nic in NICs)
{
if (OnlyUnused)
CanUse = nic.ConnectedLink == -1; //if it is not linked to anything
if (OnlyLinkable && nic.GetNicType == NicType.vpn) CanUse = false;
if (OnlyLinkable && nic.GetNicType == NicType.tun) CanUse = false;
if (nic.GetNicType != NicType.lo && (nic.GetNicType != NicType.management_interface || OnlyUnused == false))
{
if(CanUse)
macStrings.Add(nic.NicString(counter++));
}
}
return macStrings;
}
public List<string> NetworkCardInterfaceStrings(int index)
{
List<string> myList = new List<string>();
if(index >= 0 && index < NICs.Count)
{
myList.AddRange(NICs[index].IPAddresses());
}
return myList;
}
public List<string> NetworkCardInterfaceStrings(string NicName)
{
List<string> myList = new List<string>();
NetworkCard nic = NicFromName(NicName);
if(nic != null)
{
myList.AddRange(nic.IPAddresses());
}
return myList;
}
public NetworkCard NicFromID(int ID)
{
foreach (NetworkCard nic in NICs)
{
if (nic.GetUniqueIdentifier == ID)
return nic;
}
return null;
}
public NetworkCard NicFromID(HostNicID ID)
{
return NicFromID(ID.NicID);
}
public NetworkCard NicFromName(string name)
{
string tstr = name;
tstr = Regex.Replace(name, " .*", "");
foreach (NetworkCard nic in NICs)
{
if (nic.NicName() == tstr)
return nic;
}
return null;
}
/// <summary>
/// returns true if it has a connection to something.
/// </summary>
/// <returns></returns>
public bool isConnected()
{
return false;
}
private void ValidateSize()
{
if (Size > 200) Size = 200;
if (Size < 10) Size = 10;
}
public void CenterString(Image BaseImage, int x, int y, string ToPrint, Color ToDraw)
{
string measureString = ToPrint;
Font stringFont = new Font("Consolas", 17);
Color othercolor = Color.White;
if (ToDraw == Color.White)
othercolor = Color.Black;
// Measure string.
SizeF stringSize = new SizeF();
Graphics myGraphics = Graphics.FromImage(BaseImage);
stringSize = myGraphics.MeasureString(measureString, stringFont);
Brush myBrush = new SolidBrush(ToDraw);
Brush otherBrush = new SolidBrush(othercolor);
// Draw string to screen.
myGraphics.DrawString(measureString, stringFont, otherBrush, new PointF(x - (stringSize.Width / 2) +1, y +1));
myGraphics.DrawString(measureString, stringFont, myBrush, new PointF(x - (stringSize.Width / 2), y));
}
public override void Print(Image BaseImage, bool DrawTitle)
{
ValidateSize();
if (MyImage == null) return; //nothing to print
if (BaseImage == null) return; //nothing to print on
if (MyLocation.X < 0 || MyLocation.X > BaseImage.Width) return;
if (MyLocation.Y < 0 || MyLocation.Y > BaseImage.Height) return;
Rectangle Location = new Rectangle(MyLocation.X, MyLocation.Y, Size, Size);
if(BackgroundColor != Color.Empty)
{
Brush brush = new SolidBrush(Color.FromArgb(128, BackgroundColor.R, BackgroundColor.G, BackgroundColor.B));
Graphics.FromImage(BaseImage).FillRectangle(brush, Location);
}
Graphics.FromImage(BaseImage).DrawImage(MyImage, MyLocation.X, MyLocation.Y, Size, Size);
if(DrawTitle)
{
int x = MyLocation.X + (Size / 2);
int y = MyLocation.Y + Size - (Size / 6);
int gap = 22;
int counter = 0;
CenterString(BaseImage, x, y + (counter * gap), hostname, Color.Black);
counter++;
foreach (NetworkCard nic in NICs)
{
if(nic.GetNicType != NicType.lo && nic.GetNicType != NicType.port)
{
string title = "";
if (nic.GetNicType == NicType.management_interface)
title += "if: ";
else
title += nic.NicName() + ": ";
foreach(string addr_str in nic.IPAddresses(true))
{
CenterString(BaseImage, x, y + (counter * gap), title + addr_str, Color.Black);
counter++;
}
}
}
}
IsDirty = false; //We printed it, now we are content that we are clean
}
/// <summary>
/// Check all the network cards on this device to see if it has a nic with the given MAC address
/// </summary>
/// <param name="MAC">The MAC address we are looking for</param>
/// <returns>True if we have it, false if we do not.</returns>
public override bool HasMac(string MAC)
{
foreach(NetworkCard nic in NICs)
{
if (nic.MAC == MAC) return true;
}
return false;
}
/// <summary>
/// Get the host nic IDentifier for the specified MAC address
/// </summary>
/// <param name="MacIndex">The index of the network card</param>
/// <returns>The unique host-nic-ID</returns>
public HostNicID GetHostNicID(int MacIndex)
{
if (MacIndex < 0 || MacIndex > NICs.Count())
return new HostNicID(-1, -1, hostname, "");
return NICs[MacIndex].myID;
}
/// <summary>
/// Get the host nic IDentifier for the specified MAC address
/// </summary>
/// <param name="MacIndex">The index of the network card</param>
/// <returns>The unique host-nic-ID</returns>
public List<HostNicID> GetHostNicIDs()
{
List<HostNicID> tList = new List<HostNicID>();
for (int looper = 0; looper < NICs.Count; looper++)
{
tList.Add(NICs[looper].myID);
}
return tList;
}
public bool HasIPAddress(IPAddress dest)
{
foreach(NetworkCard nic in NICs)
{
if (nic.HasIPAddresses(dest))
return true;
}
return false;
}
public IPAddress RouteMatching(IPAddress dest)
{
//If we are comparing a route that has a 'special' netmask, make sure it is the right netmask
foreach (IPAddress ip in RouteTable)
{
if (dest.GetMask != 0 && dest.GetMask.ToIpString() != "255.255.255.0")
{
if (dest.GetMask == ip.GetMask && ip.IsLocal(dest))
return ip;
}
else
{
if (ip.IsLocal(dest))
return ip;
}
}
return null;
}
public bool HasRouteMatching(IPAddress dest)
{
IPAddress matched = RouteMatching(dest);
if (matched != null) return true;
return false;
}
public bool HasRouteMatching(string destString)
{
IPAddress dest = new IPAddress(destString);
if (dest.GetIPString == NB.ZeroIPString) return false;
return HasRouteMatching(dest);
}
public bool HasBroadcastAddress(IPAddress dest)
{
foreach (NetworkCard nic in NICs)
{
if (nic.HasBroadcastAddresses(dest))
return true;
}
return false;
}
public bool HasBroadcastAddress(Packet tPacket)
{
if (tPacket.destMAC == NB.BroadcastMACString) return true;
if (tPacket.destIP.GetIPString == NB.BroadcastIPString) return true;
return HasBroadcastAddress(tPacket.destIP);
}
public bool DoesRouting()
{
if (myType == NetworkComponentType.router) return true;
if (myType == NetworkComponentType.firewall) return true;
if (myType == NetworkComponentType.wap) return true;
return false;
}
public bool DoesForwarding()
{
if (myType == NetworkComponentType.net_hub) return true;
if (myType == NetworkComponentType.net_switch) return true;
if (myType == NetworkComponentType.wap) return true;
return false;
}
public override List<string> arp(UInt32 IP)
{
List<string> arps = new List<string>();
foreach (NetworkCard nic in NICs)
{
if (nic.HasIP(IP)) arps.Add(nic.MAC);
}
return arps;
}
public override void UpdateFromComponent(NetworkComponent CopyFrom)
{
if (CopyFrom.GetType() != this.GetType()) return; //we cannot copy from it if it is different
NetworkDevice ndCopyFrom = (NetworkDevice)CopyFrom;
hostname = ndCopyFrom.hostname;
Size = ndCopyFrom.Size;
DefaultGW = ndCopyFrom.DefaultGW;
MyImage = new Bitmap(ndCopyFrom.MyImage);
CanAddNics = ndCopyFrom.CanAddNics;
CanServeDHCP = ndCopyFrom.CanServeDHCP;
CanUseDHCP = ndCopyFrom.CanUseDHCP;
MustUseDHCP = ndCopyFrom.MustUseDHCP;
isDHCPServer = ndCopyFrom.isDHCPServer;
isDNSServer = ndCopyFrom.isDNSServer;
MyLocation = ndCopyFrom.MyLocation;
NICs.Clear();
foreach(NetworkCard nic in ndCopyFrom.NICs)
{
NICs.Add(NetworkCard.Clone(nic));
}
RouteTable.Clear();
RouteTable.AddRange(ndCopyFrom.RouteTable);
DHCPRanges.Clear();
DHCPRanges.AddRange(ndCopyFrom.DHCPRanges);
DHCPLeases.Clear();
DHCPLeases.AddRange(ndCopyFrom.DHCPLeases);
}
public void DHCPRequestFromHere()
{
bool tryit = false;
if (CanUseDHCP)
{
foreach (NetworkCard tnic in NICs)
{
if (tnic.UsesDHCP)
tryit = true;
}
}
if (tryit)
{
//We need to create a packet
foreach (NetworkCard nic in NICs)
{
nic.SetIPForDHCP(); //clear the source IP
}
Packet DHCPPacket = new Packet(this, "", NB.BroadcastMACString, "DHCP Request", PacketType.dhcp_request);
DHCPPacket.destIP = new IPAddress(NB.BroadcastIPString);
Network myNet = NB.GetNetwork();
myNet.addPacket(DHCPPacket);
}
}
public void PingFromHere(IPAddress Destination)
{
//We need to create a packet
Packet PingPacket = new Packet(this,Destination,"Ping",PacketType.ping_request);
Network myNet = NB.GetNetwork();
myNet.addPacket(PingPacket);
}
public void AskArpFromHere(IPAddress Destination, PacketMessage Tracker=null)
{
//We need to create a packet
Packet ArpPacket = new Packet(this, Destination, "Arp Request", PacketType.arp_request);
if (Tracker != null)
ArpPacket.ReplaceMessage(Tracker);
Network myNet = NB.GetNetwork();
myNet.addPacket(ArpPacket);
}
public void TunnelPacketFromHere(IPAddress Destination, Packet Payload, string Encryption = "")
{
PacketType TunType = PacketType.tun_packet;
if (Encryption != "")
TunType = PacketType.vpn_packet;
Packet TunnelPacket = new Packet(this, Destination, "Tunnel", TunType);
TunnelPacket.payloadPacket = Payload;
TunnelPacket.EncryptionString = Encryption;
if(Payload != null)
Payload.Tracking.AddMessage(DebugLevel.info, this, "Packet going into tunnel.");
Network myNet = NB.GetNetwork();
myNet.addPacket(TunnelPacket);
}
public void StoreOutgoingPacketInfo(Packet tpacket, ResponseToPacket response = ResponseToPacket.accept)
{
IPConnectionEntry ipc;
if (response == ResponseToPacket.accept)
{
ipc = new IPConnectionEntry(tpacket.destIP, tpacket.MyType, ResponseToPacket.accept);
}else
{
ipc = new IPConnectionEntry(tpacket.destIP, tpacket.MyType, ResponseToPacket.masq, tpacket.sourceIP);
}
IPConnections.Add(ipc);
}
public void ClearIPConnectionInfo()
{
IPConnections.Clear();
}
public ResponseToPacket HowToRespondToPacket(Packet tPacket)
{
bool typesMatch=false;
foreach(IPConnectionEntry ipc in IPConnections)
{
if(ipc.destIP.GetIP == tPacket.sourceIP.GetIP || HasBroadcastAddress(ipc.destIP))
{
if (ipc.What == PacketType.arp_request && tPacket.MyType == PacketType.arp_answer)
typesMatch = true;
if (ipc.What == PacketType.dhcp_request && tPacket.MyType == PacketType.dhcp_answer)
typesMatch = true;
if (ipc.What == PacketType.ping_request && tPacket.MyType == PacketType.ping_answer)
typesMatch = true;
if(typesMatch)
{
return ipc.Response;
}
}
}
//If we get here, we were not expecting the packet
return ResponseToPacket.reject;
}
public IPAddress PacketMasqueradeSource(Packet tPacket)
{
bool typesMatch = false;
foreach (IPConnectionEntry ipc in IPConnections)
{
if (ipc.destIP.GetIP == tPacket.sourceIP.GetIP && ipc.Response == ResponseToPacket.masq)
{
if (ipc.What == PacketType.ping_request && tPacket.MyType == PacketType.ping_answer)
typesMatch = true;
if (typesMatch)
{
return ipc.internalIP;
}
}
}
//If we get here, we were not expecting the packet
return null;
}
public override void ProcessPacket(Packet tPacket)
{
//Psuedo code for processing a packet
//We have already come in the interface and nic
//We will set the outbound nic in this process here
//All packets terminate in the device and either stop or are duplicated and sent out the next link
//Store the nic this came from so we skip sending the packet back out the same one
// We only skip sending it out the same one if it is a port.
//See if it arrives here.
// We route it if the dmac is this machine, but the dstIP does not match the IP of this machine
// if the dstIP matches exactly, it ends here.
// if the dstIP matches (broadcast), we process it but it still continues
// Set the "we have processed it" flag
// and we process arrival
bool MacAddressMatch = HasMac(tPacket.destMAC);
bool ExactMatch = HasIPAddress(tPacket.destIP);
bool BroadcastMatch = HasBroadcastAddress(tPacket.destIP);
bool NeedsRouting = MacAddressMatch && (!ExactMatch && !BroadcastMatch);
if(ExactMatch || BroadcastMatch)
{
//Change this. Need a new ProcessArrival
ProcessArrival(tPacket);
if (ExactMatch && tPacket.isFinshed())
return;
}
if (tPacket.DebugOn)
Console.WriteLine("Debug");
//Routing
//if we are supposed to route (do-not-route flag not set) or if the packet is "fresh"
// determine which nic it is supposed to exit.
// loop through all the routes and nics to see if local delivery or if we use a gateway
if(MacAddressMatch || tPacket.isFresh)
{
//It was destined for here, or it is starting from scratch. See if we need to route it.
if (tPacket.destIP == null) tPacket.destIP = new IPAddress(NB.ZeroIPString);
IPAddress dest = DestinationFromIP(tPacket.destIP); //Get the IP, or GW
if(dest.GetIPString == NB.ZeroIPString && tPacket.destIP.GetIPString != NB.BroadcastIPString)
{
//No gateway set and no route...
tPacket.AddMessage(DebugLevel.info, hostname + " No route to host: " + tPacket.destIP.GetIPString);
tPacket.Tracking.Status = hostname + " No route to host: " + tPacket.destIP.GetIPString;
tPacket.MyStatus = PacketStatus.finished_failed;
return;
}
if(dest.GetIP == tPacket.destIP.GetIP)
{
//It is a local packet. Let it go out the interface it needs to go out
tPacket.OutboundIP = tPacket.destIP;
}
else if(tPacket.destIP.GetIPString != NB.BroadcastIPString)
{
//it needs to go to a gateway. Set the next destination is the GW
tPacket.OutboundIP = dest;
}
else
{
tPacket.OutboundIP = tPacket.destIP;
}
}
NetworkCard dNic = null;
NetworkCard sNic = null;
if (DoesForwarding())
{
foreach (ArpEntry arp in ArpTable)
{
if (arp.MACAddress == tPacket.destMAC)
{
dNic = NicFromID(arp.NicOnWhichItIsFound);
}
if (arp.MACAddress == tPacket.sourceMAC)
{
sNic = NicFromID(arp.NicOnWhichItIsFound);
}
}
}
if (myType == NetworkComponentType.net_hub || myType == NetworkComponentType.wap)
dNic = null; //Hubs/WAPs never know the dnic. They still need the sNic, however
//Delivery
//Loop through all nics (skip the interface) it came in on
// if it is a port, gen a new packet and send it out the port
// if it is broadcast, or if we have not processed it.
// if it is lo or management interface, skip the nic
// if it is a nic and we are supposed to route it, pass it to the nic.
// The nic will send it out all its interfaces
// If we need arp, the nic/interface holds onto it until the arp returns
// Store the nic on the packet, store the interface on the packet
// Resume processing at the nic level, not the device level when the arp comes back
int count = 0;
foreach(NetworkCard nic in NICs)
{
switch(nic.GetNicType)
{
case NicType.lo:
case NicType.management_interface:
case NicType.none:
break; //Do nothing
case NicType.eth:
case NicType.tun:
case NicType.vpn:
case NicType.wan:
//If the packet is a new packet and is not connecting to itself
//or, if it is routing away.
if ((tPacket.isFresh && !ExactMatch ) || (NeedsRouting && DoesRouting()))
{
//Pass it to the NIC to send out each nic+interface.
//The nic checks to see if it works and then processes it
if (BroadcastMatch && tPacket.MyType != PacketType.dhcp_answer)
tPacket.OutboundDestMAC = NB.BroadcastMACString;
tPacket.destMAC = tPacket.OutboundDestMAC;
if(nic.SendPacketOutNIC(tPacket))
{
count++;
}
}
break;
case NicType.port:
if(!ExactMatch && !MacAddressMatch)
{
//If the packet does not terminate here, and we are not routing it to here...
//Pass it to the port. The port duplicates it and sends it out
//Do not send it out the port it came in on (sNic)
//If we know the dNic, only send it out that
//But if we do not know a dnic, send it out all of them (except the sNic)
if (sNic != nic && (dNic == null || (dNic != null && dNic.ConnectedLink == -1) || dNic == nic))
{
if (nic.SendPacketOutNIC(tPacket))
{
count++;
}
}
}
break;
}
}
//The packet has either been duplicated or has finished
if(count == 0)
{
if (tPacket.destMAC == "")
{
if (tPacket.MyType == PacketType.arp_request)
{
//The packet was not successfully sent anywhere. DMac = "". This means no host with the specified IP
tPacket.AddMessage(DebugLevel.info, hostname + " Failed: No such IP on the local network - Arp only searches the local network.");
tPacket.Tracking.Status = hostname + " Failed: No such IP on the local network.";
tPacket.MyStatus = PacketStatus.finished_failed;
}
else
{
//The packet was not successfully sent anywhere. DMac = "". This means no host with the specified IP
tPacket.AddMessage(DebugLevel.info, hostname + " Failed: No such IP.");
tPacket.Tracking.Status = hostname + " Failed: No such IP.";
tPacket.MyStatus = PacketStatus.finished_failed;
}
}
else
{
//The packet was not successfully sent anywhere. No interface to send out the packet
tPacket.AddMessage(DebugLevel.info, hostname + " No local interface to send packet out.");
tPacket.Tracking.Status = hostname + " No local interface to send packet out";
tPacket.MyStatus = PacketStatus.finished_failed;
}
}
if (tPacket.MyStatus != PacketStatus.finished_failed && tPacket.MyStatus != PacketStatus.finished_ok)
{
tPacket.MyStatus = PacketStatus.finished;
}
}
public void ProcessArrival(Packet tPacket)
{
Packet nPacket;
Network myNet = NB.GetNetwork();
if (tPacket.MyType == PacketType.tun_packet || tPacket.MyType == PacketType.vpn_packet)
{
tPacket.Tracking.AddMessage(DebugLevel.info,this,"Arrived at the tunnel endpoint.");
tPacket.Tracking.Status = "Arrived at the tunnel endpoint.";
//We If the encryption matches, we succeed. Otherwise, we fail
tPacket.MyStatus = PacketStatus.finished_ok; //It stops here
nPacket = tPacket.payloadPacket;
NetworkCard nc = LocalNic(nPacket.TsourceIP, true);
if (nc != null)
{
if (nPacket != null)
{
if(nPacket.destMAC != nc.MAC)
{
nPacket.Tracking.Status = "No VPN nic to recieve packet. Check VPN IP";
nPacket.Tracking.AddMessage(DebugLevel.info, this, "No corresponding IP on vpn. Packet dropped.");
nPacket.MyStatus = PacketStatus.finished_failed;
myNet.addPacket(nPacket); //so it gets pulled out apropriately
tPacket.payloadPacket = null;
return;
}
else
if (tPacket.EncryptionString == nc.EncryptionKey)
{
nPacket.destMAC = nc.MAC; //This is already the case, but we need to set it again for some reason.
nPacket.MyStatus = PacketStatus.processing;
nPacket.WhereAmI = this;
nPacket.Tracking.AddMessage(DebugLevel.info, this, "Packet coming out from tunnel.");
myNet.addPacket(nPacket);
tPacket.payloadPacket = null;
return;
}
else
{
nPacket.Tracking.Status = "Encryption failed. Unable to decrypt. Packet dropped.";
nPacket.Tracking.AddMessage(DebugLevel.info, this, "Encryption key mismatch. Packet dropped.");
nPacket.MyStatus = PacketStatus.finished_failed;
myNet.addPacket(nPacket); //so it gets pulled out apropriately
tPacket.payloadPacket = null;
return;
}
}
else
{
//There is no nic that matches the incoming IP
nPacket.Tracking.Status = "No VPN nic to recieve packet. Check VPN IP";
nPacket.Tracking.AddMessage(DebugLevel.info, this, "No corresponding IP on vpn. Packet dropped.");
nPacket.MyStatus = PacketStatus.finished_failed;
myNet.addPacket(nPacket); //so it gets pulled out apropriately
return;
}
}
}
if (tPacket.MyType == PacketType.ping_request)
{
myNet.RegisterTimeOfArrival();
nPacket = new Packet(this,tPacket.sourceIP,"",PacketType.ping_answer);
nPacket.OriginalDestIP = tPacket.destIP;
nPacket.isFresh = true; //So it starts from here
nPacket.Tracking = new PacketMessage();
myNet.addPacket(nPacket);
tPacket.AddMessage(DebugLevel.info, "Success! The ping reached the destination.");
tPacket.Tracking.Status = hostname + ":\tPing success: The ping reached the destination." + tPacket.sourceIP.GetIP.ToIpString() + " -> " + tPacket.destIP.GetIP.ToIpString();
tPacket.MyStatus = PacketStatus.finished_ok;
IPAddress tip = nPacket.sourceIP;
if (!HasBroadcastAddress(tPacket.destIP))
{
nPacket.sourceIP = tPacket.destIP;
nPacket.TsourceIP = tPacket.destIP;
}
else
{
nPacket.sourceIP = new IPAddress(NB.ZeroIPString);
nPacket.TsourceIP = new IPAddress(NB.ZeroIPString);
}
if (tip.GetIP.ToIpString() != NB.ZeroIPString)
nPacket.destIP = tip;
if (tPacket.isFresh)
{
//The packet reached itself. At this moment, the packet does not yet have the source information set
//We just need to set the dest
//
nPacket.destIP = new IPAddress(NB.LoopbackIPString);
}
if (myType == NetworkComponentType.net_hub || myType == NetworkComponentType.net_switch)
{
//put mac of management interface on packet
//dmac is originating mac
nPacket.destMAC = tPacket.sourceMAC;
nPacket.OutboundDestMAC = tPacket.sourceMAC;
nPacket.sourceMAC = HubManagementMAC();
}
else
{
nPacket.destMAC = "";
nPacket.sourceMAC = "";
}
nPacket.MyType = PacketType.ping_answer;
nPacket.MyStatus = PacketStatus.processing;
return;
}
if (tPacket.MyType == PacketType.ping_answer)
{
ResponseToPacket response = HowToRespondToPacket(tPacket);
if (response == ResponseToPacket.accept || HasIPAddress(tPacket.destIP))
{
tPacket.AddMessage(DebugLevel.info, "Success! The ping returned from its destination.");
tPacket.Tracking.Status = hostname + ":\tPing success: The ping returned from its destination" + tPacket.sourceIP.GetIP.ToIpString() + " -> " + tPacket.destIP.GetIP.ToIpString();
tPacket.MyStatus = PacketStatus.finished_ok;
if (tPacket.sourceIP.GetIP != 0)
{
myNet.NotePacketArrived(tPacket.MyType, this, tPacket.destIP, tPacket.OriginalDestIP);
}
else
{
myNet.NotePacketArrived(tPacket.MyType, this, tPacket.destIP, tPacket.sourceIP);
}
}
else
{
tPacket.AddMessage(DebugLevel.info, "ERROR! A packet returned to a machine that we were not expecting it from.");
tPacket.Tracking.Status = hostname + ":\tPing failed: Arrived at a machine that was not expecting it and was rejected." + tPacket.sourceIP.GetIP.ToIpString() + " -> " + tPacket.destIP.GetIP.ToIpString();
tPacket.MyStatus = PacketStatus.finished_failed;
}
return;
}
if(tPacket.MyType == PacketType.arp_request)
{
//The arp request may not be asking for this IP.
if(HasIPAddress(tPacket.destIP))
{
nPacket = new Packet(tPacket);
nPacket.isFresh = true; //So it starts from here
nPacket.Tracking = new PacketMessage();
myNet.addPacket(nPacket);
NetworkCard nic = LocalNic(nPacket.sourceIP);
HostNicID theID = new HostNicID();
if (nic != null) theID = nic.myID;
if (nPacket.TsourceIP == null) nPacket.TsourceIP = nPacket.sourceIP;
StoreArp(nPacket.sourceMAC, nPacket.TsourceIP.GetIP.ToIpString(), theID);
//This is the IP we are looking for, send response back
IPAddress tip = nPacket.sourceIP;
nPacket.sourceIP = nPacket.destIP;
nPacket.TsourceIP = nPacket.destIP;
nPacket.destIP = tip;
if (myType == NetworkComponentType.net_hub || myType == NetworkComponentType.net_switch)
{
//put mac of management interface on packet
//dmac is originating mac
nPacket.destMAC = nPacket.sourceMAC;
nPacket.OutboundDestMAC = nPacket.sourceMAC;
List<string> tstrings = new List<string>();
foreach(NetworkCard tNic in NICs)
{
tstrings.Clear();
tstrings.AddRange(tNic.IPAddresses());
if (tstrings.Count > 0 && !Regex.IsMatch(tstrings[0], "127.0.0.1"))
{
nPacket.sourceMAC = tNic.MAC;
break;
}
}
}
else
{
nPacket.destMAC = "";
tPacket.sourceMAC = "";
}
nPacket.MyType = PacketType.arp_answer;
nPacket.MyStatus = PacketStatus.processing;
tPacket.AddMessage(DebugLevel.info, "Success! The arp request reached the destination.");
tPacket.Tracking.Status = hostname + ":\tArp Request found IP: " + tPacket.sourceIP.GetIPString + " on MAC: "+ nPacket.sourceMAC;
tPacket.MyStatus = PacketStatus.finished_ok;
}
else
{
tPacket.MyStatus = PacketStatus.finished; //We just drop it
}
return;
}
if (tPacket.MyType == PacketType.arp_answer)
{
ResponseToPacket response = HowToRespondToPacket(tPacket);
if (response == ResponseToPacket.accept)
{
NetworkCard nic = LocalNic(tPacket.destIP);
HostNicID myid = nic.myID;
StoreArp(tPacket.sourceMAC, tPacket.TsourceIP.GetIP.ToIpString(), myid);
tPacket.Tracking.Status = hostname + ":\tArp request success: Who Has " + tPacket.sourceIP.GetIP.ToIpString() + " tell " + tPacket.sourceIP.GetIP.ToIpString() + " = " + tPacket.sourceMAC;
tPacket.MyStatus = PacketStatus.finished_ok; //Yay!
myNet.NotePacketArrived(tPacket.MyType, this, tPacket.destIP, tPacket.sourceIP);
}
else
{
tPacket.AddMessage(DebugLevel.info, "ERROR! A packet returned to a machine that we were not expecting it from.");
tPacket.Tracking.Status = hostname + ":\tARP failed: Arrived at a machine that was not expecting it and was rejected." + tPacket.sourceIP.GetIP.ToIpString() + " -> " + tPacket.destIP.GetIP.ToIpString();
tPacket.MyStatus = PacketStatus.finished_failed;
}
return;
}
if(tPacket.MyType == PacketType.dhcp_request && isDHCPServer)
{
nPacket = new Packet(tPacket);
nPacket.isFresh = true; //So it starts from here
nPacket.Tracking = new PacketMessage();
myNet.addPacket(nPacket);
//We need to find a dhcp IP for this.
IPAddress dst = RequestDHCPLease(tPacket.sourceMAC, tPacket.OutboundIP);
string tmac = nPacket.sourceMAC;
nPacket.sourceMAC = tPacket.OutboundMAC;
nPacket.sourceIP = tPacket.OutboundIP;
nPacket.destMAC = tmac;
nPacket.OutboundDestMAC = tmac;
nPacket.payloadIP = dst;
nPacket.MyType = PacketType.dhcp_answer;
nPacket.OutboundMAC = "";
nPacket.OutboundIP = null;
nPacket.MyStatus = PacketStatus.processing;
tPacket.AddMessage(DebugLevel.info, "Success! The DHCP request reached a DHCP Server.");
tPacket.Tracking.Status = hostname + ":\tDHCP Request found Server: " + nPacket.sourceIP.GetIPString;
tPacket.MyStatus = PacketStatus.finished_ok;
return;
}
if (tPacket.MyType == PacketType.dhcp_answer)
{
ResponseToPacket response = HowToRespondToPacket(tPacket);
if (response == ResponseToPacket.accept)
{
NetworkCard tnic = tPacket.OutboundNic;
if (tnic == null)
tnic = HubManagementCard();
if (tnic != null)
{
if (tPacket.payloadIP == null)
tPacket.payloadIP = new IPAddress(NB.ZeroIPString);
tnic.SetIPForDHCP(tPacket.payloadIP);
IsDirty = true; //If we need to redraw the device IP
tPacket.Tracking.Status = hostname + ":\tDHCP request/answer. " + tPacket.payloadIP.GetIP.ToIpString();
tPacket.MyStatus = PacketStatus.finished_ok; //Yay!
myNet.NotePacketArrived(tPacket.MyType, this, tPacket.payloadIP, tPacket.sourceIP);
return;
}
}
else
{
tPacket.AddMessage(DebugLevel.info, "ERROR! A packet returned to a machine that we were not expecting it from.");
tPacket.Tracking.Status = hostname + ":\tDHCP Request failed: Arrived at a machine that was not expecting it and was rejected." + tPacket.sourceIP.GetIP.ToIpString() + " -> " + tPacket.destIP.GetIP.ToIpString();
tPacket.MyStatus = PacketStatus.finished_failed;
}
return;
}
//Fall-through, if nothing else happens
tPacket.MyStatus = PacketStatus.finished; //Different things may have different finished things.
}
public IPAddress LocalDeviceIP(NetworkDevice FromWhat)
{
NetworkInterface nif;
List<IPAddress> myList = FromWhat.IPAddressList();
foreach (IPAddress ip in myList.ToList())
{
foreach (NetworkCard tNic in NICs)
{
if (tNic.GetNicType == NicType.lo) continue; //Don't check loopback nics
if (tNic.GetNicType == NicType.port) continue; //Don't check ports
nif = tNic.LocalInterface(ip, null);
if(nif != null && nif.myIP.GetIPString != NB.ZeroIPString)
{
return nif.myIP;
}
}
}
//If we get here, we do not have a local IP
return null;
}
public IPAddress HubManagementIP()
{
List<IPAddress> IPAddresses = new List<IPAddress>();
foreach (NetworkCard tNic in NICs)
{
if(tNic.GetNicType == NicType.management_interface)
{
IPAddresses.AddRange(tNic.IPAddressList());
}
}
if (IPAddresses.Count > 0)
return IPAddresses[0];
return null;
}
public NetworkCard HubManagementCard()
{
foreach (NetworkCard tNic in NICs)
{
if (tNic.GetNicType == NicType.management_interface)
{
return tNic;
}
}
return null;
}
public string HubManagementMAC()
{
foreach(NetworkCard nic in NICs)
{
if (nic.GetNicType == NicType.management_interface)
return nic.MAC;
}
return null;
}
public List<IPAddress> IPAddressList()
{
List<IPAddress> thelist = new List<IPAddress>();
foreach(NetworkCard nic in NICs)
{
thelist.AddRange(nic.IPAddressList());
}
return thelist;
}
public List<string> SubnetList()
{
List<string> thelist = new List<string>();
foreach(IPAddress taddr in IPAddressList())
{
if(!thelist.Contains(taddr.NetworkAddress.ToIpString()))
{
thelist.Add(taddr.NetworkAddress.ToIpString());
}
}
return thelist;
}
public List<string> BroadcastList()
{
List<string> thelist = new List<string>();
foreach (IPAddress taddr in IPAddressList())
{
if (!thelist.Contains(taddr.BroadcastAddress.ToIpString()))
{
thelist.Add(taddr.BroadcastAddress.ToIpString());
}
}
return thelist;
}
/// <summary>
/// Return either the destination IP or the gateway IP
/// </summary>
/// <param name="dest">The target IP</param>
/// <returns>The IP the packet should be going to</returns>
public IPAddress DestinationFromIP(IPAddress dest, NetworkCard oNic = null)
{
NetworkInterface nIF = null;
NetworkCard tCard = null;
IPAddress DestAddr;
string DHCPGW = "";
foreach( IPAddress ip in RouteTable)
{
if (ip.IsLocal(dest))
return new IPAddress(ip.GetGateway.ToIpString());//We return the gateway
}
foreach (NetworkCard nic in NICs)
{
tCard = nic;
if(nic.UsesDHCP && nic.CanUseDHCP && DHCPGW == "")
{
DHCPGW = nic.FirstIP().GetGateway.ToIpString();
}
nIF = nic.LocalInterface(dest,null);
if (nIF != null && nIF.myIP.GetIPString != NB.ZeroIPString)
{
DestAddr = dest; //We found it. Send it to the destination
return DestAddr;
}
}
if (oNic != null)
{
List<IPAddress> tlist = oNic.IPAddressList();
if(tlist.Count > 0 && tlist[0].GetGateway.ToIpString() != NB.ZeroIPString)
{
return new IPAddress(tlist[0].GetGateway.ToIpString());
}
}
if (DHCPGW != "")
return new IPAddress(DHCPGW);
//if we get here, we do not know where to send it. Use the default gw.
return DefaultGW;
}
public bool PrepPacketForSending(Packet tPacket, IPAddress dest)
{
if((tPacket.OutboundMAC == null || tPacket.OutboundMAC == "") &&
tPacket.MyType == PacketType.dhcp_request &&
(tPacket.sourceMAC == "" || tPacket.sourceMAC == null))
{
//
Network myNet = NB.GetNetwork();
foreach(NetworkCard nic in NICs)
{
//Make one DHCP request for every nic that is a DHCP nic
if(nic.UsesDHCP && CanUseDHCP)
{
nic.SetIPForDHCP();
Packet nPacket = new Packet(tPacket);
nPacket.OutboundIP = new IPAddress(NB.ZeroIPString);
nPacket.OutboundMAC = nic.MAC;
nPacket.OutboundNic = nic;
nPacket.OutboundIF = nic.GetInterface(0);
nPacket.Tracking = new PacketMessage(); //we are starting. Each one should have a different tracker
myNet.addPacket(nPacket);
}
}
tPacket.MyStatus = PacketStatus.finished; //we have replaced it with other ones
return false;
}
if ((tPacket.OutboundMAC == null || tPacket.OutboundMAC == "") &&
HasBroadcastAddress(tPacket.destIP) &&
(tPacket.sourceMAC == "" || tPacket.sourceMAC == null))
{
//
Network myNet = NB.GetNetwork();
foreach (NetworkCard nic in NICs)
{
if (!nic.HasIP(new IPAddress("127.0.0.1").GetIP)) //don't bother pinging on the loopback
{
//Make one Broadcast ping for every nic that has an IP
Packet nPacket = new Packet(tPacket);
nPacket.OutboundIP = new IPAddress(NB.ZeroIPString);
nPacket.OutboundMAC = nic.MAC;
nPacket.destMAC = NB.BroadcastMACString;
nPacket.OutboundNic = nic;
nPacket.OutboundIF = nic.GetInterface(0);
nPacket.Tracking = new PacketMessage(); //we are starting. Each one should have a different tracker
myNet.addPacket(nPacket);
}
}
tPacket.MyStatus = PacketStatus.finished; //we have replaced it with other ones
return false;
}
if (tPacket.OutboundIP == null || tPacket.OutboundIP.GetIP.ToIpString() == NB.ZeroIPString && tPacket.MyType != PacketType.dhcp_request)
{
tPacket.OutboundIP = DestinationFromIP(dest,tPacket.OutboundNic);
if (tPacket.OutboundIP.GetIP.ToIpString() == NB.ZeroIPString)
{
if (tPacket.MyType == PacketType.dhcp_answer)
{
tPacket.AddMessage(DebugLevel.info, hostname + " ERROR: DHCP Server does not have gateway set. DHCP server failing" + tPacket.OutboundIP.GetIP.ToIpString());
tPacket.Tracking.Status = hostname + " ERROR: DHCP Server does not have gateway set. DHCP server failing";
tPacket.MyStatus = PacketStatus.finished_failed;
return false;
}
else
{
tPacket.AddMessage(DebugLevel.info, hostname + " ERROR: No route or local interface for packet. " + tPacket.OutboundIP.GetIP.ToIpString());
tPacket.Tracking.Status = hostname + " No route or local interface for packet.";
tPacket.MyStatus = PacketStatus.finished_failed;
return false;
}
}
}
//If we get here, we have the local destination (dest or gateway) we are looking for.
//Now we find the nic and interface
if (tPacket.OutboundNic == null)
{
tPacket.OutboundNic = LocalNic(tPacket.OutboundIP);
if (tPacket.OutboundNic == null)
{
tPacket.AddMessage(DebugLevel.info, hostname + " ERROR: No local Network Card for packet. :" + tPacket.OutboundIP.GetIP.ToIpString());
tPacket.Tracking.Status = hostname + " No route or local network card for packet.";
tPacket.MyStatus = PacketStatus.finished_failed;
return false;
}
}
//If we get here, the nic is not null. Find the IF corresponding to the outbound IP
if (tPacket.OutboundIF == null)
{
tPacket.OutboundIF = tPacket.OutboundNic.LocalInterface(tPacket.OutboundIP, tPacket.Tracking);
if (tPacket.OutboundIF == null)
{
tPacket.AddMessage(DebugLevel.info, hostname + " ERROR: No local interface for packet. :" + tPacket.OutboundIP.GetIP.ToIpString());
tPacket.Tracking.Status = hostname + " No route or local interface for packet.";
tPacket.MyStatus = PacketStatus.finished_failed;
return false;
}
}
tPacket.TsourceIP = tPacket.OutboundIF.myIP;
//
if (tPacket.destMAC == "" || tPacket.destMAC == null) //was != broadcast-mac
{
tPacket.OutboundMAC = ArpFromIP(tPacket.OutboundIP);
}
else
{
tPacket.OutboundMAC = tPacket.destMAC;
}
if (tPacket.OutboundMAC == "")
{
bool todo = true;
if (tPacket.OutboundNic != null && tPacket.OutboundNic.GetNicType == NicType.lo)
todo = false;
if (HasBroadcastAddress(tPacket.destIP))
{
tPacket.OutboundMAC = NB.BroadcastMACString;
todo = false;
}
if (todo)
{
AskArpFromHere(tPacket.OutboundIP);
//we do not have a mac address for it. Need to do an arp.
tPacket.TickTTL = 300;
tPacket.MyStatus = PacketStatus.waiting_for_arp;
return false;
}
}
return true;
}
/// <summary>
/// Return the network card that is considered "local" for the given IP
/// </summary>
/// <param name="toFind">The IP Address we are looking for</param>
/// <returns>a network card, or null if nothing matches</returns>
public NetworkCard LocalNic(IPAddress toFind, bool skipZero= false)
{
NetworkInterface nIF;
foreach (NetworkCard nic in NICs)
{
nIF = nic.LocalInterface(toFind, null);
if (nIF != null) {
if (nIF.myIP.GetIPString == NB.ZeroIPString)
continue;
return nic;
}
}
if(!skipZero)
{
foreach (NetworkCard nic in NICs)
{
nIF = nic.LocalInterface(toFind, null);
if (nIF != null)
{
return nic;
}
}
}
return null;
}
public List<string> NICRouteStrings()
{
List<string> answer = new List<string>();
string GW = DefaultGW.GetIP.ToIpString();
foreach(NetworkCard nic in NICs)
{
answer.AddRange(nic.NICRouteStrings(GW));
}
return answer;
}
public List<string> NICNames()
{
List<string> answer = new List<string>();
string GW = DefaultGW.GetIP.ToIpString();
foreach (NetworkCard nic in NICs)
{
answer.Add(nic.NicName());
}
return answer;
}
private IPAddress IPFromTypeNic(NicType What)
{
foreach(NetworkCard nic in NB.Randomize(NICs).ToList())
{
if(nic.GetNicType == What)
{
foreach(IPAddress ip in nic.IPAddressList())
{
if (ip.GetIPString != NB.ZeroIPString && ip.GetIPString != NB.LoopbackIPString)
return ip;
}
}
}
return null;
}
public IPAddress BestIPForThis(NetworkDevice Source=null)
{
IPAddress answer=null;
if(Source != null)
{
answer = LocalDeviceIP(Source);
if (answer != null && answer.GetIPString != NB.ZeroIPString)
return answer;
}
//If we have a WAN Nic, use that first
answer = IPFromTypeNic(NicType.wan);
if (answer != null)
return answer;
answer = IPFromTypeNic(NicType.management_interface);
if (answer != null)
return answer;
//Otherwise, choose an eth nic
answer = IPFromTypeNic(NicType.eth);
if (answer != null)
return answer;
return null;
}
public List<string> DeviceRouteStrings()
{
List<string> answer = new List<string>();
foreach (IPAddress ip in RouteTable)
{
answer.Add(ip.IPFormat());
}
return answer;
}
public void AddRoute(IPAddress route)
{
RouteTable.Add(route);
}
public List<IPAddress> ListRoutes()
{
return RouteTable;
}
public void EditRoute(int index)
{
if (index < 0) return;
if (index >= RouteTable.Count) return;
RouteTable[index].Edit(this);
}
public void DeleteRoute(int index)
{
if (index < 0) return;
if (index >= RouteTable.Count) return;
RouteTable.RemoveAt(index);
}
public override void DoInput(Packet tPacket)
{
}
public void DoInputFromLink(Packet tPacket, HostNicID arrivalNic)
{
//We are entering into the computer
NetworkCard nc = NicFromID(arrivalNic);
tPacket.PacketDump(hostname, DebugPausePoint.packet_in);
if(nc == null)
{
tPacket.AddMessage(DebugLevel.info, "The packet failed to hit a Card. We should not be here!");
tPacket.Tracking.Status = hostname + " Failed: no card available to use.";
tPacket.MyStatus = PacketStatus.finished_failed;
return;
}
if(tPacket.MyType == PacketType.dhcp_answer)
if(tPacket.destMAC == nc.MAC )
{
//We have arrived back
tPacket.OutboundNic = nc;
ProcessArrival(tPacket);
return;
}
NetworkInterface nf = nc.LocalInterface(tPacket.destIP, tPacket.Tracking);
if(nf == null)
{
nf = nc.LocalInterface(tPacket.TsourceIP, tPacket.Tracking);
}
if(nf == null && tPacket.MyType == PacketType.dhcp_request && isDHCPServer)
{
List<IPAddress> addresses = nc.IPAddressList();
if (addresses.Count > 0)
{
tPacket.OutboundIP = addresses[0];
tPacket.OutboundNic = nc;
tPacket.OutboundMAC = nc.MAC;
tPacket.WhereAmI = this;
ProcessArrival(tPacket);
return;
}
}
if (!ForwardsPackets())
{
if (tPacket.MyType == PacketType.dhcp_request && !isDHCPServer)
{
tPacket.AddMessage(DebugLevel.debug, hostname + " Packet request fell on deaf ears. This is not a DHCP server.");
tPacket.Tracking.Status = hostname + " Failed: Not a DHCP Server. Packet Dropped.";
tPacket.MyStatus = PacketStatus.finished_failed;
return;
}
if ((tPacket.MyType == PacketType.ping_answer || tPacket.MyType== PacketType.ping_request) &&
!RoutesPackets() && (!HasIPAddress(tPacket.destIP) && !HasBroadcastAddress(tPacket.destIP)))
{
tPacket.AddMessage(DebugLevel.debug, hostname + " Not a router");
tPacket.Tracking.Status = hostname + " This device is not a router. Packet dropped.";
tPacket.MyStatus = PacketStatus.finished_failed;
return;
}
}
if(nf == null && myType != NetworkComponentType.net_switch && myType != NetworkComponentType.net_hub)
{
tPacket.AddMessage(DebugLevel.debug, hostname + " The device had no local IPs. Quietly dropped.");
tPacket.Tracking.Status = hostname + " Failed: no IPs local to the packet.";
tPacket.MyStatus = PacketStatus.finished_failed;
return;
}
//Now we pass it to the interface
if(nf != null)
nf.ProcessInboundPacket(tPacket);
//Now we pass it to the nic
if(nc != null)
nc.ProcessInboundPacket(tPacket);
if(!tPacket.ready_to_delete)
tPacket.StartOnDevice(this);
}
/// <summary>
/// Return true if this is a switch/hub/wap
/// </summary>
/// <returns></returns>
public bool ForwardsPackets()
{
if (myType == NetworkComponentType.net_hub) return true;
if (myType == NetworkComponentType.net_switch) return true;
if (myType == NetworkComponentType.wap) return true;
return false;
}
/// <summary>
/// Return true if this device routes packets. Router, firewall, etc.
/// </summary>
/// <returns></returns>
public bool RoutesPackets()
{
if (myType == NetworkComponentType.router) return true;
if (myType == NetworkComponentType.firewall) return true;
return false;
}
public override void DoOutput(Packet tPacket)
{
}
public string ArpFromIP(string IPAddress)
{
foreach(ArpEntry arp in ArpTable)
{
if (arp.IPAddr == IPAddress)
return arp.MACAddress;
}
return "";
}
public string IPFromArp(string MAC)
{
foreach (ArpEntry arp in ArpTable)
{
if (arp.MACAddress == MAC)
return arp.IPAddr;
}
return "";
}
public HostNicID NicIDFromArp(string MAC)
{
foreach (ArpEntry arp in ArpTable)
{
if (arp.MACAddress == MAC)
return arp.NicOnWhichItIsFound;
}
return new HostNicID(-1,-1,"","");
}
public HostNicID NicIDFromIP(string IP)
{
foreach (ArpEntry arp in ArpTable)
{
if (arp.IPAddr == IP)
return arp.NicOnWhichItIsFound;
}
return new HostNicID(-1, -1, "", "");
}
public string LookupArpFromIP(string IPAddress)
{
string arp = ArpFromIP(IPAddress);
if (arp == "")
{
Network mynet = NB.GetNetwork();
if (mynet != null)
{
List<string> arps = mynet.arp(IPAddress.ParseIp());
if (arps.Count > 0)
{
return arps[0];
}
}
}
return arp;
}
public string ArpFromIP(IPAddress IPAddress)
{
return ArpFromIP(IPAddress.GetIP.ToIpString());
}
public void StoreArp(string mac, string ip, HostNicID NicID)
{
ArpEntry AE = new ArpEntry(mac, ip, NicID);
string found = ArpFromIP(ip);
if (found == "")
{
ArpTable.Add(AE);
}
if(IPFromArp(mac) != ip && ip != NB.ZeroIPString)
{
foreach (ArpEntry arp in ArpTable.ToList())
{
if (arp.MACAddress == mac)
{
ArpTable.Remove(arp);
}
}
ArpTable.Add(AE);
}
}
public List<ArpEntry> GetArps()
{
return ArpTable;
}
public void ClearArps()
{
ArpTable.Clear();
}
/// <summary>
/// Clear out all the IP addresses on the device
/// </summary>
public void ClearIPs()
{
ClearArps();
RouteTable.Clear();
DefaultGW = new IPAddress(NB.ZeroIPString);
foreach(NetworkCard nic in NICs)
{
nic.ClearIPs();
}
}
/********************************************
* DHCP Stuff
********************************************/
public void CheckDHCPRangesAgainstInterfaces()
{
bool found = false;
List<IPAddress> theInterfaces = IPAddressList();
foreach(IPAddress dhcpIP in DHCPRanges.ToList())
{
found = false;
foreach (IPAddress interfaceIP in theInterfaces)
{
if(interfaceIP.GetIP == dhcpIP.GetIP)
{
found = true;
break;
}
}
if(!found)
{
DHCPRanges.Remove(dhcpIP);
}
}
foreach (IPAddress interfaceIP in theInterfaces)
{
found = false;
foreach (IPAddress dhcpIP in DHCPRanges)
{
if (interfaceIP.GetIP == dhcpIP.GetIP)
{
found = true;
break;
}
}
if (!found)
{
DHCPRanges.Add(new IPAddress(interfaceIP.GetIP.ToIpString(),NB.ZeroIPString,NB.ZeroIPString));
}
}
}
public List<string> DHCPStrings(bool WithAdditionalInfo=true)
{
List<string> theStrings = new List<string>();
foreach(IPAddress ip in DHCPRanges)
{
if (ip.GetIP.ToIpString() != "127.0.0.1")
{
if (WithAdditionalInfo)
{
theStrings.Add("IF:" + ip.GetIP.ToIpString().PadLeft(15) + " Range: " +
ip.GetMask.ToIpString() + " - " + ip.GetGateway.ToIpString());
}
else
{
theStrings.Add(ip.GetIP.ToIpString());
}
}
}
return theStrings;
}
public IPAddress DHCPRangeMatchingInterface(IPAddress InterfaceIP)
{
foreach (IPAddress ip in DHCPRanges)
{
if (ip.GetIP.ToIpString() != "127.0.0.1" && InterfaceIP.IsLocal(ip))
return ip;
}
return null;
}
public void EditDHCP(int index)
{
if (index > DHCPRanges.Count) return;
if (index < 0) return;
bool found = false;
IPAddress ifIP = null;
List<IPAddress> theInterfaces = IPAddressList();
foreach (IPAddress interfaceIP in theInterfaces)
{
if(interfaceIP.GetIP == DHCPRanges[index].GetIP)
{
ifIP = interfaceIP;
found = true;
}
}
if (!found) return;
DHCPRanges[index].Edit(this, ifIP); //We need to pass the interface that is local to this
DHCPLeases.Clear();
}
public IPAddress LookupDHCPLease(string MAC, IPAddress NIC_IP)
{
IPAddress gateway;
if (myType != NetworkComponentType.firewall)
{
gateway = GetGateway();
}
else
{
gateway = NIC_IP; //Return the firewall IP that it came in on
}
foreach(ArpEntry dhcp in DHCPLeases)
{
if (dhcp.MACAddress == MAC && dhcp.IPAddr != NB.ZeroIPString)
return new IPAddress(dhcp.IPAddr, NIC_IP.GetMask.ToIpString(), gateway.GetIP.ToIpString());
}
return null;
}
public bool IPAlreadyUsed(string IP)
{
foreach (ArpEntry dhcp in DHCPLeases)
{
if (dhcp.IPAddr == IP)
return true;
}
return false;
}
public void MakeDHCPLease(string IP, string MAC)
{
ArpEntry me = new ArpEntry(MAC, IP, new HostNicID());
DHCPLeases.Add(me);
}
/// <summary>
/// Look up the MAC address and return the appropriate IP, or make a new IP. Uses the interface IP of the server to know what range to use.
/// </summary>
/// <param name="MAC">The mac of the requesting machine</param>
/// <param name="NIC_IP">the IP of the server nic</param>
/// <returns>an IPAddress IP/Mask/GW</returns>
public IPAddress RequestDHCPLease(string MAC, IPAddress NIC_IP)
{
IPAddress tAddress = LookupDHCPLease(MAC, NIC_IP);
if (tAddress != null) return tAddress;
//if we are here, we need to find an address to give.
bool stillOK = true;
IPAddress startaddress = DHCPRangeMatchingInterface(NIC_IP);
if (startaddress == null) return null;
UInt32 sIPNum = startaddress.GetMask;
UInt32 eIPNum = startaddress.GetGateway;
string ipstring;
while(stillOK)
{
ipstring = sIPNum.ToIpString();
if (!IPAlreadyUsed(ipstring))
{
MakeDHCPLease(ipstring, MAC);
IPAddress gateway;
if (myType != NetworkComponentType.firewall)
{
gateway = GetGateway();
}
else
{
gateway = NIC_IP; //Return the firewall IP that it came in on
}
return new IPAddress(ipstring,NIC_IP.GetMask.ToIpString(),gateway.GetIP.ToIpString());
}
sIPNum++;
if(sIPNum > eIPNum)
{
//We have used up all the range
stillOK = false;
break;
}
}
return null; //If we get here, we are done for. Nothing to give out
}
/// <summary>
/// Return true if this device has at least one nic that can be configured from DHCP
/// </summary>
/// <returns>True if the device has a nic that can be configured with DHCP</returns>
public bool HasDHCPNic()
{
foreach(NetworkCard card in NICs)
{
if (card.UsesDHCP)
return true;
}
return false;
}
}
}