nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
/*
|
|
|
|
* \brief DHCP client state model
|
|
|
|
* \author Martin Stein
|
|
|
|
* \date 2016-08-24
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2016-2017 Genode Labs GmbH
|
|
|
|
*
|
|
|
|
* This file is part of the Genode OS framework, which is distributed
|
|
|
|
* under the terms of the GNU Affero General Public License version 3.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* local includes */
|
|
|
|
#include <dhcp_client.h>
|
|
|
|
#include <interface.h>
|
|
|
|
#include <domain.h>
|
|
|
|
#include <configuration.h>
|
|
|
|
|
2018-04-06 17:34:01 +02:00
|
|
|
enum { PKT_SIZE = 1024 };
|
|
|
|
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
using namespace Genode;
|
|
|
|
using namespace Net;
|
2018-06-13 13:28:22 +02:00
|
|
|
using Message_type = Dhcp_packet::Message_type;
|
|
|
|
using Drop_packet = Net::Interface::Drop_packet;
|
|
|
|
using Dhcp_options = Dhcp_packet::Options_aggregator<Size_guard>;
|
2018-04-06 17:34:01 +02:00
|
|
|
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
|
2018-04-06 17:34:01 +02:00
|
|
|
/***************
|
|
|
|
** Utilities **
|
|
|
|
***************/
|
|
|
|
|
|
|
|
void append_param_req_list(Dhcp_options &dhcp_opts)
|
|
|
|
{
|
|
|
|
dhcp_opts.append_param_req_list([&] (Dhcp_options::Parameter_request_list_data &data) {
|
|
|
|
data.append_param_req<Dhcp_packet::Message_type_option>();
|
|
|
|
data.append_param_req<Dhcp_packet::Server_ipv4>();
|
|
|
|
data.append_param_req<Dhcp_packet::Ip_lease_time>();
|
|
|
|
data.append_param_req<Dhcp_packet::Dns_server_ipv4>();
|
|
|
|
data.append_param_req<Dhcp_packet::Subnet_mask>();
|
|
|
|
data.append_param_req<Dhcp_packet::Router_ipv4>();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*****************
|
|
|
|
** Dhcp_client **
|
|
|
|
*****************/
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
|
|
|
|
Configuration &Dhcp_client::_config() { return _domain().config(); };
|
|
|
|
|
|
|
|
|
|
|
|
Domain &Dhcp_client::_domain() { return _interface.domain(); }
|
|
|
|
|
|
|
|
|
|
|
|
Dhcp_client::Dhcp_client(Genode::Allocator &alloc,
|
|
|
|
Timer::Connection &timer,
|
|
|
|
Interface &interface)
|
|
|
|
:
|
|
|
|
_alloc(alloc), _interface(interface),
|
|
|
|
_timeout(timer, *this, &Dhcp_client::_handle_timeout)
|
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
|
|
void Dhcp_client::discover()
|
|
|
|
{
|
2017-11-28 15:03:28 +01:00
|
|
|
_set_state(State::SELECT, _config().dhcp_discover_timeout());
|
2018-04-04 17:25:52 +02:00
|
|
|
_send(Message_type::DISCOVER, Ipv4_address(), Ipv4_address(),
|
|
|
|
Ipv4_address());
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Dhcp_client::_rerequest(State next_state)
|
|
|
|
{
|
|
|
|
_set_state(next_state, _rerequest_timeout(2));
|
2018-04-04 17:25:52 +02:00
|
|
|
Ipv4_address const client_ip = _domain().ip_config().interface.address;
|
|
|
|
_send(Message_type::REQUEST, client_ip, Ipv4_address(), client_ip);
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Dhcp_client::_set_state(State state, Microseconds timeout)
|
|
|
|
{
|
|
|
|
_state = state;
|
|
|
|
_timeout.schedule(timeout);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Microseconds Dhcp_client::_rerequest_timeout(unsigned lease_time_div_log2)
|
|
|
|
{
|
|
|
|
/* FIXME limit the time because of shortcomings in timeout framework */
|
|
|
|
enum { MAX_TIMEOUT_SEC = 3600 };
|
2019-04-09 15:46:36 +02:00
|
|
|
uint64_t timeout_sec = _lease_time_sec >> lease_time_div_log2;
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
|
|
|
|
if (timeout_sec > MAX_TIMEOUT_SEC) {
|
|
|
|
timeout_sec = MAX_TIMEOUT_SEC;
|
2018-06-13 13:28:22 +02:00
|
|
|
if (_interface.config().verbose()) {
|
|
|
|
try {
|
|
|
|
log("[", _interface.domain(), "] prune re-request timeout of "
|
|
|
|
"DHCP client");
|
|
|
|
}
|
|
|
|
catch (Pointer<Domain>::Invalid) {
|
|
|
|
log("[?] prune re-request timeout of DHCP client"); }
|
|
|
|
}
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
}
|
2019-04-09 15:46:36 +02:00
|
|
|
return Microseconds(timeout_sec * 1000 * 1000);
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Dhcp_client::_handle_timeout(Duration)
|
|
|
|
{
|
|
|
|
switch (_state) {
|
2019-05-27 13:57:48 +02:00
|
|
|
case State::BOUND: _rerequest(State::RENEW); break;
|
|
|
|
case State::RENEW: _rerequest(State::REBIND); break;
|
|
|
|
case State::REBIND: _domain().discard_ip_config(); [[fallthrough]];
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
default: discover();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-03-05 11:27:44 +01:00
|
|
|
void Dhcp_client::handle_dhcp_reply(Dhcp_packet &dhcp)
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
{
|
2020-03-05 11:27:44 +01:00
|
|
|
try {
|
|
|
|
Message_type const msg_type =
|
|
|
|
dhcp.option<Dhcp_packet::Message_type_option>().value();
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
|
2020-03-05 11:27:44 +01:00
|
|
|
switch (_state) {
|
|
|
|
case State::SELECT:
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
|
2020-03-05 11:27:44 +01:00
|
|
|
if (msg_type != Message_type::OFFER) {
|
|
|
|
throw Drop_packet("DHCP client expects an offer");
|
|
|
|
}
|
|
|
|
_set_state(State::REQUEST, _config().dhcp_request_timeout());
|
|
|
|
_send(Message_type::REQUEST, Ipv4_address(),
|
|
|
|
dhcp.option<Dhcp_packet::Server_ipv4>().value(),
|
|
|
|
dhcp.yiaddr());
|
|
|
|
break;
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
|
2020-03-05 11:27:44 +01:00
|
|
|
case State::REQUEST:
|
|
|
|
{
|
|
|
|
if (msg_type != Message_type::ACK) {
|
|
|
|
throw Drop_packet("DHCP client expects an acknowledgement");
|
|
|
|
}
|
|
|
|
_lease_time_sec = dhcp.option<Dhcp_packet::Ip_lease_time>().value();
|
|
|
|
_set_state(State::BOUND, _rerequest_timeout(1));
|
2020-03-28 10:34:01 +01:00
|
|
|
|
2020-03-05 11:27:44 +01:00
|
|
|
Ipv4_address dns_server;
|
2020-03-28 10:34:01 +01:00
|
|
|
Ipv4_address subnet_mask;
|
|
|
|
Ipv4_address router_ip;
|
|
|
|
|
2020-03-05 11:27:44 +01:00
|
|
|
try { dns_server = dhcp.option<Dhcp_packet::Dns_server_ipv4>().value(); }
|
|
|
|
catch (Dhcp_packet::Option_not_found) { }
|
2020-03-28 10:34:01 +01:00
|
|
|
try { subnet_mask = dhcp.option<Dhcp_packet::Subnet_mask>().value(); }
|
|
|
|
catch (Dhcp_packet::Option_not_found) { }
|
|
|
|
try { router_ip = dhcp.option<Dhcp_packet::Router_ipv4>().value(); }
|
|
|
|
catch (Net::Dhcp_packet::Option_not_found) { }
|
|
|
|
|
|
|
|
_domain().ip_config(dhcp.yiaddr(), subnet_mask, router_ip,
|
2020-03-05 11:27:44 +01:00
|
|
|
dns_server);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case State::RENEW:
|
|
|
|
case State::REBIND:
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
|
2018-03-23 00:30:04 +01:00
|
|
|
if (msg_type != Message_type::ACK) {
|
2018-06-13 13:28:22 +02:00
|
|
|
throw Drop_packet("DHCP client expects an acknowledgement");
|
2018-03-23 00:30:04 +01:00
|
|
|
}
|
|
|
|
_set_state(State::BOUND, _rerequest_timeout(1));
|
2020-03-05 11:27:44 +01:00
|
|
|
_lease_time_sec = dhcp.option<Dhcp_packet::Ip_lease_time>().value();
|
2018-03-23 00:30:04 +01:00
|
|
|
break;
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
|
2020-03-05 11:27:44 +01:00
|
|
|
default: throw Drop_packet("DHCP client doesn't expect a packet");
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
}
|
2020-03-05 11:27:44 +01:00
|
|
|
}
|
|
|
|
catch (Dhcp_packet::Option_not_found) {
|
|
|
|
throw Drop_packet("DHCP reply misses required option");
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Dhcp_client::_send(Message_type msg_type,
|
|
|
|
Ipv4_address client_ip,
|
2018-04-04 17:25:52 +02:00
|
|
|
Ipv4_address server_ip,
|
|
|
|
Ipv4_address requested_ip)
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
{
|
|
|
|
Mac_address client_mac = _interface.router_mac();
|
2018-04-26 14:53:29 +02:00
|
|
|
_interface.send(PKT_SIZE, [&] (void *pkt_base, Size_guard &size_guard) {
|
2017-12-20 15:56:47 +01:00
|
|
|
|
|
|
|
/* create ETH header of the request */
|
2018-04-26 14:53:29 +02:00
|
|
|
Ethernet_frame ð = Ethernet_frame::construct_at(pkt_base, size_guard);
|
2017-12-20 15:56:47 +01:00
|
|
|
eth.dst(Mac_address(0xff));
|
|
|
|
eth.src(client_mac);
|
|
|
|
eth.type(Ethernet_frame::Type::IPV4);
|
|
|
|
|
|
|
|
/* create IP header of the request */
|
|
|
|
enum { IPV4_TIME_TO_LIVE = 64 };
|
2018-04-26 14:53:29 +02:00
|
|
|
size_t const ip_off = size_guard.head_size();
|
|
|
|
Ipv4_packet &ip = eth.construct_at_data<Ipv4_packet>(size_guard);
|
2017-12-20 15:56:47 +01:00
|
|
|
ip.header_length(sizeof(Ipv4_packet) / 4);
|
|
|
|
ip.version(4);
|
|
|
|
ip.time_to_live(IPV4_TIME_TO_LIVE);
|
|
|
|
ip.protocol(Ipv4_packet::Protocol::UDP);
|
|
|
|
ip.src(client_ip);
|
|
|
|
ip.dst(Ipv4_address(0xff));
|
|
|
|
|
|
|
|
/* create UDP header of the request */
|
2018-04-26 14:53:29 +02:00
|
|
|
size_t const udp_off = size_guard.head_size();
|
|
|
|
Udp_packet &udp = ip.construct_at_data<Udp_packet>(size_guard);
|
2017-12-20 15:56:47 +01:00
|
|
|
udp.src_port(Port(Dhcp_packet::BOOTPC));
|
|
|
|
udp.dst_port(Port(Dhcp_packet::BOOTPS));
|
|
|
|
|
|
|
|
/* create mandatory DHCP fields of the request */
|
2018-04-26 14:53:29 +02:00
|
|
|
size_t const dhcp_off = size_guard.head_size();
|
|
|
|
Dhcp_packet &dhcp = udp.construct_at_data<Dhcp_packet>(size_guard);
|
2017-12-20 15:56:47 +01:00
|
|
|
dhcp.op(Dhcp_packet::REQUEST);
|
|
|
|
dhcp.htype(Dhcp_packet::Htype::ETH);
|
|
|
|
dhcp.hlen(sizeof(Mac_address));
|
|
|
|
dhcp.ciaddr(client_ip);
|
|
|
|
dhcp.client_mac(client_mac);
|
|
|
|
dhcp.default_magic_cookie();
|
|
|
|
|
|
|
|
/* append DHCP option fields to the request */
|
2018-04-26 14:53:29 +02:00
|
|
|
Dhcp_options dhcp_opts(dhcp, size_guard);
|
2017-12-20 15:56:47 +01:00
|
|
|
dhcp_opts.append_option<Dhcp_packet::Message_type_option>(msg_type);
|
|
|
|
switch (msg_type) {
|
|
|
|
case Message_type::DISCOVER:
|
2018-04-06 17:34:01 +02:00
|
|
|
append_param_req_list(dhcp_opts);
|
2017-12-20 15:56:47 +01:00
|
|
|
dhcp_opts.append_option<Dhcp_packet::Client_id>(client_mac);
|
|
|
|
dhcp_opts.append_option<Dhcp_packet::Max_msg_size>(PKT_SIZE - dhcp_off);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case Message_type::REQUEST:
|
2018-04-06 17:34:01 +02:00
|
|
|
append_param_req_list(dhcp_opts);
|
2017-12-20 15:56:47 +01:00
|
|
|
dhcp_opts.append_option<Dhcp_packet::Client_id>(client_mac);
|
|
|
|
dhcp_opts.append_option<Dhcp_packet::Max_msg_size>(PKT_SIZE - dhcp_off);
|
|
|
|
if (_state == State::REQUEST) {
|
2018-04-04 17:25:52 +02:00
|
|
|
dhcp_opts.append_option<Dhcp_packet::Requested_addr>(requested_ip);
|
2017-12-20 15:56:47 +01:00
|
|
|
dhcp_opts.append_option<Dhcp_packet::Server_ipv4>(server_ip);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
throw Interface::Bad_send_dhcp_args();
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
}
|
2017-12-20 15:56:47 +01:00
|
|
|
dhcp_opts.append_option<Dhcp_packet::Options_end>();
|
|
|
|
|
|
|
|
/* fill in header values that need the packet to be complete already */
|
2018-04-26 14:53:29 +02:00
|
|
|
udp.length(size_guard.head_size() - udp_off);
|
2017-12-20 15:56:47 +01:00
|
|
|
udp.update_checksum(ip.src(), ip.dst());
|
2018-04-26 14:53:29 +02:00
|
|
|
ip.total_length(size_guard.head_size() - ip_off);
|
2018-04-17 00:35:16 +02:00
|
|
|
ip.update_checksum();
|
2017-12-20 15:56:47 +01:00
|
|
|
});
|
nic_router: DHCP client functionality
If the attribute 'interface' is not set in a 'domain' tag, the router tries to
dynamically receive and maintain an IP configuration for that domain by using
DHCP in the client role at all interfaces that connect to the domain. In the
DHCP discover phase, the router simply chooses the first DHCP offer that
arrives. So, no comparison of different DHCP offers is done. In the DHCP
request phase, the server is expected to provide an IP address, a gateway, a
subnet mask, and an IP lease time to the router. If anything substantial goes
wrong during a DHCP exchange, the router discards the outcome of the exchange
and goes back to the DHCP discover phase. At any time where there is no valid
IP configuration present at a domain, the domain does only act as DHCP client
and all other router functionality is disabled for the domain. A domain cannot
act as DHCP client and DHCP server at once. So, a 'domain' tag must either
have an 'interface' attribute or must not contain a 'dhcp-server' tag.
Ref #2534
2017-10-16 11:31:43 +02:00
|
|
|
}
|