// 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 {
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());
}
// 4o6
bool dhcp4o6Response = false;
if (!query && ipc_ && !ipc_->empty()) {
- query = ipc_->pop()->getPkt6();
+ query = ipc_->pop()->toPkt6();
dhcp4o6Response = true;
}
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_)) {
classifyPacket(query);
try {
- NameChangeRequestPtr ncr;
+ NameChangeRequestPtr ncr;
switch (query->getType()) {
case DHCPV6_SOLICIT:
rsp = processSolicit(query);
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());
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()) {
/// @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.
///
/// 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.
/// 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.
///
\r
namespace isc {\r
namespace dhcp {\r
+\r
+Pkt4o6Ptr Pkt4o6::fromPkt6(const Pkt6Ptr& pkt6) {\r
+ if (pkt6->getType() != DHCPV4_QUERY && \r
+ pkt6->getType() != DHCPV4_RESPONSE) {\r
+ isc_throw(Pkt4o6ConstructError,\r
+ "The DHCPv6 message is not DHCPV4_QUERY or DHCPV4_RESPONSE");\r
+ }\r
+ OptionPtr opt = pkt6->getOption(OPTION_DHCPV4_MSG);\r
+ Pkt4o6Ptr pkt4o6;\r
+ if (opt) {\r
+ const OptionBuffer& data = opt->getData();\r
+ pkt4o6 = Pkt4o6Ptr(new Pkt4o6(data.data(), data.size()));\r
+ pkt4o6->setFlags(pkt6->getTransid());\r
+ pkt4o6->setPkt6RemoteAddr(pkt6->getRemoteAddr());\r
+ pkt4o6->setPkt6LocalAddr(pkt6->getLocalAddr());\r
+ pkt4o6->setPkt6Index(pkt6->getIndex());\r
+ pkt4o6->setPkt6Iface(pkt6->getIface());\r
+ } else {\r
+ isc_throw(Pkt4o6ConstructError,\r
+ "The DHCPv6 message doesn't contain a DHCPv4 Message Option");\r
+ }\r
+ return pkt4o6;\r
+}\r
+\r
+Pkt6Ptr Pkt4o6::toPkt6() {\r
+ unpack();\r
+ Pkt6Ptr pkt6 = Pkt6Ptr(new Pkt6(DHCPV4_QUERY, 0));\r
+ pkt6->setRemoteAddr(getPkt6RemoteAddr());\r
+ pkt6->setLocalAddr(getPkt6LocalAddr());\r
+ pkt6->setIndex(getPkt6Index());\r
+ pkt6->setIface(getPkt6Iface());\r
+ \r
+// appendRequestedOptions(query, reply);//TODO: should we remove this?\r
+ \r
+ OptionPtr option(new Option(Option::V6,\r
+ OPTION_DHCPV4_MSG,\r
+ getDHCPv4MsgOption()));\r
+ pkt6->addOption(option);\r
+\r
+ //Add relay info\r
+// if (!query->relay_info_.empty()) {\r
+// reply->copyRelayInfo(query);\r
+// }\r
+ return pkt6;\r
+}\r
+\r
+void Pkt4o6::pack() {\r
+// Pkt4::pack();\r
+ Pkt4::repack();\r
+ \r
+ using boost::property_tree::ptree;\r
+ ptree pt;\r
+\r
+ pt.put("RemoteAddr", getPkt6RemoteAddr().toText());\r
+ pt.put("LocalAddr", getPkt6LocalAddr().toText());\r
+// pt.put("RemotePort", pkt6_->getRemotePort());\r
+// pt.put("LocalPort", pkt6_->getLocalPort());\r
+ pt.put("Index", getPkt6Index());\r
+ pt.put("Iface", getPkt6Iface());\r
+ \r
+ pt.put("Flags", getFlags());\r
+ std::stringstream sout;\r
+ write_json(sout, pt);\r
+\r
+ buffer_ancillary_ = sout.str();\r
+}\r
+\r
+void Pkt4o6::unpack() {\r
+ Pkt4::unpack();\r
+ \r
+ using boost::property_tree::ptree;\r
+ std::istringstream sin(buffer_ancillary_);\r
+ ptree pt;\r
+ read_json(sin, pt);\r
+\r
+ try {\r
+ setPkt6RemoteAddr(isc::asiolink::IOAddress(pt.get<std::string>("RemoteAddr")));\r
+ setPkt6LocalAddr(isc::asiolink::IOAddress(pt.get<std::string>("LocalAddr")));\r
+// pkt6_->setRemotePort(pt.get<uint16_t>("RemotePort"));\r
+// pkt6_->setLocalPort(pt.get<uint16_t>("LocalPort"));\r
+ setPkt6Index(pt.get<uint32_t>("Index"));\r
+ setPkt6Iface(pt.get<std::string>("Iface"));\r
+ setFlags(pt.get<uint32_t>("Flags"));\r
+ setIface(getPkt6Iface());//Use Pkt6's Iface to find a subnet\r
+ } catch (const std::exception& ex) {\r
+ //TODO: logging\r
+ }\r
+ setPkt4LocalAddr();\r
+}\r
+\r
+/*\r
\r
Pkt4o6::Pkt4o6(const uint8_t* data4, size_t len4,\r
const uint8_t* data6, size_t len6)\r
pkt4_ = pkt4;\r
pkt6_ = pkt4o6->getPkt6();\r
}\r
-\r
+*/\r
void\r
Pkt4o6::setPkt4LocalAddr() {\r
- if (pkt4_ && pkt6_) {\r
- pkt6_->unpack();\r
- if (pkt6_->getTransid() & 0x800000) {//U flag is 1, pkt4 sent unicast\r
- pkt4_->setLocalAddr(isc::asiolink::IOAddress("8.8.8.8"));\r
- } else {//u flag is 0, pkt4 sent to broadcast\r
- pkt4_->setLocalAddr(isc::asiolink::IOAddress("255.255.255.255"));\r
- }\r
+ if (getFlags() & 0x800000) {//U flag is 1, pkt4 was sent unicast\r
+ setLocalAddr(isc::asiolink::IOAddress("8.8.8.8"));\r
+ } else {//u flag is 0, pkt4 was sent to broadcast\r
+ setLocalAddr(isc::asiolink::IOAddress("255.255.255.255"));\r
}\r
}\r
-\r
+/*\r
std::string\r
Pkt4o6::getJsonAttribute() {\r
using boost::property_tree::ptree;\r
//TODO: logging\r
}\r
}\r
-\r
+*/\r
OptionBuffer\r
Pkt4o6::getDHCPv4MsgOption() {\r
- const isc::util::OutputBuffer &buf(pkt4_->getBuffer());\r
+ Pkt4::pack();\r
+ const isc::util::OutputBuffer &buf(Pkt4::getBuffer());\r
uint8_t* head = (uint8_t*)buf.getData();\r
OptionBuffer ret(head, head + buf.getLength());\r
return ret;\r
/// It represents DHCPv4o6 packet by including a Pkt4ptr and a Pkt6ptr \r
/// member variables. Generally the Pkt4ptr points to its DHCPv4 message\r
/// content, and Pkt6ptr gives DHCPv6 information.\r
-class Pkt4o6{\r
+class Pkt4o6 : public Pkt4 {\r
public:\r
- /// @brief Constructor, used in DHCP4o6IPC to construct Pkt4o6 from\r
- /// raw data.\r
+ /// @brief Constructor, used in message reception.\r
///\r
- /// It is used when a DHCP4o6IPC receives raw data from the other server.\r
- /// It constructs internal Pkt4 and Pkt6 seperately using the given raw data.\r
+ /// Creates new 4o6 message. Call Pkt4's constructor.\r
///\r
- /// @param data4 raw data of Pkt4\r
- /// @param len4 raw data length of Pkt4\r
- /// @param data6 raw data of Pkt6\r
- /// @param len6 raw data length of Pkt6\r
- Pkt4o6(const uint8_t* data4, size_t len4,\r
- const uint8_t* data6, size_t len6);\r
- \r
- /// @brief Constructor, used in DHCPv6 server to construct Pkt4o6 from Pkt6.\r
+ /// @param data pointer to received data\r
+ /// @param len size of buffer to be allocated for this packet.\r
+ Pkt4o6(const uint8_t* data, size_t len)\r
+ : Pkt4(data, len),\r
+ pkt6_local_addr_("::"),\r
+ pkt6_remote_addr_("::") {}\r
+\r
+ /// @brief Construct Pkt4o6 from Pkt6\r
///\r
- /// It is used when a DHCPv6 server receives a DHCPv4-query message, and \r
- /// converts it into a DHCP4o6 message.\r
- /// It constructs internal Pkt4 using the pkt6's DHCPv4 Message Option\r
- /// \r
- /// @throw Pkt4o6ConstructError if given mssage is not DHCPV4_QUERY or \r
- /// DHCPV4_RESPONSE, or if OPTION_DHCPV4_MSG not found\r
+ /// Creates a new 4o6 message from DHCPv4-query message\r
///\r
- /// @param pkt6 A DHCPv6 DHCPV4_QUERY message.\r
- Pkt4o6(const Pkt6Ptr& pkt6); \r
-\r
- /// @brief Constructor, used in DHCPv4 server to construct Pkt4o6 from\r
- /// Pkt4 response and Pkt4o6 query.\r
+ /// @param pkt6 pointer to a DHCPv4-query message\r
+ static Pkt4o6Ptr fromPkt6(const Pkt6Ptr& pkt6);\r
+ \r
+ /// @brief Construct Pkt6 from Pkt4o6\r
///\r
- /// It is used when a DHCPv4 server successfully produces a DHCPv4 reply\r
- /// for a DHCP4o6 query. It converts the DHCPv4 reply into a DHCP4o6 message.\r
+ /// Creates a new DHCPv6 DHCPv4-query message from this 4o6 message\r
+ ///\r
+ /// @return pkt6 pointer to a new DHCPv4-query message\r
+ Pkt6Ptr toPkt6();\r
+ \r
+ /// @brief Sets flags field in DHCPv4-query message\r
///\r
- /// @param pkt4o6 a DHCPv4 over DHCPv6 message\r
- /// @param pkt4 a DHCPv4 response message\r
- Pkt4o6(const Pkt4o6Ptr& pkt4o6, const Pkt4Ptr& pkt4);\r
+ /// @param flags flags field in DHCPv4-query message\r
+ void setFlags(uint32_t flags) { flags_ = flags; }\r
\r
- /// @brief Get Pkt6 format of this DHCPv4 over DHCPv6 packet\r
+ /// @brief Returns flags field in DHCPv4-query message\r
///\r
- /// @return A pointer to the Pkt6 object.\r
- Pkt6Ptr getPkt6() const { return (pkt6_); }\r
+ /// @return flags field in DHCPv4-query message \r
+ uint32_t getFlags() { return flags_; }\r
\r
- /// @brief Get Pkt4 content of this DHCPv4 over DHCPv6 packet\r
- /// @return A pointer to the Pkt4 object.\r
- Pkt4Ptr getPkt4() const { return (pkt4_); }\r
+ /// @brief Prepares on-wire format of DHCPv4o6 packet.\r
+ ///\r
+ /// Prepares on-wire format of DHCPv4 message by calling Pkt4::pack(),\r
+ /// and prepares DHCP4o6 ancillary data to json-format string for transport.\r
+ ///\r
+ /// Method with throw exception if Pkt4::pack() throws\r
+ virtual void pack();\r
\r
- /// @brief Json format of nessary information\r
+ /// @brief Parses on-wire form of DHCPv4o6 packet.\r
///\r
- /// There are some nessary information that needs to be passed between\r
- /// DHCPv4 and DHCPv6 servers, such as IPv6 addresses, ports, iface, etc.\r
- /// The raw data of the DHCPv6 packet does not contain these information,\r
- /// so we transmit them using json format string\r
+ /// Parses DHCPv4 packet by calling Pkt4::unpack(), and parses ancillary\r
+ /// data of DHCP4o6 from json-format string\r
+ ///\r
+ /// Method with throw exception if Pkt4::unpack() throws\r
+ virtual void unpack();\r
+ \r
+ /// @brief Returns a string buffer of DHCP4o6 ancillary data\r
///\r
- /// @return A json format string containing all necessary information\r
- std::string getJsonAttribute();\r
+ /// @return a string of DHCP4o6 ancillary data\r
+ std::string&\r
+ getBufferAncillary() { return (buffer_ancillary_); }\r
\r
- /// @brief Set Packet attributes according to a json format string\r
- void setJsonAttribute(std::string json);\r
+ /// @brief Set string buffer of DHCP4o6 ancillary data\r
+ ///\r
+ /// @param buffer_ancillary a string of json-format DHCP4o6 ancillary data\r
+ void\r
+ setBufferAncillary(const std::string& buffer_ancillary)\r
+ { buffer_ancillary_ = buffer_ancillary; }\r
\r
/// @brief Get a DHCPv4MsgOption that contains pkt4_\r
///\r
/// @return A DHCPv4MsgOption\r
OptionBuffer getDHCPv4MsgOption();\r
\r
- /// @brief Set local address in pkt4_ according to U flag in pkt6_\r
- void setPkt4LocalAddr();\r
+ /// @brief Sets remote address.\r
+ ///\r
+ /// @param remote specifies remote address\r
+ void setPkt6RemoteAddr(const isc::asiolink::IOAddress& remote) { pkt6_remote_addr_ = remote; }\r
+\r
+ /// @brief Returns remote address\r
+ ///\r
+ /// @return remote address\r
+ const isc::asiolink::IOAddress& getPkt6RemoteAddr() const {\r
+ return (pkt6_remote_addr_);\r
+ }\r
+ \r
+ /// @brief Sets local address.\r
+ ///\r
+ /// @param local specifies local address\r
+ void setPkt6LocalAddr(const isc::asiolink::IOAddress& local) { pkt6_local_addr_ = local; }\r
+\r
+ /// @brief Returns local address.\r
+ ///\r
+ /// @return local address\r
+ const isc::asiolink::IOAddress& getPkt6LocalAddr() const {\r
+ return (pkt6_local_addr_);\r
+ }\r
\r
+ /// @brief Sets interface index.\r
+ ///\r
+ /// @param ifindex specifies interface index.\r
+ void setPkt6Index(uint32_t ifindex) { pkt6_ifindex_ = ifindex; };\r
+\r
+ /// @brief Returns interface index.\r
+ ///\r
+ /// @return interface index\r
+ uint32_t getPkt6Index() const { return (pkt6_ifindex_); };\r
+\r
+ /// @brief Returns interface name.\r
+ ///\r
+ /// Returns interface name over which packet was received or is\r
+ /// going to be transmitted.\r
+ ///\r
+ /// @return interface name\r
+ std::string getPkt6Iface() const { return pkt6_iface_; };\r
+\r
+ /// @brief Sets interface name.\r
+ ///\r
+ /// Sets interface name over which packet was received or is\r
+ /// going to be transmitted.\r
+ ///\r
+ /// @return interface name\r
+ void setPkt6Iface(const std::string& iface ) { pkt6_iface_ = iface; };\r
+ \r
protected:\r
- /// @brief A poiner to a DHCPv4 packet\r
- Pkt4Ptr pkt4_;\r
+\r
+ /// @brief DHCP4o6 flags field, the same as transaction-id in DHCPv6\r
+ uint32_t flags_;\r
+ \r
+ /// @brief local address in Pkt6\r
+ isc::asiolink::IOAddress pkt6_local_addr_;\r
+\r
+ /// @brief remote address in Pkt6\r
+ isc::asiolink::IOAddress pkt6_remote_addr_;\r
+ \r
+ /// @brief name of the network interface the DHCP6 packet was received/to be sent over\r
+ std::string pkt6_iface_;\r
+\r
+ /// @brief interface index of Pkt6\r
+ int pkt6_ifindex_;\r
+ \r
+ /// @brief Set local address in pkt4 according to U flag in pkt6_\r
+ void setPkt4LocalAddr();\r
\r
- /// @brief A pointer to a DHCPv6 packet\r
- Pkt6Ptr pkt6_; \r
+ /// @brief a json-format string containing ancillary data used by DHCP4o6\r
+ std::string buffer_ancillary_;\r
};// pkt4o6 class\r
\r
} // isc::dhcp namespace\r
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);
}
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);
}
/// @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
/// @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: