From: gnocuil Date: Tue, 14 Oct 2014 17:18:32 +0000 (+0800) Subject: [3357] Make Pkt4o6 class derive from Pkt4 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3d72468110b9572c1158e30c200ac232b2b9418d;p=thirdparty%2Fkea.git [3357] Make Pkt4o6 class derive from Pkt4 --- diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc index d9994d5903..c928f5be37 100644 --- a/src/bin/dhcp4/dhcp4_srv.cc +++ b/src/bin/dhcp4/dhcp4_srv.cc @@ -157,12 +157,12 @@ Dhcpv4Srv::run() { // 4o6 bool dhcp4o6Request = false; + Pkt4o6Ptr query4o6; if (!query && ipc_ && !ipc_->empty()) { - query = ipc_->pop()->getPkt4(); + query4o6 = ipc_->pop(); dhcp4o6Request = true; - - //set Pkt4's localAddr according to U flag in Pkt6's transid field - ipc_->currentPkt4o6()->setPkt4LocalAddr(); + query4o6->unpack(); + query = query4o6; } try { @@ -437,8 +437,7 @@ Dhcpv4Srv::run() { if (ipc_ && dhcp4o6Request) {//4o6 try { - Pkt4o6Ptr rsp4o6(new Pkt4o6(ipc_->currentPkt4o6(), rsp)); - ipc_->sendPkt4o6(rsp4o6); + ipc_->sendPkt4o6(rsp, query4o6); } catch (const Exception& ex) { LOG_ERROR(dhcp4_logger, DHCP4_IPC_SEND_ERROR).arg(ex.what()); } diff --git a/src/bin/dhcp6/dhcp6_srv.cc b/src/bin/dhcp6/dhcp6_srv.cc index 74c24c726e..5aac49017a 100644 --- a/src/bin/dhcp6/dhcp6_srv.cc +++ b/src/bin/dhcp6/dhcp6_srv.cc @@ -250,7 +250,7 @@ bool Dhcpv6Srv::run() { // 4o6 bool dhcp4o6Response = false; if (!query && ipc_ && !ipc_->empty()) { - query = ipc_->pop()->getPkt6(); + query = ipc_->pop()->toPkt6(); dhcp4o6Response = true; } @@ -297,6 +297,11 @@ bool Dhcpv6Srv::run() { bool skip_unpack = false; + // Skip unpack when it's a DHCP4o6 response from DHCPv4 server + if (dhcp4o6Response) { + skip_unpack = true; + } + // The packet has just been received so contains the uninterpreted wire // data; execute callouts registered for buffer6_receive. if (HooksManager::calloutsPresent(Hooks.hook_index_buffer6_receive_)) { @@ -382,7 +387,7 @@ bool Dhcpv6Srv::run() { classifyPacket(query); try { - NameChangeRequestPtr ncr; + NameChangeRequestPtr ncr; switch (query->getType()) { case DHCPV6_SOLICIT: rsp = processSolicit(query); @@ -2454,7 +2459,8 @@ Dhcpv6Srv::processInfRequest(const Pkt6Ptr& infRequest) { void Dhcpv6Srv::processDHCPv4Query(const Pkt6Ptr& query) { try { - Pkt4o6Ptr pkt4o6(new Pkt4o6(query)); + Pkt4o6Ptr pkt4o6 = Pkt4o6::fromPkt6(query); + pkt4o6->pack(); ipc_->sendPkt4o6(pkt4o6); } catch (const Exception& ex) { LOG_ERROR(dhcp6_logger, DHCP6_IPC_SEND_ERROR).arg(ex.what()); @@ -2463,14 +2469,12 @@ Dhcpv6Srv::processDHCPv4Query(const Pkt6Ptr& query) { Pkt6Ptr Dhcpv6Srv::processDHCPv4Response(const Pkt6Ptr& query) { - Pkt6Ptr reply = Pkt6Ptr(new Pkt6(DHCPV4_RESPONSE, query->getTransid())); + Pkt6Ptr reply = Pkt6Ptr(new Pkt6(DHCPV4_RESPONSE, 0)); appendRequestedOptions(query, reply);//TODO: should we remove this? - - OptionPtr option(new Option(Option::V6, - OPTION_DHCPV4_MSG, - ipc_->currentPkt4o6()->getDHCPv4MsgOption())); - reply->addOption(option); + + OptionPtr opt = query->getOption(OPTION_DHCPV4_MSG); + reply->addOption(opt); //Add relay info if (!query->relay_info_.empty()) { diff --git a/src/lib/dhcp/pkt4.h b/src/lib/dhcp/pkt4.h index d5817b89f2..2b1f4aaea0 100644 --- a/src/lib/dhcp/pkt4.h +++ b/src/lib/dhcp/pkt4.h @@ -68,6 +68,9 @@ public: /// @param data pointer to received data /// @param len size of buffer to be allocated for this packet. Pkt4(const uint8_t* data, size_t len); + + /// @brief Destructor. + virtual ~Pkt4() {} /// @brief Prepares on-wire format of DHCPv4 packet. /// @@ -77,7 +80,7 @@ public: /// The buffer_out_ is cleared before writting to the buffer. /// /// @throw InvalidOperation if packing fails - void + virtual void pack(); /// @brief Parses on-wire form of DHCPv4 packet. @@ -88,7 +91,7 @@ public: /// be stored in options_ container. /// /// Method with throw exception if packet parsing fails. - void unpack(); + virtual void unpack(); /// @brief performs sanity check on a packet. /// diff --git a/src/lib/dhcp/pkt4o6.cc b/src/lib/dhcp/pkt4o6.cc index 4e9a055c95..6257e5082b 100644 --- a/src/lib/dhcp/pkt4o6.cc +++ b/src/lib/dhcp/pkt4o6.cc @@ -24,6 +24,97 @@ using namespace std; namespace isc { namespace dhcp { + +Pkt4o6Ptr Pkt4o6::fromPkt6(const Pkt6Ptr& pkt6) { + if (pkt6->getType() != DHCPV4_QUERY && + pkt6->getType() != DHCPV4_RESPONSE) { + isc_throw(Pkt4o6ConstructError, + "The DHCPv6 message is not DHCPV4_QUERY or DHCPV4_RESPONSE"); + } + OptionPtr opt = pkt6->getOption(OPTION_DHCPV4_MSG); + Pkt4o6Ptr pkt4o6; + if (opt) { + const OptionBuffer& data = opt->getData(); + pkt4o6 = Pkt4o6Ptr(new Pkt4o6(data.data(), data.size())); + pkt4o6->setFlags(pkt6->getTransid()); + pkt4o6->setPkt6RemoteAddr(pkt6->getRemoteAddr()); + pkt4o6->setPkt6LocalAddr(pkt6->getLocalAddr()); + pkt4o6->setPkt6Index(pkt6->getIndex()); + pkt4o6->setPkt6Iface(pkt6->getIface()); + } else { + isc_throw(Pkt4o6ConstructError, + "The DHCPv6 message doesn't contain a DHCPv4 Message Option"); + } + return pkt4o6; +} + +Pkt6Ptr Pkt4o6::toPkt6() { + unpack(); + Pkt6Ptr pkt6 = Pkt6Ptr(new Pkt6(DHCPV4_QUERY, 0)); + pkt6->setRemoteAddr(getPkt6RemoteAddr()); + pkt6->setLocalAddr(getPkt6LocalAddr()); + pkt6->setIndex(getPkt6Index()); + pkt6->setIface(getPkt6Iface()); + +// appendRequestedOptions(query, reply);//TODO: should we remove this? + + OptionPtr option(new Option(Option::V6, + OPTION_DHCPV4_MSG, + getDHCPv4MsgOption())); + pkt6->addOption(option); + + //Add relay info +// if (!query->relay_info_.empty()) { +// reply->copyRelayInfo(query); +// } + return pkt6; +} + +void Pkt4o6::pack() { +// Pkt4::pack(); + Pkt4::repack(); + + using boost::property_tree::ptree; + ptree pt; + + pt.put("RemoteAddr", getPkt6RemoteAddr().toText()); + pt.put("LocalAddr", getPkt6LocalAddr().toText()); +// pt.put("RemotePort", pkt6_->getRemotePort()); +// pt.put("LocalPort", pkt6_->getLocalPort()); + pt.put("Index", getPkt6Index()); + pt.put("Iface", getPkt6Iface()); + + pt.put("Flags", getFlags()); + std::stringstream sout; + write_json(sout, pt); + + buffer_ancillary_ = sout.str(); +} + +void Pkt4o6::unpack() { + Pkt4::unpack(); + + using boost::property_tree::ptree; + std::istringstream sin(buffer_ancillary_); + ptree pt; + read_json(sin, pt); + + try { + setPkt6RemoteAddr(isc::asiolink::IOAddress(pt.get("RemoteAddr"))); + setPkt6LocalAddr(isc::asiolink::IOAddress(pt.get("LocalAddr"))); +// pkt6_->setRemotePort(pt.get("RemotePort")); +// pkt6_->setLocalPort(pt.get("LocalPort")); + setPkt6Index(pt.get("Index")); + setPkt6Iface(pt.get("Iface")); + setFlags(pt.get("Flags")); + setIface(getPkt6Iface());//Use Pkt6's Iface to find a subnet + } catch (const std::exception& ex) { + //TODO: logging + } + setPkt4LocalAddr(); +} + +/* Pkt4o6::Pkt4o6(const uint8_t* data4, size_t len4, const uint8_t* data6, size_t len6) @@ -58,19 +149,16 @@ Pkt4o6::Pkt4o6(const Pkt4o6Ptr& pkt4o6, const Pkt4Ptr& pkt4) { pkt4_ = pkt4; pkt6_ = pkt4o6->getPkt6(); } - +*/ void Pkt4o6::setPkt4LocalAddr() { - if (pkt4_ && pkt6_) { - pkt6_->unpack(); - if (pkt6_->getTransid() & 0x800000) {//U flag is 1, pkt4 sent unicast - pkt4_->setLocalAddr(isc::asiolink::IOAddress("8.8.8.8")); - } else {//u flag is 0, pkt4 sent to broadcast - pkt4_->setLocalAddr(isc::asiolink::IOAddress("255.255.255.255")); - } + if (getFlags() & 0x800000) {//U flag is 1, pkt4 was sent unicast + setLocalAddr(isc::asiolink::IOAddress("8.8.8.8")); + } else {//u flag is 0, pkt4 was sent to broadcast + setLocalAddr(isc::asiolink::IOAddress("255.255.255.255")); } } - +/* std::string Pkt4o6::getJsonAttribute() { using boost::property_tree::ptree; @@ -105,10 +193,11 @@ Pkt4o6::setJsonAttribute(std::string json) { //TODO: logging } } - +*/ OptionBuffer Pkt4o6::getDHCPv4MsgOption() { - const isc::util::OutputBuffer &buf(pkt4_->getBuffer()); + Pkt4::pack(); + const isc::util::OutputBuffer &buf(Pkt4::getBuffer()); uint8_t* head = (uint8_t*)buf.getData(); OptionBuffer ret(head, head + buf.getLength()); return ret; diff --git a/src/lib/dhcp/pkt4o6.h b/src/lib/dhcp/pkt4o6.h index 53bb7dcda2..86e369ea88 100644 --- a/src/lib/dhcp/pkt4o6.h +++ b/src/lib/dhcp/pkt4o6.h @@ -42,79 +42,149 @@ typedef boost::shared_ptr Pkt4o6Ptr; /// It represents DHCPv4o6 packet by including a Pkt4ptr and a Pkt6ptr /// member variables. Generally the Pkt4ptr points to its DHCPv4 message /// content, and Pkt6ptr gives DHCPv6 information. -class Pkt4o6{ +class Pkt4o6 : public Pkt4 { public: - /// @brief Constructor, used in DHCP4o6IPC to construct Pkt4o6 from - /// raw data. + /// @brief Constructor, used in message reception. /// - /// It is used when a DHCP4o6IPC receives raw data from the other server. - /// It constructs internal Pkt4 and Pkt6 seperately using the given raw data. + /// Creates new 4o6 message. Call Pkt4's constructor. /// - /// @param data4 raw data of Pkt4 - /// @param len4 raw data length of Pkt4 - /// @param data6 raw data of Pkt6 - /// @param len6 raw data length of Pkt6 - Pkt4o6(const uint8_t* data4, size_t len4, - const uint8_t* data6, size_t len6); - - /// @brief Constructor, used in DHCPv6 server to construct Pkt4o6 from Pkt6. + /// @param data pointer to received data + /// @param len size of buffer to be allocated for this packet. + Pkt4o6(const uint8_t* data, size_t len) + : Pkt4(data, len), + pkt6_local_addr_("::"), + pkt6_remote_addr_("::") {} + + /// @brief Construct Pkt4o6 from Pkt6 /// - /// It is used when a DHCPv6 server receives a DHCPv4-query message, and - /// converts it into a DHCP4o6 message. - /// It constructs internal Pkt4 using the pkt6's DHCPv4 Message Option - /// - /// @throw Pkt4o6ConstructError if given mssage is not DHCPV4_QUERY or - /// DHCPV4_RESPONSE, or if OPTION_DHCPV4_MSG not found + /// Creates a new 4o6 message from DHCPv4-query message /// - /// @param pkt6 A DHCPv6 DHCPV4_QUERY message. - Pkt4o6(const Pkt6Ptr& pkt6); - - /// @brief Constructor, used in DHCPv4 server to construct Pkt4o6 from - /// Pkt4 response and Pkt4o6 query. + /// @param pkt6 pointer to a DHCPv4-query message + static Pkt4o6Ptr fromPkt6(const Pkt6Ptr& pkt6); + + /// @brief Construct Pkt6 from Pkt4o6 /// - /// It is used when a DHCPv4 server successfully produces a DHCPv4 reply - /// for a DHCP4o6 query. It converts the DHCPv4 reply into a DHCP4o6 message. + /// Creates a new DHCPv6 DHCPv4-query message from this 4o6 message + /// + /// @return pkt6 pointer to a new DHCPv4-query message + Pkt6Ptr toPkt6(); + + /// @brief Sets flags field in DHCPv4-query message /// - /// @param pkt4o6 a DHCPv4 over DHCPv6 message - /// @param pkt4 a DHCPv4 response message - Pkt4o6(const Pkt4o6Ptr& pkt4o6, const Pkt4Ptr& pkt4); + /// @param flags flags field in DHCPv4-query message + void setFlags(uint32_t flags) { flags_ = flags; } - /// @brief Get Pkt6 format of this DHCPv4 over DHCPv6 packet + /// @brief Returns flags field in DHCPv4-query message /// - /// @return A pointer to the Pkt6 object. - Pkt6Ptr getPkt6() const { return (pkt6_); } + /// @return flags field in DHCPv4-query message + uint32_t getFlags() { return flags_; } - /// @brief Get Pkt4 content of this DHCPv4 over DHCPv6 packet - /// @return A pointer to the Pkt4 object. - Pkt4Ptr getPkt4() const { return (pkt4_); } + /// @brief Prepares on-wire format of DHCPv4o6 packet. + /// + /// Prepares on-wire format of DHCPv4 message by calling Pkt4::pack(), + /// and prepares DHCP4o6 ancillary data to json-format string for transport. + /// + /// Method with throw exception if Pkt4::pack() throws + virtual void pack(); - /// @brief Json format of nessary information + /// @brief Parses on-wire form of DHCPv4o6 packet. /// - /// There are some nessary information that needs to be passed between - /// DHCPv4 and DHCPv6 servers, such as IPv6 addresses, ports, iface, etc. - /// The raw data of the DHCPv6 packet does not contain these information, - /// so we transmit them using json format string + /// Parses DHCPv4 packet by calling Pkt4::unpack(), and parses ancillary + /// data of DHCP4o6 from json-format string + /// + /// Method with throw exception if Pkt4::unpack() throws + virtual void unpack(); + + /// @brief Returns a string buffer of DHCP4o6 ancillary data /// - /// @return A json format string containing all necessary information - std::string getJsonAttribute(); + /// @return a string of DHCP4o6 ancillary data + std::string& + getBufferAncillary() { return (buffer_ancillary_); } - /// @brief Set Packet attributes according to a json format string - void setJsonAttribute(std::string json); + /// @brief Set string buffer of DHCP4o6 ancillary data + /// + /// @param buffer_ancillary a string of json-format DHCP4o6 ancillary data + void + setBufferAncillary(const std::string& buffer_ancillary) + { buffer_ancillary_ = buffer_ancillary; } /// @brief Get a DHCPv4MsgOption that contains pkt4_ /// /// @return A DHCPv4MsgOption OptionBuffer getDHCPv4MsgOption(); - /// @brief Set local address in pkt4_ according to U flag in pkt6_ - void setPkt4LocalAddr(); + /// @brief Sets remote address. + /// + /// @param remote specifies remote address + void setPkt6RemoteAddr(const isc::asiolink::IOAddress& remote) { pkt6_remote_addr_ = remote; } + + /// @brief Returns remote address + /// + /// @return remote address + const isc::asiolink::IOAddress& getPkt6RemoteAddr() const { + return (pkt6_remote_addr_); + } + + /// @brief Sets local address. + /// + /// @param local specifies local address + void setPkt6LocalAddr(const isc::asiolink::IOAddress& local) { pkt6_local_addr_ = local; } + + /// @brief Returns local address. + /// + /// @return local address + const isc::asiolink::IOAddress& getPkt6LocalAddr() const { + return (pkt6_local_addr_); + } + /// @brief Sets interface index. + /// + /// @param ifindex specifies interface index. + void setPkt6Index(uint32_t ifindex) { pkt6_ifindex_ = ifindex; }; + + /// @brief Returns interface index. + /// + /// @return interface index + uint32_t getPkt6Index() const { return (pkt6_ifindex_); }; + + /// @brief Returns interface name. + /// + /// Returns interface name over which packet was received or is + /// going to be transmitted. + /// + /// @return interface name + std::string getPkt6Iface() const { return pkt6_iface_; }; + + /// @brief Sets interface name. + /// + /// Sets interface name over which packet was received or is + /// going to be transmitted. + /// + /// @return interface name + void setPkt6Iface(const std::string& iface ) { pkt6_iface_ = iface; }; + protected: - /// @brief A poiner to a DHCPv4 packet - Pkt4Ptr pkt4_; + + /// @brief DHCP4o6 flags field, the same as transaction-id in DHCPv6 + uint32_t flags_; + + /// @brief local address in Pkt6 + isc::asiolink::IOAddress pkt6_local_addr_; + + /// @brief remote address in Pkt6 + isc::asiolink::IOAddress pkt6_remote_addr_; + + /// @brief name of the network interface the DHCP6 packet was received/to be sent over + std::string pkt6_iface_; + + /// @brief interface index of Pkt6 + int pkt6_ifindex_; + + /// @brief Set local address in pkt4 according to U flag in pkt6_ + void setPkt4LocalAddr(); - /// @brief A pointer to a DHCPv6 packet - Pkt6Ptr pkt6_; + /// @brief a json-format string containing ancillary data used by DHCP4o6 + std::string buffer_ancillary_; };// pkt4o6 class } // isc::dhcp namespace diff --git a/src/lib/dhcpsrv/dhcp4o6_ipc.cc b/src/lib/dhcpsrv/dhcp4o6_ipc.cc index e65241a58b..70eb29df61 100644 --- a/src/lib/dhcpsrv/dhcp4o6_ipc.cc +++ b/src/lib/dhcpsrv/dhcp4o6_ipc.cc @@ -23,24 +23,37 @@ DHCP4o6IPC::DHCP4o6IPC(const std::string& local_filename, const std::string& rem open(); } +void +DHCP4o6IPC::sendPkt4o6(const Pkt4Ptr& pkt4, const Pkt4o6Ptr& pkt4o6) { + if (!pkt4 || !pkt4o6) { + isc_throw(DHCP4o6IPCSendError, "NULL Packet"); + } + isc::util::OutputBuffer buf(0); + const isc::util::OutputBuffer &buf4(pkt4->getBuffer()); + size_t len = buf4.getLength(); + buf.writeData(&len, sizeof(size_t)); + buf.writeData(buf4.getData(), len); + const std::string &bufa(pkt4o6->getBufferAncillary()); + len = bufa.size(); + buf.writeData(&len, sizeof(size_t)); + buf.writeData(bufa.c_str(), len); + UnixSocket::send(buf); +} + void DHCP4o6IPC::sendPkt4o6(const Pkt4o6Ptr& pkt4o6) { if (!pkt4o6) { isc_throw(DHCP4o6IPCSendError, "NULL 4o6 Packet"); } isc::util::OutputBuffer buf(0); - const isc::util::OutputBuffer &buf4(pkt4o6->getPkt4()->getBuffer()); + const isc::util::OutputBuffer &buf4(pkt4o6->getBuffer()); size_t len = buf4.getLength(); buf.writeData(&len, sizeof(size_t)); buf.writeData(buf4.getData(), len); - const isc::util::OutputBuffer &buf6(pkt4o6->getPkt6()->getBuffer()); - len = buf6.getLength(); - buf.writeData(&len, sizeof(size_t)); - buf.writeData(buf6.getData(), len); - std::string att = pkt4o6->getJsonAttribute(); - len = att.size(); + const std::string &bufa(pkt4o6->getBufferAncillary()); + len = bufa.size(); buf.writeData(&len, sizeof(size_t)); - buf.writeData(att.c_str(), len); + buf.writeData(bufa.c_str(), len); UnixSocket::send(buf); } @@ -49,19 +62,16 @@ void DHCP4o6IPC::recvPkt4o6() { int len = receive(); isc::util::InputBuffer buf(getReceiveBuffer(), len); - size_t len4, len6, len_json; + size_t len4, len_json; uint8_t buf4[RCVBUFSIZE]; - uint8_t buf6[RCVBUFSIZE]; char buf_json[RCVBUFSIZE] = {0}; buf.readData(&len4, sizeof(size_t)); buf.readData(buf4, len4); - buf.readData(&len6, sizeof(size_t)); - buf.readData(buf6, len6); buf.readData(&len_json, sizeof(size_t)); buf.readData(buf_json, len_json); - Pkt4o6Ptr p(new Pkt4o6(buf4, len4, buf6, len6)); - p->setJsonAttribute(buf_json); + Pkt4o6Ptr p(new Pkt4o6(buf4, len4)); + p->setBufferAncillary(buf_json); queue_.push(p); } diff --git a/src/lib/dhcpsrv/dhcp4o6_ipc.h b/src/lib/dhcpsrv/dhcp4o6_ipc.h index 97a926850f..a836cab73b 100644 --- a/src/lib/dhcpsrv/dhcp4o6_ipc.h +++ b/src/lib/dhcpsrv/dhcp4o6_ipc.h @@ -51,6 +51,16 @@ public: /// @param pkt4o6 Pointer to the packet to be sent void sendPkt4o6(const Pkt4o6Ptr& pkt4o6); + /// @brief Send a DHCPv4 ove DHCPv6 packet + /// + /// This function converts Pkt4o6 into binary data and sends it + /// through UnixSocket::send(). + /// Method will throw if UnixSocket::send() failed + /// + /// @param pkt4 Pointer to the packet that contains DHCPv4 data + /// @param pkt4o6 Pointer to the packet that contains DHCP4o6 ancillary data + void sendPkt4o6(const Pkt4Ptr& pkt4, const Pkt4o6Ptr& pkt4o6); + /// @brief Receive a DHCPv4 ove DHCPv6 packet /// /// This function calls UnixSocket::recv() to receive binary data @@ -73,9 +83,6 @@ public: /// @return A pointer to the retrived Pkt4o6, or a null pointer if the /// queue is empty. Pkt4o6Ptr pop(); - - /// @brief Get the instance of current processing Pkt4o6 - Pkt4o6Ptr currentPkt4o6() { return current_; } protected: