diff options
| author | Michael Biebl <biebl@debian.org> | 2020-10-05 22:27:18 +0200 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2020-10-05 22:27:18 +0200 |
| commit | aafc1dbe4712c86189bbc1d4d54ad8cb4c69be7e (patch) | |
| tree | a2a9bb4d007339a0b1304540388230ccedac32bd /src/dhcp | |
| parent | e7b44ef4c80907346ec7492a09c45277459924fc (diff) | |
New upstream version 1.27.90 upstream/1.27.90
Diffstat (limited to 'src/dhcp')
| -rw-r--r-- | src/dhcp/nm-dhcp-client-logging.h | 112 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-client.c | 1942 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-client.h | 291 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-dhclient-utils.c | 1241 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-dhclient-utils.h | 37 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-dhclient.c | 1185 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-dhcpcanon.c | 353 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-dhcpcd.c | 341 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-helper-api.h | 10 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-helper.c | 409 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-listener.c | 447 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-listener.h | 18 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-manager.c | 1061 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-manager.h | 116 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-nettools.c | 2525 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-options.c | 440 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-options.h | 354 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-systemd.c | 2039 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-utils.c | 1428 | ||||
| -rw-r--r-- | src/dhcp/nm-dhcp-utils.h | 45 | ||||
| -rw-r--r-- | src/dhcp/tests/test-dhcp-dhclient.c | 2094 | ||||
| -rw-r--r-- | src/dhcp/tests/test-dhcp-utils.c | 1274 |
22 files changed, 9051 insertions, 8711 deletions
diff --git a/src/dhcp/nm-dhcp-client-logging.h b/src/dhcp/nm-dhcp-client-logging.h index 4e69c698..ecbf5210 100644 --- a/src/dhcp/nm-dhcp-client-logging.h +++ b/src/dhcp/nm-dhcp-client-logging.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2016 Red Hat, Inc. */ @@ -9,69 +9,79 @@ #include "nm-dhcp-client.h" static inline NMLogDomain -_nm_dhcp_client_get_domain (NMDhcpClient *self) +_nm_dhcp_client_get_domain(NMDhcpClient *self) { - if (self) { - switch (nm_dhcp_client_get_addr_family (self)) { - case AF_INET: - return LOGD_DHCP4; - case AF_INET6: - return LOGD_DHCP6; - default: - nm_assert_not_reached (); - break; - } - } - return LOGD_DHCP; + if (self) { + switch (nm_dhcp_client_get_addr_family(self)) { + case AF_INET: + return LOGD_DHCP4; + case AF_INET6: + return LOGD_DHCP6; + default: + nm_assert_not_reached(); + break; + } + } + return LOGD_DHCP; } -#define _NMLOG_PREFIX_NAME "dhcp" -#define _NMLOG_DOMAIN LOGD_DHCP -#define _NMLOG(level, ...) \ - G_STMT_START { \ - const NMLogLevel _level = (level); \ - \ +#define _NMLOG_PREFIX_NAME "dhcp" +#define _NMLOG_DOMAIN LOGD_DHCP +#define _NMLOG(level, ...) \ + G_STMT_START \ + { \ + const NMLogLevel _level = (level); \ + \ /* we check first for LOGD_DHCP instead of the correct domain. * In the worst case, we guess wrong and enter the block. * * Same for the _NMLOG_ENABLED() macro. Probably it would be more * expensive to determine the correct value then what we could - * safe. */ \ - if (nm_logging_enabled (_level, _NMLOG_DOMAIN)) { \ - NMDhcpClient *_self = (NMDhcpClient *) (self); \ - const char *__ifname = _self ? nm_dhcp_client_get_iface (_self) : NULL; \ - const NMLogDomain _domain = _nm_dhcp_client_get_domain (_self); \ - \ - nm_log (_level, _domain, __ifname, NULL, \ - "%s%s%s%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - (_domain == LOGD_DHCP4 ? "4" : (_domain == LOGD_DHCP6 ? "6" : "")), \ - NM_PRINT_FMT_QUOTED (__ifname, " (", __ifname, ")", "") \ - _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ - } \ - } G_STMT_END + * safe. */ \ + if (nm_logging_enabled(_level, _NMLOG_DOMAIN)) { \ + NMDhcpClient * _self = (NMDhcpClient *) (self); \ + const char * __ifname = _self ? nm_dhcp_client_get_iface(_self) : NULL; \ + const NMLogDomain _domain = _nm_dhcp_client_get_domain(_self); \ + \ + nm_log(_level, \ + _domain, \ + __ifname, \ + NULL, \ + "%s%s%s%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + (_domain == LOGD_DHCP4 ? "4" : (_domain == LOGD_DHCP6 ? "6" : "")), \ + NM_PRINT_FMT_QUOTED(__ifname, " (", __ifname, ")", "") \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ + G_STMT_END -#define _NMLOG2(level, domain, ifname, ...) \ - G_STMT_START { \ - const NMLogLevel _level = (level); \ - const NMLogDomain _domain = (domain); \ - \ +#define _NMLOG2(level, domain, ifname, ...) \ + G_STMT_START \ + { \ + const NMLogLevel _level = (level); \ + const NMLogDomain _domain = (domain); \ + \ /* we check first for LOGD_DHCP instead of the correct domain. * In the worst case, we guess wrong and enter the block. * * Same for the _NMLOG_ENABLED() macro. Probably it would be more * expensive to determine the correct value then what we could - * safe. */ \ - if (nm_logging_enabled (_level, _domain)) { \ - const char *__ifname = (ifname); \ - \ - nm_log (_level, _domain, __ifname, NULL, \ - "%s%s%s%s%s: " _NM_UTILS_MACRO_FIRST (__VA_ARGS__), \ - _NMLOG_PREFIX_NAME, \ - (_domain == LOGD_DHCP4 ? "4" : (_domain == LOGD_DHCP6 ? "6" : "")), \ - NM_PRINT_FMT_QUOTED (__ifname, " (", __ifname, ")", "") \ - _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ - } \ - } G_STMT_END + * safe. */ \ + if (nm_logging_enabled(_level, _domain)) { \ + const char *__ifname = (ifname); \ + \ + nm_log(_level, \ + _domain, \ + __ifname, \ + NULL, \ + "%s%s%s%s%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + _NMLOG_PREFIX_NAME, \ + (_domain == LOGD_DHCP4 ? "4" : (_domain == LOGD_DHCP6 ? "6" : "")), \ + NM_PRINT_FMT_QUOTED(__ifname, " (", __ifname, ")", "") \ + _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ + G_STMT_END #endif /* __NETWORKMANAGER_DHCP_CLIENT_LOGGING_H__ */ diff --git a/src/dhcp/nm-dhcp-client.c b/src/dhcp/nm-dhcp-client.c index f7324baf..46ab4895 100644 --- a/src/dhcp/nm-dhcp-client.c +++ b/src/dhcp/nm-dhcp-client.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2005 - 2010 Red Hat, Inc. */ @@ -26,1232 +26,1312 @@ /*****************************************************************************/ -enum { - SIGNAL_STATE_CHANGED, - SIGNAL_PREFIX_DELEGATED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -NM_GOBJECT_PROPERTIES_DEFINE (NMDhcpClient, - PROP_ADDR_FAMILY, - 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, -); +enum { SIGNAL_STATE_CHANGED, SIGNAL_PREFIX_DELEGATED, LAST_SIGNAL }; + +static guint signals[LAST_SIGNAL] = {0}; + +NM_GOBJECT_PROPERTIES_DEFINE(NMDhcpClient, + PROP_ADDR_FAMILY, + 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, ); typedef struct _NMDhcpClientPrivate { - NMDedupMultiIndex *multi_idx; - char * iface; - GBytes * hwaddr; - GBytes * bcast_hwaddr; - char * uuid; - GBytes * client_id; - char * hostname; - char * mud_url; - 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; - bool info_only:1; - bool use_fqdn:1; - bool iaid_explicit:1; + NMDedupMultiIndex * multi_idx; + char * iface; + GBytes * hwaddr; + GBytes * bcast_hwaddr; + char * uuid; + GBytes * client_id; + char * hostname; + const char ** reject_servers; + char * mud_url; + 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; + bool info_only : 1; + bool use_fqdn : 1; + bool iaid_explicit : 1; } NMDhcpClientPrivate; -G_DEFINE_ABSTRACT_TYPE (NMDhcpClient, nm_dhcp_client, G_TYPE_OBJECT) +G_DEFINE_ABSTRACT_TYPE(NMDhcpClient, nm_dhcp_client, G_TYPE_OBJECT) -#define NM_DHCP_CLIENT_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR (self, NMDhcpClient, NM_IS_DHCP_CLIENT) +#define NM_DHCP_CLIENT_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMDhcpClient, NM_IS_DHCP_CLIENT) /*****************************************************************************/ pid_t -nm_dhcp_client_get_pid (NMDhcpClient *self) +nm_dhcp_client_get_pid(NMDhcpClient *self) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), -1); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), -1); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->pid; + return NM_DHCP_CLIENT_GET_PRIVATE(self)->pid; } NMDedupMultiIndex * -nm_dhcp_client_get_multi_idx (NMDhcpClient *self) +nm_dhcp_client_get_multi_idx(NMDhcpClient *self) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->multi_idx; + return NM_DHCP_CLIENT_GET_PRIVATE(self)->multi_idx; } const char * -nm_dhcp_client_get_iface (NMDhcpClient *self) +nm_dhcp_client_get_iface(NMDhcpClient *self) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->iface; + return NM_DHCP_CLIENT_GET_PRIVATE(self)->iface; } int -nm_dhcp_client_get_ifindex (NMDhcpClient *self) +nm_dhcp_client_get_ifindex(NMDhcpClient *self) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), -1); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), -1); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->ifindex; + return NM_DHCP_CLIENT_GET_PRIVATE(self)->ifindex; } int -nm_dhcp_client_get_addr_family (NMDhcpClient *self) +nm_dhcp_client_get_addr_family(NMDhcpClient *self) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), AF_UNSPEC); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), AF_UNSPEC); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->addr_family; + return NM_DHCP_CLIENT_GET_PRIVATE(self)->addr_family; } const char * -nm_dhcp_client_get_uuid (NMDhcpClient *self) +nm_dhcp_client_get_uuid(NMDhcpClient *self) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->uuid; + return NM_DHCP_CLIENT_GET_PRIVATE(self)->uuid; } GBytes * -nm_dhcp_client_get_hw_addr (NMDhcpClient *self) +nm_dhcp_client_get_hw_addr(NMDhcpClient *self) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->hwaddr; + return NM_DHCP_CLIENT_GET_PRIVATE(self)->hwaddr; } GBytes * -nm_dhcp_client_get_broadcast_hw_addr (NMDhcpClient *self) +nm_dhcp_client_get_broadcast_hw_addr(NMDhcpClient *self) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->bcast_hwaddr; + return NM_DHCP_CLIENT_GET_PRIVATE(self)->bcast_hwaddr; } guint32 -nm_dhcp_client_get_route_table (NMDhcpClient *self) +nm_dhcp_client_get_route_table(NMDhcpClient *self) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), RT_TABLE_MAIN); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), RT_TABLE_MAIN); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->route_table; + return NM_DHCP_CLIENT_GET_PRIVATE(self)->route_table; } void -nm_dhcp_client_set_route_table (NMDhcpClient *self, guint32 route_table) +nm_dhcp_client_set_route_table(NMDhcpClient *self, guint32 route_table) { - NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); - if (route_table != priv->route_table) { - priv->route_table = route_table; - _notify (self, PROP_ROUTE_TABLE); - } + 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) +nm_dhcp_client_get_route_metric(NMDhcpClient *self) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), G_MAXUINT32); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), G_MAXUINT32); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->route_metric; + return NM_DHCP_CLIENT_GET_PRIVATE(self)->route_metric; } void -nm_dhcp_client_set_route_metric (NMDhcpClient *self, guint32 route_metric) +nm_dhcp_client_set_route_metric(NMDhcpClient *self, guint32 route_metric) { - NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); - if (route_metric != priv->route_metric) { - priv->route_metric = route_metric; - _notify (self, PROP_ROUTE_METRIC); - } + if (route_metric != priv->route_metric) { + priv->route_metric = route_metric; + _notify(self, PROP_ROUTE_METRIC); + } } guint32 -nm_dhcp_client_get_timeout (NMDhcpClient *self) +nm_dhcp_client_get_timeout(NMDhcpClient *self) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), 0); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), 0); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->timeout; + return NM_DHCP_CLIENT_GET_PRIVATE(self)->timeout; } guint32 -nm_dhcp_client_get_iaid (NMDhcpClient *self) +nm_dhcp_client_get_iaid(NMDhcpClient *self) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), 0); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), 0); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->iaid; + return NM_DHCP_CLIENT_GET_PRIVATE(self)->iaid; } gboolean -nm_dhcp_client_get_iaid_explicit (NMDhcpClient *self) +nm_dhcp_client_get_iaid_explicit(NMDhcpClient *self) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->iaid_explicit; + return NM_DHCP_CLIENT_GET_PRIVATE(self)->iaid_explicit; } GBytes * -nm_dhcp_client_get_client_id (NMDhcpClient *self) +nm_dhcp_client_get_client_id(NMDhcpClient *self) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->client_id; + return NM_DHCP_CLIENT_GET_PRIVATE(self)->client_id; } static void -_set_client_id (NMDhcpClient *self, GBytes *client_id, gboolean take) +_set_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 (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 (!take && client_id) - g_bytes_ref (client_id); - - { - 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"); - } + 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 (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 (!take && client_id) + g_bytes_ref(client_id); + + { + 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"); + } } void -nm_dhcp_client_set_client_id (NMDhcpClient *self, GBytes *client_id) +nm_dhcp_client_set_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); + 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); + _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) +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); + 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_hostname (NMDhcpClient *self) +nm_dhcp_client_get_hostname(NMDhcpClient *self) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NULL); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->hostname; + return NM_DHCP_CLIENT_GET_PRIVATE(self)->hostname; } NMDhcpHostnameFlags -nm_dhcp_client_get_hostname_flags (NMDhcpClient *self) +nm_dhcp_client_get_hostname_flags(NMDhcpClient *self) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), NM_DHCP_HOSTNAME_FLAG_NONE); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NM_DHCP_HOSTNAME_FLAG_NONE); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->hostname_flags; + return NM_DHCP_CLIENT_GET_PRIVATE(self)->hostname_flags; } gboolean -nm_dhcp_client_get_info_only (NMDhcpClient *self) +nm_dhcp_client_get_info_only(NMDhcpClient *self) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->info_only; + return NM_DHCP_CLIENT_GET_PRIVATE(self)->info_only; } gboolean -nm_dhcp_client_get_use_fqdn (NMDhcpClient *self) +nm_dhcp_client_get_use_fqdn(NMDhcpClient *self) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->use_fqdn; + return NM_DHCP_CLIENT_GET_PRIVATE(self)->use_fqdn; } const char * -nm_dhcp_client_get_mud_url (NMDhcpClient *self) +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); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), NULL); - return NM_DHCP_CLIENT_GET_PRIVATE (self)->mud_url; + 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; } /*****************************************************************************/ static const char *state_table[NM_DHCP_STATE_MAX + 1] = { - [NM_DHCP_STATE_UNKNOWN] = "unknown", - [NM_DHCP_STATE_BOUND] = "bound", - [NM_DHCP_STATE_EXTENDED] = "extended", - [NM_DHCP_STATE_TIMEOUT] = "timeout", - [NM_DHCP_STATE_EXPIRE] = "expire", - [NM_DHCP_STATE_DONE] = "done", - [NM_DHCP_STATE_FAIL] = "fail", - [NM_DHCP_STATE_TERMINATED] = "terminated", + [NM_DHCP_STATE_UNKNOWN] = "unknown", + [NM_DHCP_STATE_BOUND] = "bound", + [NM_DHCP_STATE_EXTENDED] = "extended", + [NM_DHCP_STATE_TIMEOUT] = "timeout", + [NM_DHCP_STATE_EXPIRE] = "expire", + [NM_DHCP_STATE_DONE] = "done", + [NM_DHCP_STATE_FAIL] = "fail", + [NM_DHCP_STATE_TERMINATED] = "terminated", }; static const char * -state_to_string (NMDhcpState state) +state_to_string(NMDhcpState state) { - if ((gsize) state < G_N_ELEMENTS (state_table)) - return state_table[state]; - return NULL; + if ((gsize) state < G_N_ELEMENTS(state_table)) + return state_table[state]; + return NULL; } static NMDhcpState -reason_to_state (NMDhcpClient *self, const char *iface, const char *reason) +reason_to_state(NMDhcpClient *self, const char *iface, const char *reason) { - if (g_ascii_strcasecmp (reason, "bound") == 0 || - g_ascii_strcasecmp (reason, "bound6") == 0) - return NM_DHCP_STATE_BOUND; - else if (g_ascii_strcasecmp (reason, "renew") == 0 || - g_ascii_strcasecmp (reason, "renew6") == 0 || - g_ascii_strcasecmp (reason, "reboot") == 0 || - g_ascii_strcasecmp (reason, "rebind") == 0 || - g_ascii_strcasecmp (reason, "rebind6") == 0) - return NM_DHCP_STATE_EXTENDED; - else if (g_ascii_strcasecmp (reason, "timeout") == 0) - return NM_DHCP_STATE_TIMEOUT; - else if (g_ascii_strcasecmp (reason, "nak") == 0 || - g_ascii_strcasecmp (reason, "expire") == 0 || - g_ascii_strcasecmp (reason, "expire6") == 0) - return NM_DHCP_STATE_EXPIRE; - else if (g_ascii_strcasecmp (reason, "end") == 0) - return NM_DHCP_STATE_DONE; - else if (g_ascii_strcasecmp (reason, "fail") == 0 || - g_ascii_strcasecmp (reason, "abend") == 0) - return NM_DHCP_STATE_FAIL; - - _LOGD ("unmapped DHCP state '%s'", reason); - return NM_DHCP_STATE_UNKNOWN; + if (g_ascii_strcasecmp(reason, "bound") == 0 || g_ascii_strcasecmp(reason, "bound6") == 0) + return NM_DHCP_STATE_BOUND; + else if (g_ascii_strcasecmp(reason, "renew") == 0 || g_ascii_strcasecmp(reason, "renew6") == 0 + || g_ascii_strcasecmp(reason, "reboot") == 0 + || g_ascii_strcasecmp(reason, "rebind") == 0 + || g_ascii_strcasecmp(reason, "rebind6") == 0) + return NM_DHCP_STATE_EXTENDED; + else if (g_ascii_strcasecmp(reason, "timeout") == 0) + return NM_DHCP_STATE_TIMEOUT; + else if (g_ascii_strcasecmp(reason, "nak") == 0 || g_ascii_strcasecmp(reason, "expire") == 0 + || g_ascii_strcasecmp(reason, "expire6") == 0) + return NM_DHCP_STATE_EXPIRE; + else if (g_ascii_strcasecmp(reason, "end") == 0) + return NM_DHCP_STATE_DONE; + else if (g_ascii_strcasecmp(reason, "fail") == 0 || g_ascii_strcasecmp(reason, "abend") == 0) + return NM_DHCP_STATE_FAIL; + + _LOGD("unmapped DHCP state '%s'", reason); + return NM_DHCP_STATE_UNKNOWN; } /*****************************************************************************/ static void -timeout_cleanup (NMDhcpClient *self) +timeout_cleanup(NMDhcpClient *self) { - NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); - nm_clear_g_source (&priv->timeout_id); + nm_clear_g_source(&priv->timeout_id); } static void -watch_cleanup (NMDhcpClient *self) +watch_cleanup(NMDhcpClient *self) { - NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); - nm_clear_g_source (&priv->watch_id); + nm_clear_g_source(&priv->watch_id); } void -nm_dhcp_client_stop_pid (pid_t pid, const char *iface) +nm_dhcp_client_stop_pid(pid_t pid, const char *iface) { - char *name = iface ? g_strdup_printf ("dhcp-client-%s", iface) : NULL; - - g_return_if_fail (pid > 1); - - nm_utils_kill_child_sync (pid, SIGTERM, LOGD_DHCP, name ?: "dhcp-client", NULL, - 1000 / 2, 1000 / 20); - g_free (name); + char *name = iface ? g_strdup_printf("dhcp-client-%s", iface) : NULL; + + g_return_if_fail(pid > 1); + + nm_utils_kill_child_sync(pid, + SIGTERM, + LOGD_DHCP, + name ?: "dhcp-client", + NULL, + 1000 / 2, + 1000 / 20); + g_free(name); } static void -stop (NMDhcpClient *self, gboolean release) +stop(NMDhcpClient *self, gboolean release) { - NMDhcpClientPrivate *priv; + NMDhcpClientPrivate *priv; - g_return_if_fail (NM_IS_DHCP_CLIENT (self)); + g_return_if_fail(NM_IS_DHCP_CLIENT(self)); - priv = NM_DHCP_CLIENT_GET_PRIVATE (self); + priv = NM_DHCP_CLIENT_GET_PRIVATE(self); - 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); - } - priv->pid = -1; + 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); + } + priv->pid = -1; } void -nm_dhcp_client_set_state (NMDhcpClient *self, - NMDhcpState new_state, - NMIPConfig *ip_config, - GHashTable *options) +nm_dhcp_client_set_state(NMDhcpClient *self, + NMDhcpState new_state, + NMIPConfig * ip_config, + GHashTable * options) { - NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); - gs_free char *event_id = NULL; - - if (NM_IN_SET (new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED)) { - g_return_if_fail (NM_IS_IP_CONFIG (ip_config, priv->addr_family)); - g_return_if_fail (options); - } else { - g_return_if_fail (!ip_config); - g_return_if_fail (!options); - } - - 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 (_LOGI_ENABLED ()) { - gs_free const char **keys = NULL; - guint i, nkeys; - - keys = nm_utils_strdict_get_keys (options, TRUE, &nkeys); - for (i = 0; i < nkeys; i++) { - _LOGI ("option %-20s => '%s'", keys[i], - (char *) g_hash_table_lookup (options, keys[i])); - } - } - - if ( priv->addr_family == AF_INET6 - && NM_IN_SET (new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED)) { - char *start, *iaid; - - iaid = g_hash_table_lookup (options, "iaid"); - start = g_hash_table_lookup (options, "life_starts"); - if (iaid && start) - event_id = g_strdup_printf ("%s|%s", iaid, start); - } - - _LOGI ("state changed %s -> %s%s%s%s", - state_to_string (priv->state), - state_to_string (new_state), - NM_PRINT_FMT_QUOTED (event_id, ", event ID=\"", event_id, "\"", "")); - - priv->state = new_state; - g_signal_emit (G_OBJECT (self), - signals[SIGNAL_STATE_CHANGED], 0, - new_state, - ip_config, - options, - event_id); + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); + gs_free char * event_id = NULL; + + 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); + } + + 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 (_LOGI_ENABLED()) { + gs_free const char **keys = NULL; + guint i, nkeys; + + keys = nm_utils_strdict_get_keys(options, TRUE, &nkeys); + for (i = 0; i < nkeys; i++) { + _LOGI("option %-20s => '%s'", keys[i], (char *) g_hash_table_lookup(options, keys[i])); + } + } + + if (priv->addr_family == AF_INET6) + event_id = nm_dhcp_utils_get_dhcp6_event_id(options); + + _LOGI("state changed %s -> %s%s%s%s", + state_to_string(priv->state), + state_to_string(new_state), + NM_PRINT_FMT_QUOTED(event_id, ", event ID=\"", event_id, "\"", "")); + + priv->state = new_state; + g_signal_emit(G_OBJECT(self), signals[SIGNAL_STATE_CHANGED], 0, new_state, ip_config, options); } static gboolean -transaction_timeout (gpointer user_data) +transaction_timeout(gpointer user_data) { - NMDhcpClient *self = NM_DHCP_CLIENT (user_data); - NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); + NMDhcpClient * self = NM_DHCP_CLIENT(user_data); + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); - priv->timeout_id = 0; - _LOGW ("request timed out"); - nm_dhcp_client_set_state (self, NM_DHCP_STATE_TIMEOUT, NULL, NULL); - return G_SOURCE_REMOVE; + priv->timeout_id = 0; + _LOGW("request timed out"); + nm_dhcp_client_set_state(self, NM_DHCP_STATE_TIMEOUT, NULL, NULL); + return G_SOURCE_REMOVE; } static void -daemon_watch_cb (GPid pid, int status, gpointer user_data) +daemon_watch_cb(GPid pid, int status, gpointer user_data) { - NMDhcpClient *self = NM_DHCP_CLIENT (user_data); - NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); - - g_return_if_fail (priv->watch_id); - priv->watch_id = 0; - - if (WIFEXITED (status)) - _LOGI ("client pid %d exited with status %d", pid, WEXITSTATUS (status)); - else if (WIFSIGNALED (status)) - _LOGI ("client pid %d killed by signal %d", pid, WTERMSIG (status)); - else if (WIFSTOPPED(status)) - _LOGI ("client pid %d stopped by signal %d", pid, WSTOPSIG (status)); - else if (WIFCONTINUED (status)) - _LOGI ("client pid %d resumed (by SIGCONT)", pid); - else - _LOGW ("client died abnormally"); - - priv->pid = -1; - - nm_dhcp_client_set_state (self, NM_DHCP_STATE_TERMINATED, NULL, NULL); + NMDhcpClient * self = NM_DHCP_CLIENT(user_data); + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); + + g_return_if_fail(priv->watch_id); + priv->watch_id = 0; + + if (WIFEXITED(status)) + _LOGI("client pid %d exited with status %d", pid, WEXITSTATUS(status)); + else if (WIFSIGNALED(status)) + _LOGI("client pid %d killed by signal %d", pid, WTERMSIG(status)); + else if (WIFSTOPPED(status)) + _LOGI("client pid %d stopped by signal %d", pid, WSTOPSIG(status)); + else if (WIFCONTINUED(status)) + _LOGI("client pid %d resumed (by SIGCONT)", pid); + else + _LOGW("client died abnormally"); + + priv->pid = -1; + + nm_dhcp_client_set_state(self, NM_DHCP_STATE_TERMINATED, NULL, NULL); } void -nm_dhcp_client_start_timeout (NMDhcpClient *self) +nm_dhcp_client_start_timeout(NMDhcpClient *self) { - NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); - g_return_if_fail (priv->timeout_id == 0); + g_return_if_fail(priv->timeout_id == 0); - /* Set up a timeout on the transaction to kill it after the timeout */ + /* Set up a timeout on the transaction to kill it after the timeout */ - if (priv->timeout == NM_DHCP_TIMEOUT_INFINITY) - return; + if (priv->timeout == NM_DHCP_TIMEOUT_INFINITY) + return; - priv->timeout_id = g_timeout_add_seconds (priv->timeout, - transaction_timeout, - self); + priv->timeout_id = g_timeout_add_seconds(priv->timeout, transaction_timeout, self); } void -nm_dhcp_client_watch_child (NMDhcpClient *self, pid_t pid) +nm_dhcp_client_watch_child(NMDhcpClient *self, pid_t pid) { - NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); - g_return_if_fail (priv->pid == -1); - priv->pid = pid; + g_return_if_fail(priv->pid == -1); + priv->pid = pid; - nm_dhcp_client_start_timeout (self); + nm_dhcp_client_start_timeout(self); - g_return_if_fail (priv->watch_id == 0); - priv->watch_id = g_child_watch_add (pid, daemon_watch_cb, self); + g_return_if_fail(priv->watch_id == 0); + priv->watch_id = g_child_watch_add(pid, daemon_watch_cb, self); } gboolean -nm_dhcp_client_start_ip4 (NMDhcpClient *self, - GBytes *client_id, - const char *dhcp_anycast_addr, - const char *last_ip4_address, - GError **error) +nm_dhcp_client_start_ip4(NMDhcpClient *self, + GBytes * client_id, + const char * dhcp_anycast_addr, + const char * last_ip4_address, + GError ** error) { - NMDhcpClientPrivate *priv; + NMDhcpClientPrivate *priv; - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), 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_INET, FALSE); - g_return_val_if_fail (priv->uuid != NULL, 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_INET, FALSE); + g_return_val_if_fail(priv->uuid != NULL, FALSE); - if (priv->timeout == NM_DHCP_TIMEOUT_INFINITY) - _LOGI ("activation: beginning transaction (no timeout)"); - else - _LOGI ("activation: beginning transaction (timeout in %u seconds)", (guint) priv->timeout); + if (priv->timeout == NM_DHCP_TIMEOUT_INFINITY) + _LOGI("activation: beginning transaction (no timeout)"); + else + _LOGI("activation: beginning transaction (timeout in %u seconds)", (guint) priv->timeout); - nm_dhcp_client_set_client_id (self, client_id); + nm_dhcp_client_set_client_id(self, client_id); - return NM_DHCP_CLIENT_GET_CLASS (self)->ip4_start (self, - dhcp_anycast_addr, - last_ip4_address, - error); + return NM_DHCP_CLIENT_GET_CLASS(self)->ip4_start(self, + dhcp_anycast_addr, + last_ip4_address, + error); } gboolean -nm_dhcp_client_accept (NMDhcpClient *self, - GError **error) +nm_dhcp_client_accept(NMDhcpClient *self, GError **error) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE); - if (NM_DHCP_CLIENT_GET_CLASS (self)->accept) { - return NM_DHCP_CLIENT_GET_CLASS (self)->accept (self, - error); - } + if (NM_DHCP_CLIENT_GET_CLASS(self)->accept) { + return NM_DHCP_CLIENT_GET_CLASS(self)->accept(self, error); + } - return TRUE; + return TRUE; } gboolean -nm_dhcp_client_decline (NMDhcpClient *self, - const char *error_message, - GError **error) +nm_dhcp_client_decline(NMDhcpClient *self, const char *error_message, GError **error) { - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE); + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE); - if (NM_DHCP_CLIENT_GET_CLASS (self)->decline) { - return NM_DHCP_CLIENT_GET_CLASS (self)->decline (self, - error_message, - error); - } + if (NM_DHCP_CLIENT_GET_CLASS(self)->decline) { + return NM_DHCP_CLIENT_GET_CLASS(self)->decline(self, error_message, error); + } - return TRUE; + return TRUE; } static GBytes * -get_duid (NMDhcpClient *self) +get_duid(NMDhcpClient *self) { - return NULL; + return NULL; } gboolean -nm_dhcp_client_start_ip6 (NMDhcpClient *self, - GBytes *client_id, - gboolean enforce_duid, - const char *dhcp_anycast_addr, - const struct in6_addr *ll_addr, - NMSettingIP6ConfigPrivacy privacy, - guint needed_prefixes, - GError **error) +nm_dhcp_client_start_ip6(NMDhcpClient * self, + GBytes * client_id, + gboolean enforce_duid, + const char * dhcp_anycast_addr, + const struct in6_addr * ll_addr, + NMSettingIP6ConfigPrivacy privacy, + guint needed_prefixes, + GError ** error) { - NMDhcpClientPrivate *priv; - gs_unref_bytes GBytes *own_client_id = NULL; + 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); + 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); + 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->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); - if (!enforce_duid) - own_client_id = NM_DHCP_CLIENT_GET_CLASS (self)->get_duid (self); + if (!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_client_id(self, own_client_id ?: client_id, FALSE); - if (priv->timeout == NM_DHCP_TIMEOUT_INFINITY) - _LOGI ("activation: beginning transaction (no timeout)"); - else - _LOGI ("activation: beginning transaction (timeout in %u seconds)", (guint) priv->timeout); + if (priv->timeout == NM_DHCP_TIMEOUT_INFINITY) + _LOGI("activation: beginning transaction (no timeout)"); + else + _LOGI("activation: beginning transaction (timeout in %u seconds)", (guint) priv->timeout); - return NM_DHCP_CLIENT_GET_CLASS (self)->ip6_start (self, - dhcp_anycast_addr, - ll_addr, - privacy, - needed_prefixes, - error); + return NM_DHCP_CLIENT_GET_CLASS(self) + ->ip6_start(self, dhcp_anycast_addr, ll_addr, privacy, needed_prefixes, error); } void -nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name) +nm_dhcp_client_stop_existing(const char *pid_file, const char *binary_name) { - guint64 start_time; - pid_t pid, ppid; - const char *exe; - char proc_path[NM_STRLEN ("/proc/%lu/cmdline") + 100]; - gs_free char *pid_contents = NULL, *proc_contents = NULL; - - /* Check for an existing instance and stop it */ - if (!g_file_get_contents (pid_file, &pid_contents, NULL, NULL)) - return; - - pid = _nm_utils_ascii_str_to_int64 (pid_contents, 10, 1, G_MAXINT64, 0); - if (pid <= 0) - goto out; - - start_time = nm_utils_get_start_time_for_pid (pid, NULL, &ppid); - if (start_time == 0) - goto out; - - nm_sprintf_buf (proc_path, "/proc/%lu/cmdline", (unsigned long) pid); - if (!g_file_get_contents (proc_path, &proc_contents, NULL, NULL)) - goto out; - - exe = strrchr (proc_contents, '/'); - if (exe) - exe++; - else - exe = proc_contents; - if (!nm_streq0 (exe, binary_name)) - goto out; - - if (ppid == getpid ()) { - /* the process is our own child. */ - nm_utils_kill_child_sync (pid, SIGTERM, LOGD_DHCP, "dhcp-client", NULL, 1000 / 2, 1000 / 20); - } else { - nm_utils_kill_process_sync (pid, start_time, SIGTERM, LOGD_DHCP, - "dhcp-client", 1000 / 2, 1000 / 20, 2000); - } + guint64 start_time; + pid_t pid, ppid; + const char * exe; + char proc_path[NM_STRLEN("/proc/%lu/cmdline") + 100]; + gs_free char *pid_contents = NULL, *proc_contents = NULL; + + /* Check for an existing instance and stop it */ + if (!g_file_get_contents(pid_file, &pid_contents, NULL, NULL)) + return; + + pid = _nm_utils_ascii_str_to_int64(pid_contents, 10, 1, G_MAXINT64, 0); + if (pid <= 0) + goto out; + + start_time = nm_utils_get_start_time_for_pid(pid, NULL, &ppid); + if (start_time == 0) + goto out; + + nm_sprintf_buf(proc_path, "/proc/%lu/cmdline", (unsigned long) pid); + if (!g_file_get_contents(proc_path, &proc_contents, NULL, NULL)) + goto out; + + exe = strrchr(proc_contents, '/'); + if (exe) + exe++; + else + exe = proc_contents; + if (!nm_streq0(exe, binary_name)) + goto out; + + if (ppid == getpid()) { + /* the process is our own child. */ + nm_utils_kill_child_sync(pid, SIGTERM, LOGD_DHCP, "dhcp-client", NULL, 1000 / 2, 1000 / 20); + } else { + nm_utils_kill_process_sync(pid, + start_time, + SIGTERM, + LOGD_DHCP, + "dhcp-client", + 1000 / 2, + 1000 / 20, + 2000); + } out: - if (remove (pid_file) == -1) { - int errsv = errno; - - nm_log_dbg (LOGD_DHCP, "dhcp: could not remove pid file \"%s\": %s (%d)", - pid_file, nm_strerror_native (errsv), errsv); - } + if (remove(pid_file) == -1) { + int errsv = errno; + + nm_log_dbg(LOGD_DHCP, + "dhcp: could not remove pid file \"%s\": %s (%d)", + pid_file, + nm_strerror_native(errsv), + errsv); + } } void -nm_dhcp_client_stop (NMDhcpClient *self, gboolean release) +nm_dhcp_client_stop(NMDhcpClient *self, gboolean release) { - NMDhcpClientPrivate *priv; - pid_t old_pid = 0; + NMDhcpClientPrivate *priv; + pid_t old_pid = 0; - g_return_if_fail (NM_IS_DHCP_CLIENT (self)); + g_return_if_fail(NM_IS_DHCP_CLIENT(self)); - priv = NM_DHCP_CLIENT_GET_PRIVATE (self); + priv = NM_DHCP_CLIENT_GET_PRIVATE(self); - /* Kill the DHCP client */ - old_pid = priv->pid; - NM_DHCP_CLIENT_GET_CLASS (self)->stop (self, release); - if (old_pid > 0) - _LOGI ("canceled DHCP transaction, DHCP client pid %d", old_pid); - else - _LOGI ("canceled DHCP transaction"); - nm_assert (priv->pid == -1); + /* Kill the DHCP client */ + old_pid = priv->pid; + NM_DHCP_CLIENT_GET_CLASS(self)->stop(self, release); + if (old_pid > 0) + _LOGI("canceled DHCP transaction, DHCP client pid %d", old_pid); + else + _LOGI("canceled DHCP transaction"); + nm_assert(priv->pid == -1); - nm_dhcp_client_set_state (self, NM_DHCP_STATE_DONE, NULL, NULL); + nm_dhcp_client_set_state(self, NM_DHCP_STATE_DONE, NULL, NULL); } /*****************************************************************************/ static char * -bytearray_variant_to_string (NMDhcpClient *self, GVariant *value, const char *key) +bytearray_variant_to_string(NMDhcpClient *self, GVariant *value, const char *key) { - const guint8 *array; - gsize length; - GString *str; - int i; - unsigned char c; - char *converted = NULL; - - g_return_val_if_fail (value != NULL, NULL); - - array = g_variant_get_fixed_array (value, &length, 1); - - /* Since the DHCP options come through environment variables, they should - * already be UTF-8 safe, but just make sure. - */ - str = g_string_sized_new (length); - for (i = 0; i < length; i++) { - c = array[i]; - - /* Convert NULLs to spaces and non-ASCII characters to ? */ - if (c == '\0') - c = ' '; - else if (c > 127) - c = '?'; - str = g_string_append_c (str, c); - } - str = g_string_append_c (str, '\0'); - - converted = str->str; - if (!g_utf8_validate (converted, -1, NULL)) - _LOGW ("option '%s' couldn't be converted to UTF-8", key); - g_string_free (str, FALSE); - return converted; + const guint8 *array; + gsize length; + GString * str; + int i; + unsigned char c; + char * converted = NULL; + + g_return_val_if_fail(value != NULL, NULL); + + array = g_variant_get_fixed_array(value, &length, 1); + + /* Since the DHCP options come through environment variables, they should + * already be UTF-8 safe, but just make sure. + */ + str = g_string_sized_new(length); + for (i = 0; i < length; i++) { + c = array[i]; + + /* Convert NULLs to spaces and non-ASCII characters to ? */ + if (c == '\0') + c = ' '; + else if (c > 127) + c = '?'; + str = g_string_append_c(str, c); + } + str = g_string_append_c(str, '\0'); + + converted = str->str; + if (!g_utf8_validate(converted, -1, NULL)) + _LOGW("option '%s' couldn't be converted to UTF-8", key); + g_string_free(str, FALSE); + return converted; } static int -label_is_unknown_xyz (const char *label) +label_is_unknown_xyz(const char *label) { - if (!NM_STR_HAS_PREFIX (label, "unknown_")) - return -EINVAL; + if (!NM_STR_HAS_PREFIX(label, "unknown_")) + return -EINVAL; - label += NM_STRLEN ("unknown_"); - if ( label[0] != '2' - || !g_ascii_isdigit (label[1]) - || !g_ascii_isdigit (label[2]) - || label[3] != '\0') - return -EINVAL; + label += NM_STRLEN("unknown_"); + if (label[0] != '2' || !g_ascii_isdigit(label[1]) || !g_ascii_isdigit(label[2]) + || label[3] != '\0') + return -EINVAL; - return _nm_utils_ascii_str_to_int64 (label, 10, 224, 254, -EINVAL); + return _nm_utils_ascii_str_to_int64(label, 10, 224, 254, -EINVAL); } - #define OLD_TAG "old_" #define NEW_TAG "new_" static void -maybe_add_option (NMDhcpClient *self, - GHashTable *hash, - const char *key, - GVariant *value) +maybe_add_option(NMDhcpClient *self, GHashTable *hash, const char *key, GVariant *value) { - char *str_value = NULL; - - g_return_if_fail (g_variant_is_of_type (value, G_VARIANT_TYPE_BYTESTRING)); - - if (g_str_has_prefix (key, OLD_TAG)) - return; - - /* Filter out stuff that's not actually new DHCP options */ - if (NM_IN_STRSET (key, "interface", - "pid", - "reason", - "dhcp_message_type")) - return; - - if (NM_STR_HAS_PREFIX (key, NEW_TAG)) - key += NM_STRLEN (NEW_TAG); - if (NM_STR_HAS_PREFIX (key, "private_") || !key[0]) - return; - - str_value = bytearray_variant_to_string (self, value, key); - if (str_value) { - int priv_opt_num; - - g_hash_table_insert (hash, g_strdup (key), str_value); - - /* dhclient has no special labels for private dhcp options: it uses "unknown_xyz" - * labels for that. We need to identify those to alias them to our "private_xyz" - * format unsed in the internal dchp plugins. - */ - if ((priv_opt_num = label_is_unknown_xyz (key)) > 0) { - gs_free guint8 *check_val = NULL; - char *hex_str = NULL; - gsize len; - - /* dhclient passes values from dhcp private options in its own "string" format: - * if the raw values are printable as ascii strings, it will pass the string - * representation; if the values are not printable as an ascii string, it will - * pass a string displaying the hex values (hex string). Try to enforce passing - * always an hex string, converting string representation if needed. - */ - check_val = nm_utils_hexstr2bin_alloc (str_value, FALSE, TRUE, ":", 0, &len); - hex_str = nm_utils_bin2hexstr_full (check_val ?: (guint8 *) str_value, - check_val ? len : strlen (str_value), - ':', FALSE, NULL); - g_hash_table_insert (hash, - g_strdup_printf ("private_%d", priv_opt_num), - hex_str); - } - } + char *str_value = NULL; + + g_return_if_fail(g_variant_is_of_type(value, G_VARIANT_TYPE_BYTESTRING)); + + if (g_str_has_prefix(key, OLD_TAG)) + return; + + /* Filter out stuff that's not actually new DHCP options */ + if (NM_IN_STRSET(key, "interface", "pid", "reason", "dhcp_message_type")) + return; + + if (NM_STR_HAS_PREFIX(key, NEW_TAG)) + key += NM_STRLEN(NEW_TAG); + if (NM_STR_HAS_PREFIX(key, "private_") || !key[0]) + return; + + str_value = bytearray_variant_to_string(self, value, key); + if (str_value) { + int priv_opt_num; + + g_hash_table_insert(hash, g_strdup(key), str_value); + + /* dhclient has no special labels for private dhcp options: it uses "unknown_xyz" + * labels for that. We need to identify those to alias them to our "private_xyz" + * format unused in the internal dchp plugins. + */ + if ((priv_opt_num = label_is_unknown_xyz(key)) > 0) { + gs_free guint8 *check_val = NULL; + char * hex_str = NULL; + gsize len; + + /* dhclient passes values from dhcp private options in its own "string" format: + * if the raw values are printable as ascii strings, it will pass the string + * representation; if the values are not printable as an ascii string, it will + * pass a string displaying the hex values (hex string). Try to enforce passing + * always an hex string, converting string representation if needed. + */ + check_val = nm_utils_hexstr2bin_alloc(str_value, FALSE, TRUE, ":", 0, &len); + hex_str = nm_utils_bin2hexstr_full(check_val ?: (guint8 *) str_value, + check_val ? len : strlen(str_value), + ':', + FALSE, + NULL); + g_hash_table_insert(hash, g_strdup_printf("private_%d", priv_opt_num), hex_str); + } + } } void -nm_dhcp_client_emit_ipv6_prefix_delegated (NMDhcpClient *self, - const NMPlatformIP6Address *prefix) +nm_dhcp_client_emit_ipv6_prefix_delegated(NMDhcpClient *self, const NMPlatformIP6Address *prefix) +{ + g_signal_emit(G_OBJECT(self), signals[SIGNAL_PREFIX_DELEGATED], 0, prefix); +} + +gboolean +nm_dhcp_client_handle_event(gpointer unused, + const char * iface, + int pid, + GVariant * options, + const char * reason, + NMDhcpClient *self) { - g_signal_emit (G_OBJECT (self), - signals[SIGNAL_PREFIX_DELEGATED], 0, - prefix); + NMDhcpClientPrivate *priv; + guint32 old_state; + guint32 new_state; + gs_unref_hashtable GHashTable *str_options = NULL; + gs_unref_object NMIPConfig *ip_config = NULL; + NMPlatformIP6Address prefix = { + 0, + }; + + g_return_val_if_fail(NM_IS_DHCP_CLIENT(self), FALSE); + g_return_val_if_fail(iface != NULL, FALSE); + g_return_val_if_fail(pid > 0, FALSE); + g_return_val_if_fail(g_variant_is_of_type(options, G_VARIANT_TYPE_VARDICT), FALSE); + g_return_val_if_fail(reason != NULL, FALSE); + + priv = NM_DHCP_CLIENT_GET_PRIVATE(self); + + if (g_strcmp0(priv->iface, iface) != 0) + return FALSE; + if (priv->pid != pid) + return FALSE; + + old_state = priv->state; + new_state = reason_to_state(self, priv->iface, reason); + _LOGD("DHCP state '%s' -> '%s' (reason: '%s')", + state_to_string(old_state), + state_to_string(new_state), + reason); + + if (NM_IN_SET(new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED)) { + 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); + g_variant_iter_init(&iter, options); + while (g_variant_iter_next(&iter, "{&sv}", &name, &value)) { + maybe_add_option(self, str_options, name, value); + g_variant_unref(value); + } + + /* 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)); + } 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, + str_options, + priv->info_only)); + } + } else + g_warn_if_reached(); + } + + if (!IN6_IS_ADDR_UNSPECIFIED(&prefix.address)) { + /* If we got an IPv6 prefix to delegate, we don't change the state + * 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); + } + + nm_dhcp_client_set_state(self, new_state, ip_config, str_options); + } + + return TRUE; } gboolean -nm_dhcp_client_handle_event (gpointer unused, - const char *iface, - int pid, - GVariant *options, - const char *reason, - NMDhcpClient *self) +nm_dhcp_client_server_id_is_rejected(NMDhcpClient *self, gconstpointer addr) { - NMDhcpClientPrivate *priv; - guint32 old_state; - guint32 new_state; - gs_unref_hashtable GHashTable *str_options = NULL; - gs_unref_object NMIPConfig *ip_config = NULL; - NMPlatformIP6Address prefix = { 0, }; - - g_return_val_if_fail (NM_IS_DHCP_CLIENT (self), FALSE); - g_return_val_if_fail (iface != NULL, FALSE); - g_return_val_if_fail (pid > 0, FALSE); - g_return_val_if_fail (g_variant_is_of_type (options, G_VARIANT_TYPE_VARDICT), FALSE); - g_return_val_if_fail (reason != NULL, FALSE); - - priv = NM_DHCP_CLIENT_GET_PRIVATE (self); - - if (g_strcmp0 (priv->iface, iface) != 0) - return FALSE; - if (priv->pid != pid) - return FALSE; - - old_state = priv->state; - new_state = reason_to_state (self, priv->iface, reason); - _LOGD ("DHCP state '%s' -> '%s' (reason: '%s')", - state_to_string (old_state), state_to_string (new_state), reason); - - if (NM_IN_SET (new_state, NM_DHCP_STATE_BOUND, NM_DHCP_STATE_EXTENDED)) { - 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); - g_variant_iter_init (&iter, options); - while (g_variant_iter_next (&iter, "{&sv}", &name, &value)) { - maybe_add_option (self, str_options, name, value); - g_variant_unref (value); - } - - /* 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)); - } 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, - str_options, - priv->info_only)); - } - } else - g_warn_if_reached (); - } - - if (!IN6_IS_ADDR_UNSPECIFIED (&prefix.address)) { - /* If we got an IPv6 prefix to delegate, we don't change the state - * 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); - } - - nm_dhcp_client_set_state (self, new_state, ip_config, str_options); - } - - return TRUE; + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); + in_addr_t addr4 = *(in_addr_t *) addr; + guint i; + + /* IPv6 not implemented yet */ + nm_assert(priv->addr_family == AF_INET); + + if (!priv->reject_servers || !priv->reject_servers[0]) + return FALSE; + + for (i = 0; priv->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], + NULL, + &r_addr, + &r_prefix)) + nm_assert_not_reached(); + mask = _nm_utils_ip4_prefix_to_netmask(r_prefix < 0 ? 32 : r_prefix); + if ((addr4 & mask) == (r_addr & mask)) + return TRUE; + } + + return FALSE; } /*****************************************************************************/ static void -get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) +get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { - NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (object); - - 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; - } + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(object); + + 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; + } } static void -set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) +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 ((flags & ~((guint) (NM_DHCP_CLIENT_FLAGS_INFO_ONLY | NM_DHCP_CLIENT_FLAGS_USE_FQDN))) == 0); - priv->info_only = NM_FLAGS_HAS (flags, NM_DHCP_CLIENT_FLAGS_INFO_ONLY); - priv->use_fqdn = NM_FLAGS_HAS (flags, NM_DHCP_CLIENT_FLAGS_USE_FQDN); - 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_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; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + 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( + (flags & ~((guint)(NM_DHCP_CLIENT_FLAGS_INFO_ONLY | NM_DHCP_CLIENT_FLAGS_USE_FQDN))) + == 0); + priv->info_only = NM_FLAGS_HAS(flags, NM_DHCP_CLIENT_FLAGS_INFO_ONLY); + priv->use_fqdn = NM_FLAGS_HAS(flags, NM_DHCP_CLIENT_FLAGS_USE_FQDN); + 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_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: + /* construct-only */ + priv->reject_servers = nm_utils_strv_dup_packed(g_value_get_boxed(value), -1); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec); + break; + } } /*****************************************************************************/ static void -nm_dhcp_client_init (NMDhcpClient *self) +nm_dhcp_client_init(NMDhcpClient *self) { - NMDhcpClientPrivate *priv; + NMDhcpClientPrivate *priv; - priv = G_TYPE_INSTANCE_GET_PRIVATE (self, NM_TYPE_DHCP_CLIENT, NMDhcpClientPrivate); - self->_priv = priv; + priv = G_TYPE_INSTANCE_GET_PRIVATE(self, NM_TYPE_DHCP_CLIENT, NMDhcpClientPrivate); + self->_priv = priv; - c_list_init (&self->dhcp_client_lst); + c_list_init(&self->dhcp_client_lst); - priv->pid = -1; + priv->pid = -1; } static void -dispose (GObject *object) +dispose(GObject *object) { - NMDhcpClient *self = NM_DHCP_CLIENT (object); - NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE (self); + NMDhcpClient * self = NM_DHCP_CLIENT(object); + NMDhcpClientPrivate *priv = NM_DHCP_CLIENT_GET_PRIVATE(self); - /* Stopping the client is left up to the controlling device - * explicitly since we may want to quit NetworkManager but not terminate - * the DHCP client. - */ + /* Stopping the client is left up to the controlling device + * explicitly since we may want to quit NetworkManager but not terminate + * the DHCP client. + */ - nm_assert (c_list_is_empty (&self->dhcp_client_lst)); + nm_assert(c_list_is_empty(&self->dhcp_client_lst)); - watch_cleanup (self); - timeout_cleanup (self); + 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->mud_url); - 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_g_free(&priv->iface); + nm_clear_g_free(&priv->hostname); + nm_clear_g_free(&priv->uuid); + 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); - G_OBJECT_CLASS (nm_dhcp_client_parent_class)->dispose (object); + G_OBJECT_CLASS(nm_dhcp_client_parent_class)->dispose(object); - priv->multi_idx = nm_dedup_multi_index_unref (priv->multi_idx); + priv->multi_idx = nm_dedup_multi_index_unref(priv->multi_idx); } static void -nm_dhcp_client_class_init (NMDhcpClientClass *client_class) +nm_dhcp_client_class_init(NMDhcpClientClass *client_class) { - GObjectClass *object_class = G_OBJECT_CLASS (client_class); - - g_type_class_add_private (client_class, sizeof (NMDhcpClientPrivate)); - - object_class->dispose = dispose; - object_class->get_property = get_property; - 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, "", "", - 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_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); - - g_object_class_install_properties (object_class, _PROPERTY_ENUMS_LAST, obj_properties); - - signals[SIGNAL_STATE_CHANGED] = - g_signal_new (NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 4, G_TYPE_UINT, G_TYPE_OBJECT, G_TYPE_HASH_TABLE, G_TYPE_STRING); - - signals[SIGNAL_PREFIX_DELEGATED] = - g_signal_new (NM_DHCP_CLIENT_SIGNAL_PREFIX_DELEGATED, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, G_TYPE_POINTER); + GObjectClass *object_class = G_OBJECT_CLASS(client_class); + + g_type_class_add_private(client_class, sizeof(NMDhcpClientPrivate)); + + object_class->dispose = dispose; + object_class->get_property = get_property; + 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, + "", + "", + 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_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_STATE_CHANGED] = g_signal_new(NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 3, + G_TYPE_UINT, + G_TYPE_OBJECT, + G_TYPE_HASH_TABLE); + + signals[SIGNAL_PREFIX_DELEGATED] = g_signal_new(NM_DHCP_CLIENT_SIGNAL_PREFIX_DELEGATED, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_FIRST, + 0, + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, + G_TYPE_POINTER); } diff --git a/src/dhcp/nm-dhcp-client.h b/src/dhcp/nm-dhcp-client.h index 479ea000..05faa9ea 100644 --- a/src/dhcp/nm-dhcp-client.h +++ b/src/dhcp/nm-dhcp-client.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2005 - 2010 Red Hat, Inc. */ @@ -15,209 +15,210 @@ #define NM_DHCP_TIMEOUT_DEFAULT ((guint32) 45) /* default DHCP timeout, in seconds */ #define NM_DHCP_TIMEOUT_INFINITY ((guint32) G_MAXINT32) -#define NM_TYPE_DHCP_CLIENT (nm_dhcp_client_get_type ()) -#define NM_DHCP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DHCP_CLIENT, NMDhcpClient)) -#define NM_DHCP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DHCP_CLIENT, NMDhcpClientClass)) -#define NM_IS_DHCP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DHCP_CLIENT)) -#define NM_IS_DHCP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DHCP_CLIENT)) -#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_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_SIGNAL_STATE_CHANGED "state-changed" +#define NM_TYPE_DHCP_CLIENT (nm_dhcp_client_get_type()) +#define NM_DHCP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DHCP_CLIENT, NMDhcpClient)) +#define NM_DHCP_CLIENT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DHCP_CLIENT, NMDhcpClientClass)) +#define NM_IS_DHCP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DHCP_CLIENT)) +#define NM_IS_DHCP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DHCP_CLIENT)) +#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_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_SIGNAL_STATE_CHANGED "state-changed" #define NM_DHCP_CLIENT_SIGNAL_PREFIX_DELEGATED "prefix-delegated" typedef enum { - NM_DHCP_STATE_UNKNOWN = 0, - NM_DHCP_STATE_BOUND, /* new lease */ - NM_DHCP_STATE_EXTENDED, /* lease extended */ - NM_DHCP_STATE_TIMEOUT, /* timed out contacting server */ - NM_DHCP_STATE_DONE, /* client quit or stopped */ - NM_DHCP_STATE_EXPIRE, /* lease expired or NAKed */ - NM_DHCP_STATE_FAIL, /* failed for some reason */ - NM_DHCP_STATE_TERMINATED, /* client is no longer running */ - __NM_DHCP_STATE_MAX, - NM_DHCP_STATE_MAX = __NM_DHCP_STATE_MAX - 1, + NM_DHCP_STATE_UNKNOWN = 0, + NM_DHCP_STATE_BOUND, /* new lease */ + NM_DHCP_STATE_EXTENDED, /* lease extended */ + NM_DHCP_STATE_TIMEOUT, /* timed out contacting server */ + NM_DHCP_STATE_DONE, /* client quit or stopped */ + NM_DHCP_STATE_EXPIRE, /* lease expired or NAKed */ + NM_DHCP_STATE_FAIL, /* failed for some reason */ + NM_DHCP_STATE_TERMINATED, /* client is no longer running */ + __NM_DHCP_STATE_MAX, + NM_DHCP_STATE_MAX = __NM_DHCP_STATE_MAX - 1, } NMDhcpState; struct _NMDhcpClientPrivate; typedef struct { - GObject parent; - struct _NMDhcpClientPrivate *_priv; - CList dhcp_client_lst; + GObject parent; + struct _NMDhcpClientPrivate *_priv; + CList dhcp_client_lst; } NMDhcpClient; typedef enum { - NM_DHCP_CLIENT_FLAGS_INFO_ONLY = (1LL << 0), - NM_DHCP_CLIENT_FLAGS_USE_FQDN = (1LL << 1), + NM_DHCP_CLIENT_FLAGS_INFO_ONLY = (1LL << 0), + NM_DHCP_CLIENT_FLAGS_USE_FQDN = (1LL << 1), } NMDhcpClientFlags; typedef struct { - GObjectClass parent; - - gboolean (*ip4_start) (NMDhcpClient *self, - const char *anycast_addr, - const char *last_ip4_address, - GError **error); - - gboolean (*accept) (NMDhcpClient *self, - GError **error); - - gboolean (*decline) (NMDhcpClient *self, - const char *error_message, - GError **error); - - gboolean (*ip6_start) (NMDhcpClient *self, - const char *anycast_addr, - const struct in6_addr *ll_addr, - NMSettingIP6ConfigPrivacy privacy, - guint needed_prefixes, - GError **error); - - void (*stop) (NMDhcpClient *self, - gboolean release); - - /** - * get_duid: - * @self: the #NMDhcpClient - * - * Attempts to find an existing DHCPv6 DUID for this client in the DHCP - * client's persistent configuration. Returned DUID should be the binary - * representation of the DUID. If no DUID is found, %NULL should be - * returned. - */ - GBytes *(*get_duid) (NMDhcpClient *self); + GObjectClass parent; + + gboolean (*ip4_start)(NMDhcpClient *self, + const char * anycast_addr, + const char * last_ip4_address, + GError ** error); + + gboolean (*accept)(NMDhcpClient *self, GError **error); + + gboolean (*decline)(NMDhcpClient *self, const char *error_message, GError **error); + + gboolean (*ip6_start)(NMDhcpClient * self, + const char * anycast_addr, + const struct in6_addr * ll_addr, + NMSettingIP6ConfigPrivacy privacy, + guint needed_prefixes, + GError ** error); + + void (*stop)(NMDhcpClient *self, gboolean release); + + /** + * get_duid: + * @self: the #NMDhcpClient + * + * Attempts to find an existing DHCPv6 DUID for this client in the DHCP + * client's persistent configuration. Returned DUID should be the binary + * representation of the DUID. If no DUID is found, %NULL should be + * returned. + */ + GBytes *(*get_duid)(NMDhcpClient *self); } NMDhcpClientClass; -GType nm_dhcp_client_get_type (void); +GType nm_dhcp_client_get_type(void); -struct _NMDedupMultiIndex *nm_dhcp_client_get_multi_idx (NMDhcpClient *self); +struct _NMDedupMultiIndex *nm_dhcp_client_get_multi_idx(NMDhcpClient *self); -pid_t nm_dhcp_client_get_pid (NMDhcpClient *self); +pid_t nm_dhcp_client_get_pid(NMDhcpClient *self); -int nm_dhcp_client_get_addr_family (NMDhcpClient *self); +int nm_dhcp_client_get_addr_family(NMDhcpClient *self); -const char *nm_dhcp_client_get_iface (NMDhcpClient *self); +const char *nm_dhcp_client_get_iface(NMDhcpClient *self); -int nm_dhcp_client_get_ifindex (NMDhcpClient *self); +int nm_dhcp_client_get_ifindex(NMDhcpClient *self); -const char *nm_dhcp_client_get_uuid (NMDhcpClient *self); +const char *nm_dhcp_client_get_uuid(NMDhcpClient *self); -GBytes *nm_dhcp_client_get_duid (NMDhcpClient *self); +GBytes *nm_dhcp_client_get_duid(NMDhcpClient *self); -GBytes *nm_dhcp_client_get_hw_addr (NMDhcpClient *self); +GBytes *nm_dhcp_client_get_hw_addr(NMDhcpClient *self); -GBytes *nm_dhcp_client_get_broadcast_hw_addr (NMDhcpClient *self); +GBytes *nm_dhcp_client_get_broadcast_hw_addr(NMDhcpClient *self); -guint32 nm_dhcp_client_get_route_table (NMDhcpClient *self); +guint32 nm_dhcp_client_get_route_table(NMDhcpClient *self); -void nm_dhcp_client_set_route_table (NMDhcpClient *self, guint32 route_table); +void nm_dhcp_client_set_route_table(NMDhcpClient *self, guint32 route_table); -guint32 nm_dhcp_client_get_route_metric (NMDhcpClient *self); +guint32 nm_dhcp_client_get_route_metric(NMDhcpClient *self); -void nm_dhcp_client_set_route_metric (NMDhcpClient *self, guint32 route_metric); +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_timeout(NMDhcpClient *self); -guint32 nm_dhcp_client_get_iaid (NMDhcpClient *self); +guint32 nm_dhcp_client_get_iaid(NMDhcpClient *self); -gboolean nm_dhcp_client_get_iaid_explicit (NMDhcpClient *self); +gboolean nm_dhcp_client_get_iaid_explicit(NMDhcpClient *self); -GBytes *nm_dhcp_client_get_client_id (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 * 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); +NMDhcpHostnameFlags nm_dhcp_client_get_hostname_flags(NMDhcpClient *self); -gboolean nm_dhcp_client_get_info_only (NMDhcpClient *self); +gboolean nm_dhcp_client_get_info_only(NMDhcpClient *self); -gboolean nm_dhcp_client_get_use_fqdn (NMDhcpClient *self); +gboolean nm_dhcp_client_get_use_fqdn(NMDhcpClient *self); -gboolean nm_dhcp_client_start_ip4 (NMDhcpClient *self, - GBytes *client_id, - const char *dhcp_anycast_addr, - const char *last_ip4_address, - GError **error); +GBytes *nm_dhcp_client_get_vendor_class_identifier(NMDhcpClient *self); -gboolean nm_dhcp_client_start_ip6 (NMDhcpClient *self, - GBytes *client_id, - gboolean enforce_duid, - const char *dhcp_anycast_addr, - const struct in6_addr *ll_addr, - NMSettingIP6ConfigPrivacy privacy, - guint needed_prefixes, - GError **error); +gboolean nm_dhcp_client_start_ip4(NMDhcpClient *self, + GBytes * client_id, + const char * dhcp_anycast_addr, + const char * last_ip4_address, + GError ** error); -gboolean nm_dhcp_client_accept (NMDhcpClient *self, - GError **error); +gboolean nm_dhcp_client_start_ip6(NMDhcpClient * self, + GBytes * client_id, + gboolean enforce_duid, + const char * dhcp_anycast_addr, + const struct in6_addr * ll_addr, + NMSettingIP6ConfigPrivacy privacy, + guint needed_prefixes, + GError ** error); -gboolean nm_dhcp_client_decline (NMDhcpClient *self, - const char *error_message, - GError **error); +gboolean nm_dhcp_client_accept(NMDhcpClient *self, GError **error); -void nm_dhcp_client_stop (NMDhcpClient *self, gboolean release); +gboolean nm_dhcp_client_decline(NMDhcpClient *self, const char *error_message, GError **error); + +void nm_dhcp_client_stop(NMDhcpClient *self, gboolean release); /* Backend helpers for subclasses */ -void nm_dhcp_client_stop_existing (const char *pid_file, const char *binary_name); +void nm_dhcp_client_stop_existing(const char *pid_file, const char *binary_name); + +void nm_dhcp_client_stop_pid(pid_t pid, const char *iface); -void nm_dhcp_client_stop_pid (pid_t pid, const char *iface); +void nm_dhcp_client_start_timeout(NMDhcpClient *self); -void nm_dhcp_client_start_timeout (NMDhcpClient *self); +void nm_dhcp_client_watch_child(NMDhcpClient *self, pid_t pid); -void nm_dhcp_client_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, - NMIPConfig *ip_config, - GHashTable *options); /* str:str hash */ +gboolean nm_dhcp_client_handle_event(gpointer unused, + const char * iface, + int pid, + GVariant * options, + const char * reason, + NMDhcpClient *self); -gboolean nm_dhcp_client_handle_event (gpointer unused, - const char *iface, - int pid, - GVariant *options, - 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_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); -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); /***************************************************************************** * Client data *****************************************************************************/ typedef struct { - GType (*get_type) (void); - GType (*get_type_per_addr_family) (int addr_family); - const char *name; - const char *(*get_path) (void); - bool experimental:1; + GType (*get_type)(void); + GType (*get_type_per_addr_family)(int addr_family); + const char *name; + const char *(*get_path)(void); + bool experimental : 1; } NMDhcpClientFactory; -GType nm_dhcp_nettools_get_type (void); +GType nm_dhcp_nettools_get_type(void); extern const NMDhcpClientFactory _nm_dhcp_client_factory_dhcpcanon; extern const NMDhcpClientFactory _nm_dhcp_client_factory_dhclient; diff --git a/src/dhcp/nm-dhcp-dhclient-utils.c b/src/dhcp/nm-dhcp-dhclient-utils.c index 76fc1a89..f0eed6f5 100644 --- a/src/dhcp/nm-dhcp-dhclient-utils.c +++ b/src/dhcp/nm-dhcp-dhclient-utils.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2011 Red Hat, Inc. */ @@ -19,702 +19,695 @@ #include "platform/nm-platform.h" #include "NetworkManagerUtils.h" -#define TIMEOUT_TAG "timeout " -#define RETRY_TAG "retry " -#define CLIENTID_TAG "send dhcp-client-identifier" +#define TIMEOUT_TAG "timeout " +#define RETRY_TAG "retry " +#define CLIENTID_TAG "send dhcp-client-identifier" #define HOSTNAME4_TAG "send host-name" #define HOSTNAME4_FORMAT HOSTNAME4_TAG " \"%s\"; # added by NetworkManager" -#define FQDN_TAG_PREFIX "send fqdn." -#define FQDN_TAG FQDN_TAG_PREFIX "fqdn" -#define FQDN_FORMAT FQDN_TAG " \"%s\"; # added by NetworkManager" +#define FQDN_TAG_PREFIX "send fqdn." +#define FQDN_TAG FQDN_TAG_PREFIX "fqdn" +#define FQDN_FORMAT FQDN_TAG " \"%s\"; # added by NetworkManager" #define ALSOREQ_TAG "also request " -#define REQ_TAG "request " +#define REQ_TAG "request " -#define MUDURLv4_DEF "option mudurl code 161 = text;\n" -#define MUDURLv4_FMT "send mudurl \"%s\";\n" - -#define MUDURLv6_DEF "option dhcp6.mudurl code 112 = text;\n" -#define MUDURLv6_FMT "send dhcp6.mudurl \"%s\";\n" +#define MUDURLv4_DEF "option mudurl code 161 = text;\n" +#define MUDURLv4_FMT "send mudurl \"%s\";\n" +#define MUDURLv6_DEF "option dhcp6.mudurl code 112 = text;\n" +#define MUDURLv6_FMT "send dhcp6.mudurl \"%s\";\n" static void -add_request (GPtrArray *array, const char *item) +add_request(GPtrArray *array, const char *item) { - guint i; + guint i; - for (i = 0; i < array->len; i++) { - if (nm_streq (array->pdata[i], item)) - return; - } - g_ptr_array_add (array, g_strdup (item)); + for (i = 0; i < array->len; i++) { + if (nm_streq(array->pdata[i], item)) + return; + } + g_ptr_array_add(array, g_strdup(item)); } static gboolean -grab_request_options (GPtrArray *store, const char* line) +grab_request_options(GPtrArray *store, const char *line) { - gs_free const char **line_v = NULL; - gsize i; - - /* Grab each 'request' or 'also request' option and save for later */ - line_v = nm_utils_strsplit_set (line, "\t ,"); - for (i = 0; line_v && line_v[i]; i++) { - const char *ss = nm_str_skip_leading_spaces (line_v[i]); - gsize l; - gboolean end = FALSE; - - if (!ss[0]) - continue; - if (ss[0] == ';') { - /* all done */ - return TRUE; - } - - if (!g_ascii_isalnum (ss[0])) - continue; - - l = strlen (ss); - - while ( l > 0 - && g_ascii_isspace (ss[l - 1])) { - ((char *) ss)[l - 1] = '\0'; - l--; - } - if ( l > 0 - && ss[l - 1] == ';') { - /* Remove the EOL marker */ - ((char *) ss)[l - 1] = '\0'; - end = TRUE; - } - - if (ss[0]) - add_request (store, ss); - - if (end) - return TRUE; - } - - return FALSE; + gs_free const char **line_v = NULL; + gsize i; + + /* Grab each 'request' or 'also request' option and save for later */ + line_v = nm_utils_strsplit_set(line, "\t ,"); + for (i = 0; line_v && line_v[i]; i++) { + const char *ss = nm_str_skip_leading_spaces(line_v[i]); + gsize l; + gboolean end = FALSE; + + if (!ss[0]) + continue; + if (ss[0] == ';') { + /* all done */ + return TRUE; + } + + if (!g_ascii_isalnum(ss[0])) + continue; + + l = strlen(ss); + + while (l > 0 && g_ascii_isspace(ss[l - 1])) { + ((char *) ss)[l - 1] = '\0'; + l--; + } + if (l > 0 && ss[l - 1] == ';') { + /* Remove the EOL marker */ + ((char *) ss)[l - 1] = '\0'; + end = TRUE; + } + + if (ss[0]) + add_request(store, ss); + + if (end) + return TRUE; + } + + return FALSE; } static void -add_ip4_config (GString *str, - GBytes *client_id, - const char *hostname, - gboolean use_fqdn, - NMDhcpHostnameFlags hostname_flags) +add_ip4_config(GString * str, + GBytes * client_id, + const char * hostname, + gboolean use_fqdn, + NMDhcpHostnameFlags hostname_flags) { - if (client_id) { - const char *p; - gsize l; - guint i; - - p = g_bytes_get_data (client_id, &l); - nm_assert (p); - - /* Allow type 0 (non-hardware address) to be represented as a string - * as long as all the characters are printable. - */ - for (i = 1; (p[0] == 0) && i < l; i++) { - if (!g_ascii_isprint (p[i]) || p[i] == '\\' || p[i] == '"') - break; - } - - g_string_append (str, CLIENTID_TAG " "); - if (i < l) { - /* Unprintable; convert to a hex string */ - for (i = 0; i < l; i++) { - if (i > 0) - g_string_append_c (str, ':'); - g_string_append_printf (str, "%02x", (guint8) p[i]); - } - } else { - /* Printable; just add to the line with type 0 */ - g_string_append_c (str, '"'); - g_string_append (str, "\\x00"); - g_string_append_len (str, p + 1, l - 1); - g_string_append_c (str, '"'); - } - g_string_append (str, "; # added by NetworkManager\n"); - } - - if (hostname) { - if (use_fqdn) { - g_string_append_printf (str, FQDN_FORMAT "\n", hostname); - - g_string_append_printf (str, FQDN_TAG_PREFIX "encoded %s;\n", - (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED) - ? "on" - : "off"); - - g_string_append_printf (str, FQDN_TAG_PREFIX "server-update %s;\n", - (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE) - ? "on" - : "off"); - - g_string_append_printf (str, FQDN_TAG_PREFIX "no-client-update %s;\n", - (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE) - ? "on" - : "off"); - } else - g_string_append_printf (str, HOSTNAME4_FORMAT "\n", hostname); - } - - g_string_append_c (str, '\n'); - - /* Define options for classless static routes */ - g_string_append (str, - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n"); - g_string_append (str, - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n"); - /* Web Proxy Auto-Discovery option (bgo #368423) */ - g_string_append (str, "option wpad code 252 = string;\n"); - - g_string_append_c (str, '\n'); + if (client_id) { + const char *p; + gsize l; + guint i; + + p = g_bytes_get_data(client_id, &l); + nm_assert(p); + + /* Allow type 0 (non-hardware address) to be represented as a string + * as long as all the characters are printable. + */ + for (i = 1; (p[0] == 0) && i < l; i++) { + if (!g_ascii_isprint(p[i]) || p[i] == '\\' || p[i] == '"') + break; + } + + g_string_append(str, CLIENTID_TAG " "); + if (i < l) { + /* Unprintable; convert to a hex string */ + for (i = 0; i < l; i++) { + if (i > 0) + g_string_append_c(str, ':'); + g_string_append_printf(str, "%02x", (guint8) p[i]); + } + } else { + /* Printable; just add to the line with type 0 */ + g_string_append_c(str, '"'); + g_string_append(str, "\\x00"); + g_string_append_len(str, p + 1, l - 1); + g_string_append_c(str, '"'); + } + g_string_append(str, "; # added by NetworkManager\n"); + } + + if (hostname) { + if (use_fqdn) { + g_string_append_printf(str, FQDN_FORMAT "\n", hostname); + + g_string_append_printf(str, + FQDN_TAG_PREFIX "encoded %s;\n", + (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED) ? "on" + : "off"); + + g_string_append_printf( + str, + FQDN_TAG_PREFIX "server-update %s;\n", + (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE) ? "on" : "off"); + + g_string_append_printf(str, + FQDN_TAG_PREFIX "no-client-update %s;\n", + (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE) ? "on" + : "off"); + } else + g_string_append_printf(str, HOSTNAME4_FORMAT "\n", hostname); + } + + g_string_append_c(str, '\n'); + + /* Define options for classless static routes */ + g_string_append( + str, + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n"); + g_string_append(str, + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n"); + /* Web Proxy Auto-Discovery option (bgo #368423) */ + g_string_append(str, "option wpad code 252 = string;\n"); + + g_string_append_c(str, '\n'); } static void -add_hostname6 (GString *str, - const char *hostname, - NMDhcpHostnameFlags hostname_flags) +add_hostname6(GString *str, const char *hostname, NMDhcpHostnameFlags hostname_flags) { - if (hostname) { - g_string_append_printf (str, FQDN_FORMAT "\n", hostname); - if (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE) - g_string_append (str, FQDN_TAG_PREFIX "server-update on;\n"); - if (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE) - g_string_append (str, FQDN_TAG_PREFIX "no-client-update on;\n"); - g_string_append_c (str, '\n'); - } + if (hostname) { + g_string_append_printf(str, FQDN_FORMAT "\n", hostname); + if (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE) + g_string_append(str, FQDN_TAG_PREFIX "server-update on;\n"); + if (hostname_flags & NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE) + g_string_append(str, FQDN_TAG_PREFIX "no-client-update on;\n"); + g_string_append_c(str, '\n'); + } } -static void add_mud_url_config(GString *str, const char *mud_url, int addr_family) +static void +add_mud_url_config(GString *str, const char *mud_url, int addr_family) { - if (mud_url) { - if (addr_family == AF_INET) { - g_string_append (str, MUDURLv4_DEF); - g_string_append_printf (str, MUDURLv4_FMT, mud_url); - } else { - g_string_append (str, MUDURLv6_DEF); - g_string_append_printf (str, MUDURLv6_FMT, mud_url); - } - } + if (mud_url) { + if (addr_family == AF_INET) { + g_string_append(str, MUDURLv4_DEF); + g_string_append_printf(str, MUDURLv4_FMT, mud_url); + } else { + g_string_append(str, MUDURLv6_DEF); + g_string_append_printf(str, MUDURLv6_FMT, mud_url); + } + } } static GBytes * -read_client_id (const char *str) +read_client_id(const char *str) { - gs_free char *s = NULL; - char *p; - int i = 0, j = 0; - - nm_assert (!strncmp (str, CLIENTID_TAG, NM_STRLEN (CLIENTID_TAG))); - str += NM_STRLEN (CLIENTID_TAG); - - if (!g_ascii_isspace (*str)) - return NULL; - while (g_ascii_isspace (*str)) - str++; - - if (*str == '"') { - /* Parse string literal with escape sequences */ - s = g_strdup (str + 1); - p = strrchr (s, '"'); - if (p) - *p = '\0'; - else - return NULL; - - if (!s[0]) - return NULL; - - while (s[i]) { - if ( s[i] == '\\' - && s[i + 1] == 'x' - && g_ascii_isxdigit (s[i + 2]) - && g_ascii_isxdigit (s[i + 3])) { - s[j++] = (g_ascii_xdigit_value (s[i + 2]) << 4) - + g_ascii_xdigit_value (s[i + 3]); - i += 4; - continue; - } - if ( s[i] == '\\' - && s[i + 1] >= '0' && s[i + 1] <= '7' - && s[1 + 2] >= '0' && s[i + 2] <= '7' - && s[1 + 3] >= '0' && s[i + 3] <= '7') { - s[j++] = ((s[i + 1] - '0') << 6) - + ((s[i + 2] - '0') << 3) - + ( s[i + 3] - '0'); - i += 4; - continue; - } - s[j++] = s[i++]; - } - return g_bytes_new_take (g_steal_pointer (&s), j); - } - - /* Otherwise, try to read a hexadecimal sequence */ - s = g_strdup (str); - g_strchomp (s); - if (s[strlen (s) - 1] == ';') - s[strlen (s) - 1] = '\0'; - - return nm_utils_hexstr2bin (s); + gs_free char *s = NULL; + char * p; + int i = 0, j = 0; + + nm_assert(!strncmp(str, CLIENTID_TAG, NM_STRLEN(CLIENTID_TAG))); + str += NM_STRLEN(CLIENTID_TAG); + + if (!g_ascii_isspace(*str)) + return NULL; + while (g_ascii_isspace(*str)) + str++; + + if (*str == '"') { + /* Parse string literal with escape sequences */ + s = g_strdup(str + 1); + p = strrchr(s, '"'); + if (p) + *p = '\0'; + else + return NULL; + + if (!s[0]) + return NULL; + + while (s[i]) { + if (s[i] == '\\' && s[i + 1] == 'x' && g_ascii_isxdigit(s[i + 2]) + && g_ascii_isxdigit(s[i + 3])) { + s[j++] = (g_ascii_xdigit_value(s[i + 2]) << 4) + g_ascii_xdigit_value(s[i + 3]); + i += 4; + continue; + } + if (s[i] == '\\' && s[i + 1] >= '0' && s[i + 1] <= '7' && s[1 + 2] >= '0' + && s[i + 2] <= '7' && s[1 + 3] >= '0' && s[i + 3] <= '7') { + s[j++] = ((s[i + 1] - '0') << 6) + ((s[i + 2] - '0') << 3) + (s[i + 3] - '0'); + i += 4; + continue; + } + s[j++] = s[i++]; + } + return g_bytes_new_take(g_steal_pointer(&s), j); + } + + /* Otherwise, try to read a hexadecimal sequence */ + s = g_strdup(str); + g_strchomp(s); + if (s[strlen(s) - 1] == ';') + s[strlen(s) - 1] = '\0'; + + return nm_utils_hexstr2bin(s); } static gboolean -read_interface (const char *line, char *interface, guint size) +read_interface(const char *line, char *interface, guint size) { - gs_free char *dup = g_strdup (line + NM_STRLEN ("interface")); - char *ptr = dup, *end; - - while (g_ascii_isspace (*ptr)) - ptr++; - - if (*ptr == '"') { - ptr++; - end = strchr (ptr, '"'); - if (!end) - return FALSE; - *end = '\0'; - } else { - end = strchr (ptr, ' '); - if (!end) - end = strchr (ptr, '{'); - if (!end) - return FALSE; - *end = '\0'; - } - - if ( ptr[0] == '\0' - || strlen (ptr) + 1 > size) - return FALSE; - - snprintf (interface, size, "%s", ptr); - - return TRUE; + gs_free char *dup = g_strdup(line + NM_STRLEN("interface")); + char * ptr = dup, *end; + + while (g_ascii_isspace(*ptr)) + ptr++; + + if (*ptr == '"') { + ptr++; + end = strchr(ptr, '"'); + if (!end) + return FALSE; + *end = '\0'; + } else { + end = strchr(ptr, ' '); + if (!end) + end = strchr(ptr, '{'); + if (!end) + return FALSE; + *end = '\0'; + } + + if (ptr[0] == '\0' || strlen(ptr) + 1 > size) + return FALSE; + + snprintf(interface, size, "%s", ptr); + + return TRUE; } char * -nm_dhcp_dhclient_create_config (const char *interface, - int addr_family, - GBytes *client_id, - const char *anycast_addr, - const char *hostname, - guint32 timeout, - gboolean use_fqdn, - NMDhcpHostnameFlags hostname_flags, - const char *mud_url, - const char *orig_path, - const char *orig_contents, - GBytes **out_new_client_id) +nm_dhcp_dhclient_create_config(const char * interface, + int addr_family, + GBytes * client_id, + const char * anycast_addr, + const char * hostname, + guint32 timeout, + gboolean use_fqdn, + NMDhcpHostnameFlags hostname_flags, + const char * mud_url, + const char *const * reject_servers, + const char * orig_path, + const char * orig_contents, + GBytes ** out_new_client_id) { - nm_auto_free_gstring GString *new_contents = NULL; - gs_unref_ptrarray GPtrArray *fqdn_opts = NULL; - gs_unref_ptrarray GPtrArray *reqs = NULL; - gboolean reset_reqlist = FALSE; - int i; - - g_return_val_if_fail (!anycast_addr || nm_utils_hwaddr_valid (anycast_addr, ETH_ALEN), NULL); - g_return_val_if_fail (NM_IN_SET (addr_family, AF_INET, AF_INET6), NULL); - nm_assert (!out_new_client_id || !*out_new_client_id); - - new_contents = g_string_new (_("# Created by NetworkManager\n")); - reqs = g_ptr_array_new_full (5, g_free); - - if (orig_contents) { - gs_free const char **lines = NULL; - gsize line_i; - nm_auto_free_gstring GString *blocks_stack = NULL; - guint blocks_skip = 0; - gboolean in_alsoreq = FALSE; - gboolean in_req = FALSE; - char intf[IFNAMSIZ]; - - blocks_stack = g_string_new (NULL); - g_string_append_printf (new_contents, _("# Merged from %s\n\n"), orig_path); - intf[0] = '\0'; - - lines = nm_utils_strsplit_set (orig_contents, "\n\r"); - for (line_i = 0; lines && lines[line_i]; line_i++) { - const char *line = nm_str_skip_leading_spaces (lines[line_i]); - const char *p; - - if (line[0] == '\0') - continue; - - g_strchomp ((char *) line); - - p = line; - if (in_req) { - /* pass */ - } else if (strchr (p, '{')) { - if ( NM_STR_HAS_PREFIX (p, "lease") - || NM_STR_HAS_PREFIX (p, "alias") - || NM_STR_HAS_PREFIX (p, "interface") - || NM_STR_HAS_PREFIX (p, "pseudo")) { - /* skip over these blocks, except 'interface' when it - * matches the current interface */ - blocks_skip++; - g_string_append_c (blocks_stack, 'b'); - if ( !intf[0] - && NM_STR_HAS_PREFIX (p, "interface")) { - if (read_interface (p, intf, sizeof (intf))) - continue; - } - } else { - /* allow other blocks (conditionals) */ - if (!strchr (p, '}')) /* '} else {' */ - g_string_append_c (blocks_stack, 'c'); - } - } else if (strchr (p, '}')) { - if (blocks_stack->len > 0) { - if (blocks_stack->str[blocks_stack->len - 1] == 'b') { - g_string_truncate (blocks_stack, blocks_stack->len - 1); - nm_assert(blocks_skip > 0); - blocks_skip--; - intf[0] = '\0'; - continue; - } - g_string_truncate (blocks_stack, blocks_stack->len - 1); - } - } - - if (blocks_skip > 0 && !intf[0]) - continue; - - if (intf[0] && !nm_streq (intf, interface)) - continue; - - /* Some timing parameters in dhclient should not be imported (timeout, retry). - * The retry parameter will be simply not used as we will exit on first failure. - * The timeout one instead may affect NetworkManager behavior: if the timeout - * elapses before dhcp-timeout dhclient will report failure and cause NM to - * fail the dhcp process before dhcp-timeout. So, always skip importing timeout - * as we will need to add one greater than dhcp-timeout. - */ - if ( !strncmp (p, TIMEOUT_TAG, strlen (TIMEOUT_TAG)) - || !strncmp (p, RETRY_TAG, strlen (RETRY_TAG))) - continue; - - if (!strncmp (p, CLIENTID_TAG, strlen (CLIENTID_TAG))) { - /* Override config file "dhcp-client-id" and use one from the connection */ - if (client_id) - continue; - - /* Otherwise capture and return the existing client id */ - if (out_new_client_id) - nm_clear_pointer (out_new_client_id, g_bytes_unref); - NM_SET_OUT (out_new_client_id, read_client_id (p)); - } - - /* Override config file hostname and use one from the connection */ - if (hostname) { - if (strncmp (p, HOSTNAME4_TAG, strlen (HOSTNAME4_TAG)) == 0) - continue; - if (strncmp (p, FQDN_TAG, strlen (FQDN_TAG)) == 0) - continue; - } - - /* To let user's FQDN options (except "fqdn.fqdn") override the - * default ones set by NM, add them later - */ - if (!strncmp (p, FQDN_TAG_PREFIX, NM_STRLEN (FQDN_TAG_PREFIX))) { - if (!fqdn_opts) - fqdn_opts = g_ptr_array_new_full (5, g_free); - g_ptr_array_add (fqdn_opts, g_strdup (p + NM_STRLEN (FQDN_TAG_PREFIX))); - continue; - } - - /* Ignore 'script' since we pass our own */ - if (g_str_has_prefix (p, "script ")) - continue; - - /* Check for "request" */ - if (!strncmp (p, REQ_TAG, strlen (REQ_TAG))) { - in_req = TRUE; - p += strlen (REQ_TAG); - g_ptr_array_set_size (reqs, 0); - reset_reqlist = TRUE; - } - - /* Save all request options for later use */ - if (in_req) { - in_req = !grab_request_options (reqs, p); - continue; - } - - /* Check for "also require" */ - if (!strncmp (p, ALSOREQ_TAG, strlen (ALSOREQ_TAG))) { - in_alsoreq = TRUE; - p += strlen (ALSOREQ_TAG); - } - - if (in_alsoreq) { - in_alsoreq = !grab_request_options (reqs, p); - continue; - } - - /* Existing configuration line is OK, add it to new configuration */ - g_string_append (new_contents, line); - g_string_append_c (new_contents, '\n'); - } - } else - g_string_append_c (new_contents, '\n'); - - /* ensure dhclient timeout is greater than dhcp-timeout: as dhclient timeout default value is - * 60 seconds, we need this only if dhcp-timeout is greater than 60. - */ - if (timeout >= 60) { - timeout = timeout < G_MAXINT32 ? timeout + 1 : G_MAXINT32; - g_string_append_printf (new_contents, "timeout %u;\n", timeout); - } - - add_mud_url_config (new_contents, mud_url, addr_family); - if (addr_family == AF_INET) { - add_ip4_config (new_contents, client_id, hostname, use_fqdn, hostname_flags); - add_request (reqs, "rfc3442-classless-static-routes"); - add_request (reqs, "ms-classless-static-routes"); - add_request (reqs, "static-routes"); - add_request (reqs, "wpad"); - add_request (reqs, "ntp-servers"); - add_request (reqs, "root-path"); - } else { - add_hostname6 (new_contents, hostname, hostname_flags); - add_request (reqs, "dhcp6.name-servers"); - add_request (reqs, "dhcp6.domain-search"); - - /* FIXME: internal client does not support requesting client-id option. Does this even work? */ - add_request (reqs, "dhcp6.client-id"); - } - - if (reset_reqlist) - g_string_append (new_contents, "request; # override dhclient defaults\n"); - /* And add it to the dhclient configuration */ - for (i = 0; i < reqs->len; i++) - g_string_append_printf (new_contents, "also request %s;\n", (char *) reqs->pdata[i]); - - if (fqdn_opts) { - for (i = 0; i < fqdn_opts->len; i++) { - const char *t = fqdn_opts->pdata[i]; - - if (i == 0) - g_string_append_printf (new_contents, "\n# FQDN options from %s\n", orig_path); - g_string_append_printf (new_contents, FQDN_TAG_PREFIX "%s\n", t); - } - } - - g_string_append_c (new_contents, '\n'); - - if (anycast_addr) { - g_string_append_printf (new_contents, "interface \"%s\" {\n" - " initial-interval 1; \n" - " anycast-mac ethernet %s;\n" - "}\n", - interface, anycast_addr); - } - - return g_string_free (g_steal_pointer (&new_contents), FALSE); + nm_auto_free_gstring GString *new_contents = NULL; + gs_unref_ptrarray GPtrArray *fqdn_opts = NULL; + gs_unref_ptrarray GPtrArray *reqs = NULL; + gboolean reset_reqlist = FALSE; + int i; + + g_return_val_if_fail(!anycast_addr || nm_utils_hwaddr_valid(anycast_addr, ETH_ALEN), NULL); + g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), NULL); + g_return_val_if_fail(!reject_servers || addr_family == AF_INET, NULL); + nm_assert(!out_new_client_id || !*out_new_client_id); + + new_contents = g_string_new(_("# Created by NetworkManager\n")); + reqs = g_ptr_array_new_full(5, g_free); + + if (orig_contents) { + gs_free const char **lines = NULL; + gsize line_i; + nm_auto_free_gstring GString *blocks_stack = NULL; + guint blocks_skip = 0; + gboolean in_alsoreq = FALSE; + gboolean in_req = FALSE; + char intf[IFNAMSIZ]; + + blocks_stack = g_string_new(NULL); + g_string_append_printf(new_contents, _("# Merged from %s\n\n"), orig_path); + intf[0] = '\0'; + + lines = nm_utils_strsplit_set(orig_contents, "\n\r"); + for (line_i = 0; lines && lines[line_i]; line_i++) { + const char *line = nm_str_skip_leading_spaces(lines[line_i]); + const char *p; + + if (line[0] == '\0') + continue; + + g_strchomp((char *) line); + + p = line; + if (in_req) { + /* pass */ + } else if (strchr(p, '{')) { + if (NM_STR_HAS_PREFIX(p, "lease") || NM_STR_HAS_PREFIX(p, "alias") + || NM_STR_HAS_PREFIX(p, "interface") || NM_STR_HAS_PREFIX(p, "pseudo")) { + /* skip over these blocks, except 'interface' when it + * matches the current interface */ + blocks_skip++; + g_string_append_c(blocks_stack, 'b'); + if (!intf[0] && NM_STR_HAS_PREFIX(p, "interface")) { + if (read_interface(p, intf, sizeof(intf))) + continue; + } + } else { + /* allow other blocks (conditionals) */ + if (!strchr(p, '}')) /* '} else {' */ + g_string_append_c(blocks_stack, 'c'); + } + } else if (strchr(p, '}')) { + if (blocks_stack->len > 0) { + if (blocks_stack->str[blocks_stack->len - 1] == 'b') { + g_string_truncate(blocks_stack, blocks_stack->len - 1); + nm_assert(blocks_skip > 0); + blocks_skip--; + intf[0] = '\0'; + continue; + } + g_string_truncate(blocks_stack, blocks_stack->len - 1); + } + } + + if (blocks_skip > 0 && !intf[0]) + continue; + + if (intf[0] && !nm_streq(intf, interface)) + continue; + + /* Some timing parameters in dhclient should not be imported (timeout, retry). + * The retry parameter will be simply not used as we will exit on first failure. + * The timeout one instead may affect NetworkManager behavior: if the timeout + * elapses before dhcp-timeout dhclient will report failure and cause NM to + * fail the dhcp process before dhcp-timeout. So, always skip importing timeout + * as we will need to add one greater than dhcp-timeout. + */ + if (!strncmp(p, TIMEOUT_TAG, strlen(TIMEOUT_TAG)) + || !strncmp(p, RETRY_TAG, strlen(RETRY_TAG))) + continue; + + if (!strncmp(p, CLIENTID_TAG, strlen(CLIENTID_TAG))) { + /* Override config file "dhcp-client-id" and use one from the connection */ + if (client_id) + continue; + + /* Otherwise, capture and return the existing client id */ + if (out_new_client_id) + nm_clear_pointer(out_new_client_id, g_bytes_unref); + NM_SET_OUT(out_new_client_id, read_client_id(p)); + } + + /* Override config file hostname and use one from the connection */ + if (hostname) { + if (strncmp(p, HOSTNAME4_TAG, strlen(HOSTNAME4_TAG)) == 0) + continue; + if (strncmp(p, FQDN_TAG, strlen(FQDN_TAG)) == 0) + continue; + } + + /* To let user's FQDN options (except "fqdn.fqdn") override the + * default ones set by NM, add them later + */ + if (!strncmp(p, FQDN_TAG_PREFIX, NM_STRLEN(FQDN_TAG_PREFIX))) { + if (!fqdn_opts) + fqdn_opts = g_ptr_array_new_full(5, g_free); + g_ptr_array_add(fqdn_opts, g_strdup(p + NM_STRLEN(FQDN_TAG_PREFIX))); + continue; + } + + /* Ignore 'script' since we pass our own */ + if (g_str_has_prefix(p, "script ")) + continue; + + /* Check for "request" */ + if (!strncmp(p, REQ_TAG, strlen(REQ_TAG))) { + in_req = TRUE; + p += strlen(REQ_TAG); + g_ptr_array_set_size(reqs, 0); + reset_reqlist = TRUE; + } + + /* Save all request options for later use */ + if (in_req) { + in_req = !grab_request_options(reqs, p); + continue; + } + + /* Check for "also require" */ + if (!strncmp(p, ALSOREQ_TAG, strlen(ALSOREQ_TAG))) { + in_alsoreq = TRUE; + p += strlen(ALSOREQ_TAG); + } + + if (in_alsoreq) { + in_alsoreq = !grab_request_options(reqs, p); + continue; + } + + /* Existing configuration line is OK, add it to new configuration */ + g_string_append(new_contents, line); + g_string_append_c(new_contents, '\n'); + } + } else + g_string_append_c(new_contents, '\n'); + + /* ensure dhclient timeout is greater than dhcp-timeout: as dhclient timeout default value is + * 60 seconds, we need this only if dhcp-timeout is greater than 60. + */ + if (timeout >= 60) { + timeout = timeout < G_MAXINT32 ? timeout + 1 : G_MAXINT32; + g_string_append_printf(new_contents, "timeout %u;\n", timeout); + } + + add_mud_url_config(new_contents, mud_url, addr_family); + + if (reject_servers && reject_servers[0]) { + g_string_append(new_contents, "reject "); + for (i = 0; reject_servers[i]; i++) { + if (i != 0) + g_string_append(new_contents, ", "); + g_string_append(new_contents, reject_servers[i]); + } + g_string_append(new_contents, ";\n"); + } + + if (addr_family == AF_INET) { + add_ip4_config(new_contents, client_id, hostname, use_fqdn, hostname_flags); + add_request(reqs, "rfc3442-classless-static-routes"); + add_request(reqs, "ms-classless-static-routes"); + add_request(reqs, "static-routes"); + add_request(reqs, "wpad"); + add_request(reqs, "ntp-servers"); + add_request(reqs, "root-path"); + } else { + add_hostname6(new_contents, hostname, hostname_flags); + add_request(reqs, "dhcp6.name-servers"); + add_request(reqs, "dhcp6.domain-search"); + + /* FIXME: internal client does not support requesting client-id option. Does this even work? */ + add_request(reqs, "dhcp6.client-id"); + } + + if (reset_reqlist) + g_string_append(new_contents, "request; # override dhclient defaults\n"); + /* And add it to the dhclient configuration */ + for (i = 0; i < reqs->len; i++) + g_string_append_printf(new_contents, "also request %s;\n", (char *) reqs->pdata[i]); + + if (fqdn_opts) { + for (i = 0; i < fqdn_opts->len; i++) { + const char *t = fqdn_opts->pdata[i]; + + if (i == 0) + g_string_append_printf(new_contents, "\n# FQDN options from %s\n", orig_path); + g_string_append_printf(new_contents, FQDN_TAG_PREFIX "%s\n", t); + } + } + + g_string_append_c(new_contents, '\n'); + + if (anycast_addr) { + g_string_append_printf(new_contents, + "interface \"%s\" {\n" + " initial-interval 1; \n" + " anycast-mac ethernet %s;\n" + "}\n", + interface, + anycast_addr); + } + + return g_string_free(g_steal_pointer(&new_contents), FALSE); } /* Roughly follow what dhclient's quotify_buf() and pretty_escape() functions do */ char * -nm_dhcp_dhclient_escape_duid (GBytes *duid) +nm_dhcp_dhclient_escape_duid(GBytes *duid) { - char *escaped; - const guint8 *s, *s0; - gsize len; - char *d; - - g_return_val_if_fail (duid, NULL); - - s0 = g_bytes_get_data (duid, &len); - s = s0; - - d = escaped = g_malloc ((len * 4) + 1); - while (s < (s0 + len)) { - if (!g_ascii_isprint (*s)) { - *d++ = '\\'; - *d++ = '0' + ((*s >> 6) & 0x7); - *d++ = '0' + ((*s >> 3) & 0x7); - *d++ = '0' + (*s++ & 0x7); - } else if (*s == '"' || *s == '\'' || *s == '$' || - *s == '`' || *s == '\\' || *s == '|' || - *s == '&') { - *d++ = '\\'; - *d++ = *s++; - } else - *d++ = *s++; - } - *d++ = '\0'; - return escaped; + char * escaped; + const guint8 *s, *s0; + gsize len; + char * d; + + g_return_val_if_fail(duid, NULL); + + s0 = g_bytes_get_data(duid, &len); + s = s0; + + d = escaped = g_malloc((len * 4) + 1); + while (s < (s0 + len)) { + if (!g_ascii_isprint(*s)) { + *d++ = '\\'; + *d++ = '0' + ((*s >> 6) & 0x7); + *d++ = '0' + ((*s >> 3) & 0x7); + *d++ = '0' + (*s++ & 0x7); + } else if (*s == '"' || *s == '\'' || *s == '$' || *s == '`' || *s == '\\' || *s == '|' + || *s == '&') { + *d++ = '\\'; + *d++ = *s++; + } else + *d++ = *s++; + } + *d++ = '\0'; + return escaped; } static gboolean -isoctal (const guint8 *p) +isoctal(const guint8 *p) { - return ( p[0] >= '0' && p[0] <= '3' - && p[1] >= '0' && p[1] <= '7' - && p[2] >= '0' && p[2] <= '7'); + return (p[0] >= '0' && p[0] <= '3' && p[1] >= '0' && p[1] <= '7' && p[2] >= '0' && p[2] <= '7'); } GBytes * -nm_dhcp_dhclient_unescape_duid (const char *duid) +nm_dhcp_dhclient_unescape_duid(const char *duid) { - GByteArray *unescaped; - const guint8 *p = (const guint8 *) duid; - guint i, len; - guint8 octal; - - /* FIXME: it's wrong to have an "unescape-duid" function. dhclient - * defines a file format with escaping. So we need a general unescape - * function that can handle dhclient syntax. */ - - len = strlen (duid); - unescaped = g_byte_array_sized_new (len); - for (i = 0; i < len; i++) { - if (p[i] == '\\') { - i++; - if (isdigit (p[i])) { - /* Octal escape sequence */ - if (i + 2 >= len || !isoctal (p + i)) - goto error; - octal = ((p[i] - '0') << 6) + ((p[i + 1] - '0') << 3) + (p[i + 2] - '0'); - g_byte_array_append (unescaped, &octal, 1); - i += 2; - } else { - /* FIXME: don't warn on untrusted data. Either signal an error, or accept - * it silently. */ - - /* One of ", ', $, `, \, |, or & */ - g_warn_if_fail (p[i] == '"' || p[i] == '\'' || p[i] == '$' || - p[i] == '`' || p[i] == '\\' || p[i] == '|' || - p[i] == '&'); - g_byte_array_append (unescaped, &p[i], 1); - } - } else - g_byte_array_append (unescaped, &p[i], 1); - } - - return g_byte_array_free_to_bytes (unescaped); + GByteArray * unescaped; + const guint8 *p = (const guint8 *) duid; + guint i, len; + guint8 octal; + + /* FIXME: it's wrong to have an "unescape-duid" function. dhclient + * defines a file format with escaping. So we need a general unescape + * function that can handle dhclient syntax. */ + + len = strlen(duid); + unescaped = g_byte_array_sized_new(len); + for (i = 0; i < len; i++) { + if (p[i] == '\\') { + i++; + if (isdigit(p[i])) { + /* Octal escape sequence */ + if (i + 2 >= len || !isoctal(p + i)) + goto error; + octal = ((p[i] - '0') << 6) + ((p[i + 1] - '0') << 3) + (p[i + 2] - '0'); + g_byte_array_append(unescaped, &octal, 1); + i += 2; + } else { + /* FIXME: don't warn on untrusted data. Either signal an error, or accept + * it silently. */ + + /* One of ", ', $, `, \, |, or & */ + g_warn_if_fail(p[i] == '"' || p[i] == '\'' || p[i] == '$' || p[i] == '`' + || p[i] == '\\' || p[i] == '|' || p[i] == '&'); + g_byte_array_append(unescaped, &p[i], 1); + } + } else + g_byte_array_append(unescaped, &p[i], 1); + } + + return g_byte_array_free_to_bytes(unescaped); error: - g_byte_array_free (unescaped, TRUE); - return NULL; + g_byte_array_free(unescaped, TRUE); + return NULL; } #define DUID_PREFIX "default-duid \"" /* Beware: @error may be unset even if the function returns %NULL. */ GBytes * -nm_dhcp_dhclient_read_duid (const char *leasefile, GError **error) +nm_dhcp_dhclient_read_duid(const char *leasefile, GError **error) { - gs_free char *contents = NULL; - gs_free const char **contents_v = NULL; - gsize i; + gs_free char * contents = NULL; + gs_free const char **contents_v = NULL; + gsize i; - if (!g_file_test (leasefile, G_FILE_TEST_EXISTS)) - return NULL; + if (!g_file_test(leasefile, G_FILE_TEST_EXISTS)) + return NULL; - if (!g_file_get_contents (leasefile, &contents, NULL, error)) - return NULL; + if (!g_file_get_contents(leasefile, &contents, NULL, error)) + return NULL; - contents_v = nm_utils_strsplit_set (contents, "\n\r"); - for (i = 0; contents_v && contents_v[i]; i++) { - const char *p = nm_str_skip_leading_spaces (contents_v[i]); - GBytes *duid; + contents_v = nm_utils_strsplit_set(contents, "\n\r"); + for (i = 0; contents_v && contents_v[i]; i++) { + const char *p = nm_str_skip_leading_spaces(contents_v[i]); + GBytes * duid; - if (!NM_STR_HAS_PREFIX (p, DUID_PREFIX)) - continue; + if (!NM_STR_HAS_PREFIX(p, DUID_PREFIX)) + continue; - p += NM_STRLEN (DUID_PREFIX); + p += NM_STRLEN(DUID_PREFIX); - g_strchomp ((char *) p); + g_strchomp((char *) p); - if (!NM_STR_HAS_SUFFIX (p, "\";")) - continue; + if (!NM_STR_HAS_SUFFIX(p, "\";")) + continue; - ((char *) p)[strlen (p) - 2] = '\0'; + ((char *) p)[strlen(p) - 2] = '\0'; - duid = nm_dhcp_dhclient_unescape_duid (p); - if (duid) - return duid; - } + duid = nm_dhcp_dhclient_unescape_duid(p); + if (duid) + return duid; + } - return NULL; + return NULL; } gboolean -nm_dhcp_dhclient_save_duid (const char *leasefile, - GBytes *duid, - GError **error) +nm_dhcp_dhclient_save_duid(const char *leasefile, GBytes *duid, GError **error) { - gs_free char *escaped_duid = NULL; - gs_free const char **lines = NULL; - nm_auto_free_gstring GString *s = NULL; - const char *const*iter; - gsize len = 0; - - g_return_val_if_fail (leasefile != NULL, FALSE); - if (!duid) { - nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, - "missing duid"); - g_return_val_if_reached (FALSE); - } - - escaped_duid = nm_dhcp_dhclient_escape_duid (duid); - nm_assert (escaped_duid); - - if (g_file_test (leasefile, G_FILE_TEST_EXISTS)) { - gs_free char *contents = NULL; - - if (!g_file_get_contents (leasefile, &contents, &len, error)) { - g_prefix_error (error, "failed to read lease file %s: ", leasefile); - return FALSE; - } - - lines = nm_utils_strsplit_set_with_empty (contents, "\n\r"); - } - - s = g_string_sized_new (len + 50); - g_string_append_printf (s, DUID_PREFIX "%s\";\n", escaped_duid); - - /* Preserve existing leasefile contents */ - if (lines) { - for (iter = lines; *iter; iter++) { - const char *str = *iter; - const char *l; - - /* If we find an uncommented DUID in the file, check if - * equal to the one we are going to write: if so, no need - * to update the lease file, otherwise skip the old DUID. - */ - l = nm_str_skip_leading_spaces (str); - if (g_str_has_prefix (l, DUID_PREFIX)) { - gs_strfreev char **split = NULL; - - split = g_strsplit (l, "\"", -1); - if ( split[0] - && nm_streq0 (split[1], escaped_duid)) - return TRUE; - - continue; - } - - if (str) - g_string_append (s, str); - /* avoid to add an extra '\n' at the end of file */ - if ((iter[1]) != NULL) - g_string_append_c (s, '\n'); - } - } - - if (!g_file_set_contents (leasefile, s->str, -1, error)) { - g_prefix_error (error, "failed to set DUID in lease file %s: ", leasefile); - return FALSE; - } - - return TRUE; + gs_free char * escaped_duid = NULL; + gs_free const char **lines = NULL; + nm_auto_free_gstring GString *s = NULL; + const char *const * iter; + gsize len = 0; + + g_return_val_if_fail(leasefile != NULL, FALSE); + if (!duid) { + nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "missing duid"); + g_return_val_if_reached(FALSE); + } + + escaped_duid = nm_dhcp_dhclient_escape_duid(duid); + nm_assert(escaped_duid); + + if (g_file_test(leasefile, G_FILE_TEST_EXISTS)) { + gs_free char *contents = NULL; + + if (!g_file_get_contents(leasefile, &contents, &len, error)) { + g_prefix_error(error, "failed to read lease file %s: ", leasefile); + return FALSE; + } + + lines = nm_utils_strsplit_set_with_empty(contents, "\n\r"); + } + + s = g_string_sized_new(len + 50); + g_string_append_printf(s, DUID_PREFIX "%s\";\n", escaped_duid); + + /* Preserve existing leasefile contents */ + if (lines) { + for (iter = lines; *iter; iter++) { + const char *str = *iter; + const char *l; + + /* If we find an uncommented DUID in the file, check if + * equal to the one we are going to write: if so, no need + * to update the lease file, otherwise skip the old DUID. + */ + l = nm_str_skip_leading_spaces(str); + if (g_str_has_prefix(l, DUID_PREFIX)) { + gs_strfreev char **split = NULL; + + split = g_strsplit(l, "\"", -1); + if (split[0] && nm_streq0(split[1], escaped_duid)) + return TRUE; + + continue; + } + + if (str) + g_string_append(s, str); + /* avoid to add an extra '\n' at the end of file */ + if ((iter[1]) != NULL) + g_string_append_c(s, '\n'); + } + } + + if (!g_file_set_contents(leasefile, s->str, -1, error)) { + g_prefix_error(error, "failed to set DUID in lease file %s: ", leasefile); + return FALSE; + } + + return TRUE; } diff --git a/src/dhcp/nm-dhcp-dhclient-utils.h b/src/dhcp/nm-dhcp-dhclient-utils.h index 5094d614..3e524ee0 100644 --- a/src/dhcp/nm-dhcp-dhclient-utils.h +++ b/src/dhcp/nm-dhcp-dhclient-utils.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2010 Red Hat, Inc. */ @@ -9,27 +9,26 @@ #include "nm-setting-ip4-config.h" #include "nm-setting-ip6-config.h" -char *nm_dhcp_dhclient_create_config (const char *interface, - int addr_family, - GBytes *client_id, - const char *anycast_addr, - const char *hostname, - guint32 timeout, - gboolean use_fqdn, - NMDhcpHostnameFlags hostname_flags, - const char *mud_url, - const char *orig_path, - const char *orig_contents, - GBytes **out_new_client_id); +char *nm_dhcp_dhclient_create_config(const char * interface, + int addr_family, + GBytes * client_id, + const char * anycast_addr, + const char * hostname, + guint32 timeout, + gboolean use_fqdn, + NMDhcpHostnameFlags hostname_flags, + const char * mud_url, + const char *const * reject_servers, + const char * orig_path, + const char * orig_contents, + GBytes ** out_new_client_id); -char *nm_dhcp_dhclient_escape_duid (GBytes *duid); +char *nm_dhcp_dhclient_escape_duid(GBytes *duid); -GBytes *nm_dhcp_dhclient_unescape_duid (const char *duid); +GBytes *nm_dhcp_dhclient_unescape_duid(const char *duid); -GBytes *nm_dhcp_dhclient_read_duid (const char *leasefile, GError **error); +GBytes *nm_dhcp_dhclient_read_duid(const char *leasefile, GError **error); -gboolean nm_dhcp_dhclient_save_duid (const char *leasefile, - GBytes *duid, - GError **error); +gboolean nm_dhcp_dhclient_save_duid(const char *leasefile, GBytes *duid, GError **error); #endif /* __NETWORKMANAGER_DHCP_DHCLIENT_UTILS_H__ */ diff --git a/src/dhcp/nm-dhcp-dhclient.c b/src/dhcp/nm-dhcp-dhclient.c index 4ad056e5..260f400e 100644 --- a/src/dhcp/nm-dhcp-dhclient.c +++ b/src/dhcp/nm-dhcp-dhclient.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2005 - 2012 Red Hat, Inc. */ @@ -14,74 +14,79 @@ #if WITH_DHCLIENT -#include <stdlib.h> -#include <unistd.h> -#include <stdio.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <ctype.h> + #include <stdlib.h> + #include <unistd.h> + #include <stdio.h> + #include <netinet/in.h> + #include <arpa/inet.h> + #include <ctype.h> -#include "nm-glib-aux/nm-dedup-multi.h" + #include "nm-glib-aux/nm-dedup-multi.h" -#include "nm-utils.h" -#include "nm-dhcp-dhclient-utils.h" -#include "nm-dhcp-manager.h" -#include "NetworkManagerUtils.h" -#include "nm-dhcp-listener.h" -#include "nm-dhcp-client-logging.h" + #include "nm-utils.h" + #include "nm-dhcp-dhclient-utils.h" + #include "nm-dhcp-manager.h" + #include "NetworkManagerUtils.h" + #include "nm-dhcp-listener.h" + #include "nm-dhcp-client-logging.h" /*****************************************************************************/ static const char * -_addr_family_to_path_part (int addr_family) +_addr_family_to_path_part(int addr_family) { - nm_assert (NM_IN_SET (addr_family, AF_INET, AF_INET6)); - return (addr_family == AF_INET6) ? "6" : ""; + nm_assert(NM_IN_SET(addr_family, AF_INET, AF_INET6)); + return (addr_family == AF_INET6) ? "6" : ""; } /*****************************************************************************/ -#define NM_TYPE_DHCP_DHCLIENT (nm_dhcp_dhclient_get_type ()) -#define NM_DHCP_DHCLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DHCP_DHCLIENT, NMDhcpDhclient)) -#define NM_DHCP_DHCLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DHCP_DHCLIENT, NMDhcpDhclientClass)) -#define NM_IS_DHCP_DHCLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DHCP_DHCLIENT)) -#define NM_IS_DHCP_DHCLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DHCP_DHCLIENT)) -#define NM_DHCP_DHCLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DHCP_DHCLIENT, NMDhcpDhclientClass)) - -typedef struct _NMDhcpDhclient NMDhcpDhclient; + #define NM_TYPE_DHCP_DHCLIENT (nm_dhcp_dhclient_get_type()) + #define NM_DHCP_DHCLIENT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DHCP_DHCLIENT, NMDhcpDhclient)) + #define NM_DHCP_DHCLIENT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DHCP_DHCLIENT, NMDhcpDhclientClass)) + #define NM_IS_DHCP_DHCLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DHCP_DHCLIENT)) + #define NM_IS_DHCP_DHCLIENT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DHCP_DHCLIENT)) + #define NM_DHCP_DHCLIENT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DHCP_DHCLIENT, NMDhcpDhclientClass)) + +typedef struct _NMDhcpDhclient NMDhcpDhclient; typedef struct _NMDhcpDhclientClass NMDhcpDhclientClass; -static GType nm_dhcp_dhclient_get_type (void); +static GType nm_dhcp_dhclient_get_type(void); /*****************************************************************************/ typedef struct { - char *conf_file; - const char *def_leasefile; - char *lease_file; - char *pid_file; - NMDhcpListener *dhcp_listener; + char * conf_file; + const char * def_leasefile; + char * lease_file; + char * pid_file; + NMDhcpListener *dhcp_listener; } NMDhcpDhclientPrivate; struct _NMDhcpDhclient { - NMDhcpClient parent; - NMDhcpDhclientPrivate _priv; + NMDhcpClient parent; + NMDhcpDhclientPrivate _priv; }; struct _NMDhcpDhclientClass { - NMDhcpClientClass parent; + NMDhcpClientClass parent; }; -G_DEFINE_TYPE (NMDhcpDhclient, nm_dhcp_dhclient, NM_TYPE_DHCP_CLIENT) +G_DEFINE_TYPE(NMDhcpDhclient, nm_dhcp_dhclient, NM_TYPE_DHCP_CLIENT) -#define NM_DHCP_DHCLIENT_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDhcpDhclient, NM_IS_DHCP_DHCLIENT) + #define NM_DHCP_DHCLIENT_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMDhcpDhclient, NM_IS_DHCP_DHCLIENT) /*****************************************************************************/ static const char * -nm_dhcp_dhclient_get_path (void) +nm_dhcp_dhclient_get_path(void) { - return nm_utils_find_helper ("dhclient", DHCLIENT_PATH, NULL); + return nm_utils_find_helper("dhclient", DHCLIENT_PATH, NULL); } /** @@ -98,159 +103,169 @@ nm_dhcp_dhclient_get_path (void) * Returns: an existing leasefile, or %NULL if no matching leasefile could be found */ static char * -get_dhclient_leasefile (int addr_family, - const char *iface, - const char *uuid, - char **out_preferred_path) +get_dhclient_leasefile(int addr_family, + const char *iface, + const char *uuid, + char ** out_preferred_path) { - gs_free char *path = NULL; - - if (nm_dhcp_utils_get_leasefile_path (addr_family, "dhclient", iface, uuid, &path)) { - NM_SET_OUT (out_preferred_path, g_strdup (path)); - return g_steal_pointer (&path); - } - - NM_SET_OUT (out_preferred_path, g_steal_pointer (&path)); - - /* If the leasefile we're looking for doesn't exist yet in the new location - * (eg, /var/lib/NetworkManager) then look in old locations to maintain - * backwards compatibility with external tools (like dracut) that put - * leasefiles there. - */ - - /* Old Debian, SUSE, and Mandriva location */ - g_free (path); - path = g_strdup_printf (LOCALSTATEDIR "/lib/dhcp/dhclient%s-%s-%s.lease", - _addr_family_to_path_part (addr_family), uuid, iface); - if (g_file_test (path, G_FILE_TEST_EXISTS)) - return g_steal_pointer (&path); - - /* Old Red Hat and Fedora location */ - g_free (path); - path = g_strdup_printf (LOCALSTATEDIR "/lib/dhclient/dhclient%s-%s-%s.lease", - _addr_family_to_path_part (addr_family), uuid, iface); - if (g_file_test (path, G_FILE_TEST_EXISTS)) - return g_steal_pointer (&path); - - /* Fail */ - return NULL; + gs_free char *path = NULL; + + if (nm_dhcp_utils_get_leasefile_path(addr_family, "dhclient", iface, uuid, &path)) { + NM_SET_OUT(out_preferred_path, g_strdup(path)); + return g_steal_pointer(&path); + } + + NM_SET_OUT(out_preferred_path, g_steal_pointer(&path)); + + /* If the leasefile we're looking for doesn't exist yet in the new location + * (eg, /var/lib/NetworkManager) then look in old locations to maintain + * backwards compatibility with external tools (like dracut) that put + * leasefiles there. + */ + + /* Old Debian, SUSE, and Mandriva location */ + g_free(path); + path = g_strdup_printf(LOCALSTATEDIR "/lib/dhcp/dhclient%s-%s-%s.lease", + _addr_family_to_path_part(addr_family), + uuid, + iface); + if (g_file_test(path, G_FILE_TEST_EXISTS)) + return g_steal_pointer(&path); + + /* Old Red Hat and Fedora location */ + g_free(path); + path = g_strdup_printf(LOCALSTATEDIR "/lib/dhclient/dhclient%s-%s-%s.lease", + _addr_family_to_path_part(addr_family), + uuid, + iface); + if (g_file_test(path, G_FILE_TEST_EXISTS)) + return g_steal_pointer(&path); + + /* Fail */ + return NULL; } static gboolean -merge_dhclient_config (NMDhcpDhclient *self, - int addr_family, - const char *iface, - const char *conf_file, - GBytes *client_id, - const char *anycast_addr, - const char *hostname, - guint32 timeout, - gboolean use_fqdn, - NMDhcpHostnameFlags hostname_flags, - const char *mud_url, - const char *orig_path, - GBytes **out_new_client_id, - GError **error) +merge_dhclient_config(NMDhcpDhclient * self, + int addr_family, + const char * iface, + const char * conf_file, + GBytes * client_id, + const char * anycast_addr, + const char * hostname, + guint32 timeout, + gboolean use_fqdn, + NMDhcpHostnameFlags hostname_flags, + const char * mud_url, + const char *const * reject_servers, + const char * orig_path, + GBytes ** out_new_client_id, + GError ** error) { - gs_free char *orig = NULL; - gs_free char *new = NULL; - - g_return_val_if_fail (iface, FALSE); - g_return_val_if_fail (conf_file, FALSE); - - if ( orig_path - && g_file_test (orig_path, G_FILE_TEST_EXISTS)) { - GError *read_error = NULL; - - if (!g_file_get_contents (orig_path, &orig, NULL, &read_error)) { - _LOGW ("error reading dhclient configuration %s: %s", - orig_path, read_error->message); - g_error_free (read_error); - } - } - - new = nm_dhcp_dhclient_create_config (iface, - addr_family, - client_id, - anycast_addr, - hostname, - timeout, - use_fqdn, - hostname_flags, - mud_url, - orig_path, - orig, - out_new_client_id); - nm_assert (new); - - return g_file_set_contents (conf_file, - new, - -1, - error); + gs_free char *orig = NULL; + gs_free char *new = NULL; + + g_return_val_if_fail(iface, FALSE); + g_return_val_if_fail(conf_file, FALSE); + + if (orig_path && g_file_test(orig_path, G_FILE_TEST_EXISTS)) { + GError *read_error = NULL; + + if (!g_file_get_contents(orig_path, &orig, NULL, &read_error)) { + _LOGW("error reading dhclient configuration %s: %s", orig_path, read_error->message); + g_error_free(read_error); + } + } + + new = nm_dhcp_dhclient_create_config(iface, + addr_family, + client_id, + anycast_addr, + hostname, + timeout, + use_fqdn, + hostname_flags, + mud_url, + reject_servers, + orig_path, + orig, + out_new_client_id); + nm_assert(new); + + return g_file_set_contents(conf_file, new, -1, error); } static char * -find_existing_config (NMDhcpDhclient *self, int addr_family, const char *iface, const char *uuid) +find_existing_config(NMDhcpDhclient *self, int addr_family, const char *iface, const char *uuid) { - char *path; - - /* NetworkManager-overridden configuration can be used to ship DHCP config - * with NetworkManager itself. It can be uuid-specific, device-specific - * or generic. - */ - if (uuid) { - path = g_strdup_printf (NMCONFDIR "/dhclient%s-%s.conf", _addr_family_to_path_part (addr_family), uuid); - _LOGD ("looking for existing config %s", path); - if (g_file_test (path, G_FILE_TEST_EXISTS)) - return path; - g_free (path); - } - - path = g_strdup_printf (NMCONFDIR "/dhclient%s-%s.conf", _addr_family_to_path_part (addr_family), iface); - _LOGD ("looking for existing config %s", path); - if (g_file_test (path, G_FILE_TEST_EXISTS)) - return path; - g_free (path); - - path = g_strdup_printf (NMCONFDIR "/dhclient%s.conf", _addr_family_to_path_part (addr_family)); - _LOGD ("looking for existing config %s", path); - if (g_file_test (path, G_FILE_TEST_EXISTS)) - return path; - g_free (path); - - /* Distribution's dhclient configuration is used so that we can use - * configuration shipped with dhclient (if any). - * - * This replaces conditional compilation based on distribution name. Fedora - * and Debian store the configs in /etc/dhcp while upstream defaults to /etc - * which is then used by many other distributions. Some distributions - * (including Fedora) don't even provide a default configuration file. - */ - path = g_strdup_printf (SYSCONFDIR "/dhcp/dhclient%s-%s.conf", _addr_family_to_path_part (addr_family), iface); - _LOGD ("looking for existing config %s", path); - if (g_file_test (path, G_FILE_TEST_EXISTS)) - return path; - g_free (path); - - path = g_strdup_printf (SYSCONFDIR "/dhclient%s-%s.conf", _addr_family_to_path_part (addr_family), iface); - _LOGD ("looking for existing config %s", path); - if (g_file_test (path, G_FILE_TEST_EXISTS)) - return path; - g_free (path); - - path = g_strdup_printf (SYSCONFDIR "/dhcp/dhclient%s.conf", _addr_family_to_path_part (addr_family)); - _LOGD ("looking for existing config %s", path); - if (g_file_test (path, G_FILE_TEST_EXISTS)) - return path; - g_free (path); - - path = g_strdup_printf (SYSCONFDIR "/dhclient%s.conf", _addr_family_to_path_part (addr_family)); - _LOGD ("looking for existing config %s", path); - if (g_file_test (path, G_FILE_TEST_EXISTS)) - return path; - g_free (path); - - return NULL; + char *path; + + /* NetworkManager-overridden configuration can be used to ship DHCP config + * with NetworkManager itself. It can be uuid-specific, device-specific + * or generic. + */ + if (uuid) { + path = g_strdup_printf(NMCONFDIR "/dhclient%s-%s.conf", + _addr_family_to_path_part(addr_family), + uuid); + _LOGD("looking for existing config %s", path); + if (g_file_test(path, G_FILE_TEST_EXISTS)) + return path; + g_free(path); + } + + path = g_strdup_printf(NMCONFDIR "/dhclient%s-%s.conf", + _addr_family_to_path_part(addr_family), + iface); + _LOGD("looking for existing config %s", path); + if (g_file_test(path, G_FILE_TEST_EXISTS)) + return path; + g_free(path); + + path = g_strdup_printf(NMCONFDIR "/dhclient%s.conf", _addr_family_to_path_part(addr_family)); + _LOGD("looking for existing config %s", path); + if (g_file_test(path, G_FILE_TEST_EXISTS)) + return path; + g_free(path); + + /* Distribution's dhclient configuration is used so that we can use + * configuration shipped with dhclient (if any). + * + * This replaces conditional compilation based on distribution name. Fedora + * and Debian store the configs in /etc/dhcp while upstream defaults to /etc + * which is then used by many other distributions. Some distributions + * (including Fedora) don't even provide a default configuration file. + */ + path = g_strdup_printf(SYSCONFDIR "/dhcp/dhclient%s-%s.conf", + _addr_family_to_path_part(addr_family), + iface); + _LOGD("looking for existing config %s", path); + if (g_file_test(path, G_FILE_TEST_EXISTS)) + return path; + g_free(path); + + path = g_strdup_printf(SYSCONFDIR "/dhclient%s-%s.conf", + _addr_family_to_path_part(addr_family), + iface); + _LOGD("looking for existing config %s", path); + if (g_file_test(path, G_FILE_TEST_EXISTS)) + return path; + g_free(path); + + path = + g_strdup_printf(SYSCONFDIR "/dhcp/dhclient%s.conf", _addr_family_to_path_part(addr_family)); + _LOGD("looking for existing config %s", path); + if (g_file_test(path, G_FILE_TEST_EXISTS)) + return path; + g_free(path); + + path = g_strdup_printf(SYSCONFDIR "/dhclient%s.conf", _addr_family_to_path_part(addr_family)); + _LOGD("looking for existing config %s", path); + if (g_file_test(path, G_FILE_TEST_EXISTS)) + return path; + g_free(path); + + return NULL; } /* NM provides interface-specific options; thus the same dhclient config @@ -260,451 +275,453 @@ find_existing_config (NMDhcpDhclient *self, int addr_family, const char *iface, * config file along with the NM options. */ static char * -create_dhclient_config (NMDhcpDhclient *self, - int addr_family, - const char *iface, - const char *uuid, - GBytes *client_id, - const char *dhcp_anycast_addr, - const char *hostname, - guint32 timeout, - gboolean use_fqdn, - NMDhcpHostnameFlags hostname_flags, - const char *mud_url, - GBytes **out_new_client_id) +create_dhclient_config(NMDhcpDhclient * self, + int addr_family, + const char * iface, + const char * uuid, + GBytes * client_id, + const char * dhcp_anycast_addr, + const char * hostname, + guint32 timeout, + gboolean use_fqdn, + NMDhcpHostnameFlags hostname_flags, + const char * mud_url, + const char *const * reject_servers, + GBytes ** out_new_client_id) { - gs_free char *orig = NULL; - char *new = NULL; - GError *error = NULL; - - g_return_val_if_fail (iface != NULL, NULL); - - new = g_strdup_printf (NMSTATEDIR "/dhclient%s-%s.conf", _addr_family_to_path_part (addr_family), iface); - - _LOGD ("creating composite dhclient config %s", new); - - orig = find_existing_config (self, addr_family, iface, uuid); - if (orig) - _LOGD ("merging existing dhclient config %s", orig); - else - _LOGD ("no existing dhclient configuration to merge"); - - if (!merge_dhclient_config (self, - addr_family, - iface, - new, - client_id, - dhcp_anycast_addr, - hostname, - timeout, - use_fqdn, - hostname_flags, - mud_url, - orig, - out_new_client_id, - &error)) { - _LOGW ("error creating dhclient configuration: %s", error->message); - g_clear_error (&error); - } - - return new; + gs_free char *orig = NULL; + char *new = NULL; + GError *error = NULL; + + g_return_val_if_fail(iface != NULL, NULL); + + new = g_strdup_printf(NMSTATEDIR "/dhclient%s-%s.conf", + _addr_family_to_path_part(addr_family), + iface); + + _LOGD("creating composite dhclient config %s", new); + + orig = find_existing_config(self, addr_family, iface, uuid); + if (orig) + _LOGD("merging existing dhclient config %s", orig); + else + _LOGD("no existing dhclient configuration to merge"); + + if (!merge_dhclient_config(self, + addr_family, + iface, + new, + client_id, + dhcp_anycast_addr, + hostname, + timeout, + use_fqdn, + hostname_flags, + mud_url, + reject_servers, + orig, + out_new_client_id, + &error)) { + _LOGW("error creating dhclient configuration: %s", error->message); + g_clear_error(&error); + } + + return new; } static gboolean -dhclient_start (NMDhcpClient *client, - const char *mode_opt, - gboolean release, - pid_t *out_pid, - int prefixes, - GError **error) +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); - - g_return_val_if_fail (!priv->pid_file, FALSE); - - NM_SET_OUT (out_pid, 0); - - dhclient_path = nm_dhcp_dhclient_get_path (); - if (!dhclient_path) { - nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "dhclient binary not found"); - return FALSE; - } - - iface = nm_dhcp_client_get_iface (client); - uuid = nm_dhcp_client_get_uuid (client); - - pid_file = g_strdup_printf (NMRUNDIR "/dhclient%s-%s.pid", - _addr_family_to_path_part (addr_family), - iface); - - /* Kill any existing dhclient from the pidfile */ - binary_name = g_path_get_basename (dhclient_path); - nm_dhcp_client_stop_existing (pid_file, binary_name); - g_free (binary_name); - - if (release) { - /* release doesn't use the pidfile after killing an old client */ - nm_clear_g_free (&pid_file); - } - - g_free (priv->lease_file); - priv->lease_file = get_dhclient_leasefile (addr_family, iface, uuid, &preferred_leasefile_path); - nm_assert (preferred_leasefile_path); - if (!priv->lease_file) { - /* No existing leasefile, dhclient will create one at the preferred path */ - priv->lease_file = g_steal_pointer (&preferred_leasefile_path); - } else if (!nm_streq0 (priv->lease_file, preferred_leasefile_path)) { - gs_unref_object GFile *src = g_file_new_for_path (priv->lease_file); - gs_unref_object GFile *dst = g_file_new_for_path (preferred_leasefile_path); - - /* Try to copy the existing leasefile to the preferred location */ - if (!g_file_copy (src, dst, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &local)) { - gs_free char *s_path = NULL; - gs_free char *d_path = NULL; - - /* Failure; just use the existing leasefile */ - _LOGW ("failed to copy leasefile %s to %s: %s", - (s_path = g_file_get_path (src)), - (d_path = g_file_get_path (dst)), - local->message); - g_clear_error (&local); - } else { - /* Success; use the preferred leasefile path */ - g_free (priv->lease_file); - priv->lease_file = g_file_get_path (dst); - } - } - - /* 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)) { - nm_utils_error_set (error, - NM_UTILS_ERROR_UNKNOWN, - "failed to save DUID to '%s': %s", - priv->lease_file, - local->message); - return FALSE; - } - } - - argv = g_ptr_array_new (); - g_ptr_array_add (argv, (gpointer) dhclient_path); - - g_ptr_array_add (argv, (gpointer) "-d"); - - /* Be quiet. dhclient logs to syslog anyway. And we duplicate the syslog - * to stderr in case of NM running with --debug. - */ - g_ptr_array_add (argv, (gpointer) "-q"); - - if (release) - g_ptr_array_add (argv, (gpointer) "-r"); - - if (addr_family == AF_INET6) { - g_ptr_array_add (argv, (gpointer) "-6"); - if (mode_opt) - g_ptr_array_add (argv, (gpointer) mode_opt); - while (prefixes--) - g_ptr_array_add (argv, (gpointer) "-P"); - } - g_ptr_array_add (argv, (gpointer) "-sf"); /* Set script file */ - g_ptr_array_add (argv, (gpointer) nm_dhcp_helper_path); - - if (pid_file) { - g_ptr_array_add (argv, (gpointer) "-pf"); /* Set pid file */ - g_ptr_array_add (argv, (gpointer) pid_file); - } - - g_ptr_array_add (argv, (gpointer) "-lf"); /* Set lease file */ - g_ptr_array_add (argv, (gpointer) priv->lease_file); - - if (priv->conf_file) { - g_ptr_array_add (argv, (gpointer) "-cf"); /* Set interface config file */ - g_ptr_array_add (argv, (gpointer) priv->conf_file); - } - - /* Usually the system bus address is well-known; but if it's supposed - * to be something else, we need to push it to dhclient, since dhclient - * sanitizes the environment it gives the action scripts. - */ - system_bus_address = getenv ("DBUS_SYSTEM_BUS_ADDRESS"); - if (system_bus_address) { - system_bus_address_env = g_strdup_printf ("DBUS_SYSTEM_BUS_ADDRESS=%s", system_bus_address); - g_ptr_array_add (argv, (gpointer) "-e"); - g_ptr_array_add (argv, (gpointer) system_bus_address_env); - } - - g_ptr_array_add (argv, (gpointer) iface); - g_ptr_array_add (argv, NULL); - - _LOGD ("running: %s", - (cmd_str = g_strjoinv (" ", (char **) argv->pdata))); - - if (!g_spawn_async (NULL, (char **) argv->pdata, NULL, - G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL, - nm_utils_setpgid, NULL, &pid, &local)) { - nm_utils_error_set (error, - NM_UTILS_ERROR_UNKNOWN, - "dhclient failed to start: %s", - local->message); - return FALSE; - } - - _LOGI ("dhclient started with pid %lld", (long long int) pid); - - if (!release) - nm_dhcp_client_watch_child (client, pid); - - priv->pid_file = g_steal_pointer (&pid_file); - - NM_SET_OUT (out_pid, pid); - return TRUE; + 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); + + g_return_val_if_fail(!priv->pid_file, FALSE); + + NM_SET_OUT(out_pid, 0); + + dhclient_path = nm_dhcp_dhclient_get_path(); + if (!dhclient_path) { + nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "dhclient binary not found"); + return FALSE; + } + + iface = nm_dhcp_client_get_iface(client); + uuid = nm_dhcp_client_get_uuid(client); + + pid_file = g_strdup_printf(NMRUNDIR "/dhclient%s-%s.pid", + _addr_family_to_path_part(addr_family), + iface); + + /* Kill any existing dhclient from the pidfile */ + binary_name = g_path_get_basename(dhclient_path); + nm_dhcp_client_stop_existing(pid_file, binary_name); + g_free(binary_name); + + if (release) { + /* release doesn't use the pidfile after killing an old client */ + nm_clear_g_free(&pid_file); + } + + g_free(priv->lease_file); + priv->lease_file = get_dhclient_leasefile(addr_family, iface, uuid, &preferred_leasefile_path); + nm_assert(preferred_leasefile_path); + if (!priv->lease_file) { + /* No existing leasefile, dhclient will create one at the preferred path */ + priv->lease_file = g_steal_pointer(&preferred_leasefile_path); + } else if (!nm_streq0(priv->lease_file, preferred_leasefile_path)) { + gs_unref_object GFile *src = g_file_new_for_path(priv->lease_file); + gs_unref_object GFile *dst = g_file_new_for_path(preferred_leasefile_path); + + /* Try to copy the existing leasefile to the preferred location */ + if (!g_file_copy(src, dst, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &local)) { + gs_free char *s_path = NULL; + gs_free char *d_path = NULL; + + /* Failure; just use the existing leasefile */ + _LOGW("failed to copy leasefile %s to %s: %s", + (s_path = g_file_get_path(src)), + (d_path = g_file_get_path(dst)), + local->message); + g_clear_error(&local); + } else { + /* Success; use the preferred leasefile path */ + g_free(priv->lease_file); + priv->lease_file = g_file_get_path(dst); + } + } + + /* 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)) { + nm_utils_error_set(error, + NM_UTILS_ERROR_UNKNOWN, + "failed to save DUID to '%s': %s", + priv->lease_file, + local->message); + return FALSE; + } + } + + argv = g_ptr_array_new(); + g_ptr_array_add(argv, (gpointer) dhclient_path); + + g_ptr_array_add(argv, (gpointer) "-d"); + + /* Be quiet. dhclient logs to syslog anyway. And we duplicate the syslog + * to stderr in case of NM running with --debug. + */ + g_ptr_array_add(argv, (gpointer) "-q"); + + if (release) + g_ptr_array_add(argv, (gpointer) "-r"); + + if (addr_family == AF_INET6) { + g_ptr_array_add(argv, (gpointer) "-6"); + if (mode_opt) + g_ptr_array_add(argv, (gpointer) mode_opt); + while (prefixes--) + g_ptr_array_add(argv, (gpointer) "-P"); + } + g_ptr_array_add(argv, (gpointer) "-sf"); /* Set script file */ + g_ptr_array_add(argv, (gpointer) nm_dhcp_helper_path); + + if (pid_file) { + g_ptr_array_add(argv, (gpointer) "-pf"); /* Set pid file */ + g_ptr_array_add(argv, (gpointer) pid_file); + } + + g_ptr_array_add(argv, (gpointer) "-lf"); /* Set lease file */ + g_ptr_array_add(argv, (gpointer) priv->lease_file); + + if (priv->conf_file) { + g_ptr_array_add(argv, (gpointer) "-cf"); /* Set interface config file */ + g_ptr_array_add(argv, (gpointer) priv->conf_file); + } + + /* Usually the system bus address is well-known; but if it's supposed + * to be something else, we need to push it to dhclient, since dhclient + * sanitizes the environment it gives the action scripts. + */ + system_bus_address = getenv("DBUS_SYSTEM_BUS_ADDRESS"); + if (system_bus_address) { + system_bus_address_env = g_strdup_printf("DBUS_SYSTEM_BUS_ADDRESS=%s", system_bus_address); + g_ptr_array_add(argv, (gpointer) "-e"); + g_ptr_array_add(argv, (gpointer) system_bus_address_env); + } + + g_ptr_array_add(argv, (gpointer) iface); + g_ptr_array_add(argv, NULL); + + _LOGD("running: %s", (cmd_str = g_strjoinv(" ", (char **) argv->pdata))); + + if (!g_spawn_async(NULL, + (char **) argv->pdata, + NULL, + G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_STDOUT_TO_DEV_NULL + | G_SPAWN_STDERR_TO_DEV_NULL, + nm_utils_setpgid, + NULL, + &pid, + &local)) { + nm_utils_error_set(error, + NM_UTILS_ERROR_UNKNOWN, + "dhclient failed to start: %s", + local->message); + return FALSE; + } + + _LOGI("dhclient started with pid %lld", (long long int) pid); + + if (!release) + nm_dhcp_client_watch_child(client, pid); + + priv->pid_file = g_steal_pointer(&pid_file); + + NM_SET_OUT(out_pid, pid); + return TRUE; } static gboolean -ip4_start (NMDhcpClient *client, - const char *dhcp_anycast_addr, - const char *last_ip4_address, - GError **error) +ip4_start(NMDhcpClient *client, + const char * dhcp_anycast_addr, + const char * last_ip4_address, + 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, - dhcp_anycast_addr, - nm_dhcp_client_get_hostname (client), - nm_dhcp_client_get_timeout (client), - nm_dhcp_client_get_use_fqdn (client), - nm_dhcp_client_get_hostname_flags (client), - nm_dhcp_client_get_mud_url (client), - &new_client_id); - if (!priv->conf_file) { - nm_utils_error_set_literal (error, - NM_UTILS_ERROR_UNKNOWN, - "error creating dhclient configuration file"); - return FALSE; - } - - if (new_client_id) { - nm_assert (!client_id); - nm_dhcp_client_set_client_id (client, new_client_id); - } - return dhclient_start (client, - NULL, - FALSE, - NULL, - 0, - 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, + dhcp_anycast_addr, + nm_dhcp_client_get_hostname(client), + nm_dhcp_client_get_timeout(client), + nm_dhcp_client_get_use_fqdn(client), + nm_dhcp_client_get_hostname_flags(client), + nm_dhcp_client_get_mud_url(client), + nm_dhcp_client_get_reject_servers(client), + &new_client_id); + if (!priv->conf_file) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_UNKNOWN, + "error creating dhclient configuration file"); + return FALSE; + } + + if (new_client_id) { + nm_assert(!client_id); + nm_dhcp_client_set_client_id(client, new_client_id); + } + return dhclient_start(client, NULL, FALSE, NULL, 0, error); } static gboolean -ip6_start (NMDhcpClient *client, - const char *dhcp_anycast_addr, - const struct in6_addr *ll_addr, - NMSettingIP6ConfigPrivacy privacy, - guint needed_prefixes, - GError **error) +ip6_start(NMDhcpClient * client, + const char * dhcp_anycast_addr, + const struct in6_addr * ll_addr, + NMSettingIP6ConfigPrivacy privacy, + guint needed_prefixes, + GError ** error) { - NMDhcpDhclient *self = NM_DHCP_DHCLIENT (client); - NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (self); - - if (nm_dhcp_client_get_iaid_explicit (client)) - _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), - NULL, - dhcp_anycast_addr, - nm_dhcp_client_get_hostname (client), - nm_dhcp_client_get_timeout (client), - TRUE, - nm_dhcp_client_get_hostname_flags (client), - nm_dhcp_client_get_mud_url (client), - NULL); - if (!priv->conf_file) { - nm_utils_error_set_literal (error, - NM_UTILS_ERROR_UNKNOWN, - "error creating dhclient configuration file"); - return FALSE; - } - - return dhclient_start (client, - nm_dhcp_client_get_info_only (NM_DHCP_CLIENT (self)) - ? "-S" - : "-N", - FALSE, - NULL, - needed_prefixes, - error); + NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client); + NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self); + + if (nm_dhcp_client_get_iaid_explicit(client)) + _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), + NULL, + dhcp_anycast_addr, + nm_dhcp_client_get_hostname(client), + nm_dhcp_client_get_timeout(client), + TRUE, + nm_dhcp_client_get_hostname_flags(client), + nm_dhcp_client_get_mud_url(client), + NULL, + NULL); + if (!priv->conf_file) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_UNKNOWN, + "error creating dhclient configuration file"); + return FALSE; + } + + return dhclient_start(client, + nm_dhcp_client_get_info_only(NM_DHCP_CLIENT(self)) ? "-S" : "-N", + FALSE, + NULL, + needed_prefixes, + error); } static void -stop (NMDhcpClient *client, gboolean release) +stop(NMDhcpClient *client, gboolean release) { - NMDhcpDhclient *self = NM_DHCP_DHCLIENT (client); - NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (self); - int errsv; - - NM_DHCP_CLIENT_CLASS (nm_dhcp_dhclient_parent_class)->stop (client, release); - - if (priv->conf_file) - if (remove (priv->conf_file) == -1) { - errsv = errno; - _LOGD ("could not remove dhcp config file \"%s\": %d (%s)", priv->conf_file, errsv, nm_strerror_native (errsv)); - } - if (priv->pid_file) { - if (remove (priv->pid_file) == -1) { - errsv = errno; - _LOGD ("could not remove dhcp pid file \"%s\": %s (%d)", priv->pid_file, nm_strerror_native (errsv), errsv); - } - nm_clear_g_free (&priv->pid_file); - } - - if (release) { - pid_t rpid = -1; - - if (dhclient_start (client, - NULL, - TRUE, - &rpid, - 0, - NULL)) { - /* Wait a few seconds for the release to happen */ - nm_dhcp_client_stop_pid (rpid, nm_dhcp_client_get_iface (client)); - } - } + NMDhcpDhclient * self = NM_DHCP_DHCLIENT(client); + NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self); + int errsv; + + NM_DHCP_CLIENT_CLASS(nm_dhcp_dhclient_parent_class)->stop(client, release); + + if (priv->conf_file) + if (remove(priv->conf_file) == -1) { + errsv = errno; + _LOGD("could not remove dhcp config file \"%s\": %d (%s)", + priv->conf_file, + errsv, + nm_strerror_native(errsv)); + } + if (priv->pid_file) { + if (remove(priv->pid_file) == -1) { + errsv = errno; + _LOGD("could not remove dhcp pid file \"%s\": %s (%d)", + priv->pid_file, + nm_strerror_native(errsv), + errsv); + } + nm_clear_g_free(&priv->pid_file); + } + + if (release) { + pid_t rpid = -1; + + if (dhclient_start(client, NULL, TRUE, &rpid, 0, NULL)) { + /* Wait a few seconds for the release to happen */ + nm_dhcp_client_stop_pid(rpid, nm_dhcp_client_get_iface(client)); + } + } } static GBytes * -get_duid (NMDhcpClient *client) +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; - - /* 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), - NULL); - if (leasefile) { - _LOGD ("looking for DUID in '%s'", leasefile); - duid = nm_dhcp_dhclient_read_duid (leasefile, &error); - if (error) { - _LOGW ("failed to read leasefile '%s': %s", - leasefile, error->message); - g_clear_error (&error); - } - if (duid) - return duid; - } - - /* Otherwise read the default machine-wide DUID */ - _LOGD ("looking for default DUID in '%s'", priv->def_leasefile); - duid = nm_dhcp_dhclient_read_duid (priv->def_leasefile, &error); - if (error) { - _LOGW ("failed to read leasefile '%s': %s", - priv->def_leasefile, - error->message); - g_clear_error (&error); - } - - return duid; + 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; + + /* 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), + NULL); + if (leasefile) { + _LOGD("looking for DUID in '%s'", leasefile); + duid = nm_dhcp_dhclient_read_duid(leasefile, &error); + if (error) { + _LOGW("failed to read leasefile '%s': %s", leasefile, error->message); + g_clear_error(&error); + } + if (duid) + return duid; + } + + /* Otherwise, read the default machine-wide DUID */ + _LOGD("looking for default DUID in '%s'", priv->def_leasefile); + duid = nm_dhcp_dhclient_read_duid(priv->def_leasefile, &error); + if (error) { + _LOGW("failed to read leasefile '%s': %s", priv->def_leasefile, error->message); + g_clear_error(&error); + } + + return duid; } /*****************************************************************************/ static void -nm_dhcp_dhclient_init (NMDhcpDhclient *self) +nm_dhcp_dhclient_init(NMDhcpDhclient *self) { - static const char *const FILES[] = { - SYSCONFDIR "/dhclient6.leases", /* default */ - LOCALSTATEDIR "/lib/dhcp/dhclient6.leases", - LOCALSTATEDIR "/lib/dhclient/dhclient6.leases", - }; - NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (self); - int i; - - priv->def_leasefile = FILES[0]; - for (i = 0; i < G_N_ELEMENTS (FILES); i++) { - if (g_file_test (FILES[i], G_FILE_TEST_EXISTS)) { - priv->def_leasefile = FILES[i]; - break; - } - } - - priv->dhcp_listener = g_object_ref (nm_dhcp_listener_get ()); - g_signal_connect (priv->dhcp_listener, - NM_DHCP_LISTENER_EVENT, - G_CALLBACK (nm_dhcp_client_handle_event), - self); + static const char *const FILES[] = { + SYSCONFDIR "/dhclient6.leases", /* default */ + LOCALSTATEDIR "/lib/dhcp/dhclient6.leases", + LOCALSTATEDIR "/lib/dhclient/dhclient6.leases", + }; + NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(self); + int i; + + priv->def_leasefile = FILES[0]; + for (i = 0; i < G_N_ELEMENTS(FILES); i++) { + if (g_file_test(FILES[i], G_FILE_TEST_EXISTS)) { + priv->def_leasefile = FILES[i]; + break; + } + } + + priv->dhcp_listener = g_object_ref(nm_dhcp_listener_get()); + g_signal_connect(priv->dhcp_listener, + NM_DHCP_LISTENER_EVENT, + G_CALLBACK(nm_dhcp_client_handle_event), + self); } static void -dispose (GObject *object) +dispose(GObject *object) { - NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE (object); + NMDhcpDhclientPrivate *priv = NM_DHCP_DHCLIENT_GET_PRIVATE(object); - if (priv->dhcp_listener) { - g_signal_handlers_disconnect_by_func (priv->dhcp_listener, - G_CALLBACK (nm_dhcp_client_handle_event), - NM_DHCP_DHCLIENT (object)); - g_clear_object (&priv->dhcp_listener); - } + if (priv->dhcp_listener) { + g_signal_handlers_disconnect_by_func(priv->dhcp_listener, + G_CALLBACK(nm_dhcp_client_handle_event), + NM_DHCP_DHCLIENT(object)); + g_clear_object(&priv->dhcp_listener); + } - nm_clear_g_free (&priv->pid_file); - nm_clear_g_free (&priv->conf_file); - nm_clear_g_free (&priv->lease_file); + nm_clear_g_free(&priv->pid_file); + nm_clear_g_free(&priv->conf_file); + nm_clear_g_free(&priv->lease_file); - G_OBJECT_CLASS (nm_dhcp_dhclient_parent_class)->dispose (object); + G_OBJECT_CLASS(nm_dhcp_dhclient_parent_class)->dispose(object); } static void -nm_dhcp_dhclient_class_init (NMDhcpDhclientClass *dhclient_class) +nm_dhcp_dhclient_class_init(NMDhcpDhclientClass *dhclient_class) { - NMDhcpClientClass *client_class = NM_DHCP_CLIENT_CLASS (dhclient_class); - GObjectClass *object_class = G_OBJECT_CLASS (dhclient_class); + NMDhcpClientClass *client_class = NM_DHCP_CLIENT_CLASS(dhclient_class); + GObjectClass * object_class = G_OBJECT_CLASS(dhclient_class); - object_class->dispose = dispose; + object_class->dispose = dispose; - client_class->ip4_start = ip4_start; - client_class->ip6_start = ip6_start; - client_class->stop = stop; - client_class->get_duid = get_duid; + client_class->ip4_start = ip4_start; + client_class->ip6_start = ip6_start; + client_class->stop = stop; + client_class->get_duid = get_duid; } const NMDhcpClientFactory _nm_dhcp_client_factory_dhclient = { - .name = "dhclient", - .get_type = nm_dhcp_dhclient_get_type, - .get_path = nm_dhcp_dhclient_get_path, + .name = "dhclient", + .get_type = nm_dhcp_dhclient_get_type, + .get_path = nm_dhcp_dhclient_get_path, }; #endif /* WITH_DHCLIENT */ diff --git a/src/dhcp/nm-dhcp-dhcpcanon.c b/src/dhcp/nm-dhcp-dhcpcanon.c index 63484a4b..8e61b6e5 100644 --- a/src/dhcp/nm-dhcp-dhcpcanon.c +++ b/src/dhcp/nm-dhcp-dhcpcanon.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2017 juga <juga at riseup dot net> */ @@ -7,236 +7,237 @@ #if WITH_DHCPCANON -#include <stdlib.h> -#include <unistd.h> - -#include "nm-utils.h" -#include "nm-dhcp-manager.h" -#include "NetworkManagerUtils.h" -#include "nm-dhcp-listener.h" -#include "nm-dhcp-client-logging.h" - -#define NM_TYPE_DHCP_DHCPCANON (nm_dhcp_dhcpcanon_get_type ()) -#define NM_DHCP_DHCPCANON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DHCP_DHCPCANON, NMDhcpDhcpcanon)) -#define NM_DHCP_DHCPCANON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DHCP_DHCPCANON, NMDhcpDhcpcanonClass)) -#define NM_IS_DHCP_DHCPCANON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DHCP_DHCPCANON)) -#define NM_IS_DHCP_DHCPCANON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DHCP_DHCPCANON)) -#define NM_DHCP_DHCPCANON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DHCP_DHCPCANON, NMDhcpDhcpcanonClass)) - -typedef struct _NMDhcpDhcpcanon NMDhcpDhcpcanon; + #include <stdlib.h> + #include <unistd.h> + + #include "nm-utils.h" + #include "nm-dhcp-manager.h" + #include "NetworkManagerUtils.h" + #include "nm-dhcp-listener.h" + #include "nm-dhcp-client-logging.h" + + #define NM_TYPE_DHCP_DHCPCANON (nm_dhcp_dhcpcanon_get_type()) + #define NM_DHCP_DHCPCANON(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DHCP_DHCPCANON, NMDhcpDhcpcanon)) + #define NM_DHCP_DHCPCANON_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DHCP_DHCPCANON, NMDhcpDhcpcanonClass)) + #define NM_IS_DHCP_DHCPCANON(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DHCP_DHCPCANON)) + #define NM_IS_DHCP_DHCPCANON_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DHCP_DHCPCANON)) + #define NM_DHCP_DHCPCANON_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DHCP_DHCPCANON, NMDhcpDhcpcanonClass)) + +typedef struct _NMDhcpDhcpcanon NMDhcpDhcpcanon; typedef struct _NMDhcpDhcpcanonClass NMDhcpDhcpcanonClass; -static GType nm_dhcp_dhcpcanon_get_type (void); +static GType nm_dhcp_dhcpcanon_get_type(void); /*****************************************************************************/ typedef struct { - char *conf_file; - const char *def_leasefile; - char *lease_file; - char *pid_file; - NMDhcpListener *dhcp_listener; + char * conf_file; + const char * def_leasefile; + char * lease_file; + char * pid_file; + NMDhcpListener *dhcp_listener; } NMDhcpDhcpcanonPrivate; struct _NMDhcpDhcpcanon { - NMDhcpClient parent; - NMDhcpDhcpcanonPrivate _priv; + NMDhcpClient parent; + NMDhcpDhcpcanonPrivate _priv; }; struct _NMDhcpDhcpcanonClass { - NMDhcpClientClass parent; + NMDhcpClientClass parent; }; -G_DEFINE_TYPE (NMDhcpDhcpcanon, nm_dhcp_dhcpcanon, NM_TYPE_DHCP_CLIENT) +G_DEFINE_TYPE(NMDhcpDhcpcanon, nm_dhcp_dhcpcanon, NM_TYPE_DHCP_CLIENT) -#define NM_DHCP_DHCPCANON_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDhcpDhcpcanon, NM_IS_DHCP_DHCPCANON) + #define NM_DHCP_DHCPCANON_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMDhcpDhcpcanon, NM_IS_DHCP_DHCPCANON) /*****************************************************************************/ static const char * -nm_dhcp_dhcpcanon_get_path (void) +nm_dhcp_dhcpcanon_get_path(void) { - return nm_utils_find_helper ("dhcpcanon", DHCPCANON_PATH, NULL); + return nm_utils_find_helper("dhcpcanon", DHCPCANON_PATH, NULL); } static gboolean -dhcpcanon_start (NMDhcpClient *client, - const char *mode_opt, - GBytes *duid, - gboolean release, - pid_t *out_pid, - guint needed_prefixes, - GError **error) +dhcpcanon_start(NMDhcpClient *client, + const char * mode_opt, + GBytes * duid, + gboolean release, + pid_t * out_pid, + guint needed_prefixes, + GError ** error) { - NMDhcpDhcpcanon *self = NM_DHCP_DHCPCANON (client); - NMDhcpDhcpcanonPrivate *priv = NM_DHCP_DHCPCANON_GET_PRIVATE (self); - gs_unref_ptrarray GPtrArray *argv = NULL; - pid_t pid; - gs_free_error GError *local = NULL; - const char *iface; - const char *system_bus_address; - const char *dhcpcanon_path; - gs_free char *binary_name = NULL; - gs_free char *pid_file = NULL; - gs_free char *system_bus_address_env = NULL; - int addr_family; - - g_return_val_if_fail (!priv->pid_file, FALSE); - - iface = nm_dhcp_client_get_iface (client); - - addr_family = nm_dhcp_client_get_addr_family (client); - - dhcpcanon_path = nm_dhcp_dhcpcanon_get_path (); - if (!dhcpcanon_path) { - nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "dhcpcanon binary not found"); - return FALSE; - } - - _LOGD ("dhcpcanon_path: %s", dhcpcanon_path); - - pid_file = g_strdup_printf (RUNSTATEDIR "/dhcpcanon%c-%s.pid", - nm_utils_addr_family_to_char (addr_family), - iface); - _LOGD ("pid_file: %s", pid_file); - - /* Kill any existing dhcpcanon from the pidfile */ - binary_name = g_path_get_basename (dhcpcanon_path); - nm_dhcp_client_stop_existing (pid_file, binary_name); - - argv = g_ptr_array_new (); - g_ptr_array_add (argv, (gpointer) dhcpcanon_path); - - g_ptr_array_add (argv, (gpointer) "-sf"); /* Set script file */ - g_ptr_array_add (argv, (gpointer) nm_dhcp_helper_path); - - g_ptr_array_add (argv, (gpointer) "-pf"); /* Set pid file */ - g_ptr_array_add (argv, (gpointer) pid_file); - - if (priv->conf_file) { - g_ptr_array_add (argv, (gpointer) "-cf"); /* Set interface config file */ - g_ptr_array_add (argv, (gpointer) priv->conf_file); - } - - /* Usually the system bus address is well-known; but if it's supposed - * to be something else, we need to push it to dhcpcanon, since dhcpcanon - * sanitizes the environment it gives the action scripts. - */ - system_bus_address = getenv ("DBUS_SYSTEM_BUS_ADDRESS"); - if (system_bus_address) { - system_bus_address_env = g_strdup_printf ("DBUS_SYSTEM_BUS_ADDRESS=%s", system_bus_address); - g_ptr_array_add (argv, (gpointer) "-e"); - g_ptr_array_add (argv, (gpointer) system_bus_address_env); - } - - g_ptr_array_add (argv, (gpointer) iface); - g_ptr_array_add (argv, NULL); - - if (!g_spawn_async (NULL, - (char **) argv->pdata, - NULL, - G_SPAWN_DO_NOT_REAP_CHILD - | G_SPAWN_STDOUT_TO_DEV_NULL - | G_SPAWN_STDERR_TO_DEV_NULL, - nm_utils_setpgid, - NULL, - &pid, - &local)) { - nm_utils_error_set (error, - NM_UTILS_ERROR_UNKNOWN, - "dhcpcanon failed to start: %s", - local->message); - return FALSE; - } - - nm_assert (pid > 0); - _LOGI ("dhcpcanon started with pid %d", pid); - nm_dhcp_client_watch_child (client, pid); - priv->pid_file = g_steal_pointer (&pid_file); - return TRUE; + NMDhcpDhcpcanon * self = NM_DHCP_DHCPCANON(client); + NMDhcpDhcpcanonPrivate *priv = NM_DHCP_DHCPCANON_GET_PRIVATE(self); + gs_unref_ptrarray GPtrArray *argv = NULL; + pid_t pid; + gs_free_error GError *local = NULL; + const char * iface; + const char * system_bus_address; + const char * dhcpcanon_path; + gs_free char * binary_name = NULL; + gs_free char * pid_file = NULL; + gs_free char * system_bus_address_env = NULL; + int addr_family; + + g_return_val_if_fail(!priv->pid_file, FALSE); + + iface = nm_dhcp_client_get_iface(client); + + addr_family = nm_dhcp_client_get_addr_family(client); + + dhcpcanon_path = nm_dhcp_dhcpcanon_get_path(); + if (!dhcpcanon_path) { + nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "dhcpcanon binary not found"); + return FALSE; + } + + _LOGD("dhcpcanon_path: %s", dhcpcanon_path); + + pid_file = g_strdup_printf(RUNSTATEDIR "/dhcpcanon%c-%s.pid", + nm_utils_addr_family_to_char(addr_family), + iface); + _LOGD("pid_file: %s", pid_file); + + /* Kill any existing dhcpcanon from the pidfile */ + binary_name = g_path_get_basename(dhcpcanon_path); + nm_dhcp_client_stop_existing(pid_file, binary_name); + + argv = g_ptr_array_new(); + g_ptr_array_add(argv, (gpointer) dhcpcanon_path); + + g_ptr_array_add(argv, (gpointer) "-sf"); /* Set script file */ + g_ptr_array_add(argv, (gpointer) nm_dhcp_helper_path); + + g_ptr_array_add(argv, (gpointer) "-pf"); /* Set pid file */ + g_ptr_array_add(argv, (gpointer) pid_file); + + if (priv->conf_file) { + g_ptr_array_add(argv, (gpointer) "-cf"); /* Set interface config file */ + g_ptr_array_add(argv, (gpointer) priv->conf_file); + } + + /* Usually the system bus address is well-known; but if it's supposed + * to be something else, we need to push it to dhcpcanon, since dhcpcanon + * sanitizes the environment it gives the action scripts. + */ + system_bus_address = getenv("DBUS_SYSTEM_BUS_ADDRESS"); + if (system_bus_address) { + system_bus_address_env = g_strdup_printf("DBUS_SYSTEM_BUS_ADDRESS=%s", system_bus_address); + g_ptr_array_add(argv, (gpointer) "-e"); + g_ptr_array_add(argv, (gpointer) system_bus_address_env); + } + + g_ptr_array_add(argv, (gpointer) iface); + g_ptr_array_add(argv, NULL); + + if (!g_spawn_async(NULL, + (char **) argv->pdata, + NULL, + G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_STDOUT_TO_DEV_NULL + | G_SPAWN_STDERR_TO_DEV_NULL, + nm_utils_setpgid, + NULL, + &pid, + &local)) { + nm_utils_error_set(error, + NM_UTILS_ERROR_UNKNOWN, + "dhcpcanon failed to start: %s", + local->message); + return FALSE; + } + + nm_assert(pid > 0); + _LOGI("dhcpcanon started with pid %d", pid); + nm_dhcp_client_watch_child(client, pid); + priv->pid_file = g_steal_pointer(&pid_file); + return TRUE; } static gboolean -ip4_start (NMDhcpClient *client, - const char *dhcp_anycast_addr, - const char *last_ip4_address, - GError **error) +ip4_start(NMDhcpClient *client, + const char * dhcp_anycast_addr, + const char * last_ip4_address, + GError ** error) { - return dhcpcanon_start (client, - NULL, - NULL, - FALSE, - NULL, - 0, - error); + return dhcpcanon_start(client, NULL, NULL, FALSE, NULL, 0, error); } static void -stop (NMDhcpClient *client, gboolean release) +stop(NMDhcpClient *client, gboolean release) { - NMDhcpDhcpcanon *self = NM_DHCP_DHCPCANON (client); - NMDhcpDhcpcanonPrivate *priv = NM_DHCP_DHCPCANON_GET_PRIVATE (self); - int errsv; - - NM_DHCP_CLIENT_CLASS (nm_dhcp_dhcpcanon_parent_class)->stop (client, release); - - if (priv->pid_file) { - if (remove (priv->pid_file) == -1) { - errsv = errno; - _LOGD ("could not remove dhcp pid file \"%s\": %d (%s)", priv->pid_file, errsv, nm_strerror_native (errsv)); - } - g_free (priv->pid_file); - priv->pid_file = NULL; - } + NMDhcpDhcpcanon * self = NM_DHCP_DHCPCANON(client); + NMDhcpDhcpcanonPrivate *priv = NM_DHCP_DHCPCANON_GET_PRIVATE(self); + int errsv; + + NM_DHCP_CLIENT_CLASS(nm_dhcp_dhcpcanon_parent_class)->stop(client, release); + + if (priv->pid_file) { + if (remove(priv->pid_file) == -1) { + errsv = errno; + _LOGD("could not remove dhcp pid file \"%s\": %d (%s)", + priv->pid_file, + errsv, + nm_strerror_native(errsv)); + } + g_free(priv->pid_file); + priv->pid_file = NULL; + } } /*****************************************************************************/ static void -nm_dhcp_dhcpcanon_init (NMDhcpDhcpcanon *self) +nm_dhcp_dhcpcanon_init(NMDhcpDhcpcanon *self) { - NMDhcpDhcpcanonPrivate *priv = NM_DHCP_DHCPCANON_GET_PRIVATE (self); + NMDhcpDhcpcanonPrivate *priv = NM_DHCP_DHCPCANON_GET_PRIVATE(self); - priv->dhcp_listener = g_object_ref (nm_dhcp_listener_get ()); - g_signal_connect (priv->dhcp_listener, - NM_DHCP_LISTENER_EVENT, - G_CALLBACK (nm_dhcp_client_handle_event), - self); + priv->dhcp_listener = g_object_ref(nm_dhcp_listener_get()); + g_signal_connect(priv->dhcp_listener, + NM_DHCP_LISTENER_EVENT, + G_CALLBACK(nm_dhcp_client_handle_event), + self); } static void -dispose (GObject *object) +dispose(GObject *object) { - NMDhcpDhcpcanonPrivate *priv = NM_DHCP_DHCPCANON_GET_PRIVATE (object); + NMDhcpDhcpcanonPrivate *priv = NM_DHCP_DHCPCANON_GET_PRIVATE(object); - if (priv->dhcp_listener) { - g_signal_handlers_disconnect_by_func (priv->dhcp_listener, - G_CALLBACK (nm_dhcp_client_handle_event), - NM_DHCP_DHCPCANON (object)); - g_clear_object (&priv->dhcp_listener); - } + if (priv->dhcp_listener) { + g_signal_handlers_disconnect_by_func(priv->dhcp_listener, + G_CALLBACK(nm_dhcp_client_handle_event), + NM_DHCP_DHCPCANON(object)); + g_clear_object(&priv->dhcp_listener); + } - nm_clear_g_free (&priv->pid_file); + nm_clear_g_free(&priv->pid_file); - G_OBJECT_CLASS (nm_dhcp_dhcpcanon_parent_class)->dispose (object); + G_OBJECT_CLASS(nm_dhcp_dhcpcanon_parent_class)->dispose(object); } static void -nm_dhcp_dhcpcanon_class_init (NMDhcpDhcpcanonClass *dhcpcanon_class) +nm_dhcp_dhcpcanon_class_init(NMDhcpDhcpcanonClass *dhcpcanon_class) { - NMDhcpClientClass *client_class = NM_DHCP_CLIENT_CLASS (dhcpcanon_class); - GObjectClass *object_class = G_OBJECT_CLASS (dhcpcanon_class); + NMDhcpClientClass *client_class = NM_DHCP_CLIENT_CLASS(dhcpcanon_class); + GObjectClass * object_class = G_OBJECT_CLASS(dhcpcanon_class); - object_class->dispose = dispose; + object_class->dispose = dispose; - client_class->ip4_start = ip4_start; - client_class->stop = stop; + client_class->ip4_start = ip4_start; + client_class->stop = stop; } const NMDhcpClientFactory _nm_dhcp_client_factory_dhcpcanon = { - .name = "dhcpcanon", - .get_type = nm_dhcp_dhcpcanon_get_type, - .get_path = nm_dhcp_dhcpcanon_get_path, + .name = "dhcpcanon", + .get_type = nm_dhcp_dhcpcanon_get_type, + .get_path = nm_dhcp_dhcpcanon_get_path, }; #endif /* WITH_DHCPCANON */ diff --git a/src/dhcp/nm-dhcp-dhcpcd.c b/src/dhcp/nm-dhcp-dhcpcd.c index ff695dbe..b2b5d28b 100644 --- a/src/dhcp/nm-dhcp-dhcpcd.c +++ b/src/dhcp/nm-dhcp-dhcpcd.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2008 Roy Marples * Copyright (C) 2010 Dan Williams <dcbw@redhat.com> @@ -8,228 +8,233 @@ #if WITH_DHCPCD -#include <stdlib.h> -#include <unistd.h> -#include <stdio.h> -#include <netinet/in.h> -#include <arpa/inet.h> + #include <stdlib.h> + #include <unistd.h> + #include <stdio.h> + #include <netinet/in.h> + #include <arpa/inet.h> -#include "nm-dhcp-manager.h" -#include "nm-utils.h" -#include "NetworkManagerUtils.h" -#include "nm-dhcp-listener.h" -#include "nm-dhcp-client-logging.h" + #include "nm-dhcp-manager.h" + #include "nm-utils.h" + #include "NetworkManagerUtils.h" + #include "nm-dhcp-listener.h" + #include "nm-dhcp-client-logging.h" /*****************************************************************************/ -#define NM_TYPE_DHCP_DHCPCD (nm_dhcp_dhcpcd_get_type ()) -#define NM_DHCP_DHCPCD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DHCP_DHCPCD, NMDhcpDhcpcd)) -#define NM_DHCP_DHCPCD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DHCP_DHCPCD, NMDhcpDhcpcdClass)) -#define NM_IS_DHCP_DHCPCD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DHCP_DHCPCD)) -#define NM_IS_DHCP_DHCPCD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DHCP_DHCPCD)) -#define NM_DHCP_DHCPCD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DHCP_DHCPCD, NMDhcpDhcpcdClass)) - -typedef struct _NMDhcpDhcpcd NMDhcpDhcpcd; + #define NM_TYPE_DHCP_DHCPCD (nm_dhcp_dhcpcd_get_type()) + #define NM_DHCP_DHCPCD(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DHCP_DHCPCD, NMDhcpDhcpcd)) + #define NM_DHCP_DHCPCD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DHCP_DHCPCD, NMDhcpDhcpcdClass)) + #define NM_IS_DHCP_DHCPCD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DHCP_DHCPCD)) + #define NM_IS_DHCP_DHCPCD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DHCP_DHCPCD)) + #define NM_DHCP_DHCPCD_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DHCP_DHCPCD, NMDhcpDhcpcdClass)) + +typedef struct _NMDhcpDhcpcd NMDhcpDhcpcd; typedef struct _NMDhcpDhcpcdClass NMDhcpDhcpcdClass; -static GType nm_dhcp_dhcpcd_get_type (void); +static GType nm_dhcp_dhcpcd_get_type(void); /*****************************************************************************/ typedef struct { - char *pid_file; - NMDhcpListener *dhcp_listener; + char * pid_file; + NMDhcpListener *dhcp_listener; } NMDhcpDhcpcdPrivate; struct _NMDhcpDhcpcd { - NMDhcpClient parent; - NMDhcpDhcpcdPrivate _priv; + NMDhcpClient parent; + NMDhcpDhcpcdPrivate _priv; }; struct _NMDhcpDhcpcdClass { - NMDhcpClientClass parent; + NMDhcpClientClass parent; }; -G_DEFINE_TYPE (NMDhcpDhcpcd, nm_dhcp_dhcpcd, NM_TYPE_DHCP_CLIENT) +G_DEFINE_TYPE(NMDhcpDhcpcd, nm_dhcp_dhcpcd, NM_TYPE_DHCP_CLIENT) -#define NM_DHCP_DHCPCD_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDhcpDhcpcd, NM_IS_DHCP_DHCPCD) + #define NM_DHCP_DHCPCD_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDhcpDhcpcd, NM_IS_DHCP_DHCPCD) /*****************************************************************************/ static const char * -nm_dhcp_dhcpcd_get_path (void) +nm_dhcp_dhcpcd_get_path(void) { - return nm_utils_find_helper ("dhcpcd", DHCPCD_PATH, NULL); + return nm_utils_find_helper("dhcpcd", DHCPCD_PATH, NULL); } static gboolean -ip4_start (NMDhcpClient *client, - const char *dhcp_anycast_addr, - const char *last_ip4_address, - GError **error) +ip4_start(NMDhcpClient *client, + const char * dhcp_anycast_addr, + const char * last_ip4_address, + GError ** error) { - NMDhcpDhcpcd *self = NM_DHCP_DHCPCD (client); - NMDhcpDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE (self); - gs_unref_ptrarray GPtrArray *argv = NULL; - pid_t pid = -1; - GError *local = NULL; - gs_free char *cmd_str = NULL; - gs_free char *binary_name = NULL; - const char *iface; - const char *dhcpcd_path; - const char *hostname; - - g_return_val_if_fail (priv->pid_file == NULL, FALSE); - - iface = nm_dhcp_client_get_iface (client); - - /* dhcpcd does not allow custom pidfiles; the pidfile is always - * RUNSTATEDIR "dhcpcd-<ifname>.pid". - */ - priv->pid_file = g_strdup_printf (RUNSTATEDIR "/dhcpcd-%s.pid", iface); - - dhcpcd_path = nm_dhcp_dhcpcd_get_path (); - if (!dhcpcd_path) { - nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "dhcpcd binary not found"); - return FALSE; - } - - /* Kill any existing dhcpcd from the pidfile */ - binary_name = g_path_get_basename (dhcpcd_path); - nm_dhcp_client_stop_existing (priv->pid_file, binary_name); - - argv = g_ptr_array_new (); - g_ptr_array_add (argv, (gpointer) dhcpcd_path); - - g_ptr_array_add (argv, (gpointer) "-B"); /* Don't background on lease (disable fork()) */ - - g_ptr_array_add (argv, (gpointer) "-K"); /* Disable built-in carrier detection */ - - g_ptr_array_add (argv, (gpointer) "-L"); /* Disable built-in IPv4LL */ - - /* --noarp. Don't request or claim the address by ARP; this also disables IPv4LL. */ - g_ptr_array_add (argv, (gpointer) "-A"); - - g_ptr_array_add (argv, (gpointer) "-G"); /* Let NM handle routing */ - - g_ptr_array_add (argv, (gpointer) "-c"); /* Set script file */ - g_ptr_array_add (argv, (gpointer) nm_dhcp_helper_path); - - /* IPv4-only for now. NetworkManager knows better than dhcpcd when to - * run IPv6, and dhcpcd's automatic Router Solicitations cause problems - * with devices that don't expect them. - */ - g_ptr_array_add (argv, (gpointer) "-4"); - - hostname = nm_dhcp_client_get_hostname (client); - - if (hostname) { - if (nm_dhcp_client_get_use_fqdn (client)) { - g_ptr_array_add (argv, (gpointer) "-h"); - g_ptr_array_add (argv, (gpointer) 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) iface); - g_ptr_array_add (argv, NULL); - - _LOGD ("running: %s", - (cmd_str = g_strjoinv (" ", (char **) argv->pdata))); - - if (!g_spawn_async (NULL, - (char **) argv->pdata, NULL, - G_SPAWN_DO_NOT_REAP_CHILD - | G_SPAWN_STDOUT_TO_DEV_NULL - | G_SPAWN_STDERR_TO_DEV_NULL, - nm_utils_setpgid, - NULL, - &pid, - &local)) { - nm_utils_error_set (error, - NM_UTILS_ERROR_UNKNOWN, - "dhcpcd failed to start: %s", - local->message); - g_error_free (local); - return FALSE; - } - - nm_assert (pid > 0); - _LOGI ("dhcpcd started with pid %d", pid); - nm_dhcp_client_watch_child (client, pid); - return TRUE; + NMDhcpDhcpcd * self = NM_DHCP_DHCPCD(client); + NMDhcpDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE(self); + gs_unref_ptrarray GPtrArray *argv = NULL; + pid_t pid = -1; + GError * local = NULL; + gs_free char * cmd_str = NULL; + gs_free char * binary_name = NULL; + const char * iface; + const char * dhcpcd_path; + const char * hostname; + + g_return_val_if_fail(priv->pid_file == NULL, FALSE); + + iface = nm_dhcp_client_get_iface(client); + + /* dhcpcd does not allow custom pidfiles; the pidfile is always + * RUNSTATEDIR "dhcpcd-<ifname>.pid". + */ + priv->pid_file = g_strdup_printf(RUNSTATEDIR "/dhcpcd-%s.pid", iface); + + dhcpcd_path = nm_dhcp_dhcpcd_get_path(); + if (!dhcpcd_path) { + nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "dhcpcd binary not found"); + return FALSE; + } + + /* Kill any existing dhcpcd from the pidfile */ + binary_name = g_path_get_basename(dhcpcd_path); + nm_dhcp_client_stop_existing(priv->pid_file, binary_name); + + argv = g_ptr_array_new(); + g_ptr_array_add(argv, (gpointer) dhcpcd_path); + + g_ptr_array_add(argv, (gpointer) "-B"); /* Don't background on lease (disable fork()) */ + + g_ptr_array_add(argv, (gpointer) "-K"); /* Disable built-in carrier detection */ + + g_ptr_array_add(argv, (gpointer) "-L"); /* Disable built-in IPv4LL */ + + /* --noarp. Don't request or claim the address by ARP; this also disables IPv4LL. */ + g_ptr_array_add(argv, (gpointer) "-A"); + + g_ptr_array_add(argv, (gpointer) "-G"); /* Let NM handle routing */ + + g_ptr_array_add(argv, (gpointer) "-c"); /* Set script file */ + g_ptr_array_add(argv, (gpointer) nm_dhcp_helper_path); + + /* IPv4-only for now. NetworkManager knows better than dhcpcd when to + * run IPv6, and dhcpcd's automatic Router Solicitations cause problems + * with devices that don't expect them. + */ + g_ptr_array_add(argv, (gpointer) "-4"); + + hostname = nm_dhcp_client_get_hostname(client); + + if (hostname) { + if (nm_dhcp_client_get_use_fqdn(client)) { + g_ptr_array_add(argv, (gpointer) "-h"); + g_ptr_array_add(argv, (gpointer) 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) iface); + g_ptr_array_add(argv, NULL); + + _LOGD("running: %s", (cmd_str = g_strjoinv(" ", (char **) argv->pdata))); + + if (!g_spawn_async(NULL, + (char **) argv->pdata, + NULL, + G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_STDOUT_TO_DEV_NULL + | G_SPAWN_STDERR_TO_DEV_NULL, + nm_utils_setpgid, + NULL, + &pid, + &local)) { + nm_utils_error_set(error, + NM_UTILS_ERROR_UNKNOWN, + "dhcpcd failed to start: %s", + local->message); + g_error_free(local); + return FALSE; + } + + nm_assert(pid > 0); + _LOGI("dhcpcd started with pid %d", pid); + nm_dhcp_client_watch_child(client, pid); + return TRUE; } static void -stop (NMDhcpClient *client, gboolean release) +stop(NMDhcpClient *client, gboolean release) { - NMDhcpDhcpcd *self = NM_DHCP_DHCPCD (client); - NMDhcpDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE (self); - int errsv; - - NM_DHCP_CLIENT_CLASS (nm_dhcp_dhcpcd_parent_class)->stop (client, release); - - if (priv->pid_file) { - if (remove (priv->pid_file) == -1) { - errsv = errno; - _LOGD ("could not remove dhcp pid file \"%s\": %d (%s)", priv->pid_file, errsv, nm_strerror_native (errsv)); - } - } - - /* FIXME: implement release... */ + NMDhcpDhcpcd * self = NM_DHCP_DHCPCD(client); + NMDhcpDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE(self); + int errsv; + + NM_DHCP_CLIENT_CLASS(nm_dhcp_dhcpcd_parent_class)->stop(client, release); + + if (priv->pid_file) { + if (remove(priv->pid_file) == -1) { + errsv = errno; + _LOGD("could not remove dhcp pid file \"%s\": %d (%s)", + priv->pid_file, + errsv, + nm_strerror_native(errsv)); + } + } + + /* FIXME: implement release... */ } /*****************************************************************************/ static void -nm_dhcp_dhcpcd_init (NMDhcpDhcpcd *self) +nm_dhcp_dhcpcd_init(NMDhcpDhcpcd *self) { - NMDhcpDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE (self); + NMDhcpDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE(self); - priv->dhcp_listener = g_object_ref (nm_dhcp_listener_get ()); - g_signal_connect (priv->dhcp_listener, - NM_DHCP_LISTENER_EVENT, - G_CALLBACK (nm_dhcp_client_handle_event), - self); + priv->dhcp_listener = g_object_ref(nm_dhcp_listener_get()); + g_signal_connect(priv->dhcp_listener, + NM_DHCP_LISTENER_EVENT, + G_CALLBACK(nm_dhcp_client_handle_event), + self); } static void -dispose (GObject *object) +dispose(GObject *object) { - NMDhcpDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE (object); + NMDhcpDhcpcdPrivate *priv = NM_DHCP_DHCPCD_GET_PRIVATE(object); - if (priv->dhcp_listener) { - g_signal_handlers_disconnect_by_func (priv->dhcp_listener, - G_CALLBACK (nm_dhcp_client_handle_event), - NM_DHCP_DHCPCD (object)); - g_clear_object (&priv->dhcp_listener); - } + if (priv->dhcp_listener) { + g_signal_handlers_disconnect_by_func(priv->dhcp_listener, + G_CALLBACK(nm_dhcp_client_handle_event), + NM_DHCP_DHCPCD(object)); + g_clear_object(&priv->dhcp_listener); + } - nm_clear_g_free (&priv->pid_file); + nm_clear_g_free(&priv->pid_file); - G_OBJECT_CLASS (nm_dhcp_dhcpcd_parent_class)->dispose (object); + G_OBJECT_CLASS(nm_dhcp_dhcpcd_parent_class)->dispose(object); } static void -nm_dhcp_dhcpcd_class_init (NMDhcpDhcpcdClass *dhcpcd_class) +nm_dhcp_dhcpcd_class_init(NMDhcpDhcpcdClass *dhcpcd_class) { - NMDhcpClientClass *client_class = NM_DHCP_CLIENT_CLASS (dhcpcd_class); - GObjectClass *object_class = G_OBJECT_CLASS (dhcpcd_class); + NMDhcpClientClass *client_class = NM_DHCP_CLIENT_CLASS(dhcpcd_class); + GObjectClass * object_class = G_OBJECT_CLASS(dhcpcd_class); - object_class->dispose = dispose; + object_class->dispose = dispose; - client_class->ip4_start = ip4_start; - client_class->stop = stop; + client_class->ip4_start = ip4_start; + client_class->stop = stop; } const NMDhcpClientFactory _nm_dhcp_client_factory_dhcpcd = { - .name = "dhcpcd", - .get_type = nm_dhcp_dhcpcd_get_type, - .get_path = nm_dhcp_dhcpcd_get_path, + .name = "dhcpcd", + .get_type = nm_dhcp_dhcpcd_get_type, + .get_path = nm_dhcp_dhcpcd_get_path, }; #endif /* WITH_DHCPCD */ diff --git a/src/dhcp/nm-dhcp-helper-api.h b/src/dhcp/nm-dhcp-helper-api.h index a03049aa..aa1d203a 100644 --- a/src/dhcp/nm-dhcp-helper-api.h +++ b/src/dhcp/nm-dhcp-helper-api.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: LGPL-2.1+ +/* SPDX-License-Identifier: LGPL-2.1+ */ /* * Copyright (C) 2016 Red Hat, Inc. */ @@ -10,10 +10,10 @@ #define NM_DHCP_CLIENT_DBUS_IFACE "org.freedesktop.nm_dhcp_client" -#define NM_DHCP_HELPER_SERVER_BUS_NAME "org.freedesktop.nm_dhcp_server" -#define NM_DHCP_HELPER_SERVER_OBJECT_PATH "/org/freedesktop/nm_dhcp_server" -#define NM_DHCP_HELPER_SERVER_INTERFACE_NAME "org.freedesktop.nm_dhcp_server" -#define NM_DHCP_HELPER_SERVER_METHOD_NOTIFY "Notify" +#define NM_DHCP_HELPER_SERVER_BUS_NAME "org.freedesktop.nm_dhcp_server" +#define NM_DHCP_HELPER_SERVER_OBJECT_PATH "/org/freedesktop/nm_dhcp_server" +#define NM_DHCP_HELPER_SERVER_INTERFACE_NAME "org.freedesktop.nm_dhcp_server" +#define NM_DHCP_HELPER_SERVER_METHOD_NOTIFY "Notify" /*****************************************************************************/ diff --git a/src/dhcp/nm-dhcp-helper.c b/src/dhcp/nm-dhcp-helper.c index 071d331b..84fa859d 100644 --- a/src/dhcp/nm-dhcp-helper.c +++ b/src/dhcp/nm-dhcp-helper.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2007 - 2013 Red Hat, Inc. */ @@ -16,234 +16,227 @@ /*****************************************************************************/ #if NM_MORE_LOGGING -#define _NMLOG_ENABLED(level) TRUE + #define _NMLOG_ENABLED(level) TRUE #else -#define _NMLOG_ENABLED(level) ((level) <= LOG_ERR) + #define _NMLOG_ENABLED(level) ((level) <= LOG_ERR) #endif -#define _NMLOG(always_enabled, level, ...) \ - G_STMT_START { \ - if ((always_enabled) || _NMLOG_ENABLED (level)) { \ - GTimeVal _tv; \ - \ - g_get_current_time (&_tv); \ - g_print ("nm-dhcp-helper[%ld] %-7s [%ld.%04ld] " _NM_UTILS_MACRO_FIRST (__VA_ARGS__) "\n", \ - (long) getpid (), \ - nm_utils_syslog_to_str (level), \ - _tv.tv_sec, _tv.tv_usec / 100 \ - _NM_UTILS_MACRO_REST (__VA_ARGS__)); \ - } \ - } G_STMT_END - -#define _LOGD(...) _NMLOG(TRUE, LOG_INFO, __VA_ARGS__) -#define _LOGI(...) _NMLOG(TRUE, LOG_NOTICE, __VA_ARGS__) -#define _LOGW(...) _NMLOG(TRUE, LOG_WARNING, __VA_ARGS__) -#define _LOGE(...) _NMLOG(TRUE, LOG_ERR, __VA_ARGS__) - -#define _LOGd(...) _NMLOG(FALSE, LOG_INFO, __VA_ARGS__) -#define _LOGi(...) _NMLOG(FALSE, LOG_NOTICE, __VA_ARGS__) +#define _NMLOG(always_enabled, level, ...) \ + G_STMT_START \ + { \ + if ((always_enabled) || _NMLOG_ENABLED(level)) { \ + GTimeVal _tv; \ + \ + g_get_current_time(&_tv); \ + g_print( \ + "nm-dhcp-helper[%ld] %-7s [%ld.%04ld] " _NM_UTILS_MACRO_FIRST(__VA_ARGS__) "\n", \ + (long) getpid(), \ + nm_utils_syslog_to_str(level), \ + _tv.tv_sec, \ + _tv.tv_usec / 100 _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + } \ + G_STMT_END + +#define _LOGD(...) _NMLOG(TRUE, LOG_INFO, __VA_ARGS__) +#define _LOGI(...) _NMLOG(TRUE, LOG_NOTICE, __VA_ARGS__) +#define _LOGW(...) _NMLOG(TRUE, LOG_WARNING, __VA_ARGS__) +#define _LOGE(...) _NMLOG(TRUE, LOG_ERR, __VA_ARGS__) + +#define _LOGd(...) _NMLOG(FALSE, LOG_INFO, __VA_ARGS__) +#define _LOGi(...) _NMLOG(FALSE, LOG_NOTICE, __VA_ARGS__) #define _LOGw(...) _NMLOG(FALSE, LOG_WARNING, __VA_ARGS__) /*****************************************************************************/ static GVariant * -build_signal_parameters (void) +build_signal_parameters(void) { - const char *const*environ_iter; - GVariantBuilder builder; - - g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT); - - /* List environment and format for dbus dict */ - for (environ_iter = (const char *const*) environ; *environ_iter; environ_iter++) { - static const char *const ignore_with_prefix_list[] = { - "PATH", - "SHLVL", - "_", - "PWD", - "dhc_dbus", - NULL - }; - const char *item = *environ_iter; - gs_free char *name = NULL; - const char *val; - const char *const*p; - - val = strchr (item, '='); - if ( !val - || item == val) - continue; - - name = g_strndup (item, val - item); - val += 1; - - /* Ignore non-DHCP-related environment variables */ - for (p = ignore_with_prefix_list; *p; p++) { - if (strncmp (name, *p, strlen (*p)) == 0) - goto next; - } - - if (!g_utf8_validate (name, -1, NULL)) - continue; - - /* Value passed as a byte array rather than a string, because there are - * no character encoding guarantees with DHCP, and D-Bus requires - * strings to be UTF-8. - * - * Note that we can't use g_variant_new_bytestring() here, because that - * includes the trailing '\0'. (??!?) - */ - g_variant_builder_add (&builder, "{sv}", - name, - g_variant_new_fixed_array (G_VARIANT_TYPE_BYTE, - val, strlen (val), 1)); - -next: - ; - } - - return g_variant_ref_sink (g_variant_new ("(a{sv})", &builder)); + const char *const *environ_iter; + GVariantBuilder builder; + + g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT); + + /* List environment and format for dbus dict */ + for (environ_iter = (const char *const *) environ; *environ_iter; environ_iter++) { + static const char *const ignore_with_prefix_list[] = + {"PATH", "SHLVL", "_", "PWD", "dhc_dbus", NULL}; + const char * item = *environ_iter; + gs_free char * name = NULL; + const char * val; + const char *const *p; + + val = strchr(item, '='); + if (!val || item == val) + continue; + + name = g_strndup(item, val - item); + val += 1; + + /* Ignore non-DHCP-related environment variables */ + for (p = ignore_with_prefix_list; *p; p++) { + if (strncmp(name, *p, strlen(*p)) == 0) + goto next; + } + + if (!g_utf8_validate(name, -1, NULL)) + continue; + + /* Value passed as a byte array rather than a string, because there are + * no character encoding guarantees with DHCP, and D-Bus requires + * strings to be UTF-8. + * + * Note that we can't use g_variant_new_bytestring() here, because that + * includes the trailing '\0'. (??!?) + */ + g_variant_builder_add(&builder, + "{sv}", + name, + g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, val, strlen(val), 1)); + +next:; + } + + return g_variant_ref_sink(g_variant_new("(a{sv})", &builder)); } static void -kill_pid (void) +kill_pid(void) { - const char *pid_str; - pid_t pid = 0; - - pid_str = getenv ("pid"); - if (pid_str) - pid = strtol (pid_str, NULL, 10); - if (pid) { - _LOGI ("a fatal error occurred, kill dhclient instance with pid %d", pid); - kill (pid, SIGTERM); - } + const char *pid_str; + pid_t pid = 0; + + pid_str = getenv("pid"); + if (pid_str) + pid = strtol(pid_str, NULL, 10); + if (pid) { + _LOGI("a fatal error occurred, kill dhclient instance with pid %d", pid); + kill(pid, SIGTERM); + } } int -main (int argc, char *argv[]) +main(int argc, char *argv[]) { - gs_unref_object GDBusConnection *connection = NULL; - gs_free_error GError *error = NULL; - gs_unref_variant GVariant *parameters = NULL; - gs_unref_variant GVariant *result = NULL; - gboolean success = FALSE; - guint try_count; - gint64 time_start; - gint64 time_end; - - /* Connecting to the unix socket can fail with EAGAIN if there are too - * many pending connections and the server can't accept them in time - * before reaching backlog capacity. Ideally the server should increase - * the backlog length, but GLib doesn't provide a way to change it for a - * GDBus server. Retry for up to 5 seconds in case of failure. */ - time_start = g_get_monotonic_time (); - time_end = time_start + (5000 * 1000L); - try_count = 0; + gs_unref_object GDBusConnection *connection = NULL; + gs_free_error GError *error = NULL; + gs_unref_variant GVariant *parameters = NULL; + gs_unref_variant GVariant *result = NULL; + gboolean success = FALSE; + guint try_count; + gint64 time_start; + gint64 time_end; + + /* Connecting to the unix socket can fail with EAGAIN if there are too + * many pending connections and the server can't accept them in time + * before reaching backlog capacity. Ideally the server should increase + * the backlog length, but GLib doesn't provide a way to change it for a + * GDBus server. Retry for up to 5 seconds in case of failure. */ + time_start = g_get_monotonic_time(); + time_end = time_start + (5000 * 1000L); + try_count = 0; do_connect: - try_count++; - connection = g_dbus_connection_new_for_address_sync ("unix:path=" NMRUNDIR "/private-dhcp", - G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, - NULL, NULL, &error); - if (!connection) { - if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { - gint64 time_remaining = time_end - g_get_monotonic_time (); - gint64 interval; - - if (time_remaining > 0) { - _LOGi ("failure to connect: %s (retry %u, waited %lld ms)", - error->message, try_count, - (long long) (time_end - time_remaining - time_start) / 1000); - interval = NM_CLAMP ((gint64) (100L * (1L << NM_MIN (try_count, 31))), - 5000, - 100000); - g_usleep (NM_MIN (interval, time_remaining)); - g_clear_error (&error); - goto do_connect; - } - } - - g_dbus_error_strip_remote_error (error); - _LOGE ("could not connect to NetworkManager D-Bus socket: %s", - error->message); - goto out; - } - - parameters = build_signal_parameters (); - time_end = g_get_monotonic_time () + (200 * 1000L); /* retry for at most 200 milliseconds */ - try_count = 0; + try_count++; + connection = + g_dbus_connection_new_for_address_sync("unix:path=" NMRUNDIR "/private-dhcp", + G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT, + NULL, + NULL, + &error); + if (!connection) { + if (g_error_matches(error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { + gint64 time_remaining = time_end - g_get_monotonic_time(); + gint64 interval; + + if (time_remaining > 0) { + _LOGi("failure to connect: %s (retry %u, waited %lld ms)", + error->message, + try_count, + (long long) (time_end - time_remaining - time_start) / 1000); + interval = NM_CLAMP((gint64)(100L * (1L << NM_MIN(try_count, 31))), 5000, 100000); + g_usleep(NM_MIN(interval, time_remaining)); + g_clear_error(&error); + goto do_connect; + } + } + + g_dbus_error_strip_remote_error(error); + _LOGE("could not connect to NetworkManager D-Bus socket: %s", error->message); + goto out; + } + + parameters = build_signal_parameters(); + time_end = g_get_monotonic_time() + (200 * 1000L); /* retry for at most 200 milliseconds */ + try_count = 0; do_notify: - try_count++; - result = g_dbus_connection_call_sync (connection, - NULL, - NM_DHCP_HELPER_SERVER_OBJECT_PATH, - NM_DHCP_HELPER_SERVER_INTERFACE_NAME, - NM_DHCP_HELPER_SERVER_METHOD_NOTIFY, - parameters, - NULL, - G_DBUS_CALL_FLAGS_NONE, - 1000, - NULL, - &error); - - if (!result) { - gs_free char *s_err = NULL; - - s_err = g_dbus_error_get_remote_error (error); - if (NM_IN_STRSET (s_err, "org.freedesktop.DBus.Error.UnknownMethod")) { - gint64 remaining_time = time_end - g_get_monotonic_time (); - gint64 interval; - - /* I am not sure that a race can actually happen, as we register the object - * on the server side during GDBusServer:new-connection signal. - * - * However, there was also a race for subscribing to an event, so let's just - * do some retry. */ - if (remaining_time > 0) { - _LOGi ("failure to call notify: %s (retry %u)", error->message, try_count); - interval = NM_CLAMP ((gint64) (100L * (1L << NM_MIN (try_count, 31))), - 5000, - 25000); - g_usleep (NM_MIN (interval, remaining_time)); - g_clear_error (&error); - goto do_notify; - } - } - _LOGW ("failure to call notify: %s (try signal via Event)", error->message); - g_clear_error (&error); - - /* for backward compatibility, try to emit the signal. There is no stable - * API between the dhcp-helper and NetworkManager. However, while upgrading - * the NetworkManager package, a newer helper might want to notify an - * older server, which still uses the "Event". */ - if (!g_dbus_connection_emit_signal (connection, - NULL, - "/", - NM_DHCP_CLIENT_DBUS_IFACE, - "Event", - parameters, - &error)) { - g_dbus_error_strip_remote_error (error); - _LOGE ("could not send DHCP Event signal: %s", error->message); - goto out; - } - /* We were able to send the asynchronous Event. Consider that a success. */ - success = TRUE; - } else - success = TRUE; - - if (!g_dbus_connection_flush_sync (connection, NULL, &error)) { - g_dbus_error_strip_remote_error (error); - _LOGE ("could not flush D-Bus connection: %s", error->message); - success = FALSE; - goto out; - } + try_count++; + result = g_dbus_connection_call_sync(connection, + NULL, + NM_DHCP_HELPER_SERVER_OBJECT_PATH, + NM_DHCP_HELPER_SERVER_INTERFACE_NAME, + NM_DHCP_HELPER_SERVER_METHOD_NOTIFY, + parameters, + NULL, + G_DBUS_CALL_FLAGS_NONE, + 1000, + NULL, + &error); + + if (!result) { + gs_free char *s_err = NULL; + + s_err = g_dbus_error_get_remote_error(error); + if (NM_IN_STRSET(s_err, "org.freedesktop.DBus.Error.UnknownMethod")) { + gint64 remaining_time = time_end - g_get_monotonic_time(); + gint64 interval; + + /* I am not sure that a race can actually happen, as we register the object + * on the server side during GDBusServer:new-connection signal. + * + * However, there was also a race for subscribing to an event, so let's just + * do some retry. */ + if (remaining_time > 0) { + _LOGi("failure to call notify: %s (retry %u)", error->message, try_count); + interval = NM_CLAMP((gint64)(100L * (1L << NM_MIN(try_count, 31))), 5000, 25000); + g_usleep(NM_MIN(interval, remaining_time)); + g_clear_error(&error); + goto do_notify; + } + } + _LOGW("failure to call notify: %s (try signal via Event)", error->message); + g_clear_error(&error); + + /* for backward compatibility, try to emit the signal. There is no stable + * API between the dhcp-helper and NetworkManager. However, while upgrading + * the NetworkManager package, a newer helper might want to notify an + * older server, which still uses the "Event". */ + if (!g_dbus_connection_emit_signal(connection, + NULL, + "/", + NM_DHCP_CLIENT_DBUS_IFACE, + "Event", + parameters, + &error)) { + g_dbus_error_strip_remote_error(error); + _LOGE("could not send DHCP Event signal: %s", error->message); + goto out; + } + /* We were able to send the asynchronous Event. Consider that a success. */ + success = TRUE; + } else + success = TRUE; + + if (!g_dbus_connection_flush_sync(connection, NULL, &error)) { + g_dbus_error_strip_remote_error(error); + _LOGE("could not flush D-Bus connection: %s", error->message); + success = FALSE; + goto out; + } out: - if (!success) - kill_pid (); - return success ? EXIT_SUCCESS : EXIT_FAILURE; + if (!success) + kill_pid(); + return success ? EXIT_SUCCESS : EXIT_FAILURE; } - diff --git a/src/dhcp/nm-dhcp-listener.c b/src/dhcp/nm-dhcp-listener.c index 79dea898..c90590d5 100644 --- a/src/dhcp/nm-dhcp-listener.c +++ b/src/dhcp/nm-dhcp-listener.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2014 - 2016 Red Hat, Inc. */ @@ -20,302 +20,299 @@ #include "nm-dbus-manager.h" #include "NetworkManagerUtils.h" -#define PRIV_SOCK_PATH NMRUNDIR "/private-dhcp" -#define PRIV_SOCK_TAG "dhcp" +#define PRIV_SOCK_PATH NMRUNDIR "/private-dhcp" +#define PRIV_SOCK_TAG "dhcp" /*****************************************************************************/ const NMDhcpClientFactory *const _nm_dhcp_manager_factories[6] = { - /* the order here matters, as we will try the plugins in this order to find - * the first available plugin. */ +/* the order here matters, as we will try the plugins in this order to find + * the first available plugin. */ #if WITH_DHCPCANON - &_nm_dhcp_client_factory_dhcpcanon, + &_nm_dhcp_client_factory_dhcpcanon, #endif #if WITH_DHCLIENT - &_nm_dhcp_client_factory_dhclient, + &_nm_dhcp_client_factory_dhclient, #endif #if WITH_DHCPCD - &_nm_dhcp_client_factory_dhcpcd, + &_nm_dhcp_client_factory_dhcpcd, #endif - &_nm_dhcp_client_factory_internal, - &_nm_dhcp_client_factory_systemd, - &_nm_dhcp_client_factory_nettools, + &_nm_dhcp_client_factory_internal, + &_nm_dhcp_client_factory_systemd, + &_nm_dhcp_client_factory_nettools, }; /*****************************************************************************/ typedef struct { - NMDBusManager *dbus_mgr; - gulong new_conn_id; - gulong dis_conn_id; - GHashTable *connections; + NMDBusManager *dbus_mgr; + gulong new_conn_id; + gulong dis_conn_id; + GHashTable * connections; } NMDhcpListenerPrivate; struct _NMDhcpListener { - GObject parent; - NMDhcpListenerPrivate _priv; + GObject parent; + NMDhcpListenerPrivate _priv; }; struct _NMDhcpListenerClass { - GObjectClass parent; + GObjectClass parent; }; -enum { - EVENT, - LAST_SIGNAL -}; -static guint signals[LAST_SIGNAL] = { 0 }; +enum { EVENT, LAST_SIGNAL }; +static guint signals[LAST_SIGNAL] = {0}; -G_DEFINE_TYPE (NMDhcpListener, nm_dhcp_listener, G_TYPE_OBJECT) +G_DEFINE_TYPE(NMDhcpListener, nm_dhcp_listener, G_TYPE_OBJECT) -#define NM_DHCP_LISTENER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDhcpListener, NM_IS_DHCP_LISTENER) +#define NM_DHCP_LISTENER_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMDhcpListener, NM_IS_DHCP_LISTENER) -NM_DEFINE_SINGLETON_GETTER (NMDhcpListener, nm_dhcp_listener_get, NM_TYPE_DHCP_LISTENER); +NM_DEFINE_SINGLETON_GETTER(NMDhcpListener, nm_dhcp_listener_get, NM_TYPE_DHCP_LISTENER); /*****************************************************************************/ -#define _NMLOG_PREFIX_NAME "dhcp-listener" -#define _NMLOG_DOMAIN LOGD_DHCP -#define _NMLOG(level, ...) \ - G_STMT_START { \ - const NMDhcpListener *_self = (self); \ - char _prefix[64]; \ - \ - nm_log ((level), (_NMLOG_DOMAIN), NULL, NULL, \ - "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ - (_self != singleton_instance \ - ? nm_sprintf_buf (_prefix, "%s[%p]", _NMLOG_PREFIX_NAME, _self) \ - : _NMLOG_PREFIX_NAME )\ - _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ - } G_STMT_END +#define _NMLOG_PREFIX_NAME "dhcp-listener" +#define _NMLOG_DOMAIN LOGD_DHCP +#define _NMLOG(level, ...) \ + G_STMT_START \ + { \ + const NMDhcpListener *_self = (self); \ + char _prefix[64]; \ + \ + nm_log((level), \ + (_NMLOG_DOMAIN), \ + NULL, \ + NULL, \ + "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \ + (_self != singleton_instance \ + ? nm_sprintf_buf(_prefix, "%s[%p]", _NMLOG_PREFIX_NAME, _self) \ + : _NMLOG_PREFIX_NAME) _NM_UTILS_MACRO_REST(__VA_ARGS__)); \ + } \ + G_STMT_END /*****************************************************************************/ static char * -get_option (GVariant *options, const char *key) +get_option(GVariant *options, const char *key) { - GVariant *value; - const guchar *bytes, *s; - gsize len; - char *converted, *d; - - if (!g_variant_lookup (options, key, "@ay", &value)) - return NULL; - - bytes = g_variant_get_fixed_array (value, &len, 1); - - /* Since the DHCP options come through environment variables, they should - * already be UTF-8 safe, but just make sure. - */ - converted = g_malloc (len + 1); - for (s = bytes, d = converted; s < bytes + len; s++, d++) { - /* Convert NULLs to spaces and non-ASCII characters to ? */ - if (*s == '\0') - *d = ' '; - else if (*s > 127) - *d = '?'; - else - *d = *s; - } - *d = '\0'; - g_variant_unref (value); - - return converted; + GVariant * value; + const guchar *bytes, *s; + gsize len; + char * converted, *d; + + if (!g_variant_lookup(options, key, "@ay", &value)) + return NULL; + + bytes = g_variant_get_fixed_array(value, &len, 1); + + /* Since the DHCP options come through environment variables, they should + * already be UTF-8 safe, but just make sure. + */ + converted = g_malloc(len + 1); + for (s = bytes, d = converted; s < bytes + len; s++, d++) { + /* Convert NULLs to spaces and non-ASCII characters to ? */ + if (*s == '\0') + *d = ' '; + else if (*s > 127) + *d = '?'; + else + *d = *s; + } + *d = '\0'; + g_variant_unref(value); + + return converted; } static void -_method_call_handle (NMDhcpListener *self, - GVariant *parameters) +_method_call_handle(NMDhcpListener *self, GVariant *parameters) { - gs_free char *iface = NULL; - gs_free char *pid_str = NULL; - gs_free char *reason = NULL; - gs_unref_variant GVariant *options = NULL; - int pid; - gboolean handled = FALSE; - - g_variant_get (parameters, "(@a{sv})", &options); - - iface = get_option (options, "interface"); - if (iface == NULL) { - _LOGW ("dhcp-event: didn't have associated interface."); - return; - } - - pid_str = get_option (options, "pid"); - pid = _nm_utils_ascii_str_to_int64 (pid_str, 10, 0, G_MAXINT32, -1); - if (pid == -1) { - _LOGW ("dhcp-event: couldn't convert PID '%s' to an integer", pid_str ?: "(null)"); - return; - } - - reason = get_option (options, "reason"); - if (reason == NULL) { - _LOGW ("dhcp-event: (pid %d) DHCP event didn't have a reason", pid); - return; - } - - g_signal_emit (self, signals[EVENT], 0, iface, pid, options, reason, &handled); - if (!handled) { - if (g_ascii_strcasecmp (reason, "RELEASE") == 0) { - /* Ignore event when the dhcp client gets killed and we receive its last message */ - _LOGD ("dhcp-event: (pid %d) unhandled RELEASE DHCP event for interface %s", pid, iface); - } else - _LOGW ("dhcp-event: (pid %d) unhandled DHCP event for interface %s", pid, iface); - } + gs_free char * iface = NULL; + gs_free char * pid_str = NULL; + gs_free char * reason = NULL; + gs_unref_variant GVariant *options = NULL; + int pid; + gboolean handled = FALSE; + + g_variant_get(parameters, "(@a{sv})", &options); + + iface = get_option(options, "interface"); + if (iface == NULL) { + _LOGW("dhcp-event: didn't have associated interface."); + return; + } + + pid_str = get_option(options, "pid"); + pid = _nm_utils_ascii_str_to_int64(pid_str, 10, 0, G_MAXINT32, -1); + if (pid == -1) { + _LOGW("dhcp-event: couldn't convert PID '%s' to an integer", pid_str ?: "(null)"); + return; + } + + reason = get_option(options, "reason"); + if (reason == NULL) { + _LOGW("dhcp-event: (pid %d) DHCP event didn't have a reason", pid); + return; + } + + g_signal_emit(self, signals[EVENT], 0, iface, pid, options, reason, &handled); + if (!handled) { + if (g_ascii_strcasecmp(reason, "RELEASE") == 0) { + /* Ignore event when the dhcp client gets killed and we receive its last message */ + _LOGD("dhcp-event: (pid %d) unhandled RELEASE DHCP event for interface %s", pid, iface); + } else + _LOGW("dhcp-event: (pid %d) unhandled DHCP event for interface %s", pid, iface); + } } static void -_method_call (GDBusConnection *connection, - const char *sender, - const char *object_path, - const char *interface_name, - const char *method_name, - GVariant *parameters, - GDBusMethodInvocation *invocation, - gpointer user_data) +_method_call(GDBusConnection * connection, + const char * sender, + const char * object_path, + const char * interface_name, + const char * method_name, + GVariant * parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) { - NMDhcpListener *self = NM_DHCP_LISTENER (user_data); - - if ( !nm_streq (interface_name, NM_DHCP_HELPER_SERVER_INTERFACE_NAME) - || !nm_streq (method_name, NM_DHCP_HELPER_SERVER_METHOD_NOTIFY)) { - g_dbus_method_invocation_return_error (invocation, - G_DBUS_ERROR, - G_DBUS_ERROR_UNKNOWN_METHOD, - "Unknown method %s", - method_name); - return; - } - - _method_call_handle (self, parameters); - g_dbus_method_invocation_return_value (invocation, NULL); + NMDhcpListener *self = NM_DHCP_LISTENER(user_data); + + if (!nm_streq(interface_name, NM_DHCP_HELPER_SERVER_INTERFACE_NAME) + || !nm_streq(method_name, NM_DHCP_HELPER_SERVER_METHOD_NOTIFY)) { + g_dbus_method_invocation_return_error(invocation, + G_DBUS_ERROR, + G_DBUS_ERROR_UNKNOWN_METHOD, + "Unknown method %s", + method_name); + return; + } + + _method_call_handle(self, parameters); + g_dbus_method_invocation_return_value(invocation, NULL); } -static GDBusInterfaceInfo *const interface_info = NM_DEFINE_GDBUS_INTERFACE_INFO ( - NM_DHCP_HELPER_SERVER_INTERFACE_NAME, - .methods = NM_DEFINE_GDBUS_METHOD_INFOS ( - NM_DEFINE_GDBUS_METHOD_INFO ( - NM_DHCP_HELPER_SERVER_METHOD_NOTIFY, - .in_args = NM_DEFINE_GDBUS_ARG_INFOS ( - NM_DEFINE_GDBUS_ARG_INFO ("data", "a{sv}"), - ), - ), - ), -); +static GDBusInterfaceInfo *const interface_info = NM_DEFINE_GDBUS_INTERFACE_INFO( + NM_DHCP_HELPER_SERVER_INTERFACE_NAME, + .methods = NM_DEFINE_GDBUS_METHOD_INFOS( + NM_DEFINE_GDBUS_METHOD_INFO(NM_DHCP_HELPER_SERVER_METHOD_NOTIFY, + .in_args = NM_DEFINE_GDBUS_ARG_INFOS( + NM_DEFINE_GDBUS_ARG_INFO("data", "a{sv}"), ), ), ), ); static guint -_dbus_connection_register_object (NMDhcpListener *self, - GDBusConnection *connection, - GError **error) +_dbus_connection_register_object(NMDhcpListener *self, GDBusConnection *connection, GError **error) { - static const GDBusInterfaceVTable interface_vtable = { - .method_call = _method_call, - }; - - return g_dbus_connection_register_object (connection, - NM_DHCP_HELPER_SERVER_OBJECT_PATH, - interface_info, - NM_UNCONST_PTR (GDBusInterfaceVTable, &interface_vtable), - self, - NULL, - error); + static const GDBusInterfaceVTable interface_vtable = { + .method_call = _method_call, + }; + + return g_dbus_connection_register_object( + connection, + NM_DHCP_HELPER_SERVER_OBJECT_PATH, + interface_info, + NM_UNCONST_PTR(GDBusInterfaceVTable, &interface_vtable), + self, + NULL, + error); } static void -new_connection_cb (NMDBusManager *mgr, - GDBusConnection *connection, - GDBusObjectManager *manager, - NMDhcpListener *self) +new_connection_cb(NMDBusManager * mgr, + GDBusConnection * connection, + GDBusObjectManager *manager, + NMDhcpListener * self) { - NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE (self); - guint registration_id; - GError *error = NULL; - - /* it is important to register the object during the new-connection signal, - * as this avoids races with the connecting object. */ - registration_id = _dbus_connection_register_object (self, connection, &error); - if (!registration_id) { - _LOGE ("failure to register %s for connection %p: %s", - NM_DHCP_HELPER_SERVER_OBJECT_PATH, connection, error->message); - g_error_free (error); - return; - } - - g_hash_table_insert (priv->connections, connection, GUINT_TO_POINTER (registration_id)); + NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE(self); + guint registration_id; + GError * error = NULL; + + /* it is important to register the object during the new-connection signal, + * as this avoids races with the connecting object. */ + registration_id = _dbus_connection_register_object(self, connection, &error); + if (!registration_id) { + _LOGE("failure to register %s for connection %p: %s", + NM_DHCP_HELPER_SERVER_OBJECT_PATH, + connection, + error->message); + g_error_free(error); + return; + } + + g_hash_table_insert(priv->connections, connection, GUINT_TO_POINTER(registration_id)); } static void -dis_connection_cb (NMDBusManager *mgr, - GDBusConnection *connection, - NMDhcpListener *self) +dis_connection_cb(NMDBusManager *mgr, GDBusConnection *connection, NMDhcpListener *self) { - NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE (self); - guint id; - - id = GPOINTER_TO_UINT (g_hash_table_lookup (priv->connections, connection)); - if (id) { - g_dbus_connection_unregister_object (connection, id); - g_hash_table_remove (priv->connections, connection); - } + NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE(self); + guint id; + + id = GPOINTER_TO_UINT(g_hash_table_lookup(priv->connections, connection)); + if (id) { + g_dbus_connection_unregister_object(connection, id); + g_hash_table_remove(priv->connections, connection); + } } /*****************************************************************************/ static void -nm_dhcp_listener_init (NMDhcpListener *self) +nm_dhcp_listener_init(NMDhcpListener *self) { - NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE (self); - - /* Maps GDBusConnection :: signal-id */ - priv->connections = g_hash_table_new (nm_direct_hash, NULL); - - priv->dbus_mgr = g_object_ref (nm_dbus_manager_get ()); - - /* Register the socket our DHCP clients will return lease info on */ - nm_dbus_manager_private_server_register (priv->dbus_mgr, PRIV_SOCK_PATH, PRIV_SOCK_TAG); - priv->new_conn_id = g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_PRIVATE_CONNECTION_NEW "::" PRIV_SOCK_TAG, - G_CALLBACK (new_connection_cb), - self); - priv->dis_conn_id = g_signal_connect (priv->dbus_mgr, - NM_DBUS_MANAGER_PRIVATE_CONNECTION_DISCONNECTED "::" PRIV_SOCK_TAG, - G_CALLBACK (dis_connection_cb), - self); + NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE(self); + + /* Maps GDBusConnection :: signal-id */ + priv->connections = g_hash_table_new(nm_direct_hash, NULL); + + priv->dbus_mgr = g_object_ref(nm_dbus_manager_get()); + + /* Register the socket our DHCP clients will return lease info on */ + nm_dbus_manager_private_server_register(priv->dbus_mgr, PRIV_SOCK_PATH, PRIV_SOCK_TAG); + priv->new_conn_id = g_signal_connect(priv->dbus_mgr, + NM_DBUS_MANAGER_PRIVATE_CONNECTION_NEW "::" PRIV_SOCK_TAG, + G_CALLBACK(new_connection_cb), + self); + priv->dis_conn_id = + g_signal_connect(priv->dbus_mgr, + NM_DBUS_MANAGER_PRIVATE_CONNECTION_DISCONNECTED "::" PRIV_SOCK_TAG, + G_CALLBACK(dis_connection_cb), + self); } static void -dispose (GObject *object) +dispose(GObject *object) { - NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE (object); + NMDhcpListenerPrivate *priv = NM_DHCP_LISTENER_GET_PRIVATE(object); - nm_clear_g_signal_handler (priv->dbus_mgr, &priv->new_conn_id); - nm_clear_g_signal_handler (priv->dbus_mgr, &priv->dis_conn_id); + nm_clear_g_signal_handler(priv->dbus_mgr, &priv->new_conn_id); + nm_clear_g_signal_handler(priv->dbus_mgr, &priv->dis_conn_id); - nm_clear_pointer (&priv->connections, g_hash_table_destroy); + nm_clear_pointer(&priv->connections, g_hash_table_destroy); - g_clear_object (&priv->dbus_mgr); + g_clear_object(&priv->dbus_mgr); - G_OBJECT_CLASS (nm_dhcp_listener_parent_class)->dispose (object); + G_OBJECT_CLASS(nm_dhcp_listener_parent_class)->dispose(object); } static void -nm_dhcp_listener_class_init (NMDhcpListenerClass *listener_class) +nm_dhcp_listener_class_init(NMDhcpListenerClass *listener_class) { - GObjectClass *object_class = G_OBJECT_CLASS (listener_class); - - object_class->dispose = dispose; - - signals[EVENT] = - g_signal_new (NM_DHCP_LISTENER_EVENT, - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, 0, - g_signal_accumulator_true_handled, - NULL, NULL, - G_TYPE_BOOLEAN, /* listeners return TRUE if handled */ - 4, - G_TYPE_STRING, /* iface */ - G_TYPE_INT, /* pid */ - G_TYPE_VARIANT, /* options */ - G_TYPE_STRING); /* reason */ + GObjectClass *object_class = G_OBJECT_CLASS(listener_class); + + object_class->dispose = dispose; + + signals[EVENT] = g_signal_new(NM_DHCP_LISTENER_EVENT, + G_OBJECT_CLASS_TYPE(object_class), + G_SIGNAL_RUN_LAST, + 0, + g_signal_accumulator_true_handled, + NULL, + NULL, + G_TYPE_BOOLEAN, /* listeners return TRUE if handled */ + 4, + G_TYPE_STRING, /* iface */ + G_TYPE_INT, /* pid */ + G_TYPE_VARIANT, /* options */ + G_TYPE_STRING); /* reason */ } diff --git a/src/dhcp/nm-dhcp-listener.h b/src/dhcp/nm-dhcp-listener.h index c2b90dc3..57d3b0fc 100644 --- a/src/dhcp/nm-dhcp-listener.h +++ b/src/dhcp/nm-dhcp-listener.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2014 Red Hat, Inc. */ @@ -6,18 +6,20 @@ #ifndef __NETWORKMANAGER_DHCP_LISTENER_H__ #define __NETWORKMANAGER_DHCP_LISTENER_H__ -#define NM_TYPE_DHCP_LISTENER (nm_dhcp_listener_get_type ()) -#define NM_DHCP_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DHCP_LISTENER, NMDhcpListener)) -#define NM_IS_DHCP_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DHCP_LISTENER)) -#define NM_DHCP_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DHCP_LISTENER, NMDhcpListenerClass)) +#define NM_TYPE_DHCP_LISTENER (nm_dhcp_listener_get_type()) +#define NM_DHCP_LISTENER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DHCP_LISTENER, NMDhcpListener)) +#define NM_IS_DHCP_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DHCP_LISTENER)) +#define NM_DHCP_LISTENER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DHCP_LISTENER, NMDhcpListenerClass)) #define NM_DHCP_LISTENER_EVENT "event" -typedef struct _NMDhcpListener NMDhcpListener; +typedef struct _NMDhcpListener NMDhcpListener; typedef struct _NMDhcpListenerClass NMDhcpListenerClass; -GType nm_dhcp_listener_get_type (void); +GType nm_dhcp_listener_get_type(void); -NMDhcpListener *nm_dhcp_listener_get (void); +NMDhcpListener *nm_dhcp_listener_get(void); #endif /* __NETWORKMANAGER_DHCP_LISTENER_H__ */ diff --git a/src/dhcp/nm-dhcp-manager.c b/src/dhcp/nm-dhcp-manager.c index fc99a30a..665944d7 100644 --- a/src/dhcp/nm-dhcp-manager.c +++ b/src/dhcp/nm-dhcp-manager.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2005 - 2013 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. @@ -25,23 +25,31 @@ /*****************************************************************************/ typedef struct { - const NMDhcpClientFactory *client_factory; - char *default_hostname; - CList dhcp_client_lst_head; + const NMDhcpClientFactory *client_factory; + char * default_hostname; + CList dhcp_client_lst_head; } NMDhcpManagerPrivate; struct _NMDhcpManager { - GObject parent; - NMDhcpManagerPrivate _priv; + GObject parent; + NMDhcpManagerPrivate _priv; }; struct _NMDhcpManagerClass { - GObjectClass parent; + GObjectClass parent; }; -G_DEFINE_TYPE (NMDhcpManager, nm_dhcp_manager, G_TYPE_OBJECT) +G_DEFINE_TYPE(NMDhcpManager, nm_dhcp_manager, G_TYPE_OBJECT) -#define NM_DHCP_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDhcpManager, NM_IS_DHCP_MANAGER) +#define NM_DHCP_MANAGER_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDhcpManager, NM_IS_DHCP_MANAGER) + +/*****************************************************************************/ + +static void client_state_changed(NMDhcpClient * client, + NMDhcpState state, + GObject * ip_config, + GVariant * options, + NMDhcpManager *self); /*****************************************************************************/ @@ -51,597 +59,624 @@ const char *nm_dhcp_helper_path = LIBEXECDIR "/nm-dhcp-helper"; /*****************************************************************************/ static const NMDhcpClientFactory * -_client_factory_find_by_name (const char *name) +_client_factory_find_by_name(const char *name) { - int i; + int i; - g_return_val_if_fail (name, NULL); + g_return_val_if_fail(name, NULL); - for (i = 0; i < G_N_ELEMENTS (_nm_dhcp_manager_factories); i++) { - const NMDhcpClientFactory *f = _nm_dhcp_manager_factories[i]; + for (i = 0; i < G_N_ELEMENTS(_nm_dhcp_manager_factories); i++) { + const NMDhcpClientFactory *f = _nm_dhcp_manager_factories[i]; - if (f && nm_streq (f->name, name)) - return f; - } - return NULL; + if (f && nm_streq(f->name, name)) + return f; + } + return NULL; } static const NMDhcpClientFactory * -_client_factory_available (const NMDhcpClientFactory *client_factory) +_client_factory_available(const NMDhcpClientFactory *client_factory) { - if ( client_factory - && (!client_factory->get_path || client_factory->get_path ())) - return client_factory; - return NULL; + if (client_factory && (!client_factory->get_path || client_factory->get_path())) + return client_factory; + return NULL; } static GType -_client_factory_get_gtype (const NMDhcpClientFactory *client_factory, - int addr_family) +_client_factory_get_gtype(const NMDhcpClientFactory *client_factory, int addr_family) { - GType gtype; - nm_auto_unref_gtypeclass NMDhcpClientClass *klass = NULL; - - nm_assert (client_factory); - nm_assert_addr_family (addr_family); - - /* currently, the chosen DHCP plugin for IPv4 and IPv6 is configured in NetworkManager.conf - * and cannot be reloaded. It would be nice to configure the plugin per address family - * or to be able to reload it. - * - * Note that certain options in NetworkManager.conf depend on the chosen DHCP plugin. - * See "dhcp-plugin:" in "Device List Format" (`man NetworkManager.conf`). - * Supporting reloading the plugin would also require to re-evalate the decisions from - * the "Device List Format". Likewise, having per-address family plugins would make the - * "main.dhcp" setting and "dhcp-plugin:" match non-sensical because these configurations - * currently are address family independet. - * - * So actually, we don't want that complexity. We want to phase out all plugins in favor - * of the internal plugin. - * However, certain existing plugins are well known to not support an address family. - * In those cases, we should just silently fallback to the internal plugin. - * - * This could be a problem with forward compatibility if we ever intended to add IPv6 support - * to those plugins. But we don't intend to do so. The internal plugin is the way forward and - * not extending other plugins. */ - - if (client_factory->get_type_per_addr_family) - gtype = client_factory->get_type_per_addr_family (addr_family); - else - gtype = client_factory->get_type (); - - if (client_factory == &_nm_dhcp_client_factory_internal) { - /* we are already using the internal plugin. Nothing to do. */ - goto out; - } - - klass = g_type_class_ref (gtype); - - nm_assert (NM_IS_DHCP_CLIENT_CLASS (klass)); - - if (addr_family == AF_INET6) { - if (!klass->ip6_start) - gtype = _client_factory_get_gtype (&_nm_dhcp_client_factory_internal, addr_family); - } else { - if (!klass->ip4_start) - gtype = _client_factory_get_gtype (&_nm_dhcp_client_factory_internal, addr_family); - } + GType gtype; + nm_auto_unref_gtypeclass NMDhcpClientClass *klass = NULL; + + nm_assert(client_factory); + nm_assert_addr_family(addr_family); + + /* currently, the chosen DHCP plugin for IPv4 and IPv6 is configured in NetworkManager.conf + * and cannot be reloaded. It would be nice to configure the plugin per address family + * or to be able to reload it. + * + * Note that certain options in NetworkManager.conf depend on the chosen DHCP plugin. + * See "dhcp-plugin:" in "Device List Format" (`man NetworkManager.conf`). + * Supporting reloading the plugin would also require to re-evalate the decisions from + * the "Device List Format". Likewise, having per-address family plugins would make the + * "main.dhcp" setting and "dhcp-plugin:" match non-sensical because these configurations + * currently are address family independent. + * + * So actually, we don't want that complexity. We want to phase out all plugins in favor + * of the internal plugin. + * However, certain existing plugins are well known to not support an address family. + * In those cases, we should just silently fallback to the internal plugin. + * + * This could be a problem with forward compatibility if we ever intended to add IPv6 support + * to those plugins. But we don't intend to do so. The internal plugin is the way forward and + * not extending other plugins. */ + + if (client_factory->get_type_per_addr_family) + gtype = client_factory->get_type_per_addr_family(addr_family); + else + gtype = client_factory->get_type(); + + if (client_factory == &_nm_dhcp_client_factory_internal) { + /* we are already using the internal plugin. Nothing to do. */ + goto out; + } + + klass = g_type_class_ref(gtype); + + nm_assert(NM_IS_DHCP_CLIENT_CLASS(klass)); + + if (addr_family == AF_INET6) { + if (!klass->ip6_start) + gtype = _client_factory_get_gtype(&_nm_dhcp_client_factory_internal, addr_family); + } else { + if (!klass->ip4_start) + gtype = _client_factory_get_gtype(&_nm_dhcp_client_factory_internal, addr_family); + } out: - nm_assert (g_type_is_a (gtype, NM_TYPE_DHCP_CLIENT)); - nm_assert (({ - nm_auto_unref_gtypeclass NMDhcpClientClass *k = g_type_class_ref (gtype); + nm_assert(g_type_is_a(gtype, NM_TYPE_DHCP_CLIENT)); + nm_assert(({ + nm_auto_unref_gtypeclass NMDhcpClientClass *k = g_type_class_ref(gtype); - (addr_family == AF_INET6 && k->ip6_start) - || (addr_family == AF_INET && k->ip4_start); - })); + (addr_family == AF_INET6 && k->ip6_start) || (addr_family == AF_INET && k->ip4_start); + })); - return gtype; + return gtype; } /*****************************************************************************/ static NMDhcpClient * -get_client_for_ifindex (NMDhcpManager *manager, int addr_family, int ifindex) +get_client_for_ifindex(NMDhcpManager *manager, int addr_family, int ifindex) { - NMDhcpManagerPrivate *priv; - NMDhcpClient *client; + NMDhcpManagerPrivate *priv; + NMDhcpClient * client; - g_return_val_if_fail (NM_IS_DHCP_MANAGER (manager), NULL); - g_return_val_if_fail (ifindex > 0, NULL); + g_return_val_if_fail(NM_IS_DHCP_MANAGER(manager), NULL); + g_return_val_if_fail(ifindex > 0, NULL); - priv = NM_DHCP_MANAGER_GET_PRIVATE (manager); + priv = NM_DHCP_MANAGER_GET_PRIVATE(manager); - c_list_for_each_entry (client, &priv->dhcp_client_lst_head, dhcp_client_lst) { - if ( nm_dhcp_client_get_ifindex (client) == ifindex - && nm_dhcp_client_get_addr_family (client) == addr_family) - return client; - } + c_list_for_each_entry (client, &priv->dhcp_client_lst_head, dhcp_client_lst) { + if (nm_dhcp_client_get_ifindex(client) == ifindex + && nm_dhcp_client_get_addr_family(client) == addr_family) + return client; + } - return NULL; + return NULL; } -static void client_state_changed (NMDhcpClient *client, - NMDhcpState state, - GObject *ip_config, - GVariant *options, - const char *event_id, - NMDhcpManager *self); - static void -remove_client (NMDhcpManager *self, NMDhcpClient *client) +remove_client(NMDhcpManager *self, NMDhcpClient *client) { - g_signal_handlers_disconnect_by_func (client, client_state_changed, self); - c_list_unlink (&client->dhcp_client_lst); + g_signal_handlers_disconnect_by_func(client, client_state_changed, self); + c_list_unlink(&client->dhcp_client_lst); - /* Stopping the client is left up to the controlling device - * explicitly since we may want to quit NetworkManager but not terminate - * the DHCP client. - */ + /* Stopping the client is left up to the controlling device + * explicitly since we may want to quit NetworkManager but not terminate + * the DHCP client. + */ } static void -remove_client_unref (NMDhcpManager *self, NMDhcpClient *client) +remove_client_unref(NMDhcpManager *self, NMDhcpClient *client) { - remove_client (self, client); - g_object_unref (client); + remove_client(self, client); + g_object_unref(client); } static void -client_state_changed (NMDhcpClient *client, - NMDhcpState state, - GObject *ip_config, - GVariant *options, - const char *event_id, - NMDhcpManager *self) +client_state_changed(NMDhcpClient * client, + NMDhcpState state, + GObject * ip_config, + GVariant * options, + NMDhcpManager *self) { - if (state >= NM_DHCP_STATE_TIMEOUT) - remove_client_unref (self, client); + if (state >= NM_DHCP_STATE_TIMEOUT) + remove_client_unref(self, client); } 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, - const char *dhcp_anycast_addr, - const char *hostname, - gboolean hostname_use_fqdn, - NMDhcpHostnameFlags hostname_flags, - const char *mud_url, - gboolean info_only, - NMSettingIP6ConfigPrivacy privacy, - const char *last_ip4_address, - guint needed_prefixes, - GError **error) +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, + const char * dhcp_anycast_addr, + const char * hostname, + gboolean hostname_use_fqdn, + NMDhcpHostnameFlags hostname_flags, + const char * mud_url, + gboolean info_only, + NMSettingIP6ConfigPrivacy privacy, + const char * last_ip4_address, + guint needed_prefixes, + GBytes * vendor_class_identifier, + const char *const * reject_servers, + GError ** error) { - NMDhcpManagerPrivate *priv; - NMDhcpClient *client; - gboolean success = FALSE; - gsize hwaddr_len; - 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 (!error || !*error, NULL); - - if (addr_family == AF_INET) { - if (!hwaddr || !bcast_hwaddr) { - nm_utils_error_set (error, - NM_UTILS_ERROR_UNKNOWN, - "missing %s address", - hwaddr ? "broadcast" : "MAC"); - return NULL; - } - - hwaddr_len = g_bytes_get_size (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) { - if ( (hostname_use_fqdn && !nm_sd_dns_name_is_valid (hostname)) - || (!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), - hostname_use_fqdn ? "FQDN" : "hostname", - hostname); - hostname = NULL; - } - } - - priv = NM_DHCP_MANAGER_GET_PRIVATE (self); - - /* Kill any old client instance */ - client = get_client_for_ifindex (self, addr_family, ifindex); - if (client) { - /* FIXME: we cannot just call synchronously "stop()" and forget about the client. - * We need to wait for the client to be fully stopped because most/all clients - * cannot quit right away. - * - * FIXME(shutdown): also fix this during shutdown, to wait for all DHCP clients - * to be fully stopped. */ - remove_client (self, client); - nm_dhcp_client_stop (client, FALSE); - g_object_unref (client); - } - - gtype = _client_factory_get_gtype (priv->client_factory, 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), - 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_FLAGS, (guint) (0 - | (hostname_use_fqdn ? NM_DHCP_CLIENT_FLAGS_USE_FQDN : 0) - | (info_only ? NM_DHCP_CLIENT_FLAGS_INFO_ONLY : 0) - ), - NULL); - nm_assert (client && c_list_is_empty (&client->dhcp_client_lst)); - c_list_link_tail (&priv->dhcp_client_lst_head, &client->dhcp_client_lst); - g_signal_connect (client, NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, G_CALLBACK (client_state_changed), self); - - /* unfortunately, our implementations work differently per address-family regarding client-id/DUID. - * - * - for IPv4, the calling code may determine a client-id (from NM's connection profile). - * If present, it is taken. If not present, the DHCP plugin uses a plugin specific default. - * - for "internal" plugin, the default is just "mac". - * - for "dhclient", we try to get the configuration from dhclient's /etc/dhcp or fallback - * to whatever dhclient uses by default. - * We do it this way, because for dhclient the user may configure a default - * outside of NM, and we want to honor that. Worse, dhclient could be a wapper - * script where the wrapper script overwrites the client-id. We need to distinguish - * between: force a particular client-id and leave it unspecified to whatever dhclient - * wants. - * - * - for IPv6, the calling code always determines a client-id. It also specifies @enforce_duid, - * to determine whether the given client-id must be used. - * - for "internal" plugin @enforce_duid doesn't matter and the given client-id is - * always used. - * - for "dhclient", @enforce_duid FALSE means to first try to load the DUID from the - * lease file, and only otherwise fallback to the given client-id. - * - other plugins don't support DHCPv6. - * It's done this way, so that existing dhclient setups don't change behavior on upgrade. - * - * This difference is cumbersome and only exists because of "dhclient" which supports hacking the - * default outside of NetworkManager API. - */ - - if (addr_family == AF_INET) { - success = nm_dhcp_client_start_ip4 (client, - dhcp_client_id, - dhcp_anycast_addr, - last_ip4_address, - error); - } else { - success = nm_dhcp_client_start_ip6 (client, - dhcp_client_id, - enforce_duid, - dhcp_anycast_addr, - ipv6_ll_addr, - privacy, - needed_prefixes, - error); - } - - if (!success) { - remove_client_unref (self, client); - return NULL; - } - - return g_object_ref (client); + NMDhcpManagerPrivate *priv; + NMDhcpClient * client; + gboolean success = FALSE; + gsize hwaddr_len; + 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, + NULL); + g_return_val_if_fail(!error || !*error, NULL); + + if (addr_family == AF_INET) { + if (!hwaddr || !bcast_hwaddr) { + nm_utils_error_set(error, + NM_UTILS_ERROR_UNKNOWN, + "missing %s address", + hwaddr ? "broadcast" : "MAC"); + return NULL; + } + + hwaddr_len = g_bytes_get_size(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) { + if ((hostname_use_fqdn && !nm_sd_dns_name_is_valid(hostname)) + || (!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), + hostname_use_fqdn ? "FQDN" : "hostname", + hostname); + hostname = NULL; + } + } + + priv = NM_DHCP_MANAGER_GET_PRIVATE(self); + + /* Kill any old client instance */ + client = get_client_for_ifindex(self, addr_family, ifindex); + if (client) { + /* FIXME: we cannot just call synchronously "stop()" and forget about the client. + * We need to wait for the client to be fully stopped because most/all clients + * cannot quit right away. + * + * FIXME(shutdown): also fix this during shutdown, to wait for all DHCP clients + * to be fully stopped. */ + remove_client(self, client); + nm_dhcp_client_stop(client, FALSE); + g_object_unref(client); + } + + gtype = _client_factory_get_gtype(priv->client_factory, 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), + 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)(0 | (hostname_use_fqdn ? NM_DHCP_CLIENT_FLAGS_USE_FQDN : 0) + | (info_only ? NM_DHCP_CLIENT_FLAGS_INFO_ONLY : 0)), + NULL); + nm_assert(client && c_list_is_empty(&client->dhcp_client_lst)); + c_list_link_tail(&priv->dhcp_client_lst_head, &client->dhcp_client_lst); + g_signal_connect(client, + NM_DHCP_CLIENT_SIGNAL_STATE_CHANGED, + G_CALLBACK(client_state_changed), + self); + + /* unfortunately, our implementations work differently per address-family regarding client-id/DUID. + * + * - for IPv4, the calling code may determine a client-id (from NM's connection profile). + * If present, it is taken. If not present, the DHCP plugin uses a plugin specific default. + * - for "internal" plugin, the default is just "mac". + * - for "dhclient", we try to get the configuration from dhclient's /etc/dhcp or fallback + * to whatever dhclient uses by default. + * We do it this way, because for dhclient the user may configure a default + * outside of NM, and we want to honor that. Worse, dhclient could be a wapper + * script where the wrapper script overwrites the client-id. We need to distinguish + * between: force a particular client-id and leave it unspecified to whatever dhclient + * wants. + * + * - for IPv6, the calling code always determines a client-id. It also specifies @enforce_duid, + * to determine whether the given client-id must be used. + * - for "internal" plugin @enforce_duid doesn't matter and the given client-id is + * always used. + * - for "dhclient", @enforce_duid FALSE means to first try to load the DUID from the + * lease file, and only otherwise fallback to the given client-id. + * - other plugins don't support DHCPv6. + * It's done this way, so that existing dhclient setups don't change behavior on upgrade. + * + * This difference is cumbersome and only exists because of "dhclient" which supports hacking the + * default outside of NetworkManager API. + */ + + if (addr_family == AF_INET) { + success = nm_dhcp_client_start_ip4(client, + dhcp_client_id, + dhcp_anycast_addr, + last_ip4_address, + error); + } else { + success = nm_dhcp_client_start_ip6(client, + dhcp_client_id, + enforce_duid, + dhcp_anycast_addr, + ipv6_ll_addr, + privacy, + needed_prefixes, + error); + } + + if (!success) { + remove_client_unref(self, client); + return NULL; + } + + return g_object_ref(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, - 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 *dhcp_anycast_addr, - const char *last_ip_address, - GError **error) +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, + 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 * dhcp_anycast_addr, + 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; - - 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, - dhcp_anycast_addr, - hostname, - use_fqdn, - hostname_flags, - mud_url, - FALSE, - 0, - last_ip_address, - 0, - error); + NMDhcpManagerPrivate *priv; + const char * hostname = NULL; + gs_free char * hostname_tmp = NULL; + gboolean use_fqdn = FALSE; + char * dot; + + 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, + dhcp_anycast_addr, + hostname, + use_fqdn, + hostname_flags, + mud_url, + FALSE, + 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, - 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 *dhcp_anycast_addr, - gboolean info_only, - NMSettingIP6ConfigPrivacy privacy, - guint needed_prefixes, - GError **error) +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, + 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 * dhcp_anycast_addr, + gboolean info_only, + NMSettingIP6ConfigPrivacy privacy, + guint needed_prefixes, + GError ** error) { - NMDhcpManagerPrivate *priv; - const char *hostname = NULL; - - 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, - dhcp_anycast_addr, - hostname, - TRUE, - hostname_flags, - mud_url, - info_only, - privacy, - NULL, - needed_prefixes, - error); + NMDhcpManagerPrivate *priv; + const char * hostname = NULL; + + 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, + dhcp_anycast_addr, + hostname, + TRUE, + hostname_flags, + mud_url, + info_only, + privacy, + NULL, + needed_prefixes, + NULL, + NULL, + error); } void -nm_dhcp_manager_set_default_hostname (NMDhcpManager *manager, const char *hostname) +nm_dhcp_manager_set_default_hostname(NMDhcpManager *manager, const char *hostname) { - NMDhcpManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE (manager); + NMDhcpManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE(manager); - nm_clear_g_free (&priv->default_hostname); + nm_clear_g_free(&priv->default_hostname); - /* Never send 'localhost'-type names to the DHCP server */ - if (!nm_utils_is_specific_hostname (hostname)) - return; + /* Never send 'localhost'-type names to the DHCP server */ + if (!nm_utils_is_specific_hostname(hostname)) + return; - priv->default_hostname = g_strdup (hostname); + priv->default_hostname = g_strdup(hostname); } const char * -nm_dhcp_manager_get_config (NMDhcpManager *self) +nm_dhcp_manager_get_config(NMDhcpManager *self) { - const NMDhcpClientFactory *factory; + const NMDhcpClientFactory *factory; - g_return_val_if_fail (NM_IS_DHCP_MANAGER (self), NULL); + g_return_val_if_fail(NM_IS_DHCP_MANAGER(self), NULL); - factory = NM_DHCP_MANAGER_GET_PRIVATE (self)->client_factory; - return factory ? factory->name : NULL; + factory = NM_DHCP_MANAGER_GET_PRIVATE(self)->client_factory; + return factory ? factory->name : NULL; } /*****************************************************************************/ -NM_DEFINE_SINGLETON_GETTER (NMDhcpManager, nm_dhcp_manager_get, NM_TYPE_DHCP_MANAGER); +NM_DEFINE_SINGLETON_GETTER(NMDhcpManager, nm_dhcp_manager_get, NM_TYPE_DHCP_MANAGER); void -nmtst_dhcp_manager_unget (gpointer self) +nmtst_dhcp_manager_unget(gpointer self) { - _nmtst_nm_dhcp_manager_get_reset (self); + _nmtst_nm_dhcp_manager_get_reset(self); } static void -nm_dhcp_manager_init (NMDhcpManager *self) +nm_dhcp_manager_init(NMDhcpManager *self) { - NMDhcpManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE (self); - NMConfig *config = nm_config_get (); - gs_free char *client_free = NULL; - const char *client; - int i; - const NMDhcpClientFactory *client_factory = NULL; - - c_list_init (&priv->dhcp_client_lst_head); - - for (i = 0; i < G_N_ELEMENTS (_nm_dhcp_manager_factories); i++) { - const NMDhcpClientFactory *f = _nm_dhcp_manager_factories[i]; - - if (!f) - continue; - - nm_log_dbg (LOGD_DHCP, "dhcp-init: enabled DHCP client '%s'%s%s", - f->name, - _client_factory_available (f) ? "" : " (not available)", - f->experimental ? " (undocumented internal plugin)" : ""); - } - - /* Client-specific setup */ - client_free = nm_config_data_get_value (nm_config_get_data_orig (config), - NM_CONFIG_KEYFILE_GROUP_MAIN, - NM_CONFIG_KEYFILE_KEY_MAIN_DHCP, - NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY); - client = client_free; - if (nm_config_get_configure_and_quit (config) == NM_CONFIG_CONFIGURE_AND_QUIT_ENABLED) { - client_factory = &_nm_dhcp_client_factory_internal; - if (client && !nm_streq (client, client_factory->name)) - nm_log_info (LOGD_DHCP, "dhcp-init: Using internal DHCP client since configure-and-quit is set."); - } else { - if (client) { - client_factory = _client_factory_available (_client_factory_find_by_name (client)); - if (!client_factory) - nm_log_warn (LOGD_DHCP, "dhcp-init: DHCP client '%s' not available", client); - } - if (!client_factory) { - client_factory = _client_factory_find_by_name (""NM_CONFIG_DEFAULT_MAIN_DHCP); - if (!client_factory) - nm_log_err (LOGD_DHCP, "dhcp-init: default DHCP client '%s' is not installed", NM_CONFIG_DEFAULT_MAIN_DHCP); - else { - client_factory = _client_factory_available (client_factory); - if (!client_factory) - nm_log_info (LOGD_DHCP, "dhcp-init: default DHCP client '%s' is not available", NM_CONFIG_DEFAULT_MAIN_DHCP); - } - } - if (!client_factory) { - for (i = 0; i < G_N_ELEMENTS (_nm_dhcp_manager_factories); i++) { - client_factory = _client_factory_available (_nm_dhcp_manager_factories[i]); - if (client_factory) - break; - } - } - } - - g_return_if_fail (client_factory); - - nm_log_info (LOGD_DHCP, "dhcp-init: Using DHCP client '%s'", client_factory->name); - - /* NOTE: currently the DHCP plugin is chosen once at start. It's not - * possible to reload that configuration. If that ever becomes possible, - * beware that the "dhcp-plugin" device spec made decisions based on - * the previous plugin and may need reevaluation. */ - priv->client_factory = client_factory; + NMDhcpManagerPrivate * priv = NM_DHCP_MANAGER_GET_PRIVATE(self); + NMConfig * config = nm_config_get(); + gs_free char * client_free = NULL; + const char * client; + int i; + const NMDhcpClientFactory *client_factory = NULL; + + c_list_init(&priv->dhcp_client_lst_head); + + for (i = 0; i < G_N_ELEMENTS(_nm_dhcp_manager_factories); i++) { + const NMDhcpClientFactory *f = _nm_dhcp_manager_factories[i]; + + if (!f) + continue; + + nm_log_dbg(LOGD_DHCP, + "dhcp-init: enabled DHCP client '%s'%s%s", + f->name, + _client_factory_available(f) ? "" : " (not available)", + f->experimental ? " (undocumented internal plugin)" : ""); + } + + /* Client-specific setup */ + client_free = + nm_config_data_get_value(nm_config_get_data_orig(config), + NM_CONFIG_KEYFILE_GROUP_MAIN, + NM_CONFIG_KEYFILE_KEY_MAIN_DHCP, + NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY); + client = client_free; + if (nm_config_get_configure_and_quit(config) == NM_CONFIG_CONFIGURE_AND_QUIT_ENABLED) { + client_factory = &_nm_dhcp_client_factory_internal; + if (client && !nm_streq(client, client_factory->name)) + nm_log_info(LOGD_DHCP, + "dhcp-init: Using internal DHCP client since configure-and-quit is set."); + } else { + if (client) { + client_factory = _client_factory_available(_client_factory_find_by_name(client)); + if (!client_factory) + nm_log_warn(LOGD_DHCP, "dhcp-init: DHCP client '%s' not available", client); + } + if (!client_factory) { + client_factory = _client_factory_find_by_name("" NM_CONFIG_DEFAULT_MAIN_DHCP); + if (!client_factory) + nm_log_err(LOGD_DHCP, + "dhcp-init: default DHCP client '%s' is not installed", + NM_CONFIG_DEFAULT_MAIN_DHCP); + else { + client_factory = _client_factory_available(client_factory); + if (!client_factory) + nm_log_info(LOGD_DHCP, + "dhcp-init: default DHCP client '%s' is not available", + NM_CONFIG_DEFAULT_MAIN_DHCP); + } + } + if (!client_factory) { + for (i = 0; i < G_N_ELEMENTS(_nm_dhcp_manager_factories); i++) { + client_factory = _client_factory_available(_nm_dhcp_manager_factories[i]); + if (client_factory) + break; + } + } + } + + g_return_if_fail(client_factory); + + nm_log_info(LOGD_DHCP, "dhcp-init: Using DHCP client '%s'", client_factory->name); + + /* NOTE: currently the DHCP plugin is chosen once at start. It's not + * possible to reload that configuration. If that ever becomes possible, + * beware that the "dhcp-plugin" device spec made decisions based on + * the previous plugin and may need reevaluation. */ + priv->client_factory = client_factory; } static void -dispose (GObject *object) +dispose(GObject *object) { - NMDhcpManager *self = NM_DHCP_MANAGER (object); - NMDhcpManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE (self); - NMDhcpClient *client, *client_safe; + NMDhcpManager * self = NM_DHCP_MANAGER(object); + NMDhcpManagerPrivate *priv = NM_DHCP_MANAGER_GET_PRIVATE(self); + NMDhcpClient * client, *client_safe; - c_list_for_each_entry_safe (client, client_safe, &priv->dhcp_client_lst_head, dhcp_client_lst) - remove_client_unref (self, client); + c_list_for_each_entry_safe (client, client_safe, &priv->dhcp_client_lst_head, dhcp_client_lst) + remove_client_unref(self, client); - G_OBJECT_CLASS (nm_dhcp_manager_parent_class)->dispose (object); + G_OBJECT_CLASS(nm_dhcp_manager_parent_class)->dispose(object); - nm_clear_g_free (&priv->default_hostname); + nm_clear_g_free(&priv->default_hostname); } static void -nm_dhcp_manager_class_init (NMDhcpManagerClass *manager_class) +nm_dhcp_manager_class_init(NMDhcpManagerClass *manager_class) { - GObjectClass *object_class = G_OBJECT_CLASS (manager_class); + GObjectClass *object_class = G_OBJECT_CLASS(manager_class); - object_class->dispose = dispose; + object_class->dispose = dispose; } diff --git a/src/dhcp/nm-dhcp-manager.h b/src/dhcp/nm-dhcp-manager.h index e8e65ef3..729d6d4e 100644 --- a/src/dhcp/nm-dhcp-manager.h +++ b/src/dhcp/nm-dhcp-manager.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2005 - 2010 Red Hat, Inc. * Copyright (C) 2006 - 2008 Novell, Inc. @@ -11,73 +11,77 @@ #include "nm-ip4-config.h" #include "nm-dhcp-config.h" -#define NM_TYPE_DHCP_MANAGER (nm_dhcp_manager_get_type ()) -#define NM_DHCP_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DHCP_MANAGER, NMDhcpManager)) -#define NM_DHCP_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DHCP_MANAGER, NMDhcpManagerClass)) -#define NM_IS_DHCP_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DHCP_MANAGER)) -#define NM_IS_DHCP_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DHCP_MANAGER)) -#define NM_DHCP_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DHCP_MANAGER, NMDhcpManagerClass)) +#define NM_TYPE_DHCP_MANAGER (nm_dhcp_manager_get_type()) +#define NM_DHCP_MANAGER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DHCP_MANAGER, NMDhcpManager)) +#define NM_DHCP_MANAGER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DHCP_MANAGER, NMDhcpManagerClass)) +#define NM_IS_DHCP_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DHCP_MANAGER)) +#define NM_IS_DHCP_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DHCP_MANAGER)) +#define NM_DHCP_MANAGER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DHCP_MANAGER, NMDhcpManagerClass)) -typedef struct _NMDhcpManager NMDhcpManager; +typedef struct _NMDhcpManager NMDhcpManager; typedef struct _NMDhcpManagerClass NMDhcpManagerClass; -GType nm_dhcp_manager_get_type (void); +GType nm_dhcp_manager_get_type(void); -NMDhcpManager *nm_dhcp_manager_get (void); +NMDhcpManager *nm_dhcp_manager_get(void); -const char *nm_dhcp_manager_get_config (NMDhcpManager *self); +const char *nm_dhcp_manager_get_config(NMDhcpManager *self); -void nm_dhcp_manager_set_default_hostname (NMDhcpManager *manager, - const char *hostname); +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, - 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 *dhcp_anycast_addr, - const char *last_ip_address, - GError **error); +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, + 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 * dhcp_anycast_addr, + 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, - 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 *dhcp_anycast_addr, - gboolean info_only, - NMSettingIP6ConfigPrivacy privacy, - guint needed_prefixes, - 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, + 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 * dhcp_anycast_addr, + gboolean info_only, + NMSettingIP6ConfigPrivacy privacy, + guint needed_prefixes, + GError ** error); /* For testing only */ -extern const char* nm_dhcp_helper_path; +extern const char *nm_dhcp_helper_path; extern const NMDhcpClientFactory *const _nm_dhcp_manager_factories[6]; -void nmtst_dhcp_manager_unget (gpointer singleton_instance); +void nmtst_dhcp_manager_unget(gpointer singleton_instance); #endif /* __NETWORKMANAGER_DHCP_MANAGER_H__ */ diff --git a/src/dhcp/nm-dhcp-nettools.c b/src/dhcp/nm-dhcp-nettools.c index fe6a4582..7b4e4605 100644 --- a/src/dhcp/nm-dhcp-nettools.c +++ b/src/dhcp/nm-dhcp-nettools.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: LGPL-2.1+ +/* SPDX-License-Identifier: LGPL-2.1+ */ /* * Copyright (C) 2014 - 2019 Red Hat, Inc. */ @@ -14,7 +14,6 @@ #include <net/if_arp.h> #include "nm-sd-adapt-shared.h" -#include "hostname-util.h" #include "nm-glib-aux/nm-dedup-multi.h" #include "nm-std-aux/unaligned.h" @@ -33,51 +32,55 @@ /*****************************************************************************/ -#define NM_TYPE_DHCP_NETTOOLS (nm_dhcp_nettools_get_type ()) -#define NM_DHCP_NETTOOLS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DHCP_NETTOOLS, NMDhcpNettools)) -#define NM_DHCP_NETTOOLS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DHCP_NETTOOLS, NMDhcpNettoolsClass)) -#define NM_IS_DHCP_NETTOOLS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DHCP_NETTOOLS)) -#define NM_IS_DHCP_NETTOOLS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DHCP_NETTOOLS)) -#define NM_DHCP_NETTOOLS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DHCP_NETTOOLS, NMDhcpNettoolsClass)) - -typedef struct _NMDhcpNettools NMDhcpNettools; +#define NM_TYPE_DHCP_NETTOOLS (nm_dhcp_nettools_get_type()) +#define NM_DHCP_NETTOOLS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DHCP_NETTOOLS, NMDhcpNettools)) +#define NM_DHCP_NETTOOLS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DHCP_NETTOOLS, NMDhcpNettoolsClass)) +#define NM_IS_DHCP_NETTOOLS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DHCP_NETTOOLS)) +#define NM_IS_DHCP_NETTOOLS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DHCP_NETTOOLS)) +#define NM_DHCP_NETTOOLS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DHCP_NETTOOLS, NMDhcpNettoolsClass)) + +typedef struct _NMDhcpNettools NMDhcpNettools; typedef struct _NMDhcpNettoolsClass NMDhcpNettoolsClass; /*****************************************************************************/ typedef struct { - NDhcp4Client *client; - NDhcp4ClientProbe *probe; - NDhcp4ClientLease *lease; - GSource *event_source; - char *lease_file; + NDhcp4Client * client; + NDhcp4ClientProbe *probe; + NDhcp4ClientLease *lease; + GSource * event_source; + char * lease_file; } NMDhcpNettoolsPrivate; struct _NMDhcpNettools { - NMDhcpClient parent; - NMDhcpNettoolsPrivate _priv; + NMDhcpClient parent; + NMDhcpNettoolsPrivate _priv; }; struct _NMDhcpNettoolsClass { - NMDhcpClientClass parent; + NMDhcpClientClass parent; }; -G_DEFINE_TYPE (NMDhcpNettools, nm_dhcp_nettools, NM_TYPE_DHCP_CLIENT) +G_DEFINE_TYPE(NMDhcpNettools, nm_dhcp_nettools, NM_TYPE_DHCP_CLIENT) -#define NM_DHCP_NETTOOLS_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDhcpNettools, NM_IS_DHCP_NETTOOLS) +#define NM_DHCP_NETTOOLS_GET_PRIVATE(self) \ + _NM_GET_PRIVATE(self, NMDhcpNettools, NM_IS_DHCP_NETTOOLS) /*****************************************************************************/ static void -set_error_nettools (GError **error, int r, const char *message) +set_error_nettools(GError **error, int r, const char *message) { - /* the error code returned from n_dhcp4_* API is either a negative - * errno, or a positive internal error code. Generate different messages - * for these. */ - if (r < 0) - nm_utils_error_set_errno (error, r, "%s: %s", message); - else - nm_utils_error_set (error, r, "%s (code %d)", message, r); + /* the error code returned from n_dhcp4_* API is either a negative + * errno, or a positive internal error code. Generate different messages + * for these. */ + if (r < 0) + nm_utils_error_set_errno(error, r, "%s: %s", message); + else + nm_utils_error_set(error, r, "%s (code %d)", message, r); } /*****************************************************************************/ @@ -85,1398 +88,1446 @@ set_error_nettools (GError **error, int r, const char *message) #define DHCP_MAX_FQDN_LENGTH 255 enum { - NM_IN_ADDR_CLASS_A, - NM_IN_ADDR_CLASS_B, - NM_IN_ADDR_CLASS_C, - NM_IN_ADDR_CLASS_INVALID, + NM_IN_ADDR_CLASS_A, + NM_IN_ADDR_CLASS_B, + NM_IN_ADDR_CLASS_C, + NM_IN_ADDR_CLASS_INVALID, }; static int -in_addr_class (struct in_addr addr) +in_addr_class(struct in_addr addr) { - switch (ntohl (addr.s_addr) >> 24) { - case 0 ... 127: - return NM_IN_ADDR_CLASS_A; - case 128 ... 191: - return NM_IN_ADDR_CLASS_B; - case 192 ... 223: - return NM_IN_ADDR_CLASS_C; - default: - return NM_IN_ADDR_CLASS_INVALID; - } + switch (ntohl(addr.s_addr) >> 24) { + case 0 ... 127: + return NM_IN_ADDR_CLASS_A; + case 128 ... 191: + return NM_IN_ADDR_CLASS_B; + case 192 ... 223: + return NM_IN_ADDR_CLASS_C; + default: + return NM_IN_ADDR_CLASS_INVALID; + } } static gboolean -lease_option_consume (void *out, - size_t n_out, - uint8_t **datap, - size_t *n_datap) +lease_option_consume(void *out, size_t n_out, uint8_t **datap, size_t *n_datap) { - if (*n_datap < n_out) - return FALSE; + if (*n_datap < n_out) + return FALSE; - memcpy (out, *datap, n_out); - *datap += n_out; - *n_datap -= n_out; - return TRUE; + memcpy(out, *datap, n_out); + *datap += n_out; + *n_datap -= n_out; + return TRUE; } static gboolean -lease_option_next_in_addr (struct in_addr *addrp, - uint8_t **datap, - size_t *n_datap) +lease_option_next_in_addr(struct in_addr *addrp, uint8_t **datap, size_t *n_datap) { - return lease_option_consume (addrp, sizeof (struct in_addr), datap, n_datap); + return lease_option_consume(addrp, sizeof(struct in_addr), datap, n_datap); } static gboolean -lease_option_next_route (struct in_addr *destp, - uint8_t *plenp, - struct in_addr *gatewayp, - gboolean classless, - uint8_t **datap, - size_t *n_datap) +lease_option_next_route(struct in_addr *destp, + uint8_t * plenp, + struct in_addr *gatewayp, + gboolean classless, + uint8_t ** datap, + size_t * n_datap) { - struct in_addr dest = {}, gateway; - uint8_t *data = *datap; - size_t n_data = *n_datap; - uint8_t plen; - uint8_t bytes; - - if (classless) { - if (!lease_option_consume (&plen, sizeof (plen), &data, &n_data)) - return FALSE; - - if (plen > 32) - return FALSE; - - bytes = plen == 0 ? 0 : ((plen - 1) / 8) + 1; - - if (!lease_option_consume (&dest, bytes, &data, &n_data)) - return FALSE; - } else { - if (!lease_option_next_in_addr (&dest, &data, &n_data)) - return FALSE; - - switch (in_addr_class (dest)) { - case NM_IN_ADDR_CLASS_A: - plen = 8; - break; - case NM_IN_ADDR_CLASS_B: - plen = 16; - break; - case NM_IN_ADDR_CLASS_C: - plen = 24; - break; - case NM_IN_ADDR_CLASS_INVALID: - return FALSE; - } - } - - dest.s_addr = nm_utils_ip4_address_clear_host_address (dest.s_addr, plen); - - if (!lease_option_next_in_addr (&gateway, &data, &n_data)) - return FALSE; - - *destp = dest; - *plenp = plen; - *gatewayp = gateway; - *datap = data; - *n_datap = n_data; - return TRUE; + struct in_addr dest = {}, gateway; + uint8_t * data = *datap; + size_t n_data = *n_datap; + uint8_t plen; + uint8_t bytes; + + if (classless) { + if (!lease_option_consume(&plen, sizeof(plen), &data, &n_data)) + return FALSE; + + if (plen > 32) + return FALSE; + + bytes = plen == 0 ? 0 : ((plen - 1) / 8) + 1; + + if (!lease_option_consume(&dest, bytes, &data, &n_data)) + return FALSE; + } else { + if (!lease_option_next_in_addr(&dest, &data, &n_data)) + return FALSE; + + switch (in_addr_class(dest)) { + case NM_IN_ADDR_CLASS_A: + plen = 8; + break; + case NM_IN_ADDR_CLASS_B: + plen = 16; + break; + case NM_IN_ADDR_CLASS_C: + plen = 24; + break; + case NM_IN_ADDR_CLASS_INVALID: + return FALSE; + } + } + + dest.s_addr = nm_utils_ip4_address_clear_host_address(dest.s_addr, plen); + + if (!lease_option_next_in_addr(&gateway, &data, &n_data)) + return FALSE; + + *destp = dest; + *plenp = plen; + *gatewayp = gateway; + *datap = data; + *n_datap = n_data; + return TRUE; } static gboolean -lease_option_print_label (GString *str, size_t n_label, uint8_t **datap, size_t *n_datap) +lease_option_print_label(GString *str, size_t n_label, uint8_t **datap, size_t *n_datap) { - for (size_t i = 0; i < n_label; ++i) { - uint8_t c; - - if (!lease_option_consume(&c, sizeof (c), datap, n_datap)) - return FALSE; - - switch (c) { - case 'a' ... 'z': - case 'A' ... 'Z': - case '0' ... '9': - case '-': - case '_': - g_string_append_c(str, c); - break; - case '.': - case '\\': - g_string_append_printf(str, "\\%c", c); - break; - default: - g_string_append_printf(str, "\\%3d", c); - } - } - - return TRUE; + for (size_t i = 0; i < n_label; ++i) { + uint8_t c; + + if (!lease_option_consume(&c, sizeof(c), datap, n_datap)) + return FALSE; + + switch (c) { + case 'a' ... 'z': + case 'A' ... 'Z': + case '0' ... '9': + case '-': + case '_': + g_string_append_c(str, c); + break; + case '.': + case '\\': + g_string_append_printf(str, "\\%c", c); + break; + default: + g_string_append_printf(str, "\\%3d", c); + } + } + + return TRUE; } static gboolean -lease_option_print_domain_name (GString *str, uint8_t *cache, size_t *n_cachep, uint8_t **datap, size_t *n_datap) +lease_option_print_domain_name(GString * str, + uint8_t * cache, + size_t * n_cachep, + uint8_t **datap, + size_t * n_datap) { - uint8_t *domain; - size_t n_domain, n_cache = *n_cachep; - uint8_t **domainp = datap; - size_t *n_domainp = n_datap; - gboolean first = TRUE; - uint8_t c; - - /* - * We are given two adjacent memory regions. The @cache contains alreday parsed - * domain names, and the @datap contains the remaining data to parse. - * - * A domain name is formed from a sequence of labels. Each label start with - * a length byte, where the two most significant bits are unset. A zero-length - * label indicates the end of the domain name. - * - * Alternatively, a label can be followed by an offset (indicated by the two - * most significant bits being set in the next byte that is read). The offset - * is an offset into the cache, where the next label of the domain name can - * be found. - * - * Note, that each time a jump to an offset is performed, the size of the - * cache shrinks, so this is guaranteed to terminate. - */ - if (cache + n_cache != *datap) - return FALSE; - - for (;;) { - if (!lease_option_consume(&c, sizeof (c), domainp, n_domainp)) - return FALSE; - - switch (c & 0xC0) { - case 0x00: /* label length */ - { - size_t n_label = c; - - if (n_label == 0) { - /* - * We reached the final label of the domain name. Adjust - * the cache to include the consumed data, and return. - */ - *n_cachep = *datap - cache; - return TRUE; - } - - if (!first) - g_string_append_c(str, '.'); - else - first = FALSE; - - if (!lease_option_print_label (str, n_label, domainp, n_domainp)) - return FALSE; - - break; - } - case 0xC0: /* back pointer */ - { - size_t offset = (c & 0x3F) << 16; - - /* - * The offset is given as two bytes (in big endian), where the - * two high bits are masked out. - */ - - if (!lease_option_consume (&c, sizeof (c), domainp, n_domainp)) - return FALSE; - - offset += c; - - if (offset >= n_cache) - return FALSE; - - domain = cache + offset; - n_domain = n_cache - offset; - n_cache = offset; - - domainp = &domain; - n_domainp = &n_domain; - - break; - } - default: - return FALSE; - } - } + uint8_t * domain; + size_t n_domain, n_cache = *n_cachep; + uint8_t **domainp = datap; + size_t * n_domainp = n_datap; + gboolean first = TRUE; + uint8_t c; + + /* + * We are given two adjacent memory regions. The @cache contains alreday parsed + * domain names, and the @datap contains the remaining data to parse. + * + * A domain name is formed from a sequence of labels. Each label start with + * a length byte, where the two most significant bits are unset. A zero-length + * label indicates the end of the domain name. + * + * Alternatively, a label can be followed by an offset (indicated by the two + * most significant bits being set in the next byte that is read). The offset + * is an offset into the cache, where the next label of the domain name can + * be found. + * + * Note, that each time a jump to an offset is performed, the size of the + * cache shrinks, so this is guaranteed to terminate. + */ + if (cache + n_cache != *datap) + return FALSE; + + for (;;) { + if (!lease_option_consume(&c, sizeof(c), domainp, n_domainp)) + return FALSE; + + switch (c & 0xC0) { + case 0x00: /* label length */ + { + size_t n_label = c; + + if (n_label == 0) { + /* + * We reached the final label of the domain name. Adjust + * the cache to include the consumed data, and return. + */ + *n_cachep = *datap - cache; + return TRUE; + } + + if (!first) + g_string_append_c(str, '.'); + else + first = FALSE; + + if (!lease_option_print_label(str, n_label, domainp, n_domainp)) + return FALSE; + + break; + } + case 0xC0: /* back pointer */ + { + size_t offset = (c & 0x3F) << 16; + + /* + * The offset is given as two bytes (in big endian), where the + * two high bits are masked out. + */ + + if (!lease_option_consume(&c, sizeof(c), domainp, n_domainp)) + return FALSE; + + offset += c; + + if (offset >= n_cache) + return FALSE; + + domain = cache + offset; + n_domain = n_cache - offset; + n_cache = offset; + + domainp = &domain; + n_domainp = &n_domain; + + break; + } + default: + return FALSE; + } + } } static gboolean -lease_get_in_addr (NDhcp4ClientLease *lease, - guint8 option, - struct in_addr *addrp) { - struct in_addr addr; - uint8_t *data; - size_t n_data; - int r; - - r = n_dhcp4_client_lease_query (lease, option, &data, &n_data); - if (r) - return FALSE; - - if (!lease_option_next_in_addr (&addr, &data, &n_data)) - return FALSE; - - if (n_data != 0) - return FALSE; - - *addrp = addr; - return TRUE; +lease_get_in_addr(NDhcp4ClientLease *lease, guint8 option, struct in_addr *addrp) +{ + struct in_addr addr; + uint8_t * data; + size_t n_data; + int r; + + r = n_dhcp4_client_lease_query(lease, option, &data, &n_data); + if (r) + return FALSE; + + if (!lease_option_next_in_addr(&addr, &data, &n_data)) + return FALSE; + + if (n_data != 0) + return FALSE; + + *addrp = addr; + return TRUE; } static gboolean -lease_get_u16 (NDhcp4ClientLease *lease, - uint8_t option, - uint16_t *u16p) +lease_get_u16(NDhcp4ClientLease *lease, uint8_t option, uint16_t *u16p) { - uint8_t *data; - size_t n_data; - uint16_t be16; - int r; + uint8_t *data; + size_t n_data; + uint16_t be16; + int r; - r = n_dhcp4_client_lease_query (lease, option, &data, &n_data); - if (r) - return FALSE; + r = n_dhcp4_client_lease_query(lease, option, &data, &n_data); + if (r) + return FALSE; - if (n_data != sizeof (be16)) - return FALSE; + if (n_data != sizeof(be16)) + return FALSE; - memcpy (&be16, data, sizeof (be16)); + memcpy(&be16, data, sizeof(be16)); - *u16p = ntohs(be16); - return TRUE; + *u16p = ntohs(be16); + return TRUE; } static gboolean -lease_parse_address (NDhcp4ClientLease *lease, - NMIP4Config *ip4_config, - GHashTable *options, - GError **error) +lease_parse_address(NDhcp4ClientLease *lease, + NMIP4Config * ip4_config, + GHashTable * options, + GError ** error) { - char addr_str[NM_UTILS_INET_ADDRSTRLEN]; - struct in_addr a_address; - struct in_addr a_netmask; - struct in_addr a_next_server; - guint32 a_plen; - guint64 nettools_lifetime; - guint32 a_lifetime; - guint32 a_timestamp; - guint64 a_expiry; - - n_dhcp4_client_lease_get_yiaddr (lease, &a_address); - if (a_address.s_addr == INADDR_ANY) { - nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "could not get address from lease"); - return FALSE; - } - - n_dhcp4_client_lease_get_lifetime (lease, &nettools_lifetime); - - if (nettools_lifetime == G_MAXUINT64) { - a_timestamp = 0; - a_lifetime = NM_PLATFORM_LIFETIME_PERMANENT; - a_expiry = G_MAXUINT64; - } else { - guint64 nettools_basetime; - guint64 lifetime; - gint64 ts; - - n_dhcp4_client_lease_get_basetime (lease, &nettools_basetime); - - /* usually we shouldn't assert against external libraries like n-dhcp4. - * Here we still do it... it seems safe enough. */ - nm_assert (nettools_basetime > 0); - nm_assert (nettools_lifetime >= nettools_basetime); - nm_assert (((nettools_lifetime - nettools_basetime) % NM_UTILS_NSEC_PER_SEC) == 0); - nm_assert ((nettools_lifetime - nettools_basetime) / NM_UTILS_NSEC_PER_SEC <= G_MAXUINT32); - - if (nettools_lifetime <= nettools_basetime) { - /* A lease time of 0 is allowed on some dhcp servers, so, let's accept it. */ - lifetime = 0; - } else { - lifetime = nettools_lifetime - nettools_basetime; - - /* we "ceil" the value to the next second. In practice, we don't expect any sub-second values - * from n-dhcp4 anyway, so this should have no effect. */ - lifetime += NM_UTILS_NSEC_PER_SEC - 1; - } - - ts = nm_utils_monotonic_timestamp_from_boottime (nettools_basetime, 1); - - /* the timestamp must be positive, because we only started nettools DHCP client - * after obtaining the first monotonic timestamp. Hence, the lease must have been - * received afterwards. */ - nm_assert (ts >= NM_UTILS_NSEC_PER_SEC); - - a_timestamp = ts / NM_UTILS_NSEC_PER_SEC; - a_lifetime = NM_MIN (lifetime / NM_UTILS_NSEC_PER_SEC, NM_PLATFORM_LIFETIME_PERMANENT - 1); - a_expiry = time (NULL) + ((lifetime - (nm_utils_clock_gettime_nsec (CLOCK_BOOTTIME) - nettools_basetime)) / NM_UTILS_NSEC_PER_SEC); - } - - if (!lease_get_in_addr (lease, NM_DHCP_OPTION_DHCP4_SUBNET_MASK, &a_netmask)) { - nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "could not get netmask from lease"); - return FALSE; - } - - _nm_utils_inet4_ntop (a_address.s_addr, addr_str); - a_plen = nm_utils_ip4_netmask_to_prefix (a_netmask.s_addr); - - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, - addr_str); - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_SUBNET_MASK, - _nm_utils_inet4_ntop (a_netmask.s_addr, addr_str)); - - nm_dhcp_option_add_option_u64 (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME, - (guint64) a_lifetime); - - if (a_expiry != G_MAXUINT64) { - nm_dhcp_option_add_option_u64 (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_NM_EXPIRY, - a_expiry); - } - - - n_dhcp4_client_lease_get_siaddr (lease, &a_next_server); - if (a_next_server.s_addr != INADDR_ANY) { - _nm_utils_inet4_ntop (a_next_server.s_addr, addr_str); - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - 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 = a_timestamp, - .lifetime = a_lifetime, - .preferred = a_lifetime, - })); - - return TRUE; + char addr_str[NM_UTILS_INET_ADDRSTRLEN]; + struct in_addr a_address; + struct in_addr a_netmask; + struct in_addr a_next_server; + guint32 a_plen; + guint64 nettools_lifetime; + guint32 a_lifetime; + guint32 a_timestamp; + guint64 a_expiry; + + n_dhcp4_client_lease_get_yiaddr(lease, &a_address); + if (a_address.s_addr == INADDR_ANY) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_UNKNOWN, + "could not get address from lease"); + return FALSE; + } + + n_dhcp4_client_lease_get_lifetime(lease, &nettools_lifetime); + + if (nettools_lifetime == G_MAXUINT64) { + a_timestamp = 0; + a_lifetime = NM_PLATFORM_LIFETIME_PERMANENT; + a_expiry = G_MAXUINT64; + } else { + guint64 nettools_basetime; + guint64 lifetime; + gint64 ts; + + n_dhcp4_client_lease_get_basetime(lease, &nettools_basetime); + + /* usually we shouldn't assert against external libraries like n-dhcp4. + * Here we still do it... it seems safe enough. */ + nm_assert(nettools_basetime > 0); + nm_assert(nettools_lifetime >= nettools_basetime); + nm_assert(((nettools_lifetime - nettools_basetime) % NM_UTILS_NSEC_PER_SEC) == 0); + nm_assert((nettools_lifetime - nettools_basetime) / NM_UTILS_NSEC_PER_SEC <= G_MAXUINT32); + + if (nettools_lifetime <= nettools_basetime) { + /* A lease time of 0 is allowed on some dhcp servers, so, let's accept it. */ + lifetime = 0; + } else { + lifetime = nettools_lifetime - nettools_basetime; + + /* we "ceil" the value to the next second. In practice, we don't expect any sub-second values + * from n-dhcp4 anyway, so this should have no effect. */ + lifetime += NM_UTILS_NSEC_PER_SEC - 1; + } + + ts = nm_utils_monotonic_timestamp_from_boottime(nettools_basetime, 1); + + /* the timestamp must be positive, because we only started nettools DHCP client + * after obtaining the first monotonic timestamp. Hence, the lease must have been + * received afterwards. */ + nm_assert(ts >= NM_UTILS_NSEC_PER_SEC); + + a_timestamp = ts / NM_UTILS_NSEC_PER_SEC; + a_lifetime = NM_MIN(lifetime / NM_UTILS_NSEC_PER_SEC, NM_PLATFORM_LIFETIME_PERMANENT - 1); + a_expiry = time(NULL) + + ((lifetime - (nm_utils_clock_gettime_nsec(CLOCK_BOOTTIME) - nettools_basetime)) + / NM_UTILS_NSEC_PER_SEC); + } + + if (!lease_get_in_addr(lease, NM_DHCP_OPTION_DHCP4_SUBNET_MASK, &a_netmask)) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_UNKNOWN, + "could not get netmask from lease"); + return FALSE; + } + + _nm_utils_inet4_ntop(a_address.s_addr, addr_str); + a_plen = nm_utils_ip4_netmask_to_prefix(a_netmask.s_addr); + + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, + addr_str); + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_SUBNET_MASK, + _nm_utils_inet4_ntop(a_netmask.s_addr, addr_str)); + + nm_dhcp_option_add_option_u64(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME, + (guint64) a_lifetime); + + if (a_expiry != G_MAXUINT64) { + nm_dhcp_option_add_option_u64(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_NM_EXPIRY, + a_expiry); + } + + n_dhcp4_client_lease_get_siaddr(lease, &a_next_server); + if (a_next_server.s_addr != INADDR_ANY) { + _nm_utils_inet4_ntop(a_next_server.s_addr, addr_str); + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + 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 = a_timestamp, + .lifetime = a_lifetime, + .preferred = a_lifetime, + })); + + return TRUE; } static void -lease_parse_domain_name_servers (NDhcp4ClientLease *lease, - NMIP4Config *ip4_config, - GHashTable *options) +lease_parse_address_list(NDhcp4ClientLease * lease, + NMIP4Config * ip4_config, + NMDhcpOptionDhcp4Options option, + GHashTable * options) { - nm_auto_free_gstring GString *str = NULL; - char addr_str[NM_UTILS_INET_ADDRSTRLEN]; - struct in_addr addr; - uint8_t *data; - size_t n_data; - int r; - - r = n_dhcp4_client_lease_query (lease, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, &data, &n_data); - if (r) - return; - - nm_gstring_prepare (&str); - - while (lease_option_next_in_addr (&addr, &data, &n_data)) { - - _nm_utils_inet4_ntop (addr.s_addr, addr_str); - g_string_append (nm_gstring_add_space_delimiter (str), addr_str); - - if ( addr.s_addr == 0 - || nm_ip4_addr_is_localhost (addr.s_addr)) { - /* Skip localhost addresses, like also networkd does. - * See https://github.com/systemd/systemd/issues/4524. */ - continue; - } - nm_ip4_config_add_nameserver (ip4_config, addr.s_addr); - } - - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, - str->str); + nm_auto_free_gstring GString *str = NULL; + char addr_str[NM_UTILS_INET_ADDRSTRLEN]; + struct in_addr addr; + uint8_t * data; + size_t n_data; + int r; + + r = n_dhcp4_client_lease_query(lease, option, &data, &n_data); + if (r) + return; + + nm_gstring_prepare(&str); + + while (lease_option_next_in_addr(&addr, &data, &n_data)) { + _nm_utils_inet4_ntop(addr.s_addr, addr_str); + g_string_append(nm_gstring_add_space_delimiter(str), addr_str); + + switch (option) { + case NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER: + if (addr.s_addr == 0 || nm_ip4_addr_is_localhost(addr.s_addr)) { + /* Skip localhost addresses, like also networkd does. + * See https://github.com/systemd/systemd/issues/4524. */ + continue; + } + nm_ip4_config_add_nameserver(ip4_config, addr.s_addr); + break; + case NM_DHCP_OPTION_DHCP4_NIS_SERVERS: + nm_ip4_config_add_nis_server(ip4_config, addr.s_addr); + break; + case NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER: + nm_ip4_config_add_wins(ip4_config, addr.s_addr); + break; + default: + nm_assert_not_reached(); + } + } + + nm_dhcp_option_add_option(options, _nm_dhcp_option_dhcp4_options, option, str->str); } static void -lease_parse_routes (NDhcp4ClientLease *lease, - NMIP4Config *ip4_config, - GHashTable *options, - guint32 route_table, - guint32 route_metric) +lease_parse_routes(NDhcp4ClientLease *lease, + NMIP4Config * ip4_config, + GHashTable * options, + guint32 route_table, + guint32 route_metric) { - nm_auto_free_gstring GString *str = NULL; - char dest_str[NM_UTILS_INET_ADDRSTRLEN]; - char gateway_str[NM_UTILS_INET_ADDRSTRLEN]; - const char *s; - struct in_addr dest, gateway; - uint8_t plen; - guint32 m; - gboolean has_router_from_classless = FALSE, has_classless = FALSE; - guint32 default_route_metric = route_metric; - uint8_t *data; - size_t n_data; - int r; - - r = n_dhcp4_client_lease_query (lease, NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, &data, &n_data); - if (!r) { - nm_gstring_prepare (&str); - - has_classless = TRUE; - - while (lease_option_next_route (&dest, &plen, &gateway, TRUE, &data, &n_data)) { - - _nm_utils_inet4_ntop (dest.s_addr, dest_str); - _nm_utils_inet4_ntop (gateway.s_addr, gateway_str); - - g_string_append_printf (nm_gstring_add_space_delimiter (str), - "%s/%d %s", - dest_str, - (int) plen, - gateway_str); - - 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++; - - has_router_from_classless = TRUE; - } else { - m = route_metric; - } - - nm_ip4_config_add_route (ip4_config, - &((const NMPlatformIP4Route) { - .network = dest.s_addr, - .plen = plen, - .gateway = gateway.s_addr, - .rt_source = NM_IP_CONFIG_SOURCE_DHCP, - .metric = m, - .table_coerced = nm_platform_route_table_coerce (route_table), - }), - NULL); - } - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, - str->str); - } - - r = n_dhcp4_client_lease_query (lease, NM_DHCP_OPTION_DHCP4_STATIC_ROUTE, &data, &n_data); - if (!r) { - nm_gstring_prepare (&str); - - while (lease_option_next_route (&dest, &plen, &gateway, FALSE, &data, &n_data)) { - - _nm_utils_inet4_ntop (dest.s_addr, dest_str); - _nm_utils_inet4_ntop (gateway.s_addr, gateway_str); - - g_string_append_printf (nm_gstring_add_space_delimiter (str), - "%s/%d %s", - dest_str, - (int) plen, - gateway_str); - - if (has_classless) { - /* RFC 3443: if the DHCP server returns both a Classless Static Routes - * option and a Static Routes option, the DHCP client MUST ignore the - * Static Routes option. */ - continue; - } - - if (plen == 0) { - /* for option 33 (static route), RFC 2132 says: - * - * The default route (0.0.0.0) is an illegal destination for a static - * route. */ - continue; - } - - nm_ip4_config_add_route (ip4_config, - &((const NMPlatformIP4Route) { - .network = dest.s_addr, - .plen = plen, - .gateway = gateway.s_addr, - .rt_source = NM_IP_CONFIG_SOURCE_DHCP, - .metric = route_metric, - .table_coerced = nm_platform_route_table_coerce (route_table), - }), - NULL); - } - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_STATIC_ROUTE, - str->str); - } - - r = n_dhcp4_client_lease_query (lease, NM_DHCP_OPTION_DHCP4_ROUTER, &data, &n_data); - if (!r) { - nm_gstring_prepare (&str); - - while (lease_option_next_in_addr (&gateway, &data, &n_data)) { - s = _nm_utils_inet4_ntop (gateway.s_addr, gateway_str); - g_string_append (nm_gstring_add_space_delimiter (str), s); - - if (gateway.s_addr == 0) { - /* silently skip 0.0.0.0 */ - continue; - } - - if (has_router_from_classless) { - /* If the DHCP server returns both a Classless Static Routes option and a - * Router option, the DHCP client MUST ignore the Router option [RFC 3442]. - * - * Be more lenient and ignore the Router option only if Classless Static - * Routes contain a default gateway (as other DHCP backends do). - */ - continue; - } - - /* 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.s_addr, - .table_coerced = nm_platform_route_table_coerce (route_table), - .metric = m, - }), - NULL); - } - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_ROUTER, - str->str); - } + nm_auto_free_gstring GString *str = NULL; + char dest_str[NM_UTILS_INET_ADDRSTRLEN]; + char gateway_str[NM_UTILS_INET_ADDRSTRLEN]; + const char * s; + struct in_addr dest, gateway; + uint8_t plen; + guint32 m; + gboolean has_router_from_classless = FALSE, has_classless = FALSE; + guint32 default_route_metric = route_metric; + uint8_t * data; + size_t n_data; + int r; + + r = n_dhcp4_client_lease_query(lease, + NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, + &data, + &n_data); + if (!r) { + nm_gstring_prepare(&str); + + has_classless = TRUE; + + while (lease_option_next_route(&dest, &plen, &gateway, TRUE, &data, &n_data)) { + _nm_utils_inet4_ntop(dest.s_addr, dest_str); + _nm_utils_inet4_ntop(gateway.s_addr, gateway_str); + + g_string_append_printf(nm_gstring_add_space_delimiter(str), + "%s/%d %s", + dest_str, + (int) plen, + gateway_str); + + 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++; + + has_router_from_classless = TRUE; + } else { + m = route_metric; + } + + nm_ip4_config_add_route( + ip4_config, + &((const NMPlatformIP4Route){ + .network = dest.s_addr, + .plen = plen, + .gateway = gateway.s_addr, + .rt_source = NM_IP_CONFIG_SOURCE_DHCP, + .metric = m, + .table_coerced = nm_platform_route_table_coerce(route_table), + }), + NULL); + } + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, + str->str); + } + + r = n_dhcp4_client_lease_query(lease, NM_DHCP_OPTION_DHCP4_STATIC_ROUTE, &data, &n_data); + if (!r) { + nm_gstring_prepare(&str); + + while (lease_option_next_route(&dest, &plen, &gateway, FALSE, &data, &n_data)) { + _nm_utils_inet4_ntop(dest.s_addr, dest_str); + _nm_utils_inet4_ntop(gateway.s_addr, gateway_str); + + g_string_append_printf(nm_gstring_add_space_delimiter(str), + "%s/%d %s", + dest_str, + (int) plen, + gateway_str); + + if (has_classless) { + /* RFC 3443: if the DHCP server returns both a Classless Static Routes + * option and a Static Routes option, the DHCP client MUST ignore the + * Static Routes option. */ + continue; + } + + if (plen == 0) { + /* for option 33 (static route), RFC 2132 says: + * + * The default route (0.0.0.0) is an illegal destination for a static + * route. */ + continue; + } + + nm_ip4_config_add_route( + ip4_config, + &((const NMPlatformIP4Route){ + .network = dest.s_addr, + .plen = plen, + .gateway = gateway.s_addr, + .rt_source = NM_IP_CONFIG_SOURCE_DHCP, + .metric = route_metric, + .table_coerced = nm_platform_route_table_coerce(route_table), + }), + NULL); + } + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_STATIC_ROUTE, + str->str); + } + + r = n_dhcp4_client_lease_query(lease, NM_DHCP_OPTION_DHCP4_ROUTER, &data, &n_data); + if (!r) { + nm_gstring_prepare(&str); + + while (lease_option_next_in_addr(&gateway, &data, &n_data)) { + s = _nm_utils_inet4_ntop(gateway.s_addr, gateway_str); + g_string_append(nm_gstring_add_space_delimiter(str), s); + + if (gateway.s_addr == 0) { + /* silently skip 0.0.0.0 */ + continue; + } + + if (has_router_from_classless) { + /* If the DHCP server returns both a Classless Static Routes option and a + * Router option, the DHCP client MUST ignore the Router option [RFC 3442]. + * + * Be more lenient and ignore the Router option only if Classless Static + * Routes contain a default gateway (as other DHCP backends do). + */ + continue; + } + + /* 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.s_addr, + .table_coerced = nm_platform_route_table_coerce(route_table), + .metric = m, + }), + NULL); + } + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_ROUTER, + str->str); + } } static void -lease_parse_mtu (NDhcp4ClientLease *lease, - NMIP4Config *ip4_config, - GHashTable *options) +lease_parse_mtu(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GHashTable *options) { - uint16_t mtu; + uint16_t mtu; - if (!lease_get_u16 (lease, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, &mtu)) - return; + if (!lease_get_u16(lease, NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, &mtu)) + return; - if (mtu < 68) - return; + if (mtu < 68) + return; - nm_dhcp_option_add_option_u64 (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, - mtu); - nm_ip4_config_set_mtu (ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP); + nm_dhcp_option_add_option_u64(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, + mtu); + nm_ip4_config_set_mtu(ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP); } static void -lease_parse_metered (NDhcp4ClientLease *lease, - NMIP4Config *ip4_config, - GHashTable *options) +lease_parse_metered(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GHashTable *options) { - gboolean metered = FALSE; - uint8_t *data; - size_t n_data; - int r; - - r = n_dhcp4_client_lease_query (lease, NM_DHCP_OPTION_DHCP4_VENDOR_SPECIFIC, &data, &n_data); - if (r) - metered = FALSE; - else - metered = !!memmem (data, n_data, "ANDROID_METERED", NM_STRLEN ("ANDROID_METERED")); - - /* TODO: expose the vendor specific option when present */ - nm_ip4_config_set_metered (ip4_config, metered); + gboolean metered = FALSE; + uint8_t *data; + size_t n_data; + int r; + + r = n_dhcp4_client_lease_query(lease, NM_DHCP_OPTION_DHCP4_VENDOR_SPECIFIC, &data, &n_data); + if (r) + metered = FALSE; + else + metered = !!memmem(data, n_data, "ANDROID_METERED", NM_STRLEN("ANDROID_METERED")); + + /* TODO: expose the vendor specific option when present */ + nm_ip4_config_set_metered(ip4_config, metered); } static void -lease_parse_ntps (NDhcp4ClientLease *lease, - GHashTable *options) +lease_parse_ntps(NDhcp4ClientLease *lease, GHashTable *options) { - nm_auto_free_gstring GString *str = NULL; - char addr_str[NM_UTILS_INET_ADDRSTRLEN]; - struct in_addr addr; - uint8_t *data; - size_t n_data; - int r; - - r = n_dhcp4_client_lease_query (lease, NM_DHCP_OPTION_DHCP4_NTP_SERVER, &data, &n_data); - if (r) - return; - - nm_gstring_prepare (&str); - - while (lease_option_next_in_addr (&addr, &data, &n_data)) { - _nm_utils_inet4_ntop (addr.s_addr, addr_str); - g_string_append (nm_gstring_add_space_delimiter (str), addr_str); - } - - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_NTP_SERVER, - str->str); + nm_auto_free_gstring GString *str = NULL; + char addr_str[NM_UTILS_INET_ADDRSTRLEN]; + struct in_addr addr; + uint8_t * data; + size_t n_data; + int r; + + r = n_dhcp4_client_lease_query(lease, NM_DHCP_OPTION_DHCP4_NTP_SERVER, &data, &n_data); + if (r) + return; + + nm_gstring_prepare(&str); + + while (lease_option_next_in_addr(&addr, &data, &n_data)) { + _nm_utils_inet4_ntop(addr.s_addr, addr_str); + g_string_append(nm_gstring_add_space_delimiter(str), addr_str); + } + + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_NTP_SERVER, + str->str); } static void -lease_parse_hostname (NDhcp4ClientLease *lease, - GHashTable *options) +lease_parse_hostname(NDhcp4ClientLease *lease, GHashTable *options) { - nm_auto_free_gstring GString *str = NULL; - uint8_t *data; - size_t n_data; - int r; + nm_auto_free_gstring GString *str = NULL; + uint8_t * data; + size_t n_data; + int r; - r = n_dhcp4_client_lease_query (lease, NM_DHCP_OPTION_DHCP4_HOST_NAME, &data, &n_data); - if (r) - return; + r = n_dhcp4_client_lease_query(lease, NM_DHCP_OPTION_DHCP4_HOST_NAME, &data, &n_data); + if (r) + return; - str = g_string_new_len ((char *)data, n_data); + str = g_string_new_len((char *) data, n_data); - if (is_localhost(str->str)) - return; + if (nm_utils_is_localhost(str->str)) + return; - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_HOST_NAME, - str->str); + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_HOST_NAME, + str->str); } static void -lease_parse_domainname (NDhcp4ClientLease *lease, - NMIP4Config *ip4_config, - GHashTable *options) +lease_parse_domainname(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GHashTable *options) { - nm_auto_free_gstring GString *str = NULL; - gs_strfreev char **domains = NULL; - uint8_t *data; - size_t n_data; - int r; - - r = n_dhcp4_client_lease_query (lease, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, &data, &n_data); - if (r) - return; - - str = g_string_new_len ((char *)data, n_data); - - /* Multiple domains sometimes stuffed into option 15 "Domain Name". */ - domains = g_strsplit (str->str, " ", 0); - nm_gstring_prepare (&str); - - for (char **d = domains; *d; d++) { - if (is_localhost(*d)) - return; - - g_string_append (nm_gstring_add_space_delimiter (str), *d); - nm_ip4_config_add_domain (ip4_config, *d); - } - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, - str->str); + nm_auto_free_gstring GString *str = NULL; + gs_strfreev char ** domains = NULL; + uint8_t * data; + size_t n_data; + int r; + + r = n_dhcp4_client_lease_query(lease, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, &data, &n_data); + if (r) + return; + + str = g_string_new_len((char *) data, n_data); + + /* Multiple domains sometimes stuffed into option 15 "Domain Name". */ + domains = g_strsplit(str->str, " ", 0); + nm_gstring_prepare(&str); + + for (char **d = domains; *d; d++) { + if (nm_utils_is_localhost(*d)) + return; + + g_string_append(nm_gstring_add_space_delimiter(str), *d); + nm_ip4_config_add_domain(ip4_config, *d); + } + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, + str->str); } char ** -nm_dhcp_parse_search_list (guint8 *data, size_t n_data) +nm_dhcp_parse_search_list(guint8 *data, size_t n_data) { - GPtrArray *array = NULL; - guint8 *cache = data; - size_t n_cache = 0; + GPtrArray *array = NULL; + guint8 * cache = data; + size_t n_cache = 0; - for (;;) { - nm_auto_free_gstring GString *domain = NULL; + for (;;) { + nm_auto_free_gstring GString *domain = NULL; - nm_gstring_prepare (&domain); + nm_gstring_prepare(&domain); - if (!lease_option_print_domain_name (domain, cache, &n_cache, &data, &n_data)) - break; + if (!lease_option_print_domain_name(domain, cache, &n_cache, &data, &n_data)) + break; - if (!array) - array = g_ptr_array_new (); + if (!array) + array = g_ptr_array_new(); - g_ptr_array_add (array, g_string_free (domain, FALSE)); - domain = NULL; - } + g_ptr_array_add(array, g_string_free(domain, FALSE)); + domain = NULL; + } - if (array) { - g_ptr_array_add (array, NULL); - return (char **) g_ptr_array_free (array, FALSE); - } else - return NULL; + if (array) { + g_ptr_array_add(array, NULL); + return (char **) g_ptr_array_free(array, FALSE); + } else + return NULL; } static void -lease_parse_search_domains (NDhcp4ClientLease *lease, - NMIP4Config *ip4_config, - GHashTable *options) +lease_parse_search_domains(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GHashTable *options) { - nm_auto_free_gstring GString *str = NULL; - uint8_t *data; - size_t n_data; - gs_strfreev char **domains = NULL; - guint i; - int r; - - r = n_dhcp4_client_lease_query (lease, NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, &data, &n_data); - if (r) - return; - - domains = nm_dhcp_parse_search_list (data, n_data); - nm_gstring_prepare (&str); - - for (i = 0; domains && domains[i]; i++) { - g_string_append (nm_gstring_add_space_delimiter (str), domains[i]); - nm_ip4_config_add_search (ip4_config, domains[i]); - } - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, - str->str); + nm_auto_free_gstring GString *str = NULL; + uint8_t * data; + size_t n_data; + gs_strfreev char ** domains = NULL; + guint i; + int r; + + r = n_dhcp4_client_lease_query(lease, NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, &data, &n_data); + if (r) + return; + + domains = nm_dhcp_parse_search_list(data, n_data); + nm_gstring_prepare(&str); + + for (i = 0; domains && domains[i]; i++) { + g_string_append(nm_gstring_add_space_delimiter(str), domains[i]); + nm_ip4_config_add_search(ip4_config, domains[i]); + } + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, + str->str); } static void -lease_parse_root_path (NDhcp4ClientLease *lease, - GHashTable *options) +lease_parse_root_path(NDhcp4ClientLease *lease, GHashTable *options) { - nm_auto_free_gstring GString *str = NULL; - uint8_t *data; - size_t n_data; - int r; - - r = n_dhcp4_client_lease_query (lease, NM_DHCP_OPTION_DHCP4_ROOT_PATH, &data, &n_data); - if (r) - return; - - str = g_string_new_len ((char *)data, n_data); - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_ROOT_PATH, - str->str); + nm_auto_free_gstring GString *str = NULL; + uint8_t * data; + size_t n_data; + int r; + + r = n_dhcp4_client_lease_query(lease, NM_DHCP_OPTION_DHCP4_ROOT_PATH, &data, &n_data); + if (r) + return; + + str = g_string_new_len((char *) data, n_data); + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_ROOT_PATH, + str->str); } static void -lease_parse_wpad (NDhcp4ClientLease *lease, - GHashTable *options) +lease_parse_wpad(NDhcp4ClientLease *lease, GHashTable *options) { - gs_free char *wpad = NULL; - uint8_t *data; - size_t n_data; - int r; - - r = n_dhcp4_client_lease_query (lease, NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY, &data, &n_data); - if (r) - return; - - nm_utils_buf_utf8safe_escape ((char *)data, n_data, 0, &wpad); - if (wpad == NULL) - wpad = g_strndup ((char *)data, n_data); - - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY, - wpad); + gs_free char *wpad = NULL; + uint8_t * data; + size_t n_data; + int r; + + r = n_dhcp4_client_lease_query(lease, + NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY, + &data, + &n_data); + if (r) + return; + + nm_utils_buf_utf8safe_escape((char *) data, n_data, 0, &wpad); + if (wpad == NULL) + wpad = g_strndup((char *) data, n_data); + + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY, + wpad); } static void -lease_parse_private_options (NDhcp4ClientLease *lease, - GHashTable *options) +lease_parse_nis_domain(NDhcp4ClientLease *lease, NMIP4Config *ip4_config, GHashTable *options) { - int i; - - for (i = NM_DHCP_OPTION_DHCP4_PRIVATE_224; i <= NM_DHCP_OPTION_DHCP4_PRIVATE_254; i++) { - gs_free char *option_string = NULL; - guint8 *data; - gsize n_data; - int r; - - /* We manage private options 249 (private classless static route) and 252 (wpad) in a special - * way, so skip them as we here just manage all (the other) private options as raw data */ - if (NM_IN_SET (i, NM_DHCP_OPTION_DHCP4_PRIVATE_CLASSLESS_STATIC_ROUTE, - NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY)) - continue; - - r = n_dhcp4_client_lease_query (lease, i, &data, &n_data); - if (r) - continue; - - option_string = nm_utils_bin2hexstr_full (data, n_data, ':', FALSE, NULL); - nm_dhcp_option_take_option (options, - _nm_dhcp_option_dhcp4_options, - i, - g_steal_pointer (&option_string)); - } + gs_free char *str_free = NULL; + const char * str; + uint8_t * data; + size_t n_data; + guint i; + int r; + + r = n_dhcp4_client_lease_query(lease, NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, &data, &n_data); + if (r) + return; + + for (i = 0; i < n_data; i++) { + if (!nm_is_ascii((char) data[i])) + return; + } + + str = nm_strndup_a(300, (const char *) data, n_data, &str_free); + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, + str); + nm_ip4_config_set_nis_domain(ip4_config, str); } -static NMIP4Config * -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) +static void +lease_parse_private_options(NDhcp4ClientLease *lease, GHashTable *options) { - gs_unref_object NMIP4Config *ip4_config = NULL; - gs_unref_hashtable GHashTable *options = NULL; - - g_return_val_if_fail (lease != NULL, NULL); - - ip4_config = nm_ip4_config_new (multi_idx, ifindex); - options = nm_dhcp_option_create_options_dict (); - - if (!lease_parse_address (lease, ip4_config, options, error)) - return NULL; - - lease_parse_routes (lease, ip4_config, options, route_table, route_metric); - lease_parse_domain_name_servers (lease, ip4_config, options); - lease_parse_domainname (lease, ip4_config, options); - lease_parse_search_domains (lease, ip4_config, options); - lease_parse_mtu (lease, ip4_config, options); - lease_parse_metered (lease, ip4_config, options); - - lease_parse_hostname (lease, options); - lease_parse_ntps (lease, options); - lease_parse_root_path (lease, options); - lease_parse_wpad (lease, options); - lease_parse_private_options (lease, options); + int i; + + for (i = NM_DHCP_OPTION_DHCP4_PRIVATE_224; i <= NM_DHCP_OPTION_DHCP4_PRIVATE_254; i++) { + gs_free char *option_string = NULL; + guint8 * data; + gsize n_data; + int r; + + /* We manage private options 249 (private classless static route) and 252 (wpad) in a special + * way, so skip them as we here just manage all (the other) private options as raw data */ + if (NM_IN_SET(i, + NM_DHCP_OPTION_DHCP4_PRIVATE_CLASSLESS_STATIC_ROUTE, + NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY)) + continue; + + r = n_dhcp4_client_lease_query(lease, i, &data, &n_data); + if (r) + continue; + + option_string = nm_utils_bin2hexstr_full(data, n_data, ':', FALSE, NULL); + nm_dhcp_option_take_option(options, + _nm_dhcp_option_dhcp4_options, + i, + g_steal_pointer(&option_string)); + } +} - NM_SET_OUT (out_options, g_steal_pointer (&options)); - return g_steal_pointer (&ip4_config); +static NMIP4Config * +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) +{ + gs_unref_object NMIP4Config *ip4_config = NULL; + gs_unref_hashtable GHashTable *options = NULL; + + g_return_val_if_fail(lease != NULL, NULL); + + ip4_config = nm_ip4_config_new(multi_idx, ifindex); + options = nm_dhcp_option_create_options_dict(); + + if (!lease_parse_address(lease, ip4_config, options, error)) + return NULL; + + lease_parse_routes(lease, ip4_config, options, route_table, route_metric); + lease_parse_address_list(lease, ip4_config, NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, options); + lease_parse_domainname(lease, ip4_config, options); + lease_parse_search_domains(lease, ip4_config, options); + lease_parse_mtu(lease, ip4_config, options); + lease_parse_metered(lease, ip4_config, options); + + lease_parse_hostname(lease, options); + lease_parse_ntps(lease, options); + lease_parse_root_path(lease, options); + lease_parse_wpad(lease, options); + lease_parse_nis_domain(lease, ip4_config, options); + lease_parse_address_list(lease, ip4_config, NM_DHCP_OPTION_DHCP4_NIS_SERVERS, options); + lease_parse_address_list(lease, ip4_config, NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER, options); + lease_parse_private_options(lease, options); + + NM_SET_OUT(out_options, g_steal_pointer(&options)); + return g_steal_pointer(&ip4_config); } /*****************************************************************************/ static void -lease_save (NMDhcpNettools *self, NDhcp4ClientLease *lease, const char *lease_file) +lease_save(NMDhcpNettools *self, NDhcp4ClientLease *lease, const char *lease_file) { - struct in_addr a_address; - nm_auto_free_gstring GString *new_contents = NULL; - char sbuf[NM_UTILS_INET_ADDRSTRLEN]; - gs_free_error GError *error = NULL; + struct in_addr a_address; + nm_auto_free_gstring GString *new_contents = NULL; + char sbuf[NM_UTILS_INET_ADDRSTRLEN]; + gs_free_error GError *error = NULL; - nm_assert (lease); - nm_assert (lease_file); + nm_assert(lease); + nm_assert(lease_file); - new_contents = g_string_new ("# This is private data. Do not parse.\n"); + new_contents = g_string_new("# This is private data. Do not parse.\n"); - n_dhcp4_client_lease_get_yiaddr (lease, &a_address); - if (a_address.s_addr == INADDR_ANY) - return; + n_dhcp4_client_lease_get_yiaddr(lease, &a_address); + if (a_address.s_addr == INADDR_ANY) + return; - g_string_append_printf (new_contents, - "ADDRESS=%s\n", _nm_utils_inet4_ntop (a_address.s_addr, sbuf)); + g_string_append_printf(new_contents, + "ADDRESS=%s\n", + _nm_utils_inet4_ntop(a_address.s_addr, sbuf)); - if (!g_file_set_contents (lease_file, - new_contents->str, - -1, - &error)) - _LOGW ("error saving lease to %s: %s", lease_file, error->message); + if (!g_file_set_contents(lease_file, new_contents->str, -1, &error)) + _LOGW("error saving lease to %s: %s", lease_file, error->message); } static void -bound4_handle (NMDhcpNettools *self, NDhcp4ClientLease *lease, gboolean extended) +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; - - _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); - g_clear_error (&error); - nm_dhcp_client_set_state (NM_DHCP_CLIENT (self), NM_DHCP_STATE_FAIL, NULL, NULL); - return; - } - - nm_dhcp_option_add_requests_to_options (options, _nm_dhcp_option_dhcp4_options); - 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); + 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; + + _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); + g_clear_error(&error); + nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL); + return; + } + + nm_dhcp_option_add_requests_to_options(options, _nm_dhcp_option_dhcp4_options); + 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); } -static gboolean -dhcp4_event_handle (NMDhcpNettools *self, - NDhcp4ClientEvent *event) +static void +dhcp4_event_handle(NMDhcpNettools *self, NDhcp4ClientEvent *event) { - NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE (self); - int r; - - _LOGT ("client event %d", event->event); - - switch (event->event) { - case N_DHCP4_CLIENT_EVENT_OFFER: - /* always accept the first lease */ - r = n_dhcp4_client_lease_select (event->offer.lease); - if (r) - _LOGW ("selecting lease failed: %d", r); - 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); - break; - case N_DHCP4_CLIENT_EVENT_CANCELLED: - nm_dhcp_client_set_state (NM_DHCP_CLIENT (self), NM_DHCP_STATE_FAIL, NULL, NULL); - break; - case N_DHCP4_CLIENT_EVENT_GRANTED: - priv->lease = n_dhcp4_client_lease_ref (event->granted.lease); - bound4_handle (self, event->granted.lease, FALSE); - break; - case N_DHCP4_CLIENT_EVENT_EXTENDED: - bound4_handle (self, event->extended.lease, TRUE); - break; - case N_DHCP4_CLIENT_EVENT_DOWN: - /* ignore down events, they are purely informational */ - break; - case N_DHCP4_CLIENT_EVENT_LOG: { - NMLogLevel nm_level; - - nm_level = nm_log_level_from_syslog (event->log.level); - if (nm_logging_enabled (nm_level, LOGD_DHCP4)) { - nm_log (nm_level, LOGD_DHCP4, NULL , NULL, - "dhcp4 (%s): %s", - nm_dhcp_client_get_iface (NM_DHCP_CLIENT (self)), - event->log.message); - } - } - break; - default: - _LOGW ("unhandled DHCP event %d", event->event); - break; - } - - return TRUE; + NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self); + struct in_addr server_id; + char addr_str[INET_ADDRSTRLEN]; + int r; + + _LOGT("client event %d", event->event); + + switch (event->event) { + case N_DHCP4_CLIENT_EVENT_OFFER: + r = n_dhcp4_client_lease_get_server_identifier(event->offer.lease, &server_id); + if (r) { + _LOGW("selecting lease failed: %d", r); + return; + } + + if (nm_dhcp_client_server_id_is_rejected(NM_DHCP_CLIENT(self), &server_id)) { + _LOGD("server-id %s is in the reject-list, ignoring", + nm_utils_inet_ntop(AF_INET, &server_id, addr_str)); + return; + } + + r = n_dhcp4_client_lease_select(event->offer.lease); + if (r) { + _LOGW("selecting lease failed: %d", r); + return; + } + 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); + break; + case N_DHCP4_CLIENT_EVENT_CANCELLED: + nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL); + break; + case N_DHCP4_CLIENT_EVENT_GRANTED: + priv->lease = n_dhcp4_client_lease_ref(event->granted.lease); + bound4_handle(self, event->granted.lease, FALSE); + break; + case N_DHCP4_CLIENT_EVENT_EXTENDED: + bound4_handle(self, event->extended.lease, TRUE); + break; + case N_DHCP4_CLIENT_EVENT_DOWN: + /* ignore down events, they are purely informational */ + break; + case N_DHCP4_CLIENT_EVENT_LOG: + { + NMLogLevel nm_level; + + nm_level = nm_log_level_from_syslog(event->log.level); + if (nm_logging_enabled(nm_level, LOGD_DHCP4)) { + nm_log(nm_level, + LOGD_DHCP4, + NULL, + NULL, + "dhcp4 (%s): %s", + nm_dhcp_client_get_iface(NM_DHCP_CLIENT(self)), + event->log.message); + } + } break; + default: + _LOGW("unhandled DHCP event %d", event->event); + break; + } } static gboolean -dhcp4_event_cb (int fd, - GIOCondition condition, - gpointer data) +dhcp4_event_cb(int fd, GIOCondition condition, gpointer data) { - NMDhcpNettools *self = data; - NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE (self); - NDhcp4ClientEvent *event; - int r; - - r = n_dhcp4_client_dispatch (priv->client); - if (r < 0) { - /* FIXME: if any operation (e.g. send()) fails during the - * dispatch, n-dhcp4 returns an error without arming timers - * or progressing state, so the only reasonable thing to do - * is to move to failed state so that the client will be - * restarted. Ideally n-dhcp4 should retry failed operations - * a predefined number of times (possibly infinite). - */ - _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); - return G_SOURCE_REMOVE; - } - - while (!n_dhcp4_client_pop_event (priv->client, &event) && event) { - dhcp4_event_handle (self, event); - } - - return G_SOURCE_CONTINUE; + NMDhcpNettools * self = data; + NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self); + NDhcp4ClientEvent * event; + int r; + + r = n_dhcp4_client_dispatch(priv->client); + if (r < 0) { + /* FIXME: if any operation (e.g. send()) fails during the + * dispatch, n-dhcp4 returns an error without arming timers + * or progressing state, so the only reasonable thing to do + * is to move to failed state so that the client will be + * restarted. Ideally n-dhcp4 should retry failed operations + * a predefined number of times (possibly infinite). + */ + _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); + return G_SOURCE_REMOVE; + } + + while (!n_dhcp4_client_pop_event(priv->client, &event) && event) { + dhcp4_event_handle(self, event); + } + + return G_SOURCE_CONTINUE; } static gboolean -nettools_create (NMDhcpNettools *self, - const char *dhcp_anycast_addr, - GError **error) +nettools_create(NMDhcpNettools *self, const char *dhcp_anycast_addr, GError **error) { - NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE (self); - nm_auto (n_dhcp4_client_config_freep) NDhcp4ClientConfig *config = NULL; - nm_auto (n_dhcp4_client_unrefp) NDhcp4Client *client = NULL; - GBytes *hwaddr; - GBytes *bcast_hwaddr; - const uint8_t *hwaddr_arr; - const uint8_t *bcast_hwaddr_arr; - 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; - - g_return_val_if_fail (!priv->client, FALSE); - - hwaddr = nm_dhcp_client_get_hw_addr (NM_DHCP_CLIENT (self)); - 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_arr = g_bytes_get_data (bcast_hwaddr, &bcast_hwaddr_len); - - switch (arp_type) { - case ARPHRD_ETHER: - transport = N_DHCP4_TRANSPORT_ETHERNET; - break; - case ARPHRD_INFINIBAND: - transport = N_DHCP4_TRANSPORT_INFINIBAND; - break; - default: - nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "unsupported ARP type"); - return FALSE; - } - - /* 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)); - if (!client_id) { - client_id_new = nm_utils_dhcp_client_id_mac (arp_type, hwaddr_arr, hwaddr_len); - client_id = client_id_new; - } - - if ( !(client_id_arr = g_bytes_get_data (client_id, &client_id_len)) - || client_id_len < 2) { - - /* invalid client-ids are not expected. */ - nm_assert_not_reached (); - - nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "no valid IPv4 client-id"); - return FALSE; - } - - r = n_dhcp4_client_config_new (&config); - if (r) { - set_error_nettools (error, r, "failed to create client-config"); - return FALSE; - } - - n_dhcp4_client_config_set_ifindex (config, nm_dhcp_client_get_ifindex (NM_DHCP_CLIENT (self))); - 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); - r = n_dhcp4_client_config_set_client_id (config, - client_id_arr, - NM_MIN (client_id_len, 1 + _NM_SD_MAX_CLIENT_ID_LEN)); - if (r) { - set_error_nettools (error, r, "failed to set client-id"); - return FALSE; - } - - r = n_dhcp4_client_new (&client, config); - if (r) { - set_error_nettools (error, r, "failed to create client"); - return FALSE; - } - - priv->client = client; - client = NULL; - - n_dhcp4_client_set_log_level (priv->client, nm_log_level_to_syslog (nm_logging_get_level (LOGD_DHCP4))); - - n_dhcp4_client_get_fd (priv->client, &fd); - - priv->event_source = nm_g_unix_fd_source_new (fd, - G_IO_IN, - G_PRIORITY_DEFAULT, - dhcp4_event_cb, - self, - NULL); - g_source_attach (priv->event_source, NULL); - - return TRUE; + NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self); + nm_auto(n_dhcp4_client_config_freep) NDhcp4ClientConfig *config = NULL; + nm_auto(n_dhcp4_client_unrefp) NDhcp4Client * client = NULL; + GBytes * hwaddr; + GBytes * bcast_hwaddr; + const uint8_t * hwaddr_arr; + const uint8_t * bcast_hwaddr_arr; + 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; + + g_return_val_if_fail(!priv->client, FALSE); + + hwaddr = nm_dhcp_client_get_hw_addr(NM_DHCP_CLIENT(self)); + 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_arr = g_bytes_get_data(bcast_hwaddr, &bcast_hwaddr_len); + + switch (arp_type) { + case ARPHRD_ETHER: + transport = N_DHCP4_TRANSPORT_ETHERNET; + break; + case ARPHRD_INFINIBAND: + transport = N_DHCP4_TRANSPORT_INFINIBAND; + break; + default: + nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "unsupported ARP type"); + return FALSE; + } + + /* 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)); + if (!client_id) { + client_id_new = nm_utils_dhcp_client_id_mac(arp_type, hwaddr_arr, hwaddr_len); + client_id = client_id_new; + } + + if (!(client_id_arr = g_bytes_get_data(client_id, &client_id_len)) || client_id_len < 2) { + /* invalid client-ids are not expected. */ + nm_assert_not_reached(); + + nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "no valid IPv4 client-id"); + return FALSE; + } + + r = n_dhcp4_client_config_new(&config); + if (r) { + set_error_nettools(error, r, "failed to create client-config"); + return FALSE; + } + + n_dhcp4_client_config_set_ifindex(config, nm_dhcp_client_get_ifindex(NM_DHCP_CLIENT(self))); + 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); + r = n_dhcp4_client_config_set_client_id(config, + client_id_arr, + NM_MIN(client_id_len, 1 + _NM_SD_MAX_CLIENT_ID_LEN)); + if (r) { + set_error_nettools(error, r, "failed to set client-id"); + return FALSE; + } + + r = n_dhcp4_client_new(&client, config); + if (r) { + set_error_nettools(error, r, "failed to create client"); + return FALSE; + } + + priv->client = client; + client = NULL; + + n_dhcp4_client_set_log_level(priv->client, + nm_log_level_to_syslog(nm_logging_get_level(LOGD_DHCP4))); + + n_dhcp4_client_get_fd(priv->client, &fd); + + priv->event_source = + nm_g_unix_fd_source_new(fd, G_IO_IN, G_PRIORITY_DEFAULT, dhcp4_event_cb, self, NULL); + g_source_attach(priv->event_source, NULL); + + return TRUE; } static gboolean -_accept (NMDhcpClient *client, - GError **error) +_accept(NMDhcpClient *client, GError **error) { - NMDhcpNettools *self = NM_DHCP_NETTOOLS (client); - NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE (self); - int r; + NMDhcpNettools * self = NM_DHCP_NETTOOLS(client); + NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self); + int r; - g_return_val_if_fail (priv->lease, FALSE); + g_return_val_if_fail(priv->lease, FALSE); - _LOGT ("accept"); + _LOGT("accept"); - r = n_dhcp4_client_lease_accept (priv->lease); - if (r) { - set_error_nettools (error, r, "failed to accept lease"); - return FALSE; - } + r = n_dhcp4_client_lease_accept(priv->lease); + if (r) { + set_error_nettools(error, r, "failed to accept lease"); + return FALSE; + } - priv->lease = n_dhcp4_client_lease_unref (priv->lease); + priv->lease = n_dhcp4_client_lease_unref(priv->lease); - return TRUE; + return TRUE; } static gboolean -decline (NMDhcpClient *client, - const char *error_message, - GError **error) +decline(NMDhcpClient *client, const char *error_message, GError **error) { - NMDhcpNettools *self = NM_DHCP_NETTOOLS (client); - NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE (self); - int r; + NMDhcpNettools * self = NM_DHCP_NETTOOLS(client); + NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self); + int r; - g_return_val_if_fail (priv->lease, FALSE); + g_return_val_if_fail(priv->lease, FALSE); - _LOGT ("dhcp4-client: decline"); + _LOGT("dhcp4-client: decline"); - r = n_dhcp4_client_lease_decline (priv->lease, error_message); - if (r) { - set_error_nettools (error, r, "failed to decline lease"); - return FALSE; - } + r = n_dhcp4_client_lease_decline(priv->lease, error_message); + if (r) { + set_error_nettools(error, r, "failed to decline lease"); + return FALSE; + } - priv->lease = n_dhcp4_client_lease_unref (priv->lease); + priv->lease = n_dhcp4_client_lease_unref(priv->lease); - return TRUE; + return TRUE; } static guint8 -fqdn_flags_to_wire (NMDhcpHostnameFlags flags) +fqdn_flags_to_wire(NMDhcpHostnameFlags flags) { - guint r = 0; + guint r = 0; - /* RFC 4702 section 2.1 */ - if (flags & NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE) - r |= (1 << 0); - if (flags & NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED) - r |= (1 << 2); - if (flags & NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE) - r |= (1 << 3); + /* RFC 4702 section 2.1 */ + if (flags & NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE) + r |= (1 << 0); + if (flags & NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED) + r |= (1 << 2); + if (flags & NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE) + r |= (1 << 3); - return r; + return r; } static gboolean -ip4_start (NMDhcpClient *client, - const char *dhcp_anycast_addr, - const char *last_ip4_address, - GError **error) +ip4_start(NMDhcpClient *client, + const char * dhcp_anycast_addr, + const char * last_ip4_address, + 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; - int r, i; - - g_return_val_if_fail (!priv->probe, FALSE); - - if (!nettools_create (self, dhcp_anycast_addr, error)) - return FALSE; - - r = n_dhcp4_client_probe_config_new (&config); - if (r) { - set_error_nettools (error, r, "failed to create dhcp-client-probe-config"); - return FALSE; - } - - /* - * FIXME: - * Select, or configure, a reasonable start delay, to protect poor servers beeing flooded. - */ - n_dhcp4_client_probe_config_set_start_delay (config, 1); - - nm_dhcp_utils_get_leasefile_path (AF_INET, - "internal", - nm_dhcp_client_get_iface (client), - nm_dhcp_client_get_uuid (client), - &lease_file); - - if (last_ip4_address) - inet_pton (AF_INET, last_ip4_address, &last_addr); - else { - /* - * TODO: we stick to the systemd-networkd lease file format. Quite easy for now to - * just use the functions in systemd code. Anyway, as in the end we just use the - * ip address from all the options found in the lease, write a function that parses - * the lease file just for the assigned address and returns it in &last_address. - * Then drop reference to systemd-networkd structures and functions. - */ - nm_auto (sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; - - dhcp_lease_load (&lease, lease_file); - if (lease) - sd_dhcp_lease_get_address (lease, &last_addr); - } - - if (last_addr.s_addr) { - n_dhcp4_client_probe_config_set_requested_ip (config, last_addr); - n_dhcp4_client_probe_config_set_init_reboot (config, TRUE); - } - - /* Add requested options */ - for (i = 0; _nm_dhcp_option_dhcp4_options[i].name; i++) { - if (_nm_dhcp_option_dhcp4_options[i].include) { - nm_assert (_nm_dhcp_option_dhcp4_options[i].option_num <= 255); - n_dhcp4_client_probe_config_request_option (config, - _nm_dhcp_option_dhcp4_options[i].option_num); - } - } - - mud_url = nm_dhcp_client_get_mud_url (client); - if (mud_url) { - r = n_dhcp4_client_probe_config_append_option (config, - NM_DHCP_OPTION_DHCP4_MUD_URL, - mud_url, - strlen (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_dhcp_client_get_use_fqdn (client)) { - uint8_t buffer[255]; - NMDhcpHostnameFlags flags; - size_t fqdn_len; - - flags = nm_dhcp_client_get_hostname_flags (client); - 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); - if (r <= 0) { - if (r < 0) - nm_utils_error_set_errno (error, r, "failed to convert DHCP FQDN: %s"); - else - nm_utils_error_set (error, r, "failed to convert DHCP FQDN"); - return FALSE; - } - fqdn_len = r; - } else { - fqdn_len = strlen (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); - } - - r = n_dhcp4_client_probe_config_append_option (config, - NM_DHCP_OPTION_DHCP4_CLIENT_FQDN, - buffer, - 3 + fqdn_len); - if (r) { - set_error_nettools (error, r, "failed to set DHCP FQDN"); - return FALSE; - } - } else { - r = n_dhcp4_client_probe_config_append_option (config, - NM_DHCP_OPTION_DHCP4_HOST_NAME, - hostname, - strlen (hostname)); - if (r) { - set_error_nettools (error, r, "failed to set DHCP hostname"); - return FALSE; - } - } - } - - g_free (priv->lease_file); - priv->lease_file = g_steal_pointer (&lease_file); - - r = n_dhcp4_client_probe (priv->client, &priv->probe, config); - if (r) { - set_error_nettools (error, r, "failed to start DHCP client"); - return FALSE; - } - - _LOGT ("dhcp-client4: start %p", (gpointer) priv->client); - - nm_dhcp_client_start_timeout (client); - return TRUE; + 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; + + g_return_val_if_fail(!priv->probe, FALSE); + + if (!nettools_create(self, dhcp_anycast_addr, error)) + return FALSE; + + r = n_dhcp4_client_probe_config_new(&config); + if (r) { + set_error_nettools(error, r, "failed to create dhcp-client-probe-config"); + return FALSE; + } + + /* + * FIXME: + * Select, or configure, a reasonable start delay, to protect poor servers being flooded. + */ + n_dhcp4_client_probe_config_set_start_delay(config, 1); + + nm_dhcp_utils_get_leasefile_path(AF_INET, + "internal", + nm_dhcp_client_get_iface(client), + nm_dhcp_client_get_uuid(client), + &lease_file); + + if (last_ip4_address) + inet_pton(AF_INET, last_ip4_address, &last_addr); + else { + /* + * TODO: we stick to the systemd-networkd lease file format. Quite easy for now to + * just use the functions in systemd code. Anyway, as in the end we just use the + * ip address from all the options found in the lease, write a function that parses + * the lease file just for the assigned address and returns it in &last_address. + * Then drop reference to systemd-networkd structures and functions. + */ + nm_auto(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; + + dhcp_lease_load(&lease, lease_file); + if (lease) + sd_dhcp_lease_get_address(lease, &last_addr); + } + + if (last_addr.s_addr) { + n_dhcp4_client_probe_config_set_requested_ip(config, last_addr); + n_dhcp4_client_probe_config_set_init_reboot(config, TRUE); + } + + /* Add requested options */ + for (i = 0; _nm_dhcp_option_dhcp4_options[i].name; i++) { + if (_nm_dhcp_option_dhcp4_options[i].include) { + nm_assert(_nm_dhcp_option_dhcp4_options[i].option_num <= 255); + n_dhcp4_client_probe_config_request_option(config, + _nm_dhcp_option_dhcp4_options[i].option_num); + } + } + + mud_url = nm_dhcp_client_get_mud_url(client); + if (mud_url) { + r = n_dhcp4_client_probe_config_append_option(config, + NM_DHCP_OPTION_DHCP4_MUD_URL, + mud_url, + strlen(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_dhcp_client_get_use_fqdn(client)) { + uint8_t buffer[255]; + NMDhcpHostnameFlags flags; + size_t fqdn_len; + + flags = nm_dhcp_client_get_hostname_flags(client); + 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); + if (r <= 0) { + if (r < 0) + nm_utils_error_set_errno(error, r, "failed to convert DHCP FQDN: %s"); + else + nm_utils_error_set(error, r, "failed to convert DHCP FQDN"); + return FALSE; + } + fqdn_len = r; + } else { + fqdn_len = strlen(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); + } + + r = n_dhcp4_client_probe_config_append_option(config, + NM_DHCP_OPTION_DHCP4_CLIENT_FQDN, + buffer, + 3 + fqdn_len); + if (r) { + set_error_nettools(error, r, "failed to set DHCP FQDN"); + return FALSE; + } + } else { + r = n_dhcp4_client_probe_config_append_option(config, + NM_DHCP_OPTION_DHCP4_HOST_NAME, + hostname, + strlen(hostname)); + if (r) { + set_error_nettools(error, r, "failed to set DHCP hostname"); + return FALSE; + } + } + } + + vendor_class_identifier = nm_dhcp_client_get_vendor_class_identifier(client); + if (vendor_class_identifier) { + const void *option_data; + gsize option_size; + + option_data = g_bytes_get_data(vendor_class_identifier, &option_size); + nm_assert(option_data); + nm_assert(option_size <= 255); + + r = n_dhcp4_client_probe_config_append_option(config, + NM_DHCP_OPTION_DHCP4_VENDOR_CLASS_IDENTIFIER, + option_data, + option_size); + if (r) { + set_error_nettools(error, r, "failed to set vendor class identifier"); + return FALSE; + } + } + + g_free(priv->lease_file); + priv->lease_file = g_steal_pointer(&lease_file); + + r = n_dhcp4_client_probe(priv->client, &priv->probe, config); + if (r) { + set_error_nettools(error, r, "failed to start DHCP client"); + return FALSE; + } + + _LOGT("dhcp-client4: start %p", (gpointer) priv->client); + + nm_dhcp_client_start_timeout(client); + return TRUE; } static void -stop (NMDhcpClient *client, - gboolean release) +stop(NMDhcpClient *client, gboolean release) { - NMDhcpNettools *self = NM_DHCP_NETTOOLS (client); - NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE (self); + NMDhcpNettools * self = NM_DHCP_NETTOOLS(client); + NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(self); - NM_DHCP_CLIENT_CLASS (nm_dhcp_nettools_parent_class)->stop (client, release); + NM_DHCP_CLIENT_CLASS(nm_dhcp_nettools_parent_class)->stop(client, release); - _LOGT ("dhcp-client4: stop %p", - (gpointer) priv->client); + _LOGT("dhcp-client4: stop %p", (gpointer) priv->client); - priv->probe = n_dhcp4_client_probe_free (priv->probe); + priv->probe = n_dhcp4_client_probe_free(priv->probe); } /*****************************************************************************/ static void -nm_dhcp_nettools_init (NMDhcpNettools *self) -{ -} +nm_dhcp_nettools_init(NMDhcpNettools *self) +{} static void -dispose (GObject *object) +dispose(GObject *object) { - NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE (object); + NMDhcpNettoolsPrivate *priv = NM_DHCP_NETTOOLS_GET_PRIVATE(object); - nm_clear_g_free (&priv->lease_file); - nm_clear_g_source_inst (&priv->event_source); - nm_clear_pointer (&priv->lease, n_dhcp4_client_lease_unref); - nm_clear_pointer (&priv->probe, n_dhcp4_client_probe_free); - nm_clear_pointer (&priv->client, n_dhcp4_client_unref); + nm_clear_g_free(&priv->lease_file); + nm_clear_g_source_inst(&priv->event_source); + nm_clear_pointer(&priv->lease, n_dhcp4_client_lease_unref); + nm_clear_pointer(&priv->probe, n_dhcp4_client_probe_free); + nm_clear_pointer(&priv->client, n_dhcp4_client_unref); - G_OBJECT_CLASS (nm_dhcp_nettools_parent_class)->dispose (object); + G_OBJECT_CLASS(nm_dhcp_nettools_parent_class)->dispose(object); } static void -nm_dhcp_nettools_class_init (NMDhcpNettoolsClass *class) +nm_dhcp_nettools_class_init(NMDhcpNettoolsClass *class) { - NMDhcpClientClass *client_class = NM_DHCP_CLIENT_CLASS (class); - GObjectClass *object_class = G_OBJECT_CLASS (class); + NMDhcpClientClass *client_class = NM_DHCP_CLIENT_CLASS(class); + GObjectClass * object_class = G_OBJECT_CLASS(class); - object_class->dispose = dispose; + object_class->dispose = dispose; - client_class->ip4_start = ip4_start; - client_class->accept = _accept; - client_class->decline = decline; - client_class->stop = stop; + client_class->ip4_start = ip4_start; + client_class->accept = _accept; + client_class->decline = decline; + client_class->stop = stop; } const NMDhcpClientFactory _nm_dhcp_client_factory_nettools = { - .name = "nettools", - .get_type = nm_dhcp_nettools_get_type, - .experimental = TRUE, + .name = "nettools", + .get_type = nm_dhcp_nettools_get_type, + .experimental = TRUE, }; diff --git a/src/dhcp/nm-dhcp-options.c b/src/dhcp/nm-dhcp-options.c index d902c77c..58d38201 100644 --- a/src/dhcp/nm-dhcp-options.c +++ b/src/dhcp/nm-dhcp-options.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: LGPL-2.1+ +/* SPDX-License-Identifier: LGPL-2.1+ */ /* * Copyright (C) 2019 Red Hat, Inc. */ @@ -7,263 +7,265 @@ #include "nm-dhcp-options.h" - #define REQPREFIX "requested_" -#define REQ(_num, _name, _include) \ - { \ - .name = REQPREFIX""_name, \ - .option_num = _num, \ - .include = _include, \ - } +#define REQ(_num, _name, _include) \ + { \ + .name = REQPREFIX ""_name, .option_num = _num, .include = _include, \ + } const NMDhcpOption _nm_dhcp_option_dhcp4_options[] = { - REQ (NM_DHCP_OPTION_DHCP4_SUBNET_MASK, "subnet_mask", TRUE ), - REQ (NM_DHCP_OPTION_DHCP4_TIME_OFFSET, "time_offset", TRUE ), - REQ (NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, "domain_name_servers", TRUE ), - REQ (NM_DHCP_OPTION_DHCP4_HOST_NAME, "host_name", TRUE ), - REQ (NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, "domain_name", TRUE ), - REQ (NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, "interface_mtu", TRUE ), - REQ (NM_DHCP_OPTION_DHCP4_BROADCAST, "broadcast_address", TRUE ), - /* RFC 3442: The Classless Static Routes option code MUST appear in the parameter - * request list prior to both the Router option code and the Static - * Routes option code, if present. */ - REQ (NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, "rfc3442_classless_static_routes", TRUE ), - REQ (NM_DHCP_OPTION_DHCP4_ROUTER, "routers", TRUE ), - REQ (NM_DHCP_OPTION_DHCP4_STATIC_ROUTE, "static_routes", TRUE ), - REQ (NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, "nis_domain", TRUE ), - REQ (NM_DHCP_OPTION_DHCP4_NIS_SERVERS, "nis_servers", TRUE ), - REQ (NM_DHCP_OPTION_DHCP4_NTP_SERVER, "ntp_servers", TRUE ), - REQ (NM_DHCP_OPTION_DHCP4_SERVER_ID, "dhcp_server_identifier", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, "domain_search", TRUE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_CLASSLESS_STATIC_ROUTE, "ms_classless_static_routes", TRUE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY, "wpad", TRUE ), - REQ (NM_DHCP_OPTION_DHCP4_ROOT_PATH, "root_path", TRUE ), + REQ(NM_DHCP_OPTION_DHCP4_SUBNET_MASK, "subnet_mask", TRUE), + REQ(NM_DHCP_OPTION_DHCP4_TIME_OFFSET, "time_offset", TRUE), + REQ(NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, "domain_name_servers", TRUE), + REQ(NM_DHCP_OPTION_DHCP4_HOST_NAME, "host_name", TRUE), + REQ(NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, "domain_name", TRUE), + REQ(NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, "interface_mtu", TRUE), + REQ(NM_DHCP_OPTION_DHCP4_BROADCAST, "broadcast_address", TRUE), + /* RFC 3442: The Classless Static Routes option code MUST appear in the parameter + * request list prior to both the Router option code and the Static + * Routes option code, if present. */ + REQ(NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, "rfc3442_classless_static_routes", TRUE), + REQ(NM_DHCP_OPTION_DHCP4_ROUTER, "routers", TRUE), + REQ(NM_DHCP_OPTION_DHCP4_STATIC_ROUTE, "static_routes", TRUE), + REQ(NM_DHCP_OPTION_DHCP4_NIS_DOMAIN, "nis_domain", TRUE), + REQ(NM_DHCP_OPTION_DHCP4_NIS_SERVERS, "nis_servers", TRUE), + REQ(NM_DHCP_OPTION_DHCP4_NTP_SERVER, "ntp_servers", TRUE), + REQ(NM_DHCP_OPTION_DHCP4_SERVER_ID, "dhcp_server_identifier", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, "domain_search", TRUE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_CLASSLESS_STATIC_ROUTE, "ms_classless_static_routes", TRUE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY, "wpad", TRUE), + REQ(NM_DHCP_OPTION_DHCP4_ROOT_PATH, "root_path", TRUE), - REQ (NM_DHCP_OPTION_DHCP4_TIME_SERVERS, "time_servers", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_IEN116_NAME_SERVERS, "ien116_name_servers", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_LOG_SERVERS, "log_servers", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_COOKIE_SERVERS, "cookie_servers", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_LPR_SERVERS, "lpr_servers", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_IMPRESS_SERVERS, "impress_servers", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_RESOURCE_LOCATION_SERVERS, "resource_location_servers", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_BOOT_FILE_SIZE, "boot_size", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_MERIT_DUMP, "merit_dump", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_SWAP_SERVER, "swap_server", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_EXTENSIONS_PATH, "extensions_path", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_ENABLE_IP_FORWARDING, "ip_forwarding", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_ENABLE_SRC_ROUTING, "non_local_source_routing", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_POLICY_FILTER, "policy_filter", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_INTERFACE_MDR, "max_dgram_reassembly", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_INTERFACE_TTL, "default_ip_ttl", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_INTERFACE_MTU_AGING_TIMEOUT, "path_mtu_aging_timeout", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PATH_MTU_PLATEAU_TABLE, "path_mtu_plateau_table", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_ALL_SUBNETS_LOCAL, "all_subnets_local", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PERFORM_MASK_DISCOVERY, "perform_mask_discovery", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_MASK_SUPPLIER, "mask_supplier", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_ROUTER_DISCOVERY, "router_discovery", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_ROUTER_SOLICITATION_ADDR, "router_solicitation_address", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_TRAILER_ENCAPSULATION, "trailer_encapsulation", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_ARP_CACHE_TIMEOUT, "arp_cache_timeout", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_IEEE802_3_ENCAPSULATION, "ieee802_3_encapsulation", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_DEFAULT_TCP_TTL, "default_tcp_ttl", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_TCP_KEEPALIVE_INTERVAL, "tcp_keepalive_internal", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_TCP_KEEPALIVE_GARBAGE, "tcp_keepalive_garbage", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_VENDOR_SPECIFIC, "vendor_encapsulated_options", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER, "netbios_name_servers", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_NETBIOS_DD_SERVER, "netbios_dd_server", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_FONT_SERVERS, "font_servers", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_X_DISPLAY_MANAGER, "x_display_manager", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME, "dhcp_lease_time", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_RENEWAL_T1_TIME, "dhcp_renewal_time", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_REBINDING_T2_TIME, "dhcp_rebinding_time", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_CLIENT_ID, "dhcp_client_identifier", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE, "tcode", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_NWIP_DOMAIN, "nwip_domain", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_NWIP_SUBOPTIONS, "nwip_suboptions", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_NISPLUS_DOMAIN, "nisplus_domain", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_NISPLUS_SERVERS, "nisplus_servers", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_TFTP_SERVER_NAME, "tftp_server_name", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_BOOTFILE_NAME, "bootfile_name", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_MOBILE_IP_HOME_AGENT, "mobile_ip_home_agent", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_SMTP_SERVER, "smtp_server", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_POP_SERVER, "pop_server", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_NNTP_SERVER, "nntp_server", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_WWW_SERVER, "www_server", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_FINGER_SERVER, "finger_server", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_IRC_SERVER, "irc_server", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_STREETTALK_SERVER, "streettalk_server", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_STREETTALK_DIR_ASSIST_SERVER, "streettalk_directory_assistance_server", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_SLP_DIRECTORY_AGENT, "slp_directory_agent", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_SLP_SERVICE_SCOPE, "slp_service_scope", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_CLIENT_FQDN, "fqdn", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_RELAY_AGENT_INFORMATION, "relay_agent_information", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_NDS_SERVERS, "nds_servers", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_NDS_TREE_NAME, "nds_tree_name", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_NDS_CONTEXT, "nds_context", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_BCMS_CONTROLLER_NAMES, "bcms_controller_names", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_BCMS_CONTROLLER_ADDRESS, "bcms_controller_address", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_CLIENT_LAST_TRANSACTION, "client_last_transaction_time", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_ASSOCIATED_IP, "associated_ip", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PXE_SYSTEM_TYPE, "pxe_system_type", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PXE_INTERFACE_ID, "pxe_interface_id", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PXE_CLIENT_ID, "pxe_client_id", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_UAP_SERVERS, "uap_servers", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_GEOCONF_CIVIC, "geoconf_civic", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_NETINFO_SERVER_ADDRESS, "netinfo_server_address", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_NETINFO_SERVER_TAG, "netinfo_server_tag", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_DEFAULT_URL, "default_url", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_AUTO_CONFIG, "auto_config", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_NAME_SERVICE_SEARCH, "name_service_search", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_SUBNET_SELECTION, "subnet_selection", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_VIVCO, "vivco", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_VIVSO, "vivso", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PANA_AGENT, "pana_agent", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_V4_LOST, "v4_lost", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_SIP_UA_CS_DOMAINS, "sip_ua_cs_domains", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_IPV4_ADDRESS_ANDSF, "ipv4_address_andsf", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_RDNSS_SELECTION, "rndss_selection", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_TFTP_SERVER_ADDRESS, "tftp_server_address", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_V4_PORTPARAMS, "v4_portparams", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_V4_CAPTIVE_PORTAL, "v4_captive_portal", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_MUD_URL, "mud_url", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_LOADER_CONFIGFILE, "loader_configfile", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_LOADER_PATHPREFIX, "loader_pathprefix", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_LOADER_REBOOTTIME, "loader_reboottime", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_OPTION_6RD, "option_6rd", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_V4_ACCESS_DOMAIN, "v4_access_domain", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_224, "private_224", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_225, "private_225", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_226, "private_226", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_227, "private_227", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_228, "private_228", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_229, "private_229", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_230, "private_230", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_231, "private_231", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_232, "private_232", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_233, "private_233", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_234, "private_234", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_235, "private_235", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_236, "private_236", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_237, "private_237", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_238, "private_238", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_239, "private_239", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_240, "private_240", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_241, "private_241", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_242, "private_242", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_243, "private_243", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_244, "private_244", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_245, "private_245", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_246, "private_246", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_247, "private_247", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_248, "private_248", FALSE ), - /* NM_DHCP_OPTION_DHCP4_PRIVATE_CLASSLESS_STATIC_ROUTE */ - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_250, "private_250", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_251, "private_251", FALSE ), - /* NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY */ - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_253, "private_253", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_PRIVATE_254, "private_254", FALSE ), + REQ(NM_DHCP_OPTION_DHCP4_TIME_SERVERS, "time_servers", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_IEN116_NAME_SERVERS, "ien116_name_servers", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_LOG_SERVERS, "log_servers", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_COOKIE_SERVERS, "cookie_servers", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_LPR_SERVERS, "lpr_servers", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_IMPRESS_SERVERS, "impress_servers", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_RESOURCE_LOCATION_SERVERS, "resource_location_servers", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_BOOT_FILE_SIZE, "boot_size", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_MERIT_DUMP, "merit_dump", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_SWAP_SERVER, "swap_server", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_EXTENSIONS_PATH, "extensions_path", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_ENABLE_IP_FORWARDING, "ip_forwarding", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_ENABLE_SRC_ROUTING, "non_local_source_routing", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_POLICY_FILTER, "policy_filter", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_INTERFACE_MDR, "max_dgram_reassembly", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_INTERFACE_TTL, "default_ip_ttl", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_INTERFACE_MTU_AGING_TIMEOUT, "path_mtu_aging_timeout", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PATH_MTU_PLATEAU_TABLE, "path_mtu_plateau_table", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_ALL_SUBNETS_LOCAL, "all_subnets_local", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PERFORM_MASK_DISCOVERY, "perform_mask_discovery", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_MASK_SUPPLIER, "mask_supplier", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_ROUTER_DISCOVERY, "router_discovery", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_ROUTER_SOLICITATION_ADDR, "router_solicitation_address", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_TRAILER_ENCAPSULATION, "trailer_encapsulation", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_ARP_CACHE_TIMEOUT, "arp_cache_timeout", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_IEEE802_3_ENCAPSULATION, "ieee802_3_encapsulation", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_DEFAULT_TCP_TTL, "default_tcp_ttl", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_TCP_KEEPALIVE_INTERVAL, "tcp_keepalive_internal", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_TCP_KEEPALIVE_GARBAGE, "tcp_keepalive_garbage", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_VENDOR_SPECIFIC, "vendor_encapsulated_options", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER, "netbios_name_servers", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_NETBIOS_DD_SERVER, "netbios_dd_server", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_FONT_SERVERS, "font_servers", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_X_DISPLAY_MANAGER, "x_display_manager", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME, "dhcp_lease_time", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_RENEWAL_T1_TIME, "dhcp_renewal_time", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_REBINDING_T2_TIME, "dhcp_rebinding_time", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_CLIENT_ID, "dhcp_client_identifier", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE, "tcode", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_NWIP_DOMAIN, "nwip_domain", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_NWIP_SUBOPTIONS, "nwip_suboptions", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_NISPLUS_DOMAIN, "nisplus_domain", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_NISPLUS_SERVERS, "nisplus_servers", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_TFTP_SERVER_NAME, "tftp_server_name", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_BOOTFILE_NAME, "bootfile_name", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_MOBILE_IP_HOME_AGENT, "mobile_ip_home_agent", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_SMTP_SERVER, "smtp_server", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_POP_SERVER, "pop_server", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_NNTP_SERVER, "nntp_server", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_WWW_SERVER, "www_server", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_FINGER_SERVER, "finger_server", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_IRC_SERVER, "irc_server", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_STREETTALK_SERVER, "streettalk_server", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_STREETTALK_DIR_ASSIST_SERVER, + "streettalk_directory_assistance_server", + FALSE), + REQ(NM_DHCP_OPTION_DHCP4_SLP_DIRECTORY_AGENT, "slp_directory_agent", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_SLP_SERVICE_SCOPE, "slp_service_scope", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_CLIENT_FQDN, "fqdn", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_RELAY_AGENT_INFORMATION, "relay_agent_information", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_NDS_SERVERS, "nds_servers", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_NDS_TREE_NAME, "nds_tree_name", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_NDS_CONTEXT, "nds_context", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_BCMS_CONTROLLER_NAMES, "bcms_controller_names", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_BCMS_CONTROLLER_ADDRESS, "bcms_controller_address", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_CLIENT_LAST_TRANSACTION, "client_last_transaction_time", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_ASSOCIATED_IP, "associated_ip", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PXE_SYSTEM_TYPE, "pxe_system_type", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PXE_INTERFACE_ID, "pxe_interface_id", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PXE_CLIENT_ID, "pxe_client_id", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_UAP_SERVERS, "uap_servers", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_GEOCONF_CIVIC, "geoconf_civic", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_NETINFO_SERVER_ADDRESS, "netinfo_server_address", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_NETINFO_SERVER_TAG, "netinfo_server_tag", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_DEFAULT_URL, "default_url", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_AUTO_CONFIG, "auto_config", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_NAME_SERVICE_SEARCH, "name_service_search", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_SUBNET_SELECTION, "subnet_selection", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_VIVCO, "vivco", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_VIVSO, "vivso", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PANA_AGENT, "pana_agent", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_V4_LOST, "v4_lost", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_SIP_UA_CS_DOMAINS, "sip_ua_cs_domains", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_IPV4_ADDRESS_ANDSF, "ipv4_address_andsf", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_RDNSS_SELECTION, "rndss_selection", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_TFTP_SERVER_ADDRESS, "tftp_server_address", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_V4_PORTPARAMS, "v4_portparams", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_V4_CAPTIVE_PORTAL, "v4_captive_portal", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_MUD_URL, "mud_url", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_LOADER_CONFIGFILE, "loader_configfile", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_LOADER_PATHPREFIX, "loader_pathprefix", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_LOADER_REBOOTTIME, "loader_reboottime", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_OPTION_6RD, "option_6rd", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_V4_ACCESS_DOMAIN, "v4_access_domain", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_224, "private_224", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_225, "private_225", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_226, "private_226", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_227, "private_227", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_228, "private_228", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_229, "private_229", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_230, "private_230", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_231, "private_231", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_232, "private_232", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_233, "private_233", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_234, "private_234", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_235, "private_235", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_236, "private_236", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_237, "private_237", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_238, "private_238", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_239, "private_239", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_240, "private_240", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_241, "private_241", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_242, "private_242", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_243, "private_243", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_244, "private_244", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_245, "private_245", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_246, "private_246", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_247, "private_247", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_248, "private_248", FALSE), + /* NM_DHCP_OPTION_DHCP4_PRIVATE_CLASSLESS_STATIC_ROUTE */ + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_250, "private_250", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_251, "private_251", FALSE), + /* NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY */ + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_253, "private_253", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_PRIVATE_254, "private_254", FALSE), - /* Internal values */ - REQ (NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, "ip_address", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_NM_EXPIRY, "expiry", FALSE ), - REQ (NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, "next_server", FALSE ), + /* Internal values */ + REQ(NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, "ip_address", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_NM_EXPIRY, "expiry", FALSE), + REQ(NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER, "next_server", FALSE), - { 0 } -}; + {0}}; const NMDhcpOption _nm_dhcp_option_dhcp6_options[] = { - REQ (NM_DHCP_OPTION_DHCP6_CLIENTID, "dhcp6_client_id", FALSE ), - - /* Don't request server ID by default; some servers don't reply to - * Information Requests that request the Server ID. - */ - REQ (NM_DHCP_OPTION_DHCP6_SERVERID, "dhcp6_server_id", FALSE ), + REQ(NM_DHCP_OPTION_DHCP6_CLIENTID, "dhcp6_client_id", FALSE), - REQ (NM_DHCP_OPTION_DHCP6_DNS_SERVERS, "dhcp6_name_servers", TRUE ), - REQ (NM_DHCP_OPTION_DHCP6_DOMAIN_LIST, "dhcp6_domain_search", TRUE ), - REQ (NM_DHCP_OPTION_DHCP6_SNTP_SERVERS, "dhcp6_sntp_servers", TRUE ), - REQ (NM_DHCP_OPTION_DHCP6_FQDN, "fqdn_fqdn", FALSE ), - REQ (NM_DHCP_OPTION_DHCP6_MUD_URL, "dhcp6_mud_url", FALSE ), + /* Don't request server ID by default; some servers don't reply to + * Information Requests that request the Server ID. + */ + REQ(NM_DHCP_OPTION_DHCP6_SERVERID, "dhcp6_server_id", FALSE), - /* Internal values */ - REQ (NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS, "ip6_address", FALSE ), - REQ (NM_DHCP_OPTION_DHCP6_NM_PREFIXLEN, "ip6_prefixlen", FALSE ), - REQ (NM_DHCP_OPTION_DHCP6_NM_PREFERRED_LIFE, "preferred_life", FALSE ), - REQ (NM_DHCP_OPTION_DHCP6_NM_MAX_LIFE, "max_life", FALSE ), - REQ (NM_DHCP_OPTION_DHCP6_NM_STARTS, "starts", FALSE ), - REQ (NM_DHCP_OPTION_DHCP6_NM_LIFE_STARTS, "life_starts", FALSE ), - REQ (NM_DHCP_OPTION_DHCP6_NM_RENEW, "renew", FALSE ), - REQ (NM_DHCP_OPTION_DHCP6_NM_REBIND, "rebind", FALSE ), - REQ (NM_DHCP_OPTION_DHCP6_NM_IAID, "iaid", FALSE ), + REQ(NM_DHCP_OPTION_DHCP6_DNS_SERVERS, "dhcp6_name_servers", TRUE), + REQ(NM_DHCP_OPTION_DHCP6_DOMAIN_LIST, "dhcp6_domain_search", TRUE), + REQ(NM_DHCP_OPTION_DHCP6_SNTP_SERVERS, "dhcp6_sntp_servers", TRUE), + REQ(NM_DHCP_OPTION_DHCP6_FQDN, "fqdn_fqdn", FALSE), + REQ(NM_DHCP_OPTION_DHCP6_MUD_URL, "dhcp6_mud_url", FALSE), - { 0 } -}; + /* Internal values */ + REQ(NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS, "ip6_address", FALSE), + REQ(NM_DHCP_OPTION_DHCP6_NM_PREFIXLEN, "ip6_prefixlen", FALSE), + REQ(NM_DHCP_OPTION_DHCP6_NM_PREFERRED_LIFE, "preferred_life", FALSE), + REQ(NM_DHCP_OPTION_DHCP6_NM_MAX_LIFE, "max_life", FALSE), + REQ(NM_DHCP_OPTION_DHCP6_NM_STARTS, "starts", FALSE), + REQ(NM_DHCP_OPTION_DHCP6_NM_LIFE_STARTS, "life_starts", FALSE), + REQ(NM_DHCP_OPTION_DHCP6_NM_RENEW, "renew", FALSE), + REQ(NM_DHCP_OPTION_DHCP6_NM_REBIND, "rebind", FALSE), + REQ(NM_DHCP_OPTION_DHCP6_NM_IAID, "iaid", FALSE), + {0}}; const char * -nm_dhcp_option_request_string (const NMDhcpOption *requests, guint option) +nm_dhcp_option_request_string(const NMDhcpOption *requests, guint option) { - guint i = 0; + guint i = 0; - while (requests[i].name) { - if (requests[i].option_num == option) - return requests[i].name + NM_STRLEN (REQPREFIX); - i++; - } + while (requests[i].name) { + if (requests[i].option_num == option) + return requests[i].name + NM_STRLEN(REQPREFIX); + i++; + } - /* Option should always be found */ - nm_assert_not_reached (); - return NULL; + /* Option should always be found */ + nm_assert_not_reached(); + return NULL; } void -nm_dhcp_option_take_option (GHashTable *options, - const NMDhcpOption *requests, - guint option, - char *value) +nm_dhcp_option_take_option(GHashTable * options, + const NMDhcpOption *requests, + guint option, + char * value) { - nm_assert (options); - nm_assert (requests); - nm_assert (value); - nm_assert (g_utf8_validate (value, -1, NULL)); + nm_assert(options); + nm_assert(requests); + nm_assert(value); + nm_assert(g_utf8_validate(value, -1, NULL)); - g_hash_table_insert (options, - (gpointer) nm_dhcp_option_request_string (requests, option), - value); + g_hash_table_insert(options, (gpointer) nm_dhcp_option_request_string(requests, option), value); } void -nm_dhcp_option_add_option (GHashTable *options, const NMDhcpOption *requests, guint option, const char *value) +nm_dhcp_option_add_option(GHashTable * options, + const NMDhcpOption *requests, + guint option, + const char * value) { - if (options) - nm_dhcp_option_take_option (options, requests, option, g_strdup (value)); + if (options) + nm_dhcp_option_take_option(options, requests, option, g_strdup(value)); } void -nm_dhcp_option_add_option_u64 (GHashTable *options, const NMDhcpOption *requests, guint option, guint64 value) +nm_dhcp_option_add_option_u64(GHashTable * options, + const NMDhcpOption *requests, + guint option, + guint64 value) { - if (options) - nm_dhcp_option_take_option (options, requests, option, g_strdup_printf ("%" G_GUINT64_FORMAT, value)); + if (options) + nm_dhcp_option_take_option(options, + requests, + option, + g_strdup_printf("%" G_GUINT64_FORMAT, value)); } void -nm_dhcp_option_add_requests_to_options (GHashTable *options, const NMDhcpOption *requests) +nm_dhcp_option_add_requests_to_options(GHashTable *options, const NMDhcpOption *requests) { - guint i; + guint i; - if (!options) - return; + if (!options) + return; - for (i = 0; requests[i].name; i++) { - if (requests[i].include) - g_hash_table_insert (options, (gpointer) requests[i].name, g_strdup ("1")); - } + for (i = 0; requests[i].name; i++) { + if (requests[i].include) + g_hash_table_insert(options, (gpointer) requests[i].name, g_strdup("1")); + } } GHashTable * -nm_dhcp_option_create_options_dict (void) +nm_dhcp_option_create_options_dict(void) { - return g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, g_free); + return g_hash_table_new_full(nm_str_hash, g_str_equal, NULL, g_free); } - diff --git a/src/dhcp/nm-dhcp-options.h b/src/dhcp/nm-dhcp-options.h index bc3df5ac..6c867c40 100644 --- a/src/dhcp/nm-dhcp-options.h +++ b/src/dhcp/nm-dhcp-options.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: LGPL-2.1+ +/* SPDX-License-Identifier: LGPL-2.1+ */ /* * Copyright (C) 2019 Red Hat, Inc. */ @@ -7,189 +7,199 @@ #define __NM_DHCP_OPTIONS_H__ typedef enum { - NM_DHCP_OPTION_DHCP4_PAD = 0, - NM_DHCP_OPTION_DHCP4_SUBNET_MASK = 1, - NM_DHCP_OPTION_DHCP4_TIME_OFFSET = 2, - NM_DHCP_OPTION_DHCP4_ROUTER = 3, - NM_DHCP_OPTION_DHCP4_TIME_SERVERS = 4, - NM_DHCP_OPTION_DHCP4_IEN116_NAME_SERVERS = 5, - NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER = 6, - NM_DHCP_OPTION_DHCP4_LOG_SERVERS = 7, - NM_DHCP_OPTION_DHCP4_COOKIE_SERVERS = 8, - NM_DHCP_OPTION_DHCP4_LPR_SERVERS = 9, - NM_DHCP_OPTION_DHCP4_IMPRESS_SERVERS = 10, - NM_DHCP_OPTION_DHCP4_RESOURCE_LOCATION_SERVERS = 11, - NM_DHCP_OPTION_DHCP4_HOST_NAME = 12, - NM_DHCP_OPTION_DHCP4_BOOT_FILE_SIZE = 13, - NM_DHCP_OPTION_DHCP4_MERIT_DUMP = 14, - NM_DHCP_OPTION_DHCP4_DOMAIN_NAME = 15, - NM_DHCP_OPTION_DHCP4_SWAP_SERVER = 16, - NM_DHCP_OPTION_DHCP4_ROOT_PATH = 17, - NM_DHCP_OPTION_DHCP4_EXTENSIONS_PATH = 18, - NM_DHCP_OPTION_DHCP4_ENABLE_IP_FORWARDING = 19, - NM_DHCP_OPTION_DHCP4_ENABLE_SRC_ROUTING = 20, - NM_DHCP_OPTION_DHCP4_POLICY_FILTER = 21, - NM_DHCP_OPTION_DHCP4_INTERFACE_MDR = 22, - NM_DHCP_OPTION_DHCP4_INTERFACE_TTL = 23, - NM_DHCP_OPTION_DHCP4_INTERFACE_MTU_AGING_TIMEOUT = 24, - NM_DHCP_OPTION_DHCP4_PATH_MTU_PLATEAU_TABLE = 25, - NM_DHCP_OPTION_DHCP4_INTERFACE_MTU = 26, - NM_DHCP_OPTION_DHCP4_ALL_SUBNETS_LOCAL = 27, - NM_DHCP_OPTION_DHCP4_BROADCAST = 28, - NM_DHCP_OPTION_DHCP4_PERFORM_MASK_DISCOVERY = 29, - NM_DHCP_OPTION_DHCP4_MASK_SUPPLIER = 30, - NM_DHCP_OPTION_DHCP4_ROUTER_DISCOVERY = 31, - NM_DHCP_OPTION_DHCP4_ROUTER_SOLICITATION_ADDR = 32, - NM_DHCP_OPTION_DHCP4_STATIC_ROUTE = 33, - NM_DHCP_OPTION_DHCP4_TRAILER_ENCAPSULATION = 34, - NM_DHCP_OPTION_DHCP4_ARP_CACHE_TIMEOUT = 35, - NM_DHCP_OPTION_DHCP4_IEEE802_3_ENCAPSULATION = 36, - NM_DHCP_OPTION_DHCP4_DEFAULT_TCP_TTL = 37, - NM_DHCP_OPTION_DHCP4_TCP_KEEPALIVE_INTERVAL = 38, - NM_DHCP_OPTION_DHCP4_TCP_KEEPALIVE_GARBAGE = 39, - NM_DHCP_OPTION_DHCP4_NIS_DOMAIN = 40, - NM_DHCP_OPTION_DHCP4_NIS_SERVERS = 41, - NM_DHCP_OPTION_DHCP4_NTP_SERVER = 42, - NM_DHCP_OPTION_DHCP4_VENDOR_SPECIFIC = 43, - NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER = 44, - NM_DHCP_OPTION_DHCP4_NETBIOS_DD_SERVER = 45, - NM_DHCP_OPTION_DHCP4_FONT_SERVERS = 48, - NM_DHCP_OPTION_DHCP4_X_DISPLAY_MANAGER = 49, - NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME = 51, - NM_DHCP_OPTION_DHCP4_SERVER_ID = 54, - NM_DHCP_OPTION_DHCP4_RENEWAL_T1_TIME = 58, - NM_DHCP_OPTION_DHCP4_REBINDING_T2_TIME = 59, - NM_DHCP_OPTION_DHCP4_CLIENT_ID = 61, - NM_DHCP_OPTION_DHCP4_NWIP_DOMAIN = 62, - NM_DHCP_OPTION_DHCP4_NWIP_SUBOPTIONS = 63, - NM_DHCP_OPTION_DHCP4_NISPLUS_DOMAIN = 64, - NM_DHCP_OPTION_DHCP4_NISPLUS_SERVERS = 65, - NM_DHCP_OPTION_DHCP4_TFTP_SERVER_NAME = 66, - NM_DHCP_OPTION_DHCP4_BOOTFILE_NAME = 67, - NM_DHCP_OPTION_DHCP4_MOBILE_IP_HOME_AGENT = 68, - NM_DHCP_OPTION_DHCP4_SMTP_SERVER = 69, - NM_DHCP_OPTION_DHCP4_POP_SERVER = 70, - NM_DHCP_OPTION_DHCP4_NNTP_SERVER = 71, - NM_DHCP_OPTION_DHCP4_WWW_SERVER = 72, - NM_DHCP_OPTION_DHCP4_FINGER_SERVER = 73, - NM_DHCP_OPTION_DHCP4_IRC_SERVER = 74, - NM_DHCP_OPTION_DHCP4_STREETTALK_SERVER = 75, - NM_DHCP_OPTION_DHCP4_STREETTALK_DIR_ASSIST_SERVER = 76, - NM_DHCP_OPTION_DHCP4_SLP_DIRECTORY_AGENT = 78, - NM_DHCP_OPTION_DHCP4_SLP_SERVICE_SCOPE = 79, - NM_DHCP_OPTION_DHCP4_CLIENT_FQDN = 81, - NM_DHCP_OPTION_DHCP4_RELAY_AGENT_INFORMATION = 82, - NM_DHCP_OPTION_DHCP4_NDS_SERVERS = 85, - NM_DHCP_OPTION_DHCP4_NDS_TREE_NAME = 86, - NM_DHCP_OPTION_DHCP4_NDS_CONTEXT = 87, - NM_DHCP_OPTION_DHCP4_BCMS_CONTROLLER_NAMES = 88, - NM_DHCP_OPTION_DHCP4_BCMS_CONTROLLER_ADDRESS = 89, - NM_DHCP_OPTION_DHCP4_CLIENT_LAST_TRANSACTION = 91, - NM_DHCP_OPTION_DHCP4_ASSOCIATED_IP = 92, - NM_DHCP_OPTION_DHCP4_PXE_SYSTEM_TYPE = 93, - NM_DHCP_OPTION_DHCP4_PXE_INTERFACE_ID = 94, - NM_DHCP_OPTION_DHCP4_PXE_CLIENT_ID = 97, - NM_DHCP_OPTION_DHCP4_UAP_SERVERS = 98, - NM_DHCP_OPTION_DHCP4_GEOCONF_CIVIC = 99, - NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE = 101, - NM_DHCP_OPTION_DHCP4_NETINFO_SERVER_ADDRESS = 112, - NM_DHCP_OPTION_DHCP4_NETINFO_SERVER_TAG = 113, - NM_DHCP_OPTION_DHCP4_DEFAULT_URL = 114, - NM_DHCP_OPTION_DHCP4_AUTO_CONFIG = 116, - NM_DHCP_OPTION_DHCP4_NAME_SERVICE_SEARCH = 117, - NM_DHCP_OPTION_DHCP4_SUBNET_SELECTION = 118, - NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST = 119, - NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE = 121, - NM_DHCP_OPTION_DHCP4_VIVCO = 124, - NM_DHCP_OPTION_DHCP4_VIVSO = 125, - NM_DHCP_OPTION_DHCP4_PANA_AGENT = 136, - NM_DHCP_OPTION_DHCP4_V4_LOST = 137, - NM_DHCP_OPTION_DHCP4_SIP_UA_CS_DOMAINS = 141, - NM_DHCP_OPTION_DHCP4_IPV4_ADDRESS_ANDSF = 142, - NM_DHCP_OPTION_DHCP4_RDNSS_SELECTION = 146, - NM_DHCP_OPTION_DHCP4_TFTP_SERVER_ADDRESS = 150, - NM_DHCP_OPTION_DHCP4_V4_PORTPARAMS = 159, - NM_DHCP_OPTION_DHCP4_V4_CAPTIVE_PORTAL = 160, - NM_DHCP_OPTION_DHCP4_MUD_URL = 161, - NM_DHCP_OPTION_DHCP4_LOADER_CONFIGFILE = 209, - NM_DHCP_OPTION_DHCP4_LOADER_PATHPREFIX = 210, - NM_DHCP_OPTION_DHCP4_LOADER_REBOOTTIME = 211, - NM_DHCP_OPTION_DHCP4_OPTION_6RD = 212, - NM_DHCP_OPTION_DHCP4_V4_ACCESS_DOMAIN = 213, - NM_DHCP_OPTION_DHCP4_PRIVATE_224 = 224, - NM_DHCP_OPTION_DHCP4_PRIVATE_225 = 225, - NM_DHCP_OPTION_DHCP4_PRIVATE_226 = 226, - NM_DHCP_OPTION_DHCP4_PRIVATE_227 = 227, - NM_DHCP_OPTION_DHCP4_PRIVATE_228 = 228, - NM_DHCP_OPTION_DHCP4_PRIVATE_229 = 229, - NM_DHCP_OPTION_DHCP4_PRIVATE_230 = 230, - NM_DHCP_OPTION_DHCP4_PRIVATE_231 = 231, - NM_DHCP_OPTION_DHCP4_PRIVATE_232 = 232, - NM_DHCP_OPTION_DHCP4_PRIVATE_233 = 233, - NM_DHCP_OPTION_DHCP4_PRIVATE_234 = 234, - NM_DHCP_OPTION_DHCP4_PRIVATE_235 = 235, - NM_DHCP_OPTION_DHCP4_PRIVATE_236 = 236, - NM_DHCP_OPTION_DHCP4_PRIVATE_237 = 237, - NM_DHCP_OPTION_DHCP4_PRIVATE_238 = 238, - NM_DHCP_OPTION_DHCP4_PRIVATE_239 = 239, - NM_DHCP_OPTION_DHCP4_PRIVATE_240 = 240, - NM_DHCP_OPTION_DHCP4_PRIVATE_241 = 241, - NM_DHCP_OPTION_DHCP4_PRIVATE_242 = 242, - NM_DHCP_OPTION_DHCP4_PRIVATE_243 = 243, - NM_DHCP_OPTION_DHCP4_PRIVATE_244 = 244, - NM_DHCP_OPTION_DHCP4_PRIVATE_245 = 245, - NM_DHCP_OPTION_DHCP4_PRIVATE_246 = 246, - NM_DHCP_OPTION_DHCP4_PRIVATE_247 = 247, - NM_DHCP_OPTION_DHCP4_PRIVATE_248 = 248, - NM_DHCP_OPTION_DHCP4_PRIVATE_CLASSLESS_STATIC_ROUTE = 249, - NM_DHCP_OPTION_DHCP4_PRIVATE_250 = 250, - NM_DHCP_OPTION_DHCP4_PRIVATE_251 = 251, - NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY = 252, - NM_DHCP_OPTION_DHCP4_PRIVATE_253 = 253, - NM_DHCP_OPTION_DHCP4_PRIVATE_254 = 254, - NM_DHCP_OPTION_DHCP4_END = 255, - /* Internal values */ - NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS = 1024, - NM_DHCP_OPTION_DHCP4_NM_EXPIRY = 1025, - NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER = 1026, + NM_DHCP_OPTION_DHCP4_PAD = 0, + NM_DHCP_OPTION_DHCP4_SUBNET_MASK = 1, + NM_DHCP_OPTION_DHCP4_TIME_OFFSET = 2, + NM_DHCP_OPTION_DHCP4_ROUTER = 3, + NM_DHCP_OPTION_DHCP4_TIME_SERVERS = 4, + NM_DHCP_OPTION_DHCP4_IEN116_NAME_SERVERS = 5, + NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER = 6, + NM_DHCP_OPTION_DHCP4_LOG_SERVERS = 7, + NM_DHCP_OPTION_DHCP4_COOKIE_SERVERS = 8, + NM_DHCP_OPTION_DHCP4_LPR_SERVERS = 9, + NM_DHCP_OPTION_DHCP4_IMPRESS_SERVERS = 10, + NM_DHCP_OPTION_DHCP4_RESOURCE_LOCATION_SERVERS = 11, + NM_DHCP_OPTION_DHCP4_HOST_NAME = 12, + NM_DHCP_OPTION_DHCP4_BOOT_FILE_SIZE = 13, + NM_DHCP_OPTION_DHCP4_MERIT_DUMP = 14, + NM_DHCP_OPTION_DHCP4_DOMAIN_NAME = 15, + NM_DHCP_OPTION_DHCP4_SWAP_SERVER = 16, + NM_DHCP_OPTION_DHCP4_ROOT_PATH = 17, + NM_DHCP_OPTION_DHCP4_EXTENSIONS_PATH = 18, + NM_DHCP_OPTION_DHCP4_ENABLE_IP_FORWARDING = 19, + NM_DHCP_OPTION_DHCP4_ENABLE_SRC_ROUTING = 20, + NM_DHCP_OPTION_DHCP4_POLICY_FILTER = 21, + NM_DHCP_OPTION_DHCP4_INTERFACE_MDR = 22, + NM_DHCP_OPTION_DHCP4_INTERFACE_TTL = 23, + NM_DHCP_OPTION_DHCP4_INTERFACE_MTU_AGING_TIMEOUT = 24, + NM_DHCP_OPTION_DHCP4_PATH_MTU_PLATEAU_TABLE = 25, + NM_DHCP_OPTION_DHCP4_INTERFACE_MTU = 26, + NM_DHCP_OPTION_DHCP4_ALL_SUBNETS_LOCAL = 27, + NM_DHCP_OPTION_DHCP4_BROADCAST = 28, + NM_DHCP_OPTION_DHCP4_PERFORM_MASK_DISCOVERY = 29, + NM_DHCP_OPTION_DHCP4_MASK_SUPPLIER = 30, + NM_DHCP_OPTION_DHCP4_ROUTER_DISCOVERY = 31, + NM_DHCP_OPTION_DHCP4_ROUTER_SOLICITATION_ADDR = 32, + NM_DHCP_OPTION_DHCP4_STATIC_ROUTE = 33, + NM_DHCP_OPTION_DHCP4_TRAILER_ENCAPSULATION = 34, + NM_DHCP_OPTION_DHCP4_ARP_CACHE_TIMEOUT = 35, + NM_DHCP_OPTION_DHCP4_IEEE802_3_ENCAPSULATION = 36, + NM_DHCP_OPTION_DHCP4_DEFAULT_TCP_TTL = 37, + NM_DHCP_OPTION_DHCP4_TCP_KEEPALIVE_INTERVAL = 38, + NM_DHCP_OPTION_DHCP4_TCP_KEEPALIVE_GARBAGE = 39, + NM_DHCP_OPTION_DHCP4_NIS_DOMAIN = 40, + NM_DHCP_OPTION_DHCP4_NIS_SERVERS = 41, + NM_DHCP_OPTION_DHCP4_NTP_SERVER = 42, + NM_DHCP_OPTION_DHCP4_VENDOR_SPECIFIC = 43, + NM_DHCP_OPTION_DHCP4_NETBIOS_NAMESERVER = 44, + NM_DHCP_OPTION_DHCP4_NETBIOS_DD_SERVER = 45, + NM_DHCP_OPTION_DHCP4_FONT_SERVERS = 48, + NM_DHCP_OPTION_DHCP4_X_DISPLAY_MANAGER = 49, + NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME = 51, + NM_DHCP_OPTION_DHCP4_SERVER_ID = 54, + NM_DHCP_OPTION_DHCP4_RENEWAL_T1_TIME = 58, + NM_DHCP_OPTION_DHCP4_REBINDING_T2_TIME = 59, + NM_DHCP_OPTION_DHCP4_VENDOR_CLASS_IDENTIFIER = 60, + NM_DHCP_OPTION_DHCP4_CLIENT_ID = 61, + NM_DHCP_OPTION_DHCP4_NWIP_DOMAIN = 62, + NM_DHCP_OPTION_DHCP4_NWIP_SUBOPTIONS = 63, + NM_DHCP_OPTION_DHCP4_NISPLUS_DOMAIN = 64, + NM_DHCP_OPTION_DHCP4_NISPLUS_SERVERS = 65, + NM_DHCP_OPTION_DHCP4_TFTP_SERVER_NAME = 66, + NM_DHCP_OPTION_DHCP4_BOOTFILE_NAME = 67, + NM_DHCP_OPTION_DHCP4_MOBILE_IP_HOME_AGENT = 68, + NM_DHCP_OPTION_DHCP4_SMTP_SERVER = 69, + NM_DHCP_OPTION_DHCP4_POP_SERVER = 70, + NM_DHCP_OPTION_DHCP4_NNTP_SERVER = 71, + NM_DHCP_OPTION_DHCP4_WWW_SERVER = 72, + NM_DHCP_OPTION_DHCP4_FINGER_SERVER = 73, + NM_DHCP_OPTION_DHCP4_IRC_SERVER = 74, + NM_DHCP_OPTION_DHCP4_STREETTALK_SERVER = 75, + NM_DHCP_OPTION_DHCP4_STREETTALK_DIR_ASSIST_SERVER = 76, + NM_DHCP_OPTION_DHCP4_SLP_DIRECTORY_AGENT = 78, + NM_DHCP_OPTION_DHCP4_SLP_SERVICE_SCOPE = 79, + NM_DHCP_OPTION_DHCP4_CLIENT_FQDN = 81, + NM_DHCP_OPTION_DHCP4_RELAY_AGENT_INFORMATION = 82, + NM_DHCP_OPTION_DHCP4_NDS_SERVERS = 85, + NM_DHCP_OPTION_DHCP4_NDS_TREE_NAME = 86, + NM_DHCP_OPTION_DHCP4_NDS_CONTEXT = 87, + NM_DHCP_OPTION_DHCP4_BCMS_CONTROLLER_NAMES = 88, + NM_DHCP_OPTION_DHCP4_BCMS_CONTROLLER_ADDRESS = 89, + NM_DHCP_OPTION_DHCP4_CLIENT_LAST_TRANSACTION = 91, + NM_DHCP_OPTION_DHCP4_ASSOCIATED_IP = 92, + NM_DHCP_OPTION_DHCP4_PXE_SYSTEM_TYPE = 93, + NM_DHCP_OPTION_DHCP4_PXE_INTERFACE_ID = 94, + NM_DHCP_OPTION_DHCP4_PXE_CLIENT_ID = 97, + NM_DHCP_OPTION_DHCP4_UAP_SERVERS = 98, + NM_DHCP_OPTION_DHCP4_GEOCONF_CIVIC = 99, + NM_DHCP_OPTION_DHCP4_NEW_TZDB_TIMEZONE = 101, + NM_DHCP_OPTION_DHCP4_NETINFO_SERVER_ADDRESS = 112, + NM_DHCP_OPTION_DHCP4_NETINFO_SERVER_TAG = 113, + NM_DHCP_OPTION_DHCP4_DEFAULT_URL = 114, + NM_DHCP_OPTION_DHCP4_AUTO_CONFIG = 116, + NM_DHCP_OPTION_DHCP4_NAME_SERVICE_SEARCH = 117, + NM_DHCP_OPTION_DHCP4_SUBNET_SELECTION = 118, + NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST = 119, + NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE = 121, + NM_DHCP_OPTION_DHCP4_VIVCO = 124, + NM_DHCP_OPTION_DHCP4_VIVSO = 125, + NM_DHCP_OPTION_DHCP4_PANA_AGENT = 136, + NM_DHCP_OPTION_DHCP4_V4_LOST = 137, + NM_DHCP_OPTION_DHCP4_SIP_UA_CS_DOMAINS = 141, + NM_DHCP_OPTION_DHCP4_IPV4_ADDRESS_ANDSF = 142, + NM_DHCP_OPTION_DHCP4_RDNSS_SELECTION = 146, + NM_DHCP_OPTION_DHCP4_TFTP_SERVER_ADDRESS = 150, + NM_DHCP_OPTION_DHCP4_V4_PORTPARAMS = 159, + NM_DHCP_OPTION_DHCP4_V4_CAPTIVE_PORTAL = 160, + NM_DHCP_OPTION_DHCP4_MUD_URL = 161, + NM_DHCP_OPTION_DHCP4_LOADER_CONFIGFILE = 209, + NM_DHCP_OPTION_DHCP4_LOADER_PATHPREFIX = 210, + NM_DHCP_OPTION_DHCP4_LOADER_REBOOTTIME = 211, + NM_DHCP_OPTION_DHCP4_OPTION_6RD = 212, + NM_DHCP_OPTION_DHCP4_V4_ACCESS_DOMAIN = 213, + NM_DHCP_OPTION_DHCP4_PRIVATE_224 = 224, + NM_DHCP_OPTION_DHCP4_PRIVATE_225 = 225, + NM_DHCP_OPTION_DHCP4_PRIVATE_226 = 226, + NM_DHCP_OPTION_DHCP4_PRIVATE_227 = 227, + NM_DHCP_OPTION_DHCP4_PRIVATE_228 = 228, + NM_DHCP_OPTION_DHCP4_PRIVATE_229 = 229, + NM_DHCP_OPTION_DHCP4_PRIVATE_230 = 230, + NM_DHCP_OPTION_DHCP4_PRIVATE_231 = 231, + NM_DHCP_OPTION_DHCP4_PRIVATE_232 = 232, + NM_DHCP_OPTION_DHCP4_PRIVATE_233 = 233, + NM_DHCP_OPTION_DHCP4_PRIVATE_234 = 234, + NM_DHCP_OPTION_DHCP4_PRIVATE_235 = 235, + NM_DHCP_OPTION_DHCP4_PRIVATE_236 = 236, + NM_DHCP_OPTION_DHCP4_PRIVATE_237 = 237, + NM_DHCP_OPTION_DHCP4_PRIVATE_238 = 238, + NM_DHCP_OPTION_DHCP4_PRIVATE_239 = 239, + NM_DHCP_OPTION_DHCP4_PRIVATE_240 = 240, + NM_DHCP_OPTION_DHCP4_PRIVATE_241 = 241, + NM_DHCP_OPTION_DHCP4_PRIVATE_242 = 242, + NM_DHCP_OPTION_DHCP4_PRIVATE_243 = 243, + NM_DHCP_OPTION_DHCP4_PRIVATE_244 = 244, + NM_DHCP_OPTION_DHCP4_PRIVATE_245 = 245, + NM_DHCP_OPTION_DHCP4_PRIVATE_246 = 246, + NM_DHCP_OPTION_DHCP4_PRIVATE_247 = 247, + NM_DHCP_OPTION_DHCP4_PRIVATE_248 = 248, + NM_DHCP_OPTION_DHCP4_PRIVATE_CLASSLESS_STATIC_ROUTE = 249, + NM_DHCP_OPTION_DHCP4_PRIVATE_250 = 250, + NM_DHCP_OPTION_DHCP4_PRIVATE_251 = 251, + NM_DHCP_OPTION_DHCP4_PRIVATE_PROXY_AUTODISCOVERY = 252, + NM_DHCP_OPTION_DHCP4_PRIVATE_253 = 253, + NM_DHCP_OPTION_DHCP4_PRIVATE_254 = 254, + NM_DHCP_OPTION_DHCP4_END = 255, + /* Internal values */ + NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS = 1024, + NM_DHCP_OPTION_DHCP4_NM_EXPIRY = 1025, + NM_DHCP_OPTION_DHCP4_NM_NEXT_SERVER = 1026, } NMDhcpOptionDhcp4Options; typedef enum { - NM_DHCP_OPTION_DHCP6_CLIENTID = 1, - NM_DHCP_OPTION_DHCP6_SERVERID = 2, - NM_DHCP_OPTION_DHCP6_DNS_SERVERS = 23, - NM_DHCP_OPTION_DHCP6_DOMAIN_LIST = 24, - NM_DHCP_OPTION_DHCP6_SNTP_SERVERS = 31, - NM_DHCP_OPTION_DHCP6_FQDN = 39, - NM_DHCP_OPTION_DHCP6_MUD_URL = 112, + NM_DHCP_OPTION_DHCP6_CLIENTID = 1, + NM_DHCP_OPTION_DHCP6_SERVERID = 2, + NM_DHCP_OPTION_DHCP6_DNS_SERVERS = 23, + NM_DHCP_OPTION_DHCP6_DOMAIN_LIST = 24, + NM_DHCP_OPTION_DHCP6_SNTP_SERVERS = 31, + NM_DHCP_OPTION_DHCP6_FQDN = 39, + NM_DHCP_OPTION_DHCP6_MUD_URL = 112, - /* Internal values */ - NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS = 1026, - NM_DHCP_OPTION_DHCP6_NM_PREFIXLEN = 1027, - NM_DHCP_OPTION_DHCP6_NM_PREFERRED_LIFE = 1028, - NM_DHCP_OPTION_DHCP6_NM_MAX_LIFE = 1029, - NM_DHCP_OPTION_DHCP6_NM_STARTS = 1030, - NM_DHCP_OPTION_DHCP6_NM_LIFE_STARTS = 1031, - NM_DHCP_OPTION_DHCP6_NM_RENEW = 1032, - NM_DHCP_OPTION_DHCP6_NM_REBIND = 1033, - NM_DHCP_OPTION_DHCP6_NM_IAID = 1034, + /* Internal values */ + NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS = 1026, + NM_DHCP_OPTION_DHCP6_NM_PREFIXLEN = 1027, + NM_DHCP_OPTION_DHCP6_NM_PREFERRED_LIFE = 1028, + NM_DHCP_OPTION_DHCP6_NM_MAX_LIFE = 1029, + NM_DHCP_OPTION_DHCP6_NM_STARTS = 1030, + NM_DHCP_OPTION_DHCP6_NM_LIFE_STARTS = 1031, + NM_DHCP_OPTION_DHCP6_NM_RENEW = 1032, + NM_DHCP_OPTION_DHCP6_NM_REBIND = 1033, + NM_DHCP_OPTION_DHCP6_NM_IAID = 1034, } NMDhcpOptionDhcp6Options; typedef struct { - const char *name; - uint16_t option_num; - bool include; + const char *name; + uint16_t option_num; + bool include; } NMDhcpOption; extern const NMDhcpOption _nm_dhcp_option_dhcp4_options[]; extern const NMDhcpOption _nm_dhcp_option_dhcp6_options[]; -const char *nm_dhcp_option_request_string (const NMDhcpOption *requests, guint option); -void nm_dhcp_option_take_option (GHashTable *options, const NMDhcpOption *requests, guint option, char *value); -void nm_dhcp_option_add_option (GHashTable *options, const NMDhcpOption *requests, guint option, const char *value); -void nm_dhcp_option_add_option_u64 (GHashTable *options, const NMDhcpOption *requests, guint option, guint64 value); -void nm_dhcp_option_add_requests_to_options (GHashTable *options, const NMDhcpOption *requests); -GHashTable *nm_dhcp_option_create_options_dict (void); +const char *nm_dhcp_option_request_string(const NMDhcpOption *requests, guint option); +void nm_dhcp_option_take_option(GHashTable * options, + const NMDhcpOption *requests, + guint option, + char * value); +void nm_dhcp_option_add_option(GHashTable * options, + const NMDhcpOption *requests, + guint option, + const char * value); +void nm_dhcp_option_add_option_u64(GHashTable * options, + const NMDhcpOption *requests, + guint option, + guint64 value); +void nm_dhcp_option_add_requests_to_options(GHashTable *options, const NMDhcpOption *requests); +GHashTable *nm_dhcp_option_create_options_dict(void); #endif /* __NM_DHCP_OPTIONS_H__ */ diff --git a/src/dhcp/nm-dhcp-systemd.c b/src/dhcp/nm-dhcp-systemd.c index 737faad9..f9297223 100644 --- a/src/dhcp/nm-dhcp-systemd.c +++ b/src/dhcp/nm-dhcp-systemd.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: LGPL-2.1+ +/* SPDX-License-Identifier: LGPL-2.1+ */ /* * Copyright (C) 2014 Red Hat, Inc. */ @@ -28,1094 +28,1125 @@ /*****************************************************************************/ -#define NM_TYPE_DHCP_SYSTEMD (nm_dhcp_systemd_get_type ()) -#define NM_DHCP_SYSTEMD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_DHCP_SYSTEMD, NMDhcpSystemd)) -#define NM_DHCP_SYSTEMD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_DHCP_SYSTEMD, NMDhcpSystemdClass)) -#define NM_IS_DHCP_SYSTEMD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_DHCP_SYSTEMD)) -#define NM_IS_DHCP_SYSTEMD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_DHCP_SYSTEMD)) -#define NM_DHCP_SYSTEMD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_DHCP_SYSTEMD, NMDhcpSystemdClass)) - -typedef struct _NMDhcpSystemd NMDhcpSystemd; +#define NM_TYPE_DHCP_SYSTEMD (nm_dhcp_systemd_get_type()) +#define NM_DHCP_SYSTEMD(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), NM_TYPE_DHCP_SYSTEMD, NMDhcpSystemd)) +#define NM_DHCP_SYSTEMD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), NM_TYPE_DHCP_SYSTEMD, NMDhcpSystemdClass)) +#define NM_IS_DHCP_SYSTEMD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), NM_TYPE_DHCP_SYSTEMD)) +#define NM_IS_DHCP_SYSTEMD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), NM_TYPE_DHCP_SYSTEMD)) +#define NM_DHCP_SYSTEMD_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), NM_TYPE_DHCP_SYSTEMD, NMDhcpSystemdClass)) + +typedef struct _NMDhcpSystemd NMDhcpSystemd; typedef struct _NMDhcpSystemdClass NMDhcpSystemdClass; -static GType nm_dhcp_systemd_get_type (void); +static GType nm_dhcp_systemd_get_type(void); /*****************************************************************************/ typedef struct { - sd_dhcp_client *client4; - sd_dhcp6_client *client6; - char *lease_file; + sd_dhcp_client * client4; + sd_dhcp6_client *client6; + char * lease_file; - guint request_count; + guint request_count; - bool privacy:1; + bool privacy : 1; } NMDhcpSystemdPrivate; struct _NMDhcpSystemd { - NMDhcpClient parent; - NMDhcpSystemdPrivate _priv; + NMDhcpClient parent; + NMDhcpSystemdPrivate _priv; }; struct _NMDhcpSystemdClass { - NMDhcpClientClass parent; + NMDhcpClientClass parent; }; -G_DEFINE_TYPE (NMDhcpSystemd, nm_dhcp_systemd, NM_TYPE_DHCP_CLIENT) +G_DEFINE_TYPE(NMDhcpSystemd, nm_dhcp_systemd, NM_TYPE_DHCP_CLIENT) -#define NM_DHCP_SYSTEMD_GET_PRIVATE(self) _NM_GET_PRIVATE (self, NMDhcpSystemd, NM_IS_DHCP_SYSTEMD) +#define NM_DHCP_SYSTEMD_GET_PRIVATE(self) _NM_GET_PRIVATE(self, NMDhcpSystemd, NM_IS_DHCP_SYSTEMD) /*****************************************************************************/ static NMIP4Config * -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) +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; - const struct in_addr *addr_list; - char addr_str[NM_UTILS_INET_ADDRSTRLEN]; - const char *s; - nm_auto_free_gstring GString *str = NULL; - gs_free sd_dhcp_route **routes = NULL; - const char *const*search_domains = NULL; - guint16 mtu; - 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; - const gint32 ts = nm_utils_get_monotonic_timestamp_sec (); - gint64 ts_time = time (NULL); - struct in_addr a_address; - struct in_addr a_netmask; - struct in_addr a_next_server; - struct in_addr server_id; - struct in_addr broadcast; - const struct in_addr *a_router; - guint32 a_plen; - guint32 a_lifetime; - guint32 renewal; - guint32 rebinding; - gs_free nm_sd_dhcp_option *private_options = NULL; - - nm_assert (lease != NULL); - - if (sd_dhcp_lease_get_address (lease, &a_address) < 0) { - nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "could not get address from lease"); - return NULL; - } - - if (sd_dhcp_lease_get_netmask (lease, &a_netmask) < 0) { - nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "could not get netmask from lease"); - return NULL; - } - - if (sd_dhcp_lease_get_lifetime (lease, &a_lifetime) < 0) { - nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "could not get lifetime from lease"); - return NULL; - } - - ip4_config = nm_ip4_config_new (multi_idx, ifindex); - - options = out_options ? nm_dhcp_option_create_options_dict () : NULL; - - _nm_utils_inet4_ntop (a_address.s_addr, addr_str); - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, - addr_str); - - a_plen = nm_utils_ip4_netmask_to_prefix (a_netmask.s_addr); - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_SUBNET_MASK, - _nm_utils_inet4_ntop (a_netmask.s_addr, addr_str)); - - nm_dhcp_option_add_option_u64 (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME, - a_lifetime); - nm_dhcp_option_add_option_u64 (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_NM_EXPIRY, - (guint64) (ts_time + a_lifetime)); - - if (sd_dhcp_lease_get_next_server (lease, &a_next_server) == 0) { - _nm_utils_inet4_ntop (a_next_server.s_addr, addr_str); - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - 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, - })); - - if (sd_dhcp_lease_get_server_identifier (lease, &server_id) >= 0) { - _nm_utils_inet4_ntop (server_id.s_addr, addr_str); - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_SERVER_ID, - addr_str); - } - - if (sd_dhcp_lease_get_broadcast (lease, &broadcast) >= 0) { - _nm_utils_inet4_ntop (broadcast.s_addr, addr_str); - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_BROADCAST, - addr_str); - } - - num = sd_dhcp_lease_get_dns (lease, &addr_list); - if (num > 0) { - nm_gstring_prepare (&str); - for (i = 0; i < num; i++) { - _nm_utils_inet4_ntop (addr_list[i].s_addr, addr_str); - g_string_append (nm_gstring_add_space_delimiter (str), addr_str); - - if ( addr_list[i].s_addr == 0 - || nm_ip4_addr_is_localhost (addr_list[i].s_addr)) { - /* Skip localhost addresses, like also networkd does. - * See https://github.com/systemd/systemd/issues/4524. */ - continue; - } - nm_ip4_config_add_nameserver (ip4_config, addr_list[i].s_addr); - } - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, - str->str); - } - - num = sd_dhcp_lease_get_search_domains (lease, (char ***) &search_domains); - if (num > 0) { - 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_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, - str->str); - } - - if (sd_dhcp_lease_get_domainname (lease, &s) >= 0) { - gs_strfreev char **domains = NULL; - char **d; - - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, - s); - - /* Multiple domains sometimes stuffed into option 15 "Domain Name". - * 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); - } - - if (sd_dhcp_lease_get_hostname (lease, &s) >= 0) { - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_HOST_NAME, - s); - } - - 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; - - for (i = 0; i < num; i++) { - switch (sd_dhcp_route_get_option (routes[i])) { - case NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE: - has_classless_route = TRUE; - break; - case NM_DHCP_OPTION_DHCP4_STATIC_ROUTE: - has_static_route = TRUE; - break; - } - } - - if (has_classless_route) - str_classless = g_string_sized_new (30); - if (has_static_route) - str_static = g_string_sized_new (30); - - for (i = 0; i < num; i++) { - char network_net_str[NM_UTILS_INET_ADDRSTRLEN]; - char gateway_str[NM_UTILS_INET_ADDRSTRLEN]; - guint8 r_plen; - struct in_addr r_network; - struct in_addr r_gateway; - in_addr_t network_net; - int option; - guint32 m; - - option = sd_dhcp_route_get_option (routes[i]); - if (!NM_IN_SET (option, NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, - NM_DHCP_OPTION_DHCP4_STATIC_ROUTE)) - continue; - - if (sd_dhcp_route_get_destination (routes[i], &r_network) < 0) - continue; - if ( sd_dhcp_route_get_destination_prefix_length (routes[i], &r_plen) < 0 - || r_plen > 32) - continue; - if (sd_dhcp_route_get_gateway (routes[i], &r_gateway) < 0) - continue; - - network_net = nm_utils_ip4_address_clear_host_address (r_network.s_addr, - r_plen); - _nm_utils_inet4_ntop (network_net, network_net_str); - _nm_utils_inet4_ntop (r_gateway.s_addr, gateway_str); - - g_string_append_printf (nm_gstring_add_space_delimiter ( option == NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE - ? str_classless - : str_static), - "%s/%d %s", - network_net_str, - (int) r_plen, - gateway_str); - - if ( option == NM_DHCP_OPTION_DHCP4_STATIC_ROUTE - && has_classless_route) { - /* RFC 3443: if the DHCP server returns both a Classless Static Routes - * option and a Static Routes option, the DHCP client MUST ignore the - * Static Routes option. */ - continue; - } - - if ( r_plen == 0 - && option == NM_DHCP_OPTION_DHCP4_STATIC_ROUTE) { - /* for option 33 (static route), RFC 2132 says: - * - * The default route (0.0.0.0) is an illegal destination for a static - * route. */ - continue; - } - - 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++; - - 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); - } - - if (str_classless && str_classless->len > 0) - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, - str_classless->str); - if (str_static && str_static->len > 0) - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_STATIC_ROUTE, - str_static->str); - } - - num = sd_dhcp_lease_get_router (lease, &a_router); - if (num > 0) { - guint32 default_route_metric = route_metric; - - nm_gstring_prepare (&str); - for (i = 0; i < num; i++) { - guint32 m; - - s = _nm_utils_inet4_ntop (a_router[i].s_addr, addr_str); - g_string_append (nm_gstring_add_space_delimiter (str), s); - - if (a_router[i].s_addr == 0) { - /* silently skip 0.0.0.0 */ - continue; - } - - if (has_router_from_classless) { - /* If the DHCP server returns both a Classless Static Routes option and a - * Router option, the DHCP client MUST ignore the Router option [RFC 3442]. - * - * Be more lenient and ignore the Router option only if Classless Static - * Routes contain a default gateway (as other DHCP backends do). - */ - continue; - } - - /* 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); - } - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_ROUTER, - str->str); - } - - if ( sd_dhcp_lease_get_mtu (lease, &mtu) >= 0 - && mtu) { - nm_dhcp_option_add_option_u64 (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, - mtu); - nm_ip4_config_set_mtu (ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP); - } - - num = sd_dhcp_lease_get_ntp (lease, &addr_list); - if (num > 0) { - nm_gstring_prepare (&str); - for (i = 0; i < num; i++) { - _nm_utils_inet4_ntop (addr_list[i].s_addr, addr_str); - g_string_append (nm_gstring_add_space_delimiter (str), addr_str); - } - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_NTP_SERVER, - str->str); - } - - if (sd_dhcp_lease_get_root_path (lease, &s) >= 0) { - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_ROOT_PATH, - s); - } - - if (sd_dhcp_lease_get_t1 (lease, &renewal) >= 0) { - nm_dhcp_option_add_option_u64 (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_RENEWAL_T1_TIME, - renewal); - } - - if (sd_dhcp_lease_get_t2 (lease, &rebinding) >= 0) { - nm_dhcp_option_add_option_u64 (options, - _nm_dhcp_option_dhcp4_options, - NM_DHCP_OPTION_DHCP4_REBINDING_T2_TIME, - rebinding); - } - - if (sd_dhcp_lease_get_timezone (lease, &s) >= 0) { - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp4_options, - 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); - - num = nm_sd_dhcp_lease_get_private_options (lease, &private_options); - if (num > 0) { - for (i = 0; i < num; i++) { - char *option_string; - - option_string = nm_utils_bin2hexstr_full (private_options[i].data, - private_options[i].data_len, - ':', FALSE, NULL); - if (!options) { - g_free (option_string); - continue; - } - nm_dhcp_option_take_option (options, - _nm_dhcp_option_dhcp4_options, - private_options[i].code, - option_string); - } - } - NM_SET_OUT (out_options, g_steal_pointer (&options)); - return g_steal_pointer (&ip4_config); + gs_unref_object NMIP4Config *ip4_config = NULL; + gs_unref_hashtable GHashTable *options = NULL; + const struct in_addr * addr_list; + char addr_str[NM_UTILS_INET_ADDRSTRLEN]; + const char * s; + nm_auto_free_gstring GString *str = NULL; + gs_free sd_dhcp_route **routes = NULL; + const char *const * search_domains = NULL; + guint16 mtu; + 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; + const gint32 ts = nm_utils_get_monotonic_timestamp_sec(); + gint64 ts_time = time(NULL); + struct in_addr a_address; + struct in_addr a_netmask; + struct in_addr a_next_server; + struct in_addr server_id; + struct in_addr broadcast; + const struct in_addr * a_router; + guint32 a_plen; + guint32 a_lifetime; + guint32 renewal; + guint32 rebinding; + gs_free nm_sd_dhcp_option *private_options = NULL; + + nm_assert(lease != NULL); + + if (sd_dhcp_lease_get_address(lease, &a_address) < 0) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_UNKNOWN, + "could not get address from lease"); + return NULL; + } + + if (sd_dhcp_lease_get_netmask(lease, &a_netmask) < 0) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_UNKNOWN, + "could not get netmask from lease"); + return NULL; + } + + if (sd_dhcp_lease_get_lifetime(lease, &a_lifetime) < 0) { + nm_utils_error_set_literal(error, + NM_UTILS_ERROR_UNKNOWN, + "could not get lifetime from lease"); + return NULL; + } + + ip4_config = nm_ip4_config_new(multi_idx, ifindex); + + options = out_options ? nm_dhcp_option_create_options_dict() : NULL; + + _nm_utils_inet4_ntop(a_address.s_addr, addr_str); + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_NM_IP_ADDRESS, + addr_str); + + a_plen = nm_utils_ip4_netmask_to_prefix(a_netmask.s_addr); + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_SUBNET_MASK, + _nm_utils_inet4_ntop(a_netmask.s_addr, addr_str)); + + nm_dhcp_option_add_option_u64(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_IP_ADDRESS_LEASE_TIME, + a_lifetime); + nm_dhcp_option_add_option_u64(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_NM_EXPIRY, + (guint64)(ts_time + a_lifetime)); + + if (sd_dhcp_lease_get_next_server(lease, &a_next_server) == 0) { + _nm_utils_inet4_ntop(a_next_server.s_addr, addr_str); + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + 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, + })); + + if (sd_dhcp_lease_get_server_identifier(lease, &server_id) >= 0) { + _nm_utils_inet4_ntop(server_id.s_addr, addr_str); + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_SERVER_ID, + addr_str); + } + + if (sd_dhcp_lease_get_broadcast(lease, &broadcast) >= 0) { + _nm_utils_inet4_ntop(broadcast.s_addr, addr_str); + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_BROADCAST, + addr_str); + } + + num = sd_dhcp_lease_get_dns(lease, &addr_list); + if (num > 0) { + nm_gstring_prepare(&str); + for (i = 0; i < num; i++) { + _nm_utils_inet4_ntop(addr_list[i].s_addr, addr_str); + g_string_append(nm_gstring_add_space_delimiter(str), addr_str); + + if (addr_list[i].s_addr == 0 || nm_ip4_addr_is_localhost(addr_list[i].s_addr)) { + /* Skip localhost addresses, like also networkd does. + * See https://github.com/systemd/systemd/issues/4524. */ + continue; + } + nm_ip4_config_add_nameserver(ip4_config, addr_list[i].s_addr); + } + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_DOMAIN_NAME_SERVER, + str->str); + } + + num = sd_dhcp_lease_get_search_domains(lease, (char ***) &search_domains); + if (num > 0) { + 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_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_DOMAIN_SEARCH_LIST, + str->str); + } + + if (sd_dhcp_lease_get_domainname(lease, &s) >= 0) { + gs_strfreev char **domains = NULL; + char ** d; + + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_DOMAIN_NAME, + s); + + /* Multiple domains sometimes stuffed into option 15 "Domain Name". + * 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); + } + + if (sd_dhcp_lease_get_hostname(lease, &s) >= 0) { + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_HOST_NAME, + s); + } + + 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; + + for (i = 0; i < num; i++) { + switch (sd_dhcp_route_get_option(routes[i])) { + case NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE: + has_classless_route = TRUE; + break; + case NM_DHCP_OPTION_DHCP4_STATIC_ROUTE: + has_static_route = TRUE; + break; + } + } + + if (has_classless_route) + str_classless = g_string_sized_new(30); + if (has_static_route) + str_static = g_string_sized_new(30); + + for (i = 0; i < num; i++) { + char network_net_str[NM_UTILS_INET_ADDRSTRLEN]; + char gateway_str[NM_UTILS_INET_ADDRSTRLEN]; + guint8 r_plen; + struct in_addr r_network; + struct in_addr r_gateway; + in_addr_t network_net; + int option; + guint32 m; + + option = sd_dhcp_route_get_option(routes[i]); + if (!NM_IN_SET(option, + NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, + NM_DHCP_OPTION_DHCP4_STATIC_ROUTE)) + continue; + + if (sd_dhcp_route_get_destination(routes[i], &r_network) < 0) + continue; + if (sd_dhcp_route_get_destination_prefix_length(routes[i], &r_plen) < 0 || r_plen > 32) + continue; + if (sd_dhcp_route_get_gateway(routes[i], &r_gateway) < 0) + continue; + + network_net = nm_utils_ip4_address_clear_host_address(r_network.s_addr, r_plen); + _nm_utils_inet4_ntop(network_net, network_net_str); + _nm_utils_inet4_ntop(r_gateway.s_addr, gateway_str); + + g_string_append_printf( + nm_gstring_add_space_delimiter(option == NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE + ? str_classless + : str_static), + "%s/%d %s", + network_net_str, + (int) r_plen, + gateway_str); + + if (option == NM_DHCP_OPTION_DHCP4_STATIC_ROUTE && has_classless_route) { + /* RFC 3443: if the DHCP server returns both a Classless Static Routes + * option and a Static Routes option, the DHCP client MUST ignore the + * Static Routes option. */ + continue; + } + + if (r_plen == 0 && option == NM_DHCP_OPTION_DHCP4_STATIC_ROUTE) { + /* for option 33 (static route), RFC 2132 says: + * + * The default route (0.0.0.0) is an illegal destination for a static + * route. */ + continue; + } + + 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++; + + 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); + } + + if (str_classless && str_classless->len > 0) + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_CLASSLESS_STATIC_ROUTE, + str_classless->str); + if (str_static && str_static->len > 0) + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_STATIC_ROUTE, + str_static->str); + } + + num = sd_dhcp_lease_get_router(lease, &a_router); + if (num > 0) { + guint32 default_route_metric = route_metric; + + nm_gstring_prepare(&str); + for (i = 0; i < num; i++) { + guint32 m; + + s = _nm_utils_inet4_ntop(a_router[i].s_addr, addr_str); + g_string_append(nm_gstring_add_space_delimiter(str), s); + + if (a_router[i].s_addr == 0) { + /* silently skip 0.0.0.0 */ + continue; + } + + if (has_router_from_classless) { + /* If the DHCP server returns both a Classless Static Routes option and a + * Router option, the DHCP client MUST ignore the Router option [RFC 3442]. + * + * Be more lenient and ignore the Router option only if Classless Static + * Routes contain a default gateway (as other DHCP backends do). + */ + continue; + } + + /* 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); + } + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_ROUTER, + str->str); + } + + if (sd_dhcp_lease_get_mtu(lease, &mtu) >= 0 && mtu) { + nm_dhcp_option_add_option_u64(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_INTERFACE_MTU, + mtu); + nm_ip4_config_set_mtu(ip4_config, mtu, NM_IP_CONFIG_SOURCE_DHCP); + } + + num = sd_dhcp_lease_get_ntp(lease, &addr_list); + if (num > 0) { + nm_gstring_prepare(&str); + for (i = 0; i < num; i++) { + _nm_utils_inet4_ntop(addr_list[i].s_addr, addr_str); + g_string_append(nm_gstring_add_space_delimiter(str), addr_str); + } + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_NTP_SERVER, + str->str); + } + + if (sd_dhcp_lease_get_root_path(lease, &s) >= 0) { + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_ROOT_PATH, + s); + } + + if (sd_dhcp_lease_get_t1(lease, &renewal) >= 0) { + nm_dhcp_option_add_option_u64(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_RENEWAL_T1_TIME, + renewal); + } + + if (sd_dhcp_lease_get_t2(lease, &rebinding) >= 0) { + nm_dhcp_option_add_option_u64(options, + _nm_dhcp_option_dhcp4_options, + NM_DHCP_OPTION_DHCP4_REBINDING_T2_TIME, + rebinding); + } + + if (sd_dhcp_lease_get_timezone(lease, &s) >= 0) { + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp4_options, + 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); + + num = nm_sd_dhcp_lease_get_private_options(lease, &private_options); + if (num > 0) { + for (i = 0; i < num; i++) { + char *option_string; + + option_string = nm_utils_bin2hexstr_full(private_options[i].data, + private_options[i].data_len, + ':', + FALSE, + NULL); + if (!options) { + g_free(option_string); + continue; + } + nm_dhcp_option_take_option(options, + _nm_dhcp_option_dhcp4_options, + private_options[i].code, + option_string); + } + } + NM_SET_OUT(out_options, g_steal_pointer(&options)); + return g_steal_pointer(&ip4_config); } /*****************************************************************************/ static void -bound4_handle (NMDhcpSystemd *self, gboolean extended) +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; - - 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); - 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) { - _LOGW ("%s", error->message); - g_clear_error (&error); - nm_dhcp_client_set_state (NM_DHCP_CLIENT (self), NM_DHCP_STATE_FAIL, NULL, NULL); - return; - } - - nm_dhcp_option_add_requests_to_options (options, _nm_dhcp_option_dhcp4_options); - 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); + 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; + + 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); + 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) { + _LOGW("%s", error->message); + g_clear_error(&error); + nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL); + return; + } + + nm_dhcp_option_add_requests_to_options(options, _nm_dhcp_option_dhcp4_options); + 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); } static int -dhcp_event_cb (sd_dhcp_client *client, int event, gpointer user_data) +dhcp_event_cb(sd_dhcp_client *client, int event, gpointer user_data) { - NMDhcpSystemd *self = NM_DHCP_SYSTEMD (user_data); - NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (self); - - nm_assert (priv->client4 == client); - - _LOGD ("client event %d", event); - - switch (event) { - case SD_DHCP_CLIENT_EVENT_EXPIRED: - nm_dhcp_client_set_state (NM_DHCP_CLIENT (user_data), NM_DHCP_STATE_EXPIRE, NULL, NULL); - break; - case SD_DHCP_CLIENT_EVENT_STOP: - nm_dhcp_client_set_state (NM_DHCP_CLIENT (user_data), NM_DHCP_STATE_FAIL, NULL, NULL); - break; - case SD_DHCP_CLIENT_EVENT_RENEW: - case SD_DHCP_CLIENT_EVENT_IP_CHANGE: - bound4_handle (self, TRUE); - break; - case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE: - bound4_handle (self, FALSE); - break; - case SD_DHCP_CLIENT_EVENT_SELECTING: - break; - default: - _LOGW ("unhandled DHCP event %d", event); - break; - } - - return 0; + NMDhcpSystemd * self = NM_DHCP_SYSTEMD(user_data); + NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self); + char addr_str[INET_ADDRSTRLEN]; + sd_dhcp_lease * lease = NULL; + struct in_addr addr; + int r; + + nm_assert(priv->client4 == client); + + _LOGD("client event %d", event); + + switch (event) { + case SD_DHCP_CLIENT_EVENT_EXPIRED: + nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_EXPIRE, NULL, NULL); + break; + case SD_DHCP_CLIENT_EVENT_STOP: + nm_dhcp_client_set_state(NM_DHCP_CLIENT(user_data), NM_DHCP_STATE_FAIL, NULL, NULL); + break; + case SD_DHCP_CLIENT_EVENT_RENEW: + case SD_DHCP_CLIENT_EVENT_IP_CHANGE: + bound4_handle(self, TRUE); + break; + case SD_DHCP_CLIENT_EVENT_IP_ACQUIRE: + bound4_handle(self, FALSE); + break; + case SD_DHCP_CLIENT_EVENT_SELECTING: + r = sd_dhcp_client_get_lease(priv->client4, &lease); + if (r < 0) + return r; + r = sd_dhcp_lease_get_server_identifier(lease, &addr); + if (r < 0) + return r; + if (nm_dhcp_client_server_id_is_rejected(NM_DHCP_CLIENT(user_data), &addr)) { + _LOGD("server-id %s is in the reject-list, ignoring", + nm_utils_inet_ntop(AF_INET, &addr, addr_str)); + return -ENOMSG; + } + break; + default: + _LOGW("unhandled DHCP event %d", event); + break; + } + + return 0; } static gboolean -ip4_start (NMDhcpClient *client, - const char *dhcp_anycast_addr, - const char *last_ip4_address, - GError **error) +ip4_start(NMDhcpClient *client, + const char * dhcp_anycast_addr, + const char * last_ip4_address, + 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); - gs_free char *lease_file = NULL; - GBytes *hwaddr; - const uint8_t *hwaddr_arr; - gsize hwaddr_len; - int arp_type; - GBytes *client_id; - gs_unref_bytes GBytes *client_id_new = NULL; - const uint8_t *client_id_arr; - size_t client_id_len; - struct in_addr last_addr = { 0 }; - const char *hostname; - const char *mud_url; - int r, i; - - g_return_val_if_fail (!priv->client4, FALSE); - g_return_val_if_fail (!priv->client6, FALSE); - - r = sd_dhcp_client_new (&sd_client, FALSE); - if (r < 0) { - nm_utils_error_set_errno (error, r, "failed to create dhcp-client: %s"); - return FALSE; - } - - _LOGT ("dhcp-client4: set %p", sd_client); - - r = sd_dhcp_client_attach_event (sd_client, NULL, 0); - if (r < 0) { - nm_utils_error_set_errno (error, r, "failed to attach event: %s"); - return FALSE; - } - - hwaddr = nm_dhcp_client_get_hw_addr (client); - 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; - } - r = sd_dhcp_client_set_mac (sd_client, - hwaddr_arr, - hwaddr_len, - (guint16) arp_type); - if (r < 0) { - nm_utils_error_set_errno (error, r, "failed to set MAC address: %s"); - return FALSE; - } - - r = sd_dhcp_client_set_ifindex (sd_client, - nm_dhcp_client_get_ifindex (client)); - if (r < 0) { - nm_utils_error_set_errno (error, r, "failed to set ifindex: %s"); - return FALSE; - } - - nm_dhcp_utils_get_leasefile_path (AF_INET, - "internal", - nm_dhcp_client_get_iface (client), - nm_dhcp_client_get_uuid (client), - &lease_file); - - if (last_ip4_address) - inet_pton (AF_INET, last_ip4_address, &last_addr); - else { - nm_auto (sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; - - dhcp_lease_load (&lease, lease_file); - if (lease) - sd_dhcp_lease_get_address (lease, &last_addr); - } - - if (last_addr.s_addr) { - r = sd_dhcp_client_set_request_address (sd_client, &last_addr); - if (r < 0) { - nm_utils_error_set_errno (error, r, "failed to set last IPv4 address: %s"); - return FALSE; - } - } - - client_id = nm_dhcp_client_get_client_id (client); - if (!client_id) { - client_id_new = nm_utils_dhcp_client_id_mac (arp_type, hwaddr_arr, hwaddr_len); - client_id = client_id_new; - } - - if ( !(client_id_arr = g_bytes_get_data (client_id, &client_id_len)) - || client_id_len < 2) { - - /* invalid client-ids are not expected. */ - nm_assert_not_reached (); - - nm_utils_error_set_literal (error, NM_UTILS_ERROR_UNKNOWN, "no valid IPv4 client-id"); - return FALSE; - } - - /* 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 . */ - r = sd_dhcp_client_set_client_id (sd_client, - client_id_arr[0], - client_id_arr + 1, - NM_MIN (client_id_len - 1, _NM_SD_MAX_CLIENT_ID_LEN)); - if (r < 0) { - nm_utils_error_set_errno (error, r, "failed to set IPv4 client-id: %s"); - return FALSE; - } - - /* Add requested options */ - for (i = 0; _nm_dhcp_option_dhcp4_options[i].name; i++) { - if (_nm_dhcp_option_dhcp4_options[i].include) { - nm_assert (_nm_dhcp_option_dhcp4_options[i].option_num <= 255); - r = sd_dhcp_client_set_request_option (sd_client, _nm_dhcp_option_dhcp4_options[i].option_num); - nm_assert (r >= 0 || r == -EEXIST); - } - } - - hostname = nm_dhcp_client_get_hostname (client); - 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 - * moment there is no way to force one or another. - */ - r = sd_dhcp_client_set_hostname (sd_client, hostname); - if (r < 0) { - nm_utils_error_set_errno (error, r, "failed to set DHCP hostname: %s"); - return FALSE; - } - } - - mud_url = nm_dhcp_client_get_mud_url (client); - if (mud_url) { - r = sd_dhcp_client_set_mud_url (sd_client, mud_url); - if (r < 0) { - nm_utils_error_set_errno (error, r, "failed to set DHCP MUDURL: %s"); - return FALSE; - } - } - - r = sd_dhcp_client_set_callback (sd_client, dhcp_event_cb, client); - if (r < 0) { - nm_utils_error_set_errno (error, r, "failed to set callback: %s"); - return FALSE; - } - - priv->client4 = g_steal_pointer (&sd_client); - - g_free (priv->lease_file); - priv->lease_file = g_steal_pointer (&lease_file); - - nm_dhcp_client_set_client_id (client, client_id); - - r = sd_dhcp_client_start (priv->client4); - if (r < 0) { - sd_dhcp_client_set_callback (priv->client4, NULL, NULL); - nm_clear_pointer (&priv->client4, sd_dhcp_client_unref); - nm_utils_error_set_errno (error, r, "failed to start DHCP client: %s"); - return FALSE; - } - - nm_dhcp_client_start_timeout (client); - return TRUE; + 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); + gs_free char * lease_file = NULL; + GBytes * hwaddr; + const uint8_t * hwaddr_arr; + gsize hwaddr_len; + int arp_type; + GBytes * client_id; + gs_unref_bytes GBytes *client_id_new = NULL; + GBytes * vendor_class_identifier; + const uint8_t * client_id_arr; + size_t client_id_len; + struct in_addr last_addr = {0}; + const char * hostname; + const char * mud_url; + int r, i; + + g_return_val_if_fail(!priv->client4, FALSE); + g_return_val_if_fail(!priv->client6, FALSE); + + r = sd_dhcp_client_new(&sd_client, FALSE); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to create dhcp-client: %s"); + return FALSE; + } + + _LOGT("dhcp-client4: set %p", sd_client); + + r = sd_dhcp_client_attach_event(sd_client, NULL, 0); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to attach event: %s"); + return FALSE; + } + + hwaddr = nm_dhcp_client_get_hw_addr(client); + 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; + } + r = sd_dhcp_client_set_mac(sd_client, hwaddr_arr, hwaddr_len, (guint16) arp_type); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to set MAC address: %s"); + return FALSE; + } + + r = sd_dhcp_client_set_ifindex(sd_client, nm_dhcp_client_get_ifindex(client)); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to set ifindex: %s"); + return FALSE; + } + + nm_dhcp_utils_get_leasefile_path(AF_INET, + "internal", + nm_dhcp_client_get_iface(client), + nm_dhcp_client_get_uuid(client), + &lease_file); + + if (last_ip4_address) + inet_pton(AF_INET, last_ip4_address, &last_addr); + else { + nm_auto(sd_dhcp_lease_unrefp) sd_dhcp_lease *lease = NULL; + + dhcp_lease_load(&lease, lease_file); + if (lease) + sd_dhcp_lease_get_address(lease, &last_addr); + } + + if (last_addr.s_addr) { + r = sd_dhcp_client_set_request_address(sd_client, &last_addr); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to set last IPv4 address: %s"); + return FALSE; + } + } + + client_id = nm_dhcp_client_get_client_id(client); + if (!client_id) { + client_id_new = nm_utils_dhcp_client_id_mac(arp_type, hwaddr_arr, hwaddr_len); + client_id = client_id_new; + } + + if (!(client_id_arr = g_bytes_get_data(client_id, &client_id_len)) || client_id_len < 2) { + /* invalid client-ids are not expected. */ + nm_assert_not_reached(); + + nm_utils_error_set_literal(error, NM_UTILS_ERROR_UNKNOWN, "no valid IPv4 client-id"); + return FALSE; + } + + /* 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 . */ + r = sd_dhcp_client_set_client_id(sd_client, + client_id_arr[0], + client_id_arr + 1, + NM_MIN(client_id_len - 1, _NM_SD_MAX_CLIENT_ID_LEN)); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to set IPv4 client-id: %s"); + return FALSE; + } + + /* Add requested options */ + for (i = 0; _nm_dhcp_option_dhcp4_options[i].name; i++) { + if (_nm_dhcp_option_dhcp4_options[i].include) { + nm_assert(_nm_dhcp_option_dhcp4_options[i].option_num <= 255); + r = sd_dhcp_client_set_request_option(sd_client, + _nm_dhcp_option_dhcp4_options[i].option_num); + nm_assert(r >= 0 || r == -EEXIST); + } + } + + hostname = nm_dhcp_client_get_hostname(client); + 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 + * moment there is no way to force one or another. + */ + r = sd_dhcp_client_set_hostname(sd_client, hostname); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to set DHCP hostname: %s"); + return FALSE; + } + } + + mud_url = nm_dhcp_client_get_mud_url(client); + if (mud_url) { + r = sd_dhcp_client_set_mud_url(sd_client, mud_url); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to set DHCP MUDURL: %s"); + return FALSE; + } + } + + vendor_class_identifier = nm_dhcp_client_get_vendor_class_identifier(client); + if (vendor_class_identifier) { + const char *option_data; + gsize len; + + option_data = g_bytes_get_data(vendor_class_identifier, &len); + nm_assert(option_data); + nm_assert(len <= 255); + + option_data = nm_strndup_a(300, option_data, len, NULL); + + r = sd_dhcp_client_set_vendor_class_identifier(sd_client, option_data); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to set DHCP vendor class identifier: %s"); + return FALSE; + } + } + + r = sd_dhcp_client_set_callback(sd_client, dhcp_event_cb, client); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to set callback: %s"); + return FALSE; + } + + priv->client4 = g_steal_pointer(&sd_client); + + g_free(priv->lease_file); + priv->lease_file = g_steal_pointer(&lease_file); + + nm_dhcp_client_set_client_id(client, client_id); + + r = sd_dhcp_client_start(priv->client4); + if (r < 0) { + sd_dhcp_client_set_callback(priv->client4, NULL, NULL); + nm_clear_pointer(&priv->client4, sd_dhcp_client_unref); + nm_utils_error_set_errno(error, r, "failed to start DHCP client: %s"); + return FALSE; + } + + nm_dhcp_client_start_timeout(client); + return TRUE; } static NMIP6Config * -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) +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; - 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; - int num, i; - - nm_assert (lease); - - ip6_config = nm_ip6_config_new (multi_idx, ifindex); - - options = out_options ? nm_dhcp_option_create_options_dict () : NULL; - - sd_dhcp6_lease_reset_address_iter (lease); - nm_gstring_prepare (&str); - while (sd_dhcp6_lease_get_address (lease, &tmp_addr, &lft_pref, &lft_valid) >= 0) { - const NMPlatformIP6Address address = { - .plen = 128, - .address = tmp_addr, - .timestamp = ts, - .lifetime = lft_valid, - .preferred = lft_pref, - .addr_source = NM_IP_CONFIG_SOURCE_DHCP, - }; - - nm_ip6_config_add_address (ip6_config, &address); - - _nm_utils_inet6_ntop (&tmp_addr, addr_str); - g_string_append (nm_gstring_add_space_delimiter (str), addr_str); - }; - if (str->len) - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp6_options, - NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS, - str->str); - - if ( !info_only - && nm_ip6_config_get_num_addresses (ip6_config) == 0) { - g_set_error_literal (error, - NM_MANAGER_ERROR, - NM_MANAGER_ERROR_FAILED, - "no address received in managed mode"); - return NULL; - } - - num = sd_dhcp6_lease_get_dns (lease, &dns); - if (num > 0) { - nm_gstring_prepare (&str); - 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_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp6_options, - NM_DHCP_OPTION_DHCP6_DNS_SERVERS, - str->str); - } - - num = sd_dhcp6_lease_get_domains (lease, &domains); - if (num > 0) { - 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_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp6_options, - NM_DHCP_OPTION_DHCP6_DOMAIN_LIST, - str->str); - } - - if (sd_dhcp6_lease_get_fqdn (lease, &s) >= 0) { - nm_dhcp_option_add_option (options, - _nm_dhcp_option_dhcp6_options, - NM_DHCP_OPTION_DHCP6_FQDN, - s); - } - - NM_SET_OUT (out_options, g_steal_pointer (&options)); - return g_steal_pointer (&ip6_config); + gs_unref_object NMIP6Config *ip6_config = 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; + int num, i; + + nm_assert(lease); + + ip6_config = nm_ip6_config_new(multi_idx, ifindex); + + options = out_options ? nm_dhcp_option_create_options_dict() : NULL; + + sd_dhcp6_lease_reset_address_iter(lease); + nm_gstring_prepare(&str); + while (sd_dhcp6_lease_get_address(lease, &tmp_addr, &lft_pref, &lft_valid) >= 0) { + const NMPlatformIP6Address address = { + .plen = 128, + .address = tmp_addr, + .timestamp = ts, + .lifetime = lft_valid, + .preferred = lft_pref, + .addr_source = NM_IP_CONFIG_SOURCE_DHCP, + }; + + nm_ip6_config_add_address(ip6_config, &address); + + _nm_utils_inet6_ntop(&tmp_addr, addr_str); + g_string_append(nm_gstring_add_space_delimiter(str), addr_str); + }; + if (str->len) + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp6_options, + NM_DHCP_OPTION_DHCP6_NM_IP_ADDRESS, + str->str); + + if (!info_only && nm_ip6_config_get_num_addresses(ip6_config) == 0) { + g_set_error_literal(error, + NM_MANAGER_ERROR, + NM_MANAGER_ERROR_FAILED, + "no address received in managed mode"); + return NULL; + } + + num = sd_dhcp6_lease_get_dns(lease, &dns); + if (num > 0) { + nm_gstring_prepare(&str); + 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_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp6_options, + NM_DHCP_OPTION_DHCP6_DNS_SERVERS, + str->str); + } + + num = sd_dhcp6_lease_get_domains(lease, &domains); + if (num > 0) { + 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_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp6_options, + NM_DHCP_OPTION_DHCP6_DOMAIN_LIST, + str->str); + } + + if (sd_dhcp6_lease_get_fqdn(lease, &s) >= 0) { + nm_dhcp_option_add_option(options, + _nm_dhcp_option_dhcp6_options, + NM_DHCP_OPTION_DHCP6_FQDN, + s); + } + + NM_SET_OUT(out_options, g_steal_pointer(&options)); + return g_steal_pointer(&ip6_config); } static void -bound6_handle (NMDhcpSystemd *self) +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; - - 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); - 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_dhcp_client_get_info_only (NM_DHCP_CLIENT (self)), - &options, - ts, - &error); - - if (!ip6_config) { - _LOGW ("%s", error->message); - nm_dhcp_client_set_state (NM_DHCP_CLIENT (self), NM_DHCP_STATE_FAIL, NULL, NULL); - return; - } - - nm_dhcp_client_set_state (NM_DHCP_CLIENT (self), - NM_DHCP_STATE_BOUND, - NM_IP_CONFIG_CAST (ip6_config), - options); - - sd_dhcp6_lease_reset_pd_prefix_iter (lease); - while (!sd_dhcp6_lease_get_pd (lease, - &prefix.address, - &prefix.plen, - &prefix.preferred, - &prefix.lifetime)) { - prefix.timestamp = ts; - nm_dhcp_client_emit_ipv6_prefix_delegated (NM_DHCP_CLIENT (self), &prefix); - } + 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; + + 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); + 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_dhcp_client_get_info_only(NM_DHCP_CLIENT(self)), + &options, + ts, + &error); + + if (!ip6_config) { + _LOGW("%s", error->message); + nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), NM_DHCP_STATE_FAIL, NULL, NULL); + return; + } + + nm_dhcp_client_set_state(NM_DHCP_CLIENT(self), + NM_DHCP_STATE_BOUND, + NM_IP_CONFIG_CAST(ip6_config), + options); + + sd_dhcp6_lease_reset_pd_prefix_iter(lease); + while (!sd_dhcp6_lease_get_pd(lease, + &prefix.address, + &prefix.plen, + &prefix.preferred, + &prefix.lifetime)) { + prefix.timestamp = ts; + nm_dhcp_client_emit_ipv6_prefix_delegated(NM_DHCP_CLIENT(self), &prefix); + } } static void -dhcp6_event_cb (sd_dhcp6_client *client, int event, gpointer user_data) +dhcp6_event_cb(sd_dhcp6_client *client, int event, gpointer user_data) { - NMDhcpSystemd *self = NM_DHCP_SYSTEMD (user_data); - NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (self); - - nm_assert (priv->client6 == client); - - _LOGD ("client event %d", event); - - 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); - 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); - break; - case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE: - case SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST: - bound6_handle (self); - break; - default: - _LOGW ("unhandled event %d", event); - break; - } + NMDhcpSystemd * self = NM_DHCP_SYSTEMD(user_data); + NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self); + + nm_assert(priv->client6 == client); + + _LOGD("client event %d", event); + + 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); + 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); + break; + case SD_DHCP6_CLIENT_EVENT_IP_ACQUIRE: + case SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST: + bound6_handle(self); + break; + default: + _LOGW("unhandled event %d", event); + break; + } } static gboolean -ip6_start (NMDhcpClient *client, - const char *dhcp_anycast_addr, - const struct in6_addr *ll_addr, - NMSettingIP6ConfigPrivacy privacy, - guint needed_prefixes, - GError **error) +ip6_start(NMDhcpClient * client, + const char * dhcp_anycast_addr, + const struct in6_addr * ll_addr, + NMSettingIP6ConfigPrivacy privacy, + guint needed_prefixes, + 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 char *hostname; - const char *mud_url; - int r, i; - const guint8 *duid_arr; - gsize duid_len; - GBytes *duid; - - g_return_val_if_fail (!priv->client4, FALSE); - g_return_val_if_fail (!priv->client6, FALSE); - - if ( !(duid = nm_dhcp_client_get_client_id (client)) - || !(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); - } - - r = sd_dhcp6_client_new (&sd_client); - if (r < 0) { - nm_utils_error_set_errno (error, r, "failed to create dhcp-client: %s"); - return FALSE; - } - - _LOGT ("dhcp-client6: set %p", sd_client); - - if (nm_dhcp_client_get_info_only (client)) - sd_dhcp6_client_set_information_request (sd_client, 1); - - r = sd_dhcp6_client_set_iaid (sd_client, - nm_dhcp_client_get_iaid (client)); - if (r < 0) { - nm_utils_error_set_errno (error, r, "failed to set IAID: %s"); - return FALSE; - } - - r = sd_dhcp6_client_set_duid (sd_client, - unaligned_read_be16 (&duid_arr[0]), - &duid_arr[2], - duid_len - 2); - if (r < 0) { - nm_utils_error_set_errno (error, r, "failed to set DUID: %s"); - return FALSE; - } - - r = sd_dhcp6_client_attach_event (sd_client, NULL, 0); - if (r < 0) { - nm_utils_error_set_errno (error, r, "failed to attach event: %s"); - return FALSE; - } - - r = sd_dhcp6_client_set_ifindex (sd_client, - nm_dhcp_client_get_ifindex (client)); - if (r < 0) { - nm_utils_error_set_errno (error, r, "failed to set ifindex: %s"); - return FALSE; - } - - /* Add requested options */ - for (i = 0; _nm_dhcp_option_dhcp6_options[i].name; i++) { - if (_nm_dhcp_option_dhcp6_options[i].include) { - r = sd_dhcp6_client_set_request_option (sd_client, _nm_dhcp_option_dhcp6_options[i].option_num); - nm_assert (r >= 0 || r == -EEXIST); - } - } - - mud_url = nm_dhcp_client_get_mud_url (client); - if (mud_url) { - r = sd_dhcp6_client_set_request_mud_url (sd_client, mud_url); - if (r < 0) { - nm_utils_error_set_errno (error, r, "failed to set mud-url: %s"); - return FALSE; - } - } - - if (needed_prefixes > 0) { - if (needed_prefixes > 1) - _LOGW ("dhcp-client6: only one prefix request is supported"); - /* FIXME: systemd-networkd API only allows to request a - * single prefix */ - r = sd_dhcp6_client_set_prefix_delegation (sd_client, TRUE); - if (r < 0) { - nm_utils_error_set_errno (error, r, "failed to enable prefix delegation: %s"); - return FALSE; - } - } - - r = sd_dhcp6_client_set_local_address (sd_client, 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); - 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"); - return FALSE; - } - - r = sd_dhcp6_client_set_callback (sd_client, dhcp6_event_cb, client); - if (r < 0) { - nm_utils_error_set_errno (error, r, "failed to set callback: %s"); - return FALSE; - } - - priv->client6 = g_steal_pointer (&sd_client); - - r = sd_dhcp6_client_start (priv->client6); - if (r < 0) { - sd_dhcp6_client_set_callback (priv->client6, NULL, NULL); - nm_clear_pointer (&priv->client6, sd_dhcp6_client_unref); - nm_utils_error_set_errno (error, r, "failed to start client: %s"); - return FALSE; - } - - nm_dhcp_client_start_timeout (client); - return TRUE; + 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 char * hostname; + const char * mud_url; + int r, i; + const guint8 * duid_arr; + gsize duid_len; + GBytes * duid; + + g_return_val_if_fail(!priv->client4, FALSE); + g_return_val_if_fail(!priv->client6, FALSE); + + if (!(duid = nm_dhcp_client_get_client_id(client)) + || !(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); + } + + r = sd_dhcp6_client_new(&sd_client); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to create dhcp-client: %s"); + return FALSE; + } + + _LOGT("dhcp-client6: set %p", sd_client); + + if (nm_dhcp_client_get_info_only(client)) + sd_dhcp6_client_set_information_request(sd_client, 1); + + r = sd_dhcp6_client_set_iaid(sd_client, nm_dhcp_client_get_iaid(client)); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to set IAID: %s"); + return FALSE; + } + + r = sd_dhcp6_client_set_duid(sd_client, + unaligned_read_be16(&duid_arr[0]), + &duid_arr[2], + duid_len - 2); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to set DUID: %s"); + return FALSE; + } + + r = sd_dhcp6_client_attach_event(sd_client, NULL, 0); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to attach event: %s"); + return FALSE; + } + + r = sd_dhcp6_client_set_ifindex(sd_client, nm_dhcp_client_get_ifindex(client)); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to set ifindex: %s"); + return FALSE; + } + + /* Add requested options */ + for (i = 0; _nm_dhcp_option_dhcp6_options[i].name; i++) { + if (_nm_dhcp_option_dhcp6_options[i].include) { + r = sd_dhcp6_client_set_request_option(sd_client, + _nm_dhcp_option_dhcp6_options[i].option_num); + nm_assert(r >= 0 || r == -EEXIST); + } + } + + mud_url = nm_dhcp_client_get_mud_url(client); + if (mud_url) { + r = sd_dhcp6_client_set_request_mud_url(sd_client, mud_url); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to set mud-url: %s"); + return FALSE; + } + } + + if (needed_prefixes > 0) { + if (needed_prefixes > 1) + _LOGW("dhcp-client6: only one prefix request is supported"); + /* FIXME: systemd-networkd API only allows to request a + * single prefix */ + r = sd_dhcp6_client_set_prefix_delegation(sd_client, TRUE); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to enable prefix delegation: %s"); + return FALSE; + } + } + + r = sd_dhcp6_client_set_local_address(sd_client, 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); + 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"); + return FALSE; + } + + r = sd_dhcp6_client_set_callback(sd_client, dhcp6_event_cb, client); + if (r < 0) { + nm_utils_error_set_errno(error, r, "failed to set callback: %s"); + return FALSE; + } + + priv->client6 = g_steal_pointer(&sd_client); + + r = sd_dhcp6_client_start(priv->client6); + if (r < 0) { + sd_dhcp6_client_set_callback(priv->client6, NULL, NULL); + nm_clear_pointer(&priv->client6, sd_dhcp6_client_unref); + nm_utils_error_set_errno(error, r, "failed to start client: %s"); + return FALSE; + } + + nm_dhcp_client_start_timeout(client); + return TRUE; } static void -stop (NMDhcpClient *client, gboolean release) +stop(NMDhcpClient *client, gboolean release) { - NMDhcpSystemd *self = NM_DHCP_SYSTEMD (client); - NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (self); - int r = 0; - - NM_DHCP_CLIENT_CLASS (nm_dhcp_systemd_parent_class)->stop (client, release); - - _LOGT ("dhcp-client%d: stop %p", - priv->client4 ? '4' : '6', - priv->client4 ? (gpointer) priv->client4 : (gpointer) priv->client6); - - if (priv->client4) { - sd_dhcp_client_set_callback (priv->client4, NULL, NULL); - r = sd_dhcp_client_stop (priv->client4); - } else if (priv->client6) { - sd_dhcp6_client_set_callback (priv->client6, NULL, NULL); - r = sd_dhcp6_client_stop (priv->client6); - } - - if (r) - _LOGW ("failed to stop client (%d)", r); + NMDhcpSystemd * self = NM_DHCP_SYSTEMD(client); + NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(self); + int r = 0; + + NM_DHCP_CLIENT_CLASS(nm_dhcp_systemd_parent_class)->stop(client, release); + + _LOGT("dhcp-client%d: stop %p", + priv->client4 ? '4' : '6', + priv->client4 ? (gpointer) priv->client4 : (gpointer) priv->client6); + + if (priv->client4) { + sd_dhcp_client_set_callback(priv->client4, NULL, NULL); + r = sd_dhcp_client_stop(priv->client4); + } else if (priv->client6) { + sd_dhcp6_client_set_callback(priv->client6, NULL, NULL); + r = sd_dhcp6_client_stop(priv->client6); + } + + if (r) + _LOGW("failed to stop client (%d)", r); } /*****************************************************************************/ static void -nm_dhcp_systemd_init (NMDhcpSystemd *self) -{ -} +nm_dhcp_systemd_init(NMDhcpSystemd *self) +{} static void -dispose (GObject *object) +dispose(GObject *object) { - NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (object); + NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE(object); - nm_clear_g_free (&priv->lease_file); + nm_clear_g_free(&priv->lease_file); - if (priv->client4) { - sd_dhcp_client_stop (priv->client4); - sd_dhcp_client_unref (priv->client4); - priv->client4 = NULL; - } + if (priv->client4) { + sd_dhcp_client_stop(priv->client4); + sd_dhcp_client_unref(priv->client4); + priv->client4 = NULL; + } - if (priv->client6) { - sd_dhcp6_client_stop (priv->client6); - sd_dhcp6_client_unref (priv->client6); - priv->client6 = NULL; - } + if (priv->client6) { + sd_dhcp6_client_stop(priv->client6); + sd_dhcp6_client_unref(priv->client6); + priv->client6 = NULL; + } - G_OBJECT_CLASS (nm_dhcp_systemd_parent_class)->dispose (object); + G_OBJECT_CLASS(nm_dhcp_systemd_parent_class)->dispose(object); } static void -nm_dhcp_systemd_class_init (NMDhcpSystemdClass *sdhcp_class) +nm_dhcp_systemd_class_init(NMDhcpSystemdClass *sdhcp_class) { - NMDhcpClientClass *client_class = NM_DHCP_CLIENT_CLASS (sdhcp_class); - GObjectClass *object_class = G_OBJECT_CLASS (sdhcp_class); + NMDhcpClientClass *client_class = NM_DHCP_CLIENT_CLASS(sdhcp_class); + GObjectClass * object_class = G_OBJECT_CLASS(sdhcp_class); - object_class->dispose = dispose; + object_class->dispose = dispose; - client_class->ip4_start = ip4_start; - client_class->ip6_start = ip6_start; - client_class->stop = stop; + client_class->ip4_start = ip4_start; + client_class->ip6_start = ip6_start; + client_class->stop = stop; } const NMDhcpClientFactory _nm_dhcp_client_factory_systemd = { - .name = "systemd", - .get_type = nm_dhcp_systemd_get_type, - .experimental = TRUE, + .name = "systemd", + .get_type = nm_dhcp_systemd_get_type, + .experimental = TRUE, }; /*****************************************************************************/ static GType -_get_type_per_addr_family (int addr_family) +_get_type_per_addr_family(int addr_family) { - nm_assert_addr_family (addr_family); + nm_assert_addr_family(addr_family); - if (addr_family == AF_INET) - return nm_dhcp_nettools_get_type (); - return nm_dhcp_systemd_get_type (); + if (addr_family == AF_INET) + return nm_dhcp_nettools_get_type(); + return nm_dhcp_systemd_get_type(); } const NMDhcpClientFactory _nm_dhcp_client_factory_internal = { - .name = "internal", - .get_type_per_addr_family = _get_type_per_addr_family, + .name = "internal", + .get_type_per_addr_family = _get_type_per_addr_family, }; diff --git a/src/dhcp/nm-dhcp-utils.c b/src/dhcp/nm-dhcp-utils.c index 1c305238..bf10e2b5 100644 --- a/src/dhcp/nm-dhcp-utils.c +++ b/src/dhcp/nm-dhcp-utils.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2005 - 2010 Red Hat, Inc. */ @@ -21,690 +21,702 @@ /*****************************************************************************/ 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, + guint32 route_table, + guint32 route_metric, + NMIP4Config *ip4_config, + guint32 * gwaddr) { - char **routes, **r; - gboolean have_routes = FALSE; - - routes = g_strsplit (str, " ", 0); - if (g_strv_length (routes) == 0) - goto out; - - if ((g_strv_length (routes) % 2) != 0) { - _LOG2W (LOGD_DHCP4, iface, " classless static routes provided, but invalid"); - goto out; - } - - for (r = routes; *r; r += 2) { - char *slash; - NMPlatformIP4Route route; - int rt_cidr = 32; - guint32 rt_addr, rt_route; - - slash = strchr(*r, '/'); - if (slash) { - *slash = '\0'; - errno = 0; - rt_cidr = strtol (slash + 1, NULL, 10); - if (errno || rt_cidr > 32) { - _LOG2W (LOGD_DHCP4, iface, "DHCP provided invalid classless static route cidr: '%s'", slash + 1); - continue; - } - } - if (inet_pton (AF_INET, *r, &rt_addr) <= 0) { - _LOG2W (LOGD_DHCP4, iface, "DHCP provided invalid classless static route address: '%s'", *r); - continue; - } - if (inet_pton (AF_INET, *(r + 1), &rt_route) <= 0) { - _LOG2W (LOGD_DHCP4, iface, "DHCP provided invalid classless static route gateway: '%s'", *(r + 1)); - continue; - } - - have_routes = TRUE; - if (rt_cidr == 0 && rt_addr == 0) { - /* FIXME: how to handle multiple routers? */ - *gwaddr = rt_route; - } else { - _LOG2I (LOGD_DHCP4, iface, " classless static route %s/%d gw %s", *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); - } - } - -out: - g_strfreev (routes); - return have_routes; + gs_free const char **routes = NULL; + const char ** r; + gboolean have_routes = FALSE; + + routes = nm_utils_strsplit_set(str, " "); + if (!routes) + return FALSE; + + if ((NM_PTRARRAY_LEN(routes) % 2) != 0) { + _LOG2W(LOGD_DHCP4, iface, " classless static routes provided, but invalid"); + return FALSE; + } + + for (r = routes; *r; r += 2) { + char * slash; + NMPlatformIP4Route route; + int rt_cidr = 32; + guint32 rt_addr, rt_route; + + slash = strchr(*r, '/'); + if (slash) { + *slash = '\0'; + errno = 0; + rt_cidr = strtol(slash + 1, NULL, 10); + if (errno || rt_cidr > 32) { + _LOG2W(LOGD_DHCP4, + iface, + "DHCP provided invalid classless static route cidr: '%s'", + slash + 1); + continue; + } + } + if (inet_pton(AF_INET, *r, &rt_addr) <= 0) { + _LOG2W(LOGD_DHCP4, + iface, + "DHCP provided invalid classless static route address: '%s'", + *r); + continue; + } + if (inet_pton(AF_INET, *(r + 1), &rt_route) <= 0) { + _LOG2W(LOGD_DHCP4, + iface, + "DHCP provided invalid classless static route gateway: '%s'", + *(r + 1)); + continue; + } + + have_routes = TRUE; + if (rt_cidr == 0 && rt_addr == 0) { + /* FIXME: how to handle multiple routers? */ + *gwaddr = rt_route; + } else { + _LOG2I(LOGD_DHCP4, + iface, + " classless static route %s/%d gw %s", + *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); + } + } + + return have_routes; } static gboolean -process_dhclient_rfc3442_route (const char *const**p_octets, - NMPlatformIP4Route *route) +process_dhclient_rfc3442_route(const char *const **p_octets, NMPlatformIP4Route *route) { - const char *const*o = *p_octets; - gs_free char *next_hop = NULL; - int addr_len; - int v_plen; - in_addr_t tmp_addr; - in_addr_t v_network = 0; - - v_plen = _nm_utils_ascii_str_to_int64 (*o, 10, 0, 32, -1); - if (v_plen == -1) - return FALSE; - o++; - - addr_len = v_plen > 0 - ? ((v_plen - 1) / 8) + 1 - : 0; - - /* ensure there's at least the address + next hop left */ - if (NM_PTRARRAY_LEN (o) < addr_len + 4) - return FALSE; - - if (v_plen > 0) { - const char *addr[4] = { "0", "0", "0", "0" }; - gs_free char *str_addr = NULL; - int i; - - for (i = 0; i < addr_len; i++) - addr[i] = *o++; - - str_addr = g_strjoin (".", addr[0], addr[1], addr[2], addr[3], NULL); - if (inet_pton (AF_INET, str_addr, &tmp_addr) <= 0) - return FALSE; - v_network = nm_utils_ip4_address_clear_host_address (tmp_addr, v_plen); - } - - next_hop = g_strjoin (".", o[0], o[1], o[2], o[3], NULL); - o += 4; - if (inet_pton (AF_INET, next_hop, &tmp_addr) <= 0) - return FALSE; - - *route = (NMPlatformIP4Route) { - .network = v_network, - .plen = v_plen, - .gateway = tmp_addr, - }; - *p_octets = o; - return TRUE; + const char *const *o = *p_octets; + gs_free char * next_hop = NULL; + int addr_len; + int v_plen; + in_addr_t tmp_addr; + in_addr_t v_network = 0; + + v_plen = _nm_utils_ascii_str_to_int64(*o, 10, 0, 32, -1); + if (v_plen == -1) + return FALSE; + o++; + + addr_len = v_plen > 0 ? ((v_plen - 1) / 8) + 1 : 0; + + /* ensure there's at least the address + next hop left */ + if (NM_PTRARRAY_LEN(o) < addr_len + 4) + return FALSE; + + if (v_plen > 0) { + const char * addr[4] = {"0", "0", "0", "0"}; + gs_free char *str_addr = NULL; + int i; + + for (i = 0; i < addr_len; i++) + addr[i] = *o++; + + str_addr = g_strjoin(".", addr[0], addr[1], addr[2], addr[3], NULL); + if (inet_pton(AF_INET, str_addr, &tmp_addr) <= 0) + return FALSE; + v_network = nm_utils_ip4_address_clear_host_address(tmp_addr, v_plen); + } + + next_hop = g_strjoin(".", o[0], o[1], o[2], o[3], NULL); + o += 4; + if (inet_pton(AF_INET, next_hop, &tmp_addr) <= 0) + return FALSE; + + *route = (NMPlatformIP4Route){ + .network = v_network, + .plen = v_plen, + .gateway = tmp_addr, + }; + *p_octets = o; + return TRUE; } 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, + guint32 route_table, + guint32 route_metric, + NMIP4Config *ip4_config, + guint32 * gwaddr) { - gs_free const char **octets = NULL; - const char *const*o; - gboolean have_routes = FALSE; - - octets = nm_utils_strsplit_set_with_empty (str, " ."); - if (NM_PTRARRAY_LEN (octets) < 5) { - _LOG2W (LOGD_DHCP4, iface, "ignoring invalid classless static routes '%s'", str); - return FALSE; - } - - o = octets; - while (*o) { - NMPlatformIP4Route route; - - if (!process_dhclient_rfc3442_route (&o, &route)) { - _LOG2W (LOGD_DHCP4, iface, "ignoring invalid classless static routes"); - return have_routes; - } - - have_routes = TRUE; - if (!route.plen) { - /* gateway passed as classless static route */ - *gwaddr = route.gateway; - } else { - char b1[INET_ADDRSTRLEN]; - char b2[INET_ADDRSTRLEN]; - - /* 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); - - _LOG2I (LOGD_DHCP4, iface, " classless static route %s/%d gw %s", - _nm_utils_inet4_ntop (route.network, b1), - route.plen, - _nm_utils_inet4_ntop (route.gateway, b2)); - } - } - - return have_routes; + gs_free const char **octets = NULL; + const char *const * o; + gboolean have_routes = FALSE; + + octets = nm_utils_strsplit_set_with_empty(str, " ."); + if (NM_PTRARRAY_LEN(octets) < 5) { + _LOG2W(LOGD_DHCP4, iface, "ignoring invalid classless static routes '%s'", str); + return FALSE; + } + + o = octets; + while (*o) { + NMPlatformIP4Route route; + + if (!process_dhclient_rfc3442_route(&o, &route)) { + _LOG2W(LOGD_DHCP4, iface, "ignoring invalid classless static routes"); + return have_routes; + } + + have_routes = TRUE; + if (!route.plen) { + /* gateway passed as classless static route */ + *gwaddr = route.gateway; + } else { + char b1[INET_ADDRSTRLEN]; + char b2[INET_ADDRSTRLEN]; + + /* 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); + + _LOG2I(LOGD_DHCP4, + iface, + " classless static route %s/%d gw %s", + _nm_utils_inet4_ntop(route.network, b1), + route.plen, + _nm_utils_inet4_ntop(route.gateway, b2)); + } + } + + return have_routes; } 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, + guint32 route_table, + guint32 route_metric, + NMIP4Config *ip4_config, + guint32 * gwaddr) { - const char *str, *p; - - g_return_val_if_fail (options != NULL, FALSE); - g_return_val_if_fail (ip4_config != NULL, FALSE); - - *gwaddr = 0; - - /* dhcpd/dhclient in Fedora has support for rfc3442 implemented using a - * slightly different format: - * - * option classless-static-routes = array of (destination-descriptor ip-address); - * - * which results in: - * - * 0 192.168.0.113 25.129.210.177.132 192.168.0.113 7.2 10.34.255.6 - * - * dhcpcd supports classless static routes natively and uses this same - * option identifier with the following format: - * - * 192.168.10.0/24 192.168.1.1 10.0.0.0/8 10.17.66.41 - */ - str = g_hash_table_lookup (options, "classless_static_routes"); - - /* dhclient doesn't have actual support for rfc3442 classless static routes - * upstream. Thus, people resort to defining the option in dhclient.conf - * and using arbitrary formats like so: - * - * option rfc3442-classless-static-routes code 121 = array of unsigned integer 8; - * - * See https://lists.isc.org/pipermail/dhcp-users/2008-December/007629.html - */ - if (!str) - str = g_hash_table_lookup (options, "rfc3442_classless_static_routes"); - - /* Microsoft version; same as rfc3442 but with a different option # (249) */ - if (!str) - str = g_hash_table_lookup (options, "ms_classless_static_routes"); - - if (!str || !strlen (str)) - return FALSE; - - p = str; - while (*p) { - if (!g_ascii_isdigit (*p) && (*p != ' ') && (*p != '.') && (*p != '/')) { - _LOG2W (LOGD_DHCP4, iface, "ignoring invalid classless static routes '%s'", str); - return FALSE; - } - p++; - }; - - if (strchr (str, '/')) { - /* dhcpcd format */ - return ip4_process_dhcpcd_rfc3442_routes (iface, str, route_table, route_metric, ip4_config, gwaddr); - } - - return ip4_process_dhclient_rfc3442_routes (iface, str, route_table, route_metric, ip4_config, gwaddr); + const char *str, *p; + + g_return_val_if_fail(options != NULL, FALSE); + g_return_val_if_fail(ip4_config != NULL, FALSE); + + *gwaddr = 0; + + /* dhcpd/dhclient in Fedora has support for rfc3442 implemented using a + * slightly different format: + * + * option classless-static-routes = array of (destination-descriptor ip-address); + * + * which results in: + * + * 0 192.168.0.113 25.129.210.177.132 192.168.0.113 7.2 10.34.255.6 + * + * dhcpcd supports classless static routes natively and uses this same + * option identifier with the following format: + * + * 192.168.10.0/24 192.168.1.1 10.0.0.0/8 10.17.66.41 + */ + str = g_hash_table_lookup(options, "classless_static_routes"); + + /* dhclient doesn't have actual support for rfc3442 classless static routes + * upstream. Thus, people resort to defining the option in dhclient.conf + * and using arbitrary formats like so: + * + * option rfc3442-classless-static-routes code 121 = array of unsigned integer 8; + * + * See https://lists.isc.org/pipermail/dhcp-users/2008-December/007629.html + */ + if (!str) + str = g_hash_table_lookup(options, "rfc3442_classless_static_routes"); + + /* Microsoft version; same as rfc3442 but with a different option # (249) */ + if (!str) + str = g_hash_table_lookup(options, "ms_classless_static_routes"); + + if (!str || !strlen(str)) + return FALSE; + + p = str; + while (*p) { + if (!g_ascii_isdigit(*p) && (*p != ' ') && (*p != '.') && (*p != '/')) { + _LOG2W(LOGD_DHCP4, iface, "ignoring invalid classless static routes '%s'", str); + return FALSE; + } + p++; + }; + + if (strchr(str, '/')) { + /* dhcpcd format */ + return ip4_process_dhcpcd_rfc3442_routes(iface, + str, + route_table, + route_metric, + ip4_config, + gwaddr); + } + + return ip4_process_dhclient_rfc3442_routes(iface, + str, + route_table, + route_metric, + ip4_config, + 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, + guint32 route_table, + guint32 route_metric, + NMIP4Config *ip4_config) { - const char *str; - char **searches, **s; - - str = g_hash_table_lookup (options, "static_routes"); - if (!str) - return; - - searches = g_strsplit (str, " ", 0); - if ((g_strv_length (searches) % 2)) { - _LOG2I (LOGD_DHCP, iface, " static routes provided, but invalid"); - goto out; - } - - for (s = searches; *s; s += 2) { - NMPlatformIP4Route route; - guint32 rt_addr, rt_route; - - if (inet_pton (AF_INET, *s, &rt_addr) <= 0) { - _LOG2W (LOGD_DHCP, iface, "DHCP provided invalid static route address: '%s'", *s); - continue; - } - if (inet_pton (AF_INET, *(s + 1), &rt_route) <= 0) { - _LOG2W (LOGD_DHCP, iface, "DHCP provided invalid static route gateway: '%s'", *(s + 1)); - continue; - } - - // FIXME: ensure the IP address and route are sane - - memset (&route, 0, sizeof (route)); - route.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 - whatever network number is specified in each route entry */ - route.plen = _nm_utils_ip4_get_default_prefix (rt_addr); - if (rt_addr & ~_nm_utils_ip4_prefix_to_netmask (route.plen)) { - /* RFC 943: target not "this network"; using host routing */ - route.plen = 32; - } - 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.network = nm_utils_ip4_address_clear_host_address (route.network, route.plen); - - nm_ip4_config_add_route (ip4_config, &route, NULL); - _LOG2I (LOGD_DHCP, iface, " static route %s", - nm_platform_ip4_route_to_string (&route, NULL, 0)); - } - -out: - g_strfreev (searches); + gs_free const char **searches = NULL; + const char ** s; + const char * str; + + str = g_hash_table_lookup(options, "static_routes"); + if (!str) + return; + + searches = nm_utils_strsplit_set(str, " "); + if (!searches) + return; + + if ((NM_PTRARRAY_LEN(searches) % 2) != 0) { + _LOG2I(LOGD_DHCP, iface, " static routes provided, but invalid"); + return; + } + + for (s = searches; *s; s += 2) { + NMPlatformIP4Route route; + guint32 rt_addr, rt_route; + + if (inet_pton(AF_INET, *s, &rt_addr) <= 0) { + _LOG2W(LOGD_DHCP, iface, "DHCP provided invalid static route address: '%s'", *s); + continue; + } + if (inet_pton(AF_INET, *(s + 1), &rt_route) <= 0) { + _LOG2W(LOGD_DHCP, iface, "DHCP provided invalid static route gateway: '%s'", *(s + 1)); + continue; + } + + // FIXME: ensure the IP address and route are sane + + memset(&route, 0, sizeof(route)); + route.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 + * whatever network number is specified in each route entry */ + route.plen = _nm_utils_ip4_get_default_prefix(rt_addr); + if (rt_addr & ~_nm_utils_ip4_prefix_to_netmask(route.plen)) { + /* RFC 943: target not "this network"; using host routing */ + route.plen = 32; + } + 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.network = nm_utils_ip4_address_clear_host_address(route.network, route.plen); + + nm_ip4_config_add_route(ip4_config, &route, NULL); + _LOG2I(LOGD_DHCP, + iface, + " static route %s", + nm_platform_ip4_route_to_string(&route, NULL, 0)); + } } static void -process_domain_search (const char *iface, - const char *str, - GFunc add_func, - gpointer user_data) +process_domain_search(const char *iface, const char *str, GFunc add_func, gpointer user_data) { - char **searches, **s; - char *unescaped, *p; - int i; - - g_return_if_fail (str != NULL); - g_return_if_fail (add_func != NULL); - - p = unescaped = g_strdup (str); - do { - p = strstr (p, "\\032"); - if (!p) - break; - - /* Clear the escaped space with real spaces */ - for (i = 0; i < 4; i++) - *p++ = ' '; - } while (*p++); - - if (strchr (unescaped, '\\')) { - _LOG2W (LOGD_DHCP, iface, " invalid domain search: '%s'", unescaped); - goto out; - } - - searches = g_strsplit (unescaped, " ", 0); - for (s = searches; *s; s++) { - if (strlen (*s)) { - _LOG2I (LOGD_DHCP, iface, " domain search '%s'", *s); - add_func (*s, user_data); - } - } - g_strfreev (searches); - -out: - g_free (unescaped); + gs_free const char **searches = NULL; + gs_free char * unescaped = NULL; + const char ** s; + char * p; + int i; + + g_return_if_fail(str != NULL); + g_return_if_fail(add_func != NULL); + + unescaped = g_strdup(str); + + p = unescaped; + do { + p = strstr(p, "\\032"); + if (!p) + break; + + /* Clear the escaped space with real spaces */ + for (i = 0; i < 4; i++) + *p++ = ' '; + } while (*p++); + + if (strchr(unescaped, '\\')) { + _LOG2W(LOGD_DHCP, iface, " invalid domain search: '%s'", unescaped); + return; + } + + searches = nm_utils_strsplit_set(unescaped, " "); + for (s = searches; searches && *s; s++) { + _LOG2I(LOGD_DHCP, iface, " domain search '%s'", *s); + add_func((gpointer) *s, user_data); + } } static void -ip4_add_domain_search (gpointer data, gpointer user_data) +ip4_add_domain_search(gpointer data, gpointer user_data) { - nm_ip4_config_add_search (NM_IP4_CONFIG (user_data), (const char *) data); + nm_ip4_config_add_search(NM_IP4_CONFIG(user_data), (const char *) data); } NMIP4Config * -nm_dhcp_utils_ip4_config_from_options (NMDedupMultiIndex *multi_idx, - int ifindex, - const char *iface, - GHashTable *options, - guint32 route_table, - guint32 route_metric) +nm_dhcp_utils_ip4_config_from_options(NMDedupMultiIndex *multi_idx, + int ifindex, + const char * iface, + GHashTable * options, + guint32 route_table, + guint32 route_metric) { - 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]; - - 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 (); - - 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 - goto error; - - 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); - _LOG2I (LOGD_DHCP4, iface, " plen %d (%s)", plen, str); - } else { - /* Get default netmask for the IP according to appropriate class. */ - plen = _nm_utils_ip4_get_default_prefix (addr); - _LOG2I (LOGD_DHCP4, iface, " plen %d (default)", plen); - } - nm_platform_ip4_address_set_addr (&address, addr, plen); - - /* 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 (gateway) { - _LOG2I (LOGD_DHCP4, iface, " gateway %s", _nm_utils_inet4_ntop (gateway, sbuf)); - gateway_has = TRUE; - } else { - /* If the gateway wasn't provided as a classless static route with a - * subnet length of 0, try to find it using the old-style 'routers' option. - */ - str = g_hash_table_lookup (options, "routers"); - if (str) { - char **routers = g_strsplit (str, " ", 0); - char **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); - gateway_has = TRUE; - break; - } else - _LOG2W (LOGD_DHCP4, iface, "ignoring invalid gateway '%s'", *s); - } - g_strfreev (routers); - } - } - - if (gateway_has) { - const NMPlatformIP4Route r = { - .rt_source = NM_IP_CONFIG_SOURCE_DHCP, - .gateway = gateway, - .table_coerced = nm_platform_route_table_coerce (route_table), - .metric = route_metric, - }; - - nm_ip4_config_add_route (ip4_config, &r, NULL); - } - - str = g_hash_table_lookup (options, "dhcp_lease_time"); - if (str) { - address.lifetime = address.preferred = strtoul (str, NULL, 10); - _LOG2I (LOGD_DHCP4, iface, " lease time %u", address.lifetime); - } - - address.addr_source = NM_IP_CONFIG_SOURCE_DHCP; - nm_ip4_config_add_address (ip4_config, &address); - - str = g_hash_table_lookup (options, "host_name"); - if (str) - _LOG2I (LOGD_DHCP4, iface, " hostname '%s'", str); - - str = g_hash_table_lookup (options, "domain_name_servers"); - if (str) { - char **dns = g_strsplit (str, " ", 0); - char **s; - - for (s = dns; *s; s++) { - if (inet_pton (AF_INET, *s, &tmp_addr) > 0) { - if (tmp_addr) { - nm_ip4_config_add_nameserver (ip4_config, tmp_addr); - _LOG2I (LOGD_DHCP4, iface, " nameserver '%s'", *s); - } - } else - _LOG2W (LOGD_DHCP4, iface, "ignoring invalid nameserver '%s'", *s); - } - g_strfreev (dns); - } - - str = g_hash_table_lookup (options, "domain_name"); - if (str) { - char **domains = g_strsplit (str, " ", 0); - char **s; - - for (s = domains; *s; s++) { - _LOG2I (LOGD_DHCP4, iface, " domain name '%s'", *s); - nm_ip4_config_add_domain (ip4_config, *s); - } - g_strfreev (domains); - } - - str = g_hash_table_lookup (options, "domain_search"); - if (str) - process_domain_search (iface, str, ip4_add_domain_search, ip4_config); - - str = g_hash_table_lookup (options, "netbios_name_servers"); - if (str) { - char **nbns = g_strsplit (str, " ", 0); - char **s; - - for (s = nbns; *s; s++) { - if (inet_pton (AF_INET, *s, &tmp_addr) > 0) { - if (tmp_addr) { - nm_ip4_config_add_wins (ip4_config, tmp_addr); - _LOG2I (LOGD_DHCP4, iface, " wins '%s'", *s); - } - } else - _LOG2W (LOGD_DHCP4, iface, "ignoring invalid WINS server '%s'", *s); - } - g_strfreev (nbns); - } - - str = g_hash_table_lookup (options, "interface_mtu"); - if (str) { - int int_mtu; - - errno = 0; - int_mtu = strtol (str, NULL, 10); - if (NM_IN_SET (errno, EINVAL, ERANGE)) - goto error; - - if (int_mtu > 576) - nm_ip4_config_set_mtu (ip4_config, int_mtu, NM_IP_CONFIG_SOURCE_DHCP); - } - - 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); - } - - str = g_hash_table_lookup (options, "nis_servers"); - if (str) { - char **nis = g_strsplit (str, " ", 0); - char **s; - - for (s = 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); - _LOG2I (LOGD_DHCP4, iface, " nis '%s'", *s); - } - } else - _LOG2W (LOGD_DHCP4, iface, "ignoring invalid NIS server '%s'", *s); - } - g_strfreev (nis); - } - - str = g_hash_table_lookup (options, "vendor_encapsulated_options"); - nm_ip4_config_set_metered (ip4_config, str && strstr (str, "ANDROID_METERED")); - - return ip4_config; - -error: - g_object_unref (ip4_config); - return NULL; + 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]; + + 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(); + + 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 + return NULL; + + 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); + _LOG2I(LOGD_DHCP4, iface, " plen %d (%s)", plen, str); + } else { + /* Get default netmask for the IP according to appropriate class. */ + plen = _nm_utils_ip4_get_default_prefix(addr); + _LOG2I(LOGD_DHCP4, iface, " plen %d (default)", plen); + } + nm_platform_ip4_address_set_addr(&address, addr, plen); + + /* 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 (gateway) { + _LOG2I(LOGD_DHCP4, iface, " gateway %s", _nm_utils_inet4_ntop(gateway, sbuf)); + gateway_has = TRUE; + } else { + /* If the gateway wasn't provided as a classless static route with a + * subnet length of 0, try to find it using the old-style 'routers' option. + */ + str = g_hash_table_lookup(options, "routers"); + if (str) { + gs_free const char **routers = nm_utils_strsplit_set(str, " "); + const char ** s; + + for (s = routers; routers && *s; s++) { + /* FIXME: how to handle multiple routers? */ + if (inet_pton(AF_INET, *s, &gateway) > 0) { + _LOG2I(LOGD_DHCP4, iface, " gateway %s", *s); + gateway_has = TRUE; + break; + } else + _LOG2W(LOGD_DHCP4, iface, "ignoring invalid gateway '%s'", *s); + } + } + } + + if (gateway_has) { + const NMPlatformIP4Route r = { + .rt_source = NM_IP_CONFIG_SOURCE_DHCP, + .gateway = gateway, + .table_coerced = nm_platform_route_table_coerce(route_table), + .metric = route_metric, + }; + + nm_ip4_config_add_route(ip4_config, &r, NULL); + } + + str = g_hash_table_lookup(options, "dhcp_lease_time"); + if (str) { + address.lifetime = address.preferred = strtoul(str, NULL, 10); + _LOG2I(LOGD_DHCP4, iface, " lease time %u", address.lifetime); + } + + address.addr_source = NM_IP_CONFIG_SOURCE_DHCP; + nm_ip4_config_add_address(ip4_config, &address); + + str = g_hash_table_lookup(options, "host_name"); + if (str) + _LOG2I(LOGD_DHCP4, iface, " hostname '%s'", str); + + str = g_hash_table_lookup(options, "domain_name_servers"); + if (str) { + gs_free const char **dns = nm_utils_strsplit_set(str, " "); + const char ** s; + + 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); + _LOG2I(LOGD_DHCP4, iface, " nameserver '%s'", *s); + } + } else + _LOG2W(LOGD_DHCP4, iface, "ignoring invalid nameserver '%s'", *s); + } + } + + str = g_hash_table_lookup(options, "domain_name"); + if (str) { + gs_free const char **domains = nm_utils_strsplit_set(str, " "); + const char ** s; + + for (s = domains; domains && *s; s++) { + _LOG2I(LOGD_DHCP4, iface, " domain name '%s'", *s); + nm_ip4_config_add_domain(ip4_config, *s); + } + } + + str = g_hash_table_lookup(options, "domain_search"); + if (str) + process_domain_search(iface, str, ip4_add_domain_search, ip4_config); + + str = g_hash_table_lookup(options, "netbios_name_servers"); + if (str) { + gs_free const char **nbns = nm_utils_strsplit_set(str, " "); + const char ** s; + + 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); + _LOG2I(LOGD_DHCP4, iface, " wins '%s'", *s); + } + } else + _LOG2W(LOGD_DHCP4, iface, "ignoring invalid WINS server '%s'", *s); + } + } + + str = g_hash_table_lookup(options, "interface_mtu"); + if (str) { + int int_mtu; + + errno = 0; + int_mtu = strtol(str, NULL, 10); + if (NM_IN_SET(errno, EINVAL, ERANGE)) + return NULL; + + if (int_mtu > 576) + nm_ip4_config_set_mtu(ip4_config, int_mtu, NM_IP_CONFIG_SOURCE_DHCP); + } + + 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); + } + + str = g_hash_table_lookup(options, "nis_servers"); + if (str) { + gs_free const char **nis = nm_utils_strsplit_set(str, " "); + const char ** s; + + 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); + _LOG2I(LOGD_DHCP4, iface, " nis '%s'", *s); + } + } else + _LOG2W(LOGD_DHCP4, iface, "ignoring invalid NIS server '%s'", *s); + } + } + + str = g_hash_table_lookup(options, "vendor_encapsulated_options"); + nm_ip4_config_set_metered(ip4_config, str && strstr(str, "ANDROID_METERED")); + + return g_steal_pointer(&ip4_config); } /*****************************************************************************/ static void -ip6_add_domain_search (gpointer data, gpointer user_data) +ip6_add_domain_search(gpointer data, gpointer user_data) { - nm_ip6_config_add_search (NM_IP6_CONFIG (user_data), (const char *) data); + nm_ip6_config_add_search(NM_IP6_CONFIG(user_data), (const char *) data); } NMPlatformIP6Address -nm_dhcp_utils_ip6_prefix_from_options (GHashTable *options) +nm_dhcp_utils_ip6_prefix_from_options(GHashTable *options) { - gs_strfreev char **split_addr = NULL; - NMPlatformIP6Address address = { 0, }; - struct in6_addr tmp_addr; - char *str = NULL; - int prefix; - - g_return_val_if_fail (options != NULL, address); - - str = g_hash_table_lookup (options, "ip6_prefix"); - if (!str) - return address; - - split_addr = g_strsplit (str, "/", 2); - if (split_addr[0] == NULL && split_addr[1] == NULL) { - nm_log_warn (LOGD_DHCP6, "DHCP returned prefix without length '%s'", str); - return address; - } - - if (!inet_pton (AF_INET6, split_addr[0], &tmp_addr)) { - nm_log_warn (LOGD_DHCP6, "DHCP returned invalid prefix '%s'", str); - return address; - } - - prefix = _nm_utils_ascii_str_to_int64 (split_addr[1], 10, 0, 128, -1); - if (prefix < 0) { - nm_log_warn (LOGD_DHCP6, "DHCP returned prefix with invalid length '%s'", str); - return address; - } - - address.address = tmp_addr; - address.addr_source = NM_IP_CONFIG_SOURCE_DHCP; - address.plen = prefix; - address.timestamp = nm_utils_get_monotonic_timestamp_sec (); - - str = g_hash_table_lookup (options, "max_life"); - if (str) - address.lifetime = strtoul (str, NULL, 10); - - str = g_hash_table_lookup (options, "preferred_life"); - if (str) - address.preferred = strtoul (str, NULL, 10); - - return address; + gs_strfreev char ** split_addr = NULL; + NMPlatformIP6Address address = { + 0, + }; + struct in6_addr tmp_addr; + char * str = NULL; + int prefix; + + g_return_val_if_fail(options != NULL, address); + + str = g_hash_table_lookup(options, "ip6_prefix"); + if (!str) + return address; + + split_addr = g_strsplit(str, "/", 2); + if (split_addr[0] == NULL && split_addr[1] == NULL) { + nm_log_warn(LOGD_DHCP6, "DHCP returned prefix without length '%s'", str); + return address; + } + + if (!inet_pton(AF_INET6, split_addr[0], &tmp_addr)) { + nm_log_warn(LOGD_DHCP6, "DHCP returned invalid prefix '%s'", str); + return address; + } + + prefix = _nm_utils_ascii_str_to_int64(split_addr[1], 10, 0, 128, -1); + if (prefix < 0) { + nm_log_warn(LOGD_DHCP6, "DHCP returned prefix with invalid length '%s'", str); + return address; + } + + address.address = tmp_addr; + address.addr_source = NM_IP_CONFIG_SOURCE_DHCP; + address.plen = prefix; + address.timestamp = nm_utils_get_monotonic_timestamp_sec(); + + str = g_hash_table_lookup(options, "max_life"); + if (str) + address.lifetime = strtoul(str, NULL, 10); + + str = g_hash_table_lookup(options, "preferred_life"); + if (str) + address.preferred = strtoul(str, NULL, 10); + + return address; } NMIP6Config * -nm_dhcp_utils_ip6_config_from_options (NMDedupMultiIndex *multi_idx, - int ifindex, - const char *iface, - GHashTable *options, - gboolean info_only) +nm_dhcp_utils_ip6_config_from_options(NMDedupMultiIndex *multi_idx, + int ifindex, + const char * iface, + GHashTable * options, + gboolean info_only) { - NMIP6Config *ip6_config = NULL; - struct in6_addr tmp_addr; - NMPlatformIP6Address address; - char *str = NULL; - - g_return_val_if_fail (options != NULL, NULL); - - memset (&address, 0, sizeof (address)); - address.plen = 128; - address.timestamp = nm_utils_get_monotonic_timestamp_sec (); - - ip6_config = nm_ip6_config_new (multi_idx, ifindex); - - str = g_hash_table_lookup (options, "max_life"); - if (str) { - address.lifetime = strtoul (str, NULL, 10); - _LOG2I (LOGD_DHCP6, iface, " valid_lft %u", address.lifetime); - } - - str = g_hash_table_lookup (options, "preferred_life"); - if (str) { - address.preferred = strtoul (str, NULL, 10); - _LOG2I (LOGD_DHCP6, iface, " preferred_lft %u", address.preferred); - } - - str = g_hash_table_lookup (options, "ip6_address"); - if (str) { - if (!inet_pton (AF_INET6, str, &tmp_addr)) { - _LOG2W (LOGD_DHCP6, iface, "(%s): DHCP returned invalid address '%s'", - iface, str); - goto error; - } - - address.address = tmp_addr; - address.addr_source = NM_IP_CONFIG_SOURCE_DHCP; - nm_ip6_config_add_address (ip6_config, &address); - _LOG2I (LOGD_DHCP6, iface, " address %s", str); - } else if (info_only == FALSE) { - /* No address in Managed mode is a hard error */ - goto error; - } - - str = g_hash_table_lookup (options, "host_name"); - if (str) - _LOG2I (LOGD_DHCP6, iface, " hostname '%s'", str); - - str = g_hash_table_lookup (options, "dhcp6_name_servers"); - if (str) { - char **dns = g_strsplit (str, " ", 0); - char **s; - - for (s = 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); - _LOG2I (LOGD_DHCP6, iface, " nameserver '%s'", *s); - } - } else - _LOG2W (LOGD_DHCP6, iface, "ignoring invalid nameserver '%s'", *s); - } - g_strfreev (dns); - } - - str = g_hash_table_lookup (options, "dhcp6_domain_search"); - if (str) - process_domain_search (iface, str, ip6_add_domain_search, ip6_config); - - return ip6_config; - -error: - g_object_unref (ip6_config); - return NULL; + gs_unref_object NMIP6Config *ip6_config = NULL; + struct in6_addr tmp_addr; + NMPlatformIP6Address address; + char * str = NULL; + + g_return_val_if_fail(options != NULL, NULL); + + memset(&address, 0, sizeof(address)); + address.plen = 128; + address.timestamp = nm_utils_get_monotonic_timestamp_sec(); + + ip6_config = nm_ip6_config_new(multi_idx, ifindex); + + str = g_hash_table_lookup(options, "max_life"); + if (str) { + address.lifetime = strtoul(str, NULL, 10); + _LOG2I(LOGD_DHCP6, iface, " valid_lft %u", address.lifetime); + } + + str = g_hash_table_lookup(options, "preferred_life"); + if (str) { + address.preferred = strtoul(str, NULL, 10); + _LOG2I(LOGD_DHCP6, iface, " preferred_lft %u", address.preferred); + } + + str = g_hash_table_lookup(options, "ip6_address"); + if (str) { + if (!inet_pton(AF_INET6, str, &tmp_addr)) { + _LOG2W(LOGD_DHCP6, iface, "(%s): DHCP returned invalid address '%s'", iface, str); + return NULL; + } + + address.address = tmp_addr; + address.addr_source = NM_IP_CONFIG_SOURCE_DHCP; + nm_ip6_config_add_address(ip6_config, &address); + _LOG2I(LOGD_DHCP6, iface, " address %s", str); + } else if (info_only == FALSE) { + /* No address in Managed mode is a hard error */ + return NULL; + } + + str = g_hash_table_lookup(options, "host_name"); + if (str) + _LOG2I(LOGD_DHCP6, iface, " hostname '%s'", str); + + str = g_hash_table_lookup(options, "dhcp6_name_servers"); + if (str) { + gs_free const char **dns = nm_utils_strsplit_set(str, " "); + const char ** s; + + 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); + _LOG2I(LOGD_DHCP6, iface, " nameserver '%s'", *s); + } + } else + _LOG2W(LOGD_DHCP6, iface, "ignoring invalid nameserver '%s'", *s); + } + } + + str = g_hash_table_lookup(options, "dhcp6_domain_search"); + if (str) + process_domain_search(iface, str, ip6_add_domain_search, ip6_config); + + return g_steal_pointer(&ip6_config); } char * -nm_dhcp_utils_duid_to_string (GBytes *duid) +nm_dhcp_utils_duid_to_string(GBytes *duid) { - gconstpointer data; - gsize len; + gconstpointer data; + gsize len; - g_return_val_if_fail (duid, NULL); + g_return_val_if_fail(duid, NULL); - data = g_bytes_get_data (duid, &len); - return nm_utils_bin2hexstr_full (data, len, ':', FALSE, NULL); + data = g_bytes_get_data(duid, &len); + return nm_utils_bin2hexstr_full(data, len, ':', FALSE, NULL); } /** @@ -720,34 +732,34 @@ nm_dhcp_utils_duid_to_string (GBytes *duid) * to the DHCP server. */ GBytes * -nm_dhcp_utils_client_id_string_to_bytes (const char *client_id) +nm_dhcp_utils_client_id_string_to_bytes(const char *client_id) { - GBytes *bytes = NULL; - guint len; - char *c; - - g_return_val_if_fail (client_id && client_id[0], NULL); - - /* Try as hex encoded */ - if (strchr (client_id, ':')) { - bytes = nm_utils_hexstr2bin (client_id); - - /* the result must be at least two bytes long, - * because @client_id contains a delimiter - * but nm_utils_hexstr2bin() does not allow - * leading nor trailing delimiters. */ - nm_assert (!bytes || g_bytes_get_size (bytes) >= 2); - } - if (!bytes) { - /* Fall back to string */ - len = strlen (client_id); - c = g_malloc (len + 1); - c[0] = 0; /* type: non-hardware address per RFC 2132 section 9.14 */ - memcpy (c + 1, client_id, len); - bytes = g_bytes_new_take (c, len + 1); - } - - return bytes; + GBytes *bytes = NULL; + guint len; + char * c; + + g_return_val_if_fail(client_id && client_id[0], NULL); + + /* Try as hex encoded */ + if (strchr(client_id, ':')) { + bytes = nm_utils_hexstr2bin(client_id); + + /* the result must be at least two bytes long, + * because @client_id contains a delimiter + * but nm_utils_hexstr2bin() does not allow + * leading nor trailing delimiters. */ + nm_assert(!bytes || g_bytes_get_size(bytes) >= 2); + } + if (!bytes) { + /* Fall back to string */ + len = strlen(client_id); + c = g_malloc(len + 1); + c[0] = 0; /* type: non-hardware address per RFC 2132 section 9.14 */ + memcpy(c + 1, client_id, len); + bytes = g_bytes_new_take(c, len + 1); + } + + return bytes; } /** @@ -765,40 +777,60 @@ nm_dhcp_utils_client_id_string_to_bytes (const char *client_id) * Returns: TRUE if the lease file already exists, FALSE otherwise. */ gboolean -nm_dhcp_utils_get_leasefile_path (int addr_family, - const char *plugin_name, - const char *iface, - const char *uuid, - char **out_leasefile_path) +nm_dhcp_utils_get_leasefile_path(int addr_family, + const char *plugin_name, + const char *iface, + const char *uuid, + char ** out_leasefile_path) { - gs_free char *rundir_path = NULL; - gs_free char *statedir_path = NULL; - - rundir_path = g_strdup_printf (NMRUNDIR "/%s%s-%s-%s.lease", - plugin_name, - addr_family == AF_INET6 ? "6" : "", - uuid, - iface); - - if (g_file_test (rundir_path, G_FILE_TEST_EXISTS)) { - *out_leasefile_path = g_steal_pointer (&rundir_path); - return TRUE; - } - - statedir_path = g_strdup_printf (NMSTATEDIR "/%s%s-%s-%s.lease", - plugin_name, - addr_family == AF_INET6 ? "6" : "", - uuid, - iface); - - if (g_file_test (statedir_path, G_FILE_TEST_EXISTS)) { - *out_leasefile_path = g_steal_pointer (&statedir_path); - return TRUE; - } - - if (nm_config_get_configure_and_quit (nm_config_get ()) == NM_CONFIG_CONFIGURE_AND_QUIT_INITRD) - *out_leasefile_path = g_steal_pointer (&rundir_path); - else - *out_leasefile_path = g_steal_pointer (&statedir_path); - return FALSE; + gs_free char *rundir_path = NULL; + gs_free char *statedir_path = NULL; + + rundir_path = g_strdup_printf(NMRUNDIR "/%s%s-%s-%s.lease", + plugin_name, + addr_family == AF_INET6 ? "6" : "", + uuid, + iface); + + if (g_file_test(rundir_path, G_FILE_TEST_EXISTS)) { + *out_leasefile_path = g_steal_pointer(&rundir_path); + return TRUE; + } + + statedir_path = g_strdup_printf(NMSTATEDIR "/%s%s-%s-%s.lease", + plugin_name, + addr_family == AF_INET6 ? "6" : "", + uuid, + iface); + + if (g_file_test(statedir_path, G_FILE_TEST_EXISTS)) { + *out_leasefile_path = g_steal_pointer(&statedir_path); + return TRUE; + } + + if (nm_config_get_configure_and_quit(nm_config_get()) == NM_CONFIG_CONFIGURE_AND_QUIT_INITRD) + *out_leasefile_path = g_steal_pointer(&rundir_path); + else + *out_leasefile_path = g_steal_pointer(&statedir_path); + return FALSE; +} + +char * +nm_dhcp_utils_get_dhcp6_event_id(GHashTable *lease) +{ + const char *start; + const char *iaid; + + if (!lease) + return NULL; + + iaid = g_hash_table_lookup(lease, "iaid"); + if (!iaid) + return NULL; + + start = g_hash_table_lookup(lease, "life_starts"); + if (!start) + return NULL; + + return g_strdup_printf("%s|%s", iaid, start); } diff --git a/src/dhcp/nm-dhcp-utils.h b/src/dhcp/nm-dhcp-utils.h index ecb91809..c72d9617 100644 --- a/src/dhcp/nm-dhcp-utils.h +++ b/src/dhcp/nm-dhcp-utils.h @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2014 Red Hat, Inc. */ @@ -11,32 +11,33 @@ #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); +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); +NMIP6Config *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); +NMPlatformIP6Address nm_dhcp_utils_ip6_prefix_from_options(GHashTable *options); -char *nm_dhcp_utils_duid_to_string (GBytes *duid); +char *nm_dhcp_utils_duid_to_string(GBytes *duid); -GBytes *nm_dhcp_utils_client_id_string_to_bytes (const char *client_id); +GBytes *nm_dhcp_utils_client_id_string_to_bytes(const char *client_id); -gboolean nm_dhcp_utils_get_leasefile_path (int addr_family, - const char *plugin_name, - const char *iface, - const char *uuid, - char **out_leasefile_path); +gboolean nm_dhcp_utils_get_leasefile_path(int addr_family, + const char *plugin_name, + const char *iface, + const char *uuid, + char ** out_leasefile_path); -char **nm_dhcp_parse_search_list (guint8 *data, size_t n_data); +char **nm_dhcp_parse_search_list(guint8 *data, size_t n_data); -#endif /* __NETWORKMANAGER_DHCP_UTILS_H__ */ +char *nm_dhcp_utils_get_dhcp6_event_id(GHashTable *lease); +#endif /* __NETWORKMANAGER_DHCP_UTILS_H__ */ diff --git a/src/dhcp/tests/test-dhcp-dhclient.c b/src/dhcp/tests/test-dhcp-dhclient.c index d51bcae5..da24f3c5 100644 --- a/src/dhcp/tests/test-dhcp-dhclient.c +++ b/src/dhcp/tests/test-dhcp-dhclient.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2010 Red Hat, Inc. */ @@ -20,1234 +20,1322 @@ #include "nm-test-utils-core.h" -#define TEST_DIR NM_BUILD_SRCDIR"/src/dhcp/tests" -#define TEST_MUDURL "https://example.com/mud.json" +#define TEST_DIR NM_BUILD_SRCDIR "/src/dhcp/tests" +#define TEST_MUDURL "https://example.com/mud.json" static void -test_config (const char *orig, - const char *expected, - int addr_family, - const char *hostname, - guint32 timeout, - gboolean use_fqdn, - NMDhcpHostnameFlags hostname_flags, - const char *dhcp_client_id, - GBytes *expected_new_client_id, - const char *iface, - const char *anycast_addr, - const char *mud_url) +test_config(const char * orig, + const char * expected, + int addr_family, + const char * hostname, + guint32 timeout, + gboolean use_fqdn, + NMDhcpHostnameFlags hostname_flags, + const char * dhcp_client_id, + GBytes * expected_new_client_id, + const char * iface, + const char * anycast_addr, + const char * mud_url) { - gs_free char *new = NULL; - gs_unref_bytes GBytes *client_id = NULL; - gs_unref_bytes GBytes *new_client_id = NULL; - - if (dhcp_client_id) { - client_id = nm_dhcp_utils_client_id_string_to_bytes (dhcp_client_id); - g_assert (client_id); - } - - new = nm_dhcp_dhclient_create_config (iface, - addr_family, - client_id, - anycast_addr, - hostname, - timeout, - use_fqdn, - hostname_flags, - mud_url, - "/path/to/dhclient.conf", - orig, - &new_client_id); - g_assert (new != NULL); - - if (!nm_streq (new, expected)) { - g_message ("\n* OLD ---------------------------------\n" - "%s" - "\n- NEW -----------------------------------\n" - "%s" - "\n+ EXPECTED ++++++++++++++++++++++++++++++\n" - "%s" - "\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", - orig, new, expected); - } - g_assert_cmpstr (new, ==, expected); - - if (expected_new_client_id) { - g_assert (new_client_id); - g_assert (g_bytes_equal (new_client_id, expected_new_client_id)); - } else - g_assert (new_client_id == NULL); + gs_free char *new = NULL; + gs_unref_bytes GBytes *client_id = NULL; + gs_unref_bytes GBytes *new_client_id = NULL; + + if (dhcp_client_id) { + client_id = nm_dhcp_utils_client_id_string_to_bytes(dhcp_client_id); + g_assert(client_id); + } + + new = nm_dhcp_dhclient_create_config(iface, + addr_family, + client_id, + anycast_addr, + hostname, + timeout, + use_fqdn, + hostname_flags, + mud_url, + NULL, + "/path/to/dhclient.conf", + orig, + &new_client_id); + g_assert(new != NULL); + + if (!nm_streq(new, expected)) { + g_message("\n* OLD ---------------------------------\n" + "%s" + "\n- NEW -----------------------------------\n" + "%s" + "\n+ EXPECTED ++++++++++++++++++++++++++++++\n" + "%s" + "\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + orig, + new, + expected); + } + g_assert_cmpstr(new, ==, expected); + + if (expected_new_client_id) { + g_assert(new_client_id); + g_assert(g_bytes_equal(new_client_id, expected_new_client_id)); + } else + g_assert(new_client_id == NULL); } /*****************************************************************************/ -static const char *orig_missing_expected = \ - "# Created by NetworkManager\n" - "\n\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n" - "\n"; +static const char *orig_missing_expected = + "# Created by NetworkManager\n" + "\n\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n" + "\n"; static void -test_orig_missing (void) +test_orig_missing(void) { - test_config (NULL, - orig_missing_expected, - AF_INET, NULL, 0, FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, NULL, "eth0", NULL, NULL); + test_config(NULL, + orig_missing_expected, + AF_INET, + NULL, + 0, + FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + NULL, + NULL, + "eth0", + NULL, + NULL); } /*****************************************************************************/ - -static const char *orig_missing_add_mud_url_expected = \ - "# Created by NetworkManager\n" - "\n" - "option mudurl code 161 = text;\n" - "send mudurl \"https://example.com/mud.json\";\n\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n" - "\n"; +static const char *orig_missing_add_mud_url_expected = + "# Created by NetworkManager\n" + "\n" + "option mudurl code 161 = text;\n" + "send mudurl \"https://example.com/mud.json\";\n\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n" + "\n"; static void -test_orig_missing_add_mud_url (void) +test_orig_missing_add_mud_url(void) { - test_config (NULL, - orig_missing_add_mud_url_expected, - AF_INET, NULL, 0, FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, NULL, "eth0", NULL, TEST_MUDURL); + test_config(NULL, + orig_missing_add_mud_url_expected, + AF_INET, + NULL, + 0, + FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + NULL, + NULL, + "eth0", + NULL, + TEST_MUDURL); } /*****************************************************************************/ -static const char *override_client_id_orig = \ - "send dhcp-client-identifier 00:30:04:20:7A:08;\n"; - -static const char *override_client_id_expected = \ - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "send dhcp-client-identifier 11:22:33:44:55:66; # added by NetworkManager\n" - "\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n" - "\n"; +static const char *override_client_id_orig = "send dhcp-client-identifier 00:30:04:20:7A:08;\n"; + +static const char *override_client_id_expected = + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n" + "send dhcp-client-identifier 11:22:33:44:55:66; # added by NetworkManager\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n" + "\n"; static void -test_override_client_id (void) +test_override_client_id(void) { - test_config (override_client_id_orig, override_client_id_expected, - AF_INET, NULL, 0, FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - "11:22:33:44:55:66", - NULL, - "eth0", - NULL, - NULL); + test_config(override_client_id_orig, + override_client_id_expected, + AF_INET, + NULL, + 0, + FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + "11:22:33:44:55:66", + NULL, + "eth0", + NULL, + NULL); } /*****************************************************************************/ -static const char *quote_client_id_expected = \ - "# Created by NetworkManager\n" - "\n" - "send dhcp-client-identifier \"\\x00abcd\"; # added by NetworkManager\n" - "\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n" - "\n"; +static const char *quote_client_id_expected = + "# Created by NetworkManager\n" + "\n" + "send dhcp-client-identifier \"\\x00abcd\"; # added by NetworkManager\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n" + "\n"; static void -test_quote_client_id (void) +test_quote_client_id(void) { - test_config (NULL, quote_client_id_expected, - AF_INET, NULL, 0, FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - "abcd", - NULL, - "eth0", - NULL, - NULL); + test_config(NULL, + quote_client_id_expected, + AF_INET, + NULL, + 0, + FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + "abcd", + NULL, + "eth0", + NULL, + NULL); } /*****************************************************************************/ -static const char *quote_client_id_expected_2 = \ - "# Created by NetworkManager\n" - "\n" - "send dhcp-client-identifier 00:61:5c:62:63; # added by NetworkManager\n" - "\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n" - "\n"; +static const char *quote_client_id_expected_2 = + "# Created by NetworkManager\n" + "\n" + "send dhcp-client-identifier 00:61:5c:62:63; # added by NetworkManager\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n" + "\n"; static void -test_quote_client_id_2 (void) +test_quote_client_id_2(void) { - test_config (NULL, quote_client_id_expected_2, - AF_INET, NULL, 0, FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - "a\\bc", - NULL, - "eth0", - NULL, - NULL); + test_config(NULL, + quote_client_id_expected_2, + AF_INET, + NULL, + 0, + FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + "a\\bc", + NULL, + "eth0", + NULL, + NULL); } /*****************************************************************************/ -static const char *hex_zero_client_id_expected = \ - "# Created by NetworkManager\n" - "\n" - "send dhcp-client-identifier 00:11:22:33; # added by NetworkManager\n" - "\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n" - "\n"; +static const char *hex_zero_client_id_expected = + "# Created by NetworkManager\n" + "\n" + "send dhcp-client-identifier 00:11:22:33; # added by NetworkManager\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n" + "\n"; static void -test_hex_zero_client_id (void) +test_hex_zero_client_id(void) { - test_config (NULL, hex_zero_client_id_expected, - AF_INET, NULL, 0, FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - "00:11:22:33", - NULL, - "eth0", - NULL, - NULL); + test_config(NULL, + hex_zero_client_id_expected, + AF_INET, + NULL, + 0, + FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + "00:11:22:33", + NULL, + "eth0", + NULL, + NULL); } /*****************************************************************************/ -static const char *ascii_client_id_expected = \ - "# Created by NetworkManager\n" - "\n" - "send dhcp-client-identifier \"\\x00qb:cd:ef:12:34:56\"; # added by NetworkManager\n" - "\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n" - "\n"; +static const char *ascii_client_id_expected = + "# Created by NetworkManager\n" + "\n" + "send dhcp-client-identifier \"\\x00qb:cd:ef:12:34:56\"; # added by NetworkManager\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n" + "\n"; static void -test_ascii_client_id (void) +test_ascii_client_id(void) { - test_config (NULL, ascii_client_id_expected, - AF_INET, NULL, 0, FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - "qb:cd:ef:12:34:56", - NULL, - "eth0", - NULL, - NULL); + test_config(NULL, + ascii_client_id_expected, + AF_INET, + NULL, + 0, + FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + "qb:cd:ef:12:34:56", + NULL, + "eth0", + NULL, + NULL); } /*****************************************************************************/ -static const char *hex_single_client_id_expected = \ - "# Created by NetworkManager\n" - "\n" - "send dhcp-client-identifier ab:cd:0e:12:34:56; # added by NetworkManager\n" - "\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n" - "\n"; +static const char *hex_single_client_id_expected = + "# Created by NetworkManager\n" + "\n" + "send dhcp-client-identifier ab:cd:0e:12:34:56; # added by NetworkManager\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n" + "\n"; static void -test_hex_single_client_id (void) +test_hex_single_client_id(void) { - test_config (NULL, hex_single_client_id_expected, - AF_INET, NULL, 0, FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - "ab:cd:e:12:34:56", - NULL, - "eth0", - NULL, - NULL); + test_config(NULL, + hex_single_client_id_expected, + AF_INET, + NULL, + 0, + FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + "ab:cd:e:12:34:56", + NULL, + "eth0", + NULL, + NULL); } /*****************************************************************************/ -static const char *existing_hex_client_id_orig = \ - "send dhcp-client-identifier 10:30:04:20:7A:08;\n"; - -static const char *existing_hex_client_id_expected = \ - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "send dhcp-client-identifier 10:30:04:20:7A:08;\n" - "\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n" - "\n"; +static const char *existing_hex_client_id_orig = "send dhcp-client-identifier 10:30:04:20:7A:08;\n"; + +static const char *existing_hex_client_id_expected = + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n" + "send dhcp-client-identifier 10:30:04:20:7A:08;\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n" + "\n"; static void -test_existing_hex_client_id (void) +test_existing_hex_client_id(void) { - gs_unref_bytes GBytes *new_client_id = NULL; - const guint8 bytes[] = { 0x10, 0x30, 0x04, 0x20, 0x7A, 0x08 }; - - new_client_id = g_bytes_new (bytes, sizeof (bytes)); - test_config (existing_hex_client_id_orig, existing_hex_client_id_expected, - AF_INET, NULL, 0, FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - new_client_id, - "eth0", - NULL, - NULL); + gs_unref_bytes GBytes *new_client_id = NULL; + const guint8 bytes[] = {0x10, 0x30, 0x04, 0x20, 0x7A, 0x08}; + + new_client_id = g_bytes_new(bytes, sizeof(bytes)); + test_config(existing_hex_client_id_orig, + existing_hex_client_id_expected, + AF_INET, + NULL, + 0, + FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + NULL, + new_client_id, + "eth0", + NULL, + NULL); } /*****************************************************************************/ -static const char *existing_escaped_client_id_orig = \ - "send dhcp-client-identifier \"\\044test\\xfe\";\n"; - -static const char *existing_escaped_client_id_expected = \ - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "send dhcp-client-identifier \"\\044test\\xfe\";\n" - "\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n" - "\n"; +static const char *existing_escaped_client_id_orig = + "send dhcp-client-identifier \"\\044test\\xfe\";\n"; + +static const char *existing_escaped_client_id_expected = + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n" + "send dhcp-client-identifier \"\\044test\\xfe\";\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n" + "\n"; static void -test_existing_escaped_client_id (void) +test_existing_escaped_client_id(void) { - gs_unref_bytes GBytes *new_client_id = NULL; - - new_client_id = g_bytes_new ("$test\xfe", 6); - test_config (existing_escaped_client_id_orig, existing_escaped_client_id_expected, - AF_INET, NULL, 0, FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - new_client_id, - "eth0", - NULL, - NULL); + gs_unref_bytes GBytes *new_client_id = NULL; + + new_client_id = g_bytes_new("$test\xfe", 6); + test_config(existing_escaped_client_id_orig, + existing_escaped_client_id_expected, + AF_INET, + NULL, + 0, + FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + NULL, + new_client_id, + "eth0", + NULL, + NULL); } /*****************************************************************************/ #define EACID "qb:cd:ef:12:34:56" -static const char *existing_ascii_client_id_orig = \ - "send dhcp-client-identifier \"\\x00" EACID "\";\n"; - -static const char *existing_ascii_client_id_expected = \ - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "send dhcp-client-identifier \"\\x00" EACID "\";\n" - "\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n" - "\n"; +static const char *existing_ascii_client_id_orig = + "send dhcp-client-identifier \"\\x00" EACID "\";\n"; + +static const char *existing_ascii_client_id_expected = + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n" + "send dhcp-client-identifier \"\\x00" EACID "\";\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n" + "\n"; static void -test_existing_ascii_client_id (void) +test_existing_ascii_client_id(void) { - gs_unref_bytes GBytes *new_client_id = NULL; - char buf[NM_STRLEN (EACID) + 1] = { 0 }; - - memcpy (buf + 1, EACID, NM_STRLEN (EACID)); - new_client_id = g_bytes_new (buf, sizeof (buf)); - test_config (existing_ascii_client_id_orig, existing_ascii_client_id_expected, - AF_INET, NULL, 0, FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - new_client_id, - "eth0", - NULL, - NULL); + gs_unref_bytes GBytes *new_client_id = NULL; + char buf[NM_STRLEN(EACID) + 1] = {0}; + + memcpy(buf + 1, EACID, NM_STRLEN(EACID)); + new_client_id = g_bytes_new(buf, sizeof(buf)); + test_config(existing_ascii_client_id_orig, + existing_ascii_client_id_expected, + AF_INET, + NULL, + 0, + FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + NULL, + new_client_id, + "eth0", + NULL, + NULL); } /*****************************************************************************/ -static const char *fqdn_expected = \ - "# Created by NetworkManager\n" - "\n" - "send fqdn.fqdn \"foo.bar.com\"; # added by NetworkManager\n" - "send fqdn.encoded on;\n" - "send fqdn.server-update off;\n" - "send fqdn.no-client-update on;\n" - "\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n\n"; +static const char *fqdn_expected = + "# Created by NetworkManager\n" + "\n" + "send fqdn.fqdn \"foo.bar.com\"; # added by NetworkManager\n" + "send fqdn.encoded on;\n" + "send fqdn.server-update off;\n" + "send fqdn.no-client-update on;\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n\n"; static void -test_fqdn (void) +test_fqdn(void) { - test_config (NULL, fqdn_expected, - AF_INET, "foo.bar.com", 0, - TRUE, - NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED - | NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE, - NULL, - NULL, - "eth0", - NULL, - NULL); + test_config(NULL, + fqdn_expected, + AF_INET, + "foo.bar.com", + 0, + TRUE, + NM_DHCP_HOSTNAME_FLAG_FQDN_ENCODED | NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE, + NULL, + NULL, + "eth0", + NULL, + NULL); } -static const char *fqdn_options_override_orig = \ - "\n" - "send fqdn.fqdn \"foobar.com\"\n" /* NM must ignore this ... */ - "send fqdn.encoded off;\n" /* ... and honor these */ - "send fqdn.server-update off;\n"; - -static const char *fqdn_options_override_expected = \ - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "send fqdn.fqdn \"example2.com\"; # added by NetworkManager\n" - "send fqdn.encoded off;\n" - "send fqdn.server-update on;\n" - "send fqdn.no-client-update off;\n" - "\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n" - "\n" - "# FQDN options from /path/to/dhclient.conf\n" - "send fqdn.encoded off;\n" - "send fqdn.server-update off;\n\n"; +static const char *fqdn_options_override_orig = + "\n" + "send fqdn.fqdn \"foobar.com\"\n" /* NM must ignore this ... */ + "send fqdn.encoded off;\n" /* ... and honor these */ + "send fqdn.server-update off;\n"; + +static const char *fqdn_options_override_expected = + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n" + "send fqdn.fqdn \"example2.com\"; # added by NetworkManager\n" + "send fqdn.encoded off;\n" + "send fqdn.server-update on;\n" + "send fqdn.no-client-update off;\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n" + "\n" + "# FQDN options from /path/to/dhclient.conf\n" + "send fqdn.encoded off;\n" + "send fqdn.server-update off;\n\n"; static void -test_fqdn_options_override (void) +test_fqdn_options_override(void) { - test_config (fqdn_options_override_orig, - fqdn_options_override_expected, - AF_INET, "example2.com", 0, - NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE, - TRUE, NULL, - NULL, - "eth0", - NULL, - NULL); + test_config(fqdn_options_override_orig, + fqdn_options_override_expected, + AF_INET, + "example2.com", + 0, + NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE, + TRUE, + NULL, + NULL, + "eth0", + NULL, + NULL); } /*****************************************************************************/ -static const char *override_hostname_orig = \ - "send host-name \"foobar\";\n"; - -static const char *override_hostname_expected = \ - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "send host-name \"blahblah\"; # added by NetworkManager\n" - "\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n" - "\n"; +static const char *override_hostname_orig = "send host-name \"foobar\";\n"; + +static const char *override_hostname_expected = + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n" + "send host-name \"blahblah\"; # added by NetworkManager\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n" + "\n"; static void -test_override_hostname (void) +test_override_hostname(void) { - test_config (override_hostname_orig, override_hostname_expected, - AF_INET, "blahblah", 0, FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - NULL, - "eth0", - NULL, - NULL); + test_config(override_hostname_orig, + override_hostname_expected, + AF_INET, + "blahblah", + 0, + FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + NULL, + NULL, + "eth0", + NULL, + NULL); } /*****************************************************************************/ -static const char *override_hostname6_orig = \ - "send fqdn.fqdn \"foobar\";\n"; - -static const char *override_hostname6_expected = \ - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "send fqdn.fqdn \"blahblah.local\"; # added by NetworkManager\n" - "send fqdn.server-update on;\n" - "\n" - "also request dhcp6.name-servers;\n" - "also request dhcp6.domain-search;\n" - "also request dhcp6.client-id;\n" - "\n"; +static const char *override_hostname6_orig = "send fqdn.fqdn \"foobar\";\n"; + +static const char *override_hostname6_expected = + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n" + "send fqdn.fqdn \"blahblah.local\"; # added by NetworkManager\n" + "send fqdn.server-update on;\n" + "\n" + "also request dhcp6.name-servers;\n" + "also request dhcp6.domain-search;\n" + "also request dhcp6.client-id;\n" + "\n"; static void -test_override_hostname6 (void) +test_override_hostname6(void) { - test_config (override_hostname6_orig, override_hostname6_expected, - AF_INET6, "blahblah.local", 0, TRUE, - NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE, - NULL, - NULL, - "eth0", - NULL, - NULL); + test_config(override_hostname6_orig, + override_hostname6_expected, + AF_INET6, + "blahblah.local", + 0, + TRUE, + NM_DHCP_HOSTNAME_FLAG_FQDN_SERV_UPDATE, + NULL, + NULL, + "eth0", + NULL, + NULL); } /*****************************************************************************/ -static const char *nonfqdn_hostname6_expected = \ - "# Created by NetworkManager\n" - "\n" - "send fqdn.fqdn \"blahblah\"; # added by NetworkManager\n" - "send fqdn.no-client-update on;\n" - "\n" - "also request dhcp6.name-servers;\n" - "also request dhcp6.domain-search;\n" - "also request dhcp6.client-id;\n" - "\n"; +static const char *nonfqdn_hostname6_expected = + "# Created by NetworkManager\n" + "\n" + "send fqdn.fqdn \"blahblah\"; # added by NetworkManager\n" + "send fqdn.no-client-update on;\n" + "\n" + "also request dhcp6.name-servers;\n" + "also request dhcp6.domain-search;\n" + "also request dhcp6.client-id;\n" + "\n"; static void -test_nonfqdn_hostname6 (void) +test_nonfqdn_hostname6(void) { - /* Non-FQDN hostname can now be used with dhclient */ - test_config (NULL, nonfqdn_hostname6_expected, - AF_INET6, "blahblah", 0, TRUE, - NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE, - NULL, - NULL, - "eth0", - NULL, - NULL); + /* Non-FQDN hostname can now be used with dhclient */ + test_config(NULL, + nonfqdn_hostname6_expected, + AF_INET6, + "blahblah", + 0, + TRUE, + NM_DHCP_HOSTNAME_FLAG_FQDN_NO_UPDATE, + NULL, + NULL, + "eth0", + NULL, + NULL); } /*****************************************************************************/ -static const char *existing_alsoreq_orig = \ - "also request something;\n" - "also request another-thing;\n" - ; - -static const char *existing_alsoreq_expected = \ - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "also request something;\n" - "also request another-thing;\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n" - "\n"; +static const char *existing_alsoreq_orig = "also request something;\n" + "also request another-thing;\n"; + +static const char *existing_alsoreq_expected = + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request something;\n" + "also request another-thing;\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n" + "\n"; static void -test_existing_alsoreq (void) +test_existing_alsoreq(void) { - test_config (existing_alsoreq_orig, existing_alsoreq_expected, - AF_INET, NULL, 0, FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - NULL, - "eth0", - NULL, - NULL); + test_config(existing_alsoreq_orig, + existing_alsoreq_expected, + AF_INET, + NULL, + 0, + FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + NULL, + NULL, + "eth0", + NULL, + NULL); } /*****************************************************************************/ -static const char *existing_req_orig = \ - "request something;\n" - "also request some-other-thing;\n" - "request another-thing;\n" - "also request yet-another-thing;\n" - ; - -static const char *existing_req_expected = \ - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "request; # override dhclient defaults\n" - "also request another-thing;\n" - "also request yet-another-thing;\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n" - "\n"; +static const char *existing_req_orig = "request something;\n" + "also request some-other-thing;\n" + "request another-thing;\n" + "also request yet-another-thing;\n"; + +static const char *existing_req_expected = + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "request; # override dhclient defaults\n" + "also request another-thing;\n" + "also request yet-another-thing;\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n" + "\n"; static void -test_existing_req (void) +test_existing_req(void) { - test_config (existing_req_orig, existing_req_expected, - AF_INET, NULL, 0, FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - NULL, - "eth0", - NULL, - NULL); + test_config(existing_req_orig, + existing_req_expected, + AF_INET, + NULL, + 0, + FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + NULL, + NULL, + "eth0", + NULL, + NULL); } /*****************************************************************************/ -static const char *existing_multiline_alsoreq_orig = \ - "also request something another-thing yet-another-thing\n" - " foobar baz blah;\n" - ; - -static const char *existing_multiline_alsoreq_expected = \ - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "also request something;\n" - "also request another-thing;\n" - "also request yet-another-thing;\n" - "also request foobar;\n" - "also request baz;\n" - "also request blah;\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n" - "\n"; +static const char *existing_multiline_alsoreq_orig = + "also request something another-thing yet-another-thing\n" + " foobar baz blah;\n"; + +static const char *existing_multiline_alsoreq_expected = + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request something;\n" + "also request another-thing;\n" + "also request yet-another-thing;\n" + "also request foobar;\n" + "also request baz;\n" + "also request blah;\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n" + "\n"; static void -test_existing_multiline_alsoreq (void) +test_existing_multiline_alsoreq(void) { - test_config (existing_multiline_alsoreq_orig, existing_multiline_alsoreq_expected, - AF_INET, NULL, 0, FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - NULL, - "eth0", - NULL, - NULL); + test_config(existing_multiline_alsoreq_orig, + existing_multiline_alsoreq_expected, + AF_INET, + NULL, + 0, + FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + NULL, + NULL, + "eth0", + NULL, + NULL); } /*****************************************************************************/ static void -test_one_duid (const char *escaped, const guint8 *unescaped, guint len) +test_one_duid(const char *escaped, const guint8 *unescaped, guint len) { - gs_unref_bytes GBytes *t1 = NULL; - gs_unref_bytes GBytes *t2 = NULL; - gs_free char *w = NULL; - - t1 = nm_dhcp_dhclient_unescape_duid (escaped); - g_assert (t1); - g_assert (nm_utils_gbytes_equal_mem (t1, unescaped, len)); - - t2 = g_bytes_new (unescaped, len); - w = nm_dhcp_dhclient_escape_duid (t2); - g_assert (w); - g_assert_cmpstr (escaped, ==, w); + gs_unref_bytes GBytes *t1 = NULL; + gs_unref_bytes GBytes *t2 = NULL; + gs_free char * w = NULL; + + t1 = nm_dhcp_dhclient_unescape_duid(escaped); + g_assert(t1); + g_assert(nm_utils_gbytes_equal_mem(t1, unescaped, len)); + + t2 = g_bytes_new(unescaped, len); + w = nm_dhcp_dhclient_escape_duid(t2); + g_assert(w); + g_assert_cmpstr(escaped, ==, w); } static void -test_duids (void) +test_duids(void) { - const guint8 test1_u[] = { 0x00, 0x01, 0x00, 0x01, 0x13, 0x6f, 0x13, 0x6e, - 0x00, 0x22, 0xfa, 0x8c, 0xd6, 0xc2 }; - const char *test1_s = "\\000\\001\\000\\001\\023o\\023n\\000\\\"\\372\\214\\326\\302"; + const guint8 test1_u[] = + {0x00, 0x01, 0x00, 0x01, 0x13, 0x6f, 0x13, 0x6e, 0x00, 0x22, 0xfa, 0x8c, 0xd6, 0xc2}; + const char *test1_s = "\\000\\001\\000\\001\\023o\\023n\\000\\\"\\372\\214\\326\\302"; - const guint8 test2_u[] = { 0x00, 0x01, 0x00, 0x01, 0x17, 0x57, 0xee, 0x39, - 0x00, 0x23, 0x15, 0x08, 0x7E, 0xac }; - const char *test2_s = "\\000\\001\\000\\001\\027W\\3569\\000#\\025\\010~\\254"; + const guint8 test2_u[] = + {0x00, 0x01, 0x00, 0x01, 0x17, 0x57, 0xee, 0x39, 0x00, 0x23, 0x15, 0x08, 0x7E, 0xac}; + const char *test2_s = "\\000\\001\\000\\001\\027W\\3569\\000#\\025\\010~\\254"; - const guint8 test3_u[] = { 0x00, 0x01, 0x00, 0x01, 0x17, 0x58, 0xe8, 0x58, - 0x00, 0x23, 0x15, 0x08, 0x7e, 0xac }; - const char *test3_s = "\\000\\001\\000\\001\\027X\\350X\\000#\\025\\010~\\254"; + const guint8 test3_u[] = + {0x00, 0x01, 0x00, 0x01, 0x17, 0x58, 0xe8, 0x58, 0x00, 0x23, 0x15, 0x08, 0x7e, 0xac}; + const char *test3_s = "\\000\\001\\000\\001\\027X\\350X\\000#\\025\\010~\\254"; - const guint8 test4_u[] = { 0x00, 0x01, 0x00, 0x01, 0x15, 0xd5, 0x31, 0x97, - 0x00, 0x16, 0xeb, 0x04, 0x45, 0x18 }; - const char *test4_s = "\\000\\001\\000\\001\\025\\3251\\227\\000\\026\\353\\004E\\030"; + const guint8 test4_u[] = + {0x00, 0x01, 0x00, 0x01, 0x15, 0xd5, 0x31, 0x97, 0x00, 0x16, 0xeb, 0x04, 0x45, 0x18}; + const char *test4_s = "\\000\\001\\000\\001\\025\\3251\\227\\000\\026\\353\\004E\\030"; - const char *bad_s = "\\000\\001\\000\\001\\425\\3251\\227\\000\\026\\353\\004E\\030"; + const char *bad_s = "\\000\\001\\000\\001\\425\\3251\\227\\000\\026\\353\\004E\\030"; - test_one_duid (test1_s, test1_u, sizeof (test1_u)); - test_one_duid (test2_s, test2_u, sizeof (test2_u)); - test_one_duid (test3_s, test3_u, sizeof (test3_u)); - test_one_duid (test4_s, test4_u, sizeof (test4_u)); + test_one_duid(test1_s, test1_u, sizeof(test1_u)); + test_one_duid(test2_s, test2_u, sizeof(test2_u)); + test_one_duid(test3_s, test3_u, sizeof(test3_u)); + test_one_duid(test4_s, test4_u, sizeof(test4_u)); - /* Invalid octal digit */ - g_assert (nm_dhcp_dhclient_unescape_duid (bad_s) == NULL); + /* Invalid octal digit */ + g_assert(nm_dhcp_dhclient_unescape_duid(bad_s) == NULL); } static void -test_read_duid_from_leasefile (void) +test_read_duid_from_leasefile(void) { - const guint8 expected[] = { 0x00, 0x01, 0x00, 0x01, 0x18, 0x79, 0xa6, - 0x13, 0x60, 0x67, 0x20, 0xec, 0x4c, 0x70 }; - gs_unref_bytes GBytes *duid = NULL; - GError *error = NULL; + const guint8 expected[] = + {0x00, 0x01, 0x00, 0x01, 0x18, 0x79, 0xa6, 0x13, 0x60, 0x67, 0x20, 0xec, 0x4c, 0x70}; + gs_unref_bytes GBytes *duid = NULL; + GError * error = NULL; - duid = nm_dhcp_dhclient_read_duid (TEST_DIR"/test-dhclient-duid.leases", &error); - nmtst_assert_success (duid, error); + duid = nm_dhcp_dhclient_read_duid(TEST_DIR "/test-dhclient-duid.leases", &error); + nmtst_assert_success(duid, error); - g_assert (nm_utils_gbytes_equal_mem (duid, expected, G_N_ELEMENTS (expected))); + g_assert(nm_utils_gbytes_equal_mem(duid, expected, G_N_ELEMENTS(expected))); } static void -test_read_commented_duid_from_leasefile (void) +test_read_commented_duid_from_leasefile(void) { - GBytes *duid; - GError *error = NULL; + GBytes *duid; + GError *error = NULL; - duid = nm_dhcp_dhclient_read_duid (TEST_DIR"/test-dhclient-commented-duid.leases", &error); - g_assert_no_error (error); - g_assert (duid == NULL); + duid = nm_dhcp_dhclient_read_duid(TEST_DIR "/test-dhclient-commented-duid.leases", &error); + g_assert_no_error(error); + g_assert(duid == NULL); } /*****************************************************************************/ static void -_save_duid (const char *path, - const guint8 *duid_bin, - gsize duid_len) +_save_duid(const char *path, const guint8 *duid_bin, gsize duid_len) { - gs_unref_bytes GBytes *duid = NULL; - GError *error = NULL; - gboolean success; + gs_unref_bytes GBytes *duid = NULL; + GError * error = NULL; + gboolean success; - g_assert (path); - g_assert (duid_bin); - g_assert (duid_len > 0); + g_assert(path); + g_assert(duid_bin); + g_assert(duid_len > 0); - duid = g_bytes_new (duid_bin, duid_len); - success = nm_dhcp_dhclient_save_duid (path, duid, &error); - nmtst_assert_success (success, error); + duid = g_bytes_new(duid_bin, duid_len); + success = nm_dhcp_dhclient_save_duid(path, duid, &error); + nmtst_assert_success(success, error); } static void -test_write_duid (void) +test_write_duid(void) { - const guint8 duid[] = { 000, 001, 000, 001, 027, 'X', 0350, 'X', 0, '#', 025, 010, '~', 0254 }; - const char *expected_contents = "default-duid \"\\000\\001\\000\\001\\027X\\350X\\000#\\025\\010~\\254\";\n"; - GError *error = NULL; - gs_free char *contents = NULL; - gboolean success; - const char *path = "test-dhclient-write-duid.leases"; + const guint8 duid[] = {000, 001, 000, 001, 027, 'X', 0350, 'X', 0, '#', 025, 010, '~', 0254}; + const char * expected_contents = + "default-duid \"\\000\\001\\000\\001\\027X\\350X\\000#\\025\\010~\\254\";\n"; + GError * error = NULL; + gs_free char *contents = NULL; + gboolean success; + const char * path = "test-dhclient-write-duid.leases"; - _save_duid (path, duid, G_N_ELEMENTS (duid)); + _save_duid(path, duid, G_N_ELEMENTS(duid)); - success = g_file_get_contents (path, &contents, NULL, &error); - nmtst_assert_success (success, error); + success = g_file_get_contents(path, &contents, NULL, &error); + nmtst_assert_success(success, error); - unlink (path); + unlink(path); - g_assert_cmpstr (expected_contents, ==, contents); + g_assert_cmpstr(expected_contents, ==, contents); } static void -test_write_existing_duid (void) +test_write_existing_duid(void) { - const guint8 duid[] = { 000, 001, 000, 001, 023, 'o', 023, 'n', 000, '"', 0372, 0214, 0326, 0302 }; - const char *original_contents = "default-duid \"\\000\\001\\000\\001\\027X\\350X\\000#\\025\\010~\\254\";\n"; - const char *expected_contents = "default-duid \"\\000\\001\\000\\001\\023o\\023n\\000\\\"\\372\\214\\326\\302\";\n"; - GError *error = NULL; - gs_free char *contents = NULL; - gboolean success; - const char *path = "test-dhclient-write-existing-duid.leases"; - - success = g_file_set_contents (path, original_contents, -1, &error); - nmtst_assert_success (success, error); - - /* Save other DUID; should be overwritten */ - _save_duid (path, duid, G_N_ELEMENTS (duid)); - - /* reread original contents */ - success = g_file_get_contents (path, &contents, NULL, &error); - nmtst_assert_success (success, error); - - unlink (path); - g_assert_cmpstr (expected_contents, ==, contents); + const guint8 duid[] = + {000, 001, 000, 001, 023, 'o', 023, 'n', 000, '"', 0372, 0214, 0326, 0302}; + const char *original_contents = + "default-duid \"\\000\\001\\000\\001\\027X\\350X\\000#\\025\\010~\\254\";\n"; + const char *expected_contents = + "default-duid \"\\000\\001\\000\\001\\023o\\023n\\000\\\"\\372\\214\\326\\302\";\n"; + GError * error = NULL; + gs_free char *contents = NULL; + gboolean success; + const char * path = "test-dhclient-write-existing-duid.leases"; + + success = g_file_set_contents(path, original_contents, -1, &error); + nmtst_assert_success(success, error); + + /* Save other DUID; should be overwritten */ + _save_duid(path, duid, G_N_ELEMENTS(duid)); + + /* reread original contents */ + success = g_file_get_contents(path, &contents, NULL, &error); + nmtst_assert_success(success, error); + + unlink(path); + g_assert_cmpstr(expected_contents, ==, contents); } -static const guint8 DUID_BIN[] = { 000, 001, 000, 001, 023, 'o', 023, 'n', 000, '"', 0372, 0214, 0326, 0302 }; +static const guint8 DUID_BIN[] = + {000, 001, 000, 001, 023, 'o', 023, 'n', 000, '"', 0372, 0214, 0326, 0302}; #define DUID "\\000\\001\\000\\001\\023o\\023n\\000\\\"\\372\\214\\326\\302" static void -test_write_existing_commented_duid (void) +test_write_existing_commented_duid(void) { #define ORIG_CONTENTS "#default-duid \"\\000\\001\\000\\001\\027X\\350X\\000#\\025\\010~\\254\";\n" - const char *expected_contents = - "default-duid \"" DUID "\";\n" - ORIG_CONTENTS; - GError *error = NULL; - gs_free char *contents = NULL; - gboolean success; - const char *path = "test-dhclient-write-existing-commented-duid.leases"; - - success = g_file_set_contents (path, ORIG_CONTENTS, -1, &error); - nmtst_assert_success (success, error); - - /* Save other DUID; should be saved on top */ - _save_duid (path, DUID_BIN, G_N_ELEMENTS (DUID_BIN)); - - /* reread original contents */ - success = g_file_get_contents (path, &contents, NULL, &error); - nmtst_assert_success (success, error); - - unlink (path); - g_assert_cmpstr (expected_contents, ==, contents); + const char * expected_contents = "default-duid \"" DUID "\";\n" ORIG_CONTENTS; + GError * error = NULL; + gs_free char *contents = NULL; + gboolean success; + const char * path = "test-dhclient-write-existing-commented-duid.leases"; + + success = g_file_set_contents(path, ORIG_CONTENTS, -1, &error); + nmtst_assert_success(success, error); + + /* Save other DUID; should be saved on top */ + _save_duid(path, DUID_BIN, G_N_ELEMENTS(DUID_BIN)); + + /* reread original contents */ + success = g_file_get_contents(path, &contents, NULL, &error); + nmtst_assert_success(success, error); + + unlink(path); + g_assert_cmpstr(expected_contents, ==, contents); #undef ORIG_CONTENTS } static void -test_write_existing_multiline_duid (void) +test_write_existing_multiline_duid(void) { -#define ORIG_CONTENTS "### Commented old DUID ###\n" \ - "#default-duid \"\\000\\001\\000\\001\\027X\\350X\\000#\\025\\010~\\254\";\n" - const char *expected_contents = \ - "default-duid \"" DUID "\";\n" - ORIG_CONTENTS; - GError *error = NULL; - gs_free char *contents = NULL; - gboolean success; - nmtst_auto_unlinkfile char *path = g_strdup ("test-dhclient-write-existing-multiline-duid.leases"); +#define ORIG_CONTENTS \ + "### Commented old DUID ###\n" \ + "#default-duid \"\\000\\001\\000\\001\\027X\\350X\\000#\\025\\010~\\254\";\n" + const char * expected_contents = "default-duid \"" DUID "\";\n" ORIG_CONTENTS; + GError * error = NULL; + gs_free char * contents = NULL; + gboolean success; + nmtst_auto_unlinkfile char *path = + g_strdup("test-dhclient-write-existing-multiline-duid.leases"); - success = g_file_set_contents (path, ORIG_CONTENTS, -1, &error); - nmtst_assert_success (success, error); + success = g_file_set_contents(path, ORIG_CONTENTS, -1, &error); + nmtst_assert_success(success, error); - _save_duid (path, DUID_BIN, G_N_ELEMENTS (DUID_BIN)); + _save_duid(path, DUID_BIN, G_N_ELEMENTS(DUID_BIN)); - success = g_file_get_contents (path, &contents, NULL, &error); - nmtst_assert_success (success, error); + success = g_file_get_contents(path, &contents, NULL, &error); + nmtst_assert_success(success, error); - g_assert_cmpstr (expected_contents, ==, contents); + g_assert_cmpstr(expected_contents, ==, contents); #undef ORIG_CONTENTS } /*****************************************************************************/ -static const char *interface1_orig = \ - "interface \"eth0\" {\n" - "\talso request my-option;\n" - "\tinitial-delay 5;\n" - "}\n" - "interface \"eth1\" {\n" - "\talso request another-option;\n" - "\tinitial-delay 0;\n" - "}\n" - "\n" - "also request yet-another-option;\n"; - -static const char *interface1_expected = \ - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "initial-delay 5;\n" - "\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "also request my-option;\n" - "also request yet-another-option;\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n" - "\n"; +static const char *interface1_orig = "interface \"eth0\" {\n" + "\talso request my-option;\n" + "\tinitial-delay 5;\n" + "}\n" + "interface \"eth1\" {\n" + "\talso request another-option;\n" + "\tinitial-delay 0;\n" + "}\n" + "\n" + "also request yet-another-option;\n"; + +static const char *interface1_expected = + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n" + "initial-delay 5;\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "also request my-option;\n" + "also request yet-another-option;\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n" + "\n"; static void -test_interface1 (void) +test_interface1(void) { - test_config (interface1_orig, interface1_expected, - AF_INET, NULL, 0, FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - NULL, - "eth0", - NULL, - NULL); + test_config(interface1_orig, + interface1_expected, + AF_INET, + NULL, + 0, + FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + NULL, + NULL, + "eth0", + NULL, + NULL); } /*****************************************************************************/ -static const char *interface2_orig = \ - "interface eth0 {\n" - "\talso request my-option;\n" - "\tinitial-delay 5;\n" - " }\n" - "interface eth1 {\n" - "\tinitial-delay 0;\n" - "\trequest another-option;\n" - " } \n" - "\n" - "also request yet-another-option;\n"; - -static const char *interface2_expected = \ - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "initial-delay 0;\n" - "\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "request; # override dhclient defaults\n" - "also request another-option;\n" - "also request yet-another-option;\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n" - "\n"; +static const char *interface2_orig = "interface eth0 {\n" + "\talso request my-option;\n" + "\tinitial-delay 5;\n" + " }\n" + "interface eth1 {\n" + "\tinitial-delay 0;\n" + "\trequest another-option;\n" + " } \n" + "\n" + "also request yet-another-option;\n"; + +static const char *interface2_expected = + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n" + "initial-delay 0;\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "request; # override dhclient defaults\n" + "also request another-option;\n" + "also request yet-another-option;\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n" + "\n"; static void -test_interface2 (void) +test_interface2(void) { - test_config (interface2_orig, interface2_expected, - AF_INET, NULL, 0, FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - NULL, - "eth1", - NULL, - NULL); + test_config(interface2_orig, + interface2_expected, + AF_INET, + NULL, + 0, + FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + NULL, + NULL, + "eth1", + NULL, + NULL); } static void -test_structured (void) +test_structured(void) { - gs_unref_bytes GBytes *new_client_id = NULL; - const guint8 bytes[] = "sad-and-useless"; - - static const char *const orig = \ - "interface \"eth0\" { \n" - " send host-name \"useless.example.com\";\n" - " hardware ethernet de:ad:80:86:ba:be;\n" - " send dhcp-client-identifier \"sad-and-useless\";\n" - " script \"/bin/useless\";\n" - " send dhcp-lease-time 8086;\n" - " request subnet-mask, broadcast-address, time-offset, routers,\n" - " domain-search, domain-name, host-name;\n" - " require subnet-mask;\n" - "} \n" - "\n" - " interface \"eth1\" { \n" - " send host-name \"sad.example.com\";\n" - " hardware ethernet de:ca:f6:66:ca:fe;\n" - " send dhcp-client-identifier \"useless-and-miserable\";\n" - " script \"/bin/miserable\";\n" - " send dhcp-lease-time 1337;\n" - " request subnet-mask, broadcast-address, time-offset, routers,\n" - " domain-search, domain-name, domain-name-servers, host-name;\n" - " require subnet-mask, domain-name-servers;\n" - " if not option domain-name = \"example.org\" {\n" - " prepend domain-name-servers 127.0.0.1;\n" - " } else {\n" - " prepend domain-name-servers 127.0.0.2;\n" - " } \n" - " } \n" - "\n" - "pseudo \"secondary\" \"eth0\" { \n" - " send dhcp-client-identifier \"sad-useless-and-secondary\";\n" - " script \"/bin/secondary\";\n" - " send host-name \"secondary.useless.example.com\";\n" - " send dhcp-lease-time 666;\n" - " request routers;\n" - " require routers;\n" - " } \n" - "\n" - " pseudo \"tertiary\" \"eth0\" { \n" - " send dhcp-client-identifier \"sad-useless-and-tertiary\";\n" - " script \"/bin/tertiary\";\n" - " send host-name \"tertiary.useless.example.com\";\n" - "} \n" - "\n" - " alias{ \n" - " interface \"eth0\";\n" - " fixed-address 192.0.2.1;\n" - " option subnet-mask 255.255.255.0;\n" - " } \n" - " lease { \n" - " interface \"eth0\";\n" - " fixed-address 192.0.2.2;\n" - " option subnet-mask 255.255.255.0;\n" - " } \n" - "if not option domain-name = \"example.org\" {\n" - " prepend domain-name-servers 127.0.0.1;\n" - " if not option domain-name = \"useless.example.com\" {\n" - " prepend domain-name-servers 127.0.0.2;\n" - " }\n" - "}\n"; - - static const char *const expected = \ - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "send host-name \"useless.example.com\";\n" - "hardware ethernet de:ad:80:86:ba:be;\n" - "send dhcp-client-identifier \"sad-and-useless\";\n" - "send dhcp-lease-time 8086;\n" - "require subnet-mask;\n" - "if not option domain-name = \"example.org\" {\n" - "prepend domain-name-servers 127.0.0.1;\n" - "if not option domain-name = \"useless.example.com\" {\n" - "prepend domain-name-servers 127.0.0.2;\n" - "}\n" - "}\n" - "\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "request; # override dhclient defaults\n" - "also request subnet-mask;\n" - "also request broadcast-address;\n" - "also request time-offset;\n" - "also request routers;\n" - "also request domain-search;\n" - "also request domain-name;\n" - "also request host-name;\n" - "also request rfc3442-classless-static-routes;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request ntp-servers;\n" - "also request root-path;\n" - "\n"; - - new_client_id = g_bytes_new (bytes, sizeof (bytes) - 1); - test_config (orig, expected, - AF_INET, NULL, 0, FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - new_client_id, - "eth0", - NULL, - NULL); + gs_unref_bytes GBytes *new_client_id = NULL; + const guint8 bytes[] = "sad-and-useless"; + + static const char *const orig = + "interface \"eth0\" { \n" + " send host-name \"useless.example.com\";\n" + " hardware ethernet de:ad:80:86:ba:be;\n" + " send dhcp-client-identifier \"sad-and-useless\";\n" + " script \"/bin/useless\";\n" + " send dhcp-lease-time 8086;\n" + " request subnet-mask, broadcast-address, time-offset, routers,\n" + " domain-search, domain-name, host-name;\n" + " require subnet-mask;\n" + "} \n" + "\n" + " interface \"eth1\" { \n" + " send host-name \"sad.example.com\";\n" + " hardware ethernet de:ca:f6:66:ca:fe;\n" + " send dhcp-client-identifier \"useless-and-miserable\";\n" + " script \"/bin/miserable\";\n" + " send dhcp-lease-time 1337;\n" + " request subnet-mask, broadcast-address, time-offset, routers,\n" + " domain-search, domain-name, domain-name-servers, host-name;\n" + " require subnet-mask, domain-name-servers;\n" + " if not option domain-name = \"example.org\" {\n" + " prepend domain-name-servers 127.0.0.1;\n" + " } else {\n" + " prepend domain-name-servers 127.0.0.2;\n" + " } \n" + " } \n" + "\n" + "pseudo \"secondary\" \"eth0\" { \n" + " send dhcp-client-identifier \"sad-useless-and-secondary\";\n" + " script \"/bin/secondary\";\n" + " send host-name \"secondary.useless.example.com\";\n" + " send dhcp-lease-time 666;\n" + " request routers;\n" + " require routers;\n" + " } \n" + "\n" + " pseudo \"tertiary\" \"eth0\" { \n" + " send dhcp-client-identifier \"sad-useless-and-tertiary\";\n" + " script \"/bin/tertiary\";\n" + " send host-name \"tertiary.useless.example.com\";\n" + "} \n" + "\n" + " alias{ \n" + " interface \"eth0\";\n" + " fixed-address 192.0.2.1;\n" + " option subnet-mask 255.255.255.0;\n" + " } \n" + " lease { \n" + " interface \"eth0\";\n" + " fixed-address 192.0.2.2;\n" + " option subnet-mask 255.255.255.0;\n" + " } \n" + "if not option domain-name = \"example.org\" {\n" + " prepend domain-name-servers 127.0.0.1;\n" + " if not option domain-name = \"useless.example.com\" {\n" + " prepend domain-name-servers 127.0.0.2;\n" + " }\n" + "}\n"; + + static const char *const expected = + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n" + "send host-name \"useless.example.com\";\n" + "hardware ethernet de:ad:80:86:ba:be;\n" + "send dhcp-client-identifier \"sad-and-useless\";\n" + "send dhcp-lease-time 8086;\n" + "require subnet-mask;\n" + "if not option domain-name = \"example.org\" {\n" + "prepend domain-name-servers 127.0.0.1;\n" + "if not option domain-name = \"useless.example.com\" {\n" + "prepend domain-name-servers 127.0.0.2;\n" + "}\n" + "}\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "request; # override dhclient defaults\n" + "also request subnet-mask;\n" + "also request broadcast-address;\n" + "also request time-offset;\n" + "also request routers;\n" + "also request domain-search;\n" + "also request domain-name;\n" + "also request host-name;\n" + "also request rfc3442-classless-static-routes;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request ntp-servers;\n" + "also request root-path;\n" + "\n"; + + new_client_id = g_bytes_new(bytes, sizeof(bytes) - 1); + test_config(orig, + expected, + AF_INET, + NULL, + 0, + FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + NULL, + new_client_id, + "eth0", + NULL, + NULL); } static void -test_config_req_intf (void) +test_config_req_intf(void) { - static const char *const orig = \ - "request subnet-mask, broadcast-address, routers,\n" - "\trfc3442-classless-static-routes,\n" - "\tinterface-mtu, host-name, domain-name, domain-search,\n" - "\tdomain-name-servers, nis-domain, nis-servers,\n" - "\tnds-context, nds-servers, nds-tree-name,\n" - "\tnetbios-name-servers, netbios-dd-server,\n" - "\tnetbios-node-type, netbios-scope, ntp-servers;\n" - ""; - static const char *const expected = \ - "# Created by NetworkManager\n" - "# Merged from /path/to/dhclient.conf\n" - "\n" - "\n" - "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" - "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" - "option wpad code 252 = string;\n" - "\n" - "request; # override dhclient defaults\n" - "also request subnet-mask;\n" - "also request broadcast-address;\n" - "also request routers;\n" - "also request rfc3442-classless-static-routes;\n" - "also request interface-mtu;\n" - "also request host-name;\n" - "also request domain-name;\n" - "also request domain-search;\n" - "also request domain-name-servers;\n" - "also request nis-domain;\n" - "also request nis-servers;\n" - "also request nds-context;\n" - "also request nds-servers;\n" - "also request nds-tree-name;\n" - "also request netbios-name-servers;\n" - "also request netbios-dd-server;\n" - "also request netbios-node-type;\n" - "also request netbios-scope;\n" - "also request ntp-servers;\n" - "also request ms-classless-static-routes;\n" - "also request static-routes;\n" - "also request wpad;\n" - "also request root-path;\n" - "\n"; - - test_config (orig, expected, - AF_INET, NULL, 0, FALSE, - NM_DHCP_HOSTNAME_FLAG_NONE, - NULL, - NULL, - "eth0", - NULL, - NULL); + static const char *const orig = "request subnet-mask, broadcast-address, routers,\n" + "\trfc3442-classless-static-routes,\n" + "\tinterface-mtu, host-name, domain-name, domain-search,\n" + "\tdomain-name-servers, nis-domain, nis-servers,\n" + "\tnds-context, nds-servers, nds-tree-name,\n" + "\tnetbios-name-servers, netbios-dd-server,\n" + "\tnetbios-node-type, netbios-scope, ntp-servers;\n" + ""; + static const char *const expected = + "# Created by NetworkManager\n" + "# Merged from /path/to/dhclient.conf\n" + "\n" + "\n" + "option rfc3442-classless-static-routes code 121 = array of unsigned integer 8;\n" + "option ms-classless-static-routes code 249 = array of unsigned integer 8;\n" + "option wpad code 252 = string;\n" + "\n" + "request; # override dhclient defaults\n" + "also request subnet-mask;\n" + "also request broadcast-address;\n" + "also request routers;\n" + "also request rfc3442-classless-static-routes;\n" + "also request interface-mtu;\n" + "also request host-name;\n" + "also request domain-name;\n" + "also request domain-search;\n" + "also request domain-name-servers;\n" + "also request nis-domain;\n" + "also request nis-servers;\n" + "also request nds-context;\n" + "also request nds-servers;\n" + "also request nds-tree-name;\n" + "also request netbios-name-servers;\n" + "also request netbios-dd-server;\n" + "also request netbios-node-type;\n" + "also request netbios-scope;\n" + "also request ntp-servers;\n" + "also request ms-classless-static-routes;\n" + "also request static-routes;\n" + "also request wpad;\n" + "also request root-path;\n" + "\n"; + + test_config(orig, + expected, + AF_INET, + NULL, + 0, + FALSE, + NM_DHCP_HOSTNAME_FLAG_NONE, + NULL, + NULL, + "eth0", + NULL, + NULL); } /*****************************************************************************/ -NMTST_DEFINE (); +NMTST_DEFINE(); int -main (int argc, char **argv) +main(int argc, char **argv) { - nmtst_init_with_logging (&argc, &argv, NULL, "DEFAULT"); - - g_test_add_func ("/dhcp/dhclient/orig_missing", test_orig_missing); - g_test_add_func ("/dhcp/dhclient/orig_missing_add_mud_url", test_orig_missing_add_mud_url); - g_test_add_func ("/dhcp/dhclient/override_client_id", test_override_client_id); - g_test_add_func ("/dhcp/dhclient/quote_client_id/1", test_quote_client_id); - g_test_add_func ("/dhcp/dhclient/quote_client_id/2", test_quote_client_id_2); - g_test_add_func ("/dhcp/dhclient/hex_zero_client_id", test_hex_zero_client_id); - g_test_add_func ("/dhcp/dhclient/ascii_client_id", test_ascii_client_id); - g_test_add_func ("/dhcp/dhclient/hex_single_client_id", test_hex_single_client_id); - g_test_add_func ("/dhcp/dhclient/existing-hex-client-id", test_existing_hex_client_id); - g_test_add_func ("/dhcp/dhclient/existing-client-id", test_existing_escaped_client_id); - g_test_add_func ("/dhcp/dhclient/existing-ascii-client-id", test_existing_ascii_client_id); - g_test_add_func ("/dhcp/dhclient/fqdn", test_fqdn); - g_test_add_func ("/dhcp/dhclient/fqdn_options_override", test_fqdn_options_override); - g_test_add_func ("/dhcp/dhclient/override_hostname", test_override_hostname); - g_test_add_func ("/dhcp/dhclient/override_hostname6", test_override_hostname6); - g_test_add_func ("/dhcp/dhclient/nonfqdn_hostname6", test_nonfqdn_hostname6); - g_test_add_func ("/dhcp/dhclient/existing_req", test_existing_req); - g_test_add_func ("/dhcp/dhclient/existing_alsoreq", test_existing_alsoreq); - g_test_add_func ("/dhcp/dhclient/existing_multiline_alsoreq", test_existing_multiline_alsoreq); - g_test_add_func ("/dhcp/dhclient/duids", test_duids); - g_test_add_func ("/dhcp/dhclient/interface/1", test_interface1); - g_test_add_func ("/dhcp/dhclient/interface/2", test_interface2); - g_test_add_func ("/dhcp/dhclient/config/req_intf", test_config_req_intf); - g_test_add_func ("/dhcp/dhclient/structured", test_structured); - - g_test_add_func ("/dhcp/dhclient/read_duid_from_leasefile", test_read_duid_from_leasefile); - g_test_add_func ("/dhcp/dhclient/read_commented_duid_from_leasefile", test_read_commented_duid_from_leasefile); - - g_test_add_func ("/dhcp/dhclient/write_duid", test_write_duid); - g_test_add_func ("/dhcp/dhclient/write_existing_duid", test_write_existing_duid); - g_test_add_func ("/dhcp/dhclient/write_existing_commented_duid", test_write_existing_commented_duid); - g_test_add_func ("/dhcp/dhclient/write_existing_multiline_duid", test_write_existing_multiline_duid); - - return g_test_run (); + nmtst_init_with_logging(&argc, &argv, NULL, "DEFAULT"); + + g_test_add_func("/dhcp/dhclient/orig_missing", test_orig_missing); + g_test_add_func("/dhcp/dhclient/orig_missing_add_mud_url", test_orig_missing_add_mud_url); + g_test_add_func("/dhcp/dhclient/override_client_id", test_override_client_id); + g_test_add_func("/dhcp/dhclient/quote_client_id/1", test_quote_client_id); + g_test_add_func("/dhcp/dhclient/quote_client_id/2", test_quote_client_id_2); + g_test_add_func("/dhcp/dhclient/hex_zero_client_id", test_hex_zero_client_id); + g_test_add_func("/dhcp/dhclient/ascii_client_id", test_ascii_client_id); + g_test_add_func("/dhcp/dhclient/hex_single_client_id", test_hex_single_client_id); + g_test_add_func("/dhcp/dhclient/existing-hex-client-id", test_existing_hex_client_id); + g_test_add_func("/dhcp/dhclient/existing-client-id", test_existing_escaped_client_id); + g_test_add_func("/dhcp/dhclient/existing-ascii-client-id", test_existing_ascii_client_id); + g_test_add_func("/dhcp/dhclient/fqdn", test_fqdn); + g_test_add_func("/dhcp/dhclient/fqdn_options_override", test_fqdn_options_override); + g_test_add_func("/dhcp/dhclient/override_hostname", test_override_hostname); + g_test_add_func("/dhcp/dhclient/override_hostname6", test_override_hostname6); + g_test_add_func("/dhcp/dhclient/nonfqdn_hostname6", test_nonfqdn_hostname6); + g_test_add_func("/dhcp/dhclient/existing_req", test_existing_req); + g_test_add_func("/dhcp/dhclient/existing_alsoreq", test_existing_alsoreq); + g_test_add_func("/dhcp/dhclient/existing_multiline_alsoreq", test_existing_multiline_alsoreq); + g_test_add_func("/dhcp/dhclient/duids", test_duids); + g_test_add_func("/dhcp/dhclient/interface/1", test_interface1); + g_test_add_func("/dhcp/dhclient/interface/2", test_interface2); + g_test_add_func("/dhcp/dhclient/config/req_intf", test_config_req_intf); + g_test_add_func("/dhcp/dhclient/structured", test_structured); + + g_test_add_func("/dhcp/dhclient/read_duid_from_leasefile", test_read_duid_from_leasefile); + g_test_add_func("/dhcp/dhclient/read_commented_duid_from_leasefile", + test_read_commented_duid_from_leasefile); + + g_test_add_func("/dhcp/dhclient/write_duid", test_write_duid); + g_test_add_func("/dhcp/dhclient/write_existing_duid", test_write_existing_duid); + g_test_add_func("/dhcp/dhclient/write_existing_commented_duid", + test_write_existing_commented_duid); + g_test_add_func("/dhcp/dhclient/write_existing_multiline_duid", + test_write_existing_multiline_duid); + + return g_test_run(); } - diff --git a/src/dhcp/tests/test-dhcp-utils.c b/src/dhcp/tests/test-dhcp-utils.c index e601534e..50245c79 100644 --- a/src/dhcp/tests/test-dhcp-utils.c +++ b/src/dhcp/tests/test-dhcp-utils.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0+ +/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright (C) 2008 - 2014 Red Hat, Inc. */ @@ -18,776 +18,764 @@ #include "nm-test-utils-core.h" static NMIP4Config * -_ip4_config_from_options (int ifindex, - const char *iface, - GHashTable *options, - guint32 route_metric) +_ip4_config_from_options(int ifindex, const char *iface, GHashTable *options, guint32 route_metric) { - 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; + 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; } typedef struct { - const char *name; - const char *value; + const char *name; + const char *value; } Option; static GHashTable * -fill_table (const Option *test_options, GHashTable *table) +fill_table(const Option *test_options, GHashTable *table) { - const Option *opt; + const Option *opt; - if (!table) - table = g_hash_table_new_full (nm_str_hash, g_str_equal, NULL, NULL); - for (opt = test_options; opt->name; opt++) - g_hash_table_insert (table, (gpointer) opt->name, (gpointer) opt->value); - return table; + if (!table) + table = g_hash_table_new_full(nm_str_hash, g_str_equal, NULL, NULL); + for (opt = test_options; opt->name; opt++) + g_hash_table_insert(table, (gpointer) opt->name, (gpointer) opt->value); + return table; } static const Option generic_options[] = { - { "subnet_mask", "255.255.255.0" }, - { "ip_address", "192.168.1.106" }, - { "network_number", "192.168.1.0" }, - { "expiry", "1232324877" }, - { "dhcp_lease_time", "3600" }, - { "dhcp_server_identifier", "192.168.1.1" }, - { "routers", "192.168.1.1" }, - { "domain_name_servers", "216.254.95.2 216.231.41.2" }, - { "dhcp_message_type", "5" }, - { "broadcast_address", "192.168.1.255" }, - { "domain_search", "foobar.com blah.foobar.com" }, - { "host_name", "nmreallywhipsthe" }, - { "domain_name", "lamasass.com" }, - { "interface_mtu", "987" }, - { "static_routes", "10.1.1.5 10.1.1.1 100.99.88.56 10.1.1.1" }, - { NULL, NULL } -}; + {"subnet_mask", "255.255.255.0"}, + {"ip_address", "192.168.1.106"}, + {"network_number", "192.168.1.0"}, + {"expiry", "1232324877"}, + {"dhcp_lease_time", "3600"}, + {"dhcp_server_identifier", "192.168.1.1"}, + {"routers", "192.168.1.1"}, + {"domain_name_servers", "216.254.95.2 216.231.41.2"}, + {"dhcp_message_type", "5"}, + {"broadcast_address", "192.168.1.255"}, + {"domain_search", "foobar.com blah.foobar.com"}, + {"host_name", "nmreallywhipsthe"}, + {"domain_name", "lamasass.com"}, + {"interface_mtu", "987"}, + {"static_routes", "10.1.1.5 10.1.1.1 100.99.88.56 10.1.1.1"}, + {NULL, NULL}}; static void -test_generic_options (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); - 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); - - g_assert_cmpint (nm_ip4_config_get_num_wins (ip4_config), ==, 0); - - g_assert_cmpint (nm_ip4_config_get_mtu (ip4_config), ==, 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); - - /* 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); - - /* Routes */ - g_assert_cmpint (nm_ip4_config_get_num_routes (ip4_config), ==, 3); - - /* Route #1 */ - route = _nmtst_ip4_config_get_route (ip4_config, 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); - g_assert (route->gateway == tmp); - g_assert_cmpint (route->plen, ==, 32); - g_assert_cmpint (route->metric, ==, 0); - - /* Route #2 */ - route = _nmtst_ip4_config_get_route (ip4_config, 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); - 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); + 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); + 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); + + g_assert_cmpint(nm_ip4_config_get_num_wins(ip4_config), ==, 0); + + g_assert_cmpint(nm_ip4_config_get_mtu(ip4_config), ==, 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); + + /* 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); + + /* Routes */ + g_assert_cmpint(nm_ip4_config_get_num_routes(ip4_config), ==, 3); + + /* Route #1 */ + route = _nmtst_ip4_config_get_route(ip4_config, 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); + g_assert(route->gateway == tmp); + g_assert_cmpint(route->plen, ==, 32); + g_assert_cmpint(route->metric, ==, 0); + + /* Route #2 */ + route = _nmtst_ip4_config_get_route(ip4_config, 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); + 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) +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" }, - { NULL, NULL } - }; - - options = fill_table (generic_options, NULL); - options = fill_table (data, options); - 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); - 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); + 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"}, + {NULL, NULL}}; + + options = fill_table(generic_options, NULL); + options = fill_table(data, options); + 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); + 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); } static void -test_vendor_option_metered (void) +test_vendor_option_metered(void) { - GHashTable *options; - gs_unref_object NMIP4Config *ip4_config = 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); + GHashTable * options; + gs_unref_object NMIP4Config *ip4_config = 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); } static void -test_parse_search_list (void) +test_parse_search_list(void) { - guint8 *data; - char **domains; - - data = (guint8 []) { - 0x05, 'l', 'o', 'c', 'a', 'l', - 0x00 - }; - domains = nm_dhcp_parse_search_list (data, 7); - g_assert (domains); - g_assert_cmpint (g_strv_length (domains), ==, 1); - g_assert_cmpstr (domains[0], ==, "local"); - g_strfreev (domains); - - data = (guint8 []) { - 0x04, 't', 'e', 's', 't', - 0x07, 'e', 'x', 'a', 'm', 'p', 'l', 'e', - 0x03, 'c', 'o', 'm', - 0x00, - 0xc0, 0x05, - 0x03, 'a', 'b', 'c', - 0xc0, 0x0d, - 0x06, 'f', 'o', 'o', 'b', 'a', 'r', - 0x00 - }; - domains = nm_dhcp_parse_search_list (data, 34); - g_assert (domains); - g_assert_cmpint (g_strv_length (domains), ==, 4); - g_assert_cmpstr (domains[0], ==, "test.example.com"); - g_assert_cmpstr (domains[1], ==, "example.com"); - g_assert_cmpstr (domains[2], ==, "abc.com"); - g_assert_cmpstr (domains[3], ==, "foobar"); - g_strfreev (domains); - - data = (guint8 []) { - 0x40, 'b', 'a', 'd', - }; - domains = nm_dhcp_parse_search_list (data, 4); - g_assert (!domains); - - data = (guint8 []) { - 0x04, 'o', 'k', 'a', 'y', - 0x00, - 0x40, 'b', 'a', 'd', - }; - domains = nm_dhcp_parse_search_list (data, 10); - g_assert (domains); - g_assert_cmpint (g_strv_length (domains), ==, 1); - g_assert_cmpstr (domains[0], ==, "okay"); - g_strfreev (domains); + guint8 *data; + char ** domains; + + data = (guint8[]){0x05, 'l', 'o', 'c', 'a', 'l', 0x00}; + domains = nm_dhcp_parse_search_list(data, 7); + g_assert(domains); + g_assert_cmpint(g_strv_length(domains), ==, 1); + g_assert_cmpstr(domains[0], ==, "local"); + g_strfreev(domains); + + data = (guint8[]){0x04, 't', 'e', 's', 't', 0x07, 'e', 'x', 'a', 'm', 'p', 'l', + 'e', 0x03, 'c', 'o', 'm', 0x00, 0xc0, 0x05, 0x03, 'a', 'b', 'c', + 0xc0, 0x0d, 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x00}; + domains = nm_dhcp_parse_search_list(data, 34); + g_assert(domains); + g_assert_cmpint(g_strv_length(domains), ==, 4); + g_assert_cmpstr(domains[0], ==, "test.example.com"); + g_assert_cmpstr(domains[1], ==, "example.com"); + g_assert_cmpstr(domains[2], ==, "abc.com"); + g_assert_cmpstr(domains[3], ==, "foobar"); + g_strfreev(domains); + + data = (guint8[]){ + 0x40, + 'b', + 'a', + 'd', + }; + domains = nm_dhcp_parse_search_list(data, 4); + g_assert(!domains); + + data = (guint8[]){ + 0x04, + 'o', + 'k', + 'a', + 'y', + 0x00, + 0x40, + 'b', + 'a', + 'd', + }; + domains = nm_dhcp_parse_search_list(data, 10); + g_assert(domains); + g_assert_cmpint(g_strv_length(domains), ==, 1); + g_assert_cmpstr(domains[0], ==, "okay"); + g_strfreev(domains); } 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(NMIP4Config *ip4_config, + 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); - 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); - g_assert (route->gateway == tmp); - g_assert_cmpint (route->plen, ==, expected_prefix); - g_assert_cmpint (route->metric, ==, 0); + const NMPlatformIP4Route *route; + guint32 tmp; + + g_assert(expected_prefix <= 32); + + route = _nmtst_ip4_config_get_route(ip4_config, 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); + g_assert(route->gateway == tmp); + g_assert_cmpint(route->plen, ==, expected_prefix); + g_assert_cmpint(route->metric, ==, 0); } static void -ip4_test_gateway (NMIP4Config *ip4_config, const char *expected_gw) +ip4_test_gateway(NMIP4Config *ip4_config, const char *expected_gw) { - guint32 tmp; + 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); + 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); } static void -test_classless_static_routes_1 (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[] = { - /* 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); - - /* 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); + 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[] = { + /* 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); + + /* 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); } static void -test_classless_static_routes_2 (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[] = { - /* 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); - - /* 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); + 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[] = { + /* 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); + + /* 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); } static void -test_fedora_dhclient_classless_static_routes (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[] = { - /* 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); - - /* 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); - - /* Gateway */ - ip4_test_gateway (ip4_config, expected_gateway); - - g_hash_table_destroy (options); + 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[] = { + /* 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); + + /* 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); + + /* Gateway */ + ip4_test_gateway(ip4_config, expected_gateway); + + g_hash_table_destroy(options); } static void -test_dhclient_invalid_classless_routes_1 (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[] = { - /* dhclient format */ - { "rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 45 10 17 66 41" }, - { NULL, NULL } - }; - - options = fill_table (generic_options, NULL); - options = fill_table (data, options); - - NMTST_EXPECT_NM_WARN ("*ignoring invalid classless static routes*"); - ip4_config = _ip4_config_from_options (1, "eth0", options, 0); - 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); + 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[] = { + /* dhclient format */ + {"rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 45 10 17 66 41"}, + {NULL, NULL}}; + + options = fill_table(generic_options, NULL); + options = fill_table(data, options); + + NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*"); + ip4_config = _ip4_config_from_options(1, "eth0", options, 0); + 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); } static void -test_dhcpcd_invalid_classless_routes_1 (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[] = { - /* dhcpcd format */ - { "classless_static_routes", "192.168.10.0/24 192.168.1.1 10.0.adfadf/44 10.17.66.41" }, - { NULL, NULL } - }; - - options = fill_table (generic_options, NULL); - options = fill_table (data, options); - - NMTST_EXPECT_NM_WARN ("*ignoring invalid classless static routes*"); - ip4_config = _ip4_config_from_options (1, "eth0", options, 0); - 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); + 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[] = { + /* dhcpcd format */ + {"classless_static_routes", "192.168.10.0/24 192.168.1.1 10.0.adfadf/44 10.17.66.41"}, + {NULL, NULL}}; + + options = fill_table(generic_options, NULL); + options = fill_table(data, options); + + NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*"); + ip4_config = _ip4_config_from_options(1, "eth0", options, 0); + 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); } static void -test_dhclient_invalid_classless_routes_2 (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[] = { - { "rfc3442_classless_static_routes", "45 10 17 66 41 24 192 168 10 192 168 1 1" }, - { NULL, NULL } - }; - - options = fill_table (generic_options, NULL); - options = fill_table (data, options); - - NMTST_EXPECT_NM_WARN ("*ignoring invalid classless static routes*"); - ip4_config = _ip4_config_from_options (1, "eth0", options, 0); - 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); + 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[] = { + {"rfc3442_classless_static_routes", "45 10 17 66 41 24 192 168 10 192 168 1 1"}, + {NULL, NULL}}; + + options = fill_table(generic_options, NULL); + options = fill_table(data, options); + + NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*"); + ip4_config = _ip4_config_from_options(1, "eth0", options, 0); + 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); } static void -test_dhcpcd_invalid_classless_routes_2 (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[] = { - { "classless_static_routes", "10.0.adfadf/44 10.17.66.41 192.168.10.0/24 192.168.1.1" }, - { NULL, NULL } - }; - - options = fill_table (generic_options, NULL); - options = fill_table (data, options); - - NMTST_EXPECT_NM_WARN ("*ignoring invalid classless static routes*"); - ip4_config = _ip4_config_from_options (1, "eth0", options, 0); - g_test_assert_expected_messages (); - - /* Test falling back to old-style static routes if the classless static - * routes are invalid. - */ - - /* 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); + 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[] = { + {"classless_static_routes", "10.0.adfadf/44 10.17.66.41 192.168.10.0/24 192.168.1.1"}, + {NULL, NULL}}; + + options = fill_table(generic_options, NULL); + options = fill_table(data, options); + + NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*"); + ip4_config = _ip4_config_from_options(1, "eth0", options, 0); + g_test_assert_expected_messages(); + + /* Test falling back to old-style static routes if the classless static + * routes are invalid. + */ + + /* 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); } static void -test_dhclient_invalid_classless_routes_3 (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[] = { - { "rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 32 128 10 17 66 41" }, - { NULL, NULL } - }; - - options = fill_table (generic_options, NULL); - options = fill_table (data, options); - - NMTST_EXPECT_NM_WARN ("*ignoring invalid classless static routes*"); - ip4_config = _ip4_config_from_options (1, "eth0", options, 0); - 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); + 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[] = { + {"rfc3442_classless_static_routes", "24 192 168 10 192 168 1 1 32 128 10 17 66 41"}, + {NULL, NULL}}; + + options = fill_table(generic_options, NULL); + options = fill_table(data, options); + + NMTST_EXPECT_NM_WARN("*ignoring invalid classless static routes*"); + ip4_config = _ip4_config_from_options(1, "eth0", options, 0); + 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); } static void -test_dhcpcd_invalid_classless_routes_3 (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[] = { - { "classless_static_routes", "192.168.10.0/24 192.168.1.1 128/32 10.17.66.41" }, - { NULL, NULL } - }; - - options = fill_table (generic_options, NULL); - 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); - 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); + 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[] = { + {"classless_static_routes", "192.168.10.0/24 192.168.1.1 128/32 10.17.66.41"}, + {NULL, NULL}}; + + options = fill_table(generic_options, NULL); + 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); + 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); } static void -test_dhclient_gw_in_classless_routes (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[] = { - { "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); - - /* 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_hash_table_destroy (options); + 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[] = { + {"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); + + /* 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_hash_table_destroy(options); } static void -test_dhcpcd_gw_in_classless_routes (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[] = { - { "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); - - /* 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_hash_table_destroy (options); + 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[] = { + {"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); + + /* 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_hash_table_destroy(options); } static void -test_escaped_domain_searches (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"; - static const Option data[] = { - { "domain_search", "host1\\032host2\\032host3" }, - { NULL, NULL } - }; - - 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); - - g_hash_table_destroy (options); + GHashTable * options; + gs_unref_object NMIP4Config *ip4_config = 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}}; + + 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); + + g_hash_table_destroy(options); } static void -test_invalid_escaped_domain_searches (void) +test_invalid_escaped_domain_searches(void) { - GHashTable *options; - gs_unref_object NMIP4Config *ip4_config = NULL; - static const Option data[] = { - { "domain_search", "host1\\aahost2\\032host3" }, - { NULL, NULL } - }; + GHashTable * options; + gs_unref_object NMIP4Config *ip4_config = NULL; + static const Option data[] = {{"domain_search", "host1\\aahost2\\032host3"}, {NULL, NULL}}; - options = fill_table (generic_options, NULL); - options = fill_table (data, options); + 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); - g_test_assert_expected_messages (); + NMTST_EXPECT_NM_WARN("*invalid domain search*"); + ip4_config = _ip4_config_from_options(1, "eth0", options, 0); + g_test_assert_expected_messages(); - /* domain searches */ - g_assert_cmpint (nm_ip4_config_get_num_searches (ip4_config), ==, 0); + /* domain searches */ + g_assert_cmpint(nm_ip4_config_get_num_searches(ip4_config), ==, 0); - g_hash_table_destroy (options); + g_hash_table_destroy(options); } static void -test_ip4_missing_prefix (const char *ip, guint32 expected_prefix) +test_ip4_missing_prefix(const char *ip, guint32 expected_prefix) { - GHashTable *options; - gs_unref_object NMIP4Config *ip4_config = NULL; - const NMPlatformIP4Address *address; + GHashTable * options; + gs_unref_object NMIP4Config *ip4_config = 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"); + 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); + ip4_config = _ip4_config_from_options(1, "eth0", options, 0); - g_assert_cmpint (nm_ip4_config_get_num_addresses (ip4_config), ==, 1); - address = _nmtst_ip4_config_get_address (ip4_config, 0); - g_assert (address); - g_assert_cmpint (address->plen, ==, expected_prefix); + g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1); + address = _nmtst_ip4_config_get_address(ip4_config, 0); + g_assert(address); + g_assert_cmpint(address->plen, ==, expected_prefix); - g_hash_table_destroy (options); + g_hash_table_destroy(options); } static void -test_ip4_missing_prefix_24 (void) +test_ip4_missing_prefix_24(void) { - test_ip4_missing_prefix ("192.168.1.10", 24); + test_ip4_missing_prefix("192.168.1.10", 24); } static void -test_ip4_missing_prefix_16 (void) +test_ip4_missing_prefix_16(void) { - test_ip4_missing_prefix ("172.16.54.50", 16); + test_ip4_missing_prefix("172.16.54.50", 16); } static void -test_ip4_missing_prefix_8 (void) +test_ip4_missing_prefix_8(void) { - test_ip4_missing_prefix ("10.1.2.3", 8); + test_ip4_missing_prefix("10.1.2.3", 8); } static void -test_ip4_prefix_classless (void) +test_ip4_prefix_classless(void) { - GHashTable *options; - gs_unref_object NMIP4Config *ip4_config = NULL; - const NMPlatformIP4Address *address; + GHashTable * options; + gs_unref_object NMIP4Config *ip4_config = 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 - * doesn't send the subnet mask. - */ + /* Ensure that the missing-subnet-mask handler doesn't mangle classless + * subnet masks at all. The handler should trigger only if the server + * doesn't send the subnet mask. + */ - options = fill_table (generic_options, NULL); - g_hash_table_insert (options, "ip_address", "172.16.54.22"); - g_hash_table_insert (options, "subnet_mask", "255.255.252.0"); + options = fill_table(generic_options, NULL); + 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); + ip4_config = _ip4_config_from_options(1, "eth0", options, 0); - g_assert_cmpint (nm_ip4_config_get_num_addresses (ip4_config), ==, 1); - address = _nmtst_ip4_config_get_address (ip4_config, 0); - g_assert (address); - g_assert_cmpint (address->plen, ==, 22); + g_assert_cmpint(nm_ip4_config_get_num_addresses(ip4_config), ==, 1); + address = _nmtst_ip4_config_get_address(ip4_config, 0); + g_assert(address); + g_assert_cmpint(address->plen, ==, 22); - g_hash_table_destroy (options); + g_hash_table_destroy(options); } -#define COMPARE_ID(src, is_str, expected, expected_len) \ -G_STMT_START { \ - gs_unref_bytes GBytes *b = NULL; \ - const char *p; \ - gsize l; \ - \ - b = nm_dhcp_utils_client_id_string_to_bytes (src); \ - g_assert (b); \ - p = g_bytes_get_data (b, &l); \ - if (is_str) { \ - g_assert_cmpint (l, ==, expected_len + 1); \ - g_assert_cmpint (((const char *) p)[0], ==, 0); \ - g_assert (memcmp (p + 1, expected, expected_len) == 0); \ - } else { \ - g_assert_cmpint (l, ==, expected_len); \ - g_assert (memcmp (p, expected, expected_len) == 0); \ - } \ -} G_STMT_END +#define COMPARE_ID(src, is_str, expected, expected_len) \ + G_STMT_START \ + { \ + gs_unref_bytes GBytes *b = NULL; \ + const char * p; \ + gsize l; \ + \ + b = nm_dhcp_utils_client_id_string_to_bytes(src); \ + g_assert(b); \ + p = g_bytes_get_data(b, &l); \ + if (is_str) { \ + g_assert_cmpint(l, ==, expected_len + 1); \ + g_assert_cmpint(((const char *) p)[0], ==, 0); \ + g_assert(memcmp(p + 1, expected, expected_len) == 0); \ + } else { \ + g_assert_cmpint(l, ==, expected_len); \ + g_assert(memcmp(p, expected, expected_len) == 0); \ + } \ + } \ + G_STMT_END static void -test_client_id_from_string (void) +test_client_id_from_string(void) { - const char *nothex = "asdfasdfasdfasdfasdfasdfasdf"; - const char *allhex = "00:11:22:33:4:55:66:77:88"; - const guint8 allhex_bin[] = { 0x00, 0x11, 0x22, 0x33, 0x04, 0x55, 0x66, 0x77, 0x88 }; - const char *somehex = "00:11:22:33:44:55:asdfasdfasdf:99:10"; - const char *nocolons = "0011223344559910"; - const char *endcolon = "00:11:22:33:44:55:"; - - COMPARE_ID (nothex, TRUE, nothex, strlen (nothex)); - COMPARE_ID (allhex, FALSE, allhex_bin, sizeof (allhex_bin)); - COMPARE_ID (somehex, TRUE, somehex, strlen (somehex)); - COMPARE_ID (nocolons, TRUE, nocolons, strlen (nocolons)); - COMPARE_ID (endcolon, TRUE, endcolon, strlen (endcolon)); + const char * nothex = "asdfasdfasdfasdfasdfasdfasdf"; + const char * allhex = "00:11:22:33:4:55:66:77:88"; + const guint8 allhex_bin[] = {0x00, 0x11, 0x22, 0x33, 0x04, 0x55, 0x66, 0x77, 0x88}; + const char * somehex = "00:11:22:33:44:55:asdfasdfasdf:99:10"; + const char * nocolons = "0011223344559910"; + const char * endcolon = "00:11:22:33:44:55:"; + + COMPARE_ID(nothex, TRUE, nothex, strlen(nothex)); + COMPARE_ID(allhex, FALSE, allhex_bin, sizeof(allhex_bin)); + COMPARE_ID(somehex, TRUE, somehex, strlen(somehex)); + COMPARE_ID(nocolons, TRUE, nocolons, strlen(nocolons)); + COMPARE_ID(endcolon, TRUE, endcolon, strlen(endcolon)); } -NMTST_DEFINE (); +NMTST_DEFINE(); -int main (int argc, char **argv) +int +main(int argc, char **argv) { - nmtst_init_assert_logging (&argc, &argv, "WARN", "DEFAULT"); - - g_test_add_func ("/dhcp/generic-options", test_generic_options); - g_test_add_func ("/dhcp/wins-options", test_wins_options); - g_test_add_func ("/dhcp/classless-static-routes-1", test_classless_static_routes_1); - g_test_add_func ("/dhcp/classless-static-routes-2", test_classless_static_routes_2); - g_test_add_func ("/dhcp/fedora-dhclient-classless-static-routes", test_fedora_dhclient_classless_static_routes); - g_test_add_func ("/dhcp/dhclient-invalid-classless-routes-1", test_dhclient_invalid_classless_routes_1); - g_test_add_func ("/dhcp/dhcpcd-invalid-classless-routes-1", test_dhcpcd_invalid_classless_routes_1); - g_test_add_func ("/dhcp/dhclient-invalid-classless-routes-2", test_dhclient_invalid_classless_routes_2); - g_test_add_func ("/dhcp/dhcpcd-invalid-classless-routes-2", test_dhcpcd_invalid_classless_routes_2); - g_test_add_func ("/dhcp/dhclient-invalid-classless-routes-3", test_dhclient_invalid_classless_routes_3); - g_test_add_func ("/dhcp/dhcpcd-invalid-classless-routes-3", test_dhcpcd_invalid_classless_routes_3); - g_test_add_func ("/dhcp/dhclient-gw-in-classless-routes", test_dhclient_gw_in_classless_routes); - g_test_add_func ("/dhcp/dhcpcd-gw-in-classless-routes", test_dhcpcd_gw_in_classless_routes); - g_test_add_func ("/dhcp/escaped-domain-searches", test_escaped_domain_searches); - g_test_add_func ("/dhcp/invalid-escaped-domain-searches", test_invalid_escaped_domain_searches); - g_test_add_func ("/dhcp/ip4-missing-prefix-24", test_ip4_missing_prefix_24); - g_test_add_func ("/dhcp/ip4-missing-prefix-16", test_ip4_missing_prefix_16); - g_test_add_func ("/dhcp/ip4-missing-prefix-8", test_ip4_missing_prefix_8); - g_test_add_func ("/dhcp/ip4-prefix-classless", test_ip4_prefix_classless); - g_test_add_func ("/dhcp/client-id-from-string", test_client_id_from_string); - g_test_add_func ("/dhcp/vendor-option-metered", test_vendor_option_metered); - g_test_add_func ("/dhcp/parse-search-list", test_parse_search_list); - - return g_test_run (); + nmtst_init_assert_logging(&argc, &argv, "WARN", "DEFAULT"); + + g_test_add_func("/dhcp/generic-options", test_generic_options); + g_test_add_func("/dhcp/wins-options", test_wins_options); + g_test_add_func("/dhcp/classless-static-routes-1", test_classless_static_routes_1); + g_test_add_func("/dhcp/classless-static-routes-2", test_classless_static_routes_2); + g_test_add_func("/dhcp/fedora-dhclient-classless-static-routes", + test_fedora_dhclient_classless_static_routes); + g_test_add_func("/dhcp/dhclient-invalid-classless-routes-1", + test_dhclient_invalid_classless_routes_1); + g_test_add_func("/dhcp/dhcpcd-invalid-classless-routes-1", + test_dhcpcd_invalid_classless_routes_1); + g_test_add_func("/dhcp/dhclient-invalid-classless-routes-2", + test_dhclient_invalid_classless_routes_2); + g_test_add_func("/dhcp/dhcpcd-invalid-classless-routes-2", + test_dhcpcd_invalid_classless_routes_2); + g_test_add_func("/dhcp/dhclient-invalid-classless-routes-3", + test_dhclient_invalid_classless_routes_3); + g_test_add_func("/dhcp/dhcpcd-invalid-classless-routes-3", + test_dhcpcd_invalid_classless_routes_3); + g_test_add_func("/dhcp/dhclient-gw-in-classless-routes", test_dhclient_gw_in_classless_routes); + g_test_add_func("/dhcp/dhcpcd-gw-in-classless-routes", test_dhcpcd_gw_in_classless_routes); + g_test_add_func("/dhcp/escaped-domain-searches", test_escaped_domain_searches); + g_test_add_func("/dhcp/invalid-escaped-domain-searches", test_invalid_escaped_domain_searches); + g_test_add_func("/dhcp/ip4-missing-prefix-24", test_ip4_missing_prefix_24); + g_test_add_func("/dhcp/ip4-missing-prefix-16", test_ip4_missing_prefix_16); + g_test_add_func("/dhcp/ip4-missing-prefix-8", test_ip4_missing_prefix_8); + g_test_add_func("/dhcp/ip4-prefix-classless", test_ip4_prefix_classless); + g_test_add_func("/dhcp/client-id-from-string", test_client_id_from_string); + g_test_add_func("/dhcp/vendor-option-metered", test_vendor_option_metered); + g_test_add_func("/dhcp/parse-search-list", test_parse_search_list); + + return g_test_run(); } - |