using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; using System.Text.RegularExpressions; namespace EduNetworkBuilder { [Serializable] public class NetworkInterface { public IPAddress myIP; public string nic_name; //eth0, eth0:0, etc public HostNicID AttachedToHostNic; public List VLANs = new List() { new VLANInfo(1, VLANTagType.Untagged ) }; //We should have a feature: none, IP_in_IP_Tunnel, encrypted_vpn, vlan, etc public NetworkInterface(string name, string IP, string Mask, HostNicID AttachedTo) { nic_name = name; myIP = new IPAddress(IP, Mask,IPAddressType.ip); AttachedToHostNic = AttachedTo; } public NetworkInterface(XmlNode theNode, HostNicID AttachedTo) { AttachedToHostNic = AttachedTo; foreach (XmlNode Individual in theNode.ChildNodes) { XmlNodeType myNodetype = Individual.NodeType; if (myNodetype == XmlNodeType.Element) { switch (Individual.Name.ToLower()) { case "myip": myIP = new IPAddress(Individual); break; case "nicname": nic_name = Individual.InnerText; break; case "vlan": if (Individual.Attributes != null && Individual.Attributes["ID"] != null) { int ID; VLANTagType Tag = NB.TryParseEnum(Individual.InnerText, VLANTagType.Untagged); int.TryParse(Individual.Attributes["ID"].Value, out ID); VLANInfo current = GetVLANInfo(ID); if (current != null) VLANs.Remove(current); //we are replacing it VLANs.Add(new VLANInfo(ID, Tag)); } break; } } } } public VLANInfo GetVLANInfo(int id) { foreach(VLANInfo one in VLANs) { if (one.ID == id) return one; } return null; } public VLANTagType GetVLANTag(int id) { VLANInfo vli = GetVLANInfo(id); if (vli != null) return vli.Tag; return VLANTagType.Forbidden; //if not defined, it is forbidden } public int GetNonForbiddenVLANID() { foreach(VLANInfo vin in VLANs) { if (vin.Tag != VLANTagType.Forbidden) return vin.ID; } return -999; } public void SetVLANTag(int id, VLANTagType Tag) { bool foundit = false; Network theNet = NB.GetNetwork(); if (theNet == null) return; NetworkDevice ND = theNet.GetDeviceFromID(AttachedToHostNic); if (ND == null) return; NetworkCard NC = ND.NicFromID(AttachedToHostNic); if (NC == null) return; NicType NT = NC.GetNicType; bool isPort = NT == NicType.port; //Ports (switches) can have multiple tagged ports. //WAN, ETH0, etc, can only have one tagged or untagged per interface //nothing can have multiple untagged ports // If something is untagged, everything else is forbidden foreach (VLANInfo one in VLANs) { if (one.ID == id) { one.Tag = Tag; foundit = true; } else { if (Tag == VLANTagType.Untagged) one.Tag = VLANTagType.Forbidden; //Only one untagged port allowed at a time if (Tag == VLANTagType.Tagged && !isPort) //Ports can have multiple tags on one interface one.Tag = VLANTagType.Forbidden; if (Tag == VLANTagType.Tagged && isPort) { if(one.Tag != VLANTagType.Tagged) one.Tag = VLANTagType.Forbidden; //We cannot have an untagged port and tagged ports at the same time } } } if (!foundit) VLANs.Add(new VLANInfo(id, Tag)); } public void Save(XmlWriter writer) { writer.WriteStartElement("interface"); writer.WriteElementString("nicname", nic_name); myIP.Save(writer, "myip"); foreach (VLANInfo one in VLANs) { writer.WriteStartElement("VLAN"); writer.WriteAttributeString("ID", one.ID.ToString()); writer.WriteString(one.Tag.ToString()); writer.WriteEndElement(); } writer.WriteEndElement(); } public string InterfaceString(bool UseCidr = false) { string tstring = myIP.GetIP.ToIpString(); if (!UseCidr) { tstring += " - " + myIP.GetMask.ToIpString(); } else { string mask = myIP.GetMask.ToBitString(); mask = Regex.Replace(mask, "0", ""); int count = mask.Length; tstring += "/" + count.ToString(); } return tstring; } public string RouteString(string nic_name, string GW) { string tstring = myIP.IPFormat(GW); ; return tstring; } /// /// Pop up a window to edit this address. /// public void EditAddress() { Network myNet = NB.GetNetwork(); NetworkDevice ND = myNet.GetDeviceFromID(AttachedToHostNic); IPAddressEntry ipe = new IPAddressEntry(myIP,ND); ipe.ShowDialog(); } public bool isLocal(IPAddress tIp, bool AllowZeroMatch = true) { if (tIp == null) return false; if (!AllowZeroMatch && (myIP == null || myIP.GetIP == 0)) return false; if (myIP.IsLocal(tIp)) return true; return false; } /// /// We are sending the packet out this interface. /// /// public void ProcessOutboundPacket(Packet tPacket) { //tPacket.InboundInterface = null; //forget the interface we had come in on now that we are leaving. //if (tPacket.sourceIP == null || tPacket.sourceIP.GetIP.ToIpString() == NB.ZeroIPString) //{ // //This happens if we are starting a new packet. We should also do this if we are masquerading. // tPacket.sourceIP = new IPAddress(myIP.GetIP.ToIpString(), "", IPAddressType.ip_only); //We only want the IP address //} //VLAN stuff VLANInfo VI = OutgoingVLAN(tPacket.VLANID); VLANTagType What = VI.Tag; Network theNet = NB.GetNetwork(); NetworkDevice HD = theNet.GetDeviceFromID(AttachedToHostNic); if (HD == null) return; //Oops! Something went wrong. string hostname = HD.hostname; //added to fix the issue with vpns and pings - 11-09-2016 //Only do this on non-ports? NetworkCard nic = HD.NicFromID(AttachedToHostNic); if(nic != null && nic.GetNicType != NicType.port && nic.GetNicType != NicType.wport) tPacket.TsourceIP = myIP; if(tPacket.TsourceIP == null || tPacket.TsourceIP.GetIPString == NB.ZeroIPString) tPacket.TsourceIP = myIP; if (What == VLANTagType.Forbidden) { //we drop it silently //Console.WriteLine(" -- Forbidding outbound packet. " + tPacket.VLANID + " " + HD.hostname + " " + VI.ID); string errString = string.Format(NB.Translate("NI_VLANOut"), hostname, tPacket.destIP.GetIPString); tPacket.AddMessage(DebugLevel.switching, errString); tPacket.Tracking.Status = errString; tPacket.MyStatus = PacketStatus.finished_ok; return; } if(What == VLANTagType.Untagged) { //We strip off the tagging tPacket.VLANID = NB.UntaggedVLAN; //set to the default vlan } if(What == VLANTagType.Tagged) { //We actually do not do anything. The tag remains intact. tPacket.VLANID = VI.ID; } } private VLANInfo IncomingVLAN(int ID) { //Search through incoming vlan stuff to find the right one //If the packet is tagged with the ID, and the port is tagged, return that //If the packet is untagged, return the one that is untagged VLANInfo newVLANinfo = null; if (ID != NB.UntaggedVLAN) //It is tagged { foreach(VLANInfo vi in VLANs) { if (vi.ID == ID) { //if (vi.Tag == VLANTagType.Forbidden) // Console.WriteLine(" About to be forbidden."); return vi; } } //We do not have one set yet. Add a new one newVLANinfo = new VLANInfo(ID, VLANTagType.Forbidden); //Console.WriteLine(" Creating forbidden vlan - " + ID); VLANs.Add(newVLANinfo); return newVLANinfo; } else //the packet is untagged. { foreach (VLANInfo vi in VLANs) { if (vi.Tag == VLANTagType.Untagged) return vi; } //We do not have an "untagged" vlan. Return the settings for vlan1 foreach (VLANInfo vi in VLANs) { if (vi.ID == 1) return vi; } } //We should never get here. This is just a fall-through newVLANinfo = new VLANInfo(ID, VLANTagType.Forbidden); VLANs.Add(newVLANinfo); return newVLANinfo; } private VLANInfo OutgoingVLAN(int ID) { //Search through outgoing vlan stuff to find the right one //If the packet is tagged with the ID, and the port is tagged, return that //If the packet is untagged, return the one that is untagged VLANInfo newVLANinfo = null; if (ID != NB.UntaggedVLAN) //the packet is tagged { foreach (VLANInfo vi in VLANs) { if (vi.ID == ID) { //if (vi.Tag == VLANTagType.Forbidden) // Console.WriteLine(" About to be outbound forbidden."); return vi; } } //We do not have one set yet. Add a new one newVLANinfo = new VLANInfo(ID, VLANTagType.Forbidden); //Console.WriteLine(" Creating outbound forbidden vlan - " + ID); VLANs.Add(newVLANinfo); return newVLANinfo; } else //the packet is untagged. { //we should find the untagged vlan //if no untagged vlan, find the tagged vlan foreach (VLANInfo vi in VLANs) { if (vi.Tag == VLANTagType.Untagged) return vi; } foreach (VLANInfo vi in VLANs) { if (vi.Tag == VLANTagType.Tagged) return vi; } //We do not have an "untagged" vlan. Return the settings for vlan1 foreach (VLANInfo vi in VLANs) { if (vi.ID == 1) return vi; } } //We should never get here. This is just a fall-through newVLANinfo = new VLANInfo(ID, VLANTagType.Forbidden); VLANs.Add(newVLANinfo); return newVLANinfo; } public void ProcessInboundPacket(Packet tPacket) { bool isgood = false; if (tPacket.destIP != null && tPacket.destIP.GetIP == myIP.GetIP) isgood = true; if (tPacket.destIP != null && myIP.IsLocal(tPacket.destIP)) isgood = true; if (myIP.NetworkAddress == myIP.GetIP) isgood = true; Network MyNet = NB.GetNetwork(); NetworkDevice ND = MyNet.GetDeviceFromID(AttachedToHostNic); tPacket.InboundInterface = this; if(isgood) { //anything we should do here? //Mainly vlan if we are a vlan. VLANInfo VI = IncomingVLAN(tPacket.VLANID); VLANTagType What = VI.Tag; Network theNet = NB.GetNetwork(); NetworkDevice HD = theNet.GetDeviceFromID(AttachedToHostNic); if (HD == null) return; string hostname = HD.hostname; if (What == VLANTagType.Forbidden) { //This vlan packet is deliberately forbidden. Reject it (fail) string errString = string.Format(NB.Translate("NI_VLANInForbidden"), hostname, tPacket.destIP.GetIPString); tPacket.AddMessage(DebugLevel.switching, errString); tPacket.Tracking.Status = errString; tPacket.MyStatus = PacketStatus.finished_ok; return; } if (What == VLANTagType.Untagged) { //If it is (default vlan), this is OK. Otherwise drop. //Untagged means we expect it to be vlan of (untagged) on the cable side if(tPacket.VLANID != NB.UntaggedVLAN) { //Oops. We need to reject the packet string errString = string.Format(NB.Translate("NI_VLANInUntagged"), hostname, tPacket.destIP.GetIPString); tPacket.AddMessage(DebugLevel.switching, errString); tPacket.Tracking.Status = errString; tPacket.MyStatus = PacketStatus.finished_ok; return; } else //We need to tag the packet with the new VLAN-ID { tPacket.VLANID = VI.ID; //The packet is now tagged } } if (What == VLANTagType.Tagged) { //If the packet is tagged, and the vlan expected tagged, all is good. if (tPacket.VLANID != NB.UntaggedVLAN && tPacket.VLANID != VI.ID) { //Oops. We need to reject the packet string errString = string.Format(NB.Translate("NI_VLANInMisMatch"), hostname, tPacket.destIP.GetIPString); tPacket.AddMessage(DebugLevel.switching, errString); tPacket.Tracking.Status = errString; tPacket.MyStatus = PacketStatus.finished_ok; return; } else tPacket.VLANID = VI.ID; //Make sure it is properly tagged. } } } } }