From: Tomek Mrugalski Date: Fri, 14 Oct 2011 09:53:59 +0000 (+0200) Subject: [1186] Changes in reply to review comment 13. X-Git-Tag: perftcpdns_before_epoll~86^2~17 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f89dbf486bbbd41c3f4e85c15d2cda91706a37ba;p=thirdparty%2Fkea.git [1186] Changes in reply to review comment 13. --- diff --git a/ChangeLog b/ChangeLog index 92f98dd363..e05334190a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +299. [func]* tomek + libdhcp: DHCP packet library was implemented. Currently it handles + packet reception, option parsing, option generation and output + packet building. Generic and specialized classes for several + DHCPv6 options (IA_NA, IAADDR, address-list) are available. A + simple code was added that leverages libdhcp. It is a skeleton + DHCPv6 server. It receives incoming SOLICIT and REQUEST messages + and responds with proper ADVERTISE and REPLY. Note that since + LeaseManager is not implemented, server assigns a the same + hardcoded lease for every client. + bind10-devel-20111014 released on October 14, 2011 298. [doc] jreed diff --git a/src/bin/dhcp6/dhcp6_srv.h b/src/bin/dhcp6/dhcp6_srv.h index 90ecb8aa7a..4daef3aa4a 100644 --- a/src/bin/dhcp6/dhcp6_srv.h +++ b/src/bin/dhcp6/dhcp6_srv.h @@ -23,143 +23,134 @@ namespace isc { - namespace dhcp { - /// @brief DHCPv6 server service. - /// - /// This singleton class represents DHCPv6 server. It contains all - /// top-level methods and routines necessary for server operation. - /// In particular, it instantiates IfaceMgr, loads or generates DUID - /// that is going to be used as server-identifier, receives incoming - /// packets, processes them, manages leases assignment and generates - /// appropriate responses. - class Dhcpv6Srv : public boost::noncopyable { - private: - - /// @brief A private copy constructor. - /// - /// Creates a single Dhcpv6Srv instance and all required objects, - /// including interface manager (IfaceMgr). It is defined private on - /// purpose. We don't want to have more than one copy of Dhcpv6Srv. - /// - /// It may throw exceptions if server creation failed, e.g. due to - /// failures in IfaceMgr (e.g. socket creation) or unavailable - /// interfaces when attempting to create new DUID. - Dhcpv6Srv(const Dhcpv6Srv& src); - - /// @brief A private assignment operator. - /// - /// Note that there is no implementation of this assignment operator. - /// Its definition is here to prevent creation of any copies. - /// - Dhcpv6Srv& operator=(const Dhcpv6Srv& src); - - /// @brief Sets server-identifier. - /// - /// This method attempts to set server-identifier DUID. It loads it - /// from a file. If file load fails, it generates new DUID using - /// interface link-layer addresses (EUI-64) + timestamp (DUID type - /// duid-llt, see RFC3315, section 9.2). If there are no suitable - /// interfaces present, exception it thrown - /// - /// @throws isc::Unexpected Failed to read DUID file and no suitable - /// interfaces for new DUID generation are detected. - void setServerID(); - - /// server DUID (to be sent in server-identifier option) - boost::shared_ptr serverid_; - - public: - /// @brief Default constructor. - /// - /// Instantiates necessary services, required to run DHCPv6 server. - /// In particular, creates IfaceMgr that will be responsible for - /// network interaction. Will instantiate lease manager, and load - /// old or create new DUID. - Dhcpv6Srv(); - - /// @brief Destructor. Shuts down DHCPv6 service. - ~Dhcpv6Srv(); - - /// @brief Returns server-intentifier option - /// - /// @return reference to server-id option - /// - boost::shared_ptr& - getServerID() { return serverid_; } - - /// @brief Main server processing loop. - /// - /// Main server processing loop. Receives incoming packets, verifies - /// their correctness, generates appropriate answer (if needed) and - /// transmits respones. - /// - /// @return true, if being shut down gracefully, fail if experienced - /// critical error. - bool run(); - - protected: - /// @brief Processes incoming SOLICIT and returns response. - /// - /// Processes received SOLICIT message and verifies that its sender - /// should be served. In particular IA, TA and PD options are populated - /// with to-be assinged addresses, temporary addresses and delegated - /// prefixes, respectively. In the usual 4 message exchange, server is - /// expected to respond with ADVERTISE message. However, if client - /// requests rapid-commit and server supports it, REPLY will be sent - /// instead of ADVERTISE and requested leases will be assigned - /// immediately. - /// - /// @param solicit SOLICIT message received from client - /// - /// @return ADVERTISE, REPLY message or NULL - /// - boost::shared_ptr - processSolicit(boost::shared_ptr solicit); - - /// @brief Processes incoming REQUEST and returns REPLY response. - /// - /// Processes incoming REQUEST message and verifies that its sender - /// should be served. In particular IA, TA and PD options are populated - /// with assinged addresses, temporary addresses and delegated - /// prefixes, respectively. Uses LeaseMgr to allocate or update existing - /// leases. - /// - /// @param request REQUEST message received from client - /// - /// @return REPLY message or NULL - boost::shared_ptr - processRequest(boost::shared_ptr request); - - /// @brief Stub function that will handle incoming RENEW messages. - boost::shared_ptr - processRenew(boost::shared_ptr renew); - - /// @brief Stub function that will handle incoming REBIND messages. - boost::shared_ptr - processRebind(boost::shared_ptr rebind); - - /// @brief Stub function that will handle incoming CONFIRM messages. - boost::shared_ptr - processConfirm(boost::shared_ptr confirm); - - /// @brief Stub function that will handle incoming RELEASE messages. - boost::shared_ptr - processRelease(boost::shared_ptr release); - - /// @brief Stub function that will handle incoming DECLINE messages. - boost::shared_ptr - processDecline(boost::shared_ptr decline); - - /// @brief Stub function that will handle incoming INF-REQUEST messages. - boost::shared_ptr - processInfRequest(boost::shared_ptr infRequest); - - /// indicates if shutdown is in progress. Setting it to true will - /// initiate server shutdown procedure. - volatile bool shutdown; - }; - - }; // namespace isc::dhcp +namespace dhcp { +/// @brief DHCPv6 server service. +/// +/// This singleton class represents DHCPv6 server. It contains all +/// top-level methods and routines necessary for server operation. +/// In particular, it instantiates IfaceMgr, loads or generates DUID +/// that is going to be used as server-identifier, receives incoming +/// packets, processes them, manages leases assignment and generates +/// appropriate responses. +class Dhcpv6Srv : public boost::noncopyable { + +public: + /// @brief Default constructor. + /// + /// Instantiates necessary services, required to run DHCPv6 server. + /// In particular, creates IfaceMgr that will be responsible for + /// network interaction. Will instantiate lease manager, and load + /// old or create new DUID. + Dhcpv6Srv(); + + /// @brief Destructor. Used during DHCPv6 service shutdown. + ~Dhcpv6Srv(); + + /// @brief Returns server-intentifier option + /// + /// @return server-id option + boost::shared_ptr + getServerID() { return serverid_; } + + /// @brief Main server processing loop. + /// + /// Main server processing loop. Receives incoming packets, verifies + /// their correctness, generates appropriate answer (if needed) and + /// transmits respones. + /// + /// @return true, if being shut down gracefully, fail if experienced + /// critical error. + bool run(); + +protected: + /// @brief Processes incoming SOLICIT and returns response. + /// + /// Processes received SOLICIT message and verifies that its sender + /// should be served. In particular IA, TA and PD options are populated + /// with to-be assinged addresses, temporary addresses and delegated + /// prefixes, respectively. In the usual 4 message exchange, server is + /// expected to respond with ADVERTISE message. However, if client + /// requests rapid-commit and server supports it, REPLY will be sent + /// instead of ADVERTISE and requested leases will be assigned + /// immediately. + /// + /// @param solicit SOLICIT message received from client + /// + /// @return ADVERTISE, REPLY message or NULL + boost::shared_ptr + processSolicit(boost::shared_ptr solicit); + + /// @brief Processes incoming REQUEST and returns REPLY response. + /// + /// Processes incoming REQUEST message and verifies that its sender + /// should be served. In particular IA, TA and PD options are populated + /// with assinged addresses, temporary addresses and delegated + /// prefixes, respectively. Uses LeaseMgr to allocate or update existing + /// leases. + /// + /// @param request a message received from client + /// + /// @return REPLY message or NULL + boost::shared_ptr + processRequest(boost::shared_ptr request); + + /// @brief Stub function that will handle incoming RENEW messages. + /// + /// @param renew message received from client + boost::shared_ptr + processRenew(boost::shared_ptr renew); + + /// @brief Stub function that will handle incoming REBIND messages. + /// + /// @param rebind message received from client + boost::shared_ptr + processRebind(boost::shared_ptr rebind); + + /// @brief Stub function that will handle incoming CONFIRM messages. + /// + /// @param confirm message received from client + boost::shared_ptr + processConfirm(boost::shared_ptr confirm); + + /// @brief Stub function that will handle incoming RELEASE messages. + /// + /// @param release message received from client + boost::shared_ptr + processRelease(boost::shared_ptr release); + + /// @brief Stub function that will handle incoming DECLINE messages. + /// + /// @param decline message received from client + boost::shared_ptr + processDecline(boost::shared_ptr decline); + + /// @brief Stub function that will handle incoming INF-REQUEST messages. + /// + /// @param infRequest message received from client + boost::shared_ptr + processInfRequest(boost::shared_ptr infRequest); + + /// @brief Sets server-identifier. + /// + /// This method attempts to set server-identifier DUID. It loads it + /// from a file. If file load fails, it generates new DUID using + /// interface link-layer addresses (EUI-64) + timestamp (DUID type + /// duid-llt, see RFC3315, section 9.2). If there are no suitable + /// interfaces present, exception it thrown + /// + /// @throws isc::Unexpected Failed to read DUID file and no suitable + /// interfaces for new DUID generation are detected. + void setServerID(); + + /// server DUID (to be sent in server-identifier option) + boost::shared_ptr serverid_; + + /// indicates if shutdown is in progress. Setting it to true will + /// initiate server shutdown procedure. + volatile bool shutdown; +}; + +}; // namespace isc::dhcp }; // namespace isc #endif // DHCP6_SRV_H diff --git a/src/bin/dhcp6/iface_mgr.cc b/src/bin/dhcp6/iface_mgr.cc index 79b3c612bb..7a632848af 100644 --- a/src/bin/dhcp6/iface_mgr.cc +++ b/src/bin/dhcp6/iface_mgr.cc @@ -69,10 +69,10 @@ IfaceMgr::Iface::getPlainMac() const { ostringstream tmp; tmp.fill('0'); tmp << hex; - for (int i=0; i Addr6Lst; + + /// maximum MAC address length (Infiniband uses 20 bytes) + static const unsigned int MAX_MAC_LEN = 20; + + /// @brief represents a single network interface /// - /// IfaceMgr is an interface manager class that detects available network - /// interfaces, configured addresses, link-local addresses, and provides - /// API for using sockets. - /// - class IfaceMgr : public boost::noncopyable { - public: - /// type that defines list of addresses - typedef std::list Addr6Lst; + /// Iface structure represents network interface with all useful + /// information, like name, interface index, MAC address and + /// list of assigned addresses + struct Iface { + /// constructor + Iface(const std::string& name, int ifindex); + + /// returns full interface name in format ifname/ifindex + std::string getFullName() const; + + /// returns link-layer address a plain text + std::string getPlainMac() const; - /// maximum MAC address length (Infiniband uses 20 bytes) - static const unsigned int MAX_MAC_LEN = 20; + /// network interface name + std::string name_; + + /// interface index (a value that uniquely indentifies an interface) + int ifindex_; - /// @brief represents a single network interface - /// - /// Iface structure represents network interface with all useful - /// information, like name, interface index, MAC address and /// list of assigned addresses - struct Iface { - /// constructor - Iface(const std::string& name, int ifindex); - - /// returns full interface name in format ifname/ifindex - std::string getFullName() const; - - /// returns link-layer address a plain text - std::string getPlainMac() const; - - std::string name_; /// network interface name - int ifindex_; /// interface index (a value that uniquely - /// indentifies an interface - Addr6Lst addrs_; /// list of assigned addresses - uint8_t mac_[MAX_MAC_LEN]; /// link-layer address - int mac_len_; /// length of link-layer address (usually 6) - - int sendsock_; /// socket used to sending data - int recvsock_; /// socket used for receiving data - - // next field is not needed, let's keep it in cointainers - }; - - // TODO performance improvement: we may change this into - // 2 maps (ifindex-indexed and name-indexed) and - // also hide it (make it public make tests easier for now) - typedef std::list IfaceLst; - - /// IfaceMgr is a singleton class. This method returns reference - /// to its sole instance. - /// - /// @return the only existing instance of interface manager - static IfaceMgr& instance(); - - /// @brief Returns interface with specified interface index - /// - /// @param ifindex index of searched interface - /// - /// @return interface with requested index (or NULL if no such - /// interface is present) - /// - Iface* - getIface(int ifindex); - - /// @brief Returns interface with specified interface name - /// - /// @param ifname name of searched interface - /// - /// @return interface with requested name (or NULL if no such - /// interface is present) - /// - Iface* - getIface(const std::string& ifname); - - /// debugging method that prints out all available interfaces - /// - /// @param out specifies stream to print list of interfaces to - void - printIfaces(std::ostream& out = std::cout); - - /// @brief Sends a packet. - /// - /// Sends a packet. All parameters regarding interface, destination - /// address are set in pkt object. - /// - /// @param pkt packet to be sent - /// - /// @return true if sending was successful - /// - bool - send(boost::shared_ptr pkt); - - /// @brief Tries to receive packet over open sockets. - /// - /// Attempts to receive a single packet of any of the open sockets. - /// If reception is successful and all information about its sender - /// are obtained, Pkt6 object is created and returned. - /// - /// @return Pkt6 object representing received packet (or NULL) - /// - boost::shared_ptr receive(); - - // don't use private, we need derived classes in tests - protected: - - /// @brief Protected constructor. - /// - /// Protected constructor. This is a singleton class. We don't want - /// anyone to create instances of IfaceMgr. Use instance() method - IfaceMgr(); - - ~IfaceMgr(); - - /// @brief Detects network interfaces. - /// - /// This method will eventually detect available interfaces. For now - /// it offers stub implementation. First interface name and link-local - /// IPv6 address is read from intefaces.txt file. - void - detectIfaces(); - - /// - /// Opens UDP/IPv6 socket and binds it to address, interface nad port. - /// - /// @param ifname name of the interface - /// @param addr address to be bound. - /// @param port UDP port. - /// - /// @return socket descriptor, if socket creation, binding and multicast - /// group join were all successful. -1 otherwise. - int openSocket(const std::string& ifname, - const isc::asiolink::IOAddress& addr, - int port); - - // TODO: having 2 maps (ifindex->iface and ifname->iface would) - // probably be better for performance reasons - - /// List of available interfaces - IfaceLst ifaces_; - - /// a pointer to a sole instance of this class (a singleton) - static IfaceMgr * instance_; - - // TODO: Also keep this interface on Iface once interface detection - // is implemented. We may need it e.g. to close all sockets on - // specific interface - int recvsock_; // TODO: should be fd_set eventually, but we have only - int sendsock_; // 2 sockets for now. Will do for until next release - // we can't use the same socket, as receiving socket - // is bound to multicast address. And we all know what happens - // to people who try to use multicast as source address. - - /// control-buffer, used in transmission and reception - char * control_buf_; - int control_buf_len_; - - private: - /// Opens sockets on detected interfaces. - bool - openSockets(); - - /// creates a single instance of this class (a singleton implementation) - static void - instanceCreate(); - - /// @brief Joins IPv6 multicast group on a socket. - /// - /// Socket must be created and bound to an address. Note that this - /// address is different than the multicast address. For example DHCPv6 - /// server should bind its socket to link-local address (fe80::1234...) - /// and later join ff02::1:2 multicast group. - /// - /// @param sock socket fd (socket must be bound) - /// @param ifname interface name (for link-scoped multicast groups) - /// @param mcast multicast address to join (e.g. "ff02::1:2") - /// - /// @return true if multicast join was successful - /// - bool - joinMcast(int sock, const std::string& ifname, - const std::string& mcast); + Addr6Lst addrs_; + + /// link-layer address + uint8_t mac_[MAX_MAC_LEN]; + + /// length of link-layer address (usually 6) + int mac_len_; + + /// socket used to sending data + int sendsock_; + + /// socket used for receiving data + int recvsock_; }; - }; // namespace isc::dhcp + // TODO performance improvement: we may change this into + // 2 maps (ifindex-indexed and name-indexed) and + // also hide it (make it public make tests easier for now) + + /// type that holds a list of interfaces + typedef std::list IfaceLst; + + /// IfaceMgr is a singleton class. This method returns reference + /// to its sole instance. + /// + /// @return the only existing instance of interface manager + static IfaceMgr& instance(); + + /// @brief Returns interface with specified interface index + /// + /// @param ifindex index of searched interface + /// + /// @return interface with requested index (or NULL if no such + /// interface is present) + /// + Iface* + getIface(int ifindex); + + /// @brief Returns interface with specified interface name + /// + /// @param ifname name of searched interface + /// + /// @return interface with requested name (or NULL if no such + /// interface is present) + /// + Iface* + getIface(const std::string& ifname); + + /// debugging method that prints out all available interfaces + /// + /// @param out specifies stream to print list of interfaces to + void + printIfaces(std::ostream& out = std::cout); + + /// @brief Sends a packet. + /// + /// Sends a packet. All parameters regarding interface, destination + /// address are set in pkt object. + /// + /// @param pkt packet to be sent + /// + /// @return true if sending was successful + /// + bool + send(boost::shared_ptr pkt); + + /// @brief Tries to receive packet over open sockets. + /// + /// Attempts to receive a single packet of any of the open sockets. + /// If reception is successful and all information about its sender + /// are obtained, Pkt6 object is created and returned. + /// + /// @return Pkt6 object representing received packet (or NULL) + /// + boost::shared_ptr receive(); + + // don't use private, we need derived classes in tests +protected: + + /// @brief Protected constructor. + /// + /// Protected constructor. This is a singleton class. We don't want + /// anyone to create instances of IfaceMgr. Use instance() method + IfaceMgr(); + + ~IfaceMgr(); + + /// @brief Detects network interfaces. + /// + /// This method will eventually detect available interfaces. For now + /// it offers stub implementation. First interface name and link-local + /// IPv6 address is read from intefaces.txt file. + void + detectIfaces(); + + /// + /// Opens UDP/IPv6 socket and binds it to address, interface and port. + /// + /// @param ifname name of the interface + /// @param addr address to be bound. + /// @param port UDP port. + /// + /// @return socket descriptor, if socket creation, binding and multicast + /// group join were all successful. -1 otherwise. + int openSocket(const std::string& ifname, + const isc::asiolink::IOAddress& addr, + int port); + + // TODO: having 2 maps (ifindex->iface and ifname->iface would) + // probably be better for performance reasons + + /// List of available interfaces + IfaceLst ifaces_; + + /// a pointer to a sole instance of this class (a singleton) + static IfaceMgr * instance_; + + // TODO: Also keep this interface on Iface once interface detection + // is implemented. We may need it e.g. to close all sockets on + // specific interface + int recvsock_; // TODO: should be fd_set eventually, but we have only + int sendsock_; // 2 sockets for now. Will do for until next release + // we can't use the same socket, as receiving socket + // is bound to multicast address. And we all know what happens + // to people who try to use multicast as source address. + + /// control-buffer, used in transmission and reception + char * control_buf_; + int control_buf_len_; + +private: + /// Opens sockets on detected interfaces. + bool + openSockets(); + + /// creates a single instance of this class (a singleton implementation) + static void + instanceCreate(); + + /// @brief Joins IPv6 multicast group on a socket. + /// + /// Socket must be created and bound to an address. Note that this + /// address is different than the multicast address. For example DHCPv6 + /// server should bind its socket to link-local address (fe80::1234...) + /// and later join ff02::1:2 multicast group. + /// + /// @param sock socket fd (socket must be bound) + /// @param ifname interface name (for link-scoped multicast groups) + /// @param mcast multicast address to join (e.g. "ff02::1:2") + /// + /// @return true if multicast join was successful + /// + bool + joinMcast(int sock, const std::string& ifname, + const std::string& mcast); +}; + +}; // namespace isc::dhcp }; // namespace isc #endif