|
@@ -127,6 +127,55 @@ Dhcpv4Exchange::initResponse() {
|
|
}
|
|
}
|
|
if (resp_type > 0) {
|
|
if (resp_type > 0) {
|
|
resp_.reset(new Pkt4(resp_type, getQuery()->getTransid()));
|
|
resp_.reset(new Pkt4(resp_type, getQuery()->getTransid()));
|
|
|
|
+ copyDefaultFields();
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void
|
|
|
|
+Dhcpv4Exchange::copyDefaultFields() {
|
|
|
|
+ resp_->setIface(query_->getIface());
|
|
|
|
+ resp_->setIndex(query_->getIndex());
|
|
|
|
+
|
|
|
|
+ resp_->setSiaddr(IOAddress::IPV4_ZERO_ADDRESS()); // explicitly set this to 0
|
|
|
|
+ // ciaddr is always 0, except for the Renew/Rebind state when it may
|
|
|
|
+ // be set to the ciaddr sent by the client.
|
|
|
|
+ resp_->setCiaddr(IOAddress::IPV4_ZERO_ADDRESS());
|
|
|
|
+ resp_->setHops(query_->getHops());
|
|
|
|
+
|
|
|
|
+ // copy MAC address
|
|
|
|
+ resp_->setHWAddr(query_->getHWAddr());
|
|
|
|
+
|
|
|
|
+ // relay address
|
|
|
|
+ resp_->setGiaddr(query_->getGiaddr());
|
|
|
|
+
|
|
|
|
+ // Let's copy client-id to response. See RFC6842.
|
|
|
|
+ // It is possible to disable RFC6842 to keep backward compatibility
|
|
|
|
+ bool echo = CfgMgr::instance().echoClientId();
|
|
|
|
+ OptionPtr client_id = query_->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
|
|
|
|
+ if (client_id && echo) {
|
|
|
|
+ resp_->addOption(client_id);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // If src/dest HW addresses are used by the packet filtering class
|
|
|
|
+ // we need to copy them as well. There is a need to check that the
|
|
|
|
+ // address being set is not-NULL because an attempt to set the NULL
|
|
|
|
+ // HW would result in exception. If these values are not set, the
|
|
|
|
+ // the default HW addresses (zeroed) should be generated by the
|
|
|
|
+ // packet filtering class when creating Ethernet header for
|
|
|
|
+ // outgoing packet.
|
|
|
|
+ HWAddrPtr src_hw_addr = query_->getLocalHWAddr();
|
|
|
|
+ if (src_hw_addr) {
|
|
|
|
+ resp_->setLocalHWAddr(src_hw_addr);
|
|
|
|
+ }
|
|
|
|
+ HWAddrPtr dst_hw_addr = query_->getRemoteHWAddr();
|
|
|
|
+ if (dst_hw_addr) {
|
|
|
|
+ resp_->setRemoteHWAddr(dst_hw_addr);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // If this packet is relayed, we want to copy Relay Agent Info option
|
|
|
|
+ OptionPtr rai = query_->getOption(DHO_DHCP_AGENT_OPTIONS);
|
|
|
|
+ if (rai) {
|
|
|
|
+ resp_->addOption(rai);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -604,54 +653,6 @@ Dhcpv4Srv::computeDhcid(const Lease4Ptr& lease) {
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
void
|
|
-Dhcpv4Srv::copyDefaultFields(Dhcpv4Exchange& ex) {
|
|
|
|
- ex.getResponse()->setIface(ex.getQuery()->getIface());
|
|
|
|
- ex.getResponse()->setIndex(ex.getQuery()->getIndex());
|
|
|
|
-
|
|
|
|
- ex.getResponse()->setSiaddr(IOAddress::IPV4_ZERO_ADDRESS()); // explicitly set this to 0
|
|
|
|
- // ciaddr is always 0, except for the Renew/Rebind state when it may
|
|
|
|
- // be set to the ciaddr sent by the client.
|
|
|
|
- ex.getResponse()->setCiaddr(IOAddress::IPV4_ZERO_ADDRESS());
|
|
|
|
- ex.getResponse()->setHops(ex.getQuery()->getHops());
|
|
|
|
-
|
|
|
|
- // copy MAC address
|
|
|
|
- ex.getResponse()->setHWAddr(ex.getQuery()->getHWAddr());
|
|
|
|
-
|
|
|
|
- // relay address
|
|
|
|
- ex.getResponse()->setGiaddr(ex.getQuery()->getGiaddr());
|
|
|
|
-
|
|
|
|
- // Let's copy client-id to response. See RFC6842.
|
|
|
|
- // It is possible to disable RFC6842 to keep backward compatibility
|
|
|
|
- bool echo = CfgMgr::instance().echoClientId();
|
|
|
|
- OptionPtr client_id = ex.getQuery()->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
|
|
|
|
- if (client_id && echo) {
|
|
|
|
- ex.getResponse()->addOption(client_id);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // If src/dest HW addresses are used by the packet filtering class
|
|
|
|
- // we need to copy them as well. There is a need to check that the
|
|
|
|
- // address being set is not-NULL because an attempt to set the NULL
|
|
|
|
- // HW would result in exception. If these values are not set, the
|
|
|
|
- // the default HW addresses (zeroed) should be generated by the
|
|
|
|
- // packet filtering class when creating Ethernet header for
|
|
|
|
- // outgoing packet.
|
|
|
|
- HWAddrPtr src_hw_addr = ex.getQuery()->getLocalHWAddr();
|
|
|
|
- if (src_hw_addr) {
|
|
|
|
- ex.getResponse()->setLocalHWAddr(src_hw_addr);
|
|
|
|
- }
|
|
|
|
- HWAddrPtr dst_hw_addr = ex.getQuery()->getRemoteHWAddr();
|
|
|
|
- if (dst_hw_addr) {
|
|
|
|
- ex.getResponse()->setRemoteHWAddr(dst_hw_addr);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // If this packet is relayed, we want to copy Relay Agent Info option
|
|
|
|
- OptionPtr rai = ex.getQuery()->getOption(DHO_DHCP_AGENT_OPTIONS);
|
|
|
|
- if (rai) {
|
|
|
|
- ex.getResponse()->addOption(rai);
|
|
|
|
- }
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-void
|
|
|
|
Dhcpv4Srv::appendDefaultOptions(Dhcpv4Exchange& ex) {
|
|
Dhcpv4Srv::appendDefaultOptions(Dhcpv4Exchange& ex) {
|
|
// no-op at this time
|
|
// no-op at this time
|
|
}
|
|
}
|
|
@@ -680,26 +681,30 @@ Dhcpv4Srv::appendRequestedOptions(Dhcpv4Exchange& ex) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ Pkt4Ptr query = ex.getQuery();
|
|
|
|
+
|
|
// try to get the 'Parameter Request List' option which holds the
|
|
// try to get the 'Parameter Request List' option which holds the
|
|
// codes of requested options.
|
|
// codes of requested options.
|
|
OptionUint8ArrayPtr option_prl = boost::dynamic_pointer_cast<
|
|
OptionUint8ArrayPtr option_prl = boost::dynamic_pointer_cast<
|
|
- OptionUint8Array>(ex.getQuery()->getOption(DHO_DHCP_PARAMETER_REQUEST_LIST));
|
|
|
|
|
|
+ OptionUint8Array>(query->getOption(DHO_DHCP_PARAMETER_REQUEST_LIST));
|
|
// If there is no PRL option in the message from the client then
|
|
// If there is no PRL option in the message from the client then
|
|
// there is nothing to do.
|
|
// there is nothing to do.
|
|
if (!option_prl) {
|
|
if (!option_prl) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ Pkt4Ptr resp = ex.getResponse();
|
|
|
|
+
|
|
// Get the codes of requested options.
|
|
// Get the codes of requested options.
|
|
const std::vector<uint8_t>& requested_opts = option_prl->getValues();
|
|
const std::vector<uint8_t>& requested_opts = option_prl->getValues();
|
|
// For each requested option code get the instance of the option
|
|
// For each requested option code get the instance of the option
|
|
// to be returned to the client.
|
|
// to be returned to the client.
|
|
for (std::vector<uint8_t>::const_iterator opt = requested_opts.begin();
|
|
for (std::vector<uint8_t>::const_iterator opt = requested_opts.begin();
|
|
opt != requested_opts.end(); ++opt) {
|
|
opt != requested_opts.end(); ++opt) {
|
|
- if (!ex.getResponse()->getOption(*opt)) {
|
|
|
|
|
|
+ if (!resp->getOption(*opt)) {
|
|
OptionDescriptor desc = subnet->getCfgOption()->get("dhcp4", *opt);
|
|
OptionDescriptor desc = subnet->getCfgOption()->get("dhcp4", *opt);
|
|
if (desc.option_) {
|
|
if (desc.option_) {
|
|
- ex.getResponse()->addOption(desc.option_);
|
|
|
|
|
|
+ resp->addOption(desc.option_);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -780,16 +785,18 @@ Dhcpv4Srv::appendBasicOptions(Dhcpv4Exchange& ex) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ Pkt4Ptr resp = ex.getResponse();
|
|
|
|
+
|
|
// Try to find all 'required' options in the outgoing
|
|
// Try to find all 'required' options in the outgoing
|
|
// message. Those that are not present will be added.
|
|
// message. Those that are not present will be added.
|
|
for (int i = 0; i < required_options_size; ++i) {
|
|
for (int i = 0; i < required_options_size; ++i) {
|
|
- OptionPtr opt = ex.getResponse()->getOption(required_options[i]);
|
|
|
|
|
|
+ OptionPtr opt = resp->getOption(required_options[i]);
|
|
if (!opt) {
|
|
if (!opt) {
|
|
// Check whether option has been configured.
|
|
// Check whether option has been configured.
|
|
OptionDescriptor desc = subnet->getCfgOption()->
|
|
OptionDescriptor desc = subnet->getCfgOption()->
|
|
get("dhcp4", required_options[i]);
|
|
get("dhcp4", required_options[i]);
|
|
if (desc.option_) {
|
|
if (desc.option_) {
|
|
- ex.getResponse()->addOption(desc.option_);
|
|
|
|
|
|
+ resp->addOption(desc.option_);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -1453,7 +1460,6 @@ Dhcpv4Srv::processDiscover(Pkt4Ptr& discover) {
|
|
|
|
|
|
Dhcpv4Exchange ex(alloc_engine_, discover, selectSubnet(discover));
|
|
Dhcpv4Exchange ex(alloc_engine_, discover, selectSubnet(discover));
|
|
|
|
|
|
- copyDefaultFields(ex);
|
|
|
|
appendDefaultOptions(ex);
|
|
appendDefaultOptions(ex);
|
|
|
|
|
|
// If DHCPDISCOVER message contains the FQDN or Hostname option, server
|
|
// If DHCPDISCOVER message contains the FQDN or Hostname option, server
|
|
@@ -1507,7 +1513,6 @@ Dhcpv4Srv::processRequest(Pkt4Ptr& request) {
|
|
|
|
|
|
Dhcpv4Exchange ex(alloc_engine_, request, selectSubnet(request));
|
|
Dhcpv4Exchange ex(alloc_engine_, request, selectSubnet(request));
|
|
|
|
|
|
- copyDefaultFields(ex);
|
|
|
|
appendDefaultOptions(ex);
|
|
appendDefaultOptions(ex);
|
|
|
|
|
|
// If DHCPREQUEST message contains the FQDN or Hostname option, server
|
|
// If DHCPREQUEST message contains the FQDN or Hostname option, server
|
|
@@ -1677,7 +1682,6 @@ Dhcpv4Srv::processInform(Pkt4Ptr& inform) {
|
|
|
|
|
|
Pkt4Ptr ack = ex.getResponse();
|
|
Pkt4Ptr ack = ex.getResponse();
|
|
|
|
|
|
- copyDefaultFields(ex);
|
|
|
|
appendRequestedOptions(ex);
|
|
appendRequestedOptions(ex);
|
|
appendRequestedVendorOptions(ex);
|
|
appendRequestedVendorOptions(ex);
|
|
appendBasicOptions(ex);
|
|
appendBasicOptions(ex);
|