From 5775c3502073f289a8e2cdf85226b82014563089 Mon Sep 17 00:00:00 2001 From: Tim Young Date: Sat, 1 Aug 2015 11:58:53 -0600 Subject: [PATCH] Getting up to date and moving translation stuff to separate function --- EduNetworkBuilder/DeviceConfig.cs | 449 +++++ EduNetworkBuilder/IPAddress.cs | 274 +++ EduNetworkBuilder/IPAddressEntry.cs | 246 +++ EduNetworkBuilder/LinkEditor.cs | 6 +- EduNetworkBuilder/ListBoxWindow.cs | 442 +++++ EduNetworkBuilder/NB.cs | 570 ++++++ EduNetworkBuilder/NetTest.cs | 361 ++++ EduNetworkBuilder/NetTestEditor.cs | 259 +++ EduNetworkBuilder/Network.cs | 1111 +++++++++++ EduNetworkBuilder/NetworkBuilder.cs | 1126 +++++++++++ EduNetworkBuilder/NetworkCard.cs | 627 ++++++ EduNetworkBuilder/NetworkCardEditor.cs | 161 ++ EduNetworkBuilder/NetworkCardEditor.resx | 120 ++ EduNetworkBuilder/NetworkDevice.cs | 2281 ++++++++++++++++++++++ EduNetworkBuilder/NetworkLink.cs | 224 +++ EduNetworkBuilder/OptionsWindow.cs | 347 ++++ EduNetworkBuilder/Packet.cs | 456 +++++ EduNetworkBuilder/PacketMessage.cs | 110 ++ EduNetworkBuilder/RTFWindow.cs | 91 + EduNetworkBuilder/pullLanguageInfo.pl | 107 + 20 files changed, 9365 insertions(+), 3 deletions(-) create mode 100644 EduNetworkBuilder/DeviceConfig.cs create mode 100644 EduNetworkBuilder/IPAddress.cs create mode 100644 EduNetworkBuilder/IPAddressEntry.cs create mode 100644 EduNetworkBuilder/ListBoxWindow.cs create mode 100644 EduNetworkBuilder/NB.cs create mode 100644 EduNetworkBuilder/NetTest.cs create mode 100644 EduNetworkBuilder/NetTestEditor.cs create mode 100644 EduNetworkBuilder/Network.cs create mode 100644 EduNetworkBuilder/NetworkBuilder.cs create mode 100644 EduNetworkBuilder/NetworkCard.cs create mode 100644 EduNetworkBuilder/NetworkCardEditor.cs create mode 100644 EduNetworkBuilder/NetworkCardEditor.resx create mode 100644 EduNetworkBuilder/NetworkDevice.cs create mode 100644 EduNetworkBuilder/NetworkLink.cs create mode 100644 EduNetworkBuilder/OptionsWindow.cs create mode 100644 EduNetworkBuilder/Packet.cs create mode 100644 EduNetworkBuilder/PacketMessage.cs create mode 100644 EduNetworkBuilder/RTFWindow.cs create mode 100644 EduNetworkBuilder/pullLanguageInfo.pl diff --git a/EduNetworkBuilder/DeviceConfig.cs b/EduNetworkBuilder/DeviceConfig.cs new file mode 100644 index 0000000..de936fa --- /dev/null +++ b/EduNetworkBuilder/DeviceConfig.cs @@ -0,0 +1,449 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Text.RegularExpressions; +using System.Globalization; +using System.Resources; + + +namespace EduNetworkBuilder +{ + public partial class DeviceConfig : Form + { + NetworkComponent OriginalItem; + NetworkComponent ClonedItem; + bool processing = false; + ToolTip mytooltips = new ToolTip(); + + public DeviceConfig(NetworkComponent Original_Item) + { + InitializeComponent(); + LanguagifyComponents(); + OriginalItem = Original_Item; + ClonedItem = NetworkComponent.Clone(OriginalItem); + UpdateForm(); + lblHelp.Text = "Select the network card or interface for that network card that you wish to edit. " + + "Then press the [edit] button to make changes to that. Press the [-] to remove it, and press [+] to add another."; + } + + private void LoadFromOrig() + { + ClonedItem.UpdateFromComponent(OriginalItem); + } + + private void LoadFromClone() + { + OriginalItem.UpdateFromComponent(ClonedItem); + } + + private void LanguagifyComponents() + { + ResourceManager RM = NB.GetResource(); + CultureInfo CI = NB.GetCulture(); + Text = NB.Translate("DC_lblHostname"); + Text = NB.Translate("DC_lblHelp"); + Text = NB.Translate("DC_btnCancel"); + Text = NB.Translate("DC_btnOK"); + Text = NB.Translate("DC_btnNicPlus"); + Text = NB.Translate("DC_btnNicMinus"); + Text = NB.Translate("DC_btnNicEdit"); + Text = NB.Translate("DC_btnIfEdit"); + Text = NB.Translate("DC_btnIfMinus"); + Text = NB.Translate("DC_btnIfAdd"); + Text = NB.Translate("DC_btnGateway"); + Text = NB.Translate("DC_btnRoutes"); + Text = NB.Translate("DC_cbDHCP"); + Text = NB.Translate("DC_btnDHCP"); + Text = NB.Translate("DC_Form"); + } + + + private void UpdateForm() + { + Network theNet = NB.GetNetwork(); + if (theNet.ItemIsCritical(OriginalItem.hostname)) + { + tbHostname.Enabled = false; + mytooltips.SetToolTip(tbHostname, "This item is part of the puzzle and cannot be renamed."); + } + if (processing) return; + processing = true; + if (ClonedItem.GetType().ToString() == "EduNetworkBuilder.NetworkDevice") + { + NetworkDevice ndCLonedItem = (NetworkDevice)ClonedItem; + + if(ndCLonedItem.CanAddNics) + { + btnNicPlus.Visible = true; + btnNicMinus.Visible = true; + }else + { + btnNicPlus.Visible = false; + btnNicMinus.Visible = false; + } + + if(ndCLonedItem.CanServeDHCP) + { + if (ndCLonedItem.GetIsDHCPServer()) + cbDHCP.Checked = true; + cbDHCP.Visible = true; + if(cbDHCP.Checked) + btnDHCP.Visible = true; + else + btnDHCP.Visible = false; + } + else + { + btnDHCP.Visible = false; + cbDHCP.Visible = false; + } + + btnGateway.Visible = true; + btnGateway.Text = "Gateway: " + ndCLonedItem.GetGateway().GetIP.ToIpString(); + tbHostname.Text = ndCLonedItem.hostname; + //Network cards are changed with the [edit] button and do not need to be updated here + //IPAddresses are changed with the [edit] button and do not need to be updated here + + //The Nics + int selectedLb = lbNics.SelectedIndex; + lbNics.Items.Clear(); + List lists = ndCLonedItem.NetworkCardStrings(false); + foreach (string tstring in lists) + { + lbNics.Items.Add(tstring); + } + if(selectedLb < 0) + { + if (lbNics.Items.Count > 0) + { + lbNics.SelectedIndex = 0; + selectedLb = 0; + } + } + else + { + if (selectedLb >= lbNics.Items.Count) selectedLb = -1; + lbNics.SelectedIndex = selectedLb; + } + if (lbNics.SelectedIndex >= 0) + { + btnNicEdit.Enabled = true; + btnNicMinus.Enabled = true; + } + else + { + btnNicEdit.Enabled = false; + btnNicMinus.Enabled = false; + } + + lbArpTable.Items.Clear(); + lbArpTable.Items.Add("Arp Table MAC\tIPAddress"); + foreach(ArpEntry ae in ndCLonedItem.GetArps()) + { + lbArpTable.Items.Add(ae.MACAddress + "\t" + ae.IPAddr); + } + + //The IP Addresses for the given nic + //Use the index of the nic + string selectedNicName = ""; + if (lbNics.SelectedItem != null) selectedNicName = lbNics.SelectedItem.ToString(); + selectedNicName = Regex.Replace(selectedNicName, " .*", ""); + selectedNicName = Regex.Replace(selectedNicName, "\\*", ""); + lists = ndCLonedItem.NetworkCardInterfaceStrings(selectedNicName); + //get the IPAddress string list from the nic + selectedLb = lbAddresses.SelectedIndex; + lbAddresses.Items.Clear(); + foreach (string tstring in lists) + { + lbAddresses.Items.Add(tstring); + } + if (selectedLb < 0) + { + if (lbAddresses.Items.Count > 0) + lbAddresses.SelectedIndex = 0; + } + else + { + if (lbAddresses.Items.Count > 0 && selectedLb < lbAddresses.Items.Count) + lbAddresses.SelectedIndex = selectedLb; + } + if (lbNics.SelectedIndex >= 0) + { + btnIfEdit.Enabled = true; + btnIfMinus.Enabled = true; + } + else + { + btnIfEdit.Enabled = false; + btnIfMinus.Enabled = false; + } + + } + processing = false; + } + + private void StoreInCloneFromForm() + { + if(NB.GetComponentType(ClonedItem) == GeneralComponentType.device) + { + NetworkDevice ndCLonedItem = (NetworkDevice)ClonedItem; + ndCLonedItem.hostname = tbHostname.Text; + //Network cards are changed with the [edit] button and do not need to be updated here + //IPAddresses are changed with the [edit] button and do not need to be updated here + } + } + + private void tbHostname_Validating(object sender, CancelEventArgs e) + { + //Make sure something else does not already have this hostname + Network theNet = NB.GetNetwork(); + string otext; + if(theNet.ItemIsCritical(tbHostname.Text)) + { + if(tbHostname.Text != OriginalItem.hostname) + { + e.Cancel = true; + otext = tbHostname.Text; + tbHostname.Text = OriginalItem.hostname; + + MessageBox.Show("The name '" + otext + "' is being used as part of this puzzle and this machine cannot be named that."); + } + } + } + + private void btnNicPlus_Click(object sender, EventArgs e) + { + List WhatToAdd = new List(); + //generate a new nic and add it to the device + if (ClonedItem.GetType().ToString() == "EduNetworkBuilder.NetworkDevice") + { + NetworkDevice ndCLonedItem = (NetworkDevice)ClonedItem; + if (!ndCLonedItem.CanAddNics) return; + if(ndCLonedItem.GetNetType() == NetworkComponentType.firewall) + { + WhatToAdd.Add(NicType.eth); + WhatToAdd.Add(NicType.tun); + WhatToAdd.Add(NicType.vpn); + } + if (ndCLonedItem.GetNetType() == NetworkComponentType.net_hub || ndCLonedItem.GetNetType() == NetworkComponentType.net_switch) + { + WhatToAdd.Add(NicType.port); + } + if (ndCLonedItem.GetNetType() == NetworkComponentType.router ) + { + WhatToAdd.Add(NicType.eth); + } + if (ndCLonedItem.GetNetType() == NetworkComponentType.pc && ndCLonedItem.CountNics(NicType.eth) < 1) + { + WhatToAdd.Add(NicType.eth); + } + if (WhatToAdd.Count == 1) + { + ndCLonedItem.AddNic(WhatToAdd[0]); + } + if(WhatToAdd.Count > 1) + { + //we need to choose a type: + Form QuestionForm = new Form(); + QuestionForm.Text = "Network Card to Add"; + QuestionForm.Icon = Properties.Resources.NBIco; + + Label lblText = new Label(); + lblText.Location = new Point(5, 5); + lblText.Text = "Choose a type:"; + + ComboBox cbQuestions = new ComboBox(); + cbQuestions.Location = new Point(lblText.Location.X + lblText.Width + 5, lblText.Location.Y); + cbQuestions.Width = 60; + foreach(NicType nt in WhatToAdd) + { + cbQuestions.Items.Add(nt.ToString()); + } + cbQuestions.SelectedIndex = 0; + + QuestionForm.Width = cbQuestions.Location.X + cbQuestions.Width + 70; + QuestionForm.Height = 90; + QuestionForm.AutoSize = true; + + Button btnAccept = new Button(); + btnAccept.Location = new Point(cbQuestions.Location.X, cbQuestions.Location.Y + cbQuestions.Height + 10); + btnAccept.Text = "Add"; + btnAccept.Click += (s, g) => { Button b = (Button)s; Form f = (Form)b.Parent; f.Close(); }; + + QuestionForm.Controls.Add(lblText); + QuestionForm.Controls.Add(cbQuestions); + QuestionForm.Controls.Add(btnAccept); + + QuestionForm.ShowDialog(); + if(cbQuestions.SelectedIndex >=0) + { + ndCLonedItem.AddNic(WhatToAdd[cbQuestions.SelectedIndex]); + } + } + } + UpdateForm(); + } + + private void btnNicMinus_Click(object sender, EventArgs e) + { + //delete the specified nic + if (ClonedItem.GetType().ToString() == "EduNetworkBuilder.NetworkDevice") + { + NetworkDevice ndCLonedItem = (NetworkDevice)ClonedItem; + ndCLonedItem.DeleteNic(lbNics.SelectedIndex + 1); //Skip the loopback nic + UpdateForm(); + } + } + + private void btnNicEdit_Click(object sender, EventArgs e) + { + //open a window to change the settings on the nic + if (ClonedItem.GetType().ToString() == "EduNetworkBuilder.NetworkDevice") + { + NetworkDevice ndCLonedItem = (NetworkDevice)ClonedItem; + ndCLonedItem.EditNic(lbNics.SelectedIndex +1); //Skip the loopback nic + UpdateForm(); + } + } + + private void btnIfAdd_Click(object sender, EventArgs e) + { + if (NB.GetComponentType(ClonedItem) == GeneralComponentType.device) + { + NetworkDevice ND = (NetworkDevice)ClonedItem; + ND.AddNicInterface(lbNics.SelectedIndex + 1); //we do not show loopback + } + UpdateForm(); + } + + private void btnIfMinus_Click(object sender, EventArgs e) + { + //if one is selected and there are more than one, delete it + if(lbAddresses.SelectedIndex >= 0) + { + if (lbAddresses.Items.Count > 1) + { + //we can delete it + if(NB.GetComponentType(ClonedItem) == GeneralComponentType.device) + { + NetworkDevice ND = (NetworkDevice)ClonedItem; + ND.DeleteNicInterface(lbNics.SelectedIndex + 1, lbAddresses.SelectedIndex); + } + } + else + MessageBox.Show("You cannot delete the sole remaining interface."); + } + else + MessageBox.Show("Please select an interface to delete."); + UpdateForm(); + } + + private void editInterface() + { + if (ClonedItem.GetType().ToString() == "EduNetworkBuilder.NetworkDevice") + { + NetworkDevice ndCLonedItem = (NetworkDevice)ClonedItem; + if (lbAddresses.SelectedIndex >= 0 && lbNics.SelectedIndex >= 0) + { + string selectedNIC = lbNics.SelectedItem.ToString(); + selectedNIC = Regex.Replace(selectedNIC, " .*", ""); + selectedNIC = Regex.Replace(selectedNIC, "\\*", ""); + + ndCLonedItem.EditNicInterface(selectedNIC, lbAddresses.SelectedIndex); + UpdateForm(); + } + } + } + + private void btnIfEdit_Click(object sender, EventArgs e) + { + editInterface(); + } + + private void btnCancel_Click(object sender, EventArgs e) + { + //we should prompt to save if we made changes + Close(); + } + + private void btnOK_Click(object sender, EventArgs e) + { + StoreInCloneFromForm(); + LoadFromClone(); //this saves the values in the object we passed it + OriginalItem.IsDirty = true; //re-draw it + Close(); + } + + private void lbNics_SelectedIndexChanged(object sender, EventArgs e) + { + UpdateForm(); + processing = false; + } + + private void lbAddresses_DoubleClick(object sender, EventArgs e) + { + if(lbAddresses.SelectedIndex >=0) + { + //We have one to edit + editInterface(); + UpdateForm(); + } + } + + private void lbNics_DoubleClick(object sender, EventArgs e) + { + if (NB.GetComponentType(ClonedItem) == GeneralComponentType.device) + { + NetworkDevice nd = (NetworkDevice)ClonedItem; + nd.EditNic(lbNics.SelectedIndex + 1); //skip the loopback device + UpdateForm(); + } + } + + private void btnGateway_Click(object sender, EventArgs e) + { + if (NB.GetComponentType(ClonedItem) == GeneralComponentType.device) + { + NetworkDevice nd = (NetworkDevice)ClonedItem; + nd.EditGateway(); + UpdateForm(); + } + } + + private void btnRoutes_Click(object sender, EventArgs e) + { + if (ClonedItem == null) return; + if (NB.GetComponentType(ClonedItem) == GeneralComponentType.link) return; + NetworkDevice tItem = (NetworkDevice)ClonedItem; + ListBoxWindow lbwindow = new ListBoxWindow(tItem,LBContents.routes); + lbwindow.ShowDialog(); + } + + private void btnDHCP_Click(object sender, EventArgs e) + { + if (ClonedItem == null) return; + if (NB.GetComponentType(ClonedItem) == GeneralComponentType.link) return; + NetworkDevice tItem = (NetworkDevice)ClonedItem; + ListBoxWindow lbwindow = new ListBoxWindow(tItem, LBContents.dhcp); + lbwindow.ShowDialog(); + } + + + private void cbDHCP_CheckedChanged(object sender, EventArgs e) + { + if(NB.GetComponentType(ClonedItem) == GeneralComponentType.device) + { + NetworkDevice ndClonedItem = (NetworkDevice)ClonedItem; + ndClonedItem.SetDHCPServer(cbDHCP.Checked); + } + UpdateForm(); + } + + } +} diff --git a/EduNetworkBuilder/IPAddress.cs b/EduNetworkBuilder/IPAddress.cs new file mode 100644 index 0000000..bd6f87a --- /dev/null +++ b/EduNetworkBuilder/IPAddress.cs @@ -0,0 +1,274 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Globalization; +using System.Xml; +using System.Windows.Forms; + + +namespace EduNetworkBuilder +{ + [Serializable] + public class IPAddress + { + + private UInt32 _ip; + private UInt32 _mask; + private UInt32 _gw; + private IPAddressType myType; + + public IPAddress(string ip, string mask, IPAddressType WhatType) + { + myType = WhatType; + _ip = ip.ParseIp(); + _mask = mask.ParseIp(); + } + + public IPAddress(string ip, string mask, string gw) + { + myType = IPAddressType.route; + _ip = ip.ParseIp(); + _mask = mask.ParseIp(); + _gw = gw.ParseIp(); + } + + public IPAddress(XmlNode theNode) + { + foreach (XmlNode Individual in theNode.ChildNodes) + { + XmlNodeType myNodetype = Individual.NodeType; + if (myNodetype == XmlNodeType.Element) + { + switch (Individual.Name.ToLower()) + { + case "ip": + _ip = Individual.InnerText.ParseIp(); + break; + case "mask": + _mask = Individual.InnerText.ParseIp(); + break; + case "gateway": + _gw = Individual.InnerText.ParseIp(); + break; + case "type": + myType = NB.ParseEnum(Individual.InnerText); + break; + } + } + } + } + + public void Save(XmlWriter writer, string tag) + { + writer.WriteStartElement(tag); + writer.WriteElementString("ip", _ip.ToIpString()); + writer.WriteElementString("mask", _mask.ToIpString()); + writer.WriteElementString("gateway", _gw.ToIpString()); + writer.WriteElementString("type", myType.ToString()); + writer.WriteEndElement(); + } + + public void Reparse(string ip, string mask, string gw) + { + _ip = ip.ParseIp(); + _mask = mask.ParseIp(); + _gw = gw.ParseIp(); + } + public void Reparse(string ip, string mask) + { + _ip = ip.ParseIp(); + _mask = mask.ParseIp(); + } + + public IPAddressType GetAddressType + { + get { return myType; } + } + + public bool IsLocal(IPAddress dest) + { + if (dest == null) return false; + UInt32 answer = dest.GetIP & _mask; + if ((dest.GetIP & _mask) == NetworkAddress) + return true; + return false; + } + + public bool Edit(NetworkDevice FromWhat, string message="") + { + IPAddressEntry IPe = new IPAddressEntry(this, FromWhat); + if (message != "") + IPe.Text = message; + return IPe.Edit(); + } + + public bool Edit(NetworkDevice FromWhat, IPAddress DHCPif) + { + IPAddressEntry IPe = new IPAddressEntry(this, FromWhat); + return IPe.Edit(FromWhat, DHCPif); + } + + public IPAddress(string ip) + { + myType = IPAddressType.ip; + _ip = ip.ParseIp(); + var mySplitVal = ip.Split('/'); + if (mySplitVal.Count() < 2) + { + //We do not have a cidr. We need to guess + //For now, use 255.255.255.0 + _mask = "255.255.255.0".ParseIp(); + mySplitVal = ip.Split('.'); + if(mySplitVal.Count() > 0) + { + //If it is not one of these three, we already use 255.255.255.0 + if(mySplitVal[0] == "10") + { + _mask = "255.0.0.0".ParseIp(); + } + if (mySplitVal[0] == "172") + { + _mask = "255.255.0.0".ParseIp(); + } + if (mySplitVal[0] == "192") + { + _mask = "255.255.255.0".ParseIp(); + } + } + } + else + { + UInt32 tInt = 0; + int cdr; + int.TryParse(mySplitVal[1], out cdr); + for (int loop = 0; loop < 32; loop++) + { + tInt = (tInt << 1); + if (loop < cdr) tInt++; + } + _mask = tInt; + } + } + + + public bool Equals(UInt32 IP) + { + return IP == _ip; + } + + public bool Equals(UInt32 IP, UInt32 mask) + { + return (IP == _ip && mask == _mask); + } + + + public UInt32 NumberOfHosts + { + get { return ~_mask + 1; } + } + + public UInt32 GetIP + { + get { return _ip; } + } + public string GetIPString + { + get { return _ip.ToIpString(); } + } + public string GetBroadcastString + { + get { return BroadcastAddress.ToIpString(); } + } + public string GetMaskString + { + get { return _mask.ToIpString(); } + } + + public UInt32 GetMask + { + get { return _mask; } + } + public UInt32 GetGateway + { + get { return _gw; } + } + + public UInt32 NetworkAddress + { + get { return _ip & _mask; } + } + + public UInt32 BroadcastAddress + { + get { return NetworkAddress + ~_mask; } + } + + public IEnumerable Hosts() + { + for (var host = NetworkAddress + 1; host < BroadcastAddress; host++) + { + yield return host; + } + } + public string IPFormat() + { + return IPFormat(_gw.ToIpString()); + } + public string PadIt(string Addr) + { + string myaddr = Addr.PadRight(12); + return myaddr; + } + public string IPFormat(string gw) + { + string tstring = "IP:" +PadIt(_ip.ToIpString())+ + " Mask:" + PadIt(_mask.ToIpString())+ + " GW:" + PadIt(gw); + return tstring; + } + } + + public static class IpHelpers + { + public static string ToIpString(this UInt32 value) + { + var bitmask = 0xff000000; + var parts = new string[4]; + for (var i = 0; i < 4; i++) + { + var masked = (value & bitmask) >> ((3 - i) * 8); + bitmask >>= 8; + parts[i] = masked.ToString(CultureInfo.InvariantCulture); + } + return String.Join(".", parts); + } + + public static string ToBitString(this UInt32 value) + { + var item = System.Convert.ToString(value, 2); + return (string)item; + } + + public static UInt32 ParseIp(this string ipAddress) + { + var gw = ipAddress.Split('/'); //Pull off any cdr + var mySplitVal = gw[0].Split('.'); + if (mySplitVal.Count() != 4) + return 0; + UInt32 ip = 0; + uint part; + if (mySplitVal.Count() == 4) + { + for (var i = 0; i < 4; i++) + { + part = 0; + UInt32.TryParse(mySplitVal[i], out part); + ip = (ip << 8) + part; + } + } + return ip; + } + } +} \ No newline at end of file diff --git a/EduNetworkBuilder/IPAddressEntry.cs b/EduNetworkBuilder/IPAddressEntry.cs new file mode 100644 index 0000000..dc63a8e --- /dev/null +++ b/EduNetworkBuilder/IPAddressEntry.cs @@ -0,0 +1,246 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Globalization; +using System.Resources; + + +namespace EduNetworkBuilder +{ + public partial class IPAddressEntry : Form + { + IPAddress WhatToEdit; + IPAddress DHCPInterface=null; + bool WellDone = true; + NetworkDevice ParentDevice = null; + + + public IPAddressEntry(IPAddress toEdit, NetworkDevice ToEdit) + { + InitializeComponent(); + LanguagifyComponents(); + ParentDevice = ToEdit; + Network myNet = NB.GetNetwork(); + IPAddress lastIP = myNet.RetrieveLastIP(); + WhatToEdit = toEdit; + string hostname = ""; + if (ToEdit != null) + hostname = ToEdit.hostname; + if (toEdit.GetIP.ToIpString() == NB.ZeroIPString) + { + string lIP = lastIP.GetIP.ToIpString(); + string lNM = lastIP.GetMask.ToIpString(); + string lGW = lastIP.GetGateway.ToIpString(); + switch (WhatToEdit.GetAddressType) + { + case IPAddressType.gw: + lNM = NB.ZeroIPString; + lGW = NB.ZeroIPString; + break; + case IPAddressType.ip: + case IPAddressType.ip_only: + if (!lNM.Contains("255")) + lNM = "255.255.255.0"; + lGW = NB.ZeroIPString; + break; + case IPAddressType.route: + break; + } + WhatToEdit.Reparse(lIP, lNM, lGW); + } + UpdateFieldsFromAddress(); + switch (WhatToEdit.GetAddressType) + { + case IPAddressType.gw: + tbGateway.Enabled = false; + tbGateway.Visible = false; //This just confuses people + tbIPAddress.Enabled = true; + tbNetmask.Enabled = false; + break; + case IPAddressType.ip: + tbGateway.Enabled = false; + tbIPAddress.Enabled = true; + tbNetmask.Enabled = true; + break; + case IPAddressType.route: + tbGateway.Enabled = true; + tbIPAddress.Enabled = true; + tbNetmask.Enabled = true; + break; + case IPAddressType.ip_only: + tbGateway.Enabled = false; + tbIPAddress.Enabled = true; + tbNetmask.Enabled = false; + break; + } + + //Disable anythingthatis locked + switch (WhatToEdit.GetAddressType) + { + case IPAddressType.gw: + if (myNet.ItemIsLocked(hostname, tbIPAddress.Text, NetTestType.LockGateway)) + { + tbGateway.Enabled = false; + tbIPAddress.Enabled = false; + tbNetmask.Enabled = false; + } + break; + case IPAddressType.ip: + if (myNet.ItemIsLocked(hostname, tbIPAddress.Text, NetTestType.LockIP)) + { + tbGateway.Enabled = false; + tbIPAddress.Enabled = false; + tbNetmask.Enabled = false; + } + break; + case IPAddressType.route: + if (myNet.ItemIsLocked(hostname, tbIPAddress.Text, NetTestType.LockRoute)) + { + tbGateway.Enabled = false; + tbIPAddress.Enabled = false; + tbNetmask.Enabled = false; + } + break; + case IPAddressType.ip_only: + if (myNet.ItemIsLocked(hostname, tbIPAddress.Text, NetTestType.LockIP)) + { + tbIPAddress.Enabled = false; + } + break; + } + } + + private void LanguagifyComponents() + { + ResourceManager RM = NB.GetResource(); + CultureInfo CI = NB.GetCulture(); + Text = NB.Translate("IPAE_lblIP"); + Text = NB.Translate("IPAE_lblNetmask"); + Text = NB.Translate("IPAE_lblGateway"); + Text = NB.Translate("IPAE_btnCancel"); + Text = NB.Translate("IPAE_btnOK"); + Text = NB.Translate("IPAE_Form"); + } + + + private void UpdateFieldsFromAddress() + { + tbIPAddress.Text = WhatToEdit.GetIP.ToIpString(); + tbNetmask.Text = WhatToEdit.GetMask.ToIpString(); + tbGateway.Text = WhatToEdit.GetGateway.ToIpString(); + } + + private void btnOK_Click(object sender, EventArgs e) + { + WhatToEdit.Reparse(tbIPAddress.Text, tbNetmask.Text, tbGateway.Text); + Network myNet = NB.GetNetwork(); + myNet.StoreLastIP(WhatToEdit); + Close(); + } + + public bool Edit() + { + ShowDialog(); + return WellDone; + } + + public bool Edit(NetworkDevice ToEdit, IPAddress DHCPif) + { + DHCPInterface = DHCPif; + lblIP.Text = "Interface"; + lblNetmask.Text = "Start"; + lblGateway.Text = "End"; + tbIPAddress.Enabled = false; + tbGateway.Enabled = true; + tbNetmask.Enabled = true; + Network myNet = NB.GetNetwork(); + if (myNet.ItemIsLocked(ToEdit.hostname, tbIPAddress.Text, NetTestType.LockDHCP)) + { + tbGateway.Enabled = false; + tbIPAddress.Enabled = false; + tbNetmask.Enabled = false; + } + ShowDialog(); + return WellDone; + } + + + private void btnCancel_Click(object sender, EventArgs e) + { + UpdateFieldsFromAddress(); + WellDone = false; + Close(); + } + + private void tbGateway_Validating(object sender, CancelEventArgs e) + { + Network mynet = NB.GetNetwork(); + if (ParentDevice != null) + { + IPAddress tAddress = mynet.DNSLookup(ParentDevice, tbGateway.Text); + } + + UInt32 taddress = tbGateway.Text.ParseIp(); + UInt32 startaddress = tbNetmask.Text.ParseIp(); + tbGateway.Text = taddress.ToIpString(); + if (DHCPInterface != null) + { + //We also check to verify that the address is in the correct range + if (!DHCPInterface.IsLocal(new IPAddress(tbGateway.Text))) + { + e.Cancel = true; + MessageBox.Show("The end IP in the range must be within the scope of the interface."); + } + if (taddress < startaddress) + { + e.Cancel = true; + MessageBox.Show("The end IP must be equal to or larger than the start IP."); + } + } + } + + private void tbNetmask_Validating(object sender, CancelEventArgs e) + { + UInt32 taddress = tbNetmask.Text.ParseIp(); + tbNetmask.Text = taddress.ToIpString(); + if (DHCPInterface != null) + { + //We also check to verify that the address is in the correct range + if (!DHCPInterface.IsLocal(new IPAddress(tbNetmask.Text))) + { + e.Cancel = true; + MessageBox.Show("The start IP in the range must be within the scope of the interface."); + } + } + } + + private void tbIPAddress_Validating(object sender, CancelEventArgs e) + { + UInt32 taddress; + Network mynet = NB.GetNetwork(); + IPAddress tIPAddress = null; + if (ParentDevice != null) + { + tIPAddress = mynet.DNSLookup(ParentDevice, tbIPAddress.Text); + } + if(tIPAddress != null) + { + taddress = tIPAddress.GetIP; + } + else + taddress = tbIPAddress.Text.ParseIp(); + tbIPAddress.Text = taddress.ToIpString(); + } + + public void SetText(string text) + { + this.Text = text; + } + } +} diff --git a/EduNetworkBuilder/LinkEditor.cs b/EduNetworkBuilder/LinkEditor.cs index 990824b..c15adc9 100644 --- a/EduNetworkBuilder/LinkEditor.cs +++ b/EduNetworkBuilder/LinkEditor.cs @@ -60,9 +60,9 @@ namespace EduNetworkBuilder { ResourceManager RM = NB.GetResource(); CultureInfo CI = NB.GetCulture(); - Text = RM.GetString("LE_btnLink", CI); - Text = RM.GetString("LE_btnCancel", CI); - Text = RM.GetString("LE_Form", CI); + Text = NB.Translate("LE_btnLink"); + Text = NB.Translate("LE_btnCancel"); + Text = NB.Translate("LE_Form"); } diff --git a/EduNetworkBuilder/ListBoxWindow.cs b/EduNetworkBuilder/ListBoxWindow.cs new file mode 100644 index 0000000..595b1b9 --- /dev/null +++ b/EduNetworkBuilder/ListBoxWindow.cs @@ -0,0 +1,442 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Globalization; +using System.Resources; + + +namespace EduNetworkBuilder +{ + public partial class ListBoxWindow : Form + { + protected LBContents MyMode = LBContents.messages; + protected DebugLevel WhatToDisplay = DebugLevel.info; //used when viewing packet-messages + NetworkDevice myNetDevice; + PacketMessage myPacketMessage; + int EditableCount = -1; + bool processing = false; + + /// + /// Instantiate a ListBoxWindow for use in choosing a network to load + /// + public ListBoxWindow() + { + InitializeComponent(); + LanguagifyComponents(); + MyMode = LBContents.puzzles; + + UpdateForm(); + CheckBox newCB; + btnAdd.Visible = false; + int count = 0; + lblInstructions.Text = "Filter the puzzles by checking one the boxes."; + panelCheckboxes.SuspendLayout(); + string SelectedTag = GetSelectedTag(); + if (SelectedTag == "ALL") + Text = Text + "(All Solved)"; + foreach (string str in NB.GetPuzzleTags()) + { + newCB = AddCheckBox(count, str); + if (str == SelectedTag || (SelectedTag == "ALL" && Regex.IsMatch(str,"Level"))) + { + newCB.Checked = true; //The first level with an unsolved puzzle starts checked + } + else + { + newCB.Checked = false; + } + count++; + } + panelCheckboxes.ResumeLayout(); + btnOK.Text = "Load"; + btnAdd.Text = "Cancel"; + btnAdd.Visible = true; + cbLoadPuzzlesAtStart.Checked = Properties.Settings.Default.AutoStartPuzzles; + UpdateForm(); + } + + /// + /// We are doing a routing table or dhcp. We pass it the device and pull the data from that + /// + /// The master device to edit/view the routing table of + public ListBoxWindow(NetworkDevice MasterDevice, LBContents mode) + { + InitializeComponent(); + LanguagifyComponents(); + if (mode == LBContents.routes) + { + MyMode = LBContents.routes; + myNetDevice = MasterDevice; + lblInstructions.Text = "Double-click a route to change it."; + lbWindowData.Font = new System.Drawing.Font("Courier New", 8); + btnAdd.Visible = true; + } + if (mode == LBContents.dhcp) + { + MyMode = LBContents.dhcp; + myNetDevice = MasterDevice; + lblInstructions.Text = "Double-Click the interface to add/edit the range of DHCP to serve."; + lbWindowData.Font = new System.Drawing.Font("Courier New", 8); + btnAdd.Visible = false; + } + UpdateForm(); + } + + /// + /// We are doing a packet message detail look. + /// + /// The packet message to look at + public ListBoxWindow(PacketMessage Messages) + { + InitializeComponent(); + LanguagifyComponents(); + MyMode = LBContents.messages; + myPacketMessage = Messages; + UpdateForm(); + btnAdd.Visible = false; + int count=0; + lblInstructions.Text = "For greater detail, click on the check-boxes"; + panelCheckboxes.SuspendLayout(); + foreach (string str in Enum.GetNames(typeof(DebugLevel))) + { + AddCheckBox(count, str); + count++; + } + panelCheckboxes.ResumeLayout(); + UpdateChecked(); + } + + private void LanguagifyComponents() + { + ResourceManager RM = NB.GetResource(); + CultureInfo CI = NB.GetCulture(); + Text = NB.Translate("LBW_btnOK"); + Text = NB.Translate("LBW_lblInstructions"); + Text = NB.Translate("LBW_btnAdd"); + Text = NB.Translate("LBW_cbLoadPuzzlesAtStart"); + Text = NB.Translate("LBW_btnReset"); + Text = NB.Translate("LBW_Form"); + } + + private CheckBox AddCheckBox(int count, string name) + { + int myY = 1; + int myX = 1; + int cdwidth = 70; + int cdHeight = 20; + int divisor = panelCheckboxes.Width / cdwidth; + myX = (cdwidth * count) % (divisor * cdwidth); + myY = ((cdwidth * count) / (divisor * cdwidth)) * cdHeight; + CheckBox newCB = new CheckBox(); + newCB.Text = name; + Point mylocation = new Point(myX, myY); + newCB.AutoSize = true; + newCB.Name = "checkBox" + count.ToString(); + newCB.Size = new System.Drawing.Size(98, 21); + newCB.TabIndex = count; + newCB.UseVisualStyleBackColor = true; + newCB.Location = mylocation; + newCB.CheckedChanged += genericCheckmarkChange; + panelCheckboxes.Controls.Add(newCB); + return newCB; + } + + private string GetSelectedTag() + { + if (Properties.Settings.Default.ScoreList == null) + Properties.Settings.Default.ScoreList = new System.Collections.Specialized.StringCollection(); + PuzzleInfo PI; + foreach (string str in NB.GetPuzzleNames()) + { + if(!Properties.Settings.Default.ScoreList.Contains(str)) + { + PI = NB.GetPuzzleInfoFromName(str); + return "Level_" + PI.Level; + } + } + return "ALL"; + } + + private void UpdateForm() + { + int selectedIndex = lbWindowData.SelectedIndex; + string selected = ""; + if (lbWindowData.SelectedIndex != -1) + selected = lbWindowData.Items[lbWindowData.SelectedIndex].ToString(); + lbWindowData.Items.Clear(); + cbLoadPuzzlesAtStart.Visible = false; + btnReset.Visible = false; + List itemstrings = new List(); + if (MyMode == LBContents.messages) + { + itemstrings.AddRange(myPacketMessage.GetMessagesSummary()); + itemstrings.AddRange(myPacketMessage.GetMessagesLike(WhatToDisplay)); + foreach (string str in itemstrings) + { + lbWindowData.Items.Add(str); + } + } + if(MyMode == LBContents.routes) + { + itemstrings.Add("--Static Routes (Read/Write)--"); + itemstrings.AddRange(myNetDevice.DeviceRouteStrings()); + EditableCount = itemstrings.Count(); + itemstrings.Add("--Routes from NICs (Read-Only)--"); + itemstrings.AddRange(myNetDevice.NICRouteStrings()); + foreach (string str in itemstrings) + { + lbWindowData.Items.Add(str); + } + } + if (MyMode == LBContents.dhcp) + { + myNetDevice.CheckDHCPRangesAgainstInterfaces(); + itemstrings.AddRange(myNetDevice.DHCPStrings()); + foreach (string str in itemstrings) + { + lbWindowData.Items.Add(str); + } + } + if (MyMode == LBContents.puzzles) + { + cbLoadPuzzlesAtStart.Visible = true; + btnReset.Visible = true; + PuzzleInfo pi; + if (Properties.Settings.Default.ScoreList == null) + Properties.Settings.Default.ScoreList = new System.Collections.Specialized.StringCollection(); + string shown_name; + List Puzzles = NB.GetPuzzleNames(); + if (Puzzles == null) return; + foreach (string str in Puzzles) + { + pi = NB.GetPuzzleInfoFromName(str); + shown_name = pi.PuzzleName; + if (Properties.Settings.Default.ScoreList.Contains(str)) + shown_name = "* " + shown_name; + foreach(string tag in pi.PuzzleTags) + { + if(isChecked(tag)) + { + lbWindowData.Items.Add(shown_name); + break; + } + } + } + if(selected != null && selected != "") + { + if (lbWindowData.Items.Contains(selected)) + lbWindowData.SelectedItem = selected; + } + if(lbWindowData.SelectedIndex != -1) + { + btnOK.Enabled = true; + } + else + { + btnOK.Enabled = false; + } + } + } + + private void btnOK_Click(object sender, EventArgs e) + { + if (MyMode == LBContents.puzzles && lbWindowData.SelectedItem != null) + { + string TheName = lbWindowData.SelectedItem.ToString(); + TheName = Regex.Replace(TheName, @"^\* ", ""); + Visible = false; + BuilderWindow myWin = (BuilderWindow)Application.OpenForms["BuilderWindow"]; + if (myWin == null) + { + myWin.Activate(); + } + if(Properties.Settings.Default.AutoStartPuzzles != cbLoadPuzzlesAtStart.Checked) + { + Properties.Settings.Default.AutoStartPuzzles = cbLoadPuzzlesAtStart.Checked; + Properties.Settings.Default.Save(); + } + if (lbWindowData.SelectedItem != null) + NB.LoadNetworkFromResource(TheName); + } + Close(); + } + + /// + /// The checkmark was changed. Tally up everything + /// + /// The checkmark that changed + /// + private void genericCheckmarkChange(object sender, EventArgs e) + { + if (processing) return; + CheckBox mybox = (CheckBox)sender; + if (MyMode == LBContents.messages) + { + if (mybox.Checked) + { + WhatToDisplay = WhatToDisplay | NB.ParseEnum(mybox.Text); + } + else + { + WhatToDisplay = WhatToDisplay ^ NB.ParseEnum(mybox.Text); + } + } + UpdateChecked(); + } + + private bool isChecked(string Name) + { + foreach (Control mycontrol in panelCheckboxes.Controls) + { + //pull out the name + CheckBox cb = (CheckBox)mycontrol; + //make an enum. See if that is set. If so, mark it as checked + if(cb.Text.ToLower() == Name.ToLower()) + { + return cb.Checked; + } + } + return false; + } + + private void UpdateChecked() + { + processing = true; + DebugLevel toFind; + if (MyMode == LBContents.messages) + { + foreach (Control mycontrol in panelCheckboxes.Controls) + { + //pull out the name + CheckBox cb = (CheckBox)mycontrol; + //make an enum. See if that is set. If so, mark it as checked + toFind = NB.ParseEnum(mycontrol.Text); + if ((toFind & WhatToDisplay) == toFind) + { + cb.Checked = true; + } + else //If not, mark it as not checked. + { + cb.Checked = false; + } + } + } + processing=false; + UpdateForm(); + } + + private void btnAdd_Click(object sender, EventArgs e) + { + if (MyMode == LBContents.routes) + { + AddRoute(); + } + if(MyMode == LBContents.puzzles) + { + if (Properties.Settings.Default.AutoStartPuzzles != cbLoadPuzzlesAtStart.Checked) + { + Properties.Settings.Default.AutoStartPuzzles = cbLoadPuzzlesAtStart.Checked; + Properties.Settings.Default.Save(); + } + Close(); + } + } + private void AddRoute() + { + IPAddress newip = new IPAddress(NB.ZeroIPString, NB.ZeroIPString, NB.ZeroIPString); + newip.Edit(myNetDevice,"Create Route"); + myNetDevice.AddRoute(newip); + UpdateForm(); + } + + private void lbWindowData_DoubleClick(object sender, EventArgs e) + { + + if (MyMode == LBContents.routes) + { + if (lbWindowData.SelectedIndex >= EditableCount) return; + if (lbWindowData.SelectedIndex < 1) return; + //we always subtract 1 since we have added one line of comment to the list + myNetDevice.EditRoute(lbWindowData.SelectedIndex - 1); + } + if(MyMode == LBContents.dhcp) + { + //We always add one since we are skipping the loopback device + myNetDevice.EditDHCP(lbWindowData.SelectedIndex + 1); + } + if (MyMode == LBContents.puzzles) + { + //Just like pressing the OK button. We load the map + btnOK_Click(sender, e); + } + UpdateForm(); + } + private void lbWindowData_Edit_Click(object sender, EventArgs e) + { + lbWindowData_DoubleClick(sender, e); + } + private void lbWindowData_Delete_Click(object sender, EventArgs e) + { + if (MyMode == LBContents.routes) + { + if (lbWindowData.SelectedIndex >= EditableCount) return; + if (lbWindowData.SelectedIndex < 1) return; + //we always subtract 1 since we have added one line of comment to the list + myNetDevice.DeleteRoute(lbWindowData.SelectedIndex - 1); + } + UpdateForm(); + } + private void lbWindowData_RightMouseUp(object sender, MouseEventArgs e) + { + int index=0; + if(MyMode == LBContents.routes) + { + if (lbWindowData.ContextMenuStrip == null) + { + lbWindowData.ContextMenuStrip = new ContextMenuStrip(); + } + lbWindowData.ContextMenuStrip.Items.Clear(); + lbWindowData.ContextMenuStrip.Items.Add("Edit"); + lbWindowData.ContextMenuStrip.Items[index++].Click += lbWindowData_Edit_Click; + lbWindowData.ContextMenuStrip.Items.Add("Delete"); + lbWindowData.ContextMenuStrip.Items[index++].Click += lbWindowData_Delete_Click; + } + } + private void lbWindowData_MouseUp(object sender, MouseEventArgs e) + { + if (e.Button == System.Windows.Forms.MouseButtons.Right) + { + lbWindowData_RightMouseUp(sender, e); + return; + } + else + { + if(MyMode == LBContents.puzzles) + { + UpdateForm(); + } + } + } + + private void btnReset_Click(object sender, EventArgs e) + { + if (Properties.Settings.Default.ScoreList == null) + Properties.Settings.Default.ScoreList = new System.Collections.Specialized.StringCollection(); + DialogResult answer = MessageBox.Show("Are sure you want to forget what puzzles you have done?", "Forget Puzzles?", MessageBoxButtons.YesNo); + if (answer == System.Windows.Forms.DialogResult.Yes) + { + Properties.Settings.Default.ScoreList.Clear(); + Properties.Settings.Default.Save(); + UpdateForm(); + } + } + + } +} diff --git a/EduNetworkBuilder/NB.cs b/EduNetworkBuilder/NB.cs new file mode 100644 index 0000000..27c5228 --- /dev/null +++ b/EduNetworkBuilder/NB.cs @@ -0,0 +1,570 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Deployment.Application; +using System.Windows.Forms; +using System.Globalization; +using System.Resources; +using System.Xml; +using System.Drawing; +using System.Media; +using System.Reflection; + + +namespace EduNetworkBuilder +{ + public enum PacketStatus { + processing, //It is inside a device. It needs to be routed, masqueraded, or whatever + input, //It is hitting the interface/nic of a device. + output, //It is leaving a device. Make sure the mac address is what it should be & that we are going out the right link + waiting_for_arp, //It is in the output chain, has been procesed, but is waiting for an arp packet to give it the dest MAC + moving, //It is traveling along a link. We increment the distance it has gone and re-draw the packet. + encapsulated, //It has been put inside another packet. + finished_ok,//The packet has finished and is ready to be removed from the network + finished_failed, //The packet is finished (failed) and is ready to be removed from the network. + finished //There was an appropriate reason this packet finished. It stopped + } + public enum LinkType { normal, wireless, broken } + public enum PacketType { none, ping_request, ping_answer, arp_request, arp_answer, dhcp_request, dhcp_answer, vpn_packet, tun_packet } + public enum ResponseToPacket { none, accept, masq, drop, reject } + public enum DebugLevel { none=0, info=1, routing=2, switching=4, natting=8, filtering=16, debug=32 , packet=64, all=127} + public enum NetworkComponentType { none, router, net_switch, net_hub, laptop, pc, server, wap , + wrouter, wbridge, wrepeater, link, firewall, ip_phone, printer, copier } + public enum NicType { none, lo, eth, wlan, wan, vpn, tun, management_interface, port, wport } + public enum IPAddressType { ip, gw, route, ip_only } + public enum nb_direction { none, to_src, to_dst } + public enum GeneralComponentType { none, link, device } + public enum NBSoundType { none, success } + public enum RTFWindowContents { help, about, release_notes } + public enum NetTestType { NeedsLocalIPTo, NeedsDefaultGW, NeedsLinkToDevice, NeedsRouteToNet, + SuccessfullyPings, SuccessfullyArps, SuccessfullyDHCPs, HelpRequest, FailedPing, + LockAll, LockIP, LockRoute, LockNic, LockDHCP, LockGateway + } + public enum NetTestVerbosity { none, basic, hints, full } + public enum LBContents { routes, messages, dhcp, puzzles } + public enum HelpTopics { + DHCP, DHCPServer, Firewall, Gateway, Help, IPAddress, Link, Subnet, Ping, + VPN, Hub, Switch, ARP, StaticRoute, Subnetting, WhenToSubnet, ComparingAddresses, MACAddress, + Network, Packet, NIC, Interface + } + public enum PuzzleNames + { + Level0_IP, Level1_NoGateway, Level0_NeedsLink, Level0_NoSwitch, Level1_BadDHCP, Level1_BadGateway, + Level0_SimpleDHCP, Level1_BadIP, Level0_Help, Level0_Ping, Level0_HubVsSwitch, Level1_MixedNetwork, + Level1_MidDHCP, Level1_OneNetTwoSubnets, Level1_DuplicateIPs, Level0_NetworkLoop, Level1_DuplicateMAC, + Level2_FirewallDemo, Level1_OneNetTwoSubnets2, Level2_VPN_Demo, Level2_Bad_VPN_IP, Level2_Bad_Encryption, + Level2_Bad_Route, Level2_Blast_From_Past, Level2_Not_Working, Level2_Build_A_VPN, Level2_Connect_The_Dots, + Level3_BlackHole, Level3_Busted, Level3_Middle_Man_Out, Level3_PhoneyNetwork, Level3_VPNify, Level3_EncryptionTroubles, + Level3_NowhereToGo, Level3_GrandCentralStation, Level3_Dead, Level0_NetworkLoop2, Level0_BrokenLink, + Level4_DualWans, Level4_SinglesLife, Level4_SmallSubnets, Level4_OneRoute, Level4_RouterReplacement, + Level4_InternalSubnetting, Level4_Internalhemorrhage, + } + public enum DebugPausePoint { none=0, packet_create=1, packet_kill=2, + packet_in=4, packet_out=8, packet_duplicate=16, all=63, + dump=256, pause=512} + + + [Serializable] + public struct HostNicID //This holds a unique identifier for a network card. Links use this to know what it is connected to + { + public int HostID; + public int NicID; + public string HostName; + public string NicName; + public HostNicID(int host, int nic, string hostname, string nicname) + { + HostID = host; + NicID = nic; + HostName = hostname; + NicName = nicname; + } + public HostNicID(XmlNode theNode) + { + HostID = 0; + NicID = 0; + HostName = ""; + NicName = ""; + foreach (XmlNode Individual in theNode.ChildNodes) + { + XmlNodeType myNodetype = Individual.NodeType; + if (myNodetype == XmlNodeType.Element) + { + switch (Individual.Name.ToLower()) + { + case "hostid": + int.TryParse(Individual.InnerText, out HostID); + break; + case "nicid": + int.TryParse(Individual.InnerText, out NicID); + break; + case "hostname": + HostName = Individual.InnerText; + break; + case "nicname": + NicName = Individual.InnerText; + break; + } + } + } + } + public void Save(XmlWriter writer, string tag) + { + writer.WriteStartElement(tag); + writer.WriteElementString("hostid", HostID.ToString()); + writer.WriteElementString("nicid", NicID.ToString()); + writer.WriteElementString("hostname", HostName); + writer.WriteElementString("nicname", NicName); + writer.WriteEndElement(); + } + public string HostNicIDString + { + get { return HostID.ToString()+"-"+NicID.ToString(); } + } + public bool Equals(HostNicID toCheck) + { + if (HostID != toCheck.HostID) return false; + if (NicID != toCheck.NicID) return false; + if (HostName != toCheck.HostName) return false; + if (NicName != toCheck.NicName) return false; + return true; + } + + } + + [Serializable] + public struct IPConnectionEntry + { + public IPAddress destIP; //where we are sending the packet to. We expect a response to come from here + public PacketType What; //ping, dhcp, etc + public ResponseToPacket Response; //accept, masq + public IPAddress internalIP; //Used if we are masquerading + public IPConnectionEntry(IPAddress dest, PacketType what, ResponseToPacket response) + { + destIP = dest; + What = what; + Response = response; + internalIP = null; + } + public IPConnectionEntry(IPAddress dest, PacketType what, ResponseToPacket response, IPAddress internal_ip) + { + destIP = dest; + What = what; + Response = response; + internalIP = internal_ip; + } + } + + [Serializable] + public struct ArpEntry + { + public string MACAddress; + public string IPAddr; + public HostNicID NicOnWhichItIsFound; + public ArpEntry(string mac, string ip, HostNicID thenic) + { + MACAddress = mac; + IPAddr = ip; + NicOnWhichItIsFound = thenic; + } + } + + public class PuzzleInfo + { + public string PuzzleName; + public string PuzzleTitle; + public string PuzzleDescription; + public List PuzzleTags = new List(); + public int Level=0; + public double SortOrder=0; + public void Load(XmlNode TheNode, string Name) + { + PuzzleName = Name; + foreach (XmlNode Individual in TheNode.ChildNodes) + { + XmlNodeType myNodetype = Individual.NodeType; + if (myNodetype == XmlNodeType.Element) + { + switch (Individual.Name.ToLower()) + { + case "edunetworkbuilder": + case "network": + Load(Individual, PuzzleName); + break; + case "message": + PuzzleDescription = Individual.InnerText; + break; + case "title": + PuzzleTitle = Individual.InnerText; + break; + case "tag": + PuzzleTags.Add(Individual.InnerText); + break; + case "level": + PuzzleTags.Add("Level_" + Individual.InnerText); + int.TryParse(Individual.InnerText, out Level); + break; + case "sortorder": + double.TryParse(Individual.InnerText, out SortOrder); + break; + } + } + } + } + } + + class NB + { + + public static string BroadcastMACString = "FF:FF:FF:FF:FF:FF"; //The broadcast MAC address + public static string BroadcastIPString = "255.255.255.255"; //the generic broadcast IP address + public static string ZeroIPString = "0.0.0.0"; + public static string LoopbackIPString = "127.0.0.1"; + public static int LinkStep = 8;//The percentage of the link we move at each "tick" + public static int PacketPixelSize = 8; //The size of the packet pixel + public static int PacketVersionNum = 2; //2 uses the new stuff. Anything else uses the old stuff + public const int GridSize = 10; + public static string[,] LanguageChoices = { { "English", "en" }, { "French", "fr" } }; + + /// + /// Find the global random number generator. + /// + /// A valid random number generator + public static Random GetRandom() + { + BuilderWindow myWin = (BuilderWindow)Application.OpenForms["BuilderWindow"]; + if (myWin == null) return new Random(); + if (myWin.GameRandomGen == null) return new Random(); + return myWin.GameRandomGen; + } + /// + /// Find the global random number generator. + /// + /// A valid random number generator + public static CultureInfo GetCulture() + { + BuilderWindow myWin = (BuilderWindow)Application.OpenForms["BuilderWindow"]; + CultureInfo CI=null; + if (myWin != null) + { + CI = myWin.GetCulture(); + } + if(CI == null || myWin == null) + { + string CL = Properties.Settings.Default.ChosenLanguage; + CI = CultureInfo.CreateSpecificCulture(CL); + } + return CI; + } + /// + /// Find the global random number generator. + /// + /// A valid random number generator + public static ResourceManager GetResource() + { + ResourceManager myresource = null; + BuilderWindow myWin = (BuilderWindow)Application.OpenForms["BuilderWindow"]; + if (myWin != null) + { + myresource = myWin.GetResource(); + } + if(myresource == null || myWin == null) + { + System.Reflection.Assembly MyAssembly; + MyAssembly = Assembly.GetCallingAssembly(); + myresource = new ResourceManager("EduNetworkBuilder.Resources.languages.edustrings", MyAssembly); + } + return myresource; + } + + public static Point GetSnapped(Point Location) + { + int x = (Location.X / NB.GridSize) * NB.GridSize; + int y = (Location.Y / NB.GridSize) * NB.GridSize; + Point newlocation = new Point(x, y); + return newlocation; + } + + public static Network GetNetwork() + { + BuilderWindow myWin = (BuilderWindow)Application.OpenForms["BuilderWindow"]; + if (myWin == null) return null; + if (myWin.GameRandomGen == null) return null; + return myWin.myNetwork; + } + + /// + /// Return a translated string in the current chosen language + /// + /// The key for the item we are translating + /// A string of the translated information + public static string Translate(string key) + { + BuilderWindow myWin = (BuilderWindow)Application.OpenForms["BuilderWindow"]; + if (myWin == null) + { + ResourceManager RM = GetResource(); + CultureInfo CI = GetCulture(); + string answer; + answer = RM.GetString(key, CI); + return answer; + } + return myWin.Translate(key); + } + + public static DebugPausePoint GetDebugPauseSetting() + { + BuilderWindow myWin = (BuilderWindow)Application.OpenForms["BuilderWindow"]; + if (myWin == null) return DebugPausePoint.none; + if (myWin.GameRandomGen == null) return DebugPausePoint.none; + return myWin.DebugSetting; + } + + public static PuzzleInfo GetPuzzleInfoFromName(string PuzzleName) + { + BuilderWindow myWin = (BuilderWindow)Application.OpenForms["BuilderWindow"]; + if (myWin == null) return null; + return myWin.PuzzleInfoFromName(PuzzleName); + } + public static void ChangeLanguage() + { + //Find the window. If it exists, use /set the language setting there. If not, use / set the default. + BuilderWindow myWin = (BuilderWindow)Application.OpenForms["BuilderWindow"]; + string lang = Properties.Settings.Default.ChosenLanguage; + if (lang == "") lang = "en"; + + string StartingItem = ""; + for (int i = 0; i < LanguageChoices.GetLength(0); i++) + { + if (lang == LanguageChoices[i, 1]) + { + StartingItem = LanguageChoices[i, 0]; + } + } + + + //we need to choose a language: + Form LanguageForm = new Form(); + LanguageForm.Text = "Choose Language"; + Label lblText = new Label(); + lblText.Location = new Point(5, 5); + lblText.AutoSize = true; + lblText.Text = "Choose a Language:"; + LanguageForm.Icon = Properties.Resources.NBIco; + + ComboBox cbQuestions = new ComboBox(); + cbQuestions.Location = new Point(lblText.Location.X + lblText.Width + 10, lblText.Location.Y); + cbQuestions.Width = 60; + for (int i = 0; i < LanguageChoices.GetLength(0); i++ ) + { + cbQuestions.Items.Add(LanguageChoices[i,0]); + } + if(cbQuestions.Items.Contains(StartingItem)) + { + cbQuestions.SelectedItem = StartingItem; + } + else + cbQuestions.SelectedIndex = 0; + + LanguageForm.Width = cbQuestions.Location.X + cbQuestions.Width + 70; + LanguageForm.Height = 90; + LanguageForm.AutoSize = true; + + Button btnAccept = new Button(); + btnAccept.Location = new Point(cbQuestions.Location.X, cbQuestions.Location.Y + cbQuestions.Height + 10); + btnAccept.Text = "OK"; + btnAccept.Click += (s, g) => { Button b = (Button)s; Form f = (Form)b.Parent; f.Close(); }; + + LanguageForm.Controls.Add(lblText); + LanguageForm.Controls.Add(cbQuestions); + LanguageForm.Controls.Add(btnAccept); + + LanguageForm.ShowDialog(); + if (cbQuestions.SelectedIndex >= 0) + { + Properties.Settings.Default.LanguageHasBeenChosen = true; + string mychoice = LanguageChoices[cbQuestions.SelectedIndex, 1]; + if (myWin == null) + { + Properties.Settings.Default.ChosenLanguage = mychoice; + //Properties.Settings.Default.Save(); //We do this when we exit. No need to save it right this instant. + } + else + { + myWin.ChosenLanguage = mychoice; + } + } + } + + + public static void PlaySound(NBSoundType What) + { + SoundPlayer sndClick; + switch (What) + { + case NBSoundType.none: + break; + case NBSoundType.success: + sndClick = new SoundPlayer(Properties.Resources.wavBellDing); + sndClick.Play(); + break; + } + } + + public static List GetPuzzleTags() + { + BuilderWindow myWin = (BuilderWindow)Application.OpenForms["BuilderWindow"]; + if (myWin == null) return null; + return myWin.GetPuzzleTags(); + } + + public static List GetPuzzleNames() + { + BuilderWindow myWin = (BuilderWindow)Application.OpenForms["BuilderWindow"]; + if (myWin == null) return null; + return myWin.GetPuzzleNames(); + } + + public static void LoadNetworkFromResource(string resource) + { + BuilderWindow myWin = (BuilderWindow)Application.OpenForms["BuilderWindow"]; + if (myWin == null) return; + myWin.LoadNetworkFromResource(resource); + } + + public static void SetProgress(double HowFar, double total) + { + BuilderWindow myWin = (BuilderWindow)Application.OpenForms["BuilderWindow"]; + if (myWin == null) return; + myWin.SetProgress(HowFar, total); + } + + public static int GetUniqueIdentifier() + { + Network myNet = GetNetwork(); + if(myNet == null) + { + //We should never get here. If so, we are in a bad sort of way. + Random rnd = GetRandom(); + return rnd.Next(1,100); + } + return myNet.GetUniqueIdentifier(); + } + + public static void Delay(int amount) + { + System.Threading.Thread.Sleep(amount); + } + + public static T ParseEnum(string value) + { + return (T)Enum.Parse(typeof(T), value, true); + } + + public static GeneralComponentType GetComponentType(NetworkComponent What) + { + GeneralComponentType theType = GeneralComponentType.none; + if(What.GetType().ToString() == "EduNetworkBuilder.NetworkDevice") + theType = GeneralComponentType.device; + if (What.GetType().ToString() == "EduNetworkBuilder.NetworkLink") + theType = GeneralComponentType.link; + return theType; + } + + public static string GenerateMACAddress() + { + var sBuilder = new StringBuilder(); + var random = GetRandom(); + int number; + byte b; + for (int i = 0; i < 6; i++) + { + number = random.Next(0, 255); + b = Convert.ToByte(number); + if (i == 0) + { + b = setBit(b, 6); //--> set locally administered + b = unsetBit(b, 7); // --> set unicast + } + sBuilder.Append(number.ToString("X2")); + } + string mac= sBuilder.ToString().ToUpper(); + if (MAC_Exists(mac)) + return GenerateMACAddress(); //If it already exists, generate another + return mac; + } + + public static bool MAC_Exists(string MAC) + { + Network myNet = GetNetwork(); + if(myNet == null) return false; + return myNet.MAC_Exists(MAC); + } + + public static List arp(UInt32 IP) + { + List arps = new List(); + Network myNet = GetNetwork(); + if (myNet == null) return arps; + return myNet.arp(IP); + } + + private static byte setBit(byte b, int BitNumber) + { + if (BitNumber < 8 && BitNumber > -1) + { + return (byte)(b | (byte)(0x01 << BitNumber)); + } + else + { + throw new InvalidOperationException( + "Invalid Bit " + BitNumber.ToString() + "! (Should be from 0 to 7)"); + } + } + + private static byte unsetBit(byte b, int BitNumber) + { + if (BitNumber < 8 && BitNumber > -1) + { + return (byte)(b | (byte)(0x00 << BitNumber)); + } + else + { + throw new InvalidOperationException( + "Invalid Bit" + BitNumber.ToString() + "! (Should be from 0 to 7)"); + } + } + + /// + /// Randomize a list + /// + /// The type of list to return + /// The list to randomize + /// a new list that is randomized + public static List Randomize(List list) + { + + List randomizedList = new List(list); + Random rnd = GetRandom(); + int n = randomizedList.Count; + int counter = 0; + T value; + while (n > 1) + { + n--; + int k = rnd.Next(n + 1); + value = randomizedList[k]; + randomizedList[k] = randomizedList[n]; + randomizedList[n] = value; + counter++; + if (counter > 10) + { + counter = 0; + } + } + return randomizedList; + } + + } +} diff --git a/EduNetworkBuilder/NetTest.cs b/EduNetworkBuilder/NetTest.cs new file mode 100644 index 0000000..27cc49e --- /dev/null +++ b/EduNetworkBuilder/NetTest.cs @@ -0,0 +1,361 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Drawing; +using System.Xml; + +namespace EduNetworkBuilder +{ + public class NetTest + { + public string sHost = ""; + public string dHost = ""; + public Color WrongColor = Color.Red; + public NetTestType TheTest = NetTestType.NeedsDefaultGW; + public bool TaskWasDone = false; + + public NetTest(string srcHost, string dstHost, NetTestType tTest) + { + sHost = srcHost; + dHost = dstHost; + TheTest = tTest; + } + + public NetTest(NetTest FromWhat) + { + sHost = FromWhat.sHost; + dHost = FromWhat.dHost; + TheTest = FromWhat.TheTest; + } + + public NetTest(XmlNode theNode) + { + foreach (XmlNode Individual in theNode.ChildNodes) + { + XmlNodeType myNodetype = Individual.NodeType; + if (myNodetype == XmlNodeType.Element) + { + switch (Individual.Name.ToLower()) + { + case "sourcehost": + case "shost": + sHost = Individual.InnerText; + break; + case "desthost": + case "dhost": + dHost = Individual.InnerText; + break; + case "thetest": + TheTest = NB.ParseEnum(Individual.InnerText); + break; + } + } + } + } + + public void Save(XmlWriter writer) + { + writer.WriteStartElement("nettest"); + writer.WriteElementString("shost", sHost); + writer.WriteElementString("dhost", dHost); + writer.WriteElementString("thetest", TheTest.ToString()); + writer.WriteEndElement(); + } + + public void UpdateValuesFromAnother(NetTest WhatFrom) + { + dHost = WhatFrom.dHost; + sHost = WhatFrom.sHost; + TheTest = WhatFrom.TheTest; + WrongColor = WhatFrom.WrongColor; + } + + public bool Equals(NetTest CompareTo) + { + if (sHost != CompareTo.sHost) return false; + if (dHost != CompareTo.dHost) return false; + if (TheTest != CompareTo.TheTest) return false; + if (WrongColor != CompareTo.WrongColor) return false; + return true; + } + + public bool Edit() + { + NetTestEditor nte = new NetTestEditor(this); + NetTest copy = new NetTest(this); + nte.ShowDialog(); + if (copy.Equals(this)) return false; + return true; + } + + private string TestDescription(NetTestVerbosity amount) + { + string toreturn = ""; + switch(amount) + { + case NetTestVerbosity.basic: + toreturn = "Has a problem"; + break; + case NetTestVerbosity.hints: + switch (TheTest) + { + case NetTestType.NeedsDefaultGW: + toreturn = "Needs the gateway set"; + break; +// case NetTestType.NeedsPingToHost: +// toreturn = "Cannot ping"; +// break; + case NetTestType.NeedsRouteToNet: + toreturn = "Needs a route set"; + break; + case NetTestType.NeedsLocalIPTo: + toreturn = "Needs a local IP"; + break; + case NetTestType.NeedsLinkToDevice: + toreturn = "Needs to be connected to the network."; + break; + case NetTestType.SuccessfullyArps: + toreturn = "Needs to find ARP from some device"; + break; + case NetTestType.SuccessfullyDHCPs: + toreturn = "Needs a DHCP IP address"; + break; + case NetTestType.SuccessfullyPings: + toreturn = "Must ping a host."; + break; + case NetTestType.HelpRequest: + toreturn = "Get mouse-over help"; + break; + case NetTestType.FailedPing: + toreturn = "Should fail to ping a specific host"; + break; + case NetTestType.LockAll: + toreturn = "Is Locked"; + break; + case NetTestType.LockDHCP: + toreturn = "Has Locked DHCP"; + break; + case NetTestType.LockIP: + toreturn = "Has Locked IP"; + break; + case NetTestType.LockNic: + toreturn = "Has Locked NIC"; + break; + case NetTestType.LockRoute: + toreturn = "Has Locked Route"; + break; + case NetTestType.LockGateway: + toreturn = "Has Locked Gateway"; + break; + } + break; + case NetTestVerbosity.full: + switch (TheTest) + { + case NetTestType.NeedsDefaultGW: + toreturn = "Needs the gateway set to:"; + break; +// case NetTestType.NeedsPingToHost: +// toreturn = "Cannot ping host:"; +// break; + case NetTestType.NeedsRouteToNet: + toreturn = "Needs a route to network:"; + break; + case NetTestType.NeedsLocalIPTo: + toreturn = "Needs an IP local to host:"; + break; + case NetTestType.NeedsLinkToDevice: + toreturn = "Needs a link to host:"; + break; + case NetTestType.SuccessfullyArps: + toreturn = "Needs to find ARP from:"; + break; + case NetTestType.SuccessfullyDHCPs: + toreturn = "Needs a DHCP IP address from server:"; + break; + case NetTestType.SuccessfullyPings: + toreturn = "Must ping:"; + break; + case NetTestType.HelpRequest: + toreturn = "Get mouse-over help of level:"; + break; + case NetTestType.FailedPing: + toreturn = "Needs to try to ping (and fail):"; + break; + case NetTestType.LockAll: + toreturn = "Is Locked:"; + break; + case NetTestType.LockDHCP: + toreturn = "Has Locked DHCP:"; + break; + case NetTestType.LockIP: + toreturn = "Has Locked IP:"; + break; + case NetTestType.LockNic: + toreturn = "Has Locked NIC:"; + break; + case NetTestType.LockRoute: + toreturn = "Has Locked Route:"; + break; + case NetTestType.LockGateway: + toreturn = "Has Locked Gateway:"; + break; + } + break; + case NetTestVerbosity.none: + toreturn = ""; + break; + } + return toreturn; + } + + public string GetDescription(NetTestVerbosity amount) + { + string toreturn = ""; + switch(amount) + { + case NetTestVerbosity.basic: + toreturn = sHost + " " + TestDescription(amount); + break; + case NetTestVerbosity.hints: + toreturn = sHost + " " + TestDescription(amount); + break; + case NetTestVerbosity.full: + toreturn = sHost + " " + TestDescription(amount) + " " + dHost; + break; + case NetTestVerbosity.none: + toreturn = ""; + break; + } + return toreturn; + } + + + public bool TestPiecesExist() + { + Network theNet = NB.GetNetwork(); + NetworkDevice Source = theNet.GetDeviceFromName(sHost); + NetworkDevice Dest = theNet.GetDeviceFromName(dHost); + if (Source == null) return false; + if (Dest == null) return false; + return true; + } + + public bool ColorItemsIfNeeded(bool ChangeColor) + { + bool WasDone = TaskWasDone; + if(!TestComplete()) + { + Network theNet = NB.GetNetwork(); + NetworkDevice Source = theNet.GetDeviceFromName(sHost); + if(Source!= null) + { + if (ChangeColor) + { + Source.BackgroundColor = WrongColor; + Source.IsDirty = true; //Make sure we re-draw it + } + return true; //We have a test that is not completed + } + return true; + } + if(WasDone == false) + { + //We just solved it for the first time + TaskWasDone = true; + NB.PlaySound(NBSoundType.success); + } + return false; //No need to color anything + } + + public void SetDone() + { + if(TaskWasDone == false) + { + NB.PlaySound(NBSoundType.success); + } + TaskWasDone = true; + } + + /// + /// See if the test has been solved + /// + /// + public bool TestComplete() + { + Network theNet = NB.GetNetwork(); + NetworkDevice Source = theNet.GetDeviceFromName(sHost); + NetworkDevice Dest = theNet.GetDeviceFromName(dHost); + IPAddress gw; + IPAddress tAddr; + + switch(TheTest) + { + case NetTestType.NeedsDefaultGW: + if (Source == null) return false; //Unable to do it. Do not count it against them. + if (Dest == null) return false; //Unable to do it. Do not count it against them. + + gw = Source.GetGateway(); + if(Dest.HasIPAddress(gw)) + { + //It has the IP. Is it local to the source? + if(Source.LocalNic(gw) != null) + { + //The default gw is set to the IP of the dest + //The IP address chosen is "local" to the source host. So it should ping between them + return true; + } + } + return false; //Something is not set right. + case NetTestType.NeedsRouteToNet: + if (Source == null) return false; //Unable to do it. Do not count it against them. + tAddr = theNet.DNSLookup(Source,dHost); + if (tAddr == null || tAddr.GetIPString == NB.ZeroIPString) + tAddr = new IPAddress(dHost); + if (Source.HasRouteMatching(tAddr)) + { + IPAddress route = Source.RouteMatching(tAddr); + if (Source.LocalNic(new IPAddress(route.GetGateway.ToIpString())) == null) + return false; //The gateway specified is not local to the device. We cannot get to it + return true; + } + return false; //if we get here, it has failed somehow + case NetTestType.NeedsLocalIPTo: + if (Source == null) return false; //Unable to do it. Do not count it against them. + if (Dest == null) return false; //Unable to do it. Do not count it against them. + tAddr = Source.LocalDeviceIP(Dest); + IPAddress dAddress = Dest.LocalDeviceIP(Source); + if (Dest.HasIPAddress(tAddr)) return false; //They gave the same address to the source that the dest has. + if (!theNet.HasUniqueIP(tAddr, Source)) return false; //Verify we have not given the IP to someone else + if (tAddr != null && + tAddr.GetIPString != NB.ZeroIPString) + { + if(dAddress != null & dAddress.GetMask == tAddr.GetMask) + return true; + } + return false; //Something is not set right. + case NetTestType.NeedsLinkToDevice: + if (Source == null) return false; //Unable to do it. Do not count it against them. + if (Dest == null) return false; //Unable to do it. Do not count it against them. + if (Source.HasLinkTo(dHost)) return true; + return false; //Something is not set right. + case NetTestType.SuccessfullyArps: + case NetTestType.SuccessfullyDHCPs: + case NetTestType.SuccessfullyPings: + case NetTestType.HelpRequest: + case NetTestType.FailedPing: + return TaskWasDone; //This variable will tell us if these tests have been done. + case NetTestType.LockAll: + case NetTestType.LockDHCP: + case NetTestType.LockIP: + case NetTestType.LockNic: + case NetTestType.LockRoute: + case NetTestType.LockGateway: + return true; //Nothing to solve. We just lock it so it cannot be changed. + } + return false; + } + } +} \ No newline at end of file diff --git a/EduNetworkBuilder/NetTestEditor.cs b/EduNetworkBuilder/NetTestEditor.cs new file mode 100644 index 0000000..c230a8e --- /dev/null +++ b/EduNetworkBuilder/NetTestEditor.cs @@ -0,0 +1,259 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Text.RegularExpressions; +using System.Globalization; +using System.Resources; + + +namespace EduNetworkBuilder +{ + public partial class NetTestEditor : Form + { + NetTest ToEdit; + NetTest OrigTest; + List HostNames = new List(); + List Networks = new List(); + List Broadcasts = new List(); + bool processing = false; + + public NetTestEditor(NetTest WhatToEdit) + { + InitializeComponent(); + LanguagifyComponents(); + OrigTest = WhatToEdit; + ToEdit = new NetTest(OrigTest); + + Network mynet = NB.GetNetwork(); + HostNames.AddRange(mynet.GetHostnames()); + Networks.AddRange(mynet.GetSubnets()); + Broadcasts.AddRange(mynet.GetBroadcasts()); + UpdateForm(); + } + + private void LanguagifyComponents() + { + ResourceManager RM = NB.GetResource(); + CultureInfo CI = NB.GetCulture(); + Text = NB.Translate("NTE_lblSource"); + Text = NB.Translate("NTE_lblTest"); + Text = NB.Translate("NTE_lblDest"); + Text = NB.Translate("NTE_btnOK"); + Text = NB.Translate("NTE_btnCancel"); + Text = NB.Translate("NTE_Form"); + } + + + private void btnOK_Click(object sender, EventArgs e) + { + OrigTest.UpdateValuesFromAnother(ToEdit); + Close(); + } + + private void btnCancel_Click(object sender, EventArgs e) + { + Close(); + } + + private void UpdateForm() + { + NetworkDevice sItem; + processing = true; + Network theNet = NB.GetNetwork(); + //We add all the hostnames as source + cbSource.Items.Clear(); + foreach(string host in HostNames) + { + cbSource.Items.Add(host); + } + + //The tests are just the list of available tests. + cbTest.Items.Clear(); + List tList = new List(); + foreach (string test in Enum.GetNames(typeof(NetTestType))) + { + tList.Add(test); + } + tList.Sort(); //Sort them alphabetically. Just to make things easier + foreach (string test in tList) + { + cbTest.Items.Add(test); + } + + cbDest.Items.Clear(); + if (ToEdit.TheTest == NetTestType.NeedsRouteToNet) + { //List all the networks + foreach (string subnet in Networks) + { + cbDest.Items.Add(subnet); + } + } + else if (ToEdit.TheTest == NetTestType.HelpRequest) + { + foreach (string subnet in Enum.GetNames(typeof(NetTestVerbosity))) + { + cbDest.Items.Add(subnet); + } + cbDest.Items.Add("?Button"); + } + else if (ToEdit.TheTest == NetTestType.LockAll || ToEdit.TheTest == NetTestType.LockGateway) + { + cbDest.Items.Add("All"); + } + else if (ToEdit.TheTest == NetTestType.LockDHCP) + { + //return all the dhcp ranges + sItem = theNet.GetDeviceFromName(ToEdit.sHost); + foreach(string ip in sItem.DHCPStrings(false)) + { + cbDest.Items.Add(ip); + } + } + else if (ToEdit.TheTest == NetTestType.LockIP) + { + //return all the dhcp ranges + sItem = theNet.GetDeviceFromName(ToEdit.sHost); + foreach (IPAddress ip in sItem.IPAddressList()) + { + cbDest.Items.Add(ip.GetIPString); + } + } + else if (ToEdit.TheTest == NetTestType.LockRoute) + { + //return all the dhcp ranges + sItem = theNet.GetDeviceFromName(ToEdit.sHost); + foreach (IPAddress ip in sItem.ListRoutes()) + { + cbDest.Items.Add(ip.GetIPString); + } + } + else if (ToEdit.TheTest == NetTestType.LockNic) + { + //return all the dhcp ranges + sItem = theNet.GetDeviceFromName(ToEdit.sHost); + foreach (string nname in sItem.NICNames()) + { + cbDest.Items.Add(nname); + } + } + else + { //List all the hosts + foreach (string host in HostNames) + { + cbDest.Items.Add(host); + } + + if (ToEdit.TheTest == NetTestType.SuccessfullyPings) + { //List all the network broadcasts + foreach (string subnet in Broadcasts) + { + cbDest.Items.Add(subnet); + } + } + } + + //Now we select all the appropriate items. + if(cbSource.Items.Contains(ToEdit.sHost)) + { + cbSource.SelectedItem = ToEdit.sHost; + } + else + { + if(cbSource.Items.Count > 0) + cbSource.SelectedIndex = 0; //select the first item + } + + if (cbDest.Items.Contains(ToEdit.dHost)) + { + cbDest.SelectedItem = ToEdit.dHost; + } + else + { + if (cbDest.Items.Count > 0) + cbDest.SelectedIndex = 0; //select the first item + } + + if (cbTest.Items.Contains(ToEdit.TheTest.ToString())) + { + cbTest.SelectedItem = ToEdit.TheTest.ToString(); + } + else + { + if (cbTest.Items.Count > 0) + cbTest.SelectedIndex = 0; //select the first item + } + processing = false; + } + + private void NetTestEditor_Load(object sender, EventArgs e) + { + + } + + private bool validate_choices() + { + if (processing) return true; //If we are processing, we are all OK. + Network theNet = NB.GetNetwork(); + NetTestType ntt = NB.ParseEnum(cbTest.SelectedItem.ToString()); + if (cbSource.SelectedItem.ToString() == cbDest.SelectedItem.ToString() && ntt != NetTestType.HelpRequest) + return false; //Source cannot equal dest + if (theNet.GetDeviceFromName(cbSource.SelectedItem.ToString()) == null) + return false; //This should never happen with a drop-down list, but just in case... + if (ntt == NetTestType.LockAll || ntt == NetTestType.LockDHCP || ntt == NetTestType.LockIP || + ntt == NetTestType.LockNic || ntt == NetTestType.LockRoute) + return true; + if(ntt == NetTestType.NeedsRouteToNet) + { + //We should have a network, not a host. + } + else if (ntt == NetTestType.HelpRequest) + { + //This uses a verbosity + } + else + { + if (ntt == NetTestType.SuccessfullyPings) return true; + if (theNet.GetDeviceFromName(cbDest.SelectedItem.ToString()) == null) + return false; //This should never happen with a drop-down list, but just in case... + } + return true; + } + + private void cbTest_SelectedValueChanged(object sender, EventArgs e) + { + + ToEdit.TheTest = NB.ParseEnum(cbTest.SelectedItem.ToString()); + if (!processing) + UpdateForm(); + + } + + private void cbSource_SelectedValueChanged(object sender, EventArgs e) + { + if (validate_choices()) + { + ToEdit.sHost = cbSource.SelectedItem.ToString(); + } + else + if (!processing) + UpdateForm(); + } + + private void cbDest_SelectedValueChanged(object sender, EventArgs e) + { + if (validate_choices()) + { + ToEdit.dHost = cbDest.SelectedItem.ToString(); + } + else + if (!processing) + UpdateForm(); + } + } +} diff --git a/EduNetworkBuilder/Network.cs b/EduNetworkBuilder/Network.cs new file mode 100644 index 0000000..22a4100 --- /dev/null +++ b/EduNetworkBuilder/Network.cs @@ -0,0 +1,1111 @@ +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.Xml; +using System.IO; + + + +namespace EduNetworkBuilder +{ + /// + /// This is a whole network. LAN, WAN, Internet; everything combined + /// + public class Network + { + public string PuzzleName=""; + public int myHeight = 1024; + public int myWidth = 1024; + public int Level = 0; + public double SortOrder = 0; + public bool ShowLabels = false; + public string NetMessage = ""; + public string NetTitle = ""; + List NetComponents = new List(); + //should have background image + Image TheNetImage = new Bitmap(1024, 1024); + public int itemsize = 100; //The size of network components + PictureBox myPBox=null; + private int UniqueIdentifier = 100; //This gets used for all sorts of things. is auto-incremented every time someone asks for one + private List myPackets = new List(); + private List myMessages = new List(); + private bool _isDirty = false; + private IPAddress lastAddress = new IPAddress("0.0.0.0/24"); + public string NetworkFilename = ""; + public List NetTests = new List(); + private bool AlreadyDisplayedMessage = false; + public NetTestVerbosity HintsToDisplay = NetTestVerbosity.none; + public NetTestVerbosity StartingHelpLevel = NetTestVerbosity.none; + public bool PuzzleIsSolved = true; //only set to false if we load a puzzle + public List Tags = new List(); + private DateTime NetworkStartTime = DateTime.Now; + private bool AlreadyChosenTimeout = false; + private int DefaultTimeout = 10; + private int NumberOfSecondsForTimeout = 10; + + public Network(string Name) + { + TheNetImage = new Bitmap(myWidth, myHeight); + PuzzleName = Name; + } + + private bool isDirty() + { + if (_isDirty) return true; + foreach (NetworkComponent nc in NetComponents) + { + if (nc.IsDirty) return true; + } + return false; + } + + + public void ClearComponents() + { + NetComponents.Clear(); + } + public void ClearPackets() + { + myPackets.Clear(); + } + public void ClearMessages() + { + myMessages.Clear(); + } + + /// + /// Load the file from a xml resource + /// + public void Load() + { + Load(@"C:\Users\tyoung\Desktop\Test.enbx"); + } + + public void Load(string filename) + { + NetworkFilename = filename; + XmlDocument xmlDoc = new XmlDocument(); + PuzzleName = Path.GetFileNameWithoutExtension(filename); + if (File.Exists(filename)) + { + xmlDoc.Load(filename); + Load(xmlDoc,PuzzleName); + } + } + + public void Load(XmlNode TheNode, string Name) + { + _isDirty = true; + NetworkDevice newND; + NetworkLink newNL; + int newUnique=-1; + PuzzleName = Name; + foreach (XmlNode Individual in TheNode.ChildNodes) + { + XmlNodeType myNodetype = Individual.NodeType; + if (myNodetype == XmlNodeType.Element) + { + switch (Individual.Name.ToLower()) + { + case "edunetworkbuilder": + case "network": + Load(Individual,PuzzleName); + break; + case "message": + NetMessage = Individual.InnerText; + break; + case "title": + NetTitle = Individual.InnerText; + break; + case "showlabels": + bool.TryParse(Individual.InnerText, out ShowLabels); + break; + case "itemsize": + int.TryParse(Individual.InnerText, out itemsize); + break; + case "height": + int.TryParse(Individual.InnerText, out myHeight); + break; + case "width": + int.TryParse(Individual.InnerText, out myWidth); + break; + case "uniqueidentifier": + int.TryParse(Individual.InnerText, out UniqueIdentifier); + newUnique = UniqueIdentifier; + break; + case "link": + newNL = new NetworkLink(Individual); + NetComponents.Add(newNL); + break; + case "device": + newND = new NetworkDevice(Individual); + NetComponents.Add(newND); + break; + case "nettest": + NetTest nt = new NetTest(Individual); + NetTests.Add(nt); + break; + case "tag": + Tags.Add(Individual.InnerText); + break; + case "level": + int.TryParse(Individual.InnerText, out Level); + //Tags.Add("Level_" + Individual.InnerText); + break; + case "sortorder": + double.TryParse(Individual.InnerText, out SortOrder); + break; + case "startinghelplevel": + StartingHelpLevel = NB.ParseEnum(Individual.InnerText); + HintsToDisplay = StartingHelpLevel; + break; + } + } + } + if (NetMessage != "" && !AlreadyDisplayedMessage) + { + //We have a message loaded on this network. Display it + BuilderWindow myWin = (BuilderWindow)Application.OpenForms["BuilderWindow"]; + if (myWin != null) + { + myWin.OpenNetHelpWindow(); + } + else + { + MessageBox.Show(NetMessage, NetTitle, MessageBoxButtons.OK); + } + AlreadyDisplayedMessage = true; + } + if(NetTests.Count > 0) + PuzzleIsSolved = false; //When we load the puzzle. + + if (newUnique != -1) + UniqueIdentifier = newUnique; + } + + + public void Save() + { + Save(@"C:\Users\tyoung\Desktop\Test.enbx"); + } + + public void Save(string filename) + { + NetworkFilename = filename; + XmlWriterSettings settings = new XmlWriterSettings(); + settings.Indent = true; + settings.NewLineOnAttributes = true; + XmlWriter writer = XmlWriter.Create(filename, settings); + + //Now we write the file: + writer.WriteStartDocument(); + writer.WriteStartElement("EduNetworkBuilder"); + writer.WriteComment("This is a network file for EduNetworkBuilder."); + Save(writer); + writer.WriteEndElement(); + writer.WriteEndDocument(); + writer.Flush(); + writer.Close(); + } + + + public void Save(XmlWriter writer) + { + //Save the language name + //save the number of items + //Save all the items + writer.WriteStartElement("Network"); + writer.WriteElementString("message", NetMessage); + writer.WriteElementString("title", NetTitle); + writer.WriteElementString("height", myHeight.ToString()); + writer.WriteElementString("width", myWidth.ToString()); + writer.WriteElementString("itemsize", itemsize.ToString()); + writer.WriteElementString("showlabels", ShowLabels.ToString()); + writer.WriteElementString("level", Level.ToString()); + writer.WriteElementString("sortorder", SortOrder.ToString()); + writer.WriteElementString("uniqueidentifier", UniqueIdentifier.ToString()); + writer.WriteElementString("startinghelplevel", StartingHelpLevel.ToString()); + //Save all the devices + for (int loop = 0; loop < NetComponents.Count; loop++) + { + if (NB.GetComponentType(NetComponents[loop]) == GeneralComponentType.device) + NetComponents[loop].Save(writer); + } + //Then save the links + for (int loop = 0; loop < NetComponents.Count; loop++) + { + if (NB.GetComponentType(NetComponents[loop]) == GeneralComponentType.link) + NetComponents[loop].Save(writer); + } + foreach(NetTest nt in NetTests) + { + nt.Save(writer); + } + foreach(string Tag in Tags) + { + if(!Tag.Contains("Level")) + writer.WriteElementString("tag",Tag); + } + writer.WriteEndElement(); + } + + public void UpdateDeviceSizes() + { + NetworkDevice nd; + foreach (NetworkComponent NC in NetComponents) + { + if (NB.GetComponentType(NC) == GeneralComponentType.device) + { + nd = (NetworkDevice)NC; + nd.SetSize(itemsize); + } + } + } + + public bool MAC_Exists(string MAC) + { + foreach (NetworkComponent nc in NetComponents) + { + if (nc.HasMac(MAC)) return true; + } + return false; + } + + public void RegisterDisplayArea(PictureBox What) + { + myPBox = What; + } + + public Point clickedPos(Point pixelClickedOn) + { + if (myPBox == null) return new Point(-1, -1); + double deltaX = (double)TheNetImage.Width / myPBox.Width; + double deltaY = (double)TheNetImage.Height / myPBox.Height; + Point Dest = new Point((int)(pixelClickedOn.X * deltaX), (int)(pixelClickedOn.Y * deltaY)); + if (Dest.X > TheNetImage.Width) Dest = new Point(TheNetImage.Width, Dest.Y); + if (Dest.Y > TheNetImage.Height) Dest = new Point(Dest.X, TheNetImage.Height); + if (Dest.X <0) Dest = new Point(0, Dest.Y); + if (Dest.Y <0) Dest = new Point(Dest.X, 0); + + return Dest; + } + + public Point clickedPosCentered(Point pixelClickedOn) + { + Point NetPoint = clickedPos(pixelClickedOn); + int shift = (itemsize / 2); + Point Dest = new Point((int)(NetPoint.X - shift), (int)(NetPoint.Y - shift)); + if (Dest.X + itemsize > TheNetImage.Width) Dest = new Point(TheNetImage.Width - itemsize, Dest.Y); + if (Dest.Y + itemsize > TheNetImage.Height) Dest = new Point(Dest.X, TheNetImage.Height - itemsize); + if (Dest.X < 0) Dest = new Point(0, Dest.Y); + if (Dest.Y < 0) Dest = new Point(Dest.X, 0); + return Dest; + } + + public NetworkDevice ItemAtPosition(Point NetworkLocation) + { + NetworkDevice tDevice; + foreach (NetworkComponent tItem in NetComponents) + { + if (tItem.GetType().ToString() == "EduNetworkBuilder.NetworkDevice") + { + tDevice = (NetworkDevice)tItem; + if (tDevice.AtLocation(NetworkLocation)) + return tDevice; + } + } + return null; + } + + public NetworkDevice ItemFromName(string hostname) + { + NetworkDevice tDevice; + foreach (NetworkComponent tItem in NetComponents) + { + if (tItem.GetType().ToString() == "EduNetworkBuilder.NetworkDevice") + { + tDevice = (NetworkDevice)tItem; + if (tDevice.hostname == hostname) + return tDevice; + } + } + return null; + } + + public bool HasItemCalled(string itemname) + { + NetworkDevice tDevice; + foreach(NetworkComponent tItem in NetComponents) + { + if(tItem.GetType().ToString() == "EduNetworkBuilder.NetworkDevice") + { + tDevice = (NetworkDevice)tItem; + if (tDevice.hostname == itemname) return true; + } + } + return false; + } + + + + public NetworkComponent AddItem(NetworkComponentType WhatType, Point location) + { + if (WhatType == NetworkComponentType.none) return null; //Do not put none in + if (WhatType == NetworkComponentType.link) return null; //We need to add links another way + string basename = WhatType.ToString(); + int count=0; + while (HasItemCalled(basename + count)) + count++; + + Point newlocation = NB.GetSnapped(location); + + NetworkComponent NewItem = new NetworkDevice(WhatType, basename + count, newlocation); + ((NetworkDevice)NewItem).SetSize(itemsize); + + NetComponents.Add(NewItem); + TestForCompletion(true); + myPBox.Invalidate(); //redraw the screen + return NewItem; + } + + /// + /// Search throuh all the network components and delete any links that are attacked to the specified nic. + /// + /// + public void RemoveLinksToNic(HostNicID NicID) + { + for(int looper=NetComponents.Count()-1; looper >=0; looper--) + { + if(NetComponents[looper].GetType().ToString() == "EduNetworkBuilder.NetworkLink") + { + NetworkLink nLink = (NetworkLink)NetComponents[looper]; + if (nLink.HasLink(NicID)) + { + nLink.Destroy(); + NetComponents.RemoveAt(looper); + _isDirty = true; + } + } + } + } + + public NetworkComponent AddItem(NetworkComponent ToAdd) + { + NetComponents.Add(ToAdd); + TestForCompletion(true); + return ToAdd; + } + public List UnavailableNics() + { + NetworkLink myLink; + List usedList = new List(); + foreach (NetworkComponent NC in NetComponents) + { + if (NC.GetType().ToString() == "EduNetworkBuilder.NetworkLink") + { + myLink = (NetworkLink)NC; + usedList.AddRange(myLink.UsedNicIDStrings()); + } + } + return usedList; + } + + public void RemoveComponent(NetworkComponent tItem) + { + NetComponents.Remove(tItem); + tItem.Destroy(); + _isDirty = true; + } + + public void StoreLastIP(IPAddress ip) + { + lastAddress = ip; + } + + public IPAddress RetrieveLastIP() + { + return lastAddress; + } + + public List GetTestMessages(string host) + { + string tString; + List tMessages = new List(); + foreach(NetTest nt in NetTests) + { + if(nt.sHost == host && !nt.TestComplete()) + { + tString = nt.GetDescription(HintsToDisplay); + if(tString != "") + tMessages.Add(tString); + } + } + return tMessages; + } + public List GetIncompleteTestDestinations(string Source, bool forPing=true) + { + List tDests = new List(); + foreach (NetTest nt in NetTests) + { + if (nt.sHost == Source && !nt.TestComplete()) + { + if (forPing && (nt.TheTest == NetTestType.FailedPing || nt.TheTest == NetTestType.SuccessfullyPings)) + tDests.Add(nt.dHost); + if (!forPing && nt.TheTest == NetTestType.SuccessfullyArps) + tDests.Add(nt.dHost); + } + } + return tDests; + } + + public void TestForCompletion(bool report_as_done) + { + NetworkDevice TmpDevice; + bool PreviouslyUnsolved = !PuzzleIsSolved; //Only if we have an unsolved puzzle + int PuzzleCount = 0; + + foreach (NetworkComponent nc in NetComponents) + { + if (NB.GetComponentType(nc) == GeneralComponentType.device) + { + TmpDevice = (NetworkDevice)nc; + if (TmpDevice.BackgroundColor != Color.Empty) + { + TmpDevice.BackgroundColor = Color.Empty; + TmpDevice.IsDirty = true; + } + } + } + foreach (NetTest nt in NetTests) + { + if (nt.ColorItemsIfNeeded(HintsToDisplay != NetTestVerbosity.none)) //only change the color if we are not "none" + PuzzleCount++; + } + if (report_as_done && PuzzleCount == 0 && PreviouslyUnsolved) + { + //The puzzle was just solved + MarkAsSolved(); + } + } + + public void Print(PaintEventArgs e) + { + //we have the whole thing to print, and the display image already done + TestForCompletion(false); + if(isDirty() || _isDirty) + { + TheNetImage= new Bitmap(TheNetImage.Width, TheNetImage.Height); + //re-generate the image + //Do all the links first + foreach(NetworkComponent NC in NetComponents) + { + if (NC.GetType().ToString() == "EduNetworkBuilder.NetworkLink") + NC.Print(TheNetImage, false); + } + //Now, do all the devices + foreach (NetworkComponent NC in NetComponents) + { + if (NC.GetType().ToString() == "EduNetworkBuilder.NetworkDevice") + NC.Print(TheNetImage, ShowLabels); + } + } + if (myPackets.Count > 0) + { + Image tempNetImage = new Bitmap(TheNetImage); + foreach(Packet pkt in myPackets) + { + pkt.Print(tempNetImage); //Print all the packets over the network image + } + e.Graphics.DrawImage(tempNetImage, 0, 0, myPBox.Width, myPBox.Height); + tempNetImage.Dispose(); + } + else + { + e.Graphics.DrawImage(TheNetImage, 0, 0, myPBox.Width, myPBox.Height); + } + _isDirty = false; + } + + public void InvalidateEverything() + { + foreach(NetworkComponent nc in NetComponents) + { + nc.IsDirty = true; + } + } + + public List arp(UInt32 IP) + { + List arps = new List(); + List tlist; + foreach (NetworkComponent nc in NB.Randomize(NetComponents)) + { + tlist = nc.arp(IP); + if (tlist.Count() > 0) + { + foreach (string mac in tlist) + { + arps.Add(mac); + } + } + } + return arps; + } + public int GetUniqueIdentifier() + { + return UniqueIdentifier++; + } + + public void SortNetComponents() + { + NetComponents.Sort((x, y) => x.hostname.CompareTo(y.hostname)); + } + + public NetworkDevice HostMatchingHostNicID(HostNicID ToFind) + { + NetworkDevice tDevice; + //We cheat. the first portion of the host/nic ID is the host_id so we just find that + foreach (NetworkComponent nc in NetComponents) + { + if (NB.GetComponentType(nc) == GeneralComponentType.device) + { + if (nc.GetUniqueIdentifier == ToFind.HostID) + { + tDevice = (NetworkDevice)nc; + return tDevice; + } + } + } + return null; + } + /// + /// Search all the devices and make sure the one device is the only one that has the specified IP + /// + /// The IP address to find + /// The device that has it + /// + public bool HasUniqueIP(IPAddress ToFind, NetworkDevice Source) + { + NetworkDevice ND; + foreach (NetworkComponent nc in NetComponents) + { + if (NB.GetComponentType(nc) == GeneralComponentType.device) + { + ND = (NetworkDevice)nc; + if(ND != Source) //Skip the source + { + if (ND.HasIPAddress(ToFind)) + return false; //Something has that IP + } + } + } + return true; //We did not find any device with that IP + } + + public bool ItemIsCritical(string host) + { + foreach(NetTest nt in NetTests) + { + if (nt.dHost == host) return true; + if (nt.sHost == host) return true; + } + return false; + } + + public bool ItemIsCritical(HostNicID host) + { + NetworkDevice ND = GetDeviceFromID(host); + if (ND == null) return false; //cannot find it + foreach (NetTest nt in NetTests) + { + if (nt.dHost == ND.hostname) return true; + if (nt.sHost == ND.hostname) return true; + } + return false; + } + + public bool ItemIsLocked(string host, string dest, NetTestType WhatToCheck) + { + foreach (NetTest nt in NetTests) + { + if(nt.sHost == host) + { + if (nt.TheTest == NetTestType.LockAll) + return true; + if (WhatToCheck == nt.TheTest && dest == nt.dHost) + return true; + } + } + return false; + } + + private void MarkAsSolved() + { + PuzzleIsSolved = true; + if (PuzzleName != "" && PuzzleName != null) + { + if (Properties.Settings.Default.ScoreList == null) + Properties.Settings.Default.ScoreList = new System.Collections.Specialized.StringCollection(); + if (!Properties.Settings.Default.ScoreList.Contains(PuzzleName)) + { + Properties.Settings.Default.ScoreList.Add(PuzzleName); + Properties.Settings.Default.Save(); + } + } + DialogResult answer = MessageBox.Show("Solved! Would you like to open the puzzle box to go to the next puzzle? 'No' will let you continue to play with this one.","Solved",MessageBoxButtons.YesNo); + if(answer == DialogResult.Yes) + { + ListBoxWindow LBW = new ListBoxWindow(); + LBW.ShowDialog(); + } + } + + /// + /// See if we have any tests that are supposed to check for packet arrival. + /// + /// The type of packet that arrived + /// The host it originated from + /// The machine it went to + public void NotePacketArrived(PacketType packet_type, NetworkDevice source, IPAddress sIP, IPAddress dIP) + { + string sHost = ReverseDNSLookup(source, sIP); + string dHost = ReverseDNSLookup(source, dIP); + foreach (NetTest nt in NetTests) + { + if (nt.TheTest == NetTestType.SuccessfullyArps && packet_type == PacketType.arp_answer && sHost == nt.sHost && dHost == nt.dHost) + nt.SetDone(); + if (nt.TheTest == NetTestType.SuccessfullyDHCPs && packet_type == PacketType.dhcp_answer && sHost == nt.sHost && dHost == nt.dHost) + nt.SetDone(); + if (nt.TheTest == NetTestType.SuccessfullyPings && packet_type == PacketType.ping_answer && sHost == nt.sHost && dHost == nt.dHost) + nt.SetDone(); + if (nt.TheTest == NetTestType.SuccessfullyPings && packet_type == PacketType.ping_answer && sHost == nt.sHost && dHost == null && dIP != null && dIP.BroadcastAddress == dIP.GetIP && dIP.GetIPString == nt.dHost) + nt.SetDone(); + } + } + + public bool NoteActionDone(NetTestType theTest, string sHost, string dHost) + { + bool OldVal = false; + IPAddress sourceIP; + string sourceIPstring; + IPAddress destIP; + string destIPstring; + foreach (NetTest nt in NetTests) + { + sourceIP = new IPAddress(sHost); + sourceIPstring = ReverseDNSLookup(null, sourceIP); //this will either be an ip address or the host name + destIP = new IPAddress(dHost); + destIPstring = ReverseDNSLookup(null, destIP); //this will either be an ip address or the host name + if ((nt.TheTest == NetTestType.HelpRequest || nt.TheTest == NetTestType.FailedPing) && + (sHost == nt.sHost || sourceIPstring == nt.sHost) && + (dHost == nt.dHost || destIPstring == nt.dHost)) + { + OldVal = nt.TaskWasDone; + nt.SetDone(); + if (nt.TaskWasDone != OldVal) + return true; + } + if (nt.TheTest == NetTestType.HelpRequest && sHost == "" && dHost == nt.dHost && dHost == "?Button") + { + OldVal = nt.TaskWasDone; + nt.SetDone(); + if (nt.TaskWasDone != OldVal) + return true; + } + + } + return false; + } + + public List NetworkCardForHostList(string hostname, bool OnlyUnused = true, bool OnlyLinkable = false) + { + List theList = new List(); + NetworkDevice tDevice; + foreach (NetworkComponent nc in NetComponents) + { + if (nc.GetType().ToString() == "EduNetworkBuilder.NetworkDevice") + { + if(nc.hostname == hostname) + { + tDevice = (NetworkDevice)nc; + theList.AddRange(tDevice.NetworkCardStrings(OnlyUnused,OnlyLinkable)); + } + } + } + return theList; + } + + public List GetMessageStrings() + { + List themessages = new List(); + foreach (PacketMessage msg in myMessages) + { + themessages.AddRange(msg.GetMessagesSummary()); + } + return themessages; + } + public int CountMessages() + { + return myMessages.Count(); + } + public PacketMessage GetMessageAtIndex(int index) + { + if (index < 0 || index > myMessages.Count()) return null; + return myMessages[index]; + } + + public void addPacket(Packet toadd) + { + if(toadd != null && !myPackets.Contains(toadd)) + myPackets.Add(toadd); + } + + public int CountPackets(PacketType WhatType) + { + int count = 0; + foreach (Packet pkt in myPackets) + { + if (pkt.MyType == WhatType) + count++; + } + return count; + } + + public void ProcessPacketsOnce() + { + foreach(Packet tpackets in myPackets.ToList()) + { + if(tpackets != null) + tpackets.ProcessTick(); + if (tpackets.DebugOn) + Console.WriteLine("Debugging"); + } + for(int loop=myPackets.Count -1; loop >=0; loop--) + { + //we delete if it has finished. + if (myPackets[loop].DebugOn) + Console.WriteLine("Debugging"); + if (myPackets[loop].TickTTL < 1) //If the packet has been around too long, get rid of it + { + myPackets[loop].AddMessage(DebugLevel.info, "Packet Tick Counter reached. Did the packet go into an infinite loop?"); + myPackets[loop].PrepareToDelete(); + myPackets.RemoveAt(loop); + } + else if (myPackets[loop].ready_to_delete) + { + myPackets[loop].PrepareToDelete(); + myPackets.RemoveAt(loop); + } + } + GC.Collect();//Try to clean up memory. + myPackets = NB.Randomize(myPackets); + } + + /// + /// This checks to see if there is any reason we should stop processing the packets + /// + /// true if we should continue, false if we should pause + public bool ProcessingShouldContinue() + { + TimeSpan Duration = DateTime.Now - NetworkStartTime; + NB.SetProgress(Duration.TotalSeconds, NumberOfSecondsForTimeout); + if (Duration.TotalSeconds > NumberOfSecondsForTimeout) + { + Console.WriteLine("Total seconds = " + Duration.TotalSeconds.ToString() + " Stopping."); + foreach (Packet pkt in myPackets) + { + pkt.Tracking.AddMessage(DebugLevel.packet, "Network", "The packet timed out."); + pkt.Tracking.Status = "The packet timed out and was dropped."; + pkt.MyStatus = PacketStatus.finished_failed; + pkt.PrepareToDelete(); + } + ClearPackets(); + return false; + } + return true; + } + + public void RegisterTimeOfArrival() + { + TimeSpan Duration = DateTime.Now - NetworkStartTime; + int MaxTime = (int)Duration.TotalSeconds + 2; + if(!AlreadyChosenTimeout) + { + NumberOfSecondsForTimeout = MaxTime * 2; + AlreadyChosenTimeout = true; + } + } + + public void ProcessPackets() + { + AlreadyChosenTimeout = false; //we do this at the beginning of processing + NumberOfSecondsForTimeout = DefaultTimeout; + NetworkStartTime = DateTime.Now; + while(myPackets.Count > 0) + { + ProcessPacketsOnce(); + if (!ProcessingShouldContinue()) + { + + //we need to break out for some reason + myPBox.Refresh(); + break; + } + else + { + myPBox.Refresh(); + NB.Delay(5); + } + } + //remove any IP connection tracking info + NetworkDevice ND; + foreach(NetworkComponent nc in NetComponents) + { + if(NB.GetComponentType(nc) == GeneralComponentType.device) + { + ND = (NetworkDevice)nc; + ND.ClearIPConnectionInfo(); + } + } + DebugPausePoint WhatIsSet = NB.GetDebugPauseSetting(); + if(WhatIsSet != 0) + { + Console.WriteLine("----All Done----"); + } + TestForCompletion(true); //Now, report on the progress if we solved something in the middle of the packets going out + AlreadyChosenTimeout = false; + NB.SetProgress(0, NumberOfSecondsForTimeout); + } + + public void AddMessage(PacketMessage toAdd) + { + //Only add this if it has not already been added + if(myMessages.IndexOf(toAdd) <0 ) + { + myMessages.Add(toAdd); + } + } + + public NetworkComponent GetComponentFromID(int TheID) + { + foreach(NetworkComponent nc in NetComponents) + { + if(nc.GetUniqueIdentifier == TheID) + { + return nc; + } + } + return null; + } + + public NetworkLink GetLinkFromID(int TheID) + { + NetworkComponent nc = GetComponentFromID(TheID); + if (nc == null) return null; + if (nc.GetType().ToString() == "EduNetworkBuilder.NetworkLink") + return (NetworkLink)nc; + return null; + } + public NetworkDevice GetDeviceFromID(int ID) + { + NetworkComponent nc = GetComponentFromID(ID); + if (nc == null) return null; + if (nc.GetType().ToString() == "EduNetworkBuilder.NetworkDevice") + return (NetworkDevice)nc; + return null; + } + + public NetworkDevice GetDeviceFromID(HostNicID LinkedNic) + { + return GetDeviceFromID(LinkedNic.HostID); + } + + public NetworkDevice GetDeviceFromName(string DeviceName) + { + NetworkComponent nc = ItemFromName(DeviceName); + if (nc == null) return null; + if (NB.GetComponentType(nc) == GeneralComponentType.device) + return (NetworkDevice)nc; + return null; + } + + public List GetHostnames() + { + List tList = new List(); + NetworkDevice ND; + foreach(NetworkComponent NC in NetComponents) + { + if(NB.GetComponentType(NC) == GeneralComponentType.device) + { + ND = (NetworkDevice)NC; + tList.Add(ND.hostname); + } + } + tList.Sort(); + return tList; + } + + public List GetSubnets() + { + List tList = new List(); + NetworkDevice ND; + List subnets; + foreach (NetworkComponent NC in NetComponents) + { + if (NB.GetComponentType(NC) == GeneralComponentType.device) + { + ND = (NetworkDevice)NC; + subnets = ND.SubnetList(); + foreach(string subnet in subnets) + { + if (!tList.Contains(subnet)) + tList.Add(subnet); + } + } + } + tList.Sort(); + return tList; + } + public List GetBroadcasts() + { + List tList = new List(); + NetworkDevice ND; + List subnets; + foreach (NetworkComponent NC in NetComponents) + { + if (NB.GetComponentType(NC) == GeneralComponentType.device) + { + ND = (NetworkDevice)NC; + subnets = ND.BroadcastList(); + foreach (string subnet in subnets) + { + if (!tList.Contains(subnet)) + tList.Add(subnet); + } + } + } + tList.Sort(); + return tList; + } + public void MarkAsLinked(HostNicID LinkedNic, int LinkID) + { + NetworkDevice nd = GetDeviceFromID(LinkedNic); + //If the host exists, now mark the nic + if(nd != null) + { + NetworkCard nic = nd.NicFromID(LinkedNic); + if(nic != null) + nic.ConnectedLink = LinkID; + } + } + public void MarkAsUnlinked(HostNicID LinkedNic, int LinkID) + { + NetworkDevice nd = GetDeviceFromID(LinkedNic); + //If the host exists, now mark the nic + if (nd != null) + { + NetworkCard nic = nd.NicFromID(LinkedNic); + if ((nic != null && nic.ConnectedLink == LinkID) || LinkID == -1) + { + nic.ConnectedLink = -1; + } + } + } + + public IPAddress DNSLookup(NetworkDevice source, string toFind) + { + + foreach(NetworkComponent nc in NB.Randomize(NetComponents)) + { + NetworkDevice nd; + if(NB.GetComponentType(nc) == GeneralComponentType.device) + { + nd = (NetworkDevice)nc; + if(nd.hostname == toFind) + { + IPAddress found = nd.BestIPForThis(source); + return found; + } + } + } + return null; + } + + public string ReverseDNSLookup(NetworkDevice source, IPAddress toFind) + { + if (source != null && source.HasIPAddress(toFind)) + return source.hostname; //if the host is 127.0.0.1 or something. + foreach (NetworkComponent nc in NB.Randomize(NetComponents)) + { + NetworkDevice nd; + if (NB.GetComponentType(nc) == GeneralComponentType.device) + { + nd = (NetworkDevice)nc; + if (nd.HasIPAddress(toFind)) + return nd.hostname; + } + } + return null; + } + + + + /**************************************** + * Do On All Devices + * **************************************/ + public void DoAllDHCP() + { + NetworkDevice nd; + foreach (NetworkComponent nc in NetComponents) + { + if(NB.GetComponentType(nc) == GeneralComponentType.device) + { + nd = (NetworkDevice)nc; + nd.DHCPRequestFromHere(); + } + } + } + + public void DoAllClearArp() + { + NetworkDevice nd; + foreach (NetworkComponent nc in NetComponents) + { + if (NB.GetComponentType(nc) == GeneralComponentType.device) + { + nd = (NetworkDevice)nc; + nd.ClearArps(); + } + } + } + public void DoAllPing(IPAddress destination) + { + NetworkDevice nd; + foreach (NetworkComponent nc in NetComponents) + { + if (NB.GetComponentType(nc) == GeneralComponentType.device) + { + nd = (NetworkDevice)nc; + nd.PingFromHere(destination); + } + } + } + public void DoAllClearIPs() + { + NetworkDevice nd; + foreach (NetworkComponent nc in NetComponents) + { + if (NB.GetComponentType(nc) == GeneralComponentType.device) + { + nd = (NetworkDevice)nc; + nd.ClearIPs(); + } + } + } + } + +} diff --git a/EduNetworkBuilder/NetworkBuilder.cs b/EduNetworkBuilder/NetworkBuilder.cs new file mode 100644 index 0000000..dbdc46d --- /dev/null +++ b/EduNetworkBuilder/NetworkBuilder.cs @@ -0,0 +1,1126 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.IO; +using System.Xml; +using System.Text.RegularExpressions; +using System.Globalization; +using System.Resources; +using System.Threading; + +namespace EduNetworkBuilder +{ + public partial class BuilderWindow : Form + { + public Random GameRandomGen = new Random(); + public DebugPausePoint DebugSetting = DebugPausePoint.none; +// public DebugPausePoint DebugSetting = DebugPausePoint.all | DebugPausePoint.dump; + public Network myNetwork = new Network(""); + private List Buttons = new List(); + private string selectedButton = ""; + ToolTip myTooltip = new ToolTip(); + private NetworkDevice ItemClickedOn = null; + private NetworkDevice MouseHoverOver = null; + private Point ClickedLocation; + DateTime LastClick = DateTime.Now; + private string LastPath = Properties.Settings.Default.LastPath; + private bool processing = false; + private List PuzzleList = new List(); + private ResourceManager LanguageResources = null; + private CultureInfo LanguageCulture = null; + public string ChosenLanguage = "en"; //The language to try to load + + public BuilderWindow() + { + InitializeComponent(); + if(!Properties.Settings.Default.LanguageHasBeenChosen) + NB.ChangeLanguage(); + LanguagifyComponents(); + //I never implimented cut/copy/paste/undo. So we will remove them since they do nothing anyway + cutToolStripMenuItem.Visible = false; + copyToolStripMenuItem.Visible = false; + pasteToolStripMenuItem.Visible = false; + undoToolStripMenuItem.Visible = false; + + myTooltip.AutoPopDelay = 5000; + myTooltip.InitialDelay = 1000; + myTooltip.ReshowDelay = 500; + // Force the ToolTip text to be displayed whether or not the form is active. + myTooltip.ShowAlways = true; + + myTooltip.SetToolTip(rbHelp1, "Show no help for the puzzle"); + myTooltip.SetToolTip(rbHelp2, "Show the color of the items making the puzzle."); + myTooltip.SetToolTip(rbHelp3, "Color-code & give minor mouse-over help for the puzzle."); + myTooltip.SetToolTip(rbHelp4, "Color-code & give decent mouse-over help for the puzzle."); + myTooltip.SetToolTip(btnHelp, "Show the message describing the puzzle."); + myTooltip.Popup += myTooltip_Popup; + lblStatus.Text = ""; + + myNetwork.RegisterDisplayArea(pbNetworkView); + + BuildButtons(); + LayoutButtons(); + UpdateForm(); + this.KeyPreview = true; + this.KeyUp += GenericKeyDown; + + LoadPuzzleInfo(); + } + + private void LanguagifyComponents() + { + ResourceManager RM = GetResource(); + CultureInfo CI = GetCulture(); + msMainMenuStrip.Text = NB.Translate("NB_msMainMenuStrip"); + fileToolStripMenuItem.Text = NB.Translate("NB_fileToolStripMenuItem"); + newToolStripMenuItem.Text = NB.Translate("NB_newToolStripMenuItem"); + loadToolStripMenuItem.Text = NB.Translate("NB_loadToolStripMenuItem"); + reloadToolStripMenuItem.Text = NB.Translate("NB_reloadToolStripMenuItem"); + saveToolStripMenuItem.Text = NB.Translate("NB_saveToolStripMenuItem"); + exitToolStripMenuItem.Text = NB.Translate("NB_exitToolStripMenuItem"); + editToolStripMenuItem.Text = NB.Translate("NB_editToolStripMenuItem"); + cutToolStripMenuItem.Text = NB.Translate("NB_cutToolStripMenuItem"); + copyToolStripMenuItem.Text = NB.Translate("NB_copyToolStripMenuItem"); + pasteToolStripMenuItem.Text = NB.Translate("NB_pasteToolStripMenuItem"); + undoToolStripMenuItem.Text = NB.Translate("NB_undoToolStripMenuItem"); + optionsToolStripMenuItem.Text = NB.Translate("NB_optionsToolStripMenuItem"); + allToolStripMenuItem.Text = NB.Translate("NB_allToolStripMenuItem"); + dHCPRequestToolStripMenuItem.Text = NB.Translate("NB_dHCPRequestToolStripMenuItem"); + clearArpTableToolStripMenuItem.Text = NB.Translate("NB_clearArpTableToolStripMenuItem"); + clearIPsToolStripMenuItem.Text = NB.Translate("NB_clearIPsToolStripMenuItem"); + pingToolStripMenuItem.Text = NB.Translate("NB_pingToolStripMenuItem"); + helpToolStripMenuItem.Text = NB.Translate("NB_helpToolStripMenuItem"); + helpToolStripMenuItem1.Text = NB.Translate("NB_helpToolStripMenuItem1"); + aboutToolStripMenuItem.Text = NB.Translate("NB_aboutToolStripMenuItem"); + releaseNotesToolStripMenuItem.Text = NB.Translate("NB_releaseNotesToolStripMenuItem"); + checkForUpdatesToolStripMenuItem.Text = NB.Translate("NB_checkForUpdatesToolStripMenuItem"); + samplesToolStripMenuItem.Text = NB.Translate("NB_samplesToolStripMenuItem"); + puzzlesToolStripMenuItem.Text = NB.Translate("NB_puzzlesToolStripMenuItem"); + solvedToolStripMenuItem.Text = NB.Translate("NB_solvedToolStripMenuItem"); + dHCPToolStripMenuItem.Text = NB.Translate("NB_dHCPToolStripMenuItem"); + oneNetworkToolStripMenuItem.Text = NB.Translate("NB_oneNetworkToolStripMenuItem"); + twoNetworksToolStripMenuItem.Text = NB.Translate("NB_twoNetworksToolStripMenuItem"); + threeNetworksToolStripMenuItem.Text = NB.Translate("NB_threeNetworksToolStripMenuItem"); + firewallsToolStripMenuItem.Text = NB.Translate("NB_firewallsToolStripMenuItem"); + toSolveToolStripMenuItem.Text = NB.Translate("NB_toSolveToolStripMenuItem"); + solvedDHCPToolStripMenuItem.Text = NB.Translate("NB_solvedDHCPToolStripMenuItem"); + solvedOneNetworkToolStripMenuItem.Text = NB.Translate("NB_solvedOneNetworkToolStripMenuItem"); + solvedTwoNetworksToolStripMenuItem.Text = NB.Translate("NB_solvedTwoNetworksToolStripMenuItem"); + SolvedThreeNetworksToolStripMenuItem.Text = NB.Translate("NB_SolvedThreeNetworksToolStripMenuItem"); + firewallsToolStripMenuItem1.Text = NB.Translate("NB_firewallsToolStripMenuItem1"); + lblStatus.Text = NB.Translate("NB_lblStatus"); + btnHelp.Text = NB.Translate("NB_btnHelp"); + changeLanguageToolStripMenuItem.Text = NB.Translate("NB_changeLanguageToolStripMenuItem"); + Text = NB.Translate("NB_Form"); + } + + public ResourceManager GetResource() + { + if(LanguageResources == null) + { + System.Reflection.Assembly MyAssembly; + MyAssembly = this.GetType().Assembly; + LanguageResources = new ResourceManager("EduNetworkBuilder.Resources.languages.edustrings", MyAssembly); + } + return LanguageResources; + } + + public CultureInfo GetCulture() + { + if(LanguageCulture == null) + { + string CL = Properties.Settings.Default.ChosenLanguage; + if (CL != ChosenLanguage) ChosenLanguage = CL; + LanguageCulture = CultureInfo.CreateSpecificCulture(ChosenLanguage); + } + return LanguageCulture; + } + + /// + /// Look up a translate key from the resx file. + /// + /// The string to look up + /// The translated string + public string Translate(string Key) + { + ResourceManager RM = GetResource(); + CultureInfo CI = GetCulture(); + string answer; + answer = RM.GetString(Key, CI); + return answer; + } + + private void GenericKeyDown(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Delete) + { + pbNetworkView_Delete_Click(sender, e); + ItemClickedOn = null; + } + //MessageBox.Show(e.KeyCode.ToString()); + } + + private void myTooltip_Popup(Object sender, PopupEventArgs e) + { + //In case we have a puzzle we are trying to solve + if (MouseHoverOver == null) return; + bool didsomething = myNetwork.NoteActionDone(NetTestType.HelpRequest, MouseHoverOver.hostname, myNetwork.HintsToDisplay.ToString()); + if (didsomething) + { + pbNetworkView.Invalidate(); + myNetwork.TestForCompletion(true); + } + } + private void BuildButton(string btnName, Image btnImage, string tooltipString) + { + int size = panelChoices.Width / 2; + + Button tButton; + tButton = new Button(); + tButton.Name = btnName; + tButton.BackgroundImage = new Bitmap(btnImage); + tButton.BackgroundImageLayout = ImageLayout.Zoom; + tButton.Click += btnClick; + tButton.Height = size; + tButton.Width = size; + tButton.Location = new Point(0, 0); + Buttons.Add(tButton); + panelChoices.Controls.Add(tButton); + myTooltip.SetToolTip(tButton, tooltipString); + } + + private void BuildButtons() + { + BuildButton("btnSwitch", Properties.Resources.Switch, "Add a switch to the network."); + BuildButton("btnHub", Properties.Resources.Hub, "Add a hub to the network."); + BuildButton("btnServer", Properties.Resources.Server, "Add a server to the network."); + BuildButton("btnLaptop", Properties.Resources.Laptop, "Add a laptop to the network."); + BuildButton("btnPC", Properties.Resources.PC, "Add a PC to the network."); + BuildButton("btnRouter", Properties.Resources.Router, "Add a Router to the network."); + BuildButton("btnIPPhone", Properties.Resources.ip_phone, "Add an IP-Phone to the network."); + BuildButton("btnFirewall", Properties.Resources.firewall, "Add a firewall to the network."); + BuildButton("btnPrinter", Properties.Resources.Printer, "Add a printer to the network."); + BuildButton("btnCopier", Properties.Resources.Copier, "Add a copier to the network."); + BuildButton("btnWAP", Properties.Resources.wap, "Add a Wireless Access Point to the network."); + BuildButton("btnWRouter", Properties.Resources.WRouter, "Add a Wireless Router to the network."); + BuildButton("btnWBridge", Properties.Resources.WBridge, "Add a Wireless Bridge to the network."); + BuildButton("btnWRepeater", Properties.Resources.WRepeater, "Add a Wireless Repeater to the network."); + BuildButton("btnLink", Properties.Resources.link, "Use a network cable to connect network components."); + BuildButton("btnSelect", Properties.Resources.select, "Select items from the network."); + } + + private void LayoutButtons(List what) + { + foreach (Button btn in Buttons) + { + btn.Visible = false; //Hide them all + } + //now we place them. + int count = 0; + int size = panelChoices.Width / 2; + int x, y; + foreach (Button btn in Buttons) + { + if(what.Contains(btn.Name)) + { + x = (count % 2) * size; + y = (count / 2) * size; + btn.Location = new Point(x, y); + btn.Visible = true; + count++; + } + + } + } + + private void UpdateMessages() + { + //redo this later + lbMessages.Items.Clear(); + List messages = myNetwork.GetMessageStrings(); + foreach (string msg in messages) + { + lbMessages.Items.Add(msg); + } + + if(lbMessages.Items.Count > 0) + lbMessages.SelectedIndex = lbMessages.Items.Count-1; + + } + + public void UpdateMenu() + { + if (myNetwork.NetworkFilename != "") + { + reloadToolStripMenuItem.Enabled = true; + } + else + { + reloadToolStripMenuItem.Enabled = false; + } + } + + public void UpdateForm() + { + UpdateMenu(); + UpdateMessages(); + processing = true; + Text = "EduNetworkBuilder"; + if (myNetwork.NetTitle != "") + Text += ": " + myNetwork.NetTitle; + if (myNetwork.NetMessage != "") + { + btnHelp.Visible = true; + } + else + { + btnHelp.Visible = false; + } + if (myNetwork.NetTests.Count > 0) + { + rbHelp1.Visible = true; + rbHelp2.Visible = true; + rbHelp3.Visible = true; + rbHelp4.Visible = true; + } + else + { + rbHelp1.Visible = false; + rbHelp2.Visible = false; + rbHelp3.Visible = false; + rbHelp4.Visible = false; + } + switch(myNetwork.HintsToDisplay) + { + case NetTestVerbosity.full: + rbHelp4.Checked = true; + break; + case NetTestVerbosity.basic: + rbHelp3.Checked = true; + break; + case NetTestVerbosity.hints: + rbHelp2.Checked = true; + break; + case NetTestVerbosity.none: + rbHelp1.Checked = true; + break; + } + processing = false; + } + + private void LayoutButtons() + { + List what = new List(); + foreach(Button btn in Buttons) + { + what.Add(btn.Name); + } + LayoutButtons(what); + } + + + private void LoadPuzzleInfo() + { + XmlDocument xmlDoc = new XmlDocument(); + System.Reflection.Assembly MyAssembly; + System.String myString; + MyAssembly = this.GetType().Assembly; + PuzzleInfo newPuzzle; + + // Creates the ResourceManager. + System.Resources.ResourceManager myManager = new + System.Resources.ResourceManager("EduNetworkBuilder.Properties.Resources", + MyAssembly); + + foreach (string str in Enum.GetNames(typeof(PuzzleNames))) + { + byte[] item = (byte[])myManager.GetObject(str); + if(item == null) + { + MessageBox.Show("Skipping Invalid Puzzle: '" + str + "'"); + continue; + } + myString = new StreamReader(new MemoryStream(item), true).ReadToEnd(); + //myString = System.Text.Encoding.Default.GetString(item); + xmlDoc.LoadXml(myString); + newPuzzle = new PuzzleInfo(); + newPuzzle.Load(xmlDoc, str); + PuzzleList.Add(newPuzzle); + //Console.WriteLine("Puzzle: " + str + " " + newPuzzle.PuzzleTitle); + } + PuzzleList = PuzzleList.OrderBy( c=> c.Level).ThenBy(c => c.SortOrder).ThenBy(c=> c.PuzzleName).ToList(); + } + + public PuzzleInfo PuzzleInfoFromName(string PuzzleName) + { + foreach(PuzzleInfo pi in PuzzleList) + { + if (pi.PuzzleName == PuzzleName) + return pi; + } + return null; + } + + public List GetPuzzleTags() + { + List PuzzleTags = new List(); + List LevelTags = new List(); + foreach (PuzzleInfo pi in PuzzleList) + { + foreach(string str in pi.PuzzleTags) + { + if(Regex.IsMatch(str,"^Level")) + { + if (!LevelTags.Contains(str, StringComparer.OrdinalIgnoreCase)) + LevelTags.Add(str); + } + else + { + if (!PuzzleTags.Contains(str, StringComparer.OrdinalIgnoreCase)) + PuzzleTags.Add(str); + } + } + } + PuzzleTags.Sort(); + LevelTags.Sort(); + LevelTags.AddRange(PuzzleTags); + return LevelTags; + } + public List GetPuzzleNames() + { + List PuzzleNames = new List(); + foreach (PuzzleInfo pi in PuzzleList) + { + PuzzleNames.Add(pi.PuzzleName); + } + return PuzzleNames; + } + private void btnClick(object sender, EventArgs e) + { + foreach(Control btn in Buttons) + { + if(btn == sender) + { + //This is the selected item + btn.BackColor = Color.LightGreen; + selectedButton = btn.Name; + lblStatus.Text = myTooltip.GetToolTip(btn); + } + else + { + btn.BackColor = Button.DefaultBackColor; + } + } + } + private void btnReset() + { + foreach (Control btn in Buttons) + { + lblStatus.Text = ""; + selectedButton = ""; + btn.BackColor = Button.DefaultBackColor; + } + } + + private void pbNetworkView_DoubleClick(object sender, EventArgs e) + { + + } + + private void exitToolStripMenuItem_Click(object sender, EventArgs e) + { + Close(); + } + + private void pbNetworkView_RightMouseUp(NetworkDevice ReleasedOn, MouseEventArgs e) + { + int index = 0; + if (pbNetworkView.ContextMenuStrip == null) + { + pbNetworkView.ContextMenuStrip = new ContextMenuStrip(); + } + pbNetworkView.ContextMenuStrip.Items.Clear(); + if (ReleasedOn != null) + { + foreach (string tStr in myNetwork.GetIncompleteTestDestinations(ReleasedOn.hostname, true)) + { + pbNetworkView.ContextMenuStrip.Items.Add("Ping " + tStr); + pbNetworkView.ContextMenuStrip.Items[index++].Click += pbNetworkView_Ping_Name_Click; + } + foreach (string tStr in myNetwork.GetIncompleteTestDestinations(ReleasedOn.hostname, false)) + { + pbNetworkView.ContextMenuStrip.Items.Add("Arp " + tStr); + pbNetworkView.ContextMenuStrip.Items[index++].Click += pbNetworkView_Arp_Name_Click; + } + } + pbNetworkView.ContextMenuStrip.Items.Add("Ping [host]"); + pbNetworkView.ContextMenuStrip.Items[index++].Click += pbNetworkView_Ping_Click; + pbNetworkView.ContextMenuStrip.Items.Add("Arp Request [host]"); + pbNetworkView.ContextMenuStrip.Items[index++].Click += pbNetworkView_Arp_Click; + pbNetworkView.ContextMenuStrip.Items.Add("Clear Arp Table"); + pbNetworkView.ContextMenuStrip.Items[index++].Click += pbNetworkView_ArpClear_Click; + if (ReleasedOn != null) + { + if (!myNetwork.ItemIsCritical(ReleasedOn.hostname)) + { + pbNetworkView.ContextMenuStrip.Items.Add("Delete"); + pbNetworkView.ContextMenuStrip.Items[index++].Click += pbNetworkView_Delete_Click; + } + } + pbNetworkView.ContextMenuStrip.Items.Add("Edit"); + pbNetworkView.ContextMenuStrip.Items[index++].Click += pbNetworkView_Edit_Click; + + if (ReleasedOn != null) + { + ItemClickedOn = ReleasedOn; + if(ReleasedOn.HasDHCPNic()) + { + pbNetworkView.ContextMenuStrip.Items.Add("DHCP Request"); + pbNetworkView.ContextMenuStrip.Items[index++].Click += pbNetworkView_DHCPRequest_Click; + } + foreach (string host in ReleasedOn.ListOfConnectedHosts()) + { + pbNetworkView.ContextMenuStrip.Items.Add("Remove Link To " + host); + pbNetworkView.ContextMenuStrip.Items[index++].Click += pbNetworkView_RemoveLink_Click; + } + } + if(ReleasedOn == null) + { + pbNetworkView.ContextMenuStrip.Visible = false; + } + else + { + pbNetworkView.ContextMenuStrip.Visible = true; + pbNetworkView.ContextMenuStrip.Show(Cursor.Position); + } + } + + private void pbNetworkView_RemoveLink_Click(object sender, EventArgs e) + { + ToolStripItem thing = (ToolStripItem)sender; + string released = thing.Text; + released = Regex.Replace(released, ".* ", ""); + if (ItemClickedOn != null) + { + ItemClickedOn.RemoveLinkTo(released); + } + myNetwork.TestForCompletion(true); + pbNetworkView.Update(); + pbNetworkView.Invalidate(); + + } + + private void pbNetworkView_DHCPRequest_Click(object sender, EventArgs e) + { + ItemClickedOn.DHCPRequestFromHere(); + myNetwork.ProcessPackets(); + UpdateMessages(); + pbNetworkView.Update(); + pbNetworkView.Invalidate(); + myNetwork.TestForCompletion(true); + } + + private void pbNetworkView_Edit_Click(object sender, EventArgs e) + { + if (ItemClickedOn != null) + { + DeviceConfig editwindow = new DeviceConfig(ItemClickedOn); + editwindow.ShowDialog(); + } + myNetwork.TestForCompletion(true); + pbNetworkView.Update(); + pbNetworkView.Invalidate(); + } + + private void pbNetworkView_Delete_Click(object sender, EventArgs e) + { + //Deleting the item is easy, but we also need to delete any links to that item + List NicIDs = new List(); + if(ItemClickedOn != null) + { + if (myNetwork.ItemIsCritical(ItemClickedOn.hostname)) + return; //we cannot delete this + NicIDs = ItemClickedOn.GetHostNicIDs(); + foreach (HostNicID nicID in NicIDs) + { + myNetwork.RemoveLinksToNic(nicID); + } + myNetwork.RemoveComponent(ItemClickedOn); + } + myNetwork.TestForCompletion(true); + pbNetworkView.Update(); + pbNetworkView.Invalidate(); + } + + private void pbNetworkView_Ping_Click(object sender, EventArgs e) + { + bool todo = true; + if (ItemClickedOn == null) return; //we do not have something chosen to ping from + IPAddress destination = new IPAddress(NB.ZeroIPString, NB.ZeroIPString, IPAddressType.ip_only); + todo = destination.Edit(ItemClickedOn, "Ping IP"); + if(todo) + { + ItemClickedOn.PingFromHere(destination); + myNetwork.ProcessPackets(); + UpdateMessages(); + } + } + private void pbNetworkView_Ping_Name_Click(object sender, EventArgs e) + { + if (ItemClickedOn == null) return; //we do not have something chosen to ping from + ToolStripMenuItem Pressed = (ToolStripMenuItem)sender; + string itemname = Pressed.Text; + string dest = Regex.Replace(itemname, "Ping ", ""); + IPAddress destination; + destination = myNetwork.DNSLookup(ItemClickedOn, dest); + if(destination == null || destination.GetIPString == NB.ZeroIPString) + destination = new IPAddress(dest); + ItemClickedOn.PingFromHere(destination); + myNetwork.ProcessPackets(); + UpdateMessages(); + } + private void pbNetworkView_Arp_Name_Click(object sender, EventArgs e) + { + if (ItemClickedOn == null) return; //we do not have something chosen to ping from + ToolStripMenuItem Pressed = (ToolStripMenuItem)sender; + string itemname = Pressed.Text; + string dest = Regex.Replace(itemname, "Arp ", ""); + IPAddress destination; + destination = myNetwork.DNSLookup(ItemClickedOn, dest); + if (destination == null || destination.GetIPString == NB.ZeroIPString) + destination = new IPAddress(dest); + ItemClickedOn.AskArpFromHere(destination); + myNetwork.ProcessPackets(); + UpdateMessages(); + } + + private void pbNetworkView_Arp_Click(object sender, EventArgs e) + { + bool todo = true; + if (ItemClickedOn == null) return; //we do not have something chosen to arp request from + IPAddress destination = new IPAddress(NB.ZeroIPString, "255.255.255.255", IPAddressType.ip_only); + todo = destination.Edit(ItemClickedOn, "Arp Request"); + if (todo) + { + ItemClickedOn.AskArpFromHere(destination); + myNetwork.ProcessPackets(); + UpdateMessages(); + } + } + + private void pbNetworkView_ArpClear_Click(object sender, EventArgs e) + { + if (ItemClickedOn == null) return; //we do not have something chosen to arp request from + ItemClickedOn.ClearArps(); + } + + private void pbNetworkView_MouseUp(object sender, MouseEventArgs e) + { + //find where we were clicked + Point CenteredLocation = myNetwork.clickedPosCentered(e.Location); + Point ClickLocation = myNetwork.clickedPos(e.Location); + NetworkDevice ReleasedOn = myNetwork.ItemAtPosition(ClickLocation); + + //Do we have something selected that we should add? + TimeSpan duration; + duration = DateTime.Now - LastClick; + + if(e.Button == System.Windows.Forms.MouseButtons.Right) + { + pbNetworkView_RightMouseUp(ReleasedOn, e); + return; + } + + if (duration.TotalMilliseconds < 250) + { + //This mouse-up is part of a double-click operation. + if(ItemClickedOn!= null) + { + DeviceConfig editwindow = new DeviceConfig(ItemClickedOn); + editwindow.ShowDialog(); + pbNetworkView.Update(); + pbNetworkView.Invalidate(); + myNetwork.TestForCompletion(true); + } + } + else + { + if (selectedButton == "btnLink") + { + //We are making a link + LinkEditor myEditor = new LinkEditor(ItemClickedOn, ReleasedOn); + myEditor.ShowDialog(); + pbNetworkView.Invalidate(); //In case any changes have been made + } + else if (ItemClickedOn == null) + { + NetworkComponent NC = null; + switch (selectedButton) + { + case "btnSwitch": + NC = myNetwork.AddItem(NetworkComponentType.net_switch, CenteredLocation); + break; + case "btnHub": + NC = myNetwork.AddItem(NetworkComponentType.net_hub, CenteredLocation); + break; + case "btnLaptop": + NC = myNetwork.AddItem(NetworkComponentType.laptop, CenteredLocation); + break; + case "btnServer": + NC = myNetwork.AddItem(NetworkComponentType.server, CenteredLocation); + break; + case "btnPC": + NC = myNetwork.AddItem(NetworkComponentType.pc, CenteredLocation); + break; + case "btnRouter": + NC = myNetwork.AddItem(NetworkComponentType.router, CenteredLocation); + break; + case "btnIPPhone": + NC = myNetwork.AddItem(NetworkComponentType.ip_phone, CenteredLocation); + break; + case "btnFirewall": + NC = myNetwork.AddItem(NetworkComponentType.firewall, CenteredLocation); + break; + case "btnPrinter": + NC = myNetwork.AddItem(NetworkComponentType.printer, CenteredLocation); + break; + case "btnCopier": + NC = myNetwork.AddItem(NetworkComponentType.copier, CenteredLocation); + break; + case "btnWAP": + NC = myNetwork.AddItem(NetworkComponentType.wap, CenteredLocation); + break; + case "btnWRouter": + NC = myNetwork.AddItem(NetworkComponentType.wrouter, CenteredLocation); + break; + case "btnWBridge": + NC = myNetwork.AddItem(NetworkComponentType.wbridge, CenteredLocation); + break; + case "btnWRepeater": + NC = myNetwork.AddItem(NetworkComponentType.wrepeater, CenteredLocation); + break; + + } + if(NC != null && NB.GetComponentType(NC) == GeneralComponentType.device) + { + ItemClickedOn = (NetworkDevice)NC; + } + } + else //Drag the item + { + if (Math.Abs(ClickedLocation.X - ClickLocation.X) > 5 || Math.Abs(ClickedLocation.Y - ClickLocation.Y) > 5) + { + ItemClickedOn.ChangeLocation(CenteredLocation); + pbNetworkView.Invalidate(); + } + } + } + LastClick = DateTime.Now; + } + + private void pbNetworkView_Paint(object sender, PaintEventArgs e) + { + myNetwork.Print(e); + } + + private void pbNetworkView_MouseDown(object sender, MouseEventArgs e) + { + Point location = myNetwork.clickedPos(e.Location); + ClickedLocation = location; + //See if we have clicked on something + ItemClickedOn = myNetwork.ItemAtPosition(location); + } + + private void pbNetworkView_MouseMove(object sender, MouseEventArgs e) + { + Point location = myNetwork.clickedPos(e.Location); + NetworkDevice MouseOver = myNetwork.ItemAtPosition(location); + MouseHoverOver = MouseOver; + string oldtooltip = myTooltip.GetToolTip(pbNetworkView); + string newtooltip = ""; + if (MouseOver != null) + { + newtooltip = MouseOver.TooltipString(); + } + if(oldtooltip != newtooltip) + { + myTooltip.SetToolTip(pbNetworkView, newtooltip); + } + } + + private void PrepForLoad() + { + processing = true; + myNetwork = new Network(""); + myNetwork.RegisterDisplayArea(pbNetworkView); + GC.Collect(); + RTFWindow myWin = (RTFWindow)Application.OpenForms["RTFWindow"]; + if (myWin != null) + { + myWin.Close(); + } + + pbNetworkView.Invalidate(); + UpdateMessages(); + btnReset(); + myNetwork.HintsToDisplay = NetTestVerbosity.none; + rbHelp1.Checked = true; + processing = false; + } + + private void loadToolStripMenuItem_Click(object sender, EventArgs e) + { + OpenFileDialog mydialog = new OpenFileDialog(); + mydialog.AddExtension = true; + mydialog.Filter = "EduNet File (*.enbx)|*.enbx"; + mydialog.Multiselect = false; + mydialog.ShowHelp = true; + if (LastPath != null && LastPath != "") mydialog.FileName = LastPath; + DialogResult result = mydialog.ShowDialog(); + if (result == System.Windows.Forms.DialogResult.Cancel) return; + if(!Regex.IsMatch(mydialog.FileName,@"^.*.enbx$")) + { + MessageBox.Show("EduNetworkBuilder can only open .enbx files. If this is a valid edunetwork file, please rename it."); + return; + } + LastPath = mydialog.FileName; + if (!File.Exists(mydialog.FileName)) return; + + PrepForLoad(); + myNetwork.Load(mydialog.FileName); + UpdateMenu(); + UpdateForm(); + } + + private void reloadToolStripMenuItem_Click(object sender, EventArgs e) + { + string oldfile = myNetwork.NetworkFilename; + if (oldfile != null && oldfile != "" && File.Exists(oldfile)) + { + PrepForLoad(); + myNetwork.Load(oldfile); + } + UpdateMenu(); + UpdateForm(); + } + + + private void saveToolStripMenuItem_Click(object sender, EventArgs e) + { + SaveFileDialog mydialog = new SaveFileDialog(); + mydialog.AddExtension = true; + mydialog.Filter = "EduNet File (*.enbx)|*.enbx"; + mydialog.FileName = myNetwork.NetworkFilename; + string initialfolder = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); + if (myNetwork.NetworkFilename != "") + initialfolder = Path.GetDirectoryName(myNetwork.NetworkFilename); + mydialog.CreatePrompt = true; + mydialog.OverwritePrompt = true; + mydialog.InitialDirectory = initialfolder; + DialogResult result = mydialog.ShowDialog(); + + if (result == System.Windows.Forms.DialogResult.Cancel) return; + LastPath = mydialog.FileName; + myNetwork.Save(mydialog.FileName); + } + + private void BuilderWindow_Resize(object sender, EventArgs e) + { + //size limits go here + int smallestX = 400; + int smallestY = 300; + if (Width < smallestX) Width = smallestX; + if (Height < smallestY) Height = smallestY; + } + + private void BuilderWindow_ResizeEnd(object sender, EventArgs e) + { + pbNetworkView.Invalidate(); + } + + private void aboutToolStripMenuItem_Click(object sender, EventArgs e) + { + RTFWindow mywindow = new RTFWindow(RTFWindowContents.about); + mywindow.ShowDialog(); + + } + + private void helpToolStripMenuItem1_Click(object sender, EventArgs e) + { + RTFWindow mywindow = new RTFWindow(RTFWindowContents.help); + mywindow.ShowDialog(); + + } + + private void releaseNotesToolStripMenuItem_Click(object sender, EventArgs e) + { + RTFWindow mywindow = new RTFWindow(RTFWindowContents.release_notes); + mywindow.ShowDialog(); + } + + private void lbMessages_DoubleClick(object sender, EventArgs e) + { + if(lbMessages.SelectedIndex < 0) return; //nothing to do + if(lbMessages.SelectedIndex > myNetwork.CountMessages()) return; //invalid. Do nothing + PacketMessage newMessage = myNetwork.GetMessageAtIndex(lbMessages.SelectedIndex); + if(newMessage == null) return; //Not sure how we could get to this, but break out just in case + ListBoxWindow newwindow = new ListBoxWindow(newMessage); + newwindow.ShowDialog(); + } + + private void BuilderWindow_FormClosing(object sender, FormClosingEventArgs e) + { + Properties.Settings.Default.ChosenLanguage = ChosenLanguage; + Properties.Settings.Default.LastPath = LastPath; + Properties.Settings.Default.Save(); + } + + private void dHCPRequestToolStripMenuItem_Click(object sender, EventArgs e) + { + myNetwork.DoAllDHCP(); + myNetwork.ProcessPackets(); + UpdateMessages(); + } + + private void clearArpTableToolStripMenuItem_Click(object sender, EventArgs e) + { + myNetwork.DoAllClearArp(); + UpdateMessages(); + } + + private void clearIPsToolStripMenuItem_Click(object sender, EventArgs e) + { + myNetwork.DoAllClearIPs(); + UpdateMessages(); + } + + private void pingToolStripMenuItem_Click(object sender, EventArgs e) + { + bool todo = true; + IPAddress destination = new IPAddress(NB.ZeroIPString, NB.ZeroIPString, IPAddressType.ip_only); + todo = destination.Edit(null, "Ping IP"); + if (todo) + { + myNetwork.DoAllPing(destination); + myNetwork.ProcessPackets(); + UpdateMessages(); + } + } + + public void LoadNetworkFromResource(string resource) + { + XmlDocument xmlDoc = new XmlDocument(); + //Load(SavePath); + System.Reflection.Assembly MyAssembly; + MyAssembly = this.GetType().Assembly; + + // Creates the ResourceManager. + System.Resources.ResourceManager myManager = new + System.Resources.ResourceManager("EduNetworkBuilder.Properties.Resources", + MyAssembly); + + // Retrieves String and Image resources. + System.String myString; + byte[] item = (byte[])myManager.GetObject(resource); + myString = new StreamReader(new MemoryStream(item), true).ReadToEnd(); + //myString = System.Text.Encoding.Default.GetString(item); + xmlDoc.LoadXml(myString); + PrepForLoad(); + myNetwork.Load(xmlDoc,resource); + UpdateMenu(); + UpdateForm(); + } + + private void oneNetworkToolStripMenuItem_Click(object sender, EventArgs e) + { + LoadNetworkFromResource("OneNet"); + UpdateMessages(); + } + + private void twoNetworksToolStripMenuItem_Click(object sender, EventArgs e) + { + LoadNetworkFromResource("TwoNets"); + UpdateMessages(); + } + + private void dHCPToolStripMenuItem_Click(object sender, EventArgs e) + { + LoadNetworkFromResource("DHCP"); + UpdateMessages(); + } + + private void solvedOneNetworkToolStripMenuItem_Click(object sender, EventArgs e) + { + LoadNetworkFromResource("OneNet"); + myNetwork.DoAllClearIPs(); + UpdateMessages(); + } + + private void solvedTwoNetworksToolStripMenuItem_Click(object sender, EventArgs e) + { + LoadNetworkFromResource("TwoNets"); + myNetwork.DoAllClearIPs(); + UpdateMessages(); + } + + private void solvedDHCPToolStripMenuItem_Click(object sender, EventArgs e) + { + LoadNetworkFromResource("DHCP"); + myNetwork.DoAllClearIPs(); + UpdateMessages(); + } + + private void threeNetworksToolStripMenuItem_Click(object sender, EventArgs e) + { + LoadNetworkFromResource("ThreeNets"); + UpdateMessages(); + } + + private void SolvedThreeNetworksToolStripMenuItem_Click(object sender, EventArgs e) + { + LoadNetworkFromResource("ThreeNets"); + myNetwork.DoAllClearIPs(); + UpdateMessages(); + } + + private void newToolStripMenuItem_Click(object sender, EventArgs e) + { + PrepForLoad(); + UpdateForm(); + } + + private void optionsToolStripMenuItem_Click(object sender, EventArgs e) + { + OptionsWindow tWindow = new OptionsWindow(myNetwork); + tWindow.ShowDialog(); + myNetwork.UpdateDeviceSizes(); + pbNetworkView.Invalidate(); + UpdateForm(); + } + + private void BuilderWindow_Load(object sender, EventArgs e) + { + //If we started by clicking on a file, load that file + if (AppDomain.CurrentDomain.SetupInformation.ActivationArguments != null && AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData != null && AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData.Any()) + { + string[] activationData = AppDomain.CurrentDomain.SetupInformation.ActivationArguments.ActivationData; + var uri = new Uri(activationData[0]); + //MessageBox.Show("Trying Localpath: " + uri.LocalPath); + //MessageBox.Show("isUNC: " + uri.IsUnc.ToString()); + //MessageBox.Show("isFile: " + uri.IsFile.ToString()); + + if (uri.IsFile) + { + PrepForLoad(); + myNetwork.Load(uri.LocalPath); + UpdateMenu(); + UpdateForm(); + } + } + else + { + if (Properties.Settings.Default.AutoStartPuzzles) + { + //We are supposed to start the puzzle-selection box + puzzlesToolStripMenuItem_Click(null, null); + } + } + } + + private void btnHelp_Click(object sender, EventArgs e) + { + OpenNetHelpWindow(); + bool didsomething = myNetwork.NoteActionDone(NetTestType.HelpRequest, "", "?Button"); + if (didsomething) + { + pbNetworkView.Invalidate(); + myNetwork.TestForCompletion(true); + } + } + + public void OpenNetHelpWindow() + { + RTFWindow rtwin = (RTFWindow)Application.OpenForms["RTFWindow"]; + if (rtwin == null) + { + rtwin = new RTFWindow("Help: " + myNetwork.NetTitle, myNetwork.NetMessage, myNetwork.NetTests); + rtwin.Show(); + Activate(); + } + } + + private void rbHelp1_CheckedChanged(object sender, EventArgs e) + { + if (processing) return; + myNetwork.HintsToDisplay = NetTestVerbosity.none; + pbNetworkView.Invalidate(); + } + + private void rbHelp2_CheckedChanged(object sender, EventArgs e) + { + if (processing) return; + myNetwork.HintsToDisplay = NetTestVerbosity.basic; + pbNetworkView.Invalidate(); + } + + private void rbHelp3_CheckedChanged(object sender, EventArgs e) + { + if (processing) return; + myNetwork.HintsToDisplay = NetTestVerbosity.hints; + pbNetworkView.Invalidate(); + } + + private void rbHelp4_CheckedChanged(object sender, EventArgs e) + { + if (processing) return; + myNetwork.HintsToDisplay = NetTestVerbosity.full; + pbNetworkView.Invalidate(); + } + + + private void puzzlesToolStripMenuItem_Click(object sender, EventArgs e) + { + ListBoxWindow LBW = new ListBoxWindow(); + LBW.ShowDialog(); + } + + private void firewallsToolStripMenuItem_Click(object sender, EventArgs e) + { + LoadNetworkFromResource("firewalls"); + UpdateMessages(); + } + + private void firewallsToolStripMenuItem1_Click(object sender, EventArgs e) + { + LoadNetworkFromResource("firewalls"); + myNetwork.DoAllClearIPs(); + UpdateMessages(); + } + + public void SetProgress(double HowFar, double total) + { + int max = (int)(total * 100); + myProgressBar.Maximum = max; + int distance = (int)(HowFar * 100); + if(distance > max) distance = max; + myProgressBar.Value = distance; + } + + private void changeLanguageToolStripMenuItem_Click(object sender, EventArgs e) + { + DialogResult answer = MessageBox.Show("Changing the language can only be done when the program starts: Close the program and prompt for a new language when you start it again?","Are you Sure?",MessageBoxButtons.YesNoCancel); + if (answer == System.Windows.Forms.DialogResult.Yes) + { + Properties.Settings.Default.LanguageHasBeenChosen = false; //So we choose the language on restart + //System.Diagnostics.Process.Start(Application.ExecutablePath); // to start new instance of application + this.Close(); //to turn off current app + } + } + } +} \ No newline at end of file diff --git a/EduNetworkBuilder/NetworkCard.cs b/EduNetworkBuilder/NetworkCard.cs new file mode 100644 index 0000000..3e29c66 --- /dev/null +++ b/EduNetworkBuilder/NetworkCard.cs @@ -0,0 +1,627 @@ +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.Xml; + + +namespace EduNetworkBuilder +{ + [Serializable] + public class NetworkCard + { + public string MAC = NB.GenerateMACAddress(); //Technically we should make sure it is unique + List interfaces = new List(); + public bool UsesDHCP = false; + public bool CanUseDHCP = false; + public bool MustUseDHCP = false; + private NicType myNicType = NicType.eth; + public HostNicID myID; + public int ConnectedLink=-1; //The link that is connected to this nic. + private int UniqueIdentifier = NB.GetUniqueIdentifier(); + private string _nic_name=""; + public IPAddress TunnelEndpoint; + public string EncryptionKey; + + public NetworkCard(int index, int HostID, string hostname, NicType theType = NicType.eth) + { + myNicType = theType; + _nic_name = myNicType.ToString() + index.ToString(); + NetworkInterface nInterface = new NetworkInterface(NicName(), NB.ZeroIPString, NB.ZeroIPString, myID); + if(theType == NicType.lo) + nInterface = new NetworkInterface(NicName(), "127.0.0.1", "255.0.0.0", myID); + myID = new HostNicID(HostID, UniqueIdentifier,hostname,nInterface.nic_name); + interfaces.Add(nInterface); + ApplyNicRules(); + SetIPForDHCP(); + } + + public NetworkCard(XmlNode theNode) + { + foreach (XmlNode Individual in theNode.ChildNodes) + { + XmlNodeType myNodetype = Individual.NodeType; + if (myNodetype == XmlNodeType.Element) + { + switch (Individual.Name.ToLower()) + { + case "nictype": + myNicType = NB.ParseEnum(Individual.InnerText); + break; + case "nicname": + _nic_name = Individual.InnerText; + break; + case "myid": + myID = new HostNicID(Individual); + break; + case "usesdhcp": + bool.TryParse(Individual.InnerText, out UsesDHCP); + break; + case "uniqueidentifier": + int.TryParse(Individual.InnerText, out UniqueIdentifier); + break; + case "interface": + NetworkInterface newIF = new NetworkInterface(Individual,myID); + interfaces.Add(newIF); + break; + case "mac": + string tmac = Individual.InnerText; + if (tmac.Length == MAC.Length) + MAC = tmac.ToUpper(); //Make sure it is all uppercase + break; + case "tunnelendpoint": + TunnelEndpoint = new IPAddress(Individual); + break; + case "encryptionkey": + EncryptionKey = Individual.InnerText; + break; + } + } + } + ApplyNicRules(); + SetIPForDHCP(); + } + + private void ApplyNicRules() + { + //These are the defaults for the various nic types. They can be overridden by the device. + if(myNicType == NicType.eth || myNicType == NicType.management_interface || myNicType == NicType.wlan) + { + CanUseDHCP = true; + } + else + { + CanUseDHCP = false; + } + } + + public void Save(XmlWriter writer) + { + writer.WriteStartElement("nic"); + writer.WriteElementString("nictype", myNicType.ToString()); + writer.WriteElementString("nicname", _nic_name); + myID.Save(writer, "myid"); + writer.WriteElementString("nictype", myNicType.ToString()); + writer.WriteElementString("uniqueidentifier", UniqueIdentifier.ToString()); + writer.WriteElementString("usesdhcp", UsesDHCP.ToString()); + if(EncryptionKey != "") + writer.WriteElementString("encryptionkey", EncryptionKey); + if (TunnelEndpoint != null) + { + TunnelEndpoint.Save(writer, "tunnelendpoint"); + } + foreach (NetworkInterface nIF in interfaces) + { + nIF.Save(writer); + } + writer.WriteEndElement(); + } + + public int GetUniqueIdentifier + { + get { return UniqueIdentifier; } + } + + public NicType GetNicType + { + get { return myNicType; } + } + + public bool HasIP(UInt32 IP) + { + if (myNicType == NicType.port) return false; + if (myNicType == NicType.none) return false; + foreach (NetworkInterface IF in interfaces) + { + if (IF.myIP.Equals(IP)) + return true; + } + return false; + } + + public string NicName() + { + return _nic_name; + } + + public string NicString(int index) + { + string connected = " "; + if (isConnected(true)) connected = "*"; + if (myNicType == NicType.port) + return NicName() + connected; + return NicName() + connected + " " + MAC; + } + + public List NICRouteStrings(string GW) + { + List thestrings = new List(); + if (myNicType == NicType.port) return thestrings; + if (myNicType == NicType.none) return thestrings; + foreach (NetworkInterface iface in interfaces) + { + thestrings.Add(iface.RouteString(_nic_name,GW)); + } + return thestrings; + } + + public List IPAddresses(bool UseCidr = false) + { + List theIPs = new List(); + if (myNicType == NicType.port) return theIPs; + if (myNicType == NicType.none) return theIPs; + string DHCPString = ""; + if (UsesDHCP && CanUseDHCP) DHCPString = "DHCP: "; + foreach (NetworkInterface iface in interfaces) + { + theIPs.Add(DHCPString + iface.InterfaceString(UseCidr)); + } + return theIPs; + } + + public List IPAddressList() + { + List theIPs = new List(); + if (myNicType == NicType.port) return theIPs; + if (myNicType == NicType.none) return theIPs; + foreach (NetworkInterface iface in interfaces) + { + theIPs.Add(iface.myIP); + } + return theIPs; + } + + public bool HasIPAddresses(IPAddress dest) + { + if (myNicType == NicType.port) return false; + if (myNicType == NicType.none) return false; + if (dest == null) return false; + foreach (NetworkInterface iface in interfaces) + { + if (iface.myIP.GetIP == dest.GetIP) + return true; + } + return false; + } + public bool HasBroadcastAddresses(IPAddress dest) + { + if (myNicType == NicType.port) return false; + if (myNicType == NicType.none) return false; + if (dest == null) return false; + foreach (NetworkInterface iface in interfaces) + { + if (iface.myIP.BroadcastAddress == dest.GetIP) + return true;//If they are pinging the broadcast IP + } + return false; + } + + public void EditInterface(int index) + { + if (index < 0 || index > interfaces.Count()) + return; + interfaces[index].EditAddress(); + } + public void DeleteInterface(int index) + { + if (index < 0 || index > interfaces.Count()) + return; + if (interfaces.Count < 2) + return; //We cannot delete the sole remaining interface + interfaces.RemoveAt(index); + } + public void AddInterface() + { + NetworkInterface iface = new NetworkInterface(NicName(), NB.ZeroIPString, NB.ZeroIPString, myID); + interfaces.Add(iface); + } + + public NetworkInterface GetInterface(int index) + { + if (index < 0 || index > interfaces.Count()) + return null; + return interfaces[index]; + } + + public bool isConnected(bool CheckForBrokenLink) + { + if(ConnectedLink != -1) + { + if (!CheckForBrokenLink) return true; //We only care if there is any link + Network myNet = NB.GetNetwork(); + NetworkLink NL = myNet.GetLinkFromID(ConnectedLink); + if(NL != null) + { + if (NL.theLinkType != LinkType.broken) return true; + else return false; + } + } + return false; + } + + public void Edit() + { + NetworkCardEditor nce = new NetworkCardEditor(this); + nce.ShowDialog(); + //Now. update the interfaces if we need to do so. + SetIPForDHCP(); + } + + public void SetIPForDHCP() + { + if (UsesDHCP && CanUseDHCP) + { + //remove any extra interfaces. + //set the one interface to 0.0.0.0 + switch(myNicType) + { + case NicType.eth: + case NicType.wlan: + interfaces.Clear(); //empty out all interfaces + //Give it an interface with an empty IP + NetworkInterface nInterface = new NetworkInterface(NicName(), NB.ZeroIPString, NB.ZeroIPString,myID); + interfaces.Add(nInterface); + break; + } + } + } + public void SetIPForDHCP(IPAddress newIP) + { + if (UsesDHCP && CanUseDHCP) + { + if(interfaces.Count > 0) + interfaces[0].myIP = newIP; + } + } + + public bool HasLocalInterface(IPAddress theIP) + { + foreach(NetworkInterface nIF in interfaces) + { + if (nIF.isLocal(theIP)) + return true; + } + return false; + } + + /// + /// Return the interface that is considered "local" to the IP address we are trying to reach + /// + /// An IP address we are trying to send out + /// null if no interface is local. Otherwise, it returns the one that matches the packet + public NetworkInterface LocalInterface(IPAddress theIP, PacketMessage Tracker) + { + if (myNicType == NicType.port) return null; //ports have no local interfaces + foreach (NetworkInterface nIF in interfaces) + { + if (nIF.isLocal(theIP)) + { + if(Tracker != null) + Tracker.AddMessage(DebugLevel.routing, myID.HostName, "Found local interface: ip" + nIF.myIP.GetIP.ToIpString() + + " gw:" + nIF.myIP.GetMask.ToIpString()); + return nIF; + } + } + return null; + } + + /*************************************** + * + * *************************************/ + public bool SendPacketOutNIC(Packet tPacket) + { + bool madeprogress = false; + Packet nPacket = null; + Network myNet = NB.GetNetwork(); + NetworkLink nl; + if (NB.GetComponentType(tPacket.WhereAmI) != GeneralComponentType.device) return false; //we cannot do this. + NetworkDevice WhereFrom = (NetworkDevice)tPacket.WhereAmI; + + switch (GetNicType) + { + case NicType.lo: + case NicType.management_interface: + case NicType.none: + break; //Do nothing + case NicType.eth: + //see if it the packet dest is local to this nic + foreach (NetworkInterface nf in interfaces.ToList()) + { + if (tPacket.MyType == PacketType.arp_request && !nf.isLocal(tPacket.destIP)) + continue; //only send out arp requests on local networks + nPacket = new Packet(tPacket);//Creates a new packet but sets isfresh=false + if (nf.isLocal(tPacket.OutboundIP) || tPacket.OutboundIP.GetIPString == NB.BroadcastIPString) + { + if ((nf != null && nf.myIP.GetIPString != NB.ZeroIPString) || nPacket.MyType == PacketType.dhcp_request) + { + //this means we have a local interface to send it out of + nPacket.sourceMAC = MAC; + //If the source IP is empty then it is a new packet. We set the source to be us + if (nPacket.sourceIP == null || nPacket.sourceIP.GetIPString == NB.ZeroIPString) + nPacket.sourceIP = nf.myIP; + nPacket.TsourceIP = nf.myIP; + if (nPacket.destMAC == null || nPacket.destMAC == "") + { + nPacket.destMAC = WhereFrom.LookupArpFromIP(tPacket.OutboundIP.GetIPString); + if (nPacket.MyType == PacketType.arp_request) + { + nPacket.destMAC = NB.BroadcastMACString; + } + + if(nPacket.destMAC == "") + { + nPacket.AddMessage(DebugLevel.debug, " No Machine matching that IP address on this subnet. " + nPacket.destIP.GetIPString); + Network mynet = NB.GetNetwork(); + NetworkDevice nd = mynet.GetDeviceFromID(myID); + string hostname = "No Host"; + if (nd != null) hostname = nd.hostname; + nPacket.Tracking.Status = hostname + " No Machine matching that IP address on this subnet. " + nPacket.destIP.GetIPString; + nPacket.MyStatus = PacketStatus.finished_failed; + return false; + } + } + nl = myNet.GetLinkFromID(ConnectedLink); + nPacket.StartOnLink(nl, WhereFrom); //This sends the packet down the link. + //Store outbound information here - som we expect the returning packet + WhereFrom.StoreOutgoingPacketInfo(nPacket); + myNet.addPacket(nPacket); + nPacket.PacketDump(myID.HostName + "-" + _nic_name, DebugPausePoint.packet_out); + madeprogress = true; + } + } + } + break; + case NicType.wan: + //see if it the packet dest is local to this nic + if (tPacket.MyType == PacketType.dhcp_answer && tPacket.isFresh) + break; //We do not broadcast out the WAN port + foreach (NetworkInterface nf in interfaces.ToList()) + { + nPacket = new Packet(tPacket);//Creates a new packet but sets isfresh=false + if (nf.isLocal(tPacket.OutboundIP) || tPacket.OutboundIP.GetIPString == NB.BroadcastIPString) + { + if ((nf != null && nf.myIP != null && nf.myIP.GetIPString != NB.ZeroIPString) || nPacket.MyType == PacketType.dhcp_request) + { + //this means we have a local interface to send it out of + nPacket.sourceMAC = MAC; + //If the source IP is empty then it originated from here. We set the source to be us + if (nPacket.sourceIP == null || nPacket.sourceIP.GetIPString == NB.ZeroIPString) + { + nPacket.sourceIP = nf.myIP; + WhereFrom.StoreOutgoingPacketInfo(nPacket); //the packet is not masqueraded, just accepted + } + else + { + //When we leave the WAN port, we are masqueraded. Track that. + WhereFrom.StoreOutgoingPacketInfo(nPacket, ResponseToPacket.masq); + //Now, we masquerade the packet so it looks like it comes fromhere + nPacket.Tracking.AddMessage(DebugLevel.natting, WhereFrom.hostname, "MASQ: Changing outbound IP to: " + nf.myIP.GetIPString); + nPacket.sourceIP = nf.myIP; + } + nPacket.TsourceIP = nf.myIP; + if (nPacket.destMAC == null || nPacket.destMAC == "") + { + nPacket.destMAC = WhereFrom.LookupArpFromIP(tPacket.OutboundIP.GetIPString); + + if (nPacket.destMAC == "") + { + nPacket.AddMessage(DebugLevel.debug, " No Machine matching that IP address on this subnet. " + nPacket.destIP.GetIPString); + Network mynet = NB.GetNetwork(); + NetworkDevice nd = mynet.GetDeviceFromID(myID); + string hostname = "No Host"; + if (nd != null) hostname = nd.hostname; + nPacket.Tracking.Status = hostname + " No Machine matching that IP address on this subnet. " + nPacket.destIP.GetIPString; + nPacket.MyStatus = PacketStatus.finished_failed; + return false; + } + } + nl = myNet.GetLinkFromID(ConnectedLink); + nPacket.StartOnLink(nl, WhereFrom); //This sends the packet down the link. + //Store outbound information here - som we expect the returning packet + WhereFrom.StoreOutgoingPacketInfo(nPacket); + myNet.addPacket(nPacket); + nPacket.PacketDump(myID.HostName + "-" + _nic_name, DebugPausePoint.packet_out); + madeprogress = true; + } + } + } + break; + case NicType.tun: + case NicType.vpn: + foreach (NetworkInterface nf in interfaces.ToList()) + { + if (nf.isLocal(tPacket.OutboundIP)) + { + //We need to tell the original packet that it is inside another packet + tPacket.MyStatus = PacketStatus.encapsulated; + tPacket.TsourceIP = nf.myIP; + tPacket.destMAC = WhereFrom.LookupArpFromIP(tPacket.OutboundIP.GetIPString); + + //We need to make a new, tunnel packet + if (myNicType == NicType.tun) + EncryptionKey = ""; + Packet rnPacket = new Packet(tPacket); + WhereFrom.TunnelPacketFromHere(TunnelEndpoint, rnPacket, EncryptionKey); + //We need to send the new packet on (pass it back to the device to process) + madeprogress = true; + } + } + break; + case NicType.port: + nPacket = new Packet(tPacket); + if (HasBroadcastAddresses(tPacket.destIP)) + { + //Broadcast packets will go to everything and we want a response from all of them. + nPacket.Tracking = PacketMessage.Clone(tPacket.Tracking); + } + if (nPacket.sourceMAC == null || nPacket.sourceMAC == "") + { + //Need to find the managament interface MAC + nPacket.sourceMAC = WhereFrom.HubManagementMAC(); + } + if(nPacket.sourceIP == null || nPacket.sourceIP.GetIPString == NB.ZeroIPString) + { + //set it to be the ip of management interface + nPacket.sourceIP = WhereFrom.HubManagementIP(); + } + if (nPacket.destMAC == null || nPacket.destMAC == "") + { + nPacket.destMAC = WhereFrom.LookupArpFromIP(tPacket.OutboundIP.GetIPString); + } + if(nPacket.TsourceIP == null) + nPacket.TsourceIP = WhereFrom.HubManagementIP(); + nl = myNet.GetLinkFromID(ConnectedLink); + if (nl == null) break; + nPacket.StartOnLink(nl, WhereFrom); //This sends the packet down the link. + myNet.addPacket(nPacket); + if(tPacket.isFresh) + WhereFrom.StoreOutgoingPacketInfo(nPacket); //if it originated from here... + madeprogress = true; + nPacket.PacketDump(myID.HostName, DebugPausePoint.packet_out); + break; + } + return madeprogress; + } + + //********************Process Packet ******** + public void ProcessOutboundPacket(Packet tPacket) + { + //We set the MAC addrss to this nic + tPacket.sourceMAC = MAC; + + //If the nic has a special function, we need to do that too. + // VPN, etc + } + + public void ProcessInboundPacket(Packet tPacket) + { + Network mynet; + NetworkDevice nd; + //We make sure the MAC matches. + if (myNicType == NicType.port) + { + //Try tracking the arp if we can + mynet = NB.GetNetwork(); + nd = mynet.GetDeviceFromID(myID); + if (tPacket.TsourceIP == null) tPacket.TsourceIP = tPacket.sourceIP; + nd.StoreArp(tPacket.sourceMAC, tPacket.TsourceIP.GetIP.ToIpString(), myID); + //If it is a return DHCP packet. We should try to update the MAC + if (tPacket.MyType == PacketType.dhcp_answer) + { + HostNicID otherid = nd.NicIDFromArp(tPacket.destMAC); + if (otherid.HostID != -1) + nd.StoreArp(tPacket.destMAC, tPacket.payloadIP.GetIP.ToIpString(), otherid); + } + return; + } + if(myNicType == NicType.wan) + { + mynet = NB.GetNetwork(); + nd = mynet.GetDeviceFromID(myID); + + if(nd.HowToRespondToPacket(tPacket) == ResponseToPacket.masq) + { + IPAddress oAddress = nd.PacketMasqueradeSource(tPacket); + if(oAddress != null) + { + tPacket.Tracking.AddMessage(DebugLevel.natting, nd.hostname, "MASQ: Changing source IP back to: " + oAddress.GetIPString); + tPacket.destIP = oAddress; + } + } + else if(!HasIP(tPacket.destIP.GetIP)) + { + tPacket.AddMessage(DebugLevel.routing, "The packet was rejected by the firewall."); + tPacket.AddMessage(DebugLevel.debug, " The packet was not expected by the firewall, so it was rejected."); + mynet = NB.GetNetwork(); + nd = mynet.GetDeviceFromID(myID); + string hostname = "No Host"; + if (nd != null) hostname = nd.hostname; + tPacket.Tracking.Status = hostname + " The packet was rejected by the firewall.. Dropped."; + tPacket.MyStatus = PacketStatus.finished_failed; + } + } + if(tPacket.destMAC == MAC || tPacket.destMAC == NB.BroadcastMACString || myNicType == NicType.port) + { + //It matches. We are ok. Anything to do? + //If the NIC is a vpn, do that here. + } + else + { + tPacket.AddMessage(DebugLevel.routing,"The Packet was destined for a different machine (MAC Address): Rejected"); + tPacket.AddMessage(DebugLevel.debug, " Device MAC: " + MAC + " did not match packet: " + tPacket.destMAC); + mynet = NB.GetNetwork(); + nd = mynet.GetDeviceFromID(myID); + string hostname = "No Host"; + if (nd != null) hostname = nd.hostname; + tPacket.Tracking.Status = hostname + " Packet destined for another machine. Dropped."; + tPacket.MyStatus = PacketStatus.finished_failed; + } + } + + public void ClearIPs() + { + foreach(NetworkInterface nf in interfaces) + { + if(myNicType != NicType.lo) + nf.myIP = new IPAddress(NB.ZeroIPString); + } + } + + public IPAddress FirstIP() + { + List addresses = IPAddressList(); + if (addresses.Count > 0) + return addresses[0]; + else + return new IPAddress(NB.ZeroIPString); + } + + public static T Clone(T source) + { + if (!typeof(T).IsSerializable) + { + throw new ArgumentException("The type must be serializable.", "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); + } + } + + } +} diff --git a/EduNetworkBuilder/NetworkCardEditor.cs b/EduNetworkBuilder/NetworkCardEditor.cs new file mode 100644 index 0000000..22b7532 --- /dev/null +++ b/EduNetworkBuilder/NetworkCardEditor.cs @@ -0,0 +1,161 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Globalization; +using System.Resources; + +namespace EduNetworkBuilder +{ + public partial class NetworkCardEditor : Form + { + NetworkCard MyNicToEdit; + Button btnVPNEnd = null; + TextBox tbVPNEncrypt = null; + Label lblVPNEnd = null; + Label lblVPNEncrypt = null; + + private NetworkCardEditor() + { + InitializeComponent(); + LanguagifyComponents(); + } + + public NetworkCardEditor(NetworkCard NicToEdit) + { + InitializeComponent(); + LanguagifyComponents(); + + if (NicToEdit.GetNicType == NicType.tun || NicToEdit.GetNicType == NicType.vpn) + { + AutoSize = false; + btnVPNEnd = new Button(); + btnVPNEnd.Location = new Point(TBMacAddress.Location.X, cbDHCP.Location.Y + 28); + string btnval = "0.0.0.0"; + if (NicToEdit.TunnelEndpoint != null) + btnval = NicToEdit.TunnelEndpoint.GetIPString; + btnVPNEnd.Text = btnval; + btnVPNEnd.Click += btnVPNEnd_Click; + + lblVPNEnd = new Label(); + lblVPNEnd.Location = new Point(10, btnVPNEnd.Location.Y); + lblVPNEnd.Text = "VPN Endpoint:"; + Controls.Add(btnVPNEnd); + Controls.Add(lblVPNEnd); + this.Height = lblVPNEnd.Location.Y + lblVPNEnd.Height + 80; + + if (NicToEdit.GetNicType == NicType.vpn) + { + tbVPNEncrypt = new TextBox(); + tbVPNEncrypt.Location = new Point(TBMacAddress.Location.X, btnVPNEnd.Location.Y + 28); + + lblVPNEncrypt = new Label(); + lblVPNEncrypt.Location = new Point(10, tbVPNEncrypt.Location.Y); + lblVPNEncrypt.Text = "Encryption Key:"; + Controls.Add(tbVPNEncrypt); + Controls.Add(lblVPNEncrypt); + this.Height = tbVPNEncrypt.Location.Y + tbVPNEncrypt.Height + 80; + } + Refresh(); + //AutoSize = true; + } + TBMacAddress.Enabled = false; + tbNicName.Enabled = false; + tbNicType.Enabled = false; + cbCanUseDHCP.Enabled = false; + + TBMacAddress.Text = NicToEdit.MAC; + tbNicName.Text = NicToEdit.NicName(); + tbNicType.Text = NicToEdit.GetNicType.ToString(); + + MyNicToEdit = NicToEdit; + cbCanUseDHCP.Checked = NicToEdit.CanUseDHCP; + cbDHCP.Checked = NicToEdit.UsesDHCP; + if (!NicToEdit.CanUseDHCP) cbDHCP.Enabled = false; + if(NicToEdit.MustUseDHCP) + { + cbDHCP.Enabled = false; + cbCanUseDHCP.Enabled = false; + } + Network theNet = NB.GetNetwork(); + NetworkDevice nd = theNet.GetDeviceFromID(NicToEdit.myID); + if(theNet.ItemIsLocked(nd.hostname, NicToEdit.NicName(), NetTestType.LockNic)) + { + cbDHCP.Enabled = false; + cbCanUseDHCP.Enabled = false; + TBMacAddress.Enabled = false; + tbNicName.Enabled = false; + tbNicType.Enabled = false; + } + UpdateForm(); + } + + private void LanguagifyComponents() + { + ResourceManager RM = NB.GetResource(); + CultureInfo CI = NB.GetCulture(); + Text = NB.Translate("NCE_cbCanUseDHCP"); + Text = NB.Translate("NCE_cbDHCP"); + Text = NB.Translate("NCE_label1"); + Text = NB.Translate("NCE_label2"); + Text = NB.Translate("NCE_label3"); + Text = NB.Translate("NCE_btnDone"); + Text = NB.Translate("NCE_lblLinkStatus"); + Text = NB.Translate("NCE_Form"); + } + + private void UpdateForm() + { + if (btnVPNEnd != null) + { + string btnval = "0.0.0.0"; + if (MyNicToEdit.TunnelEndpoint != null) + btnval = MyNicToEdit.TunnelEndpoint.GetIPString; + btnVPNEnd.Text = btnval; + } + if(tbVPNEncrypt != null) + { + tbVPNEncrypt.Text = MyNicToEdit.EncryptionKey; + } + if (MyNicToEdit.GetNicType == NicType.tun || MyNicToEdit.GetNicType == NicType.vpn || + MyNicToEdit.GetNicType == NicType.management_interface || MyNicToEdit.GetNicType == NicType.lo) + { + lblLinkStatus.Visible = false; + } + else + lblLinkStatus.Visible = true; + if (MyNicToEdit.isConnected(true)) + lblLinkStatus.Text = "Connected"; + else + lblLinkStatus.Text = "Disconnected"; + } + + private void btnDone_Click(object sender, EventArgs e) + { + MyNicToEdit.CanUseDHCP = cbCanUseDHCP.Checked; + MyNicToEdit.UsesDHCP = cbDHCP.Checked; + if (tbVPNEncrypt != null) + { + MyNicToEdit.EncryptionKey = tbVPNEncrypt.Text; + } + Close(); + } + + private void btnVPNEnd_Click(object sender, EventArgs e) + { + Network theNet = NB.GetNetwork(); + NetworkDevice nd = theNet.GetDeviceFromID(MyNicToEdit.myID); + if(MyNicToEdit.TunnelEndpoint == null) + { + MyNicToEdit.TunnelEndpoint = new IPAddress(NB.ZeroIPString, "255.255.255.0", IPAddressType.ip_only); + } + MyNicToEdit.TunnelEndpoint.Edit(nd,"Endpoint"); + UpdateForm(); + } + } +} diff --git a/EduNetworkBuilder/NetworkCardEditor.resx b/EduNetworkBuilder/NetworkCardEditor.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/EduNetworkBuilder/NetworkCardEditor.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/EduNetworkBuilder/NetworkDevice.cs b/EduNetworkBuilder/NetworkDevice.cs new file mode 100644 index 0000000..bc50e89 --- /dev/null +++ b/EduNetworkBuilder/NetworkDevice.cs @@ -0,0 +1,2281 @@ +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 NICs = new List(); + protected IPAddress DefaultGW = new IPAddress(NB.ZeroIPString, NB.ZeroIPString, IPAddressType.gw); + protected Image MyImage = null; + protected Point MyLocation; + protected int Size; + protected List ArpTable = new List(); + protected NetworkComponentType myType = NetworkComponentType.none; + protected List RouteTable = new List(); + protected List DHCPRanges = new List(); + protected List DHCPLeases = new List(); + protected List IPConnections = new List(); + 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 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(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 DeviceMessages = myNet.GetTestMessages(hostname); + foreach (string tString in DeviceMessages) + { + answer += "\n" + tString; + } + } + return answer; + } + + public List ListOfConnectedHosts() + { + List thelist = new List(); + 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; + } + } + } + } + } + + /// + /// Check to see if the device has a link to the specified host + /// + /// + 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; + } + + /// + /// returns the centerpoint of the device + /// + /// a point that is the center of the device + 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 NetworkCardStrings(bool OnlyUnused=true, bool OnlyLinkable=false) + { + List macStrings = new List(); + 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 NetworkCardInterfaceStrings(int index) + { + List myList = new List(); + if(index >= 0 && index < NICs.Count) + { + myList.AddRange(NICs[index].IPAddresses()); + } + return myList; + } + public List NetworkCardInterfaceStrings(string NicName) + { + List myList = new List(); + 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; + } + /// + /// returns true if it has a connection to something. + /// + /// + 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 + } + + + /// + /// Check all the network cards on this device to see if it has a nic with the given MAC address + /// + /// The MAC address we are looking for + /// True if we have it, false if we do not. + public override bool HasMac(string MAC) + { + foreach(NetworkCard nic in NICs) + { + if (nic.MAC == MAC) return true; + } + return false; + } + + + /// + /// Get the host nic IDentifier for the specified MAC address + /// + /// The index of the network card + /// The unique host-nic-ID + public HostNicID GetHostNicID(int MacIndex) + { + if (MacIndex < 0 || MacIndex > NICs.Count()) + return new HostNicID(-1, -1, hostname, ""); + return NICs[MacIndex].myID; + } + + /// + /// Get the host nic IDentifier for the specified MAC address + /// + /// The index of the network card + /// The unique host-nic-ID + public List GetHostNicIDs() + { + List tList = new List(); + 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 arp(UInt32 IP) + { + List arps = new List(); + 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 tstrings = new List(); + 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 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 IPAddresses = new List(); + 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 IPAddressList() + { + List thelist = new List(); + foreach(NetworkCard nic in NICs) + { + thelist.AddRange(nic.IPAddressList()); + } + return thelist; + } + + public List SubnetList() + { + List thelist = new List(); + foreach(IPAddress taddr in IPAddressList()) + { + if(!thelist.Contains(taddr.NetworkAddress.ToIpString())) + { + thelist.Add(taddr.NetworkAddress.ToIpString()); + } + } + return thelist; + } + + public List BroadcastList() + { + List thelist = new List(); + foreach (IPAddress taddr in IPAddressList()) + { + if (!thelist.Contains(taddr.BroadcastAddress.ToIpString())) + { + thelist.Add(taddr.BroadcastAddress.ToIpString()); + } + } + return thelist; + } + + + /// + /// Return either the destination IP or the gateway IP + /// + /// The target IP + /// The IP the packet should be going to + 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 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; + } + + /// + /// Return the network card that is considered "local" for the given IP + /// + /// The IP Address we are looking for + /// a network card, or null if nothing matches + 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 NICRouteStrings() + { + List answer = new List(); + string GW = DefaultGW.GetIP.ToIpString(); + foreach(NetworkCard nic in NICs) + { + answer.AddRange(nic.NICRouteStrings(GW)); + } + return answer; + } + public List NICNames() + { + List answer = new List(); + 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 DeviceRouteStrings() + { + List answer = new List(); + foreach (IPAddress ip in RouteTable) + { + answer.Add(ip.IPFormat()); + } + return answer; + } + public void AddRoute(IPAddress route) + { + RouteTable.Add(route); + } + public List 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 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); + } + + /// + /// Return true if this is a switch/hub/wap + /// + /// + 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; + } + /// + /// Return true if this device routes packets. Router, firewall, etc. + /// + /// + 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 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 GetArps() + { + return ArpTable; + } + public void ClearArps() + { + ArpTable.Clear(); + } + + /// + /// Clear out all the IP addresses on the device + /// + 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 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 DHCPStrings(bool WithAdditionalInfo=true) + { + List theStrings = new List(); + 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 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); + } + + /// + /// 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. + /// + /// The mac of the requesting machine + /// the IP of the server nic + /// an IPAddress IP/Mask/GW + 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 + } + + /// + /// Return true if this device has at least one nic that can be configured from DHCP + /// + /// True if the device has a nic that can be configured with DHCP + public bool HasDHCPNic() + { + foreach(NetworkCard card in NICs) + { + if (card.UsesDHCP) + return true; + } + return false; + } + } +} diff --git a/EduNetworkBuilder/NetworkLink.cs b/EduNetworkBuilder/NetworkLink.cs new file mode 100644 index 0000000..f326c84 --- /dev/null +++ b/EduNetworkBuilder/NetworkLink.cs @@ -0,0 +1,224 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Drawing; +using System.Xml; + + +namespace EduNetworkBuilder +{ + [Serializable] + public class NetworkLink : NetworkComponent + { + HostNicID SrcNic; + HostNicID DstNic; + public LinkType theLinkType = LinkType.normal; + public bool isVisibleLink = true; //False for wireless. Skip drawing a line if it is there + + public NetworkLink(HostNicID source, HostNicID dest, LinkType type = LinkType.normal) + { + SrcNic = source; + DstNic = dest; + Network myNet = NB.GetNetwork(); + myNet.MarkAsLinked(source, GetUniqueIdentifier); + myNet.MarkAsLinked(dest, GetUniqueIdentifier); + theLinkType = type; + } + + public NetworkLink(XmlNode theNode) + { + IsDirty = true; + Load(theNode); + } + + public HostNicID Src + { + get { return SrcNic; } + } + public HostNicID Dst + { + get { return DstNic; } + } + public override void Load(XmlNode theNode) + { + foreach (XmlNode Individual in theNode.ChildNodes) + { + XmlNodeType myNodetype = Individual.NodeType; + if (myNodetype == XmlNodeType.Element) + { + switch (Individual.Name.ToLower()) + { + case "srcnic": + SrcNic = new HostNicID(Individual); + break; + case "dstnic": + DstNic = new HostNicID(Individual); + break; + case "hostname": + hostname = Individual.InnerText; + break; + case "linktype": + theLinkType = NB.ParseEnum(Individual.InnerText); + break; + case "uniqueidentifier": + int.TryParse(Individual.InnerText,out UniqueIdentifier); + break; + } + } + } + Network myNet = NB.GetNetwork(); + myNet.MarkAsLinked(SrcNic, GetUniqueIdentifier); + myNet.MarkAsLinked(DstNic, GetUniqueIdentifier); + } + + public override void Save(XmlWriter writer) + { + writer.WriteStartElement("link"); + SrcNic.Save(writer,"SrcNic"); + DstNic.Save(writer,"DstNic"); + writer.WriteElementString("hostname", hostname); + writer.WriteElementString("linktype", theLinkType.ToString()); + writer.WriteElementString("uniqueidentifier", UniqueIdentifier.ToString()); + writer.WriteEndElement(); + + } + + + public override void Destroy() + { + Network myNet = NB.GetNetwork(); + if (myNet != null) + { + myNet.MarkAsUnlinked(SrcNic, GetUniqueIdentifier); + myNet.MarkAsUnlinked(DstNic, GetUniqueIdentifier); + } + } + + public bool IsSource(int ID) + { + if (SrcNic.HostID == ID) + return true; + else return false; + } + public bool IsDest(int ID) + { + if (DstNic.HostID == ID) + return true; + else return false; + } + //Have func to verify both ends are powered on + public bool isLive() + { + return false; + } + + /// + /// Check to see if the link is connected to the specified nic at either end + /// + /// The unique identifier of the link + /// True if it has it + public bool HasLink(HostNicID toFind) + { + if (SrcNic.Equals(toFind) || DstNic.Equals(toFind)) + return true; + return false; + } + + + public override void Print(Image BaseImage, bool DrawTitle) + { + //Find the XY of the connected items + Network myNet = NB.GetNetwork(); + NetworkDevice Src = myNet.HostMatchingHostNicID(SrcNic); + NetworkDevice Dst = myNet.HostMatchingHostNicID(DstNic); + //Draw a line between them + if (Src == null || Dst == null) return; + + Point sPoint = Src.GetCenter(); + Point dPoint = Dst.GetCenter(); + Pen tPen = new Pen(Color.Black, 4); + Graphics.FromImage(BaseImage).DrawLine(tPen,sPoint,dPoint); + IsDirty = false; //we have printed, we are no longer dirty. + } + + public Point PositionOnLine(nb_direction direction, int Percentage) + { + Network myNet = NB.GetNetwork(); + if(Percentage < 0) Percentage =0; + if(Percentage > 100) Percentage = 100; + NetworkDevice Src = myNet.HostMatchingHostNicID(SrcNic); + NetworkDevice Dst = myNet.HostMatchingHostNicID(DstNic); + //Draw a line between them + if (Src == null || Dst == null) + return new Point(-1,-1); + + Point sPoint = Src.GetCenter(); + Point dPoint = Dst.GetCenter(); + + double deltax = (sPoint.X - dPoint.X) / 100.0; + double deltay = (sPoint.Y - dPoint.Y) / 100.0; + //wearehere; //We need to start at an end. (we need to add sPoint.x, spoint.y depending on which dir we are going) + Point answer; + if(direction == nb_direction.to_dst) + answer = new Point(sPoint.X-(int)(deltax * Percentage), sPoint.Y-(int)(deltay * Percentage)); + else + answer = new Point((int)(deltax * Percentage) + dPoint.X, (int)(deltay * Percentage) + dPoint.Y); + return answer; + } + + public List UsedNicIDStrings() + { + List usedLinks = new List(); + //If the nic is a wireless end point, we should not count it. We can have multiple Nics linked to one AP + usedLinks.Add(SrcNic.HostNicIDString); + usedLinks.Add(DstNic.HostNicIDString); + return usedLinks; + } + + /// + /// Have the packet traverse the network + /// + /// + public override void DoMoving(Packet tPacket) + { + NetworkDevice movingTo = null; + Network myNet = NB.GetNetwork(); + HostNicID target; + tPacket.IncrementDistance(); + if(theLinkType == LinkType.broken && tPacket.myLinkPercent > 50) + { + //The link is broken. Drop the packet + tPacket.Tracking.AddMessage(DebugLevel.info, this, "The packet tried to use a broken network wire and was corrupted."); + tPacket.Tracking.Status = "The packet got corrupted and was dropped."; + tPacket.MyStatus = PacketStatus.finished_failed; + } + if(tPacket.Arrived()) + { + //We need to pass it to the recieving device + if (tPacket.myDirection == nb_direction.to_dst) + { + movingTo= myNet.GetDeviceFromID(DstNic.HostID); + target = DstNic; + } + else + { + movingTo = myNet.GetDeviceFromID(SrcNic.HostID); + target = SrcNic; + } + if(movingTo == null) + { + tPacket.AddMessage(DebugLevel.info, "Oops! We do not have anything at the end of the network wire. This should not happen!"); + tPacket.Tracking.Status = hostname + " Nothing at far end of the wire. This should never happen.."; + tPacket.MyStatus = PacketStatus.finished_failed; + } + else + { + movingTo.DoInputFromLink(tPacket, target); + } + } + } + + } +} diff --git a/EduNetworkBuilder/OptionsWindow.cs b/EduNetworkBuilder/OptionsWindow.cs new file mode 100644 index 0000000..7854747 --- /dev/null +++ b/EduNetworkBuilder/OptionsWindow.cs @@ -0,0 +1,347 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Globalization; +using System.Resources; + + +namespace EduNetworkBuilder +{ + public partial class OptionsWindow : Form + { + private Network myNet; + private ToolTip myToolTip = new ToolTip(); + Form QuestionForm = new Form(); + + private OptionsWindow() + { + InitializeComponent(); + } + + public OptionsWindow(Network theNet) + { + myNet = theNet; + InitializeComponent(); + myToolTip.SetToolTip(tbItemSize, "The size of an item (switch, PC, etc). Default is 100."); + myToolTip.SetToolTip(lblItemSize, "The size of an item (switch, PC, etc). Default is 100."); + myToolTip.SetToolTip(tbMessage, "The message given when the network is loaded. Instructions."); + myToolTip.SetToolTip(lblNetMessage, "The message given when the network is loaded. Instructions."); + myToolTip.SetToolTip(tbNetworkTitle, "The title of the network window."); + myToolTip.SetToolTip(lblNetTitle, "The title of the network window."); + myToolTip.SetToolTip(lblNetSize, "The height and width of the network graphics area."); + myToolTip.SetToolTip(tbNetworkX, "The width of the network window graphics area."); + myToolTip.SetToolTip(tbNetworkY, "The Height of the network window graphics area."); + myToolTip.SetToolTip(lbTags, "The Tags that this puzzle is saved as (only for puzzles)"); + myToolTip.SetToolTip(lblTags, "The Tags that this puzzle is saved as (only for puzzles)"); + myToolTip.SetToolTip(lbTests, "The things that need to be solved before the puzzle is completed."); + myToolTip.SetToolTip(lblTests, "The things that need to be solved before the puzzle is completed."); + myToolTip.SetToolTip(lblLevel, "The Level that this puzzle is stored in."); + myToolTip.SetToolTip(tbLevel, "The Level that this puzzle is stored in."); + myToolTip.SetToolTip(lblSortOrder, "How this is sorted within the list of puzzles."); + myToolTip.SetToolTip(tbSortOrder, "How this is sorted within the list of puzzles."); + + LoadValuesFromNetwork(); + } + + private void LanguagifyComponents() + { + ResourceManager RM = NB.GetResource(); + CultureInfo CI = NB.GetCulture(); + Text = NB.Translate("OW_btnDone"); + Text = NB.Translate("OW_lblNetTitle"); + Text = NB.Translate("OW_cbDisplayTitles"); + Text = NB.Translate("OW_lblNetSize"); + Text = NB.Translate("OW_lblItemSize"); + Text = NB.Translate("OW_lblNetMessage"); + Text = NB.Translate("OW_lblTests"); + Text = NB.Translate("OW_lblTags"); + Text = NB.Translate("OW_lblLevel"); + Text = NB.Translate("OW_lblSortOrder"); + Text = NB.Translate("OW_lblStartingHelp"); + Text = NB.Translate("OW_Form"); + } + + + private void LoadValuesFromNetwork() + { + tbItemSize.Text = myNet.itemsize.ToString(); + tbMessage.Text = myNet.NetMessage; + tbNetworkTitle.Text = myNet.NetTitle; + cbDisplayTitles.Checked = myNet.ShowLabels; + tbNetworkX.Text = myNet.myWidth.ToString(); + tbNetworkY.Text = myNet.myHeight.ToString(); + tbLevel.Text = myNet.Level.ToString(); + tbSortOrder.Text = myNet.SortOrder.ToString("00.000"); + + lbTests.Items.Clear(); + string what; + foreach(NetTest NT in myNet.NetTests) + { + what = NT.GetDescription(NetTestVerbosity.full); + if (what != "") + { + lbTests.Items.Add(what); + } + } + lbTags.Items.Clear(); + myNet.Tags.Sort(); + foreach (string tag in myNet.Tags) + { + lbTags.Items.Add(tag); + } + cbStartingHelpLevel.Items.Clear(); + foreach (string helplevel in Enum.GetNames(typeof(NetTestVerbosity))) + { + cbStartingHelpLevel.Items.Add(helplevel); + } + cbStartingHelpLevel.SelectedItem = myNet.StartingHelpLevel.ToString(); + + } + + private void SaveValuesToNetwork() + { + int.TryParse(tbItemSize.Text, out myNet.itemsize); + myNet.NetMessage = tbMessage.Text; + myNet.NetTitle = tbNetworkTitle.Text; + myNet.ShowLabels = cbDisplayTitles.Checked; + int.TryParse(tbNetworkX.Text, out myNet.myWidth); + int.TryParse(tbNetworkY.Text, out myNet.myHeight); + myNet.InvalidateEverything(); + int.TryParse(tbLevel.Text, out myNet.Level); + double.TryParse(tbSortOrder.Text, out myNet.SortOrder); + myNet.StartingHelpLevel = NB.ParseEnum(cbStartingHelpLevel.SelectedItem.ToString()); + } + + private void btnDone_Click(object sender, EventArgs e) + { + SaveValuesToNetwork(); + Close(); + } + + private void lbTests_MouseDoubleClick(object sender, MouseEventArgs e) + { + //if left-click. + //if on an item, edit it + //if not on an item, make a new one and edit it + NetTest NT; + SaveValuesToNetwork(); + if(lbTests.SelectedIndex != -1) + { + //Something is selected. Edit it + NT = myNet.NetTests[lbTests.SelectedIndex]; + NT.Edit(); + } + else + { + //nothing is selected, create new one + NT = new NetTest("", "", NetTestType.NeedsDefaultGW); + if(NT.Edit()) + { + //Returns true. Something was changed. Save it. + myNet.NetTests.Add(NT); + } + } + LoadValuesFromNetwork(); + } + + private void lbTests_Edit_Click(object sender, EventArgs e) + { + lbTests_MouseDoubleClick(sender, null); + } + + private void lbTests_Add_Click(object sender, EventArgs e) + { + lbTests.SelectedIndex = -1; + lbTests_MouseDoubleClick(sender, null); + } + + private void lbTests_Delete_Click(object sender, EventArgs e) + { + if (lbTests.SelectedIndex >= lbTests.Items.Count) return; + if (lbTests.SelectedIndex < 0 ) return; + SaveValuesToNetwork(); + myNet.NetTests.RemoveAt(lbTests.SelectedIndex); + LoadValuesFromNetwork(); + } + + private void lbTests_MouseClick(object sender, MouseEventArgs e) + { + //see if it is right-click + // Add, delete, edit + int index = 0; + if(e.Button == MouseButtons.Right) + { + if (lbTests.ContextMenuStrip == null) + { + lbTests.ContextMenuStrip = new ContextMenuStrip(); + } + lbTests.ContextMenuStrip.Items.Clear(); + lbTests.ContextMenuStrip.Items.Add("Add"); + lbTests.ContextMenuStrip.Items[index++].Click += lbTests_Add_Click; + lbTests.ContextMenuStrip.Items.Add("Edit"); + lbTests.ContextMenuStrip.Items[index++].Click += lbTests_Edit_Click; + lbTests.ContextMenuStrip.Items.Add("Delete"); + lbTests.ContextMenuStrip.Items[index++].Click += lbTests_Delete_Click; + } + } + + private void lbTests_MouseDown(object sender, MouseEventArgs e) + { + //see if it is right-click + // Add, delete, edit + int index = 0; + if (e.Button == MouseButtons.Right) + { + if (lbTests.ContextMenuStrip == null) + { + lbTests.ContextMenuStrip = new ContextMenuStrip(); + } + lbTests.ContextMenuStrip.Items.Clear(); + lbTests.ContextMenuStrip.Items.Add("Add"); + lbTests.ContextMenuStrip.Items[index++].Click += lbTests_Add_Click; + lbTests.ContextMenuStrip.Items.Add("Edit"); + lbTests.ContextMenuStrip.Items[index++].Click += lbTests_Edit_Click; + lbTests.ContextMenuStrip.Items.Add("Delete"); + lbTests.ContextMenuStrip.Items[index++].Click += lbTests_Delete_Click; + } + } + + + /*******************************************************/ + /******* STUFF FOR TAGS *******************************/ + private void lbTags_Edit_Click(object sender, EventArgs e) + { + lbTags_MouseDoubleClick(sender, null); + } + private void lbTags_Add_Click(object sender, EventArgs e) + { + lbTags.ClearSelected(); + lbTags_MouseDoubleClick(sender, null); + } + + private void lbTags_Delete_Click(object sender, EventArgs e) + { + if (lbTags.SelectedIndex >= lbTags.Items.Count) return; + if (lbTags.SelectedIndex < 0) return; + SaveValuesToNetwork(); + myNet.Tags.RemoveAt(lbTags.SelectedIndex); + LoadValuesFromNetwork(); + } + + private void lbTags_MouseDown(object sender, MouseEventArgs e) + { + //see if it is right-click + // Add, delete, edit + int index = 0; + if (e.Button == MouseButtons.Right) + { + if (lbTags.ContextMenuStrip == null) + { + lbTags.ContextMenuStrip = new ContextMenuStrip(); + } + lbTags.ContextMenuStrip.Items.Clear(); + lbTags.ContextMenuStrip.Items.Add("Add"); + lbTags.ContextMenuStrip.Items[index++].Click += lbTags_Add_Click; + if (lbTags.SelectedIndex != -1) + { + lbTags.ContextMenuStrip.Items.Add("Edit"); + lbTags.ContextMenuStrip.Items[index++].Click += lbTags_Edit_Click; + lbTags.ContextMenuStrip.Items.Add("Delete"); + lbTags.ContextMenuStrip.Items[index++].Click += lbTags_Delete_Click; + } + } + + } + + private string QuickPrompt(string title, string prompt, string value) + { + + QuestionForm.Text = title; + Label lbPrompt = new Label(); + lbPrompt.Text = prompt; + lbPrompt.Location = new Point(1, 1); + lbPrompt.Size = new Size(200, lbPrompt.Size.Height); + + TextBox Choice = new TextBox(); + Choice.Text = value; + + Choice.Location = new Point(1, lbPrompt.Location.Y + lbPrompt.Height + 5); + + Button Done = new Button(); + Done.Click += btnClose_Click; + Done.Text = "Done"; + Done.Location = new Point(1, Choice.Location.Y + Choice.Height + 5); + QuestionForm.Controls.Clear(); + QuestionForm.Controls.Add(Choice); + QuestionForm.Controls.Add(Done); + QuestionForm.Controls.Add(lbPrompt); + QuestionForm.AcceptButton = Done; + QuestionForm.FormBorderStyle = FormBorderStyle.FixedDialog; + QuestionForm.AutoSize = true; + QuestionForm.Height = Done.Location.Y + Done.Height + 5; //This is too small for the form, it autosizes to "big enough" + QuestionForm.Width = Choice.Location.X + Choice.Width + 5; + QuestionForm.ShowDialog(); + return Choice.Text; + } + + private void btnClose_Click(object sender, EventArgs e) + { + if (QuestionForm != null) + QuestionForm.Close(); + } + + + private void lbTags_MouseDoubleClick(object sender, MouseEventArgs e) + { + //if left-click. + //if on an item, edit it + //if not on an item, make a new one and edit it + SaveValuesToNetwork(); + string newstring; + if (lbTags.SelectedIndex != -1) + { + //Something is selected. Edit it + newstring = QuickPrompt("Edit Tag", "Tag:", myNet.Tags[lbTags.SelectedIndex]); + if (newstring != "") + { + myNet.Tags[lbTags.SelectedIndex] = newstring; + } + else + { + myNet.Tags.RemoveAt(lbTags.SelectedIndex); + } + } + else + { + //nothing is selected, create new one + newstring = QuickPrompt("Edit Tag", "Tag:", ""); + if (newstring != "") + { + myNet.Tags.Add(newstring); + } + } + LoadValuesFromNetwork(); + + } + + private void tbSortOrder_Validating(object sender, CancelEventArgs e) + { + double value; + double.TryParse(tbSortOrder.Text, out value); + tbSortOrder.Text = value.ToString("00.000"); + } + + private void tbLevel_Validating(object sender, CancelEventArgs e) + { + int value; + int.TryParse(tbLevel.Text, out value); + tbLevel.Text = value.ToString(); + } + } +} diff --git a/EduNetworkBuilder/Packet.cs b/EduNetworkBuilder/Packet.cs new file mode 100644 index 0000000..a329674 --- /dev/null +++ b/EduNetworkBuilder/Packet.cs @@ -0,0 +1,456 @@ +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_failed || _MyStatus == PacketStatus.finished_ok) + { + string status = _MyStatus.ToString(); + PacketDump(" " + status, DebugPausePoint.packet_kill); + } + if (_MyStatus == PacketStatus.finished_ok) + Tracking.Finished = true; + } + } + public int TTL = 20; + public int TickTTL = 50; + public IPAddress sourceIP; + public IPAddress OriginalDestIP; + public IPAddress TsourceIP; + 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 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 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; + StartTime = copyfrom.StartTime; + OriginalDestIP = copyfrom.OriginalDestIP; + Tracking.AddMessage(DebugLevel.debug, WhereAmI, "Packet duplicated"); + } + + //Generate a packet with the given payload. + public Packet(NetworkComponent start, string source, string dest, string payload, PacketType theType) + { + 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() + "Packet Created"); + Tracking.AddMessage(DebugLevel.routing, start, " MAC:" + 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, "Packet Created"); + Tracking.AddMessage(DebugLevel.routing, start, " IP:" + source + " -> " + dest); + Tracking.AddMessage(DebugLevel.debug, start, " IPs Translated to" + sourceIP.GetIP.ToIpString() + " -> " + destIP.GetIP.ToIpString()); + } + isFresh = true; + } + + public Packet(NetworkComponent start, IPAddress dest, string payload, PacketType theType) + { + WhereAmI = start; + payloadData = payload; + MyType = theType; + 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, "Packet Created"); + Tracking.AddMessage(DebugLevel.routing, start, " IP:" + sourceIP.GetIP.ToIpString() + " -> " + dest.GetIP.ToIpString()); + } + else + { + sourceIP = new IPAddress(NB.ZeroIPString); + destMAC = NB.BroadcastMACString; + destIP = dest; + Tracking.AddMessage(DebugLevel.info, start, "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; + } + Pen myPen = new Pen(pencolor, NB.PacketPixelSize); + Graphics.FromImage(BaseImage).DrawEllipse(myPen, 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, "Unable to find a mac address for the IP address: " + dest.GetIP.ToIpString()); + Tracking.Status = WhereAmI.hostname + " Failed: Unable to find a MAC address for the specified IP."; + MyStatus = PacketStatus.finished_failed; + } + return; + } + } + break; + } + } + + private void DoMainProcessing() + { + //We pass it to the device + if (WhereAmI == null) + { + AddMessage(DebugLevel.debug, "The packet was dropped because we lost where it was. WhereAmI == null!"); + Tracking.Status = "NO_Host" + " Lost location of packet.."; + 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, "The packet was dropped because we lost where it was. WhereAmI == null!"); + Tracking.Status = "NO_Host" + " Lost location of packet.."; + 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, "The packet was dropped because we lost where it was. WhereAmI == null!"); + Tracking.Status = "NO_Host" + " Lost location of packet.."; + 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) + { + WhereAmI = 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; + AddMessage(DebugLevel.debug, " Starting on link"); + } + + 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, "Packet", "Packet failed to reach any IP. No such IP on network: " + destIP.GetIPString); + Tracking.Status = "Packet failed to reach IP: " + destIP.GetIPString; + MyStatus = PacketStatus.finished_failed; + } + 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 (MyStatus != PacketStatus.finished) + myNet.AddMessage(Tracking); //We only store finished_failed, and finished_ok + } + } + + 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(hostname + ": " + MyType.ToString()); + Console.Write(hostname + ": " + position + " PACKET: dstIP:" + dIP); + Console.WriteLine(" dstMAC:" + destMAC); + Console.Write(hostname + ": " + position + " PACKET: srcIP:" + sIP); + Console.WriteLine(" srcMAC:" + sourceMAC); + Console.WriteLine("---"); + } + AddMessage(DebugLevel.packet, hostname + ": " + position + " PACKET: dstIP:" + dIP + " dstMAC:" + destMAC); + AddMessage(DebugLevel.packet, hostname + ": " + position + " PACKET: srcIP:" + sIP + " srcMAC:" + sourceMAC); + } + + public static T Clone(T source) + { + if (!typeof(T).IsSerializable) + { + throw new ArgumentException("The type must be serializable.", "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); + } + } + } +} diff --git a/EduNetworkBuilder/PacketMessage.cs b/EduNetworkBuilder/PacketMessage.cs new file mode 100644 index 0000000..62d57c2 --- /dev/null +++ b/EduNetworkBuilder/PacketMessage.cs @@ -0,0 +1,110 @@ +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; + +namespace EduNetworkBuilder +{ + /// + /// This tracks everything that happened to a packet in transit + /// + /// + [Serializable] + public struct DebugMessage + { + public DebugLevel WhatLevel; + public string HostName; + public string Message; + public DebugMessage(DebugLevel tLevel, string tHost, string tMessage) + { + WhatLevel = tLevel; + HostName = tHost; + Message = tMessage; + } + } + + [Serializable] + public class PacketMessage + { + List Messages = new List(); + public string _Status = ""; //Usually "success" or "failed" + public bool Finished = false; + public TimeSpan duration; + public string Status + { + get { return _Status; } + set { if (!Finished) _Status = value; } + } + + public static T Clone(T source) + { + if (!typeof(T).IsSerializable) + { + throw new ArgumentException("The type must be serializable.", "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); + } + } + + + + public void AddMessage(DebugLevel tLevel, string tHost, string tMessage) + { + if(!Finished) + Messages.Add(new DebugMessage(tLevel, tHost, tMessage)); + } + + public void AddMessage(DebugLevel tLevel, NetworkComponent tHost, string tMessage) + { + string host = "unknown"; + if (tHost != null) + host = tHost.hostname; + if(! Finished) + Messages.Add(new DebugMessage(tLevel, host, tMessage)); + } + + public List GetMessagesLike(DebugLevel tLevel) + { + List answer = new List(); + string tString; + foreach( DebugMessage tmessage in Messages) + { + if((tmessage.WhatLevel | tLevel) == tLevel) + { + tString = tmessage.HostName + " \t" + tmessage.WhatLevel.ToString() + "\t" + tmessage.Message; + answer.Add(tString); + } + } + return answer; + } + + public List GetMessagesSummary() + { + List answer = new List(); + string tString; + int time = duration.Seconds * 1000 + duration.Milliseconds; + tString = time.ToString() + " ms " + Status; + answer.Add(tString); + return answer; + } + + + } +} diff --git a/EduNetworkBuilder/RTFWindow.cs b/EduNetworkBuilder/RTFWindow.cs new file mode 100644 index 0000000..dbc246f --- /dev/null +++ b/EduNetworkBuilder/RTFWindow.cs @@ -0,0 +1,91 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.IO; +using System.Globalization; +using System.Resources; + + +namespace EduNetworkBuilder +{ + public partial class RTFWindow : Form + { + public RTFWindow() + { + InitializeComponent(); + LanguagifyComponents(); + } + /// + /// Used when viewing help from the ? button. This displays network specific help information + /// + /// + /// + public RTFWindow(string title, string theHelp, List theTests) + { + InitializeComponent(); + LanguagifyComponents(); + BuilderWindow myWin = (BuilderWindow)Application.OpenForms["BuilderWindow"]; + if (myWin != null) + { + StartPosition = FormStartPosition.Manual; + Point newlocation = new Point(myWin.Location.X + myWin.Width + 5, myWin.Location.Y); + if (newlocation.X > (Screen.PrimaryScreen.Bounds.Width + 5)) + { + newlocation = new Point(Screen.PrimaryScreen.Bounds.Width - 5, newlocation.Y); + } + Location = newlocation; + } + System.Drawing.Font currentFont = rtbContent.SelectionFont; + Text = title; + rtbContent.Text = theHelp; + rtbContent.SelectAll(); + rtbContent.SelectionFont = new Font( + currentFont.FontFamily, + currentFont.Size + 2, FontStyle.Regular); + rtbContent.DeselectAll(); + } + public RTFWindow(RTFWindowContents WhatToShow) + { + InitializeComponent(); + LanguagifyComponents(); + string currentDir = Directory.GetCurrentDirectory(); + string myRTF; + if (WhatToShow == RTFWindowContents.help) + { + myRTF = Properties.Resources.Help; + rtbContent.Rtf = myRTF; + } + else if (WhatToShow == RTFWindowContents.about) + { + myRTF = Properties.Resources.about; + rtbContent.Rtf = myRTF; + } + else if (WhatToShow == RTFWindowContents.release_notes) + { + myRTF = Properties.Resources.ReleaseNotes; + rtbContent.Rtf = myRTF; + } + } + + private void LanguagifyComponents() + { + ResourceManager RM = NB.GetResource(); + CultureInfo CI = NB.GetCulture(); + Text = NB.Translate("RTFW_rtbContent"); + Text = NB.Translate("RTFW_btnOK"); + Text = NB.Translate("RTFW_Form"); + } + + private void btnOK_Click(object sender, EventArgs e) + { + Close(); + } + + } +} diff --git a/EduNetworkBuilder/pullLanguageInfo.pl b/EduNetworkBuilder/pullLanguageInfo.pl new file mode 100644 index 0000000..21187ca --- /dev/null +++ b/EduNetworkBuilder/pullLanguageInfo.pl @@ -0,0 +1,107 @@ +#!/bin/perl +# +$filedir="Resources/languages/"; +$langfile="edustrings.resx"; + +sub parse_file +{ + my $filename = "@_"; + my $front = $filename; + my %items; + my $program = $filename; + + $program =~ s/\..*//g; + $front =~ s/\..*//g; + $front =~ s/[a-z]//g; + $front = "${front}_"; + #print "$filename\n"; + #print "$front\n"; + my $count=0; + if ( -f $filename ) + { + open(INFILE, $filename); + while ( ) + { + if(/([^.]*)\.Text = (.*)$/) + { + $var=$1; + $text=$2; + + $var=~ s/ *//g; + if($var eq "this") { $var="Form"}; + $item=$var; + $var="$front$var"; + + $text=~ s/[";]//g; + $text=~ s/\r//g; + $text=~ s/\n//g; + #print "Var: $var Text: $text\n"; + #now we process them. If it does not exist yet, make an entry for it. + if(!exists($existing{$var})) + { + #print("var $key item $items{$key}\n"); + print EDUFILE (' ' . "\r\n"); + printf EDUFILE (' %s%s',$text,"\n"); + printf EDUFILE (' %s%s',"$program $item = $text","\n"); + print EDUFILE (" \n"); + + if($count == 0) + { + print CFILE "$program\n"; + print CFILE "private void LanguagifyComponents() + { + ResourceManager RM = NB.GetResource(); + CultureInfo CI = NB.GetCulture();\n" + } + if($item == "Form") + { + print CFILE ("Text = RM.GetString(\"$var\", CI);\n"); + } + else + { + print CFILE ("$item.Text = RM.GetString(\"$var\", CI);\n"); + } + $count++; + } + } + } + close INFILE; + if($count > 0) + { + print CFILE ("}\n\n"); + } + } + else + { + print "$filename does not exist\n"; + } +} + +#Read the language file to see what already exists. +$tfile="$filedir/$langfile"; +open (IFILE, $tfile) or die "$tfile does not exist."; +while ( ) +{ + if(/data name="([^"]*)"/) + { + $tag=$1; + #print("TAG: $tag\n"); + $existing{$tag}="here"; + } +} +close(IFILE); + +open(EDUFILE, ">add2edustrings.txt"); +open(CFILE, ">add2cfiles.txt"); + +#parse the various Designer files and process them +my @files = glob("*.Designer.cs"); +foreach my $file (@files) +{ + print "$file\n"; + parse_file( $file ); +} + + +close(CFILE); +close(EDUFILE);