/* * \brief DHCP server role of a domain * \author Martin Stein * \date 2016-08-19 */ /* * Copyright (C) 2016-2017 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. */ #ifndef _DHCP_SERVER_H_ #define _DHCP_SERVER_H_ /* local includes */ #include "ipv4_address_prefix.h" #include "bit_allocator_dynamic.h" #include "list.h" #include "pointer.h" /* Genode includes */ #include #include #include #include namespace Net { class Configuration; class Dhcp_server; class Dhcp_allocation; class Dhcp_allocation_tree; using Dhcp_allocation_list = List; /* forward declarations */ class Interface; class Domain; class Domain_tree; } class Net::Dhcp_server : private Genode::Noncopyable { private: Ipv4_address const _dns_server; Pointer const _dns_server_from; Genode::Microseconds const _ip_lease_time; Ipv4_address const _ip_first; Ipv4_address const _ip_last; Genode::uint32_t const _ip_first_raw; Genode::uint32_t const _ip_count; Genode::Bit_allocator_dynamic _ip_alloc; void _invalid(Domain &domain, char const *reason); Genode::Microseconds _init_ip_lease_time(Genode::Xml_node const node); Pointer _init_dns_server_from(Genode::Xml_node const node, Domain_tree &domains); public: enum { DEFAULT_IP_LEASE_TIME_SEC = 3600 }; struct Alloc_ip_failed : Genode::Exception { }; struct Invalid : Genode::Exception { }; Dhcp_server(Genode::Xml_node const node, Domain &domain, Genode::Allocator &alloc, Ipv4_address_prefix const &interface, Domain_tree &domains); Ipv4_address alloc_ip(); void alloc_ip(Ipv4_address const &ip); void free_ip(Ipv4_address const &ip); bool ready() const; /********* ** log ** *********/ void print(Genode::Output &output) const; /*************** ** Accessors ** ***************/ Ipv4_address const &dns_server() const; Domain &dns_server_from() { return _dns_server_from(); } Genode::Microseconds ip_lease_time() const { return _ip_lease_time; } }; class Net::Dhcp_allocation : public Genode::Avl_node, public Dhcp_allocation_list::Element { protected: Interface &_interface; Ipv4_address const _ip; Mac_address const _mac; Timer::One_shot_timeout _timeout; bool _bound { false }; void _handle_timeout(Genode::Duration); bool _higher(Mac_address const &mac) const; public: Dhcp_allocation(Interface &interface, Ipv4_address const &ip, Mac_address const &mac, Timer::Connection &timer, Genode::Microseconds lifetime); ~Dhcp_allocation(); Dhcp_allocation &find_by_mac(Mac_address const &mac); void lifetime(Genode::Microseconds lifetime); /************** ** Avl_node ** **************/ bool higher(Dhcp_allocation *alloc) { return _higher(alloc->_mac); } /********* ** Log ** *********/ void print(Genode::Output &output) const; /*************** ** Accessors ** ***************/ Ipv4_address const &ip() const { return _ip; } bool bound() const { return _bound; } void set_bound() { _bound = true; } }; struct Net::Dhcp_allocation_tree { private: Genode::Avl_tree _tree { }; Dhcp_allocation_list _list { }; public: struct No_match : Genode::Exception { }; Dhcp_allocation &find_by_mac(Mac_address const &mac) const; void insert(Dhcp_allocation &dhcp_alloc) { _tree.insert(&dhcp_alloc); _list.insert(&dhcp_alloc); } void remove(Dhcp_allocation &dhcp_alloc) { _tree.remove(&dhcp_alloc); _list.remove(&dhcp_alloc); } Dhcp_allocation *first() { return _tree.first(); } template void for_each(FUNC && functor) { using List_item = Dhcp_allocation_list::Element; for (Dhcp_allocation *item = _list.first(); item; ) { Dhcp_allocation *const next_item = item->List_item::next(); functor(*item); item = next_item; } } }; #endif /* _DHCP_SERVER_H_ */