Browse Source

[1186] Changes in reply to review comment 13.

Tomek Mrugalski 13 years ago
parent
commit
f89dbf486b
4 changed files with 330 additions and 317 deletions
  1. 11 0
      ChangeLog
  2. 128 137
      src/bin/dhcp6/dhcp6_srv.h
  3. 2 2
      src/bin/dhcp6/iface_mgr.cc
  4. 189 178
      src/bin/dhcp6/iface_mgr.h

+ 11 - 0
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

+ 128 - 137
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<isc::dhcp::Option> 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<isc::dhcp::Option>&
-        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<Pkt6>
-        processSolicit(boost::shared_ptr<Pkt6> 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<Pkt6>
-        processRequest(boost::shared_ptr<Pkt6> request);
-
-        /// @brief Stub function that will handle incoming RENEW messages.
-        boost::shared_ptr<Pkt6>
-        processRenew(boost::shared_ptr<Pkt6> renew);
-
-         /// @brief Stub function that will handle incoming REBIND messages.
-        boost::shared_ptr<Pkt6>
-        processRebind(boost::shared_ptr<Pkt6> rebind);
-
-        /// @brief Stub function that will handle incoming CONFIRM messages.
-        boost::shared_ptr<Pkt6>
-        processConfirm(boost::shared_ptr<Pkt6> confirm);
-
-        /// @brief Stub function that will handle incoming RELEASE messages.
-        boost::shared_ptr<Pkt6>
-        processRelease(boost::shared_ptr<Pkt6> release);
-
-        /// @brief Stub function that will handle incoming DECLINE messages.
-        boost::shared_ptr<Pkt6>
-        processDecline(boost::shared_ptr<Pkt6> decline);
-
-        /// @brief Stub function that will handle incoming INF-REQUEST messages.
-        boost::shared_ptr<Pkt6>
-        processInfRequest(boost::shared_ptr<Pkt6> 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<isc::dhcp::Option>
+    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<Pkt6>
+    processSolicit(boost::shared_ptr<Pkt6> 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<Pkt6>
+    processRequest(boost::shared_ptr<Pkt6> request);
+
+    /// @brief Stub function that will handle incoming RENEW messages.
+    ///
+    /// @param renew message received from client
+    boost::shared_ptr<Pkt6>
+    processRenew(boost::shared_ptr<Pkt6> renew);
+
+    /// @brief Stub function that will handle incoming REBIND messages.
+    ///
+    /// @param rebind message received from client
+    boost::shared_ptr<Pkt6>
+    processRebind(boost::shared_ptr<Pkt6> rebind);
+
+    /// @brief Stub function that will handle incoming CONFIRM messages.
+    ///
+    /// @param confirm message received from client
+    boost::shared_ptr<Pkt6>
+    processConfirm(boost::shared_ptr<Pkt6> confirm);
+
+    /// @brief Stub function that will handle incoming RELEASE messages.
+    ///
+    /// @param release message received from client
+    boost::shared_ptr<Pkt6>
+    processRelease(boost::shared_ptr<Pkt6> release);
+
+    /// @brief Stub function that will handle incoming DECLINE messages.
+    ///
+    /// @param decline message received from client
+    boost::shared_ptr<Pkt6>
+    processDecline(boost::shared_ptr<Pkt6> decline);
+
+    /// @brief Stub function that will handle incoming INF-REQUEST messages.
+    ///
+    /// @param infRequest message received from client
+    boost::shared_ptr<Pkt6>
+    processInfRequest(boost::shared_ptr<Pkt6> 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<isc::dhcp::Option> 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

+ 2 - 2
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<mac_len_; i++) {
+    for (int i = 0; i < mac_len_; i++) {
         tmp.width(2);
         tmp << mac_[i];
-        if (i<mac_len_-1) {
+        if (i < mac_len_-1) {
             tmp << ":";
         }
     }

+ 189 - 178
src/bin/dhcp6/iface_mgr.h

@@ -23,190 +23,201 @@
 
 namespace isc {
 
-    namespace dhcp {
-    /// @brief handles network interfaces, transmission and reception
+namespace dhcp {
+/// @brief handles network interfaces, transmission and reception
+///
+/// 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<isc::asiolink::IOAddress> 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<isc::asiolink::IOAddress> 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<Iface> 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<Pkt6> 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<Pkt6> 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<Iface> 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<Pkt6> 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<Pkt6> 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