/// <summary>This is used to process a dhcp packet on the node side, that /// includes placing data such as the local Brunet Address, Ipop Namespace, /// and other optional parameters in our request to the dhcp server. When /// receiving the results, if it is successful, the results are written to /// the TAP device.</summary> /// <param name="ipp"> The IPPacket that contains the Dhcp Request</param> /// <param name="dhcp_params"> an object containing any extra parameters for /// the dhcp server</param> /// <returns> true on if dhcp is supported.</returns> protected virtual bool HandleDhcp(IPPacket ipp) { UdpPacket udpp = new UdpPacket(ipp.Payload); DhcpPacket dhcp_packet = new DhcpPacket(udpp.Payload); MemBlock ether_addr = dhcp_packet.chaddr; if (_dhcp_config == null) { return(true); } DhcpServer dhcp_server = CheckOutDhcpServer(ether_addr); if (dhcp_server == null) { return(true); } MemBlock last_ip = null; _ether_to_ip.TryGetValue(ether_addr, out last_ip); byte[] last_ipb = (last_ip == null) ? null : (byte[])last_ip; WaitCallback wcb = delegate(object o) { ProtocolLog.WriteIf(IpopLog.DhcpLog, String.Format( "Attempting Dhcp for: {0}", Utils.MemBlockToString(ether_addr, '.'))); DhcpPacket rpacket = null; try { rpacket = dhcp_server.ProcessPacket(dhcp_packet, AppNode.Node.Address.ToString(), last_ipb); } catch (Exception e) { ProtocolLog.WriteIf(IpopLog.DhcpLog, e.Message); CheckInDhcpServer(dhcp_server); return; } /* Check our allocation to see if we're getting a new address */ MemBlock new_addr = rpacket.yiaddr; UpdateMapping(ether_addr, new_addr); MemBlock destination_ip = ipp.SourceIP; if (destination_ip.Equals(IPPacket.ZeroAddress)) { destination_ip = IPPacket.BroadcastAddress; } UdpPacket res_udpp = new UdpPacket(_dhcp_server_port, _dhcp_client_port, rpacket.Packet); IPPacket res_ipp = new IPPacket(IPPacket.Protocols.Udp, rpacket.siaddr, destination_ip, res_udpp.ICPacket); EthernetPacket res_ep = new EthernetPacket(ether_addr, EthernetPacket.UnicastAddress, EthernetPacket.Types.IP, res_ipp.ICPacket); Ethernet.Send(res_ep.ICPacket); CheckInDhcpServer(dhcp_server); }; ThreadPool.QueueUserWorkItem(wcb); return(true); }
/// <summary>Static addresses are handled nearly identically to dynamic, so /// we use one shared method to pull a dhcp server from the list of dhcp /// servers. We only want one request per Ethernet / IP at a time.</summary> protected DhcpServer CheckOutDhcpServer(MemBlock ether_addr) { DhcpServer dhcp_server = null; lock (_sync) { if (!_ether_to_dhcp_server.TryGetValue(ether_addr, out dhcp_server)) { dhcp_server = GetDhcpServer(); _ether_to_dhcp_server.Add(ether_addr, dhcp_server); } } lock (_checked_out.SyncRoot) { if (_checked_out.Contains(dhcp_server)) { return(null); } _checked_out.Add(dhcp_server, true); } return(dhcp_server); }
protected virtual bool MappingMissing(MemBlock ip) { ProtocolLog.WriteIf(IpopLog.ResolverLog, "Notified of address missing."); if (!_ip_to_ether.ContainsKey(ip)) { return(false); } WaitCallback wcb = delegate(object o) { // Easiest approach is to simply update the mapping... DhcpServer dhcp_server = GetDhcpServer(); try { dhcp_server.RequestLease(ip, true, AppNode.Node.Address.ToString(), _ipop_config.AddressData.Hostname); } catch (Exception e) { ProtocolLog.WriteIf(IpopLog.DhcpLog, e.Message); } }; ThreadPool.QueueUserWorkItem(wcb); return(true); }
/// <summary>The request on the IP allocation space (DHT) has returned. So /// we're done with the server.</summary> protected void CheckInDhcpServer(DhcpServer dhcp_server) { lock(_checked_out.SyncRoot) { _checked_out.Remove(dhcp_server); } }
/// <summary>Creates an IpopNode given a NodeConfig and an IpopConfig. /// Also sets up the Information, Ethernet device, and subscribes /// to Brunet for IP Packets</summary> /// <param name="node_config">The path to a NodeConfig xml file</param> /// <param name="ipop_config">The path to a IpopConfig xml file</param> public IpopNode(NodeConfig node_config, IpopConfig ipop_config, DHCPConfig dhcp_config) : base(node_config) { PublicNode = CreateNode(node_config); PublicNode.Node.DisconnectOnOverload = false; if(PublicNode.PrivateNode == null) { AppNode = PublicNode; } else { AppNode = PublicNode.PrivateNode; AppNode.Node.DisconnectOnOverload = false; } _ipop_config = ipop_config; Ethernet = new Ethernet(_ipop_config.VirtualNetworkDevice); Ethernet.Subscribe(this, null); Info = new Information(AppNode.Node, "IpopNode", AppNode.SecurityOverlord); Info.UserData["IpopNamespace"] = _ipop_config.IpopNamespace; if(PublicNode == AppNode) { PublicInfo = Info; } else { PublicInfo = new Information(PublicNode.Node, "PrivateIpopNode", PublicNode.SecurityOverlord); PublicInfo.UserData["IpopNamespace"] = _ipop_config.IpopNamespace; } if(_ipop_config.EndToEndSecurity && !AppNode.Config.Security.SecureEdges && AppNode.Config.Security.Enabled) { _conn_handler = new Brunet.Security.PeerSec.Symphony.SecureConnectionHandler( PType.Protocol.IP, AppNode.Node, AppNode.SymphonySecurityOverlord); } else { _conn_handler = new ConnectionHandler(PType.Protocol.IP, AppNode.Node); } _conn_handler.Subscribe(this, null); _sync = new object(); _lock = 0; _ether_to_ip = new Dictionary<MemBlock, MemBlock>(); _ip_to_ether = new Dictionary<MemBlock, MemBlock>(); _dhcp_server_port = _ipop_config.DHCPPort != 0 ? _ipop_config.DHCPPort : 67; _dhcp_client_port = _dhcp_server_port + 1; ProtocolLog.WriteIf(IpopLog.DhcpLog, String.Format( "Setting Dhcp Ports to: {0},{1}", _dhcp_server_port, _dhcp_client_port)); _ether_to_dhcp_server = new Dictionary<MemBlock, DhcpServer>(); _static_mapping = new Dictionary<MemBlock, SimpleTimer>(); _dhcp_config = dhcp_config; if(_dhcp_config != null) { SetDns(); SetTAAuth(); _dhcp_server = GetDhcpServer(); } _checked_out = new Hashtable(); AppNode.Node.HeartBeatEvent += CheckNode; _last_check_node = DateTime.UtcNow; AppNode.Node.Rpc.AddHandler("Ipop", this); }
/// <summary>The request on the IP allocation space (DHT) has returned. So /// we're done with the server.</summary> protected void CheckInDhcpServer(DhcpServer dhcp_server) { lock (_checked_out.SyncRoot) { _checked_out.Remove(dhcp_server); } }
/// <summary>Let's see if we can route for an IP. Default is do /// nothing!</summary> /// <param name="ip">The IP in question.</param> protected void HandleNewStaticIP(MemBlock ether_addr, MemBlock ip) { if (!_ipop_config.AllowStaticAddresses) { return; } lock (_sync) { if (_dhcp_config == null) { return; } } if (!_dhcp_server.IPInRange(ip)) { return; } DhcpServer dhcp_server = CheckOutDhcpServer(ether_addr); if (dhcp_server == null) { return; } ProtocolLog.WriteIf(IpopLog.DhcpLog, String.Format( "Static Address request for: {0}", Utils.MemBlockToString(ip, '.'))); WaitCallback wcb = null; wcb = delegate(object o) { byte[] res_ip = null; try { res_ip = dhcp_server.RequestLease(ip, true, AppNode.Node.Address.ToString(), _ipop_config.AddressData.Hostname); } catch (Exception e) { ProtocolLog.WriteIf(IpopLog.DhcpLog, e.Message); } if (res_ip == null) { ProtocolLog.WriteIf(IpopLog.DhcpLog, String.Format( "Request for {0} failed!", Utils.MemBlockToString(ip, '.'))); } else { lock (_sync) { bool new_entry = true; if (_ether_to_ip.ContainsKey(ether_addr)) { if (_ether_to_ip[ether_addr].Equals(ip)) { new_entry = false; } } if (new_entry) { if (_static_mapping.ContainsKey(ether_addr)) { _static_mapping[ether_addr].Stop(); } _static_mapping[ether_addr] = new SimpleTimer(wcb, null, _dhcp_config.LeaseTime * 1000 / 2, _dhcp_config.LeaseTime * 1000 / 2); _static_mapping[ether_addr].Start(); } UpdateMapping(ether_addr, MemBlock.Reference(res_ip)); } } CheckInDhcpServer(dhcp_server); }; ThreadPool.QueueUserWorkItem(wcb); }
/// <summary>Creates an IpopNode given a NodeConfig and an IpopConfig. /// Also sets up the Information, Ethernet device, and subscribes /// to Brunet for IP Packets</summary> /// <param name="node_config">The path to a NodeConfig xml file</param> /// <param name="ipop_config">The path to a IpopConfig xml file</param> public IpopNode(NodeConfig node_config, IpopConfig ipop_config, DHCPConfig dhcp_config) : base(node_config) { PublicNode = CreateNode(node_config); PublicNode.Node.DisconnectOnOverload = false; if (PublicNode.PrivateNode == null) { AppNode = PublicNode; } else { AppNode = PublicNode.PrivateNode; AppNode.Node.DisconnectOnOverload = false; } _ipop_config = ipop_config; Ethernet = new Ethernet(_ipop_config.VirtualNetworkDevice); Ethernet.Subscribe(this, null); Info = new Information(AppNode.Node, "IpopNode", AppNode.SecurityOverlord); Info.UserData["IpopNamespace"] = _ipop_config.IpopNamespace; if (PublicNode == AppNode) { PublicInfo = Info; } else { PublicInfo = new Information(PublicNode.Node, "PrivateIpopNode", PublicNode.SecurityOverlord); PublicInfo.UserData["IpopNamespace"] = _ipop_config.IpopNamespace; } if (_ipop_config.EndToEndSecurity && !AppNode.Config.Security.SecureEdges && AppNode.Config.Security.Enabled) { _conn_handler = new Brunet.Security.PeerSec.Symphony.SecureConnectionHandler( PType.Protocol.IP, AppNode.Node, AppNode.SymphonySecurityOverlord); } else { _conn_handler = new ConnectionHandler(PType.Protocol.IP, AppNode.Node); } _conn_handler.Subscribe(this, null); _sync = new object(); _lock = 0; _ether_to_ip = new Dictionary <MemBlock, MemBlock>(); _ip_to_ether = new Dictionary <MemBlock, MemBlock>(); _dhcp_server_port = _ipop_config.DHCPPort != 0 ? _ipop_config.DHCPPort : 67; _dhcp_client_port = _dhcp_server_port + 1; ProtocolLog.WriteIf(IpopLog.DhcpLog, String.Format( "Setting Dhcp Ports to: {0},{1}", _dhcp_server_port, _dhcp_client_port)); _ether_to_dhcp_server = new Dictionary <MemBlock, DhcpServer>(); _static_mapping = new Dictionary <MemBlock, SimpleTimer>(); _dhcp_config = dhcp_config; if (_dhcp_config != null) { SetDns(); SetTAAuth(); _dhcp_server = GetDhcpServer(); } _checked_out = new Hashtable(); AppNode.Node.HeartBeatEvent += CheckNode; _last_check_node = DateTime.UtcNow; AppNode.Node.Rpc.AddHandler("Ipop", this); }
/// <summary>Creates an IpopNode given a NodeConfig and an IpopConfig. /// Also sets up the Information, Ethernet device, and subscribes /// to Brunet for IP Packets</summary> /// <param name="node_config">The path to a NodeConfig xml file</param> /// <param name="ipop_config">The path to a IpopConfig xml file</param> public IpopNode(NodeConfig node_config, IpopConfig ipop_config, DHCPConfig dhcp_config) : base(node_config) { AppNode = CreateNode(node_config); AppNode.Node.DisconnectOnOverload = false; _chota = AppNode.Node.Cco; _ipop_config = ipop_config; Ethernet = new Ethernet(_ipop_config.VirtualNetworkDevice); Ethernet.Subscribe(this, null); Info = new Information(AppNode.Node, "IpopNode"); Info.UserData["IpopNamespace"] = _ipop_config.IpopNamespace; if(_ipop_config.EndToEndSecurity && AppNode.SecurityOverlord != null) { _secure_senders = true; } else { _secure_senders = false; } AppNode.Node.GetTypeSource(PType.Protocol.IP).Subscribe(this, null); _sync = new object(); _lock = 0; _ether_to_ip = new Dictionary<MemBlock, MemBlock>(); _ip_to_ether = new Dictionary<MemBlock, MemBlock>(); _dhcp_server_port = _ipop_config.DHCPPort != 0 ? _ipop_config.DHCPPort : 67; _dhcp_client_port = _dhcp_server_port + 1; ProtocolLog.WriteIf(IpopLog.DhcpLog, String.Format( "Setting Dhcp Ports to: {0},{1}", _dhcp_server_port, _dhcp_client_port)); _ether_to_dhcp_server = new Dictionary<MemBlock, DhcpServer>(); _static_mapping = new Dictionary<MemBlock, SimpleTimer>(); _dhcp_config = dhcp_config; if(_dhcp_config != null) { SetDns(); _dhcp_server = GetDhcpServer(); } _checked_out = new Hashtable(); AppNode.Node.HeartBeatEvent += CheckNode; _last_check_node = DateTime.UtcNow; AppNode.Node.Rpc.AddHandler("Ipop", this); }