summaryrefslogtreecommitdiff
path: root/src/core/dhcp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/dhcp')
-rw-r--r--src/core/dhcp/README.next.md103
-rw-r--r--src/core/dhcp/nm-dhcp-client.c1087
-rw-r--r--src/core/dhcp/nm-dhcp-client.h259
-rw-r--r--src/core/dhcp/nm-dhcp-dhclient-utils.c1
-rw-r--r--src/core/dhcp/nm-dhcp-dhclient.c145
-rw-r--r--src/core/dhcp/nm-dhcp-dhcpcanon.c2
-rw-r--r--src/core/dhcp/nm-dhcp-dhcpcd.c22
-rw-r--r--src/core/dhcp/nm-dhcp-manager.c321
-rw-r--r--src/core/dhcp/nm-dhcp-manager.h48
-rw-r--r--src/core/dhcp/nm-dhcp-nettools.c338
-rw-r--r--src/core/dhcp/nm-dhcp-systemd.c334
-rw-r--r--src/core/dhcp/nm-dhcp-utils.c299
-rw-r--r--src/core/dhcp/nm-dhcp-utils.h31
-rw-r--r--src/core/dhcp/tests/test-dhcp-dhclient.c1
-rw-r--r--src/core/dhcp/tests/test-dhcp-utils.c567
15 files changed, 1536 insertions, 2022 deletions
diff --git a/src/core/dhcp/README.next.md b/src/core/dhcp/README.next.md
new file mode 100644
index 0000000000..88fa6683c7
--- /dev/null
+++ b/src/core/dhcp/README.next.md
@@ -0,0 +1,103 @@
+`NMDhcpClient`
+==============
+
+Using `NMDhcpClient` still requires a lot of logic in `NMDevice`. The main goal
+is to simplify `NMDevice`, so `NMDhcpClient` must become more complicated to
+provide a simpler (but robust) API.
+
+NMDevice has basically two timeouts (talking about IPv4, but it applies
+similarly to IPv6): `ipv4.dhcp-timeout` and `ipv4.required-timeout`. They
+control how long NMDevice is willing to try, before failing the activation
+altogether. Note that with `ipv4.may-fail=yes`, we may very well never want to
+fail the activation entirely, regardless how DHCP is doing. In that case we
+want to stay up, but also constantly retrying whether we cannot get a lease and
+recover.
+
+Currently, if `NMDhcpClient` signals a failure, then it's basically up to
+`NMDevice` to schedule and retry. That is complicated, and we should move the
+complexity out of `NMDevice`.
+
+`NMDhcpClient` should have a simpler API:
+
+- `nm_dhcp_manager_start_ip[46]()`: creates (and starts) a `NMDhcpClient`
+ instance. The difference is, this function tries really hard not to fail
+ to create an `NMDhcpClient`. There is no explicit `start()`, but note that the
+ instance must not emit any signals before the next maincontext iteration. That is,
+ it only will call back the user after a timeout/idle or some other IO event, which
+ happens during a future iteration of the maincontext.
+
+- `nm_dhcp_client_stop()`: when `NMDevice` is done with the `NMDhcpClient`
+ instance, it will stop it and throw it away. This method exists because
+ `NMDhcpClient` is a `GObject` and ref-counted. Thus, we don't want to rely on
+ the last unref to stop the instance, but have an explicit stop. After stop, the
+ instance is defunct and won't emit any signals anymore. The class does not need
+ to support restarting a stopped instance. If `NMDevice` wants to restart DHCP, it
+ should create a new one. `NMDevice` would only want to do that, if the parameters
+ change, hence a new instance is in order (and no need for the complexity of
+ restart in `NMDhcpClient`).
+
+- as already now, `NMDhcpClient` is not very configurable. You provide most
+ (all) parameters during `nm_dhcp_manager_start_ip[46]()`, and then it keeps
+ running until stop.
+
+- `NMDhcpClient` exposes a simple state to the user:
+
+ 1. "no lease, but good". When starting, there is no lease, but we are
+ optimistic to get one. This is the inital state, but we can also get back to
+ this state after we had a lease (which might expire).
+
+ 1. "has a lease". Here there is no need to distinguish whether the current
+ lease was the first we received, or whether this was an update. In this state,
+ the instance has a lease and we are good.
+
+ 1. "no lease, but bad". `NMDhcpClient` tries really hard, and "bad" does not
+ mean that it gave up. It will keep retrying, it's just that there is little
+ hope of getting a new lease. This happens, when you try to run DHCP on a Layer3
+ link (WireGuard). There is little hope to succeed, but `NMDhcpClient`
+ (theoretically) will retry and may recover from this. Another example is when
+ we fail to start dhclient because it's not installed. In that case, we are not
+ optimistic to recover, however `NMDhcpDhclient` will retry (with backoff
+ timeout) and might still recover from this. For most cases, `NMDevice` will
+ treat the no-lease cases the same, but in case of "bad" it might give up
+ earlier.
+
+When a lease expires, that does not necessarily mean that we are now in a bad
+state. It might mean that the DHCP server is temporarily down, but we might
+recover from that easily. "bad" really means, something is wrong on our side
+which prevents us from getting a lease. Also, imagine `dhclient` dies (we would
+try to restart, but assume that fails too), but we still have a valid lease,
+then possibly `NMDhcpClient` should still pretend all is good and we still have
+a lease until it expires. It may be we can recover before that happens. The
+point of all of this, is to hide errors as much as possibly and automatically
+recover. `NMDevice` will decide to tear down, if we didn't get a lease after
+`ipv4.dhcp-timeout`. That's the main criteria, and it might not even
+distinguish between "no lease, but good" and "no lease, but bad".
+
+- `NMDhcpClient` will also take care of the `ipv4.dhcp-timeout` grace period.
+ That timeout is provided during start, and starts ticking whenever there is
+ no lease. When it expires, a timeout signal gets emitted. That's it. This is
+ independent from the 3 states above, and only saves `NMDevice` from scheduling
+ this timer themselves.
+ This is NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT notification.
+
+- for nettools, `nm_dhcp_client_can_accept()` indicates that when we receive a
+ lease, we need to accept/decline it first. In that case, `NMDevice`
+optionally does ACD first, then configures the IP address first and calls
+`nm_dhcp_client_accept()`. In case of ACD conflict, it will call
+`nm_dhcp_client_decline()` (which optimally causes `NMDhcpClient` to get a
+different lease). With this, the above state "has a lease" has actually three
+flavors: "has a lease but not yet ACD probed" and "has a lease but
+accepted/declined" (but `NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED` gets only emitted
+when we get the lease, not when we accept/decline it). With `dhclient`, when we
+receive a lease, it means "has a lease but accepted" right away.
+
+- for IPv6 prefix delegation, there is also `needed_prefixes` and
+ `NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED`. Currently `needed_prefixes` needs
+ to be specified during start (which simplifies things). Maybe `needed_prefixes`
+ should be changable at runtime. Otherwise, whether we have prefixes is similar
+ to whether we have a lease, and the simple 3 states apply.
+
+When NetworkManager quits, it may want to leave the interface up. In that case,
+we still always want to stop the DHCP client, but possibly not deconfiguring
+the interface. I don't think that this concerns `NMDhcpClient`, because `NMDhcpClient`
+only provides the lease information and `NMDevice` is responsible to configure it.
diff --git a/src/core/dhcp/nm-dhcp-client.c b/src/core/dhcp/nm-dhcp-client.c
index f88c79c0be..6f71a44501 100644
--- a/src/core/dhcp/nm-dhcp-client.c
+++ b/src/core/dhcp/nm-dhcp-client.c
@@ -20,9 +20,13 @@
#include "NetworkManagerUtils.h"
#include "nm-utils.h"
+#include "nm-l3cfg.h"
+#include "nm-l3-config-data.h"
#include "nm-dhcp-utils.h"
#include "nm-dhcp-options.h"
#include "libnm-platform/nm-platform.h"
+#include "nm-hostname-manager.h"
+#include "libnm-systemd-shared/nm-sd-utils-shared.h"
#include "nm-dhcp-client-logging.h"
@@ -32,53 +36,19 @@ enum { SIGNAL_NOTIFY, LAST_SIGNAL };
static guint signals[LAST_SIGNAL] = {0};
-NM_GOBJECT_PROPERTIES_DEFINE(NMDhcpClient,
- PROP_ADDR_FAMILY,
- PROP_ANYCAST_ADDRESS,
- PROP_FLAGS,
- PROP_HWADDR,
- PROP_BROADCAST_HWADDR,
- PROP_IFACE,
- PROP_IFINDEX,
- PROP_MULTI_IDX,
- PROP_ROUTE_METRIC,
- PROP_ROUTE_TABLE,
- PROP_TIMEOUT,
- PROP_UUID,
- PROP_IAID,
- PROP_IAID_EXPLICIT,
- PROP_HOSTNAME,
- PROP_HOSTNAME_FLAGS,
- PROP_MUD_URL,
- PROP_VENDOR_CLASS_IDENTIFIER,
- PROP_REJECT_SERVERS, );
+NM_GOBJECT_PROPERTIES_DEFINE(NMDhcpClient, PROP_CONFIG, );
typedef struct _NMDhcpClientPrivate {
- NMDedupMultiIndex * multi_idx;
- char * iface;
- GBytes * hwaddr;
- GBytes * bcast_hwaddr;
- char * uuid;
- GBytes * client_id;
- char * hostname;
- const char ** reject_servers;
- char * mud_url;
- char * anycast_address;
- GBytes * vendor_class_identifier;
- pid_t pid;
- guint timeout_id;
- guint watch_id;
- int addr_family;
- int ifindex;
- guint32 route_table;
- guint32 route_metric;
- guint32 timeout;
- guint32 iaid;
- NMDhcpState state;
- NMDhcpHostnameFlags hostname_flags;
- NMDhcpClientFlags client_flags;
- bool iaid_explicit : 1;
- bool is_stopped : 1;
+ NMDhcpClientConfig config;
+ const NML3ConfigData *l3cd;
+ GSource * no_lease_timeout_source;
+ pid_t pid;
+ guint timeout_id;
+ guint watch_id;
+ NMDhcpState state;
+ bool iaid_explicit : 1;
+ bool is_stopped : 1;
+ GBytes * effective_client_id;
} NMDhcpClientPrivate;
G_DEFINE_ABSTRACT_TYPE(NMDhcpClient, nm_dhcp_client, G_TYPE_OBJECT)
@@ -98,25 +68,6 @@ _emit_notify(NMDhcpClient *self, const NMDhcpClientNotifyData *notify_data)
g_signal_emit(G_OBJECT(self), signals[SIGNAL_NOTIFY], 0, notify_data);
}
-static void
-_emit_notify_state_changed(NMDhcpClient *self,
- NMDhcpState dhcp_state,
- NMIPConfig * ip_config,
- GHashTable * options)
-{
- const NMDhcpClientNotifyData notify_data = {
- .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED,
- .state_changed =
- {
- .dhcp_state = dhcp_state,
- .ip_config = ip_config,
- .options = options,
- },
- };
-
- _emit_notify(self, &notify_data);
-}
-
/*****************************************************************************/
pid_t
@@ -127,149 +78,24 @@ nm_dhcp_client_get_pid(NMDhcpClient *self)
return NM_DHCP_CLIENT_GET_PRIVATE(self)->pid;
}
-NMDedupMultiIndex *
-nm_dhcp_client_get_multi_idx(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->multi_idx;
-}
-
-const char *
-nm_dhcp_client_get_iface(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->iface;
-}
-
-int
-nm_dhcp_client_get_ifindex(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), -1);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->ifindex;
-}
-
-int
-nm_dhcp_client_get_addr_family(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), AF_UNSPEC);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->addr_family;
-}
-
-const char *
-nm_dhcp_client_get_uuid(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->uuid;
-}
-
-GBytes *
-nm_dhcp_client_get_hw_addr(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->hwaddr;
-}
-
-GBytes *
-nm_dhcp_client_get_broadcast_hw_addr(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->bcast_hwaddr;
-}
-
-guint32
-nm_dhcp_client_get_route_table(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), RT_TABLE_MAIN);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->route_table;
-}
-
-void
-nm_dhcp_client_set_route_table(NMDhcpClient *self, guint32 route_table)
-{
- NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
-
- if (route_table != priv->route_table) {
- priv->route_table = route_table;
- _notify(self, PROP_ROUTE_TABLE);
- }
-}
-
-guint32
-nm_dhcp_client_get_route_metric(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), G_MAXUINT32);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->route_metric;
-}
-
-void
-nm_dhcp_client_set_route_metric(NMDhcpClient *self, guint32 route_metric)
-{
- NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
-
- if (route_metric != priv->route_metric) {
- priv->route_metric = route_metric;
- _notify(self, PROP_ROUTE_METRIC);
- }
-}
-
-guint32
-nm_dhcp_client_get_timeout(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), 0);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->timeout;
-}
-
-guint32
-nm_dhcp_client_get_iaid(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), 0);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->iaid;
-}
-
-gboolean
-nm_dhcp_client_get_iaid_explicit(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->iaid_explicit;
-}
-
-GBytes *
-nm_dhcp_client_get_client_id(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->client_id;
-}
-
static void
-_set_client_id(NMDhcpClient *self, GBytes *client_id, gboolean take)
+_set_effective_client_id(NMDhcpClient *self, GBytes *client_id, gboolean take)
{
NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
nm_assert(!client_id || g_bytes_get_size(client_id) >= 2);
- if (priv->client_id == client_id
- || (priv->client_id && client_id && g_bytes_equal(priv->client_id, client_id))) {
+ if (priv->effective_client_id == client_id
+ || (priv->effective_client_id && client_id
+ && g_bytes_equal(priv->effective_client_id, client_id))) {
if (take && client_id)
g_bytes_unref(client_id);
return;
}
- if (priv->client_id)
- g_bytes_unref(priv->client_id);
- priv->client_id = client_id;
+ if (priv->effective_client_id)
+ g_bytes_unref(priv->effective_client_id);
+ priv->effective_client_id = client_id;
if (!take && client_id)
g_bytes_ref(client_id);
@@ -277,94 +103,20 @@ _set_client_id(NMDhcpClient *self, GBytes *client_id, gboolean take)
gs_free char *s = NULL;
_LOGT("%s: set %s",
- nm_dhcp_client_get_addr_family(self) == AF_INET6 ? "duid" : "client-id",
- priv->client_id ? (s = nm_dhcp_utils_duid_to_string(priv->client_id)) : "default");
+ priv->config.addr_family == AF_INET6 ? "duid" : "client-id",
+ priv->effective_client_id
+ ? (s = nm_dhcp_utils_duid_to_string(priv->effective_client_id))
+ : "default");
}
}
void
-nm_dhcp_client_set_client_id(NMDhcpClient *self, GBytes *client_id)
+nm_dhcp_client_set_effective_client_id(NMDhcpClient *self, GBytes *client_id)
{
g_return_if_fail(NM_IS_DHCP_CLIENT(self));
g_return_if_fail(!client_id || g_bytes_get_size(client_id) >= 2);
- _set_client_id(self, client_id, FALSE);
-}
-
-void
-nm_dhcp_client_set_client_id_bin(NMDhcpClient *self,
- guint8 type,
- const guint8 *client_id,
- gsize len)
-{
- guint8 *buf;
- GBytes *b;
-
- g_return_if_fail(NM_IS_DHCP_CLIENT(self));
- g_return_if_fail(client_id);
- g_return_if_fail(len > 0);
-
- buf = g_malloc(len + 1);
- buf[0] = type;
- memcpy(buf + 1, client_id, len);
- b = g_bytes_new_take(buf, len + 1);
- _set_client_id(self, b, TRUE);
-}
-
-const char *
-nm_dhcp_client_get_anycast_address(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->anycast_address;
-}
-
-const char *
-nm_dhcp_client_get_hostname(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->hostname;
-}
-
-NMDhcpHostnameFlags
-nm_dhcp_client_get_hostname_flags(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NM_DHCP_HOSTNAME_FLAG_NONE);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->hostname_flags;
-}
-
-NMDhcpClientFlags
-nm_dhcp_client_get_client_flags(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NM_DHCP_CLIENT_FLAGS_NONE);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->client_flags;
-}
-
-const char *
-nm_dhcp_client_get_mud_url(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->mud_url;
-}
-
-GBytes *
-nm_dhcp_client_get_vendor_class_identifier(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return NM_DHCP_CLIENT_GET_PRIVATE(self)->vendor_class_identifier;
-}
-
-const char *const *
-nm_dhcp_client_get_reject_servers(NMDhcpClient *self)
-{
- g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL);
-
- return (const char *const *) NM_DHCP_CLIENT_GET_PRIVATE(self)->reject_servers;
+ _set_effective_client_id(self, client_id, FALSE);
}
/*****************************************************************************/
@@ -457,78 +209,159 @@ stop(NMDhcpClient *self, gboolean release)
if (priv->pid > 0) {
/* Clean up the watch handler since we're explicitly killing the daemon */
watch_cleanup(self);
- nm_dhcp_client_stop_pid(priv->pid, priv->iface);
+ nm_dhcp_client_stop_pid(priv->pid, priv->config.iface);
}
priv->pid = -1;
}
-void
-nm_dhcp_client_set_state(NMDhcpClient *self,
- NMDhcpState new_state,
- NMIPConfig * ip_config,
- GHashTable * options)
+static gboolean
+_no_lease_timeout(gpointer user_data)
{
+ NMDhcpClient * self = user_data;
NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+ nm_clear_g_source_inst(&priv->no_lease_timeout_source);
+
+ _emit_notify(self,
+ &((NMDhcpClientNotifyData){
+ .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT,
+ }));
+ return G_SOURCE_CONTINUE;
+}
+
+const NMDhcpClientConfig *
+nm_dhcp_client_get_config(NMDhcpClient *self)
+{
+ NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+ return &priv->config;
+}
+
+void
+nm_dhcp_client_set_state(NMDhcpClient *self, NMDhcpState new_state, const NML3ConfigData *l3cd)
+{
+ NMDhcpClientPrivate * priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+ GHashTable * options;
+ const int IS_IPv4 = NM_IS_IPv4(priv->config.addr_family);
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd_merged = NULL;
+
+ g_return_if_fail(NM_IS_DHCP_CLIENT(self));
+
if (NM_IN_SET(new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED)) {
- g_return_if_fail(NM_IS_IP_CONFIG_ADDR_FAMILY(ip_config, priv->addr_family));
- g_return_if_fail(options);
- } else {
- g_return_if_fail(!ip_config);
- g_return_if_fail(!options);
- }
+ g_return_if_fail(NM_IS_L3_CONFIG_DATA(l3cd));
+ g_return_if_fail(nm_l3_config_data_get_dhcp_lease(l3cd, priv->config.addr_family));
+ } else
+ g_return_if_fail(!l3cd);
+
+ if (l3cd)
+ nm_l3_config_data_seal(l3cd);
if (new_state >= NM_DHCP_STATE_BOUND)
timeout_cleanup(self);
if (new_state >= NM_DHCP_STATE_TIMEOUT)
watch_cleanup(self);
- /* The client may send same-state transitions for RENEW/REBIND events and
- * the lease may have changed, so handle same-state transitions for the
- * EXTENDED and BOUND states. Ignore same-state transitions for other
- * events since the lease won't have changed and the state was already handled.
- */
- if ((priv->state == new_state)
- && !NM_IN_SET(new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED))
- return;
+ if (!IS_IPv4 && l3cd) {
+ if (nm_dhcp_utils_merge_new_dhcp6_lease(priv->l3cd, l3cd, &l3cd_merged)) {
+ l3cd = nm_l3_config_data_seal(l3cd_merged);
+ }
+ }
- if (_LOGD_ENABLED()) {
- gs_free const char **keys = NULL;
- guint i, nkeys;
+ if (priv->l3cd == l3cd)
+ return;
- keys = nm_strdict_get_keys(options, TRUE, &nkeys);
- for (i = 0; i < nkeys; i++) {
- _LOGD("option %-20s => '%s'", keys[i], (char *) g_hash_table_lookup(options, keys[i]));
+ if (l3cd)
+ nm_clear_g_source_inst(&priv->no_lease_timeout_source);
+ else {
+ /* FIXME(l3cfg:dhcp): we also need to start no_lease_timeout initially, if the
+ * instance starts without a previous_lease. */
+ if (!priv->no_lease_timeout_source && priv->l3cd) {
+ if (priv->config.timeout == NM_DHCP_TIMEOUT_INFINITY)
+ priv->no_lease_timeout_source = g_source_ref(nm_g_source_sentinel_get(0));
+ else {
+ priv->no_lease_timeout_source =
+ nm_g_timeout_add_source_seconds(priv->config.timeout, _no_lease_timeout, self);
+ }
}
}
- if (_LOGT_ENABLED() && priv->addr_family == AF_INET6) {
- gs_free char *event_id = NULL;
+ /* FIXME(l3cfg:dhcp): the API of NMDhcpClient is changing to expose a simpler API.
+ * The internals like NMDhcpState should not be exposed (or possibly dropped in large
+ * parts). */
+
+ nm_l3_config_data_reset(&priv->l3cd, l3cd);
+
+ options = l3cd ? nm_dhcp_lease_get_options(
+ nm_l3_config_data_get_dhcp_lease(l3cd, priv->config.addr_family))
+ : NULL;
+
+ if (_LOGD_ENABLED()) {
+ if (options) {
+ gs_free const char **keys = NULL;
+ guint nkeys;
+ guint i;
+
+ keys = nm_strdict_get_keys(options, TRUE, &nkeys);
+ for (i = 0; i < nkeys; i++) {
+ _LOGD("option %-20s => '%s'",
+ keys[i],
+ (char *) g_hash_table_lookup(options, keys[i]));
+ }
+
+ if (priv->config.addr_family == AF_INET6) {
+ gs_free char *event_id = NULL;
- event_id = nm_dhcp_utils_get_dhcp6_event_id(options);
- if (event_id)
- _LOGT("event-id: \"%s\"", event_id);
+ event_id = nm_dhcp_utils_get_dhcp6_event_id(options);
+ if (event_id)
+ _LOGT("event-id: \"%s\"", event_id);
+ }
+ }
}
if (_LOGI_ENABLED()) {
const char *req_str =
- NM_IS_IPv4(priv->addr_family)
- ? nm_dhcp_option_request_string(AF_INET, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS)
- : nm_dhcp_option_request_string(AF_INET6, NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS);
+ IS_IPv4 ? nm_dhcp_option_request_string(AF_INET, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS)
+ : nm_dhcp_option_request_string(AF_INET6, NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS);
const char *addr = nm_g_hash_table_lookup(options, req_str);
- _LOGI("state changed %s -> %s%s%s%s",
- nm_dhcp_state_to_string(priv->state),
- nm_dhcp_state_to_string(new_state),
+ _LOGI("state changed %s%s%s%s",
+ priv->l3cd ? "new lease" : "no lease",
NM_PRINT_FMT_QUOTED(addr, ", address=", addr, "", ""));
}
- priv->state = new_state;
+ /* FIXME(l3cfg:dhcp:acd): NMDhcpClient must also do ACD. It needs acd_timeout_msec
+ * as a configuration parameter (in NMDhcpClientConfig). When ACD is enabled,
+ * when a new lease gets announced, it must first use NML3Cfg to run ACD on the
+ * interface (the previous lease -- if any -- will still be used at that point).
+ * If ACD fails, we call nm_dhcp_client_decline() and try to get a different
+ * lease.
+ * If ACD passes, we need to notify the new lease, and the user (NMDevice) may
+ * then configure the address. We need to watch the configured addresses (in NML3Cfg),
+ * and if the address appears there, we need to accept the lease. That is complicated
+ * but necessary, because we can only accept the lease after we configured the
+ * address.
+ *
+ * As a whole, ACD is transparent for the user (NMDevice). It's entirely managed
+ * by NMDhcpClient. Note that we do ACD through NML3Cfg, which centralizes IP handling
+ * for one interface, so for example if the same address happens to be configured
+ * as a static address (bypassing ACD), then NML3Cfg is aware of that and signals
+ * immediate success. */
- _emit_notify_state_changed(self, new_state, ip_config, options);
+ {
+ const NMDhcpClientNotifyData notify_data = {
+ .notify_type = NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE,
+ .lease_update =
+ {
+ .l3cd = priv->l3cd,
+ },
+ };
+
+ _emit_notify(self, &notify_data);
+ }
}
-static gboolean
+/* FIXME(l3cfg:dhcp) */
+_nm_unused static gboolean
transaction_timeout(gpointer user_data)
{
NMDhcpClient * self = NM_DHCP_CLIENT(user_data);
@@ -536,7 +369,7 @@ transaction_timeout(gpointer user_data)
priv->timeout_id = 0;
_LOGW("request timed out");
- nm_dhcp_client_set_state(self, NM_DHCP_STATE_TIMEOUT, NULL, NULL);
+ nm_dhcp_client_set_state(self, NM_DHCP_STATE_TIMEOUT, NULL);
return G_SOURCE_REMOVE;
}
@@ -554,7 +387,7 @@ daemon_watch_cb(GPid pid, int status, gpointer user_data)
priv->pid = -1;
- nm_dhcp_client_set_state(self, NM_DHCP_STATE_TERMINATED, NULL, NULL);
+ nm_dhcp_client_set_state(self, NM_DHCP_STATE_TERMINATED, NULL);
}
void
@@ -566,10 +399,10 @@ nm_dhcp_client_start_timeout(NMDhcpClient *self)
/* Set up a timeout on the transaction to kill it after the timeout */
- if (priv->timeout == NM_DHCP_TIMEOUT_INFINITY)
- return;
-
- priv->timeout_id = g_timeout_add_seconds(priv->timeout, transaction_timeout, self);
+ /* FIXME(l3cfg:dhcp): no-lease-timeout is only for convenience for the user (NMDevice).
+ * Whatever the purpose of nm_dhcp_client_start_timeout() is, it is not the same timer. */
+ return;
+ //priv->timeout_id = g_timeout_add_seconds(priv->no_lease_timeout, transaction_timeout, self);
}
void
@@ -599,10 +432,7 @@ nm_dhcp_client_stop_watch_child(NMDhcpClient *self, pid_t pid)
}
gboolean
-nm_dhcp_client_start_ip4(NMDhcpClient *self,
- GBytes * client_id,
- const char * last_ip4_address,
- GError ** error)
+nm_dhcp_client_start_ip4(NMDhcpClient *self, GError **error)
{
NMDhcpClientPrivate *priv;
@@ -610,24 +440,37 @@ nm_dhcp_client_start_ip4(NMDhcpClient *self,
priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
g_return_val_if_fail(priv->pid == -1, FALSE);
- g_return_val_if_fail(priv->addr_family == AF_INET, FALSE);
- g_return_val_if_fail(priv->uuid != NULL, FALSE);
-
- if (priv->timeout == NM_DHCP_TIMEOUT_INFINITY)
+ g_return_val_if_fail(priv->config.addr_family == AF_INET, FALSE);
+ g_return_val_if_fail(priv->config.uuid, FALSE);
+
+ /* FIXME(l3cfg:dhcp:ipv6ll): for IPv6, NMDhcpClient needs to wait that
+ * a IPv6 LL address appears. The user (NMDevice) will start the generation
+ * of a LL address, but NMDhcpClient is already running and is just waiting.
+ *
+ * All the while, NM_DHCP_CLIENT_NO_LEASE_TIMEOUT is ticking. If the LL address
+ * does not appear in (e.g. 5 seconds), a NM_DHCP_CLIENT_NOTIFY_TYPE_IT_LOOKS_BAD signal
+ * can be emitted. */
+
+ if (priv->config.timeout == NM_DHCP_TIMEOUT_INFINITY)
_LOGI("activation: beginning transaction (no timeout)");
else
- _LOGI("activation: beginning transaction (timeout in %u seconds)", (guint) priv->timeout);
+ _LOGI("activation: beginning transaction (timeout in %u seconds)",
+ (guint) priv->config.timeout);
- nm_dhcp_client_set_client_id(self, client_id);
-
- return NM_DHCP_CLIENT_GET_CLASS(self)->ip4_start(self, last_ip4_address, error);
+ return NM_DHCP_CLIENT_GET_CLASS(self)->ip4_start(self, error);
}
gboolean
nm_dhcp_client_accept(NMDhcpClient *self, GError **error)
{
+ NMDhcpClientPrivate *priv;
+
g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE);
+ priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+ g_return_val_if_fail(priv->l3cd, FALSE);
+
if (NM_DHCP_CLIENT_GET_CLASS(self)->accept) {
return NM_DHCP_CLIENT_GET_CLASS(self)->accept(self, error);
}
@@ -652,8 +495,14 @@ nm_dhcp_client_can_accept(NMDhcpClient *self)
gboolean
nm_dhcp_client_decline(NMDhcpClient *self, const char *error_message, GError **error)
{
+ NMDhcpClientPrivate *priv;
+
g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE);
+ priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+ g_return_val_if_fail(priv->l3cd, FALSE);
+
if (NM_DHCP_CLIENT_GET_CLASS(self)->decline) {
return NM_DHCP_CLIENT_GET_CLASS(self)->decline(self, error_message, error);
}
@@ -668,42 +517,31 @@ get_duid(NMDhcpClient *self)
}
gboolean
-nm_dhcp_client_start_ip6(NMDhcpClient * self,
- GBytes * client_id,
- gboolean enforce_duid,
- const struct in6_addr * ll_addr,
- NMSettingIP6ConfigPrivacy privacy,
- guint needed_prefixes,
- GError ** error)
+nm_dhcp_client_start_ip6(NMDhcpClient *self, GError **error)
{
NMDhcpClientPrivate *priv;
gs_unref_bytes GBytes *own_client_id = NULL;
g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE);
- g_return_val_if_fail(client_id, FALSE);
-
priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
g_return_val_if_fail(priv->pid == -1, FALSE);
- g_return_val_if_fail(priv->addr_family == AF_INET6, FALSE);
- g_return_val_if_fail(priv->uuid != NULL, FALSE);
- g_return_val_if_fail(!priv->client_id, FALSE);
+ g_return_val_if_fail(priv->config.addr_family == AF_INET6, FALSE);
+ g_return_val_if_fail(priv->config.uuid, FALSE);
+ g_return_val_if_fail(!priv->effective_client_id, FALSE);
- if (!enforce_duid)
+ if (!priv->config.v6.enforce_duid)
own_client_id = NM_DHCP_CLIENT_GET_CLASS(self)->get_duid(self);
- _set_client_id(self, own_client_id ?: client_id, FALSE);
+ _set_effective_client_id(self, own_client_id ?: priv->config.client_id, FALSE);
- if (priv->timeout == NM_DHCP_TIMEOUT_INFINITY)
+ if (priv->config.timeout == NM_DHCP_TIMEOUT_INFINITY)
_LOGI("activation: beginning transaction (no timeout)");
else
- _LOGI("activation: beginning transaction (timeout in %u seconds)", (guint) priv->timeout);
+ _LOGI("activation: beginning transaction (timeout in %u seconds)",
+ (guint) priv->config.timeout);
- return NM_DHCP_CLIENT_GET_CLASS(self)->ip6_start(self,
- ll_addr,
- privacy,
- needed_prefixes,
- error);
+ return NM_DHCP_CLIENT_GET_CLASS(self)->ip6_start(self, error);
}
void
@@ -789,7 +627,7 @@ nm_dhcp_client_stop(NMDhcpClient *self, gboolean release)
_LOGI("canceled DHCP transaction");
nm_assert(priv->pid == -1);
- nm_dhcp_client_set_state(self, NM_DHCP_STATE_TERMINATED, NULL, NULL);
+ nm_dhcp_client_set_state(self, NM_DHCP_STATE_TERMINATED, NULL);
}
/*****************************************************************************/
@@ -921,12 +759,10 @@ nm_dhcp_client_handle_event(gpointer unused,
const char * reason,
NMDhcpClient *self)
{
- NMDhcpClientPrivate *priv;
- guint32 old_state;
- guint32 new_state;
- gs_unref_hashtable GHashTable *str_options = NULL;
- gs_unref_object NMIPConfig *ip_config = NULL;
- NMPlatformIP6Address prefix = {
+ NMDhcpClientPrivate * priv;
+ guint32 new_state;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ NMPlatformIP6Address prefix = {
0,
};
@@ -938,25 +774,26 @@ nm_dhcp_client_handle_event(gpointer unused,
priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
- if (g_strcmp0(priv->iface, iface) != 0)
+ if (!nm_streq0(priv->config.iface, iface))
return FALSE;
if (priv->pid != pid)
return FALSE;
- old_state = priv->state;
- new_state = reason_to_state(self, priv->iface, reason);
+ new_state = reason_to_state(self, priv->config.iface, reason);
+ if (new_state == NM_DHCP_STATE_NOOP)
+ return TRUE;
+
_LOGD("DHCP state '%s' -> '%s' (reason: '%s')",
- nm_dhcp_state_to_string(old_state),
+ nm_dhcp_state_to_string(priv->state),
nm_dhcp_state_to_string(new_state),
reason);
-
- if (new_state == NM_DHCP_STATE_NOOP)
- return TRUE;
+ priv->state = new_state;
if (NM_IN_SET(new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED)) {
- GVariantIter iter;
- const char * name;
- GVariant * value;
+ gs_unref_hashtable GHashTable *str_options = NULL;
+ GVariantIter iter;
+ const char * name;
+ GVariant * value;
/* Copy options */
str_options = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free);
@@ -968,25 +805,29 @@ nm_dhcp_client_handle_event(gpointer unused,
/* Create the IP config */
if (g_hash_table_size(str_options) > 0) {
- if (priv->addr_family == AF_INET) {
- ip_config = NM_IP_CONFIG_CAST(
- nm_dhcp_utils_ip4_config_from_options(nm_dhcp_client_get_multi_idx(self),
- priv->ifindex,
- priv->iface,
- str_options,
- priv->route_table,
- priv->route_metric));
+ if (priv->config.addr_family == AF_INET) {
+ l3cd = nm_dhcp_utils_ip4_config_from_options(
+ nm_l3cfg_get_multi_idx(priv->config.l3cfg),
+ nm_l3cfg_get_ifindex(priv->config.l3cfg),
+ priv->config.iface,
+ str_options);
} else {
- prefix = nm_dhcp_utils_ip6_prefix_from_options(str_options);
- ip_config = NM_IP_CONFIG_CAST(nm_dhcp_utils_ip6_config_from_options(
- nm_dhcp_client_get_multi_idx(self),
- priv->ifindex,
- priv->iface,
+ prefix = nm_dhcp_utils_ip6_prefix_from_options(str_options);
+ l3cd = nm_dhcp_utils_ip6_config_from_options(
+ nm_l3cfg_get_multi_idx(priv->config.l3cfg),
+ nm_l3cfg_get_ifindex(priv->config.l3cfg),
+ priv->config.iface,
str_options,
- NM_FLAGS_HAS(priv->client_flags, NM_DHCP_CLIENT_FLAGS_INFO_ONLY)));
+ priv->config.v6.info_only);
}
} else
g_warn_if_reached();
+
+ if (l3cd) {
+ nm_l3_config_data_set_dhcp_lease_from_options(l3cd,
+ priv->config.addr_family,
+ g_steal_pointer(&str_options));
+ }
}
if (!IN6_IS_ADDR_UNSPECIFIED(&prefix.address)) {
@@ -994,17 +835,16 @@ nm_dhcp_client_handle_event(gpointer unused,
* of the DHCP client instance. Instead, we just signal the prefix
* to the device. */
nm_dhcp_client_emit_ipv6_prefix_delegated(self, &prefix);
- } else {
- /* Fail if no valid IP config was received */
- if (NM_IN_SET(new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED) && !ip_config) {
- _LOGW("client bound but IP config not received");
- new_state = NM_DHCP_STATE_FAIL;
- nm_clear_pointer(&str_options, g_hash_table_unref);
- }
+ return TRUE;
+ }
- nm_dhcp_client_set_state(self, new_state, ip_config, str_options);
+ /* Fail if no valid IP config was received */
+ if (NM_IN_SET(new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED) && !l3cd) {
+ _LOGW("client bound but IP config not received");
+ new_state = NM_DHCP_STATE_FAIL;
}
+ nm_dhcp_client_set_state(self, new_state, l3cd);
return TRUE;
}
@@ -1016,18 +856,18 @@ nm_dhcp_client_server_id_is_rejected(NMDhcpClient *self, gconstpointer addr)
guint i;
/* IPv6 not implemented yet */
- nm_assert(priv->addr_family == AF_INET);
+ nm_assert(priv->config.addr_family == AF_INET);
- if (!priv->reject_servers || !priv->reject_servers[0])
+ if (!priv->config.reject_servers || !priv->config.reject_servers[0])
return FALSE;
- for (i = 0; priv->reject_servers[i]; i++) {
+ for (i = 0; priv->config.reject_servers[i]; i++) {
in_addr_t r_addr;
in_addr_t mask;
int r_prefix;
if (!nm_utils_parse_inaddr_prefix_bin(AF_INET,
- priv->reject_servers[i],
+ priv->config.reject_servers[i],
NULL,
&r_addr,
&r_prefix))
@@ -1040,146 +880,151 @@ nm_dhcp_client_server_id_is_rejected(NMDhcpClient *self, gconstpointer addr)
return FALSE;
}
-/*****************************************************************************/
+static void
+config_init(NMDhcpClientConfig *config, const NMDhcpClientConfig *src)
+{
+ *config = *src;
+
+ g_object_ref(config->l3cfg);
+
+ if (config->hwaddr)
+ g_bytes_ref(config->hwaddr);
+ if (config->bcast_hwaddr)
+ g_bytes_ref(config->bcast_hwaddr);
+ if (config->vendor_class_identifier)
+ g_bytes_ref(config->vendor_class_identifier);
+ if (config->client_id)
+ g_bytes_ref(config->client_id);
+
+ config->iface = g_strdup(config->iface);
+ config->uuid = g_strdup(config->uuid);
+ config->anycast_address = g_strdup(config->anycast_address);
+ config->hostname = g_strdup(config->hostname);
+ config->mud_url = g_strdup(config->mud_url);
+
+ config->reject_servers = (const char *const *) nm_strv_dup(config->reject_servers, -1, TRUE);
+
+ if (config->addr_family == AF_INET) {
+ config->v4.last_address = g_strdup(config->v4.last_address);
+ } else if (config->addr_family == AF_INET6) {
+ config->v6.ll_addr = g_memdup(config->v6.ll_addr, sizeof(struct in6_addr));
+ config->hwaddr = NULL;
+ config->bcast_hwaddr = NULL;
+ config->use_fqdn = TRUE;
+ } else {
+ nm_assert_not_reached();
+ }
+
+ if (!config->hostname && config->send_hostname) {
+ const char * hostname;
+ gs_free char *hostname_tmp = NULL;
+
+ hostname = nm_hostname_manager_get_hostname(nm_hostname_manager_get());
+
+ if (nm_utils_is_specific_hostname(hostname)) {
+ if (config->addr_family == AF_INET) {
+ char *dot;
+
+ hostname_tmp = g_strdup(hostname);
+ dot = strchr(hostname_tmp, '.');
+ if (dot)
+ *dot = '\0';
+ }
+ config->hostname = hostname_tmp ? g_steal_pointer(&hostname_tmp) : g_strdup(hostname);
+ }
+ }
+
+ if (config->hostname) {
+ if ((config->use_fqdn && !nm_sd_dns_name_is_valid(config->hostname))
+ || (!config->use_fqdn && !nm_sd_hostname_is_valid(config->hostname, FALSE))) {
+ nm_log_warn(LOGD_DHCP,
+ "dhcp%c: %s '%s' is invalid, will be ignored",
+ nm_utils_addr_family_to_char(config->addr_family),
+ config->use_fqdn ? "FQDN" : "hostname",
+ config->hostname);
+ nm_clear_g_free((gpointer *) &config->hostname);
+ }
+ }
+}
static void
-get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+config_clear(NMDhcpClientConfig *config)
{
- NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(object);
+ g_object_unref(config->l3cfg);
- switch (prop_id) {
- case PROP_IFACE:
- g_value_set_string(value, priv->iface);
- break;
- case PROP_IFINDEX:
- g_value_set_int(value, priv->ifindex);
- break;
- case PROP_HWADDR:
- g_value_set_boxed(value, priv->hwaddr);
- break;
- case PROP_BROADCAST_HWADDR:
- g_value_set_boxed(value, priv->bcast_hwaddr);
- break;
- case PROP_ADDR_FAMILY:
- g_value_set_int(value, priv->addr_family);
- break;
- case PROP_UUID:
- g_value_set_string(value, priv->uuid);
- break;
- case PROP_IAID:
- g_value_set_uint(value, priv->iaid);
- break;
- case PROP_IAID_EXPLICIT:
- g_value_set_boolean(value, priv->iaid_explicit);
- break;
- case PROP_HOSTNAME:
- g_value_set_string(value, priv->hostname);
- break;
- case PROP_ROUTE_METRIC:
- g_value_set_uint(value, priv->route_metric);
- break;
- case PROP_ROUTE_TABLE:
- g_value_set_uint(value, priv->route_table);
- break;
- case PROP_TIMEOUT:
- g_value_set_uint(value, priv->timeout);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
- break;
+ nm_clear_pointer(&config->hwaddr, g_bytes_unref);
+ nm_clear_pointer(&config->bcast_hwaddr, g_bytes_unref);
+ nm_clear_pointer(&config->vendor_class_identifier, g_bytes_unref);
+ nm_clear_pointer(&config->client_id, g_bytes_unref);
+
+ nm_clear_g_free((gpointer *) &config->iface);
+ nm_clear_g_free((gpointer *) &config->uuid);
+ nm_clear_g_free((gpointer *) &config->anycast_address);
+ nm_clear_g_free((gpointer *) &config->hostname);
+ nm_clear_g_free((gpointer *) &config->mud_url);
+
+ nm_clear_pointer((gpointer *) &config->reject_servers, g_strfreev);
+
+ if (config->addr_family == AF_INET) {
+ nm_clear_g_free((gpointer *) &config->v4.last_address);
+ } else if (config->addr_family == AF_INET6) {
+ nm_clear_g_free((gpointer *) &config->v6.ll_addr);
+ } else {
+ nm_assert_not_reached();
}
}
+int
+nm_dhcp_client_get_addr_family(NMDhcpClient *self)
+{
+ NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+ return priv->config.addr_family;
+}
+
+const char *
+nm_dhcp_client_get_iface(NMDhcpClient *self)
+{
+ NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+ return priv->config.iface;
+}
+
+NMDedupMultiIndex *
+nm_dhcp_client_get_multi_idx(NMDhcpClient *self)
+{
+ NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+ return nm_l3cfg_get_multi_idx(priv->config.l3cfg);
+}
+
+int
+nm_dhcp_client_get_ifindex(NMDhcpClient *self)
+{
+ NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+ return nm_l3cfg_get_ifindex(priv->config.l3cfg);
+}
+
+GBytes *
+nm_dhcp_client_get_effective_client_id(NMDhcpClient *self)
+{
+ NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
+
+ return priv->effective_client_id;
+}
+
+/*****************************************************************************/
+
static void
set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
{
NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(object);
- guint flags;
switch (prop_id) {
- case PROP_FLAGS:
- /* construct-only */
- flags = g_value_get_uint(value);
- nm_assert(!NM_FLAGS_ANY(flags, ~((guint) NM_DHCP_CLIENT_FLAGS_ALL)));
- priv->client_flags = flags;
- break;
- case PROP_MULTI_IDX:
- /* construct-only */
- priv->multi_idx = g_value_get_pointer(value);
- if (!priv->multi_idx)
- g_return_if_reached();
- nm_dedup_multi_index_ref(priv->multi_idx);
- break;
- case PROP_IFACE:
- /* construct-only */
- priv->iface = g_value_dup_string(value);
- g_return_if_fail(priv->iface);
- nm_assert(nm_utils_ifname_valid_kernel(priv->iface, NULL));
- break;
- case PROP_IFINDEX:
- /* construct-only */
- priv->ifindex = g_value_get_int(value);
- g_return_if_fail(priv->ifindex > 0);
- break;
- case PROP_HWADDR:
- /* construct-only */
- priv->hwaddr = g_value_dup_boxed(value);
- break;
- case PROP_ANYCAST_ADDRESS:
- /* construct-only */
- priv->anycast_address = g_value_dup_string(value);
- break;
- case PROP_BROADCAST_HWADDR:
- /* construct-only */
- priv->bcast_hwaddr = g_value_dup_boxed(value);
- break;
- case PROP_ADDR_FAMILY:
- /* construct-only */
- priv->addr_family = g_value_get_int(value);
- if (!NM_IN_SET(priv->addr_family, AF_INET, AF_INET6))
- g_return_if_reached();
- break;
- case PROP_UUID:
- /* construct-only */
- priv->uuid = g_value_dup_string(value);
- break;
- case PROP_IAID:
- /* construct-only */
- priv->iaid = g_value_get_uint(value);
- break;
- case PROP_IAID_EXPLICIT:
- /* construct-only */
- priv->iaid_explicit = g_value_get_boolean(value);
- break;
- case PROP_HOSTNAME:
- /* construct-only */
- priv->hostname = g_value_dup_string(value);
- break;
- case PROP_HOSTNAME_FLAGS:
- /* construct-only */
- priv->hostname_flags = g_value_get_uint(value);
- break;
- case PROP_MUD_URL:
- /* construct-only */
- priv->mud_url = g_value_dup_string(value);
- break;
- case PROP_ROUTE_TABLE:
- priv->route_table = g_value_get_uint(value);
- break;
- case PROP_ROUTE_METRIC:
- priv->route_metric = g_value_get_uint(value);
- break;
- case PROP_TIMEOUT:
- /* construct-only */
- priv->timeout = g_value_get_uint(value);
- break;
- case PROP_VENDOR_CLASS_IDENTIFIER:
- /* construct-only */
- priv->vendor_class_identifier = g_value_dup_boxed(value);
- break;
- case PROP_REJECT_SERVERS:
+ case PROP_CONFIG:
/* construct-only */
- priv->reject_servers = nm_strv_dup_packed(g_value_get_boxed(value), -1);
+ config_init(&priv->config, g_value_get_pointer(value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
@@ -1200,53 +1045,31 @@ nm_dhcp_client_init(NMDhcpClient *self)
priv->pid = -1;
}
-#if NM_MORE_ASSERTS
static void
-constructed(GObject *object)
+dispose(GObject *object)
{
NMDhcpClient * self = NM_DHCP_CLIENT(object);
NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
- /* certain flags only make sense with certain address family. Assert
- * for that. */
- if (NM_IS_IPv4(priv->addr_family))
- nm_assert(!NM_FLAGS_ANY(priv->client_flags, NM_DHCP_CLIENT_FLAGS_INFO_ONLY));
- else {
- nm_assert(NM_FLAGS_HAS(priv->client_flags, NM_DHCP_CLIENT_FLAGS_USE_FQDN));
- nm_assert(!NM_FLAGS_ANY(priv->client_flags, NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST));
- }
+ nm_dhcp_client_stop(self, FALSE);
- nm_assert(!priv->anycast_address || nm_utils_hwaddr_valid(priv->anycast_address, ETH_ALEN));
+ watch_cleanup(self);
+ timeout_cleanup(self);
+
+ nm_clear_g_source_inst(&priv->no_lease_timeout_source);
- G_OBJECT_CLASS(nm_dhcp_client_parent_class)->constructed(object);
+ G_OBJECT_CLASS(nm_dhcp_client_parent_class)->dispose(object);
}
-#endif
static void
-dispose(GObject *object)
+finalize(GObject *object)
{
NMDhcpClient * self = NM_DHCP_CLIENT(object);
NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self);
- nm_dhcp_client_stop(self, FALSE);
-
- watch_cleanup(self);
- timeout_cleanup(self);
-
- nm_clear_g_free(&priv->iface);
- nm_clear_g_free(&priv->hostname);
- nm_clear_g_free(&priv->uuid);
- nm_clear_g_free(&priv->anycast_address);
- nm_clear_g_free(&priv->mud_url);
- nm_clear_g_free(&priv->reject_servers);
- nm_clear_pointer(&priv->client_id, g_bytes_unref);
- nm_clear_pointer(&priv->hwaddr, g_bytes_unref);
- nm_clear_pointer(&priv->bcast_hwaddr, g_bytes_unref);
- nm_clear_pointer(&priv->vendor_class_identifier, g_bytes_unref);
+ config_clear(&priv->config);
- G_OBJECT_CLASS(nm_dhcp_client_parent_class)->dispose(object);
-
- priv->multi_idx = nm_dedup_multi_index_unref(priv->multi_idx);
+ G_OBJECT_CLASS(nm_dhcp_client_parent_class)->finalize(object);
}
static void
@@ -1256,165 +1079,19 @@ nm_dhcp_client_class_init(NMDhcpClientClass *client_class)
g_type_class_add_private(client_class, sizeof(NMDhcpClientPrivate));
-#if NM_MORE_ASSERTS
- object_class->constructed = constructed;
-#endif
object_class->dispose = dispose;
- object_class->get_property = get_property;
+ object_class->finalize = finalize;
object_class->set_property = set_property;
client_class->stop = stop;
client_class->get_duid = get_duid;
- obj_properties[PROP_MULTI_IDX] =
- g_param_spec_pointer(NM_DHCP_CLIENT_MULTI_IDX,
+ obj_properties[PROP_CONFIG] =
+ g_param_spec_pointer(NM_DHCP_CLIENT_CONFIG,
"",
"",
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
- obj_properties[PROP_IFACE] =
- g_param_spec_string(NM_DHCP_CLIENT_INTERFACE,
- "",
- "",
- NULL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_IFINDEX] =
- g_param_spec_int(NM_DHCP_CLIENT_IFINDEX,
- "",
- "",
- -1,
- G_MAXINT,
- -1,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_HWADDR] =
- g_param_spec_boxed(NM_DHCP_CLIENT_HWADDR,
- "",
- "",
- G_TYPE_BYTES,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_BROADCAST_HWADDR] =
- g_param_spec_boxed(NM_DHCP_CLIENT_BROADCAST_HWADDR,
- "",
- "",
- G_TYPE_BYTES,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_ADDR_FAMILY] =
- g_param_spec_int(NM_DHCP_CLIENT_ADDR_FAMILY,
- "",
- "",
- 0,
- G_MAXINT,
- AF_UNSPEC,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_ANYCAST_ADDRESS] =
- g_param_spec_string(NM_DHCP_CLIENT_ANYCAST_ADDRESS,
- "",
- "",
- NULL,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_UUID] =
- g_param_spec_string(NM_DHCP_CLIENT_UUID,
- "",
- "",
- NULL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_IAID] =
- g_param_spec_uint(NM_DHCP_CLIENT_IAID,
- "",
- "",
- 0,
- G_MAXUINT32,
- 0,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_IAID_EXPLICIT] =
- g_param_spec_boolean(NM_DHCP_CLIENT_IAID_EXPLICIT,
- "",
- "",
- FALSE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_HOSTNAME] =
- g_param_spec_string(NM_DHCP_CLIENT_HOSTNAME,
- "",
- "",
- NULL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_HOSTNAME_FLAGS] =
- g_param_spec_uint(NM_DHCP_CLIENT_HOSTNAME_FLAGS,
- "",
- "",
- 0,
- G_MAXUINT32,
- NM_DHCP_HOSTNAME_FLAG_NONE,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_MUD_URL] =
- g_param_spec_string(NM_DHCP_CLIENT_MUD_URL,
- "",
- "",
- NULL,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_ROUTE_TABLE] =
- g_param_spec_uint(NM_DHCP_CLIENT_ROUTE_TABLE,
- "",
- "",
- 0,
- G_MAXUINT32,
- RT_TABLE_MAIN,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_ROUTE_METRIC] =
- g_param_spec_uint(NM_DHCP_CLIENT_ROUTE_METRIC,
- "",
- "",
- 0,
- G_MAXUINT32,
- 0,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- G_STATIC_ASSERT_EXPR(G_MAXINT32 == NM_DHCP_TIMEOUT_INFINITY);
- obj_properties[PROP_TIMEOUT] =
- g_param_spec_uint(NM_DHCP_CLIENT_TIMEOUT,
- "",
- "",
- 1,
- G_MAXINT32,
- NM_DHCP_TIMEOUT_DEFAULT,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_FLAGS] =
- g_param_spec_uint(NM_DHCP_CLIENT_FLAGS,
- "",
- "",
- 0,
- G_MAXUINT32,
- 0,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_VENDOR_CLASS_IDENTIFIER] =
- g_param_spec_boxed(NM_DHCP_CLIENT_VENDOR_CLASS_IDENTIFIER,
- "",
- "",
- G_TYPE_BYTES,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
- obj_properties[PROP_REJECT_SERVERS] =
- g_param_spec_boxed(NM_DHCP_CLIENT_REJECT_SERVERS,
- "",
- "",
- G_TYPE_STRV,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
-
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
signals[SIGNAL_NOTIFY] =
diff --git a/src/core/dhcp/nm-dhcp-client.h b/src/core/dhcp/nm-dhcp-client.h
index 2e7e021650..372acc752c 100644
--- a/src/core/dhcp/nm-dhcp-client.h
+++ b/src/core/dhcp/nm-dhcp-client.h
@@ -8,8 +8,6 @@
#include "nm-setting-ip4-config.h"
#include "nm-setting-ip6-config.h"
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
#include "nm-dhcp-utils.h"
#define NM_DHCP_TIMEOUT_DEFAULT ((guint32) 45) /* default DHCP timeout, in seconds */
@@ -24,25 +22,7 @@
#define NM_DHCP_CLIENT_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DHCP_CLIENT, NMDhcpClientClass))
-#define NM_DHCP_CLIENT_ADDR_FAMILY "addr-family"
-#define NM_DHCP_CLIENT_ANYCAST_ADDRESS "anycast-address"
-#define NM_DHCP_CLIENT_FLAGS "flags"
-#define NM_DHCP_CLIENT_HWADDR "hwaddr"
-#define NM_DHCP_CLIENT_BROADCAST_HWADDR "broadcast-hwaddr"
-#define NM_DHCP_CLIENT_IFINDEX "ifindex"
-#define NM_DHCP_CLIENT_INTERFACE "iface"
-#define NM_DHCP_CLIENT_MULTI_IDX "multi-idx"
-#define NM_DHCP_CLIENT_HOSTNAME "hostname"
-#define NM_DHCP_CLIENT_MUD_URL "mud-url"
-#define NM_DHCP_CLIENT_ROUTE_METRIC "route-metric"
-#define NM_DHCP_CLIENT_ROUTE_TABLE "route-table"
-#define NM_DHCP_CLIENT_TIMEOUT "timeout"
-#define NM_DHCP_CLIENT_UUID "uuid"
-#define NM_DHCP_CLIENT_IAID "iaid"
-#define NM_DHCP_CLIENT_IAID_EXPLICIT "iaid-explicit"
-#define NM_DHCP_CLIENT_HOSTNAME_FLAGS "hostname-flags"
-#define NM_DHCP_CLIENT_VENDOR_CLASS_IDENTIFIER "vendor-class-identifier"
-#define NM_DHCP_CLIENT_REJECT_SERVERS "reject-servers"
+#define NM_DHCP_CLIENT_CONFIG "config"
#define NM_DHCP_CLIENT_NOTIFY "dhcp-notify"
@@ -59,7 +39,27 @@ typedef enum {
} NMDhcpState;
typedef enum _nm_packed {
- NM_DHCP_CLIENT_NOTIFY_TYPE_STATE_CHANGED,
+ NM_DHCP_CLIENT_NOTIFY_TYPE_LEASE_UPDATE,
+
+ /* When NM_DHCP_CLIENT_NO_LEASE_TIMEOUT expired and the state
+ * switched from NM_DHCP_CLIENT_STATE_NO_LEASE to
+ * NM_DHCP_CLIENT_STATE_NO_LEASE_WITH_TIMEOUT. */
+ NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT,
+
+ /* NMDhcpClient will indefinitely try to get/renew the lease.
+ * As such, it's never officially in a non-recoverable state.
+ * However, there are cases when it really looks like we won't
+ * be able to get a lease. For example, if the underlying interface
+ * is layer 3 only, if we have no IPv6 link local address for a prolonged
+ * time, or if dhclient is not installed.
+ * But even these cases are potentially recoverable. This is only
+ * a hint to the user (which they might ignore).
+ *
+ * In particular, NM_DHCP_CLIENT_NOTIFY_TYPE_NO_LEASE_TIMEOUT might mean
+ * that the DHCP is currently not running, but that could change
+ * at any moment and from client's side, it does not look bad. */
+ NM_DHCP_CLIENT_NOTIFY_TYPE_IT_LOOKS_BAD,
+
NM_DHCP_CLIENT_NOTIFY_TYPE_PREFIX_DELEGATED,
} NMDhcpClientNotifyType;
@@ -67,18 +67,126 @@ typedef struct {
NMDhcpClientNotifyType notify_type;
union {
struct {
- NMIPConfig *ip_config;
- GHashTable *options;
- NMDhcpState dhcp_state;
- } state_changed;
+ /* This is either the new lease information we just received,
+ * or NULL (if a previous lease timed out). It can also be the
+ * previous lease, that was injected. */
+ const NML3ConfigData *l3cd;
+ } lease_update;
struct {
const NMPlatformIP6Address *prefix;
} prefix_delegated;
+ struct {
+ const char *reason;
+ } it_looks_bad;
};
} NMDhcpClientNotifyData;
const char *nm_dhcp_state_to_string(NMDhcpState state);
+/* FIXME(l3cfg:dhcp:config): nm_dhcp_manager_start_ip[46]() has a gazillion of parameters,
+ * those get passed on as CONSTRUCT_ONLY properties to the NMDhcpClient. Drop
+ * all these parameters, and let the caller provide one NMDhcpClientConfig
+ * instance. There will be only one GObject property (NM_DHCP_CLIENT_CONFIG),
+ * which is CONSTRUCT_ONLY and takes a (mandatory) G_TYPE_POINTER for the
+ * configuration.
+ *
+ * Since NMDhcpClientConfig has an addr_family, we also don't need separate
+ * nm_dhcp_manager_start_ip[46]() methods. */
+typedef struct {
+ int addr_family;
+
+ /* The NML3Cfg instance is the manager object for the ifindex on which
+ * NMDhcpClient is supposed to run. */
+ NML3Cfg *l3cfg;
+
+ /* FIXME(l3cfg:dhcp:previous-lease): most parameters of NMDhcpClient are immutable,
+ * so to change them (during reapply), we need to create and start
+ * a new NMDhcpClient instance.
+ *
+ * However, while the restart happens, we want to stick to the previous
+ * lease (if any). Allow the caller to provide such a previous lease,
+ * and if present, the instance starts by pretending that it just received
+ * this lease, before really starting. */
+ const NML3ConfigData *previous_lease;
+
+ const char *iface;
+
+ /* The hardware address */
+ GBytes *hwaddr;
+
+ /* The broadcast hardware address */
+ GBytes *bcast_hwaddr;
+
+ /* Timeout in seconds before reporting failure */
+ guint32 timeout;
+
+ /* Flags for the hostname and FQDN DHCP options */
+ NMDhcpHostnameFlags hostname_flags;
+
+ /* The UUID of the connection. Used mainly to build
+ * lease file names. */
+ const char *uuid;
+
+ /* Set to reduce the number of broadcast packets when the
+ * anycast hardware address of the DHCP service is known. */
+ const char *anycast_address;
+
+ /* The hostname or FQDN to send. */
+ const char *hostname;
+
+ /* The Manufacturer Usage Description (RFC 8520) URL to send */
+ const char *mud_url;
+
+ /* The value for the Vendor Class Identifier option */
+ GBytes *vendor_class_identifier;
+
+ /* A list of servers from which offers should be rejected */
+ const char *const *reject_servers;
+
+ /* The client identifier (DHCPv4) or DUID (DHCPv6) to send */
+ GBytes *client_id;
+
+ /* Whether to send the hostname or FQDN option */
+ bool send_hostname : 1;
+
+ /* Whether to send the hostname as HOSTNAME option or FQDN.
+ * For DHCPv6 this is always TRUE. */
+ bool use_fqdn : 1;
+
+ union {
+ struct {
+ /* Set BOOTP broadcast flag in request packets, so that servers
+ * will always broadcast replies. */
+ bool request_broadcast : 1;
+
+ /* The address from the previous lease */
+ const char *last_address;
+ } v4;
+ struct {
+ /* The link-local IPv6 address for UDP socket bind() */
+ const struct in6_addr *ll_addr;
+
+ /* If set, the DUID from the connection is used; otherwise
+ * the one from an existing lease is used. */
+ gboolean enforce_duid;
+
+ /* The IAID to use */
+ guint32 iaid;
+
+ /* Whether the IAID was explicitly set in the connection or
+ * as global default */
+ gboolean iaid_explicit;
+
+ /* Number to prefixes (IA_PD) to request */
+ guint needed_prefixes;
+
+ /* Use Information-request to get stateless configuration
+ * parameters (don't request a IA_NA) */
+ bool info_only : 1;
+ } v6;
+ };
+} NMDhcpClientConfig;
+
struct _NMDhcpClientPrivate;
typedef struct {
@@ -100,17 +208,13 @@ typedef enum _nm_packed {
typedef struct {
GObjectClass parent;
- gboolean (*ip4_start)(NMDhcpClient *self, const char *last_ip4_address, GError **error);
+ gboolean (*ip4_start)(NMDhcpClient *self, GError **error);
gboolean (*accept)(NMDhcpClient *self, GError **error);
gboolean (*decline)(NMDhcpClient *self, const char *error_message, GError **error);
- gboolean (*ip6_start)(NMDhcpClient * self,
- const struct in6_addr * ll_addr,
- NMSettingIP6ConfigPrivacy privacy,
- guint needed_prefixes,
- GError ** error);
+ gboolean (*ip6_start)(NMDhcpClient *self, GError **error);
void (*stop)(NMDhcpClient *self, gboolean release);
@@ -128,64 +232,25 @@ typedef struct {
GType nm_dhcp_client_get_type(void);
-struct _NMDedupMultiIndex *nm_dhcp_client_get_multi_idx(NMDhcpClient *self);
-
-pid_t nm_dhcp_client_get_pid(NMDhcpClient *self);
-
-int nm_dhcp_client_get_addr_family(NMDhcpClient *self);
-
-const char *nm_dhcp_client_get_iface(NMDhcpClient *self);
-
-int nm_dhcp_client_get_ifindex(NMDhcpClient *self);
-
-const char *nm_dhcp_client_get_uuid(NMDhcpClient *self);
-
-GBytes *nm_dhcp_client_get_duid(NMDhcpClient *self);
-
-GBytes *nm_dhcp_client_get_hw_addr(NMDhcpClient *self);
-
-GBytes *nm_dhcp_client_get_broadcast_hw_addr(NMDhcpClient *self);
-
-const char *nm_dhcp_client_get_anycast_address(NMDhcpClient *self);
-
-guint32 nm_dhcp_client_get_route_table(NMDhcpClient *self);
-
-void nm_dhcp_client_set_route_table(NMDhcpClient *self, guint32 route_table);
+gboolean nm_dhcp_client_start_ip4(NMDhcpClient *self, GError **error);
+gboolean nm_dhcp_client_start_ip6(NMDhcpClient *self, GError **error);
-guint32 nm_dhcp_client_get_route_metric(NMDhcpClient *self);
+const NMDhcpClientConfig *nm_dhcp_client_get_config(NMDhcpClient *self);
-void nm_dhcp_client_set_route_metric(NMDhcpClient *self, guint32 route_metric);
-
-guint32 nm_dhcp_client_get_timeout(NMDhcpClient *self);
-
-guint32 nm_dhcp_client_get_iaid(NMDhcpClient *self);
-
-gboolean nm_dhcp_client_get_iaid_explicit(NMDhcpClient *self);
-
-GBytes *nm_dhcp_client_get_client_id(NMDhcpClient *self);
-
-const char * nm_dhcp_client_get_hostname(NMDhcpClient *self);
-const char * nm_dhcp_client_get_mud_url(NMDhcpClient *self);
-const char *const *nm_dhcp_client_get_reject_servers(NMDhcpClient *self);
-
-NMDhcpHostnameFlags nm_dhcp_client_get_hostname_flags(NMDhcpClient *self);
-
-NMDhcpClientFlags nm_dhcp_client_get_client_flags(NMDhcpClient *self);
-
-GBytes *nm_dhcp_client_get_vendor_class_identifier(NMDhcpClient *self);
-
-gboolean nm_dhcp_client_start_ip4(NMDhcpClient *self,
- GBytes * client_id,
- const char * last_ip4_address,
- GError ** error);
+pid_t nm_dhcp_client_get_pid(NMDhcpClient *self);
-gboolean nm_dhcp_client_start_ip6(NMDhcpClient * self,
- GBytes * client_id,
- gboolean enforce_duid,
- const struct in6_addr * ll_addr,
- NMSettingIP6ConfigPrivacy privacy,
- guint needed_prefixes,
- GError ** error);
+static inline const NML3ConfigData *
+nm_dhcp_client_get_lease(NMDhcpClient *self)
+{
+ /* FIXME(l3cfg:dhcp:previous-lease): this function returns the currently
+ * valid, exposed lease.
+ *
+ * Note that NMDhcpClient should accept as construct argument a *previous* lease,
+ * and (if that lease is still valid), pretend that it's good to use. The point is
+ * so that during reapply we keep using the current address, until a new lease
+ * was received. */
+ return NULL;
+}
gboolean nm_dhcp_client_accept(NMDhcpClient *self, GError **error);
gboolean nm_dhcp_client_can_accept(NMDhcpClient *self);
@@ -205,10 +270,8 @@ void nm_dhcp_client_watch_child(NMDhcpClient *self, pid_t pid);
void nm_dhcp_client_stop_watch_child(NMDhcpClient *self, pid_t pid);
-void nm_dhcp_client_set_state(NMDhcpClient *self,
- NMDhcpState new_state,
- NMIPConfig * ip_config,
- GHashTable * options); /* str:str hash */
+void
+nm_dhcp_client_set_state(NMDhcpClient *self, NMDhcpState new_state, const NML3ConfigData *l3cd);
gboolean nm_dhcp_client_handle_event(gpointer unused,
const char * iface,
@@ -217,17 +280,19 @@ gboolean nm_dhcp_client_handle_event(gpointer unused,
const char * reason,
NMDhcpClient *self);
-void nm_dhcp_client_set_client_id(NMDhcpClient *self, GBytes *client_id);
-void nm_dhcp_client_set_client_id_bin(NMDhcpClient *self,
- guint8 type,
- const guint8 *client_id,
- gsize len);
-
void nm_dhcp_client_emit_ipv6_prefix_delegated(NMDhcpClient * self,
const NMPlatformIP6Address *prefix);
gboolean nm_dhcp_client_server_id_is_rejected(NMDhcpClient *self, gconstpointer addr);
+int nm_dhcp_client_get_addr_family(NMDhcpClient *self);
+const char * nm_dhcp_client_get_iface(NMDhcpClient *self);
+NMDedupMultiIndex *nm_dhcp_client_get_multi_idx(NMDhcpClient *self);
+int nm_dhcp_client_get_ifindex(NMDhcpClient *self);
+
+void nm_dhcp_client_set_effective_client_id(NMDhcpClient *self, GBytes *client_id);
+GBytes *nm_dhcp_client_get_effective_client_id(NMDhcpClient *self);
+
/*****************************************************************************
* Client data
*****************************************************************************/
diff --git a/src/core/dhcp/nm-dhcp-dhclient-utils.c b/src/core/dhcp/nm-dhcp-dhclient-utils.c
index 341ac7b2fa..60cb46e507 100644
--- a/src/core/dhcp/nm-dhcp-dhclient-utils.c
+++ b/src/core/dhcp/nm-dhcp-dhclient-utils.c
@@ -15,7 +15,6 @@
#include "libnm-glib-aux/nm-dedup-multi.h"
#include "nm-dhcp-utils.h"
-#include "nm-ip4-config.h"
#include "nm-utils.h"
#include "libnm-platform/nm-platform.h"
#include "NetworkManagerUtils.h"
diff --git a/src/core/dhcp/nm-dhcp-dhclient.c b/src/core/dhcp/nm-dhcp-dhclient.c
index 970a51f5dd..9406ae7005 100644
--- a/src/core/dhcp/nm-dhcp-dhclient.c
+++ b/src/core/dhcp/nm-dhcp-dhclient.c
@@ -333,26 +333,28 @@ dhclient_start(NMDhcpClient *client,
const char * mode_opt,
gboolean release,
pid_t * out_pid,
- int prefixes,
GError ** error)
{
NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
gs_unref_ptrarray GPtrArray *argv = NULL;
pid_t pid;
- gs_free_error GError *local = NULL;
- const char * iface;
- const char * uuid;
- const char * system_bus_address;
- const char * dhclient_path;
- char * binary_name;
- gs_free char * cmd_str = NULL;
- gs_free char * pid_file = NULL;
- gs_free char * system_bus_address_env = NULL;
- gs_free char * preferred_leasefile_path = NULL;
- const int addr_family = nm_dhcp_client_get_addr_family(client);
+ gs_free_error GError * local = NULL;
+ const char * iface;
+ const char * uuid;
+ const char * system_bus_address;
+ const char * dhclient_path;
+ char * binary_name;
+ gs_free char * cmd_str = NULL;
+ gs_free char * pid_file = NULL;
+ gs_free char * system_bus_address_env = NULL;
+ gs_free char * preferred_leasefile_path = NULL;
+ int addr_family;
+ const NMDhcpClientConfig *client_config;
g_return_val_if_fail(!priv->pid_file, FALSE);
+ client_config = nm_dhcp_client_get_config(client);
+ addr_family = client_config->addr_family;
NM_SET_OUT(out_pid, 0);
@@ -362,8 +364,8 @@ dhclient_start(NMDhcpClient *client,
return FALSE;
}
- iface = nm_dhcp_client_get_iface(client);
- uuid = nm_dhcp_client_get_uuid(client);
+ iface = client_config->iface;
+ uuid = client_config->uuid;
pid_file = g_strdup_printf(NMRUNDIR "/dhclient%s-%s.pid",
_addr_family_to_path_part(addr_family),
@@ -409,9 +411,7 @@ dhclient_start(NMDhcpClient *client,
/* Save the DUID to the leasefile dhclient will actually use */
if (addr_family == AF_INET6) {
- if (!nm_dhcp_dhclient_save_duid(priv->lease_file,
- nm_dhcp_client_get_client_id(client),
- &local)) {
+ if (!nm_dhcp_dhclient_save_duid(priv->lease_file, client_config->client_id, &local)) {
nm_utils_error_set(error,
NM_UTILS_ERROR_UNKNOWN,
"failed to save DUID to '%s': %s",
@@ -434,13 +434,13 @@ dhclient_start(NMDhcpClient *client,
if (release)
g_ptr_array_add(argv, (gpointer) "-r");
- if (!release
- && NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)),
- NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST)) {
+ if (!release && client_config->addr_family == AF_INET && client_config->v4.request_broadcast) {
g_ptr_array_add(argv, (gpointer) "-B");
}
if (addr_family == AF_INET6) {
+ guint prefixes = client_config->v6.needed_prefixes;
+
g_ptr_array_add(argv, (gpointer) "-6");
if (prefixes > 0 && nm_streq0(mode_opt, "-S")) {
@@ -513,29 +513,28 @@ dhclient_start(NMDhcpClient *client,
}
static gboolean
-ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
+ip4_start(NMDhcpClient *client, GError **error)
{
- NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
- NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
- GBytes * client_id;
- gs_unref_bytes GBytes *new_client_id = NULL;
-
- client_id = nm_dhcp_client_get_client_id(client);
-
- priv->conf_file = create_dhclient_config(
- self,
- AF_INET,
- nm_dhcp_client_get_iface(client),
- nm_dhcp_client_get_uuid(client),
- client_id,
- nm_dhcp_client_get_anycast_address(client),
- nm_dhcp_client_get_hostname(client),
- nm_dhcp_client_get_timeout(client),
- NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client), NM_DHCP_CLIENT_FLAGS_USE_FQDN),
- nm_dhcp_client_get_hostname_flags(client),
- nm_dhcp_client_get_mud_url(client),
- nm_dhcp_client_get_reject_servers(client),
- &new_client_id);
+ NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
+ NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
+ gs_unref_bytes GBytes * new_client_id = NULL;
+ const NMDhcpClientConfig *client_config;
+
+ client_config = nm_dhcp_client_get_config(client);
+
+ priv->conf_file = create_dhclient_config(self,
+ AF_INET,
+ client_config->iface,
+ client_config->uuid,
+ client_config->client_id,
+ client_config->anycast_address,
+ client_config->hostname,
+ client_config->timeout,
+ client_config->use_fqdn,
+ client_config->hostname_flags,
+ client_config->mud_url,
+ client_config->reject_servers,
+ &new_client_id);
if (!priv->conf_file) {
nm_utils_error_set_literal(error,
NM_UTILS_ERROR_UNKNOWN,
@@ -544,36 +543,35 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
}
if (new_client_id) {
- nm_assert(!client_id);
- nm_dhcp_client_set_client_id(client, new_client_id);
+ nm_assert(!client_config->client_id);
+ nm_dhcp_client_set_effective_client_id(client, new_client_id);
}
- return dhclient_start(client, NULL, FALSE, NULL, 0, error);
+ return dhclient_start(client, NULL, FALSE, NULL, error);
}
static gboolean
-ip6_start(NMDhcpClient * client,
- const struct in6_addr * ll_addr,
- NMSettingIP6ConfigPrivacy privacy,
- guint needed_prefixes,
- GError ** error)
+ip6_start(NMDhcpClient *client, GError **error)
{
- NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
- NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
+ NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
+ NMDhcpDhclientPrivate * priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
+ const NMDhcpClientConfig *config;
- if (nm_dhcp_client_get_iaid_explicit(client))
+ config = nm_dhcp_client_get_config(client);
+
+ if (config->v6.iaid_explicit)
_LOGW("dhclient does not support specifying an IAID for DHCPv6, it will be ignored");
priv->conf_file = create_dhclient_config(self,
AF_INET6,
- nm_dhcp_client_get_iface(client),
- nm_dhcp_client_get_uuid(client),
+ config->iface,
+ config->uuid,
NULL,
- nm_dhcp_client_get_anycast_address(client),
- nm_dhcp_client_get_hostname(client),
- nm_dhcp_client_get_timeout(client),
+ config->anycast_address,
+ config->hostname,
+ config->timeout,
TRUE,
- nm_dhcp_client_get_hostname_flags(client),
- nm_dhcp_client_get_mud_url(client),
+ config->hostname_flags,
+ config->mud_url,
NULL,
NULL);
if (!priv->conf_file) {
@@ -583,15 +581,7 @@ ip6_start(NMDhcpClient * client,
return FALSE;
}
- return dhclient_start(client,
- NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)),
- NM_DHCP_CLIENT_FLAGS_INFO_ONLY)
- ? "-S"
- : "-N",
- FALSE,
- NULL,
- needed_prefixes,
- error);
+ return dhclient_start(client, config->v6.needed_prefixes ? "-S" : "-N", FALSE, NULL, error);
}
static void
@@ -625,7 +615,7 @@ stop(NMDhcpClient *client, gboolean release)
if (release) {
pid_t rpid = -1;
- if (dhclient_start(client, NULL, TRUE, &rpid, 0, NULL)) {
+ if (dhclient_start(client, NULL, TRUE, &rpid, NULL)) {
/* Wait a few seconds for the release to happen */
nm_dhcp_client_stop_pid(rpid, nm_dhcp_client_get_iface(client));
}
@@ -635,16 +625,19 @@ stop(NMDhcpClient *client, gboolean release)
static GBytes *
get_duid(NMDhcpClient *client)
{
- NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
- NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
- GBytes * duid = NULL;
- gs_free char * leasefile = NULL;
- GError * error = NULL;
+ NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client);
+ NMDhcpDhclientPrivate * priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self);
+ const NMDhcpClientConfig *client_config;
+ GBytes * duid = NULL;
+ gs_free char * leasefile = NULL;
+ GError * error = NULL;
+
+ client_config = nm_dhcp_client_get_config(client);
/* Look in interface-specific leasefile first for backwards compat */
leasefile = get_dhclient_leasefile(AF_INET6,
nm_dhcp_client_get_iface(client),
- nm_dhcp_client_get_uuid(client),
+ client_config->uuid,
NULL);
if (leasefile) {
_LOGD("looking for DUID in '%s'", leasefile);
diff --git a/src/core/dhcp/nm-dhcp-dhcpcanon.c b/src/core/dhcp/nm-dhcp-dhcpcanon.c
index f993ffb940..ed29b85cd0 100644
--- a/src/core/dhcp/nm-dhcp-dhcpcanon.c
+++ b/src/core/dhcp/nm-dhcp-dhcpcanon.c
@@ -160,7 +160,7 @@ dhcpcanon_start(NMDhcpClient *client,
}
static gboolean
-ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
+ip4_start(NMDhcpClient *client, GError **error)
{
return dhcpcanon_start(client, NULL, NULL, FALSE, NULL, 0, error);
}
diff --git a/src/core/dhcp/nm-dhcp-dhcpcd.c b/src/core/dhcp/nm-dhcp-dhcpcd.c
index 7522156bef..0a6a91b743 100644
--- a/src/core/dhcp/nm-dhcp-dhcpcd.c
+++ b/src/core/dhcp/nm-dhcp-dhcpcd.c
@@ -64,21 +64,19 @@ nm_dhcp_dhcpcd_get_path(void)
}
static gboolean
-ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
+ip4_start(NMDhcpClient *client, GError **error)
{
- NMDhcpDhcpcd * self = NM_DHCP_DHCPCD(client);
+ NMDhcpDhcpcd * self = NM_DHCP_DHCPCD(client);
+ const NMDhcpClientConfig *client_config;
gs_unref_ptrarray GPtrArray *argv = NULL;
pid_t pid;
GError * local;
gs_free char * cmd_str = NULL;
- const char * iface;
const char * dhcpcd_path;
- const char * hostname;
pid = nm_dhcp_client_get_pid(client);
g_return_val_if_fail(pid == -1, FALSE);
-
- iface = nm_dhcp_client_get_iface(client);
+ client_config = nm_dhcp_client_get_config(client);
dhcpcd_path = nm_dhcp_dhcpcd_get_path();
if (!dhcpcd_path) {
@@ -115,21 +113,19 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
*/
g_ptr_array_add(argv, (gpointer) "-4");
- hostname = nm_dhcp_client_get_hostname(client);
-
- if (hostname) {
- if (NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client), NM_DHCP_CLIENT_FLAGS_USE_FQDN)) {
+ if (client_config->hostname) {
+ if (client_config->use_fqdn) {
g_ptr_array_add(argv, (gpointer) "-h");
- g_ptr_array_add(argv, (gpointer) hostname);
+ g_ptr_array_add(argv, (gpointer) client_config->hostname);
g_ptr_array_add(argv, (gpointer) "-F");
g_ptr_array_add(argv, (gpointer) "both");
} else {
g_ptr_array_add(argv, (gpointer) "-h");
- g_ptr_array_add(argv, (gpointer) hostname);
+ g_ptr_array_add(argv, (gpointer) client_config->hostname);
}
}
- g_ptr_array_add(argv, (gpointer) iface);
+ g_ptr_array_add(argv, (gpointer) client_config->iface);
g_ptr_array_add(argv, NULL);
_LOGD("running: %s", (cmd_str = g_strjoinv(" ", (char **) argv->pdata)));
diff --git a/src/core/dhcp/nm-dhcp-manager.c b/src/core/dhcp/nm-dhcp-manager.c
index 3cb893932d..7c7ac13f33 100644
--- a/src/core/dhcp/nm-dhcp-manager.c
+++ b/src/core/dhcp/nm-dhcp-manager.c
@@ -17,7 +17,6 @@
#include <stdio.h>
#include "libnm-glib-aux/nm-dedup-multi.h"
-#include "libnm-systemd-shared/nm-sd-utils-shared.h"
#include "nm-config.h"
#include "NetworkManagerUtils.h"
@@ -26,7 +25,6 @@
typedef struct {
const NMDhcpClientFactory *client_factory;
- char * default_hostname;
} NMDhcpManagerPrivate;
struct _NMDhcpManager {
@@ -129,34 +127,8 @@ _client_factory_get_gtype(const NMDhcpClientFactory *client_factory, int addr_fa
/*****************************************************************************/
-static NMDhcpClient *
-client_start(NMDhcpManager * self,
- int addr_family,
- NMDedupMultiIndex * multi_idx,
- const char * iface,
- int ifindex,
- GBytes * hwaddr,
- GBytes * bcast_hwaddr,
- const char * uuid,
- guint32 route_table,
- guint32 route_metric,
- const struct in6_addr * ipv6_ll_addr,
- GBytes * dhcp_client_id,
- gboolean enforce_duid,
- guint32 iaid,
- gboolean iaid_explicit,
- guint32 timeout,
- NMDhcpClientFlags client_flags,
- const char * anycast_address,
- const char * hostname,
- NMDhcpHostnameFlags hostname_flags,
- const char * mud_url,
- NMSettingIP6ConfigPrivacy privacy,
- const char * last_ip4_address,
- guint needed_prefixes,
- GBytes * vendor_class_identifier,
- const char *const * reject_servers,
- GError ** error)
+NMDhcpClient *
+nm_dhcp_manager_start_client(NMDhcpManager *self, NMDhcpClientConfig *config, GError **error)
{
NMDhcpManagerPrivate *priv;
gs_unref_object NMDhcpClient *client = NULL;
@@ -165,100 +137,44 @@ client_start(NMDhcpManager * self,
GType gtype;
g_return_val_if_fail(NM_IS_DHCP_MANAGER(self), NULL);
- g_return_val_if_fail(iface, NULL);
- g_return_val_if_fail(ifindex > 0, NULL);
- g_return_val_if_fail(uuid != NULL, NULL);
- g_return_val_if_fail(!dhcp_client_id || g_bytes_get_size(dhcp_client_id) >= 2, NULL);
- g_return_val_if_fail(!vendor_class_identifier
- || g_bytes_get_size(vendor_class_identifier) <= 255,
+ g_return_val_if_fail(config, NULL);
+ g_return_val_if_fail(config->iface, NULL);
+ g_return_val_if_fail(config->l3cfg, NULL);
+ g_return_val_if_fail(config->uuid != NULL, NULL);
+ g_return_val_if_fail(!config->client_id || g_bytes_get_size(config->client_id) >= 2, NULL);
+ g_return_val_if_fail(!config->vendor_class_identifier
+ || g_bytes_get_size(config->vendor_class_identifier) <= 255,
NULL);
g_return_val_if_fail(!error || !*error, NULL);
- nm_assert(!NM_FLAGS_ANY(client_flags, ~NM_DHCP_CLIENT_FLAGS_ALL));
- if (addr_family == AF_INET) {
- if (!hwaddr || !bcast_hwaddr) {
+ if (config->addr_family == AF_INET) {
+ if (!config->hwaddr || !config->bcast_hwaddr) {
nm_utils_error_set(error,
NM_UTILS_ERROR_UNKNOWN,
"missing %s address",
- hwaddr ? "broadcast" : "MAC");
+ config->hwaddr ? "broadcast" : "MAC");
return NULL;
}
- hwaddr_len = g_bytes_get_size(hwaddr);
+ hwaddr_len = g_bytes_get_size(config->hwaddr);
if (hwaddr_len == 0 || hwaddr_len > _NM_UTILS_HWADDR_LEN_MAX) {
nm_utils_error_set(error, NM_UTILS_ERROR_UNKNOWN, "invalid MAC address");
g_return_val_if_reached(NULL);
}
- nm_assert(g_bytes_get_size(hwaddr) == g_bytes_get_size(bcast_hwaddr));
- } else {
- hwaddr = NULL;
- bcast_hwaddr = NULL;
- }
-
- if (hostname) {
- gboolean use_fqdn = NM_FLAGS_HAS(client_flags, NM_DHCP_CLIENT_FLAGS_USE_FQDN);
-
- if ((use_fqdn && !nm_sd_dns_name_is_valid(hostname))
- || (!use_fqdn && !nm_sd_hostname_is_valid(hostname, FALSE))) {
- nm_log_warn(LOGD_DHCP,
- "dhcp%c: %s '%s' is invalid, will be ignored",
- nm_utils_addr_family_to_char(addr_family),
- use_fqdn ? "FQDN" : "hostname",
- hostname);
- hostname = NULL;
- }
+ nm_assert(g_bytes_get_size(config->hwaddr) == g_bytes_get_size(config->bcast_hwaddr));
}
priv = NM_DHCP_MANAGER_GET_PRIVATE(self);
- gtype = _client_factory_get_gtype(priv->client_factory, addr_family);
+ gtype = _client_factory_get_gtype(priv->client_factory, config->addr_family);
nm_log_trace(LOGD_DHCP,
"dhcp%c: creating IPv%c DHCP client of type %s",
- nm_utils_addr_family_to_char(addr_family),
- nm_utils_addr_family_to_char(addr_family),
+ nm_utils_addr_family_to_char(config->addr_family),
+ nm_utils_addr_family_to_char(config->addr_family),
g_type_name(gtype));
- client = g_object_new(gtype,
- NM_DHCP_CLIENT_MULTI_IDX,
- multi_idx,
- NM_DHCP_CLIENT_ADDR_FAMILY,
- addr_family,
- NM_DHCP_CLIENT_INTERFACE,
- iface,
- NM_DHCP_CLIENT_IFINDEX,
- ifindex,
- NM_DHCP_CLIENT_HWADDR,
- hwaddr,
- NM_DHCP_CLIENT_BROADCAST_HWADDR,
- bcast_hwaddr,
- NM_DHCP_CLIENT_UUID,
- uuid,
- NM_DHCP_CLIENT_IAID,
- (guint) iaid,
- NM_DHCP_CLIENT_IAID_EXPLICIT,
- iaid_explicit,
- NM_DHCP_CLIENT_HOSTNAME,
- hostname,
- NM_DHCP_CLIENT_MUD_URL,
- mud_url,
- NM_DHCP_CLIENT_ROUTE_TABLE,
- (guint) route_table,
- NM_DHCP_CLIENT_ROUTE_METRIC,
- (guint) route_metric,
- NM_DHCP_CLIENT_TIMEOUT,
- (guint) timeout,
- NM_DHCP_CLIENT_HOSTNAME_FLAGS,
- (guint) hostname_flags,
- NM_DHCP_CLIENT_VENDOR_CLASS_IDENTIFIER,
- vendor_class_identifier,
- NM_DHCP_CLIENT_REJECT_SERVERS,
- reject_servers,
- NM_DHCP_CLIENT_FLAGS,
- (guint) client_flags,
- NM_DHCP_CLIENT_ANYCAST_ADDRESS,
- anycast_address,
- NULL);
+ client = g_object_new(gtype, NM_DHCP_CLIENT_CONFIG, config, NULL);
/* unfortunately, our implementations work differently per address-family regarding client-id/DUID.
*
@@ -286,16 +202,10 @@ client_start(NMDhcpManager * self,
* default outside of NetworkManager API.
*/
- if (addr_family == AF_INET) {
- success = nm_dhcp_client_start_ip4(client, dhcp_client_id, last_ip4_address, error);
+ if (config->addr_family == AF_INET) {
+ success = nm_dhcp_client_start_ip4(client, error);
} else {
- success = nm_dhcp_client_start_ip6(client,
- dhcp_client_id,
- enforce_duid,
- ipv6_ll_addr,
- privacy,
- needed_prefixes,
- error);
+ success = nm_dhcp_client_start_ip6(client, error);
}
if (!success)
@@ -304,178 +214,6 @@ client_start(NMDhcpManager * self,
return g_steal_pointer(&client);
}
-/* Caller owns a reference to the NMDhcpClient on return */
-NMDhcpClient *
-nm_dhcp_manager_start_ip4(NMDhcpManager * self,
- NMDedupMultiIndex * multi_idx,
- const char * iface,
- int ifindex,
- GBytes * hwaddr,
- GBytes * bcast_hwaddr,
- const char * uuid,
- guint32 route_table,
- guint32 route_metric,
- NMDhcpClientFlags client_flags,
- gboolean send_hostname,
- const char * dhcp_hostname,
- const char * dhcp_fqdn,
- NMDhcpHostnameFlags hostname_flags,
- const char * mud_url,
- GBytes * dhcp_client_id,
- guint32 timeout,
- const char * anycast_address,
- const char * last_ip_address,
- GBytes * vendor_class_identifier,
- const char *const * reject_servers,
- GError ** error)
-{
- NMDhcpManagerPrivate *priv;
- const char * hostname = NULL;
- gs_free char * hostname_tmp = NULL;
- gboolean use_fqdn = FALSE;
- char * dot;
-
- /* these flags are set automatically/prohibited, and not free to set to the caller. */
- nm_assert(!NM_FLAGS_ANY(client_flags,
- NM_DHCP_CLIENT_FLAGS_USE_FQDN | NM_DHCP_CLIENT_FLAGS_INFO_ONLY));
-
- g_return_val_if_fail(NM_IS_DHCP_MANAGER(self), NULL);
- priv = NM_DHCP_MANAGER_GET_PRIVATE(self);
-
- if (send_hostname) {
- /* Use, in order of preference:
- * 1. FQDN from configuration
- * 2. hostname from configuration
- * 3. system hostname (only host part)
- */
- if (dhcp_fqdn) {
- hostname = dhcp_fqdn;
- use_fqdn = TRUE;
- } else if (dhcp_hostname)
- hostname = dhcp_hostname;
- else {
- hostname = priv->default_hostname;
- if (hostname) {
- hostname_tmp = g_strdup(hostname);
- dot = strchr(hostname_tmp, '.');
- if (dot)
- *dot = '\0';
- hostname = hostname_tmp;
- }
- }
- }
-
- return client_start(
- self,
- AF_INET,
- multi_idx,
- iface,
- ifindex,
- hwaddr,
- bcast_hwaddr,
- uuid,
- route_table,
- route_metric,
- NULL,
- dhcp_client_id,
- FALSE,
- 0,
- FALSE,
- timeout,
- client_flags | (use_fqdn ? NM_DHCP_CLIENT_FLAGS_USE_FQDN : NM_DHCP_CLIENT_FLAGS_NONE),
- anycast_address,
- hostname,
- hostname_flags,
- mud_url,
- 0,
- last_ip_address,
- 0,
- vendor_class_identifier,
- reject_servers,
- error);
-}
-
-/* Caller owns a reference to the NMDhcpClient on return */
-NMDhcpClient *
-nm_dhcp_manager_start_ip6(NMDhcpManager * self,
- NMDedupMultiIndex * multi_idx,
- const char * iface,
- int ifindex,
- const struct in6_addr * ll_addr,
- const char * uuid,
- guint32 route_table,
- guint32 route_metric,
- NMDhcpClientFlags client_flags,
- gboolean send_hostname,
- const char * dhcp_hostname,
- NMDhcpHostnameFlags hostname_flags,
- const char * mud_url,
- GBytes * duid,
- gboolean enforce_duid,
- guint32 iaid,
- gboolean iaid_explicit,
- guint32 timeout,
- const char * anycast_address,
- NMSettingIP6ConfigPrivacy privacy,
- guint needed_prefixes,
- GError ** error)
-{
- NMDhcpManagerPrivate *priv;
- const char * hostname = NULL;
-
- /* this flag is set automatically, and not free to set to the caller. */
- nm_assert(!NM_FLAGS_ANY(client_flags, NM_DHCP_CLIENT_FLAGS_USE_FQDN));
-
- g_return_val_if_fail(NM_IS_DHCP_MANAGER(self), NULL);
- priv = NM_DHCP_MANAGER_GET_PRIVATE(self);
-
- if (send_hostname) {
- /* Always prefer the explicit dhcp-hostname if given */
- hostname = dhcp_hostname ?: priv->default_hostname;
- }
- return client_start(self,
- AF_INET6,
- multi_idx,
- iface,
- ifindex,
- NULL,
- NULL,
- uuid,
- route_table,
- route_metric,
- ll_addr,
- duid,
- enforce_duid,
- iaid,
- iaid_explicit,
- timeout,
- client_flags | NM_DHCP_CLIENT_FLAGS_USE_FQDN,
- anycast_address,
- hostname,
- hostname_flags,
- mud_url,
- privacy,
- NULL,
- needed_prefixes,
- NULL,
- NULL,
- error);
-}
-
-void
-nm_dhcp_manager_set_default_hostname(NMDhcpManager *manager, const char *hostname)
-{
- NMDhcpManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE(manager);
-
- nm_clear_g_free(&priv->default_hostname);
-
- /* Never send 'localhost'-type names to the DHCP server */
- if (!nm_utils_is_specific_hostname(hostname))
- return;
-
- priv->default_hostname = g_strdup(hostname);
-}
-
const char *
nm_dhcp_manager_get_config(NMDhcpManager *self)
{
@@ -573,20 +311,5 @@ nm_dhcp_manager_init(NMDhcpManager *self)
}
static void
-dispose(GObject *object)
-{
- NMDhcpManager * self = NM_DHCP_MANAGER(object);
- NMDhcpManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE(self);
-
- G_OBJECT_CLASS(nm_dhcp_manager_parent_class)->dispose(object);
-
- nm_clear_g_free(&priv->default_hostname);
-}
-
-static void
nm_dhcp_manager_class_init(NMDhcpManagerClass *manager_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS(manager_class);
-
- object_class->dispose = dispose;
-}
+{}
diff --git a/src/core/dhcp/nm-dhcp-manager.h b/src/core/dhcp/nm-dhcp-manager.h
index ce160437a5..bbd68236a3 100644
--- a/src/core/dhcp/nm-dhcp-manager.h
+++ b/src/core/dhcp/nm-dhcp-manager.h
@@ -8,7 +8,6 @@
#define __NETWORKMANAGER_DHCP_MANAGER_H__
#include "nm-dhcp-client.h"
-#include "nm-ip4-config.h"
#include "nm-dhcp-config.h"
#define NM_TYPE_DHCP_MANAGER (nm_dhcp_manager_get_type())
@@ -32,51 +31,8 @@ const char *nm_dhcp_manager_get_config(NMDhcpManager *self);
void nm_dhcp_manager_set_default_hostname(NMDhcpManager *manager, const char *hostname);
-NMDhcpClient *nm_dhcp_manager_start_ip4(NMDhcpManager * manager,
- struct _NMDedupMultiIndex *multi_idx,
- const char * iface,
- int ifindex,
- GBytes * hwaddr,
- GBytes * bcast_hwaddr,
- const char * uuid,
- guint32 route_table,
- guint32 route_metric,
- NMDhcpClientFlags client_flags,
- gboolean send_hostname,
- const char * dhcp_hostname,
- const char * dhcp_fqdn,
- NMDhcpHostnameFlags hostname_flags,
- const char * mud_url,
- GBytes * dhcp_client_id,
- guint32 timeout,
- const char * anycast_address,
- const char * last_ip_address,
- GBytes * vendor_class_identifier,
- const char *const * reject_servers,
- GError ** error);
-
-NMDhcpClient *nm_dhcp_manager_start_ip6(NMDhcpManager * manager,
- struct _NMDedupMultiIndex *multi_idx,
- const char * iface,
- int ifindex,
- const struct in6_addr * ll_addr,
- const char * uuid,
- guint32 route_table,
- guint32 route_metric,
- NMDhcpClientFlags client_flags,
- gboolean send_hostname,
- const char * dhcp_hostname,
- NMDhcpHostnameFlags hostname_flags,
- const char * mud_url,
- GBytes * duid,
- gboolean enforce_duid,
- guint32 iaid,
- gboolean iaid_explicit,
- guint32 timeout,
- const char * anycast_address,
- NMSettingIP6ConfigPrivacy privacy,
- guint needed_prefixes,
- GError ** error);
+NMDhcpClient *
+nm_dhcp_manager_start_client(NMDhcpManager *manager, NMDhcpClientConfig *config, GError **error);
/* For testing only */
extern const char *nm_dhcp_helper_path;
diff --git a/src/core/dhcp/nm-dhcp-nettools.c b/src/core/dhcp/nm-dhcp-nettools.c
index 56b485dd25..6ab7f8c18d 100644
--- a/src/core/dhcp/nm-dhcp-nettools.c
+++ b/src/core/dhcp/nm-dhcp-nettools.c
@@ -17,6 +17,7 @@
#include "libnm-std-aux/unaligned.h"
#include "libnm-glib-aux/nm-str-buf.h"
+#include "nm-l3-config-data.h"
#include "nm-utils.h"
#include "nm-config.h"
#include "nm-dhcp-utils.h"
@@ -151,7 +152,7 @@ lease_option_consume_route(const uint8_t **datap,
static gboolean
lease_parse_address(NDhcp4ClientLease *lease,
- NMIP4Config * ip4_config,
+ NML3ConfigData * l3cd,
GHashTable * options,
GError ** error)
{
@@ -256,23 +257,23 @@ lease_parse_address(NDhcp4ClientLease *lease,
a_next_server.s_addr);
}
- nm_ip4_config_add_address(ip4_config,
- &((const NMPlatformIP4Address){
- .address = a_address.s_addr,
- .peer_address = a_address.s_addr,
- .plen = a_plen,
- .addr_source = NM_IP_CONFIG_SOURCE_DHCP,
- .timestamp = a_timestamp,
- .lifetime = a_lifetime,
- .preferred = a_lifetime,
- }));
+ nm_l3_config_data_add_address_4(l3cd,
+ &((const NMPlatformIP4Address){
+ .address = a_address.s_addr,
+ .peer_address = a_address.s_addr,
+ .plen = a_plen,
+ .addr_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .timestamp = a_timestamp,
+ .lifetime = a_lifetime,
+ .preferred = a_lifetime,
+ }));
return TRUE;
}
static void
lease_parse_address_list(NDhcp4ClientLease * lease,
- NMIP4Config * ip4_config,
+ NML3ConfigData * l3cd,
NMDhcpOptionDhcp4Options option,
GHashTable * options,
NMStrBuf * sbuf)
@@ -304,13 +305,13 @@ lease_parse_address_list(NDhcp4ClientLease * lease,
* See https://github.com/systemd/systemd/issues/4524. */
continue;
}
- nm_ip4_config_add_nameserver(ip4_config, addr);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET, &addr);
break;
case NM_DHCP_OPTION_DHCP4_NIS_SERVERS:
- nm_ip4_config_add_nis_server(ip4_config, addr);
+ nm_l3_config_data_add_nis_server(l3cd, addr);
break;
case NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER:
- nm_ip4_config_add_wins(ip4_config, addr);
+ nm_l3_config_data_add_wins(l3cd, addr);
break;
case NM_DHCP_OPTION_DHCP4_NTP_SERVER:
break;
@@ -324,10 +325,8 @@ lease_parse_address_list(NDhcp4ClientLease * lease,
static void
lease_parse_routes(NDhcp4ClientLease *lease,
- NMIP4Config * ip4_config,
+ NML3ConfigData * l3cd,
GHashTable * options,
- guint32 route_table,
- guint32 route_metric,
NMStrBuf * sbuf)
{
char dest_str[NM_UTILS_INET_ADDRSTRLEN];
@@ -336,9 +335,9 @@ lease_parse_routes(NDhcp4ClientLease *lease,
in_addr_t gateway;
uint8_t plen;
guint32 m;
- gboolean has_router_from_classless = FALSE;
- gboolean has_classless = FALSE;
- guint32 default_route_metric = route_metric;
+ gboolean has_router_from_classless = FALSE;
+ gboolean has_classless = FALSE;
+ guint32 default_route_metric_offset = 0;
const guint8 *l_data;
gsize l_data_len;
int r;
@@ -367,26 +366,22 @@ lease_parse_routes(NDhcp4ClientLease *lease,
if (plen == 0) {
/* if there are multiple default routes, we add them with differing
* metrics. */
- m = default_route_metric;
- if (default_route_metric < G_MAXUINT32)
- default_route_metric++;
-
+ m = default_route_metric_offset++;
has_router_from_classless = TRUE;
- } else {
- m = route_metric;
- }
-
- nm_ip4_config_add_route(
- ip4_config,
- &((const NMPlatformIP4Route){
- .network = dest,
- .plen = plen,
- .gateway = gateway,
- .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
- .metric = m,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- }),
- NULL);
+ } else
+ m = 0;
+
+ nm_l3_config_data_add_route_4(l3cd,
+ &((const NMPlatformIP4Route){
+ .network = dest,
+ .plen = plen,
+ .gateway = gateway,
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = m,
+ }));
}
has_classless = TRUE;
@@ -419,17 +414,17 @@ lease_parse_routes(NDhcp4ClientLease *lease,
continue;
}
- nm_ip4_config_add_route(
- ip4_config,
- &((const NMPlatformIP4Route){
- .network = dest,
- .plen = plen,
- .gateway = gateway,
- .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
- .metric = route_metric,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- }),
- NULL);
+ nm_l3_config_data_add_route_4(l3cd,
+ &((const NMPlatformIP4Route){
+ .network = dest,
+ .plen = plen,
+ .gateway = gateway,
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
+ }));
}
nm_dhcp_option_add_option(options,
@@ -463,19 +458,17 @@ lease_parse_routes(NDhcp4ClientLease *lease,
/* if there are multiple default routes, we add them with differing
* metrics. */
- m = default_route_metric;
- if (default_route_metric < G_MAXUINT32)
- default_route_metric++;
-
- nm_ip4_config_add_route(
- ip4_config,
- &((const NMPlatformIP4Route){
- .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
- .gateway = gateway,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- .metric = m,
- }),
- NULL);
+ m = default_route_metric_offset++;
+
+ nm_l3_config_data_add_route_4(l3cd,
+ &((const NMPlatformIP4Route){
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .gateway = gateway,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = m,
+ }));
}
nm_dhcp_option_add_option(options,
@@ -486,7 +479,7 @@ lease_parse_routes(NDhcp4ClientLease *lease,
}
static void
-lease_parse_search_domains(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GHashTable *options)
+lease_parse_search_domains(NDhcp4ClientLease *lease, NML3ConfigData *l3cd, GHashTable *options)
{
gs_strfreev char **domains = NULL;
const guint8 * l_data;
@@ -504,7 +497,7 @@ lease_parse_search_domains(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GH
return;
for (i = 0; domains[i]; i++)
- nm_ip4_config_add_search(ip4_config, domains[i]);
+ nm_l3_config_data_add_search(l3cd, AF_INET, domains[i]);
nm_dhcp_option_take_option(options,
AF_INET,
@@ -539,34 +532,31 @@ lease_parse_private_options(NDhcp4ClientLease *lease, GHashTable *options)
}
}
-static NMIP4Config *
+static NML3ConfigData *
lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
const char * iface,
int ifindex,
NDhcp4ClientLease *lease,
- guint32 route_table,
- guint32 route_metric,
- GHashTable ** out_options,
GError ** error)
{
- nm_auto_str_buf NMStrBuf sbuf = NM_STR_BUF_INIT(0, FALSE);
- gs_unref_object NMIP4Config *ip4_config = NULL;
- gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_str_buf NMStrBuf sbuf = NM_STR_BUF_INIT(0, FALSE);
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ gs_unref_hashtable GHashTable *options = NULL;
const guint8 * l_data;
gsize l_data_len;
const char * v_str;
guint16 v_u16;
- gboolean v_bool;
in_addr_t v_inaddr;
struct in_addr v_inaddr_s;
int r;
g_return_val_if_fail(lease != NULL, NULL);
- ip4_config = nm_ip4_config_new(multi_idx, ifindex);
- options = nm_dhcp_option_create_options_dict();
+ l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP);
+
+ options = nm_dhcp_option_create_options_dict();
- if (!lease_parse_address(lease, ip4_config, options, error))
+ if (!lease_parse_address(lease, l3cd, options, error))
return NULL;
r = n_dhcp4_client_lease_get_server_identifier(lease, &v_inaddr_s);
@@ -585,13 +575,9 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
v_inaddr);
}
- lease_parse_routes(lease, ip4_config, options, route_table, route_metric, &sbuf);
+ lease_parse_routes(lease, l3cd, options, &sbuf);
- lease_parse_address_list(lease,
- ip4_config,
- NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER,
- options,
- &sbuf);
+ lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, options, &sbuf);
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, &l_data, &l_data_len);
if (r == 0 && nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) {
@@ -616,7 +602,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
nm_str_buf_append_required_delimiter(&sbuf, ' ');
nm_str_buf_append(&sbuf, s);
- nm_ip4_config_add_domain(ip4_config, s);
+ nm_l3_config_data_add_domain(l3cd, AF_INET, s);
}
}
@@ -628,18 +614,17 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
}
}
- lease_parse_search_domains(lease, ip4_config, options);
+ lease_parse_search_domains(lease, l3cd, options);
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, &l_data, &l_data_len);
if (r == 0 && nm_dhcp_lease_data_parse_mtu(l_data, l_data_len, &v_u16)) {
nm_dhcp_option_add_option_u64(options, AF_INET, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, v_u16);
- nm_ip4_config_set_mtu(ip4_config, v_u16, NM_IP_CONFIG_SOURCE_DHCP);
+ nm_l3_config_data_set_mtu(l3cd, v_u16);
}
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_VENDOR_SPECIFIC, &l_data, &l_data_len);
- v_bool =
- (r == 0) && memmem(l_data, l_data_len, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED"));
- nm_ip4_config_set_metered(ip4_config, v_bool);
+ if ((r == 0) && memmem(l_data, l_data_len, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED")))
+ nm_l3_config_data_set_metered(l3cd, TRUE);
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_HOST_NAME, &l_data, &l_data_len);
if (r == 0) {
@@ -650,7 +635,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
}
}
- lease_parse_address_list(lease, ip4_config, NM_DHCP_OPTION_DHCP4_NTP_SERVER, options, &sbuf);
+ lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_NTP_SERVER, options, &sbuf);
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_ROOT_PATH, &l_data, &l_data_len);
if (r == 0 && nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) {
@@ -681,11 +666,17 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
* We reject NUL characters inside the string (except trailing NULs).
* Otherwise, we allow any encoding and backslash-escape the result to
* UTF-8. */
- nm_dhcp_option_add_option_utf8safe_escape(options,
- AF_INET,
- NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY,
- l_data,
- l_data_len);
+ gs_free char *to_free = NULL;
+ const char * escaped;
+
+ escaped = nm_utils_buf_utf8safe_escape((char *) l_data, l_data_len, 0, &to_free);
+ nm_dhcp_option_add_option(options,
+ AF_INET,
+ NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY,
+ escaped ?: "");
+
+ nm_l3_config_data_set_proxy_method(l3cd, NM_PROXY_CONFIG_METHOD_AUTO);
+ nm_l3_config_data_set_proxy_pac_url(l3cd, escaped ?: "");
}
r = _client_lease_query(lease, NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, &l_data, &l_data_len);
@@ -700,7 +691,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
&to_free);
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, v_str ?: "");
- nm_ip4_config_set_nis_domain(ip4_config, v_str ?: "");
+ nm_l3_config_data_set_nis_domain(l3cd, v_str ?: "");
}
r = n_dhcp4_client_lease_get_file(lease, &v_str);
@@ -728,18 +719,17 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
v_str ?: "");
}
- lease_parse_address_list(lease, ip4_config, NM_DHCP_OPTION_DHCP4_NIS_SERVERS, options, &sbuf);
+ lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_NIS_SERVERS, options, &sbuf);
- lease_parse_address_list(lease,
- ip4_config,
- NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER,
- options,
- &sbuf);
+ lease_parse_address_list(lease, l3cd, NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER, options, &sbuf);
lease_parse_private_options(lease, options);
- NM_SET_OUT(out_options, g_steal_pointer(&options));
- return g_steal_pointer(&ip4_config);
+ nm_dhcp_option_add_requests_to_options(options, AF_INET);
+
+ nm_l3_config_data_set_dhcp_lease_from_options(l3cd, AF_INET, g_steal_pointer(&options));
+
+ return g_steal_pointer(&l3cd);
}
/*****************************************************************************/
@@ -771,47 +761,44 @@ lease_save(NMDhcpNettools *self, NDhcp4ClientLease *lease, const char *lease_fil
static void
bound4_handle(NMDhcpNettools *self, NDhcp4ClientLease *lease, gboolean extended)
{
- NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
- const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
- gs_unref_object NMIP4Config *ip4_config = NULL;
- gs_unref_hashtable GHashTable *options = NULL;
- GError * error = NULL;
+ NMDhcpNettoolsPrivate * priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
+ NMDhcpClient * client = NM_DHCP_CLIENT(self);
+ const NMDhcpClientConfig *client_config;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ GError * error = NULL;
_LOGT("lease available (%s)", extended ? "extended" : "new");
-
- ip4_config = lease_to_ip4_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
- iface,
- nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
- lease,
- nm_dhcp_client_get_route_table(NM_DHCP_CLIENT(self)),
- nm_dhcp_client_get_route_metric(NM_DHCP_CLIENT(self)),
- &options,
- &error);
- if (!ip4_config) {
- _LOGW("%s", error->message);
+ client_config = nm_dhcp_client_get_config(client);
+ l3cd = lease_to_ip4_config(nm_dhcp_client_get_multi_idx(client),
+ client_config->iface,
+ nm_dhcp_client_get_ifindex(client),
+ lease,
+ &error);
+ if (!l3cd) {
+ _LOGW("failure to parse lease: %s", error->message);
g_clear_error(&error);
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
return;
}
- nm_dhcp_option_add_requests_to_options(options, AF_INET);
lease_save(self, lease, priv->lease_file);
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self),
extended ? NM_DHCP_STATE_EXTENDED : NM_DHCP_STATE_BOUND,
- NM_IP_CONFIG_CAST(ip4_config),
- options);
+ l3cd);
}
static void
dhcp4_event_handle(NMDhcpNettools *self, NDhcp4ClientEvent *event)
{
- NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
- struct in_addr server_id;
- char addr_str[INET_ADDRSTRLEN];
- int r;
+ NMDhcpNettoolsPrivate * priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
+ const NMDhcpClientConfig *client_config;
+ struct in_addr server_id;
+ char addr_str[INET_ADDRSTRLEN];
+ int r;
_LOGT("client event %d", event->event);
+ client_config = nm_dhcp_client_get_config(NM_DHCP_CLIENT(self));
switch (event->event) {
case N_DHCP4_CLIENT_EVENT_OFFER:
@@ -835,10 +822,10 @@ dhcp4_event_handle(NMDhcpNettools *self, NDhcp4ClientEvent *event)
break;
case N_DHCP4_CLIENT_EVENT_RETRACTED:
case N_DHCP4_CLIENT_EVENT_EXPIRED:
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_EXPIRE, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_EXPIRE, NULL);
break;
case N_DHCP4_CLIENT_EVENT_CANCELLED:
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
break;
case N_DHCP4_CLIENT_EVENT_GRANTED:
priv->lease = n_dhcp4_client_lease_ref(event->granted.lease);
@@ -861,7 +848,7 @@ dhcp4_event_handle(NMDhcpNettools *self, NDhcp4ClientEvent *event)
NULL,
NULL,
"dhcp4 (%s): %s",
- nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self)),
+ client_config->iface,
event->log.message);
}
} break;
@@ -890,13 +877,12 @@ dhcp4_event_cb(int fd, GIOCondition condition, gpointer user_data)
*/
_LOGE("error %d dispatching events", r);
nm_clear_g_source_inst(&priv->event_source);
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
return G_SOURCE_REMOVE;
}
- while (!n_dhcp4_client_pop_event(priv->client, &event) && event) {
+ while (!n_dhcp4_client_pop_event(priv->client, &event) && event)
dhcp4_event_handle(self, event);
- }
return G_SOURCE_CONTINUE;
}
@@ -914,23 +900,26 @@ nettools_create(NMDhcpNettools *self, GError **error)
gsize hwaddr_len;
gsize bcast_hwaddr_len;
GBytes * client_id;
- gs_unref_bytes GBytes *client_id_new = NULL;
- const uint8_t * client_id_arr;
- size_t client_id_len;
- int r, fd, arp_type, transport;
+ gs_unref_bytes GBytes * client_id_new = NULL;
+ const uint8_t * client_id_arr;
+ size_t client_id_len;
+ int r, fd, arp_type, transport;
+ const NMDhcpClientConfig *client_config;
+
+ client_config = nm_dhcp_client_get_config(NM_DHCP_CLIENT(self));
g_return_val_if_fail(!priv->client, FALSE);
/* TODO: honor nm_dhcp_client_get_anycast_address() */
- hwaddr = nm_dhcp_client_get_hw_addr(NM_DHCP_CLIENT(self));
+ hwaddr = client_config->hwaddr;
if (!hwaddr || !(hwaddr_arr = g_bytes_get_data(hwaddr, &hwaddr_len))
|| (arp_type = nm_utils_arp_type_detect_from_hwaddrlen(hwaddr_len)) < 0) {
nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "invalid MAC address");
return FALSE;
}
- bcast_hwaddr = nm_dhcp_client_get_broadcast_hw_addr(NM_DHCP_CLIENT(self));
+ bcast_hwaddr = client_config->bcast_hwaddr;
bcast_hwaddr_arr = g_bytes_get_data(bcast_hwaddr, &bcast_hwaddr_len);
switch (arp_type) {
@@ -947,7 +936,7 @@ nettools_create(NMDhcpNettools *self, GError **error)
/* Note that we always set a client-id. In particular for infiniband that is necessary,
* see https://tools.ietf.org/html/rfc4390#section-2.1 . */
- client_id = nm_dhcp_client_get_client_id(NM_DHCP_CLIENT(self));
+ client_id = client_config->client_id;
if (!client_id) {
client_id_new = nm_utils_dhcp_client_id_mac(arp_type, hwaddr_arr, hwaddr_len);
client_id = client_id_new;
@@ -971,10 +960,7 @@ nettools_create(NMDhcpNettools *self, GError **error)
n_dhcp4_client_config_set_transport(config, transport);
n_dhcp4_client_config_set_mac(config, hwaddr_arr, hwaddr_len);
n_dhcp4_client_config_set_broadcast_mac(config, bcast_hwaddr_arr, bcast_hwaddr_len);
- n_dhcp4_client_config_set_request_broadcast(
- config,
- NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)),
- NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST));
+ n_dhcp4_client_config_set_request_broadcast(config, client_config->v4.request_broadcast);
r = n_dhcp4_client_config_set_client_id(config,
client_id_arr,
NM_MIN(client_id_len, 1 + _NM_MAX_CLIENT_ID_LEN));
@@ -1033,7 +1019,7 @@ decline(NMDhcpClient *client, const char *error_message, GError **error)
g_return_val_if_fail(priv->lease, FALSE);
- _LOGT("dhcp4-client: decline");
+ _LOGT("dhcp4-client: decline (%s)", error_message);
r = n_dhcp4_client_lease_decline(priv->lease, error_message);
if (r) {
@@ -1063,19 +1049,20 @@ fqdn_flags_to_wire(NMDhcpHostnameFlags flags)
}
static gboolean
-ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
+ip4_start(NMDhcpClient *client, GError **error)
{
nm_auto(n_dhcp4_client_probe_config_freep) NDhcp4ClientProbeConfig *config = NULL;
- NMDhcpNettools * self = NM_DHCP_NETTOOLS(client);
- NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
- gs_free char * lease_file = NULL;
- struct in_addr last_addr = {0};
- const char * hostname;
- const char * mud_url;
- GBytes * vendor_class_identifier;
- int r, i;
+ NMDhcpNettools * self = NM_DHCP_NETTOOLS(client);
+ NMDhcpNettoolsPrivate * priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self);
+ const NMDhcpClientConfig *client_config;
+ gs_free char * lease_file = NULL;
+ struct in_addr last_addr = {0};
+ int r, i;
+
+ client_config = nm_dhcp_client_get_config(client);
g_return_val_if_fail(!priv->probe, FALSE);
+ g_return_val_if_fail(client_config, FALSE);
if (!nettools_create(self, error))
return FALSE;
@@ -1094,12 +1081,12 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
nm_dhcp_utils_get_leasefile_path(AF_INET,
"internal",
- nm_dhcp_client_get_iface(client),
- nm_dhcp_client_get_uuid(client),
+ client_config->iface,
+ client_config->uuid,
&lease_file);
- if (last_ip4_address)
- inet_pton(AF_INET, last_ip4_address, &last_addr);
+ if (client_config->v4.last_address)
+ inet_pton(AF_INET, client_config->v4.last_address, &last_addr);
else {
/*
* TODO: we stick to the systemd-networkd lease file format. Quite easy for now to
@@ -1129,31 +1116,33 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
}
}
- mud_url = nm_dhcp_client_get_mud_url(client);
- if (mud_url) {
+ if (client_config->mud_url) {
r = n_dhcp4_client_probe_config_append_option(config,
NM_DHCP_OPTION_DHCP4_MUD_URL,
- mud_url,
- strlen(mud_url));
+ client_config->mud_url,
+ strlen(client_config->mud_url));
if (r) {
set_error_nettools(error, r, "failed to set MUD URL");
return FALSE;
}
}
- hostname = nm_dhcp_client_get_hostname(client);
- if (hostname) {
- if (NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client), NM_DHCP_CLIENT_FLAGS_USE_FQDN)) {
+
+ if (client_config->hostname) {
+ if (client_config->use_fqdn) {
uint8_t buffer[255];
NMDhcpHostnameFlags flags;
size_t fqdn_len;
- flags = nm_dhcp_client_get_hostname_flags(client);
+ flags = client_config->hostname_flags;
buffer[0] = fqdn_flags_to_wire(flags);
buffer[1] = 0; /* RCODE1 (deprecated) */
buffer[2] = 0; /* RCODE2 (deprecated) */
if (flags & NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED) {
- r = nm_sd_dns_name_to_wire_format(hostname, buffer + 3, sizeof(buffer) - 3, FALSE);
+ r = nm_sd_dns_name_to_wire_format(client_config->hostname,
+ buffer + 3,
+ sizeof(buffer) - 3,
+ FALSE);
if (r <= 0) {
if (r < 0)
nm_utils_error_set_errno(error, r, "failed to convert DHCP FQDN: %s");
@@ -1163,12 +1152,12 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
}
fqdn_len = r;
} else {
- fqdn_len = strlen(hostname);
+ fqdn_len = strlen(client_config->hostname);
if (fqdn_len > sizeof(buffer) - 3) {
nm_utils_error_set(error, r, "failed to set DHCP FQDN: name too long");
return FALSE;
}
- memcpy(buffer + 3, hostname, fqdn_len);
+ memcpy(buffer + 3, client_config->hostname, fqdn_len);
}
r = n_dhcp4_client_probe_config_append_option(config,
@@ -1182,8 +1171,8 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
} else {
r = n_dhcp4_client_probe_config_append_option(config,
NM_DHCP_OPTION_DHCP4_HOST_NAME,
- hostname,
- strlen(hostname));
+ client_config->hostname,
+ strlen(client_config->hostname));
if (r) {
set_error_nettools(error, r, "failed to set DHCP hostname");
return FALSE;
@@ -1191,12 +1180,11 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
}
}
- vendor_class_identifier = nm_dhcp_client_get_vendor_class_identifier(client);
- if (vendor_class_identifier) {
+ if (client_config->vendor_class_identifier) {
const void *option_data;
gsize option_size;
- option_data = g_bytes_get_data(vendor_class_identifier, &option_size);
+ option_data = g_bytes_get_data(client_config->vendor_class_identifier, &option_size);
nm_assert(option_data);
nm_assert(option_size <= 255);
diff --git a/src/core/dhcp/nm-dhcp-systemd.c b/src/core/dhcp/nm-dhcp-systemd.c
index af1d2238b4..a6adc0ccdc 100644
--- a/src/core/dhcp/nm-dhcp-systemd.c
+++ b/src/core/dhcp/nm-dhcp-systemd.c
@@ -17,6 +17,7 @@
#include "libnm-std-aux/unaligned.h"
#include "nm-utils.h"
+#include "nm-l3-config-data.h"
#include "nm-dhcp-utils.h"
#include "nm-dhcp-options.h"
#include "nm-core-utils.h"
@@ -51,8 +52,6 @@ typedef struct {
char * lease_file;
guint request_count;
-
- bool privacy : 1;
} NMDhcpSystemdPrivate;
struct _NMDhcpSystemd {
@@ -70,18 +69,15 @@ G_DEFINE_TYPE(NMDhcpSystemd, nm_dhcp_systemd, NM_TYPE_DHCP_CLIENT)
/*****************************************************************************/
-static NMIP4Config *
+static NML3ConfigData *
lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
const char * iface,
int ifindex,
sd_dhcp_lease * lease,
- guint32 route_table,
- guint32 route_metric,
- GHashTable ** out_options,
GError ** error)
{
- gs_unref_object NMIP4Config *ip4_config = NULL;
- gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ gs_unref_hashtable GHashTable *options = NULL;
const struct in_addr * addr_list;
char addr_str[NM_UTILS_INET_ADDRSTRLEN];
const char * s;
@@ -92,7 +88,6 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
int i, num;
const void * data;
gsize data_len;
- gboolean metered = FALSE;
gboolean has_router_from_classless = FALSE;
gboolean has_classless_route = FALSE;
gboolean has_static_route = FALSE;
@@ -133,9 +128,9 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
return NULL;
}
- ip4_config = nm_ip4_config_new(multi_idx, ifindex);
+ l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP);
- options = out_options ? nm_dhcp_option_create_options_dict() : NULL;
+ options = nm_dhcp_option_create_options_dict();
_nm_utils_inet4_ntop(a_address.s_addr, addr_str);
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, addr_str);
@@ -160,16 +155,16 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, addr_str);
}
- nm_ip4_config_add_address(ip4_config,
- &((const NMPlatformIP4Address){
- .address = a_address.s_addr,
- .peer_address = a_address.s_addr,
- .plen = a_plen,
- .addr_source = NM_IP_CONFIG_SOURCE_DHCP,
- .timestamp = ts,
- .lifetime = a_lifetime,
- .preferred = a_lifetime,
- }));
+ nm_l3_config_data_add_address_4(l3cd,
+ &((const NMPlatformIP4Address){
+ .address = a_address.s_addr,
+ .peer_address = a_address.s_addr,
+ .plen = a_plen,
+ .addr_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .timestamp = ts,
+ .lifetime = a_lifetime,
+ .preferred = a_lifetime,
+ }));
if (sd_dhcp_lease_get_server_identifier(lease, &server_id) >= 0) {
_nm_utils_inet4_ntop(server_id.s_addr, addr_str);
@@ -193,7 +188,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
* See https://github.com/systemd/systemd/issues/4524. */
continue;
}
- nm_ip4_config_add_nameserver(ip4_config, addr_list[i].s_addr);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET, &addr_list[i].s_addr);
}
nm_dhcp_option_add_option(options,
AF_INET,
@@ -206,7 +201,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
nm_gstring_prepare(&str);
for (i = 0; i < num; i++) {
g_string_append(nm_gstring_add_space_delimiter(str), search_domains[i]);
- nm_ip4_config_add_search(ip4_config, search_domains[i]);
+ nm_l3_config_data_add_search(l3cd, AF_INET, search_domains[i]);
}
nm_dhcp_option_add_option(options,
AF_INET,
@@ -224,7 +219,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
* As systemd escapes such characters, split them at \\032. */
domains = g_strsplit(s, "\\032", 0);
for (d = domains; *d; d++)
- nm_ip4_config_add_domain(ip4_config, *d);
+ nm_l3_config_data_add_domain(l3cd, AF_INET, *d);
}
if (sd_dhcp_lease_get_hostname(lease, &s) >= 0) {
@@ -233,9 +228,9 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
num = sd_dhcp_lease_get_routes(lease, &routes);
if (num > 0) {
- nm_auto_free_gstring GString *str_classless = NULL;
- nm_auto_free_gstring GString *str_static = NULL;
- guint32 default_route_metric = route_metric;
+ nm_auto_free_gstring GString *str_classless = NULL;
+ nm_auto_free_gstring GString *str_static = NULL;
+ guint32 default_route_metric_offset = 0;
for (i = 0; i < num; i++) {
switch (sd_dhcp_route_get_option(routes[i])) {
@@ -307,25 +302,22 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
if (r_plen == 0) {
/* if there are multiple default routes, we add them with differing
* metrics. */
- m = default_route_metric;
- if (default_route_metric < G_MAXUINT32)
- default_route_metric++;
-
+ m = default_route_metric_offset++;
has_router_from_classless = TRUE;
} else
- m = route_metric;
-
- nm_ip4_config_add_route(
- ip4_config,
- &((const NMPlatformIP4Route){
- .network = network_net,
- .plen = r_plen,
- .gateway = r_gateway.s_addr,
- .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
- .metric = m,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- }),
- NULL);
+ m = 0;
+
+ nm_l3_config_data_add_route_4(l3cd,
+ &((const NMPlatformIP4Route){
+ .network = network_net,
+ .plen = r_plen,
+ .gateway = r_gateway.s_addr,
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .metric_any = TRUE,
+ .metric = m,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ }));
}
if (str_classless && str_classless->len > 0)
@@ -342,7 +334,7 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
num = sd_dhcp_lease_get_router(lease, &a_router);
if (num > 0) {
- guint32 default_route_metric = route_metric;
+ guint32 default_route_metric_offset = 0;
nm_gstring_prepare(&str);
for (i = 0; i < num; i++) {
@@ -368,26 +360,24 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
/* if there are multiple default routes, we add them with differing
* metrics. */
- m = default_route_metric;
- if (default_route_metric < G_MAXUINT32)
- default_route_metric++;
-
- nm_ip4_config_add_route(
- ip4_config,
- &((const NMPlatformIP4Route){
- .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
- .gateway = a_router[i].s_addr,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- .metric = m,
- }),
- NULL);
+ m = default_route_metric_offset++;
+
+ nm_l3_config_data_add_route_4(l3cd,
+ &((const NMPlatformIP4Route){
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .gateway = a_router[i].s_addr,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = m,
+ }));
}
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_ROUTER, str->str);
}
if (sd_dhcp_lease_get_mtu(lease, &mtu) >= 0 && mtu) {
nm_dhcp_option_add_option_u64(options, AF_INET, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, mtu);
- nm_ip4_config_set_mtu(ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP);
+ nm_l3_config_data_set_mtu(l3cd, mtu);
}
num = sd_dhcp_lease_get_ntp(lease, &addr_list);
@@ -422,9 +412,10 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
nm_dhcp_option_add_option(options, AF_INET, NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE, s);
}
- if (sd_dhcp_lease_get_vendor_specific(lease, &data, &data_len) >= 0)
- metered = !!memmem(data, data_len, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED"));
- nm_ip4_config_set_metered(ip4_config, metered);
+ if (sd_dhcp_lease_get_vendor_specific(lease, &data, &data_len) >= 0) {
+ if (!!memmem(data, data_len, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED")))
+ nm_l3_config_data_set_metered(l3cd, TRUE);
+ }
num = nm_sd_dhcp_lease_get_private_options(lease, &private_options);
if (num > 0) {
@@ -436,12 +427,18 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
if (code == NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY) {
if (nm_dhcp_lease_data_parse_cstr(l_data, l_data_len, &l_data_len)) {
- nm_dhcp_option_add_option_utf8safe_escape(
- options,
- AF_INET,
- NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY,
- l_data,
- l_data_len);
+ gs_free char *to_free = NULL;
+ const char * escaped;
+
+ escaped =
+ nm_utils_buf_utf8safe_escape((char *) l_data, l_data_len, 0, &to_free);
+ nm_dhcp_option_add_option(options,
+ AF_INET,
+ NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY,
+ escaped ?: "");
+
+ nm_l3_config_data_set_proxy_method(l3cd, NM_PROXY_CONFIG_METHOD_AUTO);
+ nm_l3_config_data_set_proxy_pac_url(l3cd, escaped ?: "");
}
continue;
}
@@ -458,8 +455,12 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
nm_dhcp_option_take_option(options, AF_INET, code, option_string);
}
}
- NM_SET_OUT(out_options, g_steal_pointer(&options));
- return g_steal_pointer(&ip4_config);
+
+ nm_dhcp_option_add_requests_to_options(options, AF_INET);
+
+ nm_l3_config_data_set_dhcp_lease_from_options(l3cd, AF_INET, g_steal_pointer(&options));
+
+ return g_steal_pointer(&l3cd);
}
/*****************************************************************************/
@@ -467,43 +468,38 @@ lease_to_ip4_config(NMDedupMultiIndex *multi_idx,
static void
bound4_handle(NMDhcpSystemd *self, gboolean extended)
{
- NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
- const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
- gs_unref_object NMIP4Config *ip4_config = NULL;
- gs_unref_hashtable GHashTable *options = NULL;
- sd_dhcp_lease * lease = NULL;
- GError * error = NULL;
+ NMDhcpSystemdPrivate * priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
+ const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ gs_unref_hashtable GHashTable *options = NULL;
+ sd_dhcp_lease * lease = NULL;
+ GError * error = NULL;
if (sd_dhcp_client_get_lease(priv->client4, &lease) < 0 || !lease) {
_LOGW("no lease!");
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
return;
}
_LOGD("lease available");
- ip4_config = lease_to_ip4_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
- iface,
- nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
- lease,
- nm_dhcp_client_get_route_table(NM_DHCP_CLIENT(self)),
- nm_dhcp_client_get_route_metric(NM_DHCP_CLIENT(self)),
- &options,
- &error);
- if (!ip4_config) {
+ l3cd = lease_to_ip4_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
+ iface,
+ nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
+ lease,
+ &error);
+ if (!l3cd) {
_LOGW("%s", error->message);
g_clear_error(&error);
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
return;
}
- nm_dhcp_option_add_requests_to_options(options, AF_INET);
dhcp_lease_save(lease, priv->lease_file);
nm_dhcp_client_set_state(NM_DHCP_CLIENT(self),
extended ? NM_DHCP_STATE_EXTENDED : NM_DHCP_STATE_BOUND,
- NM_IP_CONFIG_CAST(ip4_config),
- options);
+ l3cd);
}
static int
@@ -522,10 +518,10 @@ dhcp_event_cb(sd_dhcp_client *client, int event, gpointer user_data)
switch (event) {
case SD_DHCP_CLIENT_EVENT_EXPIRED:
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_EXPIRE, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_EXPIRE, NULL);
break;
case SD_DHCP_CLIENT_EVENT_STOP:
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_FAIL, NULL);
break;
case SD_DHCP_CLIENT_EVENT_RENEW:
case SD_DHCP_CLIENT_EVENT_IP_CHANGE:
@@ -558,11 +554,12 @@ dhcp_event_cb(sd_dhcp_client *client, int event, gpointer user_data)
}
static gboolean
-ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
+ip4_start(NMDhcpClient *client, GError **error)
{
- nm_auto(sd_dhcp_client_unrefp) sd_dhcp_client *sd_client = NULL;
- NMDhcpSystemd * self = NM_DHCP_SYSTEMD(client);
- NMDhcpSystemdPrivate * priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
+ nm_auto(sd_dhcp_client_unrefp) sd_dhcp_client *sd_client = NULL;
+ NMDhcpSystemd * self = NM_DHCP_SYSTEMD(client);
+ NMDhcpSystemdPrivate * priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
+ const NMDhcpClientConfig * client_config;
gs_free char * lease_file = NULL;
GBytes * hwaddr;
const uint8_t * hwaddr_arr;
@@ -584,6 +581,8 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
g_return_val_if_fail(!priv->client4, FALSE);
g_return_val_if_fail(!priv->client6, FALSE);
+ client_config = nm_dhcp_client_get_config(client);
+
/* TODO: honor nm_dhcp_client_get_anycast_address() */
r = sd_dhcp_client_new(&sd_client, FALSE);
@@ -600,7 +599,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
return FALSE;
}
- hwaddr = nm_dhcp_client_get_hw_addr(client);
+ hwaddr = client_config->hwaddr;
if (!hwaddr || !(hwaddr_arr = g_bytes_get_data(hwaddr, &hwaddr_len))
|| (arp_type = nm_utils_arp_type_detect_from_hwaddrlen(hwaddr_len)) < 0) {
nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "invalid MAC address");
@@ -608,7 +607,8 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
}
bcast_hwaddr_arr = NULL;
- if ((bcast_hwaddr = nm_dhcp_client_get_broadcast_hw_addr(NM_DHCP_CLIENT(self)))) {
+ bcast_hwaddr = client_config->bcast_hwaddr;
+ if (bcast_hwaddr) {
bcast_hwaddr_arr = g_bytes_get_data(bcast_hwaddr, &bcast_hwaddr_len);
if (bcast_hwaddr_len != hwaddr_len)
bcast_hwaddr_arr = NULL;
@@ -632,12 +632,12 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
nm_dhcp_utils_get_leasefile_path(AF_INET,
"internal",
- nm_dhcp_client_get_iface(client),
- nm_dhcp_client_get_uuid(client),
+ client_config->iface,
+ client_config->uuid,
&lease_file);
- if (last_ip4_address)
- inet_pton(AF_INET, last_ip4_address, &last_addr);
+ if (client_config->v4.last_address)
+ inet_pton(AF_INET, client_config->v4.last_address, &last_addr);
else {
nm_auto(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL;
@@ -646,9 +646,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
sd_dhcp_lease_get_address(lease, &last_addr);
}
- r = sd_dhcp_client_set_request_broadcast(sd_client,
- NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client),
- NM_DHCP_CLIENT_FLAGS_REQUEST_BROADCAST));
+ r = sd_dhcp_client_set_request_broadcast(sd_client, client_config->v4.request_broadcast);
nm_assert(r >= 0);
if (last_addr.s_addr) {
@@ -659,7 +657,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
}
}
- client_id = nm_dhcp_client_get_client_id(client);
+ client_id = client_config->client_id;
if (!client_id) {
client_id_new = nm_utils_dhcp_client_id_mac(arp_type, hwaddr_arr, hwaddr_len);
client_id = client_id_new;
@@ -694,7 +692,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
}
}
- hostname = nm_dhcp_client_get_hostname(client);
+ hostname = client_config->hostname;
if (hostname) {
/* FIXME: sd-dhcp decides which hostname/FQDN option to send (12 or 81)
* only based on whether the hostname has a domain part or not. At the
@@ -707,7 +705,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
}
}
- mud_url = nm_dhcp_client_get_mud_url(client);
+ mud_url = client_config->mud_url;
if (mud_url) {
r = sd_dhcp_client_set_mud_url(sd_client, mud_url);
if (r < 0) {
@@ -716,7 +714,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
}
}
- vendor_class_identifier = nm_dhcp_client_get_vendor_class_identifier(client);
+ vendor_class_identifier = client_config->vendor_class_identifier;
if (vendor_class_identifier) {
const char *option_data;
gsize len;
@@ -745,7 +743,7 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
g_free(priv->lease_file);
priv->lease_file = g_steal_pointer(&lease_file);
- nm_dhcp_client_set_client_id(client, client_id);
+ nm_dhcp_client_set_effective_client_id(client, client_id);
r = sd_dhcp_client_start(priv->client4);
if (r < 0) {
@@ -759,32 +757,32 @@ ip4_start(NMDhcpClient *client, const char *last_ip4_address, GError **error)
return TRUE;
}
-static NMIP6Config *
+static NML3ConfigData *
lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
const char * iface,
int ifindex,
sd_dhcp6_lease * lease,
gboolean info_only,
- GHashTable ** out_options,
gint32 ts,
GError ** error)
{
- gs_unref_object NMIP6Config *ip6_config = NULL;
- gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ gs_unref_hashtable GHashTable *options = NULL;
struct in6_addr tmp_addr;
const struct in6_addr * dns;
uint32_t lft_pref, lft_valid;
char addr_str[NM_UTILS_INET_ADDRSTRLEN];
char ** domains;
const char * s;
- nm_auto_free_gstring GString *str = NULL;
+ nm_auto_free_gstring GString *str = NULL;
+ gboolean has_any_addresses = FALSE;
int num, i;
nm_assert(lease);
- ip6_config = nm_ip6_config_new(multi_idx, ifindex);
+ l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP);
- options = out_options ? nm_dhcp_option_create_options_dict() : NULL;
+ options = nm_dhcp_option_create_options_dict();
sd_dhcp6_lease_reset_address_iter(lease);
nm_gstring_prepare(&str);
@@ -798,15 +796,19 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
.addr_source = NM_IP_CONFIG_SOURCE_DHCP,
};
- nm_ip6_config_add_address(ip6_config, &address);
+ nm_l3_config_data_add_address_6(l3cd, &address);
_nm_utils_inet6_ntop(&tmp_addr, addr_str);
g_string_append(nm_gstring_add_space_delimiter(str), addr_str);
- };
- if (str->len)
+
+ has_any_addresses = TRUE;
+ }
+
+ if (str->len) {
nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS, str->str);
+ }
- if (!info_only && nm_ip6_config_get_num_addresses(ip6_config) == 0) {
+ if (!info_only && !has_any_addresses) {
g_set_error_literal(error,
NM_MANAGER_ERROR,
NM_MANAGER_ERROR_FAILED,
@@ -820,7 +822,7 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
for (i = 0; i < num; i++) {
_nm_utils_inet6_ntop(&dns[i], addr_str);
g_string_append(nm_gstring_add_space_delimiter(str), addr_str);
- nm_ip6_config_add_nameserver(ip6_config, &dns[i]);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET6, &dns[i]);
}
nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_DNS_SERVERS, str->str);
}
@@ -830,7 +832,7 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
nm_gstring_prepare(&str);
for (i = 0; i < num; i++) {
g_string_append(nm_gstring_add_space_delimiter(str), domains[i]);
- nm_ip6_config_add_search(ip6_config, domains[i]);
+ nm_l3_config_data_add_search(l3cd, AF_INET6, domains[i]);
}
nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_DOMAIN_LIST, str->str);
}
@@ -839,51 +841,48 @@ lease_to_ip6_config(NMDedupMultiIndex *multi_idx,
nm_dhcp_option_add_option(options, AF_INET6, NM_DHCP_OPTION_DHCP6_FQDN, s);
}
- NM_SET_OUT(out_options, g_steal_pointer(&options));
- return g_steal_pointer(&ip6_config);
+ nm_l3_config_data_set_dhcp_lease_from_options(l3cd, AF_INET6, g_steal_pointer(&options));
+
+ return g_steal_pointer(&l3cd);
}
static void
bound6_handle(NMDhcpSystemd *self)
{
- NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
- const gint32 ts = nm_utils_get_monotonic_timestamp_sec();
- const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
- gs_unref_object NMIP6Config *ip6_config = NULL;
- gs_unref_hashtable GHashTable *options = NULL;
- gs_free_error GError *error = NULL;
- NMPlatformIP6Address prefix = {0};
- sd_dhcp6_lease * lease = NULL;
+ NMDhcpSystemdPrivate * priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
+ const gint32 ts = nm_utils_get_monotonic_timestamp_sec();
+ const char * iface = nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self));
+ const NMDhcpClientConfig *client_config;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ gs_free_error GError *error = NULL;
+ NMPlatformIP6Address prefix = {0};
+ sd_dhcp6_lease * lease = NULL;
+
+ client_config = nm_dhcp_client_get_config(NM_DHCP_CLIENT(self));
if (sd_dhcp6_client_get_lease(priv->client6, &lease) < 0 || !lease) {
_LOGW(" no lease!");
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
return;
}
_LOGD("lease available");
- ip6_config =
- lease_to_ip6_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
- iface,
- nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
- lease,
- NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(NM_DHCP_CLIENT(self)),
- NM_DHCP_CLIENT_FLAGS_INFO_ONLY),
- &options,
- ts,
- &error);
-
- if (!ip6_config) {
+ l3cd = lease_to_ip6_config(nm_dhcp_client_get_multi_idx(NM_DHCP_CLIENT(self)),
+ iface,
+ nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self)),
+ lease,
+ client_config->v6.info_only,
+ ts,
+ &error);
+
+ if (!l3cd) {
_LOGW("%s", error->message);
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL);
return;
}
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(self),
- NM_DHCP_STATE_BOUND,
- NM_IP_CONFIG_CAST(ip6_config),
- options);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_BOUND, l3cd);
sd_dhcp6_lease_reset_pd_prefix_iter(lease);
while (!sd_dhcp6_lease_get_pd(lease,
@@ -908,11 +907,11 @@ dhcp6_event_cb(sd_dhcp6_client *client, int event, gpointer user_data)
switch (event) {
case SD_DHCP6_CLIENT_EVENT_RETRANS_MAX:
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_TIMEOUT, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_TIMEOUT, NULL);
break;
case SD_DHCP6_CLIENT_EVENT_RESEND_EXPIRE:
case SD_DHCP6_CLIENT_EVENT_STOP:
- nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_FAIL, NULL, NULL);
+ nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_FAIL, NULL);
break;
case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE:
case SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST:
@@ -925,15 +924,12 @@ dhcp6_event_cb(sd_dhcp6_client *client, int event, gpointer user_data)
}
static gboolean
-ip6_start(NMDhcpClient * client,
- const struct in6_addr * ll_addr,
- NMSettingIP6ConfigPrivacy privacy,
- guint needed_prefixes,
- GError ** error)
+ip6_start(NMDhcpClient *client, GError **error)
{
NMDhcpSystemd * self = NM_DHCP_SYSTEMD(client);
NMDhcpSystemdPrivate * priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self);
nm_auto(sd_dhcp6_client_unrefp) sd_dhcp6_client *sd_client = NULL;
+ const NMDhcpClientConfig * client_config;
const char * hostname;
const char * mud_url;
int r, i;
@@ -944,10 +940,12 @@ ip6_start(NMDhcpClient * client,
g_return_val_if_fail(!priv->client4, FALSE);
g_return_val_if_fail(!priv->client6, FALSE);
+ client_config = nm_dhcp_client_get_config(client);
+
/* TODO: honor nm_dhcp_client_get_anycast_address() */
- if (!(duid = nm_dhcp_client_get_client_id(client))
- || !(duid_arr = g_bytes_get_data(duid, &duid_len)) || duid_len < 2) {
+ duid = nm_dhcp_client_get_effective_client_id(client);
+ if (!duid || !(duid_arr = g_bytes_get_data(duid, &duid_len)) || duid_len < 2) {
nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "missing DUID");
g_return_val_if_reached(FALSE);
}
@@ -960,13 +958,13 @@ ip6_start(NMDhcpClient * client,
_LOGT("dhcp-client6: set %p", sd_client);
- if (NM_FLAGS_HAS(nm_dhcp_client_get_client_flags(client), NM_DHCP_CLIENT_FLAGS_INFO_ONLY)) {
+ if (client_config->v6.info_only) {
sd_dhcp6_client_set_address_request(sd_client, 0);
- if (needed_prefixes == 0)
+ if (client_config->v6.needed_prefixes == 0)
sd_dhcp6_client_set_information_request(sd_client, 1);
}
- r = sd_dhcp6_client_set_iaid(sd_client, nm_dhcp_client_get_iaid(client));
+ r = sd_dhcp6_client_set_iaid(sd_client, client_config->v6.iaid);
if (r < 0) {
nm_utils_error_set_errno(error, r, "failed to set IAID: %s");
return FALSE;
@@ -1002,7 +1000,7 @@ ip6_start(NMDhcpClient * client,
}
}
- mud_url = nm_dhcp_client_get_mud_url(client);
+ mud_url = client_config->mud_url;
if (mud_url) {
r = sd_dhcp6_client_set_request_mud_url(sd_client, mud_url);
if (r < 0) {
@@ -1011,8 +1009,8 @@ ip6_start(NMDhcpClient * client,
}
}
- if (needed_prefixes > 0) {
- if (needed_prefixes > 1)
+ if (client_config->v6.needed_prefixes > 0) {
+ if (client_config->v6.needed_prefixes > 1)
_LOGW("dhcp-client6: only one prefix request is supported");
/* FIXME: systemd-networkd API only allows to request a
* single prefix */
@@ -1023,13 +1021,13 @@ ip6_start(NMDhcpClient * client,
}
}
- r = sd_dhcp6_client_set_local_address(sd_client, ll_addr);
+ r = sd_dhcp6_client_set_local_address(sd_client, client_config->v6.ll_addr);
if (r < 0) {
nm_utils_error_set_errno(error, r, "failed to set local address: %s");
return FALSE;
}
- hostname = nm_dhcp_client_get_hostname(client);
+ hostname = client_config->hostname;
r = sd_dhcp6_client_set_fqdn(sd_client, hostname);
if (r < 0) {
nm_utils_error_set_errno(error, r, "failed to set DHCP hostname: %s");
diff --git a/src/core/dhcp/nm-dhcp-utils.c b/src/core/dhcp/nm-dhcp-utils.c
index 3cc6987ada..b1ff1b97a9 100644
--- a/src/core/dhcp/nm-dhcp-utils.c
+++ b/src/core/dhcp/nm-dhcp-utils.c
@@ -14,6 +14,7 @@
#include "libnm-systemd-shared/nm-sd-utils-shared.h"
#include "nm-dhcp-utils.h"
+#include "nm-l3-config-data.h"
#include "nm-utils.h"
#include "nm-config.h"
#include "NetworkManagerUtils.h"
@@ -24,12 +25,10 @@
/*****************************************************************************/
static gboolean
-ip4_process_dhcpcd_rfc3442_routes(const char * iface,
- const char * str,
- guint32 route_table,
- guint32 route_metric,
- NMIP4Config *ip4_config,
- guint32 * gwaddr)
+ip4_process_dhcpcd_rfc3442_routes(const char * iface,
+ const char * str,
+ NML3ConfigData *l3cd,
+ guint32 * gwaddr)
{
gs_free const char **routes = NULL;
const char ** r;
@@ -45,10 +44,9 @@ ip4_process_dhcpcd_rfc3442_routes(const char * iface,
}
for (r = routes; *r; r += 2) {
- char * slash;
- NMPlatformIP4Route route;
- int rt_cidr = 32;
- guint32 rt_addr, rt_route;
+ char * slash;
+ int rt_cidr = 32;
+ guint32 rt_addr, rt_route;
slash = strchr(*r, '/');
if (slash) {
@@ -89,14 +87,18 @@ ip4_process_dhcpcd_rfc3442_routes(const char * iface,
*r,
rt_cidr,
*(r + 1));
- memset(&route, 0, sizeof(route));
- route.network = nm_utils_ip4_address_clear_host_address(rt_addr, rt_cidr);
- route.plen = rt_cidr;
- route.gateway = rt_route;
- route.rt_source = NM_IP_CONFIG_SOURCE_DHCP;
- route.metric = route_metric;
- route.table_coerced = nm_platform_route_table_coerce(route_table);
- nm_ip4_config_add_route(ip4_config, &route, NULL);
+
+ nm_l3_config_data_add_route_4(
+ l3cd,
+ &((const NMPlatformIP4Route){
+ .network = nm_utils_ip4_address_clear_host_address(rt_addr, rt_cidr),
+ .plen = rt_cidr,
+ .gateway = rt_route,
+ .rt_source = NM_IP_CONFIG_SOURCE_DHCP,
+ .metric_any = TRUE,
+ .table_any = TRUE,
+
+ }));
}
}
@@ -153,12 +155,10 @@ process_dhclient_rfc3442_route(const char *const **p_octets, NMPlatformIP4Route
}
static gboolean
-ip4_process_dhclient_rfc3442_routes(const char * iface,
- const char * str,
- guint32 route_table,
- guint32 route_metric,
- NMIP4Config *ip4_config,
- guint32 * gwaddr)
+ip4_process_dhclient_rfc3442_routes(const char * iface,
+ const char * str,
+ NML3ConfigData *l3cd,
+ guint32 * gwaddr)
{
gs_free const char **octets = NULL;
const char *const * o;
@@ -189,9 +189,12 @@ ip4_process_dhclient_rfc3442_routes(const char * iface,
/* normal route */
route.rt_source = NM_IP_CONFIG_SOURCE_DHCP;
- route.metric = route_metric;
- route.table_coerced = nm_platform_route_table_coerce(route_table);
- nm_ip4_config_add_route(ip4_config, &route, NULL);
+ route.table_any = TRUE;
+ route.table_coerced = 0;
+ route.metric_any = TRUE;
+ route.metric = 0;
+
+ nm_l3_config_data_add_route_4(l3cd, &route);
_LOG2I(LOGD_DHCP4,
iface,
@@ -206,17 +209,15 @@ ip4_process_dhclient_rfc3442_routes(const char * iface,
}
static gboolean
-ip4_process_classless_routes(const char * iface,
- GHashTable * options,
- guint32 route_table,
- guint32 route_metric,
- NMIP4Config *ip4_config,
- guint32 * gwaddr)
+ip4_process_classless_routes(const char * iface,
+ GHashTable * options,
+ NML3ConfigData *l3cd,
+ guint32 * gwaddr)
{
const char *str, *p;
g_return_val_if_fail(options != NULL, FALSE);
- g_return_val_if_fail(ip4_config != NULL, FALSE);
+ g_return_val_if_fail(l3cd != NULL, FALSE);
*gwaddr = 0;
@@ -265,28 +266,14 @@ ip4_process_classless_routes(const char * iface,
if (strchr(str, '/')) {
/* dhcpcd format */
- return ip4_process_dhcpcd_rfc3442_routes(iface,
- str,
- route_table,
- route_metric,
- ip4_config,
- gwaddr);
+ return ip4_process_dhcpcd_rfc3442_routes(iface, str, l3cd, gwaddr);
}
- return ip4_process_dhclient_rfc3442_routes(iface,
- str,
- route_table,
- route_metric,
- ip4_config,
- gwaddr);
+ return ip4_process_dhclient_rfc3442_routes(iface, str, l3cd, gwaddr);
}
static void
-process_classful_routes(const char * iface,
- GHashTable * options,
- guint32 route_table,
- guint32 route_metric,
- NMIP4Config *ip4_config)
+process_classful_routes(const char *iface, GHashTable *options, NML3ConfigData *l3cd)
{
gs_free const char **searches = NULL;
const char ** s;
@@ -320,8 +307,10 @@ process_classful_routes(const char * iface,
// FIXME: ensure the IP address and route are sane
- memset(&route, 0, sizeof(route));
- route.network = rt_addr;
+ route = (NMPlatformIP4Route){
+ .network = rt_addr,
+ };
+
/* RFC 2132, updated by RFC 3442:
* The Static Routes option (option 33) does not provide a subnet mask
* for each route - it is assumed that the subnet mask is implicit in
@@ -333,12 +322,15 @@ process_classful_routes(const char * iface,
}
route.gateway = rt_route;
route.rt_source = NM_IP_CONFIG_SOURCE_DHCP;
- route.metric = route_metric;
- route.table_coerced = nm_platform_route_table_coerce(route_table);
+ route.table_any = TRUE;
+ route.table_coerced = 0;
+ route.metric_any = TRUE;
+ route.metric = 0;
route.network = nm_utils_ip4_address_clear_host_address(route.network, route.plen);
- nm_ip4_config_add_route(ip4_config, &route, NULL);
+ nm_l3_config_data_add_route_4(l3cd, &route);
+
_LOG2I(LOGD_DHCP,
iface,
" static route %s",
@@ -347,7 +339,7 @@ process_classful_routes(const char * iface,
}
static void
-process_domain_search(const char *iface, const char *str, GFunc add_func, gpointer user_data)
+process_domain_search(int addr_family, const char *iface, const char *str, NML3ConfigData *l3cd)
{
gs_free const char **searches = NULL;
gs_free char * unescaped = NULL;
@@ -356,7 +348,7 @@ process_domain_search(const char *iface, const char *str, GFunc add_func, gpoint
int i;
g_return_if_fail(str != NULL);
- g_return_if_fail(add_func != NULL);
+ nm_assert(l3cd);
unescaped = g_strdup(str);
@@ -379,46 +371,43 @@ process_domain_search(const char *iface, const char *str, GFunc add_func, gpoint
searches = nm_strsplit_set(unescaped, " ");
for (s = searches; searches && *s; s++) {
_LOG2I(LOGD_DHCP, iface, " domain search '%s'", *s);
- add_func((gpointer) *s, user_data);
+ nm_l3_config_data_add_search(l3cd, addr_family, *s);
}
}
-static void
-ip4_add_domain_search(gpointer data, gpointer user_data)
-{
- nm_ip4_config_add_search(NM_IP4_CONFIG(user_data), (const char *) data);
-}
-
-NMIP4Config *
+NML3ConfigData *
nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
int ifindex,
const char * iface,
- GHashTable * options,
- guint32 route_table,
- guint32 route_metric)
+ GHashTable * options)
{
- gs_unref_object NMIP4Config *ip4_config = NULL;
- guint32 tmp_addr;
- in_addr_t addr;
- NMPlatformIP4Address address;
- char * str = NULL;
- gboolean gateway_has = FALSE;
- guint32 gateway = 0;
- guint8 plen = 0;
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ guint32 tmp_addr;
+ in_addr_t addr;
+ NMPlatformIP4Address address;
+ char * str = NULL;
+ gboolean gateway_has = FALSE;
+ guint32 gateway = 0;
+ guint8 plen = 0;
+ char sbuf[NM_UTILS_INET_ADDRSTRLEN];
+ guint32 now;
g_return_val_if_fail(options != NULL, NULL);
- ip4_config = nm_ip4_config_new(multi_idx, ifindex);
- memset(&address, 0, sizeof(address));
- address.timestamp = nm_utils_get_monotonic_timestamp_sec();
+ l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP);
+
+ now = nm_utils_get_monotonic_timestamp_sec();
+
+ address = (NMPlatformIP4Address){
+ .timestamp = now,
+ };
str = g_hash_table_lookup(options, "ip_address");
- if (str && (inet_pton(AF_INET, str, &addr) > 0))
- _LOG2I(LOGD_DHCP4, iface, " address %s", str);
- else
+ if (!str || !nm_utils_parse_inaddr_bin(AF_INET, str, NULL, &addr))
return NULL;
+ _LOG2I(LOGD_DHCP4, iface, " address %s", str);
+
str = g_hash_table_lookup(options, "subnet_mask");
if (str && (inet_pton(AF_INET, str, &tmp_addr) > 0)) {
plen = nm_utils_ip4_netmask_to_prefix(tmp_addr);
@@ -433,13 +422,8 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
/* Routes: if the server returns classless static routes, we MUST ignore
* the 'static_routes' option.
*/
- if (!ip4_process_classless_routes(iface,
- options,
- route_table,
- route_metric,
- ip4_config,
- &gateway))
- process_classful_routes(iface, options, route_table, route_metric, ip4_config);
+ if (!ip4_process_classless_routes(iface, options, l3cd, &gateway))
+ process_classful_routes(iface, options, l3cd);
if (gateway) {
_LOG2I(LOGD_DHCP4, iface, " gateway %s", _nm_utils_inet4_ntop(gateway, sbuf));
@@ -453,7 +437,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
gs_free const char **routers = nm_strsplit_set(str, " ");
const char ** s;
- for (s = routers; routers && *s; s++) {
+ for (s = routers; *s; s++) {
/* FIXME: how to handle multiple routers? */
if (inet_pton(AF_INET, *s, &gateway) > 0) {
_LOG2I(LOGD_DHCP4, iface, " gateway %s", *s);
@@ -469,11 +453,13 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
const NMPlatformIP4Route r = {
.rt_source = NM_IP_CONFIG_SOURCE_DHCP,
.gateway = gateway,
- .table_coerced = nm_platform_route_table_coerce(route_table),
- .metric = route_metric,
+ .table_any = TRUE,
+ .table_coerced = 0,
+ .metric_any = TRUE,
+ .metric = 0,
};
- nm_ip4_config_add_route(ip4_config, &r, NULL);
+ nm_l3_config_data_add_route_4(l3cd, &r);
}
str = g_hash_table_lookup(options, "dhcp_lease_time");
@@ -483,7 +469,8 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
}
address.addr_source = NM_IP_CONFIG_SOURCE_DHCP;
- nm_ip4_config_add_address(ip4_config, &address);
+
+ nm_l3_config_data_add_address_4(l3cd, &address);
str = g_hash_table_lookup(options, "host_name");
if (str)
@@ -497,7 +484,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
for (s = dns; dns && *s; s++) {
if (inet_pton(AF_INET, *s, &tmp_addr) > 0) {
if (tmp_addr) {
- nm_ip4_config_add_nameserver(ip4_config, tmp_addr);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET, &tmp_addr);
_LOG2I(LOGD_DHCP4, iface, " nameserver '%s'", *s);
}
} else
@@ -512,13 +499,13 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
for (s = domains; domains && *s; s++) {
_LOG2I(LOGD_DHCP4, iface, " domain name '%s'", *s);
- nm_ip4_config_add_domain(ip4_config, *s);
+ nm_l3_config_data_add_domain(l3cd, AF_INET, *s);
}
}
str = g_hash_table_lookup(options, "domain_search");
if (str)
- process_domain_search(iface, str, ip4_add_domain_search, ip4_config);
+ process_domain_search(AF_INET, iface, str, l3cd);
str = g_hash_table_lookup(options, "netbios_name_servers");
if (str) {
@@ -528,7 +515,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
for (s = nbns; nbns && *s; s++) {
if (inet_pton(AF_INET, *s, &tmp_addr) > 0) {
if (tmp_addr) {
- nm_ip4_config_add_wins(ip4_config, tmp_addr);
+ nm_l3_config_data_add_wins(l3cd, tmp_addr);
_LOG2I(LOGD_DHCP4, iface, " wins '%s'", *s);
}
} else
@@ -546,13 +533,13 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
return NULL;
if (int_mtu > 576)
- nm_ip4_config_set_mtu(ip4_config, int_mtu, NM_IP_CONFIG_SOURCE_DHCP);
+ nm_l3_config_data_set_mtu(l3cd, int_mtu);
}
str = g_hash_table_lookup(options, "nis_domain");
if (str) {
_LOG2I(LOGD_DHCP4, iface, " NIS domain '%s'", str);
- nm_ip4_config_set_nis_domain(ip4_config, str);
+ nm_l3_config_data_add_domain(l3cd, AF_INET, str);
}
str = g_hash_table_lookup(options, "nis_servers");
@@ -563,7 +550,7 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
for (s = nis; nis && *s; s++) {
if (inet_pton(AF_INET, *s, &tmp_addr) > 0) {
if (tmp_addr) {
- nm_ip4_config_add_nis_server(ip4_config, tmp_addr);
+ nm_l3_config_data_add_nis_server(l3cd, tmp_addr);
_LOG2I(LOGD_DHCP4, iface, " nis '%s'", *s);
}
} else
@@ -572,19 +559,20 @@ nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx,
}
str = g_hash_table_lookup(options, "vendor_encapsulated_options");
- nm_ip4_config_set_metered(ip4_config, str && strstr(str, "ANDROID_METERED"));
+ if (str && strstr(str, "ANDROID_METERED"))
+ nm_l3_config_data_set_metered(l3cd, TRUE);
- return g_steal_pointer(&ip4_config);
+ str = g_hash_table_lookup(options, "wpad");
+ if (str) {
+ nm_l3_config_data_set_proxy_method(l3cd, NM_PROXY_CONFIG_METHOD_AUTO);
+ nm_l3_config_data_set_proxy_pac_url(l3cd, str);
+ }
+
+ return g_steal_pointer(&l3cd);
}
/*****************************************************************************/
-static void
-ip6_add_domain_search(gpointer data, gpointer user_data)
-{
- nm_ip6_config_add_search(NM_IP6_CONFIG(user_data), (const char *) data);
-}
-
NMPlatformIP6Address
nm_dhcp_utils_ip6_prefix_from_options(GHashTable *options)
{
@@ -635,25 +623,29 @@ nm_dhcp_utils_ip6_prefix_from_options(GHashTable *options)
return address;
}
-NMIP6Config *
+NML3ConfigData *
nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx,
int ifindex,
const char * iface,
GHashTable * options,
gboolean info_only)
{
- gs_unref_object NMIP6Config *ip6_config = NULL;
- struct in6_addr tmp_addr;
- NMPlatformIP6Address address;
- char * str = NULL;
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd = NULL;
+ struct in6_addr tmp_addr;
+ NMPlatformIP6Address address;
+ char * str = NULL;
+ guint32 now;
g_return_val_if_fail(options != NULL, NULL);
- memset(&address, 0, sizeof(address));
- address.plen = 128;
- address.timestamp = nm_utils_get_monotonic_timestamp_sec();
+ now = nm_utils_get_monotonic_timestamp_sec();
- ip6_config = nm_ip6_config_new(multi_idx, ifindex);
+ address = (NMPlatformIP6Address){
+ .plen = 128,
+ .timestamp = now,
+ };
+
+ l3cd = nm_l3_config_data_new(multi_idx, ifindex, NM_IP_CONFIG_SOURCE_DHCP);
str = g_hash_table_lookup(options, "max_life");
if (str) {
@@ -676,7 +668,7 @@ nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx,
address.address = tmp_addr;
address.addr_source = NM_IP_CONFIG_SOURCE_DHCP;
- nm_ip6_config_add_address(ip6_config, &address);
+ nm_l3_config_data_add_address_6(l3cd, &address);
_LOG2I(LOGD_DHCP6, iface, " address %s", str);
} else if (info_only == FALSE) {
/* No address in Managed mode is a hard error */
@@ -695,7 +687,7 @@ nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx,
for (s = dns; dns && *s; s++) {
if (inet_pton(AF_INET6, *s, &tmp_addr) > 0) {
if (!IN6_IS_ADDR_UNSPECIFIED(&tmp_addr)) {
- nm_ip6_config_add_nameserver(ip6_config, &tmp_addr);
+ nm_l3_config_data_add_nameserver(l3cd, AF_INET6, &tmp_addr);
_LOG2I(LOGD_DHCP6, iface, " nameserver '%s'", *s);
}
} else
@@ -705,9 +697,9 @@ nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx,
str = g_hash_table_lookup(options, "dhcp6_domain_search");
if (str)
- process_domain_search(iface, str, ip6_add_domain_search, ip6_config);
+ process_domain_search(AF_INET6, iface, str, l3cd);
- return g_steal_pointer(&ip6_config);
+ return g_steal_pointer(&l3cd);
}
char *
@@ -838,6 +830,65 @@ nm_dhcp_utils_get_dhcp6_event_id(GHashTable *lease)
return g_strdup_printf("%s|%s", iaid, start);
}
+gboolean
+nm_dhcp_utils_merge_new_dhcp6_lease(const NML3ConfigData * l3cd_old,
+ const NML3ConfigData * l3cd_new,
+ const NML3ConfigData **out_l3cd_merged)
+{
+ nm_auto_unref_l3cd_init NML3ConfigData *l3cd_merged = NULL;
+ const NMPlatformIP6Address * addr;
+ NMDhcpLease * lease_old;
+ NMDhcpLease * lease_new;
+ NMDedupMultiIter iter;
+ const char * start;
+ const char * iaid;
+
+ nm_assert(out_l3cd_merged);
+ nm_assert(!*out_l3cd_merged);
+
+ if (!l3cd_old)
+ return FALSE;
+ if (!l3cd_new)
+ return FALSE;
+
+ lease_new = nm_l3_config_data_get_dhcp_lease(l3cd_new, AF_INET6);
+ if (!lease_new)
+ return FALSE;
+
+ lease_old = nm_l3_config_data_get_dhcp_lease(l3cd_old, AF_INET6);
+ if (!lease_old)
+ return FALSE;
+
+ start = nm_dhcp_lease_lookup_option(lease_new, "life_starts");
+ if (!start)
+ return FALSE;
+ iaid = nm_dhcp_lease_lookup_option(lease_new, "iaid");
+ if (!iaid)
+ return FALSE;
+
+ if (!nm_streq0(start, nm_dhcp_lease_lookup_option(lease_old, "life_starts")))
+ return FALSE;
+ if (!nm_streq0(iaid, nm_dhcp_lease_lookup_option(lease_old, "iaid")))
+ return FALSE;
+
+ /* If the server sends multiple IPv6 addresses, we receive a state
+ * changed event for each of them. Use the event ID to merge IPv6
+ * addresses from the same transaction into a single configuration.
+ **/
+
+ l3cd_merged = nm_l3_config_data_new_clone(l3cd_old, -1);
+
+ nm_l3_config_data_iter_ip6_address_for_each (&iter, l3cd_new, &addr)
+ nm_l3_config_data_add_address_6(l3cd_merged, addr);
+
+ /* FIXME(l3cfg): Note that we keep the original NMDhcpLease. All we take from the new lease are the
+ * addresses. Maybe this is not right and we should merge the leases too?? */
+ nm_l3_config_data_set_dhcp_lease(l3cd_merged, AF_INET6, lease_old);
+
+ *out_l3cd_merged = nm_l3_config_data_ref_and_seal(g_steal_pointer(&l3cd_merged));
+ return TRUE;
+}
+
/*****************************************************************************/
gboolean
diff --git a/src/core/dhcp/nm-dhcp-utils.h b/src/core/dhcp/nm-dhcp-utils.h
index 69715f90fe..bee10de3f6 100644
--- a/src/core/dhcp/nm-dhcp-utils.h
+++ b/src/core/dhcp/nm-dhcp-utils.h
@@ -8,21 +8,18 @@
#include <stdlib.h>
-#include "nm-ip4-config.h"
-#include "nm-ip6-config.h"
-
-NMIP4Config *nm_dhcp_utils_ip4_config_from_options(struct _NMDedupMultiIndex *multi_idx,
- int ifindex,
- const char * iface,
- GHashTable * options,
- guint32 route_table,
- guint32 route_metric);
-
-NMIP6Config *nm_dhcp_utils_ip6_config_from_options(struct _NMDedupMultiIndex *multi_idx,
- int ifindex,
- const char * iface,
- GHashTable * options,
- gboolean info_only);
+#include "nm-l3-config-data.h"
+
+NML3ConfigData *nm_dhcp_utils_ip4_config_from_options(struct _NMDedupMultiIndex *multi_idx,
+ int ifindex,
+ const char * iface,
+ GHashTable * options);
+
+NML3ConfigData *nm_dhcp_utils_ip6_config_from_options(struct _NMDedupMultiIndex *multi_idx,
+ int ifindex,
+ const char * iface,
+ GHashTable * options,
+ gboolean info_only);
NMPlatformIP6Address nm_dhcp_utils_ip6_prefix_from_options(GHashTable *options);
@@ -38,6 +35,10 @@ gboolean nm_dhcp_utils_get_leasefile_path(int addr_family,
char *nm_dhcp_utils_get_dhcp6_event_id(GHashTable *lease);
+gboolean nm_dhcp_utils_merge_new_dhcp6_lease(const NML3ConfigData * l3cd_old,
+ const NML3ConfigData * l3cd_new,
+ const NML3ConfigData **out_l3cd_merged);
+
/*****************************************************************************/
static inline gboolean
diff --git a/src/core/dhcp/tests/test-dhcp-dhclient.c b/src/core/dhcp/tests/test-dhcp-dhclient.c
index e9a6209644..803933ff04 100644
--- a/src/core/dhcp/tests/test-dhcp-dhclient.c
+++ b/src/core/dhcp/tests/test-dhcp-dhclient.c
@@ -15,7 +15,6 @@
#include "dhcp/nm-dhcp-dhclient-utils.h"
#include "dhcp/nm-dhcp-utils.h"
#include "nm-utils.h"
-#include "nm-ip4-config.h"
#include "libnm-platform/nm-platform.h"
#include "nm-test-utils-core.h"
diff --git a/src/core/dhcp/tests/test-dhcp-utils.c b/src/core/dhcp/tests/test-dhcp-utils.c
index 4d47e7e283..0fab5c15ad 100644
--- a/src/core/dhcp/tests/test-dhcp-utils.c
+++ b/src/core/dhcp/tests/test-dhcp-utils.c
@@ -20,20 +20,18 @@
/*****************************************************************************/
-static NMIP4Config *
-_ip4_config_from_options(int ifindex, const char *iface, GHashTable *options, guint32 route_metric)
+static const NML3ConfigData *
+_ip4_config_from_options(int ifindex, const char *iface, GHashTable *options)
{
nm_auto_unref_dedup_multi_index NMDedupMultiIndex *multi_idx = nm_dedup_multi_index_new();
- NMIP4Config * config;
-
- config = nm_dhcp_utils_ip4_config_from_options(multi_idx,
- ifindex,
- iface,
- options,
- RT_TABLE_MAIN,
- route_metric);
- g_assert(config);
- return config;
+ NML3ConfigData * l3cd;
+
+ l3cd = nm_dhcp_utils_ip4_config_from_options(multi_idx, ifindex, iface, options);
+ g_assert(NM_IS_L3_CONFIG_DATA(l3cd));
+ g_assert(!nm_l3_config_data_is_sealed(l3cd));
+ if (nmtst_get_rand_bool())
+ nm_l3_config_data_seal(l3cd);
+ return l3cd;
}
typedef struct {
@@ -74,58 +72,57 @@ static const Option generic_options[] = {
static void
test_generic_options(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const NMPlatformIP4Address * address;
- const NMPlatformIP4Route * route;
- guint32 tmp;
- const char * expected_addr = "192.168.1.106";
- const char * expected_gw = "192.168.1.1";
- const char * expected_dns1 = "216.254.95.2";
- const char * expected_dns2 = "216.231.41.2";
- const char * expected_search1 = "foobar.com";
- const char * expected_search2 = "blah.foobar.com";
- const char * expected_route1_dest = "10.1.1.5";
- const char * expected_route1_gw = "10.1.1.1";
- const char * expected_route2_dest = "100.99.88.56";
- const char * expected_route2_gw = "10.1.1.1";
-
- options = fill_table(generic_options, NULL);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
-
- /* IP4 address */
- g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1);
- address = _nmtst_ip4_config_get_address(ip4_config, 0);
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const NMPlatformIP4Address * address;
+ const NMPlatformIP4Route * route;
+ guint32 tmp;
+ const char * expected_addr = "192.168.1.106";
+ const char * expected_gw = "192.168.1.1";
+ const char * expected_dns1 = "216.254.95.2";
+ const char * expected_dns2 = "216.231.41.2";
+ const char * expected_search1 = "foobar.com";
+ const char * expected_search2 = "blah.foobar.com";
+ const char * expected_route1_dest = "10.1.1.5";
+ const char * expected_route1_gw = "10.1.1.1";
+ const char * expected_route2_dest = "100.99.88.56";
+ const char * expected_route2_gw = "10.1.1.1";
+ const char *const * strarr;
+ const in_addr_t * ia_arr;
+ guint u;
+
+ options = fill_table(generic_options, NULL);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
+
+ g_assert_cmpint(nm_l3_config_data_get_num_addresses(l3cd, AF_INET), ==, 1);
+ address = nmtst_l3_config_data_get_address_at_4(l3cd, 0);
g_assert(inet_pton(AF_INET, expected_addr, &tmp) > 0);
g_assert(address->address == tmp);
g_assert(address->peer_address == tmp);
g_assert_cmpint(address->plen, ==, 24);
- /* Gateway */
- g_assert(inet_pton(AF_INET, expected_gw, &tmp) > 0);
- g_assert(nmtst_ip4_config_get_gateway(ip4_config) == tmp);
+ nmtst_assert_ip_address(AF_INET,
+ nmtst_l3_config_data_get_best_gateway(l3cd, AF_INET),
+ expected_gw);
- g_assert_cmpint(nm_ip4_config_get_num_wins(ip4_config), ==, 0);
+ g_assert(!nm_l3_config_data_get_wins(l3cd, &u));
+ g_assert_cmpint(u, ==, 0);
- g_assert_cmpint(nm_ip4_config_get_mtu(ip4_config), ==, 987);
+ g_assert_cmpint(nm_l3_config_data_get_mtu(l3cd), ==, 987);
- /* Domain searches */
- g_assert_cmpint(nm_ip4_config_get_num_searches(ip4_config), ==, 2);
- g_assert_cmpstr(nm_ip4_config_get_search(ip4_config, 0), ==, expected_search1);
- g_assert_cmpstr(nm_ip4_config_get_search(ip4_config, 1), ==, expected_search2);
+ strarr = nm_l3_config_data_get_searches(l3cd, AF_INET, &u);
+ g_assert_cmpint(u, ==, 2);
+ g_assert_cmpstr(strarr[0], ==, expected_search1);
+ g_assert_cmpstr(strarr[1], ==, expected_search2);
- /* DNS servers */
- g_assert_cmpint(nm_ip4_config_get_num_nameservers(ip4_config), ==, 2);
- g_assert(inet_pton(AF_INET, expected_dns1, &tmp) > 0);
- g_assert(nm_ip4_config_get_nameserver(ip4_config, 0) == tmp);
- g_assert(inet_pton(AF_INET, expected_dns2, &tmp) > 0);
- g_assert(nm_ip4_config_get_nameserver(ip4_config, 1) == tmp);
+ ia_arr = nm_l3_config_data_get_nameservers(l3cd, AF_INET, &u);
+ g_assert_cmpint(u, ==, 2);
+ nmtst_assert_ip4_address(ia_arr[0], expected_dns1);
+ nmtst_assert_ip4_address(ia_arr[1], expected_dns2);
- /* Routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
- /* Route #1 */
- route = _nmtst_ip4_config_get_route(ip4_config, 0);
+ route = nmtst_l3_config_data_get_route_at_4(l3cd, 0);
g_assert(inet_pton(AF_INET, expected_route1_dest, &tmp) > 0);
g_assert(route->network == tmp);
g_assert(inet_pton(AF_INET, expected_route1_gw, &tmp) > 0);
@@ -133,69 +130,63 @@ test_generic_options(void)
g_assert_cmpint(route->plen, ==, 32);
g_assert_cmpint(route->metric, ==, 0);
- /* Route #2 */
- route = _nmtst_ip4_config_get_route(ip4_config, 1);
+ route = nmtst_l3_config_data_get_route_at_4(l3cd, 1);
g_assert(route->network == nmtst_inet4_from_string(expected_route2_dest));
g_assert(route->gateway == nmtst_inet4_from_string(expected_route2_gw));
g_assert_cmpint(route->plen, ==, 32);
g_assert_cmpint(route->metric, ==, 0);
- route = _nmtst_ip4_config_get_route(ip4_config, 2);
+ route = nmtst_l3_config_data_get_route_at_4(l3cd, 2);
g_assert(route->network == nmtst_inet4_from_string("0.0.0.0"));
g_assert(route->gateway == nmtst_inet4_from_string("192.168.1.1"));
g_assert_cmpint(route->plen, ==, 0);
g_assert_cmpint(route->metric, ==, 0);
-
- g_hash_table_destroy(options);
}
static void
test_wins_options(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const NMPlatformIP4Address * address;
- guint32 tmp;
- const char * expected_wins1 = "63.12.199.5";
- const char * expected_wins2 = "150.4.88.120";
- static const Option data[] = {{"netbios_name_servers", "63.12.199.5 150.4.88.120"},
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const NMPlatformIP4Address * address;
+ const char * expected_wins1 = "63.12.199.5";
+ const char * expected_wins2 = "150.4.88.120";
+ static const Option data[] = {{"netbios_name_servers", "63.12.199.5 150.4.88.120"},
{NULL, NULL}};
+ const in_addr_t * ia_arr;
+ guint u;
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
- /* IP4 address */
- g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1);
- address = _nmtst_ip4_config_get_address(ip4_config, 0);
+ g_assert_cmpint(nm_l3_config_data_get_num_addresses(l3cd, AF_INET), ==, 1);
+ address = nmtst_l3_config_data_get_address_at_4(l3cd, 0);
g_assert(address);
- g_assert_cmpint(nm_ip4_config_get_num_wins(ip4_config), ==, 2);
- g_assert(inet_pton(AF_INET, expected_wins1, &tmp) > 0);
- g_assert(nm_ip4_config_get_wins(ip4_config, 0) == tmp);
- g_assert(inet_pton(AF_INET, expected_wins2, &tmp) > 0);
- g_assert(nm_ip4_config_get_wins(ip4_config, 1) == tmp);
- g_hash_table_destroy(options);
+ ia_arr = nm_l3_config_data_get_wins(l3cd, &u);
+ g_assert_cmpint(u, ==, 2);
+ nmtst_assert_ip4_address(ia_arr[0], expected_wins1);
+ nmtst_assert_ip4_address(ia_arr[1], expected_wins2);
}
static void
test_vendor_option_metered(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
static const Option data[] = {{"vendor_encapsulated_options", "ANDROID_METERED"}, {NULL, NULL}};
- options = fill_table(generic_options, NULL);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
- g_assert(nm_ip4_config_get_metered(ip4_config) == FALSE);
- g_hash_table_destroy(options);
- g_clear_object(&ip4_config);
-
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
- g_assert(nm_ip4_config_get_metered(ip4_config) == TRUE);
- g_hash_table_destroy(options);
+ options = fill_table(generic_options, NULL);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
+ g_assert(nm_l3_config_data_get_metered(l3cd) == NM_TERNARY_DEFAULT);
+ nm_clear_pointer(&options, g_hash_table_destroy);
+ nm_clear_l3cd(&l3cd);
+
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
+ g_assert(nm_l3_config_data_get_metered(l3cd) == TRUE);
}
static void
@@ -252,18 +243,18 @@ test_parse_search_list(void)
}
static void
-ip4_test_route(NMIP4Config *ip4_config,
- guint route_num,
- const char * expected_dest,
- const char * expected_gw,
- guint expected_prefix)
+ip4_test_route(const NML3ConfigData *l3cd,
+ guint route_num,
+ const char * expected_dest,
+ const char * expected_gw,
+ guint expected_prefix)
{
const NMPlatformIP4Route *route;
guint32 tmp;
g_assert(expected_prefix <= 32);
- route = _nmtst_ip4_config_get_route(ip4_config, route_num);
+ route = nmtst_l3_config_data_get_route_at_4(l3cd, route_num);
g_assert(inet_pton(AF_INET, expected_dest, &tmp) > 0);
g_assert(route->network == tmp);
g_assert(inet_pton(AF_INET, expected_gw, &tmp) > 0);
@@ -272,110 +263,105 @@ ip4_test_route(NMIP4Config *ip4_config,
g_assert_cmpint(route->metric, ==, 0);
}
-static void
-ip4_test_gateway(NMIP4Config *ip4_config, const char *expected_gw)
-{
- guint32 tmp;
-
- g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1);
- g_assert(inet_pton(AF_INET, expected_gw, &tmp) > 0);
- g_assert(nmtst_ip4_config_get_gateway(ip4_config) == tmp);
-}
+#define ip4_test_gateway(l3cd, expected_gw) \
+ G_STMT_START \
+ { \
+ const NML3ConfigData *_l3cd = (l3cd); \
+ \
+ g_assert_cmpint(nm_l3_config_data_get_num_addresses(_l3cd, AF_INET), ==, 1); \
+ nmtst_assert_ip_address(AF_INET, \
+ nmtst_l3_config_data_get_best_gateway(_l3cd, AF_INET), \
+ expected_gw); \
+ } \
+ G_STMT_END
static void
test_classless_static_routes_1(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- const char * expected_route2_dest = "10.0.0.0";
- const char * expected_route2_gw = "10.17.66.41";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ const char * expected_route2_dest = "10.0.0.0";
+ const char * expected_route2_gw = "10.17.66.41";
+ static const Option data[] = {
/* dhclient custom format */
{"rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 8 10 10 17 66 41"},
{NULL, NULL}};
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 8);
- ip4_test_route(ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 8);
+ ip4_test_route(l3cd, 2, "0.0.0.0", "192.168.1.1", 0);
}
static void
test_classless_static_routes_2(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- const char * expected_route2_dest = "10.0.0.0";
- const char * expected_route2_gw = "10.17.66.41";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ const char * expected_route2_dest = "10.0.0.0";
+ const char * expected_route2_gw = "10.17.66.41";
+ static const Option data[] = {
/* dhcpcd format */
{"classless_static_routes", "192.168.10.0/24 192.168.1.1 10.0.0.0/8 10.17.66.41"},
{NULL, NULL}};
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 8);
- ip4_test_route(ip4_config, 2, "0.0.0.0", expected_route1_gw, 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 8);
+ ip4_test_route(l3cd, 2, "0.0.0.0", expected_route1_gw, 0);
}
static void
test_fedora_dhclient_classless_static_routes(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "129.210.177.128";
- const char * expected_route1_gw = "192.168.0.113";
- const char * expected_route2_dest = "2.0.0.0";
- const char * expected_route2_gw = "10.34.255.6";
- const char * expected_gateway = "192.168.0.113";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "129.210.177.128";
+ const char * expected_route1_gw = "192.168.0.113";
+ const char * expected_route2_dest = "2.0.0.0";
+ const char * expected_route2_gw = "10.34.255.6";
+ const char * expected_gateway = "192.168.0.113";
+ static const Option data[] = {
/* Fedora dhclient format */
{"classless_static_routes",
"0 192.168.0.113 25.129.210.177.132 192.168.0.113 7.2 10.34.255.6"},
{NULL, NULL}};
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 25);
- ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 7);
- ip4_test_route(ip4_config, 2, "0.0.0.0", expected_route1_gw, 0);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 25);
+ ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 7);
+ ip4_test_route(l3cd, 2, "0.0.0.0", expected_route1_gw, 0);
- /* Gateway */
- ip4_test_gateway(ip4_config, expected_gateway);
-
- g_hash_table_destroy(options);
+ ip4_test_gateway(l3cd, expected_gateway);
}
static void
test_dhclient_invalid_classless_routes_1(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ static const Option data[] = {
/* dhclient format */
{"rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 45 10 17 66 41"},
{NULL, NULL}};
@@ -384,27 +370,25 @@ test_dhclient_invalid_classless_routes_1(void)
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, "0.0.0.0", expected_route1_gw, 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 2);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, "0.0.0.0", expected_route1_gw, 0);
}
static void
test_dhcpcd_invalid_classless_routes_1(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "10.1.1.5";
- const char * expected_route1_gw = "10.1.1.1";
- const char * expected_route2_dest = "100.99.88.56";
- const char * expected_route2_gw = "10.1.1.1";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "10.1.1.5";
+ const char * expected_route1_gw = "10.1.1.1";
+ const char * expected_route2_dest = "100.99.88.56";
+ const char * expected_route2_gw = "10.1.1.1";
+ static const Option data[] = {
/* dhcpcd format */
{"classless_static_routes", "192.168.10.0/24 192.168.1.1 10.0.adfadf/44 10.17.66.41"},
{NULL, NULL}};
@@ -413,30 +397,28 @@ test_dhcpcd_invalid_classless_routes_1(void)
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
/* Test falling back to old-style static routes if the classless static
* routes are invalid.
*/
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 32);
- ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 32);
- ip4_test_route(ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 32);
+ ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 32);
+ ip4_test_route(l3cd, 2, "0.0.0.0", "192.168.1.1", 0);
}
static void
test_dhclient_invalid_classless_routes_2(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "10.1.1.5";
- const char * expected_route1_gw = "10.1.1.1";
- const char * expected_route2_dest = "100.99.88.56";
- const char * expected_route2_gw = "10.1.1.1";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "10.1.1.5";
+ const char * expected_route1_gw = "10.1.1.1";
+ const char * expected_route2_dest = "100.99.88.56";
+ const char * expected_route2_gw = "10.1.1.1";
+ static const Option data[] = {
{"rfc3442_classless_static_routes", "45 10 17 66 41 24 192 168 10 192 168 1 1"},
{NULL, NULL}};
@@ -444,30 +426,28 @@ test_dhclient_invalid_classless_routes_2(void)
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
/* Test falling back to old-style static routes if the classless static
* routes are invalid.
*/
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 32);
- ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 32);
- ip4_test_route(ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 32);
+ ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 32);
+ ip4_test_route(l3cd, 2, "0.0.0.0", "192.168.1.1", 0);
}
static void
test_dhcpcd_invalid_classless_routes_2(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "10.1.1.5";
- const char * expected_route1_gw = "10.1.1.1";
- const char * expected_route2_dest = "100.99.88.56";
- const char * expected_route2_gw = "10.1.1.1";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "10.1.1.5";
+ const char * expected_route1_gw = "10.1.1.1";
+ const char * expected_route2_dest = "100.99.88.56";
+ const char * expected_route2_gw = "10.1.1.1";
+ static const Option data[] = {
{"classless_static_routes", "10.0.adfadf/44 10.17.66.41 192.168.10.0/24 192.168.1.1"},
{NULL, NULL}};
@@ -475,7 +455,7 @@ test_dhcpcd_invalid_classless_routes_2(void)
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
/* Test falling back to old-style static routes if the classless static
@@ -483,22 +463,20 @@ test_dhcpcd_invalid_classless_routes_2(void)
*/
/* Routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 32);
- ip4_test_route(ip4_config, 1, expected_route2_dest, expected_route2_gw, 32);
- ip4_test_route(ip4_config, 2, "0.0.0.0", "192.168.1.1", 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 3);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 32);
+ ip4_test_route(l3cd, 1, expected_route2_dest, expected_route2_gw, 32);
+ ip4_test_route(l3cd, 2, "0.0.0.0", "192.168.1.1", 0);
}
static void
test_dhclient_invalid_classless_routes_3(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- static const Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ static const Option data[] = {
{"rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 32 128 10 17 66 41"},
{NULL, NULL}};
@@ -506,25 +484,23 @@ test_dhclient_invalid_classless_routes_3(void)
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, "0.0.0.0", expected_route1_gw, 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 2);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, "0.0.0.0", expected_route1_gw, 0);
}
static void
test_dhcpcd_invalid_classless_routes_3(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- static Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ static Option data[] = {
{"classless_static_routes", "192.168.10.0/24 192.168.1.1 128/32 10.17.66.41"},
{NULL, NULL}};
@@ -532,133 +508,124 @@ test_dhcpcd_invalid_classless_routes_3(void)
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*DHCP provided invalid classless static route*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, "0.0.0.0", expected_route1_gw, 0);
-
- g_hash_table_destroy(options);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 2);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, "0.0.0.0", expected_route1_gw, 0);
}
static void
test_dhclient_gw_in_classless_routes(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- const char * expected_gateway = "192.2.3.4";
- static Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ const char * expected_gateway = "192.2.3.4";
+ static Option data[] = {
{"rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 0 192 2 3 4"},
{NULL, NULL}};
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, "0.0.0.0", "192.2.3.4", 0);
-
- /* Gateway */
- ip4_test_gateway(ip4_config, expected_gateway);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 2);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, "0.0.0.0", "192.2.3.4", 0);
- g_hash_table_destroy(options);
+ ip4_test_gateway(l3cd, expected_gateway);
}
static void
test_dhcpcd_gw_in_classless_routes(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_route1_dest = "192.168.10.0";
- const char * expected_route1_gw = "192.168.1.1";
- const char * expected_gateway = "192.2.3.4";
- static Option data[] = {
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_route1_dest = "192.168.10.0";
+ const char * expected_route1_gw = "192.168.1.1";
+ const char * expected_gateway = "192.2.3.4";
+ static Option data[] = {
{"classless_static_routes", "192.168.10.0/24 192.168.1.1 0.0.0.0/0 192.2.3.4"},
{NULL, NULL}};
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
/* IP4 routes */
- g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 2);
- ip4_test_route(ip4_config, 0, expected_route1_dest, expected_route1_gw, 24);
- ip4_test_route(ip4_config, 1, "0.0.0.0", "192.2.3.4", 0);
-
- /* Gateway */
- ip4_test_gateway(ip4_config, expected_gateway);
+ g_assert_cmpint(nm_l3_config_data_get_num_routes(l3cd, AF_INET), ==, 2);
+ ip4_test_route(l3cd, 0, expected_route1_dest, expected_route1_gw, 24);
+ ip4_test_route(l3cd, 1, "0.0.0.0", "192.2.3.4", 0);
- g_hash_table_destroy(options);
+ ip4_test_gateway(l3cd, expected_gateway);
}
static void
test_escaped_domain_searches(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const char * expected_search0 = "host1";
- const char * expected_search1 = "host2";
- const char * expected_search2 = "host3";
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const char * expected_search0 = "host1";
+ const char * expected_search1 = "host2";
+ const char * expected_search2 = "host3";
static const Option data[] = {{"domain_search", "host1\\032host2\\032host3"}, {NULL, NULL}};
+ const char *const * strarr;
+ guint u;
- options = fill_table(generic_options, NULL);
- options = fill_table(data, options);
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
-
- /* domain searches */
- g_assert_cmpint(nm_ip4_config_get_num_searches(ip4_config), ==, 3);
- g_assert_cmpstr(nm_ip4_config_get_search(ip4_config, 0), ==, expected_search0);
- g_assert_cmpstr(nm_ip4_config_get_search(ip4_config, 1), ==, expected_search1);
- g_assert_cmpstr(nm_ip4_config_get_search(ip4_config, 2), ==, expected_search2);
+ options = fill_table(generic_options, NULL);
+ options = fill_table(data, options);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
- g_hash_table_destroy(options);
+ strarr = nm_l3_config_data_get_searches(l3cd, AF_INET, &u);
+ g_assert_cmpint(u, ==, 3);
+ g_assert_cmpstr(strarr[0], ==, expected_search0);
+ g_assert_cmpstr(strarr[1], ==, expected_search1);
+ g_assert_cmpstr(strarr[2], ==, expected_search2);
}
static void
test_invalid_escaped_domain_searches(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
static const Option data[] = {{"domain_search", "host1\\aahost2\\032host3"}, {NULL, NULL}};
+ const char *const * strarr;
+ guint u;
options = fill_table(generic_options, NULL);
options = fill_table(data, options);
NMTST_EXPECT_NM_WARN("*invalid domain search*");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
g_test_assert_expected_messages();
- /* domain searches */
- g_assert_cmpint(nm_ip4_config_get_num_searches(ip4_config), ==, 0);
-
- g_hash_table_destroy(options);
+ strarr = nm_l3_config_data_get_searches(l3cd, AF_INET, &u);
+ g_assert_cmpint(u, ==, 0);
+ g_assert(!strarr);
}
static void
test_ip4_missing_prefix(const char *ip, guint32 expected_prefix)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const NMPlatformIP4Address * address;
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const NMPlatformIP4Address * address;
options = fill_table(generic_options, NULL);
g_hash_table_insert(options, "ip_address", (gpointer) ip);
g_hash_table_remove(options, "subnet_mask");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
- g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1);
- address = _nmtst_ip4_config_get_address(ip4_config, 0);
+ g_assert_cmpint(nm_l3_config_data_get_num_addresses(l3cd, AF_INET), ==, 1);
+ address = nmtst_l3_config_data_get_address_at_4(l3cd, 0);
g_assert(address);
g_assert_cmpint(address->plen, ==, expected_prefix);
-
- g_hash_table_destroy(options);
}
static void
@@ -682,9 +649,9 @@ test_ip4_missing_prefix_8(void)
static void
test_ip4_prefix_classless(void)
{
- GHashTable * options;
- gs_unref_object NMIP4Config *ip4_config = NULL;
- const NMPlatformIP4Address * address;
+ gs_unref_hashtable GHashTable *options = NULL;
+ nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL;
+ const NMPlatformIP4Address * address;
/* Ensure that the missing-subnet-mask handler doesn't mangle classless
* subnet masks at all. The handler should trigger only if the server
@@ -695,14 +662,12 @@ test_ip4_prefix_classless(void)
g_hash_table_insert(options, "ip_address", "172.16.54.22");
g_hash_table_insert(options, "subnet_mask", "255.255.252.0");
- ip4_config = _ip4_config_from_options(1, "eth0", options, 0);
+ l3cd = _ip4_config_from_options(1, "eth0", options);
- g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1);
- address = _nmtst_ip4_config_get_address(ip4_config, 0);
+ g_assert_cmpint(nm_l3_config_data_get_num_addresses(l3cd, AF_INET), ==, 1);
+ address = nmtst_l3_config_data_get_address_at_4(l3cd, 0);
g_assert(address);
g_assert_cmpint(address->plen, ==, 22);
-
- g_hash_table_destroy(options);
}
#define COMPARE_ID(src, is_str, expected, expected_len) \