diff --git a/EduNetworkBuilder/IPAddress.cs b/EduNetworkBuilder/IPAddress.cs index 3451e5a..42e0d81 100644 --- a/EduNetworkBuilder/IPAddress.cs +++ b/EduNetworkBuilder/IPAddress.cs @@ -242,7 +242,7 @@ namespace EduNetworkBuilder } /// - /// Return the number of hosts in the subnet. + /// Return the list of hosts in the subnet. /// /// public IEnumerable Hosts() diff --git a/EduNetworkBuilder/NBRenumberData.cs b/EduNetworkBuilder/NBRenumberData.cs index d048d67..8399a39 100644 --- a/EduNetworkBuilder/NBRenumberData.cs +++ b/EduNetworkBuilder/NBRenumberData.cs @@ -6,6 +6,180 @@ using System.Threading.Tasks; namespace EduNetworkBuilder { + public class NBRenumberer + { + private bool renumbered = false; + public List ListOfItems = new List(); + + public void Count(string what) + { + NBRenumberData entry = DataFromName(what); + if(entry != null) + { + entry.ActiveCount++; + return; + } + //If we get here, we have not found it yet. + NBRenumberData One = new NBRenumberData(what, ListOfItems.Count); + One.ActiveCount++; + ListOfItems.Add(One); + } + public void SetAsGateway(string what) + { + NBRenumberData GW = DataFromName(what); + if (GW == null) { + GW = new NBRenumberData(what, ListOfItems.Count); + ListOfItems.Add(GW); + } + GW.isTheGateway = true; + GW.UpdateSortOrder(); + //We can only have one gateway. Make sure all the rest are set not to be the GW + foreach(NBRenumberData one in ListOfItems) + { + if (one != GW) { + one.isTheGateway = false; + one.UpdateSortOrder(); + } + + } + } + + public NBRenumberData DataFromName(string hostname) + { + foreach (NBRenumberData NBRD in ListOfItems) + { + if (NBRD.Hostname == hostname) + { + return NBRD; + } + } + return null; + } + + public bool TryRenumbering(NB_IPAddress Network, NB_IPAddress Gateway) + { + renumbered = true; + //Separate out the devices by type + // Find the gateway too + int biggestcount = 0; + int spacing = 10; + bool HasGateway = false; + foreach (NBRenumberData NBRD in ListOfItems) + { + if (NBRD.ActiveCount > biggestcount) biggestcount = NBRD.ActiveCount; + } + //now, we can prune off everything that is not part of biggestcount. + for(int i=ListOfItems.Count-1; i>=0; i--) + { + if (ListOfItems[i].ActiveCount != biggestcount) + ListOfItems.RemoveAt(i); + else + { + if (ListOfItems[i].isTheGateway) HasGateway = true; + ListOfItems[i].SuggestedIP = ""; + } + } + if (!HasGateway) + for (int i = ListOfItems.Count - 1; i >= 0; i--) + { + if (ListOfItems[i].Device.HasIPAddress(Gateway)) + SetAsGateway(ListOfItems[i].Hostname); + } + + int switches = 0; + int servers = 0; + int printers = 0; + int wireless = 0; + int clients = 0; + foreach(NBRenumberData NBRD in ListOfItems) + { + switch(NBRD.TypeString()) + { + case "client": + clients++; + break; + + case "printer": + printers++; + break; + + case "switch": + switches++; + break; + + case "server": + servers++; + break; + case "wireless": + wireless++; + break; + } + } + //Decide on which way we want to do this. + biggestcount = 0; + if (servers > biggestcount) biggestcount = servers; + if (switches > biggestcount) biggestcount = switches; + if (printers > biggestcount) biggestcount = printers; + if (wireless > biggestcount) biggestcount = wireless; + if (clients > biggestcount) biggestcount = clients; + + ListOfItems.Sort((p, q) => p.sortorder.CompareTo(q.sortorder)); + + //If it works to do 10 for each bunch, do that. Otherwise, see what the smallest bunch that works is. + if (biggestcount < 10) + { + spacing = 10; + } + if (biggestcount > 10) + spacing = 99; //Don't bother with anything fancy. Punt if it does not fit the first time + //Fallback is to simply count up from the gateway. + if (Network.NumberOfHosts < ListOfItems.Count) + return false; + if(spacing * 5 > Network.NumberOfHosts) + { + renumberlist(Network, 1, ""); + } + else + { + //We can do this in parts + renumberlist(Network, 1, "Gateway"); + renumberlist(Network, 2, "server"); + renumberlist(Network, spacing * 1, "switch"); + renumberlist(Network, spacing * 2, "wireless"); + renumberlist(Network, spacing * 3, "printer"); + renumberlist(Network, spacing * 4, "client"); + } + return true; + } + + private void renumberlist(NB_IPAddress Network, int Base, string filter) + { + int count = Base; + for (int i = 0; i < ListOfItems.Count; i++) + { + if (ListOfItems[i].SuggestedIP != "") continue; + if (filter == "" || ListOfItems[i].TypeString() == filter || filter == "Gateway" && ListOfItems[i].isTheGateway) + { + NB_IPAddress next = new NB_IPAddress(Network); + next._ip += (UInt32)count; + ListOfItems[i].SuggestedIP = next.GetIPString; + count++; + } + } + } + + public void DoRenumbering(NB_IPAddress Network, NB_IPAddress Gateway, int vlanID) + { + if (!renumbered) TryRenumbering(Network, Gateway); + + //loop through and set all the IPs and the gateway IP if not DHCPS + for(int i = 0; i < ListOfItems.Count; i++) + { + ListOfItems[i].Device.RenumberIP(ListOfItems[i].SuggestedIP, Gateway, vlanID); + } + } + } + public class NBRenumberData { public string Hostname = ""; @@ -19,7 +193,12 @@ namespace EduNetworkBuilder public int ActiveCount=0; public string nicname; public string SuggestedIP; - + public int sortorder = 0; + private int _index = 0; + public NetworkComponentType mytype = NetworkComponentType.none; + + public bool isTheGateway = false; + private bool _isRouter = false; /// /// Return true if the Device specified by hostname does routing. @@ -36,5 +215,79 @@ namespace EduNetworkBuilder return false; } } + + public NBRenumberData(string hostname, int index) + { + Hostname = hostname; + NetworkDevice nd = Device; + mytype = nd.myType; + _index = index; + UpdateSortOrder(); + } + + public void UpdateSortOrder() + { + switch (TypeString()) + { + case "client": + sortorder=5000; + break; + + case "printer": + sortorder = 4000; + break; + + case "switch": + sortorder=2000; + break; + + case "server": + sortorder=1000; + break; + case "wireless": + sortorder=3000; + break; + } + sortorder = sortorder + _index; + if (isTheGateway) sortorder = 0; + } + + public string TypeString() + { + string what = ""; + switch (mytype) + { + case NetworkComponentType.cellphone: + case NetworkComponentType.ip_phone: + case NetworkComponentType.laptop: + case NetworkComponentType.pc: + case NetworkComponentType.tablet: + what = "client"; + break; + + case NetworkComponentType.printer: + case NetworkComponentType.copier: + what = "printer"; + break; + + case NetworkComponentType.net_hub: + case NetworkComponentType.net_switch: + what = "switch"; + break; + + case NetworkComponentType.firewall: + case NetworkComponentType.router: + case NetworkComponentType.server: + what = "server"; + break; + case NetworkComponentType.wap: + case NetworkComponentType.wbridge: + case NetworkComponentType.wrepeater: + case NetworkComponentType.wrouter: + what = "wireless"; + break; + } + return what; + } } } diff --git a/EduNetworkBuilder/NetworkBuilder.cs b/EduNetworkBuilder/NetworkBuilder.cs index 45b93bb..0967b0d 100644 --- a/EduNetworkBuilder/NetworkBuilder.cs +++ b/EduNetworkBuilder/NetworkBuilder.cs @@ -1155,6 +1155,13 @@ namespace EduNetworkBuilder //do it if (ItemsSelected.Count > 0) { + //This next entry should never happen. + if (ItemsSelected.Count < 2) + { + MessageBox.Show("You need to have more items selected"); + return; + } + int ChosenVlanID = 1; if(myNetwork != null && myNetwork.VLANsEnabled) { @@ -1177,13 +1184,6 @@ namespace EduNetworkBuilder IPAddressEntry IPE = new IPAddressEntry(prompted, null, this, false); - //This next entry should never happen. - if (ItemsSelected.Count < 2) - { - MessageBox.Show("You need to have more items selected"); - return; - } - //Read in the settings we will use IPE.ShowAsSubnetGateway(); @@ -1222,10 +1222,59 @@ namespace EduNetworkBuilder } if (gwDevice == null) return; //No gateway device selected + + NBRenumberer Renumberer = new NBRenumberer(); + //If we get here, we have a gateway and a list of items to renumber. - for (int i = ItemsSelected.Count - 1; i >= 0; i--) + //Loop through all the items + //Find find all connected items + //loop through all connected items & count them (excluding them if they are not selected) + //set the gateway. + //count them and exclude items that are not within the threshhold. + + foreach(NetworkDevice one in ItemsSelected) { + List alreadydone = new List(); + List connections = one.ConnectedTo(); + + for(int i=0; i< connections.Count; i++) + { + NetworkDevice connection = connections[i]; + //If we have not done it yet + if (!ItemsSelected.Contains(connection)) + continue; + if (myNetwork.VLANsEnabled && (ChosenVlanID != connection.PrimaryVLAN() && connection.myType != NetworkComponentType.net_switch)) + continue; //Skip the device if it is not on the primary vlan, and is not a switch (asuming switches are taggexd) + if (!alreadydone.Contains(connection)) + { + alreadydone.Add(connection); + + if(!connection.RoutesPackets() || connection.myType == NetworkComponentType.wrouter) + connections.AddRange(connection.ConnectedTo(true)); + Renumberer.Count(connection.hostname); + } + } } + Renumberer.SetAsGateway(gwDevice.hostname); + + Renumberer.TryRenumbering(network, gw); + + if (Renumberer.ListOfItems.Count > network.NumberOfHosts) + { + //Not enough room in the subnet for the various items. + MessageBox.Show("There are not enough IP addresses in the subnet you specified for the number of items we need to renumber."); + return; + } + + //We should print off the things we are hoping to do. + string message = "What we are trying to do:\n"; + foreach(NBRenumberData NBRD in Renumberer.ListOfItems) + { + message += NBRD.Hostname + " " + NBRD.TypeString() + " -> " + NBRD.SuggestedIP + "\n"; + } + DialogResult answer = MessageBox.Show(message,"Renumber?",MessageBoxButtons.OKCancel); + if (answer == DialogResult.OK) + Renumberer.DoRenumbering(network, gw, ChosenVlanID); } } diff --git a/EduNetworkBuilder/NetworkDevice.cs b/EduNetworkBuilder/NetworkDevice.cs index ef620f2..9ee8e88 100644 --- a/EduNetworkBuilder/NetworkDevice.cs +++ b/EduNetworkBuilder/NetworkDevice.cs @@ -658,14 +658,19 @@ namespace EduNetworkBuilder /// /// Return the list of devices connected to this device /// - /// A list of devices - List ConnectedTo() + /// For routers, do not show things connected on the WAN + /// A list of devices + public List ConnectedTo(bool skipwan= false) { List connected = new List(); foreach (NetworkCard nic in NICs) { - NetworkDevice nd = ConnectedTo(nic); - if (nd != null) connected.Add(nd); + //We want to skip connections through the wan when searching a broadcast network + if (!(myType == NetworkComponentType.wrouter && skipwan && nic.GetNicType == NicType.wan)) + { + NetworkDevice nd = ConnectedTo(nic); + if (nd != null) connected.Add(nd); + } } return connected; } @@ -675,7 +680,7 @@ namespace EduNetworkBuilder /// /// /// - NetworkDevice ConnectedTo(NetworkCard NIC) + public NetworkDevice ConnectedTo(NetworkCard NIC) { return NIC.ConnectedTo(); } @@ -684,7 +689,7 @@ namespace EduNetworkBuilder /// /// the network card ID /// - NetworkDevice ConnectedTo(HostNicID NIC) + public NetworkDevice ConnectedTo(HostNicID NIC) { NetworkCard nic = NicFromID(NIC); if (nic == null) return null; @@ -695,15 +700,16 @@ namespace EduNetworkBuilder /// /// The network card name /// - NetworkDevice ConnectedTo(string nicname) + public NetworkDevice ConnectedTo(string nicname) { NetworkCard nic = NicFromName(nicname); if (nic == null) return null; return nic.ConnectedTo(); } - public int VLANFromNIF(NetworkInterface nif) + public int VLANFromNIF(NetworkInterface nif, int level = 0) { + level++; if (DoesVLANs()) { //This device itself does vlans @@ -716,17 +722,21 @@ namespace EduNetworkBuilder if (nif == null) return NB.InvalidVLAN; NetworkCard nic = NicFromID(nif.AttachedToHostNic); if (nic == null) return NB.InvalidVLAN; //Nothing - return VLANFromNIC(nic); + if (level > 5) return NB.InvalidVLAN; + return VLANFromNIC(nic, level); } - public int VLANFromNIC(NetworkCard nic) + public int VLANFromNIC(NetworkCard nic, int level=0) { + level++; int vlan = NB.InvalidVLAN; if (DoesVLANs()) { foreach (NetworkInterface nif in nic.interfaces) { - int tvlan = VLANFromNIF(nif); + int tvlan = NB.InvalidVLAN; + if(DoesVLANs()) + tvlan = VLANFromNIF(nif, level); if (tvlan != NB.InvalidVLAN) { if (vlan != NB.InvalidVLAN && vlan != tvlan) @@ -1358,6 +1368,38 @@ namespace EduNetworkBuilder return null; } + public bool RenumberIP(string newip, NB_IPAddress gateway, int vlanID) + { + DefaultGW = new NB_IPAddress(gateway); + //figure out which interface to change. + + if (!RenumberIP(newip, gateway, NicType.management_interface, vlanID)) + if (!RenumberIP(newip, gateway, NicType.eth, vlanID)) + return RenumberIP(newip, gateway, NicType.wlan, vlanID); + return true; + } + + private bool RenumberIP(string newip, NB_IPAddress gateway, NicType what, int vlan) + { + List smalllist = NICsFromTypeNic(what); + smalllist.Sort((p, q) => p._nic_name.CompareTo(q._nic_name)); + foreach (NetworkCard nic in smalllist) + { + //see if we can renumber this one + //It cannot be dhcp, and must be connected. + if((!nic.UsesDHCP && nic.isConnected(false)) || nic.GetNicType == NicType.management_interface) + { + //If we are doing vlans, the vlan should match the interface if eth + //If we are doing vlans, the vlan should match if we are doing management interface + // + //right now, just do it. + nic.PrimaryInterface().myIP = new NB_IPAddress(newip, gateway._mask.ToIpString(), IPAddressType.ip); + return true; + } + } + return false; + } + public NetworkCard NicFromIP(string IP) { foreach (NetworkCard nic in NICs)